Merge "storaged: clean up disk stats code"
diff --git a/adb/adb.cpp b/adb/adb.cpp
index 8c24bbb..6b30be8 100644
--- a/adb/adb.cpp
+++ b/adb/adb.cpp
@@ -257,19 +257,6 @@
     send_packet(cp, t);
 }
 
-#if ADB_HOST
-
-void SendConnectOnHost(atransport* t) {
-    // Send an empty message before A_CNXN message. This is because the data toggle of the ep_out on
-    // host and ep_in on device may not be the same.
-    apacket* p = get_apacket();
-    CHECK(p);
-    send_packet(p, t);
-    send_connect(t);
-}
-
-#endif
-
 // qual_overwrite is used to overwrite a qualifier string.  dst is a
 // pointer to a char pointer.  It is assumed that if *dst is non-NULL, it
 // was malloc'ed and needs to freed.  *dst will be set to a dup of src.
@@ -370,7 +357,7 @@
         if (p->msg.arg0){
             send_packet(p, t);
 #if ADB_HOST
-            SendConnectOnHost(t);
+            send_connect(t);
 #endif
         } else {
             t->SetConnectionState(kCsOffline);
diff --git a/adb/adb.h b/adb/adb.h
index 6a9897f..a4d233e 100644
--- a/adb/adb.h
+++ b/adb/adb.h
@@ -224,9 +224,6 @@
 void handle_offline(atransport *t);
 
 void send_connect(atransport *t);
-#if ADB_HOST
-void SendConnectOnHost(atransport* t);
-#endif
 
 void parse_banner(const std::string&, atransport* t);
 
diff --git a/adb/client/usb_libusb.cpp b/adb/client/usb_libusb.cpp
index 7025f28..8120199 100644
--- a/adb/client/usb_libusb.cpp
+++ b/adb/client/usb_libusb.cpp
@@ -333,6 +333,13 @@
             return;
         }
 
