Merge "fs_mgr: Update for new libavb API."
diff --git a/adb/client/usb_dispatch.cpp b/adb/client/usb_dispatch.cpp
index c4eed78..ce57731 100644
--- a/adb/client/usb_dispatch.cpp
+++ b/adb/client/usb_dispatch.cpp
@@ -30,6 +30,8 @@
 void usb_cleanup() {
     if (should_use_libusb()) {
         libusb::usb_cleanup();
+    } else {
+        native::usb_cleanup();
     }
 }
 
diff --git a/adb/client/usb_linux.cpp b/adb/client/usb_linux.cpp
index f9ba7cb..a7df0ed 100644
--- a/adb/client/usb_linux.cpp
+++ b/adb/client/usb_linux.cpp
@@ -598,4 +598,7 @@
 
     std::thread(device_poll_thread).detach();
 }
+
+void usb_cleanup() {}
+
 } // namespace native
diff --git a/adb/client/usb_osx.cpp b/adb/client/usb_osx.cpp
index e366754..4e1480f 100644
--- a/adb/client/usb_osx.cpp
+++ b/adb/client/usb_osx.cpp
@@ -430,7 +430,7 @@
     VLOG(USB) << "RunLoopThread done";
 }
 
-static void usb_cleanup() NO_THREAD_SAFETY_ANALYSIS {
+void usb_cleanup() NO_THREAD_SAFETY_ANALYSIS {
     VLOG(USB) << "usb_cleanup";
     // Wait until usb operations in RunLoopThread finish, and prevent further operations.
     operate_device_lock.lock();
@@ -440,8 +440,6 @@
 void usb_init() {
     static bool initialized = false;
     if (!initialized) {
-        atexit(usb_cleanup);
-
         usb_inited_flag = false;
 
         std::thread(RunLoopThread).detach();
diff --git a/adb/daemon/main.cpp b/adb/daemon/main.cpp
index a6d43ea..1c94298 100644
--- a/adb/daemon/main.cpp
+++ b/adb/daemon/main.cpp
@@ -107,10 +107,10 @@
     // AID_SDCARD_RW to allow writing to the SD card
     // AID_NET_BW_STATS to read out qtaguid statistics
     // AID_READPROC for reading /proc entries across UID boundaries
-    gid_t groups[] = {AID_ADB,      AID_LOG,       AID_INPUT,
-                      AID_INET,     AID_NET_BT,    AID_NET_BT_ADMIN,
-                      AID_SDCARD_R, AID_SDCARD_RW, AID_NET_BW_STATS,
-                      AID_READPROC};
+    // AID_UHID for using 'hid' command to read/write to /dev/uhid
+    gid_t groups[] = {AID_ADB,          AID_LOG,          AID_INPUT,    AID_INET,
+                      AID_NET_BT,       AID_NET_BT_ADMIN, AID_SDCARD_R, AID_SDCARD_RW,
+                      AID_NET_BW_STATS, AID_READPROC,     AID_UHID};
     minijail_set_supplementary_gids(jail.get(), arraysize(groups), groups);
 
     // Don't listen on a port (default 5037) if running in secure mode.
diff --git a/debuggerd/libdebuggerd/arm/machine.cpp b/debuggerd/libdebuggerd/arm/machine.cpp
index 78c2306..ac833ae 100644
--- a/debuggerd/libdebuggerd/arm/machine.cpp
+++ b/debuggerd/libdebuggerd/arm/machine.cpp
@@ -48,6 +48,21 @@
   }
 }
 
+#define DUMP_GP_REGISTERS(log, reg_prefix)                                             \
+  _LOG(log, logtype::REGISTERS, "    r0 %08x  r1 %08x  r2 %08x  r3 %08x\n",            \
+       static_cast<uint32_t>(reg_prefix##r0), static_cast<uint32_t>(reg_prefix##r1),   \
+       static_cast<uint32_t>(reg_prefix##r2), static_cast<uint32_t>(reg_prefix##r3));  \
+  _LOG(log, logtype::REGISTERS, "    r4 %08x  r5 %08x  r6 %08x  r7 %08x\n",            \
+       static_cast<uint32_t>(reg_prefix##r4), static_cast<uint32_t>(reg_prefix##r5),   \
+       static_cast<uint32_t>(reg_prefix##r6), static_cast<uint32_t>(reg_prefix##r7));  \
+  _LOG(log, logtype::REGISTERS, "    r8 %08x  r9 %08x  sl %08x  fp %08x\n",            \
+       static_cast<uint32_t>(reg_prefix##r8), static_cast<uint32_t>(reg_prefix##r9),   \
+       static_cast<uint32_t>(reg_prefix##r10), static_cast<uint32_t>(reg_prefix##fp)); \
+  _LOG(log, logtype::REGISTERS, "    ip %08x  sp %08x  lr %08x  pc %08x  cpsr %08x\n", \
+       static_cast<uint32_t>(reg_prefix##ip), static_cast<uint32_t>(reg_prefix##sp),   \
+       static_cast<uint32_t>(reg_prefix##lr), static_cast<uint32_t>(reg_prefix##pc),   \
+       static_cast<uint32_t>(reg_prefix##cpsr))
+
 void dump_registers(log_t* log, pid_t tid) {
   pt_regs r;
   if (ptrace(PTRACE_GETREGS, tid, 0, &r)) {
@@ -55,19 +70,7 @@
     return;
   }
 
-  _LOG(log, logtype::REGISTERS, "    r0 %08x  r1 %08x  r2 %08x  r3 %08x\n",
-       static_cast<uint32_t>(r.ARM_r0), static_cast<uint32_t>(r.ARM_r1),
-       static_cast<uint32_t>(r.ARM_r2), static_cast<uint32_t>(r.ARM_r3));
-  _LOG(log, logtype::REGISTERS, "    r4 %08x  r5 %08x  r6 %08x  r7 %08x\n",
-       static_cast<uint32_t>(r.ARM_r4), static_cast<uint32_t>(r.ARM_r5),
-       static_cast<uint32_t>(r.ARM_r6), static_cast<uint32_t>(r.ARM_r7));
-  _LOG(log, logtype::REGISTERS, "    r8 %08x  r9 %08x  sl %08x  fp %08x\n",
-       static_cast<uint32_t>(r.ARM_r8), static_cast<uint32_t>(r.ARM_r9),
-       static_cast<uint32_t>(r.ARM_r10), static_cast<uint32_t>(r.ARM_fp));
-  _LOG(log, logtype::REGISTERS, "    ip %08x  sp %08x  lr %08x  pc %08x  cpsr %08x\n",
-       static_cast<uint32_t>(r.ARM_ip), static_cast<uint32_t>(r.ARM_sp),
-       static_cast<uint32_t>(r.ARM_lr), static_cast<uint32_t>(r.ARM_pc),
-       static_cast<uint32_t>(r.ARM_cpsr));
+  DUMP_GP_REGISTERS(log, r.ARM_);
 
   user_vfp vfp_regs;
   if (ptrace(PTRACE_GETVFPREGS, tid, 0, &vfp_regs)) {
@@ -81,3 +84,7 @@
   }
   _LOG(log, logtype::FP_REGISTERS, "    scr %08lx\n", vfp_regs.fpscr);
 }
+
+void dump_registers(log_t* log, const ucontext_t* uc) {
+  DUMP_GP_REGISTERS(log, uc->uc_mcontext.arm_);
+}
diff --git a/debuggerd/libdebuggerd/arm64/machine.cpp b/debuggerd/libdebuggerd/arm64/machine.cpp
index e7bf79a..fa73c99a 100644
--- a/debuggerd/libdebuggerd/arm64/machine.cpp
+++ b/debuggerd/libdebuggerd/arm64/machine.cpp
@@ -52,6 +52,17 @@
   }
 }
 
+#define DUMP_GP_REGISTERS(log)                                                                   \
+  for (int i = 0; i < 28; i += 4) {                                                              \
+    const char* fmt = "    x%-2d  %016llx  x%-2d  %016llx  x%-2d  %016llx  x%-2d  %016llx\n";    \
+    _LOG(log, logtype::REGISTERS, fmt, i, r.regs[i], i + 1, r.regs[i + 1], i + 2, r.regs[i + 2], \
+         i + 3, r.regs[i + 3]);                                                                  \
+  }                                                                                              \
+  _LOG(log, logtype::REGISTERS, "    x28  %016llx  x29  %016llx  x30  %016llx\n", r.regs[28],    \
+       r.regs[29], r.regs[30]);                                                                  \
+  _LOG(log, logtype::REGISTERS, "    sp   %016llx  pc   %016llx  pstate %016llx\n", r.sp, r.pc,  \
+       r.pstate)
+
 void dump_registers(log_t* log, pid_t tid) {
   struct user_pt_regs r;
   struct iovec io;
@@ -63,20 +74,7 @@
     return;
   }
 
-  for (int i = 0; i < 28; i += 4) {
-    _LOG(log, logtype::REGISTERS,
-         "    x%-2d  %016llx  x%-2d  %016llx  x%-2d  %016llx  x%-2d  %016llx\n",
-         i, r.regs[i],
-         i+1, r.regs[i+1],
-         i+2, r.regs[i+2],
-         i+3, r.regs[i+3]);
-  }
-
-  _LOG(log, logtype::REGISTERS, "    x28  %016llx  x29  %016llx  x30  %016llx\n",
-       r.regs[28], r.regs[29], r.regs[30]);
-
-  _LOG(log, logtype::REGISTERS, "    sp   %016llx  pc   %016llx  pstate %016llx\n",
-       r.sp, r.pc, r.pstate);
+  DUMP_GP_REGISTERS(log);
 
   struct user_fpsimd_state f;
   io.iov_base = &f;
@@ -99,3 +97,8 @@
   }
   _LOG(log, logtype::FP_REGISTERS, "    fpsr %08x  fpcr %08x\n", f.fpsr, f.fpcr);
 }
+
+void dump_registers(log_t* log, const ucontext_t* ucontext) {
+  const mcontext_t& r = ucontext->uc_mcontext;
+  DUMP_GP_REGISTERS(log);
+}
diff --git a/debuggerd/libdebuggerd/include/machine.h b/debuggerd/libdebuggerd/include/machine.h
index e65b147..5e56682 100644
--- a/debuggerd/libdebuggerd/include/machine.h
+++ b/debuggerd/libdebuggerd/include/machine.h
@@ -25,5 +25,6 @@
 
 void dump_memory_and_code(log_t* log, Backtrace* backtrace);
 void dump_registers(log_t* log, pid_t tid);
+void dump_registers(log_t* log, const ucontext_t* uc);
 
 #endif // _DEBUGGERD_MACHINE_H
diff --git a/debuggerd/libdebuggerd/tombstone.cpp b/debuggerd/libdebuggerd/tombstone.cpp
index 0c38449..edc7be5 100644
--- a/debuggerd/libdebuggerd/tombstone.cpp
+++ b/debuggerd/libdebuggerd/tombstone.cpp
@@ -470,6 +470,11 @@
   }
 }
 
+// Weak noop implementation, real implementations are in <arch>/machine.cpp.
+__attribute__((weak)) void dump_registers(log_t* log, const ucontext_t*) {
+  _LOG(log, logtype::REGISTERS, "    register dumping unimplemented on this architecture");
+}
+
 static void dump_thread(log_t* log, pid_t pid, pid_t tid, const std::string& process_name,
                         const std::string& thread_name, BacktraceMap* map,
                         uintptr_t abort_msg_address, bool primary_thread) {
@@ -749,11 +754,15 @@
   read_with_default("/proc/self/comm", thread_name, sizeof(thread_name), "<unknown>");
   read_with_default("/proc/self/cmdline", process_name, sizeof(process_name), "<unknown>");
 
+  _LOG(&log, logtype::HEADER, "*** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***\n");
+  dump_header_info(&log);
   dump_thread_info(&log, pid, tid, thread_name, process_name);
   dump_signal_info(&log, siginfo);
 
   std::unique_ptr<Backtrace> backtrace(Backtrace::Create(pid, tid));
   dump_abort_message(backtrace.get(), &log, abort_msg_address);
+  dump_registers(&log, ucontext);
+
   // TODO: Dump registers from the ucontext.
   if (backtrace->Unwind(0, ucontext)) {
     dump_backtrace_and_stack(backtrace.get(), &log);
diff --git a/fastboot/fastboot.cpp b/fastboot/fastboot.cpp
index f10b9ce..8a6877a 100644
--- a/fastboot/fastboot.cpp
+++ b/fastboot/fastboot.cpp
@@ -135,7 +135,7 @@
     return android::base::StringPrintf("%s/%s", dir, img_name);
 }
 
-std::string find_item(const std::string& item) {
+static std::string find_item(const std::string& item) {
     for (size_t i = 0; i < arraysize(images); ++i) {
         if (images[i].nickname && item == images[i].nickname) {
             return find_item_given_name(images[i].img_name);
@@ -1262,12 +1262,10 @@
 static void do_oem_command(std::vector<std::string>* args) {
     if (args->empty()) syntax_error("empty oem command");
 
-    std::string command;
+    std::string command("oem");
     while (!args->empty()) {
-        if (!command.empty()) command += ' ';
-        command += next_arg(args);
+        command += " " + next_arg(args);
     }
-
     fb_queue_command(command.c_str(), "");
 }
 
diff --git a/init/Android.mk b/init/Android.mk
index 537bbee..d25e119 100644
--- a/init/Android.mk
+++ b/init/Android.mk
@@ -61,6 +61,8 @@
 endif
 
 include $(CLEAR_VARS)
+# b/38002385, work around clang-tidy segmentation fault.
+LOCAL_TIDY_CHECKS := -misc-forwarding-reference-overload
 LOCAL_CPPFLAGS := $(init_cflags)
 LOCAL_SRC_FILES:= \
     action.cpp \
@@ -82,6 +84,8 @@
 include $(BUILD_STATIC_LIBRARY)
 
 include $(CLEAR_VARS)
+# b/38002385, work around clang-tidy segmentation fault.
+LOCAL_TIDY_CHECKS := -misc-forwarding-reference-overload
 LOCAL_CPPFLAGS := $(init_cflags)
 LOCAL_SRC_FILES:= \
     bootchart.cpp \
@@ -139,6 +143,8 @@
 # Unit tests.
 # =========================================================
 include $(CLEAR_VARS)
+# b/38002385, work around clang-tidy segmentation fault.
+LOCAL_TIDY_CHECKS := -misc-forwarding-reference-overload
 LOCAL_MODULE := init_tests
 LOCAL_SRC_FILES := \
     devices_test.cpp \
diff --git a/libcutils/include/private/android_filesystem_config.h b/libcutils/include/private/android_filesystem_config.h
index fdead23..48b50a5 100644
--- a/libcutils/include/private/android_filesystem_config.h
+++ b/libcutils/include/private/android_filesystem_config.h
@@ -152,6 +152,7 @@
 #define AID_NET_BW_ACCT 3007  /* change bandwidth statistics accounting */
 #define AID_READPROC 3009     /* Allow /proc read access */
 #define AID_WAKELOCK 3010     /* Allow system wakelock read/write access */
+#define AID_UHID 3011         /* Allow read/write to /dev/uhid node */
 
 /* The range 5000-5999 is also reserved for OEM, and must never be used here. */
 #define AID_OEM_RESERVED_2_START 5000
diff --git a/libutils/FileMap.cpp b/libutils/FileMap.cpp
index 1afa1ec..3c4d81c 100644
--- a/libutils/FileMap.cpp
+++ b/libutils/FileMap.cpp
@@ -48,8 +48,16 @@
 
 // Constructor.  Create an empty object.
 FileMap::FileMap(void)
-    : mFileName(NULL), mBasePtr(NULL), mBaseLength(0),
-      mDataPtr(NULL), mDataLength(0)
+    : mFileName(NULL),
+      mBasePtr(NULL),
+      mBaseLength(0),
+      mDataPtr(NULL),
+      mDataLength(0)
+#if defined(__MINGW32__)
+      ,
+      mFileHandle(INVALID_HANDLE_VALUE),
+      mFileMapping(NULL)
+#endif
 {
 }
 
@@ -65,8 +73,8 @@
     other.mBasePtr = NULL;
     other.mDataPtr = NULL;
 #if defined(__MINGW32__)
-    other.mFileHandle = 0;
-    other.mFileMapping = 0;
+    other.mFileHandle = INVALID_HANDLE_VALUE;
+    other.mFileMapping = NULL;
 #endif
 }
 
@@ -84,8 +92,8 @@
 #if defined(__MINGW32__)
     mFileHandle = other.mFileHandle;
     mFileMapping = other.mFileMapping;
-    other.mFileHandle = 0;
-    other.mFileMapping = 0;
+    other.mFileHandle = INVALID_HANDLE_VALUE;
+    other.mFileMapping = NULL;
 #endif
     return *this;
 }
@@ -101,7 +109,7 @@
         ALOGD("UnmapViewOfFile(%p) failed, error = %lu\n", mBasePtr,
               GetLastError() );
     }
-    if (mFileMapping != INVALID_HANDLE_VALUE) {
+    if (mFileMapping != NULL) {
         CloseHandle(mFileMapping);
     }
 #else
@@ -156,7 +164,7 @@
         ALOGE("MapViewOfFile(%" PRId64 ", %zu) failed with error %lu\n",
               adjOffset, adjLength, GetLastError() );
         CloseHandle(mFileMapping);
-        mFileMapping = INVALID_HANDLE_VALUE;
+        mFileMapping = NULL;
         return false;
     }
 #else // !defined(__MINGW32__)
diff --git a/logcat/tests/logcat_test.cpp b/logcat/tests/logcat_test.cpp
index 9c07472..786fb14 100644
--- a/logcat/tests/logcat_test.cpp
+++ b/logcat/tests/logcat_test.cpp
@@ -31,6 +31,7 @@
 #include <string>
 
 #include <android-base/file.h>
+#include <android-base/stringprintf.h>
 #include <gtest/gtest.h>
 #include <log/event_tag_map.h>
 #include <log/log.h>
@@ -80,8 +81,13 @@
     logcat_define(ctx);
 
 #undef LOG_TAG
-#define LOG_TAG "inject"
-    RLOGE(logcat_executable ".buckets");
+#define LOG_TAG "inject.buckets"
+    // inject messages into radio, system, main and events buffers to
+    // ensure that we see all the begin[] bucket messages.
+    RLOGE(logcat_executable);
+    SLOGE(logcat_executable);
+    ALOGE(logcat_executable);
+    __android_log_bswrite(0, logcat_executable ".inject.buckets");
     rest();
 
     ASSERT_TRUE(NULL !=
@@ -107,32 +113,45 @@
 
     logcat_pclose(ctx, fp);
 
-    EXPECT_EQ(15, ids);
+    EXPECT_EQ(ids, 15);
 
-    EXPECT_EQ(4, count);
+    EXPECT_EQ(count, 4);
 }
 
 TEST(logcat, event_tag_filter) {
     FILE* fp;
     logcat_define(ctx);
 
-    ASSERT_TRUE(NULL !=
-                (fp = logcat_popen(ctx, logcat_executable
-                                   " -b events -d -s auditd "
-                                   "am_proc_start am_pss am_proc_bound "
-                                   "dvm_lock_sample am_wtf 2>/dev/null")));
+#undef LOG_TAG
+#define LOG_TAG "inject.filter"
+    // inject messages into radio, system and main buffers
+    // with our unique log tag to test logcat filter.
+    RLOGE(logcat_executable);
+    SLOGE(logcat_executable);
+    ALOGE(logcat_executable);
+    rest();
+
+    std::string command = android::base::StringPrintf(
+        logcat_executable
+        " -b radio -b system -b main --pid=%d -d -s inject.filter 2>/dev/null",
+        getpid());
+    ASSERT_TRUE(NULL != (fp = logcat_popen(ctx, command.c_str())));
 
     char buffer[BIG_BUFFER];
 
     int count = 0;
 
     while (fgets(buffer, sizeof(buffer), fp)) {
-        ++count;
+        if (strncmp(begin, buffer, sizeof(begin) - 1)) ++count;
     }
 
     logcat_pclose(ctx, fp);
 
-    EXPECT_LT(4, count);
+    // logcat, liblogcat and logcatd test instances result in the progression
+    // of 3, 6 and 9 for our counts as each round is performed.
+    EXPECT_GE(count, 3);
+    EXPECT_LE(count, 9);
+    EXPECT_EQ(count % 3, 0);
 }
 
 // If there is not enough background noise in the logs, then spam the logs to
@@ -376,7 +395,7 @@
 
     } while ((count < 10) && --tries && inject(10 - count));
 
-    EXPECT_EQ(10, count);  // We want _some_ history, too small, falses below
+    EXPECT_EQ(count, 10);  // We want _some_ history, too small, falses below
     EXPECT_TRUE(last_timestamp != NULL);
     EXPECT_TRUE(first_timestamp != NULL);
     EXPECT_TRUE(second_timestamp != NULL);
@@ -701,9 +720,9 @@
 
     pclose(fp);
 
-    EXPECT_LE(2, count);
+    EXPECT_GE(count, 2);
 
-    EXPECT_EQ(1, signals);
+    EXPECT_EQ(signals, 1);
 }
 
 static void caught_blocking_tail(int signum) {
@@ -771,9 +790,9 @@
 
     pclose(fp);
 
-    EXPECT_LE(2, count);
+    EXPECT_GE(count, 2);
 
-    EXPECT_EQ(1, signals);
+    EXPECT_EQ(signals, 1);
 }
 #endif
 
@@ -881,7 +900,7 @@
             ADD_FAILURE();
         }
         pclose(fp);
-        EXPECT_EQ(11, log_file_count);
+        EXPECT_EQ(log_file_count, 11);
     }
     snprintf(command, sizeof(command), "rm -rf %s", tmp_out_dir);
     EXPECT_FALSE(IsFalse(system(command), command));
@@ -1134,17 +1153,17 @@
     char tmp_out_dir[strlen(tmp_out_dir_form) + 1];
     ASSERT_TRUE(NULL != mkdtemp(strcpy(tmp_out_dir, tmp_out_dir_form)));
 
-    EXPECT_EQ(34, logrotate_count_id(logcat_cmd, tmp_out_dir));
-    EXPECT_EQ(34, logrotate_count_id(logcat_short_cmd, tmp_out_dir));
+    EXPECT_EQ(logrotate_count_id(logcat_cmd, tmp_out_dir), 34);
+    EXPECT_EQ(logrotate_count_id(logcat_short_cmd, tmp_out_dir), 34);
 
     char id_file[strlen(tmp_out_dir_form) + strlen(log_filename) + 5];
     snprintf(id_file, sizeof(id_file), "%s/%s.id", tmp_out_dir, log_filename);
     if (getuid() != 0) {
         chmod(id_file, 0);
-        EXPECT_EQ(34, logrotate_count_id(logcat_short_cmd, tmp_out_dir));
+        EXPECT_EQ(logrotate_count_id(logcat_short_cmd, tmp_out_dir), 34);
     }
     unlink(id_file);
-    EXPECT_EQ(34, logrotate_count_id(logcat_short_cmd, tmp_out_dir));
+    EXPECT_EQ(logrotate_count_id(logcat_short_cmd, tmp_out_dir), 34);
 
     FILE* fp = fopen(id_file, "w");
     if (fp) {
@@ -1159,9 +1178,9 @@
     }
 
     int new_signature;
-    EXPECT_LE(
-        2, (new_signature = logrotate_count_id(logcat_short_cmd, tmp_out_dir)));
-    EXPECT_GT(34, new_signature);
+    EXPECT_GE(
+        (new_signature = logrotate_count_id(logcat_short_cmd, tmp_out_dir)), 2);
+    EXPECT_LT(new_signature, 34);
 
     static const char cleanup_cmd[] = "rm -rf %s";
     char command[strlen(cleanup_cmd) + strlen(tmp_out_dir_form)];
@@ -1302,10 +1321,10 @@
 
     pclose(fp);
 
-    EXPECT_LE(1, count);
-    EXPECT_EQ(1, minus_g);
+    EXPECT_GE(count, 1);
+    EXPECT_EQ(minus_g, 1);
 
-    EXPECT_EQ(1, signals);
+    EXPECT_EQ(signals, 1);
 }
 #endif
 
@@ -1560,7 +1579,7 @@
         ctx << theAnswer;
         // crafted to rest at least once after, and rest between retries.
         for (ret = -EBUSY; ret == -EBUSY; rest()) ret = ctx.write();
-        EXPECT_LE(0, ret);
+        EXPECT_GE(ret, 0);
         EXPECT_TRUE(
             End_to_End(hhgtg.tagStr, "to life the universe etc=%s", theAnswer));
     }
@@ -1572,7 +1591,7 @@
             android_log_event_list ctx(sync.tagNo);
             ctx << id << (int32_t)42 << (int32_t)-1 << (int32_t)0;
             for (ret = -EBUSY; ret == -EBUSY; rest()) ret = ctx.write();
-            EXPECT_LE(0, ret);
+            EXPECT_GE(ret, 0);
             EXPECT_TRUE(End_to_End(sync.tagStr,
                                    "[id=%s,event=42,source=-1,account=0]", id));
         }
@@ -1582,7 +1601,7 @@
             android_log_event_list ctx(sync.tagNo);
             ctx << id << (int32_t)43 << (int64_t)-1 << (int32_t)0;
             for (ret = -EBUSY; ret == -EBUSY; rest()) ret = ctx.write();
-            EXPECT_LE(0, ret);
+            EXPECT_GE(ret, 0);
             EXPECT_TRUE(End_to_End(sync.tagStr, "[id=%s,event=43,-1,0]", id));
         }
 
@@ -1591,7 +1610,7 @@
             android_log_event_list ctx(sync.tagNo);
             ctx << id << (int32_t)44 << (int32_t)-1 << (int64_t)0;
             for (ret = -EBUSY; ret == -EBUSY; rest()) ret = ctx.write();
-            EXPECT_LE(0, ret);
+            EXPECT_GE(ret, 0);
             fprintf(stderr, "Expect a \"Closest match\" message\n");
             EXPECT_FALSE(End_to_End(
                 sync.tagStr, "[id=%s,event=44,source=-1,account=0]", id));
@@ -1604,7 +1623,7 @@
             android_log_event_list ctx(sync.tagNo);
             ctx << (uint64_t)30 << (int32_t)2;
             for (ret = -EBUSY; ret == -EBUSY; rest()) ret = ctx.write();
-            EXPECT_LE(0, ret);
+            EXPECT_GE(ret, 0);
             EXPECT_TRUE(
                 End_to_End(sync.tagStr, "[aggregation time=30ms,count=2]"));
         }
@@ -1613,7 +1632,7 @@
             android_log_event_list ctx(sync.tagNo);
             ctx << (uint64_t)31570 << (int32_t)911;
             for (ret = -EBUSY; ret == -EBUSY; rest()) ret = ctx.write();
-            EXPECT_LE(0, ret);
+            EXPECT_GE(ret, 0);
             EXPECT_TRUE(
                 End_to_End(sync.tagStr, "[aggregation time=31.57s,count=911]"));
         }
@@ -1625,7 +1644,7 @@
             android_log_event_list ctx(sync.tagNo);
             ctx << (uint32_t)512;
             for (ret = -EBUSY; ret == -EBUSY; rest()) ret = ctx.write();
-            EXPECT_LE(0, ret);
+            EXPECT_GE(ret, 0);
             EXPECT_TRUE(End_to_End(sync.tagStr, "current=512B"));
         }
 
