赞
踩
第一章 引言
第二章 关机流程
2.1 PhonewindowManager
2.2 PhoneWindowManager.interceptKeyBeforeQueueing
2.3 PhoneWindowManager.interceptPowerKeyDown
2.4 PhoneWindowManager.powerLongPress()
2.5 PowerAction.onPress()
2.6 WindowManagerService.shutdown
2.7 ShutdownThread.shutdown()
2.8 ShutdownThread.shutdownInner()
2.9 ShutdownThread.beginShutdownSequence()
2.10 ShutdowmThread.run()
2.11 ShutdownThread.rebootOrShutdown()
第一章 引言
在开始分析关机流程之前,我们先总结几个关机的关键字,以便我们加深我们对关机流程的理解,关键字如下:
InputReader,ShutdownThread,LIGHTS
Line 5981: 05-28 15:24:36.220 838 996 D InputReader: processEventsLocked: type=3 Count=3 code=57 value=-1 deviceId=6 //通常我们以最后一个InputReader输出作为关机的起始时间;
Line 5992: 05-28 15:24:36.248 838 838 D ShutdownThread: Attempting to use SysUI shutdown UI //我们可以通过ShutdownThread的log打印确定这段时间内是否有异常;
Line 5993: 05-28 15:24:36.248 838 838 D ShutdownThread: SysUI handling shutdown UI
Line 6000: 05-28 15:24:36.256 838 5800 I ShutdownThread: Sending shutdown broadcast...
Line 6126: 05-28 15:24:36.605 838 5800 I ShutdownThread: Shutting down activity manager...
Line 7120: 05-28 15:24:38.212 838 5800 I ShutdownThread: Shutting down package manager...
Line 7138: 05-28 15:24:38.249 838 5866 I ShutdownThread: Waiting for Radio...
Line 7139: 05-28 15:24:38.249 838 5866 I ShutdownThread: Radio shutdown complete.
Line 7361: 05-28 15:24:38.759 838 5800 I ShutdownThread: Performing low-level shutdown...
Line 7458: 05-28 15:24:39.027 434 434 D LIGHTS : file:vendor/sprd/modules/lights/lights.c, func:write_int, path=/sys/class/backlight/sprd_backlight/brightness, value=0 //最后一句lights的打印此时屏幕灭屏,我们通常观察的关机结束以此为准;
第二章 关机流程
2.1 PhonewindowManager
Android 系统的关机流程是从用户按 power 键开始的,所有的按键处理都是通过 PhoneWindowManager.interceptKeyBeforeQueueing() 方法进行处理。
2.2 PhoneWindowManager.interceptKeyBeforeQueueing
257 public class PhoneWindowManager extends AbsPhoneWindowManager implements WindowManagerPolicy {
3817 public int interceptKeyBeforeQueueing(KeyEvent event, int policyFlags) {
…….
// Handle special keys.
3909 switch (keyCode) {
......
case KeyEvent.KEYCODE_POWER: {
4029 EventLogTags.writeInterceptPower(
4030 KeyEvent.actionToString(event.getAction()),
4031 mPowerKeyHandled ? 1 : 0, mPowerKeyPressCounter);
4032 // Any activity on the power button stops the accessibility shortcut
4033 cancelPendingAccessibilityShortcutAction();
4034 result &= ~ACTION_PASS_TO_USER;
4035 isWakeKey = false; // wake-up will be handled separately
4036 if (down) {
4037 /*SPRD : add power debug log start*/
4038 Slog.d(TAG, "Receive Input KeyEvent of Powerkey down");
4039 /*SPRD : add power debug log end*/
4040 interceptPowerKeyDown(event, interactive);
4041 } else {
4042 /*SPRD : add power debug log start*/
4043 Slog.d(TAG, "Receive Input KeyEvent of Powerkey up");
4044 /*SPRD : add power debug log end*/
4045 interceptPowerKeyUp(event, interactive, canceled);
4046 }
4047 break;
4048 }
2.3 PhoneWindowManager.interceptPowerKeyDown
946 private void interceptPowerKeyDown(KeyEvent event, boolean interactive) {
......
// Latch power key state to detect screenshot chord.
960 if (interactive && !mScreenshotChordPowerKeyTriggered
961 && (event.getFlags() & KeyEvent.FLAG_FALLBACK) == 0) {
962 mScreenshotChordPowerKeyTriggered = true;
963 mScreenshotChordPowerKeyTime = event.getDownTime();
964 interceptScreenshotChord();
965 interceptRingerToggleChord();
966 }
967
968 // Stop ringing or end call if configured to do so when power is pressed.
969 TelecomManager telecomManager = getTelecommService();
970 boolean hungUp = false;
971 if (telecomManager != null) {
972 if (telecomManager.isRinging()) {
973 // Pressing Power while there's a ringing incoming
974 // call should silence the ringer.
975 telecomManager.silenceRinger();
976 } else if ((mIncallPowerBehavior
977 & Settings.Secure.INCALL_POWER_BUTTON_BEHAVIOR_HANGUP) != 0
978 && telecomManager.isInCall() && interactive) {
979 // Otherwise, if "Power button ends call" is enabled,
980 // the Power button will hang up any current active call.
981 hungUp = telecomManager.endCall();
982 }
983 }
……
mPowerKeyHandled = hungUp || mScreenshotChordVolumeDownKeyTriggered
1004 || mA11yShortcutChordVolumeUpKeyTriggered || gesturedServiceIntercepted;
1005 if (!mPowerKeyHandled) {
1006 if (interactive) {
1007 // When interactive, we're already awake.
1008 // Wait for a long press or for the button to be released to decide what to do.
1009 if (hasLongPressOnPowerBehavior()) {
1010 if ((event.getFlags() & KeyEvent.FLAG_LONG_PRESS) != 0) {
1011 powerLongPress();//长按power键,核心
1012 } else {
……
} else {
1026 wakeUpFromPowerKey(event.getDownTime());
1027
1028 if (mSupportLongPressPowerWhenNonInteractive && hasLongPressOnPowerBehavior()) {
1029 if ((event.getFlags() & KeyEvent.FLAG_LONG_PRESS) != 0) {
1030 powerLongPress();//长按power键,核心
1031 } else {
……
mBeganFromNonInteractive = true;
1045 } else {
……
1052 }
1053 }
1054 }
1055 }
1056 }
2.4 PhoneWindowManager.powerLongPress()
3 private void powerLongPress() {
4 1267 final int behavior = getResolvedLongPressOnPowerBehavior();
5 1268 switch (behavior) {
6 1269 case LONG_PRESS_POWER_NOTHING:
7 1270 break;
8 1271 case LONG_PRESS_POWER_GLOBAL_ACTIONS://原生会走这个case
9 1272 mPowerKeyHandled = true;
10 1273 performHapticFeedback(HapticFeedbackConstants.LONG_PRESS, false,
11 1274 "Power - Long Press - Global Actions");
12 1275 showGlobalActionsInternal();//调用showlobalactioninternal
13 1276 break;
powerLongPress() 有两个核心方法,getResolvedLongPressOnPowerBehavior() 和 showGlobalActionsInternal(),在此不再做分解分析。
2.5 PowerAction.onPress()
25 public final class PowerAction extends SinglePressAction implements LongPressAction {
@Override
57 public void onPress() {
58 // shutdown by making sure radio and power are handled accordingly.
59 mWindowManagerFuncs.shutdown(false /* confirm */);
60 }
61 }
2.6 WindowManagerService.shutdown
public class WindowManagerService extends AbsWindowManagerService
290 implements Watchdog.Monitor, WindowManagerPolicy.WindowManagerFuncs {
……
// Called by window manager policy. Not exposed externally.
public void shutdown(boolean confirm) {
3174 // Pass in the UI context, since ShutdownThread requires it (to show UI).
//调用shutdownThread.shutdown()方法
3175 ShutdownThread.shutdown(ActivityThread.currentActivityThread().getSystemUiContext(),
3176 PowerManager.SHUTDOWN_USER_REQUESTED, confirm);
3177 }
2.7 ShutdownThread.shutdown()
就像在第一章引言所述,整体的关机流程是通过shutdownThread线程实现。
62 public final class ShutdownThread extends Thread {
public static void shutdown(final Context context, String reason, boolean confirm) {
153 mReboot = false;
154 mRebootSafeMode = false;
155 mReason = reason;
156 shutdownInner(context, confirm);//内部调用shytdownInner()方法
157 }
2.8 ShutdownThread.shutdownInner()
private static void shutdownInner(final Context context, boolean confirm) {
183 // ShutdownThread is called from many places, so best to verify here that the context passed
184 // in is themed.
185 context.assertRuntimeOverlayThemable();
186
187 // ensure that only one thread is trying to power down.
188 // any additional calls are just returned
189 synchronized (sIsStartedGuard) {
190 if (sIsStarted) {
191 Log.d(TAG, "Request to shutdown already running, returning.");
192 return;
193 }
194 }
195 //获取用户长按power键的处理方式
196 final int longPressBehavior = context.getResources().getInteger(
197 com.android.internal.R.integer.config_longPressOnPowerBehavior);
198 final int resourceId = mRebootSafeMode
199 ? com.android.internal.R.string.reboot_safemode_confirm
200 /*UNISOC bug 908624,add confirm dialog.*/
201 : (mReboot
202 ? com.android.internal.R.string.reboot_device_confirm
203 /*UNISOC bug 908624,add confirm dialog.*/
204 : (longPressBehavior == 2
205 ? com.android.internal.R.string.shutdown_confirm_question
206 : com.android.internal.R.string.shutdown_confirm));
207
208 Log.d(TAG, "Notifying thread to start shutdown longPressBehavior=" + longPressBehavior);
……
if (confirm) {//弹出关机,重启对话框,用户选择
215 final CloseDialogReceiver closer = new CloseDialogReceiver(context);//注册关机广播
216 if (sConfirmDialog != null) {
217 sConfirmDialog.dismiss();
218 }
219
220 //bug:1162804 add dark theme.
221 if (sInstance.mUiModeManager == null) {
222 sInstance.mUiModeManager = (UiModeManager) context.getSystemService(Context.UI_MODE_SERVICE);
223 }
224 if (sInstance.mUiModeManager != null && sInstance.mPowerManager != null &&(sInstance.mUiModeManager.getNightMode() == UiModeManager.MODE_NIGHT_YES
225 || sInstance.mPowerManager.isPowerSaveMode())) {
226 sInstance.mThemeResId = AlertDialog.THEME_DEVICE_DEFAULT_DARK;
227 } else {
228 sInstance.mThemeResId = AlertDialog.THEME_DEVICE_DEFAULT_LIGHT;
229 }
230 //创建关机Dialog
231 sConfirmDialog = new AlertDialog.Builder(context, sInstance.mThemeResId)
232 .setTitle(mRebootSafeMode
233 ? com.android.internal.R.string.reboot_safemode_title
234 /*UNISOC bug 908624*/
235 :(mReboot
236 ? com.android.internal.R.string.reboot_device_title
237 /*UNISOC bug 908624*/
238 : com.android.internal.R.string.power_off))
239 .setMessage(resourceId)
240 .setPositiveButton(com.android.internal.R.string.yes, new DialogInterface.OnClickListener() {
241 public void onClick(DialogInterface dialog, int which) {
242 beginShutdownSequence(context);//执行shutdownsequence方法,开始关机的流程
243 }
244 })
245 .setNegativeButton(com.android.internal.R.string.no, null)
246 .create();
247 closer.dialog = sConfirmDialog;
248 sConfirmDialog.setOnDismissListener(closer);
249 sConfirmDialog.getWindow().setType(WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG);
250 sConfirmDialog.show();
251 } else {
252 beginShutdownSequence(context);
253 }
254 }
2.9 ShutdownThread.beginShutdownSequence()
我们一般可以在这个方法里添加关机动画,在这里加入的sprd的关机动画
private static void beginShutdownSequence(Context context) {
420 synchronized (sIsStartedGuard) {
421 if (sIsStarted) {
422 Log.d(TAG, "Shutdown sequence already running, returning.");
423 return;
424 }
425 sIsStarted = true;
426 }
427
428 // SPRD:add for shutdownanim
429 if (shutdownAnim.hasShutdownAnimation() &&
430 !(mReason != null && mReason.startsWith(PowerManager.REBOOT_RECOVERY_UPDATE))) {
431 shutdownAnim.playShutdownAnimation();
432 } else {
433 sInstance.mProgressDialog = showShutdownDialog(context);
434 }
435 sInstance.mContext = context;
436
437 // make sure we never fall asleep again
438 sInstance.mCpuWakeLock = null;
439 try {
440 sInstance.mCpuWakeLock = sInstance.mPowerManager.newWakeLock(
441 PowerManager.PARTIAL_WAKE_LOCK, TAG + "-cpu");
442 sInstance.mCpuWakeLock.setReferenceCounted(false);
443 sInstance.mCpuWakeLock.acquire();
444 } catch (SecurityException e) {
445 Log.w(TAG, "No permission to acquire wake lock", e);
446 sInstance.mCpuWakeLock = null;
447 }
……
} else {
//启动关机线程,执行Run()方法
475 sInstance.mHandler = new Handler() {
476 };
477 sInstance.start();
478 }
479 }
480
2.10 ShutdowmThread.run()
492 public void run() {
……
{
511 String reason = (mReboot ? "1" : "0") + (mReason != null ? mReason : "");
512 SystemProperties.set(SHUTDOWN_ACTION_PROPERTY, reason);
//保存关机的原因
513 }
514
515 /*
516 * If we are rebooting into safe mode, write a system property
517 * indicating so.
518 */
519 if (mRebootSafeMode) {
520 SystemProperties.set(REBOOT_SAFEMODE_PROPERTY, "1");
521 }
522
523 metricStarted(METRIC_SEND_BROADCAST);
524 shutdownTimingLog.traceBegin("SendShutdownBroadcast");
525 Log.i(TAG, "Sending shutdown broadcast...");
526
527 // First send the high-level shut down broadcast.
528 mActionDone = false;
529 Intent intent = new Intent(Intent.ACTION_SHUTDOWN);
530 intent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND | Intent.FLAG_RECEIVER_REGISTERED_ONLY);
//发送关机广播
531 mContext.sendOrderedBroadcastAsUser(intent,
532 UserHandle.ALL, null, br, mHandler, 0, null, null);
533
534 final long endTime = SystemClock.elapsedRealtime() + MAX_BROADCAST_TIME;
535 synchronized (mActionDoneSync) {
536 while (!mActionDone) {
537 long delay = endTime - SystemClock.elapsedRealtime();
538 if (delay <= 0) {
539 Log.w(TAG, "Shutdown broadcast timed out");
540 break;
541 } else if (mRebootHasProgressBar) {
542 int status = (int)((MAX_BROADCAST_TIME - delay) * 1.0 *
543 BROADCAST_STOP_PERCENT / MAX_BROADCAST_TIME);
544 sInstance.setRebootProgress(status, null);
545 }
546 try {
547 mActionDoneSync.wait(Math.min(delay, ACTION_DONE_POLL_WAIT_MS));
548 } catch (InterruptedException e) {
549 }
550 }
551 }
552 if (mRebootHasProgressBar) {
553 sInstance.setRebootProgress(BROADCAST_STOP_PERCENT, null);
554 }
555 shutdownTimingLog.traceEnd(); // SendShutdownBroadcast
//sendshutsownbroadcast 关机广播耗时
556 metricEnded(METRIC_SEND_BROADCAST);
557
558 Log.i(TAG, "Shutting down activity manager...");
559 shutdownTimingLog.traceBegin("ShutdownActivityManager");
560 metricStarted(METRIC_AM);
561
562 final IActivityManager am =
563 IActivityManager.Stub.asInterface(ServiceManager.checkService("activity"));
564 if (am != null) {
565 try {
566 am.shutdown(MAX_BROADCAST_TIME);//关闭activitymanagerservice服务
567 } catch (RemoteException e) {
568 }
569 }
570 if (mRebootHasProgressBar) {
571 sInstance.setRebootProgress(ACTIVITY_MANAGER_STOP_PERCENT, null);
572 }
573 shutdownTimingLog.traceEnd();// ShutdownActivityManager
574 metricEnded(METRIC_AM);
575
576 Log.i(TAG, "Shutting down package manager...");
577 shutdownTimingLog.traceBegin("ShutdownPackageManager");
578 metricStarted(METRIC_PM);
579
580 final PackageManagerService pm = (PackageManagerService)
581 ServiceManager.getService("package");
582 if (pm != null) {
583 pm.shutdown();//关闭packageManagerService服务
584 }
585 if (mRebootHasProgressBar) {
586 sInstance.setRebootProgress(PACKAGE_MANAGER_STOP_PERCENT, null);
587 }
588 shutdownTimingLog.traceEnd(); // ShutdownPackageManager
589 metricEnded(METRIC_PM);
590
591 // Shutdown radios.
592 shutdownTimingLog.traceBegin("ShutdownRadios");
593 metricStarted(METRIC_RADIOS);
594 shutdownRadios(MAX_RADIO_WAIT_TIME);
595 if (mRebootHasProgressBar) {
596 sInstance.setRebootProgress(RADIO_STOP_PERCENT, null);
597 }
598 shutdownTimingLog.traceEnd(); // ShutdownRadios
599 metricEnded(METRIC_RADIOS);
600
601 if (mRebootHasProgressBar) {
602 sInstance.setRebootProgress(MOUNT_SERVICE_STOP_PERCENT, null);
603
604 // If it's to reboot to install an update and uncrypt hasn't been
605 // done yet, trigger it now.
606 uncrypt();
607 }
608
609 shutdownTimingLog.traceEnd(); // SystemServerShutdown
610 metricEnded(METRIC_SYSTEM_SERVER);
611 saveMetrics(mReboot, mReason);
612 // SPRD:add for shutdownanim
613 shutdownAnim.waitForBootanim();
614 // Remaining work will be done by init, including vold shutdown
615 rebootOrShutdown(mContext, mReboot, mReason);//执行rebootOrShutdown方法()
616 }
2.11 ShutdownThread.rebootOrShutdown()
当前方法决定是关机还是重启
public static void rebootOrShutdown(final Context context, boolean reboot, String reason) {
739 if (reboot) {//判断是否重启
740 Log.i(TAG, "Rebooting, reason: " + reason);
741 PowerManagerService.lowLevelReboot(reason);
742 Log.e(TAG, "Reboot failed, will attempt shutdown instead");
743 reason = null;
744 } else if (SHUTDOWN_VIBRATE_MS > 0 && context != null) {
745 // vibrate before shutting down
746 Vibrator vibrator = new SystemVibrator(context);
747 try {
//关机之前震动
748 vibrator.vibrate(SHUTDOWN_VIBRATE_MS, VIBRATION_ATTRIBUTES);
749 } catch (Exception e) {
750 // Failure to vibrate shouldn't interrupt shutdown. Just log it.
751 Log.w(TAG, "Failed to vibrate during shutdown.", e);
752 }
753
754 // vibrator is asynchronous so we need to wait to avoid shutting down too soon.
755 try {
756 Thread.sleep(SHUTDOWN_VIBRATE_MS);
757 } catch (InterruptedException unused) {
758 }
759 }
760 // Shutdown power
761 Log.i(TAG, "Performing low-level shutdown...");
//调用lowLevelSgutdwon方法,shutdown power
762 PowerManagerService.lowLevelShutdown(reason);
763 }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。