系统启动后,启动 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);
}
});
}
...
}
}
由上述代码可知,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);
}
...
}
从 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);
}
...
}
在 R.layout.qs_panel 中,掌管 Tile 显示的部分是 QSPanel,在布局文件中定义如下
...
...
在 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);
}
...
}
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)
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)
参考
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