辉哥的分屏学习笔记

本文先解决以下疑问,然后给出分屏的总体结构
a. 分屏task 哪里来
b. 分屏task 信息如何同步到Systemui
c. 如何进入分屏并显示分屏的操作view

  1. 首先当然是分屏task 启动了,解决分屏task 哪里来的问题
    要讲清楚这个问题,首先要明白虽然分屏task 看起来由systemui 控制,但是实际上task依旧是system_server(中WM管理模块)创建,而systemui只是拿到创建后的控制句柄(我暂且叫他控制句柄,只是是啥后面在看)。
    为了提供上面功能,Wm-shell 提供了一个创建以及监听wmtask 信息的aidl接口。
    ITaskOrganizerController 为AIDL接口,
    看他接口函数就知道这提供一个进程间创建task的途径 ,在system这边会有ITaskOrganizerController 的一个BN实例,作为创建task的服务端(也即为wm 服务端)。
    syetemui获取到BP去创建task
    主要接口:
    Java
    ParceledListSlice registerTaskOrganizer(ITaskOrganizer organizer);
    /**
    • Unregisters a previously registered task organizer.
      /
      void unregisterTaskOrganizer(ITaskOrganizer organizer);
      /
      * Creates a persistent root task in WM for a particular windowing-mode. /
      void createRootTask(int displayId, int windowingMode, IBinder launchCookie);
      /
      * Deletes a persistent root task in WM */
      boolean deleteRootTask(in WindowContainerToken task);
      看一下Systemserver(e, Systemserver 这里主要是WMS管理模块部分)的BN
      TaskOrganizerController.java
      TaskOrganizerController extends ITaskOrganizerController.Stub
      我们先不看TaskOrganizerController 内部结构,先看一下wm里面如何嵌入组织管理TaskOrganizerController 的。
      Java
      WindowOrganizerController(ActivityTaskManagerService atm) {
      mService = atm;
      mGlobalLock = atm.mGlobalLock;
      mTaskOrganizerController = new TaskOrganizerController(mService);
      mDisplayAreaOrganizerController = new DisplayAreaOrganizerController(mService);
      mTaskFragmentOrganizerController = new TaskFragmentOrganizerController(atm);
      }
      Wms 对OrganizerController 又增设置了一层管理者WindowOrganizerController里面就会有一个TaskOrganizerController 对象,作为wm的task 操作管理者。
      我们可以看到 还有DisplayAreaOrganizerController 和 TaskFragmentOrganizerController
      DisplayAreaOrganizerController 后面可能涉及到,暂时还没看(我现在处理笔记状态写的,不是很确定)。TaskFragmentOrganizerController 这个应该是平行视窗控制BN。
      然后AMS里有这么一句
      ActivityTaskManagerService.java
      Java
      @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
      public ActivityTaskManagerService(Context context) {
      mContext = context;
      mFactoryTest = FactoryTest.getMode();
      mSystemThread = ActivityThread.currentActivityThread();
      mUiContext = mSystemThread.getSystemUiContext();
      mLifecycleManager = new ClientLifecycleManager();
      mVisibleActivityProcessTracker = new VisibleActivityProcessTracker(this);
      mInternal = new LocalService();
      GL_ES_VERSION = SystemProperties.getInt(“ro.opengles.version”, GL_ES_VERSION_UNDEFINED);
      mWindowOrganizerController = new WindowOrganizerController(this);
      mTaskOrganizerController = mWindowOrganizerController.mTaskOrganizerController;
      mTaskFragmentOrganizerController =
      mWindowOrganizerController.mTaskFragmentOrganizerController;
      mBackNavigationController = BackNavigationController.isEnabled()
      ? new BackNavigationController() : null;
      }
      所以也比较简单就这下面这种结构
      在这里插入图片描述
      至于具体怎么创建移除我就不多讲了,有兴趣自己看,本文只想摸清task 主要流程和整体框架。
      好了 到这里system提供创建task 的能力算是有了
      那systemui怎么去创建呢
      来看看systemui这边逻辑
      由于SystemUI这边有一部分逻辑无代码,但是systemui这边创建Task无疑要拿到systemserver提供的TaskOrganizerController BP并创建task,
      这个TaskOrganizerController BP获取接口在TaskOrganizer
      我在pixl 4上打印systemui创建的TaskOrganizer
      实际上创建的是ShellTaskOrganizer 子类 ShellTaskOrganizer 继承至TaskOrganizer
      然后通过ShellTaskOrganizer 创建task
      Java
      11-12 08:27:40.037 2408 3213 E DEBUGTASKOR: android.window.TaskOrganizer 1 @ b 54 d d 50 c e = c o m . a n d r o i d . w m . s h e l l . S h e l l T a s k O r g a n i z e r . < i n i t > : 2 c o m . a n d r o i d . w m . s h e l l . S h e l l T a s k O r g a n i z e r . < i n i t > : 1 c o m . a n d r o i d . s y s t e m u i . m e d i a . M e d i a S e s s i o n B a s e d F i l t e r F a c t o r y . g e t : 116 d a g g e r . i n t e r n a l . D o u b l e C h e c k . g e t : 13 d a g g e r . i n t e r n a l . D e l e g a t e F a c t o r y . g e t : 4 c o m . a n d r o i d . w m . s h e l l . d a g g e r . W M S h e l l B a s e M o d u l e P r o v i d e S h e l l I n i t I m p l F a c t o r y . g e t : 40 d a g g e r . i n t e r n a l . D o u b l e C h e c k . g e t : 13 c o m . a n d r o i d . s y s t e m u i . d o z e . D o z e A u t h R e m o v e r F a c t o r y . g e t : 150 d a g g e r . i n t e r n a l . D o u b l e C h e c k . g e t : 13 c o m . a n d r o i d . s y s t e m u i . d a g g e r . D a g g e r G l o b a l R o o t C o m p o n e n t 1@b54dd50 ce = com.android.wm.shell.ShellTaskOrganizer.<init>:2 com.android.wm.shell.ShellTaskOrganizer.<init>:1 com.android.systemui.media.MediaSessionBasedFilter_Factory.get:116 dagger.internal.DoubleCheck.get:13 dagger.internal.DelegateFactory.get:4 com.android.wm.shell.dagger.WMShellBaseModule_ProvideShellInitImplFactory.get:40 dagger.internal.DoubleCheck.get:13 com.android.systemui.doze.DozeAuthRemover_Factory.get:150 dagger.internal.DoubleCheck.get:13 com.android.systemui.dagger.DaggerGlobalRootComponent 1@b54dd50ce=com.android.wm.shell.ShellTaskOrganizer.<init>:2com.android.wm.shell.ShellTaskOrganizer.<init>:1com.android.systemui.media.MediaSessionBasedFilterFactory.get:116dagger.internal.DoubleCheck.get:13dagger.internal.DelegateFactory.get:4com.android.wm.shell.dagger.WMShellBaseModuleProvideShellInitImplFactory.get:40dagger.internal.DoubleCheck.get:13com.android.systemui.doze.DozeAuthRemoverFactory.get:150dagger.internal.DoubleCheck.get:13com.android.systemui.dagger.DaggerGlobalRootComponentWMComponentImpl.getShellInit:2
      com.android.systemui.dagger.WMComponent.init:0
      com.android.systemui.dagger.DaggerGlobalRootComponent W M C o m p o n e n t I m p l . i n i t : 0 c o m . a n d r o i d . s y s t e m u i . S y s t e m U I F a c t o r y . i n i t : 15 c o m . a n d r o i d . s y s t e m u i . S y s t e m U I F a c t o r y . c r e a t e F r o m C o n f i g : 36 c o m . a n d r o i d . s y s t e m u i . m e d i a . M e d i a C o n t r o l P a n e l WMComponentImpl.init:0 com.android.systemui.SystemUIFactory.init:15 com.android.systemui.SystemUIFactory.createFromConfig:36 com.android.systemui.media.MediaControlPanel WMComponentImpl.init:0com.android.systemui.SystemUIFactory.init:15com.android.systemui.SystemUIFactory.createFromConfig:36com.android.systemui.media.MediaControlPanel E x t e r n a l S y n t h e t i c L a m b d a 7. o n C o n t e x t A v a i l a b l e : 7 c o m . a n d r o i d . s y s t e m u i . k e y g u a r d . K e y g u a r d S l i c e P r o v i d e r . o n C r e a t e S l i c e P r o v i d e r : 6 a n d r o i d x . s l i c e . S l i c e P r o v i d e r . o n C r e a t e : 0 a n d r o i d . c o n t e n t . C o n t e n t P r o v i d e r . a t t a c h I n f o : 2451 a n d r o i d . c o n t e n t . C o n t e n t P r o v i d e r . a t t a c h I n f o : 2421 a n d r o i d x . s l i c e . S l i c e P r o v i d e r . a t t a c h I n f o : 0 应 用 使 用 千 奇 百 怪 不 用 管 , 我 们 只 需 要 知 道 由 w m s h e l l S h e l l T a s k O r g a n i z e r 提 供 t a s k 操 作 接 口 , 后 续 都 是 基 于 S h e l l T a s k O r g a n i z e r 这 套 逻 辑 。 然 后 为 支 持 分 屏 s y s t e m u i 分 别 创 建 了 三 个 t a s k 第 一 个 : 11 − 1208 : 27 : 40.03724083213 E D E B U G T A S K O R : C r e a t e t a s k 1 w i n d o w i n g M o d e = 1 c o m . a n d r o i d . w m . s h e l l . S h e l l T a s k O r g a n i z e r . c r e a t e R o o t T a s k : 58 c o m . a n d r o i d . w m . s h e l l . s p l i t s c r e e n . S t a g e C o o r d i n a t o r . < i n i t > : 18 c o m . a n d r o i d . w m . s h e l l . S h e l l I n i t I m p l ExternalSyntheticLambda7.onContextAvailable:7 com.android.systemui.keyguard.KeyguardSliceProvider.onCreateSliceProvider:6 androidx.slice.SliceProvider.onCreate:0 android.content.ContentProvider.attachInfo:2451 android.content.ContentProvider.attachInfo:2421 androidx.slice.SliceProvider.attachInfo:0 应用使用千奇百怪不用管,我们只需要知道 由wmshell ShellTaskOrganizer 提供task操作接口,后续都是基于ShellTaskOrganizer 这套逻辑。 然后为支持分屏systemui 分别创建了三个task 第一个: 11-12 08:27:40.037 2408 3213 E DEBUGTASKOR: Createtask 1 windowingMode = 1com.android.wm.shell.ShellTaskOrganizer.createRootTask:58 com.android.wm.shell.splitscreen.StageCoordinator.<init>:18 com.android.wm.shell.ShellInitImpl ExternalSyntheticLambda7.onContextAvailable:7com.android.systemui.keyguard.KeyguardSliceProvider.onCreateSliceProvider:6androidx.slice.SliceProvider.onCreate:0android.content.ContentProvider.attachInfo:2451android.content.ContentProvider.attachInfo:2421androidx.slice.SliceProvider.attachInfo:0使wmshellShellTaskOrganizertaskShellTaskOrganizersystemuitask111208:27:40.03724083213EDEBUGTASKOR:Createtask1windowingMode=1com.android.wm.shell.ShellTaskOrganizer.createRootTask:58com.android.wm.shell.splitscreen.StageCoordinator.<init>:18com.android.wm.shell.ShellInitImpl E x t e r n a l S y n t h e t i c L a m b d a 1. a c c e p t : 41 j a v a . u t i l . O p t i o n a l . i f P r e s e n t : 179 c o m . a n d r o i d . w m . s h e l l . S h e l l I n i t I m p l ExternalSyntheticLambda1.accept:41 java.util.Optional.ifPresent:179 com.android.wm.shell.ShellInitImpl ExternalSyntheticLambda1.accept:41java.util.Optional.ifPresent:179com.android.wm.shell.ShellInitImplInitImpl E x t e r n a l S y n t h e t i c L a m b d a 0. r u n : 83 c o m . a n d r o i d . s y s t e m u i . S y s t e m U I A p p l i c a t i o n ExternalSyntheticLambda0.run:83 com.android.systemui.SystemUIApplication ExternalSyntheticLambda0.run:83com.android.systemui.SystemUIApplicationExternalSyntheticLambda2.run:130 com.android.wm.shell.common.HandlerExecutor.execute:12 com.android.wm.shell.common.ShellExecutor.executeBlocking:2 com.android.wm.shell.common.ShellExecutor.executeBlocking:4 com.android.wm.shell.ShellInitImpl I n i t I m p l . i n i t : 9 c o m . a n d r o i d . s y s t e m u i . d a g g e r . W M C o m p o n e n t . i n i t : 4 c o m . a n d r o i d . s y s t e m u i . d a g g e r . D a g g e r G l o b a l R o o t C o m p o n e n t InitImpl.init:9 com.android.systemui.dagger.WMComponent.init:4 com.android.systemui.dagger.DaggerGlobalRootComponent InitImpl.init:9com.android.systemui.dagger.WMComponent.init:4com.android.systemui.dagger.DaggerGlobalRootComponentWMComponentImpl.init:0 com.android.systemui.SystemUIFactory.init:15 com.android.systemui.SystemUIFactory.createFromConfig:36 com.android.systemui.media.MediaControlPanel E x t e r n a l S y n t h e t i c L a m b d a 7. o n C o n t e x t A v a i l a b l e : 7 c o m . a n d r o i d . s y s t e m u i . k e y g u a r d . K e y g u a r d S l i c e P r o v i d e r . o n C r e a t e S l i c e P r o v i d e r : 6 a n d r o i d x . s l i c e . S l i c e P r o v i d e r . o n C r e a t e : 0 a n d r o i d . c o n t e n t . C o n t e n t P r o v i d e r . a t t a c h I n f o : 2451 a n d r o i d . c o n t e n t . C o n t e n t P r o v i d e r . a t t a c h I n f o : 2421 a n d r o i d x . s l i c e . S l i c e P r o v i d e r . a t t a c h I n f o : 0 第 二 个 : 11 − 1208 : 27 : 40.03724083213 E D E B U G T A S K O R : C r e a t e t a s k 2 w i n d o w i n g M o d e = 6 c o m . a n d r o i d . w m . s h e l l . S h e l l T a s k O r g a n i z e r . c r e a t e R o o t T a s k : 58 c o m . a n d r o i d . w m . s h e l l . s p l i t s c r e e n . S t a g e T a s k L i s t e n e r . < i n i t > : 30 c o m . a n d r o i d . w m . s h e l l . s p l i t s c r e e n . M a i n S t a g e . < i n i t > : 0 c o m . a n d r o i d . w m . s h e l l . s p l i t s c r e e n . S t a g e C o o r d i n a t o r . < i n i t > : 19 c o m . a n d r o i d . w m . s h e l l . S h e l l I n i t I m p l ExternalSyntheticLambda7.onContextAvailable:7 com.android.systemui.keyguard.KeyguardSliceProvider.onCreateSliceProvider:6 androidx.slice.SliceProvider.onCreate:0 android.content.ContentProvider.attachInfo:2451 android.content.ContentProvider.attachInfo:2421 androidx.slice.SliceProvider.attachInfo:0 第二个: 11-12 08:27:40.037 2408 3213 E DEBUGTASKOR: Createtask 2 windowingMode = 6com.android.wm.shell.ShellTaskOrganizer.createRootTask:58 com.android.wm.shell.splitscreen.StageTaskListener.<init>:30 com.android.wm.shell.splitscreen.MainStage.<init>:0 com.android.wm.shell.splitscreen.StageCoordinator.<init>:19 com.android.wm.shell.ShellInitImpl ExternalSyntheticLambda7.onContextAvailable:7com.android.systemui.keyguard.KeyguardSliceProvider.onCreateSliceProvider:6androidx.slice.SliceProvider.onCreate:0android.content.ContentProvider.attachInfo:2451android.content.ContentProvider.attachInfo:2421androidx.slice.SliceProvider.attachInfo:0111208:27:40.03724083213EDEBUGTASKOR:Createtask2windowingMode=6com.android.wm.shell.ShellTaskOrganizer.createRootTask:58com.android.wm.shell.splitscreen.StageTaskListener.<init>:30com.android.wm.shell.splitscreen.MainStage.<init>:0com.android.wm.shell.splitscreen.StageCoordinator.<init>:19com.android.wm.shell.ShellInitImplExternalSyntheticLambda1.accept:41 java.util.Optional.ifPresent:179 com.android.wm.shell.ShellInitImpl I n i t I m p l InitImpl InitImpl E x t e r n a l S y n t h e t i c L a m b d a 0. r u n : 83 c o m . a n d r o i d . s y s t e m u i . S y s t e m U I A p p l i c a t i o n ExternalSyntheticLambda0.run:83 com.android.systemui.SystemUIApplication ExternalSyntheticLambda0.run:83com.android.systemui.SystemUIApplication E x t e r n a l S y n t h e t i c L a m b d a 2. r u n : 130 c o m . a n d r o i d . w m . s h e l l . c o m m o n . H a n d l e r E x e c u t o r . e x e c u t e : 12 c o m . a n d r o i d . w m . s h e l l . c o m m o n . S h e l l E x e c u t o r . e x e c u t e B l o c k i n g : 2 c o m . a n d r o i d . w m . s h e l l . c o m m o n . S h e l l E x e c u t o r . e x e c u t e B l o c k i n g : 4 c o m . a n d r o i d . w m . s h e l l . S h e l l I n i t I m p l ExternalSyntheticLambda2.run:130 com.android.wm.shell.common.HandlerExecutor.execute:12 com.android.wm.shell.common.ShellExecutor.executeBlocking:2 com.android.wm.shell.common.ShellExecutor.executeBlocking:4 com.android.wm.shell.ShellInitImpl ExternalSyntheticLambda2.run:130com.android.wm.shell.common.HandlerExecutor.execute:12com.android.wm.shell.common.ShellExecutor.executeBlocking:2com.android.wm.shell.common.ShellExecutor.executeBlocking:4com.android.wm.shell.ShellInitImplInitImpl.ini

