3插件进程死亡检测
插件进程死亡时,宿主是如何知道的呢?通过RemoteCallbackList机制。
还有万一宿主挂掉了呢,插件进程是如何知道的?
插件进程启动的时候,创建宿主Application并调用其onCreate(),因此会调用到PluginHelper的applicationOnCreate()方法。
前面论述过,除了进行Hook 初始化之外,还进行了启动并绑定PluginManagerService服务。再说一次, PluginManager是运行于
插件中的客户端,而IpluginManagerImpl是运行于宿主的服务端。
PluginManager的onServiceConnected方法完成了2件事情,
1,调用服务端的registerApplicationCallback方法进行注册。
mPluginManager.registerApplicationCallback(new IApplicationCallback.Stub() {
@Override
public Bundle onCallback(Bundle extra) throws RemoteException {
return extra;
}
});
2,监听服务端是否死亡。
mPluginManager.asBinder().linkToDeath(new IBinder.DeathRecipient() {
@Override
public void binderDied() {
onServiceDisconnected(componentName);
}
}, 0);
服务端IpluginManagerImpl如果死亡,就会调用onServiceDisconnected方法,
public void onServiceDisconnected(ComponentName componentName) {
Log.i(TAG, "onServiceDisconnected disconnected!");
mPluginManager = null;
Iterator<WeakReference<ServiceConnection>> iterator = sServiceConnection.iterator();
while (iterator.hasNext()) {
WeakReference<ServiceConnection> wsc = iterator.next();
ServiceConnection sc = wsc != null ? wsc.get() : null;
if (sc != null) {
sc.onServiceDisconnected(componentName);
} else {
iterator.remove();
}
}
//服务连接断开,需要重新连接。
connectToService();
}
onServiceDisconnected方法也很简单,直接重新启动绑定服务端。
回头看看registerApplicationCallback方法, IpluginManagerImpl的registerApplicationCallback方法如下,
public boolean registerApplicationCallback(IApplicationCallback callback) throws RemoteException {
return mActivityManagerService.registerApplicationCallback(Binder.getCallingPid(), Binder.getCallingUid(), callback);
}
BaseActivityManagerService的registerApplicationCallback方法如下,
public boolean registerApplicationCallback(int callingPid, int callingUid, IApplicationCallback callback) {
return mRemoteCallbackList.register(callback, new ProcessCookie(callingPid, callingUid));
}
ProcessCookie是内部类,主要保存插件进程的pid,uid信息。
mRemoteCallbackList是内部类MyRemoteCallbackList对象,
private RemoteCallbackList<IApplicationCallback> mRemoteCallbackList;
在BaseActivityManagerService的构造方法中,
public void onCreate(IPluginManagerImpl pluginManagerImpl) throws Exception {
if (mRemoteCallbackList == null) {
mRemoteCallbackList = new MyRemoteCallbackList();
}
}
MyRemoteCallbackList定义如下,
private class MyRemoteCallbackList extends RemoteCallbackList<IApplicationCallback> {
@Override
public void onCallbackDied(IApplicationCallback callback, Object cookie) {
super.onCallbackDied(callback, cookie);
if (cookie != null && cookie instanceof ProcessCookie) {
ProcessCookie p = (ProcessCookie) cookie;
onProcessDied(p.pid, p.uid);
}
}
}
继承于RemoteCallbackList,实现了onCallbackDied方法。
因此,当插件进程die的时候,就会调用onCallbackDied方法,这样就可以达到监听插件的目的。
onProcessDied方法如下,
protected void onProcessDied(int pid, int uid) {
Log.i(TAG, "onProcessDied,pid=%s,uid=%s", pid, uid);
}
这个方法其实啥都没做。
另外,注册的目的其实是监听,并不是为了服务端回调onCallback方法。
虽然有一个sendCallBack方法里调用客户端的onCallback方法,
protected void sendCallBack(Bundle extra) {
if (mRemoteCallbackList != null) {
int i = mRemoteCallbackList.beginBroadcast();
while (i > 0) {
i--;
try {
mRemoteCallbackList.getBroadcastItem(i).onCallback(extra);
} catch (RemoteException e) {
// The RemoteCallbackList will take care of removing
// the dead object for us.
}
}
mRemoteCallbackList.finishBroadcast();
}
}
但是这个方法从来都不会调用,并且客户端PluginManager的onCallback方法啥都没做,直接返回了。