What happened when I long press power button ?
What is shutdown sequence ?
How is it different from desktop linux shutdown sequence?
How to change shutdown menu ?

Many questions pop-up in mind when we think about Android shutdown sequence. Before you read about shutdown sequence I suggest you to read aboutboot sequence article.

Android is linux based open source operating system, x86 (x86 is a series of computer microprocessor instruction set architectures based on the Intel 8086 CPU.) is most likely system where linux kernel is deployed however all Android devices are running on ARM process (ARM (formerly Advanced RISC Machine, which was formerly Acorn RISC Machine)) except Intel’s Xolo device (http://xolo.in/xolo-x900-features). Xolo comes with Atom 1.6 GHz x86 processor. Android shutdown sequence is different from desktop linux like ubuntu, fedora, etc.  
In this article I am going to explain shutdown sequence for Android only. Please refer"Linux Boot and Shutdown Process" for details of desktop linux shutdown process.

Following diagram illustrate shutdown sequence in detail.

Step 1: Long Press Power Button for 500ms.
Step 2: PhoneWindowManager.java identify Power Button long press and call method named "interceptKeyBeforeQueueing". 
Following code display power key  snippet from the function.
  1. /** {@inheritDoc} */
  2. @Override
  3. public int interceptKeyBeforeQueueing(KeyEvent event, int policyFlags, boolean isScreenOn) {
  4. ....
  5. ....
  6. ....
  7. case KeyEvent.KEYCODE_POWER: {
  8. result &= ~ACTION_PASS_TO_USER;
  9. if (down) {
  10. if (isScreenOn && !mPowerKeyTriggered
  11. && (event.getFlags() & KeyEvent.FLAG_FALLBACK) == 0) {
  12. mPowerKeyTriggered = true;
  13. mPowerKeyTime = event.getDownTime();
  14. interceptScreenshotChord();
  15. }
  16. ITelephony telephonyService = getTelephonyService();
  17. boolean hungUp = false;
  18. if (telephonyService != null) {
  19. try {
  20. if (telephonyService.isRinging()) {
  21. // Pressing Power while there's a ringing incoming
  22. // call should silence the ringer.
  23. telephonyService.silenceRinger();
  24. } else if ((mIncallPowerBehavior
  25. & Settings.Secure.INCALL_POWER_BUTTON_BEHAVIOR_HANGUP) != 0
  26. && telephonyService.isOffhook()) {
  27. // Otherwise, if "Power button ends call" is enabled,
  28. // the Power button will hang up any current active call.
  29. hungUp = telephonyService.endCall();
  30. }
  31. } catch (RemoteException ex) {
  32. Log.w(TAG, "ITelephony threw RemoteException", ex);
  33. }
  34. }
  35. interceptPowerKeyDown(!isScreenOn || hungUp
  36. || mVolumeDownKeyTriggered || mVolumeUpKeyTriggered);
  37. } else {
  38. mPowerKeyTriggered = false;
  39. cancelPendingScreenshotChordAction();
  40. if (interceptPowerKeyUp(canceled || mPendingPowerKeyUpCanceled)) {
  41. result = (result & ~ACTION_WAKE_UP) | ACTION_GO_TO_SLEEP;
  42. }
  43. mPendingPowerKeyUpCanceled = false;
  44. }
  45. break;
  46. }
  47. ....
  48. ....
  49. ....
  50. }
Above code handle multiple options like silence ringtone, take screenshots and power off. It will identify appropriate option based on time duration and other key's status. It will call "interceptPowerKeyDown" option by eliminate other options.
 
Following code display interceptPowerKeyDown function. It will wait for 500 millisecond (ViewConfiguration#getGlobalActionKeyTimeout()) then call mPowerLongPress Thread.
  1. private void interceptPowerKeyDown(boolean handled) {
  2. mPowerKeyHandled = handled;
  3. if (!handled) {
  4. mHandler.postDelayed(mPowerLongPress, ViewConfiguration.getGlobalActionKeyTimeout());
  5. }
  6. }

Following code represent mPowerLongPress thread

  1. private final Runnable mPowerLongPress = new Runnable() {
  2. @Override
  3. public void run() {
  4. // The context isn't read
  5. if (mLongPressOnPowerBehavior < 0) {
  6. mLongPressOnPowerBehavior = mContext.getResources().getInteger(
  7. com.android.internal.R.integer.config_longPressOnPowerBehavior);
  8. }
  9. int resolvedBehavior = mLongPressOnPowerBehavior;
  10. if (FactoryTest.isLongPressOnPowerOffEnabled()) {
  11. resolvedBehavior = LONG_PRESS_POWER_SHUT_OFF_NO_CONFIRM;
  12. }
  13.  
  14. switch (resolvedBehavior) {
  15. case LONG_PRESS_POWER_NOTHING:
  16. break;
  17. case LONG_PRESS_POWER_GLOBAL_ACTIONS:
  18. mPowerKeyHandled = true;
  19. if (!performHapticFeedbackLw(null, HapticFeedbackConstants.LONG_PRESS, false)) {
  20. performAuditoryFeedbackForAccessibilityIfNeed();
  21. }
  22. sendCloseSystemWindows(SYSTEM_DIALOG_REASON_GLOBAL_ACTIONS);
  23. showGlobalActionsDialog();
  24. break;
  25. case LONG_PRESS_POWER_SHUT_OFF:
  26. case LONG_PRESS_POWER_SHUT_OFF_NO_CONFIRM:
  27. mPowerKeyHandled = true;
  28. performHapticFeedbackLw(null, HapticFeedbackConstants.LONG_PRESS, false);
  29. sendCloseSystemWindows(SYSTEM_DIALOG_REASON_GLOBAL_ACTIONS);
  30. mWindowManagerFuncs.shutdown(resolvedBehavior == LONG_PRESS_POWER_SHUT_OFF);
  31. break;
  32. }
  33. }
  34. };
Step 3: Controls goes to GlobalActions.java which is responsible to display dialogbox with various options like (Power Off, Airplan mode, Take screenshot and few toggle buttons), This dialog box has different options are per your OEM provider, model and Android OS version. GlobalAction class has method named showdialog() which is responsible to create object of Dialogbox with options.
  1. void showGlobalActionsDialog() {
  2. if (mGlobalActions == null) {
  3. mGlobalActions = new GlobalActions(mContext, mWindowManagerFuncs);
  4. }
  5. final boolean keyguardShowing = keyguardIsShowingTq();
  6. mGlobalActions.showDialog(keyguardShowing, isDeviceProvisioned());
  7. if (keyguardShowing) {
  8. // since it took two seconds of long press to bring this up,
  9. // poke the wake lock so they have some time to see the dialog.
  10. mKeyguardMediator.userActivity();
  11. }
  12. }
Step 4: If user select "Power Off" option from the dialogbox then control again goes back to PhoneWindowManager, It will start shutdown process.
Step 5: Shutdown process initiate from ShutdownThread.java file's shoutdowninner() function, It wil display confirmation dialog with ok / cancel button, If user select ok option then actual shutdown process starts.
Step 6: beginShutdownSequence() function called when user select OK option from the dialog.
  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.  
  10. // throw up an indeterminate system dialog to indicate radio is
  11. // shutting down.
  12. ProgressDialog pd = new ProgressDialog(context);
  13. pd.setTitle(context.getText(com.android.internal.R.string.power_off));
  14. pd.setMessage(context.getText(com.android.internal.R.string.shutdown_progress));
  15. pd.setIndeterminate(true);
  16. pd.setCancelable(false);
  17. pd.getWindow().setType(WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG);
  18.  
  19. pd.show();
  20.  
  21. sInstance.mContext = context;
  22. sInstance.mPowerManager = (PowerManager)context.getSystemService(Context.POWER_SERVICE);
  23.  
  24. // make sure we never fall asleep again
  25. sInstance.mCpuWakeLock = null;
  26. try {
  27. sInstance.mCpuWakeLock = sInstance.mPowerManager.newWakeLock(
  28. PowerManager.PARTIAL_WAKE_LOCK, TAG + "-cpu");
  29. sInstance.mCpuWakeLock.setReferenceCounted(false);
  30. sInstance.mCpuWakeLock.acquire();
  31. } catch (SecurityException e) {
  32. Log.w(TAG, "No permission to acquire wake lock", e);
  33. sInstance.mCpuWakeLock = null;
  34. }
  35.  
  36. // also make sure the screen stays on for better user experience
  37. sInstance.mScreenWakeLock = null;
  38. if (sInstance.mPowerManager.isScreenOn()) {
  39. try {
  40. sInstance.mScreenWakeLock = sInstance.mPowerManager.newWakeLock(
  41. PowerManager.FULL_WAKE_LOCK, TAG + "-screen");
  42. sInstance.mScreenWakeLock.setReferenceCounted(false);
  43. sInstance.mScreenWakeLock.acquire();
  44. } catch (SecurityException e) {
  45. Log.w(TAG, "No permission to acquire wake lock", e);
  46. sInstance.mScreenWakeLock = null;
  47. }
  48. }
  49.  
  50. // start the thread that initiates shutdown
  51. sInstance.mHandler = new Handler() {
  52. };
  53. sInstance.start();
  54. }

Run method, start actual shutdown process 

  1. public void run() {
  2. BroadcastReceiver br = new BroadcastReceiver() {
  3. @Override public void onReceive(Context context, Intent intent) {
  4. // We don't allow apps to cancel this, so ignore the result.
  5. actionDone();
  6. }
  7. };
  8.  
  9. /*
  10. * Write a system property in case the system_server reboots before we
  11. * get to the actual hardware restart. If that happens, we'll retry at
  12. * the beginning of the SystemServer startup.
  13. */
  14. {
  15. String reason = (mReboot ? "1" : "0") + (mRebootReason != null ? mRebootReason : "");
  16. SystemProperties.set(SHUTDOWN_ACTION_PROPERTY, reason);
  17. }
  18.  
  19. /*
  20. * If we are rebooting into safe mode, write a system property
  21. * indicating so.
  22. */
  23. if (mRebootSafeMode) {
  24. SystemProperties.set(REBOOT_SAFEMODE_PROPERTY, "1");
  25. }
  26.  
  27. Log.i(TAG, "Sending shutdown broadcast...");
  28.  
  29. // First send the high-level shut down broadcast.
  30. mActionDone = false;
  31. Intent intent = new Intent(Intent.ACTION_SHUTDOWN);
  32. intent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
  33. mContext.sendOrderedBroadcastAsUser(intent,
  34. UserHandle.ALL, null, br, mHandler, 0, null, null);
  35.  
  36. final long endTime = SystemClock.elapsedRealtime() + MAX_BROADCAST_TIME;
  37. synchronized (mActionDoneSync) {
  38. while (!mActionDone) {
  39. long delay = endTime - SystemClock.elapsedRealtime();
  40. if (delay <= 0) {
  41. Log.w(TAG, "Shutdown broadcast timed out");
  42. break;
  43. }
  44. try {
  45. mActionDoneSync.wait(delay);
  46. } catch (InterruptedException e) {
  47. }
  48. }
  49. }
  50.  
  51. Log.i(TAG, "Shutting down activity manager...");
  52.  
  53. final IActivityManager am =
  54. ActivityManagerNative.asInterface(ServiceManager.checkService("activity"));
  55. if (am != null) {
  56. try {
  57. am.shutdown(MAX_BROADCAST_TIME);
  58. } catch (RemoteException e) {
  59. }
  60. }
  61.  
  62. // Shutdown radios.
  63. shutdownRadios(MAX_RADIO_WAIT_TIME);
  64.  
  65. // Shutdown MountService to ensure media is in a safe state
  66. IMountShutdownObserver observer = new IMountShutdownObserver.Stub() {
  67. public void onShutDownComplete(int statusCode) throws RemoteException {
  68. Log.w(TAG, "Result code " + statusCode + " from MountService.shutdown");
  69. actionDone();
  70. }
  71. };
  72.  
  73. Log.i(TAG, "Shutting down MountService");
  74.  
  75. // Set initial variables and time out time.
  76. mActionDone = false;
  77. final long endShutTime = SystemClock.elapsedRealtime() + MAX_SHUTDOWN_WAIT_TIME;
  78. synchronized (mActionDoneSync) {
  79. try {
  80. final IMountService mount = IMountService.Stub.asInterface(
  81. ServiceManager.checkService("mount"));
  82. if (mount != null) {
  83. mount.shutdown(observer);
  84. } else {
  85. Log.w(TAG, "MountService unavailable for shutdown");
  86. }
  87. } catch (Exception e) {
  88. Log.e(TAG, "Exception during MountService shutdown", e);
  89. }
  90. while (!mActionDone) {
  91. long delay = endShutTime - SystemClock.elapsedRealtime();
  92. if (delay <= 0) {
  93. Log.w(TAG, "Shutdown wait timed out");
  94. break;
  95. }
  96. try {
  97. mActionDoneSync.wait(delay);
  98. } catch (InterruptedException e) {
  99. }
  100. }
  101. }
  102.  
  103. rebootOrShutdown(mReboot, mRebootReason);
  104. }

Step 7: With rebootOrShutdown() method controls transfer to the native function of com_android_server_power_PowerManagerService.cpp file, and finally control goes to android_reboot.c file which is final step of shutdown sequence.

  1. static void nativeShutdown(JNIEnv *env, jclass clazz) {
  2. android_reboot(ANDROID_RB_POWEROFF, 0, 0);
  3. }

In Depth : Android Shutdown Sequence的更多相关文章

  1. In Depth : Android Boot Sequence / Process

    In Depth : Android Boot Sequence / Process What happened when I press power on button in my Android ...

  2. I.MX6 android shutdown 内核崩溃

    /**************************************************************************** * I.MX6 android shutdo ...

  3. I.MX6 Android shutdown shell command

    /******************************************************************************* * I.MX6 Android shu ...

  4. Android Framework层Power键关机流程(二,关机流程)

    二,关机流程 从前一篇博文我们知道,当用户长按Power键时会弹出(关机.重启,飞行模式等选项)对话框,我们点击关机,则会弹出关机确认对话框.那么从选项对话框到关机确认对话框又是一个什么流程呢.下面我 ...

  5. Android关机流程源码分析

    上一篇文章Android 开关机动画显示源码分析详细介绍了开关机动画的显示过程,Android系统开机时,在启动SurfaceFlinger服务过程中通过Android属性系统方式来启动bootani ...

  6. Android 4.1.2系统添加重启功能

    对于Android的的手机或者平板长期使用,感觉会出现慢的情况,所以偶尔还是需要重启一下,而长按电源键弹出的菜单又没有重启选项,所以特在此记录自己添加这个功能的过程. 首先关机的那个弹出菜单是在fra ...

  7. 深入解析Android关机

    下图详细阐释了Android的关机顺序. 第一步: 按住电源按钮半秒钟(500ms). 第二步: 之后,PhoneWindowManager.java 将捕获长按电源按钮这一事件并调用“interce ...

  8. Android 9.0 关机流程分析

    极力推荐文章:欢迎收藏 Android 干货分享 阅读五分钟,每日十点,和您一起终身学习,这里是程序员Android 本篇文章主要介绍 Android 开发中的部分知识点,通过阅读本篇文章,您将收获以 ...

  9. No shutdown animation in the electricity display only 1%

    低电量自动关机时无关机动画 低电量自动关机时无关机动画1. 问题描述2. 分析3. solution4. 总结 1. 问题描述 DEFECT DESCRIPTION: No shutdown anim ...

随机推荐

  1. X - A == B ?(第二季水)

    Description Give you two numbers A and B, if A is equal to B, you should print "YES", or p ...

  2. MySQL 初学笔记 ② -- MySQL安装

    1. Ubuntu安装 sudo apt-get install mysql-server //安装mysql服务 sudo apt-get install mysql-client // sudo ...

  3. 理解ThreadLocal(一)

    早在JDK 1.2的版本中就提供java.lang.ThreadLocal,ThreadLocal为解决多线程程序的并发问题提供了一种新的思路.使用这个工具类可以很简洁地编写出优美的多线程程序. Th ...

  4. Samba服务器

    Windows操作系统下:DOC命令下:netstat -an查看端口 (一)简介 文件服务器 (二)端口 smbd: 为clinet提高资源访问 tcp  139  445    (类似于windo ...

  5. Nginx 变量漫谈(六)

    Nginx 内建变量用在“子请求”的上下文中时,其行为也会变得有些微妙. 前面在 (三) 中我们已经知道,许多内建变量都不是简单的“存放值的容器”,它们一般会通过注册“存取处理程序”来表现得与众不同, ...

  6. ASP.NET 短路由配置

    1. 首先在项目新建文件叫App_Code或者App_Start 在文件中新建WebFromRouteHandler.cs 文件. WebFromRouteHandler中的代码如下, public  ...

  7. sa命令从/var/account/pacct原始记账数据文件读取信息并汇总

    sa命令从/var/account/pacct原始记账数据文件读取信息并汇总

  8. asp.net基础学习笔记

    原文地址:http://blog.csdn.net/oxoxzhu/article/details/8652530 1.概论 浏览器-服务器 B/S 浏览的      浏览器和服务器之间的交互,形成上 ...

  9. Hadoop 3、Hadoop 分布式存储系统 HDFS

    HDFS是Hadoop Distribute File System 的简称,也就是Hadoop的一个分布式文件系统. 一.HDFS的优缺点 1.HDFS优点: a.高容错性 .数据保存多个副本 .数 ...

  10. Hibernate问题之'hibernate.dialect' not set

    继前文:Hibernate4中buildSessionFactory方法废弃问题.后 继续有问题.本来之前好好的项目,用了这种新的方法后发现问题. 出现  Connection cannot be n ...