recovery: install packages in a known mount environment

When installing a package, we should have /tmp and /cache mounted and
nothing else.  Ensure this is true by explicitly mounting them and
unmounting everything else as the first step of every install.

Also fix an error in the progress bar that crops up when you do
multiple package installs in one instance of recovery.

Change-Id: I4837ed707cb419ddd3d9f6188b6355ba1bcfe2b2
diff --git a/install.cpp b/install.cpp
index e1ab848..797a525 100644
--- a/install.cpp
+++ b/install.cpp
@@ -180,7 +180,9 @@
 {
     ui->SetBackground(RecoveryUI::INSTALLING_UPDATE);
     ui->Print("Finding update package...\n");
-    ui->SetProgressType(RecoveryUI::INDETERMINATE);
+    // Give verification half the progress bar...
+    ui->SetProgressType(RecoveryUI::DETERMINATE);
+    ui->ShowProgress(VERIFICATION_PROGRESS_FRACTION, VERIFICATION_PROGRESS_TIME);
     LOGI("Update location: %s\n", path);
 
     if (ensure_path_mounted(path) != 0) {
@@ -198,10 +200,7 @@
     }
     LOGI("%d key(s) loaded from %s\n", numKeys, PUBLIC_KEYS_FILE);
 
-    // Give verification half the progress bar...
     ui->Print("Verifying update package...\n");
-    ui->SetProgressType(RecoveryUI::DETERMINATE);
-    ui->ShowProgress(VERIFICATION_PROGRESS_FRACTION, VERIFICATION_PROGRESS_TIME);
 
     int err;
     err = verify_file(path, loadedKeys, numKeys);
@@ -237,7 +236,13 @@
     } else {
         LOGE("failed to open last_install: %s\n", strerror(errno));
     }
-    int result = really_install_package(path, wipe_cache);
+    int result;
+    if (setup_install_mounts() != 0) {
+        LOGE("failed to set up expected mounts for install; aborting\n");
+        result = INSTALL_ERROR;
+    } else {
+        result = really_install_package(path, wipe_cache);
+    }
     if (install_log) {
         fputc(result == INSTALL_SUCCESS ? '1' : '0', install_log);
         fputc('\n', install_log);
diff --git a/recovery.cpp b/recovery.cpp
index 38366b6..654a665 100644
--- a/recovery.cpp
+++ b/recovery.cpp
@@ -811,10 +811,6 @@
                 break;
 
             case Device::APPLY_EXT:
-                // Some packages expect /cache to be mounted (eg,
-                // standard incremental packages expect to use /cache
-                // as scratch space).
-                ensure_path_mounted(CACHE_ROOT);
                 status = update_directory(SDCARD_ROOT, SDCARD_ROOT, &wipe_cache, device);
                 if (status == INSTALL_SUCCESS && wipe_cache) {
                     ui->Print("\n-- Wiping cache (at package request)...\n");
@@ -860,7 +856,6 @@
                 break;
 
             case Device::APPLY_ADB_SIDELOAD:
-                ensure_path_mounted(CACHE_ROOT);
                 status = apply_from_adb(ui, &wipe_cache, TEMPORARY_INSTALL_FILE);
                 if (status >= 0) {
                     if (status != INSTALL_SUCCESS) {
diff --git a/roots.cpp b/roots.cpp
index 0947122..113dba1 100644
--- a/roots.cpp
+++ b/roots.cpp
@@ -202,3 +202,22 @@
     LOGE("format_volume: fs_type \"%s\" unsupported\n", v->fs_type);
     return -1;
 }
+
+int setup_install_mounts() {
+    if (fstab == NULL) {
+        LOGE("can't set up install mounts: no fstab loaded\n");
+        return -1;
+    }
+    for (int i = 0; i < fstab->num_entries; ++i) {
+        Volume* v = fstab->recs + i;
+
+        if (strcmp(v->mount_point, "/tmp") == 0 ||
+            strcmp(v->mount_point, "/cache") == 0) {
+            if (ensure_path_mounted(v->mount_point) != 0) return -1;
+
+        } else {
+            if (ensure_path_unmounted(v->mount_point) != 0) return -1;
+        }
+    }
+    return 0;
+}
diff --git a/roots.h b/roots.h
index 8abe18f..230d9de 100644
--- a/roots.h
+++ b/roots.h
@@ -42,6 +42,10 @@
 // it is mounted.
 int format_volume(const char* volume);
 
+// Ensure that all and only the volumes that packages expect to find
+// mounted (/tmp and /cache) are mounted.  Returns 0 on success.
+int setup_install_mounts();
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/screen_ui.cpp b/screen_ui.cpp
index 6a63858..8376341 100644
--- a/screen_ui.cpp
+++ b/screen_ui.cpp
@@ -467,10 +467,11 @@
     pthread_mutex_lock(&updateMutex);
     if (progressBarType != type) {
         progressBarType = type;
-        update_progress_locked();
     }
     progressScopeStart = 0;
+    progressScopeSize = 0;
     progress = 0;
+    update_progress_locked();
     pthread_mutex_unlock(&updateMutex);
 }