[app] Start and query activity from backend

This commit is contained in:
tehcneko 2021-05-21 14:37:15 +08:00 committed by LoveSy
parent 15775da810
commit e2bb7d42f2
11 changed files with 115 additions and 53 deletions

View File

@ -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<ResolveInfo> queryIntentActivitiesAsUser(Intent intent, int flags, int userId) {
List<ResolveInfo> list = new ArrayList<>();
try {
list.addAll(LSPManagerServiceClient.queryIntentActivitiesAsUser(intent, flags, userId).getList());
} catch (Throwable e) {
Log.e(App.TAG, Log.getStackTraceString(e));
}
return list;
}
}

View File

@ -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<PackageInfo> 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<ResolveInfo> 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<ResolveInfo> 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<ResolveInfo> ris = (List<ResolveInfo>) queryIntentActivitiesAsUserMethod.invoke(packageManager, intentToResolve, 0, userId);
if (ris == null || ris.size() <= 0) {
return null;
}
List<ResolveInfo> 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) {

View File

@ -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<ScopeAdapter.ViewHolder>
private final ModuleUtil moduleUtil;
private final ModuleUtil.InstalledModule module;
private final UserHandle userHandle;
private final HashSet<ApplicationWithEquals> recommendedList = new HashSet<>();
private final HashSet<ApplicationWithEquals> checkedList = new HashSet<>();
@ -136,10 +134,9 @@ public class ScopeAdapter extends RecyclerView.Adapter<ScopeAdapter.ViewHolder>
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<ScopeAdapter.ViewHolder>
} 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<ScopeAdapter.ViewHolder>
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<ScopeAdapter.ViewHolder>
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<ScopeAdapter.ViewHolder>
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);
}

View File

@ -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<ResolveInfo> queryIntentActivitiesAsUser(Intent intent, int flags, int userId) throws RemoteException, NullPointerException {
ensureService();
return service.queryIntentActivitiesAsUser(intent, flags, userId);
}
}

View File

@ -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);

View File

@ -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);

View File

@ -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" />
</androidx.coordinatorlayout.widget.CoordinatorLayout>

View File

@ -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);
}
}

View File

@ -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<ResolveInfo> queryIntentActivitiesAsUser(Intent intent, int flags, int userId) throws RemoteException {
return PackageService.queryIntentActivities(intent, intent.getType(), flags, userId);
}
}

View File

@ -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<Integer, PackageInfo> getPackageInfoFromAllUsers(String packageName, int flags) throws RemoteException {
public static @NonNull
Map<Integer, PackageInfo> getPackageInfoFromAllUsers(String packageName, int flags) throws RemoteException {
IPackageManager pm = getPackageManager();
Map<Integer, PackageInfo> 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<ResolveInfo> 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<ResolveInfo>(pm.queryIntentActivities(intent, resolvedType, flags, userId).getList());
}
@SuppressWarnings("JavaReflectionMemberAccess")

View File

@ -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<ResolveInfo> queryIntentActivitiesAsUser(in Intent intent, int flags, int userId) = 31;
}