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)