Merge "init: replace Result<> with expected<>"
diff --git a/bootstat/bootstat.cpp b/bootstat/bootstat.cpp
index da9d44c..b26f83b 100644
--- a/bootstat/bootstat.cpp
+++ b/bootstat/bootstat.cpp
@@ -1092,17 +1092,8 @@
 void LogBootInfoToStatsd(std::chrono::milliseconds end_time,
                          std::chrono::milliseconds total_duration, int32_t bootloader_duration_ms,
                          double time_since_last_boot_sec) {
-  const auto reason = android::base::GetProperty(bootloader_reboot_reason_property, "");
-
-  if (reason.empty()) {
-    android::util::stats_write(android::util::BOOT_SEQUENCE_REPORTED, "<EMPTY>", "<EMPTY>",
-                               end_time.count(), total_duration.count(),
-                               (int64_t)bootloader_duration_ms,
-                               (int64_t)time_since_last_boot_sec * 1000);
-    return;
-  }
-
-  const auto system_reason = android::base::GetProperty(system_reboot_reason_property, "");
+  const auto reason = android::base::GetProperty(bootloader_reboot_reason_property, "<EMPTY>");
+  const auto system_reason = android::base::GetProperty(system_reboot_reason_property, "<EMPTY>");
   android::util::stats_write(android::util::BOOT_SEQUENCE_REPORTED, reason.c_str(),
                              system_reason.c_str(), end_time.count(), total_duration.count(),
                              (int64_t)bootloader_duration_ms,
diff --git a/fs_mgr/tests/adb-remount-test.sh b/fs_mgr/tests/adb-remount-test.sh
index c22176b..04422f9 100755
--- a/fs_mgr/tests/adb-remount-test.sh
+++ b/fs_mgr/tests/adb-remount-test.sh
@@ -219,13 +219,31 @@
   echo ${hours}:`expr ${minutes} / 10``expr ${minutes} % 10`:`expr ${seconds} / 10``expr ${seconds} % 10`
 }
 
+[ "USAGE: USB_DEVICE=\`usb_devnum [--next]\`
+
+USB_DEVICE contains cache. Update if system changes.
+
+Returns: the devnum for the USB_SERIAL device" ]
+usb_devnum() {
+  if [ -n "${USB_SERIAL}" ]; then
+    local usb_device=`cat ${USB_SERIAL%/serial}/devnum 2>/dev/null | tr -d ' \t\r\n'`
+    if [ -n "${usb_device}" ]; then
+      USB_DEVICE=dev${usb_device}
+    elif [ -n "${USB_DEVICE}" -a "${1}" ]; then
+      USB_DEVICE=dev`expr ${USB_DEVICE#dev} + 1`
+    fi
+    echo "${USB_DEVICE}"
+  fi
+}
+
 [ "USAGE: adb_wait [timeout]
 
 Returns: waits until the device has returned for adb or optional timeout" ]
 adb_wait() {
   local ret
   if [ -n "${1}" ]; then
-    echo -n ". . . waiting `format_duration ${1}`" ${ANDROID_SERIAL} ${USB_ADDRESS} "${CR}"
+    USB_DEVICE=`usb_devnum --next`
+    echo -n ". . . waiting `format_duration ${1}`" ${ANDROID_SERIAL} ${USB_ADDRESS} ${USB_DEVICE} "${CR}"
     timeout --preserve-status --signal=KILL ${1} adb wait-for-device 2>/dev/null
     ret=${?}
     echo -n "                                                                             ${CR}"
@@ -233,6 +251,7 @@
     adb wait-for-device
     ret=${?}
   fi
+  USB_DEVICE=`usb_devnum`
   if [ 0 = ${ret} -a -n "${ACTIVE_SLOT}" ]; then
     local active_slot=`get_active_slot`
     if [ X"${ACTIVE_SLOT}" != X"${active_slot}" ]; then
@@ -242,12 +261,15 @@
   return ${ret}
 }
 
-[ "USAGE: usb_status > stdout
+[ "USAGE: usb_status > stdout 2> stderr
 
-If adb_wait failed, check if device is in adb, recovery or fastboot mode
-and report status string.
+Assumes referenced right after adb_wait or fastboot_wait failued.
+If wait failed, check if device is in adb, recovery or fastboot mode
+and report status strings like  \"(USB stack borken?)\",
+\"(In fastboot mode)\", \"(In recovery mode)\" or \"(in adb mode)\".
+Additional diagnostics may be provided to the stderr output.
 
-Returns: \"(USB stack borken?)\", \"(In fastboot mode)\" or \"(in adb mode)\"" ]
+Returns: USB status string" ]
 usb_status() {
   if inFastboot; then
     echo "(In fastboot mode)"
@@ -256,7 +278,20 @@
   elif inAdb; then
     echo "(In adb mode)"
   else
-    echo "(USB stack borken?)"
+    echo "(USB stack borken for ${USB_ADDRESS})"
+    USB_DEVICE=`usb_devnum`
+    if [ -n "${USB_DEVICE}" ]; then
+      echo "# lsusb -v -s ${USB_DEVICE#dev}"
+      local D=`lsusb -v -s ${USB_DEVICE#dev} 2>&1`
+      if [ -n "${D}" ]; then
+        echo "${D}"
+      else
+        lsusb -v
+      fi
+    else
+      echo "# lsusb -v (expected device missing)"
+      lsusb -v
+    fi >&2
   fi
 }
 
@@ -268,7 +303,8 @@
   # fastboot has no wait-for-device, but it does an automatic
   # wait and requires (even a nonsensical) command to do so.
   if [ -n "${1}" ]; then
-    echo -n ". . . waiting `format_duration ${1}`" ${ANDROID_SERIAL} ${USB_ADDRESS} "${CR}"
+    USB_DEVICE=`usb_devnum --next`
+    echo -n ". . . waiting `format_duration ${1}`" ${ANDROID_SERIAL} ${USB_ADDRESS} ${USB_DEVICE} "${CR}"
     timeout --preserve-status --signal=KILL ${1} fastboot wait-for-device >/dev/null 2>/dev/null
     ret=${?}
     echo -n "                                                                             ${CR}"
@@ -278,11 +314,12 @@
   fi ||
     inFastboot
   ret=${?}
+  USB_DEVICE=`usb_devnum`
   if [ 0 = ${ret} -a -n "${ACTIVE_SLOT}" ]; then
     local active_slot=`get_active_slot`
     if [ X"${ACTIVE_SLOT}" != X"${active_slot}" ]; then
-      echo "${ORANGE}[  WARNING ]${NORMAL} Active slot changed from ${ACTIVE_SLOT} to ${active_slot}" >&2
-    fi
+      echo "${ORANGE}[  WARNING ]${NORMAL} Active slot changed from ${ACTIVE_SLOT} to ${active_slot}"
+    fi >&2
   fi
   return ${ret}
 }
@@ -293,7 +330,8 @@
 recovery_wait() {
   local ret
   if [ -n "${1}" ]; then
-    echo -n ". . . waiting `format_duration ${1}`" ${ANDROID_SERIAL} ${USB_ADDRESS} "${CR}"
+    USB_DEVICE=`usb_devnum --next`
+    echo -n ". . . waiting `format_duration ${1}`" ${ANDROID_SERIAL} ${USB_ADDRESS} ${USB_DEVICE} "${CR}"
     timeout --preserve-status --signal=KILL ${1} adb wait-for-recovery 2>/dev/null
     ret=${?}
     echo -n "                                                                             ${CR}"
@@ -301,11 +339,12 @@
     adb wait-for-recovery
     ret=${?}
   fi
+  USB_DEVICE=`usb_devnum`
   if [ 0 = ${ret} -a -n "${ACTIVE_SLOT}" ]; then
     local active_slot=`get_active_slot`
     if [ X"${ACTIVE_SLOT}" != X"${active_slot}" ]; then
-      echo "${ORANGE}[  WARNING ]${NORMAL} Active slot changed from ${ACTIVE_SLOT} to ${active_slot}" >&2
-    fi
+      echo "${ORANGE}[  WARNING ]${NORMAL} Active slot changed from ${ACTIVE_SLOT} to ${active_slot}"
+    fi >&2
   fi
   return ${ret}
 }
@@ -370,10 +409,10 @@
     O="${1}: <empty>"
   fi
   if [ -n "${2}" -a "${1}: ${2}" != "${O}" ]; then
-    echo "${2} != ${O}" >&2
+    echo "${2} != ${O}"
     false
     return
-  fi
+  fi >&2
   echo ${O} >&2
 }
 
@@ -430,16 +469,16 @@
 Returns: exit failure, report status" ]
 die() {
   if [ X"-d" = X"${1}" ]; then
-    adb_logcat -b all -v nsec -d >&2
+    adb_logcat -b all -v nsec -d
     shift
   elif [ X"-t" = X"${1}" ]; then
     if [ -n "${2}" ]; then
-      adb_logcat -b all -v nsec -t ${2} >&2
+      adb_logcat -b all -v nsec -t ${2}
     else
-      adb_logcat -b all -v nsec -d >&2
+      adb_logcat -b all -v nsec -d
     fi
     shift 2
-  fi
+  fi >&2
   echo "${RED}[  FAILED  ]${NORMAL} ${@}" >&2
   cleanup
   restore
@@ -464,39 +503,39 @@
   if ! ( echo X"${rval}" | grep '^X'"${lval}"'$' >/dev/null 2>/dev/null ); then
     if [ `echo ${lval}${rval}${*} | wc -c` -gt 50 -o "${rval}" != "${rval%
 *}" ]; then
-      echo "${prefix} expected \"${lval}\"" >&2
+      echo "${prefix} expected \"${lval}\""
       echo "${prefix} got \"${rval}\"" |
         sed ': again
              N
              s/\(\n\)\([^ ]\)/\1             \2/
-             t again' >&2
+             t again'
       if [ -n "${*}" ] ; then
-        echo "${prefix} ${*}" >&2
+        echo "${prefix} ${*}"
       fi
     else
-      echo "${prefix} expected \"${lval}\" got \"${rval}\" ${*}" >&2
-    fi
+      echo "${prefix} expected \"${lval}\" got \"${rval}\" ${*}"
+    fi >&2
     return ${error}
   fi
   if [ -n "${*}" ] ; then
     prefix="${GREEN}[     INFO ]${NORMAL}"
     if [ X"${lval}" != X"${rval}" ]; then  # we were supplied a regex?
       if [ `echo ${lval}${rval}${*} | wc -c` -gt 60 -o "${rval}" != "${rval% *}" ]; then
-        echo "${prefix} ok \"${lval}\"" >&2
+        echo "${prefix} ok \"${lval}\""
         echo "       = \"${rval}\"" |
           sed ': again
                N
                s/\(\n\)\([^ ]\)/\1          \2/
-               t again' >&2
+               t again'
         if [ -n "${*}" ] ; then
-          echo "${prefix} ${*}" >&2
+          echo "${prefix} ${*}"
         fi
       else
-        echo "${prefix} ok \"${lval}\" = \"${rval}\" ${*}" >&2
+        echo "${prefix} ok \"${lval}\" = \"${rval}\" ${*}"
       fi
     else
-      echo "${prefix} ok \"${lval}\" ${*}" >&2
-    fi
+      echo "${prefix} ok \"${lval}\" ${*}"
+    fi >&2
   fi
   return 0
 }
@@ -631,7 +670,8 @@
   USB_ADDRESS=usb${USB_ADDRESS##*/}
 fi
 [ -z "${ANDROID_SERIAL}${USB_ADDRESS}" ] ||
-  echo "${BLUE}[     INFO ]${NORMAL}" ${ANDROID_SERIAL} ${USB_ADDRESS} >&2
+  USB_DEVICE=`usb_devnum`
+  echo "${BLUE}[     INFO ]${NORMAL}" ${ANDROID_SERIAL} ${USB_ADDRESS} ${USB_DEVICE} >&2
 BUILD_DESCRIPTION=`get_property ro.build.description`
 [ -z "${BUILD_DESCRIPTION}" ] ||
   echo "${BLUE}[     INFO ]${NORMAL} ${BUILD_DESCRIPTION}" >&2
@@ -961,8 +1001,16 @@
 
 echo "${GREEN}[ RUN      ]${NORMAL} reboot to confirm content persistent" >&2
 
+fixup_from_recovery() {
+  inRecovery || return 1
+  echo "${ORANGE}[    ERROR ]${NORMAL} Device in recovery" >&2
+  adb reboot
+  adb_wait 2m
+}
+
 adb_reboot &&
   adb_wait 2m ||
+  fixup_from_recovery ||
   die "reboot after override content added failed `usb_status`"
 
 if ${overlayfs_needed}; then
@@ -1070,6 +1118,7 @@
     die "can not reboot out of fastboot"
   echo "${ORANGE}[  WARNING ]${NORMAL} adb after fastboot"
   adb_wait 2m ||
+    fixup_from_recovery ||
     die "did not reboot after flash `usb_status`"
   if ${overlayfs_needed}; then
     adb_root &&
@@ -1191,9 +1240,25 @@
 
 echo "${GREEN}[ RUN      ]${NORMAL} test raw remount commands" >&2
 
+fixup_from_fastboot() {
+  inFastboot || return 1
+  if [ -n "${ACTIVE_SLOT}" ]; then
+    local active_slot=`get_active_slot`
+    if [ X"${ACTIVE_SLOT}" != X"${active_slot}" ]; then
+      echo "${ORANGE}[    ERROR ]${NORMAL} Active slot changed from ${ACTIVE_SLOT} to ${active_slot}"
+    else
+      echo "${ORANGE}[    ERROR ]${NORMAL} Active slot to be set to ${ACTIVE_SLOT}"
+    fi >&2
+    fastboot --set-active=${ACTIVE_SLOT}
+  fi
+  fastboot reboot
+  adb_wait 2m
+}
+
 # Prerequisite is a prepped device from above.
 adb_reboot &&
   adb_wait 2m ||
+  fixup_from_fastboot ||
   die "lost device after reboot to ro state `usb_status`"
 adb_sh grep " /vendor .* rw," /proc/mounts >/dev/null </dev/null &&
   die "/vendor is not read-only"
@@ -1206,7 +1271,8 @@
 # Prerequisite is a prepped device from above.
 adb_reboot &&
   adb_wait 2m ||
-  die "lost device after reboot to ro state (USB stack broken?)"
+  fixup_from_fastboot ||
+  die "lost device after reboot to ro state `usb_status`"
 adb_sh grep " /vendor .* rw," /proc/mounts >/dev/null </dev/null &&
   die "/vendor is not read-only"
 adb_su remount vendor </dev/null ||
@@ -1226,7 +1292,8 @@
 done
 adb_reboot &&
   adb_wait 2m ||
-  die "lost device after reboot after wipe (USB stack broken?)"
+  fixup_from_fastboot ||
+  die "lost device after reboot after wipe `usb_status`"
 adb_sh grep " /vendor .* rw," /proc/mounts >/dev/null </dev/null &&
   die "/vendor is not read-only"
 adb_su remount vendor </dev/null ||
diff --git a/init/README.md b/init/README.md
index 806bfa7..6868378 100644
--- a/init/README.md
+++ b/init/README.md
@@ -35,24 +35,14 @@
 at the beginning of its execution.  It is responsible for the initial
 set up of the system.
 
-Devices that mount /system, /vendor through the first stage mount mechanism
-load all of the files contained within the
+Init loads all of the files contained within the
 /{system,vendor,odm}/etc/init/ directories immediately after loading
 the primary /init.rc.  This is explained in more details in the
 Imports section of this file.
 
-Legacy devices without the first stage mount mechanism do the following:
-1. /init.rc imports /init.${ro.hardware}.rc which is the primary
-   vendor supplied .rc file.
-2. During the mount\_all command, the init executable loads all of the
-   files contained within the /{system,vendor,odm}/etc/init/ directories.
-   These directories are intended for all Actions and Services used after
-   file system mounting.
-
-One may specify paths in the mount\_all command line to have it import
-.rc files at the specified paths instead of the default ones listed above.
-This is primarily for supporting factory mode and other non-standard boot
-modes.  The three default paths should be used for the normal boot process.
+Legacy devices without the first stage mount mechanism previously were
+able to import init scripts during mount_all, however that is deprecated
+and not allowed for devices launching after Q.
 
 The intention of these directories is:
 
@@ -88,14 +78,6 @@
 conflict resolution when multiple services are added to the system, as
 each one will go into a separate file.
 
-There are two options "early" and "late" in mount\_all command
-which can be set after optional paths. With "--early" set, the
-init executable will skip mounting entries with "latemount" flag
-and triggering fs encryption state event. With "--late" set,
-init executable will only mount entries with "latemount" flag but skip
-importing rc files. By default, no option is set, and mount\_all will
-process all entries in the given fstab.
-
 Actions
 -------
 Actions are named sequences of commands.  Actions have a trigger which
@@ -514,10 +496,12 @@
   will be updated if the directory exists already.
 
 `mount_all <fstab> [ <path> ]\* [--<option>]`
-> Calls fs\_mgr\_mount\_all on the given fs\_mgr-format fstab and imports .rc files
-  at the specified paths (e.g., on the partitions just mounted) with optional
+> Calls fs\_mgr\_mount\_all on the given fs\_mgr-format fstab with optional
   options "early" and "late".
-  Refer to the section of "Init .rc Files" for detail.
+  With "--early" set, the init executable will skip mounting entries with
+  "latemount" flag and triggering fs encryption state event. With "--late" set,
+  init executable will only mount entries with "latemount" flag. By default,
+  no option is set, and mount\_all will process all entries in the given fstab.
 
 `mount <type> <device> <dir> [ <flag>\* ] [<options>]`
 > Attempt to mount the named device at the directory _dir_
@@ -638,8 +622,9 @@
       `ro.boot.init_rc` during initial boot.
    2. When it imports /{system,vendor,odm}/etc/init/ for first stage mount
       devices immediately after importing /init.rc.
-   3. When it imports /{system,vendor,odm}/etc/init/ or .rc files at specified
-      paths during mount_all.
+   3. (Deprecated) When it imports /{system,vendor,odm}/etc/init/ or .rc files
+      at specified paths during mount_all, not allowed for devices launching
+      after Q.
 
 The order that files are imported is a bit complex for legacy reasons
 and to keep backwards compatibility.  It is not strictly guaranteed.
diff --git a/init/builtins.cpp b/init/builtins.cpp
index 6ce7736..840f2d4 100644
--- a/init/builtins.cpp
+++ b/init/builtins.cpp
@@ -16,6 +16,7 @@
 
 #include "builtins.h"
 
+#include <android/api-level.h>
 #include <dirent.h>
 #include <errno.h>
 #include <fcntl.h>
@@ -62,6 +63,7 @@
 
 #include "action_manager.h"
 #include "bootchart.h"
+#include "host_init_stubs.h"
 #include "init.h"
 #include "mount_namespace.h"
 #include "parser.h"
@@ -588,7 +590,7 @@
     auto mount_fstab_return_code = fs_mgr_mount_all(&fstab, mount_mode);
     property_set(prop_name, std::to_string(t.duration().count()));
 
-    if (import_rc) {
+    if (import_rc && SelinuxGetVendorAndroidVersion() <= __ANDROID_API_Q__) {
         /* Paths of .rc files are specified at the 2nd argument and beyond */
         import_late(args.args, 2, path_arg_end);
     }
diff --git a/init/firmware_handler.cpp b/init/firmware_handler.cpp
index 740e82c..c067f6f 100644
--- a/init/firmware_handler.cpp
+++ b/init/firmware_handler.cpp
@@ -80,15 +80,26 @@
         return;
     }
 
+    std::vector<std::string> attempted_paths_and_errors;
+
 try_loading_again:
+    attempted_paths_and_errors.clear();
     for (const auto& firmware_directory : firmware_directories_) {
         std::string file = firmware_directory + uevent.firmware;
         unique_fd fw_fd(open(file.c_str(), O_RDONLY | O_CLOEXEC));
-        struct stat sb;
-        if (fw_fd != -1 && fstat(fw_fd, &sb) != -1) {
-            LoadFirmware(uevent, root, fw_fd, sb.st_size, loading_fd, data_fd);
-            return;
+        if (fw_fd == -1) {
+            attempted_paths_and_errors.emplace_back("firmware: attempted " + file +
+                                                    ", open failed: " + strerror(errno));
+            continue;
         }
+        struct stat sb;
+        if (fstat(fw_fd, &sb) == -1) {
+            attempted_paths_and_errors.emplace_back("firmware: attempted " + file +
+                                                    ", fstat failed: " + strerror(errno));
+            continue;
+        }
+        LoadFirmware(uevent, root, fw_fd, sb.st_size, loading_fd, data_fd);
+        return;
     }
 
     if (booting) {
@@ -100,6 +111,9 @@
     }
 
     LOG(ERROR) << "firmware: could not find firmware for " << uevent.firmware;
+    for (const auto& message : attempted_paths_and_errors) {
+        LOG(ERROR) << message;
+    }
 
     // Write "-1" as our response to the kernel's firmware request, since we have nothing for it.
     write(loading_fd, "-1", 2);
diff --git a/init/init.cpp b/init/init.cpp
index 1f3c2fc..0615d44 100644
--- a/init/init.cpp
+++ b/init/init.cpp
@@ -280,13 +280,13 @@
     return control_message_functions;
 }
 
-void HandleControlMessage(const std::string& msg, const std::string& name, pid_t pid) {
+bool HandleControlMessage(const std::string& msg, const std::string& name, pid_t pid) {
     const auto& map = get_control_message_map();
     const auto it = map.find(msg);
 
     if (it == map.end()) {
         LOG(ERROR) << "Unknown control msg '" << msg << "'";
-        return;
+        return false;
     }
 
     std::string cmdline_path = StringPrintf("proc/%d/cmdline", pid);
@@ -315,17 +315,19 @@
         default:
             LOG(ERROR) << "Invalid function target from static map key '" << msg << "': "
                        << static_cast<std::underlying_type<ControlTarget>::type>(function.target);
-            return;
+            return false;
     }
 
     if (svc == nullptr) {
         LOG(ERROR) << "Could not find '" << name << "' for ctl." << msg;
-        return;
+        return false;
     }
 
     if (auto result = function.action(svc); !result) {
         LOG(ERROR) << "Could not ctl." << msg << " for '" << name << "': " << result.error();
+        return false;
     }
+    return true;
 }
 
 static Result<Success> wait_for_coldboot_done_action(const BuiltinArguments& args) {
diff --git a/init/init.h b/init/init.h
index a76da20..90ead0e 100644
--- a/init/init.h
+++ b/init/init.h
@@ -40,7 +40,7 @@
 Parser CreateParser(ActionManager& action_manager, ServiceList& service_list);
 Parser CreateServiceOnlyParser(ServiceList& service_list);
 
-void HandleControlMessage(const std::string& msg, const std::string& arg, pid_t pid);
+bool HandleControlMessage(const std::string& msg, const std::string& arg, pid_t pid);
 
 void property_changed(const std::string& name, const std::string& value);
 
diff --git a/init/property_service.cpp b/init/property_service.cpp
index a1e9551..ab5dd61 100644
--- a/init/property_service.cpp
+++ b/init/property_service.cpp
@@ -473,8 +473,9 @@
     }
 
     if (StartsWith(name, "ctl.")) {
-        HandleControlMessage(name.c_str() + 4, value, cr.pid);
-        return PROP_SUCCESS;
+        return HandleControlMessage(name.c_str() + 4, value, cr.pid)
+                       ? PROP_SUCCESS
+                       : PROP_ERROR_HANDLE_CONTROL_MESSAGE;
     }
 
     // sys.powerctl is a special property that is used to make the device reboot.  We want to log
@@ -885,8 +886,12 @@
     load_properties_from_file("/system/build.prop", nullptr, &properties);
     load_properties_from_file("/vendor/default.prop", nullptr, &properties);
     load_properties_from_file("/vendor/build.prop", nullptr, &properties);
-    load_properties_from_file("/odm/default.prop", nullptr, &properties);
-    load_properties_from_file("/odm/build.prop", nullptr, &properties);
+    if (SelinuxGetVendorAndroidVersion() >= __ANDROID_API_Q__) {
+        load_properties_from_file("/odm/etc/build.prop", nullptr, &properties);
+    } else {
+        load_properties_from_file("/odm/default.prop", nullptr, &properties);
+        load_properties_from_file("/odm/build.prop", nullptr, &properties);
+    }
     load_properties_from_file("/product/build.prop", nullptr, &properties);
     load_properties_from_file("/product_services/build.prop", nullptr, &properties);
     load_properties_from_file("/factory/factory.prop", "ro.*", &properties);
diff --git a/libcutils/fs_config.cpp b/libcutils/fs_config.cpp
index 494a06f..6606030 100644
--- a/libcutils/fs_config.cpp
+++ b/libcutils/fs_config.cpp
@@ -158,8 +158,9 @@
     { 00750, AID_ROOT,      AID_SHELL,     0, "data/nativetest64/*" },
     { 00600, AID_ROOT,      AID_ROOT,      0, "default.prop" }, // legacy
     { 00600, AID_ROOT,      AID_ROOT,      0, "system/etc/prop.default" },
-    { 00600, AID_ROOT,      AID_ROOT,      0, "odm/build.prop" },
-    { 00600, AID_ROOT,      AID_ROOT,      0, "odm/default.prop" },
+    { 00600, AID_ROOT,      AID_ROOT,      0, "odm/build.prop" }, // legacy; only for P release
+    { 00600, AID_ROOT,      AID_ROOT,      0, "odm/default.prop" }, // legacy; only for P release
+    { 00600, AID_ROOT,      AID_ROOT,      0, "odm/etc/build.prop" },
     { 00444, AID_ROOT,      AID_ROOT,      0, odm_conf_dir + 1 },
     { 00444, AID_ROOT,      AID_ROOT,      0, odm_conf_file + 1 },
     { 00444, AID_ROOT,      AID_ROOT,      0, oem_conf_dir + 1 },
diff --git a/libmemunreachable/tests/MemUnreachable_test.cpp b/libmemunreachable/tests/MemUnreachable_test.cpp
index e464872..9cb1623 100644
--- a/libmemunreachable/tests/MemUnreachable_test.cpp
+++ b/libmemunreachable/tests/MemUnreachable_test.cpp
@@ -47,7 +47,8 @@
 
 // Trick the compiler into thinking a value on the stack is still referenced.
 static void Ref(void** ptr) {
-  write(0, ptr, 0);
+  void** volatile storage;
+  storage = ptr;
 }
 
 class MemunreachableTest : public ::testing::Test {
diff --git a/libziparchive/include/ziparchive/zip_archive.h b/libziparchive/include/ziparchive/zip_archive.h
index 46c982d..a56a4a2 100644
--- a/libziparchive/include/ziparchive/zip_archive.h
+++ b/libziparchive/include/ziparchive/zip_archive.h
@@ -25,6 +25,7 @@
 #include <sys/cdefs.h>
 #include <sys/types.h>
 
+#include <string>
 #include <string_view>
 
 #include "android-base/off64_t.h"
@@ -35,6 +36,7 @@
   kCompressDeflated = 8,  // standard deflate
 };
 
+// TODO: remove this when everyone's moved over to std::string.
 struct ZipString {
   const uint8_t* name;
   uint16_t name_length;
@@ -187,6 +189,8 @@
  * Returns 0 on success, -1 if there are no more elements in this
  * archive and lower negative values on failure.
  */
+int32_t Next(void* cookie, ZipEntry* data, std::string* name);
+// TODO: remove this when everyone's moved over to std::string.
 int32_t Next(void* cookie, ZipEntry* data, ZipString* name);
 
 /*
diff --git a/libziparchive/unzip.cpp b/libziparchive/unzip.cpp
index 3a3a694..426325e 100644
--- a/libziparchive/unzip.cpp
+++ b/libziparchive/unzip.cpp
@@ -255,9 +255,8 @@
   }
 
   ZipEntry entry;
-  ZipString string;
-  while ((err = Next(cookie, &entry, &string)) >= 0) {
-    std::string name(string.name, string.name + string.name_length);
+  std::string name;
+  while ((err = Next(cookie, &entry, &name)) >= 0) {
     if (ShouldInclude(name)) ProcessOne(zah, entry, name);
   }
 
diff --git a/libziparchive/zip_archive.cc b/libziparchive/zip_archive.cc
index 269e4ca..f4b6c74 100644
--- a/libziparchive/zip_archive.cc
+++ b/libziparchive/zip_archive.cc
@@ -747,6 +747,15 @@
   return FindEntry(archive, static_cast<uint32_t>(ent), data);
 }
 
+int32_t Next(void* cookie, ZipEntry* data, std::string* name) {
+  ZipString zs;
+  int32_t result = Next(cookie, data, &zs);
+  if (result == 0) {
+    *name = std::string(reinterpret_cast<const char*>(zs.name), zs.name_length);
+  }
+  return result;
+}
+
 int32_t Next(void* cookie, ZipEntry* data, ZipString* name) {
   IterationHandle* handle = reinterpret_cast<IterationHandle*>(cookie);
   if (handle == NULL) {
diff --git a/libziparchive/zip_archive_benchmark.cpp b/libziparchive/zip_archive_benchmark.cpp
index 434f2e1..23ed408 100644
--- a/libziparchive/zip_archive_benchmark.cpp
+++ b/libziparchive/zip_archive_benchmark.cpp
@@ -71,7 +71,7 @@
   ZipArchiveHandle handle;
   void* iteration_cookie;
   ZipEntry data;
-  ZipString name;
+  std::string name;
 
   while (state.KeepRunning()) {
     OpenArchive(temp_file->path, &handle);
diff --git a/libziparchive/zip_archive_test.cc b/libziparchive/zip_archive_test.cc
index 993c975..b6ca9ec 100644
--- a/libziparchive/zip_archive_test.cc
+++ b/libziparchive/zip_archive_test.cc
@@ -118,10 +118,10 @@
   ZipEntry data;
   std::vector<std::string> names;
 
-  ZipString name;
+  std::string name;
   for (size_t i = 0; i < expected_names_sorted.size(); ++i) {
     ASSERT_EQ(0, Next(iteration_cookie, &data, &name));
-    names.push_back(std::string(reinterpret_cast<const char*>(name.name), name.name_length));
+    names.push_back(name);
   }
 
   // End of iteration.
@@ -167,7 +167,7 @@
   ASSERT_EQ(0, StartIteration(handle, &iteration_cookie, "x", "y"));
 
   ZipEntry data;
-  ZipString name;
+  std::string name;
 
   // End of iteration.
   ASSERT_EQ(-1, Next(iteration_cookie, &data, &name));
@@ -224,7 +224,7 @@
   void* iteration_cookie;
   ASSERT_EQ(0, StartIteration(handle, &iteration_cookie));
 
-  ZipString name;
+  std::string name;
   ZipEntry data;
 
   ASSERT_EQ(Next(iteration_cookie, &data, &name), 0);