The whole process analysis of the Android system shutdown _android

Source: Internet
Author: User
Tags safe mode strcmp

In the PowerManager API documentation, a shutdown/reboot interface is given:
public void reboot (String reason)

The description of this interface is simple, just a few words.
The function of the interface is to reboot the device, and there is no return value even if the reboot succeeds.
Need to include REBOOT permissions, i.e. Android.permission.REBOOT
The unique parameter reason represents the specific restart mode that is required, such as recovery, and of course it can be null.

First, the upper space
1.frameworks/base/core/java/android/os/powermanager.java

/** 
 * Reboot the device. Won't return if the reboot is 
 * successful. Requires the {@link Android. Manifest.permission#reboot} 
 * permission. 
 * 
 * @param reason code to the kernel (e.g., "recovery")        to * request special boot modes, or null. 
 */public 
void reboot (String reason) 
{   
  try { 
    mservice.reboot (reason); 
  } catch ( RemoteException e) { 
  }   
}  

Mservice serves the Ipowermanager binder interface.

/** 
 * {@hide} 
 * 
/Public PowerManager (Ipowermanager service, Handler Handler) 
{ 
  Mservice = Service ; 
  Mhandler = handler; 
} 

2.frameworks/base/core/java/android/os/ipowermanager.aidl

Interface Ipowermanager 
{ 
... 
void reboot (String reason); 
... 
} 

3.frameworks/base/services/java/com/android/server/powermanagerservice.java

/** * Reboot The device immediately, passing ' reason ' (May is null) * to the Underl Ying __reboot system call. 
 Should not return. */public void reboot (String reason) {mcontext.enforcecallingorselfpermission (Android). 
 
  Manifest.permission.REBOOT, NULL); if (Mhandler = NULL | |!) 
  Activitymanagernative.issystemready ()) {throw new IllegalStateException ("Too Early to call reboot ()"); 
  Final String Finalreason = reason; Runnable Runnable = new Runnable () {public void run () {synchronized (this) {Shutdownthread.reboot ( 
      Getuicontext (), Finalreason, false);   
  }   
 
    }   
  }; 
  Shutdownthread must run on a looper capable of displaying the UI. 
 
  Mhandler.post (runnable); 
  Powermanager.reboot () is a documented not to return so just wait for the inevitable. 
      Synchronized (runnable) {while (true) {try {runnable.wait ();  
catch (Interruptedexception e) {      }   
    }   
  }   
} 

4.frameworks/base/services/java/com/android/server/pm/shutdownthread.java

/** 
 * Request A clean shutdown, waiting for subsystems to clean up their 
 * state etc. Must be called to looper thread in which it UI 
 * is shown. 
 * 
 * @param context used to display the shutdown progress dialog. 
 * @param reason code to the kernel (e.g. "recovery"), or null. 
 * @param confirm True if user confirmation is needed before shutting down. 
 * 
/public static void reboot (final context, String reason, Boolean confirm) { 
  mreboot = true; 
  Mrebootsafemode = false; 
  Mrebootreason = reason; 
  Shutdowninner (context, confirm); 
} 

This indicates that a reboot is required and is not safe, and that the restart parameter is the confirm parameter for the passed down Reason,shutdowninner is used to set whether there is a confirmation prompt box, and the reboot is not available through the reboot interface, False.
The implementation of the reboot is in run () because the shutdownthread is an extension of thread, so run runs automatically.

/** * makes sure we handle the shutdown gracefully. 
 * Shuts off power regardless of radio and Bluetooth state if the alloted time has passed. */public void run () {broadcastreceiver br = new Broadcastreceiver () {@Override public void onreceive 
      Context, Intent Intent) {//We don ' t allow apps to cancel this, so ignore the result. 
    Actiondone (); 
 
  } 
  }; * * Write a system property in case the System_server reboots before we actual hardware restart. 
   If that happens, we'll retry at * The beginning of the Systemserver startup. * * {String reason = (mreboot? 
    "1": "0") + (Mrebootreason!= null? Mrebootreason: ""); 
  Systemproperties.set (shutdown_action_property, reason); 
   }/* If We are rebooting into Safe mode, write a system property * indicating. 
  */if (Mrebootsafemode) {Systemproperties.set (Reboot_safemode_property, "1"); } 
  ... rebootorshutdown (mreboot, Mrebootreason); }  

