summaryrefslogtreecommitdiffstats
path: root/recovery.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'recovery.cpp')
-rw-r--r--recovery.cpp89
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);
}