Merge "Remove misleading comment."
diff --git a/debuggerd/handler/debuggerd_handler.cpp b/debuggerd/handler/debuggerd_handler.cpp
index 05e6efa..c07a34a 100644
--- a/debuggerd/handler/debuggerd_handler.cpp
+++ b/debuggerd/handler/debuggerd_handler.cpp
@@ -169,24 +169,26 @@
     return;
   }
 
-  const char* signal_name = get_signame(info->si_signo);
-  bool has_address = signal_has_si_addr(info->si_signo, info->si_code);
-
-  // Many signals don't have an address.
+  // Many signals don't have an address or sender.
   char addr_desc[32] = "";  // ", fault addr 0x1234"
-  if (has_address) {
+  if (signal_has_si_addr(info)) {
     async_safe_format_buffer(addr_desc, sizeof(addr_desc), ", fault addr %p", info->si_addr);
   }
+  pid_t self_pid = __getpid();
+  char sender_desc[32] = {};  // " from pid 1234, uid 666"
+  if (signal_has_sender(info, self_pid)) {
+    get_signal_sender(sender_desc, sizeof(sender_desc), info);
+  }
 
   char main_thread_name[MAX_TASK_NAME_LEN + 1];
   if (!get_main_thread_name(main_thread_name, sizeof(main_thread_name))) {
     strncpy(main_thread_name, "<unknown>", sizeof(main_thread_name));
   }
 
-  async_safe_format_log(
-      ANDROID_LOG_FATAL, "libc", "Fatal signal %d (%s), code %d (%s)%s in tid %d (%s), pid %d (%s)",
-      info->si_signo, signal_name, info->si_code, get_sigcode(info->si_signo, info->si_code),
-      addr_desc, __gettid(), thread_name, __getpid(), main_thread_name);
+  async_safe_format_log(ANDROID_LOG_FATAL, "libc",
+                        "Fatal signal %d (%s), code %d (%s%s)%s in tid %d (%s), pid %d (%s)",
+                        info->si_signo, get_signame(info), info->si_code, get_sigcode(info),
+                        sender_desc, addr_desc, __gettid(), thread_name, self_pid, main_thread_name);
 }
 
 /*
diff --git a/debuggerd/libdebuggerd/include/libdebuggerd/utility.h b/debuggerd/libdebuggerd/include/libdebuggerd/utility.h
index 7b04e71..7c5304e 100644
--- a/debuggerd/libdebuggerd/include/libdebuggerd/utility.h
+++ b/debuggerd/libdebuggerd/include/libdebuggerd/utility.h
@@ -74,8 +74,10 @@
 
 void drop_capabilities();
 
-bool signal_has_si_addr(int si_signo, int si_code);
-const char* get_signame(int sig);
-const char* get_sigcode(int signo, int code);
+bool signal_has_sender(const siginfo_t*, pid_t caller_pid);
+bool signal_has_si_addr(const siginfo_t*);
+void get_signal_sender(char* buf, size_t n, const siginfo_t*);
+const char* get_signame(const siginfo_t*);
+const char* get_sigcode(const siginfo_t*);
 
 #endif // _DEBUGGERD_UTILITY_H
diff --git a/debuggerd/libdebuggerd/tombstone.cpp b/debuggerd/libdebuggerd/tombstone.cpp
index af8072e..e11be1e 100644
--- a/debuggerd/libdebuggerd/tombstone.cpp
+++ b/debuggerd/libdebuggerd/tombstone.cpp
@@ -102,18 +102,24 @@
   if (!cause.empty()) _LOG(log, logtype::HEADER, "Cause: %s\n", cause.c_str());
 }
 
-static void dump_signal_info(log_t* log, const siginfo_t* si) {
+static void dump_signal_info(log_t* log, const ThreadInfo& thread_info) {
   char addr_desc[32]; // ", fault addr 0x1234"
-  if (signal_has_si_addr(si->si_signo, si->si_code)) {
-    snprintf(addr_desc, sizeof(addr_desc), "%p", si->si_addr);
+  if (signal_has_si_addr(thread_info.siginfo)) {
+    snprintf(addr_desc, sizeof(addr_desc), "%p", thread_info.siginfo->si_addr);
   } else {
     snprintf(addr_desc, sizeof(addr_desc), "--------");
   }
 
-  _LOG(log, logtype::HEADER, "signal %d (%s), code %d (%s), fault addr %s\n", si->si_signo,
-       get_signame(si->si_signo), si->si_code, get_sigcode(si->si_signo, si->si_code), addr_desc);
+  char sender_desc[32] = {};  // " from pid 1234, uid 666"
+  if (signal_has_sender(thread_info.siginfo, thread_info.pid)) {
+    get_signal_sender(sender_desc, sizeof(sender_desc), thread_info.siginfo);
+  }
 
-  dump_probable_cause(log, si);
+  _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) {
@@ -412,7 +418,7 @@
   dump_thread_info(log, thread_info);
 
   if (thread_info.siginfo) {
-    dump_signal_info(log, thread_info.siginfo);
+    dump_signal_info(log, thread_info);
   }
 
   if (primary_thread) {
@@ -442,7 +448,7 @@
     if (map) {
       uint64_t addr = 0;
       siginfo_t* si = thread_info.siginfo;
-      if (signal_has_si_addr(si->si_signo, si->si_code)) {
+      if (signal_has_si_addr(si)) {
         addr = reinterpret_cast<uint64_t>(si->si_addr);
       }
       dump_all_maps(log, map, process_memory, addr);
diff --git a/debuggerd/libdebuggerd/utility.cpp b/debuggerd/libdebuggerd/utility.cpp
index 1ad1800..1f6f3c8 100644
--- a/debuggerd/libdebuggerd/utility.cpp
+++ b/debuggerd/libdebuggerd/utility.cpp
@@ -254,13 +254,13 @@
   }
 }
 
-bool signal_has_si_addr(int si_signo, int si_code) {
+bool signal_has_si_addr(const siginfo_t* si) {
   // Manually sent signals won't have si_addr.
-  if (si_code == SI_USER || si_code == SI_QUEUE || si_code == SI_TKILL) {
+  if (si->si_code == SI_USER || si->si_code == SI_QUEUE || si->si_code == SI_TKILL) {
     return false;
   }
 
-  switch (si_signo) {
+  switch (si->si_signo) {
     case SIGBUS:
     case SIGFPE:
     case SIGILL:
@@ -272,8 +272,16 @@
   }
 }
 
-const char* get_signame(int sig) {
-  switch (sig) {
+bool signal_has_sender(const siginfo_t* si, pid_t caller_pid) {
+  return SI_FROMUSER(si) && (si->si_pid != 0) && (si->si_pid != caller_pid);
+}
+
+void get_signal_sender(char* buf, size_t n, const siginfo_t* si) {
+  snprintf(buf, n, " from pid %d, uid %d", si->si_pid, si->si_uid);
+}
+
+const char* get_signame(const siginfo_t* si) {
+  switch (si->si_signo) {
     case SIGABRT: return "SIGABRT";
     case SIGBUS: return "SIGBUS";
     case SIGFPE: return "SIGFPE";
@@ -290,11 +298,11 @@
   }
 }
 
-const char* get_sigcode(int signo, int code) {
+const char* get_sigcode(const siginfo_t* si) {
   // Try the signal-specific codes...
-  switch (signo) {
+  switch (si->si_signo) {
     case SIGILL:
-      switch (code) {
+      switch (si->si_code) {
         case ILL_ILLOPC: return "ILL_ILLOPC";
         case ILL_ILLOPN: return "ILL_ILLOPN";
         case ILL_ILLADR: return "ILL_ILLADR";
@@ -307,7 +315,7 @@
       static_assert(NSIGILL == ILL_BADSTK, "missing ILL_* si_code");
       break;
     case SIGBUS:
-      switch (code) {
+      switch (si->si_code) {
         case BUS_ADRALN: return "BUS_ADRALN";
         case BUS_ADRERR: return "BUS_ADRERR";
         case BUS_OBJERR: return "BUS_OBJERR";
@@ -317,7 +325,7 @@
       static_assert(NSIGBUS == BUS_MCEERR_AO, "missing BUS_* si_code");
       break;
     case SIGFPE:
-      switch (code) {
+      switch (si->si_code) {
         case FPE_INTDIV: return "FPE_INTDIV";
         case FPE_INTOVF: return "FPE_INTOVF";
         case FPE_FLTDIV: return "FPE_FLTDIV";
@@ -330,7 +338,7 @@
       static_assert(NSIGFPE == FPE_FLTSUB, "missing FPE_* si_code");
       break;
     case SIGSEGV:
-      switch (code) {
+      switch (si->si_code) {
         case SEGV_MAPERR: return "SEGV_MAPERR";
         case SEGV_ACCERR: return "SEGV_ACCERR";
 #if defined(SEGV_BNDERR)
@@ -350,21 +358,21 @@
       break;
 #if defined(SYS_SECCOMP) // Our glibc is too old, and we build this for the host too.
     case SIGSYS:
-      switch (code) {
+      switch (si->si_code) {
         case SYS_SECCOMP: return "SYS_SECCOMP";
       }
       static_assert(NSIGSYS == SYS_SECCOMP, "missing SYS_* si_code");
       break;
 #endif
     case SIGTRAP:
-      switch (code) {
+      switch (si->si_code) {
         case TRAP_BRKPT: return "TRAP_BRKPT";
         case TRAP_TRACE: return "TRAP_TRACE";
         case TRAP_BRANCH: return "TRAP_BRANCH";
         case TRAP_HWBKPT: return "TRAP_HWBKPT";
       }
-      if ((code & 0xff) == SIGTRAP) {
-        switch ((code >> 8) & 0xff) {
+      if ((si->si_code & 0xff) == SIGTRAP) {
+        switch ((si->si_code >> 8) & 0xff) {
           case PTRACE_EVENT_FORK:
             return "PTRACE_EVENT_FORK";
           case PTRACE_EVENT_VFORK:
@@ -387,7 +395,7 @@
       break;
   }
   // Then the other codes...
-  switch (code) {
+  switch (si->si_code) {
     case SI_USER: return "SI_USER";
     case SI_KERNEL: return "SI_KERNEL";
     case SI_QUEUE: return "SI_QUEUE";
diff --git a/fastboot/fastboot.cpp b/fastboot/fastboot.cpp
index 780ff50..9463cc9 100644
--- a/fastboot/fastboot.cpp
+++ b/fastboot/fastboot.cpp
@@ -693,10 +693,14 @@
     fb_queue_notice("--------------------------------------------");
 }
 
-static struct sparse_file** load_sparse_files(int fd, int max_size) {
+static struct sparse_file** load_sparse_files(int fd, int64_t max_size) {
     struct sparse_file* s = sparse_file_import_auto(fd, false, true);
     if (!s) die("cannot sparse read file");
 
+    if (max_size <= 0 || max_size > std::numeric_limits<uint32_t>::max()) {
+      die("invalid max size %" PRId64, max_size);
+    }
+
     int files = sparse_file_resparse(s, max_size, nullptr, 0);
     if (files < 0) die("Failed to resparse");
 
@@ -1640,20 +1644,20 @@
     }
 
     if (wants_wipe) {
-        fb_queue_erase("userdata");
-        if (set_fbe_marker) {
-            fprintf(stderr, "setting FBE marker on initial userdata...\n");
-            std::string initial_userdata_dir = create_fbemarker_tmpdir();
-            fb_perform_format(transport, "userdata", 1, "", "", initial_userdata_dir);
-            delete_fbemarker_tmpdir(initial_userdata_dir);
-        } else {
-            fb_perform_format(transport, "userdata", 1, "", "", "");
-        }
-
-        std::string cache_type;
-        if (fb_getvar(transport, "partition-type:cache", &cache_type) && !cache_type.empty()) {
-            fb_queue_erase("cache");
-            fb_perform_format(transport, "cache", 1, "", "", "");
+        std::vector<std::string> partitions = { "userdata", "cache", "metadata" };
+        for (const auto& partition : partitions) {
+            std::string partition_type;
+            if (!fb_getvar(transport, std::string{"partition-type:"} + partition, &partition_type)) continue;
+            if (partition_type.empty()) continue;
+            fb_queue_erase(partition);
+            if (partition == "userdata" && set_fbe_marker) {
+                fprintf(stderr, "setting FBE marker on initial userdata...\n");
+                std::string initial_userdata_dir = create_fbemarker_tmpdir();
+                fb_perform_format(transport, partition, 1, "", "", initial_userdata_dir);
+                delete_fbemarker_tmpdir(initial_userdata_dir);
+            } else {
+                fb_perform_format(transport, partition, 1, "", "", "");
+            }
         }
     }
     if (wants_set_active) {
diff --git a/fastboot/protocol.cpp b/fastboot/protocol.cpp
index a089567..7a333ee 100644
--- a/fastboot/protocol.cpp
+++ b/fastboot/protocol.cpp
@@ -344,12 +344,12 @@
 }
 
 int fb_download_data_sparse(Transport* transport, struct sparse_file* s) {
-    int size = sparse_file_len(s, true, false);
-    if (size <= 0) {
+    int64_t size = sparse_file_len(s, true, false);
+    if (size <= 0 || size > std::numeric_limits<uint32_t>::max()) {
         return -1;
     }
 
-    std::string cmd(android::base::StringPrintf("download:%08x", size));
+    std::string cmd(android::base::StringPrintf("download:%08" PRIx64, size));
     int r = _command_start(transport, cmd, size, 0);
     if (r < 0) {
         return -1;
diff --git a/init/README.md b/init/README.md
index b14521c..c08b07a 100644
--- a/init/README.md
+++ b/init/README.md
@@ -193,7 +193,7 @@
 
 `disabled`
 > This service will not automatically start with its class.
-  It must be explicitly started by name.
+  It must be explicitly started by name or by interface name.
 
 `file <path> <type>`
 > Open a file path and pass its fd to the launched process. _type_ must be
diff --git a/libcutils/Android.bp b/libcutils/Android.bp
index 6d00dc6..dd46750 100644
--- a/libcutils/Android.bp
+++ b/libcutils/Android.bp
@@ -164,6 +164,7 @@
 
     shared_libs: ["liblog"],
     header_libs: [
+        "libbase_headers",
         "libcutils_headers",
         "libutils_headers",
     ],
diff --git a/libcutils/include/cutils/sched_policy.h b/libcutils/include/cutils/sched_policy.h
index 4c1113b..cf91b76 100644
--- a/libcutils/include/cutils/sched_policy.h
+++ b/libcutils/include/cutils/sched_policy.h
@@ -40,16 +40,17 @@
 
 /* Keep in sync with THREAD_GROUP_* in frameworks/base/core/java/android/os/Process.java */
 typedef enum {
-    SP_DEFAULT    = -1,
+    SP_DEFAULT = -1,
     SP_BACKGROUND = 0,
     SP_FOREGROUND = 1,
-    SP_SYSTEM     = 2,  // can't be used with set_sched_policy()
-    SP_AUDIO_APP  = 3,
-    SP_AUDIO_SYS  = 4,
-    SP_TOP_APP    = 5,
-    SP_RT_APP     = 6,
+    SP_SYSTEM = 2,  // can't be used with set_sched_policy()
+    SP_AUDIO_APP = 3,
+    SP_AUDIO_SYS = 4,
+    SP_TOP_APP = 5,
+    SP_RT_APP = 6,
+    SP_RESTRICTED = 7,
     SP_CNT,
-    SP_MAX        = SP_CNT - 1,
+    SP_MAX = SP_CNT - 1,
     SP_SYSTEM_DEFAULT = SP_FOREGROUND,
 } SchedPolicy;
 
