这两天有一个需求得联调,在等待服务端同事完事,等待过程中,阅读了一下Android8.0里SystemServer的启动过程,除了设置时区语言这些,其实主要就是初始化了系统上下文以及一些服务的启动。
SystemServer是一个进程,由zygote进程fork出来,所以它的入口方法就是main方法,代码如下
public static void main(String[] args) {
new SystemServer().run();
}
直接就是new了一个SystemServer,而后执行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属性,没有执行重启操作
代码如下
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()方法启动一些服务,以前两个方法为例看一下代码
启动一些引导服务,代码如下
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);
}
开启了一些服务,无需多解释
也是启动一些服务,代码如下
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的启动过程就是如此,主要还是启动一些服务