@@ -1633,7 +1652,7 @@
             android_log_event_list ctx(sync.tagNo);
             ctx << (uint32_t)3072;
             for (ret = -EBUSY; ret == -EBUSY; rest()) ret = ctx.write();
-            EXPECT_LE(0, ret);
+            EXPECT_GE(ret, 0);
             EXPECT_TRUE(End_to_End(sync.tagStr, "current=3KB"));
         }
 
@@ -1641,7 +1660,7 @@
             android_log_event_list ctx(sync.tagNo);
             ctx << (uint32_t)2097152;
             for (ret = -EBUSY; ret == -EBUSY; rest()) ret = ctx.write();
-            EXPECT_LE(0, ret);
+            EXPECT_GE(ret, 0);
             EXPECT_TRUE(End_to_End(sync.tagStr, "current=2MB"));
         }
 
@@ -1649,7 +1668,7 @@
             android_log_event_list ctx(sync.tagNo);
             ctx << (uint32_t)2097153;
             for (ret = -EBUSY; ret == -EBUSY; rest()) ret = ctx.write();
-            EXPECT_LE(0, ret);
+            EXPECT_GE(ret, 0);
             EXPECT_TRUE(End_to_End(sync.tagStr, "current=2097153B"));
         }
 
@@ -1657,7 +1676,7 @@
             android_log_event_list ctx(sync.tagNo);
             ctx << (uint32_t)1073741824;
             for (ret = -EBUSY; ret == -EBUSY; rest()) ret = ctx.write();
