[深入SystemUI]-SystemUI_statusbar的启动流程

栏目: Android · 发布时间: 5年前

内容简介:本文流程基于Android 9.0在SystemServer中有一个方法startSystemUi,当系统启动后,会执行到SystemServer的startSystemUi()方法,正是在这个方法中启动了SystemUIService。注意,这里的

本文流程基于Android 9.0

[深入SystemUI]-SystemUI_statusbar的启动流程

1.启动SystemUIService

在SystemServer中有一个方法startSystemUi,当系统启动后,会执行到SystemServer的startSystemUi()方法,正是在这个方法中启动了SystemUIService。

static final void startSystemUi(Context context, WindowManagerService windowManager) {
    Intent intent = new Intent();
    // 指定了systemui的包名"com.android.systemui",指定了ServiceUIService的类名"com.android.systemui.SystemUIService"
    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();
}
复制代码

2.在SystemUIService中启动SystemUI中的服务

SystemUIService.java

@Override
public void onCreate() {
    super.onCreate();
    //在oncreate方法中调用SystemUIApplication的startServicesIfNeeded来启动相关服务
    ((SystemUIApplication) getApplication()).startServicesIfNeeded();

    // code...
}
复制代码

SystemUIApplication

/**
 * Makes sure that all the SystemUI services are running. If they are already running, this is a
 * no-op. This is needed to conditinally start all the services, as we only need to have it in
 * the main process.
 * <p>This method must only be called from the main thread.</p>
 */

public void startServicesIfNeeded() {
    String[] names = getResources().getStringArray(R.array.config_systemUIServiceComponents);
    startServicesIfNeeded(names);
}
复制代码

注意,这里的 servicenames 是从 config 文件中读取出来的,具体内容如下,其中就包含了 SystemBars 的路径:

<!-- SystemUI Services: The classes of the stuff to start. -->
<string-array name="config_systemUIServiceComponents" translatable="false">
    <item>com.android.systemui.Dependency</item>
    <item>com.android.systemui.util.NotificationChannels</item>
    <item>com.android.systemui.statusbar.CommandQueue$CommandQueueStart</item>
    <item>com.android.systemui.keyguard.KeyguardViewMediator</item>
    <item>com.android.systemui.recents.Recents</item>
    <item>com.android.systemui.volume.VolumeUI</item>
    <item>com.android.systemui.stackdivider.Divider</item>
    <item>com.android.systemui.SystemBars</item>
    <item>com.android.systemui.usb.StorageNotification</item>
    <item>com.android.systemui.power.PowerUI</item>
    <item>com.android.systemui.media.RingtonePlayer</item>
    <item>com.android.systemui.keyboard.KeyboardUI</item>
    <item>com.android.systemui.pip.PipUI</item>
    <item>com.android.systemui.shortcut.ShortcutKeyDispatcher</item>
    <item>@string/config_systemUIVendorServiceComponent</item>
    <item>com.android.systemui.util.leak.GarbageMonitor$Service</item>
    <item>com.android.systemui.LatencyTester</item>
    <item>com.android.systemui.globalactions.GlobalActionsComponent</item>
    <item>com.android.systemui.ScreenDecorations</item>
    <item>com.android.systemui.fingerprint.FingerprintDialogImpl</item>
    <item>com.android.systemui.SliceBroadcastRelayHandler</item>
</string-array>
复制代码

具体的启动过程

