UI是实现用户交互的重要途径之一,而Android中一个重要的UI元素就是SystemUI,本文分析基于Android 5.1,分析SystemUI的启动及运行过程。

  • SystemUI源代码所在路径为:

    frameworks/base/packages/SystemUI
  • 查看AndroidManifest.xml,整理软件实现思路。

    • 包名为com.android.systemui

      package="com.android.systemui"
    • 分配的userID为android.uid.systemui

      android:sharedUserId="android.uid.systemui"
    • 标明此应用为系统核心App

      coreApp="true"
    • 接下来是一系列的权限声明,包括Networking and telephonyPhysical hardwareActivityManagerWindowManagerDreamManagerAlarm clocksKeyguardRecentsWifi DisplayScreen Capturing等方面的权限。

    • 接下来看 <application></application>中的内容:

      • 此应用不会轻易被kill,并且会自动启动

        android:persistent="true"
      • 用户数据不可清除

        android:allowClearUserData="false"
      • 启用硬件加速

        android:hardwareAccelerated="true"
      • 设置系统进程

        android:process="com.android.systemui"
      • 其他属性为常规属性,很多app都会有,在此不再赘述。

      • 接下来是分析SystemUI的重点,看下都涉及到了哪些activity,service和receiver。

        1. activity:

          • .usb.UsbStorageActivity
          • com.android.internal.app.ExternalMediaFormatActivity
          • .recent.RecentsActivity
          • .recents.RecentsActivity
          • .usb.UsbConfirmActivity
          • .usb.UsbPermissionActivity
          • .usb.UsbResolverActivity
          • .usb.UsbAccessoryUriActivity
          • .usb.UsbDebuggingActivity
          • .net.NetworkOverLimitActivity
          • .media.MediaProjectionPermissionActivity
          • .DessertCase
          • .egg.LLandActivity
          • .Somnambulator
          • .settings.BrightnessDialog
        2. service:

          • SystemUIService
          • .screenshot.TakeScreenshotService
          • .LoadAverageService
          • .ImageWallpaper
          • .DessertCaseDream
          • .keyguard.KeyguardService
          • .doze.DozeService
        3. receiver:

          • .BootReceiver
          • .qs.tiles.HotspotTile$APChangedReceiver
          • .recent.RecentsPreloadReceiver
          • .recents.RecentsUserEventProxyReceiver
      • 众多activity中并没有LAUNCHER,也就是说SystemUI是没有启动界面的。

  • SystemUI的启动

    既然SystemUI没有启动界面,也无需人为启动,那么SystemUI是怎么启动起来的呢?接下来就将对这个问题进行说明。

    • 在service中有一个SystemUIService,这就是入口。那么这个SystemUIService又是怎么启动的呢?要找到答案,就要考虑到这是一个系统app,自然会在系统完成初始化以后启动,那么利用Source Insight在frameworks/base中看看有没有。

    从结果来看,在SystemService貌似有什么线索。打开SystemService.java(frameworks/base/services/java/com/android/server/),以下代码就展现在眼前了。

    static final void startSystemUi(Context context) {
    Intent intent = new Intent();
    intent.setComponent(new ComponentName("com.android.systemui",
    "com.android.systemui.SystemUIService"));
    //Slog.d(TAG, "Starting service: " + intent);
    context.startServiceAsUser(intent, UserHandle.OWNER);
    }

    在代码中可以看到SystemUIService被启动了起来,那么哪里调用了这个方法呢?在此类中继续查找,又发现如下代码:

    mActivityManagerService.systemReady(new Runnable() {
    @Override
    public void run() {
    Slog.i(TAG, "Making services ready");
    mSystemServiceManager.startBootPhase(SystemService.PHASE_ACTIVITY_MANAGER_READY); try {
    mActivityManagerService.startObservingNativeCrashes();
    } catch (Throwable e) {
    reportWtf("observing native crashes", e);
    } Slog.i(TAG, "WebViewFactory preparation");
    WebViewFactory.prepareWebViewInSystemServer(); try {
    startSystemUi(context);
    } catch (Throwable e) {
    reportWtf("starting System UI", e);
    }
    ...
    }
    }

    由代码可知,ActivityManagerService调用了systemReady()方法,也就是系统就绪就会调用run()方法。那么会在何时执行到此处呢?再往上探索,发现上述代码位于startOtherServices()方法中,那么还是那个问题,何时调用startOtherServices()方法。再往上探索,发现startOtherServices()位于一个run()方法中

    private void run() {
    ···
    // Start services.
    try {
    startBootstrapServices();
    startCoreServices();
    startOtherServices();
    } catch (Throwable ex) {
    Slog.e("System", "******************************************");
    Slog.e("System", "************ Failure starting system services", ex);
    throw ex;
    }
    ···
    }

    再往上追一追,最终找到了这个类的开始:

    public static void main(String[] args) {
    new SystemServer().run();
    }

    嗯,这是···,很熟悉嘛。

    至于SystemService则是由Zygote启动的,在此就不多追溯了。

    至此,SystemServer已经启动,那么在SystemServer里面又做了什么事情呢?

  • SystemUIService的初始化

    在SystemUIService中,主要代码就一个onCreate()方法,来看看他做了啥:

    @Override
    public void onCreate() {
    super.onCreate();
    ((SystemUIApplication) getApplication()).startServicesIfNeeded();
    }

    转型为SystemUIApplication并且调用startServicesIfNeeded()方法。那么接下来去看看startServicesIfNeeded()方法做了些什么。

    public void startServicesIfNeeded() {
    if (mServicesStarted) {
    return;
    } 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.");
    final int N = SERVICES.length;
    for (int i=0; i<N; i++) {
    Class<?> cl = SERVICES[i];
    if (DEBUG) Log.d(TAG, "loading: " + cl);
    try {
    mServices[i] = (SystemUI)cl.newInstance();
    } 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(); if (mBootCompleted) {
    mServices[i].onBootCompleted();
    }
    }
    mServicesStarted = true;
    }

    根据代码中涉及到的mServices,追溯其来源:

    private final SystemUI[] mServices = new SystemUI[SERVICES.length];

    再往上,得到SERVICES的由来:

    private final Class<?>[] SERVICES = new Class[] {
    com.android.systemui.keyguard.KeyguardViewMediator.class,
    com.android.systemui.recent.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
    };

    在这里定义了很多System Panel,这里叫做SERVICES,并非真正的services,运行在SystemUIService中的子服务。此时再来回头看onCreate()方法:

    @Override
    public void onCreate() {
    super.onCreate();
    // Set the application theme that is inherited by all services. Note that setting the
    // application theme in the manifest does only work for activities. Keep this in sync with
    // the theme set there.
    setTheme(R.style.systemui_theme); IntentFilter filter = new IntentFilter(Intent.ACTION_BOOT_COMPLETED);
    filter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY);
    registerReceiver(new BroadcastReceiver() {
    @Override
    public void onReceive(Context context, Intent intent) {
    if (mBootCompleted) return; if (DEBUG) Log.v(TAG, "BOOT_COMPLETED received");
    unregisterReceiver(this);
    mBootCompleted = true;
    if (mServicesStarted) {
    final int N = mServices.length;
    for (int i = 0; i < N; i++) {
    mServices[i].onBootCompleted();
    }
    }
    }
    }, filter);
    }

    在onCreate()方法中,注册了广播接收器,用于接收开机完成的广播,并将开机完成的状态传递给每个SERVICE。

    经过以上代码的追溯,可知:

    mServices[i] = (SystemUI)cl.newInstance();//实例化子服务,并将其存储于mService[i]中。

    mServices[i].mContext = this; //设置mService[i]的Context

    mServices[i].mComponents = mComponents;//设置mService[i]的Components

    mServices[i].start();//运行mService[i]

