Merge "Mark libsysutils vendor_available." into oc-dev
diff --git a/adb/bugreport.cpp b/adb/bugreport.cpp
index d159d6a..b3e391b 100644
--- a/adb/bugreport.cpp
+++ b/adb/bugreport.cpp
@@ -149,7 +149,7 @@
             int progress = std::stoi(line.substr(idx1, (idx2 - idx1)));
             int total = std::stoi(line.substr(idx2 + 1));
             int progress_percentage = (progress * 100 / total);
-            if (progress_percentage <= last_progress_percentage_) {
+            if (progress_percentage != 0 && progress_percentage <= last_progress_percentage_) {
                 // Ignore.
                 return;
             }
diff --git a/adb/bugreport_test.cpp b/adb/bugreport_test.cpp
index 2b368d7..d3787b4 100644
--- a/adb/bugreport_test.cpp
+++ b/adb/bugreport_test.cpp
@@ -311,6 +311,29 @@
     ASSERT_EQ(0, br_.DoIt(kTransportLocal, "HannibalLecter", 2, args));
 }
 
+// Tests 'adb bugreport file.zip' when it succeeds and displays the initial progress of 0%
+TEST_F(BugreportTest, OkProgressZeroPercentIsNotIgnored) {
+    ExpectBugreportzVersion("1.1");
+    ExpectProgress(0);
+    ExpectProgress(1);
+    // clang-format off
+    EXPECT_CALL(br_, SendShellCommand(kTransportLocal, "HannibalLecter", "bugreportz -p", false, _))
+        // NOTE: DoAll accepts at most 10 arguments, and we're almost reached that limit...
+        .WillOnce(DoAll(
+            WithArg<4>(WriteOnStdout("BEGIN:/device/bugreport.zip\n")),
+            WithArg<4>(WriteOnStdout("PROGRESS:1/100000\n")),
+            WithArg<4>(WriteOnStdout("PROGRESS:1/100\n")), // 1%
+            WithArg<4>(WriteOnStdout("OK:/device/bugreport.zip")),
+            WithArg<4>(ReturnCallbackDone())));
+    // clang-format on
+    EXPECT_CALL(br_, DoSyncPull(ElementsAre(StrEq("/device/bugreport.zip")), StrEq("file.zip"),
+                                true, StrEq("pulling file.zip")))
+        .WillOnce(Return(true));
+
+    const char* args[] = {"bugreport", "file.zip"};
+    ASSERT_EQ(0, br_.DoIt(kTransportLocal, "HannibalLecter", 2, args));
+}
+
 // Tests 'adb bugreport dir' when it succeeds and destination is a directory.
 TEST_F(BugreportTest, OkDirectory) {
     ExpectBugreportzVersion("1.1");
diff --git a/fs_mgr/fs_mgr.cpp b/fs_mgr/fs_mgr.cpp
index abdd498..803b894 100644
--- a/fs_mgr/fs_mgr.cpp
+++ b/fs_mgr/fs_mgr.cpp
@@ -744,23 +744,6 @@
     }
 }
 
-static std::string extract_by_name_prefix(struct fstab* fstab) {
-    // We assume that there's an entry for the /misc mount point in the
-    // fstab file and use that to get the device file by-name prefix.
-    // The device needs not to have an actual /misc partition.
-    // e.g.,
-    //    - /dev/block/platform/soc.0/7824900.sdhci/by-name/misc ->
-    //    - /dev/block/platform/soc.0/7824900.sdhci/by-name/
-    struct fstab_rec* fstab_entry = fs_mgr_get_entry_for_mount_point(fstab, "/misc");
-    if (fstab_entry == nullptr) {
-        LERROR << "/misc mount point not found in fstab";
-        return "";
-    }
-    std::string full_path(fstab_entry->blk_device);
-    size_t end_slash = full_path.find_last_of("/");
-    return full_path.substr(0, end_slash + 1);
-}
-
 // TODO: add ueventd notifiers if they don't exist.
 // This is just doing a wait_for_device for maximum of 1s
 int fs_mgr_test_access(const char *device) {
@@ -850,7 +833,7 @@
 
         if (fstab->recs[i].fs_mgr_flags & MF_AVB) {
             if (!avb_handle) {
-                avb_handle = FsManagerAvbHandle::Open(extract_by_name_prefix(fstab));
+                avb_handle = FsManagerAvbHandle::Open(*fstab);
                 if (!avb_handle) {
                     LERROR << "Failed to open FsManagerAvbHandle";
                     return -1;
@@ -966,16 +949,20 @@
             }
             encryptable = FS_MGR_MNTALL_DEV_MIGHT_BE_ENCRYPTED;
         } else {
+            // fs_options might be null so we cannot use PERROR << directly.
+            // Use StringPrintf to output "(null)" instead.
             if (fs_mgr_is_nofail(&fstab->recs[attempted_idx])) {
-                PERROR << "Ignoring failure to mount an un-encryptable or wiped partition on"
-                       << fstab->recs[attempted_idx].blk_device << " at "
-                       << fstab->recs[attempted_idx].mount_point << " options: "
-                       << fstab->recs[attempted_idx].fs_options;
+                PERROR << android::base::StringPrintf(
+                    "Ignoring failure to mount an un-encryptable or wiped "
+                    "partition on %s at %s options: %s",
+                    fstab->recs[attempted_idx].blk_device, fstab->recs[attempted_idx].mount_point,
+                    fstab->recs[attempted_idx].fs_options);
             } else {
-                PERROR << "Failed to mount an un-encryptable or wiped partition on"
-                       << fstab->recs[attempted_idx].blk_device << " at "
-                       << fstab->recs[attempted_idx].mount_point << " options: "
-                       << fstab->recs[attempted_idx].fs_options;
+                PERROR << android::base::StringPrintf(
+                    "Failed to mount an un-encryptable or wiped partition "
+                    "on %s at %s options: %s",
+                    fstab->recs[attempted_idx].blk_device, fstab->recs[attempted_idx].mount_point,
+                    fstab->recs[attempted_idx].fs_options);
                 ++error_count;
             }
             continue;
@@ -1061,7 +1048,7 @@
 
         if (fstab->recs[i].fs_mgr_flags & MF_AVB) {
             if (!avb_handle) {
-                avb_handle = FsManagerAvbHandle::Open(extract_by_name_prefix(fstab));
+                avb_handle = FsManagerAvbHandle::Open(*fstab);
                 if (!avb_handle) {
                     LERROR << "Failed to open FsManagerAvbHandle";
                     return -1;
diff --git a/fs_mgr/fs_mgr_avb.cpp b/fs_mgr/fs_mgr_avb.cpp
index d4dd76a..36883e6 100644
--- a/fs_mgr/fs_mgr_avb.cpp
+++ b/fs_mgr/fs_mgr_avb.cpp
@@ -14,6 +14,8 @@
  * limitations under the License.
  */
 
+#include "fs_mgr_avb.h"
+
 #include <errno.h>
 #include <fcntl.h>
 #include <inttypes.h>
@@ -38,9 +40,8 @@
 #include <utils/Compat.h>
 
 #include "fs_mgr.h"
-#include "fs_mgr_avb.h"
-#include "fs_mgr_avb_ops.h"
 #include "fs_mgr_priv.h"
+#include "fs_mgr_priv_avb_ops.h"
 #include "fs_mgr_priv_dm_ioctl.h"
 #include "fs_mgr_priv_sha.h"
 
@@ -457,12 +458,21 @@
     return true;
 }
 
-FsManagerAvbUniquePtr FsManagerAvbHandle::Open(const std::string& device_file_by_name_prefix) {
-    if (device_file_by_name_prefix.empty()) {
-        LERROR << "Missing device file by-name prefix";
+FsManagerAvbUniquePtr FsManagerAvbHandle::Open(const fstab& fstab) {
+    FsManagerAvbOps avb_ops(fstab);
+    return DoOpen(&avb_ops);
+}
+
+FsManagerAvbUniquePtr FsManagerAvbHandle::Open(ByNameSymlinkMap&& by_name_symlink_map) {
+    if (by_name_symlink_map.empty()) {
+        LERROR << "Empty by_name_symlink_map when opening FsManagerAvbHandle";
         return nullptr;
     }
+    FsManagerAvbOps avb_ops(std::move(by_name_symlink_map));
+    return DoOpen(&avb_ops);
+}
 
+FsManagerAvbUniquePtr FsManagerAvbHandle::DoOpen(FsManagerAvbOps* avb_ops) {
     // Gets the expected hash value of vbmeta images from kernel cmdline.
     std::unique_ptr<FsManagerAvbVerifier> avb_verifier = FsManagerAvbVerifier::Create();
     if (!avb_verifier) {
@@ -476,8 +486,7 @@
         return nullptr;
     }
 
-    FsManagerAvbOps avb_ops(device_file_by_name_prefix);
-    AvbSlotVerifyResult verify_result = avb_ops.AvbSlotVerify(
+    AvbSlotVerifyResult verify_result = avb_ops->AvbSlotVerify(
         fs_mgr_get_slot_suffix(), avb_verifier->IsDeviceUnlocked(), &avb_handle->avb_slot_data_);
 
     // Only allow two verify results:
diff --git a/fs_mgr/fs_mgr_avb_ops.cpp b/fs_mgr/fs_mgr_avb_ops.cpp
index 981e9fc..47df861 100644
--- a/fs_mgr/fs_mgr_avb_ops.cpp
+++ b/fs_mgr/fs_mgr_avb_ops.cpp
@@ -22,6 +22,8 @@
  * SOFTWARE.
  */
 
+#include "fs_mgr_priv_avb_ops.h"
+
 #include <errno.h>
 #include <fcntl.h>
 #include <stdlib.h>
@@ -36,7 +38,6 @@
 #include <utils/Compat.h>
 
 #include "fs_mgr.h"
-#include "fs_mgr_avb_ops.h"
 #include "fs_mgr_priv.h"
 
 static AvbIOResult read_from_partition(AvbOps* ops, const char* partition, int64_t offset,
@@ -88,11 +89,7 @@
     return AVB_IO_RESULT_OK;
 }
 
-FsManagerAvbOps::FsManagerAvbOps(const std::string& device_file_by_name_prefix)
-    : device_file_by_name_prefix_(device_file_by_name_prefix) {
-    if (device_file_by_name_prefix_.back() != '/') {
-        device_file_by_name_prefix_ += '/';
-    }
+void FsManagerAvbOps::InitializeAvbOps() {
     // We only need to provide the implementation of read_from_partition()
     // operation since that's all what is being used by the avb_slot_verify().
     // Other I/O operations are only required in bootloader but not in
@@ -107,13 +104,31 @@
     avb_ops_.user_data = this;
 }
 
+FsManagerAvbOps::FsManagerAvbOps(std::map<std::string, std::string>&& by_name_symlink_map)
+    : by_name_symlink_map_(std::move(by_name_symlink_map)) {
+    InitializeAvbOps();
+}
+
+FsManagerAvbOps::FsManagerAvbOps(const fstab& fstab) {
+    // Constructs the by-name symlink map for each fstab record.
+    // /dev/block/platform/soc.0/7824900.sdhci/by-name/system_a =>
+    // by_name_symlink_map_["system_a"] = "/dev/block/platform/soc.0/7824900.sdhci/by-name/system_a"
+    for (int i = 0; i < fstab.num_entries; i++) {
+        std::string partition_name = basename(fstab.recs[i].blk_device);
+        by_name_symlink_map_[partition_name] = fstab.recs[i].blk_device;
+    }
+    InitializeAvbOps();
+}
+
 AvbIOResult FsManagerAvbOps::ReadFromPartition(const char* partition, int64_t offset,
                                                size_t num_bytes, void* buffer,
                                                size_t* out_num_read) {
-    // Appends |partition| to the device_file_by_name_prefix_, e.g.,
-    //    - /dev/block/platform/soc.0/7824900.sdhci/by-name/ ->
-    //    - /dev/block/platform/soc.0/7824900.sdhci/by-name/system_a
-    std::string path = device_file_by_name_prefix_ + partition;
+    const auto iter = by_name_symlink_map_.find(partition);
+    if (iter == by_name_symlink_map_.end()) {
+        LERROR << "by-name symlink not found for partition: '" << partition << "'";
+        return AVB_IO_RESULT_ERROR_NO_SUCH_PARTITION;
+    }
+    std::string path = iter->second;
 
     // Ensures the device path (a symlink created by init) is ready to
     // access. fs_mgr_test_access() will test a few iterations if the
@@ -124,7 +139,7 @@
 
     android::base::unique_fd fd(TEMP_FAILURE_RETRY(open(path.c_str(), O_RDONLY | O_CLOEXEC)));
     if (fd < 0) {
-        PERROR << "Failed to open " << path.c_str();
+        PERROR << "Failed to open " << path;
         return AVB_IO_RESULT_ERROR_IO;
     }
 
@@ -148,8 +163,7 @@
     // for EOF).
     ssize_t num_read = TEMP_FAILURE_RETRY(pread64(fd, buffer, num_bytes, offset));
     if (num_read < 0 || (size_t)num_read != num_bytes) {
-        PERROR << "Failed to read " << num_bytes << " bytes from " << path.c_str() << " offset "
-               << offset;
+        PERROR << "Failed to read " << num_bytes << " bytes from " << path << " offset " << offset;
         return AVB_IO_RESULT_ERROR_IO;
     }
 
diff --git a/fs_mgr/fs_mgr_fstab.cpp b/fs_mgr/fs_mgr_fstab.cpp
index 0a694c1..7d09d01 100644
--- a/fs_mgr/fs_mgr_fstab.cpp
+++ b/fs_mgr/fs_mgr_fstab.cpp
@@ -397,6 +397,15 @@
         std::vector<std::string> fstab_entry;
         std::string file_name;
         std::string value;
+        // skip a partition entry if the status property is present and not set to ok
+        file_name = android::base::StringPrintf("%s/%s/status", fstabdir_name.c_str(), dp->d_name);
+        if (read_dt_file(file_name, &value)) {
+            if (value != "okay" && value != "ok") {
+                LINFO << "dt_fstab: Skip disabled entry for partition " << dp->d_name;
+                continue;
+            }
+        }
+
         file_name = android::base::StringPrintf("%s/%s/dev", fstabdir_name.c_str(), dp->d_name);
         if (!read_dt_file(file_name, &value)) {
             LERROR << "dt_fstab: Failed to find device for partition " << dp->d_name;
diff --git a/fs_mgr/fs_mgr_avb_ops.h b/fs_mgr/fs_mgr_priv_avb_ops.h
similarity index 87%
rename from fs_mgr/fs_mgr_avb_ops.h
rename to fs_mgr/fs_mgr_priv_avb_ops.h
index ec4a8c9..a6b52e4 100644
--- a/fs_mgr/fs_mgr_avb_ops.h
+++ b/fs_mgr/fs_mgr_priv_avb_ops.h
@@ -22,8 +22,11 @@
  * SOFTWARE.
  */
 
-#ifndef __CORE_FS_MGR_AVB_OPS_H
-#define __CORE_FS_MGR_AVB_OPS_H
+#ifndef __CORE_FS_MGR_PRIV_AVB_OPS_H
+#define __CORE_FS_MGR_PRIV_AVB_OPS_H
+
+#include <map>
+#include <string>
 
 #include <libavb/libavb.h>
 
@@ -43,7 +46,8 @@
 //
 class FsManagerAvbOps {
   public:
-    FsManagerAvbOps(const std::string& device_file_by_name_prefix);
+    FsManagerAvbOps(const fstab& fstab);
+    FsManagerAvbOps(std::map<std::string, std::string>&& by_name_symlink_map);
 
     static FsManagerAvbOps* GetInstanceFromAvbOps(AvbOps* ops) {
         return reinterpret_cast<FsManagerAvbOps*>(ops->user_data);
@@ -56,7 +60,9 @@
                                       AvbSlotVerifyData** out_data);
 
   private:
+    void InitializeAvbOps();
+
     AvbOps avb_ops_;
-    std::string device_file_by_name_prefix_;
+    std::map<std::string, std::string> by_name_symlink_map_;
 };
-#endif /* __CORE_FS_MGR_AVB_OPS_H */
+#endif /* __CORE_FS_MGR_PRIV_AVB_OPS_H */
diff --git a/fs_mgr/include/fs_mgr_avb.h b/fs_mgr/include/fs_mgr_avb.h
index 65ff9941..bbafe1a 100644
--- a/fs_mgr/include/fs_mgr_avb.h
+++ b/fs_mgr/include/fs_mgr_avb.h
@@ -17,6 +17,7 @@
 #ifndef __CORE_FS_MGR_AVB_H
 #define __CORE_FS_MGR_AVB_H
 
+#include <map>
 #include <memory>
 #include <string>
 
@@ -31,9 +32,13 @@
     kFsManagerAvbHandleErrorVerification = 2,
 };
 
+class FsManagerAvbOps;
+
 class FsManagerAvbHandle;
 using FsManagerAvbUniquePtr = std::unique_ptr<FsManagerAvbHandle>;
 
+using ByNameSymlinkMap = std::map<std::string, std::string>;
+
 // Provides a factory method to return a unique_ptr pointing to itself and the
 // SetUpAvb() function to extract dm-verity parameters from AVB metadata to
 // load verity table into kernel through ioctl.
@@ -49,6 +54,13 @@
     // A typical usage will be:
     //   - FsManagerAvbUniquePtr handle = FsManagerAvbHandle::Open();
     //
+    // There are two overloaded Open() functions with a single parameter.
+    // The argument can be a ByNameSymlinkMap describing the mapping from partition
+    // name to by-name symlink, or a fstab file to which the ByNameSymlinkMap is
+    // constructed from. e.g.,
+    //   - /dev/block/platform/soc.0/7824900.sdhci/by-name/system_a ->
+    //   - ByNameSymlinkMap["system_a"] = "/dev/block/platform/soc.0/7824900.sdhci/by-name/system_a"
+    //
     // Possible return values:
     //   - nullptr: any error when reading and verifying the metadata,
     //     e.g., I/O error, digest value mismatch, size mismatch, etc.
@@ -61,7 +73,8 @@
     //   - a valid unique_ptr with status kFsMgrAvbHandleSuccess: the metadata
     //     is verified and can be trusted.
     //
-    static FsManagerAvbUniquePtr Open(const std::string& device_file_by_name_prefix);
+    static FsManagerAvbUniquePtr Open(const fstab& fstab);
+    static FsManagerAvbUniquePtr Open(ByNameSymlinkMap&& by_name_symlink_map);
 
     // Sets up dm-verity on the given fstab entry.
     // The 'wait_for_verity_dev' parameter makes this function wait for the
@@ -88,10 +101,10 @@
         }
     };
 
-  protected:
-    FsManagerAvbHandle() : avb_slot_data_(nullptr), status_(kFsManagerAvbHandleUninitialized) {}
-
   private:
+    FsManagerAvbHandle() : avb_slot_data_(nullptr), status_(kFsManagerAvbHandleUninitialized) {}
+    static FsManagerAvbUniquePtr DoOpen(FsManagerAvbOps* avb_ops);
+
     AvbSlotVerifyData* avb_slot_data_;
     FsManagerAvbHandleStatus status_;
     std::string avb_version_;
diff --git a/include/nativebridge/native_bridge.h b/include/nativebridge/native_bridge.h
index 929b8ae..9bfc935 100644
--- a/include/nativebridge/native_bridge.h
+++ b/include/nativebridge/native_bridge.h
@@ -161,6 +161,9 @@
 // Use NativeBridgeLoadLibrary() instead in non-namespace scenario.
 void* NativeBridgeLoadLibraryExt(const char* libpath, int flag, native_bridge_namespace_t* ns);
 
+// Returns vendor namespace if it is enabled for the device and null otherwise
+native_bridge_namespace_t* NativeBridgeGetVendorNamespace();
+
 // Native bridge interfaces to runtime.
 struct NativeBridgeCallbacks {
   // Version number of the interface.
@@ -348,6 +351,15 @@
   // Starting with v3, NativeBridge has two scenarios: with/without namespace.
   // Use loadLibrary instead in non-namespace scenario.
   void* (*loadLibraryExt)(const char* libpath, int flag, native_bridge_namespace_t* ns);
+
+  // Get native bridge version of vendor namespace.
+  // The vendor namespace is the namespace used to load vendor public libraries.
+  // With O release this namespace can be different from the default namespace.
+  // For the devices without enable vendor namespaces this function should return null
+  //
+  // Returns:
+  //   vendor namespace or null if it was not set up for the device
+  native_bridge_namespace_t* (*getVendorNamespace)();
 };
 
 // Runtime interfaces to native bridge.
diff --git a/init/devices.cpp b/init/devices.cpp
index 405f92e..39571ac 100644
--- a/init/devices.cpp
+++ b/init/devices.cpp
@@ -526,8 +526,7 @@
     return NULL;
 }
 
-static char **get_block_device_symlinks(struct uevent *uevent)
-{
+char** get_block_device_symlinks(struct uevent* uevent) {
     const char *device;
     struct platform_node *pdev;
     const char *slash;
diff --git a/init/devices.h b/init/devices.h
index 26a064b..3f2cde4 100644
--- a/init/devices.h
+++ b/init/devices.h
@@ -55,4 +55,6 @@
                          unsigned short wildcard);
 int get_device_fd();
 
+char** get_block_device_symlinks(struct uevent* uevent);
+
 #endif	/* _INIT_DEVICES_H */
diff --git a/init/init_first_stage.cpp b/init/init_first_stage.cpp
index a139e34..bcc8d1b 100644
--- a/init/init_first_stage.cpp
+++ b/init/init_first_stage.cpp
@@ -47,18 +47,22 @@
     bool InitDevices();
 
   protected:
-    void InitRequiredDevices(std::set<std::string>* devices_partition_names);
+    void InitRequiredDevices();
     void InitVerityDevice(const std::string& verity_device);
     bool MountPartitions();
 
-    virtual bool GetRequiredDevices(std::set<std::string>* out_devices_partition_names,
-                                    bool* out_need_dm_verity) = 0;
+    virtual coldboot_action_t ColdbootCallback(uevent* uevent);
+
+    // Pure virtual functions.
+    virtual bool GetRequiredDevices() = 0;
     virtual bool SetUpDmVerity(fstab_rec* fstab_rec) = 0;
 
+    bool need_dm_verity_;
     // Device tree fstab entries.
     std::unique_ptr<fstab, decltype(&fs_mgr_free_fstab)> device_tree_fstab_;
     // Eligible first stage mount candidates, only allow /system, /vendor and/or /odm.
     std::vector<fstab_rec*> mount_fstab_recs_;
+    std::set<std::string> required_devices_partition_names_;
 };
 
 class FirstStageMountVBootV1 : public FirstStageMount {
@@ -67,27 +71,26 @@
     ~FirstStageMountVBootV1() override = default;
 
   protected:
-    bool GetRequiredDevices(std::set<std::string>* out_devices_partition_names,
-                            bool* out_need_dm_verity) override;
+    bool GetRequiredDevices() override;
     bool SetUpDmVerity(fstab_rec* fstab_rec) override;
 };
 
 class FirstStageMountVBootV2 : public FirstStageMount {
   public:
+    friend void SetInitAvbVersionInRecovery();
+
     FirstStageMountVBootV2();
     ~FirstStageMountVBootV2() override = default;
 
-    const std::string& by_name_prefix() const { return device_tree_by_name_prefix_; }
-
   protected:
-    bool GetRequiredDevices(std::set<std::string>* out_devices_partition_names,
-                            bool* out_need_dm_verity) override;
+    coldboot_action_t ColdbootCallback(uevent* uevent) override;
+    bool GetRequiredDevices() override;
     bool SetUpDmVerity(fstab_rec* fstab_rec) override;
     bool InitAvbHandle();
 
     std::string device_tree_vbmeta_parts_;
-    std::string device_tree_by_name_prefix_;
     FsManagerAvbUniquePtr avb_handle_;
+    ByNameSymlinkMap by_name_symlink_map_;
 };
 
 // Static Functions
@@ -102,7 +105,8 @@
 
 // Class Definitions
 // -----------------
-FirstStageMount::FirstStageMount() : device_tree_fstab_(fs_mgr_read_fstab_dt(), fs_mgr_free_fstab) {
+FirstStageMount::FirstStageMount()
+    : need_dm_verity_(false), device_tree_fstab_(fs_mgr_read_fstab_dt(), fs_mgr_free_fstab) {
     if (!device_tree_fstab_) {
         LOG(ERROR) << "Failed to read fstab from device tree";
         return;
@@ -136,72 +140,71 @@
 }
 
 bool FirstStageMount::InitDevices() {
-    bool need_dm_verity;
-    std::set<std::string> devices_partition_names;
+    if (!GetRequiredDevices()) return false;
 
-    // The partition name in devices_partition_names MUST have A/B suffix when A/B is used.
-    if (!GetRequiredDevices(&devices_partition_names, &need_dm_verity)) return false;
+    InitRequiredDevices();
 
-    if (need_dm_verity) {
+    // InitRequiredDevices() will remove found partitions from required_devices_partition_names_.
+    // So if it isn't empty here, it means some partitions are not found.
+    if (!required_devices_partition_names_.empty()) {
+        LOG(ERROR) << __FUNCTION__ << "(): partition(s) not found: "
+                   << android::base::Join(required_devices_partition_names_, ", ");
+        return false;
+    } else {
+        return true;
+    }
+}
+
+// Creates devices with uevent->partition_name matching one in the member variable
+// required_devices_partition_names_. Found partitions will then be removed from it
+// for the subsequent member function to check which devices are NOT created.
+void FirstStageMount::InitRequiredDevices() {
+    if (required_devices_partition_names_.empty()) {
+        return;
+    }
+
+    if (need_dm_verity_) {
         const std::string dm_path = "/devices/virtual/misc/device-mapper";
         device_init(("/sys" + dm_path).c_str(), [&dm_path](uevent* uevent) -> coldboot_action_t {
-            if (uevent->path == dm_path) return COLDBOOT_STOP;
+            if (uevent->path && uevent->path == dm_path) return COLDBOOT_STOP;
             return COLDBOOT_CONTINUE;  // dm_path not found, continue to find it.
         });
     }
 
-    bool success = false;
-    InitRequiredDevices(&devices_partition_names);
-
-    // InitRequiredDevices() will remove found partitions from devices_partition_names.
-    // So if it isn't empty here, it means some partitions are not found.
-    if (!devices_partition_names.empty()) {
-        LOG(ERROR) << __FUNCTION__ << "(): partition(s) not found: "
-                   << android::base::Join(devices_partition_names, ", ");
-    } else {
-        success = true;
-    }
+    device_init(nullptr,
+                [this](uevent* uevent) -> coldboot_action_t { return ColdbootCallback(uevent); });
 
     device_close();
-    return success;
 }
 
-// Creates devices with uevent->partition_name matching one in the in/out
-// devices_partition_names. Found partitions will then be removed from the
-// devices_partition_names for the caller to check which devices are NOT created.
-void FirstStageMount::InitRequiredDevices(std::set<std::string>* devices_partition_names) {
-    if (devices_partition_names->empty()) {
-        return;
+coldboot_action_t FirstStageMount::ColdbootCallback(uevent* uevent) {
+    // We need platform devices to create symlinks.
+    if (!strncmp(uevent->subsystem, "platform", 8)) {
+        return COLDBOOT_CREATE;
     }
-    device_init(nullptr, [=](uevent* uevent) -> coldboot_action_t {
-        // We need platform devices to create symlinks.
-        if (!strncmp(uevent->subsystem, "platform", 8)) {
-            return COLDBOOT_CREATE;
-        }
 
-        // Ignores everything that is not a block device.
-        if (strncmp(uevent->subsystem, "block", 5)) {
-            return COLDBOOT_CONTINUE;
-        }
+    // Ignores everything that is not a block device.
+    if (strncmp(uevent->subsystem, "block", 5)) {
+        return COLDBOOT_CONTINUE;
+    }
 
-        if (uevent->partition_name) {
-            // Matches partition name to create device nodes.
-            // Both devices_partition_names and uevent->partition_name have A/B
-            // suffix when A/B is used.
-            auto iter = devices_partition_names->find(uevent->partition_name);
-            if (iter != devices_partition_names->end()) {
-                LOG(VERBOSE) << __FUNCTION__ << "(): found partition: " << *iter;
-                devices_partition_names->erase(iter);
-                if (devices_partition_names->empty()) {
-                    return COLDBOOT_STOP;  // Found all partitions, stop coldboot.
-                } else {
-                    return COLDBOOT_CREATE;  // Creates this device and continue to find others.
-                }
+    if (uevent->partition_name) {
+        // Matches partition name to create device nodes.
+        // Both required_devices_partition_names_ and uevent->partition_name have A/B
+        // suffix when A/B is used.
+        auto iter = required_devices_partition_names_.find(uevent->partition_name);
+        if (iter != required_devices_partition_names_.end()) {
+            LOG(VERBOSE) << __FUNCTION__ << "(): found partition: " << *iter;
+            required_devices_partition_names_.erase(iter);
+            if (required_devices_partition_names_.empty()) {
+                return COLDBOOT_STOP;  // Found all partitions, stop coldboot.
+            } else {
+                return COLDBOOT_CREATE;  // Creates this device and continue to find others.
             }
         }
-        // Not found a partition or find an unneeded partition, continue to find others.
-        return COLDBOOT_CONTINUE;
-    });
+    }
+    // Not found a partition or find an unneeded partition, continue to find others.
+    return COLDBOOT_CONTINUE;
 }
 
 // Creates "/dev/block/dm-XX" for dm-verity by running coldboot on /sys/block/dm-XX.
@@ -210,7 +213,7 @@
     const std::string syspath = "/sys/block/" + device_name;
 
     device_init(syspath.c_str(), [&](uevent* uevent) -> coldboot_action_t {
-        if (uevent->device_name && device_name == uevent->device_name) {
+        if (uevent->device_name && uevent->device_name == device_name) {
             LOG(VERBOSE) << "Creating dm-verity device : " << verity_device;
             return COLDBOOT_STOP;
         }
@@ -233,10 +236,9 @@
     return true;
 }
 
-bool FirstStageMountVBootV1::GetRequiredDevices(std::set<std::string>* out_devices_partition_names,
-                                                bool* out_need_dm_verity) {
+bool FirstStageMountVBootV1::GetRequiredDevices() {
     std::string verity_loc_device;
-    *out_need_dm_verity = false;
+    need_dm_verity_ = false;
 
     for (auto fstab_rec : mount_fstab_recs_) {
         // Don't allow verifyatboot in the first stage.
@@ -246,7 +248,7 @@
         }
         // Checks for verified partitions.
         if (fs_mgr_is_verified(fstab_rec)) {
-            *out_need_dm_verity = true;
+            need_dm_verity_ = true;
         }
         // Checks if verity metadata is on a separate partition. Note that it is
         // not partition specific, so there must be only one additional partition
@@ -265,11 +267,11 @@
     // Includes the partition names of fstab records and verity_loc_device (if any).
     // Notes that fstab_rec->blk_device has A/B suffix updated by fs_mgr when A/B is used.
     for (auto fstab_rec : mount_fstab_recs_) {
-        out_devices_partition_names->emplace(basename(fstab_rec->blk_device));
+        required_devices_partition_names_.emplace(basename(fstab_rec->blk_device));
     }
 
     if (!verity_loc_device.empty()) {
-        out_devices_partition_names->emplace(basename(verity_loc_device.c_str()));
+        required_devices_partition_names_.emplace(basename(verity_loc_device.c_str()));
     }
 
     return true;
@@ -292,15 +294,13 @@
 }
 
 // FirstStageMountVBootV2 constructor.
-// Gets the vbmeta configurations from device tree.
-// Specifically, the 'parts' and 'by_name_prefix' below.
+// Gets the vbmeta partitions from device tree.
 // /{
 //     firmware {
 //         android {
 //             vbmeta {
 //                 compatible = "android,vbmeta";
 //                 parts = "vbmeta,boot,system,vendor"
-//                 by_name_prefix = "/dev/block/platform/soc.0/f9824900.sdhci/by-name/"
 //             };
 //         };
 //     };
@@ -310,31 +310,24 @@
         PLOG(ERROR) << "Failed to read vbmeta/parts from device tree";
         return;
     }
-
-    // TODO: removes by_name_prefix to allow partitions on different block devices.
-    if (!read_android_dt_file("vbmeta/by_name_prefix", &device_tree_by_name_prefix_)) {
-        PLOG(ERROR) << "Failed to read vbmeta/by_name_prefix from dt";
-        return;
-    }
 }
 
-bool FirstStageMountVBootV2::GetRequiredDevices(std::set<std::string>* out_devices_partition_names,
-                                                bool* out_need_dm_verity) {
-    *out_need_dm_verity = false;
+bool FirstStageMountVBootV2::GetRequiredDevices() {
+    need_dm_verity_ = false;
 
     // fstab_rec->blk_device has A/B suffix.
     for (auto fstab_rec : mount_fstab_recs_) {
         if (fs_mgr_is_avb(fstab_rec)) {
-            *out_need_dm_verity = true;
+            need_dm_verity_ = true;
         }
-        out_devices_partition_names->emplace(basename(fstab_rec->blk_device));
+        required_devices_partition_names_.emplace(basename(fstab_rec->blk_device));
     }
 
     // libavb verifies AVB metadata on all verified partitions at once.
     // e.g., The device_tree_vbmeta_parts_ will be "vbmeta,boot,system,vendor"
     // for libavb to verify metadata, even if there is only /vendor in the
     // above mount_fstab_recs_.
-    if (*out_need_dm_verity) {
+    if (need_dm_verity_) {
         if (device_tree_vbmeta_parts_.empty()) {
             LOG(ERROR) << "Missing vbmeta parts in device tree";
             return false;
@@ -342,16 +335,45 @@
         std::vector<std::string> partitions = android::base::Split(device_tree_vbmeta_parts_, ",");
         std::string ab_suffix = fs_mgr_get_slot_suffix();
         for (const auto& partition : partitions) {
-            // out_devices_partition_names is of type std::set so it's not an issue to emplace
-            // a partition twice. e.g., /vendor might be in both places:
+            // required_devices_partition_names_ is of type std::set so it's not an issue
+            // to emplace a partition twice. e.g., /vendor might be in both places:
             //   - device_tree_vbmeta_parts_ = "vbmeta,boot,system,vendor"
             //   - mount_fstab_recs_: /vendor_a
-            out_devices_partition_names->emplace(partition + ab_suffix);
+            required_devices_partition_names_.emplace(partition + ab_suffix);
         }
     }
     return true;
 }
 
+coldboot_action_t FirstStageMountVBootV2::ColdbootCallback(uevent* uevent) {
+    // Invokes the parent function to see if any desired partition has been found.
+    // If yes, record the by-name symlink for creating FsManagerAvbHandle later.
+    coldboot_action_t parent_callback_ret = FirstStageMount::ColdbootCallback(uevent);
+
+    // Skips the uevent if the parent function returns COLDBOOT_CONTINUE (meaning
+    // that the uevent was skipped) or there is no uevent->partition_name to
+    // create the by-name symlink.
+    if (parent_callback_ret != COLDBOOT_CONTINUE && uevent->partition_name) {
+        // get_block_device_symlinks() will return three symlinks at most, depending on
+        // the content of uevent. by-name symlink will be at [0] if uevent->partition_name
+        // is not empty. e.g.,
+        //   - /dev/block/platform/soc.0/f9824900.sdhci/by-name/modem
+        //   - /dev/block/platform/soc.0/f9824900.sdhci/by-num/p1
+        //   - /dev/block/platform/soc.0/f9824900.sdhci/mmcblk0p1
+        char** links = get_block_device_symlinks(uevent);
+        if (links && links[0]) {
+            auto[it, inserted] = by_name_symlink_map_.emplace(uevent->partition_name, links[0]);
+            if (!inserted) {
+                LOG(ERROR) << "Partition '" << uevent->partition_name
+                           << "' already existed in the by-name symlink map with a value of '"
+                           << it->second << "', new value '" << links[0] << "' will be ignored.";
+            }
+        }
+    }
+
+    return parent_callback_ret;
+}
+
 bool FirstStageMountVBootV2::SetUpDmVerity(fstab_rec* fstab_rec) {
     if (fs_mgr_is_avb(fstab_rec)) {
         if (!InitAvbHandle()) return false;
@@ -371,7 +393,14 @@
 bool FirstStageMountVBootV2::InitAvbHandle() {
     if (avb_handle_) return true;  // Returns true if the handle is already initialized.
 
-    avb_handle_ = FsManagerAvbHandle::Open(device_tree_by_name_prefix_);
+    if (by_name_symlink_map_.empty()) {
+        LOG(ERROR) << "by_name_symlink_map_ is empty";
+        return false;
+    }
+
+    avb_handle_ = FsManagerAvbHandle::Open(std::move(by_name_symlink_map_));
+    by_name_symlink_map_.clear();  // Removes all elements after the above std::move().
+
     if (!avb_handle_) {
         PLOG(ERROR) << "Failed to open FsManagerAvbHandle";
         return false;
@@ -427,7 +456,8 @@
         return;
     }
 
-    FsManagerAvbUniquePtr avb_handle = FsManagerAvbHandle::Open(avb_first_mount.by_name_prefix());
+    FsManagerAvbUniquePtr avb_handle =
+        FsManagerAvbHandle::Open(std::move(avb_first_mount.by_name_symlink_map_));
     if (!avb_handle) {
         PLOG(ERROR) << "Failed to open FsManagerAvbHandle for INIT_AVB_VERSION";
         return;
diff --git a/init/reboot.cpp b/init/reboot.cpp
index c997519..aac1b5c 100644
--- a/init/reboot.cpp
+++ b/init/reboot.cpp
@@ -331,7 +331,7 @@
     // keep debugging tools until non critical ones are all gone.
     const std::set<std::string> kill_after_apps{"tombstoned", "logd", "adbd"};
     // watchdogd is a vendor specific component but should be alive to complete shutdown safely.
-    const std::set<std::string> to_starts{"watchdogd", "vold"};
+    const std::set<std::string> to_starts{"watchdogd", "vold", "ueventd"};
     ServiceManager::GetInstance().ForEachService([&kill_after_apps, &to_starts](Service* s) {
         if (kill_after_apps.count(s->name())) {
             s->SetShutdownCritical();
diff --git a/libappfuse/FuseBuffer.cc b/libappfuse/FuseBuffer.cc
index b42a049..653e96b 100644
--- a/libappfuse/FuseBuffer.cc
+++ b/libappfuse/FuseBuffer.cc
@@ -119,7 +119,12 @@
                     return ResultOrAgain::kFailure;
             }
         }
-        CHECK(static_cast<uint32_t>(result) == header.len);
+
+        if (static_cast<unsigned int>(result) != header.len) {
+            LOG(ERROR) << "Written bytes " << result << " is different from length in header "
+                       << header.len;
+            return ResultOrAgain::kFailure;
+        }
         return ResultOrAgain::kSuccess;
     }
 }
@@ -141,8 +146,8 @@
     }
 
     constexpr int kMaxMessageSize = sizeof(FuseBuffer);
-    if (setsockopt(fds[0], SOL_SOCKET, SO_SNDBUF, &kMaxMessageSize, sizeof(int)) != 0 ||
-        setsockopt(fds[1], SOL_SOCKET, SO_SNDBUF, &kMaxMessageSize, sizeof(int)) != 0) {
+    if (setsockopt(fds[0], SOL_SOCKET, SO_SNDBUFFORCE, &kMaxMessageSize, sizeof(int)) != 0 ||
+        setsockopt(fds[1], SOL_SOCKET, SO_SNDBUFFORCE, &kMaxMessageSize, sizeof(int)) != 0) {
         PLOG(ERROR) << "Failed to update buffer size for socket";
         return false;
     }
diff --git a/libcrypto_utils/Android.bp b/libcrypto_utils/Android.bp
index f2560e6..4a5f2a7 100644
--- a/libcrypto_utils/Android.bp
+++ b/libcrypto_utils/Android.bp
@@ -16,6 +16,7 @@
 
 cc_library {
     name: "libcrypto_utils",
+    vendor_available: true,
     host_supported: true,
     srcs: [
         "android_pubkey.c",
diff --git a/libcutils/fs_config.c b/libcutils/fs_config.c
index 17d7cb9..d98a923 100644
--- a/libcutils/fs_config.c
+++ b/libcutils/fs_config.c
@@ -214,6 +214,9 @@
     /* Support wifi_hal_legacy administering a network interface. */
     { 00755, AID_WIFI,      AID_WIFI,      CAP_MASK_LONG(CAP_NET_ADMIN) |
                                            CAP_MASK_LONG(CAP_NET_RAW),
+                                              "system/vendor/bin/hw/android.hardware.wifi@1.0-service" },
+    { 00755, AID_WIFI,      AID_WIFI,      CAP_MASK_LONG(CAP_NET_ADMIN) |
+                                           CAP_MASK_LONG(CAP_NET_RAW),
                                               "vendor/bin/hw/android.hardware.wifi@1.0-service" },
 
     /* A non-privileged zygote that spawns
diff --git a/liblog/tests/liblog_test.cpp b/liblog/tests/liblog_test.cpp
index ec32da0..71f74ab 100644
--- a/liblog/tests/liblog_test.cpp
+++ b/liblog/tests/liblog_test.cpp
@@ -36,6 +36,7 @@
 #endif
 #include <gtest/gtest.h>
 #include <log/log_event_list.h>
+#include <log/log_properties.h>
 #include <log/log_transport.h>
 #include <log/logprint.h>
 #include <private/android_filesystem_config.h>
@@ -1786,6 +1787,12 @@
         stderr,
         "WARNING: test conditions request being run as root and not AID=%d\n",
         getuid());
+    if (!__android_log_is_debuggable()) {
+      fprintf(
+          stderr,
+          "WARNING: can not run test on a \"user\" build, bypassing test\n");
+      return;
+    }
   }
 
   system((getuid() == AID_ROOT) ? "stop logd" : "su 0 stop logd");
diff --git a/liblog/tests/log_read_test.cpp b/liblog/tests/log_read_test.cpp
index a63ab8e..6ed568a 100644
--- a/liblog/tests/log_read_test.cpp
+++ b/liblog/tests/log_read_test.cpp
@@ -23,6 +23,7 @@
 #include <android-base/stringprintf.h>
 #include <android/log.h>  // minimal logging API
 #include <gtest/gtest.h>
+#include <log/log_properties.h>
 // Test the APIs in this standalone include file
 #include <log/log_read.h>
 // Do not use anything in log/log_time.h despite side effects of the above.
@@ -97,9 +98,12 @@
     /* security buffer is allowed to be denied */
     if (strcmp("security", name)) {
       EXPECT_LT(0, get_log_size);
-      /* crash buffer is allowed to be empty, that is actually healthy! */
-      EXPECT_LE((strcmp("crash", name)) != 0,
-                android_logger_get_log_readable_size(logger));
+      // crash buffer is allowed to be empty, that is actually healthy!
+      // kernel buffer is allowed to be empty on "user" builds
+      EXPECT_LE(  // boolean 1 or 0 depending on expected content or empty
+          !!((strcmp("crash", name) != 0) &&
+             ((strcmp("kernel", name) != 0) || __android_log_is_debuggable())),
+          android_logger_get_log_readable_size(logger));
     } else {
       EXPECT_NE(0, get_log_size);
       if (get_log_size < 0) {
diff --git a/libnativebridge/.clang-format b/libnativebridge/.clang-format
new file mode 120000
index 0000000..fd0645f
--- /dev/null
+++ b/libnativebridge/.clang-format
@@ -0,0 +1 @@
+../.clang-format-2
\ No newline at end of file
diff --git a/libnativebridge/native_bridge.cc b/libnativebridge/native_bridge.cc
index 7976f67..cc30aaf 100644
--- a/libnativebridge/native_bridge.cc
+++ b/libnativebridge/native_bridge.cc
@@ -85,12 +85,14 @@
 // Nativebridge implementation.
 // Used by isCompatibleWith() which is introduced in v2.
 enum NativeBridgeImplementationVersion {
-    // first version, not used.
-    DEFAULT_VERSION = 1,
-    // The version which signal semantic is introduced.
-    SIGNAL_VERSION = 2,
-    // The version which namespace semantic is introduced.
-    NAMESPACE_VERSION = 3,
+  // first version, not used.
+  DEFAULT_VERSION = 1,
+  // The version which signal semantic is introduced.
+  SIGNAL_VERSION = 2,
+  // The version which namespace semantic is introduced.
+  NAMESPACE_VERSION = 3,
+  // The version with vendor namespaces
+  VENDOR_NAMESPACE_VERSION = 4,
 };
 
 // Whether we had an error at some point.
@@ -621,6 +623,14 @@
     return false;
 }
 
+native_bridge_namespace_t* NativeBridgeGetVendorNamespace() {
+  if (!NativeBridgeInitialized() || !isCompatibleWith(VENDOR_NAMESPACE_VERSION)) {
+    return nullptr;
+  }
+
+  return callbacks->getVendorNamespace();
+}
+
 void* NativeBridgeLoadLibraryExt(const char* libpath, int flag, native_bridge_namespace_t* ns) {
   if (NativeBridgeInitialized()) {
     if (isCompatibleWith(NAMESPACE_VERSION)) {
diff --git a/libnativeloader/.clang-format b/libnativeloader/.clang-format
new file mode 120000
index 0000000..fd0645f
--- /dev/null
+++ b/libnativeloader/.clang-format
@@ -0,0 +1 @@
+../.clang-format-2
\ No newline at end of file
diff --git a/libnativeloader/include/nativeloader/dlext_namespaces.h b/libnativeloader/include/nativeloader/dlext_namespaces.h
index 9121277..43c9329 100644
--- a/libnativeloader/include/nativeloader/dlext_namespaces.h
+++ b/libnativeloader/include/nativeloader/dlext_namespaces.h
@@ -124,6 +124,8 @@
  */
 extern void android_get_LD_LIBRARY_PATH(char* buffer, size_t buffer_size);
 
+extern android_namespace_t* android_get_exported_namespace(const char* name);
+
 __END_DECLS
 
 #endif /* __ANDROID_DLEXT_NAMESPACES_H__ */
diff --git a/libnativeloader/native_loader.cpp b/libnativeloader/native_loader.cpp
index 100c31d..36a2e44 100644
--- a/libnativeloader/native_loader.cpp
+++ b/libnativeloader/native_loader.cpp
@@ -83,6 +83,12 @@
 static constexpr const char* kPublicNativeLibrariesVendorConfig =
                                   "/vendor/etc/public.libraries.txt";
 
+// The device may be configured to have the vendor libraries loaded to a separate namespace.
+// For historical reasons this namespace was named sphal but effectively it is intended
+// to use to load vendor libraries to separate namespace with controlled interface between
+// vendor and system namespaces.
+static constexpr const char* kVendorNamespaceName = "sphal";
+
 // (http://b/27588281) This is a workaround for apps using custom classloaders and calling
 // System.load() with an absolute path which is outside of the classloader library search path.
 // This list includes all directories app is allowed to access this way.
@@ -170,11 +176,23 @@
         return false;
       }
 
-      if (!android_link_namespaces(ns, nullptr, public_libraries_.c_str())) {
+      // Note that when vendor_ns is not configured this function will return nullptr
+      // and it will result in linking vendor_public_libraries_ to the default namespace
+      // which is expected behavior in this case.
+      android_namespace_t* vendor_ns = android_get_exported_namespace(kVendorNamespaceName);
+
+      if (!android_link_namespaces(ns, nullptr, system_public_libraries_.c_str())) {
         *error_msg = dlerror();
         return false;
       }
 
+      if (!vendor_public_libraries_.empty()) {
+        if (!android_link_namespaces(ns, vendor_ns, vendor_public_libraries_.c_str())) {
+          *error_msg = dlerror();
+          return false;
+        }
+      }
+
       native_loader_ns = NativeLoaderNamespace(ns);
     } else {
       native_bridge_namespace_t* ns = NativeBridgeCreateNamespace("classloader-namespace",
@@ -183,14 +201,24 @@
                                                                   namespace_type,
                                                                   permitted_path.c_str(),
                                                                   parent_ns.get_native_bridge_ns());
+
       if (ns == nullptr) {
         *error_msg = NativeBridgeGetError();
         return false;
       }
 
-      if (!NativeBridgeLinkNamespaces(ns, nullptr, public_libraries_.c_str())) {
+      native_bridge_namespace_t* vendor_ns = NativeBridgeGetVendorNamespace();
+
+      if (!NativeBridgeLinkNamespaces(ns, nullptr, system_public_libraries_.c_str())) {
+        *error_msg = NativeBridgeGetError();
+        return false;
+      }
+
+      if (!vendor_public_libraries_.empty()) {
+        if (!NativeBridgeLinkNamespaces(ns, vendor_ns, vendor_public_libraries_.c_str())) {
           *error_msg = NativeBridgeGetError();
           return false;
+        }
       }
 
       native_loader_ns = NativeLoaderNamespace(ns);
@@ -249,9 +277,6 @@
       }
     }
 
-    // This file is optional, quietly ignore if the file does not exist.
-    ReadConfig(kPublicNativeLibrariesVendorConfig, &sonames);
-
     // android_init_namespaces() expects all the public libraries
     // to be loaded so that they can be found by soname alone.
     //
@@ -266,7 +291,13 @@
                           soname.c_str(), dlerror());
     }
 
-    public_libraries_ = base::Join(sonames, ':');
+    system_public_libraries_ = base::Join(sonames, ':');
+
+    sonames.clear();
+    // This file is optional, quietly ignore if the file does not exist.
+    ReadConfig(kPublicNativeLibrariesVendorConfig, &sonames);
+
+    vendor_public_libraries_ = base::Join(sonames, ':');
   }
 
   void Reset() {
@@ -325,7 +356,7 @@
     // code is one example) unknown to linker in which  case linker uses anonymous
     // namespace. The second argument specifies the search path for the anonymous
     // namespace which is the library_path of the classloader.
-    initialized_ = android_init_anonymous_namespace(public_libraries_.c_str(),
+    initialized_ = android_init_anonymous_namespace(system_public_libraries_.c_str(),
                                                     is_native_bridge ? nullptr : library_path);
     if (!initialized_) {
       *error_msg = dlerror();
@@ -334,10 +365,10 @@
 
     // and now initialize native bridge namespaces if necessary.
     if (NativeBridgeInitialized()) {
-        initialized_ = NativeBridgeInitAnonymousNamespace(
-            public_libraries_.c_str(), is_native_bridge ? library_path : nullptr);
-        if (!initialized_) {
-            *error_msg = NativeBridgeGetError();
+      initialized_ = NativeBridgeInitAnonymousNamespace(system_public_libraries_.c_str(),
+                                                        is_native_bridge ? library_path : nullptr);
+      if (!initialized_) {
+        *error_msg = NativeBridgeGetError();
       }
     }
 
@@ -371,8 +402,8 @@
 
   bool initialized_;
   std::vector<std::pair<jweak, NativeLoaderNamespace>> namespaces_;
-  std::string public_libraries_;
-
+  std::string system_public_libraries_;
+  std::string vendor_public_libraries_;
 
   DISALLOW_COPY_AND_ASSIGN(LibraryNamespaces);
 };
diff --git a/libutils/Android.bp b/libutils/Android.bp
index 696db3b..5e76279 100644
--- a/libutils/Android.bp
+++ b/libutils/Android.bp
@@ -94,6 +94,7 @@
                 "libcutils",
                 "libdl",
                 "liblog",
+                "libvndksupport",
             ],
 
             sanitize: {
diff --git a/libutils/misc.cpp b/libutils/misc.cpp
index ab72fe6..d95fd05 100644
--- a/libutils/misc.cpp
+++ b/libutils/misc.cpp
@@ -23,6 +23,13 @@
 #include <utils/Log.h>
 #include <utils/Vector.h>
 
+#if defined(__ANDROID__)
+#include <dlfcn.h>
+#include <vndksupport/linker.h>
+#endif
+
+extern "C" void do_report_sysprop_change();
+
 using namespace android;
 
 namespace android {
@@ -61,7 +68,36 @@
 #endif
 }
 
+#if defined(__ANDROID__)
+void (*get_report_sysprop_change_func())() {
+    void (*func)() = nullptr;
+    void* handle = android_load_sphal_library("libutils.so", RTLD_NOW);
+    if (handle != nullptr) {
+        func = reinterpret_cast<decltype(func)>(dlsym(handle, "do_report_sysprop_change"));
+    }
+
+    return func;
+}
+#endif
+
 void report_sysprop_change() {
+    do_report_sysprop_change();
+
+#if defined(__ANDROID__)
+    // libutils.so is double loaded; from the default namespace and from the
+    // 'sphal' namespace. Redirect the sysprop change event to the other instance
+    // of libutils.so loaded in the 'sphal' namespace so that listeners attached
+    // to that instance is also notified with this event.
+    static auto func = get_report_sysprop_change_func();
+    if (func != nullptr) {
+        (*func)();
+    }
+#endif
+}
+
+};  // namespace android
+
+void do_report_sysprop_change() {
 #if !defined(_WIN32)
     pthread_mutex_lock(&gSyspropMutex);
     Vector<sysprop_change_callback_info> listeners;
@@ -76,5 +112,3 @@
     }
 #endif
 }
-
-}; // namespace android
diff --git a/libvndksupport/Android.bp b/libvndksupport/Android.bp
new file mode 100644
index 0000000..b624223
--- /dev/null
+++ b/libvndksupport/Android.bp
@@ -0,0 +1,15 @@
+subdirs = ["tests"]
+
+cc_library {
+    name: "libvndksupport",
+    srcs: ["linker.c"],
+    local_include_dirs: ["include/vndksupport"],
+    export_include_dirs: ["include"],
+    shared_libs: ["liblog"],
+}
+
+llndk_library {
+    name: "libvndksupport",
+    symbol_file: "libvndksupport.map.txt",
+    export_include_dirs: ["include"],
+}
diff --git a/libvndksupport/include/vndksupport/linker.h b/libvndksupport/include/vndksupport/linker.h
new file mode 100644
index 0000000..f509564
--- /dev/null
+++ b/libvndksupport/include/vndksupport/linker.h
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2017 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 VNDKSUPPORT_LINKER_H_
+#define VNDKSUPPORT_LINKER_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void* android_load_sphal_library(const char* name, int flag);
+
+int android_unload_sphal_library(void* handle);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif  // VNDKSUPPORT_LINKER_H_
diff --git a/libvndksupport/libvndksupport.map.txt b/libvndksupport/libvndksupport.map.txt
new file mode 100644
index 0000000..16e38da
--- /dev/null
+++ b/libvndksupport/libvndksupport.map.txt
@@ -0,0 +1,7 @@
+LIBVNDKSUPPORT {
+  global:
+    android_load_sphal_library; # vndk
+    android_unload_sphal_library; # vndk
+  local:
+    *;
+};
diff --git a/libvndksupport/linker.c b/libvndksupport/linker.c
new file mode 100644
index 0000000..12aa3be
--- /dev/null
+++ b/libvndksupport/linker.c
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2017 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.
+ */
+#include "linker.h"
+
+#include <android/dlext.h>
+#include <dlfcn.h>
+
+#define LOG_TAG "vndksupport"
+#include <log/log.h>
+
+extern struct android_namespace_t* android_get_exported_namespace(const char*);
+
+void* android_load_sphal_library(const char* name, int flag) {
+    struct android_namespace_t* sphal_namespace = android_get_exported_namespace("sphal");
+    if (sphal_namespace != NULL) {
+        const android_dlextinfo dlextinfo = {
+            .flags = ANDROID_DLEXT_USE_NAMESPACE, .library_namespace = sphal_namespace,
+        };
+        void* handle = android_dlopen_ext(name, flag, &dlextinfo);
+        if (handle) {
+            return handle;
+        } else {
+            ALOGW(
+                "Could not load %s from sphal namespace: %s. "
+                "Falling back to loading it from the current namespace,",
+                name, dlerror());
+        }
+    } else {
+        ALOGI(
+            "sphal namespace is not configured for this process. "
+            "Loading %s from the current namespace instead.",
+            name);
+    }
+    return dlopen(name, flag);
+}
+
+int android_unload_sphal_library(void* handle) { return dlclose(handle); }
diff --git a/libvndksupport/tests/Android.bp b/libvndksupport/tests/Android.bp
new file mode 100644
index 0000000..3587cf8
--- /dev/null
+++ b/libvndksupport/tests/Android.bp
@@ -0,0 +1,26 @@
+// Copyright (C) 2017 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.
+
+cc_test {
+    name: "libvndksupport-tests",
+    srcs: [
+        "linker_test.cpp",
+    ],
+
+    host_supported: false,
+    shared_libs: [
+        "libvndksupport",
+        "libbase",
+    ]
+}
diff --git a/libvndksupport/tests/linker_test.cpp b/libvndksupport/tests/linker_test.cpp
new file mode 100644
index 0000000..7ce27d4
--- /dev/null
+++ b/libvndksupport/tests/linker_test.cpp
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2017 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.
+ */
+#include <gtest/gtest.h>
+
+#include <android-base/strings.h>
+#include <dirent.h>
+#include <dlfcn.h>
+#include <vndksupport/linker.h>
+#include <string>
+
+// Since the test executable will be in /data and ld.config.txt does not
+// configure sphal namespace for executables in /data, the call to
+// android_load_sphal_library will always fallback to the plain dlopen from the
+// default namespace.
+
+// Let's use libEGL_<chipset>.so as a SP-HAL in test
+static std::string find_sphal_lib() {
+    const char* path =
+#if defined(__LP64__)
+        "/vendor/lib64/egl";
+#else
+        "/vendor/lib/egl";
+#endif
+    std::unique_ptr<DIR, decltype(&closedir)> dir(opendir(path), closedir);
+
+    dirent* dp;
+    while ((dp = readdir(dir.get())) != nullptr) {
+        std::string name = dp->d_name;
+        if (android::base::StartsWith(name, "libEGL_")) {
+            return std::string(path) + "/" + name;
+        }
+    }
+    return "";
+}
+
+TEST(linker, load_existing_lib) {
+    std::string name = find_sphal_lib();
+    ASSERT_NE("", name);
+    void* handle = android_load_sphal_library(name.c_str(), RTLD_NOW | RTLD_LOCAL);
+    ASSERT_NE(nullptr, handle);
+    android_unload_sphal_library(handle);
+}
+
+TEST(linker, load_nonexisting_lib) {
+    void* handle = android_load_sphal_library("libNeverUseThisName.so", RTLD_NOW | RTLD_LOCAL);
+    ASSERT_EQ(nullptr, handle);
+}
diff --git a/libziparchive/Android.bp b/libziparchive/Android.bp
index 44daf36..0a4f088 100644
--- a/libziparchive/Android.bp
+++ b/libziparchive/Android.bp
@@ -56,6 +56,8 @@
 cc_library {
     name: "libziparchive",
     host_supported: true,
+    vendor_available:true,
+
     defaults: ["libziparchive_defaults", "libziparchive_flags"],
     shared_libs: ["liblog", "libbase"],
     target: {
diff --git a/rootdir/etc/ld.config.txt b/rootdir/etc/ld.config.txt
index e8a34bf..5961411 100644
--- a/rootdir/etc/ld.config.txt
+++ b/rootdir/etc/ld.config.txt
@@ -60,11 +60,7 @@
 namespace.sphal.links = default,vndk,rs
 
 # WARNING: only NDK libs can be listed here.
-# However, this is commented out because some SP-HALs (gralloc.msm8996.so, etc)
-# are currently using some non-stable libs such as libbacktrace.so. We will get back
-# to this list once the dependencies are fixed.
-#namespace.sphal.link.default.shared_libs = libc.so:libz.so:libm.so:libdl.so:libstdc++.so:liblog.so:libnativewindow.so:libsync.so
-namespace.sphal.link.default.shared_libs = libc.so:libz.so:libm.so:libdl.so:libstdc++.so:liblog.so:libnativewindow.so:libEGL.so:libsync.so:libbacktrace.so:libGLESv1_CM.so:libGLESv2.so
+namespace.sphal.link.default.shared_libs = libc.so:libz.so:libm.so:libdl.so:libstdc++.so:liblog.so:libnativewindow.so:libEGL.so:libsync.so:libGLESv1_CM.so:libGLESv2.so:libvndksupport.so
 
 # WARNING: only VNDK-SP libs can be listed here. DO NOT EDIT this line.
 namespace.sphal.link.vndk.shared_libs = android.hardware.renderscript@1.0.so:android.hardware.graphics.allocator@2.0.so:android.hardware.graphics.mapper@2.0.so:android.hardware.graphics.common@1.0.so:android.hidl.base@1.0.so:libhwbinder.so:libbase.so:libcutils.so:libhardware.so:libhidlbase.so:libhidltransport.so:libutils.so:libc++.so
@@ -81,11 +77,14 @@
 # to load the compiled *.so file and libmediandk.so can be used here.
 ###############################################################################
 namespace.rs.isolated = true
-namespace.rs.search.paths = /system/${LIB}/vndk-sp:/vendor/${LIB}
+namespace.rs.search.paths = /vendor/${LIB}/vndk-sp:/system/${LIB}/vndk-sp:/vendor/${LIB}
 namespace.rs.permitted.paths = /vendor/${LIB}:/data
 
+namespace.rs.asan.search.paths = /data/asan/vendor/${LIB}/vndk-sp:/vendor/${LIB}/vndk-sp:/data/asan/system/${LIB}/vndk-sp:/system/${LIB}/vndk-sp:/data/asan/vendor/${LIB}:/vendor/${LIB}
+namespace.rs.asan.permitted.paths = /data/asan/vendor/${LIB}:/vendor/${LIB}:/data
+
 namespace.rs.links = default,vndk
-namespace.rs.link.default.shared_libs = libc.so:libz.so:libm.so:libdl.so:libstdc++.so:liblog.so:libnativewindow.so:libEGL.so:libsync.so:libbacktrace.so:libGLESv1_CM.so:libGLESv2.so:libmediandk.so:libui.so
+namespace.rs.link.default.shared_libs = libc.so:libz.so:libm.so:libdl.so:libstdc++.so:liblog.so:libnativewindow.so:libEGL.so:libsync.so:libGLESv1_CM.so:libGLESv2.so:libmediandk.so:libui.so:libvndksupport.so
 namespace.rs.link.vndk.shared_libs = android.hardware.renderscript@1.0.so:android.hardware.graphics.allocator@2.0.so:android.hardware.graphics.mapper@2.0.so:android.hardware.graphics.common@1.0.so:android.hidl.base@1.0.so:libhwbinder.so:libbase.so:libcutils.so:libhardware.so:libhidlbase.so:libhidltransport.so:libutils.so:libc++.so
 
 ###############################################################################
@@ -94,27 +93,21 @@
 # This namespace is exclusively for vndk-sp libs.
 ###############################################################################
 namespace.vndk.isolated = true
-namespace.vndk.search.paths = /system/${LIB}/vndk-sp:/vendor/${LIB}
+namespace.vndk.search.paths = /vendor/${LIB}/vndk-sp:/system/${LIB}/vndk-sp:/vendor/${LIB}
 namespace.vndk.permitted.paths = /vendor/${LIB}/hw:/vendor/${LIB}/egl
 
-namespace.vndk.asan.search.paths = /data/asan/system/${LIB}/vndk-sp:/system/${LIB}/vndk-sp:/data/asan/vendor/${LIB}:/vendor/${LIB}
+namespace.vndk.asan.search.paths = /data/asan/vendor/${LIB}/vndk-sp:/vendor/${LIB}/vndk-sp:/data/asan/system/${LIB}/vndk-sp:/system/${LIB}/vndk-sp:/data/asan/vendor/${LIB}:/vendor/${LIB}
 namespace.vndk.asan.permitted.paths = /data/asan/vendor/${LIB}/hw:/vendor/${LIB}/hw:/data/asan/vendor/${LIB}/egl:/vendor/${LIB}/egl
 
 # When these NDK libs are required inside this namespace, then it is redirected
 # to the default namespace. This is possible since their ABI is stable across
 # Android releases.
 namespace.vndk.links = default
-
-# WARNING: only NDK libs can be listed here.
-# However, this is commented out because some SP-HALs (gralloc.msm8996.so, etc)
-# are currently using some non-stable libs such as libbacktrace.so. We will get back
-# to this list once the dependencies are fixed.
-#namespace.vndk.link.default.shared_libs = libc.so:libz.so:libm.so:libdl.so:libstdc++.so:liblog.so:libnativewindow.so:libsync.so
-namespace.vndk.link.default.shared_libs = libc.so:libz.so:libm.so:libdl.so:libstdc++.so:liblog.so:libnativewindow.so:libEGL.so:libsync.so:libbacktrace.so
+namespace.vndk.link.default.shared_libs = libc.so:libz.so:libm.so:libdl.so:libstdc++.so:liblog.so:libnativewindow.so:libEGL.so:libsync.so:libvndksupport.so
 
 
 [vendor]
 namespace.default.isolated = false
-namespace.default.search.paths = /vendor/${LIB}:/system/${LIB}/vndk-sp:/system/${LIB}
+namespace.default.search.paths = /vendor/${LIB}:/vendor/${LIB}/vndk-sp:/system/${LIB}/vndk-sp:/system/${LIB}
 
-namespace.default.asan.search.paths = /data/asan/vendor/${LIB}:/vendor/${LIB}:/data/asan/system/${LIB}/vndk-sp:/system/${LIB}/vndk-sp:/data/asan/system/${LIB}:/system/${LIB}
+namespace.default.asan.search.paths = /data/asan/vendor/${LIB}:/vendor/${LIB}:/data/asan/vendor/${LIB}/vndk-sp:/vendor/${LIB}/vndk-sp:/data/asan/system/${LIB}/vndk-sp:/system/${LIB}/vndk-sp:/data/asan/system/${LIB}:/system/${LIB}
diff --git a/rootdir/init.rc b/rootdir/init.rc
index 944aae7..3b996a4 100644
--- a/rootdir/init.rc
+++ b/rootdir/init.rc
@@ -7,6 +7,7 @@
 import /init.environ.rc
 import /init.usb.rc
 import /init.${ro.hardware}.rc
+import /vendor/etc/init/hw/init.${ro.hardware}.rc
 import /init.usb.configfs.rc
 import /init.${ro.zygote}.rc
 
diff --git a/shell_and_utilities/Android.bp b/shell_and_utilities/Android.bp
new file mode 100644
index 0000000..4f4fc5d
--- /dev/null
+++ b/shell_and_utilities/Android.bp
@@ -0,0 +1,16 @@
+phony {
+    name: "shell_and_utilities",
+    required: [
+        "bzip2",
+        "grep",
+        "gzip",
+        "mkshrc",
+        "mkshrc_vendor",
+        "reboot",
+        "sh",
+        "sh_vendor",
+        "toolbox",
+        "toybox",
+        "toybox_vendor",
+    ],
+}