前言
上一篇文档我们描述了在 Android 启动流程中 Zygote 部分的内容,从 Zygote 的配置、启动、初始化等内容展开,描述了 Zygote 在 Android 启动中的功能逻辑。本篇文档将会继续 Android 启动流程的描述,从 SystemServer 进程的内容展开,继续了解 Android 是如何启动的。
正文
本篇文档将会从 SystemServer 进程的内容继续描述 Android 启动流程。对于 SystemServer 进程,主要是对服务的初始化顺序、重要服务列举、启动方式等方面展开,从整体的角度展开描述。
1、SystemServer 启动
SystemServer 启动从 main 函数开始运行,我们来看下此函数的逻辑:
java
public static void main(String[] args) {
new SystemServer().run();
}
SystemServer 的 main 函数中初始化了 SystemServer 对象,并且调用 run 函数执行,下面我们来看下 run 函数的逻辑:
java
private void run() {
try {
......
// 如果设备时间早于 1970 年,很多 API 处理负数时会 crash。所以直接设置为 1970 年 1 月 1 日
if (System.currentTimeMillis() < EARLIEST_SUPPORTED_TIME) {
Slog.w(TAG, "System clock is before 1970; setting to 1970.");
SystemClock.setCurrentTimeMillis(EARLIEST_SUPPORTED_TIME);
}
// 未设置时区的话默认设为 GMT
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 (!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.setForceSafeLabels(true);
// 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!
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);
}
// 设置虚拟机运行库路径
SystemProperties.set("persist.sys.dalvik.vm.lib.2", VMRuntime.getRuntime().vmLibrary());
// Mmmmmm... more memory!
// 清除虚拟机内存增长限制,允许应用申请更多内存
VMRuntime.getRuntime().clearGrowthLimit();
// 设置堆内存的有效利用率为 0.8,(可能被忽略)
VMRuntime.getRuntime().setTargetHeapUtilization(0.8f);
// 确保指纹信息已经定义
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);
// 确保系统的 Binder 调用总是运行在前台优先级
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);
// 1. 创建主线程 Looper
Looper.prepareMainLooper();
Looper.getMainLooper().setSlowLogThresholdMs(
SLOW_DISPATCH_THRESHOLD_MS, SLOW_DELIVERY_THRESHOLD_MS);
// 初始化 native 服务,加载 libandroid_servers.so
System.loadLibrary("android_servers");
// 检查上次关机是否失败,可能不会有返回值
performPendingShutdown();
// 2. 初始化系统上下文
createSystemContext();
// 3. 创建系统服务管理 SystemServiceManager
// 并将 mSystemServiceManager 注册到 sLocalServiceObjects 中
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(); // 4. 启动系统引导服务
startCoreServices(); // 5. 启动系统核心服务
startOtherServices(); // 6. 启动其他服务
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);
}
}
// 7. Loop forever.
Looper.loop();
throw new RuntimeException("Main thread loop unexpectedly exited");
}
上述代码是 run 函数的主要内容,简单概括功能如下:
A:设置默认时间、时区、语言等参数
B:创建主线程的 Looper
C:初始化系统上下文
D:创建系统服务管理类 SystemServiceManager
E:按顺序启动系统服务,启动顺序为 BootStarpService、CoreService、OtherService
F:启动 Loop 循环处理消息
下面我们将会根据流程来描述 SystemServer 的运行过程。
2、SystemServer 启动阶段
2.1 设置默认时间、时区、语言
在 SystemServer 的 run() 函数中,会先对系统时间进行默认设置,如果设备时间早于 1970 年,那么时间戳就是负数(1970-01-01 00:00:00+0000 时间戳为 0),很多 API 在处理负数时会 crash。所以这里要先将时间设置成默认值 1970 年 1 月 1 日。
Android 通过属性来配置语言数据,persist.sys.language 属性定义了系统的默认语言。
2.1.1 Android 中时间标准和时区
- 原子时:International Atomic Time (IAT)
又称国际原子时,是一种通过原子钟得到的时间标准,原子钟是世界上已知最准确的时间测量和频率标准,原子钟在 37 亿年的误差不超过 1 秒。
- 世界时:Universal Time(UT)
在格林尼治子午线上的平太阳时称为世界时(UT0),又叫格林尼治平时(GMT)。格林尼治标准时间(旧译格林尼治平均时间或格林威治标准时间,英语:Greenwich Mean Time,GMT)是指位于英国伦敦郊区的皇家格林尼治天文台的标准时间,因为本初子午线被定义在通过那里的经线。
- 协调世界时:Coordinated Universal Time(UTC)
又称世界标准时间、世界统一时间。是经过平均太阳时(以格林威治时间GMT为准)、地轴运动修正后的新时标以及以"秒"为单位的国际原子时所综合精算而成的时间,计算过程相当严谨精密,因此若以"世界标准时间"的角度来说,UTC比GMT更精准。其误差值必须保持在0.9秒以内,若大于0.9秒则由位于巴黎的国际地球自转事务中央局发布闰秒,使UTC与地球自转周期一致。UTC被应用在大多数的计算机以及网络标准中。
2.1.2 GMT 时间和 UTC 时间的区别
GMT(格林威治标准时间)和 UTC(协调世界时)是两种常用的时间标准,它们之间有一些相似之处,但也存在一些重要的区别:
相似之处
-
时间基准: GMT 和 UTC 都是用于表示时间的基准,通常用于协调不同地区的时间。
-
时间格式: 两者都可以表示为小时和分钟的格式,例如 GMT+8:00 或 UTC+8:00。
主要区别
- 定义:
GMT: 是一种基于地球自转的时间标准,最初是以格林威治天文台为基准。它反映的是地球自转与太阳位置之间的关系。
UTC: 是一种更精确的时间标准,基于原子钟的时间测量。UTC 是国际上广泛使用的时间标准,不受地球自转变化的影响。
- 精度:
GMT: 随着地球自转的不规则性,GMT 的精度相对较低。
UTC: 通过引入闰秒来调整,使其与地球自转保持一致,因而更为精确。
- 使用场景:
GMT: 在某些地区和特定场合(如航海和航空)仍然被使用。
UTC: 是现代计算机系统、网络协议(如 NTP)和全球时间标准的基础。
虽然 GMT 和 UTC 在日常使用中常常可以互换,但在技术和科学领域,UTC 更为准确和可靠。对于编程和系统设计,推荐使用 UTC 作为时间标准。
2.1.3 时间戳
时间戳是指某个特定时间点的标识,通常是一个数字或字符串。它表示从某个固定的起始时间(通常是1970 年1月1日00:00:00 UTC)到该时间点所经过的秒数或毫秒数。时间戳可以用于记录事件发生的时间、计算时间间隔、进行时间排序等操作。
注意:时间戳的优点是具有唯一性和可比较性,不受时区和地域的影响(也就是说,在全世界任何时区,获取的时间戳都是一样的)。
java
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ssZ", Locale.getDefault());
Log.i("Test", sdf.parse("2018-09-01 08:00:00+0800").getTime()+"");
Log.i("Test", sdf.parse("2018-09-01 00:00:00+0000").getTime()+"");
Log.i("Test", sdf.parse("1970-01-01 00:00:00+0000").getTime()+"");
运行结果:
1535760000000
1535760000000
0
相同时间对应不同的时区的时间,在转换成时间戳得到的值是一致的。
2.1.4 修改默认语言
- 修改 PRODUCT_LOCALES 字段
在 /build/target/product/languages_full.mk 文件中 PRODUCT_LOCALES 字段定义了所有的语言,系统的默认语言是因为,第一位是 en_US,如果修改,可以将要修改的语言放在第一位,例如 zh_CN。
-
修改device/{硬件平台}/{产品}/system.prop或者default.prop,加入:
-
修改 init.rc
setprop persist.sys.language zh
setprop persist.sys.country CN -
修改device/{硬件平台}/{产品}/device.mk,加入:
PRODUCT_PROPERTY_OVERRIDES +=
persist.sys.language=zh
persist.sys.country=CN \ -
修改build/tools/buildinfo.sh
echo "persist.sys.language=zh"
echo "persist.sys.country=CN"
3、Service 服务的启动
本章节将会介绍服务的启动流程,在 SystemServer 中会启动 Android 上层服务,用于支持 Android 的各类功能,下列小章节将会从服务启动的介绍、启动阶段和启动方式展开描述。
3.1 服务启动介绍
SystemServer 通过如下三个函数进行各类服务的启动
java
startBootstrapServices(); // 4. 启动系统引导服务
startCoreServices(); // 5. 启动系统核心服务
startOtherServices(); // 6. 启动其他服务
3.1.1 startBootstrapServices
startBootstrapServices 函数用于启动系统引导服务,启动的内容如下所示:
java
private void startBootstrapServices() {
final String TAG_SYSTEM_CONFIG = "ReadingSystemConfig";
SystemServerInitThreadPool.get().submit(SystemConfig::getInstance, TAG_SYSTEM_CONFIG);
// 阻塞等待与 installd 建立 socket 通道
Installer installer = mSystemServiceManager.startService(Installer.class);
// 启动 DeviceIdentifiersPolicyService,在 ActivityManagerService 之前
mSystemServiceManager.startService(DeviceIdentifiersPolicyService.class);
// 启动服务 ActivityManagerService
mActivityManagerService = mSystemServiceManager.startService(
ActivityManagerService.Lifecycle.class).getService();
mActivityManagerService.setSystemServiceManager(mSystemServiceManager);
mActivityManagerService.setInstaller(installer);
// 启动服务 PowerManagerService
mPowerManagerService = mSystemServiceManager.startService(PowerManagerService.class);
// Now that the power manager has been started, let the activity manager
// initialize power management features.
mActivityManagerService.initPowerManagement();
// 启动服务 RecoverySystemService
mSystemServiceManager.startService(RecoverySystemService.class);
// Now that we have the bare essentials of the OS up and running, take
// note that we just booted, which might send out a rescue party if
// we're stuck in a runtime restart loop.
RescueParty.noteBoot(mSystemContext);
// 启动服务 LightsService
mSystemServiceManager.startService(LightsService.class);
// Package manager isn't started yet; need to use SysProp not hardware feature
if (SystemProperties.getBoolean("config.enable_sidekick_graphics", false)) {
mSystemServiceManager.startService(WEAR_SIDEKICK_SERVICE_CLASS);
}
// 启动 DisplayManagerService,在 PackageManagerService 之前
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);
// 正在加密设备时只运行核心 app
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;
}
// 启动服务 PackageManagerService
if (!mRuntimeRestart) {
MetricsLogger.histogram(null, "boot_package_manager_init_start",
(int) SystemClock.elapsedRealtime());
}
mPackageManagerService = PackageManagerService.main(mSystemContext, installer,
mFactoryTestMode != FactoryTest.FACTORY_TEST_OFF, mOnlyCore);
mFirstBoot = mPackageManagerService.isFirstBoot();
mPackageManager = mSystemContext.getPackageManager();
if (!mRuntimeRestart && !isFirstBootOrUpgrade()) {
MetricsLogger.histogram(null, "boot_package_manager_init_ready",
(int) SystemClock.elapsedRealtime());
}
if (!mOnlyCore) {
boolean disableOtaDexopt = SystemProperties.getBoolean("config.disable_otadexopt",
false);
if (!disableOtaDexopt) {
traceBeginAndSlog("StartOtaDexOptService");
try {
OtaDexoptService.main(mSystemContext, mPackageManagerService);
} catch (Throwable e) {
reportWtf("starting OtaDexOptService", e);
} finally {
traceEnd();
}
}
}
// 启动服务 UserManagerService
mSystemServiceManager.startService(UserManagerService.LifeCycle.class);
// 初始化属性 cache 以缓存包资源
AttributeCache.init(mSystemContext);
// 设置 AMS
mActivityManagerService.setSystemProcess();
// DisplayManagerService needs to setup android.display scheduling related policies
// since setSystemProcess() would have overridden policies due to setProcessGroup
mDisplayManagerService.setupSchedulerPolicies();
// 启动服务 OverlayManagerService
OverlayManagerService overlayManagerService = new OverlayManagerService(
mSystemContext, installer);
mSystemServiceManager.startService(overlayManagerService);
if (SystemProperties.getInt("persist.sys.displayinset.top", 0) > 0) {
// DisplayManager needs the overlay immediately.
overlayManagerService.updateSystemUiContext();
LocalServices.getService(DisplayManagerInternal.class).onOverlayChanged();
}
// 在单独的线程中启动 SensorService
mSensorServiceStart = SystemServerInitThreadPool.get().submit(() -> {
TimingsTraceLog traceLog = new TimingsTraceLog(
SYSTEM_SERVER_TIMING_ASYNC_TAG, Trace.TRACE_TAG_SYSTEM_SERVER);
startSensorService();
}, START_SENSOR_SERVICE);
}
启动的服务列表入下表所示:
服务名称 | 描述 |
---|---|
Installer | 负责apk安装相关的工作 |
DeviceIdentifiersPolicyService | 设备标识符策略服务 |
UriGrantsManagerService | Uri授权管理 |
ActivityTaskManagerService | 用于管理Activity及其容器(task, stacks, displays,... )的系统服务 |
ActivityManagerService | 管理Activity的启动,调度等工作 |
PowerManagerService | 负责协调设备上的电源管理功能 |
ThermalManagerService | 热缓解服务 |
RecoverySystemService | 负责协调设备上与恢复有关的功能 |
LightsService | 管理LED和屏幕背光 |
DisplayManagerService | 管理显示设备 |
PackageManagerService | 主要负责APK、jar包的管理 |
UserManagerService | 管理用户的系统服务 |
OverlayManagerService | 负责动态资源overlay工作,具体请搜索android RRO技术 |
SensorPrivacyService | 和传感器有关,具体作用不明 |
SensorPrivacySere | 传感器服务 |
3.1.2 startCoreServices
startCoreServices 函数用于启动 SystemServer 中的核心服务。
java
private void startCoreServices() {
// 追踪电池充电状态和电量。需要LightService
mSystemServiceManager.startService(BatteryService.class);
//跟踪应用程序使用状态
mSystemServiceManager.startService(UsageStatsService.class);
mActivityManagerService.setUsageStatsManager(
LocalServices.getService(UsageStatsManagerInternal.class));
// 跟踪可更新的WebView是否处于就绪状态,并监视更新安装。
if (mPackageManager.hasSystemFeature(PackageManager.FEATURE_WEBVIEW)) {
traceBeginAndSlog("StartWebViewUpdateService");
mWebViewUpdateService = mSystemServiceManager.startService(WebViewUpdateService.class);
traceEnd();
}
//跟踪并缓存设备状态。
mSystemServiceManager.startService(CachedDeviceStateService.class);
// 跟踪在Binder调用中花费的cpu时间
mSystemServiceManager.startService(BinderCallsStatsService.LifeCycle.class);
// 跟踪handlers中处理messages所花费的时间。
mSystemServiceManager.startService(LooperStatsService.Lifecycle.class);
//管理apk回滚
mSystemServiceManager.startService(RollbackManagerService.class);
// 用于捕获bugreport,adb bugreport 命令调用的就是这个服务
mSystemServiceManager.startService(BugreportManagerService.class);
// 管理Gpu和Gpu驱动的服务
mSystemServiceManager.startService(GpuService.class);
}
核心服务如下表所示:
服务名称 | 描述 |
---|---|
BatteryService | 追踪电池充电状态和电量 |
UsageStatsManagerInternal | 跟踪应用程序使用状态 |
WebViewUpdateService | 跟踪可更新的WebView是否处于就绪状态,并监视更新安装。 |
CachedDeviceStateService | 跟踪并缓存设备状态 |
BinderCallsStatsService | 跟踪在Binder调用中花费的cpu时间 |
LooperStatsService | 跟踪handlers中处理messages所花费的时间。 |
RollbackManagerService | 管理apk回滚 |
BugreportManagerService | 用于捕获bugreport |
GpuService | 管理Gpu和Gpu驱动 |
3.1.3 startOtherServices
startOtherServices 用于启动 SystemServer 中的其他服务,在这个方法中启动的服务比较多。
java
KeyAttestationApplicationIdProviderService/KeyChainSystemService
SchedulingPolicyService/TelecomLoaderService/TelephonyRegistry
mContentResolver = context.getContentResolver();
AccountManagerService/ContentService
mActivityManagerService.installSystemProviders();
DropBoxManagerService/VibratorService/ConsumerIrService/AlarmManagerService
final Watchdog watchdog = Watchdog.getInstance();
watchdog.init(context, mActivityManagerService);
InputManagerService/WindowManagerService/VrManagerService/BluetoothService
IpConnectivityMetrics/NetworkWatchlistService/PinnerService
InputMethodManagerService/AccessibilityManagerService/StorageManagerService
StorageStatsService/UiModeManagerService/LockSettingsService
PersistentDataBlockService/OemLockService/DeviceIdleController
DevicePolicyManagerService/StatusBarManagerService/ClipboardService
NetworkManagementService/IpSecService/TextServicesManagerService
TextClassificationManagerService/NetworkScoreService/NetworkStatsService
NetworkPolicyManagerService/WifiScanningService/RttService
WifiAware/WifiP2P/Lowpan/Ethernet/ConnectivityService/NsdService
SystemUpdateManagerService/UpdateLockService/NotificationManagerService
DeviceStorageMonitorService/LocationManagerService/CountryDetectorService
SearchManagerService/WallpaperManagerService/AudioService/BroadcastRadioService
DockObserver/ThermalObserver/WiredAccessoryManager/MidiManager/UsbService
SerialService/HardwarePropertiesManagerService/TwilightService
ColorDisplayService/JobSchedulerService/SoundTriggerService/TrustManagerService
BackupManager/AppWidgerService/VoiceRecognitionManager/GestureLauncherService
SensorNotificationService/ContextHubSystemService/DiskStatsService
TimeZoneRulesManagerService/NetworkTimeUpdateService/CommonTimeManagementService
CertBlacklister/EmergencyAffordanceService/DreamManagerService/GraphicsStatsService
CoverageService/PrintManager/CompanionDeviceManager/RestrictionsManagerService
MediaSessionService/MediaUpdateService/HdmiControlService/TvInputManagerService
MediaResourceMonitorService/TvRemoteService/MediaRouterService/FingerprintService
BackgroundDexOptService/PruneInstantAppsJobService/ShortcutService
LauncherAppsService/CrossProfileAppsService/MediaProjectionManagerService
WearConfigService/WearConnectivityService/WearTimeService/WearLeftyService
WearGlobalActionsService/SliceManagerService/CameraServiceProxy/IoTSystemService
MmsServiceBroker/AutoFillService
// It is now time to start up the app processes...
vibrator.systemReady();
lockSettings.systemReady();
// 480
mSystemServiceManager.startBootPhase(SystemService.PHASE_LOCK_SETTINGS_READY);
// 500
mSystemServiceManager.startBootPhase(SystemService.PHASE_SYSTEM_SERVICES_READY);
wm.systemReady();
mPowerManagerService.systemReady(mActivityManagerService.getAppOpsService());
mPackageManagerService.systemReady();
mDisplayManagerService.systemReady(safeMode, mOnlyCore);
// Start device specific services
final String[] classes = mSystemContext.getResources().getStringArray(
R.array.config_deviceSpecificSystemServices);
for (final String className : classes) {
try {
mSystemServiceManager.startService(className);
} catch (Throwable e) {
reportWtf("starting " + className, e);
}
}
// 520
mSystemServiceManager.startBootPhase(SystemService.PHASE_DEVICE_SPECIFIC_SERVICES_READY);
mActivityManagerService.systemReady(() -> {
// 550
mSystemServiceManager.startBootPhase(SystemService.PHASE_ACTIVITY_MANAGER_READY);
startSystemUi(context, windowManagerF);
networkManagementF.systemReady();
ipSecServiceF.systemReady();
networkStatsF.systemReady();
connectivityF.systemReady();
Watchdog.getInstance().start
mPackageManagerService.waitForAppDataPrepared();
// 600
mSystemServiceManager.startBootPhase(SystemService.PHASE_THIRD_PARTY_APPS_CAN_START);
locationF.systemRunning();
countryDetectorF.systemRunning();
networkTimeUpdaterF.systemRunning();
commonTimeMgmtServiceF.systemRunning();
inputManagerF.systemRunning();
telephonyRegistryF.systemRunning();
mediaRouterF.systemRunning();
mmsServiceF.systemRunning();
incident.systemRunning();
}
这部分启动的服务比较多,具体的服务如下图所示:
3.2 服务启动阶段
在服务的启动过程中,我们可以看到会调用 mSystemServiceManager.startBootPhase() 函数进行启动阶段的逻辑执行。
启动阶段定义在 android/frameworks/base/services/core/java/com/android/server/SystemService.java 文件中。
java
/*
* Boot Phases
*
* 启动阶段
*/
public static final int PHASE_WAIT_FOR_DEFAULT_DISPLAY = 100; // maybe should be a dependency?
/**
* After receiving this boot phase, services can obtain lock settings data.
*/
public static final int PHASE_LOCK_SETTINGS_READY = 480;
/**
* After receiving this boot phase, services can safely call into core system services
* such as the PowerManager or PackageManager.
*
* 在这个阶段之后,可以安全的调用系统核心服务,如 PowerManager 和 PackageManager
*/
public static final int PHASE_SYSTEM_SERVICES_READY = 500;
/**
* After receiving this boot phase, services can safely call into device specific services.
*
* 在这个阶段之后,可以安全调用设备特定的服务
*/
public static final int PHASE_DEVICE_SPECIFIC_SERVICES_READY = 520;
/**
* After receiving this boot phase, services can broadcast Intents.
*
* 在这个阶段之后,服务可以广播
*/
public static final int PHASE_ACTIVITY_MANAGER_READY = 550;
/**
* After receiving this boot phase, services can start/bind to third party apps.
* Apps will be able to make Binder calls into services at this point.
*
* 在这个阶段之后,服务可以启动/绑定第三方应用
* 应用此时可以进行 Binder 调用
*/
public static final int PHASE_THIRD_PARTY_APPS_CAN_START = 600;
/**
* After receiving this boot phase, services can allow user interaction with the device.
* This phase occurs when boot has completed and the home application has started.
* System services may prefer to listen to this phase rather than registering a
* broadcast receiver for ACTION_BOOT_COMPLETED to reduce overall latency.
*
* 在这个阶段之后,允许用户和设备交互。
* 这个阶段发生在启动完成,home 应用已经开始。
* 系统服务更倾向于监听这个阶段,而不是监听启动广播 ACTION_BOOT_COMPLETED,以降低延迟
*/
public static final int PHASE_BOOT_COMPLETED = 1000;
这些启动阶段会穿插在各项的服务启动序列中,每一个启动阶段节点的插入,都会伴随着该启动阶段节点之前的服务执行相关逻辑。
所以这里启动阶段节点相对于标识或者说依赖关系,即后续的启动阶段需要依赖于前面某些服务的特色处理逻辑之后才能进行。
在系统启动过程中,启动阶段的大致流程如下所示:
java
private void startBootstrapServices() {
...
// 100
mSystemServiceManager.startBootPhase(SystemService.PHASE_WAIT_FOR_DEFAULT_DISPLAY);
...
}
private void startOtherServices() {
...
// 480
mSystemServiceManager.startBootPhase(SystemService.PHASE_LOCK_SETTINGS_READY);
// 500
mSystemServiceManager.startBootPhase(SystemService.PHASE_SYSTEM_SERVICES_READY);
...
// 520
mSystemServiceManager.startBootPhase(SystemService.PHASE_DEVICE_SPECIFIC_SERVICES_READY);
mActivityManagerService.systemReady(() -> {
mSystemServiceManager.startBootPhase(
SystemService.PHASE_ACTIVITY_MANAGER_READY); // 550
...
mSystemServiceManager.startBootPhase(
SystemService.PHASE_THIRD_PARTY_APPS_CAN_START); // 600
}
}
// 最后的 SystemService.PHASE_BOOT_COMPLETED(1000) 在 AMS 的 finishBooting() 方法中调用。
系统通过 startBootPhase 函数去开启启动时的关键节点。
startBootPhase -> onBootPhase的设计,是对Service之间、以及Service对系统各阶段依赖性的一个处理。在启动过程中各阶段的优化工作上是一个切入点。
下面引用图为梳理服务角色的关系:
3.3 服务启动方式
SystemServiceManager.startService 函数在 SystemServer 中用于启动系统服务,我们来看下系统服务的启动方式。
java
public <T extends SystemService> T startService(Class<T> serviceClass) {
try {
// 获取服务名称
final String name = serviceClass.getName();
// 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<T> constructor = serviceClass.getConstructor(Context.class);
// 反射创建 service
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);
}
startService(service);
return service;
} finally {
Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
}
}
创建并启动一个系统服务。这个系统服务必须是 com.android.server.SystemService
的子类。根据参数传入的 Class
对象反射创建其实例,再调用重载方法 startService()
:
java
public void startService(@NonNull final SystemService service) {
// Register it.
mServices.add(service);
// Start it.
long time = SystemClock.elapsedRealtime();
try {
// 回调系统服务的 onStart() 方法
service.onStart();
} catch (RuntimeException ex) {
throw new RuntimeException("Failed to start service " + service.getClass().getName()
+ ": onStart threw an exception", ex);
}
warnIfTooLong(SystemClock.elapsedRealtime() - time, service, "onStart");
}
就两步。第一步,注册服务,mServices
是一个 ArrayList<SystemService>
对象,用来保存已经创建的系统服务。第二步,回调服务的 onStart()
方法,还是以 Installer
为例:
java
@Override
public void onStart() {
if (mIsolated) {
mInstalld = null;
} else {
connect();
}
}
这样一个服务就启动完成了。这是一种比较普遍的启动方式。
总结
final SystemService service) {
// Register it.
mServices.add(service);
// Start it.
long time = SystemClock.elapsedRealtime();
try {
// 回调系统服务的 onStart() 方法
service.onStart();
} catch (RuntimeException ex) {
throw new RuntimeException("Failed to start service " + service.getClass().getName()
- ": onStart threw an exception", ex);
}
warnIfTooLong(SystemClock.elapsedRealtime() - time, service, "onStart");
}
就两步。第一步,注册服务,`mServices` 是一个 `ArrayList<SystemService>` 对象,用来保存已经创建的系统服务。第二步,回调服务的 `onStart()` 方法,还是以 `Installer` 为例:
```java
@Override
public void onStart() {
if (mIsolated) {
mInstalld = null;
} else {
connect();
}
}
这样一个服务就启动完成了。这是一种比较普遍的启动方式。
总结
本篇文章主要描述了 Android 启动过程中 SystemServer 阶段的逻辑,从SystemServer 中服务展开描述,大致整理了 SystemServer 启动服务的流程、启动阶段、启动服务的方式等。从整体流程大致记录,具体细节仍需学习。本篇文章由于时间关系,引用内容较多,内容较为基本。