android 关机流程详细分析。前面有提到过android事件上报流程,InputReaderThread 从EventHub读到按键事件后,交给InputDispatcher 往上上报,我们从这里跟踪一下长按power键关键流程,

frameworks/native/services/inputflinger/InputDispatcher.cpp

?
1 2 3 4 5 void  InputDispatcher::notifyKey( const  NotifyKeyArgs* args) { mPolicy->interceptKeyBeforeQueueing(&event,  /*byref*/  policyFlags); }

这里的mPolicy是NativeInputManager对象.

frameworks/base/services/core/jni/com_android_server_input_InputManagerService.cpp

?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 void  NativeInputManager::interceptKeyBeforeQueueing( const  KeyEvent* keyEvent, uint32_t& policyFlags) {    jobject keyEventObj = android_view_KeyEvent_fromNative(env, keyEvent); 886           jint wmActions; 887           if  (keyEventObj) { 888               wmActions = env->CallIntMethod(mServiceObj, 889                       gServiceClassInfo.interceptKeyBeforeQueueing, 890                       keyEventObj, policyFlags); 891               if  (checkAndClearExceptionFromCallback(env,  "interceptKeyBeforeQueueing" )) { 892                   wmActions =  0 ; 893               } 894               android_view_KeyEvent_recycle(env, keyEventObj); 895               env->DeleteLocalRef(keyEventObj); 896           else  { 897               ALOGE( "Failed to obtain key event object for interceptKeyBeforeQueueing." ); 898               wmActions =  0 ; 899           } }
这里会call到java层,call 到InputManagerService里面。

frameworks/base/services/core/java/com/android/server/input/InputManagerService.java

?
1 2 3 // Native callback. 1871       private  int  interceptKeyBeforeQueueing(KeyEvent event,  int  policyFlags) { 1872           return  mWindowManagerCallbacks.interceptKeyBeforeQueueing(event, policyFlags);
?
1

这个mWindowManagerCallbacks 是通过下面的接口设置的。

?
1 inputManager.setWindowManagerCallbacks(wm.getInputMonitor());
继续追查下去,就是一个InputMonitor 实例。

frameworks/base/services/core/java/com/android/server/wm/InputMonitor.java

?
1 2 3 public  int  interceptKeyBeforeQueueing(KeyEvent event,  int  policyFlags) {       return  mService.mPolicy.interceptKeyBeforeQueueing(event, policyFlags);   }

这里的mService就是WindowManagerService。

frameworks/base/services/core/java/com/android/server/wm/WindowManagerService.java ?
1 final  WindowManagerPolicy mPolicy =  new  PhoneWindowManager();
所以这个mPolicy就是PhoneWindowManager对象。
frameworks/base/services/core/java/com/android/server/policy/PhoneWindowManager.java ?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 public  int  interceptKeyBeforeQueueing(KeyEvent event,  int  policyFlags) {   @Override public  int  interceptKeyBeforeQueueing(KeyEvent event,  int  policyFlags) {     case  KeyEvent.KEYCODE_POWER: { 5815                   result &= ~ACTION_PASS_TO_USER; 5816                   isWakeKey =  false // wake-up will be handled separately 5817                   if  (down) { 5818                       interceptPowerKeyDown(event, interactive); 5819                   else  { 5820                       interceptPowerKeyUp(event, interactive, canceled); 5821                   } 5822                   break ; 5823               }
继续走到interceptPowerKeyDown()函数里面。 ?
1 private  void  interceptPowerKeyDown(KeyEvent event,  boolean  interactive) {
?
1 2 3 4 5 6 7 8 9 10 11 ... if  (interactive) { 1087                   // When interactive, we're already awake. 1088                   // Wait for a long press or for the button to be released to decide what to do. 1089                   if  (hasLongPressOnPowerBehavior()) { 1090                       Message msg = mHandler.obtainMessage(MSG_POWER_LONG_PRESS); 1091                       msg.setAsynchronous( true ); 1092                       mHandler.sendMessageDelayed(msg, 1093                               ViewConfiguration.get(mContext).getDeviceGlobalActionKeyTimeout()); 1094                   } 1095               }
?
1 }
这里面判断是长按power键后会发一个MSG_POWER_LONG_PRESS消息出来,我们看一下它的处理。 ?
1 2 3 4 5 6 7 8 9 10 private  class  PolicyHandler  extends  Handler { ... 746           @Override 747           public  void  handleMessage(Message msg) { 748               switch  (msg.what) {    case  MSG_POWER_LONG_PRESS: 790                       powerLongPress(); 791                       break ;

?
1 2 3 4 5 6 7 8 9 10 11 12 13 14    private  void  powerLongPress() { 1255           final  int  behavior = getResolvedLongPressOnPowerBehavior(); 1256           switch  (behavior) { 1257           case  LONG_PRESS_POWER_NOTHING: 1258               break ; 1259           case  LONG_PRESS_POWER_GLOBAL_ACTIONS: 1260               mPowerKeyHandled =  true ; 1261               if  (!performHapticFeedbackLw( null , HapticFeedbackConstants.LONG_PRESS,  false )) { 1262                   performAuditoryFeedbackForAccessibilityIfNeed(); 1263               } 1264               showGlobalActionsInternal(); 1265               break ; 1273           } 1274       }
接下来会走到showGlobalActionsInternal()函数里面。 ?
1 2 3 4 5 6 7 8 9 10 11 12 13    void  showGlobalActionsInternal() { 1389           sendCloseSystemWindows(SYSTEM_DIALOG_REASON_GLOBAL_ACTIONS); 1390           if  (mGlobalActions ==  null ) { 1391               mGlobalActions =  new  GlobalActions(mContext, mWindowManagerFuncs); 1392           } 1393           final  boolean  keyguardShowing = isKeyguardShowingAndNotOccluded(); 1394           mGlobalActions.showDialog(keyguardShowing, isDeviceProvisioned()); 1395           if  (keyguardShowing) { 1396               // since it took two seconds of long press to bring this up, 1397               // poke the wake lock so they have some time to see the dialog. 1398               mPowerManager.userActivity(SystemClock.uptimeMillis(),  false ); 1399           } 1400       }

showDialog(keyguardShowing, isDeviceProvisioned());会弹出选择界面。

frameworks/base/services/core/java/com/android/server/policy/GlobalActions.java ?
1 2 3 4 5 6 7 8 9 10 11 12    public  void  showDialog( boolean  keyguardShowing,  boolean  isDeviceProvisioned) { 172           mKeyguardShowing = keyguardShowing; 173           mDeviceProvisioned = isDeviceProvisioned; 174           if  (mDialog !=  null ) { 175               mDialog.dismiss(); 176               mDialog =  null ; 177               // Show delayed, so that the dismiss of the previous dialog completes 178               mHandler.sendEmptyMessage(MESSAGE_SHOW); 179           else  { 180               handleShow(); 181           } 182       }

?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 private  void  handleShow() { 197           awakenIfNecessary(); 198           mDialog = createDialog(); 199           prepareDialog(); 200  201           // If we only have 1 item and it's a simple press action, just do this action. 202           if  (mAdapter.getCount() ==  1 203                   && mAdapter.getItem( 0 instanceof SinglePressAction 204                   && !(mAdapter.getItem( 0 instanceof LongPressAction)) { 205               ((SinglePressAction) mAdapter.getItem( 0 )).onPress(); 206           else  { 207               WindowManager.LayoutParams attrs = mDialog.getWindow().getAttributes(); 208               attrs.setTitle( "GlobalActions" ); 209               mDialog.getWindow().setAttributes(attrs); 210               mDialog.show(); 211               mDialog.getWindow().getDecorView().setSystemUiVisibility(View.STATUS_BAR_DISABLE_EXPAND); 212           } 213       }
createDialog()里面很重要的一点是创建了多项选项按钮,并绑定了对应的处理函数。
?
1 2 3 4 5 6 7 8 private  GlobalActionsDialog createDialog() {    if  (GLOBAL_ACTION_KEY_POWER.equals(actionKey)) { 281                   mItems.add( new  PowerAction()); 282               else  if  (GLOBAL_ACTION_KEY_AIRPLANE.equals(actionKey)) { 283                   mItems.add(mAirplaneModeOn); 284               }   }
关机对应的是PowerAction 。 ?
1 2 3 4 5 6 7 private  final  class  PowerAction  extends  SinglePressAction  implements  LongPressAction {    @Override 376           public  void  onPress() { 377               // shutdown by making sure radio and power are handled accordingly. 378               mWindowManagerFuncs.shutdown( false  /* confirm */ ); 379           } 380       }

如果点击关机按钮,就会走到onPress(),调用WindowManagerservice的shutdown接口。

?
1 2 3 4 5 // Called by window manager policy.  Not exposed externally. 5823       @Override 5824       public  void  shutdown( boolean  confirm) { 5825           ShutdownThread.shutdown(mContext, PowerManager.SHUTDOWN_USER_REQUESTED, confirm); 5826       }
frameworks/base/services/core/java/com/android/server/power/ShutdownThread.java ?
1 2 3 4 5 6      public  static  void  shutdown( final  Context context, String reason,  boolean confirm) { 133           mReboot =  false ; 134           mRebootSafeMode =  false ; 135           mReason = reason; 136           shutdownInner(context, confirm); 137       }
?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 static  void  shutdownInner( final  Context context,  boolean  confirm) { ... 159           if  (confirm) { 160               final  CloseDialogReceiver closer =  new CloseDialogReceiver(context); 161               if  (sConfirmDialog !=  null ) { 162                   sConfirmDialog.dismiss(); 163               } 164               sConfirmDialog =  new  AlertDialog.Builder(context) 165                       .setTitle(mRebootSafeMode 166                               ? com.android.internal.R.string.reboot_safemode_title 167                               : com.android.internal.R.string.power_off) 168                       .setMessage(resourceId) 169                       .setPositiveButton(com.android.internal.R.string.yes,  new DialogInterface.OnClickListener() { 170                           public  void onClick(DialogInterface dialog,  int  which) { 171                               beginShutdownSequence(context); 172                           } 173                       }) 174                       .setNegativeButton(com.android.internal.R.string.no,  null ) 175                       .create(); 176               closer.dialog = sConfirmDialog; 177               sConfirmDialog.setOnDismissListener(closer); 178               sConfirmDialog.getWindow().setType(WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG); 179               sConfirmDialog.show(); 180           else  { 181               beginShutdownSequence(context); 182           } 183       }
如果confirm为true,则弹出确认对话框,总之最终会走beginShutdownSequence(context) 进行接下来的关机流程。 ?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 private  static  void  beginShutdownSequence(Context context) { ... 276           if  (PowerManager.REBOOT_RECOVERY_UPDATE.equals(mReason)) { ... 301           else  { 302               pd.setTitle(context.getText(com.android.internal.R.string.power_off)); 303               pd.setMessage(context.getText(com.android.internal.R.string.shutdown_progress)); 304               pd.setIndeterminate( true ); 305           } 306           pd.setCancelable( false ); 307           pd.getWindow().setType(WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG); 308  309           pd.show(); 310   ... 341           // start the thread that initiates shutdown 342           sInstance.mHandler =  new  Handler() { 343           }; 344           sInstance.start(); 345       }
pd.show(); 显示关机的进度界面,sInstance.start(); 会启动另外一个线程,走接下来的关机流程。 ?
1 private  static  final  ShutdownThread sInstance =  new  ShutdownThread();
?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 358       public  void  run() { 359          ... 384           Log.i(TAG,  "Sending shutdown broadcast..." ); 385  386           // First send the high-level shut down broadcast. 387           mActionDone =  false ; 388           Intent intent =  new  Intent(Intent.ACTION_SHUTDOWN); 389           intent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND); 390           mContext.sendOrderedBroadcastAsUser(intent, 391                   UserHandle.ALL,  null , br, mHandler,  0 null null ); 392  393         ... 497           rebootOrShutdown(mContext, mReboot, mReason); 498       }
ShutdownThread启动之后,就会跑它的run()函数,做了很多工作,发送关机广播,做一些状态检查和清理工作。 ?
1 2 3 4 5 6 7 8 9 10 11 12 13 14      public  static  void  rebootOrShutdown( final  Context context,  boolean  reboot, String reason) { 644           if  (reboot) { 645               Log.i(TAG,  "Rebooting, reason: "  + reason); 646               PowerManagerService.lowLevelReboot(reason); 647               Log.e(TAG,  "Reboot failed, will attempt shutdown instead" ); 648               reason =  null ; 649           else  if  (SHUTDOWN_VIBRATE_MS >  0  && context !=  null ) { ... 664           } 665  666           // Shutdown power 667           Log.i(TAG,  "Performing low-level shutdown..." ); 668           PowerManagerService.lowLevelShutdown(reason); 669       }

最后又跑到PowerManagerService 的lowLevelShutdown()。

frameworks/base/services/core/java/com/android/server/power/PowerManagerService.java ?
1 2 3 4 5 6      public  static  void  lowLevelShutdown(String reason) { 2787           if  (reason ==  null ) { 2788               reason =  "" ; 2789           } 2790           SystemProperties.set( "sys.powerctl" "shutdown,"  + reason); 2791       }

很多人疑惑SystemProperties.set("sys.powerctl", "shutdown,"+ reason);又跑到了哪里?



首先sys.powerctl 在init.rc中有配置,它是一类特殊的property,可以认为是command。

它对应的处理函数定义在/system/core/init/builtins.cpp中。

?
1 2 3 4 { "mount" ,                   { 3 ,     kMax, do_mount}},       { "umount" ,                  { 1 ,      1 ,    do_umount}},       { "powerctl" ,                { 1 ,      1 ,    do_powerctl}},       { "restart" ,                 { 1 ,      1 ,    do_restart}},

所以接着会调到do_powerctl(),注意传下来的参数有shutdown,所以cmd是ANDROID_RB_POWEROFF,reboot_target是上面传的reason字符串。

?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 static  int  do_powerctl( const  std::vector& args) { 696       const  char * command = args[ 1 ].c_str(); 697       int  len =  0 ; 698       unsigned  int  cmd =  0 ; 699       const  char  *reboot_target =  "" ; 700       void  (*callback_on_ro_remount)( const  struct mntent*) = NULL; 701  702       if  (strncmp(command,  "shutdown" 8 ) ==  0 ) { 703           cmd = ANDROID_RB_POWEROFF; 704           len =  8 ; 705       else  if  (strncmp(command,  "reboot" 6 ) ==  0 ) { 706           cmd = ANDROID_RB_RESTART2; 707           len =  6 ; 708       } ... 763       return  android_reboot_with_callback(cmd,  0 , reboot_target, 764                                           callback_on_ro_remount); 765   }

函数和cmd值在/system/core/include/cutils/android_reboot.h 中有声明

?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 int  android_reboot_with_callback( 213       int  cmd,  int  flags __unused,  const  char  *arg, 214       void  (*cb_on_remount)( const  struct mntent*)) 215   { 216       int  ret; 217       remount_ro(cb_on_remount); 218       switch  (cmd) { 219           case  ANDROID_RB_RESTART: 220               ret = reboot(RB_AUTOBOOT); 221               break ; 222  223           case  ANDROID_RB_POWEROFF: 224               ret = reboot(RB_POWER_OFF); 225               break ; 226  227           case  ANDROID_RB_RESTART2: 228               ret = syscall(__NR_reboot, LINUX_REBOOT_MAGIC1, LINUX_REBOOT_MAGIC2, 229                              LINUX_REBOOT_CMD_RESTART2, arg); 230               break ; 231  232           default : 233               ret = - 1 ; 234       } 235  236       return  ret; 237   }

所以最后又调用到了reboot()函数,传入的参数是RB_POWER_OFF。

reboot()定义在/bionic/libc/bionic/reboot.cpp

?
1 2 3 4 5 6 7 8 #include 30   #include "" > 31  32   extern  "C"  int  __reboot( int int int void *); 33  34   int  reboot( int  mode) { 35     return  __reboot(LINUX_REBOOT_MAGIC1, LINUX_REBOOT_MAGIC2, mode, NULL); 36   }

又调用到了__reboot(),在__reboot.s中用汇编实现,不同的cpu架构在不同目录下,比如32为arm平台。

bionic/libc/arch-arm/syscalls/__reboot.S ?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 3   #include < private  bionic_asm.h= "" > 4  5   ENTRY(__reboot) 6       mov     ip, r7 7       .cfi_register r7, ip 8       ldr     r7, =__NR_reboot 9       swi     # 0 10       mov     r7, ip 11       .cfi_restore r7 12       cmn     r0, #(MAX_ERRNO +  1 ) 13       bxls    lr 14       neg     r0, r0 15       b       __set_errno_internal 16   END(__reboot) private >

这里又将__reboot的实现映射到了__NR_reboot。

bionic/libc/kernel/uapi/asm-generic/unistd.h ?
1 2 3 4 5 /* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */ 219   #define __NR_rt_sigreturn  139 220   #define __NR_setpriority  140 221   #define __NR_getpriority  141 222   #define __NR_reboot  142

__NR_reboot对应的系统调用声明在Unistd.h中

linux-4.10/include/uapi/asm-generic/unistd.h ?
1 2 3 4 5 6 7 8 9 10 #define __NR_rt_sigreturn  139 419   __SC_COMP(__NR_rt_sigreturn, sys_rt_sigreturn, compat_sys_rt_sigreturn) 420  421   /* kernel/sys.c */ 422   #define __NR_setpriority  140 423   __SYSCALL(__NR_setpriority, sys_setpriority) 424   #define __NR_getpriority  141 425   __SYSCALL(__NR_getpriority, sys_getpriority) 426   #define __NR_reboot  142 427   __SYSCALL(__NR_reboot, sys_reboot)

对应的函数是sys_reboot(),声明在linux-4.10\include\linux\syscalls.h


?
1 2 3 4 5 6 7                      struct timespec __user *interval); 311   asmlinkage  long  sys_setpriority( int  which,  int  who,  int  niceval); 312   asmlinkage  long  sys_getpriority( int  which,  int  who); 313  314   asmlinkage  long  sys_shutdown( int int ); 315   asmlinkage  long  sys_reboot( int  magic1,  int  magic2, unsigned  int  cmd, 316                  void  __user *arg);

sys_reboot()的定义在linux-4.10.3\kernel\reboot.c。


/*

    add by puo补充一点,这里sys_reboot的实现其实就是 SYSCALL_DEFINE4(reboot, int, magic1, int, magic2, unsigned int, cmd,        void __user *, arg); 自己看SYSCALL_DEFINE4的宏定义实现就知道了。

*/


1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 280   SYSCALL_DEFINE4(reboot,  int , magic1,  int , magic2, unsigned  int , cmd, 281          void  __user *, arg) 282   { 283   ... 314      mutex_lock(&reboot_mutex); 315      switch  (cmd) { 316      case  LINUX_REBOOT_CMD_RESTART: 317          kernel_restart(NULL); 318          break ; 319  320      case  LINUX_REBOOT_CMD_CAD_ON: 321          C_A_D =  1 ; 322          break ; 323  324      case  LINUX_REBOOT_CMD_CAD_OFF: 325          C_A_D =  0 ; 326          break ; 327  328      case  LINUX_REBOOT_CMD_HALT: 329          kernel_halt(); 330          do_exit( 0 ); 331          panic( "cannot halt" ); 332  333      case  LINUX_REBOOT_CMD_POWER_OFF: 334          kernel_power_off(); 335          do_exit( 0 ); 336          break ;           ... 361      default : 362          ret = -EINVAL; 363          break ; 364      } 365      mutex_unlock(&reboot_mutex); 366      return  ret; 367   }
mode从上面传下来的值是RB_POWER_OFF。
bionic/libc/include/sys/reboot.h ?
1 2 3 4 5 6 7 /* use glibc names as well */ 37  38   #define RB_AUTOBOOT     LINUX_REBOOT_CMD_RESTART 39   #define RB_HALT_SYSTEM  LINUX_REBOOT_CMD_HALT 40   #define RB_ENABLE_CAD   LINUX_REBOOT_CMD_CAD_ON 41   #define RB_DISABLE_CAD  LINUX_REBOOT_CMD_CAD_OFF 42   #define RB_POWER_OFF    LINUX_REBOOT_CMD_POWER_OFF
所以接下来走到kernel_power_off(); ?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 /** 253   * kernel_power_off - power_off the system 254   * 255   * Shutdown everything and perform a clean system power_off. 256   */ 257   void  kernel_power_off( void ) 258   { 259      kernel_shutdown_prepare(SYSTEM_POWER_OFF); 260      if  (pm_power_off_prepare) 261          pm_power_off_prepare(); 262      migrate_to_reboot_cpu(); 263      syscore_shutdown(); 264      pr_emerg( "Power down\n" ); 265      kmsg_dump(KMSG_DUMP_POWEROFF); 266      machine_power_off(); 267   } 268   EXPORT_SYMBOL_GPL(kernel_power_off);


kernel/kernel/exit.c

         do_exit

            exit_notify(tsk, group_dead);

                forget_original_parent(tsk, &dead);

                    reaper = find_child_reaper(father);

                        panic("Attempted to kill init! exitcode=0x%08x\n",father->signal->group_exit_code ?: father->exit_code);

更多相关文章

  1. Android使用UncaughtExceptionHandler捕获全局异常
  2. android自定义Dialog实现底部弹窗
  3. [置顶] 电源管理之android内核suspend to disk的实现(六)--STD执行
  4. Android(安卓)Fragment详解(二):Fragment创建及其生命周期
  5. Android中statfs使用注意事项
  6. Android(安卓)中使用自定义字体的方法
  7. Android(安卓)Sensor HAL层分析
  8. Android(安卓)自定义手写签名并保存到sdcard中(可以保存背景图)
  9. android 自定义 view 实现表盘效果

随机推荐

  1. 开源公司IronTec将推动PHP进驻Android平
  2. Android/iOS内嵌Unity开发示例
  3. Kotlin在AndroidStudio中的环境搭建以及
  4. 【Android自助餐】Handler消息机制完全解
  5. Android数据库高手秘籍(零)——前言[转载
  6. android 系统服务
  7. adb设备连接以及文件拷贝
  8. Android与HTML JavaScript交互
  9. Android 游戏开发的一些基础和经验
  10. android sqlite 介绍