从Android SystemServer开始
安卓的Framework层也就是zygote是从SystemServer开始的,所有重要的上层服务都集中在SystemServer这个进程中,这个进程的名字为app_process(64位为app_process64).这个进程的启动脚本示例如下:
init.zygote64.rc
service zygote /system/bin/app_process64 -Xzygote /system/bin --zygote --start-system-server
class main
priority -20
user root
group root readproc reserved_disk
socket zygote stream 660 root system
socket usap_pool_primary stream 660 root system
onrestart write /sys/android_power/request_state wake
onrestart write /sys/power/state on
onrestart restart audioserver
onrestart restart cameraserver
onrestart restart media
onrestart restart netd
onrestart restart wificond
onrestart restart vendor.servicetracker-1-1
writepid /dev/cpuset/foreground/tasks
可以看到,当我们这个进程被重启以后很多需要被依赖的本地进程需要被拉起来,这些restart的server都是以binder的服务端存在的本地服务,提供了例如音频camera等的基础服务功能,我们Framework只是作为客户端会去调用这些服务里的一些功能,然后framework再为上层应用提供接口,作为中间人统筹管理这些所有的硬件资源。
上面提到的app_process这个进程源码目录在frameworks/base/cmds/app_pro
cess它只是作为一个启动器的存在,只有一个源文件就是app_main.cpp它可以被编译成32以及64位的版本。
这里的main函数通过AppRuntime继承自AndroidRuntime来启动java的类。
if (zygote) {
runtime.start("com.android.internal.os.ZygoteInit", args, zygote);
} else if (className) {
runtime.start("com.android.internal.os.RuntimeInit", args, zygote);
} else {
fprintf(stderr, "Error: no class name or --zygote supplied.\n");
app_usage();
LOG_ALWAYS_FATAL("app_process: no class name or --zygote supplied.");
}
这里的zygote是通过参数来判断的,我们上面的rc文件中可以看到我们通过这个进程带的参数是
--zygote --start-system-server
启动systemserver是从这里开始的,当然这个进程也可以启动普通app,当后面启动应用的时候还需要这个进程来创建镜像。
具体的如何启动vm然后怎么加载的java类我们先不做探讨。
我们知道在启动zygote的时候是调用了ZygoteInit这个类来完成的,它同样有个main函数如下:
frameworks\base\core\java\com\android\internal\os\ZygoteInit.java
@UnsupportedAppUsage
public static void main(String argv[]) {
ZygoteServer zygoteServer = null;
。。。。。省略一部分
zygoteServer = new ZygoteServer(isPrimaryZygote);
if (startSystemServer) {
Runnable r = forkSystemServer(abiList, zygoteSocketName, zygoteServer);
// {@code r == null} in the parent (zygote) process, and {@code r != null} in the
// child (system_server) process.
if (r != null) {
r.run();
return;
}
}
这里可以看到通过forkSystemServer继续去创建
private static Runnable forkSystemServer(String abiList, String socketName,
ZygoteServer zygoteServer) {
这个函数里有个参数列表比较重要
/* 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,1021,1023,"
+ "1024,1032,1065,3001,3002,3003,3006,3007,3009,3010",
"--capabilities=" + capabilities + "," + capabilities,
"--nice-name=system_server",
"--runtime-args",
"--target-sdk-version=" + VMRuntime.SDK_VERSION_CUR_DEVELOPMENT,
"com.android.server.SystemServer",
};
这里的setgroups限制了那些uid的访问权限。以及指定了我们的类com.android.server.SystemServer
然后通过Zygote这个类继续创建如下:
/* Request to fork the system server process */
pid = Zygote.forkSystemServer(
parsedArgs.mUid, parsedArgs.mGid,
parsedArgs.mGids,
parsedArgs.mRuntimeFlags,
null,
parsedArgs.mPermittedCapabilities,
parsedArgs.mEffectiveCapabilities);
当我们第一次创建子进程成功的时候这个pid肯定返回的是0,到这我们的SystemServer就要被启动了,并被作为主进程存在。
frameworks\base\core\java\com\android\internal\os\Zygote.java
public static int forkSystemServer(int uid, int gid, int[] gids, int runtimeFlags,
int[][] rlimits, long permittedCapabilities, long effectiveCapabilities) {
ZygoteHooks.preFork();
// Resets nice priority for zygote process.
resetNicePriority();
int pid = nativeForkSystemServer(
uid, gid, gids, runtimeFlags, rlimits,
permittedCapabilities, effectiveCapabilities);
// Enable tracing as soon as we enter the system_server.
if (pid == 0) {
Trace.setTracingEnabled(true, runtimeFlags);
}
ZygoteHooks.postForkCommon();
return pid;
}
这里的nativeForkSystemServer就到了c++的底层程序了属于linux的编程,很容易就可以创建子进程。
这样我们就可以继续分析SystemServer。
SystemServer可以开始了,去到它的main函数。
frameworks\base\services\java\com\android\server\SystemServer.java
/**
* The main entry point from zygote.
*/
public static void main(String[] args) {
new SystemServer().run();
}
这里也说了我们的main函数来自zygote,同时注意这里也定义了构造函数
public SystemServer() {
// Check for factory test mode.
mFactoryTestMode = FactoryTest.getMode();
/ Record process start information.
// Note SYSPROP_START_COUNT will increment by *2* on a FDE device when it fully boots;
// one for the password screen, second for the actual boot.
mStartCount = SystemProperties.getInt(SYSPROP_START_COUNT, 0) + 1;
mRuntimeStartElapsedTime = SystemClock.elapsedRealtime();
mRuntimeStartUptime = SystemClock.uptimeMillis();
// Remember if it's runtime restart(when sys.boot_completed is already set) or reboot
// We don't use "mStartCount > 1" here because it'll be wrong on a FDE device.
// TODO: mRuntimeRestart will *not* be set to true if the proccess crashes before
// sys.boot_completed is set. Fix it.
mRuntimeRestart = "1".equals(SystemProperties.get("sys.boot_completed"));
}
检查工厂模式,记录一些时间信息,判断是否为重启systemserver。
mian函数只调用了run函数
我们继续去看run都做了什么
函数有点长但是非常主要,所有的主要动作都在这里完成:
private void run() {
try {
traceBeginAndSlog("InitBeforeStartServices");//开始记录事件及打印log
// Record the process start information in sys props.记录启动信息比如次数时间信息等
SystemProperties.set(SYSPROP_START_COUNT, String.valueOf(mStartCount));
SystemProperties.set(SYSPROP_START_ELAPSED, String.valueOf(mRuntimeStartElapsedTime));
SystemProperties.set(SYSPROP_START_UPTIME, String.valueOf(mRuntimeStartUptime));
EventLog.writeEvent(EventLogTags.SYSTEM_SERVER_START,
mStartCount, mRuntimeStartUptime, mRuntimeStartElapsedTime);
//处理系统时间
// 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);
}
//处理时区
// Default the timezone property to GMT if not set.
//
String timezoneProperty = SystemProperties.get("persist.sys.timezone");
if (timezoneProperty == null || timezoneProperty.isEmpty()) {
Slog.w(TAG, "Timezone not set; setting to GMT.");
SystemProperties.set("persist.sys.timezone", "GMT");
}
//处理系统语言
// 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", "");
}
// The system server should never make non-oneway calls系统服务为了响应速度需要为异步非阻塞形式
Binder.setWarnOnBlocking(true);
// The system server should always load safe labels
PackageItemInfo.forceSafeLabels();
// Default to FULL within the system server.
SQLiteGlobal.sDefaultSyncMode = SQLiteGlobal.SYNC_MODE_FULL;
// Deactivate SQLiteCompatibilityWalFlags until settings provider is initialized
SQLiteCompatibilityWalFlags.init(null);
// Here we go!检查这个log开始
Slog.i(TAG, "Entered the Android system server!");
int uptimeMillis = (int) SystemClock.elapsedRealtime();
EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_SYSTEM_RUN, uptimeMillis);
if (!mRuntimeRestart) {
MetricsLogger.histogram(null, "boot_system_server_init", 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 | xq oqi'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());
// 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);
// Within the system server, when parceling exceptions, include the stack trace
Parcel.setStackTraceParceling(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.prepareMainLooper();
Looper.getMainLooper().setSlowLogThresholdMs(
SLOW_DISPATCH_THRESHOLD_MS, SLOW_DELIVERY_THRESHOLD_MS);
// Initialize native services.加载本地服务库
System.loadLibrary("android_servers");
// Debug builds - allow heap profiling.
if (Build.IS_DEBUGGABLE) {
initZygoteChildHeapProfiling();
}
// Check whether we failed to shut down last time we tried.
// This call may not return.
performPendingShutdown();
// Initialize the system context.创建系统上下文,为system相关服务使用
createSystemContext();
// Create the system service manager.创建系统服务管理器后面所有的系统服务都是由他管理
mSystemServiceManager = new SystemServiceManager(mSystemContext);
mSystemServiceManager.setStartInfo(mRuntimeRestart,
mRuntimeStartElapsedTime, mRuntimeStartUptime);
LocalServices.addService(SystemServiceManager.class, mSystemServiceManager);
// Prepare the thread pool for init tasks that can be parallelized
SystemServerInitThreadPool.get();
} finally {
traceEnd(); // InitBeforeStartServices
}
// Start services.启动各种系统服务,由最重要到次重要
try {
traceBeginAndSlog("StartServices");
startBootstrapServices();
startCoreServices();
startOtherServices();
SystemServerInitThreadPool.shutdown();
} catch (Throwable ex) {
Slog.e("System", "******************************************");
Slog.e("System", "************ Failure starting system services", ex);
throw ex;
} finally {
traceEnd();
}
StrictMode.initVmDefaults(null);
if (!mRuntimeRestart && !isFirstBootOrUpgrade()) {
int uptimeMillis = (int) SystemClock.elapsedRealtime();
MetricsLogger.histogram(null, "boot_system_server_ready", uptimeMillis);
final int MAX_UPTIME_MILLIS = 60 * 1000;
if (uptimeMillis > MAX_UPTIME_MILLIS) {
Slog.wtf(SYSTEM_SERVER_TIMING_TAG,
"SystemServer init took too long. uptimeMillis=" + uptimeMillis);
}
}
// Diagnostic to ensure that the system is in a base healthy state. Done here as a common
// non-zygote process.
if (!VMRuntime.hasBootImageSpaces()) {
Slog.wtf(TAG, "Runtime is not running with a boot image!");
}
// Loop forever.开始消息循环队列等待处理系统消息,不允许退出系统服务的朱looper
Looper.loop();
throw new RuntimeException("Main thread loop unexpectedly exited");
}
到这里SystemServer就跑完了基本的系统服务也基本开机结束了。
做个简单的总结:
我们在内核启动后使用init启动了zygote,zygote是通过app_process这个bin执行文件实现的,这个进程只有一个main文件以及main函数,这个函数接收启动的参数,选择性启动zygote。这个进程调用了AndroidRuntime的库,继而可以使用java的虚拟环境,通过类名找到com.android.internal.os.RuntimeInit然后启动它,RuntimeInit的main函数会判断是否是启动系统服务(SystemServer),如果是则使用forkSystemServer函数去创建系统服务的子进程,在创建子进程之前添加了uid组管理等策略,并且将这些策略以及我们即将启动的系统服务类 "com.android.server.SystemServer"(SystemServer)等作为参数继续传递给com.android.internal.os.Zygote然后又调用了Zygote的 pid = Zygote.forkSystemServer函数继续去创建子进程。接下来通过本地服务去启动我们的SystemServer,然后就又开始了SystemServer的main以及run函数。具体本地如何fork子进程后续再探究。
然后我们继续细化SystemServer的服务启动流程。