Merge "Convert libnetutils to Android.bp" into oc-dev
diff --git a/debuggerd/debuggerd_test.cpp b/debuggerd/debuggerd_test.cpp
index b705e27..568879e 100644
--- a/debuggerd/debuggerd_test.cpp
+++ b/debuggerd/debuggerd_test.cpp
@@ -78,6 +78,14 @@
     }                                                                           \
   } while (0)
 
+#define ASSERT_NOT_MATCH(str, pattern)                                                      \
+  do {                                                                                      \
+    std::regex r((pattern));                                                                \
+    if (std::regex_search((str), r)) {                                                      \
+      FAIL() << "regex mismatch: expected to not find " << (pattern) << " in: \n" << (str); \
+    }                                                                                       \
+  } while (0)
+
 static void tombstoned_intercept(pid_t target_pid, unique_fd* intercept_fd, unique_fd* output_fd) {
   intercept_fd->reset(socket_local_client(kTombstonedInterceptSocketName,
                                           ANDROID_SOCKET_NAMESPACE_RESERVED, SOCK_SEQPACKET));
@@ -226,12 +234,14 @@
     FAIL() << "failed to wait for crasher: " << strerror(errno);
   }
 
-  if (WIFEXITED(status)) {
-    FAIL() << "crasher failed to exec: " << strerror(WEXITSTATUS(status));
-  } else if (!WIFSIGNALED(status)) {
-    FAIL() << "crasher didn't terminate via a signal";
+  if (signo == 0) {
+    ASSERT_TRUE(WIFEXITED(status));
+    ASSERT_EQ(0, WEXITSTATUS(signo));
+  } else {
+    ASSERT_FALSE(WIFEXITED(status));
+    ASSERT_TRUE(WIFSIGNALED(status)) << "crasher didn't terminate via a signal";
+    ASSERT_EQ(signo, WTERMSIG(status));
   }
-  ASSERT_EQ(signo, WTERMSIG(status));
   crasher_pid = -1;
 }
 
@@ -336,6 +346,26 @@
   ASSERT_MATCH(result, R"(Abort message: 'abort message goes here')");
 }
 
+TEST_F(CrasherTest, abort_message_backtrace) {
+  int intercept_result;
+  unique_fd output_fd;
+  StartProcess([]() {
+    android_set_abort_message("not actually aborting");
+    raise(DEBUGGER_SIGNAL);
+    exit(0);
+  });
+  StartIntercept(&output_fd);
+  FinishCrasher();
+  AssertDeath(0);
+  FinishIntercept(&intercept_result);
+
+  ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
+
+  std::string result;
+  ConsumeFd(std::move(output_fd), &result);
+  ASSERT_NOT_MATCH(result, R"(Abort message:)");
+}
+
 TEST_F(CrasherTest, intercept_timeout) {
   int intercept_result;
   unique_fd output_fd;
diff --git a/debuggerd/handler/debuggerd_handler.cpp b/debuggerd/handler/debuggerd_handler.cpp
index cd00dc5..b70554f 100644
--- a/debuggerd/handler/debuggerd_handler.cpp
+++ b/debuggerd/handler/debuggerd_handler.cpp
@@ -389,8 +389,9 @@
 
   log_signal_summary(signal_number, info);
 
-  // Populate si_value with the abort message address, if found.
-  if (abort_message) {
+  // If this was a fatal crash, populate si_value with the abort message address if possible.
+  // Note that applications can set an abort message without aborting.
+  if (abort_message && signal_number != DEBUGGER_SIGNAL) {
     info->si_value.sival_ptr = abort_message;
   }
 
diff --git a/init/Android.mk b/init/Android.mk
index 3c878b5..42e42ec 100644
--- a/init/Android.mk
+++ b/init/Android.mk
@@ -85,6 +85,7 @@
     builtins.cpp \
     devices.cpp \
     init.cpp \
+    init_first_stage.cpp \
     keychords.cpp \
     property_service.cpp \
     reboot.cpp \
@@ -141,6 +142,7 @@
 LOCAL_SRC_FILES := \
     init_parser_test.cpp \
     property_service_test.cpp \
+    service_test.cpp \
     util_test.cpp \
 
 LOCAL_SHARED_LIBRARIES += \
diff --git a/init/init.cpp b/init/init.cpp
index 9cdbd19..84e4f84 100644
--- a/init/init.cpp
+++ b/init/init.cpp
@@ -50,16 +50,14 @@
 
 #include <fstream>
 #include <memory>
-#include <set>
 #include <vector>
 
 #include "action.h"
 #include "bootchart.h"
 #include "devices.h"
-#include "fs_mgr.h"
-#include "fs_mgr_avb.h"
 #include "import_parser.h"
 #include "init.h"
+#include "init_first_stage.h"
 #include "init_parser.h"
 #include "keychords.h"
 #include "log.h"
@@ -485,71 +483,10 @@
     }
 }
 
-/* Reads the content of device tree file into dt_value.
- * Returns true if the read is success, false otherwise.
- */
-static bool read_dt_file(const std::string& file_name, std::string* dt_value) {
-    if (android::base::ReadFileToString(file_name, dt_value)) {
-        if (!dt_value->empty()) {
-            dt_value->pop_back();  // Trim the trailing '\0' out.
-            return true;
-        }
-    }
-    return false;
-}
-
-static const std::string kAndroidDtDir("/proc/device-tree/firmware/android/");
-
-static bool is_dt_value_expected(const std::string& dt_file_suffix,
-                                 const std::string& expected_value) {
-    std::string dt_value;
-    std::string file_name = kAndroidDtDir + dt_file_suffix;
-
-    if (read_dt_file(file_name, &dt_value)) {
-        if (dt_value == expected_value) {
-            return true;
-        }
-    }
-    return false;
-}
-
-static inline bool is_dt_compatible() {
-    return is_dt_value_expected("compatible", "android,firmware");
-}
-
-static inline bool is_dt_fstab_compatible() {
-    return is_dt_value_expected("fstab/compatible", "android,fstab");
-}
-
-static inline bool is_dt_vbmeta_compatible() {
-    return is_dt_value_expected("vbmeta/compatible", "android,vbmeta");
-}
-
-// Gets the vbmeta config from device tree. Specifically, the 'parts' and 'by_name_prefix'.
-// /{
-//     firmware {
-//         android {
-//             vbmeta {
-//                 compatible = "android,vbmeta";
-//                 parts = "vbmeta,boot,system,vendor"
-//                 by_name_prefix="/dev/block/platform/soc.0/f9824900.sdhci/by-name/"
-//             };
-//         };
-//     };
-//  }
-static bool get_vbmeta_config_from_dt(std::string* vbmeta_partitions,
-                                      std::string* device_file_by_name_prefix) {
-    std::string file_name = kAndroidDtDir + "vbmeta/parts";
-    if (!read_dt_file(file_name, vbmeta_partitions)) return false;
-
-    file_name = kAndroidDtDir + "vbmeta/by_name_prefix";
-    if (!read_dt_file(file_name, device_file_by_name_prefix)) return false;
-
-    return true;
-}
-
 static void process_kernel_dt() {
-    if (!is_dt_compatible()) return;
+    if (!is_android_dt_value_expected("compatible", "android,firmware")) {
+        return;
+    }
 
     std::unique_ptr<DIR, int (*)(DIR*)> dir(opendir(kAndroidDtDir.c_str()), closedir);
     if (!dir) return;
@@ -982,289 +919,6 @@
     }
 }
 
