android 7.0 关机流程详细分析

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);又跑到了哪里?

android 7.0 关机流程详细分析_第1张图片

首先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);

你可能感兴趣的:(kernel)