Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1292300
  • 博文数量: 478
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 4833
  • 用 户 组: 普通用户
  • 注册时间: 2014-06-28 11:12
文章分类

全部博文(478)

文章存档

2019年(1)

2018年(27)

2017年(21)

2016年(171)

2015年(258)

我的朋友

分类: Android平台

2015-07-23 09:45:04

http://blog.csdn.net/andyhuabing/article/details/9223163
  昨天开会讨论IP网络升级时,需要一个后台服务做升级检测及下载数据,最后在定义下载的数据存放位置及如何做开机标志时,突然发现一个很好用的上层java类对象。


frameworks\base\core\java\android\os\RecoverySystem.java
那么这个类做了什么事情呢?又是如何做到的。


RecoverySystem类,可以帮助我们调用系统还原等操作:


android.os.RecoverySystem,提供了如下静态方法
  static void  installPackage(Context context, File packageFile)   //重启设备,安装一个更新包

  static void  rebootWipeUserData(Context context)  //重启设备,清除用户数据分区类似恢复出厂设置

  static String handleAftermath() 提供清除recover中相关文件,在开机广播中被调用

  static void  verifyPackage(File packageFile, RecoverySystem.ProgressListener listener, File deviceCertsZipFile)  //验证加密签名的系统更新包在安装前,其中第二个数接口的具体定义为 android.os.RecoverySystem.ProgressListener  其中只有一个回调方法  abstract void  onProgress(int progress)   来显示效验的进度。
  


下面具体看一下代码中是如何实现:
1、安装更新包:



  1. /** 
  2.  * Reboots the device in order to install the given update 
  3.  * package. 
  4.  * Requires the {@link android.Manifest.permission#REBOOT} permission. 
  5.  * 
  6.  * @param context      the Context to use 
  7.  * @param packageFile  the update package to install.  Must be on 
  8.  * a partition mountable by recovery.  (The set of partitions 
  9.  * known to recovery may vary from device to device.  Generally, 
  10.  * /cache and /data are safe.) 
  11.  * 
  12.  * @throws IOException  if writing the recovery command file 
  13.  * fails, or if the reboot itself fails. 
  14.  */  
  15. public static void installPackage(Context context, File packageFile)  
  16.     throws IOException {  
  17.     String filename = packageFile.getCanonicalPath();  
  18.     Log.w(TAG, "!!! REBOOTING TO INSTALL " + filename + " !!!");  
  19.     String arg = "--update_package=" + filename;  
  20.     bootCommand(context, arg); // 都是调用了这个函数  
  21. }  
  22.   
  23.   
  24. /** 
  25.  * Reboot into the recovery system with the supplied argument. 
  26.  * @param arg to pass to the recovery utility. 
  27.  * @throws IOException if something goes wrong. 
  28.  */  
  29. private static void bootCommand(Context context, String arg) throws IOException {  
  30.     RECOVERY_DIR.mkdirs();  // In case we need it  
  31.     COMMAND_FILE.delete();  // In case it's not writable  
  32.     LOG_FILE.delete();  
  33.   
  34.   
  35.     FileWriter command = new FileWriter(COMMAND_FILE);  // 写命令写入到recover中  
  36.     try {  
  37.         command.write(arg);  
  38.         command.write("\n");  
  39.     } finally {  
  40.         command.close();  
  41.     }  
  42.   
  43.   
  44.     // Having written the command file, go ahead and reboot 系统重启  
  45.     PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE);  
  46.     pm.reboot("recovery");  
  47.   
  48.   
  49.     throw new IOException("Reboot failed (no permissions?)");  
  50. }  



2、出厂恢复



  1. /** 
  2.  * Reboots the device and wipes the user data partition.  This is 
  3.  * sometimes called a "factory reset", which is something of a 
  4.  * misnomer because the system partition is not restored to its 
  5.  * factory state. 
  6.  * Requires the {@link android.Manifest.permission#REBOOT} permission. 
  7.  * 
  8.  * @param context  the Context to use 
  9.  * 
  10.  * @throws IOException  if writing the recovery command file 
  11.  * fails, or if the reboot itself fails. 
  12.  */  
  13. public static void rebootWipeUserData(Context context) throws IOException {  
  14.     final ConditionVariable condition = new ConditionVariable();  
  15.   
  16.   
  17.     Intent intent = new Intent("android.intent.action.MASTER_CLEAR_NOTIFICATION");  
  18.     context.sendOrderedBroadcast(intent, android.Manifest.permission.MASTER_CLEAR,  
  19.             new BroadcastReceiver() {  
  20.                 @Override  
  21.                 public void onReceive(Context context, Intent intent) {  
  22.                     condition.open();  
  23.                 }  
  24.             }, null, 0, null, null);  
  25.   
  26.   
  27.     // Block until the ordered broadcast has completed.  
  28.     condition.block();  
  29.   
  30.   
  31.     bootCommand(context, "--wipe_data");  
  32. }  
  33. /** 
  34.  * Reboot into the recovery system to wipe the /cache partition. 
  35.  * @throws IOException if something goes wrong. 
  36.  */  
  37. public static void rebootWipeCache(Context context) throws IOException {  
  38.     bootCommand(context, "--wipe_cache");  
  39. }  



3、验证签名
    public static void verifyPackage(File packageFile,
                                     ProgressListener listener,
                                     File deviceCertsZipFile)  请自行阅读源码


后面说一下重启 reboot 命令如何执行的:


无论是 factory reset 工厂恢复还是 安装更新包都会调用到reboot函数,调用   pm.reboot("recovery");

通到jni就是: android_os_Power.cpp


shutdown 调用 android_reboot(ANDROID_RB_POWEROFF, 0, 0);
reboot 调用 android_reboot(ANDROID_RB_RESTART2, 0, (char *) chars);
最终都是调用到下面函数:
int reboot (int  mode) 
{
    return __reboot( LINUX_REBOOT_MAGIC1, LINUX_REBOOT_MAGIC2, mode, NULL );
}


=====linux kernel 内核流程=====
/bionic/libc/arch-arm/syscalls/__reboot.S
这个文件由gensyscalls.py自动产生,调用系统调用 __NR_reboot


bionic/libc/include/sys/linux-syscalls.h
#define __NR_reboot (__NR_SYSCALL_BASE+88)


/arch/arm/kernel/calls.S
__NR_reboot?就是系统函数sys_reboot


sys_reboot定义在./include/linux/syscalls.h,实现在./kernel/sys.c?sys_reboot会调用kernel_restart
最终kernel_restart调用每一个架构特定的machine_restart,即machine_restart执行每个架构特定的函数


版权声明:本文为博主原创文章,未经博主允许不得转载。

8
阅读(1395) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~