Merge "Revert "init: chroot from recovery to /first_stage_ramdisk"" am: 223114008c am: b3ef4f838f
am: 997a8094e7

Change-Id: Ica86595f5f78bbab631d7e9e07721722830964d9
diff --git a/adb/transport.cpp b/adb/transport.cpp
index c2d4917..76a31ce 100644
--- a/adb/transport.cpp
+++ b/adb/transport.cpp
@@ -1009,14 +1009,11 @@
 const FeatureSet& supported_features() {
     // Local static allocation to avoid global non-POD variables.
     static const FeatureSet* features = new FeatureSet{
-        kFeatureShell2, kFeatureCmd, kFeatureStat2, kFeatureFixedPushMkdir,
-#if ADB_HOST
-                kFeatureApex
-#endif
-        // Increment ADB_SERVER_VERSION when adding a feature that adbd needs
-        // to know about. Otherwise, the client can be stuck running an old
-        // version of the server even after upgrading their copy of adb.
-        // (http://b/24370690)
+            kFeatureShell2, kFeatureCmd, kFeatureStat2, kFeatureFixedPushMkdir, kFeatureApex
+            // Increment ADB_SERVER_VERSION when adding a feature that adbd needs
+            // to know about. Otherwise, the client can be stuck running an old
+            // version of the server even after upgrading their copy of adb.
+            // (http://b/24370690)
     };
 
     return *features;
diff --git a/libpackagelistparser/include/packagelistparser/packagelistparser.h b/libpackagelistparser/include/packagelistparser/packagelistparser.h
index d602c26..8bcc1e2 100644
--- a/libpackagelistparser/include/packagelistparser/packagelistparser.h
+++ b/libpackagelistparser/include/packagelistparser/packagelistparser.h
@@ -53,6 +53,7 @@
     char *seinfo;
     gid_list gids;
     void *private_data;
+    bool profileable_from_shell;
 };
 
 /**
diff --git a/libpackagelistparser/packagelistparser.c b/libpackagelistparser/packagelistparser.c
index 3e1a3d1..4ce2363 100644
--- a/libpackagelistparser/packagelistparser.c
+++ b/libpackagelistparser/packagelistparser.c
@@ -223,6 +223,23 @@
             }
         }
 
+        cur = strsep(&next, " \t\r\n");
+        if (cur) {
+            tmp = strtoul(cur, &endptr, 10);
+            if (*endptr != '\0') {
+                errmsg = "Could not convert field \"profileable_from_shell\" to integer value";
+                goto err;
+            }
+
+            /* should be a valid boolean of 1 or 0 */
+            if (!(tmp == 0 || tmp == 1)) {
+                errmsg = "Field \"profileable_from_shell\" is not 0 or 1 boolean value";
+                goto err;
+            }
+
+            pkg_info->profileable_from_shell = (bool)tmp;
+        }
+
         rc = callback(pkg_info, userdata);
         if (rc == false) {
             /*
diff --git a/lmkd/lmkd.c b/lmkd/lmkd.c
index 3a89706..c9c9e8e 100644
--- a/lmkd/lmkd.c
+++ b/lmkd/lmkd.c
@@ -954,7 +954,7 @@
 }
 
 #ifdef LMKD_LOG_STATS
-static void memory_stat_parse_line(char *line, struct memory_stat *mem_st) {
+static void memory_stat_parse_line(char* line, struct memory_stat* mem_st) {
     char key[LINE_MAX + 1];
     int64_t value;
 
@@ -976,25 +976,62 @@
         mem_st->swap_in_bytes = value;
 }
 
-static int memory_stat_parse(struct memory_stat *mem_st,  int pid, uid_t uid) {
-   FILE *fp;
-   char buf[PATH_MAX];
+static int memory_stat_from_cgroup(struct memory_stat* mem_st, int pid, uid_t uid) {
+    FILE *fp;
+    char buf[PATH_MAX];
 
-   snprintf(buf, sizeof(buf), MEMCG_PROCESS_MEMORY_STAT_PATH, uid, pid);
+    snprintf(buf, sizeof(buf), MEMCG_PROCESS_MEMORY_STAT_PATH, uid, pid);
 
-   fp = fopen(buf, "r");
+    fp = fopen(buf, "r");
 
-   if (fp == NULL) {
-       ALOGE("%s open failed: %s", buf, strerror(errno));
-       return -1;
-   }
+    if (fp == NULL) {
+        ALOGE("%s open failed: %s", buf, strerror(errno));
+        return -1;
+    }
 
-   while (fgets(buf, PAGE_SIZE, fp) != NULL ) {
-       memory_stat_parse_line(buf, mem_st);
-   }
-   fclose(fp);
+    while (fgets(buf, PAGE_SIZE, fp) != NULL) {
+        memory_stat_parse_line(buf, mem_st);
+    }
+    fclose(fp);
 
-   return 0;
+    return 0;
+}
+
+static int memory_stat_from_procfs(struct memory_stat* mem_st, int pid) {
+    char path[PATH_MAX];
+    char buffer[PROC_STAT_BUFFER_SIZE];
+    int fd, ret;
+
+    snprintf(path, sizeof(path), PROC_STAT_FILE_PATH, pid);
+    if ((fd = open(path, O_RDONLY | O_CLOEXEC)) < 0) {
+        ALOGE("%s open failed: %s", path, strerror(errno));
+        return -1;
+    }
+
+    ret = read(fd, buffer, sizeof(buffer));
+    if (ret < 0) {
+        ALOGE("%s read failed: %s", path, strerror(errno));
+        close(fd);
+        return -1;
+    }
+    close(fd);
+
+    // field 10 is pgfault
+    // field 12 is pgmajfault
+    // field 24 is rss_in_pages
+    int64_t pgfault = 0, pgmajfault = 0, rss_in_pages = 0;
+    if (sscanf(buffer,
+               "%*u %*s %*s %*d %*d %*d %*d %*d %*d %" SCNd64 " %*d "
+               "%" SCNd64 " %*d %*u %*u %*d %*d %*d %*d %*d %*d "
+               "%*d %*d %" SCNd64 "",
+               &pgfault, &pgmajfault, &rss_in_pages) != 3) {
+        return -1;
+    }
+    mem_st->pgfault = pgfault;
+    mem_st->pgmajfault = pgmajfault;
+    mem_st->rss_in_bytes = (rss_in_pages * PAGE_SIZE);
+
+    return 0;
 }
 #endif
 
@@ -1251,7 +1288,11 @@
 
 #ifdef LMKD_LOG_STATS
     if (enable_stats_log) {
-        memory_stat_parse_result = memory_stat_parse(&mem_st, pid, uid);
+        if (per_app_memcg) {
+            memory_stat_parse_result = memory_stat_from_cgroup(&mem_st, pid, uid);
+        } else {
+            memory_stat_parse_result = memory_stat_from_procfs(&mem_st, pid);
+        }
     }
 #endif
 
@@ -1276,6 +1317,9 @@
             stats_write_lmk_kill_occurred(log_ctx, LMK_KILL_OCCURRED, uid, taskname,
                     procp->oomadj, mem_st.pgfault, mem_st.pgmajfault, mem_st.rss_in_bytes,
                     mem_st.cache_in_bytes, mem_st.swap_in_bytes);
+        } else if (enable_stats_log) {
+            stats_write_lmk_kill_occurred(log_ctx, LMK_KILL_OCCURRED, uid, taskname, procp->oomadj,
+                                          -1, -1, tasksize * BYTES_IN_KILOBYTE, -1, -1);
         }
 #endif
         result = tasksize;
diff --git a/lmkd/statslog.h b/lmkd/statslog.h
index edebb19..8458480 100644
--- a/lmkd/statslog.h
+++ b/lmkd/statslog.h
@@ -67,6 +67,9 @@
 };
 
 #define MEMCG_PROCESS_MEMORY_STAT_PATH "/dev/memcg/apps/uid_%u/pid_%u/memory.stat"
+#define PROC_STAT_FILE_PATH "/proc/%d/stat"
+#define PROC_STAT_BUFFER_SIZE 1024
+#define BYTES_IN_KILOBYTE 1024
 
 /**
  * Logs the change in LMKD state which is used as start/stop boundaries for logging
diff --git a/rootdir/etc/public.libraries.android.txt b/rootdir/etc/public.libraries.android.txt
index d8f6095..27e855f 100644
--- a/rootdir/etc/public.libraries.android.txt
+++ b/rootdir/etc/public.libraries.android.txt
@@ -1,6 +1,7 @@
 # See https://android.googlesource.com/platform/ndk/+/master/docs/PlatformApis.md
 libandroid.so
 libaaudio.so
+libamidi.so
 libbinder_ndk.so
 libc.so
 libcamera2ndk.so
diff --git a/rootdir/etc/public.libraries.iot.txt b/rootdir/etc/public.libraries.iot.txt
index 20905bf..b565340 100644
--- a/rootdir/etc/public.libraries.iot.txt
+++ b/rootdir/etc/public.libraries.iot.txt
@@ -2,6 +2,7 @@
 libandroid.so
 libandroidthings.so
 libaaudio.so
+libamidi.so
 libbinder_ndk.so
 libc.so
 libcamera2ndk.so
diff --git a/rootdir/etc/public.libraries.wear.txt b/rootdir/etc/public.libraries.wear.txt
index 4ece5b5..7cbda08 100644
--- a/rootdir/etc/public.libraries.wear.txt
+++ b/rootdir/etc/public.libraries.wear.txt
@@ -1,6 +1,7 @@
 # See https://android.googlesource.com/platform/ndk/+/master/docs/PlatformApis.md
 libandroid.so
 libaaudio.so
+libamidi.so
 libbinder_ndk.so
 libc.so
 libcamera2ndk.so
diff --git a/run-as/run-as.cpp b/run-as/run-as.cpp
index f49bdf7..dea191d 100644
--- a/run-as/run-as.cpp
+++ b/run-as/run-as.cpp
@@ -45,7 +45,7 @@
 //
 //  - that the ro.boot.disable_runas property is not set
 //  - that it is invoked from the 'shell' or 'root' user (abort otherwise)
-//  - that '<package-name>' is the name of an installed and debuggable package
+//  - that '<package-name>' is the name of an installed and debuggable/profileableFromShell package
 //  - that the package's data directory is well-formed
 //
 //  If so, it will drop to the application's user id / group id, cd to the
@@ -57,6 +57,7 @@
 //    during development.
 //
 //  - Run the 'gdbserver' binary executable to allow native debugging
+//  - Run simpleperf to allow native profiling
 //
 
 static bool packagelist_parse_callback(pkg_info* this_package, void* userdata) {
@@ -196,9 +197,9 @@
     error(1, 0, "package not an application: %s", pkgname);
   }
 
-  // Reject any non-debuggable package.
-  if (!info.debuggable) {
-    error(1, 0, "package not debuggable: %s", pkgname);
+  // Reject packages that are neither debuggable nor profileable from shell.
+  if (!info.debuggable && !info.profileable_from_shell) {
+    error(1, 0, "package is neither debuggable nor profileable from shell: %s", pkgname);
   }
 
   // Check that the data directory path is valid.