至此,SystemUIService的启动就已完成,伴随着SystemUIService的完成,SystemUI的核心service也就启动了,SystemUIService的使命也就完成了,接下来的事情就交由各个子服务去完成了。

以上属于个人体验心得总结,若有不足之处,还望不吝赐教,欢迎批评指正,共同进步

Android核心程序之SystemUI - (一)开篇的更多相关文章

  1. Android核心分析之二十Android应用程序框架之无边界设计意图

    Android应用程序框架1 无边界设计理念 Android的应用框架的外特性空间的描述在SDK文档(http://androidappdocs.appspot.com/guide/topics/fu ...

  2. Qt on Android 核心编程

    Qt on Android 核心编程(最好看的Qt编程书!CSDN博主foruok倾力奉献!) 安晓辉 著   ISBN 978-7-121-24457-5 2015年1月出版 定价:65.00元 4 ...

  3. 使用jQuery Mobile + PhoneGap 开发Android应用程序(转)

    使用jQuery Mobile + PhoneGap 开发Android应用程序(转) 一.简介 jQuery Mobile是jQuery在手机上和平板设备上的版本.jQuery Mobile 不仅给 ...

  4. Unity开发Android应用程序:调用安卓应用程序功能

    开发环境: Eclipse3.4 + adt12 + jdk6 + AndroidSDK2.2 Unity3.4 + windows7 测试设备: HTC Desire HD 本文要涉及到的几个重点问 ...

  5. Android核心分析之二十二Android应用框架之Activity

    3 Activity设计框架 3.1 外特性空间的Activity    我们先来看看,android应用开发人员接触的外特性空间中的Activity,对于AMS来讲,这个Activity就是客服端的 ...

  6. Android核心分析之二十一Android应用框架之AndroidApplication

    Android Application Android提供给开发程序员的概念空间中Application只是一个松散的表征概念,没有多少实质上的表征.在Android实际空间中看不到实际意义上的应用程 ...

  7. 一、Android应用程序的基本原理(Fundamentals [,fʌndə'mentlz])

    Android 应用程序以java作为编程语言.Android SDK工具把代码连同数据.资源文件一起编译成一个以.apk为后缀(suffix)的android 程序存档(archive)文件包.在一 ...

  8. Android平台程序崩溃的类型及原因列举

    Android平台程序崩溃大家都应该遇到过,force close和ANR应该是大家遇到较多的. 这里把Android平台程序崩溃的各种类型做一个简述和原因列举. 1.ANR(可见ANR): 发生场景 ...

  9. Android应用程序线程消息循环模型分析

    文章转载至CSDN社区罗升阳的安卓之旅,原文地址:http://blog.csdn.net/luoshengyang/article/details/6905587 我们知道,Android应用程序是 ...

随机推荐

  1. ElementUI 之 DatePicker 日期限制范围 disabledDate

    需求: 时间选择器,只能选择 2000 年 - 至今的年份. <el-date-picker v-model="year" type="year" :pi ...

  2. Greenplum 查看表的分区键与分区类型

    方法一 查看表的分区键 select d.nspname||'.'||a.relname as table_name,string_agg(b.attname,',') as column_namef ...

  3. CF369E Valera and Queries kdtree

    给你一堆线段,求:一个区间内包含的本质不同线段种类数(只要线段有一部分在区间中就算是包含) 考虑容斥:总线段数-被那些没有询问的区间完全覆盖的数量. 用离线+树状数组数点或者 KDtree 数点即可. ...

  4. P5431 【模板】乘法逆元2

    洛谷题目链接 刚开始做乘法逆元还是有点懵逼的~ 以下式子都在模\(p\)意义下进行 我们把式子改一下,变成:\[\sum\limits_{i=1}^nk^i\times a_i^{-1}\] 我们先算 ...

  5. PAT TOP 1005 Programming Pattern (35 分)哈希做法

    1005 Programming Pattern (35 分) Programmers often have a preference among program constructs. For ex ...

  6. syniverse是一家怎样的公司

    syniverse是一家怎样的公司?(详见问题描述)? 李超   核心业务当然是国际漫游了.简单来说就是做全球各个运营商之间的hub. 打个比方说,一家运营商A做通信,它的覆盖范围肯定是有限的(比如中 ...

  7. Python的is和==

    is是对比地址:==是对比值

  8. 关于Linux安装中NAT模式和桥接模式的区别详解

    1.一般我们在创建一个Linux虚拟机时候,会面临三个网络配置选择: 桥接模式.nat模式.host-only模式(主机模式,这个模式用得少,就不介绍了) 2.NAT模式: 所谓nat模式,就是虚拟系 ...

  9. 微信小程序之分享功能

    说到分享 大家都会想到手机右上角点击不就分享了么?对的没错,那样是分享转发的是小程序  而不是指定的某个页面,所以自己动手丰衣足食,自己写一个转发功能被, 其实也没那么可怕,主要参考的是微信小程序AP ...

  10. 初识kaggle,以及记录 kaggle的使用

    1.简介:Kaggle是一个数据建模和数据分析竞赛的平台.企业和研究者可在其上发布数据,统计学者和数据挖掘专家可在其上进行竞赛,通过“众包”的形式以产生最好的模型.Kaggle可以分为Competit ...