当前位置:   article > 正文

Android 9.0 关机流程分析

sysui handling shutdown ui

640?wx_fmt=gif

640?wx_fmt=gif

极力推荐文章:欢迎收藏

Android 干货分享 640?wx_fmt=gif

阅读五分钟,每日十点,和您一起终身学习,这里是程序员Android

本篇文章主要介绍 Android 开发中的部分知识点,通过阅读本篇文章,您将收获以下内容:

1.ShutdownThread 概述

1.ShutdownThread 概述

关机线程实现类

Android关机线程实现类frameworks/base/services/core/java/com/android/server/power/ShutdownThread.java

ShutdownThread 大致流程

640?wx_fmt=other

关机线程大致流程

ShutdownThread 部分静态变量如下:
  1. public final class ShutdownThread extends Thread {
  2. // constants
  3. private static final String TAG = "ShutdownThread";
  4. private static final int ACTION_DONE_POLL_WAIT_MS = 500;
  5. private static final int RADIOS_STATE_POLL_SLEEP_MS = 100;
  6. // maximum time we wait for the shutdown broadcast before going on.
  7. private static final int MAX_BROADCAST_TIME = 10*1000;
  8. private static final int MAX_SHUTDOWN_WAIT_TIME = 20*1000;
  9. private static final int MAX_RADIO_WAIT_TIME = 12*1000;
  10. private static final int MAX_UNCRYPT_WAIT_TIME = 15*60*1000;
  11. // constants for progress bar. the values are roughly estimated based on timeout.
  12. private static final int BROADCAST_STOP_PERCENT = 2;
  13. private static final int ACTIVITY_MANAGER_STOP_PERCENT = 4;
  14. private static final int PACKAGE_MANAGER_STOP_PERCENT = 6;
  15. private static final int RADIO_STOP_PERCENT = 18;
  16. private static final int MOUNT_SERVICE_STOP_PERCENT = 20;
  17. // Time we should wait for vendor subsystem shutdown
  18. // Sleep times(ms) between checks of the vendor subsystem state
  19. private static final int VENDOR_SUBSYS_STATE_CHECK_INTERVAL_MS = 100;
  20. // Max time we wait for vendor subsystems to shut down before resuming
  21. // with full system shutdown
  22. private static final int VENDOR_SUBSYS_MAX_WAIT_MS = 10000;
  23. // length of vibration before shutting down
  24. private static final int SHUTDOWN_VIBRATE_MS = 500;
  25. ... ...
  26. }
ShutdownThread 无参构造方法
  1. private ShutdownThread() {
  2. }

2. shutdown 关机方法

长按 ·Power· 键调用 shutdown方法,通过调用内部shutdownInner方法,实现 弹出 关机 、重启对话框,供用户选择关机 或者重启。

  1. /**
  2. * Request a clean shutdown, waiting for subsystems to clean up their
  3. * state etc. Must be called from a Looper thread in which its UI
  4. * is shown.
  5. *
  6. * @param context Context used to display the shutdown progress dialog. This must be a context
  7. * suitable for displaying UI (aka Themable).
  8. * @param reason code to pass to android_reboot() (e.g. "userrequested"), or null.
  9. * @param confirm true if user confirmation is needed before shutting down.
  10. */
  11. public static void shutdown(final Context context, String reason, boolean confirm) {
  12. mReboot = false;
  13. mRebootSafeMode = false;
  14. mReason = reason;
  15. shutdownInner(context, confirm); // 详见分析3
  16. }

3.shutdownInner 方法实现