-// Creates "/dev/block/dm-XX" for dm-verity by running coldboot on /sys/block/dm-XX.
-static void device_init_dm_device(const std::string& dm_device) {
-    const std::string device_name(basename(dm_device.c_str()));
-    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) {
-            LOG(VERBOSE) << "early_mount: creating dm-verity device : " << dm_device;
-            return COLDBOOT_STOP;
-        }
-        return COLDBOOT_CONTINUE;
-    });
-    device_close();
-}
-
-static bool vboot_1_0_mount_partitions(const std::vector<fstab_rec*>& fstab_recs) {
-    if (fstab_recs.empty()) return false;
-
-    for (auto rec : fstab_recs) {
-        bool need_create_dm_device = false;
-        if (fs_mgr_is_verified(rec)) {
-            // setup verity and create the dm-XX block device
-            // needed to mount this partition
-            int ret = fs_mgr_setup_verity(rec, false /* wait_for_verity_dev */);
-            if (ret == FS_MGR_SETUP_VERITY_DISABLED) {
-                LOG(INFO) << "verity disabled for '" << rec->mount_point << "'";
-            } else if (ret == FS_MGR_SETUP_VERITY_SUCCESS) {
-                need_create_dm_device = true;
-            } else {
-                PLOG(ERROR) << "early_mount: failed to setup verity for '" << rec->mount_point
-                            << "'";
-                return false;
-            }
-        }
-        if (need_create_dm_device) {
-            // The exact block device name (rec->blk_device) is changed to "/dev/block/dm-XX".
-            // Need to create it because ueventd isn't started during early mount.
-            device_init_dm_device(rec->blk_device);
-        }
-        if (fs_mgr_do_mount_one(rec)) {
-            PLOG(ERROR) << "early_mount: failed to mount '" << rec->mount_point << "'";
-            return false;
-        }
-    }
-
-    return true;
-}
-
-static bool vboot_2_0_mount_partitions(const std::vector<fstab_rec*>& fstab_recs,
-                                       const std::string& device_file_by_name_prefix) {
-    if (fstab_recs.empty()) return false;
-
-    FsManagerAvbUniquePtr avb_handle = FsManagerAvbHandle::Open(device_file_by_name_prefix);
-    if (!avb_handle) {
-        LOG(INFO) << "Failed to Open FsManagerAvbHandle";
-        return false;
-    }
-
-    setenv("INIT_AVB_VERSION", avb_handle->avb_version().c_str(), 1);
-    for (auto rec : fstab_recs) {
-        bool need_create_dm_device = false;
-        if (fs_mgr_is_avb(rec)) {
-            if (avb_handle->hashtree_disabled()) {
-                LOG(INFO) << "avb hashtree disabled for '" << rec->mount_point << "'";
-            } else if (avb_handle->SetUpAvb(rec, false /* wait_for_verity_dev */)) {
-                need_create_dm_device = true;
-            } else {
-                PLOG(ERROR) << "early_mount: failed to set up AVB on partition: '"
-                            << rec->mount_point << "'";
-                return false;
-            }
-        }
-        if (need_create_dm_device) {
-            // The exact block device name (rec->blk_device) is changed to "/dev/block/dm-XX".
-            // Need to create it because ueventd isn't started during early mount.
-            device_init_dm_device(rec->blk_device);
-        }
-        if (fs_mgr_do_mount_one(rec)) {
-            PLOG(ERROR) << "early_mount: failed to mount '" << rec->mount_point << "'";
-            return false;
-        }
-    }
-
-    return true;
-}
-
-static bool mount_early_partitions(const std::vector<fstab_rec*>& fstab_recs,
-                                   const std::string& device_file_by_name_prefix) {
-    if (is_dt_vbmeta_compatible()) {  // AVB (external/avb) is used to setup dm-verity.
-        return vboot_2_0_mount_partitions(fstab_recs, device_file_by_name_prefix);
-    } else {
-        return vboot_1_0_mount_partitions(fstab_recs);
-    }
-}
-
-// Creates devices with uevent->partition_name matching one in the in/out
-// partition_names. Note that the partition_names MUST have A/B suffix
-// when A/B is used. Found partitions will then be removed from the
-// partition_names for caller to check which devices are NOT created.
-static void early_device_init(std::set<std::string>* partition_names) {
-    if (partition_names->empty()) {
-        return;
-    }
-    device_init(nullptr, [=](uevent* uevent) -> coldboot_action_t {
-        if (!strncmp(uevent->subsystem, "firmware", 8)) {
-            return COLDBOOT_CONTINUE;
-        }
-
-        // we need platform devices to create symlinks
-        if (!strncmp(uevent->subsystem, "platform", 8)) {
-            return COLDBOOT_CREATE;
-        }
-
-        // Ignore everything that is not a block device
-        if (strncmp(uevent->subsystem, "block", 5)) {
-            return COLDBOOT_CONTINUE;
-        }
-
-        if (uevent->partition_name) {
-            // match partition names to create device nodes for partitions
-            // both partition_names and uevent->partition_name have A/B suffix when A/B is used
-            auto iter = partition_names->find(uevent->partition_name);
-            if (iter != partition_names->end()) {
-                LOG(VERBOSE) << "early_mount: found partition: " << *iter;
-                partition_names->erase(iter);
-                if (partition_names->empty()) {
-                    return COLDBOOT_STOP;  // found all partitions, stop coldboot
-                } else {
-                    return COLDBOOT_CREATE;  // create this device and continue to find others
-                }
-            }
-        }
-        // Not found a partition or find an unneeded partition, continue to find others
-        return COLDBOOT_CONTINUE;
-    });
-}
-
-static bool vboot_1_0_early_partitions(const std::vector<fstab_rec*>& early_fstab_recs,
-                                       std::set<std::string>* out_partitions,
-                                       bool* out_need_verity) {
-    std::string meta_partition;
-    for (auto fstab_rec : early_fstab_recs) {
-        // don't allow verifyatboot for early mounted partitions
-        if (fs_mgr_is_verifyatboot(fstab_rec)) {
-            LOG(ERROR) << "early_mount: partitions can't be verified at boot";
-            return false;
-        }
-        // check for verified partitions
-        if (fs_mgr_is_verified(fstab_rec)) {
-            *out_need_verity = true;
-        }
-        // check if verity metadata is on a separate partition and get partition
-        // name from the end of the ->verity_loc path. verity state is not partition
-        // specific, so there must be only 1 additional partition that carries
-        // verity state.
-        if (fstab_rec->verity_loc) {
-            if (!meta_partition.empty()) {
-                LOG(ERROR) << "early_mount: more than one meta partition found: " << meta_partition
-                           << ", " << basename(fstab_rec->verity_loc);
-                return false;
-            } else {
-                meta_partition = basename(fstab_rec->verity_loc);
-            }
-        }
-    }
-
-    // includes those early mount partitions and meta_partition (if any)
-    // note that fstab_rec->blk_device has A/B suffix updated by fs_mgr when A/B is used
-    for (auto fstab_rec : early_fstab_recs) {
-        out_partitions->emplace(basename(fstab_rec->blk_device));
-    }
-
-    if (!meta_partition.empty()) {
-        out_partitions->emplace(std::move(meta_partition));
-    }
-
-    return true;
-}
-
-// a.k.a. AVB (external/avb)
-static bool vboot_2_0_early_partitions(std::set<std::string>* out_partitions, bool* out_need_verity,
-                                       std::string* out_device_file_by_name_prefix) {
-    std::string vbmeta_partitions;
-    if (!get_vbmeta_config_from_dt(&vbmeta_partitions, out_device_file_by_name_prefix)) {
-        return false;
-    }
-    // libavb verifies AVB metadata on all verified partitions at once.
-    // e.g., The vbmeta_partitions will be "vbmeta,boot,system,vendor"
-    // for libavb to verify metadata, even if we only need to early mount /vendor.
-    std::vector<std::string> partitions = android::base::Split(vbmeta_partitions, ",");
-    std::string ab_suffix = fs_mgr_get_slot_suffix();
-    for (const auto& partition : partitions) {
-        out_partitions->emplace(partition + ab_suffix);
-    }
-    *out_need_verity = true;
-    return true;
-}
-
-static bool get_early_partitions(const std::vector<fstab_rec*>& early_fstab_recs,
-                                 std::set<std::string>* out_partitions, bool* out_need_verity,
-                                 std::string* out_device_file_by_name_prefix) {
-    *out_need_verity = false;
-    out_partitions->clear();
-    out_device_file_by_name_prefix->clear();
-
-    if (is_dt_vbmeta_compatible()) {  // AVB (external/avb) is used to setup dm-verity.
-        return vboot_2_0_early_partitions(out_partitions, out_need_verity,
-                                          out_device_file_by_name_prefix);
-    } else {
-        return vboot_1_0_early_partitions(early_fstab_recs, out_partitions, out_need_verity);
-    }
-}
-
-/* Early mount vendor and ODM partitions. The fstab is read from device-tree. */
-static bool early_mount() {
-    // skip early mount if we're in recovery mode
-    if (access("/sbin/recovery", F_OK) == 0) {
-        LOG(INFO) << "Early mount skipped (recovery mode)";
-        return true;
-    }
-
-    // first check if device tree fstab entries are compatible
-    if (!is_dt_fstab_compatible()) {
-        LOG(INFO) << "Early mount skipped (missing/incompatible fstab in device tree)";
-        return true;
-    }
-
-    std::unique_ptr<fstab, decltype(&fs_mgr_free_fstab)> tab(
-        fs_mgr_read_fstab_dt(), fs_mgr_free_fstab);
-    if (!tab) {
-        LOG(ERROR) << "Early mount failed to read fstab from device tree";
-        return false;
-    }
-
-    // find out fstab records for odm, system and vendor
-    std::vector<fstab_rec*> early_fstab_recs;
-    for (auto mount_point : {"/odm", "/system", "/vendor"}) {
-        fstab_rec* fstab_rec = fs_mgr_get_entry_for_mount_point(tab.get(), mount_point);
-        if (fstab_rec != nullptr) {
-            early_fstab_recs.push_back(fstab_rec);
-        }
-    }
-
-    // nothing to early mount
-    if (early_fstab_recs.empty()) return true;
-
-    bool need_verity;
-    std::string device_file_by_name_prefix;
-    std::set<std::string> partition_names;
-    // partition_names MUST have A/B suffix when A/B is used
-    if (!get_early_partitions(early_fstab_recs, &partition_names, &need_verity,
-                              &device_file_by_name_prefix)) {
-        return false;
-    }
-
-    bool success = false;
-    // create the devices we need..
-    early_device_init(&partition_names);
-
-    // early_device_init will remove found partitions from partition_names
-    // So if the partition_names is not empty here, means some partitions
-    // are not found
-    if (!partition_names.empty()) {
-        LOG(ERROR) << "early_mount: partition(s) not found: "
-                   << android::base::Join(partition_names, ", ");
-        goto done;
-    }
-
-    if (need_verity) {
-        // create /dev/device mapper
-        device_init("/sys/devices/virtual/misc/device-mapper",
-                    [&](uevent* uevent) -> coldboot_action_t { return COLDBOOT_STOP; });
-    }
-
-    if (mount_early_partitions(early_fstab_recs, device_file_by_name_prefix)) {
-        success = true;
-    }
-
-done:
-    device_close();
-    return success;
-}
-
 static void install_reboot_signal_handlers() {
     // Instead of panic'ing the kernel as is the default behavior when init crashes,
     // we prefer to reboot to bootloader on development builds, as this will prevent
@@ -1337,11 +991,13 @@
 
         LOG(INFO) << "init first stage started!";
 
-        if (!early_mount()) {
+        if (!DoFirstStageMount()) {
             LOG(ERROR) << "Failed to mount required partitions early ...";
             panic();
         }
 
+        SetInitAvbVersionInRecovery();
+
         // Set up SELinux, loading the SELinux policy.
         selinux_initialize(true);
 
diff --git a/init/init_first_stage.cpp b/init/init_first_stage.cpp
new file mode 100644
index 0000000..e6b2f24
--- /dev/null
+++ b/init/init_first_stage.cpp
@@ -0,0 +1,433 @@
+/*
+ * 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 "init_first_stage.h"
+
+#include <stdlib.h>
+#include <unistd.h>
+
+#include <memory>
+#include <set>
+#include <string>
+#include <vector>
+
+#include <android-base/file.h>
+#include <android-base/logging.h>
+#include <android-base/strings.h>
+
+#include "devices.h"
+#include "fs_mgr.h"
+#include "fs_mgr_avb.h"
+#include "util.h"
+
+// Class Declarations
+// ------------------
+class FirstStageMount {
+  public:
+    FirstStageMount();
+    virtual ~FirstStageMount() = default;
+
+    // The factory method to create either FirstStageMountVBootV1 or FirstStageMountVBootV2
+    // based on device tree configurations.
+    static std::unique_ptr<FirstStageMount> Create();
+    bool DoFirstStageMount();  // Mounts fstab entries read from device tree.
+    bool InitDevices();
+
+  protected:
+    void InitRequiredDevices(std::set<std::string>* devices_partition_names);
+    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 bool SetUpDmVerity(fstab_rec* fstab_rec) = 0;
+
+    // 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_;
+};
+
+class FirstStageMountVBootV1 : public FirstStageMount {
+  public:
+    FirstStageMountVBootV1() = default;
+    ~FirstStageMountVBootV1() override = default;
+
+  protected:
+    bool GetRequiredDevices(std::set<std::string>* out_devices_partition_names,
+                            bool* out_need_dm_verity) override;
+    bool SetUpDmVerity(fstab_rec* fstab_rec) override;
+};
+
+class FirstStageMountVBootV2 : public FirstStageMount {
+  public:
+    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;
+    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_;
+};
+
+// Static Functions
+// ----------------
+static inline bool IsDtVbmetaCompatible() {
+    return is_android_dt_value_expected("vbmeta/compatible", "android,vbmeta");
+}
+
+static bool inline IsRecoveryMode() {
+    return access("/sbin/recovery", F_OK) == 0;
+}
+
+// Class Definitions
+// -----------------
+FirstStageMount::FirstStageMount() : 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;
+    }
+    for (auto mount_point : {"/system", "/vendor", "/odm"}) {
+        fstab_rec* fstab_rec =
+            fs_mgr_get_entry_for_mount_point(device_tree_fstab_.get(), mount_point);
+        if (fstab_rec != nullptr) {
+            mount_fstab_recs_.push_back(fstab_rec);
+        }
+    }
+}
+
+std::unique_ptr<FirstStageMount> FirstStageMount::Create() {
+    if (IsDtVbmetaCompatible()) {
+        return std::make_unique<FirstStageMountVBootV2>();
+    } else {
+        return std::make_unique<FirstStageMountVBootV1>();
+    }
+}
+
+bool FirstStageMount::DoFirstStageMount() {
+    // Nothing to mount.
+    if (mount_fstab_recs_.empty()) return true;
+
+    if (!InitDevices()) return false;
+
+    if (!MountPartitions()) return false;
+
+    return true;
+}
+
+bool FirstStageMount::InitDevices() {
+    bool need_dm_verity;
+    std::set<std::string> devices_partition_names;
+
+    // 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;
+
+    if (need_dm_verity) {
+        device_init("/sys/devices/virtual/misc/device-mapper",
+                    [&](uevent* uevent) -> coldboot_action_t { return COLDBOOT_STOP; });
+    }
+
+    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_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;
+    }
+    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;
+        }
+
+        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.
+                }
+            }
+        }
+        // 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.
+void FirstStageMount::InitVerityDevice(const std::string& verity_device) {
+    const std::string device_name(basename(verity_device.c_str()));
+    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) {
+            LOG(VERBOSE) << "Creating dm-verity device : " << verity_device;
+            return COLDBOOT_STOP;
+        }
+        return COLDBOOT_CONTINUE;
+    });
+    device_close();
+}
+
+bool FirstStageMount::MountPartitions() {
+    for (auto fstab_rec : mount_fstab_recs_) {
+        if (!SetUpDmVerity(fstab_rec)) {
+            PLOG(ERROR) << "Failed to setup verity for '" << fstab_rec->mount_point << "'";
+            return false;
+        }
+        if (fs_mgr_do_mount_one(fstab_rec)) {
+            PLOG(ERROR) << "Failed to mount '" << fstab_rec->mount_point << "'";
+            return false;
+        }
+    }
+    return true;
+}
+
+bool FirstStageMountVBootV1::GetRequiredDevices(std::set<std::string>* out_devices_partition_names,
+                                                bool* out_need_dm_verity) {
+    std::string verity_loc_device;
+    *out_need_dm_verity = false;
+
+    for (auto fstab_rec : mount_fstab_recs_) {
+        // Don't allow verifyatboot in the first stage.
+        if (fs_mgr_is_verifyatboot(fstab_rec)) {
+            LOG(ERROR) << "Partitions can't be verified at boot";
+            return false;
+        }
+        // Checks for verified partitions.
+        if (fs_mgr_is_verified(fstab_rec)) {
+            *out_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
+        // that carries verity state.
+        if (fstab_rec->verity_loc) {
+            if (verity_loc_device.empty()) {
+                verity_loc_device = fstab_rec->verity_loc;
+            } else if (verity_loc_device != fstab_rec->verity_loc) {
+                LOG(ERROR) << "More than one verity_loc found: " << verity_loc_device << ", "
+                           << fstab_rec->verity_loc;
+                return false;
+            }
+        }
+    }
+
+    // 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));
+    }
+
+    if (!verity_loc_device.empty()) {
+        out_devices_partition_names->emplace(basename(verity_loc_device.c_str()));
+    }
+
+    return true;
+}
+
+bool FirstStageMountVBootV1::SetUpDmVerity(fstab_rec* fstab_rec) {
+    if (fs_mgr_is_verified(fstab_rec)) {
+        int ret = fs_mgr_setup_verity(fstab_rec, false /* wait_for_verity_dev */);
+        if (ret == FS_MGR_SETUP_VERITY_DISABLED) {
+            LOG(INFO) << "Verity disabled for '" << fstab_rec->mount_point << "'";
+        } else if (ret == FS_MGR_SETUP_VERITY_SUCCESS) {
+            // The exact block device name (fstab_rec->blk_device) is changed to "/dev/block/dm-XX".
+            // Needs to create it because ueventd isn't started in init first stage.
+            InitVerityDevice(fstab_rec->blk_device);
+        } else {
+            return false;
+        }
+    }
+    return true;  // Returns true to mount the partition.
+}
+
+// FirstStageMountVBootV2 constructor.
+// Gets the vbmeta configurations from device tree.
+// Specifically, the 'parts' and 'by_name_prefix' below.
+// /{
+//     firmware {
+//         android {
+//             vbmeta {
+//                 compatible = "android,vbmeta";
+//                 parts = "vbmeta,boot,system,vendor"
+//                 by_name_prefix = "/dev/block/platform/soc.0/f9824900.sdhci/by-name/"
+//             };
+//         };
+//     };
+//  }
+FirstStageMountVBootV2::FirstStageMountVBootV2() : avb_handle_(nullptr) {
+    if (!read_android_dt_file("vbmeta/parts", &device_tree_vbmeta_parts_)) {
+        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;
+
+    // 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;
+        }
+        out_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 (device_tree_vbmeta_parts_.empty()) {
+            LOG(ERROR) << "Missing vbmeta parts in device tree";
+            return false;
+        }
+        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:
+            //   - device_tree_vbmeta_parts_ = "vbmeta,boot,system,vendor"
+            //   - mount_fstab_recs_: /vendor_a
+            out_devices_partition_names->emplace(partition + ab_suffix);
+        }
+    }
+    return true;
+}
+
+bool FirstStageMountVBootV2::SetUpDmVerity(fstab_rec* fstab_rec) {
+    if (fs_mgr_is_avb(fstab_rec)) {
+        if (!InitAvbHandle()) return false;
+        if (avb_handle_->hashtree_disabled()) {
+            LOG(INFO) << "avb hashtree disabled for '" << fstab_rec->mount_point << "'";
+        } else if (avb_handle_->SetUpAvb(fstab_rec, false /* wait_for_verity_dev */)) {
+            // The exact block device name (fstab_rec->blk_device) is changed to "/dev/block/dm-XX".
+            // Needs to create it because ueventd isn't started in init first stage.
+            InitVerityDevice(fstab_rec->blk_device);
+        } else {
+            return false;
+        }
+    }
+    return true;  // Returns true to mount the partition.
+}
+
+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 (!avb_handle_) {
+        PLOG(ERROR) << "Failed to open FsManagerAvbHandle";
+        return false;
+    }
+    // Sets INIT_AVB_VERSION here for init to set ro.boot.avb_version in the second stage.
+    setenv("INIT_AVB_VERSION", avb_handle_->avb_version().c_str(), 1);
+    return true;
+}
+
+// Public functions
+// ----------------
+// Mounts /system, /vendor, and/or /odm if they are present in the fstab provided by device tree.
+bool DoFirstStageMount() {
+    // Skips first stage mount if we're in recovery mode.
+    if (IsRecoveryMode()) {
+        LOG(INFO) << "First stage mount skipped (recovery mode)";
+        return true;
+    }
+
+    // Firstly checks if device tree fstab entries are compatible.
+    if (!is_android_dt_value_expected("fstab/compatible", "android,fstab")) {
+        LOG(INFO) << "First stage mount skipped (missing/incompatible fstab in device tree)";
+        return true;
+    }
+
+    std::unique_ptr<FirstStageMount> handle = FirstStageMount::Create();
+    if (!handle) {
+        LOG(ERROR) << "Failed to create FirstStageMount";
+        return false;
+    }
+    return handle->DoFirstStageMount();
+}
+
+void SetInitAvbVersionInRecovery() {
+    if (!IsRecoveryMode()) {
+        LOG(INFO) << "Skipped setting INIT_AVB_VERSION (not in recovery mode)";
+        return;
+    }
+
+    if (!IsDtVbmetaCompatible()) {
+        LOG(INFO) << "Skipped setting INIT_AVB_VERSION (not vbmeta compatible)";
+        return;
+    }
+
+    // Initializes required devices for the subsequent FsManagerAvbHandle::Open()
+    // to verify AVB metadata on all partitions in the verified chain.
+    // We only set INIT_AVB_VERSION when the AVB verification succeeds, i.e., the
+    // Open() function returns a valid handle.
+    // We don't need to mount partitions here in recovery mode.
+    FirstStageMountVBootV2 avb_first_mount;
+    if (!avb_first_mount.InitDevices()) {
+        LOG(ERROR) << "Failed to init devices for INIT_AVB_VERSION";
+        return;
+    }
+
+    FsManagerAvbUniquePtr avb_handle = FsManagerAvbHandle::Open(avb_first_mount.by_name_prefix());
+    if (!avb_handle) {
+        PLOG(ERROR) << "Failed to open FsManagerAvbHandle for INIT_AVB_VERSION";
+        return;
+    }
+    setenv("INIT_AVB_VERSION", avb_handle->avb_version().c_str(), 1);
+}
diff --git a/init/init_first_stage.h b/init/init_first_stage.h
new file mode 100644
index 0000000..170a24c
--- /dev/null
+++ b/init/init_first_stage.h
@@ -0,0 +1,23 @@
+/*
+ * 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 _INIT_FIRST_STAGE_H
+#define _INIT_FIRST_STAGE_H
+
+bool DoFirstStageMount();
+void SetInitAvbVersionInRecovery();
+
+#endif
diff --git a/init/reboot.cpp b/init/reboot.cpp
index c1edf7c..c997519 100644
--- a/init/reboot.cpp
+++ b/init/reboot.cpp
@@ -423,7 +423,6 @@
 bool HandlePowerctlMessage(const std::string& command) {
     unsigned int cmd = 0;
     std::vector<std::string> cmd_params = android::base::Split(command, ",");
-    std::string reason_string = cmd_params[0];
     std::string reboot_target = "";
     bool run_fsck = false;
     bool command_invalid = false;
@@ -436,7 +435,6 @@
             // The shutdown reason is PowerManager.SHUTDOWN_USER_REQUESTED.
             // Run fsck once the file system is remounted in read-only mode.
             run_fsck = true;
-            reason_string = cmd_params[1];
         }
     } else if (cmd_params[0] == "reboot") {
         cmd = ANDROID_RB_RESTART2;
@@ -467,6 +465,6 @@
         return false;
     }
 
-    DoReboot(cmd, reason_string, reboot_target, run_fsck);
+    DoReboot(cmd, command, reboot_target, run_fsck);
     return true;
 }
diff --git a/init/service.cpp b/init/service.cpp
index 3db34db..9ba0272 100644
--- a/init/service.cpp
+++ b/init/service.cpp
@@ -160,6 +160,7 @@
       gid_(0),
       namespace_flags_(0),
       seclabel_(""),
+      keychord_id_(0),
       ioprio_class_(IoSchedClass_NONE),
       ioprio_pri_(0),
       priority_(0),
@@ -183,6 +184,7 @@
       capabilities_(capabilities),
       namespace_flags_(namespace_flags),
       seclabel_(seclabel),
+      keychord_id_(0),
       ioprio_class_(IoSchedClass_NONE),
       ioprio_pri_(0),
       priority_(0),
@@ -275,10 +277,6 @@
     std::for_each(descriptors_.begin(), descriptors_.end(),
                   std::bind(&DescriptorInfo::Clean, std::placeholders::_1));
 
-    if (flags_ & SVC_EXEC) {
-        LOG(INFO) << "SVC_EXEC pid " << pid_ << " finished...";
-    }
-
     if (flags_ & SVC_TEMPORARY) {
         return;
     }
@@ -1056,21 +1054,26 @@
     Service* svc = FindServiceByPid(pid);
 
     std::string name;
+    std::string wait_string;
     if (svc) {
         name = android::base::StringPrintf("Service '%s' (pid %d)",
                                            svc->name().c_str(), pid);
+        if (svc->flags() & SVC_EXEC) {
+            wait_string =
+                android::base::StringPrintf(" waiting took %f seconds", exec_waiter_->duration_s());
+        }
     } else {
         name = android::base::StringPrintf("Untracked pid %d", pid);
     }
 
     if (WIFEXITED(status)) {
-        LOG(INFO) << name << " exited with status " << WEXITSTATUS(status);
+        LOG(INFO) << name << " exited with status " << WEXITSTATUS(status) << wait_string;
     } else if (WIFSIGNALED(status)) {
-        LOG(INFO) << name << " killed by signal " << WTERMSIG(status);
+        LOG(INFO) << name << " killed by signal " << WTERMSIG(status) << wait_string;
     } else if (WIFSTOPPED(status)) {
-        LOG(INFO) << name << " stopped by signal " << WSTOPSIG(status);
+        LOG(INFO) << name << " stopped by signal " << WSTOPSIG(status) << wait_string;
     } else {
-        LOG(INFO) << name << " state changed";
+        LOG(INFO) << name << " state changed" << wait_string;
     }
 
     if (!svc) {
@@ -1080,7 +1083,6 @@
     svc->Reap();
 
     if (svc->flags() & SVC_EXEC) {
-        LOG(INFO) << "Wait for exec took " << *exec_waiter_;
         exec_waiter_.reset();
     }
     if (svc->flags() & SVC_TEMPORARY) {
diff --git a/init/service.h b/init/service.h
index f08a03f..f93ac38 100644
--- a/init/service.h
+++ b/init/service.h
@@ -93,14 +93,19 @@
     const std::set<std::string>& classnames() const { return classnames_; }
     unsigned flags() const { return flags_; }
     pid_t pid() const { return pid_; }
+    int crash_count() const { return crash_count_; }
     uid_t uid() const { return uid_; }
     gid_t gid() const { return gid_; }
-    int priority() const { return priority_; }
+    unsigned namespace_flags() const { return namespace_flags_; }
     const std::vector<gid_t>& supp_gids() const { return supp_gids_; }
     const std::string& seclabel() const { return seclabel_; }
     const std::vector<int>& keycodes() const { return keycodes_; }
     int keychord_id() const { return keychord_id_; }
     void set_keychord_id(int keychord_id) { keychord_id_ = keychord_id; }
+    IoSchedClass ioprio_class() const { return ioprio_class_; }
+    int ioprio_pri() const { return ioprio_pri_; }
+    int priority() const { return priority_; }
+    int oom_score_adjust() const { return oom_score_adjust_; }
     const std::vector<std::string>& args() const { return args_; }
 
   private:
@@ -180,6 +185,9 @@
 public:
     static ServiceManager& GetInstance();
 
+    // Exposed for testing
+    ServiceManager();
+
     void AddService(std::unique_ptr<Service> service);
     Service* MakeExecOneshotService(const std::vector<std::string>& args);
     bool Exec(const std::vector<std::string>& args);
@@ -198,8 +206,6 @@
     void DumpState() const;
 
 private:
-    ServiceManager();
-
     // Cleans up a child process that exited.
     // Returns true iff a children was cleaned up.
     bool ReapOneProcess();
diff --git a/init/service_test.cpp b/init/service_test.cpp
new file mode 100644
index 0000000..4493f25
--- /dev/null
+++ b/init/service_test.cpp
@@ -0,0 +1,67 @@
+/*
+ * 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 "service.h"
+
+#include <algorithm>
+#include <memory>
+#include <type_traits>
+#include <vector>
+
+#include <gtest/gtest.h>
+
+TEST(service, pod_initialized) {
+    constexpr auto memory_size = sizeof(Service);
+    alignas(alignof(Service)) char old_memory[memory_size];
+
+    for (std::size_t i = 0; i < memory_size; ++i) {
+        old_memory[i] = 0xFF;
+    }
+
+    std::vector<std::string> dummy_args{"/bin/test"};
+    Service* service_in_old_memory = new (old_memory) Service("test_old_memory", dummy_args);
+
+    EXPECT_EQ(0U, service_in_old_memory->flags());
+    EXPECT_EQ(0, service_in_old_memory->pid());
+    EXPECT_EQ(0, service_in_old_memory->crash_count());
+    EXPECT_EQ(0U, service_in_old_memory->uid());
+    EXPECT_EQ(0U, service_in_old_memory->gid());
+    EXPECT_EQ(0U, service_in_old_memory->namespace_flags());
+    EXPECT_EQ(0, service_in_old_memory->keychord_id());
+    EXPECT_EQ(IoSchedClass_NONE, service_in_old_memory->ioprio_class());
+    EXPECT_EQ(0, service_in_old_memory->ioprio_pri());
+    EXPECT_EQ(0, service_in_old_memory->priority());
+    EXPECT_EQ(-1000, service_in_old_memory->oom_score_adjust());
+
+    for (std::size_t i = 0; i < memory_size; ++i) {
+        old_memory[i] = 0xFF;
+    }
+
+    Service* service_in_old_memory2 = new (old_memory)
+        Service("test_old_memory", 0U, 0U, 0U, std::vector<gid_t>(), CapSet(), 0U, "", dummy_args);
+
+    EXPECT_EQ(0U, service_in_old_memory2->flags());
+    EXPECT_EQ(0, service_in_old_memory2->pid());
+    EXPECT_EQ(0, service_in_old_memory2->crash_count());
+    EXPECT_EQ(0U, service_in_old_memory2->uid());
+    EXPECT_EQ(0U, service_in_old_memory2->gid());
+    EXPECT_EQ(0U, service_in_old_memory2->namespace_flags());
+    EXPECT_EQ(0, service_in_old_memory2->keychord_id());
+    EXPECT_EQ(IoSchedClass_NONE, service_in_old_memory2->ioprio_class());
+    EXPECT_EQ(0, service_in_old_memory2->ioprio_pri());
+    EXPECT_EQ(0, service_in_old_memory2->priority());
+    EXPECT_EQ(-1000, service_in_old_memory2->oom_score_adjust());
+}
diff --git a/init/util.cpp b/init/util.cpp
index 895e78a..4e3537b 100644
--- a/init/util.cpp
+++ b/init/util.cpp
@@ -421,3 +421,26 @@
     os << t.duration_s() << " seconds";
     return os;
 }
+
+// Reads the content of device tree file under kAndroidDtDir directory.
+// Returns true if the read is success, false otherwise.
+bool read_android_dt_file(const std::string& sub_path, std::string* dt_content) {
+    const std::string file_name = kAndroidDtDir + sub_path;
+    if (android::base::ReadFileToString(file_name, dt_content)) {
+        if (!dt_content->empty()) {
+            dt_content->pop_back();  // Trims the trailing '\0' out.
+            return true;
+        }
+    }
+    return false;
+}
+
+bool is_android_dt_value_expected(const std::string& sub_path, const std::string& expected_content) {
+    std::string dt_content;
+    if (read_android_dt_file(sub_path, &dt_content)) {
+        if (dt_content == expected_content) {
+            return true;
+        }
+    }
+    return false;
+}
diff --git a/init/util.h b/init/util.h
index 90ec6bb..bb281bd 100644
--- a/init/util.h
+++ b/init/util.h
@@ -27,6 +27,8 @@
 
 #define COLDBOOT_DONE "/dev/.coldboot_done"
 
+const std::string kAndroidDtDir("/proc/device-tree/firmware/android/");
+
 using namespace std::chrono_literals;
 
 int create_socket(const char *name, int type, mode_t perm,
@@ -80,4 +82,8 @@
 
 void panic() __attribute__((__noreturn__));
 
+// Reads or compares the content of device tree file under kAndroidDtDir directory.
+bool read_android_dt_file(const std::string& sub_path, std::string* dt_content);
+bool is_android_dt_value_expected(const std::string& sub_path, const std::string& expected_content);
+
 #endif
diff --git a/libcutils/fs_config.c b/libcutils/fs_config.c
index 1b7139b..d98a923 100644
--- a/libcutils/fs_config.c
+++ b/libcutils/fs_config.c
@@ -140,8 +140,14 @@
     { 00600, AID_ROOT,      AID_ROOT,      0, "odm/default.prop" },
     { 00444, AID_ROOT,      AID_ROOT,      0, odm_conf_dir + 1 },
     { 00444, AID_ROOT,      AID_ROOT,      0, odm_conf_file + 1 },
+    { 00600, AID_ROOT,      AID_ROOT,      0, "system/odm/build.prop" },
+    { 00600, AID_ROOT,      AID_ROOT,      0, "system/odm/default.prop" },
+    { 00444, AID_ROOT,      AID_ROOT,      0, "system/odm/etc/fs_config_dirs" },
+    { 00444, AID_ROOT,      AID_ROOT,      0, "system/odm/etc/fs_config_files" },
     { 00444, AID_ROOT,      AID_ROOT,      0, oem_conf_dir + 1 },
     { 00444, AID_ROOT,      AID_ROOT,      0, oem_conf_file + 1 },
+    { 00444, AID_ROOT,      AID_ROOT,      0, "system/oem/etc/fs_config_dirs" },
+    { 00444, AID_ROOT,      AID_ROOT,      0, "system/oem/etc/fs_config_files" },
     { 00750, AID_ROOT,      AID_SHELL,     0, "sbin/fs_mgr" },
     { 00755, AID_ROOT,      AID_SHELL,     0, "system/bin/crash_dump32" },
     { 00755, AID_ROOT,      AID_SHELL,     0, "system/bin/crash_dump64" },
@@ -158,6 +164,10 @@
     { 00555, AID_ROOT,      AID_ROOT,      0, "system/etc/ppp/*" },
     { 00555, AID_ROOT,      AID_ROOT,      0, "system/etc/rc.*" },
     { 00440, AID_ROOT,      AID_ROOT,      0, "system/etc/recovery.img" },
+    { 00600, AID_ROOT,      AID_ROOT,      0, "system/vendor/build.prop" },
+    { 00600, AID_ROOT,      AID_ROOT,      0, "system/vendor/default.prop" },
+    { 00444, AID_ROOT,      AID_ROOT,      0, "system/vendor/etc/fs_config_dirs" },
+    { 00444, AID_ROOT,      AID_ROOT,      0, "system/vendor/etc/fs_config_files" },
     { 00600, AID_ROOT,      AID_ROOT,      0, "vendor/build.prop" },
     { 00600, AID_ROOT,      AID_ROOT,      0, "vendor/default.prop" },
     { 00444, AID_ROOT,      AID_ROOT,      0, ven_conf_dir + 1 },
@@ -187,14 +197,28 @@
     /* Support hostapd administering a network interface. */
     { 00755, AID_WIFI,      AID_WIFI,      CAP_MASK_LONG(CAP_NET_ADMIN) |
                                            CAP_MASK_LONG(CAP_NET_RAW),
+                                              "system/vendor/bin/hostapd" },
+    { 00755, AID_WIFI,      AID_WIFI,      CAP_MASK_LONG(CAP_NET_ADMIN) |
+                                           CAP_MASK_LONG(CAP_NET_RAW),
                                               "vendor/bin/hostapd" },
 
     /* Support Bluetooth legacy hal accessing /sys/class/rfkill
      * Support RT scheduling in Bluetooth */
     { 00700, AID_BLUETOOTH, AID_BLUETOOTH, CAP_MASK_LONG(CAP_NET_ADMIN) |
                                            CAP_MASK_LONG(CAP_SYS_NICE),
+                                              "system/vendor/bin/hw/android.hardware.bluetooth@1.0-service" },
+    { 00700, AID_BLUETOOTH, AID_BLUETOOTH, CAP_MASK_LONG(CAP_NET_ADMIN) |
+                                           CAP_MASK_LONG(CAP_SYS_NICE),
                                               "vendor/bin/hw/android.hardware.bluetooth@1.0-service" },
 
