• Android核心程序之SystemUI


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

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

  • 相关阅读:
    决策表
    边界值
    等价类
    python_安装python2.7.7和easy_install
    网络_系统测试方案
    软件测试之魂_测试方案模板
    初识HTTP协议web开发
    Bootstrap框架
    jQuery快速入门
    前端基础之BOM和DOM
  • 原文地址:https://www.cnblogs.com/cj5785/p/9892979.html
Copyright © 2020-2023  润新知