shutdownInner 主要作用是BehaviorDialog

  1. private static void shutdownInner(final Context context, boolean confirm) {
  2. // ShutdownThread is called from many places, so best to verify here that the context passed
  3. // in is themed.
  4. context.assertRuntimeOverlayThemable();
  5. // ensure that only one thread is trying to power down.
  6. // any additional calls are just returned
  7. synchronized (sIsStartedGuard) {
  8. if (sIsStarted) {
  9. Log.d(TAG, "Request to shutdown already running, returning.");
  10. return;
  11. }
  12. }
  13. // 获取用户长按Power键的处理行为
  14. final int longPressBehavior = context.getResources().getInteger(
  15. com.android.internal.R.integer.config_longPressOnPowerBehavior);
  16. final int resourceId = mRebootSafeMode
  17. ? com.android.internal.R.string.reboot_safemode_confirm
  18. : (longPressBehavior == 2
  19. ? com.android.internal.R.string.shutdown_confirm_question
  20. : com.android.internal.R.string.shutdown_confirm);
  21. Log.d(TAG, "Notifying thread to start shutdown longPressBehavior=" + longPressBehavior);
  22. if (confirm) {
  23. //注册关机对话框广播 详细实现见 4
  24. final CloseDialogReceiver closer = new CloseDialogReceiver(context);
  25. if (sConfirmDialog != null) {
  26. sConfirmDialog.dismiss();
  27. }
  28. // 创建关机Dialg 详见 实现5
  29. sConfirmDialog = new AlertDialog.Builder(context)
  30. .setTitle(mRebootSafeMode
  31. ? com.android.internal.R.string.reboot_safemode_title
  32. : com.android.internal.R.string.power_off)
  33. .setMessage(resourceId)
  34. .setPositiveButton(com.android.internal.R.string.yes, new DialogInterface.OnClickListener() {
  35. public void onClick(DialogInterface dialog, int which) {
  36. // 开始一系列的关机流程,详见 6
  37. beginShutdownSequence(context);
  38. }
  39. })
  40. .setNegativeButton(com.android.internal.R.string.no, null)
  41. .create();
  42. closer.dialog = sConfirmDialog;
  43. sConfirmDialog.setOnDismissListener(closer);
  44. sConfirmDialog.getWindow().setType(WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG);
  45. sConfirmDialog.show();
  46. } else {
  47. beginShutdownSequence(context);
  48. }
  49. }

其中 config_longPressOnPowerBehavior 用来控制用户长按Power键触发的行为。

  1. <!-- Control the behavior when the user long presses the power button.
  2. 0 - Nothing
  3. 1 - Global actions menu
  4. 2 - Power off (with confirmation)
  5. 3 - Power off (without confirmation)
  6. 4 - Go to voice assist
  7. -->
  8. <integer name="config_longPressOnPowerBehavior">1</integer>

此源码 可以在 config.xml中查看,代码目录如下:frameworks\base\core\res\res\values\config.xml

4.CloseDialogReceiver 注册关机对话框广播

注册action 为ACTION_CLOSE_SYSTEM_DIALOGS广播接收器。

  1. private static class CloseDialogReceiver extends BroadcastReceiver
  2. implements DialogInterface.OnDismissListener {
  3. private Context mContext;
  4. public Dialog dialog;
  5. CloseDialogReceiver(Context context) {
  6. mContext = context;
  7. IntentFilter filter = new IntentFilter(Intent.ACTION_CLOSE_SYSTEM_DIALOGS);
  8. context.registerReceiver(this, filter);
  9. }
  10. @Override
  11. public void onReceive(Context context, Intent intent) {
  12. dialog.cancel();
  13. }
  14. public void onDismiss(DialogInterface unused) {
  15. mContext.unregisterReceiver(this);
  16. }
  17. }

5. new sConfirmDialog 显示关机对话框

Android原生关机对话框如下:

640?wx_fmt=other

关机对话框创建

  1. // 创建关机Dialg 详见 实现5
  2. sConfirmDialog = new AlertDialog.Builder(context)
  3. .setTitle(mRebootSafeMode
  4. ? com.android.internal.R.string.reboot_safemode_title
  5. : com.android.internal.R.string.power_off)
  6. .setMessage(resourceId)
  7. .setPositiveButton(com.android.internal.R.string.yes, new DialogInterface.OnClickListener() {
  8. public void onClick(DialogInterface dialog, int which) {
  9. // 开始一系列的关机流程,详见 6
  10. beginShutdownSequence(context);
  11. }
  12. })
  13. .setNegativeButton(com.android.internal.R.string.no, null)
  14. .create();
  15. closer.dialog = sConfirmDialog;
  16. sConfirmDialog.setOnDismissListener(closer);
  17. sConfirmDialog.getWindow().setType(WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG);
  18. sConfirmDialog.show();

6. beginShutdownSequence开始关机流程

