Merge "Fix the generated getevent labels."
diff --git a/adb/adb.cpp b/adb/adb.cpp
index c3f1a96..725aa91 100644
--- a/adb/adb.cpp
+++ b/adb/adb.cpp
@@ -46,8 +46,6 @@
 #include "adb_utils.h"
 #include "transport.h"
 
-#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
-
 #if !ADB_HOST
 #include <cutils/properties.h>
 #include <sys/capability.h>
diff --git a/fastboot/engine.cpp b/fastboot/engine.cpp
index a245e49..728dcb8 100644
--- a/fastboot/engine.cpp
+++ b/fastboot/engine.cpp
@@ -38,8 +38,6 @@
 #include <sys/types.h>
 #include <unistd.h>
 
-#define ARRAY_SIZE(x)           (sizeof(x)/sizeof((x)[0]))
-
 #define OP_DOWNLOAD   1
 #define OP_COMMAND    2
 #define OP_QUERY      3
diff --git a/fastboot/fastboot.cpp b/fastboot/fastboot.cpp
index 1839d25..665b9d0 100644
--- a/fastboot/fastboot.cpp
+++ b/fastboot/fastboot.cpp
@@ -47,6 +47,7 @@
 #include <utility>
 #include <vector>
 
+#include <android-base/macros.h>
 #include <android-base/parseint.h>
 #include <android-base/parsenetaddress.h>
 #include <android-base/stringprintf.h>
@@ -67,8 +68,6 @@
 #define O_BINARY 0
 #endif
 
-#define ARRAY_SIZE(a) (sizeof(a)/sizeof(*(a)))
-
 char cur_product[FB_RESPONSE_SZ + 1];
 
 static const char* serial = nullptr;
@@ -926,7 +925,7 @@
 
     setup_requirements(reinterpret_cast<char*>(data), sz);
 
-    for (size_t i = 0; i < ARRAY_SIZE(images); ++i) {
+    for (size_t i = 0; i < arraysize(images); ++i) {
         int fd = unzip_to_file(zip, images[i].img_name);
         if (fd == -1) {
             if (images[i].is_optional) {
@@ -988,7 +987,7 @@
 
     setup_requirements(reinterpret_cast<char*>(data), sz);
 
-    for (size_t i = 0; i < ARRAY_SIZE(images); i++) {
+    for (size_t i = 0; i < arraysize(images); i++) {
         fname = find_item(images[i].part_name, product);
         fastboot_buffer buf;
         if (!load_buf(transport, fname.c_str(), &buf)) {
diff --git a/init/service.cpp b/init/service.cpp
index d2edddd..03c0064 100644
--- a/init/service.cpp
+++ b/init/service.cpp
@@ -17,6 +17,9 @@
 #include "service.h"
 
 #include <fcntl.h>
+#include <sched.h>
+#include <sys/mount.h>
+#include <sys/prctl.h>
 #include <sys/resource.h>
 #include <sys/stat.h>
 #include <sys/time.h>
@@ -49,6 +52,46 @@
 #define CRITICAL_CRASH_THRESHOLD    4       // if we crash >4 times ...
 #define CRITICAL_CRASH_WINDOW       (4*60)  // ... in 4 minutes, goto recovery
 
+static void SetUpPidNamespace(const std::string& service_name) {
+    constexpr unsigned int kSafeFlags = MS_NODEV | MS_NOEXEC | MS_NOSUID;
+
+    // It's OK to LOG(FATAL) in this function since it's running in the first
+    // child process.
+    if (mount("", "/proc", "proc", kSafeFlags | MS_REMOUNT, "") == -1) {
+        PLOG(FATAL) << "couldn't remount(/proc)";
+    }
+
+    if (prctl(PR_SET_NAME, service_name.c_str()) == -1) {
+        PLOG(FATAL) << "couldn't set name";
+    }
+
+    pid_t child_pid = fork();
+    if (child_pid == -1) {
+        PLOG(FATAL) << "couldn't fork init inside the PID namespace";
+    }
+
+    if (child_pid > 0) {
+        // So that we exit with the right status.
+        static int init_exitstatus = 0;
+        signal(SIGTERM, [](int) { _exit(init_exitstatus); });
+
+        pid_t waited_pid;
+        int status;
+        while ((waited_pid = wait(&status)) > 0) {
+             // This loop will end when there are no processes left inside the
+             // PID namespace or when the init process inside the PID namespace
+             // gets a signal.
+            if (waited_pid == child_pid) {
+                init_exitstatus = status;
+            }
+        }
+        if (!WIFEXITED(init_exitstatus)) {
+            _exit(EXIT_FAILURE);
+        }
+        _exit(WEXITSTATUS(init_exitstatus));
+    }
+}
+
 SocketInfo::SocketInfo() : uid(0), gid(0), perm(0) {
 }
 
@@ -68,18 +111,22 @@
 Service::Service(const std::string& name, const std::string& classname,
                  const std::vector<std::string>& args)
     : name_(name), classname_(classname), flags_(0), pid_(0), time_started_(0),
-      time_crashed_(0), nr_crashed_(0), uid_(0), gid_(0), seclabel_(""),
-      ioprio_class_(IoSchedClass_NONE), ioprio_pri_(0), priority_(0), args_(args) {
+      time_crashed_(0), nr_crashed_(0), uid_(0), gid_(0), namespace_flags_(0),
+      seclabel_(""), ioprio_class_(IoSchedClass_NONE), ioprio_pri_(0),
+      priority_(0), args_(args) {
     onrestart_.InitSingleTrigger("onrestart");
 }
 
 Service::Service(const std::string& name, const std::string& classname,
-                 unsigned flags, uid_t uid, gid_t gid, const std::vector<gid_t>& supp_gids,
-                 const std::string& seclabel,  const std::vector<std::string>& args)
-    : name_(name), classname_(classname), flags_(flags), pid_(0), time_started_(0),
-      time_crashed_(0), nr_crashed_(0), uid_(uid), gid_(gid), supp_gids_(supp_gids),
-      seclabel_(seclabel), ioprio_class_(IoSchedClass_NONE), ioprio_pri_(0), priority_(0),
-      args_(args) {
+                 unsigned flags, uid_t uid, gid_t gid,
+                 const std::vector<gid_t>& supp_gids, unsigned namespace_flags,
+                 const std::string& seclabel,
+                 const std::vector<std::string>& args)
+    : name_(name), classname_(classname), flags_(flags), pid_(0),
+      time_started_(0), time_crashed_(0), nr_crashed_(0), uid_(uid), gid_(gid),
+      supp_gids_(supp_gids), namespace_flags_(namespace_flags),
+      seclabel_(seclabel), ioprio_class_(IoSchedClass_NONE), ioprio_pri_(0),
+      priority_(0), args_(args) {
     onrestart_.InitSingleTrigger("onrestart");
 }
 
@@ -174,29 +221,29 @@
     }
 }
 
-bool Service::HandleClass(const std::vector<std::string>& args, std::string* err) {
+bool Service::ParseClass(const std::vector<std::string>& args, std::string* err) {
     classname_ = args[1];
     return true;
 }
 
-bool Service::HandleConsole(const std::vector<std::string>& args, std::string* err) {
+bool Service::ParseConsole(const std::vector<std::string>& args, std::string* err) {
     flags_ |= SVC_CONSOLE;
     console_ = args.size() > 1 ? "/dev/" + args[1] : "";
     return true;
 }
 
-bool Service::HandleCritical(const std::vector<std::string>& args, std::string* err) {
+bool Service::ParseCritical(const std::vector<std::string>& args, std::string* err) {
     flags_ |= SVC_CRITICAL;
     return true;
 }
 
-bool Service::HandleDisabled(const std::vector<std::string>& args, std::string* err) {
+bool Service::ParseDisabled(const std::vector<std::string>& args, std::string* err) {
     flags_ |= SVC_DISABLED;
     flags_ |= SVC_RC_DISABLED;
     return true;
 }
 
-bool Service::HandleGroup(const std::vector<std::string>& args, std::string* err) {
+bool Service::ParseGroup(const std::vector<std::string>& args, std::string* err) {
     gid_ = decode_uid(args[1].c_str());
     for (std::size_t n = 2; n < args.size(); n++) {
         supp_gids_.emplace_back(decode_uid(args[n].c_str()));
@@ -204,7 +251,7 @@
     return true;
 }
 
-bool Service::HandlePriority(const std::vector<std::string>& args, std::string* err) {
+bool Service::ParsePriority(const std::vector<std::string>& args, std::string* err) {
     priority_ = std::stoi(args[1]);
 
     if (priority_ < ANDROID_PRIORITY_HIGHEST || priority_ > ANDROID_PRIORITY_LOWEST) {
@@ -217,7 +264,7 @@
     return true;
 }
 
-bool Service::HandleIoprio(const std::vector<std::string>& args, std::string* err) {
+bool Service::ParseIoprio(const std::vector<std::string>& args, std::string* err) {
     ioprio_pri_ = std::stoul(args[2], 0, 8);
 
     if (ioprio_pri_ < 0 || ioprio_pri_ > 7) {
@@ -239,36 +286,52 @@
     return true;
 }
 
-bool Service::HandleKeycodes(const std::vector<std::string>& args, std::string* err) {
+bool Service::ParseKeycodes(const std::vector<std::string>& args, std::string* err) {
     for (std::size_t i = 1; i < args.size(); i++) {
         keycodes_.emplace_back(std::stoi(args[i]));
     }
     return true;
 }
 
-bool Service::HandleOneshot(const std::vector<std::string>& args, std::string* err) {
+bool Service::ParseOneshot(const std::vector<std::string>& args, std::string* err) {
     flags_ |= SVC_ONESHOT;
     return true;
 }
 
-bool Service::HandleOnrestart(const std::vector<std::string>& args, std::string* err) {
+bool Service::ParseOnrestart(const std::vector<std::string>& args, std::string* err) {
     std::vector<std::string> str_args(args.begin() + 1, args.end());
     onrestart_.AddCommand(str_args, "", 0, err);
     return true;
 }
 
-bool Service::HandleSeclabel(const std::vector<std::string>& args, std::string* err) {
+bool Service::ParseNamespace(const std::vector<std::string>& args, std::string* err) {
+    for (size_t i = 1; i < args.size(); i++) {
+        if (args[i] == "pid") {
+            namespace_flags_ |= CLONE_NEWPID;
+            // PID namespaces require mount namespaces.
+            namespace_flags_ |= CLONE_NEWNS;
+        } else if (args[i] == "mnt") {
+            namespace_flags_ |= CLONE_NEWNS;
+        } else {
+            *err = "namespace must be 'pid' or 'mnt'";
+            return false;
+        }
+    }
+    return true;
+}
+
+bool Service::ParseSeclabel(const std::vector<std::string>& args, std::string* err) {
     seclabel_ = args[1];
     return true;
 }
 
-bool Service::HandleSetenv(const std::vector<std::string>& args, std::string* err) {
+bool Service::ParseSetenv(const std::vector<std::string>& args, std::string* err) {
     envvars_.emplace_back(args[1], args[2]);
     return true;
 }
 
 /* name type perm [ uid gid context ] */
-bool Service::HandleSocket(const std::vector<std::string>& args, std::string* err) {
+bool Service::ParseSocket(const std::vector<std::string>& args, std::string* err) {
     if (args[2] != "dgram" && args[2] != "stream" && args[2] != "seqpacket") {
         *err = "socket type must be 'dgram', 'stream' or 'seqpacket'";
         return false;
@@ -283,60 +346,61 @@
     return true;
 }
 
-bool Service::HandleUser(const std::vector<std::string>& args, std::string* err) {
+bool Service::ParseUser(const std::vector<std::string>& args, std::string* err) {
     uid_ = decode_uid(args[1].c_str());
     return true;
 }
 
-bool Service::HandleWritepid(const std::vector<std::string>& args, std::string* err) {
+bool Service::ParseWritepid(const std::vector<std::string>& args, std::string* err) {
     writepid_files_.assign(args.begin() + 1, args.end());
     return true;
 }
 
-class Service::OptionHandlerMap : public KeywordMap<OptionHandler> {
+class Service::OptionParserMap : public KeywordMap<OptionParser> {
 public:
-    OptionHandlerMap() {
+    OptionParserMap() {
     }
 private:
     Map& map() const override;
 };
 
-Service::OptionHandlerMap::Map& Service::OptionHandlerMap::map() const {
+Service::OptionParserMap::Map& Service::OptionParserMap::map() const {
     constexpr std::size_t kMax = std::numeric_limits<std::size_t>::max();
-    static const Map option_handlers = {
-        {"class",       {1,     1,    &Service::HandleClass}},
-        {"console",     {0,     1,    &Service::HandleConsole}},
-        {"critical",    {0,     0,    &Service::HandleCritical}},
-        {"disabled",    {0,     0,    &Service::HandleDisabled}},
-        {"group",       {1,     NR_SVC_SUPP_GIDS + 1, &Service::HandleGroup}},
-        {"ioprio",      {2,     2,    &Service::HandleIoprio}},
-        {"priority",    {1,     1,    &Service::HandlePriority}},
-        {"keycodes",    {1,     kMax, &Service::HandleKeycodes}},
-        {"oneshot",     {0,     0,    &Service::HandleOneshot}},
-        {"onrestart",   {1,     kMax, &Service::HandleOnrestart}},
-        {"seclabel",    {1,     1,    &Service::HandleSeclabel}},
-        {"setenv",      {2,     2,    &Service::HandleSetenv}},
-        {"socket",      {3,     6,    &Service::HandleSocket}},
-        {"user",        {1,     1,    &Service::HandleUser}},
-        {"writepid",    {1,     kMax, &Service::HandleWritepid}},
+    static const Map option_parsers = {
+        {"class",       {1,     1,    &Service::ParseClass}},
+        {"console",     {0,     1,    &Service::ParseConsole}},
+        {"critical",    {0,     0,    &Service::ParseCritical}},
+        {"disabled",    {0,     0,    &Service::ParseDisabled}},
+        {"group",       {1,     NR_SVC_SUPP_GIDS + 1, &Service::ParseGroup}},
+        {"ioprio",      {2,     2,    &Service::ParseIoprio}},
+        {"priority",    {1,     1,    &Service::ParsePriority}},
+        {"keycodes",    {1,     kMax, &Service::ParseKeycodes}},
+        {"oneshot",     {0,     0,    &Service::ParseOneshot}},
+        {"onrestart",   {1,     kMax, &Service::ParseOnrestart}},
+        {"namespace",   {1,     2,    &Service::ParseNamespace}},
+        {"seclabel",    {1,     1,    &Service::ParseSeclabel}},
+        {"setenv",      {2,     2,    &Service::ParseSetenv}},
+        {"socket",      {3,     6,    &Service::ParseSocket}},
+        {"user",        {1,     1,    &Service::ParseUser}},
+        {"writepid",    {1,     kMax, &Service::ParseWritepid}},
     };
-    return option_handlers;
+    return option_parsers;
 }
 
-bool Service::HandleLine(const std::vector<std::string>& args, std::string* err) {
+bool Service::ParseLine(const std::vector<std::string>& args, std::string* err) {
     if (args.empty()) {
         *err = "option needed, but not provided";
         return false;
     }
 
-    static const OptionHandlerMap handler_map;
-    auto handler = handler_map.FindFunction(args[0], args.size() - 1, err);
+    static const OptionParserMap parser_map;
+    auto parser = parser_map.FindFunction(args[0], args.size() - 1, err);
 
-    if (!handler) {
+    if (!parser) {
         return false;
     }
 
-    return (this->*handler)(args, err);
+    return (this->*parser)(args, err);
 }
 
 bool Service::Start() {
@@ -389,7 +453,7 @@
 
         rc = getfilecon(args_[0].c_str(), &fcon);
         if (rc < 0) {
-            LOG(ERROR) << "could not get context while starting '" << name_ << "'";
+            LOG(ERROR) << "could not get file context while starting '" << name_ << "'";
             free(mycon);
             return false;
         }
@@ -417,10 +481,23 @@
 
     LOG(VERBOSE) << "Starting service '" << name_ << "'...";
 
-    pid_t pid = fork();
+    pid_t pid = -1;
+    if (namespace_flags_) {
+        pid = clone(nullptr, nullptr, namespace_flags_ | SIGCHLD,
+                    nullptr);
+    } else {
+        pid = fork();
+    }
+
     if (pid == 0) {
         umask(077);
 
+        if (namespace_flags_ & CLONE_NEWPID) {
+            // This will fork again to run an init process inside the PID
+            // namespace.
+            SetUpPidNamespace(name_);
+        }
+
         for (const auto& ei : envvars_) {
             add_environment(ei.name.c_str(), ei.value.c_str());
         }
@@ -695,6 +772,7 @@
     exec_count_++;
     std::string name = StringPrintf("exec %d (%s)", exec_count_, str_args[0].c_str());
     unsigned flags = SVC_EXEC | SVC_ONESHOT;
+    unsigned namespace_flags = 0;
 
     std::string seclabel = "";
     if (command_arg > 2 && args[1] != "-") {
@@ -715,7 +793,8 @@
     }
 
     std::unique_ptr<Service> svc_p(new Service(name, "default", flags, uid, gid,
-                                               supp_gids, seclabel, str_args));
+                                               supp_gids, namespace_flags,
+                                               seclabel, str_args));
     if (!svc_p) {
         LOG(ERROR) << "Couldn't allocate service for exec of '" << str_args[0] << "'";
         return nullptr;
@@ -870,7 +949,7 @@
 bool ServiceParser::ParseLineSection(const std::vector<std::string>& args,
                                      const std::string& filename, int line,
                                      std::string* err) const {
-    return service_ ? service_->HandleLine(args, err) : false;
+    return service_ ? service_->ParseLine(args, err) : false;
 }
 
 void ServiceParser::EndSection() {
diff --git a/init/service.h b/init/service.h
index 8b3a0ad..38c5d64 100644
--- a/init/service.h
+++ b/init/service.h
@@ -72,10 +72,11 @@
             const std::vector<std::string>& args);
 
     Service(const std::string& name, const std::string& classname,
-            unsigned flags, uid_t uid, gid_t gid, const std::vector<gid_t>& supp_gids,
-            const std::string& seclabel,  const std::vector<std::string>& args);
+            unsigned flags, uid_t uid, gid_t gid,
+            const std::vector<gid_t>& supp_gids, unsigned namespace_flags,
+            const std::string& seclabel, const std::vector<std::string>& args);
 
-    bool HandleLine(const std::vector<std::string>& args, std::string* err);
+    bool ParseLine(const std::vector<std::string>& args, std::string* err);
     bool Start();
     bool StartIfNotDisabled();
     bool Enable();
@@ -102,9 +103,9 @@
     const std::vector<std::string>& args() const { return args_; }
 
 private:
-    using OptionHandler = bool (Service::*) (const std::vector<std::string>& args,
-                                             std::string* err);
-    class OptionHandlerMap;
+    using OptionParser = bool (Service::*) (const std::vector<std::string>& args,
+                                            std::string* err);
+    class OptionParserMap;
 
     void NotifyStateChange(const std::string& new_state) const;
     void StopOrReset(int how);
@@ -113,21 +114,22 @@
     void PublishSocket(const std::string& name, int fd) const;
     void KillProcessGroup(int signal);
 
-    bool HandleClass(const std::vector<std::string>& args, std::string* err);
-    bool HandleConsole(const std::vector<std::string>& args, std::string* err);
-    bool HandleCritical(const std::vector<std::string>& args, std::string* err);
-    bool HandleDisabled(const std::vector<std::string>& args, std::string* err);
-    bool HandleGroup(const std::vector<std::string>& args, std::string* err);
-    bool HandlePriority(const std::vector<std::string>& args, std::string* err);
-    bool HandleIoprio(const std::vector<std::string>& args, std::string* err);
-    bool HandleKeycodes(const std::vector<std::string>& args, std::string* err);
-    bool HandleOneshot(const std::vector<std::string>& args, std::string* err);
-    bool HandleOnrestart(const std::vector<std::string>& args, std::string* err);
-    bool HandleSeclabel(const std::vector<std::string>& args, std::string* err);
-    bool HandleSetenv(const std::vector<std::string>& args, std::string* err);
-    bool HandleSocket(const std::vector<std::string>& args, std::string* err);
-    bool HandleUser(const std::vector<std::string>& args, std::string* err);
-    bool HandleWritepid(const std::vector<std::string>& args, std::string* err);
+    bool ParseClass(const std::vector<std::string>& args, std::string* err);
+    bool ParseConsole(const std::vector<std::string>& args, std::string* err);
+    bool ParseCritical(const std::vector<std::string>& args, std::string* err);
+    bool ParseDisabled(const std::vector<std::string>& args, std::string* err);
+    bool ParseGroup(const std::vector<std::string>& args, std::string* err);
+    bool ParsePriority(const std::vector<std::string>& args, std::string* err);
+    bool ParseIoprio(const std::vector<std::string>& args, std::string* err);
+    bool ParseKeycodes(const std::vector<std::string>& args, std::string* err);
+    bool ParseOneshot(const std::vector<std::string>& args, std::string* err);
+    bool ParseOnrestart(const std::vector<std::string>& args, std::string* err);
+    bool ParseNamespace(const std::vector<std::string>& args, std::string* err);
+    bool ParseSeclabel(const std::vector<std::string>& args, std::string* err);
+    bool ParseSetenv(const std::vector<std::string>& args, std::string* err);
+    bool ParseSocket(const std::vector<std::string>& args, std::string* err);
+    bool ParseUser(const std::vector<std::string>& args, std::string* err);
+    bool ParseWritepid(const std::vector<std::string>& args, std::string* err);
 
     std::string name_;
     std::string classname_;
@@ -142,6 +144,7 @@
     uid_t uid_;
     gid_t gid_;
     std::vector<gid_t> supp_gids_;
+    unsigned namespace_flags_;
 
     std::string seclabel_;
 
diff --git a/libcutils/tests/PropertiesTest.cpp b/libcutils/tests/PropertiesTest.cpp
index 5f2396b..f66590b 100644
--- a/libcutils/tests/PropertiesTest.cpp
+++ b/libcutils/tests/PropertiesTest.cpp
@@ -24,11 +24,12 @@
 #include <sstream>
 #include <iostream>
 
+#include <android-base/macros.h>
+
 namespace android {
 
 #define STRINGIFY_INNER(x) #x
 #define STRINGIFY(x) STRINGIFY_INNER(x)
-#define ARRAY_SIZE(x) (sizeof(x)/sizeof((x)[0]))
 #define ASSERT_OK(x) ASSERT_EQ(0, (x))
 #define EXPECT_OK(x) EXPECT_EQ(0, (x))
 
@@ -85,7 +86,7 @@
     }
 
     void ResetValue(unsigned char c = 0xFF) {
-        for (size_t i = 0; i < ARRAY_SIZE(mValue); ++i) {
+        for (size_t i = 0; i < arraysize(mValue); ++i) {
             mValue[i] = (char) c;
         }
     }
@@ -177,7 +178,7 @@
      * TRUE
      */
     const char *valuesTrue[] = { "1", "true", "y", "yes", "on", };
-    for (size_t i = 0; i < ARRAY_SIZE(valuesTrue); ++i) {
+    for (size_t i = 0; i < arraysize(valuesTrue); ++i) {
         ASSERT_OK(property_set(PROPERTY_TEST_KEY, valuesTrue[i]));
         bool val = property_get_bool(PROPERTY_TEST_KEY, /*default_value*/false);
         EXPECT_TRUE(val) << "Property should've been TRUE for value: '" << valuesTrue[i] << "'";
@@ -187,7 +188,7 @@
      * FALSE
      */
     const char *valuesFalse[] = { "0", "false", "n", "no", "off", };
-    for (size_t i = 0; i < ARRAY_SIZE(valuesFalse); ++i) {
+    for (size_t i = 0; i < arraysize(valuesFalse); ++i) {
         ASSERT_OK(property_set(PROPERTY_TEST_KEY, valuesFalse[i]));
         bool val = property_get_bool(PROPERTY_TEST_KEY, /*default_value*/true);
         EXPECT_FALSE(val) << "Property shoud've been FALSE For string value: '" << valuesFalse[i] << "'";
@@ -200,7 +201,7 @@
             "+1", "  1  ", "  true", "  true  ", "  y  ", "  yes", "yes  ",
             "+0", "-0", "00", "  00  ", "  false", "false  ",
     };
-    for (size_t i = 0; i < ARRAY_SIZE(valuesNeither); ++i) {
+    for (size_t i = 0; i < arraysize(valuesNeither); ++i) {
         ASSERT_OK(property_set(PROPERTY_TEST_KEY, valuesNeither[i]));
 
         // The default value should always be used
@@ -249,9 +250,9 @@
         DEFAULT_VALUE, DEFAULT_VALUE,
     };
 
-    ASSERT_EQ(ARRAY_SIZE(setValues), ARRAY_SIZE(getValues));
+    ASSERT_EQ(arraysize(setValues), arraysize(getValues));
 
-    for (size_t i = 0; i < ARRAY_SIZE(setValues); ++i) {
+    for (size_t i = 0; i < arraysize(setValues); ++i) {
         ASSERT_OK(property_set(PROPERTY_TEST_KEY, setValues[i]));
 
         int64_t val = property_get_int64(PROPERTY_TEST_KEY, DEFAULT_VALUE);
@@ -296,9 +297,9 @@
         DEFAULT_VALUE, DEFAULT_VALUE,
     };
 
-    ASSERT_EQ(ARRAY_SIZE(setValues), ARRAY_SIZE(getValues));
+    ASSERT_EQ(arraysize(setValues), arraysize(getValues));
 
-    for (size_t i = 0; i < ARRAY_SIZE(setValues); ++i) {
+    for (size_t i = 0; i < arraysize(setValues); ++i) {
         ASSERT_OK(property_set(PROPERTY_TEST_KEY, setValues[i]));
 
         int32_t val = property_get_int32(PROPERTY_TEST_KEY, DEFAULT_VALUE);
diff --git a/libmemunreachable/Allocator.cpp b/libmemunreachable/Allocator.cpp
index 68f654c..6fe67a4 100644
--- a/libmemunreachable/Allocator.cpp
+++ b/libmemunreachable/Allocator.cpp
@@ -52,8 +52,6 @@
   return (x + y - 1) / y;
 }
 
-#define ARRAY_SIZE(x) (sizeof(x)/sizeof((x)[0]))
-
 static constexpr size_t kPageSize = 4096;
 static constexpr size_t kChunkSize = 256 * 1024;
 static constexpr size_t kUsableChunkSize = kChunkSize - kPageSize;
@@ -258,7 +256,7 @@
   unsigned int i = first_free_bitmap_;
   while (free_bitmap_[i] == 0)
     i++;
-  assert(i < ARRAY_SIZE(free_bitmap_));
+  assert(i < arraysize(free_bitmap_));
   unsigned int bit = __builtin_ffs(free_bitmap_[i]) - 1;
   assert(free_bitmap_[i] & (1U << bit));
   free_bitmap_[i] &= ~(1U << bit);
@@ -266,7 +264,7 @@
   assert(n < max_allocations_);
 
   unsigned int page = n * allocation_size_ / kPageSize;
-  assert(page / 32 < ARRAY_SIZE(dirty_pages_));
+  assert(page / 32 < arraysize(dirty_pages_));
   dirty_pages_[page / 32] |= 1U << (page % 32);
 
   free_count_--;
@@ -285,7 +283,7 @@
   unsigned int i = n / 32;
   unsigned int bit = n % 32;
 
-  assert(i < ARRAY_SIZE(free_bitmap_));
+  assert(i < arraysize(free_bitmap_));
   assert(!(free_bitmap_[i] & (1U << bit)));
   free_bitmap_[i] |= 1U << bit;
   free_count_++;
diff --git a/toolbox/Android.mk b/toolbox/Android.mk
index ad8ac03..c9e2ddd 100644
--- a/toolbox/Android.mk
+++ b/toolbox/Android.mk
@@ -34,13 +34,10 @@
     getevent \
     newfs_msdos \
     sendevent \
-    start \
-    stop \
 
 ALL_TOOLS = $(BSD_TOOLS) $(OUR_TOOLS)
 
 LOCAL_SRC_FILES := \
-    start_stop.cpp \
     toolbox.c \
     $(patsubst %,%.c,$(OUR_TOOLS)) \
 
diff --git a/toolbox/start.c b/toolbox/start.c
deleted file mode 100644
index cca5fef..0000000
--- a/toolbox/start.c
+++ /dev/null
@@ -1 +0,0 @@
-/* Needed by Android.mk. Actual code in start_stop.cpp. */
diff --git a/toolbox/start_stop.cpp b/toolbox/start_stop.cpp
deleted file mode 100644
index dc48c0c..0000000
--- a/toolbox/start_stop.cpp
+++ /dev/null
@@ -1,43 +0,0 @@
-#include <error.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-
-#include <cutils/properties.h>
-
-static const char* services[] = {
-  "netd",
-  "surfaceflinger",
-  "zygote",
-  "zygote_secondary",
-};
-
-static int start_stop(bool start, int argc, char* argv[]) {
-  if (getuid() != 0) error(1, 0, "must be root");
-  const char* property = start ? "ctl.start" : "ctl.stop";
-  if (argc > 2) {
-    error(1, 0, "usage: %s [SERVICE]\n", argv[0]);
-  } else if (argc == 2) {
-    property_set(property, argv[1]);
-  } else {
-    if (start) {
-      for (size_t i = 0; i < sizeof(services)/sizeof(services[0]); ++i) {
-        property_set(property, services[i]);
-      }
-    } else {
-      for (int i = sizeof(services)/sizeof(services[0]) - 1; i >= 0; --i) {
-        property_set(property, services[i]);
-      }
-    }
-  }
-  return 0;
-}
-
-extern "C" int start_main(int argc, char* argv[]) {
-  return start_stop(true, argc, argv);
-}
-
-extern "C" int stop_main(int argc, char* argv[]) {
-  return start_stop(false, argc, argv);
-}
diff --git a/toolbox/stop.c b/toolbox/stop.c
deleted file mode 100644
index cca5fef..0000000
--- a/toolbox/stop.c
+++ /dev/null
@@ -1 +0,0 @@
-/* Needed by Android.mk. Actual code in start_stop.cpp. */