極力推薦文章:歡迎收藏 Android 乾貨分享 java
#####閱讀五分鐘,每日十點,和您一塊兒終身學習,這裏是程序員Androidandroid
本篇文章主要介紹 Android
開發中的部分知識點,經過閱讀本篇文章,您將收穫如下內容:ios
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
app
####ShutdownThread 大體流程less
####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
方法,實現 彈出 關機 、重啓對話框,供用戶選擇關機 或者重啓。async
/** * 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 方法實現ide
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
至此,本篇已結束,若有不對的地方,歡迎您的建議與指正。同時期待您的關注,感謝您的閱讀,謝謝!