Implement module service

This commit is contained in:
Nullptr 2022-12-31 20:18:09 +08:00 committed by LoveSy
parent d29a3bf16e
commit fb0ceca588
12 changed files with 157 additions and 44 deletions

View File

@ -57,15 +57,6 @@ public class ApplicationServiceClient implements ILSPApplicationService, IBinder
} }
} }
@Override
public IBinder requestModuleBinder(String name) {
try {
return service.requestModuleBinder(name);
} catch (RemoteException | NullPointerException ignored) {
}
return null;
}
@Override @Override
public List<Module> getLegacyModulesList() { public List<Module> getLegacyModulesList() {
try { try {

View File

@ -25,7 +25,6 @@ import static org.lsposed.lspd.core.ApplicationServiceClient.serviceClient;
import android.app.ActivityThread; import android.app.ActivityThread;
import android.app.AndroidAppHelper; import android.app.AndroidAppHelper;
import android.app.LoadedApk; import android.app.LoadedApk;
import android.os.IBinder;
import org.lsposed.lspd.impl.LSPosedContext; import org.lsposed.lspd.impl.LSPosedContext;
import org.lsposed.lspd.util.Hookers; import org.lsposed.lspd.util.Hookers;
@ -89,10 +88,7 @@ public class LoadedApkGetCLHooker extends XC_MethodHook {
lpparam.appInfo = loadedApk.getApplicationInfo(); lpparam.appInfo = loadedApk.getApplicationInfo();
lpparam.isFirstApplication = isFirstApplication; lpparam.isFirstApplication = isFirstApplication;
IBinder moduleBinder = serviceClient.requestModuleBinder(lpparam.packageName); hookNewXSP(lpparam);
if (moduleBinder != null) {
hookNewXSP(lpparam);
}
Hookers.logD("Call handleLoadedPackage: packageName=" + lpparam.packageName + " processName=" + lpparam.processName + " isFirstApplication=" + isFirstApplication + " classLoader=" + lpparam.classLoader + " appInfo=" + lpparam.appInfo); Hookers.logD("Call handleLoadedPackage: packageName=" + lpparam.packageName + " processName=" + lpparam.processName + " isFirstApplication=" + isFirstApplication + " classLoader=" + lpparam.classLoader + " appInfo=" + lpparam.appInfo);
XC_LoadPackage.callAll(lpparam); XC_LoadPackage.callAll(lpparam);

View File

@ -0,0 +1,15 @@
package io.github.libxposed.service;
import io.github.xposed.xposedservice.IXposedService;
public abstract class XposedService extends IXposedService.Stub {
public static final int API = 100;
public static final String AUTHORITY_SUFFIX = ".XposedService";
public static final String SEND_BINDER = "SendBinder";
@Override
public final int getVersion() {
return API;
}
}

View File

@ -25,6 +25,7 @@ import android.annotation.SuppressLint;
import android.app.IActivityManager; import android.app.IActivityManager;
import android.app.IApplicationThread; import android.app.IApplicationThread;
import android.app.IServiceConnection; import android.app.IServiceConnection;
import android.app.IUidObserver;
import android.app.ProfilerInfo; import android.app.ProfilerInfo;
import android.content.Context; import android.content.Context;
import android.content.IContentProvider; import android.content.IContentProvider;
@ -194,4 +195,9 @@ public class ActivityManagerService {
} }
} }
public static void registerUidObserver(IUidObserver observer, int which, int cutpoint, String callingPackage) throws RemoteException {
IActivityManager am = getActivityManager();
if (am == null) return;
am.registerUidObserver(observer, which, cutpoint, callingPackage);
}
} }

View File

