您的位置:首页 > 移动开发 > Android开发

源码分析Android SystemServer进程的启动过程

2015-10-30 18:31 776 查看
最近复习了柯元旦老师的《Android内核剖析》,获益良多。所以想从自己的钻研出发,走一遍柯老师走过的路。我看的《Android内核剖析》版本是基于Android2.3系统来写的,因为我尝试从Android5.1系统再钻研一遍书籍中所钻研过的知识点。

本文将尝试从源码分析SystemServer进程的启动过程,Ams,Wms及其他常用到的服务的创建,以及打开第三方应用的启动过程。

一、SystemServer进程的启动

SystemServer听名字就知道是个非常重要的进程,它是Android Framework启动后fork的第一个进程,可见其重要性。那么该进程在跑什么东西呢?主要是一些系统服务,例如我们常听说的Ams(ActivityManagerService)和Wms(WindowManagerService)。

SystemServer的启动入口在ZygoteInit.java的main函数中。ZygoteInit是Zygote进程加载的第一个类,Zygote进程则是所有Apk应用进程的父进程,所有应用进程都是由Zygote进程fork出来。

从源码开始着手,我们只关心SystemServer相关的部分,ZygoteInit.java:

public static void main(String argv[]) {
try {
// 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 (startSystemServer) {
startSystemServer(abiList, socketName);           ②
}

...
} catch (MethodAndArgsCaller caller) {
caller.run();
} catch (RuntimeException ex) {
Log.e(TAG, "Zygote died with exception", ex);
closeServerSocket();
throw ex;
}
}


先看看main函数的参数,它的参数来自启动Zygote的命令,该命令在于系统根目录下的init.rc文件中,其中有一行是:

service zygote /system/bin/app_process -Xzygote /system/bin --zygote -- start-system-server


该行的意思是调用/system/bin/下的app_process命令(或工具),并且后面一串就是其主要参数。

该命令的源码在/frameworks/base/cmds/app_process/app_main.cpp里,我们跟进去看看主要部分:

int main(int argc, char* const argv[])
{
...

// Parse runtime arguments.  Stop at first unrecognized option.
bool zygote = false;
bool startSystemServer = false;
bool application = false;
String8 niceName;
String8 className;

++i;  // Skip unused "parent dir" argument.
while (i < argc) {
const char* arg = argv[i++];
if (strcmp(arg, "--zygote") == 0) {
zygote = true;
niceName = ZYGOTE_NICE_NAME;
} else if (strcmp(arg, "--start-system-server") == 0) {
startSystemServer = true;        ①
} else if (strcmp(arg, "--application") == 0) {
application = true;
} else if (strncmp(arg, "--nice-name=", 12) == 0) {
niceName.setTo(arg + 12);
} else if (strncmp(arg, "--", 2) != 0) {
className.setTo(arg);
break;
} else {
--i;
break;
}
}

Vector<String8> args;
if (!className.isEmpty()) {
// We're not in zygote mode, the only argument we need to pass
// to RuntimeInit is the application argument.
//
// The Remainder of args get passed to startup class main(). Make
// copies of them before we overwrite them with the process name.
args.add(application ? String8("application") : String8("tool"));
runtime.setClassNameAndArgs(className, argc - i, argv + i);
} else {
// We're in zygote mode.
maybeCreateDalvikCache();

if (startSystemServer) {
args.add(String8("start-system-server"));        ②
}

char prop[PROP_VALUE_MAX];
if (property_get(ABI_LIST_PROPERTY, prop, NULL) == 0) {
LOG_ALWAYS_FATAL("app_process: Unable to determine ABI list from property %s.",
ABI_LIST_PROPERTY);
return 11;
}

String8 abiFlag("--abi-list=");
abiFlag.append(prop);
args.add(abiFlag);

// In zygote mode, pass all remaining arguments to the zygote
// main() method.
for (; i < argc; ++i) {
args.add(String8(argv[i]));
}
}

if (!niceName.isEmpty()) {
runtime.setArgv0(niceName.string());
set_process_name(niceName.string());
}

if (zygote) {
runtime.start("com.android.internal.os.ZygoteInit", args);        ③
} else if (className) {
runtime.start("com.android.internal.os.RuntimeInit", args);
} else {
fprintf(stderr, "Error: no class name or --zygote supplied.\n");
app_usage();
LOG_ALWAYS_FATAL("app_process: no class name or --zygote supplied.");
return 10;
}
}


看上面标注①的地方:如果有参数是”–start-system-server”,那么变量startSystemServer被置为true,从我们调用的命令来看,这么为true;

标注②:如果startSystemServer为true,那么变量args将添加”start-system-server”这个字符串。我们从变量名args可以猜测到这个变量是保存一些启动参数的。