-            EXPECT_LE(0, ret);
+            EXPECT_GE(ret, 0);
             EXPECT_TRUE(End_to_End(sync.tagStr, "current=1GB"));
         }
 
@@ -1665,7 +1684,7 @@
             android_log_event_list ctx(sync.tagNo);
             ctx << (uint32_t)3221225472;  // 3MB, but on purpose overflowed
             for (ret = -EBUSY; ret == -EBUSY; rest()) ret = ctx.write();
-            EXPECT_LE(0, ret);
+            EXPECT_GE(ret, 0);
             EXPECT_TRUE(End_to_End(sync.tagStr, "current=-1GB"));
         }
     }
@@ -1674,7 +1693,7 @@
         static const struct tag sync = { 27501, "notification_panel_hidden" };
         android_log_event_list ctx(sync.tagNo);
         for (ret = -EBUSY; ret == -EBUSY; rest()) ret = ctx.write();
-        EXPECT_LE(0, ret);
+        EXPECT_GE(ret, 0);
         EXPECT_TRUE(End_to_End(sync.tagStr, ""));
     }
 
@@ -1694,28 +1713,28 @@
             android_log_event_list ctx(sync.tagNo);
             ctx << (uint32_t)7;
             for (ret = -EBUSY; ret == -EBUSY; rest()) ret = ctx.write();
