1. 上层应用的设置->隐私权->恢复出厂设置对应的java代码在如下路径文件:
packages/apps/Settings/src/com/android/settings/MasterClear.java
MasterClear:mFinalClickListener()函数会发送一个广播出去:
sendBroadcast(new Intent("android.intent.action.MASTER_CLEAR"));

2. 这个广播的接收者在收到广播之后会开启一个java服务线程:MasterClearReceiver:RebootThread
frameworks/base/services/java/com/android/server/MasterClearReceiver.java -- TAG = "MasterClear"
public void onReceive(Context context, Intent intent) {

        RebootThread mThread = new RebootThread(context, intent);        mThread.start();    }


在线程的run函数中会调用函数:RecoverySystem.rebootWipeUserData(mContext);这个方法是RecoverySystem类的静态方法。

3. RecoverySystem类定义于文件:frameworks/base/core/java/android/os/RecoverySystem.java -- TAG = "RecoverySystem"

public class RecoverySystem {  /** Used to communicate with recovery.  See bootable/recovery/recovery.c. */      private static File RECOVERY_DIR = new File("/cache/recovery");     private static File COMMAND_FILE = new File(RECOVERY_DIR, "command");     private static File LOG_FILE = new File(RECOVERY_DIR, "log");    public static void rebootWipeUserData(Context context)         throws IOException {         bootCommand(context, "--wipe_data");     }          private static void bootCommand(Context context, String arg) throws IOException {         RECOVERY_DIR.mkdirs();  // In case we need it         COMMAND_FILE.delete();  // In case it's not writable         LOG_FILE.delete();          FileWriter command = new FileWriter(COMMAND_FILE);         try {             command.write(arg);  // 往文件/cache/recovery/command中写入recovery ELF的执行参数。             command.write("\n");         } finally {             command.close();         }          // Having written the command file, go ahead and reboot         PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE);         pm.reboot("recovery");  // 调用PowerManager类中的reboot方法          throw new IOException("Reboot failed (no permissions?)");     } }



4. PowerManager类定义于文件:frameworks/base/core/java/android/os/PowerManager.java -- TAG = "PowerManager"
 public class PowerManager {  ...  public void reboot(String reason)     {         try {             mService.reboot(reason);         } catch (RemoteException e) {         }     }     public PowerManager(IPowerManager service, Handler handler)     {         mService = service;         mHandler = handler;     }    IPowerManager mService;     Handler mHandler; }


5. mService指向的是PowerManagerService类,这个类定义于文件:

 frameworks/base/services/java/com/android/server/PowerManagerService.java  --  TAG = "PowerManagerService" /**     * Reboot the device immediately, passing 'reason' (may be null)     * to the underlying __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(mContext, finalReason, false);                } // 调用ShutdownThread服务中的reboot方法                           }        };        // ShutdownThread must run on a looper capable of displaying the UI.        mHandler.post(runnable);        // PowerManager.reboot() is documented not to return so just wait for the inevitable.        synchronized (runnable) {            while (true) {                try {                    runnable.wait();                } catch (InterruptedException e) {                }            }        }    }

 frameworks/base/services/java/com/android/server/PowerManagerService.java  --  TAG = "PowerManagerService" /**     * Reboot the device immediately, passing 'reason' (may be null)     * to the underlying __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(mContext, finalReason, false);                } // 调用ShutdownThread服务中的reboot方法                           }        };        // ShutdownThread must run on a looper capable of displaying the UI.        mHandler.post(runnable);        // PowerManager.reboot() is documented not to return so just wait for the inevitable.        synchronized (runnable) {            while (true) {                try {                    runnable.wait();                } catch (InterruptedException e) {                }            }        }    }


6. ShutdownThread类在下列文件中实现:
 frameworks/base/core/java/com/android/internal/app/ShutdownThread.java   -- TAG = "ShutdownThread" public final class ShutdownThread extends Thread {  ...  public static void reboot(final Context context, String reason, boolean confirm) {         mReboot = true;         mRebootReason = reason;         shutdown(context, confirm);     }         ...     public void run() {      ...      if (mReboot) {             Log.i(TAG, "Rebooting, reason: " + mRebootReason);             try {                 Power.reboot(mRebootReason);             } catch (Exception e) {                 Log.e(TAG, "Reboot failed, will attempt shutdown instead", e);             }         } else if (SHUTDOWN_VIBRATE_MS > 0) {             ...         }         ...     } }


流程:reboot() --> shutdown() --> beginShutdownSequence() --> sInstance.start() --> run() --> Power.reboot(mRebootReason).
最后调用Power类的reboot方法。

7. Power类定义于文件:frameworks/base/core/java/android/os/Power.java ---

 public class Power {  ...  public static void reboot(String reason) throws IOException     {         rebootNative(reason);     }     private static native void rebootNative(String reason) throws IOException ; }


 frameworks/base/core/java/android/os/Power.java    --- public class Power {  ...  public static void reboot(String reason) throws IOException     {         rebootNative(reason);     }     private static native void rebootNative(String reason) throws IOException ; }

调用本地JNI接口rebootNative().

8.Power类对应的JNI接口函数定义于文件:

 frameworks/base/core/jni/android_os_Power.cpp static void android_os_Power_reboot(JNIEnv *env, jobject clazz, jstring reason) {     sync(); #ifdef HAVE_ANDROID_OS     if (reason == NULL) {         reboot(RB_AUTOBOOT);     } else {         const char *chars = env->GetStringUTFChars(reason, NULL);         __reboot(LINUX_REBOOT_MAGIC1, LINUX_REBOOT_MAGIC2,                  LINUX_REBOOT_CMD_RESTART2, (char*) chars);         env->ReleaseStringUTFChars(reason, chars);  // In case it fails.     }     jniThrowIOException(env, errno); #endif }


上面的各种宏定义于文件:bionic/libc/kernel/common/linux/reboot.h
 #define LINUX_REBOOT_MAGIC1 0xfee1dead #define LINUX_REBOOT_MAGIC2 672274793 #define LINUX_REBOOT_MAGIC2A 85072278 #define LINUX_REBOOT_MAGIC2B 369367448 #define LINUX_REBOOT_MAGIC2C 537993216  /*  * Commands accepted by the _reboot() system call.  *  * RESTART     Restart system using default command and mode.  * HALT        Stop OS and give system control to 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 0x01234567 #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 #define LINUX_REBOOT_CMD_RESTART2 0xA1B2C3D4 #define LINUX_REBOOT_CMD_SW_SUSPEND 0xD000FCE2 #define LINUX_REBOOT_CMD_KEXEC 0x45584543  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


9. libc中__reboot的实现
bionic/libc/arch-arm/syscalls/__reboot.S

 #include <sys/linux-syscalls.h>    .text    .type __reboot, #function    .globl __reboot    .align 4    .fnstart__reboot:    .save   {r4, r7}    stmfd   sp!, {r4, r7}    ldr     r7, =__NR_reboot // 系统调用号 88, binoic/libc/include/sys/linux-syscalls.h    swi     #0         ldmfd   sp!, {r4, r7}    movs    r0, r0    bxpl    lr    b       __set_syscall_errno    .fnend

10. reboot系统调用实现
kernel/kernel/sys.c

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_REBOOT_MAGIC2B &&                  magic2 != LINUX_REBOOT_MAGIC2C))   return -EINVAL;   if ((cmd == LINUX_REBOOT_CMD_POWER_OFF) && !pm_power_off)   cmd = LINUX_REBOOT_CMD_HALT;   lock_kernel();  switch (cmd) {   ...   case LINUX_REBOOT_CMD_POWER_OFF:    kernel_power_off();    unlock_kernel();    do_exit(0);    break;     case LINUX_REBOOT_CMD_RESTART2:    if (strncpy_from_user(&buffer[0], arg, sizeof(buffer) - 1) < 0) {     unlock_kernel();     return -EFAULT;    }    buffer[sizeof(buffer) - 1] = '\0';      kernel_restart(buffer);    break;      ...     default:    ret = -EINVAL;    break;  }  unlock_kernel();  return ret; } 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);  machine_restart(cmd); } void kernel_restart_prepare(char *cmd) {  blocking_notifier_call_chain(&reboot_notifier_list, SYS_RESTART, cmd); // 调用通知链reboot_notifier_list上的函数  system_state = SYSTEM_RESTART;  device_shutdown(); // shutdown设备  sysdev_shutdown(); // 系统设备shutdoen } @kernel/arch/arm/kernel/process.c void (*arm_pm_restart)(char str, const char *cmd) = arm_machine_restart; void machine_restart(char *cmd) {  arm_pm_restart(reboot_mode, cmd); } void arm_machine_restart(char mode, const char *cmd) {  /*   * Clean and disable cache, and turn off interrupts   */  cpu_proc_fin();   /*   * Tell the mm system that we are going to reboot -   * we may need it to insert some 1:1 mappings so that   * soft boot works.   */  setup_mm_for_reboot(mode);   /*   * Now call the architecture specific reboot code.   */  arch_reset(mode, cmd);   // reset硬件系统,写reboot标记,供bootloader中判断   /*   * Whoops - the architecture was unable to reboot.   * Tell the user!   */  mdelay(1000);  printk("Reboot failed -- System halted\n");  while (1); }11. arch_reset() 文件:kernel/arch/arm/mach-mt6516/system.c void arch_reset(char mode, const char *cmd) {  printk("arch_reset: cmd = %s\n", cmd ? : "NULL");   if (cmd && !strcmp(cmd, "charger")) {   /* do nothing */  } else if (cmd && !strcmp(cmd, "recovery")) {   rtc_mark_recovery();  // 写recovery的标记到寄存器中去。  } else {   rtc_mark_swreset();  }   DRV_WriteReg32(RGU_USRST1,0xbb1f);     printk("MT6516 SW Reset\n");  DRV_WriteReg32(WDT_MODE, 0x2221);  DRV_WriteReg32(WDT_RESTART, 0x1971);  DRV_WriteReg32(WDT_SWRST, 0x1209);   /* enter loop waiting for restart */  while (1); } @ kernel/driver/ret/ret-mt6516.c /* used in arch_reset() */ void rtc_mark_recovery(void) {  u16 pdn1;   spin_lock_irq(&rtc_lock);  pdn1 = rtc_read(RTC_PDN1) & ~0x0030;  pdn1 |= 0x0010;  rtc_writeif_unlock();  rtc_write(RTC_PDN1, pdn1);  rtc_writeif_lock();  spin_unlock_irq(&rtc_lock); } /* used in arch_reset() */ void rtc_mark_swreset(void) {  u16 pdn1;   spin_lock_irq(&rtc_lock);  pdn1 = rtc_read(RTC_PDN1) & ~0x0030;  pdn1 |= 0x0020;  rtc_writeif_unlock();  rtc_write(RTC_PDN1, pdn1);  rtc_writeif_lock();  spin_unlock_irq(&rtc_lock); }


可以看出,recovery和reset都是往RTC_PDN1的bit5:bit4上分别写01和10来标识。


12.正常的log如下:
#logcat ShutdownThread:D *:S &# --------- beginning of /dev/log/system--------- beginning of /dev/log/mainD/ShutdownThread(  127): !!! Request to shutdown !!!D/ShutdownThread(  127): Notifying thread to start radio shutdownD/ShutdownThread(  127): shutdown acquire partial WakeLock 2I/ShutdownThread(  127): Sending shutdown broadcast...I/ShutdownThread(  127): Shutting down activity manager...W/ShutdownThread(  127): Turning off radio...I/ShutdownThread(  127): Waiting for Bluetooth and Radio...I/ShutdownThread(  127): Radio and Bluetooth shutdown complete.I/ShutdownThread(  127): Shutting down MountServiceW/ShutdownThread(  127): Result code 0 from MountService.shutdown[  127.981918] save exit: isCheckpointed 1[  127.985002] save exit: isCheckpointed 1I/ShutdownThread(  127): Rebooting, reason: recovery[  128.081532] [lizhiguo reboot1] LINUX_REBOOT_CMD_RESTART2.[  128.082357] GPS: mt3326_gps_shutdown: Shutting down[  128.083011] GPS: mt3326_gps_power: Switching GPS device off[  128.083741] GPS: mt3326_gps_power: null pointer!![  128.084376] GPIO Shut down[  128.089814] [MATV] shutdown[  128.090193] [H264_DEC] h264_dec_shutdown[  128.090710] JPEG Codec shutdown[  128.091248] ----MT6516 M3D shutdown----[  128.091839] m2d_shutdown() is called[  128.092320] ******** MT6516 WDT driver shutdown!! ********[  128.093040] [MM_QUEUE] mm_queue_shutdown[  128.094333] [lizhiguo reboot2] kernel_restart.[  128.094955] Restarting system with command 'recovery'.[  128.097483] [lizhiguo reboot3] arm_machine_restart.[  128.099275] arch_reset: cmd = recovery[  128.100917] MT6516 SW Resetu516 EVBgetflashID ADBC successful!!![MEM] complex R/W mem test pass



13. uboot中会先后检查三种方式进入recovery是否成立:第一种是kernel直接写一个寄存器来标记下次启动将进入recovery模式;第二种是快捷键:powerkey+downVOL;第三中就是上层应用发送下来的回复出厂设置的命令,这个命令在restart之前kernel会往MISC分区中写command(boot-recovery)。这项工作在文件:bootable/bootloader/uboot/board/mt6516/mt6516_recovery.c完成。
recovery_check_key_trigger()
recovery_check_command_trigger()

BOOL recovery_check_command_trigger(void){ struct misc_message misc_msg; struct misc_message *pmisc_msg = &misc_msg; const unsigned int size = NAND_WRITE_SIZE * MISC_PAGES; unsigned char *pdata;     int ret; pdata = (uchar*)malloc(sizeof(uchar)*size); ret = mboot_recovery_load_misc(pdata, size);     if (ret < 0)    {     return FALSE;     }  #ifdef LOG_VERBOSE    MSG("\n--- get_bootloader_message ---\n");    dump_data(pdata, size);    MSG("\n");#endif memcpy(pmisc_msg, &pdata[NAND_WRITE_SIZE * MISC_COMMAND_PAGE], sizeof(misc_msg));  MSG("Boot command: %.*s\n", sizeof(misc_msg.command), misc_msg.command); MSG("Boot status: %.*s\n", sizeof(misc_msg.status), misc_msg.status); MSG("Boot message\n\"%.20s\"\n", misc_msg.recovery); if(strcmp(misc_msg.command, "boot-recovery")==0) { g_boot_mode = RECOVERY_BOOT; } return TRUE;}// recovery模式检测BOOL recovery_detection(void){ if ((DRV_Reg16(RTC_PDN1) & 0x0030) == 0x0010) { /* factory data reset */  g_boot_mode = RECOVERY_BOOT;  return TRUE; } // 读取寄存器的值    if(recovery_check_key_trigger())    {     return TRUE;    }    // 检测是否有快捷键按下       #ifdef CFG_NAND_BOOT recovery_check_command_trigger(); #endif // 检测是否通过将忘MISC分区写命令的方式 // 以上如果都不是,那么最后一次检查模式全局量是够是RECOVERY_BOOT if (g_boot_mode == RECOVERY_BOOT) { return TRUE; } else { return FALSE; }}


14. g_boot_mode = RECOVERY_BOOT这个成立之后,uboot将会从RECOVERY分区加载recovery.img进SDRAM来运行。
其实这个recovery.img和boot.img结构类似,zImage一样,所不同的是ramdisk.img不同而已。
在运行recovery这个elf的时候会从/cache/recovery/comamnd中读取参数,这个参数是android的上层应用写进入的,--wipe-data,
之后会清除USERDATA和CACHE分区,在将recovery的log文件放在/cache/recovery/下,将原来的command文件删除,最后
调用函数reboot(RB_AUTOBOOT)来重新启动系统。
bootable/recovery/recovery.c

最后需要注意的一个问题是,recovery这个elf在编译user-release版本软件的时候没有copy到/system/bin下面去,需要修改
bootable/recovery/Android.mk文件中的如下地方:
/* BENGIN: lizhiguo 2011-07-27, copy recovery to /system/bin for user builds.*/
#LOCAL_MODULE_TAGS := eng
/* END: lizhiguo 2011-07-27 */
如果放开这行,将只会在eng版本软件中有copy到/system/bin的动作。


更多相关文章

  1. android tips:从资源文件中读取文件流显示
  2. android NDK/JNI-实例开发流程
  3. 使用 EditText来调用软键盘的搜索功能
  4. android 调用 SharedPreferences 实现偏好信息设置
  5. Android(安卓)Launcher全面剖析
  6. Android(安卓)bluetooth介绍(三): 蓝牙扫描(scan)设备分析
  7. 箭头函数的基础使用
  8. NPM 和webpack 的基础使用
  9. Python技巧匿名函数、回调函数和高阶函数

随机推荐

  1. Android(安卓)手机制式和网络类型 GSM/ED
  2. TextView通过获得dimens.xml中定义的大小
  3. android listview 删除item 刷新 notifyD
  4. android studio安装 虚拟机"VT-x is disa
  5. Android开发本地及网络Mp3音乐播放器(五)
  6. Android(安卓)thumbnail 缩略图的获取及
  7. [Android]Fragment进行show和hide时候刷
  8. Eclipse中如何关联android sdk源码
  9. Android(安卓)Color 小结
  10. 简单基站定位程序