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等方面的权限。

    • 接下来看 中的内容:

      • 此应用不会轻易被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()方法,来看看他做了啥:

    @Overridepublic 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 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()方法:

    @Overridepublic 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的使命也就完成了,接下来的事情就交由各个子服务去完成了。

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

更多相关文章

  1. Android(安卓)使用SQLiteDatabase操作SQLite数据库
  2. Android(安卓)MVP模式 谷歌官方代码解读
  3. Android混合开发之------ AndroidStudio集成Cordova项目
  4. Android(安卓)Bundle总结
  5. 自定义activity启动退出效果
  6. 第一个android 程序的学习心得
  7. 精通android之Broadcast Receiver
  8. Android(安卓)出现的警告(Service Intent must be explicit)解决
  9. Android(安卓)代码中设置EditText只输入数字、字母

随机推荐

  1. android gradle 配置 build.gradle
  2. Android——gradle
  3. android 跳转到应用通知设置界面
  4. Android学习笔记——Android生命周期
  5. Android(安卓)App Developers GUI Kits,
  6. Android(安卓)自定义Progress Bar
  7. 将ffmpeg编译到android 源码
  8. Android(安卓)Wi-Fi AutoConnect to Ap t
  9. Android通过AES128加密解密字符串
  10. Android(不)联动的顶层菜单栏tabLayout+v