Android 9.0 关机流程分析

极力推荐文章:欢迎收藏
Android 干货分享

阅读五分钟,每日十点,和您一起终身学习,这里是程序员Android
本篇文章主要介绍 Android 开发中的部分知识点,通过阅读本篇文章,您将收获以下内容:
1.ShutdownThread 概述
2.shutdown 关机方法
3.shutdownInner 方法实现
4.CloseDialogReceiver 注册关机对话框广播
5.new sConfirmDialog 显示关机对话框
6.beginShutdownSequence开始关机流程
7.showShutdownDialog 显示关机进度对话框
8.判断是否显示SystemUIReboot
9.启动 关机线程 ,执行 Run 方法
10.shutdownRadios 关闭Radio 实现
11.rebootOrShutdown 初始化并决定关机还是重启
12.关机log 分析
1.ShutdownThread 概述
关机线程实现类
Android 关机线程实现类frameworks/base/services/core/java/com/android/server/power/ShutdownThread.java
ShutdownThread 大致流程

ShutdownThread 部分静态变量如下:
public final class ShutdownThread extends Thread {
// constants
private static final String TAG = "ShutdownThread";
private static final int ACTION_DONE_POLL_WAIT_MS = 500;
private static final int RADIOS_STATE_POLL_SLEEP_MS = 100;
// maximum time we wait for the shutdown broadcast before going on.
private static final int MAX_BROADCAST_TIME = 10*1000;
private static final int MAX_SHUTDOWN_WAIT_TIME = 20*1000;
private static final int MAX_RADIO_WAIT_TIME = 12*1000;
private static final int MAX_UNCRYPT_WAIT_TIME = 15*60*1000;
// constants for progress bar. the values are roughly estimated based on timeout.
private static final int BROADCAST_STOP_PERCENT = 2;
private static final int ACTIVITY_MANAGER_STOP_PERCENT = 4;
private static final int PACKAGE_MANAGER_STOP_PERCENT = 6;
private static final int RADIO_STOP_PERCENT = 18;
private static final int MOUNT_SERVICE_STOP_PERCENT = 20;
// Time we should wait for vendor subsystem shutdown
// Sleep times(ms) between checks of the vendor subsystem state
private static final int VENDOR_SUBSYS_STATE_CHECK_INTERVAL_MS = 100;
// Max time we wait for vendor subsystems to shut down before resuming
// with full system shutdown
private static final int VENDOR_SUBSYS_MAX_WAIT_MS = 10000;
// length of vibration before shutting down
private static final int SHUTDOWN_VIBRATE_MS = 500;
... ...
}
ShutdownThread 无参构造方法
private ShutdownThread() {
}
2. shutdown 关机方法
长按 ·Power· 键调用 shutdown 方法,通过调用内部shutdownInner方法,实现 弹出 关机 、重启对话框,供用户选择关机 或者重启。
/**
* Request a clean shutdown, waiting for subsystems to clean up their
* state etc. Must be called from a Looper thread in which its UI
* is shown.
*
* @param context Context used to display the shutdown progress dialog. This must be a context
* suitable for displaying UI (aka Themable).
* @param reason code to pass to android_reboot() (e.g. "userrequested"), or null.
* @param confirm true if user confirmation is needed before shutting down.
*/
public static void shutdown(final Context context, String reason, boolean confirm) {
mReboot = false;
mRebootSafeMode = false;
mReason = reason;
shutdownInner(context, confirm); // 详见分析3
}
3.shutdownInner 方法实现
shutdownInner 主要作用是
1.获取用户关机 Behavior。
2.注册关机广播,详见4.
3.创建关机Dialog。
4.执行一系列关机流程。
private static void shutdownInner(final Context context, boolean confirm) {
// ShutdownThread is called from many places, so best to verify here that the context passed
// in is themed.
context.assertRuntimeOverlayThemable();
// ensure that only one thread is trying to power down.
// any additional calls are just returned
synchronized (sIsStartedGuard) {
if (sIsStarted) {
Log.d(TAG, "Request to shutdown already running, returning.");
return;
}
}
// 获取用户长按Power键的处理行为
final int longPressBehavior = context.getResources().getInteger(
com.android.internal.R.integer.config_longPressOnPowerBehavior);
final int resourceId = mRebootSafeMode
? com.android.internal.R.string.reboot_safemode_confirm
: (longPressBehavior == 2
? com.android.internal.R.string.shutdown_confirm_question
: com.android.internal.R.string.shutdown_confirm);
Log.d(TAG, "Notifying thread to start shutdown longPressBehavior=" + longPressBehavior);
if (confirm) {
//注册关机对话框广播 详细实现见 4
final CloseDialogReceiver closer = new CloseDialogReceiver(context);
if (sConfirmDialog != null) {
sConfirmDialog.dismiss();
}
// 创建关机Dialg 详见 实现5
sConfirmDialog = new AlertDialog.Builder(context)
.setTitle(mRebootSafeMode
? com.android.internal.R.string.reboot_safemode_title
: com.android.internal.R.string.power_off)
.setMessage(resourceId)
.setPositiveButton(com.android.internal.R.string.yes, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
// 开始一系列的关机流程,详见 6
beginShutdownSequence(context);
}
})
.setNegativeButton(com.android.internal.R.string.no, null)
.create();
closer.dialog = sConfirmDialog;
sConfirmDialog.setOnDismissListener(closer);
sConfirmDialog.getWindow().setType(WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG);
sConfirmDialog.show();
} else {
beginShutdownSequence(context);
}
}
其中 config_longPressOnPowerBehavior 用来控制用户长按Power键触发的行为。
主要行为如下:
<!-- Control the behavior when the user long presses the power button.
0 - Nothing
1 - Global actions menu
2 - Power off (with confirmation)
3 - Power off (without confirmation)
4 - Go to voice assist
-->
<integer name="config_longPressOnPowerBehavior">1</integer>
此源码 可以在 config.xml中查看,代码目录如下:frameworks\base\core\res\res\values\config.xml
4.CloseDialogReceiver 注册关机对话框广播
注册action 为ACTION_CLOSE_SYSTEM_DIALOGS广播接收器。
private static class CloseDialogReceiver extends BroadcastReceiver
implements DialogInterface.OnDismissListener {
private Context mContext;
public Dialog dialog;
CloseDialogReceiver(Context context) {
mContext = context;
IntentFilter filter = new IntentFilter(Intent.ACTION_CLOSE_SYSTEM_DIALOGS);
context.registerReceiver(this, filter);
}
@Override
public void onReceive(Context context, Intent intent) {
dialog.cancel();
}
public void onDismiss(DialogInterface unused) {
mContext.unregisterReceiver(this);
}
}
5. new sConfirmDialog 显示关机对话框
Android 原生关机对话框如下:

