android system recovery utility,Android RecoverSystem 类(一)

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、安装更新包:

/**

* Reboots the device in order to install the given update

* package.

* Requires the {@link android.Manifest.permission#REBOOT} permission.

*

* @param context      the Context to use

* @param packageFile  the update package to install.  Must be on

* a partition mountable by recovery.  (The set of partitions

* known to recovery may vary from device to device.  Generally,

* /cache and /data are safe.)

*

* @throws IOException  if writing the recovery command file

* fails, or if the reboot itself fails.

*/

public static void installPackage(Context context, File packageFile)

throws IOException {

String filename = packageFile.getCanonicalPath();

Log.w(TAG, "!!! REBOOTING TO INSTALL " + filename + " !!!");

String arg = "--update_package=" + filename;

bootCommand(context, arg); // 都是调用了这个函数

}

/**

* Reboot into the recovery system with the supplied argument.

* @param arg to pass to the recovery utility.

* @throws IOException if something goes wrong.

*/

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);  // 写命令写入到recover中

try {

command.write(arg);

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");

throw new IOException("Reboot failed (no permissions?)");

}

2、出厂恢复

/**

* Reboots the device and wipes the user data partition.  This is

* sometimes called a "factory reset", which is something of a

* misnomer because the system partition is not restored to its

* factory state.

* Requires the {@link android.Manifest.permission#REBOOT} permission.

*

* @param context  the Context to use

*

* @throws IOException  if writing the recovery command file

* fails, or if the reboot itself fails.

*/

public static void rebootWipeUserData(Context context) throws IOException {

final ConditionVariable condition = new ConditionVariable();

Intent intent = new Intent("android.intent.action.MASTER_CLEAR_NOTIFICATION");

context.sendOrderedBroadcast(intent, android.Manifest.permission.MASTER_CLEAR,

new BroadcastReceiver() {

@Override

public void onReceive(Context context, Intent intent) {

condition.open();

}

}, null, 0, null, null);

// Block until the ordered broadcast has completed.

condition.block();

bootCommand(context, "--wipe_data");

}

/**

* Reboot into the recovery system to wipe the /cache partition.

* @throws IOException if something goes wrong.

*/

public static void rebootWipeCache(Context context) throws IOException {

bootCommand(context, "--wipe_cache");

}

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执行每个架构特定的函数

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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值