Android 9.0 recovery 菜单页跳过弹窗自动 WIPE_DATA(恢复出厂设置)

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功能了

猜你喜欢

转载自blog.csdn.net/baidu_41666295/article/details/128291391#comments_27588024
今日推荐