From 133c00e54c87683a27bc7d8b5466939ab7b5418f Mon Sep 17 00:00:00 2001 From: tehcneko <7764726+tehcneko@users.noreply.github.com> Date: Thu, 28 Jan 2021 16:06:14 +0800 Subject: [PATCH] Compile using sui --- .../org/meowcat/edxposed/manager/App.java | 4 + .../manager/ui/activity/BaseActivity.java | 50 +------ .../ui/fragment/CompileDialogFragment.java | 82 ++++++++++-- .../ui/fragment/StatusDialogBuilder.java | 1 - .../edxposed/manager/util/CompileUtil.java | 122 ++++++++++++++++-- .../android/content/pm/IPackageManager.java | 25 ++++ 6 files changed, 212 insertions(+), 72 deletions(-) create mode 100644 hiddenapi-stubs/src/main/java/android/content/pm/IPackageManager.java diff --git a/app/src/main/java/org/meowcat/edxposed/manager/App.java b/app/src/main/java/org/meowcat/edxposed/manager/App.java index 59ce6f50..4a8cb500 100644 --- a/app/src/main/java/org/meowcat/edxposed/manager/App.java +++ b/app/src/main/java/org/meowcat/edxposed/manager/App.java @@ -16,6 +16,8 @@ import androidx.preference.PreferenceManager; import org.meowcat.edxposed.manager.adapters.AppHelper; import org.meowcat.edxposed.manager.ui.activity.CrashReportActivity; +import org.meowcat.edxposed.manager.ui.fragment.CompileDialogFragment; +import org.meowcat.edxposed.manager.util.CompileUtil; import org.meowcat.edxposed.manager.util.ModuleUtil; import org.meowcat.edxposed.manager.util.NotificationUtil; import org.meowcat.edxposed.manager.util.RebootUtil; @@ -53,6 +55,8 @@ public class App extends Application implements Application.ActivityLifecycleCal private void onRequestPermissionsResult(int requestCode, int grantResult) { if (requestCode < 10) { RebootUtil.onRequestPermissionsResult(requestCode, grantResult); + } else { + CompileUtil.onRequestPermissionsResult(requestCode, grantResult); } } diff --git a/app/src/main/java/org/meowcat/edxposed/manager/ui/activity/BaseActivity.java b/app/src/main/java/org/meowcat/edxposed/manager/ui/activity/BaseActivity.java index 1880e0a4..e9764363 100644 --- a/app/src/main/java/org/meowcat/edxposed/manager/ui/activity/BaseActivity.java +++ b/app/src/main/java/org/meowcat/edxposed/manager/ui/activity/BaseActivity.java @@ -8,7 +8,6 @@ import android.content.res.Resources; import android.content.res.TypedArray; import android.os.Bundle; import android.view.MenuItem; -import android.widget.Toast; import androidx.annotation.NonNull; import androidx.annotation.Nullable; @@ -18,13 +17,12 @@ import androidx.appcompat.app.AppCompatDelegate; import androidx.core.content.ContextCompat; import com.google.android.material.dialog.MaterialAlertDialogBuilder; -import com.topjohnwu.superuser.Shell; import org.meowcat.edxposed.manager.App; import org.meowcat.edxposed.manager.R; +import org.meowcat.edxposed.manager.util.CompileUtil; import org.meowcat.edxposed.manager.util.CustomThemeColor; import org.meowcat.edxposed.manager.util.CustomThemeColors; -import org.meowcat.edxposed.manager.util.NavUtil; import org.meowcat.edxposed.manager.util.RebootUtil; import java.util.Objects; @@ -156,51 +154,9 @@ public class BaseActivity extends AppCompatActivity { public boolean onOptionsItemSelected(@NonNull MenuItem item) { int itemId = item.getItemId(); if (itemId == R.id.dexopt_all) { - areYouSure(R.string.take_while_cannot_resore, (dialog, which) -> { - new MaterialAlertDialogBuilder(this) - .setTitle(R.string.dexopt_now) - .setMessage(R.string.this_may_take_a_while) - .setCancelable(false) - .show(); - new Thread("dexopt") { - @Override - public void run() { - if (!Shell.rootAccess()) { - dialog.dismiss(); - NavUtil.showMessage(BaseActivity.this, getString(R.string.root_failed)); - return; - } - - Shell.su("cmd package bg-dexopt-job").exec(); - - dialog.dismiss(); - App.runOnUiThread(() -> Toast.makeText(BaseActivity.this, R.string.done, Toast.LENGTH_LONG).show()); - } - }.start(); - }); + CompileUtil.compileAllDexopt(this); } else if (itemId == R.id.speed_all) { - areYouSure(R.string.take_while_cannot_resore, (dialog, which) -> { - new MaterialAlertDialogBuilder(this) - .setTitle(R.string.speed_now) - .setMessage(R.string.this_may_take_a_while) - .setCancelable(false) - .show(); - new Thread("dex2oat") { - @Override - public void run() { - if (!Shell.rootAccess()) { - dialog.dismiss(); - NavUtil.showMessage(BaseActivity.this, getString(R.string.root_failed)); - return; - } - - Shell.su("cmd package compile -m speed -a").exec(); - - dialog.dismiss(); - App.runOnUiThread(() -> Toast.makeText(BaseActivity.this, R.string.done, Toast.LENGTH_LONG).show()); - } - }; - }); + CompileUtil.compileAllSpeed(this); } else if (itemId == R.id.reboot) { areYouSure(R.string.reboot, (dialog, which) -> RebootUtil.reboot(RebootUtil.RebootType.NORMAL)); } else if (itemId == R.id.soft_reboot) { diff --git a/app/src/main/java/org/meowcat/edxposed/manager/ui/fragment/CompileDialogFragment.java b/app/src/main/java/org/meowcat/edxposed/manager/ui/fragment/CompileDialogFragment.java index a426c391..e910c7be 100644 --- a/app/src/main/java/org/meowcat/edxposed/manager/ui/fragment/CompileDialogFragment.java +++ b/app/src/main/java/org/meowcat/edxposed/manager/ui/fragment/CompileDialogFragment.java @@ -16,19 +16,31 @@ import androidx.appcompat.app.AppCompatDialogFragment; import com.google.android.material.dialog.MaterialAlertDialogBuilder; import com.topjohnwu.superuser.Shell; +import org.meowcat.edxposed.manager.App; import org.meowcat.edxposed.manager.R; import org.meowcat.edxposed.manager.databinding.FragmentCompileDialogBinding; +import org.meowcat.edxposed.manager.util.CompileUtil; import org.meowcat.edxposed.manager.util.ToastUtil; import java.lang.ref.WeakReference; import java.util.ArrayList; import java.util.List; +import rikka.shizuku.ShizukuSystemProperties; + +import static android.content.pm.PackageManager.PERMISSION_GRANTED; + +@SuppressWarnings("deprecation") public class CompileDialogFragment extends AppCompatDialogFragment { + private static final String COMPILE_COMMAND_PREFIX = "cmd package "; + private static final String COMPILE_RESET_COMMAND = COMPILE_COMMAND_PREFIX + "compile --reset "; + private static final String COMPILE_SPEED_COMMAND = COMPILE_COMMAND_PREFIX + "compile -f -m speed "; + private static final String COMPILE_DEXOPT_COMMAND = COMPILE_COMMAND_PREFIX + "force-dex-opt "; + private static final String KEY_APP_INFO = "app_info"; private static final String KEY_MSG = "msg"; - private static final String KEY_COMMANDS = "commands"; + private static final String KEY_TYPE = "type"; private ApplicationInfo appInfo; @@ -36,11 +48,11 @@ public class CompileDialogFragment extends AppCompatDialogFragment { } public static CompileDialogFragment newInstance(ApplicationInfo appInfo, - String msg, String[] commands) { + String msg, CompileUtil.CompileType type) { Bundle arguments = new Bundle(); arguments.putParcelable(KEY_APP_INFO, appInfo); arguments.putString(KEY_MSG, msg); - arguments.putStringArray(KEY_COMMANDS, commands); + arguments.putInt(KEY_TYPE, type.ordinal()); CompileDialogFragment fragment = new CompileDialogFragment(); fragment.setArguments(arguments); fragment.setCancelable(false); @@ -72,28 +84,70 @@ public class CompileDialogFragment extends AppCompatDialogFragment { return alertDialog; } + public void onRequestPermissionsResult(int requestCode, int grantResult) { + CompileUtil.CompileType mode = CompileUtil.CompileType.values()[(requestCode - 1) / 10]; + if (grantResult == PERMISSION_GRANTED) { + AsyncTask.THREAD_POOL_EXECUTOR.execute(() -> { + try { + boolean checkProfiles = ShizukuSystemProperties.getBoolean("dalvik.vm.usejitprofiles", false); + switch (mode) { + case RESET: + CompileUtil.PACKAGE_MANAGER.get().clearApplicationProfileData(appInfo.packageName); + String filter = ShizukuSystemProperties.get("pm.dexopt.install"); + CompileUtil.PACKAGE_MANAGER.get().performDexOptMode(appInfo.packageName, checkProfiles, filter, true, true, null); + break; + case SPEED: + CompileUtil.PACKAGE_MANAGER.get().performDexOptMode(appInfo.packageName, checkProfiles, "speed", true, true, null); + break; + case DEXOPT: + CompileUtil.PACKAGE_MANAGER.get().forceDexOpt(appInfo.packageName); + break; + } + App.runOnUiThread(() -> { + ToastUtil.showLongToast(requireContext(), R.string.done); + dismiss(); + }); + } catch (Exception e) { + e.printStackTrace(); + compileWithShell(mode); + } + }); + } else { + compileWithShell(mode); + } + } + @Override public void onAttach(@NonNull Context context) { super.onAttach(context); Bundle arguments = getArguments(); if (arguments != null) { - String[] commandPrefixes = arguments.getStringArray(KEY_COMMANDS); + int type = arguments.getInt(KEY_TYPE); appInfo = arguments.getParcelable(KEY_APP_INFO); - if (commandPrefixes == null || commandPrefixes.length == 0 || appInfo == null) { - ToastUtil.showShortToast(context, R.string.empty_param); - dismissAllowingStateLoss(); - return; - } - String[] commands = new String[commandPrefixes.length]; - for (int i = 0; i < commandPrefixes.length; i++) { - commands[i] = commandPrefixes[i] + appInfo.packageName; - } - new CompileTask(this).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, commands); + type = type * 10 + 1; + if (App.checkPermission(type)) + onRequestPermissionsResult(type, PERMISSION_GRANTED); } else { dismissAllowingStateLoss(); } } + private void compileWithShell(CompileUtil.CompileType type) { + String command = null; + if (type == CompileUtil.CompileType.RESET) { + command = COMPILE_RESET_COMMAND + appInfo.packageName; + } else if (type == CompileUtil.CompileType.DEXOPT) { + command = COMPILE_DEXOPT_COMMAND + appInfo.packageName; + } else if (type == CompileUtil.CompileType.SPEED) { + command = COMPILE_SPEED_COMMAND + appInfo.packageName; + } + if (command != null) { + new CompileTask(this).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, command); + } else { + dismiss(); + } + } + private static class CompileTask extends AsyncTask { WeakReference outerRef; diff --git a/app/src/main/java/org/meowcat/edxposed/manager/ui/fragment/StatusDialogBuilder.java b/app/src/main/java/org/meowcat/edxposed/manager/ui/fragment/StatusDialogBuilder.java index fea97c1e..49da0c64 100644 --- a/app/src/main/java/org/meowcat/edxposed/manager/ui/fragment/StatusDialogBuilder.java +++ b/app/src/main/java/org/meowcat/edxposed/manager/ui/fragment/StatusDialogBuilder.java @@ -5,7 +5,6 @@ import android.content.Context; import android.os.Build; import android.util.Log; import android.view.LayoutInflater; -import android.view.View; import androidx.annotation.NonNull; import androidx.core.content.ContextCompat; diff --git a/app/src/main/java/org/meowcat/edxposed/manager/util/CompileUtil.java b/app/src/main/java/org/meowcat/edxposed/manager/util/CompileUtil.java index 16d82ce6..628c302c 100644 --- a/app/src/main/java/org/meowcat/edxposed/manager/util/CompileUtil.java +++ b/app/src/main/java/org/meowcat/edxposed/manager/util/CompileUtil.java @@ -1,43 +1,145 @@ package org.meowcat.edxposed.manager.util; +import android.annotation.SuppressLint; +import android.app.Activity; import android.content.Context; import android.content.pm.ApplicationInfo; +import android.content.pm.IPackageManager; +import android.os.AsyncTask; +import android.widget.Toast; +import androidx.appcompat.app.AlertDialog; import androidx.fragment.app.FragmentManager; +import com.google.android.material.dialog.MaterialAlertDialogBuilder; +import com.topjohnwu.superuser.Shell; + +import org.meowcat.edxposed.manager.App; import org.meowcat.edxposed.manager.R; import org.meowcat.edxposed.manager.ui.fragment.CompileDialogFragment; +import java.util.List; + +import rikka.shizuku.ShizukuBinderWrapper; +import rikka.shizuku.ShizukuSystemProperties; +import rikka.shizuku.SystemServiceHelper; + +import static android.content.pm.PackageManager.PERMISSION_GRANTED; + +@SuppressWarnings("deprecation") public class CompileUtil { - private static final String COMPILE_COMMAND_PREFIX = "cmd package "; - private static final String COMPILE_RESET_COMMAND = COMPILE_COMMAND_PREFIX + "compile --reset "; - private static final String COMPILE_SPEED_COMMAND = COMPILE_COMMAND_PREFIX + "compile -f -m speed "; - private static final String COMPILE_DEXOPT_COMMAND = COMPILE_COMMAND_PREFIX + "force-dex-opt "; + public enum CompileType { + RESET, + SPEED, + DEXOPT, + SPEED_ALL, + DEXOPT_ALL; + + @Override + public String toString() { + return super.toString().toLowerCase(); + } + } + + private static CompileDialogFragment instance; + private static final String TAG_COMPILE_DIALOG = "compile_dialog"; + public static final Singleton PACKAGE_MANAGER = new Singleton() { + @Override + protected IPackageManager create() { + return IPackageManager.Stub.asInterface(new ShizukuBinderWrapper(SystemServiceHelper.getSystemService("package"))); + } + }; + + @SuppressLint("StaticFieldLeak") + private static Activity sActivity; + + public static void onRequestPermissionsResult(int requestCode, int grantResult) { + CompileUtil.CompileType mode = CompileUtil.CompileType.values()[(requestCode - 1) / 10]; + if (mode == CompileType.DEXOPT_ALL || mode == CompileType.SPEED_ALL) { + AlertDialog dialog = new MaterialAlertDialogBuilder(sActivity) + .setTitle(R.string.speed_now) + .setMessage(R.string.this_may_take_a_while) + .setCancelable(false) + .show(); + AsyncTask.THREAD_POOL_EXECUTOR.execute(() -> { + if (grantResult == PERMISSION_GRANTED) { + try { + IPackageManager packageManager = PACKAGE_MANAGER.get(); + if (mode == CompileType.DEXOPT_ALL) { + packageManager.runBackgroundDexoptJob(null); + } else { + boolean checkProfiles = ShizukuSystemProperties.getBoolean("dalvik.vm.usejitprofiles", false); + List list = packageManager.getAllPackages(); + for (String packageName : list) { + CompileUtil.PACKAGE_MANAGER.get().performDexOptMode(packageName, checkProfiles, "speed", true, true, null); + } + } + dialog.dismiss(); + App.runOnUiThread(() -> Toast.makeText(sActivity, R.string.done, Toast.LENGTH_LONG).show()); + return; + } catch (Exception e) { + e.printStackTrace(); + } + } + if (!Shell.rootAccess()) { + dialog.dismiss(); + App.runOnUiThread(() -> Toast.makeText(sActivity, R.string.root_failed, Toast.LENGTH_LONG).show()); + return; + } + + if (mode == CompileType.SPEED_ALL) { + Shell.su("cmd package compile -m speed -a").exec(); + } else { + Shell.su("cmd package bg-dexopt-job").exec(); + } + + dialog.dismiss(); + App.runOnUiThread(() -> Toast.makeText(sActivity, R.string.done, Toast.LENGTH_LONG).show()); + }); + } else if (instance != null) { + instance.onRequestPermissionsResult(requestCode, grantResult); + } + } + public static void reset(Context context, FragmentManager fragmentManager, ApplicationInfo info) { compilePackageInBg(fragmentManager, info, - context.getString(R.string.compile_reset_msg), COMPILE_RESET_COMMAND); + context.getString(R.string.compile_reset_msg), CompileType.RESET); } public static void compileSpeed(Context context, FragmentManager fragmentManager, ApplicationInfo info) { compilePackageInBg(fragmentManager, info, - context.getString(R.string.compile_speed_msg), COMPILE_SPEED_COMMAND); + context.getString(R.string.compile_speed_msg), CompileType.SPEED); } public static void compileDexopt(Context context, FragmentManager fragmentManager, ApplicationInfo info) { compilePackageInBg(fragmentManager, info, - context.getString(R.string.compile_speed_msg), COMPILE_DEXOPT_COMMAND); + context.getString(R.string.compile_speed_msg), CompileType.DEXOPT); + } + + public static void compileAllDexopt(Activity activity) { + sActivity = activity; + int type = CompileType.DEXOPT_ALL.ordinal() * 10 + 1; + if (App.checkPermission(type)) + onRequestPermissionsResult(type, PERMISSION_GRANTED); + } + + public static void compileAllSpeed(Activity activity) { + sActivity = activity; + int type = CompileType.SPEED_ALL.ordinal() * 10 + 1; + if (App.checkPermission(type)) + onRequestPermissionsResult(type, PERMISSION_GRANTED); } private static void compilePackageInBg(FragmentManager fragmentManager, - ApplicationInfo info, String msg, String... commands) { - CompileDialogFragment fragment = CompileDialogFragment.newInstance(info, msg, commands); - fragment.show(fragmentManager, TAG_COMPILE_DIALOG); + ApplicationInfo info, String msg, CompileType type) { + instance = CompileDialogFragment.newInstance(info, msg, type); + instance.show(fragmentManager, TAG_COMPILE_DIALOG); } } diff --git a/hiddenapi-stubs/src/main/java/android/content/pm/IPackageManager.java b/hiddenapi-stubs/src/main/java/android/content/pm/IPackageManager.java new file mode 100644 index 00000000..15ae4ab8 --- /dev/null +++ b/hiddenapi-stubs/src/main/java/android/content/pm/IPackageManager.java @@ -0,0 +1,25 @@ +package android.content.pm; + +import android.os.Binder; +import android.os.IBinder; +import android.os.IInterface; +import android.os.RemoteException; + +import java.util.List; + +public interface IPackageManager extends IInterface { + + void forceDexOpt(String packageName) throws RemoteException; + boolean performDexOptMode(String packageName, boolean checkProfiles, + String targetCompilerFilter, boolean force, boolean bootComplete, String splitName) throws RemoteException; + void clearApplicationProfileData(String packageName) throws RemoteException; + List getAllPackages() throws RemoteException; + boolean runBackgroundDexoptJob(List packageNames) throws RemoteException; + + abstract class Stub extends Binder implements IPackageManager { + + public static IPackageManager asInterface(IBinder obj) { + throw new UnsupportedOperationException(); + } + } +}