-            EXPECT_LE(0, ret);
+            EXPECT_GE(ret, 0);
             EXPECT_TRUE(End_to_End(sync.tagStr, "new=7s"));
         }
         {
             android_log_event_list ctx(sync.tagNo);
             ctx << (uint32_t)62;
             for (ret = -EBUSY; ret == -EBUSY; rest()) ret = ctx.write();
-            EXPECT_LE(0, ret);
+            EXPECT_GE(ret, 0);
             EXPECT_TRUE(End_to_End(sync.tagStr, "new=1:02"));
         }
         {
             android_log_event_list ctx(sync.tagNo);
             ctx << (uint32_t)3673;
             for (ret = -EBUSY; ret == -EBUSY; rest()) ret = ctx.write();
-            EXPECT_LE(0, ret);
+            EXPECT_GE(ret, 0);
             EXPECT_TRUE(End_to_End(sync.tagStr, "new=1:01:13"));
         }
         {
             android_log_event_list ctx(sync.tagNo);
             ctx << (uint32_t)(86400 + 7200 + 180 + 58);
             for (ret = -EBUSY; ret == -EBUSY; rest()) ret = ctx.write();
-            EXPECT_LE(0, ret);
+            EXPECT_GE(ret, 0);
             EXPECT_TRUE(End_to_End(sync.tagStr, "new=1d 2:03:58"));
         }
     }