Reboot will be written to sys.shutdown.requested before reboot, if not, if not, if it is safe mode will be Persist.sys.safemode 1, after some shutdown before the pretreatment, shutdown Activitymanager and Mountservic E, the final call to the Rebootorshutdown for shutdown operation.

/** * Do not called this directly. 
   Use {@link the #reboot (context, String, Boolean)} * or {@link #shutdown (context, Boolean)} instead. * * @param reboot true to reboot or false to shutdown * @param reason reason for reboot/public static VO   
      ID Rebootorshutdown (boolean reboot, String reason) {if (reboot) {log.i (TAG, "rebooting, Reason:" + reason); 
      try {powermanagerservice.lowlevelreboot (reason); 
      catch (Exception e) {log.e (TAG, "Reboot failed, 'll attempt shutdown", e); else if (Shutdown_vibrate_ms > 0) {//vibrate before shutting down vibrator vibrator = new Sys 
      Temvibrator (); 
      try {vibrator.vibrate (Shutdown_vibrate_ms); The catch (Exception e) {//failure to vibrate shouldn ' t interrupt shutdown. 
        Just log it. 
      LOG.W (TAG, "Failed to vibrate during shutdown.", e); }//VibraThe Tor is asynchronous so we need the to and avoid shutting down too soon. 
      try {thread.sleep (Shutdown_vibrate_ms); catch (Interruptedexception unused) {}}//Shutdown power log.i (TAG, "performing low 
    -level shutdown ... "); 
  Powermanagerservice.lowlevelshutdown (); } 
} 

If the reboot is confirmed, the Powermanagerservice lowlevelreboot function is invoked, and the argument is passed down to the reason for later analysis. If it is not a reboot, that is, mreboot=false, it is necessary to shut down the machine, in the shutdown function can know.

/** 
 * Request A clean shutdown, waiting for subsystems to clean up their 
 * state etc. Must be called to looper thread in which it UI 
 * is shown. 
 * 
 * @param context used to display the shutdown progress dialog. 
 * @param confirm True if user confirmation is needed before shutting down. 
 * 
/public static void shutdown (final context, Boolean confirm) { 
  mreboot = false; 
  Mrebootsafemode = false; 
  Shutdowninner (context, confirm); 
} 

It needs to vibrate when it shuts down. Shutdown_vibrate_ms, the default definition is 500ms. But look at the code, anyway, the end will call the Lowlevelshutdown function, that is, shutdown. Logically, this may be a problem, but in practice, if the reboot operation succeeds, the entire system reboots, and the code behind it is certainly impossible to execute.
Turn your eyes back to Powermanagerservice
4.frameworks/base/services/java/com/android/server/powermanagerservice.java

/**  
 * Low-level function to reboot the device. 
 * 
 * @param reason code to the kernel (e.g. "recovery"), or null. 
 * @throws IOException If reboot fails for some reason (eg, lack of 
 *     permission) */public 
static void Levelreboot (String reason) throws IOException { 
  nativereboot (reason); 
}  
 
/**  
 * Low-level function turn the device off immediately, without trying * to is clean 
 . Most people should use 
 * {@link com.android.server.pm.internal.app.ShutdownThread} for a clean shutdown. 
 */public 
static void Lowlevelshutdown () { 
  nativeshutdown (); 

Very familiar typeface native, is JNI called:

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}, 
  ... 
}; 

The realization of these two good brothers is also together:

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 (Andr Oid_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); 
 

You can see whether the shutdown or restart, is called Android_reboot to achieve, but the parameters are not the same.

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; } 