// 创建关机Dialg 详见 实现5
sConfirmDialog = new AlertDialog.Builder(context)
.setTitle(mRebootSafeMode
? com.android.internal.R.string.reboot_safemode_title
: com.android.internal.R.string.power_off)
.setMessage(resourceId)
.setPositiveButton(com.android.internal.R.string.yes, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
// 开始一系列的关机流程,详见 6
beginShutdownSequence(context);
}
})
.setNegativeButton(com.android.internal.R.string.no, null)
.create();
closer.dialog = sConfirmDialog;
sConfirmDialog.setOnDismissListener(closer);
sConfirmDialog.getWindow().setType(WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG);
sConfirmDialog.show();
6. beginShutdownSequence开始关机流程
beginShutdownSequence 开始一系列关机流程,主要功能如下:
1.显示关机进度条对话框。
2.启动ShutdownThead 线程。
private static void beginShutdownSequence(Context context) {
synchronized (sIsStartedGuard) {
if (sIsStarted) {
Log.d(TAG, "Shutdown sequence already running, returning.");
return;
}
sIsStarted = true;
}
// 显示关机进度对话框 详见 7
sInstance.mProgressDialog = showShutdownDialog(context);
sInstance.mContext = context;
sInstance.mPowerManager = (PowerManager)context.getSystemService(Context.POWER_SERVICE);
// make sure we never fall asleep again
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;
}
// also make sure the screen stays on for better user experience
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;
}
}
if (SecurityLog.isLoggingEnabled()) {
SecurityLog.writeEvent(SecurityLog.TAG_OS_SHUTDOWN);
}
// 启动 关机线程 ,执行 Run 方法,详见 9
sInstance.mHandler = new Handler() {
};
sInstance.start();
}
7.showShutdownDialog 显示关机进度对话框
showShutdownDialog 主要用来显示关机进度对话框
private static ProgressDialog showShutdownDialog(Context context) {
// Throw up a system dialog to indicate the device is rebooting / shutting down.
ProgressDialog pd = new ProgressDialog(context);
// Path 1: Reboot to recovery for update
// Condition: mReason startswith REBOOT_RECOVERY_UPDATE
//
// Path 1a: uncrypt needed
// Condition: if /cache/recovery/uncrypt_file exists but
// /cache/recovery/block.map doesn't.
// UI: determinate progress bar (mRebootHasProgressBar == True)
//
// * Path 1a is expected to be removed once the GmsCore shipped on
// device always calls uncrypt prior to reboot.
//
// Path 1b: uncrypt already done
// UI: spinning circle only (no progress bar)
//
// Path 2: Reboot to recovery for factory reset
// Condition: mReason == REBOOT_RECOVERY
// UI: spinning circle only (no progress bar)
//
// Path 3: Regular reboot / shutdown
// Condition: Otherwise
// UI: spinning circle only (no progress bar)
// mReason could be "recovery-update" or "recovery-update,quiescent".
if (mReason != null && mReason.startsWith(PowerManager.REBOOT_RECOVERY_UPDATE)) {
// We need the progress bar if uncrypt will be invoked during the
// reboot, which might be time-consuming.
mRebootHasProgressBar = RecoverySystem.UNCRYPT_PACKAGE_FILE.exists()
&& !(RecoverySystem.BLOCK_MAP_FILE.exists());
pd.setTitle(context.getText(com.android.internal.R.string.reboot_to_update_title));
if (mRebootHasProgressBar) {
pd.setMax(100);
pd.setProgress(0);
pd.setIndeterminate(false);
pd.setProgressNumberFormat(null);
pd.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
pd.setMessage(context.getText(
com.android.internal.R.string.reboot_to_update_prepare));
} else {
if (showSysuiReboot()) {
return null;
}
pd.setIndeterminate(true);
pd.setMessage(context.getText(
com.android.internal.R.string.reboot_to_update_reboot));
}
} else if (mReason != null && mReason.equals(PowerManager.REBOOT_RECOVERY)) {
if (RescueParty.isAttemptingFactoryReset()) {
// We're not actually doing a factory reset yet; we're rebooting
// to ask the user if they'd like to reset, so give them a less
// scary dialog message.
pd.setTitle(context.getText(com.android.internal.R.string.power_off));
pd.setMessage(context.getText(com.android.internal.R.string.shutdown_progress));
pd.setIndeterminate(true);
} else {
// Factory reset path. Set the dialog message accordingly.
pd.setTitle(context.getText(com.android.internal.R.string.reboot_to_reset_title));
pd.setMessage(context.getText(
com.android.internal.R.string.reboot_to_reset_message));
pd.setIndeterminate(true);
}
} else {
// 判断是否显示SystemUIReboot 详见 8
if (showSysuiReboot()) {
return null;
}
// 显示关机 进度对话框 详见 8
pd.setTitle(context.getText(com.android.internal.R.string.power_off));
pd.setMessage(context.getText(com.android.internal.R.string.shutdown_progress));
pd.setIndeterminate(true);
}
pd.setCancelable(false);
pd.getWindow().setType(WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG);
pd.show();
return pd;
}
关机 进度对话框实现