@@ -1756,7 +1775,7 @@
 
 TEST(logcat, help) {
     size_t logcatHelpTextSize = commandOutputSize(logcat_executable " -h 2>&1");
-    EXPECT_LT(4096UL, logcatHelpTextSize);
+    EXPECT_GT(logcatHelpTextSize, 4096UL);
     size_t logcatLastHelpTextSize =
         commandOutputSize(logcat_executable " -L -h 2>&1");
 #ifdef USING_LOGCAT_EXECUTABLE_DEFAULT  // logcat and liblogcat
diff --git a/logd/LogBuffer.h b/logd/LogBuffer.h
index e597754..f0d6fcb 100644
--- a/logd/LogBuffer.h
+++ b/logd/LogBuffer.h
@@ -159,9 +159,12 @@
     const char* pidToName(pid_t pid) {
         return stats.pidToName(pid);
     }
-    uid_t pidToUid(pid_t pid) {
+    virtual uid_t pidToUid(pid_t pid) override {
         return stats.pidToUid(pid);
     }
+    virtual pid_t tidToPid(pid_t tid) override {
+        return stats.tidToPid(tid);
+    }
     const char* uidToName(uid_t uid) {
         return stats.uidToName(uid);
     }
diff --git a/logd/LogBufferInterface.cpp b/logd/LogBufferInterface.cpp
index 3cb2b89..4b6d363 100644
--- a/logd/LogBufferInterface.cpp
+++ b/logd/LogBufferInterface.cpp
@@ -15,8 +15,15 @@
  */
 
 #include "LogBufferInterface.h"
+#include "LogUtils.h"
 
 LogBufferInterface::LogBufferInterface() {
 }
 LogBufferInterface::~LogBufferInterface() {
-}
\ No newline at end of file
+}
+uid_t LogBufferInterface::pidToUid(pid_t pid) {
+    return android::pidToUid(pid);
+}
+pid_t LogBufferInterface::tidToPid(pid_t tid) {
+    return android::tidToPid(tid);
+}
diff --git a/logd/LogBufferInterface.h b/logd/LogBufferInterface.h
index 7d82b91..ff73a22 100644
--- a/logd/LogBufferInterface.h
+++ b/logd/LogBufferInterface.h
@@ -33,6 +33,9 @@
     virtual int log(log_id_t log_id, log_time realtime, uid_t uid, pid_t pid,
                     pid_t tid, const char* msg, unsigned short len) = 0;
 
+    virtual uid_t pidToUid(pid_t pid);
+    virtual pid_t tidToPid(pid_t tid);
+
    private:
     DISALLOW_COPY_AND_ASSIGN(LogBufferInterface);
 };
