AndroidQ SystemUI之插件化机制Plugin

您所在的位置:网站首页 systemui模块 AndroidQ SystemUI之插件化机制Plugin

AndroidQ SystemUI之插件化机制Plugin

2023-12-11 23:33| 来源: 网络整理| 查看: 265

这篇文章接着上一篇SystemUI之启动未分析完的SystemUI插件化机制相关的代码

SystemUI插件

SystemUI插件提供了一种快速创建SystemUI功能原型的简便方法,可以在运行时更改SystemUI的行为。 通过创建插件实现SysUI中使用的一组基本接口来完成,然后可以比当前更快的速度迭代由该接口控制的部分代码。

简单来说就是可以快速替换SystemUI原有的组件,也叫hook,我们就来分析下其中的原理

SystemUIApplication.startServicesIfNeeded private void startServicesIfNeeded(String[] services) { //省略上一篇文章分析过的代码 ..... Dependency.get(InitController.class).executePostInitTasks(); log.traceEnd(); final Handler mainHandler = new Handler(Looper.getMainLooper()); //调用addPluginListener传入了三个参数,PluginListener, //OverlayPlugin.class,和一个boolean值true Dependency.get(PluginManager.class).addPluginListener( new PluginListener() { private ArraySet mOverlays = new ArraySet(); @Override public void onPluginConnected(OverlayPlugin plugin, Context pluginContext) { mainHandler.post(new Runnable() { @Override public void run() { StatusBar statusBar = getComponent(StatusBar.class); if (statusBar != null) { plugin.setup(statusBar.getStatusBarWindow(), statusBar.getNavigationBarView(), new Callback(plugin)); } } }); } @Override public void onPluginDisconnected(OverlayPlugin plugin) { mainHandler.post(new Runnable() { @Override public void run() { mOverlays.remove(plugin); Dependency.get(StatusBarWindowController.class).setForcePluginOpen( mOverlays.size() != 0); } }); } class Callback implements OverlayPlugin.Callback { private final OverlayPlugin mPlugin; Callback(OverlayPlugin plugin) { mPlugin = plugin; } @Override public void onHoldStatusBarOpenChange() { if (mPlugin.holdStatusBarOpen()) { mOverlays.add(mPlugin); } else { mOverlays.remove(mPlugin); } mainHandler.post(new Runnable() { @Override public void run() { Dependency.get(StatusBarWindowController.class) .setStateListener(b -> mOverlays.forEach( o -> o.setCollapseDesired(b))); Dependency.get(StatusBarWindowController.class) .setForcePluginOpen(mOverlays.size() != 0); } }); } } }, OverlayPlugin.class, true /* Allow multiple plugins */); mServicesStarted = true; }

Dependency是定义在config_systemUIServiceComponents这个config文件中的,在startServicesIfNeeded中会遍历此config定义的所有SystemUI重要类,调用它们的Start方法:

Dependency.start @Override public void start() { // TODO: Think about ways to push these creation rules out of Dependency to cut down // on imports. mProviders.put(TIME_TICK_HANDLER, mTimeTickHandler::get); mProviders.put(BG_LOOPER, mBgLooper::get); mProviders.put(BG_HANDLER, mBgHandler::get); mProviders.put(MAIN_HANDLER, mMainHandler::get); mProviders.put(ActivityStarter.class, mActivityStarter::get); mProviders.put(ActivityStarterDelegate.class, mActivityStarterDelegate::get); mProviders.put(AsyncSensorManager.class, mAsyncSensorManager::get); mProviders.put(BluetoothController.class, mBluetoothController::get); mProviders.put(SensorPrivacyManager.class, mSensorPrivacyManager::get); mProviders.put(LocationController.class, mLocationController::get); mProviders.put(RotationLockController.class, mRotationLockController::get); mProviders.put(NetworkController.class, mNetworkController::get); mProviders.put(ZenModeController.class, mZenModeController::get); mProviders.put(HotspotController.class, mHotspotController::get); mProviders.put(CastController.class, mCastController::get); mProviders.put(FlashlightController.class, mFlashlightController::get); mProviders.put(KeyguardMonitor.class, mKeyguardMonitor::get); mProviders.put(UserSwitcherController.class, mUserSwitcherController::get); mProviders.put(UserInfoController.class, mUserInfoController::get); mProviders.put(BatteryController.class, mBatteryController::get); ...... sDependency = this; }

我们可以看到,start方法中将很多的类添加到了mProviders中,接着看:

Dependency.get private static Dependency sDependency; @Deprecated public static T get(Class cls) { return sDependency.getDependency(cls); } protected final T getDependency(Class cls) { return getDependencyInner(cls); } private synchronized T getDependencyInner(Object key) { @SuppressWarnings("unchecked") T obj = (T) mDependencies.get(key); if (obj == null) { obj = createDependency(key); mDependencies.put(key, obj); } return obj; }

get方法最终通过mDependencies.get来获取对象,mDependencies是个ArrayMap,如果没有获取到就调用createDependency创建对象,创建之后放入mDependencies中

createDependency @VisibleForTesting protected T createDependency(Object cls) { @SuppressWarnings("unchecked") LazyDependencyCreator provider = mProviders.get(cls); if (provider == null) { throw new IllegalArgumentException("Unsupported dependency " + cls + ". " + mProviders.size() + " providers known."); } return provider.createDependency(); }

此方法通过mProviders.get来获取对象,mProviders中的类就是在Start方法中添加的,所以能够直接获取,Dependency中用到了dagger框架的Lazy,Provider等机制。

addPluginListener

所以我们在看到Dependency.get(T.class)时就可以简单认为是获取T的实现类 接着SystemUIApplication的startServicesIfNeeded方法添加插件监听,这里实际调用PluginManagerImpl的addPluginListener方法,此方法接收三个参数:一个PluginListener接口,一个Class对象,一个boolean值

PluginManagerImpl中的addPluginListener有几个重载,为了好说明,我给它们编了个号

(1) public void addPluginListener(PluginListener listener, Class cls) { addPluginListener(listener, cls, false); } (2) public void addPluginListener(PluginListener listener, Class cls, boolean allowMultiple) { addPluginListener(PluginManager.Helper.getAction(cls), listener, cls, allowMultiple); } (3) public void addPluginListener(String action, PluginListener listener, Class cls) { addPluginListener(action, listener, cls, false); } (4) public void addPluginListener(String action, PluginListener listener, Class cls, boolean allowMultiple) { android.util.Log.d("djtang","addPluginListener...action = :"+action+",name = :"+cls.getName()); mPluginPrefs.addAction(action); PluginInstanceManager p = mFactory.createPluginInstanceManager(mContext, action, listener, allowMultiple, mLooper, cls, this); p.loadAll(); mPluginMap.put(listener, p); startListening(); } PluginListener

我们先来看下PluginListener这个接口,这是个泛型接口,其中T必须是Plugin的子类,此接口提供两个生命周期方法,插件连接时调用onPluginConnected,断开连接调用 onPluginDisconnected

public interface PluginListener { void onPluginConnected(T plugin, Context pluginContext); default void onPluginDisconnected(T plugin) { } }

从上面代码我们知道,Dependency.get(PluginManager.class).addPluginListener调用的是(2)号重载方法,获取了一个Action后调用了(4)号方法,看下Action是啥:

PluginManager.Helper.getAction(cls) public interface PluginManager { class Helper { public static String getAction(Class cls) { //获取ProvidesInterface的注解信息 ProvidesInterface info = cls.getDeclaredAnnotation(ProvidesInterface.class); if (info == null) { throw new RuntimeException(cls + " doesn't provide an interface"); } if (TextUtils.isEmpty(info.action())) { throw new RuntimeException(cls + " doesn't provide an action"); } //获取ProvidesInterface注解的action return info.action(); } }

通过getDeclaredAnnotation方法获取注解,ProvidesInterface这是个注解类,每个继承Plugin的类包含一个ProvidesInterface,这个注解类包含两项,version和action

public @interface ProvidesInterface { int version(); String action() default ""; }

用法如下:

@ProvidesInterface(action = MyPlugin.ACTION, version = MyPlugin.VERSION) public interface MyPlugin extends Plugin { String ACTION = "com.android.systemui.action.PLUGIN_MY_PLUGIN"; int VERSION = 1; ... }

这样就通过ProvidesInterface注解将action和version暴露了出来,获取的方式很简单,调用ProvidesInterface的action方法获取的就是其action

public interface PluginManager { class Helper { public static String getAction(Class cls) { ProvidesInterface info = cls.getDeclaredAnnotation(ProvidesInterface.class); if (info == null) { throw new RuntimeException(cls + " doesn't provide an interface"); } if (TextUtils.isEmpty(info.action())) { throw new RuntimeException(cls + " doesn't provide an action"); } return info.action(); } }

我们再回到Dependency.get(PluginManager.class).addPluginListener的方法,它的第二个参数是OverlayPlugin.class

OverlayPlugin @ProvidesInterface(action = OverlayPlugin.ACTION, version = OverlayPlugin.VERSION) public interface OverlayPlugin extends Plugin { String ACTION = "com.android.systemui.action.PLUGIN_OVERLAY"; int VERSION = 3; ..... }

根据我们上面的分析,就知道了在(2)号方法中获取的action就是OverlayPlugin中定义的ACTION = “com.android.systemui.action.PLUGIN_OVERLAY”,通过ProvidesInterface注解获取,好了接着(2)号方法调到了(4)号方法:

public void addPluginListener(String action, PluginListener listener, Class cls, boolean allowMultiple) { mPluginPrefs.addAction(action); PluginInstanceManager p = mFactory.createPluginInstanceManager(mContext, action, listener, allowMultiple, mLooper, cls, this); p.loadAll(); mPluginMap.put(listener, p); startListening(); }

首先将action添加到mPluginPrefs,mPluginPrefs是一个PluginPrefs,它的内部有一个ArraySet和一个SharedPreferences,它的存储机制就是将action先存储到ArraySet,再将此ArraySet存到SharedPreferences中,具体代码就不贴出了

接着mFactory.createPluginInstanceManager方法,mFactory是PluginInstanceManagerFactory类型,是PluginManagerImpl的静态内部类

@VisibleForTesting public static class PluginInstanceManagerFactory { public PluginInstanceManager createPluginInstanceManager(Context context, String action, PluginListener listener, boolean allowMultiple, Looper looper, Class cls, PluginManagerImpl manager) { return new PluginInstanceManager(context, action, listener, allowMultiple, looper, new VersionInfo().addClass(cls), manager); } }

createPluginInstanceManager其实就是new了一个PluginInstanceManager对象, 接着调用了PluginInstanceManager的loadAll方法

PluginInstanceManager.loadAll() public void loadAll() { if (DEBUG) Log.d(TAG, "startListening"); mPluginHandler.sendEmptyMessage(PluginHandler.QUERY_ALL); }

通过handler处理消息,注意mPluginHandler这个handler,它发送的消息并不是到主线程的,因为它使用的不是主线程的Looper,这个looper其实是: mProviders.put(BG_LOOPER, mBgLooper::get),是一个后台Looper

PluginInstanceManager(Context context, PackageManager pm, String action, PluginListener listener, boolean allowMultiple, Looper looper, VersionInfo version, PluginManagerImpl manager, boolean debuggable, String[] pluginWhitelist) { mMainHandler = new MainHandler(Looper.getMainLooper()); mPluginHandler = new PluginHandler(looper); ... } QUERY_ALL

接着看mPluginHandler里的具体处理:

private class PluginHandler extends Handler { private final ArrayList mPlugins = new ArrayList(); public void handleMessage(Message msg) { switch (msg.what) { case QUERY_ALL: if (DEBUG) Log.d(TAG, "queryAll " + mAction); //如果mPlugins不为空,则遍历mPlugins,调用onPluginDisconnected //清理Plugin for (int i = mPlugins.size() - 1; i >= 0; i--) { PluginInfo plugin = mPlugins.get(i); mListener.onPluginDisconnected(plugin.mPlugin); if (!(plugin.mPlugin instanceof PluginFragment)) { plugin.mPlugin.onDestroy(); } } //清空mPlugins mPlugins.clear(); handleQueryPlugins(null); break; ..... } } handleQueryPlugins private void handleQueryPlugins(String pkgName) { Intent intent = new Intent(mAction); //pkgName == null,此处的intent只有action,没有pkgName if (pkgName != null) { intent.setPackage(pkgName); } //給定intent,返回满足条件的ResolveInfo(本质是service)集合 List result = mPm.queryIntentServices(intent, 0); if (DEBUG) Log.d(TAG, "Found " + result.size() + " plugins"); //mAllowMultiple == true,不会走进去 if (result.size() > 1 && !mAllowMultiple) { Log.w(TAG, "Multiple plugins found for " + mAction); if (DEBUG) { for (ResolveInfo info : result) { ComponentName name = new ComponentName(info.serviceInfo.packageName, info.serviceInfo.name); Log.w(TAG, " " + name); } } return; } //遍历ResolveInfo for (ResolveInfo info : result) { ComponentName name = new ComponentName(info.serviceInfo.packageName, info.serviceInfo.name); //根据info信息创建插件 PluginInfo t = handleLoadPlugin(name); if (t == null) continue; //如果成功创建了PluginInfo就添加到mPlugins保存 mPlugins.add(t); //将创建好的PluginInfo发送到主线程处理 mMainHandler.obtainMessage(mMainHandler.PLUGIN_CONNECTED, t).sendToTarget(); } } PLUGIN_CONNECTED private class MainHandler extends Handler { public void handleMessage(Message msg) { switch (msg.what) { case PLUGIN_CONNECTED: if (DEBUG) Log.d(TAG, "onPluginConnected"); PluginPrefs.setHasPlugins(mContext); //将handler发送过来的obj强转为PluginInfo PluginInfo info = (PluginInfo) msg.obj; mManager.handleWtfs(); //如果是Fragment类型的Plugin if (!(msg.obj instanceof PluginFragment)) { //调用它的onCreate方法 info.mPlugin.onCreate(mContext, info.mPluginContext); } //调用onPluginConnected方法 mListener.onPluginConnected(info.mPlugin, info.mPluginContext); break; ...... } }

我们可以看到mPluginHandler和mMainHandler的逻辑还是比较对称的:

mPluginHandler在后台线程处理消息,在收到QUERY_ALL消息后如果有Plugin则先判断是否是Fragment类型Plugin,如果是则调用onDestroy方法,还会调用Plugin添加的PluginListener的回调onPluginDisconnectedmMainHandler在主线程处理mPluginHandler发送来的Plugin,同样判断如果是Fragment类型Plugin则调用onCreate,还会调用Plugin添加的PluginListener的回调onPluginConnected

我们再会到addPluginListener,经过上面的分析,我们知道了PluginInstanceManager是一个专门用来管理Plugin的类,每个Plugin对应一个

public void addPluginListener(String action, PluginListener listener, Class cls, boolean allowMultiple) { mPluginPrefs.addAction(action); PluginInstanceManager p = mFactory.createPluginInstanceManager(mContext, action, listener, allowMultiple, mLooper, cls, this); p.loadAll(); mPluginMap.put(listener, p); startListening(); }

mPluginMap是一个ArrayMap,将同一个Plugin的listener和PluginInstanceManager一一对应的保存进去

private final ArrayMap mPluginMap = new ArrayMap(); startListening() private void startListening() { //保证只启动一次 if (mListening) return; mListening = true; IntentFilter filter = new IntentFilter(Intent.ACTION_PACKAGE_ADDED); filter.addAction(Intent.ACTION_PACKAGE_CHANGED); filter.addAction(Intent.ACTION_PACKAGE_REPLACED); filter.addAction(Intent.ACTION_PACKAGE_REMOVED); filter.addAction(PLUGIN_CHANGED); filter.addAction(DISABLE_PLUGIN); filter.addDataScheme("package"); mContext.registerReceiver(this, filter); filter = new IntentFilter(Intent.ACTION_USER_UNLOCKED); mContext.registerReceiver(this, filter); }

这个方法就是注册了一些广播,PluginManagerImpl继承BroadcastReceiver,所有收到广播的处理都在它自己的onReceive方法中:

public void onReceive(Context context, Intent intent) { if(Intent.ACTION_USER_UNLOCKED.equals(intent.getAction())){ ...... }else if(DISABLE_PLUGIN.equals(intent.getAction())){ ...... }else { ..... if (!Intent.ACTION_PACKAGE_REMOVED.equals(intent.getAction())) { for (PluginInstanceManager manager : mPluginMap.values()) { manager.onPackageChange(pkg); } } else { for (PluginInstanceManager manager : mPluginMap.values()) { manager.onPackageRemoved(pkg); } } } }

我们可以看到,else分支中如果是ACTION_PACKAGE_REMOVED广播则调用 manager.onPackageRemoved,否则调用manager.onPackageChange,这两个方法在PluginInstanceManager类中,其实它们是一对相对应的方法,一个onPackageRemoved最终会调到PluginListener的onPluginDisconnected中, onPackageChange最终会调到PluginListener的onPluginConnected中,我们看下具体代码:

PluginInstanceManager

onPackageChange中相当于先调了一次onPackageRemoved

public void onPackageRemoved(String pkg) { mPluginHandler.obtainMessage(PluginHandler.REMOVE_PKG, pkg).sendToTarget(); } public void onPackageChange(String pkg) { mPluginHandler.obtainMessage(PluginHandler.REMOVE_PKG, pkg).sendToTarget(); mPluginHandler.obtainMessage(PluginHandler.QUERY_PKG, pkg).sendToTarget(); } QUERY_PKG和REMOVE_PKG private class PluginHandler extends Handler { public void handleMessage(Message msg) { switch (msg.what) { case REMOVE_PKG: mMainHandler.obtainMessage(MainHandler.PLUGIN_DISCONNECTED, plugin.mPlugin).sendToTarget(); break; case QUERY_PKG: String p = (String) msg.obj; handleQueryPlugins(p); ..... break; } } }

REMOVE_PKG中向MainHandler主线程发送了PLUGIN_DISCONNECTED的msg,QUERY_PKG中调用了handleQueryPlugins方法,此方法前面已经分析过了,最终是向MainHandler主线程发送了PLUGIN_CONNECTED的msg

private class MainHandler extends Handler { switch (msg.what) { case PLUGIN_CONNECTED: ...... mListener.onPluginConnected(info.mPlugin, info.mPluginContext); break; case PLUGIN_DISCONNECTED: mListener.onPluginDisconnected((T) msg.obj); ...... break; } }

我们看到startListening注册的广播里处理了PluginListener的回调

本篇以SystemUI启动过程中添加的OverlayPlugin为例分析了SystemUI的插件化机制Plugin

关于Plugin作一个总结: Systemui插件化机制的添加步骤:

创建一个继承自Plugin或者FragmentBase的接口,定义ACTION和VERSION,使用ProvidesInterface注解将ACTION和VERSION暴露出去创建PluginListener接口作为Plugin的回调调用PluginManagerImpl的addPluginListener方法添加PluginListener和Plugin

SystemUI插件化的目的就是使开发者能够轻松随意替换SystemUI的一些组件,而不需要修改大量代码,在AOSP提供的官方doc中提到要使用插件化Plugin的条件有:

必须使用平台证书进行签名必须在LOCAL_JAVA_LIBRARIES中包含SystemUIPluginLib(不能是LOCAL_STATIC_JAVA_LIBRARIES)声明插件还需要在清单文件中注册类似如下代码: 需要添加相应权限: 然后实现你需要替换的SystemUI组件的提供的插件接口 @Requires(target = OverlayPlugin.class, version = OverlayPlugin.VERSION) public class SampleOverlayPlugin implements OverlayPlugin { ... }


【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3