beginShutdownSequence开始一系列关机流程,主要功能如下:ShutdownThead 线程。

  1. private static void beginShutdownSequence(Context context) {
  2. synchronized (sIsStartedGuard) {
  3. if (sIsStarted) {
  4. Log.d(TAG, "Shutdown sequence already running, returning.");
  5. return;
  6. }
  7. sIsStarted = true;
  8. }
  9. // 显示关机进度对话框 详见 7
  10. sInstance.mProgressDialog = showShutdownDialog(context);
  11. sInstance.mContext = context;
  12. sInstance.mPowerManager = (PowerManager)context.getSystemService(Context.POWER_SERVICE);
  13. // make sure we never fall asleep again
  14. sInstance.mCpuWakeLock = null;
  15. try {
  16. sInstance.mCpuWakeLock = sInstance.mPowerManager.newWakeLock(
  17. PowerManager.PARTIAL_WAKE_LOCK, TAG + "-cpu");
  18. sInstance.mCpuWakeLock.setReferenceCounted(false);
  19. sInstance.mCpuWakeLock.acquire();
  20. } catch (SecurityException e) {
  21. Log.w(TAG, "No permission to acquire wake lock", e);
  22. sInstance.mCpuWakeLock = null;
  23. }
  24. // also make sure the screen stays on for better user experience
  25. sInstance.mScreenWakeLock = null;
  26. if (sInstance.mPowerManager.isScreenOn()) {
  27. try {
  28. sInstance.mScreenWakeLock = sInstance.mPowerManager.newWakeLock(
  29. PowerManager.FULL_WAKE_LOCK, TAG + "-screen");
  30. sInstance.mScreenWakeLock.setReferenceCounted(false);
  31. sInstance.mScreenWakeLock.acquire();
  32. } catch (SecurityException e) {
  33. Log.w(TAG, "No permission to acquire wake lock", e);
  34. sInstance.mScreenWakeLock = null;
  35. }
  36. }
  37. if (SecurityLog.isLoggingEnabled()) {
  38. SecurityLog.writeEvent(SecurityLog.TAG_OS_SHUTDOWN);
  39. }
  40. // 启动 关机线程 ,执行 Run 方法,详见 9
  41. sInstance.mHandler = new Handler() {
  42. };
  43. sInstance.start();
  44. }

7.showShutdownDialog 显示关机进度对话框

showShutdownDialog主要用来显示关机进度对话框

  1. private static ProgressDialog showShutdownDialog(Context context) {
  2. // Throw up a system dialog to indicate the device is rebooting / shutting down.
  3. ProgressDialog pd = new ProgressDialog(context);
  4. // Path 1: Reboot to recovery for update
  5. // Condition: mReason startswith REBOOT_RECOVERY_UPDATE
  6. //
  7. // Path 1a: uncrypt needed
  8. // Condition: if /cache/recovery/uncrypt_file exists but
  9. // /cache/recovery/block.map doesn't.
  10. // UI: determinate progress bar (mRebootHasProgressBar == True)
  11. //
  12. // * Path 1a is expected to be removed once the GmsCore shipped on
  13. // device always calls uncrypt prior to reboot.
  14. //
  15. // Path 1b: uncrypt already done
  16. // UI: spinning circle only (no progress bar)
  17. //
  18. // Path 2: Reboot to recovery for factory reset
  19. // Condition: mReason == REBOOT_RECOVERY
  20. // UI: spinning circle only (no progress bar)
  21. //
  22. // Path 3: Regular reboot / shutdown
  23. // Condition: Otherwise
  24. // UI: spinning circle only (no progress bar)
  25. // mReason could be "recovery-update" or "recovery-update,quiescent".
  26. if (mReason != null && mReason.startsWith(PowerManager.REBOOT_RECOVERY_UPDATE)) {
  27. // We need the progress bar if uncrypt will be invoked during the
  28. // reboot, which might be time-consuming.
  29. mRebootHasProgressBar = RecoverySystem.UNCRYPT_PACKAGE_FILE.exists()
  30. && !(RecoverySystem.BLOCK_MAP_FILE.exists());
  31. pd.setTitle(context.getText(com.android.internal.R.string.reboot_to_update_title));
  32. if (mRebootHasProgressBar) {
  33. pd.setMax(100);
  34. pd.setProgress(0);
  35. pd.setIndeterminate(false);
  36. pd.setProgressNumberFormat(null);
  37. pd.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
  38. pd.setMessage(context.getText(
  39. com.android.internal.R.string.reboot_to_update_prepare));
  40. } else {
  41. if (showSysuiReboot()) {
  42. return null;
  43. }
  44. pd.setIndeterminate(true);
  45. pd.setMessage(context.getText(
  46. com.android.internal.R.string.reboot_to_update_reboot));
  47. }
  48. } else if (mReason != null && mReason.equals(PowerManager.REBOOT_RECOVERY)) {
  49. if (RescueParty.isAttemptingFactoryReset()) {
  50. // We're not actually doing a factory reset yet; we're rebooting
  51. // to ask the user if they'd like to reset, so give them a less
  52. // scary dialog message.
  53. pd.setTitle(context.getText(com.android.internal.R.string.power_off));
  54. pd.setMessage(context.getText(com.android.internal.R.string.shutdown_progress));
  55. pd.setIndeterminate(true);
  56. } else {
  57. // Factory reset path. Set the dialog message accordingly.
  58. pd.setTitle(context.getText(com.android.internal.R.string.reboot_to_reset_title));
  59. pd.setMessage(context.getText(
  60. com.android.internal.R.string.reboot_to_reset_message));
  61. pd.setIndeterminate(true);
  62. }
  63. } else {
  64. // 判断是否显示SystemUIReboot 详见 8
  65. if (showSysuiReboot()) {
  66. return null;
  67. }
  68. // 显示关机 进度对话框 详见 8
  69. pd.setTitle(context.getText(com.android.internal.R.string.power_off));
  70. pd.setMessage(context.getText(com.android.internal.R.string.shutdown_progress));
  71. pd.setIndeterminate(true);
  72. }
  73. pd.setCancelable(false);
  74. pd.getWindow().setType(WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG);
  75. pd.show();
  76. return pd;
  77. }
