Android启动流程_SystemServer阶段

前言

上一篇文档我们描述了在 Android 启动流程中 Zygote 部分的内容,从 Zygote 的配置、启动、初始化等内容展开,描述了 Zygote 在 Android 启动中的功能逻辑。本篇文档将会继续 Android 启动流程的描述,从 SystemServer 进程的内容展开,继续了解 Android 是如何启动的。

正文

本篇文档将会从 SystemServer 进程的内容继续描述 Android 启动流程。对于 SystemServer 进程,主要是对服务的初始化顺序、重要服务列举、启动方式等方面展开,从整体的角度展开描述。

1、SystemServer 启动

SystemServer 启动从 main 函数开始运行,我们来看下此函数的逻辑:

public static void main(String[] args) {new SystemServer().run();
}

SystemServer 的 main 函数中初始化了 SystemServer 对象,并且调用 run 函数执行,下面我们来看下 run 函数的逻辑:

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);}// 未设置时区的话默认设为 GMTString 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 callsBinder.setWarnOnBlocking(true);// The system server should always load safe labelsPackageItemInfo.setForceSafeLabels(true);// Default to FULL within the system server.SQLiteGlobal.sDefaultSyncMode = SQLiteGlobal.SYNC_MODE_FULL;// Deactivate SQLiteCompatibilityWalFlags until settings provider is initializedSQLiteCompatibilityWalFlags.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 traceParcel.setStackTraceParceling(true);// 确保系统的 Binder 调用总是运行在前台优先级BinderInternal.disableBackgroundScheduling(true);// Increase the number of binder threads in system_serverBinderInternal.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. 创建主线程 LooperLooper.prepareMainLooper();Looper.getMainLooper().setSlowLogThresholdMs(SLOW_DISPATCH_THRESHOLD_MS, SLOW_DELIVERY_THRESHOLD_MS);// 初始化 native 服务,加载 libandroid_servers.soSystem.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 parallelizedSystemServerInitThreadPool.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)到该时间点所经过的秒数或毫秒数。时间戳可以用于记录事件发生的时间、计算时间间隔、进行时间排序等操作。

注意:时间戳的优点是具有唯一性和可比较性,不受时区和地域的影响(也就是说,在全世界任何时区,获取的时间戳都是一样的)。

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()+"");运行结果:153576000000015357600000000

相同时间对应不同的时区的时间,在转换成时间戳得到的值是一致的。

2.1.4 修改默认语言

  • 修改 PRODUCT_LOCALES 字段

在 /build/target/product/languages_full.mk 文件中 PRODUCT_LOCALES 字段定义了所有的语言,系统的默认语言是因为,第一位是 en_US,如果修改,可以将要修改的语言放在第一位,例如 zh_CN。

  • 修改device/{硬件平台}/{产品}/system.prop或者default.prop,加入:
[persist.sys.language]: [zh]
[persist.sys.country]: [CN]
  • 修改 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 通过如下三个函数进行各类服务的启动

startBootstrapServices(); // 4. 启动系统引导服务
startCoreServices();      // 5. 启动系统核心服务
startOtherServices();     // 6. 启动其他服务
3.1.1 startBootstrapServices

