一、Android Shutdown Process OverView
二、Android Shutdown Process
这里简单梳理下当我们长按power键后,系统事件监听服务InputManagerService会通过一系列的消息传递通过PhoneWindowManager调用LegacyGlobalActions来显示关机界面,我们通选择关机,系统此时会调用ShutdownThread弹出一个对话框,当我们点击“确认”按钮时,开始真正意义上进入关机流程。这里从我们点击“确认”按钮开始简单梳理下Android oreo 关机流程。
2.1 ShutdownThread
2.1.1 shutdownInner()//除了按键,我们可以通过很多方式调用PM的api来执行关机流程,比如从RecoverySystem调用相关api执行重启进行恢厂操作等。但是最后总都会走到这个函数,所以我们由此函数进行梳理;由于我们通过长按power键来梳理,所以此时在这个函数中会创建一个对话框AlertDialog,来调用beginShutdownSequence来开始真正意义上的关机流程;
2.1.2 beginShutdownSequence()
2.1.2.1 获取wake锁,来确保关机过程中不会进入休眠状态;
sInstance.mCpuWakeLock = null;
try {
sInstance.mCpuWakeLock = sInstance.mPowerManager.newWakeLock(
PowerManager.PARTIAL_WAKE_LOCK, TAG + "-cpu");
sInstance.mCpuWakeLock.setReferenceCounted(false);
sInstance.mCpuWakeLock.acquire();
} catch (SecurityException e) {
Log.w(TAG, "No permission to acquire wake lock", e);
sInstance.mCpuWakeLock = null;
}
2.1.2.1 获取ScreenWakeLock锁,来确保关机过程中不会灭屏;
sInstance.mScreenWakeLock = null;
if (sInstance.mPowerManager.isScreenOn()) {
try {
sInstance.mScreenWakeLock = sInstance.mPowerManager.newWakeLock(
PowerManager.FULL_WAKE_LOCK, TAG + "-screen");
sInstance.mScreenWakeLock.setReferenceCounted(false);
sInstance.mScreenWakeLock.acquire();
} catch (SecurityException e) {
Log.w(TAG, "No permission to acquire wake lock", e);
sInstance.mScreenWakeLock = null;
}
}
2.1.2.3启动关机线程实例
sInstance.start()
2.1.3 启动关机线程
2.1.3.1 发送有序的关机广播,如果发送过程超过10s,这认为广播发送超时。
Intent intent = new Intent(Intent.ACTION_SHUTDOWN);
intent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND
| Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND);
mContext.sendOrderedBroadcastAsUser(intent,
UserHandle.ALL, null, br, mHandler, 0, null, null);
通过Log.w(TAG, "Shutdown broadcast timed out");我们可以确认广播是否发送超时;
2.1.3.2 通知AMS执行相关关机操作
am.shutdown(MAX_BROADCAST_TIME);
2.1.3.3 通知PMS执行相关关机操作
pm.shutdown();
2.1.3.4 关闭Radios,并设置超时
shutdownRadios(MAX_RADIO_WAIT_TIME);
2.1.3.4 通知StorageManagerService执行相关关机流程
2.1.3.5 调用rebootOrShutdown函数来判断当前是关机还是重启,最终通过PowerManagerService的logLwevelShutdown()函数来处理接下来的流程。
2.1.4 lowLevelShutdown()或lowLevelReboot()
该函数通过设置sys.powerctl属性的值来触发关机
2.2 init
当属性服务(/system/core/init/property_service.cpp)监测到属性发生变化时会调用init.cpp中的property_change()函数进行值为sys.powerctl的key进行校验,将flag标示为do_shutdown的值设置为true;随后进入init.cpp的main函数中的loop,最终调用HandlePowerctlMessage进行处理。
3.3 reboot
/system/core/init/reboot.cpp
HandlePowerctlMessage函数调用DoReboot函数,在DoReboot中中止系统服务的运行,并通过RebootSystem进入kernle层。
三、Android Shutdown Process vital log
Log.d(TAG, "Notifying thread to start shutdown longPressBehavior=" + longPressBehavior);
shutdownTimingLog.traceBegin("SystemServerShutdown");
Log.i(TAG, "Sending shutdown broadcast...");
Log.w(TAG, "Shutdown broadcast timed out");
Log.i(TAG, "Shutting down activity manager...");
Log.i(TAG, "Shutting down package manager...");
shutdownTimingLog.traceBegin("ShutdownRadios");
Log.i(TAG, "Shutting down StorageManagerService");
Log.i(TAG, "Performing low-level shutdown...");
LOG(INFO) << "Clear action queue and start shutdown trigger";
LOG(INFO) << "Reboot start, reason: " << reason << ", rebootTarget: " << rebootTarget;
LOG(INFO) << "Shutdown timeout: " << shutdown_timeout.count() << " ms";
LOG(INFO) << "terminating init services";
LOG(INFO) << "Terminating running services took " << t
<< " with remaining services:" << service_count;
LOG(INFO) << "Reboot ending, jumping to kernel";