Home | History | Annotate | Download | only in recovery
      1 /*
      2  * Copyright (C) 2007 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 #include "install.h"
     18 
     19 #include <ctype.h>
     20 #include <errno.h>
     21 #include <fcntl.h>
     22 #include <inttypes.h>
     23 #include <limits.h>
     24 #include <string.h>
     25 #include <sys/stat.h>
     26 #include <sys/wait.h>
     27 #include <unistd.h>
     28 
     29 #include <algorithm>
     30 #include <atomic>
     31 #include <chrono>
     32 #include <condition_variable>
     33 #include <functional>
     34 #include <limits>
     35 #include <map>
     36 #include <mutex>
     37 #include <string>
     38 #include <thread>
     39 #include <vector>
     40 
     41 #include <android-base/file.h>
     42 #include <android-base/logging.h>
     43 #include <android-base/parsedouble.h>
     44 #include <android-base/parseint.h>
     45 #include <android-base/properties.h>
     46 #include <android-base/stringprintf.h>
     47 #include <android-base/strings.h>
     48 #include <vintf/VintfObjectRecovery.h>
     49 #include <ziparchive/zip_archive.h>
     50 
     51 #include "common.h"
     52 #include "otautil/SysUtil.h"
     53 #include "otautil/ThermalUtil.h"
     54 #include "otautil/error_code.h"
     55 #include "private/install.h"
     56 #include "roots.h"
     57 #include "ui.h"
     58 #include "verifier.h"
     59 
     60 using namespace std::chrono_literals;
     61 
     62 // Default allocation of progress bar segments to operations
     63 static constexpr int VERIFICATION_PROGRESS_TIME = 60;
     64 static constexpr float VERIFICATION_PROGRESS_FRACTION = 0.25;
     65 
     66 static std::condition_variable finish_log_temperature;
     67 
     68 // This function parses and returns the build.version.incremental
     69 static std::string parse_build_number(const std::string& str) {
     70     size_t pos = str.find('=');
     71     if (pos != std::string::npos) {
     72         return android::base::Trim(str.substr(pos+1));
     73     }
     74 
     75     LOG(ERROR) << "Failed to parse build number in " << str;
     76     return "";
     77 }
     78 
     79 bool read_metadata_from_package(ZipArchiveHandle zip, std::string* metadata) {
     80   CHECK(metadata != nullptr);
     81 
     82   static constexpr const char* METADATA_PATH = "META-INF/com/android/metadata";
     83   ZipString path(METADATA_PATH);
     84   ZipEntry entry;
     85   if (FindEntry(zip, path, &entry) != 0) {
     86     LOG(ERROR) << "Failed to find " << METADATA_PATH;
     87     return false;
     88   }
     89 
     90   uint32_t length = entry.uncompressed_length;
     91   metadata->resize(length, '\0');
     92   int32_t err = ExtractToMemory(zip, &entry, reinterpret_cast<uint8_t*>(&(*metadata)[0]), length);
     93   if (err != 0) {
     94     LOG(ERROR) << "Failed to extract " << METADATA_PATH << ": " << ErrorCodeString(err);
     95     return false;
     96   }
     97   return true;
     98 }
     99 
    100 // Read the build.version.incremental of src/tgt from the metadata and log it to last_install.
    101 static void read_source_target_build(ZipArchiveHandle zip, std::vector<std::string>* log_buffer) {
    102   std::string metadata;
    103   if (!read_metadata_from_package(zip, &metadata)) {
    104     return;
    105   }
    106   // Examples of the pre-build and post-build strings in metadata:
    107   //   pre-build-incremental=2943039
    108   //   post-build-incremental=2951741
    109   std::vector<std::string> lines = android::base::Split(metadata, "\n");
    110   for (const std::string& line : lines) {
    111     std::string str = android::base::Trim(line);
    112     if (android::base::StartsWith(str, "pre-build-incremental")) {
    113       std::string source_build = parse_build_number(str);
    114       if (!source_build.empty()) {
    115         log_buffer->push_back("source_build: " + source_build);
    116       }
    117     } else if (android::base::StartsWith(str, "post-build-incremental")) {
    118       std::string target_build = parse_build_number(str);
    119       if (!target_build.empty()) {
    120         log_buffer->push_back("target_build: " + target_build);
    121       }
    122     }
    123   }
    124 }
    125 
    126 #ifdef AB_OTA_UPDATER
    127 
    128 // Parses the metadata of the OTA package in |zip| and checks whether we are
    129 // allowed to accept this A/B package. Downgrading is not allowed unless
    130 // explicitly enabled in the package and only for incremental packages.
    131 static int check_newer_ab_build(ZipArchiveHandle zip) {
    132   std::string metadata_str;
    133   if (!read_metadata_from_package(zip, &metadata_str)) {
    134     return INSTALL_CORRUPT;
    135   }
    136   std::map<std::string, std::string> metadata;
    137   for (const std::string& line : android::base::Split(metadata_str, "\n")) {
    138     size_t eq = line.find('=');
    139     if (eq != std::string::npos) {
    140       metadata[line.substr(0, eq)] = line.substr(eq + 1);
    141     }
    142   }
    143 
    144   std::string value = android::base::GetProperty("ro.product.device", "");
    145   const std::string& pkg_device = metadata["pre-device"];
    146   if (pkg_device != value || pkg_device.empty()) {
    147     LOG(ERROR) << "Package is for product " << pkg_device << " but expected " << value;
    148     return INSTALL_ERROR;
    149   }
    150 
    151   // We allow the package to not have any serialno; and we also allow it to carry multiple serial
    152   // numbers split by "|"; e.g. serialno=serialno1|serialno2|serialno3 ... We will fail the
    153   // verification if the device's serialno doesn't match any of these carried numbers.
    154   value = android::base::GetProperty("ro.serialno", "");
    155   const std::string& pkg_serial_no = metadata["serialno"];
    156   if (!pkg_serial_no.empty()) {
    157     bool match = false;
    158     for (const std::string& number : android::base::Split(pkg_serial_no, "|")) {
    159       if (value == android::base::Trim(number)) {
    160         match = true;
    161         break;
    162       }
    163     }
    164     if (!match) {
    165       LOG(ERROR) << "Package is for serial " << pkg_serial_no;
    166       return INSTALL_ERROR;
    167     }
    168   }
    169 
    170   if (metadata["ota-type"] != "AB") {
    171     LOG(ERROR) << "Package is not A/B";
    172     return INSTALL_ERROR;
    173   }
    174 
    175   // Incremental updates should match the current build.
    176   value = android::base::GetProperty("ro.build.version.incremental", "");
    177   const std::string& pkg_pre_build = metadata["pre-build-incremental"];
    178   if (!pkg_pre_build.empty() && pkg_pre_build != value) {
    179     LOG(ERROR) << "Package is for source build " << pkg_pre_build << " but expected " << value;
    180     return INSTALL_ERROR;
    181   }
    182 
    183   value = android::base::GetProperty("ro.build.fingerprint", "");
    184   const std::string& pkg_pre_build_fingerprint = metadata["pre-build"];
    185   if (!pkg_pre_build_fingerprint.empty() && pkg_pre_build_fingerprint != value) {
    186     LOG(ERROR) << "Package is for source build " << pkg_pre_build_fingerprint << " but expected "
    187                << value;
    188     return INSTALL_ERROR;
    189   }
    190 
    191   // Check for downgrade version.
    192   int64_t build_timestamp =
    193       android::base::GetIntProperty("ro.build.date.utc", std::numeric_limits<int64_t>::max());
    194   int64_t pkg_post_timestamp = 0;
    195   // We allow to full update to the same version we are running, in case there
    196   // is a problem with the current copy of that version.
    197   if (metadata["post-timestamp"].empty() ||
    198       !android::base::ParseInt(metadata["post-timestamp"].c_str(), &pkg_post_timestamp) ||
    199       pkg_post_timestamp < build_timestamp) {
    200     if (metadata["ota-downgrade"] != "yes") {
    201       LOG(ERROR) << "Update package is older than the current build, expected a build "
    202                     "newer than timestamp "
    203                  << build_timestamp << " but package has timestamp " << pkg_post_timestamp
    204                  << " and downgrade not allowed.";
    205       return INSTALL_ERROR;
    206     }
    207     if (pkg_pre_build_fingerprint.empty()) {
    208       LOG(ERROR) << "Downgrade package must have a pre-build version set, not allowed.";
    209       return INSTALL_ERROR;
    210     }
    211   }
    212 
    213   return 0;
    214 }
    215 
    216 int update_binary_command(const std::string& package, ZipArchiveHandle zip,
    217                           const std::string& binary_path, int /* retry_count */, int status_fd,
    218                           std::vector<std::string>* cmd) {
    219   CHECK(cmd != nullptr);
    220   int ret = check_newer_ab_build(zip);
    221   if (ret != 0) {
    222     return ret;
    223   }
    224 
    225   // For A/B updates we extract the payload properties to a buffer and obtain the RAW payload offset
    226   // in the zip file.
    227   static constexpr const char* AB_OTA_PAYLOAD_PROPERTIES = "payload_properties.txt";
    228   ZipString property_name(AB_OTA_PAYLOAD_PROPERTIES);
    229   ZipEntry properties_entry;
    230   if (FindEntry(zip, property_name, &properties_entry) != 0) {
    231     LOG(ERROR) << "Failed to find " << AB_OTA_PAYLOAD_PROPERTIES;
    232     return INSTALL_CORRUPT;
    233   }
    234   uint32_t properties_entry_length = properties_entry.uncompressed_length;
    235   std::vector<uint8_t> payload_properties(properties_entry_length);
    236   int32_t err =
    237       ExtractToMemory(zip, &properties_entry, payload_properties.data(), properties_entry_length);
    238   if (err != 0) {
    239     LOG(ERROR) << "Failed to extract " << AB_OTA_PAYLOAD_PROPERTIES << ": " << ErrorCodeString(err);
    240     return INSTALL_CORRUPT;
    241   }
    242 
    243   static constexpr const char* AB_OTA_PAYLOAD = "payload.bin";
    244   ZipString payload_name(AB_OTA_PAYLOAD);
    245   ZipEntry payload_entry;
    246   if (FindEntry(zip, payload_name, &payload_entry) != 0) {
    247     LOG(ERROR) << "Failed to find " << AB_OTA_PAYLOAD;
    248     return INSTALL_CORRUPT;
    249   }
    250   long payload_offset = payload_entry.offset;
    251   *cmd = {
    252     binary_path,
    253     "--payload=file://" + package,
    254     android::base::StringPrintf("--offset=%ld", payload_offset),
    255     "--headers=" + std::string(payload_properties.begin(), payload_properties.end()),
    256     android::base::StringPrintf("--status_fd=%d", status_fd),
    257   };
    258   return 0;
    259 }
    260 
    261 #else  // !AB_OTA_UPDATER
    262 
    263 int update_binary_command(const std::string& package, ZipArchiveHandle zip,
    264                           const std::string& binary_path, int retry_count, int status_fd,
    265                           std::vector<std::string>* cmd) {
    266   CHECK(cmd != nullptr);
    267 
    268   // On traditional updates we extract the update binary from the package.
    269   static constexpr const char* UPDATE_BINARY_NAME = "META-INF/com/google/android/update-binary";
    270   ZipString binary_name(UPDATE_BINARY_NAME);
    271   ZipEntry binary_entry;
    272   if (FindEntry(zip, binary_name, &binary_entry) != 0) {
    273     LOG(ERROR) << "Failed to find update binary " << UPDATE_BINARY_NAME;
    274     return INSTALL_CORRUPT;
    275   }
    276 
    277   unlink(binary_path.c_str());
    278   int fd = open(binary_path.c_str(), O_CREAT | O_WRONLY | O_TRUNC | O_CLOEXEC, 0755);
    279   if (fd == -1) {
    280     PLOG(ERROR) << "Failed to create " << binary_path;
    281     return INSTALL_ERROR;
    282   }
    283 
    284   int32_t error = ExtractEntryToFile(zip, &binary_entry, fd);
    285   close(fd);
    286   if (error != 0) {
    287     LOG(ERROR) << "Failed to extract " << UPDATE_BINARY_NAME << ": " << ErrorCodeString(error);
    288     return INSTALL_ERROR;
    289   }
    290 
    291   *cmd = {
    292     binary_path,
    293     std::to_string(kRecoveryApiVersion),
    294     std::to_string(status_fd),
    295     package,
    296   };
    297   if (retry_count > 0) {
    298     cmd->push_back("retry");
    299   }
    300   return 0;
    301 }
    302 #endif  // !AB_OTA_UPDATER
    303 
    304 static void log_max_temperature(int* max_temperature, const std::atomic<bool>& logger_finished) {
    305   CHECK(max_temperature != nullptr);
    306   std::mutex mtx;
    307   std::unique_lock<std::mutex> lck(mtx);
    308   while (!logger_finished.load() &&
    309          finish_log_temperature.wait_for(lck, 20s) == std::cv_status::timeout) {
    310     *max_temperature = std::max(*max_temperature, GetMaxValueFromThermalZone());
    311   }
    312 }
    313 
    314 // If the package contains an update binary, extract it and run it.
    315 static int try_update_binary(const std::string& package, ZipArchiveHandle zip, bool* wipe_cache,
    316                              std::vector<std::string>* log_buffer, int retry_count,
    317                              int* max_temperature) {
    318   read_source_target_build(zip, log_buffer);
    319 
    320   int pipefd[2];
    321   pipe(pipefd);
    322 
    323   std::vector<std::string> args;
    324 #ifdef AB_OTA_UPDATER
    325   int ret = update_binary_command(package, zip, "/sbin/update_engine_sideload", retry_count,
    326                                   pipefd[1], &args);
    327 #else
    328   int ret = update_binary_command(package, zip, "/tmp/update-binary", retry_count, pipefd[1],
    329                                   &args);
    330 #endif
    331   if (ret) {
    332     close(pipefd[0]);
    333     close(pipefd[1]);
    334     log_buffer->push_back(android::base::StringPrintf("error: %d", kUpdateBinaryCommandFailure));
    335     return ret;
    336   }
    337 
    338   // When executing the update binary contained in the package, the
    339   // arguments passed are:
    340   //
    341   //   - the version number for this interface
    342   //
    343   //   - an FD to which the program can write in order to update the
    344   //     progress bar.  The program can write single-line commands:
    345   //
    346   //        progress <frac> <secs>
    347   //            fill up the next <frac> part of of the progress bar
    348   //            over <secs> seconds.  If <secs> is zero, use
    349   //            set_progress commands to manually control the
    350   //            progress of this segment of the bar.
    351   //
    352   //        set_progress <frac>
    353   //            <frac> should be between 0.0 and 1.0; sets the
    354   //            progress bar within the segment defined by the most
    355   //            recent progress command.
    356   //
    357   //        ui_print <string>
    358   //            display <string> on the screen.
    359   //
    360   //        wipe_cache
    361   //            a wipe of cache will be performed following a successful
    362   //            installation.
    363   //
    364   //        clear_display
    365   //            turn off the text display.
    366   //
    367   //        enable_reboot
    368   //            packages can explicitly request that they want the user
    369   //            to be able to reboot during installation (useful for
    370   //            debugging packages that don't exit).
    371   //
    372   //        retry_update
    373   //            updater encounters some issue during the update. It requests
    374   //            a reboot to retry the same package automatically.
    375   //
    376   //        log <string>
    377   //            updater requests logging the string (e.g. cause of the
    378   //            failure).
    379   //
    380   //   - the name of the package zip file.
    381   //
    382   //   - an optional argument "retry" if this update is a retry of a failed
    383   //   update attempt.
    384   //
    385 
    386   // Convert the vector to a NULL-terminated char* array suitable for execv.
    387   const char* chr_args[args.size() + 1];
    388   chr_args[args.size()] = nullptr;
    389   for (size_t i = 0; i < args.size(); i++) {
    390     chr_args[i] = args[i].c_str();
    391   }
    392 
    393   pid_t pid = fork();
    394 
    395   if (pid == -1) {
    396     close(pipefd[0]);
    397     close(pipefd[1]);
    398     PLOG(ERROR) << "Failed to fork update binary";
    399     log_buffer->push_back(android::base::StringPrintf("error: %d", kForkUpdateBinaryFailure));
    400     return INSTALL_ERROR;
    401   }
    402 
    403   if (pid == 0) {
    404     umask(022);
    405     close(pipefd[0]);
    406     execv(chr_args[0], const_cast<char**>(chr_args));
    407     // Bug: 34769056
    408     // We shouldn't use LOG/PLOG in the forked process, since they may cause
    409     // the child process to hang. This deadlock results from an improperly
    410     // copied mutex in the ui functions.
    411     fprintf(stdout, "E:Can't run %s (%s)\n", chr_args[0], strerror(errno));
    412     _exit(EXIT_FAILURE);
    413   }
    414   close(pipefd[1]);
    415 
    416   std::atomic<bool> logger_finished(false);
    417   std::thread temperature_logger(log_max_temperature, max_temperature, std::ref(logger_finished));
    418 
    419   *wipe_cache = false;
    420   bool retry_update = false;
    421 
    422   char buffer[1024];
    423   FILE* from_child = fdopen(pipefd[0], "r");
    424   while (fgets(buffer, sizeof(buffer), from_child) != nullptr) {
    425     std::string line(buffer);
    426     size_t space = line.find_first_of(" \n");
    427     std::string command(line.substr(0, space));
    428     if (command.empty()) continue;
    429 
    430     // Get rid of the leading and trailing space and/or newline.
    431     std::string args = space == std::string::npos ? "" : android::base::Trim(line.substr(space));
    432 
    433     if (command == "progress") {
    434       std::vector<std::string> tokens = android::base::Split(args, " ");
    435       double fraction;
    436       int seconds;
    437       if (tokens.size() == 2 && android::base::ParseDouble(tokens[0].c_str(), &fraction) &&
    438           android::base::ParseInt(tokens[1], &seconds)) {
    439         ui->ShowProgress(fraction * (1 - VERIFICATION_PROGRESS_FRACTION), seconds);
    440       } else {
    441         LOG(ERROR) << "invalid \"progress\" parameters: " << line;
    442       }
    443     } else if (command == "set_progress") {
    444       std::vector<std::string> tokens = android::base::Split(args, " ");
    445       double fraction;
    446       if (tokens.size() == 1 && android::base::ParseDouble(tokens[0].c_str(), &fraction)) {
    447         ui->SetProgress(fraction);
    448       } else {
    449         LOG(ERROR) << "invalid \"set_progress\" parameters: " << line;
    450       }
    451     } else if (command == "ui_print") {
    452       ui->PrintOnScreenOnly("%s\n", args.c_str());
    453       fflush(stdout);
    454     } else if (command == "wipe_cache") {
    455       *wipe_cache = true;
    456     } else if (command == "clear_display") {
    457       ui->SetBackground(RecoveryUI::NONE);
    458     } else if (command == "enable_reboot") {
    459       // packages can explicitly request that they want the user
    460       // to be able to reboot during installation (useful for
    461       // debugging packages that don't exit).
    462       ui->SetEnableReboot(true);
    463     } else if (command == "retry_update") {
    464       retry_update = true;
    465     } else if (command == "log") {
    466       if (!args.empty()) {
    467         // Save the logging request from updater and write to last_install later.
    468         log_buffer->push_back(args);
    469       } else {
    470         LOG(ERROR) << "invalid \"log\" parameters: " << line;
    471       }
    472     } else {
    473       LOG(ERROR) << "unknown command [" << command << "]";
    474     }
    475   }
    476   fclose(from_child);
    477 
    478   int status;
    479   waitpid(pid, &status, 0);
    480 
    481   logger_finished.store(true);
    482   finish_log_temperature.notify_one();
    483   temperature_logger.join();
    484 
    485   if (retry_update) {
    486     return INSTALL_RETRY;
    487   }
    488   if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) {
    489     LOG(ERROR) << "Error in " << package << " (Status " << WEXITSTATUS(status) << ")";
    490     return INSTALL_ERROR;
    491   }
    492 
    493   return INSTALL_SUCCESS;
    494 }
    495 
    496 // Verifes the compatibility info in a Treble-compatible package. Returns true directly if the
    497 // entry doesn't exist. Note that the compatibility info is packed in a zip file inside the OTA
    498 // package.
    499 bool verify_package_compatibility(ZipArchiveHandle package_zip) {
    500   LOG(INFO) << "Verifying package compatibility...";
    501 
    502   static constexpr const char* COMPATIBILITY_ZIP_ENTRY = "compatibility.zip";
    503   ZipString compatibility_entry_name(COMPATIBILITY_ZIP_ENTRY);
    504   ZipEntry compatibility_entry;
    505   if (FindEntry(package_zip, compatibility_entry_name, &compatibility_entry) != 0) {
    506     LOG(INFO) << "Package doesn't contain " << COMPATIBILITY_ZIP_ENTRY << " entry";
    507     return true;
    508   }
    509 
    510   std::string zip_content(compatibility_entry.uncompressed_length, '\0');
    511   int32_t ret;
    512   if ((ret = ExtractToMemory(package_zip, &compatibility_entry,
    513                              reinterpret_cast<uint8_t*>(&zip_content[0]),
    514                              compatibility_entry.uncompressed_length)) != 0) {
    515     LOG(ERROR) << "Failed to read " << COMPATIBILITY_ZIP_ENTRY << ": " << ErrorCodeString(ret);
    516     return false;
    517   }
    518 
    519   ZipArchiveHandle zip_handle;
    520   ret = OpenArchiveFromMemory(static_cast<void*>(const_cast<char*>(zip_content.data())),
    521                               zip_content.size(), COMPATIBILITY_ZIP_ENTRY, &zip_handle);
    522   if (ret != 0) {
    523     LOG(ERROR) << "Failed to OpenArchiveFromMemory: " << ErrorCodeString(ret);
    524     return false;
    525   }
    526 
    527   // Iterate all the entries inside COMPATIBILITY_ZIP_ENTRY and read the contents.
    528   void* cookie;
    529   ret = StartIteration(zip_handle, &cookie, nullptr, nullptr);
    530   if (ret != 0) {
    531     LOG(ERROR) << "Failed to start iterating zip entries: " << ErrorCodeString(ret);
    532     CloseArchive(zip_handle);
    533     return false;
    534   }
    535   std::unique_ptr<void, decltype(&EndIteration)> guard(cookie, EndIteration);
    536 
    537   std::vector<std::string> compatibility_info;
    538   ZipEntry info_entry;
    539   ZipString info_name;
    540   while (Next(cookie, &info_entry, &info_name) == 0) {
    541     std::string content(info_entry.uncompressed_length, '\0');
    542     int32_t ret = ExtractToMemory(zip_handle, &info_entry, reinterpret_cast<uint8_t*>(&content[0]),
    543                                   info_entry.uncompressed_length);
    544     if (ret != 0) {
    545       LOG(ERROR) << "Failed to read " << info_name.name << ": " << ErrorCodeString(ret);
    546       CloseArchive(zip_handle);
    547       return false;
    548     }
    549     compatibility_info.emplace_back(std::move(content));
    550   }
    551   CloseArchive(zip_handle);
    552 
    553   // VintfObjectRecovery::CheckCompatibility returns zero on success.
    554   std::string err;
    555   int result = android::vintf::VintfObjectRecovery::CheckCompatibility(compatibility_info, &err);
    556   if (result == 0) {
    557     return true;
    558   }
    559 
    560   LOG(ERROR) << "Failed to verify package compatibility (result " << result << "): " << err;
    561   return false;
    562 }
    563 
    564 static int really_install_package(const std::string& path, bool* wipe_cache, bool needs_mount,
    565                                   std::vector<std::string>* log_buffer, int retry_count,
    566                                   int* max_temperature) {
    567   ui->SetBackground(RecoveryUI::INSTALLING_UPDATE);
    568   ui->Print("Finding update package...\n");
    569   // Give verification half the progress bar...
    570   ui->SetProgressType(RecoveryUI::DETERMINATE);
    571   ui->ShowProgress(VERIFICATION_PROGRESS_FRACTION, VERIFICATION_PROGRESS_TIME);
    572   LOG(INFO) << "Update location: " << path;
    573 
    574   // Map the update package into memory.
    575   ui->Print("Opening update package...\n");
    576 
    577   if (needs_mount) {
    578     if (path[0] == '@') {
    579       ensure_path_mounted(path.substr(1).c_str());
    580     } else {
    581       ensure_path_mounted(path.c_str());
    582     }
    583   }
    584 
    585   MemMapping map;
    586   if (!map.MapFile(path)) {
    587     LOG(ERROR) << "failed to map file";
    588     log_buffer->push_back(android::base::StringPrintf("error: %d", kMapFileFailure));
    589     return INSTALL_CORRUPT;
    590   }
    591 
    592   // Verify package.
    593   if (!verify_package(map.addr, map.length)) {
    594     log_buffer->push_back(android::base::StringPrintf("error: %d", kZipVerificationFailure));
    595     return INSTALL_CORRUPT;
    596   }
    597 
    598   // Try to open the package.
    599   ZipArchiveHandle zip;
    600   int err = OpenArchiveFromMemory(map.addr, map.length, path.c_str(), &zip);
    601   if (err != 0) {
    602     LOG(ERROR) << "Can't open " << path << " : " << ErrorCodeString(err);
    603     log_buffer->push_back(android::base::StringPrintf("error: %d", kZipOpenFailure));
    604 
    605     CloseArchive(zip);
    606     return INSTALL_CORRUPT;
    607   }
    608 
    609   // Additionally verify the compatibility of the package.
    610   if (!verify_package_compatibility(zip)) {
    611     log_buffer->push_back(android::base::StringPrintf("error: %d", kPackageCompatibilityFailure));
    612     CloseArchive(zip);
    613     return INSTALL_CORRUPT;
    614   }
    615 
    616   // Verify and install the contents of the package.
    617   ui->Print("Installing update...\n");
    618   if (retry_count > 0) {
    619     ui->Print("Retry attempt: %d\n", retry_count);
    620   }
    621   ui->SetEnableReboot(false);
    622   int result = try_update_binary(path, zip, wipe_cache, log_buffer, retry_count, max_temperature);
    623   ui->SetEnableReboot(true);
    624   ui->Print("\n");
    625 
    626   CloseArchive(zip);
    627   return result;
    628 }
    629 
    630 int install_package(const std::string& path, bool* wipe_cache, const std::string& install_file,
    631                     bool needs_mount, int retry_count) {
    632   CHECK(!path.empty());
    633   CHECK(!install_file.empty());
    634   CHECK(wipe_cache != nullptr);
    635 
    636   modified_flash = true;
    637   auto start = std::chrono::system_clock::now();
    638 
    639   int start_temperature = GetMaxValueFromThermalZone();
    640   int max_temperature = start_temperature;
    641 
    642   int result;
    643   std::vector<std::string> log_buffer;
    644   if (setup_install_mounts() != 0) {
    645     LOG(ERROR) << "failed to set up expected mounts for install; aborting";
    646     result = INSTALL_ERROR;
    647   } else {
    648     result = really_install_package(path, wipe_cache, needs_mount, &log_buffer, retry_count,
    649                                     &max_temperature);
    650   }
    651 
    652   // Measure the time spent to apply OTA update in seconds.
    653   std::chrono::duration<double> duration = std::chrono::system_clock::now() - start;
    654   int time_total = static_cast<int>(duration.count());
    655 
    656   bool has_cache = volume_for_mount_point("/cache") != nullptr;
    657   // Skip logging the uncrypt_status on devices without /cache.
    658   if (has_cache) {
    659     static constexpr const char* UNCRYPT_STATUS = "/cache/recovery/uncrypt_status";
    660     if (ensure_path_mounted(UNCRYPT_STATUS) != 0) {
    661       LOG(WARNING) << "Can't mount " << UNCRYPT_STATUS;
    662     } else {
    663       std::string uncrypt_status;
    664       if (!android::base::ReadFileToString(UNCRYPT_STATUS, &uncrypt_status)) {
    665         PLOG(WARNING) << "failed to read uncrypt status";
    666       } else if (!android::base::StartsWith(uncrypt_status, "uncrypt_")) {
    667         LOG(WARNING) << "corrupted uncrypt_status: " << uncrypt_status;
    668       } else {
    669         log_buffer.push_back(android::base::Trim(uncrypt_status));
    670       }
    671     }
    672   }
    673 
    674   // The first two lines need to be the package name and install result.
    675   std::vector<std::string> log_header = {
    676     path,
    677     result == INSTALL_SUCCESS ? "1" : "0",
    678     "time_total: " + std::to_string(time_total),
    679     "retry: " + std::to_string(retry_count),
    680   };
    681 
    682   int end_temperature = GetMaxValueFromThermalZone();
    683   max_temperature = std::max(end_temperature, max_temperature);
    684   if (start_temperature > 0) {
    685     log_buffer.push_back("temperature_start: " + std::to_string(start_temperature));
    686   }
    687   if (end_temperature > 0) {
    688     log_buffer.push_back("temperature_end: " + std::to_string(end_temperature));
    689   }
    690   if (max_temperature > 0) {
    691     log_buffer.push_back("temperature_max: " + std::to_string(max_temperature));
    692   }
    693 
    694   std::string log_content =
    695       android::base::Join(log_header, "\n") + "\n" + android::base::Join(log_buffer, "\n") + "\n";
    696   if (!android::base::WriteStringToFile(log_content, install_file)) {
    697     PLOG(ERROR) << "failed to write " << install_file;
    698   }
    699 
    700   // Write a copy into last_log.
    701   LOG(INFO) << log_content;
    702 
    703   return result;
    704 }
    705 
    706 bool verify_package(const unsigned char* package_data, size_t package_size) {
    707   static constexpr const char* PUBLIC_KEYS_FILE = "/res/keys";
    708   std::vector<Certificate> loadedKeys;
    709   if (!load_keys(PUBLIC_KEYS_FILE, loadedKeys)) {
    710     LOG(ERROR) << "Failed to load keys";
    711     return false;
    712   }
    713   LOG(INFO) << loadedKeys.size() << " key(s) loaded from " << PUBLIC_KEYS_FILE;
    714 
    715   // Verify package.
    716   ui->Print("Verifying update package...\n");
    717   auto t0 = std::chrono::system_clock::now();
    718   int err = verify_file(package_data, package_size, loadedKeys,
    719                         std::bind(&RecoveryUI::SetProgress, ui, std::placeholders::_1));
    720   std::chrono::duration<double> duration = std::chrono::system_clock::now() - t0;
    721   ui->Print("Update package verification took %.1f s (result %d).\n", duration.count(), err);
    722   if (err != VERIFY_SUCCESS) {
    723     LOG(ERROR) << "Signature verification failed";
    724     LOG(ERROR) << "error: " << kZipVerificationFailure;
    725     return false;
    726   }
    727   return true;
    728 }
    729