标注③:毫无疑问这里会启动”com.android.internal.os.ZygoteInit”这个类并且带有参数args,如果一来就会辗转到ZygoteInit的main函数里,并且带有args的参数。

OK,终于明白ZygoteInit的main函数的参数有什么东东,接下来回到该类的main方法里:

public static void main(String argv[]) {
try {
// 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 (startSystemServer) {
startSystemServer(abiList, socketName);           ②
}

...
} catch (MethodAndArgsCaller caller) {
caller.run();
} catch (RuntimeException ex) {
Log.e(TAG, "Zygote died with exception", ex);
closeServerSocket();
throw ex;
}
}


标注①:正如刚才分析的,这里的参数是含有”start-system-server”这个字符串,所以此处startSystemServer变量被置为true;

标注②:调用接口startSystemServer();

终于看到启动SystemServer的地方了:

/**
* Prepare the arguments and fork for the system server process.
*/
private static boolean startSystemServer(String abiList, String socketName)
throws MethodAndArgsCaller, RuntimeException {
...
/* Hardcoded command line to start the system server */
String args[] = {        ①
"--setuid=1000",
"--setgid=1000",
"--setgroups=1001,1002,1003,1004,1005,1006,1007,1008,1009,1010,1018,1032,3001,3002,3003,3006,3007",
"--capabilities=" + capabilities + "," + capabilities,
"--runtime-init",
"--nice-name=system_server",
"com.android.server.SystemServer",
};
ZygoteConnection.Arguments parsedArgs = null;

int pid;

try {
parsedArgs = new ZygoteConnection.Arguments(args);
ZygoteConnection.applyDebuggerSystemProperty(parsedArgs);
ZygoteConnection.applyInvokeWithSystemProperty(parsedArgs);

/* Request to fork the system server process */
pid = Zygote.forkSystemServer(        ②
parsedArgs.uid, parsedArgs.gid,
parsedArgs.gids,
parsedArgs.debugFlags,
null,
parsedArgs.permittedCapabilities,
parsedArgs.effectiveCapabilities);
} catch (IllegalArgumentException ex) {
throw new RuntimeException(ex);
}

/* For child process */
if (pid == 0) {
if (hasSecondZygote(abiList)) {
waitForSecondaryZygote(socketName);
}

handleSystemServerProcess(parsedArgs);        ③
}

return true;
}


标注①:为SystemServer创建一些启动参数,注意这个参数,后面启动会用到。并且从参数可以知道,SystemServer的uid是1000,gid是1000还有一些相关信息都被硬编码的方式编写在此。(一般情况每一个apk应用都有唯一一个uid,用于区分,系统服务如Ams也会根据uid来判断应用的权限,一般uid=1000及其他一些系统的uid程序拥有很多系统权限,uid=0代表root用户)

标注②:重头戏来了!调用Zygote.forkSystemServer()接口fork一个SystemServer进程。fork是linux系统创建子进程的重要方法,其作用是复制当前进程,创建一个新的进程,但是其进程id不相同。当该方法返回值等于0时,代表是创建的新进程。

跟踪进去Zygote.forkSystemServer()接口,发现其调用了JNI的native方法,所以不跟进去,大概流程就是创建了一个新的进程。

标注③:正如上面所说,返回值等于0代表是创建了新的进程,也就是子进程,此时将会调用handleSystemServerProcess()方法去完成SystemServer的创建。

再跟进去该方法:

/**
* Finish remaining work for the newly forked system server process.
*/
private static void handleSystemServerProcess(
ZygoteConnection.Arguments parsedArgs)
throws ZygoteInit.MethodAndArgsCaller {
...
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,
null, args);
} else {
...
}

/* should never reach here */
}


标注①:此处会调用WrapperInit.execApplication()方法,不断跟踪进去,会发现其最终调用的代码在于RuntimeInit类中:

RuntimeInit.java:

private static void invokeStaticMain(String className, String[] argv, ClassLoader classLoader)
throws ZygoteInit.MethodAndArgsCaller {
Class<?> cl;

try {
cl = Class.forName(className, true, classLoader);
} 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 });
} 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.
*/
throw new ZygoteInit.MethodAndArgsCaller(m, argv);
}


该方法的作用是反射调用你要创建的类的main方法。还记得上面创建SystemServer时有创建一堆参数,其最后一个参数是”com.android.server.SystemServer”。没错这个参数辗转最后会作为RuntimeInit.invokeStaticMain()方法的参数,所以这里会反射”com.android.server.SystemServer”该类,并执行其main函数,也就是创建了SystemServer进程后,执行其SystemServer类的main函数。

