Otapreopt: Try to mount vendor partition for A/B OTA

Vendor apps are usually not preopted, so A/B dexopt should pick
them up. update_engine is not mounting the vendor partition, so
let otapreopt_chroot do the work.

Bug: 25612095
Bug: 29498238
Change-Id: I5a77bdb78a8e478ce10f6c1d0f911a8d6686becb
(cherry picked from commit 0ba073ce81fbe544592e0a3cd526b274e83fdf9f)
diff --git a/cmds/installd/commands.cpp b/cmds/installd/commands.cpp
index 64afd96..95451bf 100644
--- a/cmds/installd/commands.cpp
+++ b/cmds/installd/commands.cpp
@@ -44,6 +44,7 @@
 
 #include <globals.h>
 #include <installd_deps.h>
+#include <otapreopt_utils.h>
 #include <utils.h>
 
 #ifndef LOG_TAG
@@ -2124,10 +2125,7 @@
         }
         slot_suffix = buf;
 
-        // Validate.
-        std::regex slot_suffix_regex("[a-zA-Z0-9_]+");
-        std::smatch slot_suffix_match;
-        if (!std::regex_match(slot_suffix, slot_suffix_match, slot_suffix_regex)) {
+        if (!ValidateTargetSlotSuffix(slot_suffix)) {
             LOG(ERROR) << "Target slot suffix not legal: " << slot_suffix;
             return -1;
         }
diff --git a/cmds/installd/otapreopt.cpp b/cmds/installd/otapreopt.cpp
index 6c87f7a..5fa972a 100644
--- a/cmds/installd/otapreopt.cpp
+++ b/cmds/installd/otapreopt.cpp
@@ -40,6 +40,7 @@
 #include <file_parsing.h>
 #include <globals.h>
 #include <installd_deps.h>  // Need to fill in requirements of commands.
+#include <otapreopt_utils.h>
 #include <system_properties.h>
 #include <utils.h>
 
@@ -261,13 +262,9 @@
         }
         // Sanitize value. Only allow (a-zA-Z0-9_)+.
         target_slot_ = target_slot_arg;
-        {
-            std::regex slot_suffix_regex("[a-zA-Z0-9_]+");
-            std::smatch slot_suffix_match;
-            if (!std::regex_match(target_slot_, slot_suffix_match, slot_suffix_regex)) {
-                LOG(ERROR) << "Target slot suffix not legal: " << target_slot_;
-                return false;
-            }
+        if (!ValidateTargetSlotSuffix(target_slot_)) {
+            LOG(ERROR) << "Target slot suffix not legal: " << target_slot_;
+            return false;
         }
 
         // Check for "dexopt" next.
diff --git a/cmds/installd/otapreopt_chroot.cpp b/cmds/installd/otapreopt_chroot.cpp
index e6030bf..5ea89e6 100644
--- a/cmds/installd/otapreopt_chroot.cpp
+++ b/cmds/installd/otapreopt_chroot.cpp
@@ -26,6 +26,7 @@
 #include <android-base/stringprintf.h>
 
 #include <commands.h>
+#include <otapreopt_utils.h>
 
 #ifndef LOG_TAG
 #define LOG_TAG "otapreopt"
@@ -94,6 +95,28 @@
         }
     }
 
+    // Try to mount the vendor partition. update_engine doesn't do this for us, but we
+    // want it for vendor APKs.
+    // Notes:
+    //  1) We pretty much guess a name here and hope to find the partition by name.
+    //     It is just as complicated and brittle to scan /proc/mounts. But this requires
+    //     validating the target-slot so as not to try to mount some totally random path.
+    //  2) We're in a mount namespace here, so when we die, this will be cleaned up.
+    //  3) Ignore errors. Printing anything at this stage will open a file descriptor
+    //     for logging.
+    if (!ValidateTargetSlotSuffix(arg[2])) {
+        LOG(ERROR) << "Target slot suffix not legal: " << arg[2];
+        exit(207);
+    }
+    std::string vendor_partition = StringPrintf("/dev/block/bootdevice/by-name/vendor%s",
+                                                arg[2]);
+    int vendor_result = mount(vendor_partition.c_str(),
+                              "/postinstall/vendor",
+                              "ext4",
+                              MS_RDONLY,
+                              /* data */ nullptr);
+    UNUSED(vendor_result);
+
     // Chdir into /postinstall.
     if (chdir("/postinstall") != 0) {
         PLOG(ERROR) << "Unable to chdir into /postinstall.";
diff --git a/cmds/installd/otapreopt_utils.h b/cmds/installd/otapreopt_utils.h
new file mode 100644
index 0000000..436e554
--- /dev/null
+++ b/cmds/installd/otapreopt_utils.h
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef OTAPREOPT_UTILS_H_
+#define OTAPREOPT_UTILS_H_
+
+#include <regex>
+
+namespace android {
+namespace installd {
+
+static inline bool ValidateTargetSlotSuffix(const std::string& input) {
+    std::regex slot_suffix_regex("[a-zA-Z0-9_]+");
+    std::smatch slot_suffix_match;
+    return std::regex_match(input, slot_suffix_match, slot_suffix_regex);
+}
+
+}  // namespace installd
+}  // namespace android
+
+#endif  // OTAPREOPT_UTILS_H_