2019独角兽企业重金招聘Python工程师标准>>>
声明
- 前阶段在项目中涉及到了Android系统定制任务,Android系统定制前提要知道Android系统是如何启动的。
- 本文参考了一些书籍的若干章节,比如《Android进阶解密-第2章-Android系统启动》、《深入理解Android虚拟机-第8/9/10章-init进程详解/Dalvik VM的进程系统/Dalvik VM运作流程详解》、《深入理解Android系统-第6/7/8章-init启动进程详解/Zygote进程详解/System进程详解》等
- 本文使用的代码是LineageOS的cm-14.1,对应Android 7.1.2,可以参考我的另一篇博客:如何下载Nexus5的LineageOS14.1(cm-14.1)系统源码并编译、刷机
- 很多代码注释待详细写
0 写在前面的
在上一篇《[日更-2019.4.20、21] cm-14.1 Android系统启动过程分析(二)-Zygote进程启动过程》的第3.2节启动了SystemServer,Zygote让SystemServer启动是为了让它去创建Android的系统服务:AMS、WMS、PMS等。
Zygote启动SystemServer的时序图(盗一张图)
1 Zygote进程启动SystemServer
分析startSystemServer方法最终调用的方法handleSystemServerProcess,源码目录为:~/LineageOS/frameworks/base/core/java/com/android/internal/os/ZygoteInit.java中:
/*** Finish remaining work for the newly forked system server process.*/private static void handleSystemServerProcess(ZygoteConnection.Arguments parsedArgs)throws ZygoteInit.MethodAndArgsCaller {//关闭Zygote进程创建的Socket(SystemServer进程是由Zygote进程fork而来,所以拥有Zygote进程的地址空间,//因此也会得到Zygote进程创建的Socket,这个Socket对SystemServer进程没用,所以要关闭它);closeServerSocket();// set umask to 0077 so new files and directories will default to owner-only permissions.Os.umask(S_IRWXG | S_IRWXO);if (parsedArgs.niceName != null) {Process.setArgV0(parsedArgs.niceName);}final String systemServerClasspath = Os.getenv("SYSTEMSERVERCLASSPATH");if (systemServerClasspath != null) {performSystemServerDexOpt(systemServerClasspath);}if (parsedArgs.invokeWith != null) {String[] args = parsedArgs.remainingArgs;// If we have a non-null system server class path, we'll have to duplicate the// existing arguments and append the classpath to it. ART will handle the classpath// correctly when we exec a new process.if (systemServerClasspath != null) {String[] amendedArgs = new String[args.length + 2];amendedArgs[0] = "-cp";amendedArgs[1] = systemServerClasspath;System.arraycopy(parsedArgs.remainingArgs, 0, amendedArgs, 2, parsedArgs.remainingArgs.length);}WrapperInit.execApplication(parsedArgs.invokeWith,parsedArgs.niceName, parsedArgs.targetSdkVersion,VMRuntime.getCurrentInstructionSet(), null, args);} else {ClassLoader cl = null;if (systemServerClasspath != null) {//创建了PathClassLoader,关于它将在后面介绍ClassLoader时分析;cl = createSystemServerClassLoader(systemServerClasspath,parsedArgs.targetSdkVersion);Thread.currentThread().setContextClassLoader(cl);}/** Pass the remaining arguments to SystemServer.* 调用ZygoteInit的zygoteinit方法;*/RuntimeInit.zygoteInit(parsedArgs.targetSdkVersion, parsedArgs.remainingArgs, cl);}/* should never reach here */}
分析zygoteinit方法,源码目录为:~/LineageOS/frameworks/base/core/java/com/android/internal/os/RuntimeInit.java中:
/*** The main function called when started through the zygote process. This* could be unified with main(), if the native code in nativeFinishInit()* were rationalized with Zygote startup.<p>** Current recognized args:* <ul>* <li> <code> [--] <start class name> <args>* </ul>** @param targetSdkVersion target SDK version* @param argv arg strings*/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();//1-1 调用Native层方法启动Binder线程池,这样SystemServer进程就可以使用Binder与其他进程进行通信了;nativeZygoteInit();//1.2 进入SystemServer的main方法applicationInit(targetSdkVersion, argv, classLoader);}
1.1 如何启动Binder线程池
在代码注释1-1处nativeZygoteInit方法是RuntimeInit.java的一个Native方法,其对应的Native层的JNI函数为com_android_internal_os_RuntimeInit_nativeZygoteInit函数,源码目录:~/LineageOS/frameworks/base/core/jni/AndroidRuntime.cpp中
static void com_android_internal_os_RuntimeInit_nativeZygoteInit(JNIEnv* env, jobject clazz)
{gCurRuntime->onZygoteInit();
}
其中,gCurRuntime为AndroidRuntime类型的指针,具体是AndroidRuntime类型的子类AppRuntime,其定义在源码目录:~/LineageOS/frameworks/base/cmds/app_process/app_main.cpp中
virtual void onZygoteInit(){sp<ProcessState> proc = ProcessState::self();ALOGV("App process: starting thread pool.\n");//1-1-1 启动一个Binder线程池,proc->startThreadPool();}
1.2 如何进入SystemServer的main方法
在代码注释1-2处调用了RuntimeInit的applicationInit方法,该方法在源码目录:~/LineageOS/frameworks/base/core/java/com/android/internal/os/RuntimeInit.java中:
private static void applicationInit(int targetSdkVersion, String[] argv, ClassLoader classLoader)throws ZygoteInit.MethodAndArgsCaller {// If the application calls System.exit(), terminate the process// immediately without running any shutdown hooks. It is not possible to// shutdown an Android application gracefully. Among other things, the// Android runtime shutdown hooks close the Binder driver, which can cause// leftover running threads to crash before the process actually exits.nativeSetExitWithoutCleanup(true);// We want to be fairly aggressive about heap utilization, to avoid// holding on to a lot of memory that isn't needed.VMRuntime.getRuntime().setTargetHeapUtilization(0.75f);VMRuntime.getRuntime().setTargetSdkVersion(targetSdkVersion);final Arguments args;try {args = new Arguments(argv);} catch (IllegalArgumentException ex) {Slog.e(TAG, ex.getMessage());// let the process exitreturn;}// The end of of the RuntimeInit event (see #zygoteInit).Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);// Remaining arguments are passed to the start class's static main//1-2-1 application方法中主要调用了invokeStaticMain方法;invokeStaticMain(args.startClass, args.startArgs, classLoader);}
在代码注释1-2处调用了invokeStaticMain方法,在源码目录:~/LineageOS/frameworks/base/core/java/com/android/internal/os/RuntimeInit.java中
/*** Invokes a static "main(argv[]) method on class "className".* Converts various failing exceptions into RuntimeExceptions, with* the assumption that they will then cause the VM instance to exit.** @param className Fully-qualified class name* @param argv Argument vector for main()* @param classLoader the classLoader to load {@className} with*/private static void invokeStaticMain(String className, String[] argv, ClassLoader classLoader)throws ZygoteInit.MethodAndArgsCaller {Class<?> cl;try {//1-2-2 通过反射得到SystemServer类,ClassName为com.android.server.SystemServer,返回的的cl为SystemServer类;cl = Class.forName(className, true, classLoader);} catch (ClassNotFoundException ex) {throw new RuntimeException("Missing class when invoking static main " + className,ex);}Method m;try {//1-2-3 找到SystemServer的main方法;m = cl.getMethod("main", new Class[] { String[].class });} 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);}/** This throw gets caught in ZygoteInit.main(), which responds* by invoking the exception's run() method. This arrangement* clears up all the stack frames that were required in setting* up the process.*///1-2-4 将找到的main函数传入到MethodAndArgsCaller异常中并抛出该异常(截获MethodAndArgsCaller异常的代码在ZygoteInit.java的main函数中)throw new ZygoteInit.MethodAndArgsCaller(m, argv);}
在代码注释1-2-4 处截获MethodAndArgsCaller异常的代码在ZygoteInit.java的main函数中,这个main方法会调用SystemServer的main方法,源码目录:~/LineageOS/frameworks/base/core/java/com/android/internal/os/ZygoteInit.java中:
public static void main(String argv[]) {// Mark zygote start. This ensures that thread creation will throw// an error.ZygoteHooks.startZygoteNoThreadCreation();try {Trace.traceBegin(Trace.TRACE_TAG_DALVIK, "ZygoteInit");RuntimeInit.enableDdms();// Start profiling the zygote initialization.SamplingProfilerIntegration.start();boolean startSystemServer = false;String socketName = "zygote";String abiList = null;for (int i = 1; i < argv.length; i++) {if ("start-system-server".equals(argv[i])) {startSystemServer = true;} else if (argv[i].startsWith(ABI_LIST_ARG)) {abiList = argv[i].substring(ABI_LIST_ARG.length());} else if (argv[i].startsWith(SOCKET_NAME_ARG)) {socketName = argv[i].substring(SOCKET_NAME_ARG.length());} else {throw new RuntimeException("Unknown command line argument: " + argv[i]);}}if (abiList == null) {throw new RuntimeException("No ABI list supplied.");}registerZygoteSocket(socketName);Trace.traceBegin(Trace.TRACE_TAG_DALVIK, "ZygotePreload");EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_START,SystemClock.uptimeMillis());preload();EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_END,SystemClock.uptimeMillis());Trace.traceEnd(Trace.TRACE_TAG_DALVIK);// Finish profiling the zygote initialization.SamplingProfilerIntegration.writeZygoteSnapshot();// Do an initial gc to clean up after startupTrace.traceBegin(Trace.TRACE_TAG_DALVIK, "PostZygoteInitGC");gcAndFinalize();Trace.traceEnd(Trace.TRACE_TAG_DALVIK);Trace.traceEnd(Trace.TRACE_TAG_DALVIK);// Disable tracing so that forked processes do not inherit stale tracing tags from// Zygote.Trace.setTracingEnabled(false);// Zygote process unmounts root storage spaces.Zygote.nativeUnmountStorageOnInit();ZygoteHooks.stopZygoteNoThreadCreation();if (startSystemServer) {startSystemServer(abiList, socketName);}Log.i(TAG, "Accepting command socket connections");runSelectLoop(abiList);closeServerSocket();} catch (MethodAndArgsCaller caller) {//1-2-5 捕获到MethodAndArgsCaller异常时调用MethodAndArgsCaller的run方法,MethodAndArgsCaller是ZygoteInit.java的静态内部类;caller.run();} catch (Throwable ex) {Log.e(TAG, "Zygote died with exception", ex);closeServerSocket();throw ex;}}
在代码注释1-2-5 处的MethodAndArgsCaller是ZygoteInit.java的内部类:
/*** Helper exception class which holds a method and arguments and* can call them. This is used as part of a trampoline to get rid of* the initial process setup stack frames.*/public static class MethodAndArgsCaller extends Exceptionimplements Runnable {/** method to call */private final Method mMethod;/** argument array */private final String[] mArgs;public MethodAndArgsCaller(Method method, String[] args) {mMethod = method;mArgs = args;}public void run() {try {//其中mMethod指的是SystemServer的main方法,调用了mMethod的invoke方法后,SystemServer的main方法就会被动态调用,SystemServer进程就进入了SystemServer的main方法中了;mMethod.invoke(null, new Object[] { mArgs });} catch (IllegalAccessException ex) {throw new RuntimeException(ex);} catch (InvocationTargetException ex) {Throwable cause = ex.getCause();if (cause instanceof RuntimeException) {throw (RuntimeException) cause;} else if (cause instanceof Error) {throw (Error) cause;}throw new RuntimeException(ex);}}}
有一个疑问了在代码注释1-2-4为什么要以这种抛出异常的形式代用SystemServer的main方法呢?
因为这种抛出异常的处理会清除所有的设置过程需要的堆栈帧,而让SystemServer的main方法看起来像是SystemServer进程的入口方法。在Zygote启动了SystemServer后,SystemServer进程已经做了很多准备工作,而这些工作都是在SystemServer的main方法调用之前做的,这使得SystemServer的main方法看起来不像是SystemServer进程的入口方法,而这种抛出异常交给ZygoteInit.java的main方法处理,会让SystemServer的main方法看起来像是SystemServer进程的入口方法;(可以参考下图)
Zygote启动SystemServer的时序图(盗一张图)
2 SystemServer进程都做了什么?
进入源码目录:~/LineageOS/frameworks/base/services/java/com/android/server/SystemServer.java中查看SystemServer的main方法:
/*** The main entry point from zygote.*/public static void main(String[] args) {//main方法中只调用了SystemServer的main方法;new SystemServer().run();}
private void run() {try {Trace.traceBegin(Trace.TRACE_TAG_SYSTEM_SERVER, "InitBeforeStartServices");// If a device's clock is before 1970 (before 0), a lot of// APIs crash dealing with negative numbers, notably// java.io.File#setLastModified, so instead we fake it and// hope that time from cell towers or NTP fixes it shortly.if (System.currentTimeMillis() < EARLIEST_SUPPORTED_TIME) {Slog.w(TAG, "System clock is before 1970; setting to 1970.");SystemClock.setCurrentTimeMillis(EARLIEST_SUPPORTED_TIME);}// If the system has "persist.sys.language" and friends set, replace them with// "persist.sys.locale". Note that the default locale at this point is calculated// using the "-Duser.locale" command line flag. That flag is usually populated by// AndroidRuntime using the same set of system properties, but only the system_server// and system apps are allowed to set them.//// NOTE: Most changes made here will need an equivalent change to// core/jni/AndroidRuntime.cppif (!SystemProperties.get("persist.sys.language").isEmpty()) {final String languageTag = Locale.getDefault().toLanguageTag();SystemProperties.set("persist.sys.locale", languageTag);SystemProperties.set("persist.sys.language", "");SystemProperties.set("persist.sys.country", "");SystemProperties.set("persist.sys.localevar", "");}// Here we go!Slog.i(TAG, "Entered the Android system server!");EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_SYSTEM_RUN, SystemClock.uptimeMillis());// In case the runtime switched since last boot (such as when// the old runtime was removed in an OTA), set the system// property so that it is in sync. We can't do this in// libnativehelper's JniInvocation::Init code where we already// had to fallback to a different runtime because it is// running as root and we need to be the system user to set// the property. http://b/11463182SystemProperties.set("persist.sys.dalvik.vm.lib.2", VMRuntime.getRuntime().vmLibrary());// Enable the sampling profiler.if (SamplingProfilerIntegration.isEnabled()) {SamplingProfilerIntegration.start();mProfilerSnapshotTimer = new Timer();mProfilerSnapshotTimer.schedule(new TimerTask() {@Overridepublic void run() {SamplingProfilerIntegration.writeSnapshot("system_server", null);}}, SNAPSHOT_INTERVAL, SNAPSHOT_INTERVAL);}// Mmmmmm... more memory!VMRuntime.getRuntime().clearGrowthLimit();// The system server has to run all of the time, so it needs to be// as efficient as possible with its memory usage.VMRuntime.getRuntime().setTargetHeapUtilization(0.8f);// Some devices rely on runtime fingerprint generation, so make sure// we've defined it before booting further.Build.ensureFingerprintProperty();// Within the system server, it is an error to access Environment paths without// explicitly specifying a user.Environment.setUserRequired(true);// Within the system server, any incoming Bundles should be defused// to avoid throwing BadParcelableException.BaseBundle.setShouldDefuse(true);// Ensure binder calls into the system always run at foreground priority.BinderInternal.disableBackgroundScheduling(true);// Increase the number of binder threads in system_serverBinderInternal.setMaxThreads(sMaxBinderThreads);// Prepare the main looper thread (this thread).android.os.Process.setThreadPriority(android.os.Process.THREAD_PRIORITY_FOREGROUND);android.os.Process.setCanSelfBackground(false);//创建消息LooperLooper.prepareMainLooper();// Initialize native services.//加载动态库libandroid_servers.soSystem.loadLibrary("android_servers");// Check whether we failed to shut down last time we tried.// This call may not return.performPendingShutdown();// Initialize the system context.//创建系统的ContextcreateSystemContext();// Create the system service manager.//创建SystemServiceManager对系统服务进行创建、启动、生命周期管理;mSystemServiceManager = new SystemServiceManager(mSystemContext);mSystemServiceManager.setRuntimeRestarted(mRuntimeRestart);LocalServices.addService(SystemServiceManager.class, mSystemServiceManager);} finally {Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);}// Start services.try {Trace.traceBegin(Trace.TRACE_TAG_SYSTEM_SERVER, "StartServices");//启动引导服务;startBootstrapServices();//启动核心服务;startCoreServices();//启动其他服务,其他服务是一些非必须或不需要立即启动的服务;startOtherServices();} catch (Throwable ex) {Slog.e("System", "******************************************");Slog.e("System", "************ Failure starting system services", ex);throw ex;} finally {Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);}// For debug builds, log event loop stalls to dropbox for analysis.if (StrictMode.conditionallyEnableDebugLogging()) {Slog.i(TAG, "Enabled StrictMode for system server main thread.");}// Loop forever.Looper.loop();throw new RuntimeException("Main thread loop unexpectedly exited");}
参考文章:Android 系统服务一览表
cm14-1 引导服务 | 作用 |
---|---|
Installer | 系统安装APK时的一个服务类,启动完成Installer服务之后才能启动其他系统服务 |
ActivityManagerService | Android framework框架核心服务,管理整个框架中任务、进程管理, Intent解析等的核心实现,管理四大组建的生命周期。 |
PowerManagerService | 电源管理服务 |
LightsService | 光感应传感器服务 |
DisplayManagerService | 用于管理全局显示生命周期,决定在已连接的物理设备如何配置逻辑显示,并且通知系统和应用状态的改变 |
UserManagerService | 多用户模式管理 |
SensorService | 为系统提供各种感应服务 |
PackageManagerService | 用来对APK进行安装、解析、删除、卸载等操作 |
... | ... |
cm14-1 核心服务 | 作用 |
---|---|
BatteryService | 管理电池相关系统服务 |
UsageStatsService | 收集用户使用的每个App的频率及时长 |
WebViewUpdateService | WebView更新服务 |
cm14-1 其他服务 | 作用 |
---|---|
VibratorService | 振动器服务 |
NetworkStatsService | 网络统计相关 |
NetworkPolicyManagerService | 维护网络使用策略 |
ConnectivityService | 网络连接状态服务 |
NsdService | 网络服务搜索 |
WindowManagerService | Android framework框架核心服务,窗口管理服务 |
SerialService | 对串口的设备进行操作 |
NetworkTimeUpdateService | 监视网络时间,当网络时间变化时更新本地时间 |
CommonTimeManagementService | 管理本地常见的时间服务的配置,在网络配置变化时重新配置本地服务 |
InputManagerService | 以前在WindowManagerService中,现在独立了出来,用户处理事件分发 |
ConsumerIrService | 远程控制,通过红外等控制周围的设备(例如电视等) |
CameraService | 摄像头相关服务 |
AlarmManagerService | 全局定时器管理服务 |
LocationManagerService | 定位管理服务 |
AudioService | 音频相关管理服务 |
... | ... |
2.1 利用SystemServiceManager的startService方法启动
这些系统服务的启动逻辑是相似的,以DisplayManagerService为例分析,其代码为:
// Display manager is needed to provide display metrics before package manager// starts up.mDisplayManagerService = mSystemServiceManager.startService(DisplayManagerService.class);
SystemServiceManager的startService方法启动了DisplayManagerService,其在源码目录:~/LineageOS/frameworks/base/services/core/java/com/android/server /SystemServiceManager.java
/*** Creates and starts a system service. The class must be a subclass of* {@link com.android.server.SystemService}.** @param serviceClass A Java class that implements the SystemService interface.* @return The service instance, never null.* @throws RuntimeException if the service fails to start.*/@SuppressWarnings("unchecked")public <T extends SystemService> T startService(Class<T> serviceClass) {try {final String name = serviceClass.getName();Slog.i(TAG, "Starting " + name);Trace.traceBegin(Trace.TRACE_TAG_SYSTEM_SERVER, "StartService " + name);// Create the service.if (!SystemService.class.isAssignableFrom(serviceClass)) {throw new RuntimeException("Failed to create " + name+ ": service must extend " + SystemService.class.getName());}final T service;try {Constructor<T> constructor = serviceClass.getConstructor(Context.class);service = constructor.newInstance(mContext);} catch (InstantiationException ex) {throw new RuntimeException("Failed to create service " + name+ ": service could not be instantiated", ex);} catch (IllegalAccessException ex) {throw new RuntimeException("Failed to create service " + name+ ": service must have a public constructor with a Context argument", ex);} catch (NoSuchMethodException ex) {throw new RuntimeException("Failed to create service " + name+ ": service must have a public constructor with a Context argument", ex);} catch (InvocationTargetException ex) {throw new RuntimeException("Failed to create service " + name+ ": service constructor threw an exception", ex);}// 注册Service,mServices是一个存储SystemService类型的ArrayList;mServices.add(service);// Start it.try {//启动Service,调用PowerManagerService的onStart方法完成启动PowerManagerService;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);}}
2.2 利用Service自身main方法启动
以PancakeManagerService为例:
// Start the package manager.traceBeginAndSlog("StartPackageManagerService");//直接调用PackageManagerService的main方法;mPackageManagerService = PackageManagerService.main(mSystemContext, installer,mFactoryTestMode != FactoryTest.FACTORY_TEST_OFF, mOnlyCore);mFirstBoot = mPackageManagerService.isFirstBoot();mPackageManager = mSystemContext.getPackageManager();Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
其main方法在源码目录:~/LineageOS/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();//先将Package管理服务PackageManagerService启动起来;PackageManagerService m = new PackageManagerService(context, installer,factoryTest, onlyCore);m.enableSystemUserPackages();//将该Package管理服务注册到ServiceManager中,这样其它组件就可以通过ServiceManager来获取它的访问接口了,ServiceManager用来管理系统中各种Service,用于系统C/S架构中的Binder通信机制;ServiceManager.addService("package", m);return m;}
2.3 SystemServer进程小结
SystemServer进程被Zygote创建后的主要用来:
- 启动Binder线程池,这样就可与其他进程通信;
- 创建SystemServiceManager,用于对系统的服务进行创建、启动、生命周期的管理;
- 启动各种系统服务(引导服务、核心服务、其他服务);
Enjoy it !!
下一篇分析下Launcher的启动过程