至此,SystemServer进程的启动过程已大致分析完成。

二、创建Ams、Wms等主要系统服务

这部分源码相对比较简单,主要就是SystemServer中调用的接口。

继续上部分的代码,这里会进入SystemServer的main函数:

/**
* The main entry point from zygote.
*/
public static void main(String[] args) {
new SystemServer().run();
}

public SystemServer() {
// Check for factory test mode.
mFactoryTestMode = FactoryTest.getMode();
}

private void run() {
// 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);
}

// 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);

// Ensure binder calls into the system always run at foreground priority.
BinderInternal.disableBackgroundScheduling(true);

// Prepare the main looper thread (this thread).
android.os.Process.setThreadPriority(
android.os.Process.THREAD_PRIORITY_FOREGROUND);
android.os.Process.setCanSelfBackground(false);
Looper.prepareMainLooper();        ①

// Initialize native services.
System.loadLibrary("android_servers");
nativeInit();        ②

// Check whether we failed to shut down last time we tried.
// This call may not return.
performPendingShutdown();

// Initialize the system context.
createSystemContext();         ③

// Create the system service manager.
mSystemServiceManager = new SystemServiceManager(mSystemContext);        ④
LocalServices.addService(SystemServiceManager.class, mSystemServiceManager);

// Start services.
try {
startBootstrapServices();         ⑤
startCoreServices();
startOtherServices();
} catch (Throwable ex) {
Slog.e("System", "******************************************");
Slog.e("System", "************ Failure starting system services", ex);
throw ex;
}

// 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");
}


标注①:准备主线程(也就是正在运行的线程)的Looper;

标注②:native调用,该方法的注释是Called to initialize native system services.

标注③:创建SystemServer的Context,后面继续分析;

标注④:创建SystemServiceManager,其作用就是创建并管理系统服务的生命周期;

标注⑤:

startBootstrapServices();

startCoreServices();

startOtherServices();

连续调用了三个接口,这三个接口正是创建了我们常见的各种系统服务,后面继续分析;

标注⑥:Looper开始循环,等待消息执行。

我们看看SystemServer的Context创建过程:

private void createSystemContext() {
ActivityThread activityThread = ActivityThread.systemMain();
mSystemContext = activityThread.getSystemContext();
mSystemContext.setTheme(android.R.style.Theme_DeviceDefault_Light_DarkActionBar);
}


调用了ActivityThread.systemMain():

public static ActivityThread systemMain() {
// The system process on low-memory devices do not get to use hardware
// accelerated drawing, since this can add too much overhead to the
// process.
if (!ActivityManager.isHighEndGfx()) {
HardwareRenderer.disable(true);
} else {
HardwareRenderer.enableForegroundTrimming();
}
ActivityThread thread = new ActivityThread();
thread.attach(true);
return thread;
}


从这里可以看出SystemServer与普通Apk程序的创建还是很不相同,SystemServer的ActivityThread 是通过ActivityThread 的静态方法systemMain()创建,做了一些简单处理如设置无硬件加速等。不过同样的,其最终还是会调用attach方法,不同的是,普通apk程序调用的是attch(false),那么创建过程肯定也会大不一样。这里就不分析了,继续代码。

mSystemContext = activityThread.getSystemContext()会调用getSystemContext方法,然后里面又会调用ContextImpl.createSystemContext的方法:

static ContextImpl createSystemContext(ActivityThread mainThread) {
LoadedApk packageInfo = new LoadedApk(mainThread);
ContextImpl context = new ContextImpl(null, mainThread,
packageInfo, null, null, false, null, null);
context.mResources.updateConfiguration(context.mResourcesManager.getConfiguration(),
context.mResourcesManager.getDisplayMetricsLocked(Display.DEFAULT_DISPLAY));
return context;
}


对比创建Activity的Context,发现会有一些不同:

static ContextImpl createActivityContext(ActivityThread mainThread,
LoadedApk packageInfo, IBinder activityToken) {
if (packageInfo == null) throw new IllegalArgumentException("packageInfo");
if (activityToken == null) throw new IllegalArgumentException("activityInfo");
return new ContextImpl(null, mainThread,
packageInfo, activityToken, null, false, null, null);
}


其不同性,这里不分析,至此SystemServer的Context已经创建好。

回到SystemServer.main()最重要的部分,创建系统服务,跟踪分析其三连调用

startBootstrapServices();

startCoreServices();

startOtherServices();:

/**
* Starts the small tangle of critical services that are needed to get
* the system off the ground.  These services have complex mutual dependencies
* which is why we initialize them all in one place here.  Unless your service
* is also entwined in these dependencies, it should be initialized in one of
* the other functions.
*/
private void startBootstrapServices() {
// Wait for installd to finish starting up so that it has a chance to
// create critical directories such as /data/user with the appropriate
// permissions.  We need this to complete before we initialize other services.
Installer installer = mSystemServiceManager.startService(Installer.class);

// Activity manager runs the show.
mActivityManagerService = mSystemServiceManager.startService(
ActivityManagerService.Lifecycle.class).getService();
mActivityManagerService.setSystemServiceManager(mSystemServiceManager);
mActivityManagerService.setInstaller(installer);

// Power manager needs to be started early because other services need it.
// Native daemons may be watching for it to be registered so it must be ready
// to handle incoming binder calls immediately (including being able to verify
// the permissions for those calls).
mPowerManagerService = mSystemServiceManager.startService(PowerManagerService.class);

// Now that the power manager has been started, let the activity manager
// initialize power management features.
mActivityManagerService.initPowerManagement();

// Display manager is needed to provide display metrics before package manager
// starts up.
mDisplayManagerService = mSystemServiceManager.startService(DisplayManagerService.class);

// We need the default display before we can initialize the package manager.
mSystemServiceManager.startBootPhase(SystemService.PHASE_WAIT_FOR_DEFAULT_DISPLAY);

// Only run "core" apps if we're encrypting the device.
String cryptState = SystemProperties.get("vold.decrypt");
if (ENCRYPTING_STATE.equals(cryptState)) {
Slog.w(TAG, "Detected encryption in progress - only parsing core apps");
mOnlyCore = true;
} else if (ENCRYPTED_STATE.equals(cryptState)) {
Slog.w(TAG, "Device encrypted - only parsing core apps");
mOnlyCore = true;
}

// Start the package manager.
Slog.i(TAG, "Package Manager");
mPackageManagerService = PackageManagerService.main(mSystemContext, installer,
mFactoryTestMode != FactoryTest.FACTORY_TEST_OFF, mOnlyCore);
mFirstBoot = mPackageManagerService.isFirstBoot();
mPackageManager = mSystemContext.getPackageManager();

Slog.i(TAG, "User Service");
ServiceManager.addService(Context.USER_SERVICE, UserManagerService.getInstance());

// Initialize attribute cache used to cache resources from packages.
AttributeCache.init(mSystemContext);

// Set up the Application instance for the system process and get started.
mActivityManagerService.setSystemProcess();
}

/**
* Starts some essential services that are not tangled up in the bootstrap process.
*/
private void startCoreServices() {
// Manages LEDs and display backlight.
mSystemServiceManager.startService(LightsService.class);

// Tracks the battery level.  Requires LightService.
mSystemServiceManager.startService(BatteryService.class);

// Tracks application usage stats.
mSystemServiceManager.startService(UsageStatsService.class);
mActivityManagerService.setUsageStatsManager(
LocalServices.getService(UsageStatsManagerInternal.class));
// Update after UsageStatsService is available, needed before performBootDexOpt.
mPackageManagerService.getUsageStatsIfNoPackageUsageInfo();

// Tracks whether the updatable WebView is in a ready state and watches for update installs.
mSystemServiceManager.startService(WebViewUpdateService.class);
}

/**
* Starts a miscellaneous grab bag of stuff that has yet to be refactored
* and organized.
*/
private void startOtherServices() {
final Context context = mSystemContext;
AccountManagerService accountManager = null;
ContentService contentService = null;
VibratorService vibrator = null;
IAlarmManager alarm = null;
MountService mountService = null;
NetworkManagementService networkManagement = null;
NetworkStatsService networkStats = null;
NetworkPolicyManagerService networkPolicy = null;
ConnectivityService connectivity = null;
NetworkScoreService networkScore = null;
NsdService serviceDiscovery= null;
WindowManagerService wm = null;
BluetoothManagerService bluetooth = null;
UsbService usb = null;
SerialService serial = null;
NetworkTimeUpdateService networkTimeUpdater = null;
CommonTimeManagementService commonTimeMgmtService = null;
InputManagerService inputManager = null;
TelephonyRegistry telephonyRegistry = null;
ConsumerIrService consumerIr = null;
AudioService audioService = null;
MmsServiceBroker mmsService = null;
...
}


其实就是创建并用SystemServiceManager或者ServiceManager管理着这些服务。注意,以前是没有SystemServiceManager,全部服务都是由ServiceManager进行管理的,官方这样修改的意图是什么还需要后续去研究。

上面的代码可以看到我们经常通过Context.getSystemService常用的一些Manager都这里创建了。

至此该部分的研究暂一段落。

三、普通Apk应用程序的启动过程

请看下一篇《源码分析Android 应用进程的启动过程》
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: