[core] Workaround for service manager overwritten on Android R (#581)
This commit is contained in:
parent
d9f95d1280
commit
0df0a14808
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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));
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
}
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -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));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,7 @@
|
|||
package com.android.internal.os;
|
||||
|
||||
import android.os.IBinder;
|
||||
|
||||
public class BinderInternal {
|
||||
public static final native IBinder getContextObject();
|
||||
}
|
||||
Loading…
Reference in New Issue