[core] Recognize module from other user profile (#555)
Co-authored-by: tehcneko <7764726+tehcneko@users.noreply.github.com>
This commit is contained in:
parent
b0f3c4d0bb
commit
dbc0226d66
|
|
@ -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());
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -153,4 +153,9 @@ public class LSPosedManagerServiceClient {
|
|||
ensureService();
|
||||
return service.isSepolicyLoaded();
|
||||
}
|
||||
|
||||
public static int[] getUsers() throws RemoteException, NullPointerException {
|
||||
ensureService();
|
||||
return service.getUsers();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -46,4 +46,6 @@ interface ILSPManagerService {
|
|||
boolean uninstallPackage(String packageName) = 25;
|
||||
|
||||
boolean isSepolicyLoaded() = 26;
|
||||
|
||||
int[] getUsers() = 27;
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue