Merge "Support fastboot variable 'variant'."
diff --git a/adb/fdevent.cpp b/adb/fdevent.cpp
index dee87bd..98a73eb 100644
--- a/adb/fdevent.cpp
+++ b/adb/fdevent.cpp
@@ -147,24 +147,34 @@
     return fde;
 }
 
-void fdevent_destroy(fdevent* fde) {
+unique_fd fdevent_release(fdevent* fde) {
     check_main_thread();
-    if (fde == nullptr) return;
+    if (!fde) {
+        return {};
+    }
+
     if (!(fde->state & FDE_CREATED)) {
         LOG(FATAL) << "destroying fde not created by fdevent_create(): " << dump_fde(fde);
     }
 
+    unique_fd result = std::move(fde->fd);
     if (fde->state & FDE_ACTIVE) {
-        g_poll_node_map.erase(fde->fd.get());
+        g_poll_node_map.erase(result.get());
+
         if (fde->state & FDE_PENDING) {
             g_pending_list.remove(fde);
         }
-        fde->fd.reset();
         fde->state = 0;
         fde->events = 0;
     }
 
     delete fde;
+    return result;
+}
+
+void fdevent_destroy(fdevent* fde) {
+    // Release, and then let unique_fd's destructor cleanup.
+    fdevent_release(fde);
 }
 
 static void fdevent_update(fdevent* fde, unsigned events) {
diff --git a/adb/fdevent.h b/adb/fdevent.h
index d501b86..df2339a 100644
--- a/adb/fdevent.h
+++ b/adb/fdevent.h
@@ -50,11 +50,12 @@
 */
 fdevent *fdevent_create(int fd, fd_func func, void *arg);
 
-/* Uninitialize and deallocate an fdevent object that was
-** created by fdevent_create()
-*/
+// Deallocate an fdevent object that was created by fdevent_create.
 void fdevent_destroy(fdevent *fde);
 
+// fdevent_destroy, except releasing the file descriptor previously owned by the fdevent.
+unique_fd fdevent_release(fdevent* fde);
+
 /* Change which events should cause notifications
 */
 void fdevent_set(fdevent *fde, unsigned events);
diff --git a/adb/test_device.py b/adb/test_device.py
old mode 100644
new mode 100755
index 9f45115..c3166ff
--- a/adb/test_device.py
+++ b/adb/test_device.py
@@ -751,7 +751,7 @@
                 shutil.rmtree(host_dir)
 
     def test_push_empty(self):
-        """Push a directory containing an empty directory to the device."""
+        """Push an empty directory to the device."""
         self.device.shell(['rm', '-rf', self.DEVICE_TEMP_DIR])
         self.device.shell(['mkdir', self.DEVICE_TEMP_DIR])
 
@@ -767,9 +767,10 @@
 
             self.device.push(empty_dir_path, self.DEVICE_TEMP_DIR)
 
-            test_empty_cmd = ['[', '-d',
-                              os.path.join(self.DEVICE_TEMP_DIR, 'empty')]
+            remote_path = os.path.join(self.DEVICE_TEMP_DIR, "empty")
+            test_empty_cmd = ["[", "-d", remote_path, "]"]
             rc, _, _ = self.device.shell_nocheck(test_empty_cmd)
+
             self.assertEqual(rc, 0)
             self.device.shell(['rm', '-rf', self.DEVICE_TEMP_DIR])
         finally:
diff --git a/base/Android.bp b/base/Android.bp
index 3d80d97..daa820a 100644
--- a/base/Android.bp
+++ b/base/Android.bp
@@ -56,6 +56,7 @@
         "test_utils.cpp",
     ],
 
+    cppflags: ["-Wexit-time-destructors"],
     shared_libs: ["liblog"],
     target: {
         android: {
@@ -68,13 +69,11 @@
             srcs: [
                 "errors_unix.cpp",
             ],
-            cppflags: ["-Wexit-time-destructors"],
         },
         darwin: {
             srcs: [
                 "errors_unix.cpp",
             ],
-            cppflags: ["-Wexit-time-destructors"],
         },
         linux_bionic: {
             enabled: true,
diff --git a/bootstat/bootstat.cpp b/bootstat/bootstat.cpp
index c17e00f..6700b6c 100644
--- a/bootstat/bootstat.cpp
+++ b/bootstat/bootstat.cpp
@@ -236,7 +236,7 @@
     {"reboot,rescueparty", 90},
     {"charge", 91},
     {"oem_tz_crash", 92},
-    {"uvlo", 93},
+    {"uvlo", 93},  // aliasReasons converts to reboot,undervoltage
     {"oem_ps_hold", 94},
     {"abnormal_reset", 95},
     {"oemerr_unknown", 96},
@@ -248,9 +248,9 @@
     {"watchdog_nonsec", 102},
     {"watchdog_apps_bark", 103},
     {"reboot_dmverity_corrupted", 104},
-    {"reboot_smpl", 105},
+    {"reboot_smpl", 105},  // aliasReasons converts to reboot,powerloss
     {"watchdog_sdi_apps_reset", 106},
-    {"smpl", 107},
+    {"smpl", 107},  // aliasReasons converts to reboot,powerloss
     {"oem_modem_failed_to_powerup", 108},
     {"reboot_normal", 109},
     {"oem_lpass_cfg", 110},
@@ -262,8 +262,8 @@
     {"oem_rpm_undef_error", 116},
     {"oem_crash_on_the_lk", 117},
     {"oem_rpm_reset", 118},
-    {"REUSE1", 119},  // Former dupe, can be re-used
-    {"REUSE2", 120},  // Former dupe, can be re-used
+    {"reboot,powerloss", 119},
+    {"reboot,undervoltage", 120},
     {"factory_cable", 121},
     {"oem_ar6320_failed_to_powerup", 122},
     {"watchdog_rpm_bite", 123},
@@ -840,6 +840,8 @@
         {"reboot,tool", "tool_by_pass_pwk"},
         {"!reboot,longkey", "reboot_longkey"},
         {"!reboot,longkey", "kpdpwr"},
+        {"!reboot,undervoltage", "uvlo"},
+        {"!reboot,powerloss", "smpl"},
         {"bootloader", ""},
     };
 
diff --git a/fs_mgr/fs_mgr_overlayfs.cpp b/fs_mgr/fs_mgr_overlayfs.cpp
index c0bef2c..7fe21b6 100644
--- a/fs_mgr/fs_mgr_overlayfs.cpp
+++ b/fs_mgr/fs_mgr_overlayfs.cpp
@@ -260,7 +260,7 @@
             errno = save_errno;
             return true;
         }
-        PERROR << "overlayfs open " << path;
+        PERROR << "opendir " << path;
         return false;
     }
     dirent* entry;
