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