第三个:
11-12 08:27:40.037 2408 3213 E DEBUGTASKOR: Createtask 3 windowingMode = 6com.android.wm.shell.ShellTaskOrganizer.createRootTask:58 com.android.wm.shell.splitscreen.StageTaskListener.:30 com.android.wm.shell.splitscreen.SideStage.:0 com.android.wm.shell.splitscreen.StageCoordinator.:20 com.android.wm.shell.ShellInitImplKaTeX parse error: Can't use function '$' in math mode at position 103: …l.ShellInitImpl$̲InitImplExternalSyntheticLambda0.run:83 com.android.systemui.SystemUIApplicationKaTeX parse error: Can't use function '$' in math mode at position 243: …l.ShellInitImpl$̲InitImpl.init:9…ExternalSyntheticLambda7.onContextAvailable:7 com.android.systemui.keyguard.KeyguardSliceProvider.onCreateSliceProvider:6 androidx.slice.SliceProvider.onCreate:0 android.content.ContentProvider.attachInfo:2451
从堆栈我们就能看出一个简单的结构:
Systemui 初始化shell的时候会创建StageCoordinator
以及内部有两个SideStage 和MainStage
虽然还没看,但可以大胆猜想一下,其实这里StageCoordinator常见的是分屏的根SideStage 和MainStage分别创建了两个容纳两个应用的task,那么我猜测StageCoordinator 从名字以及创建的位置可以确定他是决定分屏两个task的位置大小层级的。
SideStage 和 MainStage不用说 就是分屏的主次task app状态维护的了。