In the case of reboot recovery, ARG is recovery, which is passed in to Android_rb_restart2 at the fifth step. In the Android_reboot function, you will see this definition #ifdef Recovery_pre_command, which is the command that will be executed before the reboot, if it is defined.
The following is also done some preprocessing before the shutdown restart, sync () is to write the information in the cache to disk, so as to avoid the end of the program to cause file damage, Linux system shutdown will do several times before the action, and Remount_ro () by calling the emergency _remount () forces the file system to be mounted as read-only, no more writes are allowed, and checks the/proc/mounts device state to verify that all current writes are complete and that the check process is blocking.
Next is the parsing of the parameters:
1 Normal restart android_rb_restart, reason = Rb_autoboot,
2) shutdown Android_rb_poweroff, no reason, Direct call to reboot for shutdown,
3) Special restart Android_rb_restart2 with parameters, reason will be default value-1
Here's another #ifdef RECOVERY_PRE_COMMAND_CLEAR_ REASON, if you define it, whatever the upper-level parameters are, it's just a normal reboot. The way to define it is to add Target_recovery_pre_command_clear_reason in the boardconfig.mk: = True, there should be a manufacturer would like to do so, after all, in addition to ordinary restart, may bring the user a certain risk.
The end of the reason will be a test, then through the analysis above, in fact, only with the special reboot with parameters will be-1, and not equal to 1 of the case has a normal restart and shutdown, and shutdown has its own solution ... So, not equal to-1 of the situation here and only the ordinary reboot. In the end, this is where the common reboot and special reboot are distinguished. Here is another question, what are the values of the other several cmd? The answer is in bionic/libc/include/sys/reboot.h:

#define RB_AUTOBOOT   linux_reboot_cmd_restart 
#define Rb_halt_system linux_reboot_cmd_halt 
#define Rb_ Enable_cad  linux_reboot_cmd_cad_on 
#define RB_DISABLE_CAD linux_reboot_cmd_cad_off 
#define Rb_power_ Off  Linux_reboot_cmd_power_off 

And, Linux_reboot_xxxx and the like in the Bionic/libc/kernel/common/linux/reboot.h:

#define LINUX_REBOOT_MAGIC1 0xfee1dead 
#define LINUX_REBOOT_MAGIC2 672274793/ 
* Warning:do not EDIT, auto-generated Code-see Top For instructions */ 
#define LINUX_REBOOT_MAGIC2A 85072278 
#define Linux_reboot_ MAGIC2B 369367448 
#define LINUX_REBOOT_MAGIC2C 537993216 
#define LINUX_REBOOT_CMD_RESTART 0x01234567/ 
* Warning:do not EDIT, auto-generated code-see top for instructions */ 
#define LINUX_REBOOT_CMD_HALT 0xcdef0123 
# Define LINUX_REBOOT_CMD_CAD_ON 0x89abcdef 
#define Linux_reboot_cmd_cad_off 0x00000000 
#define Linux_ Reboot_cmd_power_off 0x4321fedc/ 
* Warning:do not EDIT, auto-generated code-see top for instructions */ 
#defi NE linux_reboot_cmd_restart2 0xa1b2c3d4 
#define Linux_reboot_cmd_sw_suspend 0xd000fce2 
#define Linux_ Reboot_cmd_kexec 0x45584543 

As for why they are such a strange value of this problem, I can only say that they are magic number, magic, it is normal people can not understand, so ~ ~ Let them go, as long as they do not have to know that 1 of the OK.
First look at the reboot function, according to the usual experience, reboot will eventually call to __reboot.

7.bionic/libc/unistd/reboot.c

int reboot (int mode)  
{return 
  __reboot (Linux_reboot_magic1, Linux_reboot_magic2, mode, NULL); 
} 

Bingo! Sure enough, so to say reboot (reason)-> reboot (rb_autoboot)-> __reboot (Linux_reboot_magic1, Linux_reboot_magic2, linux_ Reboot_cmd_restart, NULL), if it is so good to write directly so as to avoid around this layer.

