SystemUI之呈现流程

  • SystemUI主体框架启动流程
  • SystemUI视图呈现

在SystemUI之功能介绍和UI布局实现 曾挖了一个坑,最近手头项目快结尾了,开始补坑。本篇基于AndroidL分析SystemUI的启动流程。

SystemUI主体框架启动流程

AndroidL上SystemUI是以Application的形式存在的,本质上来讲它和我们平时常见的App一样,只是它被放在了Frameworks包下,开机自启动,且能获取到的系统权限比普通应用要高。既然它也是一个App,那么分析之前不妨从AndroidManifest文件入手,SystemUI代码位于:
frameworks/base/packages/SystemUI
打开AndroidManifest文件,可以看到和一般应用一样注册了一堆activity/service/receiver组件,但没有provider组件。摘录主要的组件

<application
        android:name=".SystemUIApplication"
        android:persistent="true"
        android:allowClearUserData="false"
        android:allowBackup="false"
        android:process="com.android.systemui"
        android:supportsRtl="true"
        android:theme="@style/systemui_theme">
        ...
        <!-- Keep theme in sync with SystemUIApplication.onCreate().
             Setting the theme on the application does not affect views inflated by services.
             The application theme is set again from onCreate to take effect for those views. -->
    <service android:name="SystemUIService"
            android:exported="true"
            />

仔细浏览Manifest文件我们发现Activity组件里没有我们常见的
<category android:name="android.intent.category.LAUNCHER" />
这也是systemui没有出现在系统应用列表里的原因。那么看到这问题来了,一般的应用我们是通过点击桌面的应用图标来启动的,那么SystemUI在开机完成后就立马呈现出来了,是谁将它在什么时候启动的呢?
注意到AndroidManifest文件中的SystemUIService这个service组件,查看其java代码,路径位于frameworks/base/packages/SystemUI/src/com/android/systemui/SystemUIService.java,代码很少直接贴出来:

public class SystemUIService extends Service {
    @Override
    public void onCreate() {
        super.onCreate();
        ((SystemUIApplication) getApplication()).startServicesIfNeeded();
    }
    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }
}

可以看到这里的onCreate方法里有一个startServicesIfNeeded方法,我们从这在进入到SystemUIApplication类中查看,原来这里通过反射形式
mServices[i].start();
启动了一堆services,这些services如下:

private final Class<?>[] SERVICES = new Class[] {
            com.android.systemui.tuner.TunerService.class,
            com.android.systemui.keyguard.KeyguardViewMediator.class,
            com.android.systemui.recents.Recents.class,
            com.android.systemui.volume.VolumeUI.class,
            com.android.systemui.statusbar.SystemBars.class,
            com.android.systemui.usb.StorageNotification.class,
            com.android.systemui.power.PowerUI.class,
            com.android.systemui.media.RingtonePlayer.class,
};

这里的services都是抽象类SystemUI的子类,它们是SystemUi的核心服务,到此算是来到了SystemUI的大门跟前,回顾下一路走来的路线:
SystemUIService.onCreate—–>SystemUIApplication.startServicesIfNeeded—->循环中调用mServices[i].start()启动各种核心service。
我们还需要补充作为源头的SystemUIService是从哪启动的呢。SystemUIService作为一个Service肯定需要在某处被startService,而且被调用的时机还要比较早,通过搜索SystemUIService关键字,在SystemServer类中查到如下启动代码,SystemServer路径位于
frameworks/base/services/java/com/android/server/SystemServer.java