+    /* 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
      * isolated processes for web rendering. */
     { 0750,  AID_ROOT,      AID_ROOT,      CAP_MASK_LONG(CAP_SETUID) |
diff --git a/libsystem/include/system/window-deprecated.h b/libsystem/include/system/window-deprecated.h
index 2ccfd66..e836aea 100644
--- a/libsystem/include/system/window-deprecated.h
+++ b/libsystem/include/system/window-deprecated.h
@@ -334,6 +334,12 @@
      * present info, 0 if it won't.
      */
     NATIVE_WINDOW_FRAME_TIMESTAMPS_SUPPORTS_PRESENT = 18,
+
+    /*
+     * The consumer end is capable of handling protected buffers, i.e. buffer
+     * with GRALLOC_USAGE_PROTECTED usage bits on.
+     */
+    NATIVE_WINDOW_CONSUMER_IS_PROTECTED = 19,
 };
 
 /* Valid operations for the (*perform)() hook.
diff --git a/libsysutils/Android.bp b/libsysutils/Android.bp
new file mode 100644
index 0000000..296bd26
--- /dev/null
+++ b/libsysutils/Android.bp
@@ -0,0 +1,25 @@
+cc_library_shared {
+    name: "libsysutils",
+    srcs: [
+        "src/SocketListener.cpp",
+        "src/FrameworkListener.cpp",
+        "src/NetlinkListener.cpp",
+        "src/NetlinkEvent.cpp",
+        "src/FrameworkCommand.cpp",
+        "src/SocketClient.cpp",
+        "src/ServiceManager.cpp",
+    ],
+
+    logtags: ["EventLogTags.logtags"],
+
+    cflags: ["-Werror"],
+
+    shared_libs: [
+        "libbase",
+        "libcutils",
+        "liblog",
+        "libnl",
+    ],
+
+    export_include_dirs: ["include"],
+}
diff --git a/libsysutils/Android.mk b/libsysutils/Android.mk
deleted file mode 100644
index 584e5a2..0000000
--- a/libsysutils/Android.mk
+++ /dev/null
@@ -1,27 +0,0 @@
-LOCAL_PATH:= $(call my-dir)
-
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES:=                             \
-                  src/SocketListener.cpp      \
-                  src/FrameworkListener.cpp   \
-                  src/NetlinkListener.cpp     \
-                  src/NetlinkEvent.cpp        \
-                  src/FrameworkCommand.cpp    \
-                  src/SocketClient.cpp        \
-                  src/ServiceManager.cpp      \
-                  EventLogTags.logtags
-
-LOCAL_MODULE:= libsysutils
-
-LOCAL_CFLAGS := -Werror
-
-LOCAL_SHARED_LIBRARIES := \
-        libbase \
-        libcutils \
-        liblog \
-        libnl
-
-LOCAL_EXPORT_C_INCLUDE_DIRS := system/core/libsysutils/include
-
-include $(BUILD_SHARED_LIBRARY)
diff --git a/rootdir/init.rc b/rootdir/init.rc
index 15fce90..def686b 100644
--- a/rootdir/init.rc
+++ b/rootdir/init.rc
@@ -387,6 +387,7 @@
     mkdir /data/misc/radio 0770 system radio
     mkdir /data/misc/sms 0770 system radio
     mkdir /data/misc/zoneinfo 0775 system system
+    mkdir /data/misc/textclassifier 0771 system system
     mkdir /data/misc/vpn 0770 system vpn
     mkdir /data/misc/shared_relro 0771 shared_relro shared_relro
     mkdir /data/misc/systemkeys 0700 system system