Android核心程序之SystemUI

来源:互联网 发布:如何编译java程序 编辑:程序博客网 时间:2024/06/09 17:52

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()方法,来看看他做了啥:

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

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

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

原创粉丝点击