关机 进度对话框实现

640?wx_fmt=other

关机 进度对话框实现

8.判断是否显示SystemUIReboot

showSysuiReboot 主要用来显示是否显示SystemUIReboot.

  1. private static boolean showSysuiReboot() {
  2. Log.d(TAG, "Attempting to use SysUI shutdown UI");
  3. try {
  4. StatusBarManagerInternal service = LocalServices.getService(
  5. StatusBarManagerInternal.class);
  6. if (service.showShutdownUi(mReboot, mReason)) {
  7. // Sysui will handle shutdown UI.
  8. Log.d(TAG, "SysUI handling shutdown UI");
  9. return true;
  10. }
  11. } catch (Exception e) {
  12. // If anything went wrong, ignore it and use fallback ui
  13. }
  14. Log.d(TAG, "SysUI is unavailable");
  15. return false;
  16. }

9.启动 关机线程 ,执行 Run 方法

beginShutdownSequence方法中启动 关机线程。

  1. private static void beginShutdownSequence(Context context) {
  2. ... ...
  3. // static instance of this thread
  4. private static final ShutdownThread sInstance = new ShutdownThread();
  5. // start the thread that initiates shutdown
  6. sInstance.mHandler = new Handler() {
  7. };
  8. sInstance.start();
  9. ... ...
  10. }
ShutdownThread Run 实现

