从SystemServer开始
frameworks/base/services/java/com/android/server/SystemServer.java
private void startOtherServices() {
...
mActivityManagerService.systemReady(() -> {
...
traceBeginAndSlog("StartSystemUI");
try {
startSystemUi(context, windowManagerF);//启动SystemUIService
} catch (Throwable e) {
reportWtf("starting System UI", e);
}
traceEnd();
...
}
...
static final void startSystemUi(Context context, WindowManagerService windowManager) {
Intent intent = new Intent();
intent.setComponent(new ComponentName("com.android.systemui",
"com.android.systemui.SystemUIService"));
intent.addFlags(Intent.FLAG_DEBUG_TRIAGED_MISSING);
//Slog.d(TAG, "Starting service: " + intent);
context.startServiceAsUser(intent, UserHandle.SYSTEM);
windowManager.onSystemUiStarted();
}
在startOtherServices()中,代码7行调startSystemUi方法,在该方法中,启动了SystemUIService,接着往下看SystemUIService.java
frameworks/base/packages/SystemUI/src/com/android/systemui/SystemUIService.java
@Override
public void onCreate() {
super.onCreate();
((SystemUIApplication) getApplication()).startServicesIfNeeded(); //关注这里
// For debugging RescueParty
if (Build.IS_DEBUGGABLE && SystemProperties.getBoolean("debug.crash_sysui", false)) {
throw new RuntimeException();
}
}
SystemUIService服务起来后,onCreate()调用了SystemUIApplication的startServicesIfNeeded()方法
frameworks/base/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java
private final Class>[] SERVICES = new Class[] {
Dependency.class,
NotificationChannels.class,
CommandQueue.CommandQueueStart.class,
KeyguardViewMediator.class,//锁屏
Recents.class,//近期应用
VolumeUI.class,//声音调节窗口
Divider.class,//分屏
SystemBars.class,//状态栏,导航栏
StorageNotification.class,
PowerUI.class,
RingtonePlayer.class,
KeyboardUI.class,
PipUI.class,//提供对于画中画模式的管理
ShortcutKeyDispatcher.class,
VendorServices.class,
GarbageMonitor.Service.class,
LatencyTester.class,
GlobalActionsComponent.class,
RoundedCorners.class,
};
...
public void startServicesIfNeeded() {
startServicesIfNeeded(SERVICES);
}
...
private void startServicesIfNeeded(Class>[] services) {
...
final int N = services.length;
for (int i = 0; i < N; i++) {//遍历SERVICES
Class> cl = services[i];
if (DEBUG) Log.d(TAG, "loading: " + cl);
log.traceBegin("StartServices" + cl.getSimpleName());
long ti = System.currentTimeMillis();
try {
Object newService = SystemUIFactory.getInstance().createInstance(cl);
mServices[i] = (SystemUI) ((newService == null) ? cl.newInstance() : newService);//实例化SERVICES中的类并存于mServices中
} catch (IllegalAccessException ex) {
throw new RuntimeException(ex);
} catch (InstantiationException ex) {
throw new RuntimeException(ex);
}
mServices[i].mContext = this;
mServices[i].mComponents = mComponents;
if (DEBUG) Log.d(TAG, "running: " + mServices[i]);
mServices[i].start();//并调用他们的start()方法
...
}
...
}
startServicesIfNeeded(SERVICES)主要做了遍历SERVICES中的类,实例化SERVICES中的类并存于mServices中,从实例化的过程可以看得出来SERVICES中的类都属于SystemUI,一一打开他们,确实也发现他们都继承自SystemUI.然后所有实例化的的对象都调用了start(),SERVICES中的类其实就是SystemUI所有的功能模块了,每一个模块从这里开始展开
到了这里,每个模块的start()方法被掉用以后,SystemUI的各个模块又是如何的完成初始化,开始工作的呢?这里从最熟悉的状态栏导航栏先开始分析
状态栏导航栏的所属模块在android8.1是SystemBars,前面说到过所有的模块被实例化然后调用了start()方法,那么先来看看SystemBars的start()
frameworks/base/packages/SystemUI/src/com/android/systemui/SystemBars.java
@Override
public void start() {
if (DEBUG) Log.d(TAG, "start");
createStatusBarFromConfig();
}
...
private void createStatusBarFromConfig() {
if (DEBUG) Log.d(TAG, "createStatusBarFromConfig");
final String clsName = mContext.getString(R.string.config_statusBarComponent);//获取类名
if (clsName == null || clsName.length() == 0) {
throw andLog("No status bar component configured", null);
}
Class> cls = null;
try {
cls = mContext.getClassLoader().loadClass(clsName);//反射
} catch (Throwable t) {
throw andLog("Error loading status bar component: " + clsName, t);
}
try {
mStatusBar = (SystemUI) cls.newInstance();//得到StatusBar对象
} catch (Throwable t) {
throw andLog("Error creating status bar component: " + clsName, t);
}
mStatusBar.mContext = mContext;
mStatusBar.mComponents = mComponents;
mStatusBar.start();//把mContext和mComponents传给StatusBar对象,并调用start()方法
if (DEBUG) Log.d(TAG, "started " + mStatusBar.getClass().getSimpleName());
}
在SystemBar中的start()方法调用了createStatusBarFromConfig(),在createStatusBarFromConfig()中通过反射得到mStatusBar对象,先查查看mStatusBar是什么类型的,就是通过R.string.config_statusBarComponent去找
发现mStatusBar是StatusBar类,那么继续追踪StatusBar的start()方法,在这里之前有个疑问R.string.config_statusBarComponent可以配置成其他的类吗,答案是可以的
除了StatusBar还可以配置成TvStatusBar,CarStatusBar,这两个本质上跟跟StatusBar是一样的,只是为了适配电视跟车载做出来的,如果你的产品是电视就配置成com.android.systemui.statusbar.tv.TvStatusBar
在看看StatusBar的start()主要做了什么事情
frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
public void start() {
...
// Connect in to the status bar manager service
mCommandQueue = getComponent(CommandQueue.class);//实例化mCommandQueue
mCommandQueue.addCallbacks(this);//把自己注册到mCommandQueue
...
mBarService = IStatusBarService.Stub.asInterface(
ServiceManager.getService(Context.STATUS_BAR_SERVICE));//获取IStatusBarService实例
...
try {
mBarService.registerStatusBar(mCommandQueue, iconSlots, icons, switches, binders,
fullscreenStackBounds, dockedStackBounds);//向IStatusBarServie进行注册
} catch (RemoteException ex) {
// If the system process isn't there we're doomed anyway.
}
createAndAddWindows();//创建状态栏与导航栏的窗口
...
}
第一步,在StatusBar的start()中首先实例化了StatusBarManagerService访问StatusBar的桥梁CommandQueue(4行),并且把StatusBar自己注册到CommandQueue(5行),第二步,然后把实例化的CommandQueue传给StatusBarManagerService(7、8行),第三步,最后创建创建状态栏与导航栏的窗口(18行),先分析第一第二步,StatusBarManagerService访问StatusBar的桥梁搭建
frameworks/base/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
public class StatusBarManagerService extends IStatusBarService.Stub {
...
// ================================================================================
// Callbacks from the status bar service.
// ================================================================================
@Override
public void registerStatusBar(IStatusBar bar, List iconSlots,
List iconList, int switches[], List binders,
Rect fullscreenStackBounds, Rect dockedStackBounds) {
...
mBar = bar;
...
}
...
@Override
public void expandNotificationsPanel() {
enforceExpandStatusBar();
if (mBar != null) {
try {
mBar.animateExpandNotificationsPanel();
} catch (RemoteException ex) {
}
}
}
...
}
StatusBarManagerService的创建是在SystemServer中完成的,他是一个系统服务,他的作用是跟StatusBar关联起来,外界想要调用StatusBar方法可以通过它来完成,那么StatusBarManagerService跟StatusBar又是怎么关联起来的呢?,前面StatusBar的start()中,上述提及到的第二步,传入了一个mCommandQueue参数到StatusBarManagerService,而这个参数传到StatusBarManagerService被保存到了mBar中,比如其他地方通过StatusBarManagerService调用expandNotificationsPanel(),实际上是调用了mCommandQueue的animateExpandNotificationsPanel(),在看看mCommandQueue的代码
frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
public class CommandQueue extends IStatusBar.Stub {
...
public void addCallbacks(Callbacks callbacks) {
mCallbacks.add(callbacks);
callbacks.disable(mDisable1, mDisable2, false /* animate */);
}
...
public void animateExpandNotificationsPanel() {
synchronized (mLock) {
mHandler.removeMessages(MSG_EXPAND_NOTIFICATIONS);
mHandler.sendEmptyMessage(MSG_EXPAND_NOTIFICATIONS);//发MSG_EXPAND_NOTIFICATIONS消息到Handler 去处理
}
}
private final class H extends Handler {
private H(Looper l) {
super(l);
}
public void handleMessage(Message msg) {
final int what = msg.what & MSG_MASK;
switch (what) {
...
case MSG_EXPAND_NOTIFICATIONS:
for (int i = 0; i < mCallbacks.size(); i++) {
mCallbacks.get(i).animateExpandNotificationsPanel();
}
break;
...
}
}
}
...
}
可以看到CommandQueue是通过mCallbacks继续下一步的调用(28行),而这里的mCallbacks正是StatusBar,因为前面在StatusBar的start()方法中正式把自己注册了进来,28行中实际就是StatusBar调用自己的animateExpandNotificationsPanel(),这样一来StatusBar跟StatusBarManagerService的桥梁旧通过CommandQueue建立起来了。
分析StatusBar的start()的第一第二步,接着分析第三步createAndAddWindows()
frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
public void createAndAddWindows() {
addStatusBarWindow();
}
private void addStatusBarWindow() {
makeStatusBarView();
mStatusBarWindowManager = Dependency.get(StatusBarWindowManager.class);
mRemoteInputController = new RemoteInputController(mHeadsUpManager);
mStatusBarWindowManager.add(mStatusBarWindow, getStatusBarHeight());
}
protected void makeStatusBarView() {
final Context context = mContext;
updateDisplaySize(); // populates mDisplayMetrics
updateResources();
updateTheme();
inflateStatusBarWindow(context);//加载状态栏布局
...
FragmentHostManager.get(mStatusBarWindow)
.addTagListener(CollapsedStatusBarFragment.TAG, (tag, fragment) -> {
CollapsedStatusBarFragment statusBarFragment =
(CollapsedStatusBarFragment) fragment;
statusBarFragment.initNotificationIconArea(mNotificationIconAreaController);
mStatusBarView = (PhoneStatusBarView) fragment.getView();
mStatusBarView.setBar(this);
mStatusBarView.setPanel(mNotificationPanel);
mStatusBarView.setScrimController(mScrimController);
mStatusBarView.setBouncerShowing(mBouncerShowing);
setAreThereNotifications();
checkBarModes();
}).getFragmentManager()
.beginTransaction()
.replace(R.id.status_bar_container, new CollapsedStatusBarFragment(),
CollapsedStatusBarFragment.TAG)//把super_status_bar中的status_bar_container替换成CollapsedStatusBarFragment
.commit();
...
try {
boolean showNav = mWindowManagerService.hasNavigationBar();
if (DEBUG) Log.v(TAG, "hasNavigationBar=" + showNav);
if (showNav) {
createNavigationBar();//创建导航栏
}
} catch (RemoteException ex) {
// no window manager? good luck with that
}
...
}
protected void inflateStatusBarWindow(Context context) {
mStatusBarWindow = (StatusBarWindowView) View.inflate(context,
R.layout.super_status_bar, null);
}
protected void createNavigationBar() {
mNavigationBarView = NavigationBarFragment.create(mContext, (tag, fragment) -> {
mNavigationBar = (NavigationBarFragment) fragment;
if (mLightBarController != null) {
mNavigationBar.setLightBarController(mLightBarController);
}
mNavigationBar.setCurrentSysuiVisibility(mSystemUiVisibility);
});
}
创建于调用顺序createAndAddWindows()->addStatusBarWindow()->makeStatusBarView(),在makeStatusBarView()加载了R.layout.super_status_bar然后再把super_status_bar中的status_bar_container替换成CollapsedStatusBarFragment,CollapsedStatusBarFragment加载的是R.layout.status_bar,至此状态栏旧加载好了,然后makeStatusBarView()中继续调用createNavigationBar(),然后创建mNavigationBarView实例,mNavigationBarView实例加载R.layout.navigation_bar,至此导航栏也加载好了。