private void startServicesIfNeeded(String[] services) {
    //这里就是方法名IfNeeded的原因,首先会判断boolean变量mServicesStarted是否为ture,为true,表示服务已经启动,就不需要执行后面的启动流程了
    if (mServicesStarted) {
        return;
    }
    //定义一个用于启动SystemUI服务的数组,并且这些要启动的服务都是继承自SystemUI的
    mServices = new SystemUI[services.length];

    if (!mBootCompleted) {
        // check to see if maybe it was already completed long before we began
        // see ActivityManagerService.finishBooting()
        if ("1".equals(SystemProperties.get("sys.boot_completed"))) {
            mBootCompleted = true;
            if (DEBUG) Log.v(TAG, "BOOT_COMPLETED was already sent");
        }
    }

    Log.v(TAG, "Starting SystemUI services for user " +
            Process.myUserHandle().getIdentifier() + ".");
    TimingsTraceLog log = new TimingsTraceLog("SystemUIBootTiming",
            Trace.TRACE_TAG_APP);
    log.traceBegin("StartServices");
    final int N = services.length;
    //通过遍历,将所有的服务启动起来
    for (int i = 0; i < N; i++) {
        String clsName = services[i];
        if (DEBUG) Log.d(TAG, "loading: " + clsName);
        log.traceBegin("StartServices" + clsName);
        long ti = System.currentTimeMillis();
        Class cls;
        try {
            cls = Class.forName(clsName);
            mServices[i] = (SystemUI) cls.newInstance();
        } catch(ClassNotFoundException ex){
            throw new RuntimeException(ex);
        } 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]);
        //调用各个服务重写了的start()方法
        mServices[i].start();
        log.traceEnd();

        // Warn if initialization of component takes too long
        ti = System.currentTimeMillis() - ti;
        if (ti > 1000) {
            Log.w(TAG, "Initialization of " + cls.getName() + " took " + ti + " ms");
        }
        if (mBootCompleted) {
            mServices[i].onBootCompleted();
        }
    }
    // code...

    //启动过一次后,就将mServicesStarted置为true,避免重复启动
    mServicesStarted = true;
}
复制代码

3.在SystemBars中启动statusbar

关于 SystemBars 类的注释是这样的,“根据产品配置,使用进程内实现,确保一个 status bar 服务能够一直运行”。

/**
 * Ensure a single status bar service implementation is running at all times, using the in-process
 * implementation according to the product config.
 */
复制代码

那么status bar是怎样启动的呢?在SystemUIApplication中也是通过调用SystemBars的start()方法,在SystemBars中的start()方法中去启动statusbar。

@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();
    } catch (Throwable t) {
        throw andLog("Error creating status bar component: " + clsName, t);
    }
    mStatusBar.mContext = mContext;
    mStatusBar.mComponents = mComponents;
    mStatusBar.start();
    if (DEBUG) Log.d(TAG, "started " + mStatusBar.getClass().getSimpleName());
}
复制代码

这里的clsName和之前服务的names一样,也是从config中读取的,具体如下,是StatusBar的类路径。

<!-- Component to be used as the status bar service.  Must implement the IStatusBar
 interface.  This name is in the ComponentName flattened format (package/class)  -->
<string name="config_statusBarComponent" translatable="false">com.android.systemui.statusbar.phone.StatusBar</string>
复制代码

于是乎,通过这样一种方式,就启动起来一个一直运行着的StatusBar服务了。


以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

大话存储

大话存储

张冬 / 清华大学出版社 / 2008-11 / 58.00元

网络存储,是近二十年来的新兴行业。从纸带到硬盘再到大型磁盘阵列,存储系统经历了从简单到复杂,从单块硬盘到存储区域网络(SAN)。网络存储行业目前已经是一个步入正轨的IT行业了。. 网络存储是一个涉及计算机硬件以及网络协议/技术、操作系统以及专业软件等各方面综合知识的领域。目前国内阐述网络存储的书籍少之又少,大部分是国外作品,对存储系统底层细节的描述不够深入,加之术语太多,初学者很难真正理解网......一起来看看 《大话存储》 这本书的介绍吧!

URL 编码/解码
URL 编码/解码

URL 编码/解码

XML、JSON 在线转换
XML、JSON 在线转换

在线XML、JSON转换工具

HEX CMYK 转换工具
HEX CMYK 转换工具

HEX CMYK 互转工具