1. 程式人生 > >Android SyetemServer程序啟動過程(基於7.0 N版本原始碼)

Android SyetemServer程序啟動過程(基於7.0 N版本原始碼)

前言

上一篇我們學習了Zygote程序,並且知道Zygote程序啟動了SyetemServer程序,那麼這一篇我們就來學習Android7.0版本的SyetemServer程序的啟動過程。

1.Zygote啟動SyetemServer程序

在上一篇文章中我們講到在ZygoteInit.java的startSystemServer函式中啟動了SyetemServer程序,如下所示。frameworks/base/core/java/com/android/internal/os/ZygoteInit.java

private static boolean startSystemServer(String abiList, String socketName)
           throws MethodAndArgsCaller, RuntimeException {
    ...
       if (pid == 0) {
           if (hasSecondZygote(abiList)) {
               waitForSecondaryZygote(socketName);
           }
           handleSystemServerProcess(parsedArgs);
       }
       return true;
   }

在startSystemServer函式中呼叫handleSystemServerProcess來啟動SyetemServer程序。

2.SyetemServer程序啟動過程

handleSystemServerProcess函式的程式碼如下所示。

private static void handleSystemServerProcess(
          ZygoteConnection.Arguments parsedArgs)
          throws ZygoteInit.MethodAndArgsCaller {
      closeServerSocket();//1
    ...
      if (parsedArgs.invokeWith != null) {
         ...
      } else {
          ClassLoader cl = null;
          if (systemServerClasspath != null) {
              cl = createSystemServerClassLoader(systemServerClasspath,
                                                 parsedArgs.targetSdkVersion);
              Thread.currentThread().setContextClassLoader(cl);
          }
          RuntimeInit.zygoteInit(parsedArgs.targetSdkVersion, parsedArgs.remainingArgs, cl);//2
      }
  }

SyetemServer程序是複製了Zygote程序的地址空間,因此也會得到Zygote程序建立的Socket,這個Socket對於SyetemServer程序沒有用處,因此,需要註釋1處的程式碼來關閉該Socket。在註釋2處呼叫RuntimeInit的zygoteInit函式,它的程式碼如下所示。

frameworks/base/core/java/com/android/internal/os/RuntimeInit.java

public static final void zygoteInit(int targetSdkVersion, String[] argv, ClassLoader classLoader)
            throws ZygoteInit.MethodAndArgsCaller {
        if (DEBUG) Slog.d(TAG, "RuntimeInit: Starting application from zygote");
        Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "RuntimeInit");
        redirectLogStreams();
        commonInit();
        nativeZygoteInit();//1
        applicationInit(targetSdkVersion, argv, classLoader);//2
    }

註釋1處呼叫nativeZygoteInit函式,一看函式的名稱就知道呼叫Native層的程式碼。

啟動Binder執行緒池

接著我們來檢視nativeZygoteInit函式對用的JNI檔案,如下所示。frameworks/base/core/jni/AndroidRuntime.cpp

static const JNINativeMethod gMethods[] = {
    { "nativeFinishInit", "()V",
        (void*) com_android_internal_os_RuntimeInit_nativeFinishInit },
    { "nativeZygoteInit", "()V",
        (void*) com_android_internal_os_RuntimeInit_nativeZygoteInit },
    { "nativeSetExitWithoutCleanup", "(Z)V",
        (void*) com_android_internal_os_RuntimeInit_nativeSetExitWithoutCleanup },
};

通過JNI的gMethods陣列,可以看出nativeZygoteInit函式對應的是JNI檔案AndroidRuntime.cpp的com_android_internal_os_RuntimeInit_nativeZygoteInit函式:

...
static AndroidRuntime* gCurRuntime = NULL;
...
static void com_android_internal_os_RuntimeInit_nativeZygoteInit(JNIEnv* env, jobject clazz)
{
    gCurRuntime->onZygoteInit();
}

這裡gCurRuntime是AndroidRuntime型別的指標,AndroidRuntime的子類AppRuntime在app_main.cpp中定義,我們來檢視AppRuntime的onZygoteInit函式,程式碼如下所示。frameworks/base/cmds/app_process/app_main.cpp

virtual void onZygoteInit()
   {
       sp<ProcessState> proc = ProcessState::self();
       ALOGV("App process: starting thread pool.\n");
       proc->startThreadPool();//1
   }

註釋1處的程式碼用來啟動一個Binder執行緒池,這樣SyetemServer程序就可以使用Binder來與其他程序進行通訊了。看到這裡我們知道RuntimeInit.java的nativeZygoteInit函式主要做的就是啟動Binder執行緒池。