mActivityManagerService.systemReady(new Runnable() {
    @Override
        public void run() {
            try {
                    startSystemUi(context);
            } catch (Throwable e) {
                    reportWtf("starting System UI", e);
            }
}
...
static final void startSystemUi(Context context) {
        Intent intent = new Intent();
        intent.setComponent(new ComponentName("com.android.systemui","com.android.systemui.SystemUIService"));
        context.startServiceAsUser(intent, UserHandle.OWNER);
}

查看到这可以补全SystemUI主体框架的启动流程:
SystemService启动Android核心服务包括了ActivityManagerService
--->ActivityManagerService一旦启动完成就会在systemReady的回调里启动SystemUIService
--->SystemUIService.onCreate—--->SystemUIApplication.startServicesIfNeeded
--->循环中调用mServices[i].start()启动SystemUI的各种核心service。

SystemUI视图呈现

在SystemUI主体框架启动流程我们分析到了SystemUI的核心Service是如何启动的,那么服务有了,视图又是如何呈现的呢?到现在我们还没有看到Activity的身影,通常view都是通过setContentView()方法在Activity里加载进来的。这里没有Activity,所以忘掉setContentView吧。
上节我们分析到SystemUI的核心service的启动。
SystemUIService->SystemUIService.onCreate— –>SystemUIApplication.startServicesIfNeeded—->循环中调用mServices[i].start()启动SystemUI的各种核心service。
提个醒,这里的service和平常所讲的四大组件中的service不是同一个概念,它就是一个SystemUI模块自定义的普通对象。核心service不少,这里拿 SystemBars分析,它是SystemUI的主要视图。
首先调用的是SystemBars的start()方法,

@Override
public void start() { if (DEBUG) Log.d(TAG, "start");
        mServiceMonitor = new ServiceMonitor(TAG, DEBUG,
                mContext, Settings.Secure.BAR_SERVICE_COMPONENT, this);
        mServiceMonitor.start();// will call onNoService if no remote service is found }

这里ServiceMonitor的作用是管理来自其他进程对SystemUI视图的操控,这里先启动 ServiceMonitor,然后通过ServiceMonitor的回调方法创建StatusBar。下面的Log清楚的显示了该过程:
这里写图片描述
createStatusBarFromConfig方法里通过反射开启PhoneStatusBar,顺便提下PhoneStatusBar的继承关系:
SystemUI之呈现流程_第1张图片
它是SystemUI的孙子,BaseStatusBar的儿子,还有个兄弟TvStatusBar,这个在大屏设备如电视上才会出现。
PhoneStatusBar的start()主要做了下面几件事:

  • super.start()—>在父类里创建并添加主视图,源码里给出了注释// calls createAndAddWindows()
  • addNavigationBar()—>添加底部导航栏
  • new PhoneStatusBarPolicy—>实例化状态栏代理
  • startKeyguard()—>启动keyguard

本节分析视图呈现,所以我们主要关注super.start()做了什么事。BaseStatusBar的start方法里初始化了一堆系统服务WindowManager/AccessibilityManager/PowerManager/UserManager,注册了一堆数据库监者,然后终于看到了createAndAddWindows,它是一个抽象方法,实现在子类中,至此我们又回到PhoneStatusBar查看createAndAddWindows。重头戏来了,它会调用makeStatusBarView方法,从方法注释Constructing the view里清楚了解到PhoneStatusBar的View正是在这里构建的。这个方法很长,但主要还是在下面这行代码

mStatusBarWindow = (StatusBarWindowView) View.inflate(context,
                R.layout.super_status_bar, null);

无论多长它的主要作用还在构建View,这个View就是 super_status_bar,可以对比之前的博文SystemUI之功能介绍和UI布局实现看它的视图。视图有了,还需要将它呈现出来,还是看createAndAddWindows方法,这里我们已经完成了create的动作,在看Add动作。

@Override
public void createAndAddWindows() {
        addStatusBarWindow();
}

private void addStatusBarWindow() {
        makeStatusBarView();
        mStatusBarWindowManager = new StatusBarWindowManager(mContext);
        mStatusBarWindowManager.add(mStatusBarWindow, getStatusBarHeight());
}

刚刚create的视图正是通过

mStatusBarWindowManager.add(mStatusBarWindow, getStatusBarHeight());

添加进来的,查看mStatusBarWindowManager.add方法揭开终极秘密。

mWindowManager.addView(mStatusBarView, mLp);

mWindowManager就是一个WindowManager对象,原来我们create的View是通过WindowManager呈现出来的。
分析到此,我们的视图已经出来了,在补全之前的思路:


SystemService启动Android核心服务包括了ActivityManagerService
—>ActivityManagerService启动完成就会在systemReady的回调里启动SystemUIService
—>SystemUIService—>SystemUIService.onCreate
—>SystemUIApplication.startServicesIfNeeded
—>循环中调用mServices[i].start()启动SystemUI的各种核心service
—>SystemBars启动—>SystemBars创建PhoneStatusBar
—>PhoneStatusBar通过makeStatusBarView创建视图
—>PhoneStatusBar通过WindowManager将视图呈现给用户

你可能感兴趣的:(框架,UI,frameworks)