aboutsummaryrefslogtreecommitdiffstats
path: root/recovery.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'recovery.cpp')
-rw-r--r--recovery.cpp116
1 files changed, 90 insertions, 26 deletions
diff --git a/recovery.cpp b/recovery.cpp
index 85381335..58805622 100644
--- a/recovery.cpp
+++ b/recovery.cpp
@@ -74,6 +74,8 @@
#include "stub_ui.h"
#include "ui.h"
+#include "voldclient.h"
+
extern "C" {
#include "recovery_cmds.h"
}
@@ -112,7 +114,6 @@ 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";
@@ -662,8 +663,8 @@ static bool erase_volume(const char* volume) {
// return a positive number beyond the given range. Caller sets 'menu_only' to true to ensure only
// a menu item gets selected. 'initial_selection' controls the initial cursor location. Returns the
// (non-negative) chosen item number, or -1 if timed out waiting for input.
-static int get_menu_selection(const char* const* headers, const char* const* items, bool menu_only,
- int initial_selection, Device* device) {
+int get_menu_selection(const char* const* headers, const char* const* items, bool menu_only,
+ int initial_selection, Device* device) {
// Throw away keys pressed previously, so user doesn't accidentally trigger menu items.
ui->FlushKeys();
@@ -705,12 +706,16 @@ static int get_menu_selection(const char* const* headers, const char* const* ite
case Device::kGoHome:
chosen_item = Device::kGoHome;
break;
+ case Device::kRefresh:
+ chosen_item = Device::kRefresh;
+ break;
}
} else if (!menu_only) {
chosen_item = action;
}
if (chosen_item == Device::kGoBack ||
- chosen_item == Device::kGoHome) {
+ chosen_item == Device::kGoHome ||
+ chosen_item == Device::kRefresh) {
break;
}
}
@@ -721,8 +726,6 @@ static int get_menu_selection(const char* const* headers, const char* const* ite
// Returns the selected filename, or an empty string.
static std::string browse_directory(const std::string& path, Device* device) {
- ensure_path_mounted(path.c_str());
-
std::unique_ptr<DIR, decltype(&closedir)> d(opendir(path.c_str()), closedir);
if (!d) {
PLOG(ERROR) << "error opening " << path;
@@ -769,6 +772,9 @@ static std::string browse_directory(const std::string& path, Device* device) {
// Go up but continue browsing (if the caller is browse_directory).
return "";
}
+ if (chosen_item == Device::kRefresh) {
+ return "@refresh";
+ }
const std::string& item = zips[chosen_item];
@@ -1080,33 +1086,88 @@ static void run_graphics_test() {
ui->ShowText(true);
}
-static int apply_from_sdcard(Device* device, bool* wipe_cache) {
+static int apply_from_storage(Device* device, const std::string& id, bool* wipe_cache) {
modified_flash = true;
- if (ensure_path_mounted(SDCARD_ROOT) != 0) {
- ui->Print("\n-- Couldn't mount %s.\n", SDCARD_ROOT);
+ int status;
+
+ if (!vdc->volumeMount(id)) {
return INSTALL_ERROR;
}
- std::string path = browse_directory(SDCARD_ROOT, device);
- if (path == "@") {
- return INSTALL_NONE;
+ VolumeInfo vi = vdc->getVolume(id);
+
+ std::string path;
+ do {
+ path = browse_directory(vi.mInternalPath, device);
+ if (path == "@") {
+ return INSTALL_NONE;
+ }
}
+ while (path == "@refresh");
+
if (path.empty()) {
ui->Print("\n-- No package file selected.\n");
- ensure_path_unmounted(SDCARD_ROOT);
- return INSTALL_ERROR;
+ vdc->volumeUnmount(vi.mId);
+ return INSTALL_NONE;
}
ui->Print("\n-- Install %s ...\n", path.c_str());
set_sdcard_update_bootloader_message();
void* token = start_sdcard_fuse(path.c_str());
- int status = install_package(FUSE_SIDELOAD_HOST_PATHNAME, wipe_cache,
+ vdc->volumeUnmount(vi.mId, true);
+
+ status = install_package(FUSE_SIDELOAD_HOST_PATHNAME, wipe_cache,
TEMPORARY_INSTALL_FILE, false, 0/*retry_count*/);
finish_sdcard_fuse(token);
- ensure_path_unmounted(SDCARD_ROOT);
+ return status;
+}
+
+static int
+show_apply_update_menu(Device* device, bool* wipe_cache) {
+ static const char* headers[] = { "Apply update", nullptr };
+ char* menu_items[MAX_NUM_MANAGED_VOLUMES + 1 + 1];
+ std::vector<VolumeInfo> volumes = vdc->getVolumes();
+
+ const int item_sideload = 0;
+ int n, i;
+ std::vector<VolumeInfo>::iterator vitr;
+
+refresh:
+ menu_items[item_sideload] = strdup("Apply from ADB");
+
+ n = item_sideload + 1;
+ for (vitr = volumes.begin(); vitr != volumes.end(); ++vitr) {
+ menu_items[n] = (char*)malloc(256);
+ sprintf(menu_items[n], "Choose from %s", vitr->mLabel.c_str());
+ ++n;
+ }
+ menu_items[n] = nullptr;
+
+ int status = INSTALL_ERROR;
+
+ for (;;) {
+ int chosen = get_menu_selection(headers, menu_items, 0, 0, device);
+ for (i = 0; i < n; ++i) {
+ free(menu_items[i]);
+ }
+ if (chosen == Device::kRefresh) {
+ goto refresh;
+ }
+ if (chosen == Device::kGoBack) {
+ break;
+ }
+ if (chosen == item_sideload) {
+ status = apply_from_adb(ui, wipe_cache, TEMPORARY_INSTALL_FILE);
+ }
+ else {
+ std::string id = volumes[chosen - 1].mId;
+ status = apply_from_storage(device, id, wipe_cache);
+ }
+ }
+
return status;
}
@@ -1131,7 +1192,8 @@ static Device::BuiltinAction prompt_and_wait(Device* device, int status) {
int chosen_item = get_menu_selection(nullptr, device->GetMenuItems(), false, 0, device);
// We are already in the main menu
if (chosen_item == Device::kGoBack ||
- chosen_item == Device::kGoHome) {
+ chosen_item == Device::kGoHome ||
+ chosen_item == Device::kRefresh) {
continue;
}
@@ -1166,15 +1228,9 @@ static Device::BuiltinAction prompt_and_wait(Device* device, int status) {
if (!ui->IsTextVisible()) return Device::NO_ACTION;
break;
- case Device::APPLY_ADB_SIDELOAD:
- case Device::APPLY_SDCARD:
+ case Device::APPLY_UPDATE:
{
- bool adb = (chosen_action == Device::APPLY_ADB_SIDELOAD);
- if (adb) {
- status = apply_from_adb(ui, &should_wipe_cache, TEMPORARY_INSTALL_FILE);
- } else {
- status = apply_from_sdcard(device, &should_wipe_cache);
- }
+ status = show_apply_update_menu(device, &should_wipe_cache);
if (status == INSTALL_SUCCESS && should_wipe_cache) {
if (!wipe_cache(false, device)) {
@@ -1189,7 +1245,7 @@ static Device::BuiltinAction prompt_and_wait(Device* device, int status) {
} 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");
+ ui->Print("\nInstall complete.\n");
}
}
break;
@@ -1571,6 +1627,9 @@ int main(int argc, char **argv) {
}
}
+ vdc = new VoldClient(device);
+ vdc->start();
+
// Set background string to "installing security update" for security update,
// otherwise set it to "installing system update".
ui->SetSystemUpdateText(security_update);
@@ -1721,6 +1780,11 @@ int main(int argc, char **argv) {
// Save logs and clean up before rebooting or shutting down.
finish_recovery();
+ vdc->unmountAll();
+ vdc->stop();
+
+ sync();
+
switch (after) {
case Device::SHUTDOWN:
ui->Print("Shutting down...\n");