• Quick Settings 中 Tile 的加载


    系统启动后,启动 SystemUI
    SystemServer::run -> SystemServer::startBootstrapServices-> SystemServer::startOtherServices() -> startSystemUi(context);
    SystemUI 加载 Quick Settings:
    SystemUIService::onCreate() -> SystemUIApplication::startServicesIfNeeded -> StatusBar::start() -> StatusBar::createAndAddWindows -> StatusBar::makeStatusBarView

    public class StatusBar extends SystemUI ... {
        ...
        protected void makeStatusBarView(@Nullable RegisterStatusBarResult result) {
            ...
            // Set up the quick settings tile panel
            final View container = mNotificationShadeWindowView.findViewById(R.id.qs_frame);
            if (container != null) {
                FragmentHostManager fragmentHostManager = FragmentHostManager.get(container);
                ExtensionFragmentListener.attachExtensonToFragment(container, QS.TAG, R.id.qs_frame,
                        mExtensionController
                                .newExtension(QS.class)
                                .withPlugin(QS.class)
                                .withDefault(this::createDefaultQSFragment)
                                .build());
                mBrightnessMirrorController = new BrightnessMirrorController(
                        mNotificationShadeWindowView,
                        mNotificationPanelViewController,
                        mNotificationShadeDepthControllerLazy.get(),
                        (visible) -> {
                            mBrightnessMirrorVisible = visible;
                            updateScrimController();
                        });
                fragmentHostManager.addTagListener(QS.TAG, (tag, f) -> {
                    QS qs = (QS) f;
                    if (qs instanceof QSFragment) {
                        mQSPanel = ((QSFragment) qs).getQsPanel();
                        mQSPanel.setBrightnessMirror(mBrightnessMirrorController);
                    }
                });
            }
            ...
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33

    由上述代码可知,Quick Settings 对应 StatusBar::createDefaultQSFragment 方法创建的 Fragment,并被放置 mNotificationShadeWindowView 中的 R.id.qs_frame 下

    public class StatusBar extends SystemUI ... {
        ...
        protected QS createDefaultQSFragment() {
            return FragmentHostManager.get(mNotificationShadeWindowView).create(QSFragment.class);
        }
        ...
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    从 QSFragment::onCreateView 方法可知,对应的布局文件为 R.layout.qs_panel

    public class QSFragment extends LifecycleFragment implements QS, CommandQueue.Callbacks,
            StatusBarStateController.StateListener {
        ...
        @Override
        public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container,
                Bundle savedInstanceState) {
            inflater = mInjectionInflater.injectable(
                    inflater.cloneInContext(new ContextThemeWrapper(getContext(),
                            R.style.Theme_SystemUI_QuickSettings)));
            return inflater.inflate(R.layout.qs_panel, container, false);
        }
        ...
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    在 R.layout.qs_panel 中,掌管 Tile 显示的部分是 QSPanel,在布局文件中定义如下

    
    
        ...
            
                
            
        ...
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22

    在 QSFragment::onViewCreated 中获得 QSPanelController 的实例,并初始化它

    public class QSFragment extends LifecycleFragment implements QS, CommandQueue.Callbacks,
            StatusBarStateController.StateListener {
        ...
        @Override
        public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container,
                Bundle savedInstanceState) {
            inflater = mInjectionInflater.injectable(
                    inflater.cloneInContext(new ContextThemeWrapper(getContext(),
                            R.style.Theme_SystemUI_QuickSettings)));
            return inflater.inflate(R.layout.qs_panel, container, false);
        }
        ...
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    Tile 首次加载时的调用栈 log

    QSTileHost: java.lang.RuntimeException
    QSTileHost:    at com.android.systemui.qs.QSTileHost.getTiles(QSTileHost.java:230)
    QSTileHost:    at com.android.systemui.qs.QSPanelControllerBase.setTiles(QSPanelControllerBase.java:186)
    QSTileHost:    at com.android.systemui.qs.QSPanelControllerBase.onViewAttached(QSPanelControllerBase.java:158)
    QSTileHost:    at com.android.systemui.qs.QSPanelController.onViewAttached(QSPanelController.java:147)
    QSTileHost:    at com.android.systemui.util.ViewController$1.onViewAttachedToWindow(ViewController.java:52)
    QSTileHost:    at com.android.systemui.util.ViewController.init(ViewController.java:80)
    QSTileHost:    at com.android.systemui.qs.QSFragment.onViewCreated(QSFragment.java:178)
    QSTileHost:    at android.app.FragmentManagerImpl.moveToState(FragmentManager.java:1313)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    com.android.systemui.qs.QSTileHost#loadTileSpecs
    com.android.systemui.qs.QSTileHost#onTuningChanged
    com.android.systemui.qs.QSTileHost#QSTileHost
    挪动 QS 中 Tile 的调用栈 log

    QSTileHost: saveTilesToSettings() Called: com.android.systemui.qs.QSTileHost@93fba
    QSTileHost: java.lang.RuntimeException
    QSTileHost:    at com.android.systemui.qs.QSTileHost.saveTilesToSettings(QSTileHost.java:403)
    QSTileHost:    at com.android.systemui.qs.QSTileHost.changeTiles(QSTileHost.java:472)
    QSTileHost:    at com.android.systemui.qs.customize.TileAdapter.saveSpecs(TileAdapter.java:184)
    QSTileHost:    at com.android.systemui.qs.customize.TileAdapter.move(TileAdapter.java:520)
    QSTileHost:    at com.android.systemui.qs.customize.TileAdapter.move(TileAdapter.java:500)
    QSTileHost:    at com.android.systemui.qs.customize.TileAdapter.access$1900(TileAdapter.java:70)
    QSTileHost:    at com.android.systemui.qs.customize.TileAdapter$5.onMove(TileAdapter.java:821)
    QSTileHost:    at androidx.recyclerview.widget.ItemTouchHelper.moveIfNecessary(ItemTouchHelper.java:885)
    QSTileHost:    at androidx.recyclerview.widget.ItemTouchHelper$2.onTouchEvent(ItemTouchHelper.java:389)
    QSTileHost:    at androidx.recyclerview.widget.RecyclerView.dispatchToOnItemTouchListeners(RecyclerView.java:3338)
    QSTileHost:    at androidx.recyclerview.widget.RecyclerView.onTouchEvent(RecyclerView.java:3532)
    QSTileHost:    at android.view.View.dispatchTouchEvent(View.java:14551)
    QSTileHost:    at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:3114)
    QSTileHost:    at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2787)
    QSTileHost:    at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:3120)
    QSTileHost:    at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2801)
    QSTileHost:    at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:3120)
    QSTileHost:    at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2801)
    QSTileHost:    at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:3120)
    QSTileHost:    at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2801)
    QSTileHost:    at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:3120)
    QSTileHost:    at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2801)
    QSTileHost:    at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:3120)
    QSTileHost:    at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2801)
    QSTileHost:    at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:3120)
    QSTileHost:    at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2801)
    QSTileHost:    at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:3120)
    QSTileHost:    at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2801)
    QSTileHost:    at com.android.systemui.statusbar.phone.NotificationShadeWindowView.dispatchTouchEvent(NotificationShadeWindowView.java:176)
    QSTileHost:    at android.view.View.dispatchPointerEvent(View.java:14810)
    QSTileHost:    at android.view.ViewRootImpl$ViewPostImeInputStage.processPointerEvent(ViewRootImpl.java:6351)
    QSTileHost:    at android.view.ViewRootImpl$ViewPostImeInputStage.onProcess(ViewRootImpl.java:6152)
    QSTileHost:    at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:5630)
    QSTileHost:    at android.view.ViewRootImpl$InputStage.onDeliverToNext(ViewRootImpl.java:5687)
    QSTileHost:    at android.view.ViewRootImpl$InputStage.forward(ViewRootImpl.java:5653)
    QSTileHost:    at android.view.ViewRootImpl$AsyncInputStage.forward(ViewRootImpl.java:5818)
    QSTileHost:    at android.view.ViewRootImpl$InputStage.apply(ViewRootImpl.java:5661)
    QSTileHost:    at android.view.ViewRootImpl$AsyncInputStage.apply(ViewRootImpl.java:5875)
    QSTileHost:    at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:5634)
    QSTileHost:    at android.view.ViewRootImpl$InputStage.onDeliverToNext(ViewRootImpl.java:5687)
    QSTileHost:    at android.view.ViewRootImpl$InputStage.forward(ViewRootImpl.java:5653)
    QSTileHost:    at android.view.ViewRootImpl$InputStage.apply(ViewRootImpl.java:5661)
    QSTileHost:    at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:5634)
    QSTileHost:    at android.view.ViewRootImpl.deliverInputEvent(ViewRootImpl.java:8574)
    QSTileHost:    at android.view.ViewRootImpl.doProcessInputEvents(ViewRootImpl.java:8525)
    QSTileHost:    at android.view.ViewRootImpl.enqueueInputEvent(ViewRootImpl.java:8493)
    QSTileHost:    at android.view.ViewRootImpl$WindowInputEventReceiver.onInputEvent(ViewRootImpl.java:8697)
    QSTileHost:    at android.view.InputEventReceiver.dispatchInputEvent(InputEventReceiver.java:260)
    QSTileHost:    at android.view.InputEventReceiver.nativeConsumeBatchedInputEvents(Native Method)
    QSTileHost:    at android.view.InputEventReceiver.consumeBatchedInputEvents(InputEventReceiver.java:240)
    QSTileHost:    at android.view.ViewRootImpl.doConsumeBatchedInput(ViewRootImpl.java:8654)
    QSTileHost:    at android.view.ViewRootImpl$ConsumeBatchedInputRunnable.run(ViewRootImpl.java:8783)
    QSTileHost:    at android.view.Choreographer$CallbackRecord.run(Choreographer.java:1120)
    QSTileHost:    at android.view.Choreographer.doCallbacks(Choreographer.java:926)
    QSTileHost:    at android.view.Choreographer.doFrame(Choreographer.java:851)
    QSTileHost:    at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:1105)
    QSTileHost:    at android.os.Handler.handleCallback(Handler.java:938)
    QSTileHost:    at android.os.Handler.dispatchMessage(Handler.java:99)
    QSTileHost:    at android.os.Looper.loopOnce(Looper.java:356)
    QSTileHost:    at android.os.Looper.loop(Looper.java:475)
    QSTileHost:    at android.app.ActivityThread.main(ActivityThread.java:7889)
    QSTileHost:    at java.lang.reflect.Method.invoke(Native Method)
    QSTileHost:    at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:548)
    QSTileHost:    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1009)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66

    参考
    https://blog.csdn.net/zplxl99/article/details/74906133?spm=1001.2101.3001.6650.1&utm_medium=distribute.pc_relevant.none-task-blog-2%7Edefault%7EBlogCommendFromBaidu%7Edefault-1.queryctrv2&depth_1-utm_source=distribute.pc_relevant.none-task-blog-2%7Edefault%7EBlogCommendFromBaidu%7Edefault-1.queryctrv2&utm_relevant_index=2

  • 相关阅读:
    Redis(主从复制)
    一种跳板机的实现思路
    Android Frgment中onActivityResult无效的问题
    湖南(广告效果测评)源点调研 广告对消费者行为的影响效果
    基于R语言实现中介效应检验以及sobel检验代码
    MySQL InnoDB Cluster部署
    30 位学者合力发表 Nature 综述,10 年回顾解构 AI 如何重塑科研范式
    图解分布式事务实现原理(一)
    8个很棒的Vue开发技巧
    WebRTC 如何指定 H265解码器
  • 原文地址:https://blog.csdn.net/lzs781/article/details/127401204