1.概述
在9.0的系统产品开发中,对系统原生的recovery功能也是系统中比较重要的一个部分,所以对于恢复出厂设置在开发中也是常有的功能
而在一款产品的开发过程中,由于在recovery界面需要手动输入确认,在产品中没有音量按键需要自动recovery,所以需要自动恢复出厂设置
去掉recovery弹窗的相关操作,接下来分析下手动确认相关功能来实现自动恢复出厂设置功能
2.recovery 菜单页跳过弹窗自动 WIPE_DATA(恢复出厂设置)的核心类
/bootable/recovery/device.cpp
/bootable/recovery/recovery.cpp
3.recovery 菜单页跳过弹窗自动 WIPE_DATA(恢复出厂设置)的核心功能分析和实现
3.1 device.cpp中关于recovery弹窗菜单项分析
static const char* MENU_ITEMS[] = {
"Reboot system now",
"Reboot to bootloader",
"Apply update from ADB",
"Apply update from SD card",
"Wipe data/factory reset",
#ifndef AB_OTA_UPDATER
"Wipe cache partition",
#endif // !AB_OTA_UPDATER
"Mount /system",
"View recovery logs",
"Run graphics test",
"Run locale test",
"Power off",
nullptr,
};
static const Device::BuiltinAction MENU_ACTIONS[] = {
Device::REBOOT,
Device::REBOOT_BOOTLOADER,
Device::APPLY_ADB_SIDELOAD,
Device::APPLY_SDCARD,
Device::WIPE_DATA,
#ifndef AB_OTA_UPDATER
Device::WIPE_CACHE,
#endif // !AB_OTA_UPDATER
Device::MOUNT_SYSTEM,
Device::VIEW_RECOVERY_LOGS,
Device::RUN_GRAPHICS_TEST,
Device::RUN_LOCALE_TEST,
Device::SHUTDOWN,
};
在device.cpp的上述代码可以看到,在MENU_ITEMS[]就是上述recovery页面菜单项,通过音量键来选择这些选项,然后进行对应的
recovery的选项功能,而在MENU_ACTIONS[]就是recovery菜单对应的recovery action事件,接下来需要分析下recovery.cpp的相关
具体recovery功能
3.2 recovery.cpp关于恢复出厂设置的相关方法的分析
int main(int argc, char **argv) {
.....
Device::BuiltinAction after = shutdown_after ? Device::SHUTDOWN : Device::REBOOT;
// 1. If the recovery menu is visible, prompt and wait for commands.
// 2. If the state is INSTALL_NONE, wait for commands. (i.e. In user build, manually reboot into
// recovery to sideload a package.)
// 3. sideload_auto_reboot is an option only available in user-debug build, reboot the device
// without waiting.
// 4. In all other cases, reboot the device. Therefore, normal users will observe the device
// reboot after it shows the "error" screen for 5s.
if ((status == INSTALL_NONE && !sideload_auto_reboot) || ui->IsTextVisible()) {
Device::BuiltinAction temp = prompt_and_wait(device, status);
if (temp != Device::NO_ACTION) {
after = temp;
}
}
// Save logs and clean up before rebooting or shutting down.
finish_recovery();
switch (after) {
case Device::SHUTDOWN:
ui->Print("Shutting down...\n");
android::base::SetProperty(ANDROID_RB_PROPERTY, "shutdown,");
break;
case Device::REBOOT_BOOTLOADER:
ui->Print("Rebooting to bootloader...\n");
android::base::SetProperty(ANDROID_RB_PROPERTY, "reboot,bootloader");
break;
default:
ui->Print("Rebooting...\n");
reboot("reboot,");
break;
}
while (true) {
pause();
}
// Should be unreachable.
return EXIT
}
在recovery.cpp的main(int argc, char **argv)方法中,会根据是否有recovery参数来决定执行什么样的recovery 的action事件,而
如果没有带recovery的相关参数,就会进入到prompt_and_wait(device, status);来等待用户通过菜单选择相关的recovery相关事件
,进行recovery。接下来看下prompt_and_wait(device, status)的相关方法
static Device::BuiltinAction prompt_and_wait(Device* device, int status) {
for (;;) {
finish_recovery();
switch (status) {
case INSTALL_SUCCESS:
case INSTALL_NONE:
ui->SetBackground(RecoveryUI::NO_COMMAND);
break;
case INSTALL_ERROR:
case INSTALL_CORRUPT:
ui->SetBackground(RecoveryUI::ERROR);
break;
}
ui->SetProgressType(RecoveryUI::EMPTY);
// 注释掉关于等待选择菜单项的代码
// int chosen_item = get_menu_selection(nullptr, device->GetMenuItems(), false, 0, device);
// Device-specific code may take some action here. It may return one of the core actions
// handled in the switch statement below.
// 直接赋值菜单项为恢复出厂设置选项
Device::BuiltinAction chosen_action = Device::WIPE_DATA;
/* (chosen_item == -1) ? Device::REBOOT : device->InvokeMenuItem(chosen_item);*/
bool should_wipe_cache = false;
switch (chosen_action) {
case Device::NO_ACTION:
break;
case Device::REBOOT:
case Device::SHUTDOWN:
case Device::REBOOT_BOOTLOADER:
return chosen_action;
case Device::WIPE_DATA:
// 注释掉关于选择确定的弹窗
// if (ui->IsTextVisible()) {
// if (ask_to_wipe_data(device)) {
wipe_data(device);
return Device::NO_ACTION;
//}
//} else {
// wipe_data(device);
//return Device::NO_ACTION;
//}
//break;
case Device::WIPE_CACHE:
wipe_cache(ui->IsTextVisible(), device);
if (!ui->IsTextVisible()) return Device::NO_ACTION;
break;
case Device::APPLY_ADB_SIDELOAD:
case Device::APPLY_SDCARD:
{
bool adb = (chosen_action == Device::APPLY_ADB_SIDELOAD);
if (adb) {
status = apply_from_adb(&should_wipe_cache, TEMPORARY_INSTALL_FILE);
} else {
status = apply_from_sdcard(device, &should_wipe_cache);
}
if (status == INSTALL_SUCCESS && should_wipe_cache) {
if (!wipe_cache(false, device)) {
status = INSTALL_ERROR;
}
}
if (status != INSTALL_SUCCESS) {
ui->SetBackground(RecoveryUI::ERROR);
ui->Print("Installation aborted.\n");
copy_logs();
} else if (!ui->IsTextVisible()) {
return Device::NO_ACTION; // reboot if logs aren't visible
} else {
ui->Print("\nInstall from %s complete.\n", adb ? "ADB" : "SD card");
}
}
break;
case Device::VIEW_RECOVERY_LOGS:
choose_recovery_file(device);
break;
case Device::RUN_GRAPHICS_TEST:
run_graphics_test();
break;
case Device::RUN_LOCALE_TEST: {
ScreenRecoveryUI* screen_ui = static_cast<ScreenRecoveryUI*>(ui);
screen_ui->CheckBackgroundTextImages(locale);
break;
}
case Device::MOUNT_SYSTEM:
// For a system image built with the root directory (i.e. system_root_image == "true"), we
// mount it to /system_root, and symlink /system to /system_root/system to make adb shell
// work (the symlink is created through the build system). (Bug: 22855115)
if (android::base::GetBoolProperty("ro.build.system_root_image", false)) {
if (ensure_path_mounted_at("/", "/system_root") != -1) {
ui->Print("Mounted /system.\n");
}
} else {
if (ensure_path_mounted("/system") != -1) {
ui->Print("Mounted /system.\n");
}
}
break;
}
}
}
在recovery.cpp的prompt_and_wait(Device* device, int status)的方法就是主要等待用户选择recovey菜单项的方法,然后根据
选择的菜单项执行相关的recovery功能,在int chosen_item = get_menu_selection(nullptr, device->GetMenuItems(), false, 0, device);中
就是关于等待用户选择菜单项,所以需要注释掉,然后在给Device::BuiltinAction chosen_action直接赋值就好,然后在
case Device::WIPE_DATA:注释掉相关弹窗确认的相关代码就可以实现自动恢复出厂设置的recovery功能了