[日更-2019.4.22、23、24] cm-14.1 Android系统启动过程分析(三)-SystemServer进程启动过程...
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. * * Current recognized args: *
* -
[--] <start class name> <args> *
* * @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 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 exit return; } // 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 startup Trace.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 Exception implements 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.cpp if (!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/11463182 SystemProperties.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() { @Override public 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_server BinderInternal.setMaxThreads(sMaxBinderThreads); // Prepare the main looper thread (this thread). android.os.Process.setThreadPriority( android.os.Process.THREAD_PRIORITY_FOREGROUND); android.os.Process.setCanSelfBackground(false); //创建消息Looper Looper.prepareMainLooper(); // Initialize native services. //加载动态库libandroid_servers.so System.loadLibrary("android_servers"); // Check whether we failed to shut down last time we tried. // This call may not return. performPendingShutdown(); // Initialize the system context. //创建系统的Context createSystemContext(); // 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 startService(Class 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 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的启动过程
转载于:https://my.oschina.net/XiaoMaPedro/blog/3043293
更多相关文章
- Android下引用系统库的方法及问题
- Android 系统 目录 分析
- Android系统的Binder机制之一——Service Manager
- 安卓系统结构
- 关于Zipalign的介绍和使用方法
- [置顶] 深入浅出 - Android系统移植与平台开发(四)- 搭建Linux编译
- Android测试方法总结