好我们现在主角出现了四个(顺便提一句 StageCoordinator依附SplitScreenController ,SplitScreenController 有wmshell中WMShellModule.java 对sysmeui提供)

ShellTaskOrganizer StageCoordinator SideStage MainStage

ShellTaskOrganizer 没啥好说的BP的封装,以及APP 注入信息回调等,可以理解为 两进城的信息传递桥梁。 当然我们这里只是关注BP部分,这里面还有个BN其实 主要是systemui这边为了监听system测task信息变化,属于下一个问题,一会再说。

来看看 StageCoordinator, 他的创建在SplitScreenController
Java
public void onOrganizerRegistered() {
if (mStageCoordinator == null) {
// TODO: Multi-display
mStageCoordinator = new StageCoordinator(mContext, DEFAULT_DISPLAY, mSyncQueue,
mTaskOrganizer, mDisplayController, mDisplayImeController,
mDisplayInsetsController, mTransitions, mTransactionPool, mLogger,
mIconProvider, mMainExecutor, mRecentTasksOptional, mUnfoldControllerProvider);
}
}
SplitScreenController 属于ShellInitImpl 一部分,并跟随ShellInitImpl 初始化

看一下StageCoordinator 初始化的时候做了啥

Java
StageCoordinator(Context context, int displayId, SyncTransactionQueue syncQueue,
ShellTaskOrganizer taskOrganizer, DisplayController displayController,
DisplayImeController displayImeController,
DisplayInsetsController displayInsetsController, Transitions transitions,
TransactionPool transactionPool, SplitscreenEventLogger logger,
IconProvider iconProvider, ShellExecutor mainExecutor,
Optional recentTasks,
Provider<Optional> unfoldControllerProvider) {
mContext = context;
mDisplayId = displayId;
mSyncQueue = syncQueue;
mTaskOrganizer = taskOrganizer;
mLogger = logger;
mMainExecutor = mainExecutor;
mRecentTasks = recentTasks;
mMainUnfoldController = unfoldControllerProvider.get().orElse(null);
mSideUnfoldController = unfoldControllerProvider.get().orElse(null);
创建分屏的主task
taskOrganizer.createRootTask(displayId, WINDOWING_MODE_FULLSCREEN, this /* listener */);

    mMainStage = new MainStage(
            mContext,
            mTaskOrganizer,
            mDisplayId,
            mMainStageListener,
            mSyncQueue,
            mSurfaceSession,
            iconProvider,
            mMainUnfoldController);
    mSideStage = new SideStage(
            mContext,
            mTaskOrganizer,
            mDisplayId,
            mSideStageListener,
            mSyncQueue,
            mSurfaceSession,
            iconProvider,
            mSideUnfoldController);
    mDisplayController = displayController;
    mDisplayImeController = displayImeController;
    mDisplayInsetsController = displayInsetsController;
    mTransactionPool = transactionPool;
    final DeviceStateManager deviceStateManager =
            mContext.getSystemService(DeviceStateManager.class);
    deviceSt

可以看到 主要创建了一个分屏的主task,这下面会挂两个主次分屏应用
另外这里还有个private SplitLayout mSplitLayout; 这个可能和分屏bar有关,后面看分屏view 操作的时候看。

主次分屏主要处理类为这里创建的mMainStage 和 mSideStage
再分别看看mMainStage 和 mSideStage
这两个类构造函数都是创建了各自装自己app的task
Java
StageTaskListener(Context context, ShellTaskOrganizer taskOrganizer, int displayId,
StageListenerCallbacks callbacks, SyncTransactionQueue syncQueue,
SurfaceSession surfaceSession, IconProvider iconProvider,
@Nullable StageTaskUnfoldController stageTaskUnfoldController) {
mContext = context;
mCallbacks = callbacks;
mSyncQueue = syncQueue;
mSurfaceSession = surfaceSession;
mIconProvider = iconProvider;
mStageTaskUnfoldController = stageTaskUnfoldController;
taskOrganizer.createRootTask(displayId, WINDOWING_MODE_MULTI_WINDOW, this);
}

现在分屏的主体结构有了。看一下到目前为止systemui这边 或者说wmshell的整体结构吧
在这里插入图片描述
到此view 出现了。
后续view 至于怎么加入的,有兴趣自己看就不看了。

不知道你注意到没,要想走到这里还有一至关重要的条件就是mMainStage.isActive()

好再看一下mMainStage 的状态。
这个是在startTasks 时候将mMainStage设置为active的。
如果走的系统直接reparent 就直接走onStageHasChildrenChanged 这条路径。有兴趣自己跟一下流程。
好了就完事了。

我这个也是第一次看,但是我基本觉得我可以搞分屏开发了,就看各位看了了解了几分吧

目前已经成功用此框架完成新功能开发

里面也许有些许错误 毕竟第一次看 只看了不到两天哈 见谅。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值