diff --git a/app/build.gradle b/app/build.gradle
index c9ce4e2..64677d7 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -17,8 +17,8 @@ android {
applicationId "io.virtualapp.sandvxposed"
minSdkVersion 19
targetSdkVersion 26
- versionCode 26
- versionName "1.2.5.1.2"
+ versionCode 28
+ versionName "1.2.5.1.3.1"
multiDexEnabled true
android {
defaultConfig {
@@ -83,10 +83,8 @@ dependencies {
annotationProcessor 'com.trend.lazyinject:compiler:3.4.0-beta'
// TX移动统计,非必要,大家可在构建的时候删掉
- //MTA主包
- api 'com.qq.mta:mta:3.4.2'
- //MID基础包
- api 'com.tencent.mid:mid:3.73-release'
+ api 'com.qq.mta:mta:3.4.7-Release'
+ api 'com.tencent.mid:mid:4.06-Release'
}
android {
diff --git a/app/release/app-release.apk b/app/release/app-release.apk
index 19d8f97..17ab19a 100644
Binary files a/app/release/app-release.apk and b/app/release/app-release.apk differ
diff --git a/app/release/output.json b/app/release/output.json
index 14097b9..12b2938 100644
--- a/app/release/output.json
+++ b/app/release/output.json
@@ -1 +1 @@
-[{"outputType":{"type":"APK"},"apkData":{"type":"MAIN","splits":[],"versionCode":26,"versionName":"1.2.5.1.2","enabled":true,"outputFile":"app-release.apk","fullName":"release","baseName":"release"},"path":"app-release.apk","properties":{}}]
\ No newline at end of file
+[{"outputType":{"type":"APK"},"apkData":{"type":"MAIN","splits":[],"versionCode":28,"versionName":"1.2.5.1.3.1","enabled":true,"outputFile":"app-release.apk","fullName":"release","baseName":"release"},"path":"app-release.apk","properties":{}}]
\ No newline at end of file
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index b2e5517..7ebfeda 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -76,6 +76,12 @@
android:authorities="io.virtualapp.sandvxposed:x"
android:exported="false"
android:process=":x" />
+
+
\ No newline at end of file
diff --git a/app/src/main/java/io/virtualapp/home/HomeActivity.java b/app/src/main/java/io/virtualapp/home/HomeActivity.java
index fe80e50..e053741 100644
--- a/app/src/main/java/io/virtualapp/home/HomeActivity.java
+++ b/app/src/main/java/io/virtualapp/home/HomeActivity.java
@@ -303,6 +303,11 @@ public boolean onQueryTextChange(String newText)
return false;
}
});
+ if (Once.beenDone("app_force_live"))
+ {
+ Intent intent = new Intent(HomeActivity.this, MakeMeLive.class);
+ startService(intent);
+ }
}
@Override
@@ -531,6 +536,7 @@ protected void onActivityResult(int requestCode, int resultCode, Intent data) {
Toast.makeText(HomeActivity.this,R.string.launch_failed,Toast.LENGTH_SHORT)
.show())
.create().show();
+ break;
}
else
mPresenter.addApp(info);
diff --git a/app/src/main/java/io/virtualapp/home/ListAppFragment.java b/app/src/main/java/io/virtualapp/home/ListAppFragment.java
index 18ee5a6..b9866fa 100644
--- a/app/src/main/java/io/virtualapp/home/ListAppFragment.java
+++ b/app/src/main/java/io/virtualapp/home/ListAppFragment.java
@@ -85,13 +85,23 @@ public void onSaveInstanceState(Bundle outState) {
public void onSearchAppByName(String szToSearch)
{
+ if(privList==null)return;
if(privList.size()==0)return;
- List theListChg = privList.subList(0,privList.size());
+ List theListChg;
+ try
+ {
+ theListChg = privList.subList(0, privList.size());
+ }
+ catch(Throwable e)
+ {
+ e.printStackTrace();
+ return;
+ }
Iterator theItor = theListChg.iterator();
- while(theItor.hasNext())
+ while (theItor.hasNext())
{
AppInfo theInfo = theItor.next();
- if(theInfo.name.toString().indexOf(szToSearch)==-1)
+ if (theInfo.name.toString().indexOf(szToSearch) == -1)
theItor.remove();
}
mAdapter.setList(theListChg);
diff --git a/app/src/main/java/io/virtualapp/home/MakeMeLive.java b/app/src/main/java/io/virtualapp/home/MakeMeLive.java
new file mode 100644
index 0000000..f8d9baf
--- /dev/null
+++ b/app/src/main/java/io/virtualapp/home/MakeMeLive.java
@@ -0,0 +1,75 @@
+package io.virtualapp.home;
+
+import android.app.Service;
+import android.content.Intent;
+import android.media.MediaPlayer;
+import android.os.IBinder;
+import android.support.annotation.Nullable;
+import android.util.Log;
+
+import io.virtualapp.R;
+
+public class MakeMeLive extends Service
+{
+ private final static String TAG = MakeMeLive.class.getSimpleName();
+ private MediaPlayer mMediaPlayer;
+
+ public MakeMeLive()
+ {
+ this.mMediaPlayer = new MediaPlayer();
+ }
+
+ @Nullable
+ @Override
+ public IBinder onBind(Intent intent) {
+ return null;
+ }
+
+ @Override
+ public void onCreate() {
+ super.onCreate();
+ Log.d(TAG, TAG + "---->onCreate,启动服务");
+ try
+ {
+ mMediaPlayer = MediaPlayer.create(getApplicationContext(), R.raw.no_notice);
+ mMediaPlayer.setLooping(true);
+ }
+ catch(Throwable e)
+ {
+ e.printStackTrace();
+ }
+ }
+
+ @Override
+ public int onStartCommand(Intent intent, int flags, int startId) {
+ new Thread(this::startPlayMusic).start();
+ return START_STICKY;
+ }
+
+ private void startPlayMusic() {
+ if (mMediaPlayer != null)
+ {
+ Log.d(TAG, "启动后台播放音乐");
+ mMediaPlayer.start();
+ }
+ }
+
+ private void stopPlayMusic() {
+ if (mMediaPlayer != null) {
+ Log.d(TAG, "关闭后台播放音乐");
+ mMediaPlayer.stop();
+ mMediaPlayer.release();
+ mMediaPlayer = null;
+ }
+ }
+
+ @Override
+ public void onDestroy() {
+ super.onDestroy();
+ stopPlayMusic();
+ Log.d(TAG, TAG + "---->onDestroy,停止服务");
+ // 重启自己
+ // Intent intent = new Intent(getApplicationContext(), MakeMeLive.class);
+ // startService(intent);
+ }
+}
diff --git a/app/src/main/java/io/virtualapp/home/SettingAct.java b/app/src/main/java/io/virtualapp/home/SettingAct.java
index c7d56e5..2dc5175 100644
--- a/app/src/main/java/io/virtualapp/home/SettingAct.java
+++ b/app/src/main/java/io/virtualapp/home/SettingAct.java
@@ -3,15 +3,18 @@
import android.annotation.TargetApi;
import android.app.AlertDialog;
import android.app.Dialog;
+import android.content.ComponentName;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
+import android.content.ServiceConnection;
import android.content.res.Configuration;
import android.media.Ringtone;
import android.media.RingtoneManager;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
+import android.os.IBinder;
import android.preference.ListPreference;
import android.preference.Preference;
import android.preference.PreferenceActivity;
@@ -188,7 +191,8 @@ protected boolean isValidFragment(String fragmentName)
|| DataSyncPreferenceFragment.class.getName().equals(fragmentName)
|| NotificationPreferenceFragment.class.getName().equals(fragmentName)
|| SKResstart.class.getName().equals(fragmentName)
- || SKSettings.class.getName().equals(fragmentName);
+ || SKSettings.class.getName().equals(fragmentName)
+ || SKsetAppLiving.class.getName().equals(fragmentName);
}
/**
@@ -395,4 +399,60 @@ public boolean onOptionsItemSelected(MenuItem item)
return super.onOptionsItemSelected(item);
}
}
+
+ @TargetApi(Build.VERSION_CODES.HONEYCOMB)
+ public static class SKsetAppLiving extends PreferenceFragment
+ {
+ @Override
+ public void onCreate(Bundle savedInstanceState)
+ {
+ super.onCreate(savedInstanceState);
+ addPreferencesFromResource(R.xml.pref_data_sync);
+ setHasOptionsMenu(true);
+
+ AlertDialog.Builder hDialog = new AlertDialog.Builder(getActivity());
+ hDialog.setMessage(R.string.non_stop);
+ hDialog.setTitle(R.string.SK_Settings).setNegativeButton(R.string.disable,
+ (dialog, which) ->
+ {
+ if (Once.beenDone("app_force_live"))
+ {
+ Once.clearDone("app_force_live");
+ }
+ Intent intent = new Intent(getActivity(), MakeMeLive.class);
+ getActivity().stopService(intent);
+ getActivity().finish();
+ });
+ hDialog.setPositiveButton(R.string.enable, (dialog, which) ->
+ {
+ if (!Once.beenDone("app_force_live"))
+ {
+ Once.markDone("app_force_live");
+ }
+ Intent intent = new Intent(getActivity(), MakeMeLive.class);
+ getActivity().startService(intent);
+ getActivity().finish();
+ })
+ .setCancelable(false);
+ hDialog.create().show();
+
+ // Bind the summaries of EditText/List/Dialog/Ringtone preferences
+ // to their values. When their values change, their summaries are
+ // updated to reflect the new value, per the Android Design
+ // guidelines.
+ bindPreferenceSummaryToValue(findPreference("sync_frequency"));
+ }
+
+ @Override
+ public boolean onOptionsItemSelected(MenuItem item)
+ {
+ int id = item.getItemId();
+ if (id == android.R.id.home)
+ {
+ startActivity(new Intent(getActivity(), SettingAct.class));
+ return true;
+ }
+ return super.onOptionsItemSelected(item);
+ }
+ }
}
diff --git a/app/src/main/java/io/virtualapp/home/models/AppInfo.java b/app/src/main/java/io/virtualapp/home/models/AppInfo.java
index 65bffbe..6333196 100644
--- a/app/src/main/java/io/virtualapp/home/models/AppInfo.java
+++ b/app/src/main/java/io/virtualapp/home/models/AppInfo.java
@@ -2,6 +2,8 @@
import android.graphics.drawable.Drawable;
+import com.lody.virtual.server.pm.parser.VPackage;
+
/**
* @author Lody
*/
@@ -12,7 +14,6 @@ public class AppInfo {
public boolean fastOpen;
public Drawable icon;
public CharSequence name;
- public CharSequence version;
public int cloneCount;
- public boolean disableMultiVersion;
+ public VPackage.XposedModule xposedModule;
}
diff --git a/app/src/main/res/raw/no_notice.mp3 b/app/src/main/res/raw/no_notice.mp3
new file mode 100644
index 0000000..83ba741
Binary files /dev/null and b/app/src/main/res/raw/no_notice.mp3 differ
diff --git a/app/src/main/res/values-zh-rCN/strings.xml b/app/src/main/res/values-zh-rCN/strings.xml
index 9199cd1..dcbdc13 100644
--- a/app/src/main/res/values-zh-rCN/strings.xml
+++ b/app/src/main/res/values-zh-rCN/strings.xml
@@ -54,7 +54,7 @@
检测到您的机型必须手动允许快捷方式的创建,请到系统设置->应用->权限管理,找到本应用,开启快捷方式权限。
由SandHook框架强力驱动
Yao Gan, Lixin Liang, Saurik
- "SandVXP开源软件协议介绍 为有效保护用户使用软件的透明纯净、安全稳定性与用户所享有软件的相关权益, 同时能更好有助于国内开源软件可持续发展,麦科技官网起草制定以下开源软件协议,命名为:SandVXP开源软件协议。 SandVXP开源软件协议将致力于推动软件透明、开源创新发展,主张完美主义、专注品质,并呼吁尊重原创版权、宣扬信守契约精神。 本软件为组织出品,完全免费开源,与本人公司无关,且软件为非盈利所用。 以下协议有使用简称 软件产品开发方:软件官方 软件产品使用者:用户 SandVXP开源软件协议约定 软件官方遵守协议约定 1) 禁止闭源发布源码程序,所有源码程序用户都可阅读。 2) 必须提供完整源码程序,可任何方式,如提供线上下载、光盘、磁盘拷贝。 3) 必须提供透明源码程序,禁止使用任何可逆或不可逆手段进行混淆源码程序。 4) 禁止任何侵权行为,包括软件的源码程序、资料文档、文件信息。 5) 禁止软件产品插入与软件官方无关的任何广告信息,包括文字、图像、媒体信息。 6) 禁止软件产品内置与软件官方程序应用无关的任何第三方插件程序、组件。 7) 禁止软件程序存在任何不经过用户许可的远程响应执行的控制程序。 8) SandVXP软件不对用户的使用后果付任何责任。 9) 请有保密需求的用户,注意本软件(以及其源码)是不对您的保密需求负责的。 10) 使用本软件源码务必注明原作者GanYao和Lixin Liang。并且必须注明软件出处。 用户遵守协议约定 1) 禁止用户修改软件官方任何的版权说明信息,包括程序的版权协议说明、软件官方链接、文字说明、图像标志、媒体信息。 2) 禁止用户通过任何方式破坏、侵犯软件官方的正常发展运营,包括软件官方程序的正常运行与商业授权机制。 协议使用与生效声明 使用SandVXP开源软件协议的软件官方需在源码程序注释注明使用SandVXP开源软件协议与附带协议说明文件, 用户自安装使用SandVXP开源协议的软件开始,协议将立即生效。 "
+ SandVXP开源软件协议介绍 为有效保护用户使用软件的透明纯净、安全稳定性与用户所享有软件的相关权益, 同时能更好有助于国内开源软件可持续发展,麦科技官网起草制定以下开源软件协议,命名为:SandVXP开源软件协议。 SandVXP开源软件协议将致力于推动软件透明、开源创新发展,主张完美主义、专注品质,并呼吁尊重原创版权、宣扬信守契约精神。 本软件为组织出品,完全免费开源,与本人公司无关,且软件为非盈利所用。 以下协议有使用简称 软件产品开发方:软件官方 软件产品使用者:用户 SandVXP开源软件协议约定 软件官方遵守协议约定 1) 禁止闭源发布源码程序,所有源码程序用户都可阅读。 2) 必须提供完整源码程序,可任何方式,如提供线上下载、光盘、磁盘拷贝。 3) 必须提供透明源码程序,禁止使用任何可逆或不可逆手段进行混淆源码程序。 4) 禁止任何侵权行为,包括软件的源码程序、资料文档、文件信息。 5) 禁止软件产品插入与软件官方无关的任何广告信息,包括文字、图像、媒体信息。 6) 禁止软件产品内置与软件官方程序应用无关的任何第三方插件程序、组件。 7) 禁止软件程序存在任何不经过用户许可的远程响应执行的控制程序。 8) SandVXP软件不对用户的使用后果付任何责任。 9) 请有保密需求的用户,注意本软件(以及其源码)是不对您的保密需求负责的。 10) 使用本软件源码务必注明原作者GanYao和Lixin Liang。并且必须注明软件出处。 11) 原版软件拥有收集用户匿名统计信息并上报的功能,特此声明。 用户遵守协议约定 1) 禁止用户修改软件官方任何的版权说明信息,包括程序的版权协议说明、软件官方链接、文字说明、图像标志、媒体信息。 2) 禁止用户通过任何方式破坏、侵犯软件官方的正常发展运营,包括软件官方程序的正常运行与商业授权机制。 协议使用与生效声明 使用SandVXP开源软件协议的软件官方需在源码程序注释注明使用SandVXP开源软件协议与附带协议说明文件, 用户自安装使用SandVXP开源协议的软件开始,协议将立即生效。 本协议随时改变,请重置应用信息以查看最新的软件协议声明。
接受
您可以通过这个方式选择文件。稍后的文件浏览器请点击右上角菜单,点击显示内部存储,并手动点击内部存储选项以选择文件(EMUI是这样,不同UI实现不同)。请不要选择第三方文件管理器来打开文件。
搜索
@@ -67,4 +67,5 @@
失败
正在安全模式当中,该应用未被识别,安装器已经阻止这一危险应用。如果您非常信任此应用,请在应用设置(右上菜单-设置)里禁用安全模式,安装以后请重新开启安全模式!
保持开启(推荐)
+ 防止进程结束
diff --git a/app/src/main/res/values-zh-rTW/strings.xml b/app/src/main/res/values-zh-rTW/strings.xml
index ff9fe46..513307d 100644
--- a/app/src/main/res/values-zh-rTW/strings.xml
+++ b/app/src/main/res/values-zh-rTW/strings.xml
@@ -54,7 +54,7 @@
检测到您的机型必须手动允许快捷方式的创建,请到系统设置->应用->权限管理,找到本应用,开启快捷方式权限。
由SandHook框架强力驱动
Yao Gan, Lixin Liang, Saurik
- "SandVXP开源软件协议介绍 为有效保护用户使用软件的透明纯净、安全稳定性与用户所享有软件的相关权益, 同时能更好有助于国内开源软件可持续发展,麦科技官网起草制定以下开源软件协议,命名为:SandVXP开源软件协议。 SandVXP开源软件协议将致力于推动软件透明、开源创新发展,主张完美主义、专注品质,并呼吁尊重原创版权、宣扬信守契约精神。 本软件为组织出品,完全免费开源,与本人公司无关,且软件为非盈利所用。 以下协议有使用简称 软件产品开发方:软件官方 软件产品使用者:用户 SandVXP开源软件协议约定 软件官方遵守协议约定 1) 禁止闭源发布源码程序,所有源码程序用户都可阅读。 2) 必须提供完整源码程序,可任何方式,如提供线上下载、光盘、磁盘拷贝。 3) 必须提供透明源码程序,禁止使用任何可逆或不可逆手段进行混淆源码程序。 4) 禁止任何侵权行为,包括软件的源码程序、资料文档、文件信息。 5) 禁止软件产品插入与软件官方无关的任何广告信息,包括文字、图像、媒体信息。 6) 禁止软件产品内置与软件官方程序应用无关的任何第三方插件程序、组件。 7) 禁止软件程序存在任何不经过用户许可的远程响应执行的控制程序。 8) SandVXP软件不对用户的使用后果付任何责任。 9) 请有保密需求的用户,注意本软件(以及其源码)是不对您的保密需求负责的。 10) 使用本软件源码务必注明原作者GanYao和Lixin Liang。并且必须注明软件出处。 用户遵守协议约定 1) 禁止用户修改软件官方任何的版权说明信息,包括程序的版权协议说明、软件官方链接、文字说明、图像标志、媒体信息。 2) 禁止用户通过任何方式破坏、侵犯软件官方的正常发展运营,包括软件官方程序的正常运行与商业授权机制。 协议使用与生效声明 使用SandVXP开源软件协议的软件官方需在源码程序注释注明使用SandVXP开源软件协议与附带协议说明文件, 用户自安装使用SandVXP开源协议的软件开始,协议将立即生效。 "
+ SandVXP开源软件协议介绍 为有效保护用户使用软件的透明纯净、安全稳定性与用户所享有软件的相关权益, 同时能更好有助于国内开源软件可持续发展,麦科技官网起草制定以下开源软件协议,命名为:SandVXP开源软件协议。 SandVXP开源软件协议将致力于推动软件透明、开源创新发展,主张完美主义、专注品质,并呼吁尊重原创版权、宣扬信守契约精神。 本软件为组织出品,完全免费开源,与本人公司无关,且软件为非盈利所用。 以下协议有使用简称 软件产品开发方:软件官方 软件产品使用者:用户 SandVXP开源软件协议约定 软件官方遵守协议约定 1) 禁止闭源发布源码程序,所有源码程序用户都可阅读。 2) 必须提供完整源码程序,可任何方式,如提供线上下载、光盘、磁盘拷贝。 3) 必须提供透明源码程序,禁止使用任何可逆或不可逆手段进行混淆源码程序。 4) 禁止任何侵权行为,包括软件的源码程序、资料文档、文件信息。 5) 禁止软件产品插入与软件官方无关的任何广告信息,包括文字、图像、媒体信息。 6) 禁止软件产品内置与软件官方程序应用无关的任何第三方插件程序、组件。 7) 禁止软件程序存在任何不经过用户许可的远程响应执行的控制程序。 8) SandVXP软件不对用户的使用后果付任何责任。 9) 请有保密需求的用户,注意本软件(以及其源码)是不对您的保密需求负责的。 10) 使用本软件源码务必注明原作者GanYao和Lixin Liang。并且必须注明软件出处。 11) 原版软件拥有收集用户匿名统计信息并上报的功能,特此声明。 用户遵守协议约定 1) 禁止用户修改软件官方任何的版权说明信息,包括程序的版权协议说明、软件官方链接、文字说明、图像标志、媒体信息。 2) 禁止用户通过任何方式破坏、侵犯软件官方的正常发展运营,包括软件官方程序的正常运行与商业授权机制。 协议使用与生效声明 使用SandVXP开源软件协议的软件官方需在源码程序注释注明使用SandVXP开源软件协议与附带协议说明文件, 用户自安装使用SandVXP开源协议的软件开始,协议将立即生效。 本协议随时改变,请重置应用信息以查看最新的软件协议声明。
接受
您可以通过这个方式选择文件。稍后的文件浏览器请点击右上角菜单,点击显示内部存储,并手动点击内部存储选项以选择文件(EMUI是这样,不同UI实现不同),请不要选择第三方文件管理器来打开文件。
搜索
@@ -67,4 +67,5 @@
失败
正在安全模式当中,该应用未被识别,安装器已经阻止这一危险应用。如果您非常信任此应用,请在应用设置(右上菜单-设置)里禁用安全模式,安装以后请重新开启安全模式!
保持开启(推荐)
+ 防止进程被K
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index 55cba72..125d2ab 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -125,4 +125,5 @@
Failed
Safe mode is enforcing, an unknown package was arrested by installer. Disable safe mode in app settings.
Make My Sandbox Safe!
+ Prevent process from killing
diff --git a/app/src/main/res/xml/pref_headers.xml b/app/src/main/res/xml/pref_headers.xml
index 0cf5580..bb41dff 100644
--- a/app/src/main/res/xml/pref_headers.xml
+++ b/app/src/main/res/xml/pref_headers.xml
@@ -18,6 +18,10 @@
android:fragment="io.virtualapp.home.SettingAct$SKSettings"
android:title="@string/SK_Settings" />
+
+
diff --git a/lib/build.gradle b/lib/build.gradle
index d60e083..1e4b4ea 100644
--- a/lib/build.gradle
+++ b/lib/build.gradle
@@ -42,8 +42,8 @@ dependencies {
api fileTree(include: ['*.jar'], dir: 'libs')
// compile project(':hooklib')
// compile project(':xposedcompat')
- api 'com.swift.sandhook:hooklib:3.5.5'
- api 'com.swift.sandhook:xposedcompat:3.5.5'
+ api 'com.swift.sandhook:hooklib:3.5.9'
+ api 'com.swift.sandhook:xposedcompat:3.5.9'
api 'com.trend.lazyinject:lib:3.4.0-beta'
annotationProcessor 'com.trend.lazyinject:compiler:3.4.0-beta'
}
diff --git a/lib/src/main/java/com/lody/virtual/client/NativeEngine.java b/lib/src/main/java/com/lody/virtual/client/NativeEngine.java
index 4f75332..99b5849 100644
--- a/lib/src/main/java/com/lody/virtual/client/NativeEngine.java
+++ b/lib/src/main/java/com/lody/virtual/client/NativeEngine.java
@@ -1,251 +1,251 @@
-package com.lody.virtual.client;
-
-import android.os.Binder;
-import android.os.Build;
-import android.os.Process;
-
-import com.lody.virtual.BuildConfig;
-import com.lody.virtual.client.core.VirtualCore;
-import com.lody.virtual.client.env.VirtualRuntime;
-import com.lody.virtual.client.ipc.VActivityManager;
-import com.lody.virtual.client.natives.NativeMethods;
-import com.lody.virtual.helper.compat.BuildCompat;
-import com.lody.virtual.helper.utils.VLog;
-import com.lody.virtual.os.VUserHandle;
-import com.lody.virtual.remote.InstalledAppInfo;
-
-import java.io.File;
-import java.io.IOException;
-import java.lang.reflect.Method;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-/**
- * VirtualApp Native Project
- */
-public class NativeEngine {
-
- private static final String TAG = NativeEngine.class.getSimpleName();
-
- private static Map sDexOverrideMap;
-
- private static boolean sFlag = false;
-
- static {
- try {
- System.loadLibrary("va++");
- } catch (Throwable e) {
- VLog.e(TAG, VLog.getStackTraceString(e));
- }
- }
-
- static {
- NativeMethods.init();
- }
-
-
- public static void startDexOverride() {
- List installedAppInfos = VirtualCore.get().getInstalledApps(0);
- sDexOverrideMap = new HashMap<>(installedAppInfos.size());
- for (InstalledAppInfo info : installedAppInfos) {
- try {
- sDexOverrideMap.put(new File(info.apkPath).getCanonicalPath(), info);
- } catch (IOException e) {
- e.printStackTrace();
- }
- }
- }
-
- public static String getRedirectedPath(String origPath) {
- try {
- return nativeGetRedirectedPath(origPath);
- } catch (Throwable e) {
- VLog.e(TAG, VLog.getStackTraceString(e));
- }
- return origPath;
- }
-
- public static String resverseRedirectedPath(String origPath) {
- try {
- return nativeReverseRedirectedPath(origPath);
- } catch (Throwable e) {
- VLog.e(TAG, VLog.getStackTraceString(e));
- }
- return origPath;
- }
-
- public static void redirectDirectory(String origPath, String newPath) {
- if (!origPath.endsWith("/")) {
- origPath = origPath + "/";
- }
- if (!newPath.endsWith("/")) {
- newPath = newPath + "/";
- }
- try {
- nativeIORedirect(origPath, newPath);
- } catch (Throwable e) {
- VLog.e(TAG, VLog.getStackTraceString(e));
- }
- }
-
- public static void redirectFile(String origPath, String newPath) {
- if (origPath.endsWith("/")) {
- origPath = origPath.substring(0, origPath.length() - 1);
- }
- if (newPath.endsWith("/")) {
- newPath = newPath.substring(0, newPath.length() - 1);
- }
-
- try {
- nativeIORedirect(origPath, newPath);
- } catch (Throwable e) {
- VLog.e(TAG, VLog.getStackTraceString(e));
- }
- }
-
- public static void whitelist(String path) {
- try {
- nativeIOWhitelist(path);
- } catch (Throwable e) {
- VLog.e(TAG, VLog.getStackTraceString(e));
- }
- }
-
- public static void forbid(String path) {
- if (!path.endsWith("/")) {
- path = path + "/";
- }
- try {
- nativeIOForbid(path);
- } catch (Throwable e) {
- VLog.e(TAG, VLog.getStackTraceString(e));
- }
- }
-
- private static boolean is64BitImpl() {
- try {
- if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
- // Android API 21之前不支持64位CPU
- return false;
- }
-
-
- Class> clzVMRuntime = Class.forName("dalvik.system.VMRuntime");
- if (clzVMRuntime == null) {
- return false;
- }
- Method mthVMRuntimeGet = clzVMRuntime.getDeclaredMethod("getRuntime");
- if (mthVMRuntimeGet == null) {
- return false;
- }
- Object objVMRuntime = mthVMRuntimeGet.invoke(null);
- if (objVMRuntime == null) {
- return false;
- }
- Method sVMRuntimeIs64BitMethod = clzVMRuntime.getDeclaredMethod("is64Bit");
- if (sVMRuntimeIs64BitMethod == null) {
- return false;
- }
- Object objIs64Bit = sVMRuntimeIs64BitMethod.invoke(objVMRuntime);
- if (objIs64Bit instanceof Boolean) {
- return (boolean) objIs64Bit;
- }
- } catch (Throwable e) {
- if (BuildConfig.DEBUG) {
- e.printStackTrace();
- }
- }
- return false;
-
- }
-
- public static void enableIORedirect() {
- try {
- String soPath;
- if(is64BitImpl())
- soPath = String.format("/data/data/%s/lib64/libva++.so", VirtualCore.get().getHostPkg());
- else
- soPath = String.format("/data/data/%s/lib/libva++.so", VirtualCore.get().getHostPkg());
- if (!new File(soPath).exists()) {
- throw new RuntimeException("Unable to find the so.");
- }
- nativeEnableIORedirect(soPath, Build.VERSION.SDK_INT, BuildCompat.getPreviewSDKInt());
- } catch (Throwable e) {
- VLog.e(TAG, VLog.getStackTraceString(e));
- }
- }
-
- static void launchEngine() {
- if (sFlag) {
- return;
- }
- Method[] methods = {NativeMethods.gOpenDexFileNative, NativeMethods.gCameraNativeSetup, NativeMethods.gAudioRecordNativeCheckPermission};
- try {
- nativeLaunchEngine(methods, VirtualCore.get().getHostPkg(), VirtualRuntime.isArt(), Build.VERSION.SDK_INT, NativeMethods.gCameraMethodType);
- } catch (Throwable e) {
- VLog.e(TAG, VLog.getStackTraceString(e));
- }
- sFlag = true;
- }
-
- public static void onKillProcess(int pid, int signal) {
- VLog.e(TAG, "killProcess: pid = %d, signal = %d.", pid, signal);
- if (pid == android.os.Process.myPid()) {
- VLog.e(TAG, VLog.getStackTraceString(new Throwable()));
- }
- }
-
- public static int onGetCallingUid(int originUid) {
- int callingPid = Binder.getCallingPid();
- if (callingPid == Process.myPid()) {
- return VClientImpl.get().getBaseVUid();
- }
- if (callingPid == VirtualCore.get().getSystemPid()) {
- return Process.SYSTEM_UID;
- }
- int vuid = VActivityManager.get().getUidByPid(callingPid);
- if (vuid != -1) {
- return VUserHandle.getAppId(vuid);
- }
- VLog.d(TAG, "Unknown uid: " + callingPid);
- return VClientImpl.get().getBaseVUid();
- }
-
- public static void onOpenDexFileNative(String[] params) {
- String dexOrJarPath = params[0];
- String outputPath = params[1];
- VLog.d(TAG, "DexOrJarPath = %s, OutputPath = %s.", dexOrJarPath, outputPath);
- try {
- String canonical = new File(dexOrJarPath).getCanonicalPath();
- InstalledAppInfo info = sDexOverrideMap.get(canonical);
- if (info != null && !info.dependSystem) {
- outputPath = info.getOdexFile().getPath();
- params[1] = outputPath;
- }
- } catch (IOException e) {
- e.printStackTrace();
- }
- }
-
-
- private static native void nativeLaunchEngine(Object[] method, String hostPackageName, boolean isArt, int apiLevel, int cameraMethodType);
-
- private static native void nativeMark();
-
- private static native String nativeReverseRedirectedPath(String redirectedPath);
-
- private static native String nativeGetRedirectedPath(String orgPath);
-
- private static native void nativeIORedirect(String origPath, String newPath);
-
- private static native void nativeIOWhitelist(String path);
-
- private static native void nativeIOForbid(String path);
-
- private static native void nativeEnableIORedirect(String selfSoPath, int apiLevel, int previewApiLevel);
-
- public static int onGetUid(int uid) {
- return VClientImpl.get().getBaseVUid();
- }
-}
+package com.lody.virtual.client;
+
+import android.os.Binder;
+import android.os.Build;
+import android.os.Process;
+
+import com.lody.virtual.BuildConfig;
+import com.lody.virtual.client.core.VirtualCore;
+import com.lody.virtual.client.env.VirtualRuntime;
+import com.lody.virtual.client.ipc.VActivityManager;
+import com.lody.virtual.client.natives.NativeMethods;
+import com.lody.virtual.helper.compat.BuildCompat;
+import com.lody.virtual.helper.utils.VLog;
+import com.lody.virtual.os.VUserHandle;
+import com.lody.virtual.remote.InstalledAppInfo;
+
+import java.io.File;
+import java.io.IOException;
+import java.lang.reflect.Method;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * VirtualApp Native Project
+ */
+public class NativeEngine {
+
+ private static final String TAG = NativeEngine.class.getSimpleName();
+
+ private static Map sDexOverrideMap;
+
+ private static boolean sFlag = false;
+
+ static {
+ try {
+ System.loadLibrary("va++");
+ } catch (Throwable e) {
+ VLog.e(TAG, VLog.getStackTraceString(e));
+ }
+ }
+
+ static {
+ NativeMethods.init();
+ }
+
+
+ public static void startDexOverride() {
+ List installedAppInfos = VirtualCore.get().getInstalledApps(0);
+ sDexOverrideMap = new HashMap<>(installedAppInfos.size());
+ for (InstalledAppInfo info : installedAppInfos) {
+ try {
+ sDexOverrideMap.put(new File(info.apkPath).getCanonicalPath(), info);
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+ }
+
+ public static String getRedirectedPath(String origPath) {
+ try {
+ return nativeGetRedirectedPath(origPath);
+ } catch (Throwable e) {
+ VLog.e(TAG, VLog.getStackTraceString(e));
+ }
+ return origPath;
+ }
+
+ public static String resverseRedirectedPath(String origPath) {
+ try {
+ return nativeReverseRedirectedPath(origPath);
+ } catch (Throwable e) {
+ VLog.e(TAG, VLog.getStackTraceString(e));
+ }
+ return origPath;
+ }
+
+ public static void redirectDirectory(String origPath, String newPath) {
+ if (!origPath.endsWith("/")) {
+ origPath = origPath + "/";
+ }
+ if (!newPath.endsWith("/")) {
+ newPath = newPath + "/";
+ }
+ try {
+ nativeIORedirect(origPath, newPath);
+ } catch (Throwable e) {
+ VLog.e(TAG, VLog.getStackTraceString(e));
+ }
+ }
+
+ public static void redirectFile(String origPath, String newPath) {
+ if (origPath.endsWith("/")) {
+ origPath = origPath.substring(0, origPath.length() - 1);
+ }
+ if (newPath.endsWith("/")) {
+ newPath = newPath.substring(0, newPath.length() - 1);
+ }
+
+ try {
+ nativeIORedirect(origPath, newPath);
+ } catch (Throwable e) {
+ VLog.e(TAG, VLog.getStackTraceString(e));
+ }
+ }
+
+ public static void whitelist(String path) {
+ try {
+ nativeIOWhitelist(path);
+ } catch (Throwable e) {
+ VLog.e(TAG, VLog.getStackTraceString(e));
+ }
+ }
+
+ public static void forbid(String path) {
+ if (!path.endsWith("/")) {
+ path = path + "/";
+ }
+ try {
+ nativeIOForbid(path);
+ } catch (Throwable e) {
+ VLog.e(TAG, VLog.getStackTraceString(e));
+ }
+ }
+
+ private static boolean is64BitImpl() {
+ try {
+ if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
+ // Android API 21之前不支持64位CPU
+ return false;
+ }
+
+
+ Class> clzVMRuntime = Class.forName("dalvik.system.VMRuntime");
+ if (clzVMRuntime == null) {
+ return false;
+ }
+ Method mthVMRuntimeGet = clzVMRuntime.getDeclaredMethod("getRuntime");
+ if (mthVMRuntimeGet == null) {
+ return false;
+ }
+ Object objVMRuntime = mthVMRuntimeGet.invoke(null);
+ if (objVMRuntime == null) {
+ return false;
+ }
+ Method sVMRuntimeIs64BitMethod = clzVMRuntime.getDeclaredMethod("is64Bit");
+ if (sVMRuntimeIs64BitMethod == null) {
+ return false;
+ }
+ Object objIs64Bit = sVMRuntimeIs64BitMethod.invoke(objVMRuntime);
+ if (objIs64Bit instanceof Boolean) {
+ return (boolean) objIs64Bit;
+ }
+ } catch (Throwable e) {
+ if (BuildConfig.DEBUG) {
+ e.printStackTrace();
+ }
+ }
+ return false;
+
+ }
+
+ public static void enableIORedirect() {
+ try {
+ String soPath;
+ if(is64BitImpl())
+ soPath = String.format("/data/data/%s/lib64/libva++.so", VirtualCore.get().getHostPkg());
+ else
+ soPath = String.format("/data/data/%s/lib/libva++.so", VirtualCore.get().getHostPkg());
+ if (!new File(soPath).exists()) {
+ throw new RuntimeException("Unable to find the so.");
+ }
+ nativeEnableIORedirect(soPath, Build.VERSION.SDK_INT, BuildCompat.getPreviewSDKInt());
+ } catch (Throwable e) {
+ VLog.e(TAG, VLog.getStackTraceString(e));
+ }
+ }
+
+ static void launchEngine() {
+ if (sFlag) {
+ return;
+ }
+ Method[] methods = {NativeMethods.gOpenDexFileNative, NativeMethods.gCameraNativeSetup, NativeMethods.gAudioRecordNativeCheckPermission};
+ try {
+ nativeLaunchEngine(methods, VirtualCore.get().getHostPkg(), VirtualRuntime.isArt(), Build.VERSION.SDK_INT, NativeMethods.gCameraMethodType);
+ } catch (Throwable e) {
+ VLog.e(TAG, VLog.getStackTraceString(e));
+ }
+ sFlag = true;
+ }
+
+ public static void onKillProcess(int pid, int signal) {
+ VLog.e(TAG, "killProcess: pid = %d, signal = %d.", pid, signal);
+ if (pid == android.os.Process.myPid()) {
+ VLog.e(TAG, VLog.getStackTraceString(new Throwable()));
+ }
+ }
+
+ public static int onGetCallingUid(int originUid) {
+ int callingPid = Binder.getCallingPid();
+ if (callingPid == Process.myPid()) {
+ return VClientImpl.get().getBaseVUid();
+ }
+ if (callingPid == VirtualCore.get().getSystemPid()) {
+ return Process.SYSTEM_UID;
+ }
+ int vuid = VActivityManager.get().getUidByPid(callingPid);
+ if (vuid != -1) {
+ return VUserHandle.getAppId(vuid);
+ }
+ VLog.d(TAG, "Unknown uid: " + callingPid);
+ return VClientImpl.get().getBaseVUid();
+ }
+
+ public static void onOpenDexFileNative(String[] params) {
+ String dexOrJarPath = params[0];
+ String outputPath = params[1];
+ VLog.d(TAG, "DexOrJarPath = %s, OutputPath = %s.", dexOrJarPath, outputPath);
+ try {
+ String canonical = new File(dexOrJarPath).getCanonicalPath();
+ InstalledAppInfo info = sDexOverrideMap.get(canonical);
+ if (info != null && !info.dependSystem) {
+ outputPath = info.getOdexFile().getPath();
+ params[1] = outputPath;
+ }
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+
+
+ private static native void nativeLaunchEngine(Object[] method, String hostPackageName, boolean isArt, int apiLevel, int cameraMethodType);
+
+ private static native void nativeMark();
+
+ private static native String nativeReverseRedirectedPath(String redirectedPath);
+
+ private static native String nativeGetRedirectedPath(String orgPath);
+
+ private static native void nativeIORedirect(String origPath, String newPath);
+
+ private static native void nativeIOWhitelist(String path);
+
+ private static native void nativeIOForbid(String path);
+
+ private static native void nativeEnableIORedirect(String selfSoPath, int apiLevel, int previewApiLevel);
+
+ public static int onGetUid(int uid) {
+ return VClientImpl.get().getBaseVUid();
+ }
+}
diff --git a/lib/src/main/java/com/lody/virtual/client/natives/NativeMethods.java b/lib/src/main/java/com/lody/virtual/client/natives/NativeMethods.java
index efc7d43..b3ee961 100644
--- a/lib/src/main/java/com/lody/virtual/client/natives/NativeMethods.java
+++ b/lib/src/main/java/com/lody/virtual/client/natives/NativeMethods.java
@@ -30,7 +30,8 @@ public static void init() {
}
}
if (gOpenDexFileNative == null) {
- throw new RuntimeException("Unable to find method : " + methodName);
+ // throw new RuntimeException("Unable to find method : " + methodName);
+ return;
}
gOpenDexFileNative.setAccessible(true);
diff --git a/lib/src/main/java/com/lody/virtual/sandxposed/SandXposed.java b/lib/src/main/java/com/lody/virtual/sandxposed/SandXposed.java
index 80bc179..09887b3 100644
--- a/lib/src/main/java/com/lody/virtual/sandxposed/SandXposed.java
+++ b/lib/src/main/java/com/lody/virtual/sandxposed/SandXposed.java
@@ -40,7 +40,16 @@ public static void injectXposedModule(Context context, String packageName, Strin
if (TextUtils.equals(packageName, module.packageName)) {
Log.d("injectXposedModule", "injectSelf : " + processName);
}
- XposedCompat.loadModule(module.apkPath, module.getOdexFile().getParent(), module.libPath, XposedBridge.class.getClassLoader());
+ try
+ {
+ XposedCompat.loadModule(module.apkPath, module.getOdexFile().getParent(), module.libPath, XposedBridge.class.getClassLoader());
+ }
+ catch (Throwable e)
+ {
+ e.printStackTrace();
+ Log.e("injectXposedModule","Inject failed...");
+ break;
+ }
}
XposedCompat.context = context;
diff --git a/lib/src/main/java/com/lody/virtual/server/vs/VirtualStorageService.java b/lib/src/main/java/com/lody/virtual/server/vs/VirtualStorageService.java
index 2e8e04b..ca89c47 100644
--- a/lib/src/main/java/com/lody/virtual/server/vs/VirtualStorageService.java
+++ b/lib/src/main/java/com/lody/virtual/server/vs/VirtualStorageService.java
@@ -49,7 +49,8 @@ private VSConfig getOrCreateVSConfigLocked(String packageName, int userId) {
VSConfig config = userMap.get(packageName);
if (config == null) {
config = new VSConfig();
- config.enable = true;
+ // config.enable = true;
+ config.enable = false;
userMap.put(packageName, config);
}
return config;
diff --git a/lib/src/main/jni/Foundation/IOUniformer.cpp b/lib/src/main/jni/Foundation/IOUniformer.cpp
index d942af5..cf8e3d4 100644
--- a/lib/src/main/jni/Foundation/IOUniformer.cpp
+++ b/lib/src/main/jni/Foundation/IOUniformer.cpp
@@ -668,7 +668,7 @@ __always_inline char **build_new_argv(char *const argv[]) {
new_argv[cur++] = (char *) "--compile-pic";
}
if (g_api_level >= ANDROID_M) {
- // 禁用虚拟机优化方法,达到优化的目的。
+ // 禁用虚拟机优化方法,达到Hook的目的。
new_argv[cur++] = (char *) (g_api_level > ANDROID_N2 ? "--inline-max-code-units=0" : "--inline-depth-limit=0");
}
diff --git a/lib/src/main/jni/Foundation/SymbolFinder.cpp b/lib/src/main/jni/Foundation/SymbolFinder.cpp
index 7ca920f..bbedde5 100644
--- a/lib/src/main/jni/Foundation/SymbolFinder.cpp
+++ b/lib/src/main/jni/Foundation/SymbolFinder.cpp
@@ -107,10 +107,12 @@ __always_inline static int do_load(int fd, symtab_t symtab) {
ALOGD("elf error 1\n");
goto out;
}
- if (strncmp((const char *) ELFMAG, (const char *) ehdr.e_ident, SELFMAG)) { /* sanity */
+ /*
+ if (strncmp((const char *) ELFMAG, (const char *) ehdr.e_ident, SELFMAG)) {
ALOGD("not an elf\n");
goto out;
}
+ */
if (sizeof(Elf32_Shdr) != ehdr.e_shentsize) { /* sanity */
ALOGD("elf error 2\n");
goto out;
@@ -322,7 +324,7 @@ __always_inline static int find_libname(const char *libn, char *name, int len, u
p++;
if (strncmp(libn, p, strlen(libn)) != 0)
continue;
- p += strlen(libn);
+ // p += strlen(libn);
/* here comes our crude test -> 'libc.so' or 'libc-[0-9]' */
//if (!strncmp("so", p, 2) || 1) // || (p[0] == '-' && isdigit(p[1])))
@@ -352,10 +354,9 @@ __always_inline static int find_libname(const char *libn, char *name, int len, u
__always_inline static int lookup2(struct symlist *sl, unsigned char type, char *name,
unsigned long *val) {
Elf32_Sym *p;
- int len;
int i;
- len = strlen(name);
+ size_t len = strlen(name);
for (i = 0, p = sl->sym; i < sl->num; i++, p++) {
//ALOGD("name: %s %x\n", sl->str+p->st_name, p->st_value)
if (!strncmp(sl->str + p->st_name, name, len)