+        rc = libusb_set_interface_alt_setting(handle.get(), interface_num, 0);
+        if (rc != 0) {
+            LOG(WARNING) << "failed to set interface alt setting for device '" << device_serial
+                         << "'" << libusb_error_name(rc);
+            return;
+        }
+
         for (uint8_t endpoint : {bulk_in, bulk_out}) {
             rc = libusb_clear_halt(handle.get(), endpoint);
             if (rc != 0) {
diff --git a/adb/services.cpp b/adb/services.cpp
index ca34556..aff7012 100644
--- a/adb/services.cpp
+++ b/adb/services.cpp
@@ -58,6 +58,7 @@
 #include "transport.h"
 
 struct stinfo {
+    const char* service_name;
     void (*func)(int fd, void *cookie);
     int fd;
     void *cookie;
@@ -65,7 +66,7 @@
 
 static void service_bootstrap_func(void* x) {
     stinfo* sti = reinterpret_cast<stinfo*>(x);
-    adb_thread_setname(android::base::StringPrintf("service %d", sti->fd));
+    adb_thread_setname(android::base::StringPrintf("%s svc %d", sti->service_name, sti->fd));
     sti->func(sti->fd, sti->cookie);
     free(sti);
 }
@@ -160,8 +161,7 @@
     return true;
 }
 
-void reboot_service(int fd, void* arg)
-{
+void reboot_service(int fd, void* arg) {
     if (reboot_service_impl(fd, static_cast<const char*>(arg))) {
         // Don't return early. Give the reboot command time to take effect
         // to avoid messing up scripts which do "adb reboot && adb wait-for-device"
@@ -236,8 +236,7 @@
 
 #endif  // !ADB_HOST
 
-static int create_service_thread(void (*func)(int, void *), void *cookie)
-{
+static int create_service_thread(const char* service_name, void (*func)(int, void*), void* cookie) {
     int s[2];
     if (adb_socketpair(s)) {
         printf("cannot create service socket pair\n");
@@ -258,6 +257,7 @@
     if (sti == nullptr) {
         fatal("cannot allocate stinfo");
     }
+    sti->service_name = service_name;
     sti->func = func;
     sti->cookie = cookie;
     sti->fd = s[1];
@@ -281,7 +281,7 @@
     } else if(!strncmp("dev:", name, 4)) {
         ret = unix_open(name + 4, O_RDWR | O_CLOEXEC);
     } else if(!strncmp(name, "framebuffer:", 12)) {
-        ret = create_service_thread(framebuffer_service, 0);
+        ret = create_service_thread("fb", framebuffer_service, nullptr);
     } else if (!strncmp(name, "jdwp:", 5)) {
         ret = create_jdwp_connection_fd(atoi(name+5));
     } else if(!strncmp(name, "shell", 5)) {
@@ -289,17 +289,17 @@
     } else if(!strncmp(name, "exec:", 5)) {
         ret = StartSubprocess(name + 5, nullptr, SubprocessType::kRaw, SubprocessProtocol::kNone);
     } else if(!strncmp(name, "sync:", 5)) {
-        ret = create_service_thread(file_sync_service, NULL);
+        ret = create_service_thread("sync", file_sync_service, nullptr);
     } else if(!strncmp(name, "remount:", 8)) {
-        ret = create_service_thread(remount_service, NULL);
+        ret = create_service_thread("remount", remount_service, nullptr);
     } else if(!strncmp(name, "reboot:", 7)) {
         void* arg = strdup(name + 7);
         if (arg == NULL) return -1;
-        ret = create_service_thread(reboot_service, arg);
+        ret = create_service_thread("reboot", reboot_service, arg);
     } else if(!strncmp(name, "root:", 5)) {
-        ret = create_service_thread(restart_root_service, NULL);
+        ret = create_service_thread("root", restart_root_service, nullptr);
     } else if(!strncmp(name, "unroot:", 7)) {
-        ret = create_service_thread(restart_unroot_service, NULL);
+        ret = create_service_thread("unroot", restart_unroot_service, nullptr);
     } else if(!strncmp(name, "backup:", 7)) {
         ret = StartSubprocess(android::base::StringPrintf("/system/bin/bu backup %s",
                                                           (name + 7)).c_str(),
@@ -312,17 +312,20 @@
         if (sscanf(name + 6, "%d", &port) != 1) {
             return -1;
         }
-        ret = create_service_thread(restart_tcp_service, (void *) (uintptr_t) port);
+        ret = create_service_thread("tcp", restart_tcp_service, reinterpret_cast<void*>(port));
     } else if(!strncmp(name, "usb:", 4)) {
-        ret = create_service_thread(restart_usb_service, NULL);
+        ret = create_service_thread("usb", restart_usb_service, nullptr);
     } else if (!strncmp(name, "reverse:", 8)) {
         ret = reverse_service(name + 8);
     } else if(!strncmp(name, "disable-verity:", 15)) {
-        ret = create_service_thread(set_verity_enabled_state_service, (void*)0);
+        ret = create_service_thread("verity-on", set_verity_enabled_state_service,
+                                    reinterpret_cast<void*>(0));
     } else if(!strncmp(name, "enable-verity:", 15)) {
-        ret = create_service_thread(set_verity_enabled_state_service, (void*)1);
+        ret = create_service_thread("verity-off", set_verity_enabled_state_service,
+                                    reinterpret_cast<void*>(1));
     } else if (!strcmp(name, "reconnect")) {
-        ret = create_service_thread(reconnect_service, const_cast<atransport*>(transport));
+        ret = create_service_thread("reconnect", reconnect_service,
+                                    const_cast<atransport*>(transport));
 #endif
     }
     if (ret >= 0) {
@@ -484,14 +487,14 @@
             return nullptr;
         }
 
-        int fd = create_service_thread(wait_for_state, sinfo.get());
+        int fd = create_service_thread("wait", wait_for_state, sinfo.get());
         if (fd != -1) {
             sinfo.release();
         }
         return create_local_socket(fd);
     } else if (!strncmp(name, "connect:", 8)) {
         char* host = strdup(name + 8);
-        int fd = create_service_thread(connect_service, host);
+        int fd = create_service_thread("connect", connect_service, host);
         if (fd == -1) {
             free(host);
         }
diff --git a/adb/shell_service.cpp b/adb/shell_service.cpp
index ee821f8..5b48da0 100644
--- a/adb/shell_service.cpp
+++ b/adb/shell_service.cpp
@@ -435,8 +435,7 @@
 void Subprocess::ThreadHandler(void* userdata) {
     Subprocess* subprocess = reinterpret_cast<Subprocess*>(userdata);
 
-    adb_thread_setname(android::base::StringPrintf(
-            "shell srvc %d", subprocess->pid()));
+    adb_thread_setname(android::base::StringPrintf("shell svc %d", subprocess->pid()));
 
     D("passing data streams for PID %d", subprocess->pid());
     subprocess->PassDataStreams();
diff --git a/adb/transport.cpp b/adb/transport.cpp
index 34cc026..089a1ec 100644
--- a/adb/transport.cpp
+++ b/adb/transport.cpp
@@ -1101,11 +1101,4 @@
     keys_.pop_front();
     return result;
 }
-bool atransport::SetSendConnectOnError() {
-    if (has_send_connect_on_error_) {
-        return false;
-    }
-    has_send_connect_on_error_ = true;
-    return true;
-}
 #endif
diff --git a/adb/transport.h b/adb/transport.h
index 79e3075..8c101fd 100644
--- a/adb/transport.h
+++ b/adb/transport.h
@@ -122,7 +122,6 @@
 
 #if ADB_HOST
     std::shared_ptr<RSA> NextKey();
-    bool SetSendConnectOnError();
 #endif
 
     char token[TOKEN_SIZE] = {};
@@ -181,7 +180,6 @@
     std::atomic<ConnectionState> connection_state_;
 #if ADB_HOST
     std::deque<std::shared_ptr<RSA>> keys_;
-    bool has_send_connect_on_error_ = false;
 #endif
 
     DISALLOW_COPY_AND_ASSIGN(atransport);
diff --git a/adb/transport_usb.cpp b/adb/transport_usb.cpp
index 6768d31..fdecccf 100644
--- a/adb/transport_usb.cpp
+++ b/adb/transport_usb.cpp
@@ -103,13 +103,6 @@
 
 err_msg:
     p->msg.command = 0;
-    if (t->GetConnectionState() == kCsOffline) {
-        // If the data toggle of ep_out on device and ep_in on host are not the same, we may receive
-        // an error message. In this case, resend one A_CNXN message to connect the device.
-        if (t->SetSendConnectOnError()) {
-            SendConnectOnHost(t);
-        }
-    }
     return 0;
 }
 
@@ -162,8 +155,7 @@
     return 0;
 }
 
-static void remote_close(atransport *t)
-{
+static void remote_close(atransport* t) {
     usb_close(t->usb);
     t->usb = 0;
 }
diff --git a/base/Android.bp b/base/Android.bp
index 82aee2a..da262d2 100644
--- a/base/Android.bp
+++ b/base/Android.bp
@@ -95,7 +95,6 @@
                 "errors_unix.cpp",
             ],
             cppflags: ["-Wexit-time-destructors"],
-            host_ldlibs: ["-lrt"],
         },
         windows: {
             srcs: [
@@ -138,7 +137,6 @@
         },
         linux: {
             srcs: ["chrono_utils_test.cpp"],
-            host_ldlibs: ["-lrt"],
         },
         windows: {
             srcs: ["utf8_test.cpp"],
diff --git a/fs_mgr/fs_mgr_fstab.cpp b/fs_mgr/fs_mgr_fstab.cpp
index 9f52fdf..92c6ee8 100644
--- a/fs_mgr/fs_mgr_fstab.cpp
+++ b/fs_mgr/fs_mgr_fstab.cpp
@@ -788,47 +788,21 @@
 }
 
 /*
- * Returns the 1st matching fstab_rec that follows the start_rec.
- * start_rec is the result of a previous search or NULL.
+ * Returns the fstab_rec* whose mount_point is path.
+ * Returns nullptr if not found.
  */
-struct fstab_rec* fs_mgr_get_entry_for_mount_point_after(struct fstab_rec* start_rec,
-                                                         struct fstab* fstab,
-                                                         const std::string& path) {
-    int i;
+struct fstab_rec* fs_mgr_get_entry_for_mount_point(struct fstab* fstab, const std::string& path) {
     if (!fstab) {
         return nullptr;
     }
-
-    if (start_rec) {
-        for (i = 0; i < fstab->num_entries; i++) {
-            if (&fstab->recs[i] == start_rec) {
-                i++;
-                break;
-            }
-        }
-    } else {
-        i = 0;
-    }
-
-    for (; i < fstab->num_entries; i++) {
+    for (int i = 0; i < fstab->num_entries; i++) {
         if (fstab->recs[i].mount_point && path == fstab->recs[i].mount_point) {
             return &fstab->recs[i];
         }
     }
-
     return nullptr;
 }
 
-/*
- * Returns the 1st matching mount point.
- * There might be more. To look for others, use fs_mgr_get_entry_for_mount_point_after()
- * and give the fstab_rec from the previous search.
- */
-struct fstab_rec *fs_mgr_get_entry_for_mount_point(struct fstab *fstab, const char *path)
-{
-    return fs_mgr_get_entry_for_mount_point_after(NULL, fstab, path);
-}
-
 int fs_mgr_is_voldmanaged(const struct fstab_rec *fstab)
 {
     return fstab->fs_mgr_flags & MF_VOLDMANAGED;
diff --git a/fs_mgr/include_fstab/fstab/fstab.h b/fs_mgr/include_fstab/fstab/fstab.h
index 15c8caf..0a8496b 100644
--- a/fs_mgr/include_fstab/fstab/fstab.h
+++ b/fs_mgr/include_fstab/fstab/fstab.h
@@ -71,7 +71,6 @@
 
 int fs_mgr_add_entry(struct fstab* fstab, const char* mount_point, const char* fs_type,
                      const char* blk_device);
-struct fstab_rec* fs_mgr_get_entry_for_mount_point(struct fstab* fstab, const char* path);
 int fs_mgr_is_voldmanaged(const struct fstab_rec* fstab);
 int fs_mgr_is_nonremovable(const struct fstab_rec* fstab);
 int fs_mgr_is_verified(const struct fstab_rec* fstab);
@@ -96,6 +95,7 @@
 // TODO: move this into separate header files under include/fs_mgr/*.h
 #ifdef __cplusplus
 std::string fs_mgr_get_slot_suffix();
+struct fstab_rec* fs_mgr_get_entry_for_mount_point(struct fstab* fstab, const std::string& path);
 #endif
 
 #endif /* __CORE_FS_TAB_H */
diff --git a/init/Android.bp b/init/Android.bp
index 0e580fc..e906771 100644
--- a/init/Android.bp
+++ b/init/Android.bp
@@ -78,6 +78,8 @@
         "security.cpp",
         "selinux.cpp",
         "service.cpp",
+        "subcontext.cpp",
+        "subcontext.proto",
         "rlimit_parser.cpp",
         "tokenizer.cpp",
         "uevent_listener.cpp",
@@ -173,6 +175,7 @@
         "result_test.cpp",
         "rlimit_parser_test.cpp",
         "service_test.cpp",
+        "subcontext_test.cpp",
         "ueventd_test.cpp",
         "util_test.cpp",
     ],
@@ -188,4 +191,22 @@
     ],
 }
 
+cc_benchmark {
+    name: "init_benchmarks",
+    defaults: ["init_defaults"],
+    srcs: [
+        "subcontext_benchmark.cpp",
+    ],
+    shared_libs: [
+        "libbase",
+        "libcutils",
+    ],
+    static_libs: [
+        "libinit",
+        "libselinux",
+        "libcrypto",
+        "libprotobuf-cpp-lite",
+    ],
+}
+
 subdirs = ["*"]
diff --git a/init/action.cpp b/init/action.cpp
index 60204a8..2617d00 100644
--- a/init/action.cpp
+++ b/init/action.cpp
@@ -24,34 +24,48 @@
 #include "util.h"
 
 using android::base::Join;
+using android::base::StartsWith;
 
 namespace android {
 namespace init {
 
-Command::Command(BuiltinFunction f, const std::vector<std::string>& args, int line)
-    : func_(f), args_(args), line_(line) {}
+Result<Success> RunBuiltinFunction(const BuiltinFunction& function,
+                                   const std::vector<std::string>& args,
+                                   const std::string& context) {
+    auto builtin_arguments = BuiltinArguments(context);
 
-Result<Success> Command::InvokeFunc() const {
-    std::vector<std::string> expanded_args;
-    expanded_args.resize(args_.size());
-    expanded_args[0] = args_[0];
-    for (std::size_t i = 1; i < args_.size(); ++i) {
-        if (!expand_props(args_[i], &expanded_args[i])) {
-            return Error() << "cannot expand '" << args_[i] << "'";
+    builtin_arguments.args.resize(args.size());
+    builtin_arguments.args[0] = args[0];
+    for (std::size_t i = 1; i < args.size(); ++i) {
+        if (!expand_props(args[i], &builtin_arguments.args[i])) {
+            return Error() << "cannot expand '" << args[i] << "'";
         }
     }
 
-    return func_(expanded_args);
+    return function(builtin_arguments);
+}
+
+Command::Command(BuiltinFunction f, bool execute_in_subcontext,
+                 const std::vector<std::string>& args, int line)
+    : func_(std::move(f)), execute_in_subcontext_(execute_in_subcontext), args_(args), line_(line) {}
+
+Result<Success> Command::InvokeFunc(Subcontext* subcontext) const {
+    if (execute_in_subcontext_ && subcontext) {
+        return subcontext->Execute(args_);
+    } else {
+        const std::string& context = subcontext ? subcontext->context() : kInitContext;
+        return RunBuiltinFunction(func_, args_, context);
+    }
 }
 
 std::string Command::BuildCommandString() const {
     return Join(args_, ' ');
 }
 
-Action::Action(bool oneshot, const std::string& filename, int line)
-    : oneshot_(oneshot), filename_(filename), line_(line) {}
+Action::Action(bool oneshot, Subcontext* subcontext, const std::string& filename, int line)
+    : oneshot_(oneshot), subcontext_(subcontext), filename_(filename), line_(line) {}
 
-const KeywordMap<BuiltinFunction>* Action::function_map_ = nullptr;
+const KeywordFunctionMap* Action::function_map_ = nullptr;
 
 Result<Success> Action::AddCommand(const std::vector<std::string>& args, int line) {
     if (!function_map_) {
@@ -61,12 +75,12 @@
     auto function = function_map_->FindFunction(args);
     if (!function) return Error() << function.error();
 
-    AddCommand(*function, args, line);
+    commands_.emplace_back(function->second, function->first, args, line);
     return Success();
 }
 
 void Action::AddCommand(BuiltinFunction f, const std::vector<std::string>& args, int line) {
-    commands_.emplace_back(f, args, line);
+    commands_.emplace_back(f, false, args, line);
 }
 
 std::size_t Action::NumCommands() const {
@@ -88,7 +102,7 @@
 
 void Action::ExecuteCommand(const Command& command) const {
     android::base::Timer t;
-    auto result = command.InvokeFunc();
+    auto result = command.InvokeFunc(subcontext_);
     auto duration = t.duration();
 
     // There are many legacy paths in rootdir/init.rc that will virtually never exist on a new
@@ -261,7 +275,7 @@
 }
 
 void ActionManager::QueueBuiltinAction(BuiltinFunction func, const std::string& name) {
-    auto action = std::make_unique<Action>(true, "<Builtin Action>", 0);
+    auto action = std::make_unique<Action>(true, nullptr, "<Builtin Action>", 0);
     std::vector<std::string> name_vector{name};
 
     if (auto result = action->InitSingleTrigger(name); !result) {
@@ -341,7 +355,17 @@
         return Error() << "Actions must have a trigger";
     }
 
-    auto action = std::make_unique<Action>(false, filename, line);
+    Subcontext* action_subcontext = nullptr;
+    if (subcontexts_) {
+        for (auto& subcontext : *subcontexts_) {
+            if (StartsWith(filename, subcontext.path_prefix().c_str())) {
+                action_subcontext = &subcontext;
+                break;
+            }
+        }
+    }
+
+    auto action = std::make_unique<Action>(false, action_subcontext, filename, line);
 
     if (auto result = action->InitTriggers(triggers); !result) {
         return Error() << "InitTriggers() failed: " << result.error();
diff --git a/init/action.h b/init/action.h
index d977f82..cdfc6a0 100644
--- a/init/action.h
+++ b/init/action.h
@@ -27,21 +27,27 @@
 #include "keyword_map.h"
 #include "parser.h"
 #include "result.h"
+#include "subcontext.h"
 
 namespace android {
 namespace init {
 
+Result<Success> RunBuiltinFunction(const BuiltinFunction& function,
+                                   const std::vector<std::string>& args, const std::string& context);
+
 class Command {
   public:
-    Command(BuiltinFunction f, const std::vector<std::string>& args, int line);
+    Command(BuiltinFunction f, bool execute_in_subcontext, const std::vector<std::string>& args,
+            int line);
 
-    Result<Success> InvokeFunc() const;
+    Result<Success> InvokeFunc(Subcontext* subcontext) const;
     std::string BuildCommandString() const;
 
     int line() const { return line_; }
 
   private:
     BuiltinFunction func_;
+    bool execute_in_subcontext_;
     std::vector<std::string> args_;
     int line_;
 };
@@ -52,7 +58,7 @@
 
 class Action {
   public:
-    explicit Action(bool oneshot, const std::string& filename, int line);
+    Action(bool oneshot, Subcontext* subcontext, const std::string& filename, int line);
 
     Result<Success> AddCommand(const std::vector<std::string>& args, int line);
     void AddCommand(BuiltinFunction f, const std::vector<std::string>& args, int line);
@@ -70,12 +76,11 @@
     bool oneshot() const { return oneshot_; }
     const std::string& filename() const { return filename_; }
     int line() const { return line_; }
-    static void set_function_map(const KeywordMap<BuiltinFunction>* function_map) {
+    static void set_function_map(const KeywordFunctionMap* function_map) {
         function_map_ = function_map;
     }
 
-
-private:
+  private:
     void ExecuteCommand(const Command& command) const;
     bool CheckPropertyTriggers(const std::string& name = "",
                                const std::string& value = "") const;
@@ -85,9 +90,10 @@
     std::string event_trigger_;
     std::vector<Command> commands_;
     bool oneshot_;
+    Subcontext* subcontext_;
     std::string filename_;
     int line_;
-    static const KeywordMap<BuiltinFunction>* function_map_;
+    static const KeywordFunctionMap* function_map_;
 };
 
 class ActionManager {
@@ -119,8 +125,8 @@
 
 class ActionParser : public SectionParser {
   public:
-    ActionParser(ActionManager* action_manager)
-        : action_manager_(action_manager), action_(nullptr) {}
+    ActionParser(ActionManager* action_manager, std::vector<Subcontext>* subcontexts)
+        : action_manager_(action_manager), subcontexts_(subcontexts), action_(nullptr) {}
     Result<Success> ParseSection(std::vector<std::string>&& args, const std::string& filename,
                                  int line) override;
     Result<Success> ParseLineSection(std::vector<std::string>&& args, int line) override;
@@ -128,6 +134,7 @@
 
   private:
     ActionManager* action_manager_;
+    std::vector<Subcontext>* subcontexts_;
     std::unique_ptr<Action> action_;
 };
 
diff --git a/init/bootchart.cpp b/init/bootchart.cpp
index ec84317..379b4fa 100644
--- a/init/bootchart.cpp
+++ b/init/bootchart.cpp
@@ -191,7 +191,7 @@
     return Success();
 }
 
-Result<Success> do_bootchart(const std::vector<std::string>& args) {
+Result<Success> do_bootchart(const BuiltinArguments& args) {
     if (args[1] == "start") return do_bootchart_start();
     return do_bootchart_stop();
 }
diff --git a/init/bootchart.h b/init/bootchart.h
index f614f71..05474ca 100644
--- a/init/bootchart.h
+++ b/init/bootchart.h
@@ -20,12 +20,13 @@
 #include <string>
 #include <vector>
 
+#include "builtin_arguments.h"
 #include "result.h"
 
 namespace android {
 namespace init {
 
-Result<Success> do_bootchart(const std::vector<std::string>& args);
+Result<Success> do_bootchart(const BuiltinArguments& args);
 
 }  // namespace init
 }  // namespace android
diff --git a/init/builtin_arguments.h b/init/builtin_arguments.h
new file mode 100644
index 0000000..1742b78
--- /dev/null
+++ b/init/builtin_arguments.h
@@ -0,0 +1,43 @@
+/*
+ * 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_BUILTIN_ARGUMENTS_H
+#define _INIT_BUILTIN_ARGUMENTS_H
+
+#include <string>
+#include <vector>
+
+namespace android {
+namespace init {
+
+struct BuiltinArguments {
+    BuiltinArguments(const std::string& context) : context(context) {}
+    BuiltinArguments(std::vector<std::string> args, const std::string& context)
+        : args(std::move(args)), context(context) {}
+
+    const std::string& operator[](std::size_t i) const { return args[i]; }
+    auto begin() const { return args.begin(); }
+    auto end() const { return args.end(); }
+    auto size() const { return args.size(); }
+
+    std::vector<std::string> args;
+    const std::string& context;
+};
+
+}  // namespace init
+}  // namespace android
+
+#endif
diff --git a/init/builtins.cpp b/init/builtins.cpp
index 0fef883..4c2dc9a 100644
--- a/init/builtins.cpp
+++ b/init/builtins.cpp
@@ -66,6 +66,7 @@
 #include "reboot.h"
 #include "rlimit_parser.h"
 #include "service.h"
+#include "subcontext.h"
 #include "util.h"
 
 using namespace std::literals::string_literals;
@@ -95,36 +96,36 @@
     }
 }
 
-static Result<Success> do_class_start(const std::vector<std::string>& args) {
+static Result<Success> do_class_start(const BuiltinArguments& args) {
     // Starting a class does not start services which are explicitly disabled.
     // They must  be started individually.
     ForEachServiceInClass(args[1], &Service::StartIfNotDisabled);
     return Success();
 }
 
-static Result<Success> do_class_stop(const std::vector<std::string>& args) {
+static Result<Success> do_class_stop(const BuiltinArguments& args) {
     ForEachServiceInClass(args[1], &Service::Stop);
     return Success();
 }
 
-static Result<Success> do_class_reset(const std::vector<std::string>& args) {
+static Result<Success> do_class_reset(const BuiltinArguments& args) {
     ForEachServiceInClass(args[1], &Service::Reset);
     return Success();
 }
 
-static Result<Success> do_class_restart(const std::vector<std::string>& args) {
+static Result<Success> do_class_restart(const BuiltinArguments& args) {
     ForEachServiceInClass(args[1], &Service::Restart);
     return Success();
 }
 
-static Result<Success> do_domainname(const std::vector<std::string>& args) {
+static Result<Success> do_domainname(const BuiltinArguments& args) {
     if (auto result = WriteFile("/proc/sys/kernel/domainname", args[1]); !result) {
         return Error() << "Unable to write to /proc/sys/kernel/domainname: " << result.error();
     }
     return Success();
 }
 
-static Result<Success> do_enable(const std::vector<std::string>& args) {
+static Result<Success> do_enable(const BuiltinArguments& args) {
     Service* svc = ServiceList::GetInstance().FindService(args[1]);
     if (!svc) return Error() << "Could not find service";
 
@@ -135,8 +136,8 @@
     return Success();
 }
 
-static Result<Success> do_exec(const std::vector<std::string>& args) {
-    auto service = Service::MakeTemporaryOneshotService(args);
+static Result<Success> do_exec(const BuiltinArguments& args) {
+    auto service = Service::MakeTemporaryOneshotService(args.args);
     if (!service) {
         return Error() << "Could not create exec service";
     }
@@ -148,8 +149,8 @@
     return Success();
 }
 
-static Result<Success> do_exec_background(const std::vector<std::string>& args) {
-    auto service = Service::MakeTemporaryOneshotService(args);
+static Result<Success> do_exec_background(const BuiltinArguments& args) {
+    auto service = Service::MakeTemporaryOneshotService(args.args);
     if (!service) {
         return Error() << "Could not create exec background service";
     }
@@ -161,7 +162,7 @@
     return Success();
 }
 
-static Result<Success> do_exec_start(const std::vector<std::string>& args) {
+static Result<Success> do_exec_start(const BuiltinArguments& args) {
     Service* service = ServiceList::GetInstance().FindService(args[1]);
     if (!service) {
         return Error() << "Service not found";
@@ -174,21 +175,21 @@
     return Success();
 }
 
-static Result<Success> do_export(const std::vector<std::string>& args) {
+static Result<Success> do_export(const BuiltinArguments& args) {
     if (setenv(args[1].c_str(), args[2].c_str(), 1) == -1) {
         return ErrnoError() << "setenv() failed";
     }
     return Success();
 }
 
-static Result<Success> do_hostname(const std::vector<std::string>& args) {
+static Result<Success> do_hostname(const BuiltinArguments& args) {
     if (auto result = WriteFile("/proc/sys/kernel/hostname", args[1]); !result) {
         return Error() << "Unable to write to /proc/sys/kernel/hostname: " << result.error();
     }
     return Success();
 }
 
-static Result<Success> do_ifup(const std::vector<std::string>& args) {
+static Result<Success> do_ifup(const BuiltinArguments& args) {
     struct ifreq ifr;
 
     strlcpy(ifr.ifr_name, args[1].c_str(), IFNAMSIZ);
@@ -209,7 +210,7 @@
     return Success();
 }
 
-static Result<Success> do_insmod(const std::vector<std::string>& args) {
+static Result<Success> do_insmod(const BuiltinArguments& args) {
     int flags = 0;
     auto it = args.begin() + 1;
 
@@ -231,7 +232,7 @@
 }
 
 // mkdir <path> [mode] [owner] [group]
-static Result<Success> do_mkdir(const std::vector<std::string>& args) {
+static Result<Success> do_mkdir(const BuiltinArguments& args) {
     mode_t mode = 0755;
     if (args.size() >= 3) {
         mode = std::strtoul(args[2].c_str(), 0, 8);
@@ -287,7 +288,7 @@
 }
 
 /* umount <path> */
-static Result<Success> do_umount(const std::vector<std::string>& args) {
+static Result<Success> do_umount(const BuiltinArguments& args) {
     if (umount(args[1].c_str()) < 0) {
         return ErrnoError() << "umount() failed";
     }
@@ -319,7 +320,7 @@
 #define DATA_MNT_POINT "/data"
 
 /* mount <type> <device> <path> <flags ...> <options> */
-static Result<Success> do_mount(const std::vector<std::string>& args) {
+static Result<Success> do_mount(const BuiltinArguments& args) {
     const char* options = nullptr;
     unsigned flags = 0;
     bool wait = false;
@@ -530,7 +531,7 @@
  * This function might request a reboot, in which case it will
  * not return.
  */
-static Result<Success> do_mount_all(const std::vector<std::string>& args) {
+static Result<Success> do_mount_all(const BuiltinArguments& args) {
     std::size_t na = 0;
     bool import_rc = true;
     bool queue_event = true;
@@ -563,7 +564,7 @@
 
     if (import_rc) {
         /* Paths of .rc files are specified at the 2nd argument and beyond */
-        import_late(args, 2, path_arg_end);
+        import_late(args.args, 2, path_arg_end);
     }
 
     if (queue_event) {
@@ -578,7 +579,7 @@
     return Success();
 }
 
-static Result<Success> do_swapon_all(const std::vector<std::string>& args) {
+static Result<Success> do_swapon_all(const BuiltinArguments& args) {
     struct fstab *fstab;
     int ret;
 
@@ -590,13 +591,13 @@
     return Success();
 }
 
-static Result<Success> do_setprop(const std::vector<std::string>& args) {
+static Result<Success> do_setprop(const BuiltinArguments& args) {
     property_set(args[1], args[2]);
     return Success();
 }
 
-static Result<Success> do_setrlimit(const std::vector<std::string>& args) {
-    auto rlimit = ParseRlimit(args);
+static Result<Success> do_setrlimit(const BuiltinArguments& args) {
+    auto rlimit = ParseRlimit(args.args);
     if (!rlimit) return rlimit.error();
 
     if (setrlimit(rlimit->first, &rlimit->second) == -1) {
@@ -605,7 +606,7 @@
     return Success();
 }
 
-static Result<Success> do_start(const std::vector<std::string>& args) {
+static Result<Success> do_start(const BuiltinArguments& args) {
     Service* svc = ServiceList::GetInstance().FindService(args[1]);
     if (!svc) return Error() << "service " << args[1] << " not found";
     if (auto result = svc->Start(); !result) {
@@ -614,26 +615,26 @@
     return Success();
 }
 
-static Result<Success> do_stop(const std::vector<std::string>& args) {
+static Result<Success> do_stop(const BuiltinArguments& args) {
     Service* svc = ServiceList::GetInstance().FindService(args[1]);
     if (!svc) return Error() << "service " << args[1] << " not found";
     svc->Stop();
     return Success();
 }
 
-static Result<Success> do_restart(const std::vector<std::string>& args) {
+static Result<Success> do_restart(const BuiltinArguments& args) {
     Service* svc = ServiceList::GetInstance().FindService(args[1]);
     if (!svc) return Error() << "service " << args[1] << " not found";
     svc->Restart();
     return Success();
 }
 
-static Result<Success> do_trigger(const std::vector<std::string>& args) {
+static Result<Success> do_trigger(const BuiltinArguments& args) {
     ActionManager::GetInstance().QueueEventTrigger(args[1]);
     return Success();
 }
 
-static Result<Success> do_symlink(const std::vector<std::string>& args) {
+static Result<Success> do_symlink(const BuiltinArguments& args) {
     if (symlink(args[1].c_str(), args[2].c_str()) < 0) {
         // The symlink builtin is often used to create symlinks for older devices to be backwards
         // compatible with new paths, therefore we skip reporting this error.
@@ -645,21 +646,21 @@
     return Success();
 }
 
-static Result<Success> do_rm(const std::vector<std::string>& args) {
+static Result<Success> do_rm(const BuiltinArguments& args) {
     if (unlink(args[1].c_str()) < 0) {
         return ErrnoError() << "unlink() failed";
     }
     return Success();
 }
 
-static Result<Success> do_rmdir(const std::vector<std::string>& args) {
+static Result<Success> do_rmdir(const BuiltinArguments& args) {
     if (rmdir(args[1].c_str()) < 0) {
         return ErrnoError() << "rmdir() failed";
     }
     return Success();
 }
 
-static Result<Success> do_sysclktz(const std::vector<std::string>& args) {
+static Result<Success> do_sysclktz(const BuiltinArguments& args) {
     struct timezone tz = {};
     if (!android::base::ParseInt(args[1], &tz.tz_minuteswest)) {
         return Error() << "Unable to parse mins_west_of_gmt";
@@ -671,7 +672,7 @@
     return Success();
 }
 
-static Result<Success> do_verity_load_state(const std::vector<std::string>& args) {
+static Result<Success> do_verity_load_state(const BuiltinArguments& args) {
     int mode = -1;
     bool loaded = fs_mgr_load_verity_state(&mode);
     if (loaded && mode != VERITY_MODE_DEFAULT) {
@@ -687,14 +688,14 @@
     property_set("partition."s + mount_point + ".verified", std::to_string(mode));
 }
 
-static Result<Success> do_verity_update_state(const std::vector<std::string>& args) {
+static Result<Success> do_verity_update_state(const BuiltinArguments& args) {
     if (!fs_mgr_update_verity_state(verity_update_property)) {
         return Error() << "fs_mgr_update_verity_state() failed";
     }
     return Success();
 }
 
-static Result<Success> do_write(const std::vector<std::string>& args) {
+static Result<Success> do_write(const BuiltinArguments& args) {
     if (auto result = WriteFile(args[1], args[2]); !result) {
         return Error() << "Unable to write to file '" << args[1] << "': " << result.error();
     }
@@ -725,7 +726,7 @@
     return Success();
 }
 
-static Result<Success> do_readahead(const std::vector<std::string>& args) {
+static Result<Success> do_readahead(const BuiltinArguments& args) {
     struct stat sb;
 
     if (stat(args[1].c_str(), &sb)) {
@@ -784,7 +785,7 @@
     return Success();
 }
 
-static Result<Success> do_copy(const std::vector<std::string>& args) {
+static Result<Success> do_copy(const BuiltinArguments& args) {
     auto file_contents = ReadFile(args[1]);
     if (!file_contents) {
         return Error() << "Could not read input file '" << args[1] << "': " << file_contents.error();
@@ -796,7 +797,7 @@
     return Success();
 }
 
-static Result<Success> do_chown(const std::vector<std::string>& args) {
+static Result<Success> do_chown(const BuiltinArguments& args) {
     auto uid = DecodeUid(args[1]);
     if (!uid) {
         return Error() << "Unable to decode UID for '" << args[1] << "': " << uid.error();
@@ -833,7 +834,7 @@
     return mode;
 }
 
-static Result<Success> do_chmod(const std::vector<std::string>& args) {
+static Result<Success> do_chmod(const BuiltinArguments& args) {
     mode_t mode = get_mode(args[1].c_str());
     if (fchmodat(AT_FDCWD, args[2].c_str(), mode, AT_SYMLINK_NOFOLLOW) < 0) {
         return ErrnoError() << "fchmodat() failed";
@@ -841,7 +842,7 @@
     return Success();
 }
 
-static Result<Success> do_restorecon(const std::vector<std::string>& args) {
+static Result<Success> do_restorecon(const BuiltinArguments& args) {
     int ret = 0;
 
     struct flag_type {const char* name; int value;};
@@ -883,13 +884,13 @@
     return Success();
 }
 
-static Result<Success> do_restorecon_recursive(const std::vector<std::string>& args) {
-    std::vector<std::string> non_const_args(args);
+static Result<Success> do_restorecon_recursive(const BuiltinArguments& args) {
+    std::vector<std::string> non_const_args(args.args);
     non_const_args.insert(std::next(non_const_args.begin()), "--recursive");
-    return do_restorecon(non_const_args);
+    return do_restorecon({std::move(non_const_args), args.context});
 }
 
-static Result<Success> do_loglevel(const std::vector<std::string>& args) {
+static Result<Success> do_loglevel(const BuiltinArguments& args) {
     // TODO: support names instead/as well?
     int log_level = -1;
     android::base::ParseInt(args[1], &log_level);
@@ -910,17 +911,17 @@
     return Success();
 }
 
-static Result<Success> do_load_persist_props(const std::vector<std::string>& args) {
+static Result<Success> do_load_persist_props(const BuiltinArguments& args) {
     load_persist_props();
     return Success();
 }
 
-static Result<Success> do_load_system_props(const std::vector<std::string>& args) {
+static Result<Success> do_load_system_props(const BuiltinArguments& args) {
     load_system_props();
     return Success();
 }
 
-static Result<Success> do_wait(const std::vector<std::string>& args) {
+static Result<Success> do_wait(const BuiltinArguments& args) {
     auto timeout = kCommandRetryTimeout;
     if (args.size() == 3) {
         int timeout_int;
@@ -937,7 +938,7 @@
     return Success();
 }
 
-static Result<Success> do_wait_for_prop(const std::vector<std::string>& args) {
+static Result<Success> do_wait_for_prop(const BuiltinArguments& args) {
     const char* name = args[1].c_str();
     const char* value = args[2].c_str();
     size_t value_len = strlen(value);
@@ -958,7 +959,7 @@
     return android::base::GetProperty("ro.crypto.type", "") == "file";
 }
 
-static Result<Success> do_installkey(const std::vector<std::string>& args) {
+static Result<Success> do_installkey(const BuiltinArguments& args) {
     if (!is_file_crypto()) return Success();
 
     auto unencrypted_dir = args[1] + e4crypt_unencrypted_folder;
@@ -967,64 +968,66 @@
     }
     std::vector<std::string> exec_args = {"exec", "/system/bin/vdc", "--wait", "cryptfs",
                                           "enablefilecrypto"};
-    return do_exec(exec_args);
+    return do_exec({std::move(exec_args), args.context});
 }
 
-static Result<Success> do_init_user0(const std::vector<std::string>& args) {
+static Result<Success> do_init_user0(const BuiltinArguments& args) {
     std::vector<std::string> exec_args = {"exec", "/system/bin/vdc", "--wait", "cryptfs",
                                           "init_user0"};
-    return do_exec(exec_args);
+    return do_exec({std::move(exec_args), args.context});
 }
 
 const BuiltinFunctionMap::Map& BuiltinFunctionMap::map() const {
     constexpr std::size_t kMax = std::numeric_limits<std::size_t>::max();
     // clang-format off
     static const Map builtin_functions = {
-        {"bootchart",               {1,     1,    do_bootchart}},
-        {"chmod",                   {2,     2,    do_chmod}},
-        {"chown",                   {2,     3,    do_chown}},
-        {"class_reset",             {1,     1,    do_class_reset}},
-        {"class_restart",           {1,     1,    do_class_restart}},
-        {"class_start",             {1,     1,    do_class_start}},
-        {"class_stop",              {1,     1,    do_class_stop}},
-        {"copy",                    {2,     2,    do_copy}},
-        {"domainname",              {1,     1,    do_domainname}},
-        {"enable",                  {1,     1,    do_enable}},
-        {"exec",                    {1,     kMax, do_exec}},
-        {"exec_background",         {1,     kMax, do_exec_background}},
-        {"exec_start",              {1,     1,    do_exec_start}},
-        {"export",                  {2,     2,    do_export}},
-        {"hostname",                {1,     1,    do_hostname}},
-        {"ifup",                    {1,     1,    do_ifup}},
-        {"init_user0",              {0,     0,    do_init_user0}},
-        {"insmod",                  {1,     kMax, do_insmod}},
-        {"installkey",              {1,     1,    do_installkey}},
-        {"load_persist_props",      {0,     0,    do_load_persist_props}},
-        {"load_system_props",       {0,     0,    do_load_system_props}},
-        {"loglevel",                {1,     1,    do_loglevel}},
-        {"mkdir",                   {1,     4,    do_mkdir}},
-        {"mount_all",               {1,     kMax, do_mount_all}},
-        {"mount",                   {3,     kMax, do_mount}},
-        {"umount",                  {1,     1,    do_umount}},
-        {"readahead",               {1,     2,    do_readahead}},
-        {"restart",                 {1,     1,    do_restart}},
-        {"restorecon",              {1,     kMax, do_restorecon}},
-        {"restorecon_recursive",    {1,     kMax, do_restorecon_recursive}},
-        {"rm",                      {1,     1,    do_rm}},
-        {"rmdir",                   {1,     1,    do_rmdir}},
-        {"setprop",                 {2,     2,    do_setprop}},
-        {"setrlimit",               {3,     3,    do_setrlimit}},
-        {"start",                   {1,     1,    do_start}},
-        {"stop",                    {1,     1,    do_stop}},
-        {"swapon_all",              {1,     1,    do_swapon_all}},
-        {"symlink",                 {2,     2,    do_symlink}},
-        {"sysclktz",                {1,     1,    do_sysclktz}},
-        {"trigger",                 {1,     1,    do_trigger}},
-        {"verity_load_state",       {0,     0,    do_verity_load_state}},
-        {"verity_update_state",     {0,     0,    do_verity_update_state}},
-        {"wait",                    {1,     2,    do_wait}},
-        {"wait_for_prop",           {2,     2,    do_wait_for_prop}},
-        {"write",                   {2,     2,    do_write}},
+        {"bootchart",               {1,     1,    {false,  do_bootchart}}},
+        {"chmod",                   {2,     2,    {true,   do_chmod}}},
+        {"chown",                   {2,     3,    {true,   do_chown}}},
+        {"class_reset",             {1,     1,    {false,  do_class_reset}}},
+        {"class_restart",           {1,     1,    {false,  do_class_restart}}},
+        {"class_start",             {1,     1,    {false,  do_class_start}}},
+        {"class_stop",              {1,     1,    {false,  do_class_stop}}},
+        {"copy",                    {2,     2,    {true,   do_copy}}},
+        {"domainname",              {1,     1,    {true,   do_domainname}}},
+        {"enable",                  {1,     1,    {false,  do_enable}}},
+        {"exec",                    {1,     kMax, {false,  do_exec}}},
+        {"exec_background",         {1,     kMax, {false,  do_exec_background}}},
+        {"exec_start",              {1,     1,    {false,  do_exec_start}}},
+        {"export",                  {2,     2,    {false,  do_export}}},
+        {"hostname",                {1,     1,    {true,   do_hostname}}},
+        {"ifup",                    {1,     1,    {true,   do_ifup}}},
+        {"init_user0",              {0,     0,    {false,  do_init_user0}}},
+        {"insmod",                  {1,     kMax, {true,   do_insmod}}},
+        {"installkey",              {1,     1,    {false,  do_installkey}}},
+        {"load_persist_props",      {0,     0,    {false,  do_load_persist_props}}},
+        {"load_system_props",       {0,     0,    {false,  do_load_system_props}}},
+        {"loglevel",                {1,     1,    {false,  do_loglevel}}},
+        {"mkdir",                   {1,     4,    {true,   do_mkdir}}},
+        {"mount_all",               {1,     kMax, {false,  do_mount_all}}},
+        {"mount",                   {3,     kMax, {false,  do_mount}}},
+        {"umount",                  {1,     1,    {false,  do_umount}}},
+        {"readahead",               {1,     2,    {true,   do_readahead}}},
+        {"restart",                 {1,     1,    {false,  do_restart}}},
+        {"restorecon",              {1,     kMax, {true,   do_restorecon}}},
+        {"restorecon_recursive",    {1,     kMax, {true,   do_restorecon_recursive}}},
+        {"rm",                      {1,     1,    {true,   do_rm}}},
+        {"rmdir",                   {1,     1,    {true,   do_rmdir}}},
+        //  TODO: setprop should be run in the subcontext, but property service needs to be split
+        //        out from init before that is possible.
+        {"setprop",                 {2,     2,    {false,  do_setprop}}},
+        {"setrlimit",               {3,     3,    {false,  do_setrlimit}}},
+        {"start",                   {1,     1,    {false,  do_start}}},
+        {"stop",                    {1,     1,    {false,  do_stop}}},
+        {"swapon_all",              {1,     1,    {false,  do_swapon_all}}},
+        {"symlink",                 {2,     2,    {true,   do_symlink}}},
+        {"sysclktz",                {1,     1,    {false,  do_sysclktz}}},
+        {"trigger",                 {1,     1,    {false,  do_trigger}}},
+        {"verity_load_state",       {0,     0,    {false,  do_verity_load_state}}},
+        {"verity_update_state",     {0,     0,    {false,  do_verity_update_state}}},
+        {"wait",                    {1,     2,    {true,   do_wait}}},
+        {"wait_for_prop",           {2,     2,    {true,   do_wait_for_prop}}},
+        {"write",                   {2,     2,    {true,   do_write}}},
     };
     // clang-format on
     return builtin_functions;
diff --git a/init/builtins.h b/init/builtins.h
index f66ae19..814b2d5 100644
--- a/init/builtins.h
+++ b/init/builtins.h
@@ -22,14 +22,17 @@
 #include <string>
 #include <vector>
 
+#include "builtin_arguments.h"
 #include "keyword_map.h"
 #include "result.h"
 
 namespace android {
 namespace init {
 
-using BuiltinFunction = std::function<Result<Success>(const std::vector<std::string>&)>;
-class BuiltinFunctionMap : public KeywordMap<BuiltinFunction> {
+using BuiltinFunction = std::function<Result<Success>(const BuiltinArguments&)>;
+
+using KeywordFunctionMap = KeywordMap<std::pair<bool, BuiltinFunction>>;
+class BuiltinFunctionMap : public KeywordFunctionMap {
   public:
     BuiltinFunctionMap() {}
 
diff --git a/init/init.cpp b/init/init.cpp
index ad045b1..51a98a2 100644
--- a/init/init.cpp
+++ b/init/init.cpp
@@ -84,6 +84,8 @@
 
 std::vector<std::string> late_import_paths;
 
+static std::vector<Subcontext>* subcontexts;
+
 void DumpState() {
     ServiceList::GetInstance().DumpState();
     ActionManager::GetInstance().DumpState();
@@ -92,8 +94,8 @@
 Parser CreateParser(ActionManager& action_manager, ServiceList& service_list) {
     Parser parser;
 
-    parser.AddSectionParser("service", std::make_unique<ServiceParser>(&service_list));
-    parser.AddSectionParser("on", std::make_unique<ActionParser>(&action_manager));
+    parser.AddSectionParser("service", std::make_unique<ServiceParser>(&service_list, subcontexts));
+    parser.AddSectionParser("on", std::make_unique<ActionParser>(&action_manager, subcontexts));
     parser.AddSectionParser("import", std::make_unique<ImportParser>(&parser));
 
     return parser;
@@ -220,7 +222,7 @@
     }
 }
 
-static Result<Success> wait_for_coldboot_done_action(const std::vector<std::string>& args) {
+static Result<Success> wait_for_coldboot_done_action(const BuiltinArguments& args) {
     Timer t;
 
     LOG(VERBOSE) << "Waiting for " COLDBOOT_DONE "...";
@@ -241,12 +243,12 @@
     return Success();
 }
 
-static Result<Success> keychord_init_action(const std::vector<std::string>& args) {
+static Result<Success> keychord_init_action(const BuiltinArguments& args) {
     keychord_init();
     return Success();
 }
 
-static Result<Success> console_init_action(const std::vector<std::string>& args) {
+static Result<Success> console_init_action(const BuiltinArguments& args) {
     std::string console = GetProperty("ro.boot.console", "");
     if (!console.empty()) {
         default_console = "/dev/" + console;
@@ -333,13 +335,13 @@
     if (qemu[0]) import_kernel_cmdline(true, import_kernel_nv);
 }
 
-static Result<Success> property_enable_triggers_action(const std::vector<std::string>& args) {
+static Result<Success> property_enable_triggers_action(const BuiltinArguments& args) {
     /* Enable property triggers. */
     property_triggers_enabled = 1;
     return Success();
 }
 
-static Result<Success> queue_property_triggers_action(const std::vector<std::string>& args) {
+static Result<Success> queue_property_triggers_action(const BuiltinArguments& args) {
     ActionManager::GetInstance().QueueBuiltinAction(property_enable_triggers_action, "enable_property_trigger");
     ActionManager::GetInstance().QueueAllPropertyActions();
     return Success();
@@ -446,6 +448,12 @@
         return watchdogd_main(argc, argv);
     }
 
+    if (argc > 1 && !strcmp(argv[1], "subcontext")) {
+        InitKernelLogging(argv);
+        const BuiltinFunctionMap function_map;
+        return SubcontextMain(argc, argv, &function_map);
+    }
+
     if (REBOOT_BOOTLOADER_ON_PANIC) {
         InstallRebootSignalHandlers();
     }
@@ -587,6 +595,8 @@
     const BuiltinFunctionMap function_map;
     Action::set_function_map(&function_map);
 
+    subcontexts = InitializeSubcontexts();
+
     ActionManager& am = ActionManager::GetInstance();
     ServiceList& sm = ServiceList::GetInstance();
 
diff --git a/init/init_test.cpp b/init/init_test.cpp
index 27659f9..29a65ab 100644
--- a/init/init_test.cpp
+++ b/init/init_test.cpp
@@ -25,33 +25,12 @@
 #include "import_parser.h"
 #include "keyword_map.h"
 #include "parser.h"
+#include "test_function_map.h"
 #include "util.h"
 
 namespace android {
 namespace init {
 
-class TestFunctionMap : public KeywordMap<BuiltinFunction> {
-  public:
-    // Helper for argument-less functions
-    using BuiltinFunctionNoArgs = std::function<void(void)>;
-    void Add(const std::string& name, const BuiltinFunctionNoArgs function) {
-        Add(name, 0, 0, [function](const std::vector<std::string>&) {
-            function();
-            return Success();
-        });
-    }
-
-    void Add(const std::string& name, std::size_t min_parameters, std::size_t max_parameters,
-             const BuiltinFunction function) {
-        builtin_functions_[name] = make_tuple(min_parameters, max_parameters, function);
-    }
-
-  private:
-    Map builtin_functions_ = {};
-
-    const Map& map() const override { return builtin_functions_; }
-};
-
 using ActionManagerCommand = std::function<void(ActionManager&)>;
 
 void TestInit(const std::string& init_script_file, const TestFunctionMap& test_function_map,
@@ -61,7 +40,7 @@
     Action::set_function_map(&test_function_map);
 
     Parser parser;
-    parser.AddSectionParser("on", std::make_unique<ActionParser>(&am));
+    parser.AddSectionParser("on", std::make_unique<ActionParser>(&am, nullptr));
     parser.AddSectionParser("import", std::make_unique<ImportParser>(&parser));
 
     ASSERT_TRUE(parser.ParseConfig(init_script_file));
@@ -171,14 +150,14 @@
     ASSERT_TRUE(android::base::WriteStringToFd(start_script, start.fd));
 
     int num_executed = 0;
-    auto execute_command = [&num_executed](const std::vector<std::string>& args) {
+    auto execute_command = [&num_executed](const BuiltinArguments& args) {
         EXPECT_EQ(2U, args.size());
         EXPECT_EQ(++num_executed, std::stoi(args[1]));
         return Success();
     };
 
     TestFunctionMap test_function_map;
-    test_function_map.Add("execute", 1, 1, execute_command);
+    test_function_map.Add("execute", 1, 1, false, execute_command);
 
     ActionManagerCommand trigger_boot = [](ActionManager& am) { am.QueueEventTrigger("boot"); };
     std::vector<ActionManagerCommand> commands{trigger_boot};
diff --git a/init/reboot.cpp b/init/reboot.cpp
index 18f493a..d06dcc5 100644
--- a/init/reboot.cpp
+++ b/init/reboot.cpp
@@ -521,8 +521,7 @@
     // Queue shutdown trigger first
     ActionManager::GetInstance().QueueEventTrigger("shutdown");
     // Queue built-in shutdown_done
-    auto shutdown_handler = [cmd, command, reboot_target,
-                             run_fsck](const std::vector<std::string>&) {
+    auto shutdown_handler = [cmd, command, reboot_target, run_fsck](const BuiltinArguments&) {
         DoReboot(cmd, command, reboot_target, run_fsck);
         return Success();
     };
diff --git a/init/security.cpp b/init/security.cpp
index aac8f2e..a3494a2 100644
--- a/init/security.cpp
+++ b/init/security.cpp
@@ -43,7 +43,7 @@
 // devices/configurations where these I/O operations are blocking for a long
 // time. We do not reboot or halt on failures, as this is a best-effort
 // attempt.
-Result<Success> MixHwrngIntoLinuxRngAction(const std::vector<std::string>& args) {
+Result<Success> MixHwrngIntoLinuxRngAction(const BuiltinArguments&) {
     unique_fd hwrandom_fd(
         TEMP_FAILURE_RETRY(open("/dev/hw_random", O_RDONLY | O_NOFOLLOW | O_CLOEXEC)));
     if (hwrandom_fd == -1) {
@@ -147,7 +147,7 @@
 // 9e08f57d684a x86: mm: support ARCH_MMAP_RND_BITS
 // ec9ee4acd97c drivers: char: random: add get_random_long()
 // 5ef11c35ce86 mm: ASLR: use get_random_long()
-Result<Success> SetMmapRndBitsAction(const std::vector<std::string>& args) {
+Result<Success> SetMmapRndBitsAction(const BuiltinArguments&) {
 // values are arch-dependent
 #if defined(USER_MODE_LINUX)
     // uml does not support mmap_rnd_bits
@@ -187,7 +187,7 @@
 // Set kptr_restrict to the highest available level.
 //
 // Aborts if unable to set this to an acceptable value.
-Result<Success> SetKptrRestrictAction(const std::vector<std::string>& args) {
+Result<Success> SetKptrRestrictAction(const BuiltinArguments&) {
     std::string path = KPTR_RESTRICT_PATH;
 
     if (!SetHighestAvailableOptionValue(path, KPTR_RESTRICT_MINVALUE, KPTR_RESTRICT_MAXVALUE)) {
diff --git a/init/security.h b/init/security.h
index 31e5790..6f6b944 100644
--- a/init/security.h
+++ b/init/security.h
@@ -20,14 +20,15 @@
 #include <string>
 #include <vector>
 
+#include "builtin_arguments.h"
 #include "result.h"
 
 namespace android {
 namespace init {
 
-Result<Success> MixHwrngIntoLinuxRngAction(const std::vector<std::string>& args);
-Result<Success> SetMmapRndBitsAction(const std::vector<std::string>& args);
-Result<Success> SetKptrRestrictAction(const std::vector<std::string>& args);
+Result<Success> MixHwrngIntoLinuxRngAction(const BuiltinArguments&);
+Result<Success> SetMmapRndBitsAction(const BuiltinArguments&);
+Result<Success> SetKptrRestrictAction(const BuiltinArguments&);
 
 }  // namespace init
 }  // namespace android
diff --git a/init/service.cpp b/init/service.cpp
index 86b910a..b339bc0 100644
--- a/init/service.cpp
+++ b/init/service.cpp
@@ -155,13 +155,14 @@
 unsigned long Service::next_start_order_ = 1;
 bool Service::is_exec_service_running_ = false;
 
-Service::Service(const std::string& name, const std::vector<std::string>& args)
-    : Service(name, 0, 0, 0, {}, 0, 0, "", args) {}
+Service::Service(const std::string& name, Subcontext* subcontext_for_restart_commands,
+                 const std::vector<std::string>& args)
+    : Service(name, 0, 0, 0, {}, 0, 0, "", subcontext_for_restart_commands, args) {}
 
 Service::Service(const std::string& name, unsigned flags, uid_t uid, gid_t gid,
                  const std::vector<gid_t>& supp_gids, const CapSet& capabilities,
                  unsigned namespace_flags, const std::string& seclabel,
-                 const std::vector<std::string>& args)
+                 Subcontext* subcontext_for_restart_commands, const std::vector<std::string>& args)
     : name_(name),
       classnames_({"default"}),
       flags_(flags),
@@ -173,7 +174,7 @@
       capabilities_(capabilities),
       namespace_flags_(namespace_flags),
       seclabel_(seclabel),
-      onrestart_(false, "<Service '" + name + "' onrestart>", 0),
+      onrestart_(false, subcontext_for_restart_commands, "<Service '" + name + "' onrestart>", 0),
       keychord_id_(0),
       ioprio_class_(IoSchedClass_NONE),
       ioprio_pri_(0),
@@ -1007,7 +1008,7 @@
     }
 
     return std::make_unique<Service>(name, flags, *uid, *gid, supp_gids, no_capabilities,
-                                     namespace_flags, seclabel, str_args);
+                                     namespace_flags, seclabel, nullptr, str_args);
 }
 
 // Shutdown services in the opposite order that they were started.
@@ -1055,8 +1056,18 @@
         return Error() << "ignored duplicate definition of service '" << name << "'";
     }
 
+    Subcontext* restart_action_subcontext = nullptr;
+    if (subcontexts_) {
+        for (auto& subcontext : *subcontexts_) {
+            if (StartsWith(filename, subcontext.path_prefix().c_str())) {
+                restart_action_subcontext = &subcontext;
+                break;
+            }
+        }
+    }
+
     std::vector<std::string> str_args(args.begin() + 2, args.end());
-    service_ = std::make_unique<Service>(name, str_args);
+    service_ = std::make_unique<Service>(name, restart_action_subcontext, str_args);
     return Success();
 }
 
diff --git a/init/service.h b/init/service.h
index 67542ca..89dd780 100644
--- a/init/service.h
+++ b/init/service.h
@@ -33,6 +33,7 @@
 #include "descriptors.h"
 #include "keyword_map.h"
 #include "parser.h"
+#include "subcontext.h"
 
 #define SVC_DISABLED 0x001        // do not autostart with class
 #define SVC_ONESHOT 0x002         // do not restart on exit
@@ -60,12 +61,13 @@
 
 class Service {
   public:
-    Service(const std::string& name, const std::vector<std::string>& args);
+    Service(const std::string& name, Subcontext* subcontext_for_restart_commands,
+            const std::vector<std::string>& args);
 
     Service(const std::string& name, unsigned flags, uid_t uid, gid_t gid,
             const std::vector<gid_t>& supp_gids, const CapSet& capabilities,
             unsigned namespace_flags, const std::string& seclabel,
-            const std::vector<std::string>& args);
+            Subcontext* subcontext_for_restart_commands, const std::vector<std::string>& args);
 
     static std::unique_ptr<Service> MakeTemporaryOneshotService(const std::vector<std::string>& args);
 
@@ -237,7 +239,8 @@
 
 class ServiceParser : public SectionParser {
   public:
-    ServiceParser(ServiceList* service_list) : service_list_(service_list), service_(nullptr) {}
+    ServiceParser(ServiceList* service_list, std::vector<Subcontext>* subcontexts)
+        : service_list_(service_list), subcontexts_(subcontexts), service_(nullptr) {}
     Result<Success> ParseSection(std::vector<std::string>&& args, const std::string& filename,
                                  int line) override;
     Result<Success> ParseLineSection(std::vector<std::string>&& args, int line) override;
@@ -247,6 +250,7 @@
     bool IsValidName(const std::string& name) const;
 
     ServiceList* service_list_;
+    std::vector<Subcontext>* subcontexts_;
     std::unique_ptr<Service> service_;
 };
 
diff --git a/init/service_test.cpp b/init/service_test.cpp
index 98d876f..b43c2e9 100644
--- a/init/service_test.cpp
+++ b/init/service_test.cpp
@@ -37,7 +37,8 @@
     }
 
     std::vector<std::string> dummy_args{"/bin/test"};
-    Service* service_in_old_memory = new (old_memory) Service("test_old_memory", dummy_args);
+    Service* service_in_old_memory =
+        new (old_memory) Service("test_old_memory", nullptr, dummy_args);
 
     EXPECT_EQ(0U, service_in_old_memory->flags());
     EXPECT_EQ(0, service_in_old_memory->pid());
@@ -56,8 +57,8 @@
         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);
+    Service* service_in_old_memory2 = new (old_memory) Service(
+        "test_old_memory", 0U, 0U, 0U, std::vector<gid_t>(), CapSet(), 0U, "", nullptr, dummy_args);
 
     EXPECT_EQ(0U, service_in_old_memory2->flags());
     EXPECT_EQ(0, service_in_old_memory2->pid());
diff --git a/init/sigchld_handler.cpp b/init/sigchld_handler.cpp
index fa67199..072a0fb 100644
--- a/init/sigchld_handler.cpp
+++ b/init/sigchld_handler.cpp
@@ -60,22 +60,28 @@
     // want the pid to remain valid throughout that (and potentially future) usages.
     auto reaper = make_scope_guard([pid] { TEMP_FAILURE_RETRY(waitpid(pid, nullptr, WNOHANG)); });
 
-    if (PropertyChildReap(pid)) return true;
-
-    Service* service = ServiceList::GetInstance().FindService(pid, &Service::pid);
-
     std::string name;
     std::string wait_string;
-    if (service) {
-        name = StringPrintf("Service '%s' (pid %d)", service->name().c_str(), pid);
-        if (service->flags() & SVC_EXEC) {
-            auto exec_duration = boot_clock::now() - service->time_started();
-            auto exec_duration_ms =
-                std::chrono::duration_cast<std::chrono::milliseconds>(exec_duration).count();
-            wait_string = StringPrintf(" waiting took %f seconds", exec_duration_ms / 1000.0f);
-        }
+    Service* service = nullptr;
+
+    if (PropertyChildReap(pid)) {
+        name = "Async property child";
+    } else if (SubcontextChildReap(pid)) {
+        name = "Subcontext";
     } else {
-        name = StringPrintf("Untracked pid %d", pid);
+        service = ServiceList::GetInstance().FindService(pid, &Service::pid);
+
+        if (service) {
+            name = StringPrintf("Service '%s' (pid %d)", service->name().c_str(), pid);
+            if (service->flags() & SVC_EXEC) {
+                auto exec_duration = boot_clock::now() - service->time_started();
+                auto exec_duration_ms =
+                    std::chrono::duration_cast<std::chrono::milliseconds>(exec_duration).count();
+                wait_string = StringPrintf(" waiting took %f seconds", exec_duration_ms / 1000.0f);
+            }
+        } else {
+            name = StringPrintf("Untracked pid %d", pid);
+        }
     }
 
     auto status = siginfo.si_status;
diff --git a/init/subcontext.cpp b/init/subcontext.cpp
new file mode 100644
index 0000000..1306c7d
--- /dev/null
+++ b/init/subcontext.cpp
@@ -0,0 +1,282 @@
+/*
+ * 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 "subcontext.h"
+
+#include <fcntl.h>
+#include <poll.h>
+#include <sys/socket.h>
+#include <unistd.h>
+
+#include <android-base/file.h>
+#include <android-base/logging.h>
+#include <android-base/strings.h>
+#include <selinux/android.h>
+
+#include "action.h"
+#include "system/core/init/subcontext.pb.h"
+#include "util.h"
+
+using android::base::GetExecutablePath;
+using android::base::Join;
+using android::base::Socketpair;
+using android::base::Split;
+using android::base::StartsWith;
+using android::base::unique_fd;
+
+namespace android {
+namespace init {
+
+const std::string kInitContext = "u:object_r:init:s0";
+const std::string kVendorContext = "u:object_r:vendor_init:s0";
+
+namespace {
+
+constexpr size_t kBufferSize = 4096;
+
+Result<std::string> ReadMessage(int socket) {
+    char buffer[kBufferSize] = {};
+    auto result = TEMP_FAILURE_RETRY(recv(socket, buffer, sizeof(buffer), 0));
+    if (result <= 0) {
+        return ErrnoError();
+    }
+    return std::string(buffer, result);
+}
+
+template <typename T>
+Result<Success> SendMessage(int socket, const T& message) {
+    std::string message_string;
+    if (!message.SerializeToString(&message_string)) {
+        return Error() << "Unable to serialize message";
+    }
+
+    if (message_string.size() > kBufferSize) {
+        return Error() << "Serialized message too long to send";
+    }
+
+    if (auto result =
+            TEMP_FAILURE_RETRY(send(socket, message_string.c_str(), message_string.size(), 0));
+        result != static_cast<long>(message_string.size())) {
+        return ErrnoError() << "send() failed to send message contents";
+    }
+    return Success();
+}
+
+class SubcontextProcess {
+  public:
+    SubcontextProcess(const KeywordFunctionMap* function_map, std::string context, int init_fd)
+        : function_map_(function_map), context_(std::move(context)), init_fd_(init_fd){};
+    void MainLoop();
+
+  private:
+    void RunCommand(const SubcontextCommand::ExecuteCommand& execute_command,
+                    SubcontextReply::ResultMessage* result_message) const;
+
+    const KeywordFunctionMap* function_map_;
+    const std::string context_;
+    const int init_fd_;
+};
+
+void SubcontextProcess::RunCommand(const SubcontextCommand::ExecuteCommand& execute_command,
+                                   SubcontextReply::ResultMessage* result_message) const {
+    // Need to use ArraySplice instead of this code.
+    auto args = std::vector<std::string>();
+    for (const auto& string : execute_command.args()) {
+        args.emplace_back(string);
+    }
+
+    auto map_result = function_map_->FindFunction(args);
+    Result<Success> result;
+    if (!map_result) {
+        result = Error() << "Cannot find command: " << map_result.error();
+    } else {
+        result = RunBuiltinFunction(map_result->second, args, context_);
+    }
+
+    if (result) {
+        result_message->set_success(true);
+    } else {
+        result_message->set_success(false);
+        result_message->set_error_string(result.error_string());
+        result_message->set_error_errno(result.error_errno());
+    }
+}
+
+void SubcontextProcess::MainLoop() {
+    pollfd ufd[1];
+    ufd[0].events = POLLIN;
+    ufd[0].fd = init_fd_;
+
+    while (true) {
+        ufd[0].revents = 0;
+        int nr = TEMP_FAILURE_RETRY(poll(ufd, arraysize(ufd), -1));
+        if (nr == 0) continue;
+        if (nr < 0) {
+            PLOG(FATAL) << "poll() of subcontext socket failed, continuing";
+        }
+
+        auto init_message = ReadMessage(init_fd_);
+        if (!init_message) {
+            LOG(FATAL) << "Could not read message from init: " << init_message.error();
+        }
+
+        auto subcontext_command = SubcontextCommand();
+        if (!subcontext_command.ParseFromString(*init_message)) {
+            LOG(FATAL) << "Unable to parse message from init";
+        }
+
+        auto reply = SubcontextReply();
+        switch (subcontext_command.command_case()) {
+            case SubcontextCommand::kExecuteCommand: {
+                RunCommand(subcontext_command.execute_command(), reply.mutable_result());
+                break;
+            }
+            default:
+                LOG(FATAL) << "Unknown message type from init: "
+                           << subcontext_command.command_case();
+        }
+
+        if (auto result = SendMessage(init_fd_, reply); !result) {
+            LOG(FATAL) << "Failed to send message to init: " << result.error();
+        }
+    }
+}
+
+}  // namespace
+
+int SubcontextMain(int argc, char** argv, const KeywordFunctionMap* function_map) {
+    if (argc < 4) LOG(FATAL) << "Fewer than 4 args specified to subcontext (" << argc << ")";
+
+    auto context = std::string(argv[2]);
+    auto init_fd = std::atoi(argv[3]);
+
+    auto subcontext_process = SubcontextProcess(function_map, context, init_fd);
+    subcontext_process.MainLoop();
+    return 0;
+}
+
+void Subcontext::Fork() {
+    unique_fd subcontext_socket;
+    if (!Socketpair(AF_UNIX, SOCK_SEQPACKET | SOCK_CLOEXEC, 0, &socket_, &subcontext_socket)) {
+        LOG(FATAL) << "Could not create socket pair to communicate to subcontext";
+        return;
+    }
+
+    auto result = fork();
+
+    if (result == -1) {
+        LOG(FATAL) << "Could not fork subcontext";
+    } else if (result == 0) {
+        socket_.reset();
+
+        // We explicitly do not use O_CLOEXEC here, such that we can reference this FD by number
+        // in the subcontext process after we exec.
+        int child_fd = dup(subcontext_socket);
+        if (child_fd < 0) {
+            PLOG(FATAL) << "Could not dup child_fd";
+        }
+
+        if (setexeccon(context_.c_str()) < 0) {
+            PLOG(FATAL) << "Could not set execcon for '" << context_ << "'";
+        }
+
+        auto init_path = GetExecutablePath();
+        auto child_fd_string = std::to_string(child_fd);
+        const char* args[] = {init_path.c_str(), "subcontext", context_.c_str(),
+                              child_fd_string.c_str(), nullptr};
+        execv(init_path.data(), const_cast<char**>(args));
+
+        PLOG(FATAL) << "Could not execv subcontext init";
+    } else {
+        subcontext_socket.reset();
+        pid_ = result;
+        LOG(INFO) << "Forked subcontext for '" << context_ << "' with pid " << pid_;
+    }
+}
+
+void Subcontext::Restart() {
+    LOG(ERROR) << "Restarting subcontext '" << context_ << "'";
+    if (pid_) {
+        kill(pid_, SIGKILL);
+    }
+    pid_ = 0;
+    socket_.reset();
+    Fork();
+}
+
+Result<Success> Subcontext::Execute(const std::vector<std::string>& args) {
+    auto subcontext_command = SubcontextCommand();
+    std::copy(
+        args.begin(), args.end(),
+        RepeatedPtrFieldBackInserter(subcontext_command.mutable_execute_command()->mutable_args()));
+
+    if (auto result = SendMessage(socket_, subcontext_command); !result) {
+        Restart();
+        return ErrnoError() << "Failed to send message to subcontext";
+    }
+
+    auto subcontext_message = ReadMessage(socket_);
+    if (!subcontext_message) {
+        Restart();
+        return Error() << "Failed to receive result from subcontext: " << subcontext_message.error();
+    }
+
+    auto subcontext_reply = SubcontextReply();
+    if (!subcontext_reply.ParseFromString(*subcontext_message)) {
+        Restart();
+        return Error() << "Unable to parse message from subcontext";
+    }
+
+    switch (subcontext_reply.reply_case()) {
+        case SubcontextReply::kResult: {
+            auto result = subcontext_reply.result();
+            if (result.success()) {
+                return Success();
+            } else {
+                return ResultError(result.error_string(), result.error_errno());
+            }
+        }
+        default:
+            return Error() << "Unknown message type from subcontext: "
+                           << subcontext_reply.reply_case();
+    }
+}
+
+static std::vector<Subcontext> subcontexts;
+
+std::vector<Subcontext>* InitializeSubcontexts() {
+    static const char* const paths_and_secontexts[][2] = {
+        //  TODO: Enable this once the SEPolicy is in place.
+        //  {"/vendor", kVendorContext.c_str()},
+    };
+    for (const auto& [path_prefix, secontext] : paths_and_secontexts) {
+        subcontexts.emplace_back(path_prefix, secontext);
+    }
+    return &subcontexts;
+}
+
+bool SubcontextChildReap(pid_t pid) {
+    for (auto& subcontext : subcontexts) {
+        if (subcontext.pid() == pid) {
+            subcontext.Restart();
+            return true;
+        }
+    }
+    return false;
+}
+
+}  // namespace init
+}  // namespace android
diff --git a/init/subcontext.h b/init/subcontext.h
new file mode 100644
index 0000000..ac77e08
--- /dev/null
+++ b/init/subcontext.h
@@ -0,0 +1,80 @@
+/*
+ * 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_SUBCONTEXT_H
+#define _INIT_SUBCONTEXT_H
+
+#include <signal.h>
+
+#include <string>
+#include <vector>
+
+#include <android-base/unique_fd.h>
+
+#include "builtins.h"
+
+namespace android {
+namespace init {
+
+extern const std::string kInitContext;
+extern const std::string kVendorContext;
+
+class Subcontext {
+  public:
+    Subcontext(std::string path_prefix, std::string context)
+        : path_prefix_(path_prefix), context_(std::move(context)) {
+        Fork();
+    }
+
+    Result<Success> Execute(const std::vector<std::string>& command);
+    void Restart();
+
+    const std::string& path_prefix() const { return path_prefix_; }
+    const std::string& context() const { return context_; }
+    pid_t pid() const { return pid_; }
+
+  private:
+    void Fork();
+
+    std::string path_prefix_;
+    std::string context_;
+    pid_t pid_;
+    android::base::unique_fd socket_;
+};
+
+// For testing, to kill the subcontext after the test has completed.
+class SubcontextKiller {
+  public:
+    SubcontextKiller(const Subcontext& subcontext) : subcontext_(subcontext) {}
+    ~SubcontextKiller() {
+        if (subcontext_.pid() > 0) {
+            kill(subcontext_.pid(), SIGTERM);
+            kill(subcontext_.pid(), SIGKILL);
+        }
+    }
+
+  private:
+    const Subcontext& subcontext_;
+};
+
+int SubcontextMain(int argc, char** argv, const KeywordFunctionMap* function_map);
+std::vector<Subcontext>* InitializeSubcontexts();
+bool SubcontextChildReap(pid_t pid);
+
+}  // namespace init
+}  // namespace android
+
+#endif
diff --git a/init/subcontext.proto b/init/subcontext.proto
new file mode 100644
index 0000000..0d89734
--- /dev/null
+++ b/init/subcontext.proto
@@ -0,0 +1,33 @@
+/*
+ * 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.
+ */
+
+syntax = "proto2";
+option optimize_for = LITE_RUNTIME;
+
+message SubcontextCommand {
+    message ExecuteCommand { repeated string args = 1; }
+    oneof command { ExecuteCommand execute_command = 1; }
+}
+
+message SubcontextReply {
+    message ResultMessage {
+        optional bool success = 1;
+        optional string error_string = 2;
+        optional int32 error_errno = 3;
+    }
+
+    oneof reply { ResultMessage result = 1; }
+}
\ No newline at end of file
diff --git a/init/subcontext_benchmark.cpp b/init/subcontext_benchmark.cpp
new file mode 100644
index 0000000..a62b959
--- /dev/null
+++ b/init/subcontext_benchmark.cpp
@@ -0,0 +1,57 @@
+/*
+ * 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 "subcontext.h"
+
+#include <benchmark/benchmark.h>
+
+#include "test_function_map.h"
+
+namespace android {
+namespace init {
+
+static void BenchmarkSuccess(benchmark::State& state) {
+    auto subcontext = Subcontext("path", kVendorContext);
+    auto subcontext_killer = SubcontextKiller(subcontext);
+
+    while (state.KeepRunning()) {
+        subcontext.Execute(std::vector<std::string>{"return_success"});
+    }
+}
+
+BENCHMARK(BenchmarkSuccess);
+
+TestFunctionMap BuildTestFunctionMap() {
+    TestFunctionMap test_function_map;
+    test_function_map.Add("return_success", 0, 0, true,
+                          [](const BuiltinArguments& args) { return Success(); });
+
+    return test_function_map;
+}
+
+}  // namespace init
+}  // namespace android
+
+int main(int argc, char** argv) {
+    if (argc > 1 && !strcmp(basename(argv[1]), "subcontext")) {
+        auto test_function_map = android::init::BuildTestFunctionMap();
+        return android::init::SubcontextMain(argc, argv, &test_function_map);
+    }
+
+    ::benchmark::Initialize(&argc, argv);
+    if (::benchmark::ReportUnrecognizedArguments(argc, argv)) return 1;
+    ::benchmark::RunSpecifiedBenchmarks();
+}
diff --git a/init/subcontext_test.cpp b/init/subcontext_test.cpp
new file mode 100644
index 0000000..60b45b9
--- /dev/null
+++ b/init/subcontext_test.cpp
@@ -0,0 +1,179 @@
+/*
+ * 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 "subcontext.h"
+
+#include <unistd.h>
+
+#include <chrono>
+
+#include <android-base/properties.h>
+#include <android-base/strings.h>
+#include <gtest/gtest.h>
+
+#include "builtin_arguments.h"
+#include "test_function_map.h"
+
+using namespace std::literals;
+
+using android::base::GetProperty;
+using android::base::Join;
+using android::base::SetProperty;
+using android::base::Split;
+using android::base::WaitForProperty;
+
+namespace android {
+namespace init {
+
+TEST(subcontext, CheckDifferentPid) {
+    auto subcontext = Subcontext("path", kVendorContext);
+    auto subcontext_killer = SubcontextKiller(subcontext);
+
+    auto result = subcontext.Execute(std::vector<std::string>{"return_pids_as_error"});
+    ASSERT_FALSE(result);
+
+    auto pids = Split(result.error_string(), " ");
+    ASSERT_EQ(2U, pids.size());
+    auto our_pid = std::to_string(getpid());
+    EXPECT_NE(our_pid, pids[0]);
+    EXPECT_EQ(our_pid, pids[1]);
+}
+
+TEST(subcontext, SetProp) {
+    auto subcontext = Subcontext("path", kVendorContext);
+    auto subcontext_killer = SubcontextKiller(subcontext);
+
+    SetProperty("init.test.subcontext", "fail");
+    WaitForProperty("init.test.subcontext", "fail");
+
+    auto args = std::vector<std::string>{
+        "setprop",
+        "init.test.subcontext",
+        "success",
+    };
+    auto result = subcontext.Execute(args);
+    ASSERT_TRUE(result) << result.error();
+
+    EXPECT_TRUE(WaitForProperty("init.test.subcontext", "success", 10s));
+}
+
+TEST(subcontext, MultipleCommands) {
+    auto subcontext = Subcontext("path", kVendorContext);
+    auto subcontext_killer = SubcontextKiller(subcontext);
+
+    auto first_pid = subcontext.pid();
+
+    auto expected_words = std::vector<std::string>{
+        "this",
+        "is",
+        "a",
+        "test",
+    };
+
+    for (const auto& word : expected_words) {
+        auto args = std::vector<std::string>{
+            "add_word",
+            word,
+        };
+        auto result = subcontext.Execute(args);
+        ASSERT_TRUE(result) << result.error();
+    }
+
+    auto result = subcontext.Execute(std::vector<std::string>{"return_words_as_error"});
+    ASSERT_FALSE(result);
+    EXPECT_EQ(Join(expected_words, " "), result.error_string());
+    EXPECT_EQ(first_pid, subcontext.pid());
+}
+
+TEST(subcontext, RecoverAfterAbort) {
+    auto subcontext = Subcontext("path", kVendorContext);
+    auto subcontext_killer = SubcontextKiller(subcontext);
+
+    auto first_pid = subcontext.pid();
+
+    auto result = subcontext.Execute(std::vector<std::string>{"cause_log_fatal"});
+    ASSERT_FALSE(result);
+
+    auto result2 = subcontext.Execute(std::vector<std::string>{"generate_sane_error"});
+    ASSERT_FALSE(result2);
+    EXPECT_EQ("Sane error!", result2.error_string());
+    EXPECT_NE(subcontext.pid(), first_pid);
+}
+
+TEST(subcontext, ContextString) {
+    auto subcontext = Subcontext("path", kVendorContext);
+    auto subcontext_killer = SubcontextKiller(subcontext);
+
+    auto result = subcontext.Execute(std::vector<std::string>{"return_context_as_error"});
+    ASSERT_FALSE(result);
+    ASSERT_EQ(kVendorContext, result.error_string());
+}
+
+TestFunctionMap BuildTestFunctionMap() {
+    TestFunctionMap test_function_map;
+    // For CheckDifferentPid
+    test_function_map.Add("return_pids_as_error", 0, 0, true,
+                          [](const BuiltinArguments& args) -> Result<Success> {
+                              return Error() << getpid() << " " << getppid();
+                          });
+
+    // For SetProp
+    test_function_map.Add("setprop", 2, 2, true, [](const BuiltinArguments& args) {
+        android::base::SetProperty(args[1], args[2]);
+        return Success();
+    });
+
+    // For MultipleCommands
+    // Using a shared_ptr to extend lifetime of words to both lambdas
+    auto words = std::make_shared<std::vector<std::string>>();
+    test_function_map.Add("add_word", 1, 1, true, [words](const BuiltinArguments& args) {
+        words->emplace_back(args[1]);
+        return Success();
+    });
+    test_function_map.Add("return_words_as_error", 0, 0, true,
+                          [words](const BuiltinArguments& args) -> Result<Success> {
+                              return Error() << Join(*words, " ");
+                          });
+
+    // For RecoverAfterAbort
+    test_function_map.Add("cause_log_fatal", 0, 0, true,
+                          [](const BuiltinArguments& args) -> Result<Success> {
+                              return Error() << std::string(4097, 'f');
+                          });
+    test_function_map.Add(
+        "generate_sane_error", 0, 0, true,
+        [](const BuiltinArguments& args) -> Result<Success> { return Error() << "Sane error!"; });
+
+    // For ContextString
+    test_function_map.Add(
+        "return_context_as_error", 0, 0, true,
+        [](const BuiltinArguments& args) -> Result<Success> { return Error() << args.context; });
+
+    return test_function_map;
+}
+
+}  // namespace init
+}  // namespace android
+
+int main(int argc, char** argv) {
+    if (argc > 1 && !strcmp(basename(argv[1]), "subcontext")) {
+        auto test_function_map = android::init::BuildTestFunctionMap();
+        return android::init::SubcontextMain(argc, argv, &test_function_map);
+    }
+
+    testing::InitGoogleTest(&argc, argv);
+    return RUN_ALL_TESTS();
+}
diff --git a/init/test_function_map.h b/init/test_function_map.h
new file mode 100644
index 0000000..583df1a
--- /dev/null
+++ b/init/test_function_map.h
@@ -0,0 +1,55 @@
+/*
+ * 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_TEST_FUNCTION_MAP_H
+#define _INIT_TEST_FUNCTION_MAP_H
+
+#include <string>
+#include <vector>
+
+#include "builtin_arguments.h"
+#include "keyword_map.h"
+
+namespace android {
+namespace init {
+
+class TestFunctionMap : public KeywordFunctionMap {
+  public:
+    // Helper for argument-less functions
+    using BuiltinFunctionNoArgs = std::function<void(void)>;
+    void Add(const std::string& name, const BuiltinFunctionNoArgs function) {
+        Add(name, 0, 0, false, [function](const BuiltinArguments&) {
+            function();
+            return Success();
+        });
+    }
+
+    void Add(const std::string& name, std::size_t min_parameters, std::size_t max_parameters,
+             bool run_in_subcontext, const BuiltinFunction function) {
+        builtin_functions_[name] =
+            make_tuple(min_parameters, max_parameters, make_pair(run_in_subcontext, function));
+    }
+
+  private:
+    Map builtin_functions_ = {};
+
+    const Map& map() const override { return builtin_functions_; }
+};
+
+}  // namespace init
+}  // namespace android
+
+#endif
diff --git a/libbacktrace/Android.bp b/libbacktrace/Android.bp
index e889bdd..69d7b6d 100644
--- a/libbacktrace/Android.bp
+++ b/libbacktrace/Android.bp
@@ -94,7 +94,6 @@
             ],
 
             static_libs: ["libcutils"],
-            host_ldlibs: ["-lrt"],
         },
         linux_bionic: {
             enabled: true,
@@ -229,15 +228,11 @@
         android: {
             cflags: ["-DENABLE_PSS_TESTS"],
             shared_libs: [
-                "libdl",
                 "libutils",
             ],
         },
         linux: {
             host_ldlibs: [
-                "-lpthread",
-                "-lrt",
-                "-ldl",
                 "-lncurses",
             ],
             static_libs: ["libutils"],
diff --git a/liblog/Android.bp b/liblog/Android.bp
index b98d18f..d5bb29e 100644
--- a/liblog/Android.bp
+++ b/liblog/Android.bp
@@ -91,9 +91,6 @@
         not_windows: {
             srcs: ["event_tag_map.cpp"],
         },
-        linux: {
-            host_ldlibs: ["-lrt"],
-        },
         linux_bionic: {
             enabled: true,
         },
diff --git a/libnativebridge/Android.bp b/libnativebridge/Android.bp
index b3c42f0..089f3b8 100644
--- a/libnativebridge/Android.bp
+++ b/libnativebridge/Android.bp
@@ -22,13 +22,6 @@
     cppflags: [
         "-fvisibility=protected",
     ],
-
-    host_ldlibs: ["-ldl"],
-    target: {
-        android: {
-            shared_libs: ["libdl"],
-        },
-    },
 }
 
 subdirs = ["tests"]
diff --git a/libnativebridge/tests/Android.bp b/libnativebridge/tests/Android.bp
index e31dae0..9e2e641 100644
--- a/libnativebridge/tests/Android.bp
+++ b/libnativebridge/tests/Android.bp
@@ -25,14 +25,6 @@
     ],
     header_libs: ["libnativebridge-dummy-headers"],
     cppflags: ["-fvisibility=protected"],
-    target: {
-        android: {
-            shared_libs: ["libdl"],
-        },
-        host: {
-            host_ldlibs: ["-ldl"],
-        },
-    },
 }
 
 cc_library_shared {
diff --git a/libnativeloader/Android.bp b/libnativeloader/Android.bp
index 13f9744..4b21edc 100644
--- a/libnativeloader/Android.bp
+++ b/libnativeloader/Android.bp
@@ -11,14 +11,6 @@
         "libnativebridge",
         "libbase",
     ],
-    target: {
-        android: {
-            shared_libs: ["libdl"],
-        },
-        host: {
-            host_ldlibs: ["-ldl"],
-        },
-    },
     cflags: [
         "-Werror",
         "-Wall",
@@ -27,5 +19,4 @@
         "-fvisibility=hidden",
     ],
     export_include_dirs: ["include"],
-    local_include_dirs: ["include"],
 }
diff --git a/libsparse/Android.bp b/libsparse/Android.bp
index 6ec0991..b894656 100644
--- a/libsparse/Android.bp
+++ b/libsparse/Android.bp
@@ -15,19 +15,11 @@
     cflags: ["-Werror"],
     local_include_dirs: ["include"],
     export_include_dirs: ["include"],
+    shared_libs: [
+        "libz",
+        "libbase",
+    ],
     target: {
-        host: {
-            shared_libs: [
-                "libz-host",
-                "libbase",
-            ],
-        },
-        android: {
-            shared_libs: [
-                "libz",
-                "libbase",
-            ],
-        },
         windows: {
             enabled: true,
         },
diff --git a/libunwindstack/Android.bp b/libunwindstack/Android.bp
index ca05516..cf2ac4e 100644
--- a/libunwindstack/Android.bp
+++ b/libunwindstack/Android.bp
@@ -143,14 +143,6 @@
         "libgmock",
     ],
 
-    target: {
-        linux: {
-            host_ldlibs: [
-                "-lrt",
-            ],
-        },
-    },
-
     data: [
         "tests/files/elf32.xz",
         "tests/files/elf64.xz",
@@ -178,14 +170,6 @@
     srcs: [
         "tools/unwind.cpp",
     ],
-
-    target: {
-        linux: {
-            host_ldlibs: [
-                "-lrt",
-            ],
-        },
-    },
 }
 
 cc_binary {
diff --git a/libutils/RefBase.cpp b/libutils/RefBase.cpp
index 24737b9..f5f881f 100644
--- a/libutils/RefBase.cpp
+++ b/libutils/RefBase.cpp
@@ -442,6 +442,11 @@
     // and all accesses to refs happen before its deletion in the final decWeak.
     // The destructor can safely access mRefs because either it's deleting
     // mRefs itself, or it's running entirely before the final mWeak decrement.
+    //
+    // Since we're doing atomic loads of `flags`, the static analyzer assumes
+    // they can change between `delete this;` and `refs->decWeak(id);`. This is
+    // not the case. The analyzer may become more okay with this patten when
+    // https://bugs.llvm.org/show_bug.cgi?id=34365 gets resolved. NOLINTNEXTLINE
     refs->decWeak(id);
 }
 
diff --git a/libutils/tests/Android.bp b/libutils/tests/Android.bp
index 0869175..3fadef4 100644
--- a/libutils/tests/Android.bp
+++ b/libutils/tests/Android.bp
@@ -44,7 +44,6 @@
                 "libcutils",
                 "libutils",
                 "libbase",
-                "libdl",
             ],
         },
         linux: {
@@ -59,7 +58,6 @@
                 "liblog",
                 "libbase",
             ],
-            host_ldlibs: ["-ldl"],
         },
     },
 
diff --git a/libziparchive/Android.bp b/libziparchive/Android.bp
index f395c74..e3faee3 100644
--- a/libziparchive/Android.bp
+++ b/libziparchive/Android.bp
@@ -69,11 +69,11 @@
     shared_libs: [
         "liblog",
         "libbase",
+        "libz",
     ],
     target: {
         android: {
             shared_libs: [
-                "libz",
                 "libutils",
             ],
         },
@@ -81,18 +81,8 @@
             static_libs: ["libutils"],
         },
         linux_bionic: {
-            static_libs: ["libz"],
             enabled: true,
         },
-        linux: {
-            shared_libs: ["libz-host"],
-        },
-        darwin: {
-            shared_libs: ["libz-host"],
-        },
-        windows: {
-            shared_libs: ["libz-host"],
-        },
     },
 }
 
@@ -105,7 +95,7 @@
         "libziparchive_defaults",
         "libziparchive_flags",
     ],
-    shared_libs: ["libz-host"],
+    shared_libs: ["libz"],
     static_libs: ["libutils"],
 }
 
diff --git a/logd/tests/logd_test.cpp b/logd/tests/logd_test.cpp
index 8ee5ea1..9e1541b 100644
--- a/logd/tests/logd_test.cpp
+++ b/logd/tests/logd_test.cpp
@@ -1099,7 +1099,7 @@
     // and dac_read_search on every try to get past the message
     // de-duper.  We will also rotate the file name in the directory
     // as another measure.
-    static const char file[] = "/data/backup/cannot_access_directory_%u";
+    static const char file[] = "/data/drm/cannot_access_directory_%u";
     static const unsigned avc_requests_per_access = 2;
 
     rate /= avc_requests_per_access;
diff --git a/reboot/reboot.c b/reboot/reboot.c
index f0cf40c..fe763a8 100644
--- a/reboot/reboot.c
+++ b/reboot/reboot.c
@@ -21,13 +21,13 @@
 #include <cutils/android_reboot.h>
 #include <unistd.h>
 
-int main(int argc, char *argv[])
-{
+int main(int argc, char* argv[]) {
     int ret;
     size_t prop_len;
     char property_val[PROPERTY_VALUE_MAX];
-    const char *cmd = "reboot";
-    char *optarg = "";
+    static const char reboot[] = "reboot";
+    const char* cmd = reboot;
+    char* optarg = "";
 
     opterr = 0;
     do {
@@ -60,19 +60,23 @@
 
     prop_len = snprintf(property_val, sizeof(property_val), "%s,%s", cmd, optarg);
     if (prop_len >= sizeof(property_val)) {
-        fprintf(stderr, "reboot command too long: %s\n", optarg);
+        fprintf(stderr, "%s command too long: %s\n", cmd, optarg);
         exit(EXIT_FAILURE);
     }
 
     ret = property_set(ANDROID_RB_PROPERTY, property_val);
-    if(ret < 0) {
-        perror("reboot");
+    if (ret < 0) {
+        perror(cmd);
         exit(EXIT_FAILURE);
     }
 
     // Don't return early. Give the reboot command time to take effect
     // to avoid messing up scripts which do "adb shell reboot && adb wait-for-device"
-    while(1) { pause(); }
+    if (cmd == reboot) {
+        while (1) {
+            pause();
+        }
+    }
 
     fprintf(stderr, "Done\n");
     return 0;
diff --git a/rootdir/etc/ld.config.txt b/rootdir/etc/ld.config.txt
index 7f86a95..8aa3369 100644
--- a/rootdir/etc/ld.config.txt
+++ b/rootdir/etc/ld.config.txt
@@ -7,10 +7,14 @@
 dir.system = /system/bin/
 dir.system = /system/xbin/
 dir.vendor = /vendor/bin/
-dir.test = /data/nativetest/
-dir.test = /data/nativetest64/
-dir.test = /data/benchmarktest/
-dir.test = /data/benchmarktest64/
+dir.vendor = /data/nativetest/vendor
+dir.vendor = /data/nativetest64/vendor
+dir.vendor = /data/benchmarktest/vendor
+dir.vendor = /data/benchmarktest64/vendor
+dir.system = /data/nativetest
+dir.system = /data/nativetest64
+dir.system = /data/benchmarktest
+dir.system = /data/benchmarktest64
 
 [system]
 additional.namespaces = sphal,vndk,rs
@@ -98,6 +102,7 @@
 # This namespace is exclusively for vndk-sp libs.
 ###############################################################################
 namespace.vndk.isolated = true
+namespace.vndk.visible = true
 namespace.vndk.search.paths = /vendor/${LIB}/vndk-sp:/system/${LIB}/vndk-sp
 namespace.vndk.permitted.paths = /vendor/${LIB}/hw:/vendor/${LIB}/egl
 
@@ -121,12 +126,3 @@
 namespace.default.search.paths = /vendor/${LIB}/hw:/vendor/${LIB}/egl:/vendor/${LIB}:/system/${LIB}/vndk:/vendor/${LIB}/vndk-sp:/system/${LIB}/vndk-sp:/system/${LIB}
 
 namespace.default.asan.search.paths = /data/asan/vendor/${LIB}/hw:/vendor/${LIB}/hw:/data/asan/vendor/${LIB}/egl:/vendor/${LIB}/egl:/data/asan/vendor/${LIB}:/vendor/${LIB}:/data/asan/system/${LIB}/vndk:/system/${LIB}/vndk:/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}
-
-###############################################################################
-# Namespace config for tests. No VNDK restriction is enforced for these tests.
-###############################################################################
-[test]
-namespace.default.isolated = false
-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/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/etc/ld.config.txt.in b/rootdir/etc/ld.config.txt.in
index af37287..2c73056 100644
--- a/rootdir/etc/ld.config.txt.in
+++ b/rootdir/etc/ld.config.txt.in
@@ -132,9 +132,7 @@
 namespace.default.asan.permitted.paths = /data/asan/vendor:/vendor:/data/asan/system/${LIB}/vndk:/system/${LIB}/vndk:/data/asan/system/${LIB}/vndk-sp:/system/${LIB}/vndk-sp
 
 namespace.default.links = system
-namespace.default.link.system.shared_libs = %LLNDK_LIBRARIES%:libmedia.so:libandroid_runtime.so
-# libmedia.so must be removed after we have fix for lib-dplmedia.so (b/64427765)
-# libandroid_runtime.so must be removed after we have a fix for qseeproxydaemon (b/64820887)
+namespace.default.link.system.shared_libs = %LLNDK_LIBRARIES%
 
 ###############################################################################
 # "system" namespace
diff --git a/run-as/run-as.cpp b/run-as/run-as.cpp
index e7b8cc2..b27cfad 100644
--- a/run-as/run-as.cpp
+++ b/run-as/run-as.cpp
@@ -194,6 +194,7 @@
   ScopedMinijail j(minijail_new());
   minijail_change_uid(j.get(), uid);
   minijail_change_gid(j.get(), gid);
+  minijail_keep_supplementary_gids(j.get());
   minijail_enter(j.get());
 
   if (selinux_android_setcontext(uid, 0, info.seinfo, pkgname) < 0) {
diff --git a/trusty/keymaster/trusty_keymaster_device_test.cpp b/trusty/keymaster/trusty_keymaster_device_test.cpp
index e8f5c0b..9227964 100644
--- a/trusty/keymaster/trusty_keymaster_device_test.cpp
+++ b/trusty/keymaster/trusty_keymaster_device_test.cpp
@@ -15,9 +15,9 @@
  */
 #include <algorithm>
 #include <fstream>
+#include <memory>
 
 #include <gtest/gtest.h>
-#include <nativehelper/UniquePtr.h>
 #include <openssl/engine.h>
 
 #include <hardware/keymaster0.h>
@@ -181,7 +181,7 @@
 
     keymaster_rsa_sign_params_t sig_params = {DIGEST_NONE, PADDING_NONE};
     size_t message_len = params.modulus_size / 8;
-    UniquePtr<uint8_t[]> message(build_message(message_len));
+    std::unique_ptr<uint8_t[]> message(build_message(message_len));
     uint8_t* signature;
     size_t siglen;
     EXPECT_EQ(KM_ERROR_OK, device.sign_data(&sig_params, ptr, size, message.get(), message_len,
@@ -200,7 +200,7 @@
 
     keymaster_rsa_sign_params_t sig_params = {DIGEST_NONE, PADDING_NONE};
     size_t message_len = params.modulus_size / 8 - 1;
-    UniquePtr<uint8_t[]> message(build_message(message_len));
+    std::unique_ptr<uint8_t[]> message(build_message(message_len));
     uint8_t* signature;
     size_t siglen;
     EXPECT_EQ(KM_ERROR_UNKNOWN_ERROR, device.sign_data(&sig_params, ptr, size, message.get(),
@@ -217,7 +217,7 @@
 
     keymaster_rsa_sign_params_t sig_params = {DIGEST_NONE, PADDING_NONE};
     size_t message_len = params.modulus_size / 8 + 1;
-    UniquePtr<uint8_t[]> message(build_message(message_len));
+    std::unique_ptr<uint8_t[]> message(build_message(message_len));
     uint8_t* signature;
     size_t siglen;
     EXPECT_EQ(KM_ERROR_UNKNOWN_ERROR, device.sign_data(&sig_params, ptr, size, message.get(),
@@ -272,7 +272,7 @@
 
     keymaster_ec_sign_params_t sig_params = {DIGEST_NONE};
     size_t message_len = 1024 * 7;
-    UniquePtr<uint8_t[]> message(new uint8_t[message_len]);
+    std::unique_ptr<uint8_t[]> message(new uint8_t[message_len]);
     // contents of message don't matter.
     uint8_t* signature;
     size_t siglen;
@@ -294,7 +294,7 @@
 
     keymaster_rsa_sign_params_t sig_params = {DIGEST_NONE, PADDING_NONE};
     size_t message_len = params.modulus_size / 8;
-    UniquePtr<uint8_t[]> message(build_message(message_len));
+    std::unique_ptr<uint8_t[]> message(build_message(message_len));
     uint8_t* signature;
     size_t siglen;
     EXPECT_EQ(KM_ERROR_OK, device.sign_data(&sig_params, ptr, size, message.get(), message_len,
@@ -315,7 +315,7 @@
 
     keymaster_rsa_sign_params_t sig_params = {DIGEST_NONE, PADDING_NONE};
     size_t message_len = params.modulus_size / 8;
-    UniquePtr<uint8_t[]> message(build_message(message_len));
+    std::unique_ptr<uint8_t[]> message(build_message(message_len));
     uint8_t* signature;
     size_t siglen;
     EXPECT_EQ(KM_ERROR_OK, device.sign_data(&sig_params, ptr, size, message.get(), message_len,
@@ -338,7 +338,7 @@
 
     keymaster_rsa_sign_params_t sig_params = {DIGEST_NONE, PADDING_NONE};
     size_t message_len = params.modulus_size / 8;
-    UniquePtr<uint8_t[]> message(build_message(message_len));
+    std::unique_ptr<uint8_t[]> message(build_message(message_len));
     uint8_t* signature;
     size_t siglen;
     EXPECT_EQ(KM_ERROR_OK, device.sign_data(&sig_params, ptr, size, message.get(), message_len,
@@ -360,7 +360,7 @@
 
     keymaster_rsa_sign_params_t sig_params = {DIGEST_NONE, PADDING_NONE};
     size_t message_len = params.modulus_size / 8;
-    UniquePtr<uint8_t[]> message(build_message(message_len));
+    std::unique_ptr<uint8_t[]> message(build_message(message_len));
     uint8_t* signature;
     size_t siglen;
     EXPECT_EQ(KM_ERROR_OK, device.sign_data(&sig_params, ptr, size, message.get(), message_len,
@@ -382,7 +382,7 @@
 
     keymaster_rsa_sign_params_t sig_params = {DIGEST_NONE, PADDING_NONE};
     size_t message_len = params.modulus_size / 8;
-    UniquePtr<uint8_t[]> message(build_message(message_len + 1));
+    std::unique_ptr<uint8_t[]> message(build_message(message_len + 1));
     uint8_t* signature;
     size_t siglen;
     EXPECT_EQ(KM_ERROR_OK, device.sign_data(&sig_params, ptr, size, message.get(), message_len,
@@ -422,7 +422,7 @@
 
     keymaster_ec_sign_params_t sig_params = {DIGEST_NONE};
     size_t message_len = 1024 * 7;
-    UniquePtr<uint8_t[]> message(new uint8_t[message_len]);
+    std::unique_ptr<uint8_t[]> message(new uint8_t[message_len]);
     // contents of message don't matter.
     uint8_t* signature;
     size_t siglen;
@@ -453,7 +453,7 @@
 
     keymaster_rsa_sign_params_t sig_params = {DIGEST_NONE, PADDING_NONE};
     size_t message_size = 1024 /* key size */ / 8;
-    UniquePtr<uint8_t[]> message(new uint8_t[message_size]);
+    std::unique_ptr<uint8_t[]> message(new uint8_t[message_size]);
     memset(message.get(), 'a', message_size);
     uint8_t* signature;
     size_t siglen;
@@ -491,9 +491,9 @@
 
 static void VerifySignature(const uint8_t* key, size_t key_len, const uint8_t* signature,
                             size_t signature_len, const uint8_t* message, size_t message_len) {
-    UniquePtr<EVP_PKEY, EVP_PKEY_Delete> pkey(d2i_PUBKEY(NULL, &key, key_len));
+    std::unique_ptr<EVP_PKEY, EVP_PKEY_Delete> pkey(d2i_PUBKEY(NULL, &key, key_len));
     ASSERT_TRUE(pkey.get() != NULL);
-    UniquePtr<EVP_PKEY_CTX, EVP_PKEY_CTX_Delete> ctx(EVP_PKEY_CTX_new(pkey.get(), NULL));
+    std::unique_ptr<EVP_PKEY_CTX, EVP_PKEY_CTX_Delete> ctx(EVP_PKEY_CTX_new(pkey.get(), NULL));
     ASSERT_TRUE(ctx.get() != NULL);
     ASSERT_EQ(1, EVP_PKEY_verify_init(ctx.get()));
     if (EVP_PKEY_type(pkey->type) == EVP_PKEY_RSA)
@@ -518,7 +518,7 @@
     // Sign a message so we can verify it with the exported pubkey.
     keymaster_rsa_sign_params_t sig_params = {DIGEST_NONE, PADDING_NONE};
     size_t message_len = params.modulus_size / 8;
-    UniquePtr<uint8_t[]> message(build_message(message_len));
+    std::unique_ptr<uint8_t[]> message(build_message(message_len));
     uint8_t* signature;
     size_t siglen;
     EXPECT_EQ(KM_ERROR_OK, device.sign_data(&sig_params, ptr, size, message.get(), message_len,