wmshell是systemui进程里面的,随着systemui的application创建构造出来,包含了很多模块比如pip,freeform,split,shelltransition。大量使用了dagger2注解。
xml
<application
android:name=".SystemUIApplication"
android:persistent="true"
android:allowClearUserData="false"
android:backupAgent=".backup.BackupHelper"
android:killAfterRestore="false"
android:hardwareAccelerated="true"
android:label="@string/app_label"
android:icon="@drawable/android15_patch_adaptive"
android:process="com.android.systemui"
android:supportsRtl="true"
android:theme="@style/Theme.SystemUI"
android:defaultToDeviceProtectedStorage="true"
android:directBootAware="true"
android:appComponentFactory=".PhoneSystemUIAppComponentFactory">
systemui自定义了application---> SystemUIApplication 并且提供了appComponentFactory工厂,这个是在构建四大组件的时候,方便用户定制自己的需求提供了钩子。
通过堆栈
java
07-29 10:50:08.264 922 922 D xmsysui : java.lang.Exception
07-29 10:50:08.264 922 922 D xmsysui : at com.android.systemui.SystemUIAppComponentFactoryBase.instantiateApplicationCompat(SystemUIAppComponentFactoryBase.kt:83)
07-29 10:50:08.264 922 922 D xmsysui : at androidx.core.app.AppComponentFactory.instantiateApplication(AppComponentFactory.java:61)
07-29 10:50:08.264 922 922 D xmsysui : at android.app.Instrumentation.newApplication(Instrumentation.java:1357)
07-29 10:50:08.264 922 922 D xmsysui : at android.app.LoadedApk.makeApplicationInner(LoadedApk.java:1471)
07-29 10:50:08.264 922 922 D xmsysui : at android.app.LoadedApk.makeApplicationInner(LoadedApk.java:1403)
07-29 10:50:08.264 922 922 D xmsysui : at android.app.ActivityThread.handleBindApplication(ActivityThread.java:7658)
07-29 10:50:08.264 922 922 D xmsysui : at android.app.ActivityThread.-$$Nest$mhandleBindApplication(Unknown Source:0)
07-29 10:50:08.264 922 922 D xmsysui : at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2500)
07-29 10:50:08.264 922 922 D xmsysui : at android.os.Handler.dispatchMessage(Handler.java:109)
07-29 10:50:08.264 922 922 D xmsysui : at android.os.Looper.loopOnce(Looper.java:232)
07-29 10:50:08.264 922 922 D xmsysui : at android.os.Looper.loop(Looper.java:317)
07-29 10:50:08.264 922 922 D xmsysui : at android.app.ActivityThread.main(ActivityThread.java:8934)
07-29 10:50:08.264 922 922 D xmsysui : at java.lang.reflect.Method.invoke(Native Method)
07-29 10:50:08.264 922 922 D xmsysui : at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:591)
07-29 10:50:08.264 922 922 D xmsysui : at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:911)
可以看到在创建application时,会回调android.app.AppComponentFactory中的instantiateApplication()方法,systemui里面提供了PhoneSystemUIAppComponentFactory。
class android.app.AppComponentFactory class androidx.core.app.AppComponentFactory class com.android.systemui.SystemUIAppComponentFactoryBase class com.android.systemui.PhoneSystemUIAppComponentFactory 下面的是上面的子类,systemiui的实现类SystemUIAppComponentFactoryBase。
回调instantiateApplicationCompat方法。
java
packages/SystemUI/src/com/android/systemui/SystemUIAppComponentFactoryBase.kt
override fun instantiateApplicationCompat(cl: ClassLoader, className: String): Application {
val app = super.instantiateApplicationCompat(cl, className)
if (app !is ContextInitializer) {
throw RuntimeException("App must implement ContextInitializer")
} else {
// 使用application context
app.setContextAvailableCallback { context ->
createSystemUIInitializerInternal(context)
}
}
return app
}
初始化systemui各模块,用了dagger2
private fun createSystemUIInitializerInternal(context: Context): SystemUIInitializer {
return systemUIInitializer ?: run {
val initializer = createSystemUIInitializer(context.applicationContext)
try {
// systemui初始化
initializer.init(false)
}
.....
// 注入到当前对象this@SystemUIAppComponentFactoryBase
initializer.sysUIComponent.inject(
this@SystemUIAppComponentFactoryBase
)
systemUIInitializer = initializer
return initializer
}
}
systemui初始化
java
packages/SystemUI/src/com/android/systemui/SystemUIInitializer.java
public void init(boolean fromTest) throws ExecutionException, InterruptedException {
mRootComponent = getGlobalRootComponentBuilder()
.context(mContext)
.instrumentationTest(fromTest)
.build();
mInitializationChecker = mRootComponent.getInitializationChecker();
boolean initializeComponents = mInitializationChecker.initializeComponents();
// Stand up WMComponent
//设置wmshell相关的模块
setupWmComponent(mContext);
// And finally, retrieve whatever SysUI needs from WMShell and build SysUI.
SysUIComponent.Builder builder = mRootComponent.getSysUIComponent();
if (initializeComponents) {
// Only initialize when not starting from tests since this currently initializes some
// components that shouldn't be run in the test environment
//调用mWMComponent.getXXX()方法
builder = prepareSysUIComponentBuilder(builder, mWMComponent)
.setShell(mWMComponent.getShell())
.setPip(mWMComponent.getPip())
.setSplitScreen(mWMComponent.getSplitScreen())
.setOneHanded(mWMComponent.getOneHanded())
.setBubbles(mWMComponent.getBubbles())
.setTaskViewFactory(mWMComponent.getTaskViewFactory())
.setShellTransitions(mWMComponent.getShellTransitions())
.setKeyguardTransitions(mWMComponent.getKeyguardTransitions())
.setStartingSurface(mWMComponent.getStartingSurface())
.setDisplayAreaHelper(mWMComponent.getDisplayAreaHelper())
.setRecentTasks(mWMComponent.getRecentTasks())
.setBackAnimation(mWMComponent.getBackAnimation())
.setDesktopMode(mWMComponent.getDesktopMode());
// Only initialize when not starting from tests since this currently initializes some
// components that shouldn't be run in the test environment
// wmshell各模块初始化调用init方法
mWMComponent.init();
} else {
}
mSysUIComponent = builder.build();
// Every other part of our codebase currently relies on Dependency, so we
// really need to ensure the Dependency gets initialized early on.
Dependency dependency = mSysUIComponent.createDependency();
dependency.start();
}
设置wmshell相关的模块
java
packages/SystemUI/src/com/android/systemui/SystemUIInitializer.java
private void setupWmComponent(Context context) {
WMComponent.Builder wmBuilder = mRootComponent.getWMComponentBuilder();
// If the shell main thread is enabled, initialize the component on that thread
HandlerThread shellThread = WMShellConcurrencyModule.createShellMainThread();
shellThread.start();
// Use an async handler since we don't care about synchronization
Handler shellHandler = Handler.createAsync(shellThread.getLooper());
boolean built = shellHandler.runWithScissors(() -> {
wmBuilder.setShellMainThread(shellThread);
// 构造wmcomponent,使用了dagger2
mWMComponent = wmBuilder.build();
}, 5000);
}
wmshell各模块初始化调用init方法
java
libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMComponent.java
default void init() {
getShell().onInit();
}
libs/WindowManager/Shell/src/com/android/wm/shell/sysui/ShellController.java
private class ShellInterfaceImpl implements ShellInterface {
@Override
public void onInit() {
mMainExecutor.execute(ShellController.this::handleInit);
}
}
private void handleInit() {
SurfaceControlRegistry.createProcessInstance(mContext);
mShellInit.init();
}
libs/WindowManager/Shell/src/com/android/wm/shell/sysui/ShellInit.java
public void init() {
ProtoLog.v(WM_SHELL_INIT, "Initializing Shell Components: %d", mInitCallbacks.size());
SurfaceControl.setDebugUsageAfterRelease(true);
// Init in order of registration
for (int i = 0; i < mInitCallbacks.size(); i++) {
final Pair<String, Runnable> info = mInitCallbacks.get(i);
final long t1 = SystemClock.uptimeMillis();
info.second.run();
final long t2 = SystemClock.uptimeMillis();
ProtoLog.v(WM_SHELL_INIT, "\t%s init took %dms", info.first, (t2 - t1));
}
mInitCallbacks.clear();
mHasInitialized = true;
}
最后就是遍历mInitCallbacks中的每个item调用runable的run方法。
这个mInitCallbacks里面的值从哪里来的,查找发现只有这个方法添加了item,这里面也有protolog
java
public <T extends Object> void addInitCallback(Runnable r, T instance) {
if (mHasInitialized) {
if (Build.isDebuggable()) {
// All callbacks must be added prior to the Shell being initialized
throw new IllegalArgumentException("Can not add callback after init");
}
return;
}
final String className = instance.getClass().getSimpleName();
mInitCallbacks.add(new Pair<>(className, r));
ProtoLog.v(WM_SHELL_INIT, "Adding init callback for %s", className);
android.util.Log.d("xmsysui", " addInitCallback ", new Exception());
}
抓了log如下:
java
Line 122: 07-29 10:50:08.658 922 922 V WindowManagerShell: Adding init callback for DisplayChangeController
Line 157: 07-29 10:50:08.659 922 922 V WindowManagerShell: Adding init callback for DisplayController
Line 191: 07-29 10:50:08.661 922 922 V WindowManagerShell: Adding init callback for DisplayInsetsController
Line 228: 07-29 10:50:08.663 922 922 V WindowManagerShell: Adding init callback for DisplayImeController
Line 262: 07-29 10:50:08.667 922 922 V WindowManagerShell: Adding init callback for ShellController
Line 303: 07-29 10:50:08.722 922 922 V WindowManagerShell: Adding init callback for CompatUIController
Line 379: 07-29 10:50:08.758 922 922 V WindowManagerShell: Adding init callback for TaskStackTransitionObserver
Line 420: 07-29 10:50:08.771 922 922 V WindowManagerShell: Adding init callback for RecentTasksController
Line 491: 07-29 10:50:08.784 922 922 V WindowManagerShell: Adding init callback for ShellTaskOrganizer
Line 527: 07-29 10:50:08.882 922 922 V WindowManagerShell: Adding init callback for OneHandedController
Line 565: 07-29 10:50:08.887 922 922 V WindowManagerShell: Adding init callback for RootTaskDisplayAreaOrganizer
Line 645: 07-29 10:50:08.903 922 922 V WindowManagerShell: Adding init callback for DefaultTransitionHandler
Line 688: 07-29 10:50:08.905 922 922 V WindowManagerShell: Adding init callback for Transitions
Line 728: 07-29 10:50:08.913 922 922 V WindowManagerShell: Adding init callback for DragAndDropController
Line 765: 07-29 10:50:08.953 922 922 V WindowManagerShell: Adding init callback for BubbleController
Line 799: 07-29 10:50:09.059 922 922 V WindowManagerShell: Adding init callback for CaptionWindowDecorViewModel
Line 839: 07-29 10:50:09.070 922 922 V WindowManagerShell: Adding init callback for SplitScreenController
Line 876: 07-29 10:50:09.072 922 922 V WindowManagerShell: Adding init callback for FullscreenTaskListener
Line 910: 07-29 10:50:09.088 922 922 V WindowManagerShell: Adding init callback for FreeformTaskListener
Line 950: 07-29 10:50:09.090 922 922 V WindowManagerShell: Adding init callback for FreeformTaskTransitionObserver
Line 990: 07-29 10:50:09.093 922 922 V WindowManagerShell: Adding init callback for FreeformTaskTransitionStarterInitializer
Line 1030: 07-29 10:50:09.095 922 922 V WindowManagerShell: Adding init callback for RecentsTransitionHandler
Line 1064: 07-29 10:50:09.099 922 922 V WindowManagerShell: Adding init callback for ActivityEmbeddingController
Line 1099: 07-29 10:50:09.126 922 922 V WindowManagerShell: Adding init callback for PipTransition
Line 1143: 07-29 10:50:09.133 922 922 V WindowManagerShell: Adding init callback for PerfHintController
Line 1201: 07-29 10:50:09.154 922 922 V WindowManagerShell: Adding init callback for PipTransition
Line 1245: 07-29 10:50:09.156 922 922 V WindowManagerShell: Adding init callback for KeyguardTransitionHandler
Line 1285: 07-29 10:50:09.159 922 922 V WindowManagerShell: Adding init callback for DefaultMixedHandler
Line 1322: 07-29 10:50:09.181 922 922 V WindowManagerShell: Adding init callback for StartingWindowController
Line 1356: 07-29 10:50:09.189 922 922 V WindowManagerShell: Adding init callback for ProtoLogController
Line 1390: 07-29 10:50:09.193 922 922 V WindowManagerShell: Adding init callback for TransitionStateHolder
Line 1428: 07-29 10:50:09.210 922 922 V WindowManagerShell: Adding init callback for BackAnimationController
Line 1474: 07-29 10:50:09.231 922 922 V WindowManagerShell: Adding init callback for PipTouchHandler
Line 1511: 07-29 10:50:09.234 922 922 V WindowManagerShell: Adding init callback for DevicePostureController
Line 1548: 07-29 10:50:09.235 922 922 V WindowManagerShell: Adding init callback for TabletopModeController
Line 1582: 07-29 10:50:09.244 922 922 V WindowManagerShell: Adding init callback for PipController
Line 1639: 07-29 10:50:09.247 922 922 V WindowManagerShell: Adding init callback for RootDisplayAreaOrganizer
也就是说wmshell有这些模块,这里面有熟悉的ShellTaskOrganizer,FreeformTaskListener,PipController,SplitScreenController,Transitions
分析一下SplitScreenController的初始化流程。在上面的addInitCallback添加堆栈,SplitScreenController是如何添加进来的。
java
07-29 10:50:09.070 922 922 V WindowManagerShell: Adding init callback for SplitScreenController
07-29 10:50:09.071 922 922 D xmsysui : addInitCallback
07-29 10:50:09.071 922 922 D xmsysui : java.lang.Exception
07-29 10:50:09.071 922 922 D xmsysui : at com.android.wm.shell.sysui.ShellInit.addInitCallback(ShellInit.java:73)
07-29 10:50:09.071 922 922 D xmsysui : at com.android.wm.shell.splitscreen.SplitScreenController.<init>(SplitScreenController.java:262)
07-29 10:50:09.071 922 922 D xmsysui : at com.android.wm.shell.dagger.WMShellModule.provideSplitScreenController(WMShellModule.java:521)
07-29 10:50:09.071 922 922 D xmsysui : at com.android.wm.shell.dagger.WMShellModule_ProvideSplitScreenControllerFactory.provideSplitScreenController(WMShellModule_ProvideSplitScreenControllerFactory.java:182)
07-29 10:50:09.071 922 922 D xmsysui : at com.android.systemui.dagger.DaggerReferenceGlobalRootComponent$WMComponentImpl$SwitchingProvider.get0(DaggerReferenceGlobalRootComponent.java:5236)
07-29 10:50:09.071 922 922 D xmsysui : at com.android.systemui.dagger.DaggerReferenceGlobalRootComponent$WMComponentImpl$SwitchingProvider.get(DaggerReferenceGlobalRootComponent.java:5669)
07-29 10:50:09.071 922 922 D xmsysui : at dagger.internal.DoubleCheck.get(DoubleCheck.java:47)
07-29 10:50:09.071 922 922 D xmsysui : at com.android.systemui.dagger.DaggerReferenceGlobalRootComponent$WMComponentImpl$SwitchingProvider.get0(DaggerReferenceGlobalRootComponent.java:5233)
07-29 10:50:09.071 922 922 D xmsysui : at com.android.systemui.dagger.DaggerReferenceGlobalRootComponent$WMComponentImpl$SwitchingProvider.get(DaggerReferenceGlobalRootComponent.java:5669)
07-29 10:50:09.071 922 922 D xmsysui : at dagger.internal.DoubleCheck.get(DoubleCheck.java:47)
07-29 10:50:09.071 922 922 D xmsysui : at com.android.systemui.dagger.DaggerReferenceGlobalRootComponent$WMComponentImpl$SwitchingProvider.get0(DaggerReferenceGlobalRootComponent.java:5116)
07-29 10:50:09.071 922 922 D xmsysui : at com.android.systemui.dagger.DaggerReferenceGlobalRootComponent$WMComponentImpl$SwitchingProvider.get(DaggerReferenceGlobalRootComponent.java:5669)
07-29 10:50:09.071 922 922 D xmsysui : at dagger.internal.DoubleCheck.get(DoubleCheck.java:47)
07-29 10:50:09.071 922 922 D xmsysui : at com.android.systemui.dagger.DaggerReferenceGlobalRootComponent$WMComponentImpl$SwitchingProvider.get0(DaggerReferenceGlobalRootComponent.java:5113)
07-29 10:50:09.071 922 922 D xmsysui : at com.android.systemui.dagger.DaggerReferenceGlobalRootComponent$WMComponentImpl$SwitchingProvider.get(DaggerReferenceGlobalRootComponent.java:5669)
07-29 10:50:09.071 922 922 D xmsysui : at dagger.internal.DoubleCheck.get(DoubleCheck.java:47)
07-29 10:50:09.071 922 922 D xmsysui : at com.android.systemui.dagger.DaggerReferenceGlobalRootComponent$WMComponentImpl.getShell(DaggerReferenceGlobalRootComponent.java:5032)
07-29 10:50:09.071 922 922 D xmsysui : at com.android.systemui.SystemUIInitializer.init(SystemUIInitializer.java:91)
07-29 10:50:09.071 922 922 D xmsysui : at com.android.systemui.SystemUIAppComponentFactoryBase.createSystemUIInitializerInternal(SystemUIAppComponentFactoryBase.kt:67)
07-29 10:50:09.071 922 922 D xmsysui : at com.android.systemui.SystemUIAppComponentFactoryBase.access$createSystemUIInitializerInternal(SystemUIAppComponentFactoryBase.kt:46)
07-29 10:50:09.071 922 922 D xmsysui : at com.android.systemui.SystemUIAppComponentFactoryBase$instantiateProviderCompat$1.onContextAvailable(SystemUIAppComponentFactoryBase.kt:101)
07-29 10:50:09.071 922 922 D xmsysui : at com.android.systemui.keyguard.CustomizationProvider.attachInfo(CustomizationProvider.kt:90)
07-29 10:50:09.071 922 922 D xmsysui : at android.app.ActivityThread.installProvider(ActivityThread.java:8509)
07-29 10:50:09.071 922 922 D xmsysui : at android.app.ActivityThread.installContentProviders(ActivityThread.java:8024)
07-29 10:50:09.071 922 922 D xmsysui : at android.app.ActivityThread.handleBindApplication(ActivityThread.java:7682)
07-29 10:50:09.071 922 922 D xmsysui : at android.app.ActivityThread.-$$Nest$mhandleBindApplication(Unknown Source:0)
07-29 10:50:09.071 922 922 D xmsysui : at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2500)
07-29 10:50:09.071 922 922 D xmsysui : at android.os.Handler.dispatchMessage(Handler.java:109)
07-29 10:50:09.071 922 922 D xmsysui : at android.os.Looper.loopOnce(Looper.java:232)
07-29 10:50:09.071 922 922 D xmsysui : at android.os.Looper.loop(Looper.java:317)
07-29 10:50:09.071 922 922 D xmsysui : at android.app.ActivityThread.main(ActivityThread.java:8934)
07-29 10:50:09.071 922 922 D xmsysui : at java.lang.reflect.Method.invoke(Native Method)
07-29 10:50:09.071 922 922 D xmsysui : at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:591)
07-29 10:50:09.071 922 922 D xmsysui : at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:911)
可以看到是初始化application的时候,SystemUIInitializer.init -> WMShellModule.provideSplitScreenController -> SplitScreenController. -> ShellInit.addInitCallback 其他的wmshell的模块也是同样的堆栈路径。