Android系统关机的全流程解析

2019-12-10 19:02:04刘景俊

private static native void nativeShutdown(); 
private static native void nativeReboot(String reason) throws IOException; 

5.frameworks/base/services/jni/com_android_server_PowerManagerService.cpp

static JNINativeMethod gPowerManagerServiceMethods[] = {  
  /* name, signature, funcPtr */ 
  ... 
  { "nativeShutdown", "()V", 
      (void*) nativeShutdown }, 
  { "nativeReboot", "(Ljava/lang/String;)V", 
      (void*) nativeReboot }, 
  ... 
}; 

这两个好哥俩的实现也是在一起的:

static void nativeShutdown(JNIEnv *env, jobject clazz) { 
  android_reboot(ANDROID_RB_POWEROFF, 0, 0); 
} 
 
static void nativeReboot(JNIEnv *env, jobject clazz, jstring reason) { 
  if (reason == NULL) { 
    android_reboot(ANDROID_RB_RESTART, 0, 0); 
  } else { 
    const char *chars = env->GetStringUTFChars(reason, NULL); 
    android_reboot(ANDROID_RB_RESTART2, 0, (char *) chars); 
    env->ReleaseStringUTFChars(reason, chars); // In case it fails. 
  } 
  jniThrowIOException(env, errno); 
} 

可以看到无论是关机还是重启,都是调用android_reboot来实现的,只是参数不一样而已。

6.system/core/libcutils/android_reboot.c

int android_reboot(int cmd, int flags, char *arg) 
{ 
  int ret = 0; 
  int reason = -1; 
 
#ifdef RECOVERY_PRE_COMMAND 
  if (cmd == (int) ANDROID_RB_RESTART2) { 
    if (arg && strlen(arg) > 0) { 
      char cmd[PATH_MAX]; 
      sprintf(cmd, RECOVERY_PRE_COMMAND " %s", arg); 
      system(cmd); 
    } 
  } 
#endif 
 
  if (!(flags & ANDROID_RB_FLAG_NO_SYNC)) 
    sync(); 
 
  if (!(flags & ANDROID_RB_FLAG_NO_REMOUNT_RO)) 
    remount_ro(); 
 
  switch (cmd) { 
    case ANDROID_RB_RESTART: 
      reason = RB_AUTOBOOT; 
      break; 
 
    case ANDROID_RB_POWEROFF: 
      ret = reboot(RB_POWER_OFF); 
      return ret; 
 
    case ANDROID_RB_RESTART2: 
      // REBOOT_MAGIC 
      break; 
 
    default: 
      return -1; 
  } 
 
#ifdef RECOVERY_PRE_COMMAND_CLEAR_REASON 
  reason = RB_AUTOBOOT; 
#endif 
 
  if (reason != -1) 
    ret = reboot(reason); 
  else 
    ret = __reboot(LINUX_REBOOT_MAGIC1, LINUX_REBOOT_MAGIC2, 
              LINUX_REBOOT_CMD_RESTART2, arg); 
 
  return ret; 
}