ShutdownThread 主要作用:ActivityManagerPackageManagerRadiosSystem Server 的关闭。

  1. /**
  2. * Makes sure we handle the shutdown gracefully.
  3. * Shuts off power regardless of radio state if the allotted time has passed.
  4. */
  5. public void run() {
  6. TimingsTraceLog shutdownTimingLog = newTimingsLog();
  7. shutdownTimingLog.traceBegin("SystemServerShutdown");
  8. metricShutdownStart();
  9. metricStarted(METRIC_SYSTEM_SERVER);
  10. BroadcastReceiver br = new BroadcastReceiver() {
  11. @Override public void onReceive(Context context, Intent intent) {
  12. // We don't allow apps to cancel this, so ignore the result.
  13. actionDone();
  14. }
  15. };
  16. /*
  17. * Write a system property in case the system_server reboots before we
  18. * get to the actual hardware restart. If that happens, we'll retry at
  19. * the beginning of the SystemServer startup.
  20. */
  21. {
  22. String reason = (mReboot ? "1" : "0") + (mReason != null ? mReason : "");
  23. SystemProperties.set(SHUTDOWN_ACTION_PROPERTY, reason);
  24. }
  25. /*
  26. * If we are rebooting into safe mode, write a system property
  27. * indicating so.
  28. */
  29. if (mRebootSafeMode) {
  30. SystemProperties.set(REBOOT_SAFEMODE_PROPERTY, "1");
  31. }
  32. metricStarted(METRIC_SEND_BROADCAST);
  33. shutdownTimingLog.traceBegin("SendShutdownBroadcast");
  34. Log.i(TAG, "Sending shutdown broadcast...");
  35. // First send the high-level shut down broadcast.
  36. mActionDone = false;
  37. Intent intent = new Intent(Intent.ACTION_SHUTDOWN);
  38. intent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND | Intent.FLAG_RECEIVER_REGISTERED_ONLY);
  39. // 发送 有序的 关机广播
  40. mContext.sendOrderedBroadcastAsUser(intent,
  41. UserHandle.ALL, null, br, mHandler, 0, null, null);
  42. final long endTime = SystemClock.elapsedRealtime() + MAX_BROADCAST_TIME;
  43. synchronized (mActionDoneSync) {
  44. while (!mActionDone) {
  45. long delay = endTime - SystemClock.elapsedRealtime();
  46. if (delay <= 0) {
  47. Log.w(TAG, "Shutdown broadcast timed out");
  48. break;
  49. } else if (mRebootHasProgressBar) {
  50. int status = (int)((MAX_BROADCAST_TIME - delay) * 1.0 *
  51. BROADCAST_STOP_PERCENT / MAX_BROADCAST_TIME);
  52. sInstance.setRebootProgress(status, null);
  53. }
  54. try {
  55. mActionDoneSync.wait(Math.min(delay, ACTION_DONE_POLL_WAIT_MS));
  56. } catch (InterruptedException e) {
  57. }
  58. }
  59. }
  60. if (mRebootHasProgressBar) {
  61. sInstance.setRebootProgress(BROADCAST_STOP_PERCENT, null);
  62. }
  63. // 测量 发送有序 关机广播所用的时间
  64. shutdownTimingLog.traceEnd(); // SendShutdownBroadcast
  65. metricEnded(METRIC_SEND_BROADCAST);
  66. Log.i(TAG, "Shutting down activity manager...");
  67. shutdownTimingLog.traceBegin("ShutdownActivityManager");
  68. metricStarted(METRIC_AM);
  69. // 关闭 Activity Manager
  70. final IActivityManager am =
  71. IActivityManager.Stub.asInterface(ServiceManager.checkService("activity"));
  72. if (am != null) {
  73. try {
  74. am.shutdown(MAX_BROADCAST_TIME);
  75. } catch (RemoteException e) {
  76. }
  77. }
  78. if (mRebootHasProgressBar) {
  79. sInstance.setRebootProgress(ACTIVITY_MANAGER_STOP_PERCENT, null);
  80. }
  81. shutdownTimingLog.traceEnd();// ShutdownActivityManager
  82. metricEnded(METRIC_AM);
  83. Log.i(TAG, "Shutting down package manager...");
  84. shutdownTimingLog.traceBegin("ShutdownPackageManager");
  85. metricStarted(METRIC_PM);
  86. // 关闭 Package Manager
  87. final PackageManagerService pm = (PackageManagerService)
  88. ServiceManager.getService("package");
  89. if (pm != null) {
  90. pm.shutdown();
  91. }
  92. if (mRebootHasProgressBar) {
  93. sInstance.setRebootProgress(PACKAGE_MANAGER_STOP_PERCENT, null);
  94. }
  95. shutdownTimingLog.traceEnd(); // ShutdownPackageManager
  96. metricEnded(METRIC_PM);
  97. // Shutdown radios.
  98. shutdownTimingLog.traceBegin("ShutdownRadios");
  99. metricStarted(METRIC_RADIOS);
  100. //关闭 Radios shutdownRadios 详细 请看 10
  101. shutdownRadios(MAX_RADIO_WAIT_TIME);
  102. if (mRebootHasProgressBar) {
  103. sInstance.setRebootProgress(RADIO_STOP_PERCENT, null);
  104. }
  105. shutdownTimingLog.traceEnd(); // ShutdownRadios
  106. metricEnded(METRIC_RADIOS);
  107. // 关闭 System Server
  108. if (mRebootHasProgressBar) {
  109. sInstance.setRebootProgress(MOUNT_SERVICE_STOP_PERCENT, null);
  110. // If it's to reboot to install an update and uncrypt hasn't been
  111. // done yet, trigger it now.
  112. uncrypt();
  113. }
  114. shutdownTimingLog.traceEnd(); // SystemServerShutdown
  115. metricEnded(METRIC_SYSTEM_SERVER);
  116. saveMetrics(mReboot, mReason);
  117. //初始化 并判断是关机还是重启 详见 11
  118. rebootOrShutdown(mContext, mReboot, mReason);
  119. }