8.判断是否显示SystemUIReboot
showSysuiReboot 主要用来显示是否显示SystemUIReboot.
private static boolean showSysuiReboot() {
Log.d(TAG, "Attempting to use SysUI shutdown UI");
try {
StatusBarManagerInternal service = LocalServices.getService(
StatusBarManagerInternal.class);
if (service.showShutdownUi(mReboot, mReason)) {
// Sysui will handle shutdown UI.
Log.d(TAG, "SysUI handling shutdown UI");
return true;
}
} catch (Exception e) {
// If anything went wrong, ignore it and use fallback ui
}
Log.d(TAG, "SysUI is unavailable");
return false;
}
9.启动 关机线程 ,执行 Run 方法
在beginShutdownSequence方法中启动 关机线程。
private static void beginShutdownSequence(Context context) {
... ...
// static instance of this thread
private static final ShutdownThread sInstance = new ShutdownThread();
// start the thread that initiates shutdown
sInstance.mHandler = new Handler() {
};
sInstance.start();
... ...
}
ShutdownThread Run 实现
ShutdownThread 主要作用:
1.发送有序的关机广播。
2.测量关闭某些项目的时间。
3.关闭 ActivityManager。
4.关闭PackageManager。
5.关闭 Radios。
6.完成System Server 的关闭。
7.初始化并判定执行关机还是重启
/**
* Makes sure we handle the shutdown gracefully.
* Shuts off power regardless of radio state if the allotted time has passed.
*/
public void run() {
TimingsTraceLog shutdownTimingLog = newTimingsLog();
shutdownTimingLog.traceBegin("SystemServerShutdown");
metricShutdownStart();
metricStarted(METRIC_SYSTEM_SERVER);
BroadcastReceiver br = new BroadcastReceiver() {
@Override public void onReceive(Context context, Intent intent) {
// We don't allow apps to cancel this, so ignore the result.
actionDone();
}
};
/*
* Write a system property in case the system_server reboots before we
* get to the actual hardware restart. If that happens, we'll retry at
* the beginning of the SystemServer startup.
*/
{
String reason = (mReboot ? "1" : "0") + (mReason != null ? mReason : "");
SystemProperties.set(SHUTDOWN_ACTION_PROPERTY, reason);
}
/*
* If we are rebooting into safe mode, write a system property
* indicating so.
*/
if (mRebootSafeMode) {
SystemProperties.set(REBOOT_SAFEMODE_PROPERTY, "1");
}
metricStarted(METRIC_SEND_BROADCAST);
shutdownTimingLog.traceBegin("SendShutdownBroadcast");
Log.i(TAG, "Sending shutdown broadcast...");
// First send the high-level shut down broadcast.
mActionDone = false;
Intent intent = new Intent(Intent.ACTION_SHUTDOWN);
intent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND | Intent.FLAG_RECEIVER_REGISTERED_ONLY);
// 发送 有序的 关机广播
mContext.sendOrderedBroadcastAsUser(intent,
UserHandle.ALL, null, br, mHandler, 0, null, null);
final long endTime = SystemClock.elapsedRealtime() + MAX_BROADCAST_TIME;
synchronized (mActionDoneSync) {
while (!mActionDone) {
long delay = endTime - SystemClock.elapsedRealtime();
if (delay <= 0) {
Log.w(TAG, "Shutdown broadcast timed out");
break;
} else if (mRebootHasProgressBar) {
int status = (int)((MAX_BROADCAST_TIME - delay) * 1.0 *
BROADCAST_STOP_PERCENT / MAX_BROADCAST_TIME);
sInstance.setRebootProgress(status, null);
}
try {
mActionDoneSync.wait(Math.min(delay, ACTION_DONE_POLL_WAIT_MS));
} catch (InterruptedException e) {
}
}
}
if (mRebootHasProgressBar) {
sInstance.setRebootProgress(BROADCAST_STOP_PERCENT, null);
}
// 测量 发送有序 关机广播所用的时间
shutdownTimingLog.traceEnd(); // SendShutdownBroadcast
metricEnded(METRIC_SEND_BROADCAST);
Log.i(TAG, "Shutting down activity manager...");
shutdownTimingLog.traceBegin("ShutdownActivityManager");
metricStarted(METRIC_AM);
// 关闭 Activity Manager
final IActivityManager am =
IActivityManager.Stub.asInterface(ServiceManager.checkService("activity"));
if (am != null) {
try {
am.shutdown(MAX_BROADCAST_TIME);
} catch (RemoteException e) {
}
}
if (mRebootHasProgressBar) {
sInstance.setRebootProgress(ACTIVITY_MANAGER_STOP_PERCENT, null);
}
shutdownTimingLog.traceEnd();// ShutdownActivityManager
metricEnded(METRIC_AM);
Log.i(TAG, "Shutting down package manager...");
shutdownTimingLog.traceBegin("ShutdownPackageManager");
metricStarted(METRIC_PM);
// 关闭 Package Manager
final PackageManagerService pm = (PackageManagerService)
ServiceManager.getService("package");
if (pm != null) {
pm.shutdown();
}
if (mRebootHasProgressBar) {
sInstance.setRebootProgress(PACKAGE_MANAGER_STOP_PERCENT, null);
}
shutdownTimingLog.traceEnd(); // ShutdownPackageManager
metricEnded(METRIC_PM);
// Shutdown radios.
shutdownTimingLog.traceBegin("ShutdownRadios");
metricStarted(METRIC_RADIOS);
//关闭 Radios shutdownRadios 详细 请看 10
shutdownRadios(MAX_RADIO_WAIT_TIME);
if (mRebootHasProgressBar) {
sInstance.setRebootProgress(RADIO_STOP_PERCENT, null);
}
shutdownTimingLog.traceEnd(); // ShutdownRadios
metricEnded(METRIC_RADIOS);
// 关闭 System Server
if (mRebootHasProgressBar) {
sInstance.setRebootProgress(MOUNT_SERVICE_STOP_PERCENT, null);
// If it's to reboot to install an update and uncrypt hasn't been
// done yet, trigger it now.
uncrypt();
}
shutdownTimingLog.traceEnd(); // SystemServerShutdown
metricEnded(METRIC_SYSTEM_SERVER);
saveMetrics(mReboot, mReason);
//初始化 并判断是关机还是重启 详见 11
rebootOrShutdown(mContext, mReboot, mReason);
}
10.shutdownRadios 关闭Radio 实现
shutdownRadios 用来关闭phone Radio相关内容 ,主要实现如下:
private void shutdownRadios(final int timeout) {
// If a radio is wedged, disabling it may hang so we do this work in another thread,
// just in case.
final long endTime = SystemClock.elapsedRealtime() + timeout;
final boolean[] done = new boolean[1];
//另起线程 异步关闭 Radios
Thread t = new Thread() {
public void run() {
TimingsTraceLog shutdownTimingsTraceLog = newTimingsLog();
boolean radioOff;
final ITelephony phone =
ITelephony.Stub.asInterface(ServiceManager.checkService("phone"));
try {
radioOff = phone == null || !phone.needMobileRadioShutdown();
if (!radioOff) {
Log.w(TAG, "Turning off cellular radios...");
metricStarted(METRIC_RADIO);
phone.shutdownMobileRadios();
}
} catch (RemoteException ex) {
Log.e(TAG, "RemoteException during radio shutdown", ex);
radioOff = true;
}
Log.i(TAG, "Waiting for Radio...");
long delay = endTime - SystemClock.elapsedRealtime();
while (delay > 0) {
if (mRebootHasProgressBar) {
int status = (int)((timeout - delay) * 1.0 *
(RADIO_STOP_PERCENT - PACKAGE_MANAGER_STOP_PERCENT) / timeout);
status += PACKAGE_MANAGER_STOP_PERCENT;
sInstance.setRebootProgress(status, null);
}
if (!radioOff) {
try {
radioOff = !phone.needMobileRadioShutdown();
} catch (RemoteException ex) {
Log.e(TAG, "RemoteException during radio shutdown", ex);
radioOff = true;
}
if (radioOff) {
Log.i(TAG, "Radio turned off.");
metricEnded(METRIC_RADIO);
shutdownTimingsTraceLog
.logDuration("ShutdownRadio", TRON_METRICS.get(METRIC_RADIO));
}
}
if (radioOff) {
Log.i(TAG, "Radio shutdown complete.");
done[0] = true;
break;
}
SystemClock.sleep(RADIOS_STATE_POLL_SLEEP_MS);
delay = endTime - SystemClock.elapsedRealtime();
}
}
};
//另起线程 异步关闭 Radios
t.start();
try {
t.join(timeout);
} catch (InterruptedException ex) {
}
if (!done[0]) {
Log.w(TAG, "Timed out waiting for Radio shutdown.");
}
}
11.rebootOrShutdown 初始化并决定关机还是重启
rebootOrShutdown主要用来 初始化并决定关机还是重启。
/**
* Do not call this directly. Use {@link #reboot(Context, String, boolean)}
* or {@link #shutdown(Context, String, boolean)} instead.
*
* @param context Context used to vibrate or null without vibration
* @param reboot true to reboot or false to shutdown
* @param reason reason for reboot/shutdown
*/
public static void rebootOrShutdown(final Context context, boolean reboot, String reason) {
String subsysProp;
subsysProp = SystemProperties.get("vendor.peripheral.shutdown_critical_list",
"ERROR");
//If we don't have the shutdown critical subsystem list we can't
//really do anything. Proceed with full system shutdown.
if (!subsysProp.equals("ERROR")) {
Log.i(TAG, "Shutdown critical subsyslist is :"+subsysProp+": ");
Log.i(TAG, "Waiting for a maximum of " +
(VENDOR_SUBSYS_MAX_WAIT_MS) + "ms");
String[] subsysList = subsysProp.split(" ");
int wait_count = 0;
boolean okToShutdown = true;
String subsysState;
int subsysListLength = subsysList.length;
do {
okToShutdown = true;
for (int i = 0; i < subsysListLength; i++) {
subsysState =
SystemProperties.get(
"vendor.peripheral." +
subsysList[i] +
".state",
"ERROR");
if(subsysState.equals("ONLINE")) {
//We only want to delay shutdown while
//one of the shutdown critical
//subsystems still shows as 'ONLINE'.
okToShutdown = false;
}
}
if (okToShutdown == false) {
SystemClock.sleep(VENDOR_SUBSYS_STATE_CHECK_INTERVAL_MS);
wait_count++;
}
} while (okToShutdown != true &&
wait_count < (VENDOR_SUBSYS_MAX_WAIT_MS/VENDOR_SUBSYS_STATE_CHECK_INTERVAL_MS));
if (okToShutdown != true) {
for (int i = 0; i < subsysList.length; i++) {
subsysState =
SystemProperties.get(
"vendor.peripheral." +
subsysList[i] +
".state",
"ERROR");
if(subsysState.equals("ONLINE")) {
Log.w(TAG, "Subsystem " + subsysList[i]+
"did not shut down within timeout");
}
}
} else {
Log.i(TAG, "Vendor subsystem(s) shutdown successful");
}
}
if (reboot) {
Log.i(TAG, "Rebooting, reason: " + reason);
PowerManagerService.lowLevelReboot(reason);
Log.e(TAG, "Reboot failed, will attempt shutdown instead");
reason = null;
} else if (SHUTDOWN_VIBRATE_MS > 0 && context != null) {
// vibrate before shutting down
Vibrator vibrator = new SystemVibrator(context);
try {
vibrator.vibrate(SHUTDOWN_VIBRATE_MS, VIBRATION_ATTRIBUTES);
} catch (Exception e) {
// Failure to vibrate shouldn't interrupt shutdown. Just log it.
Log.w(TAG, "Failed to vibrate during shutdown.", e);
}
// vibrator is asynchronous so we need to wait to avoid shutting down too soon.
try {
Thread.sleep(SHUTDOWN_VIBRATE_MS);
} catch (InterruptedException unused) {
}
}
// Shutdown power
Log.i(TAG, "Performing low-level shutdown...");
PowerManagerService.lowLevelShutdown(reason);
}
12. 关机log 分析
通过 链接adb,我们可以抓取关机的Log, 部分Log信息如下:
Line 96: 07-26 01:02:26.205 2510 3766 I AudioController: internalShutdown
Line 540: 07-26 01:02:30.968 790 790 D ShutdownThread: Notifying thread to start shutdown longPressBehavior=1
Line 540: 07-26 01:02:30.968 790 790 D ShutdownThread: Notifying thread to start shutdown longPressBehavior=1
Line 541: 07-26 01:02:30.970 790 790 D ShutdownThread: Attempting to use SysUI shutdown UI
Line 541: 07-26 01:02:30.970 790 790 D ShutdownThread: Attempting to use SysUI shutdown UI
Line 542: 07-26 01:02:30.971 790 790 D ShutdownThread: SysUI handling shutdown UI
Line 542: 07-26 01:02:30.971 790 790 D ShutdownThread: SysUI handling shutdown UI
Line 555: 07-26 01:02:30.997 790 3902 I ShutdownThread: Sending shutdown broadcast...
Line 555: 07-26 01:02:30.997 790 3902 I ShutdownThread: Sending shutdown broadcast...
Line 561: 07-26 01:02:31.014 790 790 W SyncManager: Writing sync state before shutdown...
Line 666: 07-26 01:02:31.436 2510 3766 I AudioController: internalShutdown
Line 669: 07-26 01:02:31.443 790 790 I StatsCompanionService: StatsCompanionService noticed a shutdown.
Line 708: 07-26 01:02:31.671 790 3902 D ShutdownTiming: SendShutdownBroadcast took to complete: 675ms
Line 708: 07-26 01:02:31.671 790 3902 D ShutdownTiming: SendShutdownBroadcast took to complete: 675ms
Line 711: 07-26 01:02:31.671 790 3902 I ShutdownThread: Shutting down activity manager...
Line 740: 07-26 01:02:31.954 790 3902 W AppOps : Writing app ops before shutdown...
Line 771: 07-26 01:02:32.152 790 3902 W BatteryStats: Writing battery stats before shutdown...
Line 806: 07-26 01:02:32.386 790 1015 W system_server: Long monitor contention with owner Thread-29 (3902) at void com.android.server.am.BatteryStatsService.shutdown()(BatteryStatsService.java:249) waiters=0 in void com.android.server.am.BatteryStatsService.noteProcessStart(java.lang.String, int) for 132ms
Line 840: 07-26 01:02:32.507 790 3902 W ProcessStatsService: Writing process stats before shutdown...
Line 850: 07-26 01:02:32.563 790 3902 D ShutdownTiming: ShutdownActivityManager took to complete: 891ms
Line 850: 07-26 01:02:32.563 790 3902 D ShutdownTiming: ShutdownActivityManager took to complete: 891ms
Line 853: 07-26 01:02:32.563 790 3902 I ShutdownThread: Shutting down package manager...
Line 872: 07-26 01:02:32.656 790 3902 D ShutdownTiming: ShutdownPackageManager took to complete: 93ms
Line 872: 07-26 01:02:32.656 790 3902 D ShutdownTiming: ShutdownPackageManager took to complete: 93ms
Line 879: 07-26 01:02:32.677 1804 1976 V PhoneInterfaceManager: [PhoneIntfMgr] 1 Phones are shutdown.
Line 882: 07-26 01:02:32.678 790 3951 I ShutdownThread: Waiting for Radio...
Line 883: 07-26 01:02:32.679 790 3951 I ShutdownThread: Radio shutdown complete.
Line 883: 07-26 01:02:32.679 790 3951 I ShutdownThread: Radio shutdown complete.
Line 884: 07-26 01:02:32.681 790 3902 D ShutdownTiming: ShutdownRadios took to complete: 25ms
Line 884: 07-26 01:02:32.681 790 3902 D ShutdownTiming: ShutdownRadios took to complete: 25ms
Line 885: 07-26 01:02:32.681 790 3902 D ShutdownTiming: SystemServerShutdown took to complete: 1705ms
Line 885: 07-26 01:02:32.681 790 3902 D ShutdownTiming: SystemServerShutdown took to complete: 1705ms
Line 886: 07-26 01:02:32.684 790 3902 I ShutdownThread: Shutdown critical subsyslist is :modem :
Line 886: 07-26 01:02:32.684 790 3902 I ShutdownThread: Shutdown critical subsyslist is :modem :
Line 887: 07-26 01:02:32.684 790 3902 I ShutdownThread: Waiting for a maximum of 10000ms
Line 888: 07-26 01:02:32.684 790 3902 I ShutdownThread: Vendor subsystem(s) shutdown successful
Line 888: 07-26 01:02:32.684 790 3902 I ShutdownThread: Vendor subsystem(s) shutdown successful
Line 931: 07-26 01:02:33.192 790 3902 I ShutdownThread: Performing low-level shutdown...
Line 931: 07-26 01:02:33.192 790 3902 I ShutdownThread: Performing low-level shutdown...
Line 1003: 07-26 01:02:33.543 565 585 E Dpps : ProcessAlMsg():471 Shutdown event recieved quit -108
Line 1005: 07-26 01:02:33.543 565 585 I Dpps : ProcessNextEvent():142 Shutdown notification quit processing
Line 1009: 07-26 01:02:33.562 565 583 E Dpps : ProcessAbaMsg():579 Shutdown event recieved quit -108
至此,本篇已结束,如有不对的地方,欢迎您的建议与指正。同时期待您的关注,感谢您的阅读,谢谢!

Android 9.0 关机流程分析的更多相关文章
- Gradle之Android Gradle Plugin 主要流程分析(二)
[Android 修炼手册]Gradle 篇 -- Android Gradle Plugin 主要流程分析 预备知识 理解 gradle 的基本开发 了解 gradle task 和 plugin ...
- Android 4.4KitKat AudioRecord 流程分析
Android是架构分为三层: 底层 Linux Kernel 中间层 主要由C++实现 (Android 60%源码都是C++实现) 应用层 主要由JAVA开发的应用程序 应用程序执行 ...
- Android FART脱壳机流程分析
本文首发于安全客 链接:https://www.anquanke.com/post/id/219094 0x1 前言 在Android平台上,程序员编写的Java代码最终将被编译成字节码在Androi ...
- Cocos2d-x3.3RC0的Android编译Activity启动流程分析
本文将从引擎源代码Jni分析Cocos2d-x3.3RC0的Android Activity的启动流程,以下是具体分析. 1.引擎源代码Jni.部分Java层和C++层代码分析 watermark/2 ...
- Android恢复出厂设置流程分析【Android源码解析十】
最近看恢复出厂的一个问题,以前也查过这方面的流程,所以这里整理一些AP+framework层的流程: 在setting-->备份与重置--->恢复出厂设置--->重置手机---> ...
- Android 5.0 双卡信息管理分析
首先,如前面的博文所讲的,Android5.0开始支持双卡了.另外,对于双卡的卡信息的管理,也有了实现,尽管还不是完全彻底完整,如卡的slot id, display name,iccid,color ...
- Android 5.0 Phone初始化分析
已经更新至个人blog:http://dxjia.cn/2015/07/android-5-0-phone-init-analysis/ persistent属性 要想了解phone的框架,首先需要了 ...
- 【转载】Android 中 View 绘制流程分析
创建Window 在Activity的attach方法中通过调用PolicyManager.makeNewWindo创建Window,将一个View add到WindowManager时,Window ...
- Android View 绘制刷新流程分析
Android中对View的更新有很多种方式,使用时要区分不同的应用场合.1.不使用多线程和双缓冲 这种情况最简单,一般只是希望在View发生改变时对UI进行重绘.你只需显式地调用View对 ...
随机推荐
- 从无到有构建vue实战项目(一)
vue的安装 首先下载nodehttp://nodejs.cn/download/ 有两种安装方式安装包安装和二进制文件安装 输入以下命令,出现版本提示表示安装成功: node -v 10.15.3 ...
- CSS3常用转换总结
一.2D转换 translate(npx,npx) 相对当前元素位置移动 /* 实现div向左移动50个像素,并向下移动100个像素 */ div { transform: translate(50p ...
- Jsoup配合 htmlunit 爬取异步加载的网页
加入 jsoup 和 htmlunit 的依赖 <dependency> <groupId>org.jsoup</groupId> <artifactId&g ...
- SqlCommand的Parameters的用法
SqlCommand的Parameters的用法 可以用的SqlCommand的Parameters的方法SqlCommand cmd=new ("insert into notice(ly ...
- C语言学习书籍推荐《明解C语言》下载
柴田望洋 (作者), 管杰 (译者), 罗勇 (译者) <明解C语言>是日本的C语言经典教材,自出版以来不断重印.修订,被誉为“C语言圣经”.作者在日本IT界家喻户晓,出版过一系列极富影响 ...
- 9.22考试 crf的视察 题解
这道题当时第一反应就是一道典型的NOIP第一题的难度,绝对要A掉,不然分数一定会被拉开. 然后就开始分析,暴力是一开始想的是用二维树状数组打加上暴力枚举长度,然而这道题满足二分性质,所以时间复杂度就是 ...
- 9.18考试 第一题count题解
这道题说起来挺可惜的,当时纠结是用常数大但有可能减少递归层数的模还是用常数小但递归多的回溯纠结了好半天,最终错误的选择了模.导致T了20分,改成回溯就A了. 先分析一下性质,我在考试的时候打表发现在数 ...
- 从四个属性的角度来理解C语言的指针也许会更好理解
文章会在文末更新! 关于指针是什么,很多教材已经作出了定义,大多数都会定义为"存放变量内存地址的变量".从这句话中我觉得除了让我知道这个定义有11个字以外,其他就没什么用了.我个人 ...
- C++ 编程技巧锦集(一)
C++刷题精髓在STL编程,还有一些函数.下面我就总结一下本人在刷题过程中,每逢遇见总要百度的内容………………(大概率因为本人刷题太少了) 1. map map<string, int> ...
- 利用stub技术进行单元测试
待测试类:WebClient: import java.io.IOException; import java.io.InputStream; import java.net.HttpURLConne ...