startBootstrapServices 函数用于启动系统引导服务,启动的内容如下所示:

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);// 启动服务 ActivityManagerServicemActivityManagerService = mSystemServiceManager.startService(ActivityManagerService.Lifecycle.class).getService();mActivityManagerService.setSystemServiceManager(mSystemServiceManager);mActivityManagerService.setInstaller(installer);// 启动服务 PowerManagerServicemPowerManagerService = mSystemServiceManager.startService(PowerManagerService.class);// Now that the power manager has been started, let the activity manager// initialize power management features.mActivityManagerService.initPowerManagement();// 启动服务 RecoverySystemServicemSystemServiceManager.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);// 启动服务 LightsServicemSystemServiceManager.startService(LightsService.class);// Package manager isn't started yet; need to use SysProp not hardware featureif (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);// 正在加密设备时只运行核心 appString 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;}// 启动服务 PackageManagerServiceif (!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();}}}// 启动服务 UserManagerServicemSystemServiceManager.startService(UserManagerService.LifeCycle.class);// 初始化属性 cache 以缓存包资源AttributeCache.init(mSystemContext);// 设置 AMSmActivityManagerService.setSystemProcess();// DisplayManagerService needs to setup android.display scheduling related policies// since setSystemProcess() would have overridden policies due to setProcessGroupmDisplayManagerService.setupSchedulerPolicies();// 启动服务 OverlayManagerServiceOverlayManagerService 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();}// 在单独的线程中启动 SensorServicemSensorServiceStart = SystemServerInitThreadPool.get().submit(() -> {TimingsTraceLog traceLog = new TimingsTraceLog(SYSTEM_SERVER_TIMING_ASYNC_TAG, Trace.TRACE_TAG_SYSTEM_SERVER);startSensorService();}, START_SENSOR_SERVICE);
}

启动的服务列表入下表所示:

服务名称描述
Installer负责apk安装相关的工作
DeviceIdentifiersPolicyService设备标识符策略服务
UriGrantsManagerServiceUri授权管理
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 中的核心服务。

