Skip to content

Instantly share code, notes, and snippets.

@hyongbai
Created November 30, 2018 03:24
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save hyongbai/8473c8aa1b464d4bb9252d963424012e to your computer and use it in GitHub Desktop.
Save hyongbai/8473c8aa1b464d4bb9252d963424012e to your computer and use it in GitHub Desktop.
PmHostSvc:IPluginHost
=====================
@Override
public Map<String, List<String>> queryLocalBroadcasts(String action, boolean hostOnly) throws RemoteException {
if (LogDebug.LOG) {
LogDebug.d("IPluginHost", String.format("queryLocalBroadcasts(%s): >>>>>> ", action));
}
final long start = LogDebug.LOG ? System.currentTimeMillis() : 0;
//
final Map<String, List<String>> map = new HashMap<>();
final PluginBinderInfo info = new PluginBinderInfo(PluginBinderInfo.NONE_REQUEST);
for (PluginRunningList prl : mManager.getRunningMap().values()) {
final IPluginClient client = getClientByPid(prl.getPid(), info);
if (LogDebug.LOG) {
LogDebug.d("IPluginHost", String.format("Process %s -> %s", client, prl));
}
if (client == null) continue;
final List<String> list = new ArrayList<>(1 << 4);
// 从宿主获取: 历史遗留问题,旧版本插件的本地广播代理的的是宿主的LocalBroadcast
if (search(action, client, prl.getProcessName())) list.add(prl.getProcessName());
/* 从插件获取:使用插件获取对应ClassLoader获取其中的class文件,见@{link com.qihoo360.loader2.PluginProcessPer} */
if (!hostOnly) for (String p : prl) if (search(action, client, p)) list.add(p);
// 装载结果
if (!list.isEmpty()) map.put(prl.getProcessName(), list);
}
//
if (LogDebug.LOG) {
LogDebug.d("IPluginHost", String.format("queryLocalBroadcasts[%sms]: %s", (System.currentTimeMillis() - start), map));
}
return map;
}
////
private boolean search(String action, IPluginClient client, String plugin) throws RemoteException {
final List<String> actions = client.dumpLocalBroadcasts(plugin);
return actions != null && actions.contains(action);
}
private IPluginClient getClientByPid(int pid, PluginBinderInfo info) {
if (pid == IPC.getCurrentProcessId()) return mPluginMgr.mClient;
return PluginProcessMain.probePluginClientByPid(pid, info);
}
PluginProcessPer:IPluginClient
==============================
private Map<Integer, Class> mLoBroadClzCache = new ConcurrentHashMap<>(1 << 4);
// private Map<Integer, Object> mLoBroadIntancesCache = new ConcurrentHashMap<>(1 << 4);
private Class loadLocalBroadcastClass(String plugin) {
if (TextUtils.isEmpty(plugin) || TextUtils.equals(plugin, IPC.getCurrentProcessName())) {
return LocalBroadcastManager.class;
}
final Plugin p = PMF.sPluginMgr.getPlugin(plugin);
if (p == null || !p.isLoaded()) return null;
// Cache class, ClassLoader not null
final Integer key = p.getClassLoader().hashCode();
final Map<Integer, Class> cache = mLoBroadClzCache;
if (cache.containsKey(key)) return cache.get(key);
Class clz = null;
try {
clz = p.getClassLoader().loadClass("android.support.v4.content.LocalBroadcastManager");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
cache.put(key, clz);
return clz;
}
private List<String> doDumpLocalBroadcast(String plugin, Class cls) throws NoSuchFieldException, IllegalAccessException {
if (cls == null) return null;
final Object lbm = ReflectUtils.readStaticField(cls, "mInstance");
if (lbm == null) {
if (LogDebug.LOG) {
LogDebug.d("IPluginClient", String.format("dumpLocalBroadcasts [ %s ] mInstance = NULL", plugin));
}
return null;
}
// Cache mInstance ????
final Object actions = ReflectUtils.readField(lbm, "mActions");
if (LogDebug.LOG) {
LogDebug.d("IPluginClient", String.format("dumpLocalBroadcasts [ %s ] mInstance = %s, mActions = %s", plugin, lbm, actions));
}
if (actions == null) return null;
return new ArrayList(((Map) actions).keySet());
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment