Merge "Fix null pointer dereference in auditParse"
diff --git a/TEST_MAPPING b/TEST_MAPPING
index c47230f..f9c3b4a 100644
--- a/TEST_MAPPING
+++ b/TEST_MAPPING
@@ -2,6 +2,30 @@
   "presubmit": [
     {
       "name": "adbd_test"
+    },
+    {
+      "name": "debuggerd_test"
+    },
+    {
+      "name": "init_tests"
+    },
+    {
+      "name": "libbase_test"
+    },
+    {
+      "name": "libprocinfo_test"
+    },
+    {
+      "name": "memunreachable_test"
+    },
+    {
+      "name": "memunreachable_binder_test"
+    },
+    {
+      "name": "propertyinfoserializer_tests"
+    },
+    {
+      "name": "ziparchive-tests"
     }
   ]
 }
diff --git a/adb/Android.bp b/adb/Android.bp
index 00e98fe..e994075 100644
--- a/adb/Android.bp
+++ b/adb/Android.bp
@@ -285,6 +285,15 @@
         "deploypatchgenerator",
     ],
 
+    // Archive adb, adb.exe.
+    dist: {
+        targets: [
+            "dist_files",
+            "sdk",
+            "win_sdk",
+        ],
+    },
+
     target: {
         darwin: {
             cflags: [
diff --git a/adb/Android.mk b/adb/Android.mk
deleted file mode 100644
index 8b2d558..0000000
--- a/adb/Android.mk
+++ /dev/null
@@ -1,8 +0,0 @@
-LOCAL_PATH := $(call my-dir)
-
-# Archive adb, adb.exe.
-$(call dist-for-goals,dist_files sdk win_sdk,$(HOST_OUT_EXECUTABLES)/adb)
-
-ifdef HOST_CROSS_OS
-$(call dist-for-goals,dist_files sdk win_sdk,$(ALL_MODULES.host_cross_adb.BUILT))
-endif
diff --git a/adb/adb_auth.h b/adb/adb_auth.h
index 715e04f..2fc8478 100644
--- a/adb/adb_auth.h
+++ b/adb/adb_auth.h
@@ -36,6 +36,7 @@
 void adb_auth_init();
 
 int adb_auth_keygen(const char* filename);
+int adb_auth_pubkey(const char* filename);
 std::string adb_auth_get_userkey();
 std::deque<std::shared_ptr<RSA>> adb_auth_get_private_keys();
 
diff --git a/adb/client/auth.cpp b/adb/client/auth.cpp
index 71c19b8..bcb829b 100644
--- a/adb/client/auth.cpp
+++ b/adb/client/auth.cpp
@@ -43,6 +43,7 @@
 
 #include "adb.h"
 #include "adb_auth.h"
+#include "adb_io.h"
 #include "adb_utils.h"
 #include "sysdeps.h"
 #include "transport.h"
@@ -52,30 +53,7 @@
     *new std::map<std::string, std::shared_ptr<RSA>>;
 static std::map<int, std::string>& g_monitored_paths = *new std::map<int, std::string>;
 
-static std::string get_user_info() {
-    LOG(INFO) << "get_user_info...";
-
-    std::string hostname;
-    if (getenv("HOSTNAME")) hostname = getenv("HOSTNAME");
-#if !defined(_WIN32)
-    char buf[64];
-    if (hostname.empty() && gethostname(buf, sizeof(buf)) != -1) hostname = buf;
-#endif
-    if (hostname.empty()) hostname = "unknown";
-
-    std::string username;
-    if (getenv("LOGNAME")) username = getenv("LOGNAME");
-#if !defined _WIN32 && !defined ADB_HOST_ON_TARGET
-    if (username.empty() && getlogin()) username = getlogin();
-#endif
-    if (username.empty()) hostname = "unknown";
-
-    return " " + username + "@" + hostname;
-}
-
-static bool write_public_keyfile(RSA* private_key, const std::string& private_key_path) {
-    LOG(INFO) << "write_public_keyfile...";
-
+static bool calculate_public_key(std::string* out, RSA* private_key) {
     uint8_t binary_key_data[ANDROID_PUBKEY_ENCODED_SIZE];
     if (!android_pubkey_encode(private_key, binary_key_data, sizeof(binary_key_data))) {
         LOG(ERROR) << "Failed to convert to public key";
@@ -88,20 +66,10 @@
         return false;
     }
 
-    std::string content;
-    content.resize(expected_length);
-    size_t actual_length = EVP_EncodeBlock(reinterpret_cast<uint8_t*>(&content[0]), binary_key_data,
+    out->resize(expected_length);
+    size_t actual_length = EVP_EncodeBlock(reinterpret_cast<uint8_t*>(out->data()), binary_key_data,
                                            sizeof(binary_key_data));
-    content.resize(actual_length);
-
-    content += get_user_info();
-
-    std::string path(private_key_path + ".pub");
-    if (!android::base::WriteStringToFile(content, path)) {
-        PLOG(ERROR) << "Failed to write public key to '" << path << "'";
-        return false;
-    }
-
+    out->resize(actual_length);
     return true;
 }
 
@@ -140,11 +108,6 @@
         goto out;
     }
 
-    if (!write_public_keyfile(rsa, file)) {
-        D("Failed to write public key");
-        goto out;
-    }
-
     ret = 1;
 
 out:
@@ -170,36 +133,41 @@
     return result;
 }
 
-static bool read_key_file(const std::string& file) {
-    LOG(INFO) << "read_key_file '" << file << "'...";
-
+static std::shared_ptr<RSA> read_key_file(const std::string& file) {
     std::unique_ptr<FILE, decltype(&fclose)> fp(fopen(file.c_str(), "r"), fclose);
     if (!fp) {
         PLOG(ERROR) << "Failed to open '" << file << "'";
-        return false;
+        return nullptr;
     }
 
     RSA* key = RSA_new();
     if (!PEM_read_RSAPrivateKey(fp.get(), &key, nullptr, nullptr)) {
         LOG(ERROR) << "Failed to read key";
         RSA_free(key);
+        return nullptr;
+    }
+
+    return std::shared_ptr<RSA>(key, RSA_free);
+}
+
+static bool load_key(const std::string& file) {
+    std::shared_ptr<RSA> key = read_key_file(file);
+    if (!key) {
         return false;
     }
 
     std::lock_guard<std::mutex> lock(g_keys_mutex);
-    std::string fingerprint = hash_key(key);
+    std::string fingerprint = hash_key(key.get());
     if (g_keys.find(fingerprint) != g_keys.end()) {
         LOG(INFO) << "ignoring already-loaded key: " << file;
-        RSA_free(key);
     } else {
-        g_keys[fingerprint] = std::shared_ptr<RSA>(key, RSA_free);
+        g_keys[fingerprint] = std::move(key);
     }
-
     return true;
 }
 
-static bool read_keys(const std::string& path, bool allow_dir = true) {
-    LOG(INFO) << "read_keys '" << path << "'...";
+static bool load_keys(const std::string& path, bool allow_dir = true) {
+    LOG(INFO) << "load_keys '" << path << "'...";
 
     struct stat st;
     if (stat(path.c_str(), &st) != 0) {
@@ -208,7 +176,7 @@
     }
 
     if (S_ISREG(st.st_mode)) {
-        return read_key_file(path);
+        return load_key(path);
     } else if (S_ISDIR(st.st_mode)) {
         if (!allow_dir) {
             // inotify isn't recursive. It would break expectations to load keys in nested
@@ -237,7 +205,7 @@
                 continue;
             }
 
-            result |= read_key_file((path + OS_PATH_SEPARATOR + name));
+            result |= load_key((path + OS_PATH_SEPARATOR + name));
         }
         return result;
     }
@@ -250,7 +218,7 @@
     return adb_get_android_dir_path() + OS_PATH_SEPARATOR + "adbkey";
 }
 
-static bool get_user_key() {
+static bool generate_userkey() {
     std::string path = get_user_key_path();
     if (path.empty()) {
         PLOG(ERROR) << "Error getting user key filename";
@@ -266,7 +234,7 @@
         }
     }
 
-    return read_key_file(path);
+    return load_key(path);
 }
 
 static std::set<std::string> get_vendor_keys() {
@@ -320,26 +288,42 @@
     return result;
 }
 
+static bool pubkey_from_privkey(std::string* out, const std::string& path) {
+    std::shared_ptr<RSA> privkey = read_key_file(path);
+    if (!privkey) {
+        return false;
+    }
+    return calculate_public_key(out, privkey.get());
+}
+
 std::string adb_auth_get_userkey() {
     std::string path = get_user_key_path();
     if (path.empty()) {
         PLOG(ERROR) << "Error getting user key filename";
         return "";
     }
-    path += ".pub";
 
-    std::string content;
-    if (!android::base::ReadFileToString(path, &content)) {
-        PLOG(ERROR) << "Can't load '" << path << "'";
+    std::string result;
+    if (!pubkey_from_privkey(&result, path)) {
         return "";
     }
-    return content;
+    return result;
 }
 
 int adb_auth_keygen(const char* filename) {
     return (generate_key(filename) == 0);
 }
 
+int adb_auth_pubkey(const char* filename) {
+    std::string pubkey;
+    if (!pubkey_from_privkey(&pubkey, filename)) {
+        return 1;
+    }
+    pubkey.push_back('\n');
+
+    return WriteFdExactly(STDOUT_FILENO, pubkey.data(), pubkey.size()) ? 0 : 1;
+}
+
 #if defined(__linux__)
 static void adb_auth_inotify_update(int fd, unsigned fd_event, void*) {
     LOG(INFO) << "adb_auth_inotify_update called";
@@ -380,7 +364,7 @@
                     LOG(INFO) << "ignoring new directory at '" << path << "'";
                 } else {
                     LOG(INFO) << "observed new file at '" << path << "'";
-                    read_keys(path, false);
+                    load_keys(path, false);
                 }
             } else {
                 LOG(WARNING) << "unmonitored event for " << path << ": 0x" << std::hex
@@ -420,8 +404,8 @@
 void adb_auth_init() {
     LOG(INFO) << "adb_auth_init...";
 
-    if (!get_user_key()) {
-        LOG(ERROR) << "Failed to get user key";
+    if (!generate_userkey()) {
+        LOG(ERROR) << "Failed to generate user key";
         return;
     }
 
@@ -432,7 +416,7 @@
 #endif
 
     for (const std::string& path : key_paths) {
-        read_keys(path.c_str());
+        load_keys(path.c_str());
     }
 }
 
diff --git a/adb/client/commandline.cpp b/adb/client/commandline.cpp
index b5bed28..c11052d 100644
--- a/adb/client/commandline.cpp
+++ b/adb/client/commandline.cpp
@@ -185,7 +185,6 @@
         " enable-verity            re-enable dm-verity checking on userdebug builds\n"
         " keygen FILE\n"
         "     generate adb public/private key; private key stored in FILE,\n"
-        "     public key stored in FILE.pub (existing files overwritten)\n"
         "\n"
         "scripting:\n"
         " wait-for[-TRANSPORT]-STATE\n"
@@ -1756,14 +1755,14 @@
         // Always print key generation information for keygen command.
         adb_trace_enable(AUTH);
         return adb_auth_keygen(argv[1]);
-    }
-    else if (!strcmp(argv[0], "jdwp")) {
+    } else if (!strcmp(argv[0], "pubkey")) {
+        if (argc != 2) error_exit("pubkey requires an argument");
+        return adb_auth_pubkey(argv[1]);
+    } else if (!strcmp(argv[0], "jdwp")) {
         return adb_connect_command("jdwp");
-    }
-    else if (!strcmp(argv[0], "track-jdwp")) {
+    } else if (!strcmp(argv[0], "track-jdwp")) {
         return adb_connect_command("track-jdwp");
-    }
-    else if (!strcmp(argv[0], "track-devices")) {
+    } else if (!strcmp(argv[0], "track-devices")) {
         return adb_connect_command("host:track-devices");
     } else if (!strcmp(argv[0], "raw")) {
         if (argc != 2) {
@@ -1772,13 +1771,11 @@
         return adb_connect_command(argv[1]);
     }
 
-
     /* "adb /?" is a common idiom under Windows */
     else if (!strcmp(argv[0], "--help") || !strcmp(argv[0], "help") || !strcmp(argv[0], "/?")) {
         help();
         return 0;
-    }
-    else if (!strcmp(argv[0], "--version") || !strcmp(argv[0], "version")) {
+    } else if (!strcmp(argv[0], "--version") || !strcmp(argv[0], "version")) {
         fprintf(stdout, "%s", adb_version().c_str());
         return 0;
     } else if (!strcmp(argv[0], "features")) {
diff --git a/cpio/Android.bp b/cpio/Android.bp
index 847e0f1..baa0319 100644
--- a/cpio/Android.bp
+++ b/cpio/Android.bp
@@ -5,4 +5,7 @@
     srcs: ["mkbootfs.c"],
     cflags: ["-Werror"],
     shared_libs: ["libcutils"],
+    dist: {
+        targets: ["dist_files"],
+    },
 }
diff --git a/cpio/Android.mk b/cpio/Android.mk
deleted file mode 100644
index fc3551b..0000000
--- a/cpio/Android.mk
+++ /dev/null
@@ -1,3 +0,0 @@
-# Copyright 2005 The Android Open Source Project
-
-$(call dist-for-goals,dist_files,$(ALL_MODULES.mkbootfs.BUILT))
diff --git a/debuggerd/libdebuggerd/tombstone.cpp b/debuggerd/libdebuggerd/tombstone.cpp
index 0b8a936..1179263 100644
--- a/debuggerd/libdebuggerd/tombstone.cpp
+++ b/debuggerd/libdebuggerd/tombstone.cpp
@@ -78,7 +78,7 @@
   _LOG(log, logtype::HEADER, "ABI: '%s'\n", ABI_STRING);
 }
 
-static void dump_probable_cause(log_t* log, const siginfo_t* si) {
+static void dump_probable_cause(log_t* log, const siginfo_t* si, BacktraceMap* map) {
   std::string cause;
   if (si->si_signo == SIGSEGV && si->si_code == SEGV_MAPERR) {
     if (si->si_addr < reinterpret_cast<void*>(4096)) {
@@ -94,6 +94,14 @@
     } else if (si->si_addr == reinterpret_cast<void*>(0xffff0f60)) {
       cause = "call to kuser_cmpxchg64";
     }
+  } else if (si->si_signo == SIGSEGV && si->si_code == SEGV_ACCERR) {
+    for (auto it = map->begin(); it != map->end(); ++it) {
+      const backtrace_map_t* entry = *it;
+      if (si->si_addr >= reinterpret_cast<void*>(entry->start) &&
+          si->si_addr < reinterpret_cast<void*>(entry->end) && entry->flags == PROT_EXEC) {
+        cause = "execute-only (no-read) memory access error; likely due to data in .text.";
+      }
+    }
   } else if (si->si_signo == SIGSYS && si->si_code == SYS_SECCOMP) {
     cause = StringPrintf("seccomp prevented call to disallowed %s system call %d", ABI_STRING,
                          si->si_syscall);
@@ -125,8 +133,6 @@
   _LOG(log, logtype::HEADER, "signal %d (%s), code %d (%s%s), fault addr %s\n",
        thread_info.siginfo->si_signo, get_signame(thread_info.siginfo),
        thread_info.siginfo->si_code, get_sigcode(thread_info.siginfo), sender_desc, addr_desc);
-
-  dump_probable_cause(log, thread_info.siginfo);
 }
 
 static void dump_thread_info(log_t* log, const ThreadInfo& thread_info) {
@@ -426,6 +432,7 @@
 
   if (thread_info.siginfo) {
     dump_signal_info(log, thread_info, process_memory);
+    dump_probable_cause(log, thread_info.siginfo, map);
   }
 
   if (primary_thread) {
diff --git a/fastboot/Android.bp b/fastboot/Android.bp
index faed376..8006c41 100644
--- a/fastboot/Android.bp
+++ b/fastboot/Android.bp
@@ -260,6 +260,13 @@
         "mke2fs",
         "make_f2fs",
     ],
+    dist: {
+        targets: [
+            "dist_files",
+            "sdk",
+            "win_sdk",
+        ],
+    },
 
     target: {
         not_windows: {
diff --git a/fastboot/Android.mk b/fastboot/Android.mk
index e4c1317..17ec392 100644
--- a/fastboot/Android.mk
+++ b/fastboot/Android.mk
@@ -18,13 +18,9 @@
 # Package fastboot-related executables.
 #
 
-my_dist_files := $(HOST_OUT_EXECUTABLES)/fastboot
-my_dist_files += $(HOST_OUT_EXECUTABLES)/mke2fs
+my_dist_files := $(HOST_OUT_EXECUTABLES)/mke2fs
 my_dist_files += $(HOST_OUT_EXECUTABLES)/e2fsdroid
 my_dist_files += $(HOST_OUT_EXECUTABLES)/make_f2fs
 my_dist_files += $(HOST_OUT_EXECUTABLES)/sload_f2fs
 $(call dist-for-goals,dist_files sdk win_sdk,$(my_dist_files))
-ifdef HOST_CROSS_OS
-$(call dist-for-goals,dist_files sdk win_sdk,$(ALL_MODULES.host_cross_fastboot.BUILT))
-endif
 my_dist_files :=
diff --git a/fastboot/fs.cpp b/fastboot/fs.cpp
index fc6a16b..8c0aa6b 100644
--- a/fastboot/fs.cpp
+++ b/fastboot/fs.cpp
@@ -172,13 +172,8 @@
     mkf2fs_args.push_back("-S");
     std::string size_str = std::to_string(partSize);
     mkf2fs_args.push_back(size_str.c_str());
-    mkf2fs_args.push_back("-f");
-    mkf2fs_args.push_back("-O");
-    mkf2fs_args.push_back("encrypt");
-    mkf2fs_args.push_back("-O");
-    mkf2fs_args.push_back("quota");
-    mkf2fs_args.push_back("-O");
-    mkf2fs_args.push_back("verity");
+    mkf2fs_args.push_back("-g");
+    mkf2fs_args.push_back("android");
     mkf2fs_args.push_back(fileName);
     mkf2fs_args.push_back(nullptr);
 
diff --git a/fs_mgr/fs_mgr_format.cpp b/fs_mgr/fs_mgr_format.cpp
index 845cca9..0983663 100644
--- a/fs_mgr/fs_mgr_format.cpp
+++ b/fs_mgr/fs_mgr_format.cpp
@@ -117,12 +117,7 @@
     // clang-format off
     const char* const args[] = {
         "/system/bin/make_f2fs",
-        "-d1",
-        "-f",
-        "-O", "encrypt",
-        "-O", "quota",
-        "-O", "verity",
-        "-w", "4096",
+        "-g", "android",
         fs_blkdev,
         size_str.c_str(),
         nullptr
diff --git a/fs_mgr/fs_mgr_vendor_overlay.cpp b/fs_mgr/fs_mgr_vendor_overlay.cpp
index e1815ff..830f0dd 100644
--- a/fs_mgr/fs_mgr_vendor_overlay.cpp
+++ b/fs_mgr/fs_mgr_vendor_overlay.cpp
@@ -35,43 +35,42 @@
 
 namespace {
 
-const auto kVendorOverlaySourceDir = "/system/vendor_overlay/"s;
+// The order of the list means the priority to show the files in the directory.
+// The last one has the highest priority.
+const std::vector<const std::string> kVendorOverlaySourceDirs = {
+        "/system/vendor_overlay/",
+        "/product/vendor_overlay/",
+};
 const auto kVndkVersionPropertyName = "ro.vndk.version"s;
 const auto kVendorTopDir = "/vendor/"s;
 const auto kLowerdirOption = "lowerdir="s;
 
-std::string fs_mgr_get_vendor_overlay_top_dir() {
-    // VNDK version is provided by the /vendor/default.prop
-    // To read the property, it must be called at the second init stage after the default
-    // properties are loaded.
-    std::string vndk_version = android::base::GetProperty(kVndkVersionPropertyName, "");
-    if (vndk_version.empty()) {
-        return "";
-    }
-    return kVendorOverlaySourceDir + vndk_version;
-}
+std::vector<std::pair<std::string, std::string>> fs_mgr_get_vendor_overlay_dirs(
+        const std::string& vndk_version) {
+    std::vector<std::pair<std::string, std::string>> vendor_overlay_dirs;
+    for (const auto& vendor_overlay_source : kVendorOverlaySourceDirs) {
+        const auto overlay_top = vendor_overlay_source + vndk_version;
+        std::unique_ptr<DIR, decltype(&closedir)> vendor_overlay_top(opendir(overlay_top.c_str()),
+                                                                     closedir);
+        if (!vendor_overlay_top) continue;
 
-std::vector<std::string> fs_mgr_get_vendor_overlay_dirs(const std::string& overlay_top) {
-    std::vector<std::string> vendor_overlay_dirs;
-    std::unique_ptr<DIR, decltype(&closedir)> vendor_overlay_top(opendir(overlay_top.c_str()),
-                                                                 closedir);
-    if (!vendor_overlay_top) return vendor_overlay_dirs;
+        // Vendor overlay root for current vendor version found!
+        LINFO << "vendor overlay root: " << overlay_top;
 
-    // Vendor overlay root for current vendor version found!
-    LINFO << "vendor overlay root: " << overlay_top;
-    struct dirent* dp;
-    while ((dp = readdir(vendor_overlay_top.get())) != nullptr) {
-        if (dp->d_type != DT_DIR || dp->d_name[0] == '.') {
-            continue;
+        struct dirent* dp;
+        while ((dp = readdir(vendor_overlay_top.get())) != nullptr) {
+            if (dp->d_type != DT_DIR || dp->d_name[0] == '.') {
+                continue;
+            }
+            vendor_overlay_dirs.emplace_back(overlay_top, dp->d_name);
         }
-        vendor_overlay_dirs.push_back(dp->d_name);
     }
-
     return vendor_overlay_dirs;
 }
 
-bool fs_mgr_vendor_overlay_mount(const std::string& overlay_top, const std::string& mount_point) {
-    const auto vendor_mount_point = kVendorTopDir + mount_point;
+bool fs_mgr_vendor_overlay_mount(const std::pair<std::string, std::string>& mount_point) {
+    const auto [overlay_top, mount_dir] = mount_point;
+    const auto vendor_mount_point = kVendorTopDir + mount_dir;
     LINFO << "vendor overlay mount on " << vendor_mount_point;
 
     const auto target_context = fs_mgr_get_context(vendor_mount_point);
@@ -79,7 +78,7 @@
         PERROR << " failed: cannot find the target vendor mount point";
         return false;
     }
-    const auto source_directory = overlay_top + "/" + mount_point;
+    const auto source_directory = overlay_top + "/" + mount_dir;
     const auto source_context = fs_mgr_get_context(source_directory);
     if (target_context != source_context) {
         LERROR << " failed: source and target contexts do not match (source:" << source_context
@@ -112,22 +111,25 @@
 // To read the properties, vendor overlay must be mounted at the second stage, right
 // after "property_load_boot_defaults()" is called.
 bool fs_mgr_vendor_overlay_mount_all() {
-    const auto overlay_top = fs_mgr_get_vendor_overlay_top_dir();
-    if (overlay_top.empty()) {
+    // To read the property, it must be called at the second init stage after the default
+    // properties are loaded.
+    static const auto vndk_version = android::base::GetProperty(kVndkVersionPropertyName, "");
+    if (vndk_version.empty()) {
         LINFO << "vendor overlay: vndk version not defined";
         return false;
     }
-    const auto vendor_overlay_dirs = fs_mgr_get_vendor_overlay_dirs(overlay_top);
+
+    const auto vendor_overlay_dirs = fs_mgr_get_vendor_overlay_dirs(vndk_version);
     if (vendor_overlay_dirs.empty()) return true;
     if (fs_mgr_overlayfs_valid() == OverlayfsValidResult::kNotSupported) {
         LINFO << "vendor overlay: kernel does not support overlayfs";
         return false;
     }
 
-    // Mount each directory in /system/vendor_overlay/<ver> on /vendor
+    // Mount each directory in /(system|product)/vendor_overlay/<ver> on /vendor
     auto ret = true;
     for (const auto& vendor_overlay_dir : vendor_overlay_dirs) {
-        if (!fs_mgr_vendor_overlay_mount(overlay_top, vendor_overlay_dir)) {
+        if (!fs_mgr_vendor_overlay_mount(vendor_overlay_dir)) {
             ret = false;
         }
     }
diff --git a/init/Android.mk b/init/Android.mk
index dc46d21..ee030c7 100644
--- a/init/Android.mk
+++ b/init/Android.mk
@@ -92,6 +92,7 @@
 LOCAL_SANITIZE := signed-integer-overflow
 # First stage init is weird: it may start without stdout/stderr, and no /proc.
 LOCAL_NOSANITIZE := hwaddress
+LOCAL_XOM := false
 include $(BUILD_EXECUTABLE)
 
 include $(CLEAR_VARS)
diff --git a/libziparchive/Android.bp b/libziparchive/Android.bp
index 2095189..9538bba 100644
--- a/libziparchive/Android.bp
+++ b/libziparchive/Android.bp
@@ -125,6 +125,7 @@
             enabled: true,
         },
     },
+    test_suites: ["device-tests"],
 }
 
 // Performance benchmarks.
diff --git a/rootdir/ueventd.rc b/rootdir/ueventd.rc
index 2f85dec..d47506c 100644
--- a/rootdir/ueventd.rc
+++ b/rootdir/ueventd.rc
@@ -72,7 +72,7 @@
 /dev/diag_arm9            0660   radio      radio
 /dev/ttyMSM0              0600   bluetooth  bluetooth
 /dev/uhid                 0660   uhid       uhid
-/dev/uinput               0660   system     bluetooth
+/dev/uinput               0660   uhid       uhid
 /dev/alarm                0664   system     radio
 /dev/rtc0                 0640   system     system
 /dev/tty0                 0660   root       system