diff --git a/libcutils/include/cutils/trace.h b/libcutils/include/cutils/trace.h
index bbb150d..58b9f09 100644
--- a/libcutils/include/cutils/trace.h
+++ b/libcutils/include/cutils/trace.h
@@ -74,7 +74,8 @@
 #define ATRACE_TAG_ADB              (1<<22)
 #define ATRACE_TAG_VIBRATOR         (1<<23)
 #define ATRACE_TAG_AIDL             (1<<24)
-#define ATRACE_TAG_LAST             ATRACE_TAG_AIDL
+#define ATRACE_TAG_NNAPI            (1<<25)
+#define ATRACE_TAG_LAST             ATRACE_TAG_NNAPI
 
 // Reserved for initialization.
 #define ATRACE_TAG_NOT_READY        (1ULL<<63)
diff --git a/libcutils/sched_policy.cpp b/libcutils/sched_policy.cpp
index f5ce82f..3fa548f 100644
--- a/libcutils/sched_policy.cpp
+++ b/libcutils/sched_policy.cpp
@@ -25,6 +25,7 @@
 #include <string.h>
 #include <unistd.h>
 
+#include <android-base/macros.h>
 #include <log/log.h>
 
 /* Re-map SP_DEFAULT to the system default policy, and leave other values unchanged.
@@ -57,6 +58,7 @@
 static int bg_cpuset_fd = -1;
 static int fg_cpuset_fd = -1;
 static int ta_cpuset_fd = -1; // special cpuset for top app
+static int rs_cpuset_fd = -1;  // special cpuset for screen off restrictions
 
 // File descriptors open to /dev/stune/../tasks, setup by initialize, or -1 on error
 static int bg_schedboost_fd = -1;
@@ -151,6 +153,8 @@
             system_bg_cpuset_fd = open(filename, O_WRONLY | O_CLOEXEC);
             filename = "/dev/cpuset/top-app/tasks";
             ta_cpuset_fd = open(filename, O_WRONLY | O_CLOEXEC);
+            filename = "/dev/cpuset/restricted/tasks";
+            rs_cpuset_fd = open(filename, O_WRONLY | O_CLOEXEC);
 
             if (schedboost_enabled()) {
                 filename = "/dev/stune/top-app/tasks";
@@ -308,6 +312,9 @@
     case SP_SYSTEM:
         fd = system_bg_cpuset_fd;
         break;
+    case SP_RESTRICTED:
+        fd = rs_cpuset_fd;
+        break;
     default:
         boost_fd = fd = -1;
         break;
@@ -454,20 +461,16 @@
 
 #endif
 
-const char *get_sched_policy_name(SchedPolicy policy)
-{
+const char* get_sched_policy_name(SchedPolicy policy) {
     policy = _policy(policy);
-    static const char * const strings[SP_CNT] = {
-       [SP_BACKGROUND] = "bg",
-       [SP_FOREGROUND] = "fg",
-       [SP_SYSTEM]     = "  ",
-       [SP_AUDIO_APP]  = "aa",
-       [SP_AUDIO_SYS]  = "as",
-       [SP_TOP_APP]    = "ta",
-       [SP_RT_APP]    = "rt",
+    static const char* const kSchedPolicyNames[] = {
+            [SP_BACKGROUND] = "bg", [SP_FOREGROUND] = "fg", [SP_SYSTEM] = "  ",
+            [SP_AUDIO_APP] = "aa",  [SP_AUDIO_SYS] = "as",  [SP_TOP_APP] = "ta",
+            [SP_RT_APP] = "rt",     [SP_RESTRICTED] = "rs",
     };
-    if ((policy < SP_CNT) && (strings[policy] != NULL))
-        return strings[policy];
-    else
+    static_assert(arraysize(kSchedPolicyNames) == SP_CNT, "missing name");
+    if (policy < SP_BACKGROUND || policy >= SP_CNT) {
         return "error";
+    }
+    return kSchedPolicyNames[policy];
 }
diff --git a/libcutils/tests/sched_policy_test.cpp b/libcutils/tests/sched_policy_test.cpp
index 173174a..5942ee5 100644
--- a/libcutils/tests/sched_policy_test.cpp
+++ b/libcutils/tests/sched_policy_test.cpp
@@ -60,6 +60,12 @@
     return sleepTimes[median];
 }
 
+static void AssertPolicy(SchedPolicy expected_policy) {
+    SchedPolicy current_policy;
+    ASSERT_EQ(0, get_sched_policy(0, &current_policy));
+    EXPECT_EQ(expected_policy, current_policy);
+}
+
 TEST(SchedPolicy, set_sched_policy) {
     if (!hasCapSysNice()) {
         GTEST_LOG_(INFO) << "skipping test that requires CAP_SYS_NICE";
@@ -76,23 +82,17 @@
     const unsigned int BG_FG_SLACK_FACTOR = 100;
 
     ASSERT_EQ(0, set_sched_policy(0, SP_BACKGROUND));
+    AssertPolicy(SP_BACKGROUND);
     auto bgSleepTime = medianSleepTime();
 
     ASSERT_EQ(0, set_sched_policy(0, SP_FOREGROUND));
+    AssertPolicy(SP_FOREGROUND);
     auto fgSleepTime = medianSleepTime();
     ASSERT_GT(bgSleepTime, fgSleepTime * BG_FG_SLACK_FACTOR);
 }
 
-TEST(SchedPolicy, get_sched_policy) {
-    SchedPolicy policy;
-    ASSERT_EQ(0, get_sched_policy(0, &policy));
-
-    const char *policyName = get_sched_policy_name(policy);
-    EXPECT_NE(nullptr, policyName);
-    EXPECT_STRNE("error", policyName);
-
-    ASSERT_EQ(0, set_sched_policy(0, SP_BACKGROUND));
-    SchedPolicy newPolicy;
-    ASSERT_EQ(0, get_sched_policy(0, &newPolicy));
-    EXPECT_EQ(SP_BACKGROUND, newPolicy);
+TEST(SchedPolicy, get_sched_policy_name) {
+    EXPECT_STREQ("bg", get_sched_policy_name(SP_BACKGROUND));
+    EXPECT_STREQ("error", get_sched_policy_name(SchedPolicy(-2)));
+    EXPECT_STREQ("error", get_sched_policy_name(SP_CNT));
 }
diff --git a/libziparchive/Android.bp b/libziparchive/Android.bp
index ed1b9bc..6c06618 100644
--- a/libziparchive/Android.bp
+++ b/libziparchive/Android.bp
@@ -93,6 +93,10 @@
     host_supported: true,
     defaults: ["libziparchive_flags"],
 
+    data: [
+        "testdata/**/*",
+    ],
+
     srcs: [
         "entry_name_utils_test.cc",
         "zip_archive_test.cc",
diff --git a/libziparchive/zip_archive_test.cc b/libziparchive/zip_archive_test.cc
index ad673dc..377479f 100644
--- a/libziparchive/zip_archive_test.cc
+++ b/libziparchive/zip_archive_test.cc
@@ -34,7 +34,7 @@
 #include <ziparchive/zip_archive.h>
 #include <ziparchive/zip_archive_stream_entry.h>
 
-static std::string test_data_dir;
+static std::string test_data_dir = android::base::GetExecutableDirectory() + "/testdata";
 
 static const std::string kMissingZip = "missing.zip";
 static const std::string kValidZip = "valid.zip";
@@ -729,41 +729,3 @@
     ASSERT_EQ(0u, writer.GetOutput().size());
   }
 }
