diff --git a/app/src/main/java/org/lsposed/manager/ConfigManager.java b/app/src/main/java/org/lsposed/manager/ConfigManager.java index 94b7fcc6..15fc83d8 100644 --- a/app/src/main/java/org/lsposed/manager/ConfigManager.java +++ b/app/src/main/java/org/lsposed/manager/ConfigManager.java @@ -19,8 +19,10 @@ package org.lsposed.manager; +import android.content.Intent; import android.content.pm.PackageInfo; import android.content.pm.PackageManager; +import android.content.pm.ResolveInfo; import android.os.ParcelFileDescriptor; import android.os.RemoteException; import android.util.Log; @@ -262,4 +264,23 @@ public class ConfigManager { return false; } } + + public static int startActivityAsUserWithFeature(Intent intent, int userId) { + try { + return LSPManagerServiceClient.startActivityAsUserWithFeature(intent, userId); + } catch (Throwable e) { + Log.e(App.TAG, Log.getStackTraceString(e)); + return -1; + } + } + + public static List queryIntentActivitiesAsUser(Intent intent, int flags, int userId) { + List list = new ArrayList<>(); + try { + list.addAll(LSPManagerServiceClient.queryIntentActivitiesAsUser(intent, flags, userId).getList()); + } catch (Throwable e) { + Log.e(App.TAG, Log.getStackTraceString(e)); + } + return list; + } } diff --git a/app/src/main/java/org/lsposed/manager/adapters/AppHelper.java b/app/src/main/java/org/lsposed/manager/adapters/AppHelper.java index ae1051f4..34e37280 100644 --- a/app/src/main/java/org/lsposed/manager/adapters/AppHelper.java +++ b/app/src/main/java/org/lsposed/manager/adapters/AppHelper.java @@ -20,20 +20,17 @@ package org.lsposed.manager.adapters; -import android.app.Activity; import android.content.Intent; import android.content.SharedPreferences; import android.content.pm.ApplicationInfo; import android.content.pm.PackageInfo; import android.content.pm.PackageManager; import android.content.pm.ResolveInfo; -import android.os.UserHandle; import android.view.MenuItem; import org.lsposed.manager.ConfigManager; import org.lsposed.manager.R; -import java.lang.reflect.Method; import java.util.Collections; import java.util.Comparator; import java.util.List; @@ -44,44 +41,62 @@ public class AppHelper { private static List appList; public static Intent getSettingsIntent(String packageName, int userId, PackageManager packageManager) { - Intent intent = getIntentForCategory(packageName, userId, packageManager, SETTINGS_CATEGORY); - if (intent != null) { - return intent; + Intent intentToResolve = new Intent(Intent.ACTION_MAIN); + intentToResolve.addCategory(SETTINGS_CATEGORY); + intentToResolve.setPackage(packageName); + + List ris = ConfigManager.queryIntentActivitiesAsUser(intentToResolve, 0, userId); + + if (ris.size() <= 0) { + return getLaunchIntentForPackage(packageName, userId); } - return getIntentForCategory(packageName, userId, packageManager, Intent.CATEGORY_LAUNCHER); + + Intent intent = new Intent(intentToResolve); + intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + intent.setClassName(ris.get(0).activityInfo.packageName, + ris.get(0).activityInfo.name); + return intent; } - public static void startActivityAsUser(Activity activity, Intent intent, UserHandle user) { - try { - //noinspection JavaReflectionMemberAccess - var startActivityAsUserMethod = Activity.class.getMethod("startActivityAsUser", Intent.class, UserHandle.class); - startActivityAsUserMethod.invoke(activity, intent, user); - } catch (Throwable t) { - t.printStackTrace(); + public static Intent getLaunchIntentForPackage(String packageName, int userId) { + Intent intentToResolve = new Intent(Intent.ACTION_MAIN); + intentToResolve.addCategory(Intent.CATEGORY_INFO); + intentToResolve.setPackage(packageName); + List ris = ConfigManager.queryIntentActivitiesAsUser(intentToResolve, 0, userId); + + if (ris.size() <= 0) { + intentToResolve.removeCategory(Intent.CATEGORY_INFO); + intentToResolve.addCategory(Intent.CATEGORY_LAUNCHER); + intentToResolve.setPackage(packageName); + ris = ConfigManager.queryIntentActivitiesAsUser(intentToResolve, 0, userId); } + + if (ris.size() <= 0) { + return null; + } + + Intent intent = new Intent(intentToResolve); + intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + intent.setClassName(ris.get(0).activityInfo.packageName, + ris.get(0).activityInfo.name); + return intent; } public static Intent getIntentForCategory(String packageName, int userId, PackageManager packageManager, String category) { Intent intentToResolve = new Intent(Intent.ACTION_MAIN); intentToResolve.addCategory(category); intentToResolve.setPackage(packageName); - try { - //noinspection JavaReflectionMemberAccess - Method queryIntentActivitiesAsUserMethod = PackageManager.class.getMethod("queryIntentActivitiesAsUser", Intent.class, int.class, int.class); - //noinspection unchecked - List ris = (List) queryIntentActivitiesAsUserMethod.invoke(packageManager, intentToResolve, 0, userId); - if (ris == null || ris.size() <= 0) { - return null; - } + List ris = ConfigManager.queryIntentActivitiesAsUser(intentToResolve, 0, userId); - Intent intent = new Intent(intentToResolve); - intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); - intent.setClassName(ris.get(0).activityInfo.packageName, ris.get(0).activityInfo.name); - return intent; - } catch (Throwable t) { + if (ris.size() <= 0) { return null; } + + Intent intent = new Intent(intentToResolve); + intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + intent.setClassName(ris.get(0).activityInfo.packageName, ris.get(0).activityInfo.name); + return intent; } public static boolean onOptionsItemSelected(MenuItem item, SharedPreferences preferences) { diff --git a/app/src/main/java/org/lsposed/manager/adapters/ScopeAdapter.java b/app/src/main/java/org/lsposed/manager/adapters/ScopeAdapter.java index 2b5ce3a9..e06cccb5 100644 --- a/app/src/main/java/org/lsposed/manager/adapters/ScopeAdapter.java +++ b/app/src/main/java/org/lsposed/manager/adapters/ScopeAdapter.java @@ -35,7 +35,6 @@ import android.os.Build; import android.os.Handler; import android.os.HandlerThread; import android.os.Message; -import android.os.UserHandle; import android.text.Spannable; import android.text.SpannableStringBuilder; import android.text.TextUtils; @@ -101,7 +100,6 @@ public class ScopeAdapter extends RecyclerView.Adapter private final ModuleUtil moduleUtil; private final ModuleUtil.InstalledModule module; - private final UserHandle userHandle; private final HashSet recommendedList = new HashSet<>(); private final HashSet checkedList = new HashSet<>(); @@ -136,10 +134,9 @@ public class ScopeAdapter extends RecyclerView.Adapter private boolean refreshing = false; private boolean enabled = true; - public ScopeAdapter(AppListActivity activity, ModuleUtil.InstalledModule module, UserHandle userHandle) { + public ScopeAdapter(AppListActivity activity, ModuleUtil.InstalledModule module) { this.activity = activity; this.module = module; - this.userHandle = userHandle; moduleUtil = ModuleUtil.getInstance(); HandlerThread handlerThread = new HandlerThread("appList"); handlerThread.start(); @@ -260,7 +257,7 @@ public class ScopeAdapter extends RecyclerView.Adapter } else if (itemId == R.id.menu_launch) { Intent launchIntent = AppHelper.getSettingsIntent(module.packageName, module.userId, pm); if (launchIntent != null) { - AppHelper.startActivityAsUser(activity, launchIntent, userHandle); + ConfigManager.startActivityAsUserWithFeature(launchIntent, module.userId); } else { activity.makeSnackBar(R.string.module_no_ui, Snackbar.LENGTH_LONG); } @@ -293,7 +290,7 @@ public class ScopeAdapter extends RecyclerView.Adapter if (itemId == R.id.menu_launch) { Intent launchIntent = pm.getLaunchIntentForPackage(info.packageName); if (launchIntent != null) { - AppHelper.startActivityAsUser(activity, launchIntent, userHandle); + ConfigManager.startActivityAsUserWithFeature(launchIntent, module.userId); } } else if (itemId == R.id.menu_compile_speed) { CompileDialogFragment.speed(activity.getSupportFragmentManager(), info); @@ -307,7 +304,7 @@ public class ScopeAdapter extends RecyclerView.Adapter e.printStackTrace(); } } else if (itemId == R.id.menu_app_info) { - AppHelper.startActivityAsUser(activity, new Intent(ACTION_APPLICATION_DETAILS_SETTINGS, Uri.fromParts("package", info.packageName, null)), userHandle); + ConfigManager.startActivityAsUserWithFeature(new Intent(ACTION_APPLICATION_DETAILS_SETTINGS, Uri.fromParts("package", info.packageName, null)), module.userId); } else if (itemId == R.id.menu_force_stop) { if (info.packageName.equals("android")) { ConfigManager.reboot(false, null, false); @@ -416,7 +413,7 @@ public class ScopeAdapter extends RecyclerView.Adapter holder.itemView.setOnCreateContextMenuListener((menu, v, menuInfo) -> { activity.getMenuInflater().inflate(R.menu.menu_app_item, menu); menu.setHeaderTitle(appName); - Intent launchIntent = AppHelper.getIntentForCategory(appInfo.packageName, userId, pm, Intent.CATEGORY_LAUNCHER); + Intent launchIntent = AppHelper.getLaunchIntentForPackage(appInfo.packageName, userId); if (launchIntent == null) { menu.removeItem(R.id.menu_launch); } diff --git a/app/src/main/java/org/lsposed/manager/receivers/LSPManagerServiceClient.java b/app/src/main/java/org/lsposed/manager/receivers/LSPManagerServiceClient.java index 0e49a89d..0a11d485 100644 --- a/app/src/main/java/org/lsposed/manager/receivers/LSPManagerServiceClient.java +++ b/app/src/main/java/org/lsposed/manager/receivers/LSPManagerServiceClient.java @@ -19,7 +19,9 @@ package org.lsposed.manager.receivers; +import android.content.Intent; import android.content.pm.PackageInfo; +import android.content.pm.ResolveInfo; import android.os.IBinder; import android.os.ParcelFileDescriptor; import android.os.RemoteException; @@ -168,4 +170,14 @@ public class LSPManagerServiceClient { ensureService(); return service.systemServerRequested(); } + + public static int startActivityAsUserWithFeature(Intent intent, int userId) throws RemoteException, NullPointerException { + ensureService(); + return service.startActivityAsUserWithFeature(intent, userId); + } + + public static ParceledListSlice queryIntentActivitiesAsUser(Intent intent, int flags, int userId) throws RemoteException, NullPointerException { + ensureService(); + return service.queryIntentActivitiesAsUser(intent, flags, userId); + } } diff --git a/app/src/main/java/org/lsposed/manager/ui/activity/AppListActivity.java b/app/src/main/java/org/lsposed/manager/ui/activity/AppListActivity.java index a46dbed2..3aa4c6df 100644 --- a/app/src/main/java/org/lsposed/manager/ui/activity/AppListActivity.java +++ b/app/src/main/java/org/lsposed/manager/ui/activity/AppListActivity.java @@ -23,7 +23,6 @@ package org.lsposed.manager.ui.activity; import android.content.Intent; import android.os.AsyncTask; import android.os.Bundle; -import android.os.UserHandle; import android.view.Menu; import android.view.MenuItem; @@ -65,7 +64,6 @@ public class AppListActivity extends BaseActivity { super.onCreate(savedInstanceState); String modulePackageName = getIntent().getStringExtra("modulePackageName"); int moduleUserId = getIntent().getIntExtra("moduleUserId", -1); - UserHandle userHandle = getIntent().getParcelableExtra("userHandle"); binding = ActivityAppListBinding.inflate(getLayoutInflater()); setContentView(binding.getRoot()); setAppBar(binding.appBar, binding.toolbar); @@ -86,7 +84,7 @@ public class AppListActivity extends BaseActivity { } bar.setSubtitle(module.packageName); } - scopeAdapter = new ScopeAdapter(this, module, userHandle); + scopeAdapter = new ScopeAdapter(this, module); scopeAdapter.setHasStableIds(true); binding.recyclerView.setAdapter(scopeAdapter); binding.recyclerView.setHasFixedSize(true); diff --git a/app/src/main/java/org/lsposed/manager/ui/activity/ModulesActivity.java b/app/src/main/java/org/lsposed/manager/ui/activity/ModulesActivity.java index 9652cac8..c345744b 100644 --- a/app/src/main/java/org/lsposed/manager/ui/activity/ModulesActivity.java +++ b/app/src/main/java/org/lsposed/manager/ui/activity/ModulesActivity.java @@ -65,7 +65,6 @@ import androidx.viewpager2.widget.ViewPager2; import com.bumptech.glide.request.target.CustomTarget; import com.bumptech.glide.request.transition.Transition; import com.google.android.material.checkbox.MaterialCheckBox; -import com.google.android.material.floatingactionbutton.FloatingActionButton; import com.google.android.material.snackbar.Snackbar; import com.google.android.material.tabs.TabLayoutMediator; @@ -108,7 +107,6 @@ public class ModulesActivity extends BaseActivity implements ModuleUtil.ModuleLi private PackageManager pm; private ModuleUtil moduleUtil; private ModuleUtil.InstalledModule selectedModule; - private UserHandle selectedModuleUser; private UserManager userManager; @Override @@ -305,7 +303,7 @@ public class ModulesActivity extends BaseActivity implements ModuleUtil.ModuleLi } Intent intent = AppHelper.getSettingsIntent(packageName, module.userId, pm); if (intent != null) { - AppHelper.startActivityAsUser(this, intent, selectedModuleUser); + ConfigManager.startActivityAsUserWithFeature(intent, module.userId); } else { Snackbar.make(binding.snackbar, R.string.module_no_ui, Snackbar.LENGTH_LONG).show(); } @@ -321,7 +319,7 @@ public class ModulesActivity extends BaseActivity implements ModuleUtil.ModuleLi } return true; } else if (itemId == R.id.menu_app_info) { - AppHelper.startActivityAsUser(this, (new Intent(ACTION_APPLICATION_DETAILS_SETTINGS, Uri.fromParts("package", module.packageName, null))), selectedModuleUser); + ConfigManager.startActivityAsUserWithFeature(new Intent(ACTION_APPLICATION_DETAILS_SETTINGS, Uri.fromParts("package", module.packageName, null)), module.userId); return true; } else if (itemId == R.id.menu_uninstall) { new AlertDialog.Builder(this) @@ -504,9 +502,12 @@ public class ModulesActivity extends BaseActivity implements ModuleUtil.ModuleLi menu.removeItem(R.id.menu_app_info); } if (item.userId == 0) { - for (int profile : ConfigManager.getUsers()) { - if (ModuleUtil.getInstance().getModule(item.packageName, profile) == null) { - menu.add(1, profile, 0, getString(R.string.install_to_user, profile)); + int[] users = ConfigManager.getUsers(); + if (users != null) { + for (int profile : users) { + if (ModuleUtil.getInstance().getModule(item.packageName, profile) == null) { + menu.add(1, profile, 0, getString(R.string.install_to_user, profile)); + } } } } @@ -518,13 +519,11 @@ public class ModulesActivity extends BaseActivity implements ModuleUtil.ModuleLi Intent intent = new Intent(ModulesActivity.this, AppListActivity.class); intent.putExtra("modulePackageName", item.packageName); intent.putExtra("moduleUserId", item.userId); - intent.putExtra("userHandle", userHandle); startActivity(intent); }); holder.itemView.setOnLongClickListener(v -> { selectedModule = item; - selectedModuleUser = userHandle; return false; }); holder.appVersion.setVisibility(View.VISIBLE); diff --git a/app/src/main/res/layout/activity_module_detail.xml b/app/src/main/res/layout/activity_module_detail.xml index d5f1b792..0dab6ac7 100644 --- a/app/src/main/res/layout/activity_module_detail.xml +++ b/app/src/main/res/layout/activity_module_detail.xml @@ -69,6 +69,8 @@ android:src="@drawable/ic_baseline_add_24" android:layout_margin="16dp" android:visibility="invisible" + android:outlineAmbientShadowColor="?colorAccent" + android:outlineSpotShadowColor="?colorAccent" app:layout_fitsSystemWindowsInsets="bottom" android:contentDescription="@string/add_module_to_user" /> diff --git a/core/src/main/java/org/lsposed/lspd/service/ActivityManagerService.java b/core/src/main/java/org/lsposed/lspd/service/ActivityManagerService.java index d28475dd..dff1cce2 100644 --- a/core/src/main/java/org/lsposed/lspd/service/ActivityManagerService.java +++ b/core/src/main/java/org/lsposed/lspd/service/ActivityManagerService.java @@ -119,16 +119,16 @@ public class ActivityManagerService { return am.unbindService(connection); } - public static int startActivityAsUserWithFeature(IApplicationThread caller, String callingPackage, + public static int startActivityAsUserWithFeature(String callingPackage, String callingFeatureId, Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode, int flags, ProfilerInfo profilerInfo, Bundle options, int userId) throws RemoteException { IActivityManager am = getActivityManager(); if (am == null || thread == null) return -1; if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) { - return am.startActivityAsUserWithFeature(caller, callingPackage, callingFeatureId, intent, resolvedType, resultTo, resultWho, requestCode, flags, profilerInfo, options, userId); + return am.startActivityAsUserWithFeature(thread, callingPackage, callingFeatureId, intent, resolvedType, resultTo, resultWho, requestCode, flags, profilerInfo, options, userId); } else { - return am.startActivityAsUser(caller, callingPackage, intent, resolvedType, resultTo, resultWho, requestCode, flags, profilerInfo, options, userId); + return am.startActivityAsUser(thread, callingPackage, intent, resolvedType, resultTo, resultWho, requestCode, flags, profilerInfo, options, userId); } } diff --git a/core/src/main/java/org/lsposed/lspd/service/LSPManagerService.java b/core/src/main/java/org/lsposed/lspd/service/LSPManagerService.java index 911114c3..c4b1e3b2 100644 --- a/core/src/main/java/org/lsposed/lspd/service/LSPManagerService.java +++ b/core/src/main/java/org/lsposed/lspd/service/LSPManagerService.java @@ -26,6 +26,7 @@ import android.content.ComponentName; import android.content.Intent; import android.content.pm.PackageInfo; import android.content.pm.PackageManager; +import android.content.pm.ResolveInfo; import android.content.pm.VersionedPackage; import android.os.IBinder; import android.os.ParcelFileDescriptor; @@ -226,4 +227,14 @@ public class LSPManagerService extends ILSPManagerService.Stub { public boolean systemServerRequested() throws RemoteException { return ServiceManager.systemServerRequested(); } + + @Override + public int startActivityAsUserWithFeature(Intent intent, int userId) throws RemoteException { + return ActivityManagerService.startActivityAsUserWithFeature("android", null, intent, intent.getType(), null, null, 0, 0, null, null, userId); + } + + @Override + public ParceledListSlice queryIntentActivitiesAsUser(Intent intent, int flags, int userId) throws RemoteException { + return PackageService.queryIntentActivities(intent, intent.getType(), flags, userId); + } } diff --git a/core/src/main/java/org/lsposed/lspd/service/PackageService.java b/core/src/main/java/org/lsposed/lspd/service/PackageService.java index e23f4fee..013948fe 100644 --- a/core/src/main/java/org/lsposed/lspd/service/PackageService.java +++ b/core/src/main/java/org/lsposed/lspd/service/PackageService.java @@ -33,6 +33,7 @@ import android.content.pm.IPackageManager; import android.content.pm.PackageInfo; import android.content.pm.PackageInstaller; import android.content.pm.PackageManager; +import android.content.pm.ResolveInfo; import android.content.pm.ServiceInfo; import android.content.pm.VersionedPackage; import android.os.Build; @@ -106,7 +107,8 @@ public class PackageService { return pm.getPackageInfo(packageName, flags, userId); } - public static @NonNull Map getPackageInfoFromAllUsers(String packageName, int flags) throws RemoteException { + public static @NonNull + Map getPackageInfoFromAllUsers(String packageName, int flags) throws RemoteException { IPackageManager pm = getPackageManager(); Map res = new HashMap<>(); if (pm == null) return res; @@ -269,10 +271,11 @@ public class PackageService { } } - public static android.content.pm.ParceledListSlice queryIntentActivities(android.content.Intent intent, java.lang.String resolvedType, int flags, int userId) throws RemoteException { + public static ParceledListSlice queryIntentActivities(android.content.Intent intent, java.lang.String resolvedType, int flags, int userId) throws RemoteException { IPackageManager pm = getPackageManager(); if (pm == null) return null; - return pm.queryIntentActivities(intent, resolvedType, flags, userId); + //noinspection unchecked + return new ParceledListSlice(pm.queryIntentActivities(intent, resolvedType, flags, userId).getList()); } @SuppressWarnings("JavaReflectionMemberAccess") diff --git a/manager-service/src/main/aidl/org/lsposed/lspd/ILSPManagerService.aidl b/manager-service/src/main/aidl/org/lsposed/lspd/ILSPManagerService.aidl index fd0651b3..87b4f987 100644 --- a/manager-service/src/main/aidl/org/lsposed/lspd/ILSPManagerService.aidl +++ b/manager-service/src/main/aidl/org/lsposed/lspd/ILSPManagerService.aidl @@ -52,4 +52,8 @@ interface ILSPManagerService { int installExistingPackageAsUser(String packageName, int userId) = 28; boolean systemServerRequested() = 29; + + int startActivityAsUserWithFeature(in Intent intent, int userId) = 30; + + ParceledListSlice queryIntentActivitiesAsUser(in Intent intent, int flags, int userId) = 31; }