Second, kernel domain
8.__reboot came to the core through Syscall.
Here in some space to briefly introduce Syscall, later encountered similar things to better track some.
The seventh step in the implementation of the __reboot in the ARM architecture is this (bionic/libc/arch-arm/syscalls/__reboot. S

ENTRY (__reboot) 
  . Save  {r4, R7}  
  stmfd  sp!, {r4, R7} 
  ldr   R7,   =__nr_reboot SWI # 0  
  ldmfd  sp!, {r4, R7} 
  movs  r0, r0 
  bxpl  lr  
  b    __set_syscall_errno End 
( __reboot) 

As you can see, the implementation of __reboot is mapped to __nr_reboot, and Bionic/libc/sys/linux-syscalls.h can find:

#define __nr_reboot            (__nr_syscall_base + 88) 

It is specified a fixed offset, at the time of the call is through this offset to the kernel to find the corresponding entry, this shows that the kernel must have the same definition, otherwise it will not be able to successfully invoke. The definition of syscall offsets in the kernel is arch/arm/include/asm/unistd.h in the kernel source code, and the relevant information is exactly the same.
have found the corresponding mapping in the kernel, then the next step is to find the real implementation function, in the include/asm-generic/unistd.h can find the kernel of the __nr_reboot syscall function mapping, namely

/* KERNEL/SYS.C 
/* #define __NR_SETPRIORITY 140 
__syscall (__nr_setpriority, sys_setpriority) 
#define __ Nr_getpriority 
__syscall (__nr_getpriority, sys_getpriority) 
#define __nr_reboot-__syscall 
(__NR _reboot, Sys_reboot) 

At the same time, to find such a warm scene, the kernel has shown us where to go next to find Sys_reboot, that is, kernel/sys.c.

9.kernel/sys.c
Before entering this file, let's look at the definition of sys_reboot in Include/linux/syscalls.h:

Asmlinkage long sys_reboot (int magic1, int magic2, unsigned int cmd, 
        void __user *arg); 

Consistent with the invocation parameters of the __reboot.
After entering the sys.c file, the function named Sys_reboot was not found, and by looking carefully, a very interesting function was found, defined as Syscall_define4 (reboot, int, magic1, int, magic2, unsigned int, cmd, void __user *, arg), compared to __reboot parameters, can be met. Is this function really?
Also in the Include/linux/syscalls.h file, you can find such a few definitions:

#define SYSCALL_DEFINE1 (name, ...) Syscall_definex (1, _# #name, __va_args__) 
#define SYSCALL_DEFINE2 (name, ...) Syscall_definex (2, _# #name, __va_args__) 
#define SYSCALL_DEFINE3 (name, ...) Syscall_definex (3, _# #name, __va_args__) 
#define SYSCALL_DEFINE4 (name, ...) Syscall_definex (4, _# #name, __va_args__) 
#define SYSCALL_DEFINE5 (name, ...) Syscall_definex (5, _# #name, __va_args__) 
#define SYSCALL_DEFINE6 (name, ...) Syscall_definex (6, _# #name, __va_args__) ... 
 
#define SYSCALL_DEFINEX (x, Sname, ...)       \ 
  __syscall_definex (x, sname, __va_args__) ... 
 
#define __SYSCALL_DEFINEX (x, Name, ...)         \ 
  asmlinkage Long sys# #name (__sc_decl# #x (__va_args__)) 

Integration is equivalent to:

#define SYSCALL_DEFINE4 (name, ...) \ 
  asmlinkage long sys# #_name (__sc_decl# #4 (__va_args__)) 

It's not hard to see that syscall_define4 (reboot, int, magic1, int, magic2, unsigned int, cmd, void __user *, arg) is sys_reboot, the upper-level call __re The final implementation of the boot. The function implementation is as follows:

* * Reboot System call:for Obvious reasons only root could call it, * and even root needs to set up some magic number 
 s in the "registers * so" some mistake won ' t make this reboot the whole machine. 
 * You can also set the meaning of the ctrl-alt-del-key here. 
 * * Reboot doesn ' t sync:do that yourself before calling this. 
  * * SYSCALL_DEFINE4 (reboot, int, magic1, int, magic2, unsigned int, cmd, void __user *, arg) {char buffer[256]; 
 
  int ret = 0; /* We only trust the Superuser with rebooting the system. 
 
  */if (!capable (cap_sys_boot)) return-eperm; /* For safety, we require "magic" arguments. 
    */if (magic1!= Linux_reboot_magic1 | | (Magic2!= linux_reboot_magic2 && magic2!= linux_reboot_magic2a && magic2!= Linux_rebo 
 
  OT_MAGIC2B && magic2!= linux_reboot_magic2c)) Return-einval; /* Instead of trying to make the Power_off code look like * halt when pm_power_off are not Set do it is easy way. 
 
  */if ((cmd = = linux_reboot_cmd_power_off) &&!pm_power_off) cmd = Linux_reboot_cmd_halt; 
  Mutex_lock (&reboot_mutex); 
    Switch (CMD) {case Linux_reboot_cmd_restart:kernel_restart (NULL); 
 
  Break 
    Case linux_reboot_cmd_cad_on:c_a_d = 1; 
 
  Break 
    Case linux_reboot_cmd_cad_off:c_a_d = 0; 
 
  Break 
    Case Linux_reboot_cmd_halt:kernel_halt (); 
    Do_exit (0); 
 
  Panic ("Cannot halt"); 
    Case Linux_reboot_cmd_power_off:kernel_power_off (); 
    Do_exit (0); 
 
  Break  Case Linux_reboot_cmd_restart2:if (Strncpy_from_user (&buffer[0], ARG, sizeof (buffer)-1) < 0) {ret = 
      -efault; 
    Break 
 
    buffer[sizeof (buffer)-1] = '; 
    Kernel_restart (buffer); 
 
Break 
    #ifdef config_kexec Case linux_reboot_cmd_kexec:ret = kernel_kexec (); 
Break #endif #ifdef config_hibernation Case linux_reboot_cmd_sw_suspend:ret = HiBernate (); 
Break 
    #endif default:ret =-einval; 
  Break 
  } mutex_unlock (&reboot_mutex); 
return ret; 

 }

In this function, permission issues are detected first, and only Superuser can perform the reboot of the system:

/* We only trust the Superuser with rebooting the system. * 
/if (!capable (cap_sys_boot)) 
  return-eperm; 

Otherwise the permission error will be returned. The corresponding list of permissions in Include/linux/capability.h, the restart operation is 22.
The magic number is then validated:

/* For safety, we require "magic" arguments. * 
/if (magic1!= Linux_reboot_magic1 | | 
  (Magic2!= linux_reboot_magic2 && 
        magic2!= linux_reboot_magic2a && 
    magic2!= linux_reboot_ MAGIC2B && 
        magic2!= linux_reboot_magic2c)) 
  Return-einval; 

If there is no error in the data transfer process, there is certainly no problem here, so just a security check, the basic will not happen error.
Then there is a very interesting check, if the user requests to shutdown, and Pm_power_off is empty, the user's shutdown command to the switch to suspend:

/* Instead of trying to make the Power_off code look like * halt when Pm_power_off was not set does it the easy 
 way. 
 * 
/if ((cmd = = linux_reboot_cmd_power_off) &&!pm_power_off) 
  cmd = Linux_reboot_cmd_halt; 

You can find its definition in ARCH/ARM/KERNEL/PROCESS.C:

 
 /* Function pointers to optional machine specific functions 
 / 
Void (*pm_power_off) (void); 
Export_symbol (Pm_power_off); 

OK, just a function pointer, and do a global operation, the entire kernel can call it. In the case of High-pass msm7x30, this function pointer is assigned in ARCH/ARM/MACH-MSM/PM2.C:

Pm_power_off = Msm_pm_power_off; 

The concrete realization of Msm_pm_power_off no longer follow, each family is different, follow down not much meaning. Now as long as you know, I analyzed this kernel is assigned to this function pointer, so it is not NULL, the shutdown command will normally execute.
The next step is to get to the point of the function, parse the user command, and the process is protected with a Reboot_mutex mutex to ensure that only one parsing process is possible at the same time to avoid conflict.
The following is a definition of the command associated with the machine reboot:

 * * Commands accepted by the _reboot () system call. 
 * * Restart restart system using default command and mode. 
 * HALT Stop OS and give system control-ROM monitor, if any. 
 * CAD_ON ctrl-alt-del sequence causes restart command. 
 * Cad_off Ctrl-alt-del sequence sends SIGINT to init task. 
 * Power_off Stop OS and remove all power from system, if possible. 
 * RESTART2 restart system using given command string. 
 * Sw_suspend SUSPEND system using software SUSPEND if compiled in. * Kexec Restart system using a previously loaded Linux kernel/#define Linux_reboot_cmd_restart 0x012345 #define LINUX_REBOOT_CMD_HALT 0xcdef0123 #define LINUX_REBOOT_CMD_CAD_ON 0x89abcdef #define Linux_reboot_cmd_ca D_off 0x00000000 #define Linux_reboot_cmd_power_off 0x4321fedc #define LINUX_REBOOT_CMD_RESTART2 0xa1b2c3d4 #define Linux_reboot_cmd_sw_suspend 0xd000fce2 #define LINUX_REBOOT_CMD_KEXEC 0x45584543 

Note the description in detail, the more unfamiliar is about CAD, in fact, is used to want to use Ctrl+alt+del operation; then Sw_syspend is the software hibernate; Kexec is too high-end, a patch of the kernel, used to restart the old kernel, details: http:// Www.ibm.com/developerworks/cn/linux/l-kexec/?ca=dwcn-newsletter-linux
These are only the first six commands used by the Android system, why so, can go to see bionic/libc/include/sys/reboot.h, the top has been posted. Linux_reboot_cmd_halt Although there is a definition, but also did not find the Android system where there is a call, a master found, I hope to be able to inform. In the end, there are only three that can be used:

    • Restart
    • Power_off
    • RESTART2

10. Final realization
Restart call is Kernel_restart, the difference is that the parameter is not empty, the shutdown is called Kernel_power_off (), first look at the shutdown:

/** 
 * Kernel_power_off-power_off the system 
 * * 
 Shutdown Everything and perform a clean system power_off.
   */ 
void Kernel_power_off (void) 
{ 
  kernel_shutdown_prepare (system_power_off); 
  if (pm_power_off_prepare) 
    pm_power_off_prepare (); 
  Disable_nonboot_cpus (); 
  Syscore_shutdown (); 
  PRINTK (Kern_emerg "Power down.\n"); 
  Kmsg_dump (Kmsg_dump_poweroff); 
  Machine_power_off (); 
} 
EXPORT_SYMBOL_GPL (Kernel_power_off); 

The most a series of preparatory work, the final call to Machine_power_off ():

void Machine_power_off (void) 
{   
  machine_shutdown (); 
  if (Pm_power_off) 
    Pm_power_off (); 
} 

The previous search for Pm_power_off is useful here, and is the last step in shutting down the machine. Shutdown complete, and then look at the restart operation:

/** 
 * Kernel_restart-reboot the system 
 * @cmd: Pointer to buffer containing command to execute for restart 
 *   or%null 
 * * 
 Shutdown Everything and perform a clean reboot. 
 * This isn't safe to call in the interrupt context. 
 */ 
void Kernel_restart (char *cmd) 
{ 
  kernel_restart_prepare (cmd); 
  if (!cmd) 
    PRINTK (Kern_emerg "restarting system.\n"); 
  else 
    PRINTK (Kern_emerg "Restarting system with Command '%s '. \ n", cmd); 
  Kmsg_dump (Kmsg_dump_restart); 
  Machine_restart (cmd); 
EXPORT_SYMBOL_GPL (Kernel_restart); 

The same routine, is also going to do some preparation work, then call Machine_restart (CMD), if it is ordinary restart, then the middle of a CMD is null, if it is a special restart, then this cmd is a layer by layer pass to the ARG.

void Machine_restart (char *cmd) 
{ 
  machine_shutdown (); 
  Arm_pm_restart (Reboot_mode, cmd); 
... 
void (*arm_pm_restart) (char str, const char *cmd) = Arm_machine_restart; 
EXPORT_SYMBOL_GPL (Arm_pm_restart); 

And remember the pm2.c just now? There is also a pointer assignment to the Arm_pm_restart:

Arm_pm_restart = Msm_pm_restart; 

The function of the assignment is Msm_pm_init, which is called

Late_initcall_sync (Msm_pm_init); 

The Late_initcall_sync start priority is the lowest, at 7. Module_init is actually a 6 priority, and the larger the number, the lower the priority. So, the final arm_pm_restart of this function pointer will point to Msm_pm_restart. On the specific implementation of the Msm_pm_restart also do not look at, the front side said the same, are different from home, on a few lines of code:

static void Msm_pm_restart (char str, const char *cmd) 
{     
  msm_rpcrouter_close (); 
  Msm_proc_comm (pcom_reset_chip, &restart_reason, 0); 
 
  for (;;) 
    ; 
}  

But careful friends may find that there is a restart_reason, this is not passed down the parameters. In fact, this value has already been set up before Kernel_restart_prepare (CMD).

void Kernel_restart_prepare (char *cmd) 
{   
  blocking_notifier_call_chain (&reboot_notifier_list, SYS_ restart, cmd); 
  System_state = System_restart; 
  Usermodehelper_disable (); 
  Device_shutdown (); 
  Syscore_shutdown (); 
} 

Is the blocking_notifier mechanism, this operation in the previous shutdown shutdown operation also has, and is the same list, are reboot_notifier_list. It is also easy to understand, is to register on the Reboot_notifier_list function passed into the relevant parameters after the implementation, as an understanding, look at the specific how to use: (ARCH/ARM/MACH-MSM/PM2.C)

 static int Msm_reboot_call (struct notifier_block *this, unsigned long code, void *_cm 
    D) {if ((code = = Sys_restart) && _cmd) {char *cmd = _cmd; 
    if (!strcmp (cmd, "bootloader")) {Restart_reason = 0x77665500; 
    else if (!strcmp (cmd, "recovery")) {Restart_reason = 0x77665502; 
    else if (!strcmp (cmd, "Eraseflash")) {Restart_reason = 0x776655ef; 
      else if (!strncmp (cmd, "oem-", 4)) {Unsigned code = Simple_strtoul (cmd + 4, 0,) & 0xFF; Restart_reason = 0x6f656d00 | 
    Code  
    else {Restart_reason = 0x77665501; 
} return Notify_done; 
 
static struct Notifier_block Msm_reboot_notifier = {. Notifier_call = Msm_reboot_call,}; 
... static int __init msm_pm_init (void) {... register_reboot_notifier (&msm_reboot_notifier); 

... 
} 

OK, all right, in the Kernel_restart_prepare time Msm_reboot_call will be called first, the function is to assign a value according to the user command to Restart_reason, and then call Msm_pm_ Use when restart. Here we find that the parameters that can be taken in reboot are not only Recovery,bootloader, but also Eraseflash and OEM-???, which are literally used to erase ROM and lock.

Third, how to use the shutdown?
the analysis of this article is based on the Android reboot interface, but analysis to analyze, look back to find that the Android interface reboot really can only reboot, can not be shutdown operation, you will be able to track the process in the course of the discovery, It is true that there is an associated interface with a shutdown. So what's the use of shutting down the machine?
Frameworks/base/services/java/com/android/serverbatteryservice.java

Private final void Shutdownifnopower () { 
//Shut down gracefully if we battery are critically low and we are not power Ed. 
Wait until the system has booted before attempting to display the shutdown dialog. 
if (Mbatterylevel = = 0 &&!ispowered () && Activitymanagernative.issystemready ()) { 
  Intent Intent = NE W Intent (Intent.action_request_shutdown); 
  Intent.putextra (intent.extra_key_confirm, false); 
  Intent.setflags (intent.flag_activity_new_task); 
  Mcontext.startactivity (intent); 
} 

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.