-
-int main(int argc, char** argv) {
-  ::testing::InitGoogleTest(&argc, argv);
-
-  static struct option options[] = {{"test_data_dir", required_argument, nullptr, 't'},
-                                    {nullptr, 0, nullptr, 0}};
-
-  while (true) {
-    int option_index;
-    const int c = getopt_long_only(argc, argv, "", options, &option_index);
-    if (c == -1) {
-      break;
-    }
-
-    if (c == 't') {
-      test_data_dir = optarg;
-    }
-  }
-
-  if (test_data_dir.size() == 0) {
-    printf("Test data flag (--test_data_dir) required\n\n");
-    return -1;
-  }
-
-  if (test_data_dir[0] != '/') {
-    std::vector<char> cwd_buffer(1024);
-    const char* cwd = getcwd(cwd_buffer.data(), cwd_buffer.size() - 1);
-    if (cwd == nullptr) {
-      printf("Cannot get current working directory, use an absolute path instead, was %s\n\n",
-             test_data_dir.c_str());
-      return -2;
-    }
-    test_data_dir = '/' + test_data_dir;
-    test_data_dir = cwd + test_data_dir;
-  }
-
-  return RUN_ALL_TESTS();
-}
diff --git a/logd/LogKlog.cpp b/logd/LogKlog.cpp
index 7a7ac7d..ab980ac 100755
--- a/logd/LogKlog.cpp
+++ b/logd/LogKlog.cpp
@@ -825,7 +825,7 @@
                          (unsigned short)n);
 
     // notify readers
-    if (!rc) {
+    if (rc > 0) {
         reader->notifyNewLog(static_cast<log_mask_t>(1 << LOG_ID_KERNEL));
     }
 
diff --git a/rootdir/etc/public.libraries.iot.txt b/rootdir/etc/public.libraries.iot.txt
new file mode 100644
index 0000000..ff0813d
--- /dev/null
+++ b/rootdir/etc/public.libraries.iot.txt
@@ -0,0 +1,27 @@
+# See https://android.googlesource.com/platform/ndk/+/master/docs/PlatformApis.md
+libandroid.so
+libandroidthings.so
+libaaudio.so
+libc.so
+libcamera2ndk.so
+libdl.so
+libEGL.so
+libGLESv1_CM.so
+libGLESv2.so
+libGLESv3.so
+libicui18n.so
+libicuuc.so
+libjnigraphics.so
+liblog.so
+libmediandk.so
+libm.so
+libnativewindow.so
+libneuralnetworks.so
+libOpenMAXAL.so
+libOpenSLES.so
+libRS.so
+libstdc++.so
+libsync.so
+libvulkan.so
+libwebviewchromium_plat_support.so
+libz.so