@@ -278,7 +278,7 @@
                 if (change) *change = true;
             } else {
                 ret = false;
-                PERROR << "overlayfs rmdir " << file;
+                PERROR << "rmdir " << file;
             }
             continue;
         }
@@ -286,7 +286,7 @@
             if (change) *change = true;
         } else {
             ret = false;
-            PERROR << "overlayfs rm " << file;
+            PERROR << "rm " << file;
         }
     }
     return ret;
@@ -301,14 +301,14 @@
 
     if (setfscreatecon(kOverlayfsFileContext)) {
         ret = false;
-        PERROR << "overlayfs setfscreatecon " << kOverlayfsFileContext;
+        PERROR << "setfscreatecon " << kOverlayfsFileContext;
     }
     auto save_errno = errno;
     if (!mkdir(fsrec_mount_point.c_str(), 0755)) {
         if (change) *change = true;
     } else if (errno != EEXIST) {
         ret = false;
-        PERROR << "overlayfs mkdir " << fsrec_mount_point;
+        PERROR << "mkdir " << fsrec_mount_point;
     } else {
         errno = save_errno;
     }
@@ -318,7 +318,7 @@
         if (change) *change = true;
     } else if (errno != EEXIST) {
         ret = false;
-        PERROR << "overlayfs mkdir " << fsrec_mount_point << kWorkName;
+        PERROR << "mkdir " << fsrec_mount_point << kWorkName;
     } else {
         errno = save_errno;
     }
@@ -327,7 +327,7 @@
     auto new_context = fs_mgr_get_context(mount_point);
     if (!new_context.empty() && setfscreatecon(new_context.c_str())) {
         ret = false;
-        PERROR << "overlayfs setfscreatecon " << new_context;
+        PERROR << "setfscreatecon " << new_context;
     }
     auto upper = fsrec_mount_point + kUpperName;
     save_errno = errno;
@@ -335,7 +335,7 @@
         if (change) *change = true;
     } else if (errno != EEXIST) {
         ret = false;
-        PERROR << "overlayfs mkdir " << upper;
+        PERROR << "mkdir " << upper;
     } else {
         errno = save_errno;
     }
@@ -426,7 +426,7 @@
     if (!fs_mgr_wants_overlayfs()) return ret;
     if (!fs_mgr_boot_completed()) {
         errno = EBUSY;
-        PERROR << "overlayfs setup";
+        PERROR << "setup";
         return ret;
     }
 
@@ -437,14 +437,14 @@
     if (fstab && mounts.empty()) return ret;
 
     if (setfscreatecon(kOverlayfsFileContext)) {
-        PERROR << "overlayfs setfscreatecon " << kOverlayfsFileContext;
+        PERROR << "setfscreatecon " << kOverlayfsFileContext;
     }
     auto overlay = kOverlayMountPoint + kOverlayTopDir;
     auto save_errno = errno;
     if (!mkdir(overlay.c_str(), 0755)) {
         if (change) *change = true;
     } else if (errno != EEXIST) {
-        PERROR << "overlayfs mkdir " << overlay;
+        PERROR << "mkdir " << overlay;
     } else {
         errno = save_errno;
     }
@@ -476,7 +476,7 @@
         if (change) *change = true;
     } else if (errno != ENOENT) {
         ret = false;
-        PERROR << "overlayfs mv " << oldpath << " " << newpath;
+        PERROR << "mv " << oldpath << " " << newpath;
     } else {
         errno = save_errno;
     }
@@ -486,7 +486,7 @@
         if (change) *change = true;
     } else if (errno != ENOENT) {
         ret = false;
-        PERROR << "overlayfs rmdir " << newpath;
+        PERROR << "rmdir " << newpath;
     } else {
         errno = save_errno;
     }
@@ -496,7 +496,7 @@
             if (change) *change = true;
         } else if ((errno != ENOENT) && (errno != ENOTEMPTY)) {
             ret = false;
-            PERROR << "overlayfs rmdir " << overlay;
+            PERROR << "rmdir " << overlay;
         } else {
             errno = save_errno;
         }
@@ -511,7 +511,7 @@
     // caller that there may still be more to do.
     if (!fs_mgr_boot_completed()) {
         errno = EBUSY;
-        PERROR << "overlayfs teardown";
+        PERROR << "teardown";
         ret = false;
     }
     return ret;
diff --git a/init/first_stage_mount.cpp b/init/first_stage_mount.cpp
index 1f4bec1..71a8e0d 100644
--- a/init/first_stage_mount.cpp
+++ b/init/first_stage_mount.cpp
@@ -120,14 +120,18 @@
     return is_android_dt_value_expected("vbmeta/compatible", "android,vbmeta");
 }
 
