[core] Recognize module from other user profile (#555)

Co-authored-by: tehcneko <7764726+tehcneko@users.noreply.github.com>
This commit is contained in:
LoveSy 2021-05-14 16:28:12 +08:00 committed by GitHub
parent b0f3c4d0bb
commit dbc0226d66
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
17 changed files with 232 additions and 60 deletions

View File

@ -183,9 +183,9 @@ public class ConfigManager {
}
}
public static PackageInfo getPackageInfo(String packageName, int flags) throws PackageManager.NameNotFoundException {
public static PackageInfo getPackageInfo(String packageName, int flags, int userId) throws PackageManager.NameNotFoundException {
try {
return LSPosedManagerServiceClient.getPackageInfo(packageName, flags, 0);
return LSPosedManagerServiceClient.getPackageInfo(packageName, flags, userId);
} catch (RemoteException | NullPointerException e) {
Log.e(App.TAG, Log.getStackTraceString(e));
throw new PackageManager.NameNotFoundException();
@ -230,6 +230,15 @@ public class ConfigManager {
}
}
public static int[] getUsers() {
try {
return LSPosedManagerServiceClient.getUsers();
} catch (RemoteException | NullPointerException e) {
Log.e(App.TAG, Log.getStackTraceString(e));
return null;
}
}
public static boolean isMagiskInstalled() {
return Arrays.stream(System.getenv("PATH").split(File.pathSeparator))
.anyMatch(str -> new File(str, "magisk").exists());

View File

@ -40,12 +40,13 @@ public class AppHelper {
public static final String SETTINGS_CATEGORY = "de.robv.android.xposed.category.MODULE_SETTINGS";
private static List<PackageInfo> appList;
public static Intent getSettingsIntent(String packageName, PackageManager packageManager) {
public static Intent getSettingsIntent(String packageName, int userId, PackageManager packageManager) {
// taken from
// ApplicationPackageManager.getLaunchIntentForPackage(String)
// first looks for an Xposed-specific category, falls back to
// getLaunchIntentForPackage
//TODO:multiuser
Intent intentToResolve = new Intent(Intent.ACTION_MAIN);
intentToResolve.addCategory(SETTINGS_CATEGORY);
intentToResolve.setPackage(packageName);

View File

@ -151,6 +151,9 @@ public class ScopeAdapter extends RecyclerView.Adapter<ScopeAdapter.ViewHolder>
}
private boolean shouldHideApp(PackageInfo info, ApplicationWithEquals app) {
if (app.userId != module.userId) {
return true;
}
if (info.packageName.equals(this.module.packageName)) {
return true;
}
@ -251,7 +254,7 @@ public class ScopeAdapter extends RecyclerView.Adapter<ScopeAdapter.ViewHolder>
item.setChecked(!item.isChecked());
preferences.edit().putBoolean("filter_modules", item.isChecked()).apply();
} else if (itemId == R.id.menu_launch) {
Intent launchIntent = AppHelper.getSettingsIntent(module.packageName, pm);
Intent launchIntent = AppHelper.getSettingsIntent(module.packageName, module.userId, pm);
if (launchIntent != null) {
activity.startActivity(launchIntent);
} else {
@ -320,7 +323,7 @@ public class ScopeAdapter extends RecyclerView.Adapter<ScopeAdapter.ViewHolder>
public void onCreateOptionsMenu(@NonNull Menu menu, @NonNull MenuInflater inflater) {
inflater.inflate(R.menu.menu_app_list, menu);
Intent intent = AppHelper.getSettingsIntent(module.packageName, pm);
Intent intent = AppHelper.getSettingsIntent(module.packageName, module.userId, pm);
if (intent == null) {
menu.removeItem(R.id.menu_launch);
}
@ -366,11 +369,7 @@ public class ScopeAdapter extends RecyclerView.Adapter<ScopeAdapter.ViewHolder>
boolean android = appInfo.packageName.equals("android");
CharSequence appName;
int userId = appInfo.applicationInfo.uid / 100000;
if (userId != 0) {
appName = String.format("%s (%s)", appInfo.label, userId);
} else {
appName = android ? activity.getString(R.string.android_framework) : appInfo.label;
}
appName = android ? activity.getString(R.string.android_framework) : appInfo.label;
holder.appName.setText(appName);
GlideApp.with(holder.appIcon)
.load(appInfo.packageInfo)

View File

@ -153,4 +153,9 @@ public class LSPosedManagerServiceClient {
ensureService();
return service.isSepolicyLoaded();
}
public static int[] getUsers() throws RemoteException, NullPointerException {
ensureService();
return service.getUsers();
}
}

View File

@ -37,20 +37,21 @@ public class ServiceReceiver extends BroadcastReceiver {
@Override
public void onReceive(final Context context, final Intent intent) {
int userId = intent.getIntExtra(Intent.EXTRA_USER, 0);
String packageName = getPackageName(intent);
if (packageName == null) {
return;
}
ModuleUtil.InstalledModule module = ModuleUtil.getInstance().reloadSingleModule(packageName);
ModuleUtil.InstalledModule module = ModuleUtil.getInstance().reloadSingleModule(packageName, userId);
if (module == null) {
return;
}
if (intent.getAction().equals("org.lsposed.action.MODULE_NOT_ACTIVATAED")) {
NotificationUtil.showNotification(context, packageName, module.getAppName(), false);
NotificationUtil.showNotification(context, packageName, module.getAppName(), userId, false);
} else if (intent.getAction().equals("org.lsposed.action.MODULE_UPDATED")) {
NotificationUtil.showNotification(context, packageName, module.getAppName(), true);
NotificationUtil.showNotification(context, packageName, module.getAppName(), userId, true);
}
}
}

View File

@ -61,12 +61,13 @@ public class AppListActivity extends BaseActivity {
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
String modulePackageName = getIntent().getStringExtra("modulePackageName");
int moduleUserId = getIntent().getIntExtra("moduleUserId", -1);
binding = ActivityAppListBinding.inflate(getLayoutInflater());
setContentView(binding.getRoot());
setAppBar(binding.appBar, binding.toolbar);
binding.appBar.setRaised(true);
binding.toolbar.setNavigationOnClickListener(view -> onBackPressed());
ModuleUtil.InstalledModule module = ModuleUtil.getInstance().getModule(modulePackageName);
ModuleUtil.InstalledModule module = ModuleUtil.getInstance().getModule(modulePackageName, moduleUserId);
if (module == null) {
finish();
return;

View File

@ -45,40 +45,57 @@ import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Filter;
import android.widget.Filterable;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.ActionBar;
import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.widget.SearchView;
import androidx.core.content.ContextCompat;
import androidx.lifecycle.Lifecycle;
import androidx.recyclerview.widget.RecyclerView;
import androidx.viewpager2.widget.ViewPager2;
import com.bumptech.glide.request.target.CustomTarget;
import com.bumptech.glide.request.transition.Transition;
import com.google.android.material.snackbar.Snackbar;
import com.google.android.material.tabs.TabLayoutMediator;
import org.lsposed.manager.ConfigManager;
import org.lsposed.manager.R;
import org.lsposed.manager.adapters.AppHelper;
import org.lsposed.manager.databinding.ActivityModuleDetailBinding;
import org.lsposed.manager.databinding.ItemRepoRecyclerviewBinding;
import org.lsposed.manager.repo.RepoLoader;
import org.lsposed.manager.ui.activity.base.ListActivity;
import org.lsposed.manager.ui.activity.base.BaseActivity;
import org.lsposed.manager.util.GlideApp;
import org.lsposed.manager.util.LinearLayoutManagerFix;
import org.lsposed.manager.util.ModuleUtil;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.stream.Collectors;
public class ModulesActivity extends ListActivity implements ModuleUtil.ModuleListener {
import rikka.recyclerview.RecyclerViewKt;
import rikka.widget.borderview.BorderRecyclerView;
import rikka.widget.borderview.BorderView;
public class ModulesActivity extends BaseActivity implements ModuleUtil.ModuleListener {
protected ActivityModuleDetailBinding binding;
protected SearchView searchView;
private SearchView.OnQueryTextListener mSearchListener;
private final ArrayList<ModuleAdapter> adapters = new ArrayList<>();
private static final Handler uninstallHandler;
private PackageManager pm;
private ModuleUtil moduleUtil;
private ModuleAdapter adapter = null;
private String selectedPackageName;
private ModuleUtil.InstalledModule selectedModule;
static {
HandlerThread uninstallThread = new HandlerThread("uninstall");
@ -88,20 +105,89 @@ public class ModulesActivity extends ListActivity implements ModuleUtil.ModuleLi
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
binding = ActivityModuleDetailBinding.inflate(getLayoutInflater());
setContentView(binding.getRoot());
setAppBar(binding.appBar, binding.toolbar);
binding.getRoot().bringChildToFront(binding.appBar);
binding.toolbar.setNavigationOnClickListener(view -> onBackPressed());
ActionBar bar = getSupportActionBar();
if (bar != null) {
bar.setDisplayHomeAsUpEnabled(true);
}
binding.viewPager.setAdapter(new PagerAdapter());
binding.viewPager.registerOnPageChangeCallback(new ViewPager2.OnPageChangeCallback() {
@Override
public void onPageSelected(int position) {
BorderRecyclerView recyclerView = findViewById(R.id.recyclerView);
if (recyclerView != null) {
binding.appBar.setRaised(!recyclerView.getBorderViewDelegate().isShowingTopBorder());
}
}
});
mSearchListener = new SearchView.OnQueryTextListener() {
@Override
public boolean onQueryTextSubmit(String query) {
adapters.forEach(adapter -> {
adapter.getFilter().filter(query);
});
return false;
}
@Override
public boolean onQueryTextChange(String newText) {
adapters.forEach(adapter -> {
adapter.getFilter().filter(newText);
});
return false;
}
};
moduleUtil = ModuleUtil.getInstance();
pm = getPackageManager();
moduleUtil.addListener(this);
super.onCreate(savedInstanceState);
int[] users = ConfigManager.getUsers();
if (users != null) {
if (users.length != 1) {
ArrayList<String> titles = new ArrayList<>();
for (int userId : users) {
var adapter = new ModuleAdapter(userId);
adapter.setHasStableIds(true);
adapters.add(adapter);
titles.add(getString(R.string.user_title, userId));
}
new TabLayoutMediator(binding.tabLayout, binding.viewPager, (tab, position) -> tab.setText(titles.get(position))).attach();
} else {
binding.tabLayout.setVisibility(View.GONE);
}
}
if (ConfigManager.getXposedVersionName() == null) {
Toast.makeText(this, R.string.lsposed_not_active, Toast.LENGTH_LONG).show();
finish();
}
}
@Override
public boolean onPrepareOptionsMenu(Menu menu) {
searchView = (SearchView) menu.findItem(R.id.menu_search).getActionView();
searchView.setOnQueryTextListener(mSearchListener);
return super.onPrepareOptionsMenu(menu);
}
@Override
public void onBackPressed() {
if (searchView.isIconified()) {
super.onBackPressed();
} else {
searchView.setIconified(true);
}
}
@Override
protected void onResume() {
super.onResume();
adapter.refresh(true);
adapters.forEach(ModuleAdapter::refresh);
}
@Override
@ -117,22 +203,22 @@ public class ModulesActivity extends ListActivity implements ModuleUtil.ModuleLi
}
@Override
public void onSingleInstalledModuleReloaded(ModuleUtil moduleUtil, String packageName, ModuleUtil.InstalledModule module) {
adapter.refresh();
public void onSingleInstalledModuleReloaded() {
adapters.forEach(ModuleAdapter::refresh);
}
@Override
public boolean onOptionsItemSelected(@NonNull MenuItem item) {
int itemId = item.getItemId();
if (itemId == R.id.menu_refresh) {
adapter.refresh(true);
adapters.forEach(ModuleAdapter::refresh);
}
return super.onOptionsItemSelected(item);
}
@Override
public boolean onContextItemSelected(@NonNull MenuItem item) {
ModuleUtil.InstalledModule module = ModuleUtil.getInstance().getModule(selectedPackageName);
ModuleUtil.InstalledModule module = ModuleUtil.getInstance().getModule(selectedModule.packageName, selectedModule.userId);
if (module == null) {
return false;
}
@ -142,7 +228,7 @@ public class ModulesActivity extends ListActivity implements ModuleUtil.ModuleLi
if (packageName == null) {
return false;
}
Intent intent = AppHelper.getSettingsIntent(packageName, pm);
Intent intent = AppHelper.getSettingsIntent(packageName, module.userId, pm);
if (intent != null) {
startActivity(intent);
} else {
@ -177,7 +263,8 @@ public class ModulesActivity extends ListActivity implements ModuleUtil.ModuleLi
Toast.makeText(ModulesActivity.this, text, Toast.LENGTH_SHORT).show();
}
});
if (success) moduleUtil.reloadSingleModule(module.packageName);
if (success)
moduleUtil.reloadSingleModule(module.packageName, module.userId);
}))
.setNegativeButton(android.R.string.cancel, null)
.show();
@ -192,16 +279,45 @@ public class ModulesActivity extends ListActivity implements ModuleUtil.ModuleLi
return super.onContextItemSelected(item);
}
@Override
protected BaseAdapter<?> createAdapter() {
return adapter = new ModuleAdapter();
private class PagerAdapter extends RecyclerView.Adapter<PagerAdapter.ViewHolder> {
@NonNull
@Override
public PagerAdapter.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
return new PagerAdapter.ViewHolder(ItemRepoRecyclerviewBinding.inflate(getLayoutInflater(), parent, false).getRoot());
}
@Override
public void onBindViewHolder(@NonNull PagerAdapter.ViewHolder holder, int position) {
holder.recyclerView.setAdapter(adapters.get(position));
holder.recyclerView.setLayoutManager(new LinearLayoutManagerFix(ModulesActivity.this));
holder.recyclerView.getBorderViewDelegate().setBorderVisibilityChangedListener((top, oldTop, bottom, oldBottom) -> binding.appBar.setRaised(!top));
RecyclerViewKt.fixEdgeEffect(holder.recyclerView, false, true);
RecyclerViewKt.addFastScroller(holder.recyclerView, holder.itemView);
}
@Override
public int getItemCount() {
return adapters.size();
}
class ViewHolder extends RecyclerView.ViewHolder {
BorderRecyclerView recyclerView;
public ViewHolder(@NonNull View itemView) {
super(itemView);
recyclerView = itemView.findViewById(R.id.recyclerView);
}
}
}
private class ModuleAdapter extends BaseAdapter<ModuleAdapter.ViewHolder> {
private class ModuleAdapter extends RecyclerView.Adapter<ModuleAdapter.ViewHolder> implements Filterable {
private final List<ModuleUtil.InstalledModule> searchList = new ArrayList<>();
private final List<ModuleUtil.InstalledModule> showList = new ArrayList<>();
private final int userId;
ModuleAdapter() {
ModuleAdapter(int userId) {
this.userId = userId;
refresh();
}
@ -216,7 +332,13 @@ public class ModulesActivity extends ListActivity implements ModuleUtil.ModuleLi
public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
ModuleUtil.InstalledModule item = showList.get(position);
holder.root.setAlpha(moduleUtil.isModuleEnabled(item.packageName) ? 1.0f : .5f);
holder.appName.setText(item.getAppName());
String appName;
if (item.userId != 0) {
appName = String.format("%s (%s)", item.getAppName(), item.userId);
} else {
appName = item.getAppName();
}
holder.appName.setText(appName);
GlideApp.with(holder.appIcon)
.load(item.getPackageInfo())
.into(new CustomTarget<Drawable>() {
@ -266,7 +388,7 @@ public class ModulesActivity extends ListActivity implements ModuleUtil.ModuleLi
holder.itemView.setOnCreateContextMenuListener((menu, v, menuInfo) -> {
getMenuInflater().inflate(R.menu.context_menu_modules, menu);
menu.setHeaderTitle(item.getAppName());
Intent intent = AppHelper.getSettingsIntent(item.packageName, pm);
Intent intent = AppHelper.getSettingsIntent(item.packageName, item.userId, pm);
if (intent == null) {
menu.removeItem(R.id.menu_launch);
}
@ -278,11 +400,12 @@ public class ModulesActivity extends ListActivity implements ModuleUtil.ModuleLi
holder.itemView.setOnClickListener(v -> {
Intent intent = new Intent(ModulesActivity.this, AppListActivity.class);
intent.putExtra("modulePackageName", item.packageName);
intent.putExtra("moduleUserId", item.userId);
startActivity(intent);
});
holder.itemView.setOnLongClickListener(v -> {
selectedPackageName = item.packageName;
selectedModule = item;
return false;
});
@ -298,7 +421,8 @@ public class ModulesActivity extends ListActivity implements ModuleUtil.ModuleLi
@Override
public long getItemId(int position) {
return showList.get(position).packageName.hashCode();
var module = showList.get(position);
return (module.packageName + "!" + module.userId).hashCode();
}
@Override
@ -318,7 +442,7 @@ public class ModulesActivity extends ListActivity implements ModuleUtil.ModuleLi
private final Runnable reloadModules = new Runnable() {
public void run() {
searchList.clear();
searchList.addAll(moduleUtil.getModules().values());
searchList.addAll(moduleUtil.getModules().values().stream().filter(module -> module.userId == userId).collect(Collectors.toList()));
Comparator<PackageInfo> cmp = AppHelper.getAppListComparator(0, pm);
searchList.sort((a, b) -> {
boolean aChecked = moduleUtil.isModuleEnabled(a.packageName);

View File

@ -32,7 +32,6 @@ import java.io.InputStream;
import java.io.OutputStream;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.zip.GZIPInputStream;
import java.util.zip.GZIPOutputStream;
@ -48,7 +47,7 @@ public class BackupUtils {
JSONObject rootObject = new JSONObject();
rootObject.put("version", VERSION);
JSONArray modulesArray = new JSONArray();
Map<String, ModuleUtil.InstalledModule> modules = ModuleUtil.getInstance().getModules();
var modules = ModuleUtil.getInstance().getModules();
for (ModuleUtil.InstalledModule module : modules.values()) {
if (packageName != null && !module.packageName.equals(packageName)) {
continue;

View File

@ -27,6 +27,7 @@ import android.content.pm.PackageManager.NameNotFoundException;
import android.os.Build;
import androidx.annotation.NonNull;
import androidx.core.util.Pair;
import org.lsposed.manager.App;
import org.lsposed.manager.ConfigManager;
@ -47,7 +48,7 @@ public final class ModuleUtil {
private final PackageManager pm;
private final List<ModuleListener> listeners = new CopyOnWriteArrayList<>();
private final HashSet<String> enabledModules;
private Map<String, InstalledModule> installedModules;
private Map<Pair<String, Integer>, InstalledModule> installedModules;
private boolean isReloading = false;
private ModuleUtil() {
@ -82,15 +83,15 @@ public final class ModuleUtil {
isReloading = true;
}
Map<String, InstalledModule> modules = new HashMap<>();
Map<Pair<String, Integer>, InstalledModule> modules = new HashMap<>();
for (PackageInfo pkg : ConfigManager.getInstalledPackagesFromAllUsers(PackageManager.GET_META_DATA, false)) {
ApplicationInfo app = pkg.applicationInfo;
if (!app.enabled || app.uid / 100000 != 0)
if (!app.enabled)
continue;
if (app.metaData != null && app.metaData.containsKey("xposedminversion")) {
InstalledModule installed = new InstalledModule(pkg, false);
modules.put(pkg.packageName, installed);
modules.put(Pair.create(pkg.packageName, app.uid / 100000), installed);
}
}
@ -101,10 +102,10 @@ public final class ModuleUtil {
}
}
public InstalledModule reloadSingleModule(String packageName) {
public InstalledModule reloadSingleModule(String packageName, int userId) {
PackageInfo pkg;
try {
pkg = ConfigManager.getPackageInfo(packageName, PackageManager.GET_META_DATA);
pkg = ConfigManager.getPackageInfo(packageName, PackageManager.GET_META_DATA, userId);
if (pkg == null) {
throw new NameNotFoundException();
}
@ -112,7 +113,7 @@ public final class ModuleUtil {
InstalledModule old = installedModules.remove(packageName);
if (old != null) {
for (ModuleListener listener : listeners) {
listener.onSingleInstalledModuleReloaded(instance, packageName, null);
listener.onSingleInstalledModuleReloaded();
}
}
return null;
@ -121,28 +122,31 @@ public final class ModuleUtil {
ApplicationInfo app = pkg.applicationInfo;
if (app.enabled && app.metaData != null && app.metaData.containsKey("xposedminversion")) {
InstalledModule module = new InstalledModule(pkg, false);
installedModules.put(packageName, module);
installedModules.put(Pair.create(packageName, userId), module);
for (ModuleListener listener : listeners) {
listener.onSingleInstalledModuleReloaded(instance, packageName,
module);
listener.onSingleInstalledModuleReloaded();
}
return module;
} else {
InstalledModule old = installedModules.remove(packageName);
InstalledModule old = installedModules.remove(Pair.create(packageName, userId));
if (old != null) {
for (ModuleListener listener : listeners) {
listener.onSingleInstalledModuleReloaded(instance, packageName, null);
listener.onSingleInstalledModuleReloaded();
}
}
return null;
}
}
public InstalledModule getModule(String packageName) {
return installedModules.get(packageName);
public InstalledModule getModule(String packageName, int userId) {
return installedModules.get(Pair.create(packageName, userId));
}
public Map<String, InstalledModule> getModules() {
public InstalledModule getModule(String packageName) {
return getModule(packageName, 0);
}
public Map<Pair<String, Integer>, InstalledModule> getModules() {
return installedModules;
}
@ -180,11 +184,12 @@ public final class ModuleUtil {
* Called whenever one (previously or now) installed module has been
* reloaded
*/
void onSingleInstalledModuleReloaded(ModuleUtil moduleUtil, String packageName, InstalledModule module);
void onSingleInstalledModuleReloaded();
}
public class InstalledModule {
//private static final int FLAG_FORWARD_LOCK = 1 << 29;
public final int userId;
public final String packageName;
public final String versionName;
public final long versionCode;
@ -201,6 +206,7 @@ public final class ModuleUtil {
private InstalledModule(PackageInfo pkg, boolean isFramework) {
this.app = pkg.applicationInfo;
this.pkg = pkg;
this.userId = pkg.applicationInfo.uid / 100000;
this.packageName = pkg.packageName;
this.isFramework = isFramework;
this.versionName = pkg.versionName;

View File

@ -38,7 +38,7 @@ public final class NotificationUtil {
private static final int PENDING_INTENT_OPEN_APP_LIST = 0;
private static final String NOTIFICATION_MODULES_CHANNEL = "modules_channel_2";
public static void showNotification(Context context, String modulePackageName, String moduleName, boolean enabled) {
public static void showNotification(Context context, String modulePackageName, String moduleName, int moduleUserId, boolean enabled) {
NotificationManager notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
NotificationChannel channel = new NotificationChannel(NOTIFICATION_MODULES_CHANNEL,
@ -53,6 +53,7 @@ public final class NotificationUtil {
Intent intent = new Intent(context, AppListActivity.class)
.putExtra("modulePackageName", modulePackageName)
.putExtra("moduleUserId", moduleUserId)
.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
PendingIntent contentIntent = PendingIntent.getActivity(context, PENDING_INTENT_OPEN_APP_LIST, intent, PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE);

View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@ -85,6 +85,7 @@
<string name="module_uninstall_message">Do you want to uninstall this module?</string>
<string name="module_uninstalled">Uninstalled %1$s</string>
<string name="module_uninstall_failed">Uninstall unsuccessful</string>
<string name="user_title">User %d</string>
<!-- AppListActivity -->
<string name="compile_speed">Re-optimize</string>

View File

@ -68,6 +68,8 @@ public class ConfigManager {
"android.permission.WRITE_SECURE_SETTINGS"
};
private static final int PER_USER_RANGE = 100000;
static ConfigManager instance = null;
private static final File basePath = new File("/data/adb/lspd");
@ -312,9 +314,9 @@ public class ConfigManager {
while (cursor.moveToNext()) {
String packageName = cursor.getString(pkgNameIdx);
try {
PackageInfo pkgInfo = PackageService.getPackageInfo(packageName, 0, 0);
PackageInfo pkgInfo = PackageService.getPackageInfoFromAllUsers(packageName, 0);
if (pkgInfo != null && pkgInfo.applicationInfo != null) {
cachedModule.put(pkgInfo.applicationInfo.uid, pkgInfo.packageName);
cachedModule.put(pkgInfo.applicationInfo.uid % PER_USER_RANGE, pkgInfo.packageName);
} else {
obsoleteModules.add(packageName);
}
@ -635,7 +637,7 @@ public class ConfigManager {
}
public boolean isModule(int uid) {
return cachedModule.containsKey(uid);
return cachedModule.containsKey(uid % PER_USER_RANGE);
}
private void recursivelyChown(File file, int uid, int gid) throws ErrnoException {

View File

@ -161,4 +161,9 @@ public class LSPManagerService extends ILSPManagerService.Stub {
public boolean isSepolicyLoaded() throws RemoteException {
return ConfigManager.getInstance().isSepolicyLoaded();
}
@Override
public int[] getUsers() throws RemoteException {
return UserService.getUsers();
}
}

View File

@ -102,8 +102,7 @@ public class LSPosedService extends ILSPosedService.Stub {
}
ApplicationInfo applicationInfo = PackageService.getApplicationInfo(packageName, PackageManager.GET_META_DATA, 0);
boolean isXposedModule = (userId == 0 || userId == -1) &&
applicationInfo != null &&
boolean isXposedModule = applicationInfo != null &&
applicationInfo.enabled &&
applicationInfo.metaData != null &&
applicationInfo.metaData.containsKey("xposedminversion");
@ -118,6 +117,7 @@ public class LSPosedService extends ILSPosedService.Stub {
broadcastIntent.addFlags(0x01000000);
broadcastIntent.addFlags(0x00400000);
broadcastIntent.setData(intent.getData());
broadcastIntent.putExtras(intent.getExtras());
broadcastIntent.setComponent(ComponentName.unflattenFromString(ConfigManager.getInstance().getManagerPackageName() + "/.receivers.ServiceReceiver"));
try {

View File

@ -96,6 +96,16 @@ public class PackageService {
return pm.getPackageInfo(packageName, flags, userId);
}
public static PackageInfo getPackageInfoFromAllUsers(String packageName, int flags) throws RemoteException {
IPackageManager pm = getPackageManager();
if (pm == null) return null;
for (int userId : UserService.getUsers()) {
var info = pm.getPackageInfo(packageName, flags, userId);
if (info != null) return info;
}
return null;
}
public static ApplicationInfo getApplicationInfo(String packageName, int flags, int userId) throws RemoteException {
IPackageManager pm = getPackageManager();
if (pm == null) return null;

View File

@ -46,4 +46,6 @@ interface ILSPManagerService {
boolean uninstallPackage(String packageName) = 25;
boolean isSepolicyLoaded() = 26;
int[] getUsers() = 27;
}