private void startCoreServices() {// 追踪电池充电状态和电量。需要LightServicemSystemServiceManager.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 中的其他服务,在这个方法中启动的服务比较多。

KeyAttestationApplicationIdProviderService/KeyChainSystemService
SchedulingPolicyService/TelecomLoaderService/TelephonyRegistrymContentResolver = context.getContentResolver();AccountManagerService/ContentServicemActivityManagerService.installSystemProviders();DropBoxManagerService/VibratorService/ConsumerIrService/AlarmManagerServicefinal 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(() -> {// 550mSystemServiceManager.startBootPhase(SystemService.PHASE_ACTIVITY_MANAGER_READY);startSystemUi(context, windowManagerF);networkManagementF.systemReady();ipSecServiceF.systemReady();networkStatsF.systemReady();connectivityF.systemReady();Watchdog.getInstance().startmPackageManagerService.waitForAppDataPrepared();// 600mSystemServiceManager.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();
}

这部分启动的服务比较多,具体的服务如下图所示:

image.png

3.2 服务启动阶段

在服务的启动过程中,我们可以看到会调用 mSystemServiceManager.startBootPhase() 函数进行启动阶段的逻辑执行。

启动阶段定义在 android/frameworks/base/services/core/java/com/android/server/SystemService.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;

这些启动阶段会穿插在各项的服务启动序列中,每一个启动阶段节点的插入,都会伴随着该启动阶段节点之前的服务执行相关逻辑。

所以这里启动阶段节点相对于标识或者说依赖关系,即后续的启动阶段需要依赖于前面某些服务的特色处理逻辑之后才能进行。

在系统启动过程中,启动阶段的大致流程如下所示:

private void startBootstrapServices() {...// 100mSystemServiceManager.startBootPhase(SystemService.PHASE_WAIT_FOR_DEFAULT_DISPLAY);...
}private void startOtherServices() {...// 480mSystemServiceManager.startBootPhase(SystemService.PHASE_LOCK_SETTINGS_READY);// 500mSystemServiceManager.startBootPhase(SystemService.PHASE_SYSTEM_SERVICES_READY);...// 520mSystemServiceManager.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 中用于启动系统服务,我们来看下系统服务的启动方式。

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);// 反射创建 serviceservice = 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()

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 为例:

@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 启动服务的流程、启动阶段、启动服务的方式等。从整体流程大致记录,具体细节仍需学习。本篇文章由于时间关系,引用内容较多,内容较为基本。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/460950.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

一年期免费HTTPS证书:网络安全新选择

HTTPS证书的重要性 HTTPS证书&#xff0c;全称为安全套接字层/传输层安全协议证书&#xff0c;是一种在互联网上建立安全连接的数字证书。它通过公钥加密技术&#xff0c;对网站和用户之间的数据传输进行加密&#xff0c;有效防止数据被窃取或篡改&#xff0c;保障用户信息的安…

(实战)WebApi第10讲:Swagger配置、RESTful与路由重载

一、Swagger配置 1、导入SwashBuckle.AspNetCore包 2、在.NET Core 5框架里的startup.cs文件里配置swagger 3、在.NET Core 6框架里的Program.cs文件里配置swagger 二、RESTful风格&#xff1a;路由重载&#xff0c;HttpGet()括号中加参数 &#xff08;1&#xff09;原则&…

Pr 视频效果:闪光灯

视频效果/风格化/闪光灯 Stylize/Strobe Light 闪光灯 Strobe Light效果可用于在视频中创建闪烁或频闪的效果&#xff0c;类似于舞台上的频闪灯或摄影中的闪光灯。 ◆ ◆ ◆ 效果选项说明 通过调整各种参数&#xff0c;可以自定义闪光的颜色、频率、持续时间和混合模式&#…

Spring自动装配(特别版)

今天整理了一下Spring自动装配的过程,也突出了几个比较难以解答的问题.实践来求真知. 一. 自动装配过程 先按类型查找,若只有一个则直接返回如果找到多个,则匹配名字如果名字不一致,则报错. 二. 自动装配方式 构造器注入(推荐): 因为如果有一天脱离了Spring的环境,我们去使用…

力扣之612.平面上的最近距离

文章目录 1. 612.平面上的最近距离1.1 题目说明1.2 准备数据1.3 解法1.4 结果截图 1. 612.平面上的最近距离 1.1 题目说明 Point2D 表&#xff1a; ----------------- | Column Name | Type | ----------------- | x | int | | y | int | ----------------- (x, y) 是该表的…

Mac下载 安装MIMIC-IV 3.0数据集

参考blog MIMIC IV 3.0数据库安装方法_mimic数据下载-CSDN博客 MIMIC IV数据库安装&#xff08;二&#xff09;_mimic数据库安装-CSDN博客 MIMIC-IV3.0安装_mimic iv 3.0-CSDN博客 MIMIC-IV-v2.0安装教程_mimic iv 安装教程-CSDN博客 MIMIC IV 3.0数据库安装方法或者思路&…

java项目之教师工作量管理系统源码(springboot)

风定落花生&#xff0c;歌声逐流水&#xff0c;大家好我是风歌&#xff0c;混迹在java圈的辛苦码农。今天要和大家聊的是一款基于springboot的教师工作量管理系统。项目源码以及部署相关请联系风歌&#xff0c;文末附上联系信息 。 项目简介&#xff1a; 教师工作量管理系统的…

12. MapReduce全局计数器

一. 计数器概述 在执行MapReduce程序时&#xff0c;控制台的输出中一般会包含如下内容。 这些输出就是MapReduce的全局计数器的输出信息。计数器是用来记录job的执行进度和状态的&#xff0c;它的作用可以理解为日志&#xff0c;方便用户了解任务的执行状况&#xff0c;辅助…

STM32F103C8T6 IO 操作

1.开启相关时钟 在 STM32 微控制器中&#xff0c;开启 GPIO 端口的时钟是确保 IO 口可以正常工作的第一步。 查找 RCC 寄存器使能时钟 在 STM32 中&#xff0c;时钟控制的寄存器通常位于 RCC (Reset and Clock Control) 模块中。不同的 STM32 系列&#xff08;如 STM32F1、STM…

使用LangChain控制大模型的输出——解析器Parser

LangChain框架中有两个好用的工具&#xff1a; 提示词模板(PromptTemplate)用于指定LLM的输入&#xff0c;解析器(Parser)来正确解释LLM给出的输出 即&#xff1a; 提示词模板(PromptTemplate)&#xff1a;用于格式化地接受输入string变量&#xff0c;作为完整的提示词。 如 给…

架构的本质之 MVC 架构

前言 程序员习惯的编程方式就是三步曲。 所以&#xff0c;为了不至于让一个类撑到爆&#x1f4a5;&#xff0c;需要把黄色的对象、绿色的方法、红色的接口&#xff0c;都分配到不同的包结构下。这就是你编码人生中所接触到的第一个解耦操作。 分层框架 MVC 是一种非常常见且常…

VScode + PlatformIO 了解

​Visual Studio Code Visual Studio Code&#xff08;简称 VS Code&#xff09;是一款由微软开发且跨平台的免费源代码编辑器。该软件以扩展的方式支持语法高亮、代码自动补全&#xff08;又称 IntelliSense&#xff09;、代码重构功能&#xff0c;并且内置了工具和 Git 版本…

微信公众号(或微信浏览器)获取openId(网页授权)

下单支付需要openId 首先授权去拿到code --然后调用后太换取openId 1.去拿取code 下图中执行到window.location.href &#xff08; redirect_uri 传入当前路径-&#xff09;–执行后重新跳转到当前页面–但是路径上会带上code参数 //然后调用后台方法–将code传给后台得到 o…

Steam deck 倒腾日记 - 安装Windows软件,玩上黑神话悟空

Steam deck 倒腾日记 关于Steam Deck基本信息性能特点游戏兼容性 问题一: 软键盘输入问题二: 系统切换问题三: 安装运行Window 软件关于Proton如何运行 问题四: 优化网络问题黑神话.悟空PS参考 关于Steam Deck Steam Deck是一款由Valve开发的便携式游戏PC&#xff0c;它搭载了A…

人工智能的前世今生:从幻想走向现实

在科技飞速发展的今天&#xff0c;人工智能&#xff08;AI&#xff09;已经成为我们生活中不可或缺的一部分。从智能手机的语音助手到自动驾驶汽车&#xff0c;AI的应用无处不在。但是&#xff0c;人工智能的发展历程并非一帆风顺&#xff0c;它经历了从兴起、寒冬到复兴的曲折…

ARM base instruction -- bfc

Bitfield Clear sets a bitfield of <width> bits at bit position <lsb> of the destination register to zero, leaving the other destination bits unchanged. 位域清除将目标寄存器位位置<lsb>处<width>位的位域设置为零&#xff0c;而保留其他目…

预处理详解(一)

目录 预定义符号define定义常量define定义宏宏替换的规则宏与函数的对比 预定义符号 C语⾔设置了⼀些预定义符号&#xff0c;可以直接使用&#xff0c;预定义符号也是在预处理期间处理的。 __FILE__ //进⾏编译的源⽂件 __LINE__ //⽂件当前的⾏号 __DATE__ //⽂件被编译的⽇…

2024-10-30 学习人工智能的Day18

Python包和模块 当使用Python编程时&#xff0c;包&#xff08;Packages&#xff09;和模块&#xff08;Modules&#xff09;是两个关键的概念&#xff0c;它们有助于组织、管理和复用代码。 1. 模块&#xff08;Modules&#xff09; 1.1 什么是模块 一个.py 文件就是一个模…

从 TCP 友好性看传输优化

再看一遍最传统 TCP AIMD 吞吐的推导&#xff1a; 这个积分用离散求和表示很简单&#xff0c;一个锯齿发送的报文总数为&#xff1a; ( W 2 0 ) ( W 2 1 ) ( W 2 2 ) . . . ( W 2 ( W − W 2 ) ) ≈ 3 ⋅ W 2 8 (\dfrac{W}{2}0)(\dfrac{W}{2}1)(\dfrac{W}{2}2)...(\df…

css 对称按钮,中间斜平行间隔,两头半圆

序&#xff1a;稍一看&#xff0c;挺好看&#xff0c;看也简单&#xff0c;实现起来应该也是一样&#xff0c;没什么难度&#xff0c;分分钟完成。后面将其他的UI做了七七八八后&#xff0c;到这个按钮的时候&#xff0c;不知怎么&#xff0c;突然卡机了&#xff0c;想不起来怎…