@ -151,15 +151,6 @@ public class LSPApplicationService extends ILSPApplicationService.Stub {
return bundle; return bundle;
} }
@Override
public IBinder requestModuleBinder(String name) throws RemoteException {
var processInfo = ensureRegistered();
if (ConfigManager.getInstance().isModule(processInfo.uid, name)) {
ConfigManager.getInstance().ensureModulePrefsPermission(processInfo.uid, name);
return ServiceManager.getModuleService(name);
} else return null;
}
@Override @Override
public ParcelFileDescriptor requestInjectedManagerBinder(List<IBinder> binder) throws RemoteException { public ParcelFileDescriptor requestInjectedManagerBinder(List<IBinder> binder) throws RemoteException {
var processInfo = ensureRegistered(); var processInfo = ensureRegistered();

View File

@ -19,27 +19,95 @@
package org.lsposed.lspd.service; package org.lsposed.lspd.service;
import android.os.IBinder; import android.app.IUidObserver;
import android.content.AttributionSource;
import android.os.Build;
import android.os.Bundle;
import android.os.RemoteException;
import android.util.Log;
import org.lsposed.daemon.BuildConfig; import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import io.github.xposed.xposedservice.IXposedService; import hidden.HiddenApiBridge;
import io.github.libxposed.service.XposedService;
public class LSPModuleService extends IXposedService.Stub { public class LSPModuleService extends XposedService {
final private String name; private static final String TAG = "LSPosedModuleService";
public LSPModuleService(String name) { private final Set<Integer> uidSet = ConcurrentHashMap.newKeySet();
this.name = name; private final IUidObserver uidObserver = new IUidObserver.Stub() {
@Override
public void onUidActive(int uid) {
uidStarts(uid);
}
@Override
public void onUidCachedChanged(int uid, boolean cached) {
if (!cached) uidStarts(uid);
}
@Override
public void onUidIdle(int uid, boolean disabled) {
uidStarts(uid);
}
@Override
public void onUidGone(int uid, boolean disabled) {
uidSet.remove(uid);
}
};
void registerObserver() {
uidSet.clear();
int flags = HiddenApiBridge.ActivityManager_UID_OBSERVER_ACTIVE()
| HiddenApiBridge.ActivityManager_UID_OBSERVER_GONE()
| HiddenApiBridge.ActivityManager_UID_OBSERVER_IDLE()
| HiddenApiBridge.ActivityManager_UID_OBSERVER_CACHED();
try {
ActivityManagerService.registerUidObserver(uidObserver, flags, HiddenApiBridge.ActivityManager_PROCESS_STATE_UNKNOWN(), null);
Log.i(TAG, "registered uid observer");
} catch (RemoteException e) {
Log.e(TAG, "failed to register uid observer", e);
}
} }
@Override private void uidStarts(int uid) {
public IBinder asBinder() { if (!uidSet.contains(uid)) {
return this; uidSet.add(uid);
var module = ConfigManager.getInstance().getModule(uid);
if (module != null) sendBinder(uid, module);
}
} }
@Override private void sendBinder(int uid, String name) {
public int getVersion() { try {
return BuildConfig.API_CODE; int userId = uid / PackageService.PER_USER_RANGE;
var authority = name + AUTHORITY_SUFFIX;
var provider = ActivityManagerService.getContentProvider(authority, userId);
if (provider == null) {
Log.d(TAG, "no service provider for " + name);
return;
}
var extra = new Bundle();
extra.putBinder("binder", asBinder());
Bundle reply = null;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
reply = provider.call(new AttributionSource.Builder(1000).setPackageName("android").build(),
authority, SEND_BINDER, null, extra);
} else if (Build.VERSION.SDK_INT == Build.VERSION_CODES.R) {
reply = provider.call("android", null, authority, SEND_BINDER, null, extra);
} else if (Build.VERSION.SDK_INT == Build.VERSION_CODES.Q) {
reply = provider.call("android", authority, SEND_BINDER, null, extra);
}
if (reply != null) {
Log.d(TAG, "sent module binder to " + name);
} else {
Log.w(TAG, "failed to send module binder to " + name);
}
} catch (RemoteException | NoSuchMethodError e) {
Log.w(TAG, "failed to send module binder for uid " + uid, e);
}
} }
} }

View File

@ -36,7 +36,6 @@ import com.android.internal.os.BinderInternal;
import org.lsposed.daemon.BuildConfig; import org.lsposed.daemon.BuildConfig;
import java.io.File; import java.io.File;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ExecutorService; import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors; import java.util.concurrent.Executors;
@ -44,12 +43,12 @@ import hidden.HiddenApiBridge;
public class ServiceManager { public class ServiceManager {
public static final String TAG = "LSPosedService"; public static final String TAG = "LSPosedService";
private static final ConcurrentHashMap<String, LSPModuleService> moduleServices = new ConcurrentHashMap<>();
private static final File globalNamespace = new File("/proc/1/root"); private static final File globalNamespace = new File("/proc/1/root");
@SuppressWarnings("FieldCanBeLocal") @SuppressWarnings("FieldCanBeLocal")
private static LSPosedService mainService = null; private static LSPosedService mainService = null;
private static LSPApplicationService applicationService = null; private static LSPApplicationService applicationService = null;
private static LSPManagerService managerService = null; private static LSPManagerService managerService = null;
private static LSPModuleService moduleService = null;
private static LSPSystemServerService systemServerService = null; private static LSPSystemServerService systemServerService = null;
private static LogcatService logcatService = null; private static LogcatService logcatService = null;
private static Dex2OatService dex2OatService = null; private static Dex2OatService dex2OatService = null;
@ -114,6 +113,7 @@ public class ServiceManager {
mainService = new LSPosedService(); mainService = new LSPosedService();
applicationService = new LSPApplicationService(); applicationService = new LSPApplicationService();
managerService = new LSPManagerService(); managerService = new LSPManagerService();
moduleService = new LSPModuleService();
systemServerService = new LSPSystemServerService(systemServerMaxRetry); systemServerService = new LSPSystemServerService(systemServerMaxRetry);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
dex2OatService = new Dex2OatService(); dex2OatService = new Dex2OatService();
@ -142,6 +142,7 @@ public class ServiceManager {
@Override @Override
public void onSystemServerRestarted() { public void onSystemServerRestarted() {
Log.w(TAG, "system restarted..."); Log.w(TAG, "system restarted...");
moduleService.registerObserver();
} }
@Override @Override
@ -152,6 +153,7 @@ public class ServiceManager {
Log.w(TAG, "no response from bridge"); Log.w(TAG, "no response from bridge");
} }
systemServerService.maybeRetryInject(); systemServerService.maybeRetryInject();
moduleService.registerObserver();
} }
@Override @Override
@ -171,10 +173,6 @@ public class ServiceManager {
throw new RuntimeException("Main thread loop unexpectedly exited"); throw new RuntimeException("Main thread loop unexpectedly exited");
} }
public static LSPModuleService getModuleService(String module) {
return moduleServices.computeIfAbsent(module, LSPModuleService::new);
}
public static LSPApplicationService getApplicationService() { public static LSPApplicationService getApplicationService() {
return applicationService; return applicationService;
} }

View File

@ -19,6 +19,7 @@
package hidden; package hidden;
import android.app.ActivityManager;
import android.content.BroadcastReceiver; import android.content.BroadcastReceiver;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
@ -127,4 +128,24 @@ public class HiddenApiBridge {
return Os.ioctlInt(fd, cmd); return Os.ioctlInt(fd, cmd);
} }
} }
public static int ActivityManager_UID_OBSERVER_GONE() {
return ActivityManager.UID_OBSERVER_GONE;
}
public static int ActivityManager_UID_OBSERVER_ACTIVE() {
return ActivityManager.UID_OBSERVER_ACTIVE;
}
public static int ActivityManager_UID_OBSERVER_IDLE() {
return ActivityManager.UID_OBSERVER_IDLE;
}
public static int ActivityManager_UID_OBSERVER_CACHED() {
return ActivityManager.UID_OBSERVER_CACHED;
}
public static int ActivityManager_PROCESS_STATE_UNKNOWN() {
return ActivityManager.PROCESS_STATE_UNKNOWN;
}
} }

View File

@ -0,0 +1,9 @@
package android.app;
public class ActivityManager {
public static int UID_OBSERVER_GONE;
public static int UID_OBSERVER_ACTIVE;
public static int UID_OBSERVER_IDLE;
public static int UID_OBSERVER_CACHED;
public static int PROCESS_STATE_UNKNOWN;
}

View File

@ -40,6 +40,7 @@ public interface IActivityManager extends IInterface {
String[] requiredPermissions, String[] excludedPermissions, String[] requiredPermissions, String[] excludedPermissions,
String[] excludePackages, int appOp, Bundle bOptions, String[] excludePackages, int appOp, Bundle bOptions,
boolean serialized, boolean sticky, int userId) throws RemoteException; boolean serialized, boolean sticky, int userId) throws RemoteException;
@RequiresApi(31) @RequiresApi(31)
int broadcastIntentWithFeature(IApplicationThread caller, String callingFeatureId, int broadcastIntentWithFeature(IApplicationThread caller, String callingFeatureId,
Intent intent, String resolvedType, IIntentReceiver resultTo, Intent intent, String resolvedType, IIntentReceiver resultTo,
@ -122,6 +123,8 @@ public interface IActivityManager extends IInterface {
Configuration getConfiguration() throws RemoteException; Configuration getConfiguration() throws RemoteException;
void registerUidObserver(IUidObserver observer, int which, int cutpoint, String callingPackage) throws RemoteException;
abstract class Stub extends Binder implements IActivityManager { abstract class Stub extends Binder implements IActivityManager {
public static int TRANSACTION_setActivityController; public static int TRANSACTION_setActivityController;

View File

@ -0,0 +1,17 @@
package android.app;
import android.os.Binder;
public interface IUidObserver {
void onUidGone(int uid, boolean disabled);
void onUidActive(int uid);
void onUidIdle(int uid, boolean disabled);
void onUidCachedChanged(int uid, boolean cached);
abstract class Stub extends Binder implements IUidObserver {
}
}

View File

@ -3,8 +3,6 @@ package org.lsposed.lspd.service;
import org.lsposed.lspd.models.Module; import org.lsposed.lspd.models.Module;
interface ILSPApplicationService { interface ILSPApplicationService {
IBinder requestModuleBinder(String name);
List<Module> getLegacyModulesList(); List<Module> getLegacyModulesList();
List<Module> getModulesList(); List<Module> getModulesList();