[core] Workaround for service manager overwritten on Android R (#581)

This commit is contained in:
LoveSy 2021-05-15 03:05:04 +08:00 committed by GitHub
parent d9f95d1280
commit 0df0a14808
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
14 changed files with 209 additions and 79 deletions

View File

@ -0,0 +1,7 @@
package org.lsposed.lspd.service;
import org.lsposed.lspd.service.ILSPApplicationService;
interface ILSPSystemServerService {
ILSPApplicationService requestApplicationService(int uid, int pid, String processName, IBinder heartBeat) = 1;
}

View File

@ -36,21 +36,21 @@ public class LSPApplicationServiceClient implements ILSPApplicationService {
static String processName = null;
public static LSPApplicationServiceClient serviceClient = null;
private static final IBinder.DeathRecipient recipient = new IBinder.DeathRecipient() {
@Override
public void binderDied() {
serviceBinder.unlinkToDeath(this, 0);
serviceBinder = null;
service = null;
}
};
public static void Init(IBinder binder, String niceName) {
if (serviceClient == null && binder != null && serviceBinder == null && service == null) {
serviceBinder = binder;
processName = niceName;
try {
serviceBinder.linkToDeath(
new IBinder.DeathRecipient() {
@Override
public void binderDied() {
serviceBinder.unlinkToDeath(this, 0);
serviceBinder = null;
service = null;
}
}, 0);
serviceBinder.linkToDeath(recipient, 0);
} catch (RemoteException e) {
Utils.logE("link to death error: ", e);
}

View File

@ -34,22 +34,25 @@ import static org.lsposed.lspd.service.ServiceManager.TAG;
public class ActivityManagerService {
private static IActivityManager am = null;
private static IBinder binder = null;
private static final IBinder.DeathRecipient deathRecipient = new IBinder.DeathRecipient() {
@Override
public void binderDied() {
Log.w(TAG, "am is dead");
binder.unlinkToDeath(this, 0);
binder = null;
am = null;
}
};
public static IActivityManager getActivityManager() {
if (binder == null && am == null) {
binder = ServiceManager.getService("activity");
if (binder == null) return null;
try {
binder.linkToDeath(new IBinder.DeathRecipient() {
@Override
public void binderDied() {
Log.w(TAG, "am is dead");
binder.unlinkToDeath(this, 0);
binder = null;
am = null;
}
}, 0);
binder.linkToDeath(deathRecipient, 0);
} catch (RemoteException e) {
Log.e(TAG, Log.getStackTraceString(e));
}

View File

@ -64,13 +64,8 @@ public class BridgeService {
private static ILSPosedService service = null;
// for service
static class BridgeServiceDeathRecipient implements IBinder.DeathRecipient {
private final IBinder bridgeService;
BridgeServiceDeathRecipient(IBinder bridgeService) throws RemoteException {
this.bridgeService = bridgeService;
bridgeService.linkToDeath(this, 0);
}
private static IBinder bridgeService;
private static final IBinder.DeathRecipient bridgeRecipient = new IBinder.DeathRecipient() {
@Override
public void binderDied() {
@ -96,16 +91,21 @@ public class BridgeService {
}
bridgeService.unlinkToDeath(this, 0);
bridgeService = null;
listener.onSystemServerDied();
sendToBridge(serviceBinder, true);
}
}
};
// for client
private static final IBinder.DeathRecipient LSPSERVICE_DEATH_RECIPIENT = () -> {
serviceBinder = null;
service = null;
Log.e(TAG, "service is dead");
private static final IBinder.DeathRecipient serviceRecipient = new IBinder.DeathRecipient() {
@Override
public void binderDied() {
serviceBinder.unlinkToDeath(this, 0);
serviceBinder = null;
service = null;
Log.e(TAG, "service is dead");
}
};
public interface Listener {
@ -121,7 +121,6 @@ public class BridgeService {
// For service
private static void sendToBridge(IBinder binder, boolean isRestart) {
IBinder bridgeService;
do {
bridgeService = ServiceManager.getService(SERVICE_NAME);
if (bridgeService != null && bridgeService.pingBinder()) {
@ -143,7 +142,7 @@ public class BridgeService {
}
try {
new BridgeServiceDeathRecipient(bridgeService);
bridgeService.linkToDeath(bridgeRecipient, 0);
} catch (Throwable e) {
Log.w(TAG, "linkToDeath " + Log.getStackTraceString(e));
sendToBridge(binder, false);
@ -218,15 +217,16 @@ public class BridgeService {
}
});
} else {
serviceBinder.unlinkToDeath(LSPSERVICE_DEATH_RECIPIENT, 0);
serviceBinder.unlinkToDeath(serviceRecipient, 0);
}
Binder.restoreCallingIdentity(token);
serviceBinder = Binder_allowBlocking(binder);
service = ILSPosedService.Stub.asInterface(serviceBinder);
try {
serviceBinder.linkToDeath(LSPSERVICE_DEATH_RECIPIENT, 0);
} catch (RemoteException ignored) {
serviceBinder.linkToDeath(serviceRecipient, 0);
} catch (Throwable e) {
Log.e(TAG, "service link to death: ", e);
}
Log.i(TAG, "binder received");
@ -324,8 +324,8 @@ public class BridgeService {
public static IBinder getApplicationServiceForSystemServer(IBinder binder, IBinder heartBeat) {
if (binder == null || heartBeat == null) return null;
try {
ILSPosedService service = ILSPosedService.Stub.asInterface(binder);
ILSPApplicationService applicationService = service.requestApplicationService(Process.myUid(), Process.myPid(), "android", heartBeat);
var service = ILSPSystemServerService.Stub.asInterface(binder);
var applicationService = service.requestApplicationService(Process.myUid(), Process.myPid(), "android", heartBeat);
if (applicationService != null) return applicationService.asBinder();
} catch (Throwable e) {
Log.e(TAG, Log.getStackTraceString(e));

View File

@ -35,18 +35,22 @@ public class LSPApplicationService extends ILSPApplicationService.Stub {
// <uid, pid>
private final static Set<Pair<Integer, Integer>> cache = ConcurrentHashMap.newKeySet();
private final static Set<IBinder> handles = ConcurrentHashMap.newKeySet();
private final static Set<IBinder.DeathRecipient> recipients = ConcurrentHashMap.newKeySet();
public boolean registerHeartBeat(int uid, int pid, IBinder handle) {
try {
handle.linkToDeath(new DeathRecipient() {
var recipient = new DeathRecipient() {
@Override
public void binderDied() {
Log.d(TAG, "pid=" + pid + " uid=" + uid + " is dead.");
cache.remove(new Pair<>(uid, pid));
handles.remove(handle);
handle.unlinkToDeath(this, 0);
recipients.remove(this);
}
}, 0);
};
recipients.add(recipient);
handle.linkToDeath(recipient, 0);
handles.add(handle);
cache.add(new Pair<>(uid, pid));
return true;

View File

@ -0,0 +1,82 @@
package org.lsposed.lspd.service;
import static org.lsposed.lspd.service.ServiceManager.TAG;
import static org.lsposed.lspd.service.ServiceManager.getSystemServiceManager;
import android.os.Build;
import android.os.IBinder;
import android.os.IServiceCallback;
import android.os.Parcel;
import android.os.RemoteException;
import android.util.Log;
public class LSPSystemServerService extends ILSPSystemServerService.Stub implements IBinder.DeathRecipient {
public static final String PROXY_SERVICE_NAME = "serial";
private IBinder originService = null;
public void putBinderForSystemServer() {
android.os.ServiceManager.addService(PROXY_SERVICE_NAME, this);
binderDied();
}
private final IServiceCallback serviceCallback = new IServiceCallback.Stub() {
@Override
public void onRegistration(String name, IBinder binder) {
if (name.equals(PROXY_SERVICE_NAME) && binder != null && binder != LSPSystemServerService.this) {
Log.d(TAG, "Register " + name + " " + binder);
originService = binder;
LSPSystemServerService.this.linkToDeath();
}
}
@Override
public IBinder asBinder() {
return this;
}
};
public LSPSystemServerService() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
try {
getSystemServiceManager().registerForNotifications(PROXY_SERVICE_NAME, serviceCallback);
} catch (Throwable e) {
Log.e(TAG, "unregister: ", e);
}
}
}
@Override
public ILSPApplicationService requestApplicationService(int uid, int pid, String processName, IBinder heartBeat) throws RemoteException {
if (ConfigManager.getInstance().shouldSkipSystemServer() || uid != 1000 || heartBeat == null || !"android".equals(processName))
return null;
else
return ServiceManager.requestApplicationService(uid, pid, heartBeat);
}
@Override
public boolean onTransact(int code, Parcel data, Parcel reply, int flags) throws RemoteException {
if (originService != null) {
return originService.transact(code, data, reply, flags);
}
return super.onTransact(code, data, reply, flags);
}
public void linkToDeath() {
try {
originService.linkToDeath(this, 0);
} catch (Throwable e) {
Log.e(TAG, "system server service: link to death", e);
}
}
@Override
public void binderDied() {
if (originService != null) {
originService.unlinkToDeath(this, 0);
originService = null;
}
}
}

View File

@ -42,12 +42,6 @@ public class LSPosedService extends ILSPosedService.Stub {
Log.w(TAG, "Someone else got my binder!?");
return null;
}
if (uid == 1000 && processName.equals("android")) {
if (ConfigManager.getInstance().shouldSkipSystemServer())
return null;
else
return ServiceManager.requestApplicationService(uid, pid, heartBeat);
}
if (ConfigManager.getInstance().shouldSkipProcess(new ConfigManager.ProcessScope(processName, uid))) {
Log.d(TAG, "Skipped " + processName + "/" + uid);
return null;
@ -60,7 +54,6 @@ public class LSPosedService extends ILSPosedService.Stub {
return ServiceManager.requestApplicationService(uid, pid, heartBeat);
}
@Override
public void dispatchPackageChanged(Intent intent) throws RemoteException {
if (Binder.getCallingUid() != 1000 || intent == null) return;

View File

@ -67,21 +67,22 @@ import hidden.HiddenApiBridge;
public class PackageService {
private static IPackageManager pm = null;
private static IBinder binder = null;
private static final IBinder.DeathRecipient recipient = new IBinder.DeathRecipient() {
@Override
public void binderDied() {
Log.w(TAG, "pm is dead");
binder.unlinkToDeath(this, 0);
binder = null;
pm = null;
}
};
public static IPackageManager getPackageManager() {
if (binder == null && pm == null) {
binder = ServiceManager.getService("package");
if (binder == null) return null;
try {
binder.linkToDeath(new IBinder.DeathRecipient() {
@Override
public void binderDied() {
Log.w(TAG, "pm is dead");
binder.unlinkToDeath(this, 0);
binder = null;
pm = null;
}
}, 0);
binder.linkToDeath(recipient, 0);
} catch (RemoteException e) {
Log.e(TAG, Log.getStackTraceString(e));
}

View File

@ -11,21 +11,22 @@ import static org.lsposed.lspd.service.ServiceManager.TAG;
public class PowerService {
private static IPowerManager pm = null;
private static IBinder binder = null;
private static final IBinder.DeathRecipient recipient = new IBinder.DeathRecipient() {
@Override
public void binderDied() {
Log.w(TAG, "pm is dead");
binder.unlinkToDeath(this, 0);
binder = null;
pm = null;
}
};
public static IPowerManager getPowerManager() {
if (binder == null && pm == null) {
binder = ServiceManager.getService("power");
if (binder == null) return null;
try {
binder.linkToDeath(new IBinder.DeathRecipient() {
@Override
public void binderDied() {
Log.w(TAG, "pm is dead");
binder.unlinkToDeath(this, 0);
binder = null;
pm = null;
}
}, 0);
binder.linkToDeath(recipient, 0);
} catch (RemoteException e) {
Log.e(TAG, Log.getStackTraceString(e));
}

View File

@ -20,18 +20,23 @@
package org.lsposed.lspd.service;
import android.content.Context;
import android.os.Build;
import android.os.IBinder;
import android.os.IServiceManager;
import android.os.Looper;
import android.util.Log;
import com.android.internal.os.BinderInternal;
import org.lsposed.lspd.BuildConfig;
import hidden.HiddenApiBridge;
public class ServiceManager {
private static LSPosedService mainService = null;
private static LSPModuleService moduleService = null;
private static LSPApplicationService applicationService = null;
private static LSPManagerService managerService = null;
private static LSPSystemServerService systemServerService = null;
public static final String TAG = "LSPosedService";
private static void waitSystemService(String name) {
@ -45,8 +50,8 @@ public class ServiceManager {
}
}
private static void putBinderForSystemServer() {
android.os.ServiceManager.addService("serial", mainService);
public static IServiceManager getSystemServiceManager() {
return IServiceManager.Stub.asInterface(HiddenApiBridge.Binder_allowBlocking(BinderInternal.getContextObject()));
}
// call by ourselves
@ -63,8 +68,9 @@ public class ServiceManager {
moduleService = new LSPModuleService();
applicationService = new LSPApplicationService();
managerService = new LSPManagerService();
systemServerService = new LSPSystemServerService();
putBinderForSystemServer();
systemServerService.putBinderForSystemServer();
waitSystemService("package");
waitSystemService("activity");
@ -89,7 +95,7 @@ public class ServiceManager {
@Override
public void onSystemServerDied() {
Log.w(TAG, "system server died");
putBinderForSystemServer();
systemServerService.putBinderForSystemServer();
}
});

View File

@ -34,21 +34,22 @@ import static org.lsposed.lspd.service.ServiceManager.TAG;
public class UserService {
private static IUserManager um = null;
private static IBinder binder = null;
private static IBinder.DeathRecipient recipient = new IBinder.DeathRecipient() {
@Override
public void binderDied() {
Log.w(TAG, "um is dead");
binder.unlinkToDeath(this, 0);
binder = null;
um = null;
}
};
public static IUserManager getUserManager() {
if (binder == null && um == null) {
binder = ServiceManager.getService("user");
if (binder == null) return null;
try {
binder.linkToDeath(new IBinder.DeathRecipient() {
@Override
public void binderDied() {
Log.w(TAG, "um is dead");
binder.unlinkToDeath(this, 0);
binder = null;
um = null;
}
}, 0);
binder.linkToDeath(recipient, 0);
} catch (RemoteException e) {
Log.e(TAG, Log.getStackTraceString(e));
}

View File

@ -0,0 +1,13 @@
package android.os;
public interface IServiceCallback extends IInterface
{
public static abstract class Stub extends android.os.Binder implements android.os.IServiceCallback {
}
/**
* Called when a service is registered.
*
* @param name the service name that has been registered with
* @param binder the binder that is registered
*/
public void onRegistration(java.lang.String name, android.os.IBinder binder) throws android.os.RemoteException;
}

View File

@ -1,4 +1,16 @@
package android.os;
public interface IServiceManager {
public interface IServiceManager extends IInterface {
void tryUnregisterService(java.lang.String name, android.os.IBinder service);
IBinder getService(String name);
public void registerForNotifications(String name, IServiceCallback cb);
abstract class Stub extends Binder implements IServiceManager {
public static IServiceManager asInterface(IBinder obj) {
throw new UnsupportedOperationException();
}
}
}

View File

@ -0,0 +1,7 @@
package com.android.internal.os;
import android.os.IBinder;
public class BinderInternal {
public static final native IBinder getContextObject();
}