10.shutdownRadios 关闭Radio 实现

shutdownRadios 用来关闭phone Radio相关内容 ,主要实现如下:

  1. private void shutdownRadios(final int timeout) {
  2. // If a radio is wedged, disabling it may hang so we do this work in another thread,
  3. // just in case.
  4. final long endTime = SystemClock.elapsedRealtime() + timeout;
  5. final boolean[] done = new boolean[1];
  6. //另起线程 异步关闭 Radios
  7. Thread t = new Thread() {
  8. public void run() {
  9. TimingsTraceLog shutdownTimingsTraceLog = newTimingsLog();
  10. boolean radioOff;
  11. final ITelephony phone =
  12. ITelephony.Stub.asInterface(ServiceManager.checkService("phone"));
  13. try {
  14. radioOff = phone == null || !phone.needMobileRadioShutdown();
  15. if (!radioOff) {
  16. Log.w(TAG, "Turning off cellular radios...");
  17. metricStarted(METRIC_RADIO);
  18. phone.shutdownMobileRadios();
  19. }
  20. } catch (RemoteException ex) {
  21. Log.e(TAG, "RemoteException during radio shutdown", ex);
  22. radioOff = true;
  23. }
  24. Log.i(TAG, "Waiting for Radio...");
  25. long delay = endTime - SystemClock.elapsedRealtime();
  26. while (delay > 0) {
  27. if (mRebootHasProgressBar) {
  28. int status = (int)((timeout - delay) * 1.0 *
  29. (RADIO_STOP_PERCENT - PACKAGE_MANAGER_STOP_PERCENT) / timeout);
  30. status += PACKAGE_MANAGER_STOP_PERCENT;
  31. sInstance.setRebootProgress(status, null);
  32. }
  33. if (!radioOff) {
  34. try {
  35. radioOff = !phone.needMobileRadioShutdown();
  36. } catch (RemoteException ex) {
  37. Log.e(TAG, "RemoteException during radio shutdown", ex);
  38. radioOff = true;
  39. }
  40. if (radioOff) {
  41. Log.i(TAG, "Radio turned off.");
  42. metricEnded(METRIC_RADIO);
  43. shutdownTimingsTraceLog
  44. .logDuration("ShutdownRadio", TRON_METRICS.get(METRIC_RADIO));
  45. }
  46. }
  47. if (radioOff) {
  48. Log.i(TAG, "Radio shutdown complete.");
  49. done[0] = true;
  50. break;
  51. }
  52. SystemClock.sleep(RADIOS_STATE_POLL_SLEEP_MS);
  53. delay = endTime - SystemClock.elapsedRealtime();
  54. }
  55. }
  56. };
  57. //另起线程 异步关闭 Radios
  58. t.start();
  59. try {
  60. t.join(timeout);
  61. } catch (InterruptedException ex) {
  62. }
  63. if (!done[0]) {
  64. Log.w(TAG, "Timed out waiting for Radio shutdown.");
  65. }
  66. }

11.rebootOrShutdown 初始化并决定关机还是重启

rebootOrShutdown主要用来 初始化并决定关机还是重启。

  1. /**
  2. * Do not call this directly. Use {@link #reboot(Context, String, boolean)}
  3. * or {@link #shutdown(Context, String, boolean)} instead.
  4. *
  5. * @param context Context used to vibrate or null without vibration
  6. * @param reboot true to reboot or false to shutdown
  7. * @param reason reason for reboot/shutdown
  8. */
  9. public static void rebootOrShutdown(final Context context, boolean reboot, String reason) {
  10. String subsysProp;
  11. subsysProp = SystemProperties.get("vendor.peripheral.shutdown_critical_list",
  12. "ERROR");
  13. //If we don't have the shutdown critical subsystem list we can't
  14. //really do anything. Proceed with full system shutdown.
  15. if (!subsysProp.equals("ERROR")) {
  16. Log.i(TAG, "Shutdown critical subsyslist is :"+subsysProp+": ");
  17. Log.i(TAG, "Waiting for a maximum of " +
  18. (VENDOR_SUBSYS_MAX_WAIT_MS) + "ms");
  19. String[] subsysList = subsysProp.split(" ");
  20. int wait_count = 0;
  21. boolean okToShutdown = true;
  22. String subsysState;
  23. int subsysListLength = subsysList.length;
  24. do {
  25. okToShutdown = true;
  26. for (int i = 0; i < subsysListLength; i++) {
  27. subsysState =
  28. SystemProperties.get(
  29. "vendor.peripheral." +
  30. subsysList[i] +
  31. ".state",
  32. "ERROR");
  33. if(subsysState.equals("ONLINE")) {
  34. //We only want to delay shutdown while
  35. //one of the shutdown critical
  36. //subsystems still shows as 'ONLINE'.
  37. okToShutdown = false;
  38. }
  39. }
  40. if (okToShutdown == false) {
  41. SystemClock.sleep(VENDOR_SUBSYS_STATE_CHECK_INTERVAL_MS);
  42. wait_count++;
  43. }
  44. } while (okToShutdown != true &&
  45. wait_count < (VENDOR_SUBSYS_MAX_WAIT_MS/VENDOR_SUBSYS_STATE_CHECK_INTERVAL_MS));
  46. if (okToShutdown != true) {
  47. for (int i = 0; i < subsysList.length; i++) {
  48. subsysState =
  49. SystemProperties.get(
  50. "vendor.peripheral." +
  51. subsysList[i] +
  52. ".state",
  53. "ERROR");
  54. if(subsysState.equals("ONLINE")) {
  55. Log.w(TAG, "Subsystem " + subsysList[i]+
  56. "did not shut down within timeout");
  57. }
  58. }
  59. } else {
  60. Log.i(TAG, "Vendor subsystem(s) shutdown successful");
  61. }
  62. }
  63. if (reboot) {
  64. Log.i(TAG, "Rebooting, reason: " + reason);
  65. PowerManagerService.lowLevelReboot(reason);
  66. Log.e(TAG, "Reboot failed, will attempt shutdown instead");
  67. reason = null;
  68. } else if (SHUTDOWN_VIBRATE_MS > 0 && context != null) {
  69. // vibrate before shutting down
  70. Vibrator vibrator = new SystemVibrator(context);
  71. try {
  72. vibrator.vibrate(SHUTDOWN_VIBRATE_MS, VIBRATION_ATTRIBUTES);
  73. } catch (Exception e) {
  74. // Failure to vibrate shouldn't interrupt shutdown. Just log it.
  75. Log.w(TAG, "Failed to vibrate during shutdown.", e);
  76. }
  77. // vibrator is asynchronous so we need to wait to avoid shutting down too soon.
  78. try {
  79. Thread.sleep(SHUTDOWN_VIBRATE_MS);
  80. } catch (InterruptedException unused) {
  81. }
  82. }
  83. // Shutdown power
  84. Log.i(TAG, "Performing low-level shutdown...");
  85. PowerManagerService.lowLevelShutdown(reason);
  86. }

12. 关机log 分析

