背景
这两天有一个需求得联调,在等待服务端同事完事,等待过程中,阅读了一下Android8.0里SystemServer的启动过程,除了设置时区语言这些,其实主要就是初始化了系统上下文以及一些服务的启动。
main()方法
SystemServer是一个进程,由zygote进程fork出来,所以它的入口方法就是main方法,代码如下
-
public static void main(String[] args) {
-
new SystemServer().run();
-
}
直接就是new了一个SystemServer,而后执行run()方法
run()方法
方法比较长,代码如下
-
private void run() {
-
try {
-
traceBeginAndSlog("InitBeforeStartServices");
-
// 如果当前系统时间早于1970年元月1号,就更新之为1970年元月1号
-
if (System.currentTimeMillis() < EARLIEST_SUPPORTED_TIME) {
-
SystemClock.setCurrentTimeMillis(EARLIEST_SUPPORTED_TIME);
-
}
-
// 设置时区
-
String timezoneProperty = SystemProperties.get("persist.sys.timezone");
-
if (timezoneProperty == null || timezoneProperty.isEmpty()) {
-
SystemProperties.set("persist.sys.timezone", "GMT"); // 默认时区是格林尼治时区
-
}
-
// 设置系统语言
-
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", "");
-
}
-
// 系统Server不能进行非oneway通信,因为非oneway通信要等待对方的恢复,这个等待过程是阻塞的
-
Binder.setWarnOnBlocking(true); // 所以设置阻塞时警告
-
// 正式启动SystemServer
-
int uptimeMillis = (int) SystemClock.elapsedRealtime();
-
EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_SYSTEM_RUN, uptimeMillis);
-
if (!mRuntimeRestart) {
-
MetricsLogger.histogram(null, "boot_system_server_init", uptimeMillis);
-
}
-
// 设置vmLibrary
-
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);
-
}
-
// 清除内存增长上限,因为加载SystemServer需要很多内存
-
VMRuntime.getRuntime().clearGrowthLimit();
-
// 设置内存利用率最大是0.8
-
VMRuntime.getRuntime().setTargetHeapUtilization(0.8f);
-
// 初始化指纹系统
-
Build.ensureFingerprintProperty();
-
// 设置访问环境变量(例如sd卡路径等)时,必须指定用户
-
Environment.setUserRequired(true);
-
// 设置系统的Bundle是可defuse的,意为如果在解析bundle的时候,忽略发生的badParcelableException
-
// 那个异常如果发送,就直接清空这个Bundle的内容。所以defuse使能最好在Bundle到了终点后再设置,因为这样总不会导致下流再失去bundle的内容
-
BaseBundle.setShouldDefuse(true);
-
// 保证进入SystemServer的binder都运行在前台
-
BinderInternal.disableBackgroundScheduling(true);
-
// 设置最大线程数为31
-
BinderInternal.setMaxThreads(sMaxBinderThreads);
-
// 设置当前线程(主线程)也是在前台进行
-
android.os.Process.setThreadPriority(
-
android.os.Process.THREAD_PRIORITY_FOREGROUND);
-
android.os.Process.setCanSelfBackground(false); // 主线程不能自己切到后台
-
Looper.prepareMainLooper(); // 主线程的消息循环开始
-
// 加载native服务
-
System.loadLibrary("android_servers");
-
// 检测上次是否成功关机
-
performPendingShutdown();
-
// 初始化系统上下文
-
createSystemContext();
-
// 初始化SysytemServiceManager,并把它添加到LocalServices中
-
mSystemServiceManager = new SystemServiceManager(mSystemContext);
-
mSystemServiceManager.setRuntimeRestarted(mRuntimeRestart);
-
LocalServices.addService(SystemServiceManager.class, mSystemServiceManager);
-
// 创建SystemServerInit线程池的单例
-
SystemServerInitThreadPool.get();
-
} finally {
-
traceEnd();
-
}
-
// 启动一些服务
-
// Start services.
-
try {
-
traceBeginAndSlog("StartServices");
-
startBootstrapServices(); // 启动引导服务
-
startCoreServices(); // 启动核心服务
-
startOtherServices(); // 启动其他服务
-
SystemServerInitThreadPool.shutdown();
-
} catch (Throwable ex) {
-
...
-
} finally {
-
traceEnd();
-
}
-
... // 日志
-
// Loop forever.
-
// 开始消息循环
-
Looper.loop();
-
throw new RuntimeException("Main thread loop unexpectedly exited"); // 消息循环是不能退出的
-
}
代码多但是逻辑并不复杂,值得注意的方法除了启动引导服务、核心服务和其他服务外,再就是检测上次关机是否成功的performPendingShutdown()方法,这个方法主要是针对recovery模式下系统更新引起的重启,这种情况要多重启一次。而这里只是设置了一下sys.powerctl属性,没有执行重启操作
performPendingShutdown()方法
代码如下
-
private void performPendingShutdown() {
-
final String shutdownAction = SystemProperties.get(
-
ShutdownThread.SHUTDOWN_ACTION_PROPERTY, ""); // 获取上次的关机信息
-
if (shutdownAction != null && shutdownAction.length() > 0) {
-
boolean reboot = (shutdownAction.charAt(0) == '1'); // 关机信息第一位表示关机是否是为了重启
-
final String reason;
-
if (shutdownAction.length() > 1) {
-
reason = shutdownAction.substring(1, shutdownAction.length()); // 第一位往后表示关机的原因
-
} else {
-
reason = null;
-
}
-
if (reason != null && reason.startsWith(PowerManager.REBOOT_RECOVERY_UPDATE)) {
-
/*
-
* 关机原因是否是REBOOT_RECOVERY_UPDATE,也就是recovery模式下,为了执行系统更新而关的机
-
* 这种情况下,一定会多重启一次,多的这一次重启,原因就不是REBOOT_RECOVERY_UPDATE了
-
* @hide
-
public static final String REBOOT_RECOVERY_UPDATE = "recovery-update";
-
*/
-
File packageFile = new File(UNCRYPT_PACKAGE_FILE);
-
if (packageFile.exists()) {
-
String filename = null;
-
try {
-
filename = FileUtils.readTextFile(packageFile, 0, null); // 读取uncrypt_file的内容,获取的是一个文件名
-
} catch (IOException e) {
-
Slog.e(TAG, "Error reading uncrypt package file", e);
-
}
-
if (filename != null && filename.startsWith("/data")) { // 如果读出来的文件名以/data开头,也就是在data目录内
-
if (!new File(BLOCK_MAP_FILE).exists()) { // 如果block.map文件不存在,直接抛异常,重启失败
-
Slog.e(TAG, "Can't find block map file, uncrypt failed or " +
-
"unexpected runtime restart?");
-
return;
-
}
-
}
-
}
-
}
-
ShutdownThread.rebootOrShutdown(null, reboot, reason);
-
}
-
}
主要是调用了ShutdownThread.rebootOrShutdown()方法,这个方法只是保存了一下sys.powerctl属性,代码如下
-
public static void rebootOrShutdown(final Context context, boolean reboot, String reason) {
-
if (reboot) {
-
.. // 日志
-
PowerManagerService.lowLevelReboot(reason);
-
.. // 日志
-
reason = null;
-
} else if (SHUTDOWN_VIBRATE_MS > 0 && context != null) {
-
// 关机前要进行振动
-
Vibrator vibrator = new SystemVibrator(context); // 振动器
-
try {
-
vibrator.vibrate(SHUTDOWN_VIBRATE_MS, VIBRATION_ATTRIBUTES); // 传入振动持续时间和振动方式
-
} catch (Exception e) {
-
.. // 日志
-
}
-
try {
-
Thread.sleep(SHUTDOWN_VIBRATE_MS); // 振动是异步的,所以当前线程要阻塞一会儿,保证振动完了,再关机
-
} catch (InterruptedException unused) {
-
}
-
}
-
// Shutdown power
-
PowerManagerService.lowLevelShutdown(reason);
如果是进来这个方法是要重启,reboot就是真,先调用PowerManagerService.lowLevelReboot()方法,传入重启原因reason。此方法代码如下
-
public static void lowLevelReboot(String reason) {
-
if (reason == null) {
-
reason = "";
-
}
-
if (reason.equals(PowerManager.REBOOT_QUIESCENT)) {
-
sQuiescent = true;
-
reason = "";
-
} else if (reason.endsWith("," + PowerManager.REBOOT_QUIESCENT)) {
-
sQuiescent = true;
-
reason = reason.substring(0,
-
reason.length() - PowerManager.REBOOT_QUIESCENT.length() - 1);
-
}
-
if (reason.equals(PowerManager.REBOOT_RECOVERY)
-
|| reason.equals(PowerManager.REBOOT_RECOVERY_UPDATE)) { // 如果reason是或REBOOT_RECOVERY或REBOOT_RECOVERY_UPDATE,就把reason换成recovery
-
reason = "recovery";
-
}
-
if (sQuiescent) {
-
reason = reason + ",quiescent";
-
}
-
SystemProperties.set("sys.powerctl", "reboot," + reason); // 保存sys.powerctl属性
-
try {
-
Thread.sleep(20 * 1000L); // 阻塞20秒
-
} catch (InterruptedException e) {
-
Thread.currentThread().interrupt();
-
}
-
Slog.wtf(TAG, "Unexpected return from lowLevelReboot!");
-
}
可以看到,主要是把重启原因进行转换和保存,然后把重启线程阻塞20s。方法执行完后,就会执行lowLevelShutdown(),代码如下
-
public static void lowLevelShutdown(String reason) {
-
if (reason == null) {
-
reason = "";
-
}
-
SystemProperties.set("sys.powerctl", "shutdown," + reason); // 保存/更新sys.powerctl属性
-
}
回到SystemServer.run()方法,检测完上次是否正常关机后,调用了createSystemContext()方法获取系统上下文,代码如下
-
private void createSystemContext() {
-
ActivityThread activityThread = ActivityThread.systemMain();
-
mSystemContext = activityThread.getSystemContext();
-
mSystemContext.setTheme(DEFAULT_SYSTEM_THEME);
-
final Context systemUiContext = activityThread.getSystemUiContext();
-
systemUiContext.setTheme(DEFAULT_SYSTEM_THEME);
-
}
这个方法主要是调用了ActivityThread的一系列方法来实现,参见文章安卓开发学习之获取系统上下文。然后就是调用startBootstrapServices()、startCoreServices()、startOtherServices()方法启动一些服务,以前两个方法为例看一下代码
startBootstrapServices()方法
启动一些引导服务,代码如下
-
private void startBootstrapServices() {
-
// 创建SystemConfig,进行权限的获取
-
SystemServerInitThreadPool.get().submit(SystemConfig::getInstance, TAG_SYSTEM_CONFIG);
-
// 开启安装器服务
-
Installer installer = mSystemServiceManager.startService(Installer.class);
-
// 设备识别器服务
-
mSystemServiceManager.startService(DeviceIdentifiersPolicyService.class);
-
// 启动并初始化ActivityManagerService
-
mActivityManagerService = mSystemServiceManager.startService(
-
ActivityManagerService.Lifecycle.class).getService();
-
mActivityManagerService.setSystemServiceManager(mSystemServiceManager);
-
mActivityManagerService.setInstaller(installer);
-
// 启动电量管理服务
-
mPowerManagerService = mSystemServiceManager.startService(PowerManagerService.class);
-
// 初始化电量管理器
-
mActivityManagerService.initPowerManagement();
-
if (!SystemProperties.getBoolean("config.disable_noncore", false)) {
-
traceBeginAndSlog("StartRecoverySystemService");
-
// 启动RecoverySystem服务
-
mSystemServiceManager.startService(RecoverySystemService.class);
-
}
-
// 标记裸机已经启动完了,如果我们困在了运行时的重启循环中,这个标记可以跳出这个循环
-
RescueParty.noteBoot(mSystemContext);
-
// 启动灯光服务,包括背景亮度、闪光灯等
-
mSystemServiceManager.startService(LightsService.class);
-
// 启动显示服务,用来显示UI
-
mDisplayManagerService = mSystemServiceManager.startService(DisplayManagerService.class);
-
// 开始开机动画
-
mSystemServiceManager.startBootPhase(SystemService.PHASE_WAIT_FOR_DEFAULT_DISPLAY);
-
// 加密模式下,只运行内核应用,此处先设置标志位
-
String cryptState = SystemProperties.get("vold.decrypt");
-
if (ENCRYPTING_STATE.equals(cryptState)) {
-
mOnlyCore = true;
-
} else if (ENCRYPTED_STATE.equals(cryptState)) {
-
mOnlyCore = true;
-
}
-
// 开启包管理器服务
-
mPackageManagerService = PackageManagerService.main(mSystemContext, installer,
-
mFactoryTestMode != FactoryTest.FACTORY_TEST_OFF, mOnlyCore);
-
mFirstBoot = mPackageManagerService.isFirstBoot();
-
// 获取包管理器
-
mPackageManager = mSystemContext.getPackageManager();
-
if (!mOnlyCore) {
-
boolean disableOtaDexopt = SystemProperties.getBoolean("config.disable_otadexopt",
-
false);
-
if (!disableOtaDexopt) {
-
try {
-
// OTADexOpt(空中下载dex并优化,用于OTA升级)使能时,启动OTA升级服务
-
OtaDexoptService.main(mSystemContext, mPackageManagerService);
-
} catch (Throwable e) {
-
..
-
} finally {
-
..
-
}
-
}
-
}
-
// 启动用户管理服务
-
mSystemServiceManager.startService(UserManagerService.LifeCycle.class);
-
traceBeginAndSlog("InitAttributerCache");
-
// 从系统包中初始化属性资源
-
AttributeCache.init(mSystemContext);
-
// 设置系统进程
-
mActivityManagerService.setSystemProcess();
-
// 设置ui的调度策略
-
mDisplayManagerService.setupSchedulerPolicies();
-
// 启动OverlayManagerService,用于定制系统界面
-
mSystemServiceManager.startService(new OverlayManagerService(mSystemContext, installer));
-
// 开启传感器服务
-
mSensorServiceStart = SystemServerInitThreadPool.get().submit(() -> {
-
BootTimingsTraceLog traceLog = new BootTimingsTraceLog(
-
SYSTEM_SERVER_TIMING_ASYNC_TAG, Trace.TRACE_TAG_SYSTEM_SERVER);
-
traceLog.traceBegin(START_SENSOR_SERVICE);
-
startSensorService();
-
traceLog.traceEnd();
-
}, START_SENSOR_SERVICE);
-
}
开启了一些服务,无需多解释
startCoreServices()方法
也是启动一些服务,代码如下
-
private void startCoreServices() {
-
// 启动DropBox服务,用来记录系统日志
-
mSystemServiceManager.startService(DropBoxManagerService.class);
-
// 启动电池服务
-
mSystemServiceManager.startService(BatteryService.class);
-
traceBeginAndSlog("StartUsageService");
-
// 启动使用状态服务
-
mSystemServiceManager.startService(UsageStatsService.class);
-
mActivityManagerService.setUsageStatsManager(
-
LocalServices.getService(UsageStatsManagerInternal.class));
-
// 启动WebView更新服务
-
mWebViewUpdateService = mSystemServiceManager.startService(WebViewUpdateService.class);
-
}
结语
SystemService的启动过程就是如此,主要还是启动一些服务