diff --git a/logd/LogListener.cpp b/logd/LogListener.cpp
index 3c0d08d..d2df68e 100644
--- a/logd/LogListener.cpp
+++ b/logd/LogListener.cpp
@@ -14,7 +14,9 @@
  * limitations under the License.
  */
 
+#include <ctype.h>
 #include <limits.h>
+#include <stdio.h>
 #include <sys/cdefs.h>
 #include <sys/prctl.h>
 #include <sys/socket.h>
@@ -72,8 +74,11 @@
         cmsg = CMSG_NXTHDR(&hdr, cmsg);
     }
 
+    struct ucred fake_cred;
     if (cred == NULL) {
-        return false;
+        cred = &fake_cred;
+        cred->pid = 0;
+        cred->uid = DEFAULT_OVERFLOWUID;
     }
 
     if (cred->uid == AID_LOGD) {
@@ -96,6 +101,27 @@
         return false;
     }
 
+    // Check credential validity, acquire corrected details if not supplied.
+    if (cred->pid == 0) {
+        cred->pid = logbuf ? logbuf->tidToPid(header->tid)
+                           : android::tidToPid(header->tid);
+        if (cred->pid == getpid()) {
+            // We expect that /proc/<tid>/ is accessible to self even without
+            // readproc group, so that we will always drop messages that come
+            // from any of our logd threads and their library calls.
+            return false;  // ignore self
+        }
+    }
+    if (cred->uid == DEFAULT_OVERFLOWUID) {
+        uid_t uid =
+            logbuf ? logbuf->pidToUid(cred->pid) : android::pidToUid(cred->pid);
+        if (uid == AID_LOGD) {
+            uid = logbuf ? logbuf->pidToUid(header->tid)
+                         : android::pidToUid(cred->pid);
+        }
+        if (uid != AID_LOGD) cred->uid = uid;
+    }
+
     char* msg = ((char*)buffer) + sizeof(android_log_header_t);
     n -= sizeof(android_log_header_t);
 
diff --git a/logd/LogListener.h b/logd/LogListener.h
index e16c5fb..a562a54 100644
--- a/logd/LogListener.h
+++ b/logd/LogListener.h
@@ -20,6 +20,16 @@
 #include <sysutils/SocketListener.h>
 #include "LogReader.h"
 
