- UI进程,Persistent进程
Replugin启动时会默认启动两个进程,一个是UI进程,一个是Persistent进程(常驻进程),在IPluginManager
接口中定义了两个常量PROCESS_UI
和PROCESS_PERSIST
来表示这两个进程。
public interface IPluginManager {
int PROCESS_UI = -1; //UI进程
int PROCESS_PERSIST = -2; //Persistent进程
}
UI进程很好理解,就是程序的主进程。
Persistent进程是一个服务器进程,默认用:GuardService来标示,它是Replugin的核心之一。所有其他的进程在启动组件的时候都会通过PmHostSvc 与这个进程通信,
以下是Persistent进程中运行的两个重要服务:
- PluginManagerServer 用于插件的管理,比如加载插件,更新插件信息,签名验证,版本检查,插件卸载等
- PluginServiceServer 用于Service的启动调度等工作
出处:神罗天征_39a0
还是先来到attachBaseContext这里
public static void attachBaseContext(Application app, RePluginConfig config) {
......
RePluginInternal.init(app);
sConfig = config;
sConfig.initDefaults(app);
IPC.init(app); //初始化进程信息,判断当前进程是UI进程还是Persistent进程
......
PMF.init(app); //初始化当前进程
PMF.callAttach();
sAttached = true;
}
还是去看PMF.init()
public static final void init(Application application) {
setApplicationContext(application);
PluginManager.init(application);
//感觉这个pluginMgr才像PluginManager
sPluginMgr = new PmBase(application);
sPluginMgr.init();
Factory.sPluginManager = PMF.getLocal();
Factory2.sPLProxy = PMF.getInternal();
//之前我们已经知道这是用来Hook的
PatchClassLoaderUtils.patch(application);
}
我们这里看下sPluginMgr.init();做了啥
void init() {
//这些都不用看
if (HostConfigHelper.PERSISTENT_ENABLE) {
// (默认)“常驻进程”作为插件管理进程,则常驻进程作为Server,其余进程作为Client
if (IPC.isPersistentProcess()) {
// 初始化“Server”所做工作
initForServer();
} else {
// 连接到Server
initForClient();
}
} else {
// “UI进程”作为插件管理进程(唯一进程),则UI进程既可以作为Server也可以作为Client
if (IPC.isUIProcess()) {
// 1. 尝试初始化Server所做工作,
initForServer();
// 2. 注册该进程信息到“插件管理进程”中
// 注意:这里无需再做 initForClient,因为不需要再走一次Binder
PMF.sPluginMgr.attach();
} else {
// 其它进程?直接连接到Server即可
initForClient();
}
}
}
我来解释一下上面做了啥, 这里处理的并不是很好, 因为插件有两种方式, 第一种是单独使用一个常驻进程用做插件管理, 第二种是让UI进程成为插件管理进程, 少一个进程的开销。这里我们主要看initForServer();
initForClient(); 这两个方法
顾名思义, 一个用来初始化服务端, 一个初始化客户端
先来看初始化服务端的
/**
* Persistent(常驻)进程的初始化
*
*/
private final void initForServer() {
if (LOG) {
LogDebug.d(PLUGIN_TAG, "search plugins from file system");
}
mHostSvc = new (mContext, this);
PluginProcessMain.installHost(mHostSvc);
StubProcessManager.schedulePluginProcessLoop(StubProcessManager.CHECK_STAGE1_DELAY);
// 兼容即将废弃的p-n方案 by Jiongxuan Zhang
mAll = new Builder.PxAll();
Builder.builder(mContext, mAll);
refreshPluginMap(mAll.getPlugins());
// [Newest!] 使用全新的RePlugin APK方案
// Added by Jiongxuan Zhang
try {
List<PluginInfo> l = PluginManagerProxy.load();
if (l != null) {
// 将"纯APK"插件信息并入总的插件信息表中,方便查询
// 这里有可能会覆盖之前在p-n中加入的信息。本来我们就想这么干,以"纯APK"插件为准
refreshPluginMap(l);
}
} catch (RemoteException e) {
if (LOGR) {
LogRelease.e(PLUGIN_TAG, "lst.p: " + e.getMessage(), e);
}
}
}
我们看到了PmHostSvc, 前面我们知道, 所有其他的进程在启动组件的时候都会通过PmHostSvc 与这个进程通信,PluginProcessMain.installHost(mHostSvc);
这里没有看太明白
先忽略上面的
我们来看看PMF.init的最后一个流程
这里先挂载了当前进程的所有插件
若运行在PluginProcess中, 则启动该插件
final void callAttach() {
//
mClassLoader = PmBase.class.getClassLoader();
// 挂载
for (Plugin p : mPlugins.values()) {
p.attach(mContext, mClassLoader, mLocal);
}
// 加载默认插件
if (PluginManager.isPluginProcess()) {
if (!TextUtils.isEmpty(mDefaultPluginName)) {
//
Plugin p = mPlugins.get(mDefaultPluginName);
if (p != null) {
boolean rc = p.load(Plugin.LOAD_APP, true);
if (!rc) {
if (LOG) {
LogDebug.d(PLUGIN_TAG, "failed to load default plugin=" + mDefaultPluginName);
}
}
if (rc) {
mDefaultPlugin = p;
mClient.init(p);
}
}
}
}
}
好了, 就这么多, 目前不清楚的是initForServer(), 和initForClient()
这样我们就完成了UI进程 以及插件管理进程的启动, 以及某些default插件的加载初始化