invokeStaticMain

我們再回到RuntimeInit.java的程式碼,在註釋2處呼叫了applicationInit函式,程式碼如下所示。

frameworks/base/core/java/com/android/internal/os/RuntimeInit.java

  private static void applicationInit(int targetSdkVersion, String[] argv, ClassLoader classLoader)
            throws ZygoteInit.MethodAndArgsCaller {
...
        invokeStaticMain(args.startClass, args.startArgs, classLoader);
    }

applicationInit函式中主要呼叫了invokeStaticMain函式:

private static void invokeStaticMain(String className, String[] argv, ClassLoader classLoader)
         throws ZygoteInit.MethodAndArgsCaller {
     Class<?> cl;
     try {
         cl = Class.forName(className, true, classLoader);//1
     } catch (ClassNotFoundException ex) {
         throw new RuntimeException(
                 "Missing class when invoking static main " + className,
                 ex);
     }
     Method m;
     try {
         m = cl.getMethod("main", new Class[] { String[].class });//2
     } catch (NoSuchMethodException ex) {
         throw new RuntimeException(
                 "Missing static main on " + className, ex);
     } catch (SecurityException ex) {
         throw new RuntimeException(
                 "Problem getting static main on " + className, ex);
     }
     int modifiers = m.getModifiers();
     if (! (Modifier.isStatic(modifiers) && Modifier.isPublic(modifiers))) {
         throw new RuntimeException(
                 "Main method is not public and static on " + className);
     }
     throw new ZygoteInit.MethodAndArgsCaller(m, argv);//3
 }

註釋1處className為“com.android.server.SystemServer”,因此通過反射返回的cl為SystemServer類。註釋2處找到SystemServer中的main函式。在註釋3處將找到的main函式傳入到MethodAndArgsCaller異常中並丟擲該異常。截獲MethodAndArgsCaller異常的程式碼在ZygoteInit.java的main函式中,如下所示。

frameworks/base/core/java/com/android/internal/os/ZygoteInit.java

public static void main(String argv[]) {
     ...
          closeServerSocket();
      } catch (MethodAndArgsCaller caller) {
          caller.run();//1
      } catch (RuntimeException ex) {
          Log.e(TAG, "Zygote died with exception", ex);
          closeServerSocket();
          throw ex;
      }
  }

在註釋1處呼叫了MethodAndArgsCaller的run函式:

   public void run() {
        try {
            mMethod.invoke(null, new Object[] { mArgs });
        } catch (IllegalAccessException ex) {
         ...
        }
    }
}

這裡mMethod指的就是SystemServer的main函式,因此main函式被動態呼叫。

3.解析SyetemServer程序

我們先來檢視SystemServer的main函式:frameworks/base/services/java/com/android/server/SystemServer.java

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

main函式中只調用了SystemServer的run函式,如下所示。

private void run() {
       ...
           System.loadLibrary("android_servers");//1
       ...
           mSystemServiceManager = new SystemServiceManager(mSystemContext);//2
           LocalServices.addService(SystemServiceManager.class, mSystemServiceManager);
       ...    
        try {
           Trace.traceBegin(Trace.TRACE_TAG_SYSTEM_SERVER, "StartServices");
           startBootstrapServices();//3
           startCoreServices();//4
           startOtherServices();//5
       } catch (Throwable ex) {
           Slog.e("System", "******************************************");
           Slog.e("System", "************ Failure starting system services", ex);
           throw ex;
       } finally {
           Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
       }
       ...
   }

run函式程式碼很多,關鍵就是在註釋1處載入了libandroid_servers.so。接下來在註釋2處建立SystemServiceManager,它會對系統的服務進行建立、啟動和生命週期管理。啟動系統的各種服務,在註釋3中的startBootstrapServices函式中用SystemServiceManager啟動了ActivityManagerService、PowerManagerService、PackageManagerService等服務。在註釋4處的函式中則啟動了BatteryService、UsageStatsService和WebViewUpdateService。註釋5處的startOtherServices函式中則啟動了CameraService、AlarmManagerService、VrManagerService等服務,這些服務的父類為SystemService。從註釋3、4、5的函式可以看出,官方把系統服務分為了三種類型,分別是引導服務、核心服務和其他服務,其中其他服務為一些非緊要和一些不需要立即啟動的服務。系統服務大約有80多個,這裡列出部分系統服務以及它們的作用如下表所示:

引導服務 作用
Installer 系統安裝apk時的一個服務類,啟動完成Installer服務之後才能啟動其他的系統服務
ActivityManagerService 負責四大元件的啟動、切換、排程。
PowerManagerService 計算系統中和Power相關的計算,然後決策系統應該如何反應
LightsService 管理和顯示背光LED
DisplayManagerService 用來管理所有顯示裝置
UserManagerService 多使用者模式管理
SensorService 為系統提供各種感應器服務
PackageManagerService 用來對apk進行安裝、解析、刪除、解除安裝等等操作
核心服務
BatteryService 管理電池相關的服務
UsageStatsService 收集使用者使用每一個APP的頻率、使用時常
WebViewUpdateService WebView更新服務
其他服務
CameraService 攝像頭相關服務
AlarmManagerService 全域性定時器管理服務
InputManagerService 管理輸入事件
WindowManagerService 視窗管理服務
VrManagerService VR模式管理服務
BluetoothService 藍芽管理服務
NotificationManagerService 通知管理服務
DeviceStorageMonitorService 儲存相關管理服務
LocationManagerService 定位管理服務
AudioService 音訊相關管理服務
….

比如要啟動PowerManagerService則會呼叫如下程式碼:

mPowerManagerService = mSystemServiceManager.startService(PowerManagerService.class);

SystemServiceManager的startService函式啟動了PowerManagerService,startService函式如下所示。

frameworks/base/services/core/java/com/android/server/SystemServiceManager.java

  public <T extends SystemService> T startService(Class<T> serviceClass) {
  ...
            final T service;
            try {
                Constructor<T> constructor = serviceClass.getConstructor(Context.class);
                service = constructor.newInstance(mContext);//1
            } catch (InstantiationException ex) {
                throw new RuntimeException("Failed to create service " + name
                        + ": service could not be instantiated", ex);
            }
...
            // Register it.
            mServices.add(service);//2
            // Start it.
            try {
                service.onStart();
            } catch (RuntimeException ex) {
                throw new RuntimeException("Failed to start service " + name
                        + ": onStart threw an exception", ex);
            }
            return service;
        } finally {
            Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
        }
    }

註釋1處的程式碼用來建立SystemService,這裡的SystemService是PowerManagerService,在註釋2處將PowerManagerService新增到mServices中,這裡mServices是一個儲存SystemService型別的ArrayList。接著呼叫PowerManagerService的onStart函式啟動PowerManagerService並返回,這樣就完成了PowerManagerService啟動的過程。 除了用mSystemServiceManager的startService函式來啟動系統服務外,也可以通過如下形式來啟動系統服務,以PackageManagerService為例:

mPackageManagerService = PackageManagerService.main(mSystemContext, installer,
               mFactoryTestMode != FactoryTest.FACTORY_TEST_OFF, mOnlyCore);

直接呼叫了PackageManagerService的main函式:frameworks/base/services/core/java/com/android/server/pm/PackageManagerService.java

public static PackageManagerService main(Context context, Installer installer,
        boolean factoryTest, boolean onlyCore) {
    // Self-check for initial settings.
    PackageManagerServiceCompilerMapping.checkProperties();
    PackageManagerService m = new PackageManagerService(context, installer,
            factoryTest, onlyCore);//1
    m.enableSystemUserPackages();
    // Disable any carrier apps. We do this very early in boot to prevent the apps from being
    // disabled after already being started.
    CarrierAppUtils.disableCarrierAppsUntilPrivileged(context.getOpPackageName(), m,
            UserHandle.USER_SYSTEM);
    ServiceManager.addService("package", m);//2
    return m;
}

註釋1處直接建立PackageManagerService並在註釋2處將PackageManagerService註冊到ServiceManager中,ServiceManager用來管理系統中的各種Service,用於系統C/S架構中的Binder機制通訊:Client端要使用某個Service,則需要先到ServiceManager查詢Service的相關資訊,然後根據Service的相關資訊與Service所在的Server程序建立通訊通路,這樣Client端就可以使用Service了。還有的服務是直接註冊到ServiceManager中的,如下所示。

frameworks/base/services/java/com/android/server/SystemServer.java

telephonyRegistry = new TelephonyRegistry(context);
ServiceManager.addService("telephony.registry", telephonyRegistry);

4.總結SyetemServer程序

SyetemServer在啟動時做了如下工作: 1.啟動Binder執行緒池,這樣就可以與其他程序進行通訊。 2.建立SystemServiceManager用於對系統的服務進行建立、啟動和生命週期管理。 3.啟動各種系統服務。