+// DEFAULT_OVERFLOWUID is defined in linux/highuid.h, which is not part of
+// the uapi headers for userspace to use.  This value is filled in on the
+// out-of-band socket credentials if the OS fails to find one available.
+// One of the causes of this is if SO_PASSCRED is set, all the packets before
+// that point will have this value.  We also use it in a fake credential if
+// no socket credentials are supplied.
+#ifndef DEFAULT_OVERFLOWUID
+#define DEFAULT_OVERFLOWUID 65534
+#endif
+
 class LogListener : public SocketListener {
     LogBufferInterface* logbuf;
     LogReader* reader;
diff --git a/logd/LogStatistics.cpp b/logd/LogStatistics.cpp
index d20d90e..af59ddc 100644
--- a/logd/LogStatistics.cpp
+++ b/logd/LogStatistics.cpp
@@ -14,6 +14,7 @@
  * limitations under the License.
  */
 
+#include <ctype.h>
 #include <fcntl.h>
 #include <inttypes.h>
 #include <pwd.h>
@@ -824,8 +825,10 @@
     FILE* fp = fopen(buffer, "r");
     if (fp) {
         while (fgets(buffer, sizeof(buffer), fp)) {
-            int uid;
-            if (sscanf(buffer, "Uid: %d", &uid) == 1) {
+            int uid = AID_LOGD;
+            char space = 0;
+            if ((sscanf(buffer, "Uid: %d%c", &uid, &space) == 2) &&
+                isspace(space)) {
                 fclose(fp);
                 return uid;
             }
@@ -834,12 +837,35 @@
     }
     return AID_LOGD;  // associate this with the logger
 }
+
+pid_t tidToPid(pid_t tid) {
+    char buffer[512];
+    snprintf(buffer, sizeof(buffer), "/proc/%u/status", tid);
+    FILE* fp = fopen(buffer, "r");
+    if (fp) {
+        while (fgets(buffer, sizeof(buffer), fp)) {
+            int pid = tid;
+            char space = 0;
+            if ((sscanf(buffer, "Tgid: %d%c", &pid, &space) == 2) &&
+                isspace(space)) {
+                fclose(fp);
+                return pid;
+            }
+        }
+        fclose(fp);
+    }
+    return tid;
+}
 }
 
 uid_t LogStatistics::pidToUid(pid_t pid) {
     return pidTable.add(pid)->second.getUid();
 }
 
+pid_t LogStatistics::tidToPid(pid_t tid) {
+    return tidTable.add(tid)->second.getPid();
+}
+
 // caller must free character string
 const char* LogStatistics::pidToName(pid_t pid) const {
     // An inconvenient truth ... getName() can alter the object
diff --git a/logd/LogStatistics.h b/logd/LogStatistics.h
index 945fc0a..8808aac 100644
--- a/logd/LogStatistics.h
+++ b/logd/LogStatistics.h
@@ -306,10 +306,6 @@
     std::string format(const LogStatistics& stat, log_id_t id) const;
 };
 
-namespace android {
-uid_t pidToUid(pid_t pid);
-}
-
 struct PidEntry : public EntryBaseDropped {
     const pid_t pid;
     uid_t uid;
@@ -389,6 +385,13 @@
           uid(android::pidToUid(tid)),
           name(android::tidToName(tid)) {
     }
+    TidEntry(pid_t tid)
+        : EntryBaseDropped(),
+          tid(tid),
+          pid(android::tidToPid(tid)),
+          uid(android::pidToUid(tid)),
+          name(android::tidToName(tid)) {
+    }
     explicit TidEntry(const LogBufferElement* element)
         : EntryBaseDropped(element),
           tid(element->getTid()),
@@ -785,6 +788,7 @@
     // helper (must be locked directly or implicitly by mLogElementsLock)
     const char* pidToName(pid_t pid) const;
     uid_t pidToUid(pid_t pid);
+    pid_t tidToPid(pid_t tid);
     const char* uidToName(uid_t uid) const;
 };
 
diff --git a/logd/LogUtils.h b/logd/LogUtils.h
index fa9f398..4dcd3e7 100644
--- a/logd/LogUtils.h
+++ b/logd/LogUtils.h
@@ -38,6 +38,8 @@
 // Caller must own and free returned value
 char* pidToName(pid_t pid);
 char* tidToName(pid_t tid);
+uid_t pidToUid(pid_t pid);
+pid_t tidToPid(pid_t tid);
 
 // Furnished in LogTags.cpp. Thread safe.
 const char* tagToName(uint32_t tag);
diff --git a/logd/tests/logd_test.cpp b/logd/tests/logd_test.cpp
index f90c9fb..cd80212 100644
--- a/logd/tests/logd_test.cpp
+++ b/logd/tests/logd_test.cpp
@@ -32,8 +32,8 @@
 #include <android-base/stringprintf.h>
 #include <cutils/sockets.h>
 #include <gtest/gtest.h>
-#include <log/log.h>
 #include <private/android_filesystem_config.h>
+#include <private/android_logger.h>
 #ifdef __ANDROID__
 #include <selinux/selinux.h>
 #endif
@@ -1061,8 +1061,8 @@
 
     if (pid) {
         siginfo_t info = {};
-        if (TEMP_FAILURE_RETRY(waitid(P_PID, pid, &info, WEXITED))) return 0;
-        if (info.si_status) return 0;
+        if (TEMP_FAILURE_RETRY(waitid(P_PID, pid, &info, WEXITED))) return -1;
+        if (info.si_status) return -1;
         return pid;
     }
 
@@ -1077,7 +1077,7 @@
             freecon(context);
             _exit(-1);
             // NOTREACHED
-            return 0;
+            return -1;
         }
     }
 
@@ -1106,25 +1106,39 @@
         if (access(android::base::StringPrintf(file, num).c_str(), F_OK) == 0) {
             _exit(-1);
             // NOTREACHED
-            return 0;
+            return -1;
         }
         usleep(usec);
         --num;
     }
     _exit(0);
     // NOTREACHED
-    return 0;
+    return -1;
 }
 
