Use correct pkg name for system_server (#2580)

Allow hooking processes of android package besides system_server

system_server: uid=1000 pkg=system  proc=system
ChooserActivity,ResolverActivity: uid=1000 pkg=android proc=android:ui,system:ui

Co-authored-by: 5ec1cff <ewtqyqyewtqyqy@gmail.com>
Co-authored-by: vvb2060 <vvb2060@gmail.com>
This commit is contained in:
LoveSy 2023-07-03 13:40:12 +08:00 committed by GitHub
parent 8b3e331c5e
commit 6f6c4b67d7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 102 additions and 68 deletions

View File

@ -27,6 +27,7 @@ import android.content.pm.ApplicationInfo;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.os.Parcel;
import android.view.MenuItem;
import org.lsposed.manager.ConfigManager;
@ -140,6 +141,20 @@ public class AppHelper {
synchronized public static List<PackageInfo> getAppList(boolean force) {
if (appList == null || force) {
appList = ConfigManager.getInstalledPackagesFromAllUsers(PackageManager.GET_META_DATA | PackageManager.MATCH_UNINSTALLED_PACKAGES, true);
PackageInfo system = null;
for (var app : appList) {
if ("android".equals(app.packageName)) {
var p = Parcel.obtain();
app.writeToParcel(p, 0);
p.setDataPosition(0);
system = PackageInfo.CREATOR.createFromParcel(p);
system.packageName = "system";
break;
}
}
if (system != null) {
appList.add(system);
}
}
return appList;
}

View File

@ -90,7 +90,6 @@ import rikka.material.app.LocaleDelegate;
import rikka.widget.mainswitchbar.MainSwitchBar;
import rikka.widget.mainswitchbar.OnMainSwitchChangeListener;
@SuppressLint("NotifyDataSetChanged")
public class ScopeAdapter extends EmptyStateRecyclerView.EmptyStateAdapter<ScopeAdapter.ViewHolder> implements Filterable {
private final Activity activity;
@ -165,7 +164,7 @@ public class ScopeAdapter extends EmptyStateRecyclerView.EmptyStateAdapter<Scope
}
private boolean shouldHideApp(PackageInfo info, ApplicationWithEquals app, HashSet<ApplicationWithEquals> tmpChkList) {
if (info.packageName.equals("android")) {
if (info.packageName.equals("system")) {
return false;
}
if (tmpChkList.contains(app)) {
@ -190,18 +189,15 @@ public class ScopeAdapter extends EmptyStateRecyclerView.EmptyStateAdapter<Scope
return true;
}
}
if ((info.applicationInfo.flags & ApplicationInfo.FLAG_HAS_CODE) == 0) {
return true;
}
return preferences.getBoolean("filter_system_apps", true) && (info.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0;
}
private int sortApps(AppInfo x, AppInfo y) {
Comparator<PackageInfo> comparator = AppHelper.getAppListComparator(preferences.getInt("list_sort", 0), pm);
Comparator<AppInfo> frameworkComparator = (a, b) -> {
if (a.packageName.equals("android") == b.packageName.equals("android")) {
if (a.packageName.equals("system") == b.packageName.equals("system")) {
return comparator.compare(a.packageInfo, b.packageInfo);
} else if (a.packageName.equals("android")) {
} else if (a.packageName.equals("system")) {
return -1;
} else {
return 1;
@ -303,7 +299,6 @@ public class ScopeAdapter extends EmptyStateRecyclerView.EmptyStateAdapter<Scope
return true;
}
@SuppressLint("WrongConstant")
public boolean onContextItemSelected(@NonNull MenuItem item) {
ApplicationInfo info = selectedInfo;
if (info == null) {
@ -325,7 +320,7 @@ public class ScopeAdapter extends EmptyStateRecyclerView.EmptyStateAdapter<Scope
} else if (itemId == R.id.menu_app_info) {
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")) {
if (info.packageName.equals("system")) {
ConfigManager.reboot();
} else {
new BlurBehindDialogBuilder(activity, R.style.ThemeOverlay_MaterialAlertDialog_Centered_FullWidthButtons)
@ -395,10 +390,10 @@ public class ScopeAdapter extends EmptyStateRecyclerView.EmptyStateAdapter<Scope
AppInfo appInfo = showList.get(position);
boolean deny = denyList.contains(appInfo.packageName);
holder.root.setAlpha(!deny && enabled ? 1.0f : .5f);
boolean android = appInfo.packageName.equals("android");
boolean system = appInfo.packageName.equals("system");
CharSequence appName;
int userId = appInfo.applicationInfo.uid / App.PER_USER_RANGE;
appName = android ? activity.getString(R.string.android_framework) : appInfo.label;
appName = system ? activity.getString(R.string.android_framework) : appInfo.label;
holder.appName.setText(appName);
GlideApp.with(holder.appIcon).load(appInfo.packageInfo).into(new CustomTarget<Drawable>() {
@Override
@ -416,16 +411,18 @@ public class ScopeAdapter extends EmptyStateRecyclerView.EmptyStateAdapter<Scope
holder.appIcon.setImageDrawable(pm.getDefaultActivityIcon());
}
});
SpannableStringBuilder sb = new SpannableStringBuilder();
if (android) {
holder.appPackageName.setVisibility(View.GONE);
if (system) {
//noinspection SetTextI18n
holder.appPackageName.setText("system");
holder.appVersionName.setVisibility(View.GONE);
} else {
holder.appPackageName.setVisibility(View.VISIBLE);
holder.appVersionName.setVisibility(View.VISIBLE);
holder.appPackageName.setText(appInfo.packageName);
holder.appVersionName.setText(activity.getString(R.string.app_version, appInfo.packageInfo.versionName));
}
holder.appPackageName.setVisibility(View.VISIBLE);
holder.appVersionName.setText(activity.getString(R.string.app_version, appInfo.packageInfo.versionName));
var sb = new SpannableStringBuilder();
if (!recommendedList.isEmpty() && recommendedList.contains(appInfo.application)) {
String recommended = activity.getString(R.string.requested_by_module);
sb.append(recommended);
@ -467,9 +464,11 @@ public class ScopeAdapter extends EmptyStateRecyclerView.EmptyStateAdapter<Scope
if (launchIntent == null) {
menu.removeItem(R.id.menu_launch);
}
if (android) {
if (system) {
menu.findItem(R.id.menu_force_stop).setTitle(R.string.reboot);
menu.removeItem(R.id.menu_compile_speed);
menu.removeItem(R.id.menu_other_app);
menu.removeItem(R.id.menu_app_info);
}
});
@ -522,7 +521,7 @@ public class ScopeAdapter extends EmptyStateRecyclerView.EmptyStateAdapter<Scope
appList.parallelStream().forEach(info -> {
int userId = info.applicationInfo.uid / App.PER_USER_RANGE;
String packageName = info.packageName;
if (packageName.equals("android") && userId != 0 ||
if (packageName.equals("system") && userId != 0 ||
packageName.equals(module.packageName) ||
packageName.equals(BuildConfig.APPLICATION_ID)) {
return;
@ -587,7 +586,7 @@ public class ScopeAdapter extends EmptyStateRecyclerView.EmptyStateAdapter<Scope
tmpChkList.remove(appInfo.application);
}
buttonView.setChecked(!isChecked);
} else if (appInfo.packageName.equals("android")) {
} else if (appInfo.packageName.equals("system")) {
fragment.showHint(R.string.reboot_required, true, R.string.reboot, v -> ConfigManager.reboot());
} else if (denyList.contains(appInfo.packageName)) {
fragment.showHint(activity.getString(R.string.deny_list, appInfo.label), true);

View File

@ -43,6 +43,7 @@ import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
@ -257,9 +258,9 @@ public final class ModuleUtil {
public final long updateTime;
public final ApplicationInfo app;
public final PackageInfo pkg;
private String appName; // loaded lazyily
private String description; // loaded lazyily
private List<String> scopeList; // loaded lazyily
private String appName; // loaded lazily
private String description; // loaded lazily
private List<String> scopeList; // loaded lazily
private InstalledModule(PackageInfo pkg, ZipFile modernModuleApk) {
app = pkg.applicationInfo;
@ -305,6 +306,8 @@ public final class ModuleUtil {
try (var reader = new BufferedReader(new InputStreamReader(modernModuleApk.getInputStream(scopeEntry)))) {
scopeList = reader.lines().collect(Collectors.toList());
}
} else {
scopeList = Collections.emptyList();
}
} catch (IOException | OutOfMemoryError e) {
Log.e(App.TAG, "Error while closing modern module APK", e);
@ -350,25 +353,37 @@ public final class ModuleUtil {
public List<String> getScopeList() {
if (scopeList != null) return scopeList;
if (legacy) {
try {
int scopeListResourceId = app.metaData.getInt("xposedscope");
if (scopeListResourceId != 0) {
scopeList = Arrays.asList(pm.getResourcesForApplication(app).getStringArray(scopeListResourceId));
} else {
String scopeListString = app.metaData.getString("xposedscope");
if (scopeListString != null)
scopeList = Arrays.asList(scopeListString.split(";"));
}
} catch (Exception ignored) {
List<String> list = null;
try {
int scopeListResourceId = app.metaData.getInt("xposedscope");
if (scopeListResourceId != 0) {
scopeList = Arrays.asList(pm.getResourcesForApplication(app).getStringArray(scopeListResourceId));
} else {
String scopeListString = app.metaData.getString("xposedscope");
if (scopeListString != null)
list = Arrays.asList(scopeListString.split(";"));
}
} catch (Exception ignored) {
}
if (scopeList == null) {
if (list == null) {
OnlineModule module = RepoLoader.getInstance().getOnlineModule(packageName);
if (module != null && module.getScope() != null) {
scopeList = module.getScope();
list = module.getScope();
}
}
if (list != null) {
list.replaceAll(s ->
switch (s) {
case "android":
yield "system";
case "system":
yield "android";
default:
yield s;
}
);
scopeList = list;
}
return scopeList;
}

View File

@ -66,11 +66,11 @@ val verCode by extra(commitCount)
val verName by extra(latestTag)
val androidTargetSdkVersion by extra(33)
val androidMinSdkVersion by extra(27)
val androidBuildToolsVersion by extra("33.0.1")
val androidBuildToolsVersion by extra("33.0.2")
val androidCompileSdkVersion by extra(33)
val androidCompileNdkVersion by extra("25.2.9519653")
val androidSourceCompatibility by extra(JavaVersion.VERSION_11)
val androidTargetCompatibility by extra(JavaVersion.VERSION_11)
val androidSourceCompatibility by extra(JavaVersion.VERSION_17)
val androidTargetCompatibility by extra(JavaVersion.VERSION_17)
tasks.register("Delete", Delete::class) {
delete(rootProject.buildDir)

View File

@ -20,15 +20,12 @@
package org.lsposed.lspd.hooker;
import android.app.ActivityThread;
import android.app.LoadedApk;
import android.content.res.XResources;
import android.util.Log;
import org.lsposed.lspd.util.Hookers;
import java.util.Optional;
import de.robv.android.xposed.XC_MethodHook;
import de.robv.android.xposed.XposedHelpers;
import de.robv.android.xposed.XposedInit;
@ -59,12 +56,6 @@ public class LoadedApkCtorHooker extends XC_MethodHook {
}
}
// mIncludeCode checking should go ahead of loadedPackagesInProcess added checking
if (!XposedHelpers.getBooleanField(loadedApk, "mIncludeCode")) {
Hookers.logD("LoadedApk#<init> mIncludeCode == false: " + mAppDir);
return;
}
if (!XposedInit.loadedPackagesInProcess.add(packageName)) {
Hookers.logD("LoadedApk#<init> has been loaded before, skip: " + mAppDir);
return;

View File

@ -24,7 +24,6 @@ import static org.lsposed.lspd.core.ApplicationServiceClient.serviceClient;
import android.annotation.SuppressLint;
import android.app.ActivityThread;
import android.app.AndroidAppHelper;
import android.app.LoadedApk;
import android.content.pm.ApplicationInfo;
import android.os.Build;
@ -90,7 +89,7 @@ public class LoadedApkGetCLHooker extends XC_MethodHook {
boolean isFirstPackage = packageName != null && processName != null && packageName.equals(loadedApk.getPackageName());
if (!isFirstPackage) {
packageName = loadedApk.getPackageName();
processName = AndroidAppHelper.currentProcessName();
processName = ActivityThread.currentPackageName();
} else if (packageName.equals("android")) {
packageName = "system";
}

View File

@ -20,18 +20,18 @@
package org.lsposed.lspd.util;
import android.app.AndroidAppHelper;
import android.app.ActivityThread;
public class Hookers {
public static void logD(String prefix) {
Utils.logD(String.format("%s: pkg=%s, prc=%s", prefix, AndroidAppHelper.currentPackageName(),
AndroidAppHelper.currentProcessName()));
Utils.logD(String.format("%s: pkg=%s, prc=%s", prefix, ActivityThread.currentPackageName(),
ActivityThread.currentProcessName()));
}
public static void logE(String prefix, Throwable throwable) {
Utils.logE(String.format("%s: pkg=%s, prc=%s", prefix, AndroidAppHelper.currentPackageName(),
AndroidAppHelper.currentProcessName()), throwable);
Utils.logE(String.format("%s: pkg=%s, prc=%s", prefix, ActivityThread.currentPackageName(),
ActivityThread.currentProcessName()), throwable);
}
}

View File

@ -39,6 +39,7 @@ import android.os.Bundle;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.ParcelFileDescriptor;
import android.os.Process;
import android.os.RemoteException;
import android.os.SELinux;
import android.os.SharedMemory;
@ -202,7 +203,7 @@ public class ConfigManager {
Log.e(TAG, "skip injecting into android because sepolicy was not loaded properly");
return true; // skip
}
try (Cursor cursor = db.query("scope INNER JOIN modules ON scope.mid = modules.mid", new String[]{"modules.mid"}, "app_pkg_name=? AND enabled=1", new String[]{"android"}, null, null, null)) {
try (Cursor cursor = db.query("scope INNER JOIN modules ON scope.mid = modules.mid", new String[]{"modules.mid"}, "app_pkg_name=? AND enabled=1", new String[]{"system"}, null, null, null)) {
return cursor == null || !cursor.moveToNext();
}
}
@ -220,7 +221,7 @@ public class ConfigManager {
}
List<Module> modules = new LinkedList<>();
try (Cursor cursor = db.query("scope INNER JOIN modules ON scope.mid = modules.mid", new String[]{"module_pkg_name", "apk_path"}, "app_pkg_name=? AND enabled=1", new String[]{"android"}, null, null, null)) {
try (Cursor cursor = db.query("scope INNER JOIN modules ON scope.mid = modules.mid", new String[]{"module_pkg_name", "apk_path"}, "app_pkg_name=? AND enabled=1", new String[]{"system"}, null, null, null)) {
int apkPathIdx = cursor.getColumnIndex("apk_path");
int pkgNameIdx = cursor.getColumnIndex("module_pkg_name");
while (cursor.moveToNext()) {
@ -416,11 +417,15 @@ public class ConfigManager {
db.compileStatement("DROP TABLE old_configs;").execute();
db.setVersion(2);
});
case 2:
executeInTransaction(() -> {
db.compileStatement("UPDATE scope SET app_pkg_name = 'system' WHERE app_pkg_name = 'android';").execute();
db.setVersion(3);
});
default:
break;
}
} catch (
Throwable e) {
} catch (Throwable e) {
Log.e(TAG, "init db", e);
}
@ -429,8 +434,17 @@ public class ConfigManager {
private List<ProcessScope> getAssociatedProcesses(Application app) throws RemoteException {
Pair<Set<String>, Integer> result = PackageService.fetchProcessesWithUid(app);
List<ProcessScope> processes = new ArrayList<>();
if (app.packageName.equals("android")) {
// this is hardcoded for ResolverActivity
processes.add(new ProcessScope("system:ui", Process.SYSTEM_UID));
}
for (String processName : result.first) {
processes.add(new ProcessScope(processName, result.second));
var uid = result.second;
if (uid == Process.SYSTEM_UID && processName.equals("system")) {
// code run in system_server
continue;
}
processes.add(new ProcessScope(processName, uid));
}
return processes;
}
@ -669,7 +683,7 @@ public class ConfigManager {
})) continue;
// system server always loads database
if (app.packageName.equals("android")) continue;
if (app.packageName.equals("system")) continue;
try {
List<ProcessScope> processesScope = cachedProcessScope.computeIfAbsent(new Pair<>(app.packageName, app.userId), (k) -> {
@ -841,7 +855,7 @@ public class ConfigManager {
executeInTransaction(() -> {
db.delete("scope", "mid = ?", new String[]{String.valueOf(mid)});
for (Application app : scopes) {
if (app.packageName.equals("android") && app.userId != 0) continue;
if (app.packageName.equals("system") && app.userId != 0) continue;
ContentValues values = new ContentValues();
values.put("mid", mid);
values.put("app_pkg_name", app.packageName);
@ -858,7 +872,7 @@ public class ConfigManager {
if (scopePackageName == null) return false;
int mid = getModuleId(packageName);
if (mid == -1) return false;
if (scopePackageName.equals("android") && userId != 0) return false;
if (scopePackageName.equals("system") && userId != 0) return false;
executeInTransaction(() -> {
ContentValues values = new ContentValues();
values.put("mid", mid);
@ -875,7 +889,7 @@ public class ConfigManager {
if (scopePackageName == null) return false;
int mid = getModuleId(packageName);
if (mid == -1) return false;
if (scopePackageName.equals("android") && userId != 0) return false;
if (scopePackageName.equals("system") && userId != 0) return false;
executeInTransaction(() -> {
db.delete("scope", "mid = ? AND app_pkg_name = ? AND user_id = ?", new String[]{String.valueOf(mid), scopePackageName, String.valueOf(userId)});
});

View File

@ -24,6 +24,7 @@ import static org.lsposed.lspd.service.ServiceManager.TAG;
import android.os.IBinder;
import android.os.Parcel;
import android.os.ParcelFileDescriptor;
import android.os.Process;
import android.os.RemoteException;
import android.util.Log;
import android.util.Pair;
@ -117,7 +118,7 @@ public class LSPApplicationService extends ILSPApplicationService.Stub {
private List<Module> getAllModulesList() throws RemoteException {
var processInfo = ensureRegistered();
if (processInfo.uid == 1000 && processInfo.processName.equals("android")) {
if (processInfo.uid == Process.SYSTEM_UID && processInfo.processName.equals("system")) {
return ConfigManager.getInstance().getModulesForSystemServer();
}
if (ServiceManager.getManagerService().isRunningManager(processInfo.pid, processInfo.uid))

View File

@ -80,7 +80,7 @@ public class LSPSystemServerService extends ILSPSystemServerService.Stub impleme
public ILSPApplicationService requestApplicationService(int uid, int pid, String processName, IBinder heartBeat) {
Log.d(TAG, "ILSPApplicationService.requestApplicationService: " + uid + " " + pid + " " + processName + " " + heartBeat);
requested = 1;
if (ConfigManager.getInstance().shouldSkipSystemServer() || uid != 1000 || heartBeat == null || !"android".equals(processName))
if (ConfigManager.getInstance().shouldSkipSystemServer() || uid != 1000 || heartBeat == null || !"system".equals(processName))
return null;
else
return ServiceManager.requestApplicationService(uid, pid, processName, heartBeat);

View File

@ -206,7 +206,7 @@ public class LSPosedService extends ILSPosedService.Stub {
if (isXposedModule) {
var enabledModules = ConfigManager.getInstance().enabledModules();
var scope = ConfigManager.getInstance().getModuleScope(packageName);
boolean systemModule = scope != null && scope.parallelStream().anyMatch(app -> app.packageName.equals("android"));
boolean systemModule = scope != null && scope.parallelStream().anyMatch(app -> app.packageName.equals("system"));
boolean enabled = Arrays.asList(enabledModules).contains(packageName);
if (!(Intent.ACTION_UID_REMOVED.equals(action) || Intent.ACTION_PACKAGE_FULLY_REMOVED.equals(action) || allUsers))
LSPNotificationManager.notifyModuleUpdated(packageName, userId, enabled, systemModule);

View File

@ -139,7 +139,7 @@ namespace lspd {
SetupEntryClass(env);
FindAndCall(env, "forkCommon",
"(ZLjava/lang/String;Ljava/lang/String;Landroid/os/IBinder;)V",
JNI_TRUE, JNI_NewStringUTF(env, "android"), nullptr, application_binder);
JNI_TRUE, JNI_NewStringUTF(env, "system"), nullptr, application_binder);
GetArt(true);
} else {
LOGI("skipped system server");

View File

@ -297,7 +297,7 @@ namespace lspd {
JNI_CallVoidMethod(env, wrapper.data, write_int_method_, getuid());
JNI_CallVoidMethod(env, wrapper.data, write_int_method_, getpid());
JNI_CallVoidMethod(env, wrapper.data, write_string_method_, JNI_NewStringUTF(env, "android"));
JNI_CallVoidMethod(env, wrapper.data, write_string_method_, JNI_NewStringUTF(env, "system"));
JNI_CallVoidMethod(env, wrapper.data, write_strong_binder_method_, heart_beat_binder);
auto res = wrapper.transact(system_server_binder, BRIDGE_TRANSACTION_CODE);