插件进程死亡检测

来源:互联网 发布:订餐系统源码 编辑:程序博客网 时间:2024/05/11 05:46

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方法啥都没做,直接返回了。