-static bool IsRecoveryMode() {
+static bool ForceNormalBoot() {
     static bool force_normal_boot = []() {
         std::string cmdline;
         android::base::ReadFileToString("/proc/cmdline", &cmdline);
         return cmdline.find("androidboot.force_normal_boot=1") != std::string::npos;
     }();
 
-    return !force_normal_boot && access("/system/bin/recovery", F_OK) == 0;
+    return force_normal_boot;
+}
+
+static bool IsRecoveryMode() {
+    return !ForceNormalBoot() && access("/system/bin/recovery", F_OK) == 0;
 }
 
 static inline bool IsDmLinearEnabled() {
@@ -368,11 +372,15 @@
     // this case, we mount system first then pivot to it.  From that point on,
     // we are effectively identical to a system-as-root device.
     auto system_partition =
-            std::find_if(mount_fstab_recs_.begin(), mount_fstab_recs_.end(), [](const auto& rec) {
-                return rec->mount_point == "/system"s ||
-                       rec->mount_point == "/system_recovery_mount"s;
-            });
+            std::find_if(mount_fstab_recs_.begin(), mount_fstab_recs_.end(),
+                         [](const auto& rec) { return rec->mount_point == "/system"s; });
+
     if (system_partition != mount_fstab_recs_.end()) {
+        if (ForceNormalBoot()) {
+            free((*system_partition)->mount_point);
+            (*system_partition)->mount_point = strdup("/system_recovery_mount");
+        }
+
         if (!MountPartition(*system_partition)) {
             return false;
         }
diff --git a/libmemunreachable/HeapWalker.h b/libmemunreachable/HeapWalker.h
index 5c7ec13..92a8325 100644
--- a/libmemunreachable/HeapWalker.h
+++ b/libmemunreachable/HeapWalker.h
@@ -52,7 +52,7 @@
         allocation_bytes_(0),
         roots_(allocator),
         root_vals_(allocator),
-        segv_handler_(allocator),
+        segv_handler_(),
         walking_ptr_(0) {
     valid_allocations_range_.end = 0;
     valid_allocations_range_.begin = ~valid_allocations_range_.end;
diff --git a/libmemunreachable/LeakFolding.cpp b/libmemunreachable/LeakFolding.cpp
index 69f320c..074dc48 100644
--- a/libmemunreachable/LeakFolding.cpp
+++ b/libmemunreachable/LeakFolding.cpp
@@ -57,7 +57,7 @@
 }
 
 void LeakFolding::AccumulateLeaks(SCCInfo* dominator) {
-  std::function<void(SCCInfo*)> walk(std::allocator_arg, allocator_, [&](SCCInfo* scc) {
+  std::function<void(SCCInfo*)> walk([&](SCCInfo* scc) {
     if (scc->accumulator != dominator) {
       scc->accumulator = dominator;
       dominator->cuumulative_size += scc->size;
diff --git a/libmemunreachable/ScopedSignalHandler.h b/libmemunreachable/ScopedSignalHandler.h
index ff53fad..9e08a8e 100644
--- a/libmemunreachable/ScopedSignalHandler.h
+++ b/libmemunreachable/ScopedSignalHandler.h
@@ -32,15 +32,14 @@
  public:
   using Fn = std::function<void(ScopedSignalHandler&, int, siginfo_t*, void*)>;
 
-  explicit ScopedSignalHandler(Allocator<Fn> allocator) : allocator_(allocator), signal_(-1) {}
+  explicit ScopedSignalHandler() : signal_(-1) {}
   ~ScopedSignalHandler() { reset(); }
 
   template <class F>
   void install(int signal, F&& f) {
     if (signal_ != -1) MEM_LOG_ALWAYS_FATAL("ScopedSignalHandler already installed");
 
-    handler_ = SignalFn(std::allocator_arg, allocator_,
-                        [=](int signal, siginfo_t* si, void* uctx) { f(*this, signal, si, uctx); });
+    handler_ = SignalFn([=](int signal, siginfo_t* si, void* uctx) { f(*this, signal, si, uctx); });
 
     struct sigaction act {};
     act.sa_sigaction = [](int signal, siginfo_t* si, void* uctx) { handler_(signal, si, uctx); };
@@ -68,7 +67,6 @@
  private:
   using SignalFn = std::function<void(int, siginfo_t*, void*)>;
   DISALLOW_COPY_AND_ASSIGN(ScopedSignalHandler);
-  Allocator<Fn> allocator_;
   int signal_;
   struct sigaction old_act_;
   // TODO(ccross): to support multiple ScopedSignalHandlers handler_ would need
diff --git a/mkbootimg/Android.bp b/mkbootimg/Android.bp
index 576a677..c3cf746 100644
--- a/mkbootimg/Android.bp
+++ b/mkbootimg/Android.bp
@@ -31,3 +31,34 @@
     header_libs: ["libmkbootimg_abi_headers"],
     export_header_lib_headers: ["libmkbootimg_abi_headers"],
 }
+
+python_defaults {
+    name: "mkbootimg_defaults",
+
+    version: {
+        py2: {
+            enabled: true,
+            embedded_launcher: true,
+        },
+        py3: {
+            enabled: false,
+            embedded_launcher: false,
+        },
+    },
+}
+
+python_binary_host {
+    name: "mkbootimg",
+    defaults: ["mkbootimg_defaults"],
+    srcs: [
+        "mkbootimg.py",
+    ],
+}
+
+python_binary_host {
+    name: "unpack_bootimg",
+    defaults: ["mkbootimg_defaults"],
+    srcs: [
+        "unpack_bootimg.py",
+    ],
+}
diff --git a/mkbootimg/Android.mk b/mkbootimg/Android.mk
deleted file mode 100644
index 92e1e27..0000000
--- a/mkbootimg/Android.mk
+++ /dev/null
@@ -1,20 +0,0 @@
-
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES := mkbootimg
-LOCAL_MODULE_CLASS := EXECUTABLES
-LOCAL_IS_HOST_MODULE := true
-
-LOCAL_MODULE := mkbootimg
-
-include $(BUILD_PREBUILT)
-
-include $(CLEAR_VARS)
-LOCAL_SRC_FILES := unpack_bootimg
-LOCAL_MODULE_CLASS := EXECUTABLES
-LOCAL_IS_HOST_MODULE := true
-
-LOCAL_MODULE := unpack_bootimg
-
-include $(BUILD_PREBUILT)
diff --git a/mkbootimg/mkbootimg b/mkbootimg/mkbootimg.py
old mode 100755
new mode 100644
similarity index 100%
rename from mkbootimg/mkbootimg
rename to mkbootimg/mkbootimg.py
diff --git a/mkbootimg/unpack_bootimg b/mkbootimg/unpack_bootimg.py
old mode 100755
new mode 100644
similarity index 100%
rename from mkbootimg/unpack_bootimg
rename to mkbootimg/unpack_bootimg.py
diff --git a/trusty/keymaster/3.0/TrustyKeymaster3Device.cpp b/trusty/keymaster/3.0/TrustyKeymaster3Device.cpp
index 8e3b3b1..0849ee9 100644
--- a/trusty/keymaster/3.0/TrustyKeymaster3Device.cpp
+++ b/trusty/keymaster/3.0/TrustyKeymaster3Device.cpp
@@ -21,6 +21,7 @@
 #include <cutils/log.h>
 #include <keymaster/android_keymaster_messages.h>
 #include <trusty_keymaster/TrustyKeymaster3Device.h>
+#include <trusty_keymaster/ipc/trusty_keymaster_ipc.h>
 
 using ::keymaster::AbortOperationRequest;
 using ::keymaster::AbortOperationResponse;
@@ -393,20 +394,32 @@
                                             const hidl_vec<KeyParameter>& inParams,
                                             const hidl_vec<uint8_t>& input, update_cb _hidl_cb) {
     UpdateOperationRequest request;
-    request.op_handle = operationHandle;
-    request.input.Reinitialize(input.data(), input.size());
-    request.additional_params.Reinitialize(KmParamSet(inParams));
-
     UpdateOperationResponse response;
-    impl_->UpdateOperation(request, &response);
-
-    uint32_t resultConsumed = 0;
     hidl_vec<KeyParameter> resultParams;
     hidl_vec<uint8_t> resultBlob;
-    if (response.error == KM_ERROR_OK) {
-        resultConsumed = response.input_consumed;
-        resultParams = kmParamSet2Hidl(response.output_params);
-        resultBlob = kmBuffer2hidlVec(response.output);
+    uint32_t resultConsumed = 0;
+
+    request.op_handle = operationHandle;
+    request.additional_params.Reinitialize(KmParamSet(inParams));
+
+    size_t inp_size = input.size();
+    size_t ser_size = request.SerializedSize();
+
+    if (ser_size > TRUSTY_KEYMASTER_SEND_BUF_SIZE) {
+        response.error = KM_ERROR_INVALID_INPUT_LENGTH;
+    } else {
+        if (ser_size + inp_size > TRUSTY_KEYMASTER_SEND_BUF_SIZE) {
+            inp_size = TRUSTY_KEYMASTER_SEND_BUF_SIZE - ser_size;
+        }
+        request.input.Reinitialize(input.data(), inp_size);
+
+        impl_->UpdateOperation(request, &response);
+
+        if (response.error == KM_ERROR_OK) {
+            resultConsumed = response.input_consumed;
+            resultParams = kmParamSet2Hidl(response.output_params);
+            resultBlob = kmBuffer2hidlVec(response.output);
+        }
     }
     _hidl_cb(legacy_enum_conversion(response.error), resultConsumed, resultParams, resultBlob);
     return Void();