diff options
Diffstat (limited to 'recovery.cpp')
-rw-r--r-- | recovery.cpp | 89 |
1 files changed, 84 insertions, 5 deletions
diff --git a/recovery.cpp b/recovery.cpp index 0dfcce02e..45a6fe90c 100644 --- a/recovery.cpp +++ b/recovery.cpp @@ -57,6 +57,7 @@ #include "bootloader.h" #include "common.h" #include "device.h" +#include "error_code.h" #include "fuse_sdcard_provider.h" #include "fuse_sideload.h" #include "install.h" @@ -81,6 +82,7 @@ static const struct option OPTIONS[] = { { "stages", required_argument, NULL, 'g' }, { "shutdown_after", no_argument, NULL, 'p' }, { "reason", required_argument, NULL, 'r' }, + { "security", no_argument, NULL, 'e'}, { "brick", no_argument, NULL, 0 }, { NULL, 0, NULL, 0 }, }; @@ -90,14 +92,18 @@ static const char *COMMAND_FILE = "/cache/recovery/command"; static const char *LOG_FILE = "/cache/recovery/log"; static const char *LAST_INSTALL_FILE = "/cache/recovery/last_install"; static const char *LOCALE_FILE = "/cache/recovery/last_locale"; +static const char *CONVERT_FBE_DIR = "/tmp/convert_fbe"; +static const char *CONVERT_FBE_FILE = "/tmp/convert_fbe/convert_fbe"; static const char *CACHE_ROOT = "/cache"; +static const char *DATA_ROOT = "/data"; static const char *SDCARD_ROOT = "/sdcard"; static const char *TEMPORARY_LOG_FILE = "/tmp/recovery.log"; static const char *TEMPORARY_INSTALL_FILE = "/tmp/last_install"; static const char *LAST_KMSG_FILE = "/cache/recovery/last_kmsg"; static const char *LAST_LOG_FILE = "/cache/recovery/last_log"; static const int KEEP_LOG_COUNT = 10; -static const int EIO_RETRY_COUNT = 2; +// We will try to apply the update package 5 times at most in case of an I/O error. +static const int EIO_RETRY_COUNT = 4; static const int BATTERY_READ_TIMEOUT_IN_SEC = 10; // GmsCore enters recovery mode to install package when having enough battery // percentage. Normally, the threshold is 40% without charger and 20% with charger. @@ -107,7 +113,7 @@ static const int BATTERY_WITH_CHARGER_OK_PERCENTAGE = 15; constexpr const char* RECOVERY_BRICK = "/etc/recovery.brick"; RecoveryUI* ui = NULL; -char* locale = NULL; +static const char* locale = "en_US"; char* stage = NULL; char* reason = NULL; bool modified_flash = false; @@ -540,6 +546,7 @@ typedef struct _saved_log_file { static bool erase_volume(const char* volume) { bool is_cache = (strcmp(volume, CACHE_ROOT) == 0); + bool is_data = (strcmp(volume, DATA_ROOT) == 0); ui->SetBackground(RecoveryUI::ERASING); ui->SetProgressType(RecoveryUI::INDETERMINATE); @@ -594,7 +601,28 @@ static bool erase_volume(const char* volume) { ui->Print("Formatting %s...\n", volume); ensure_path_unmounted(volume); - int result = format_volume(volume); + + int result; + + if (is_data && reason && strcmp(reason, "convert_fbe") == 0) { + // Create convert_fbe breadcrumb file to signal to init + // to convert to file based encryption, not full disk encryption + if (mkdir(CONVERT_FBE_DIR, 0700) != 0) { + ui->Print("Failed to make convert_fbe dir %s\n", strerror(errno)); + return true; + } + FILE* f = fopen(CONVERT_FBE_FILE, "wb"); + if (!f) { + ui->Print("Failed to convert to file encryption %s\n", strerror(errno)); + return true; + } + fclose(f); + result = format_volume(volume, CONVERT_FBE_DIR); + remove(CONVERT_FBE_FILE); + rmdir(CONVERT_FBE_DIR); + } else { + result = format_volume(volume); + } if (is_cache) { while (head) { @@ -954,6 +982,37 @@ static void choose_recovery_file(Device* device) { } } +static void run_graphics_test(Device* device) { + // Switch to graphics screen. + ui->ShowText(false); + + ui->SetProgressType(RecoveryUI::INDETERMINATE); + ui->SetBackground(RecoveryUI::INSTALLING_UPDATE); + sleep(1); + + ui->SetBackground(RecoveryUI::ERROR); + sleep(1); + + ui->SetBackground(RecoveryUI::NO_COMMAND); + sleep(1); + + ui->SetBackground(RecoveryUI::ERASING); + sleep(1); + + ui->SetBackground(RecoveryUI::INSTALLING_UPDATE); + + ui->SetProgressType(RecoveryUI::DETERMINATE); + ui->ShowProgress(1.0, 10.0); + float fraction = 0.0; + for (size_t i = 0; i < 100; ++i) { + fraction += .01; + ui->SetProgress(fraction); + usleep(100000); + } + + ui->ShowText(true); +} + // How long (in seconds) we wait for the fuse-provided package file to // appear, before timing out. #define SDCARD_INSTALL_TIMEOUT 10 @@ -1012,7 +1071,7 @@ static int apply_from_sdcard(Device* device, bool* wipe_cache) { } result = install_package(FUSE_SIDELOAD_HOST_PATHNAME, wipe_cache, - TEMPORARY_INSTALL_FILE, false); + TEMPORARY_INSTALL_FILE, false, 0/*retry_count*/); break; } @@ -1112,6 +1171,10 @@ prompt_and_wait(Device* device, int status) { choose_recovery_file(device); break; + case Device::RUN_GRAPHICS_TEST: + run_graphics_test(device); + break; + case Device::MOUNT_SYSTEM: char system_root_image[PROPERTY_VALUE_MAX]; property_get("ro.build.system_root_image", system_root_image, ""); @@ -1353,6 +1416,7 @@ int main(int argc, char **argv) { bool just_exit = false; bool shutdown_after = false; int retry_count = 0; + bool security_update = false; int arg; int option_index; @@ -1377,6 +1441,7 @@ int main(int argc, char **argv) { } case 'p': shutdown_after = true; break; case 'r': reason = optarg; break; + case 'e': security_update = true; break; case 0: { if (strcmp(OPTIONS[option_index].name, "brick") == 0) { should_brick = true; @@ -1403,6 +1468,9 @@ int main(int argc, char **argv) { ui->SetLocale(locale); ui->Init(); + // Set background string to "installing security update" for security update, + // otherwise set it to "installing system update". + ui->SetSystemUpdateText(security_update); int st_cur, st_max; if (stage != NULL && sscanf(stage, "%d/%d", &st_cur, &st_max) == 2) { @@ -1465,10 +1533,21 @@ int main(int argc, char **argv) { if (!is_battery_ok()) { ui->Print("battery capacity is not enough for installing package, needed is %d%%\n", BATTERY_OK_PERCENTAGE); + // Log the error code to last_install when installation skips due to + // low battery. + FILE* install_log = fopen_path(LAST_INSTALL_FILE, "w"); + if (install_log != nullptr) { + fprintf(install_log, "%s\n", update_package); + fprintf(install_log, "0\n"); + fprintf(install_log, "error: %d\n", kLowBattery); + fclose(install_log); + } else { + LOGE("failed to open last_install: %s\n", strerror(errno)); + } status = INSTALL_SKIPPED; } else { status = install_package(update_package, &should_wipe_cache, - TEMPORARY_INSTALL_FILE, true); + TEMPORARY_INSTALL_FILE, true, retry_count); if (status == INSTALL_SUCCESS && should_wipe_cache) { wipe_cache(false, device); } |