通过 链接adb,我们可以抓取关机的Log, 部分Log信息如下:

  1. Line 96: 07-26 01:02:26.205 2510 3766 I AudioController: internalShutdown
  2. Line 540: 07-26 01:02:30.968 790 790 D ShutdownThread: Notifying thread to start shutdown longPressBehavior=1
  3. Line 540: 07-26 01:02:30.968 790 790 D ShutdownThread: Notifying thread to start shutdown longPressBehavior=1
  4. Line 541: 07-26 01:02:30.970 790 790 D ShutdownThread: Attempting to use SysUI shutdown UI
  5. Line 541: 07-26 01:02:30.970 790 790 D ShutdownThread: Attempting to use SysUI shutdown UI
  6. Line 542: 07-26 01:02:30.971 790 790 D ShutdownThread: SysUI handling shutdown UI
  7. Line 542: 07-26 01:02:30.971 790 790 D ShutdownThread: SysUI handling shutdown UI
  8. Line 555: 07-26 01:02:30.997 790 3902 I ShutdownThread: Sending shutdown broadcast...
  9. Line 555: 07-26 01:02:30.997 790 3902 I ShutdownThread: Sending shutdown broadcast...
  10. Line 561: 07-26 01:02:31.014 790 790 W SyncManager: Writing sync state before shutdown...
  11. Line 666: 07-26 01:02:31.436 2510 3766 I AudioController: internalShutdown
  12. Line 669: 07-26 01:02:31.443 790 790 I StatsCompanionService: StatsCompanionService noticed a shutdown.
  13. Line 708: 07-26 01:02:31.671 790 3902 D ShutdownTiming: SendShutdownBroadcast took to complete: 675ms
  14. Line 708: 07-26 01:02:31.671 790 3902 D ShutdownTiming: SendShutdownBroadcast took to complete: 675ms
  15. Line 711: 07-26 01:02:31.671 790 3902 I ShutdownThread: Shutting down activity manager...
  16. Line 740: 07-26 01:02:31.954 790 3902 W AppOps : Writing app ops before shutdown...
  17. Line 771: 07-26 01:02:32.152 790 3902 W BatteryStats: Writing battery stats before shutdown...
  18. 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
  19. Line 840: 07-26 01:02:32.507 790 3902 W ProcessStatsService: Writing process stats before shutdown...
  20. Line 850: 07-26 01:02:32.563 790 3902 D ShutdownTiming: ShutdownActivityManager took to complete: 891ms
  21. Line 850: 07-26 01:02:32.563 790 3902 D ShutdownTiming: ShutdownActivityManager took to complete: 891ms
  22. Line 853: 07-26 01:02:32.563 790 3902 I ShutdownThread: Shutting down package manager...
  23. Line 872: 07-26 01:02:32.656 790 3902 D ShutdownTiming: ShutdownPackageManager took to complete: 93ms
  24. Line 872: 07-26 01:02:32.656 790 3902 D ShutdownTiming: ShutdownPackageManager took to complete: 93ms
  25. Line 879: 07-26 01:02:32.677 1804 1976 V PhoneInterfaceManager: [PhoneIntfMgr] 1 Phones are shutdown.
  26. Line 882: 07-26 01:02:32.678 790 3951 I ShutdownThread: Waiting for Radio...
  27. Line 883: 07-26 01:02:32.679 790 3951 I ShutdownThread: Radio shutdown complete.
  28. Line 883: 07-26 01:02:32.679 790 3951 I ShutdownThread: Radio shutdown complete.
  29. Line 884: 07-26 01:02:32.681 790 3902 D ShutdownTiming: ShutdownRadios took to complete: 25ms
  30. Line 884: 07-26 01:02:32.681 790 3902 D ShutdownTiming: ShutdownRadios took to complete: 25ms
  31. Line 885: 07-26 01:02:32.681 790 3902 D ShutdownTiming: SystemServerShutdown took to complete: 1705ms
  32. Line 885: 07-26 01:02:32.681 790 3902 D ShutdownTiming: SystemServerShutdown took to complete: 1705ms
  33. Line 886: 07-26 01:02:32.684 790 3902 I ShutdownThread: Shutdown critical subsyslist is :modem :
  34. Line 886: 07-26 01:02:32.684 790 3902 I ShutdownThread: Shutdown critical subsyslist is :modem :
  35. Line 887: 07-26 01:02:32.684 790 3902 I ShutdownThread: Waiting for a maximum of 10000ms
  36. Line 888: 07-26 01:02:32.684 790 3902 I ShutdownThread: Vendor subsystem(s) shutdown successful
  37. Line 888: 07-26 01:02:32.684 790 3902 I ShutdownThread: Vendor subsystem(s) shutdown successful
  38. Line 931: 07-26 01:02:33.192 790 3902 I ShutdownThread: Performing low-level shutdown...
  39. Line 931: 07-26 01:02:33.192 790 3902 I ShutdownThread: Performing low-level shutdown...
  40. Line 1003: 07-26 01:02:33.543 565 585 E Dpps : ProcessAlMsg():471 Shutdown event recieved quit -108
  41. Line 1005: 07-26 01:02:33.543 565 585 I Dpps : ProcessNextEvent():142 Shutdown notification quit processing
  42. Line 1009: 07-26 01:02:33.562 565 583 E Dpps : ProcessAbaMsg():579 Shutdown event recieved quit -108

至此,本篇已结束,如有不对的地方,欢迎您的建议与指正。同时期待您的关注,感谢您的阅读,谢谢!640?wx_fmt=png

坚持就有惊喜

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/运维做开发/article/detail/945254
推荐阅读
相关标签
  

闽ICP备14008679号