+static constexpr int background_period = 10;
+
 static int count_avc(pid_t pid) {
     int count = 0;
 
-    if (pid == 0) return count;
+    // pid=-1 skip as pid is in error
+    if (pid == (pid_t)-1) return count;
 
-    struct logger_list* logger_list;
-    if (!(logger_list = android_logger_list_open(
-              LOG_ID_EVENTS, ANDROID_LOG_RDONLY | ANDROID_LOG_NONBLOCK, 0, pid)))
+    // pid=0 means we want to report the background count of avc: activities
+    struct logger_list* logger_list =
+        pid ? android_logger_list_alloc(
+                  ANDROID_LOG_RDONLY | ANDROID_LOG_NONBLOCK, 0, pid)
+            : android_logger_list_alloc_time(
+                  ANDROID_LOG_RDONLY | ANDROID_LOG_NONBLOCK,
+                  log_time(android_log_clockid()) -
+                      log_time(background_period, 0),
+                  0);
+    if (!logger_list) return count;
+    struct logger* logger = android_logger_open(logger_list, LOG_ID_EVENTS);
+    if (!logger) {
+        android_logger_list_close(logger_list);
         return count;
+    }
     for (;;) {
         log_msg log_msg;
 
@@ -1156,56 +1170,64 @@
 }
 #endif
 
-TEST(logd, sepolicy_rate_limiter_maximum) {
+TEST(logd, sepolicy_rate_limiter) {
 #ifdef __ANDROID__
-    static const int rate = AUDIT_RATE_LIMIT_MAX;
-    static const int duration = 2;
-    // Two seconds of a liveable sustained rate
-    EXPECT_EQ(rate * duration, count_avc(sepolicy_rate(rate, rate * duration)));
-#else
-    GTEST_LOG_(INFO) << "This test does nothing.\n";
-#endif
-}
-
-TEST(logd, sepolicy_rate_limiter_sub_burst) {
-#ifdef __ANDROID__
-    // maximum period below half way between sustainable and burst rate.
-    static const int threshold =
-        ((AUDIT_RATE_LIMIT_BURST_DURATION *
-          (AUDIT_RATE_LIMIT_DEFAULT + AUDIT_RATE_LIMIT_MAX)) +
-         1) /
-        2;
-    static const int rate = (threshold / AUDIT_RATE_LIMIT_BURST_DURATION) - 1;
-    static const int duration = AUDIT_RATE_LIMIT_BURST_DURATION;
-    EXPECT_EQ(rate * duration, count_avc(sepolicy_rate(rate, rate * duration)));
-#else
-    GTEST_LOG_(INFO) << "This test does nothing.\n";
-#endif
-}
-
-TEST(logd, sepolicy_rate_limiter_spam) {
-#ifdef __ANDROID__
-    // maximum period of double the maximum burst rate
-    static const int threshold =
-        ((AUDIT_RATE_LIMIT_BURST_DURATION *
-          (AUDIT_RATE_LIMIT_DEFAULT + AUDIT_RATE_LIMIT_MAX)) +
-         1) /
-        2;
-    static const int rate = AUDIT_RATE_LIMIT_DEFAULT * 2;
-    static const int duration = threshold / AUDIT_RATE_LIMIT_DEFAULT;
-    EXPECT_GE(
-        ((AUDIT_RATE_LIMIT_DEFAULT * duration) * 115) / 100,  // +15% margin
-        count_avc(sepolicy_rate(rate, rate * duration)));
-    // give logd another 3 seconds to react to the burst before checking
-    sepolicy_rate(rate, rate * 3);
-    // maximum period at double the maximum burst rate (spam filter kicked in)
-    EXPECT_GE(
-        threshold * 2,
-        count_avc(sepolicy_rate(rate, rate * AUDIT_RATE_LIMIT_BURST_DURATION)));
-    // cool down, and check unspammy rate still works
-    sleep(2);
-    EXPECT_LE(AUDIT_RATE_LIMIT_BURST_DURATION - 1,  // allow _one_ to be lost
-              count_avc(sepolicy_rate(1, AUDIT_RATE_LIMIT_BURST_DURATION)));
+    int background_selinux_activity_too_high = count_avc(0);
+    if (background_selinux_activity_too_high > 2) {
+        GTEST_LOG_(ERROR) << "Too much background selinux activity "
+                          << background_selinux_activity_too_high * 60 /
+                                 background_period
+                          << "/minute on the device, this test\n"
+                          << "can not measure the functionality of the "
+                          << "sepolicy rate limiter.  Expect test to\n"
+                          << "fail as this device is in a bad state, "
+                          << "but is not strictly a unit test failure.";
+    }
+    // sepolicy_rate_limiter_maximum
+    {  // maximum precharch test block.
+        static constexpr int rate = AUDIT_RATE_LIMIT_MAX;
+        static constexpr int duration = 2;
+        // Two seconds of a liveable sustained rate
+        EXPECT_EQ(rate * duration,
+                  count_avc(sepolicy_rate(rate, rate * duration)));
+    }
+    // sepolicy_rate_limiter_sub_burst
+    {  // maximum period below half way between sustainable and burst rate
+        static constexpr int threshold =
+            ((AUDIT_RATE_LIMIT_BURST_DURATION *
+              (AUDIT_RATE_LIMIT_DEFAULT + AUDIT_RATE_LIMIT_MAX)) +
+             1) /
+            2;
+        static constexpr int rate =
+            (threshold / AUDIT_RATE_LIMIT_BURST_DURATION) - 1;
+        static constexpr int duration = AUDIT_RATE_LIMIT_BURST_DURATION;
+        EXPECT_EQ(rate * duration,
+                  count_avc(sepolicy_rate(rate, rate * duration)));
+    }
+    // sepolicy_rate_limiter_spam
+    {  // hit avc: hard beyond reason block.
+        // maximum period of double the maximum burst rate
+        static constexpr int threshold =
+            ((AUDIT_RATE_LIMIT_BURST_DURATION *
+              (AUDIT_RATE_LIMIT_DEFAULT + AUDIT_RATE_LIMIT_MAX)) +
+             1) /
+            2;
+        static constexpr int rate = AUDIT_RATE_LIMIT_DEFAULT * 2;
+        static constexpr int duration = threshold / AUDIT_RATE_LIMIT_DEFAULT;
+        EXPECT_GE(
+            ((AUDIT_RATE_LIMIT_DEFAULT * duration) * 115) / 100,  // +15% margin
+            count_avc(sepolicy_rate(rate, rate * duration)));
+        // give logd another 3 seconds to react to the burst before checking
+        sepolicy_rate(rate, rate * 3);
+        // maximum period at double maximum burst rate (spam filter kicked in)
+        EXPECT_GE(threshold * 2,
+                  count_avc(sepolicy_rate(
+                      rate, rate * AUDIT_RATE_LIMIT_BURST_DURATION)));
+        // cool down, and check unspammy rate still works
+        sleep(2);
+        EXPECT_LE(AUDIT_RATE_LIMIT_BURST_DURATION - 1,  // allow _one_ lost
+                  count_avc(sepolicy_rate(1, AUDIT_RATE_LIMIT_BURST_DURATION)));
+    }
 #else
     GTEST_LOG_(INFO) << "This test does nothing.\n";
 #endif
diff --git a/rootdir/ueventd.rc b/rootdir/ueventd.rc
index 1609ef2..efd0da5 100644
--- a/rootdir/ueventd.rc
+++ b/rootdir/ueventd.rc
@@ -68,7 +68,7 @@
 /dev/diag                 0660   radio      radio
 /dev/diag_arm9            0660   radio      radio
 /dev/ttyMSM0              0600   bluetooth  bluetooth
-/dev/uhid                 0660   system     bluetooth
+/dev/uhid                 0660   uhid       uhid
 /dev/uinput               0660   system     bluetooth
 /dev/alarm                0664   system     radio
 /dev/rtc0                 0640   system     system