Merge "adb: switch install to unique_fd."
diff --git a/adb/client/commandline.cpp b/adb/client/commandline.cpp
index 1592c43..9bc42e1 100644
--- a/adb/client/commandline.cpp
+++ b/adb/client/commandline.cpp
@@ -142,7 +142,7 @@
         "     -x: disable remote exit codes and stdout/stderr separation\n"
         " emu COMMAND              run emulator console command\n"
         "\n"
-        "app installation:\n"
+        "app installation (see also `adb shell cmd package help`):\n"
         " install [-lrtsdg] [--instant] PACKAGE\n"
         "     push a single package to the device and install it\n"
         " install-multiple [-lrtsdpg] [--instant] PACKAGE...\n"
diff --git a/fs_mgr/Android.bp b/fs_mgr/Android.bp
index bf58315..d9f2837 100644
--- a/fs_mgr/Android.bp
+++ b/fs_mgr/Android.bp
@@ -99,6 +99,11 @@
         "fs_mgr_boot_config.cpp",
         "fs_mgr_slotselect.cpp",
     ],
+    target: {
+        darwin: {
+            enabled: false,
+        },
+    },
     export_include_dirs: ["include_fstab"],
     header_libs: ["libbase_headers"],
 }
diff --git a/fs_mgr/README.overlayfs.md b/fs_mgr/README.overlayfs.md
index 960410c..8784c94 100644
--- a/fs_mgr/README.overlayfs.md
+++ b/fs_mgr/README.overlayfs.md
@@ -53,9 +53,13 @@
     $ adb disable-verity
     $ adb reboot
 
-can be replaced with:
+*or*
 
-    $ adb reboot -R
+    $ adb remount
+
+can be replaced in both places with:
+
+    $ adb remount -R
 
 which will not reboot if everything is already prepared and ready
 to go.
diff --git a/fs_mgr/fs_mgr.cpp b/fs_mgr/fs_mgr.cpp
index 9f6c550..785f9a2 100644
--- a/fs_mgr/fs_mgr.cpp
+++ b/fs_mgr/fs_mgr.cpp
@@ -954,6 +954,17 @@
     std::map<std::string, std::string> device_map_;
 };
 
+static bool IsMountPointMounted(const std::string& mount_point) {
+    // Check if this is already mounted.
+    Fstab fstab;
+    if (!ReadFstabFromFile("/proc/mounts", &fstab)) {
+        return false;
+    }
+    auto it = std::find_if(fstab.begin(), fstab.end(),
+                           [&](const auto& entry) { return entry.mount_point == mount_point; });
+    return it != fstab.end();
+}
+
 // When multiple fstab records share the same mount_point, it will try to mount each
 // one in turn, and ignore any duplicates after a first successful mount.
 // Returns -1 on error, and  FS_MGR_MNTALL_* otherwise.
@@ -970,9 +981,18 @@
     for (size_t i = 0; i < fstab->size(); i++) {
         auto& current_entry = (*fstab)[i];
 
+        // If a filesystem should have been mounted in the first stage, we
+        // ignore it here. With one exception, if the filesystem is
+        // formattable, then it can only be formatted in the second stage,
+        // so we allow it to mount here.
+        if (current_entry.fs_mgr_flags.first_stage_mount &&
+            (!current_entry.fs_mgr_flags.formattable ||
+             IsMountPointMounted(current_entry.mount_point))) {
+            continue;
+        }
+
         // Don't mount entries that are managed by vold or not for the mount mode.
         if (current_entry.fs_mgr_flags.vold_managed || current_entry.fs_mgr_flags.recovery_only ||
-            current_entry.fs_mgr_flags.first_stage_mount ||
             ((mount_mode == MOUNT_MODE_LATE) && !current_entry.fs_mgr_flags.late_mount) ||
             ((mount_mode == MOUNT_MODE_EARLY) && current_entry.fs_mgr_flags.late_mount)) {
             continue;
diff --git a/fs_mgr/tests/adb-remount-test.sh b/fs_mgr/tests/adb-remount-test.sh
index a849578..825109f 100755
--- a/fs_mgr/tests/adb-remount-test.sh
+++ b/fs_mgr/tests/adb-remount-test.sh
@@ -378,7 +378,7 @@
   D=`echo / /
      echo "${D}" | grep -v /dev/root`
 fi
-D=`echo "${D}" | cut -s -d' ' -f1`
+D=`echo "${D}" | cut -s -d' ' -f1 | sort -u`
 D=`adb_sh df -k ${D} </dev/null`
 echo "${D}"
 if [ X"${D}" = X"${D##* 100[%] }" ]; then
@@ -506,7 +506,9 @@
     echo "${D}" &&
     echo "${D}" | grep "^overlay .* /system\$" >/dev/null ||
     die  "overlay takeover after remount"
-  !(adb_sh grep "^overlay " /proc/mounts </dev/null | grep -v "^overlay /vendor/..* overlay ro," | grep " overlay ro,") &&
+  !(adb_sh grep "^overlay " /proc/mounts </dev/null |
+    grep -v "^overlay /\(vendor\|system\)/..* overlay ro," |
+    grep " overlay ro,") &&
     !(adb_sh grep " rw," /proc/mounts </dev/null |
       skip_administrative_mounts data) ||
     die "remount overlayfs missed a spot (ro)"
diff --git a/healthd/BatteryMonitor.cpp b/healthd/BatteryMonitor.cpp
index a1519da..06c8176 100644
--- a/healthd/BatteryMonitor.cpp
+++ b/healthd/BatteryMonitor.cpp
@@ -26,6 +26,8 @@
 #include <stdlib.h>
 #include <sys/types.h>
 #include <unistd.h>
+
+#include <algorithm>
 #include <memory>
 
 #include <android-base/file.h>
@@ -476,10 +478,16 @@
 
         while ((entry = readdir(dir.get()))) {
             const char* name = entry->d_name;
+            std::vector<String8>::iterator itIgnoreName;
 
             if (!strcmp(name, ".") || !strcmp(name, ".."))
                 continue;
 
+            itIgnoreName = find(hc->ignorePowerSupplyNames.begin(),
+                                hc->ignorePowerSupplyNames.end(), String8(name));
+            if (itIgnoreName != hc->ignorePowerSupplyNames.end())
+                continue;
+
             // Look for "type" file in each subdirectory
             path.clear();
             path.appendFormat("%s/%s/type", POWER_SUPPLY_SYSFS_PATH, name);
diff --git a/healthd/include/healthd/healthd.h b/healthd/include/healthd/healthd.h
index c01e8d7..a900071 100644
--- a/healthd/include/healthd/healthd.h
+++ b/healthd/include/healthd/healthd.h
@@ -22,6 +22,8 @@
 #include <utils/Errors.h>
 #include <utils/String8.h>
 
+#include <vector>
+
 // periodic_chores_interval_fast, periodic_chores_interval_slow: intervals at
 // which healthd wakes up to poll health state and perform periodic chores,
 // in units of seconds:
@@ -71,6 +73,7 @@
     int (*energyCounter)(int64_t *);
     int boot_min_cap;
     bool (*screen_on)(android::BatteryProperties *props);
+    std::vector<android::String8> ignorePowerSupplyNames;
 };
 
 enum EventWakeup {
diff --git a/init/README.md b/init/README.md
index 8d47e0a..3a7c71c 100644
--- a/init/README.md
+++ b/init/README.md
@@ -482,9 +482,8 @@
   -f: force installation of the module even if the version of the running kernel
   and the version of the kernel for which the module was compiled do not match.
 
-`load_all_props`
-> Loads properties from /system, /vendor, et cetera.
-  This is included in the default init.rc.
+`load_system_props`
+> (This action is deprecated and no-op.)
 
 `load_persist_props`
 > Loads persistent properties when /data has been decrypted.
diff --git a/init/builtins.cpp b/init/builtins.cpp
index 4a66e46..43a520f 100644
--- a/init/builtins.cpp
+++ b/init/builtins.cpp
@@ -972,7 +972,7 @@
 }
 
 static Result<Success> do_load_system_props(const BuiltinArguments& args) {
-    load_system_props();
+    LOG(INFO) << "deprecated action `load_system_props` called.";
     return Success();
 }
 
diff --git a/init/init.cpp b/init/init.cpp
index dc46a82..d360fdd 100644
--- a/init/init.cpp
+++ b/init/init.cpp
@@ -451,6 +451,8 @@
     // Also, binder can't be used by recovery.
 #ifndef RECOVERY
     android::ProcessState::self()->setThreadPoolMaxThreadCount(0);
+    android::ProcessState::self()->setCallRestriction(
+            ProcessState::CallRestriction::ERROR_IF_NOT_ONEWAY);
 #endif
     return Success();
 }
diff --git a/init/property_service.cpp b/init/property_service.cpp
index 5328869..3199d45 100644
--- a/init/property_service.cpp
+++ b/init/property_service.cpp
@@ -699,22 +699,6 @@
     }
 }
 
-void property_load_boot_defaults() {
-    if (!load_properties_from_file("/system/etc/prop.default", NULL)) {
-        // Try recovery path
-        if (!load_properties_from_file("/prop.default", NULL)) {
-            // Try legacy path
-            load_properties_from_file("/default.prop", NULL);
-        }
-    }
-    load_properties_from_file("/product/build.prop", NULL);
-    load_properties_from_file("/product_services/build.prop", NULL);
-    load_properties_from_file("/odm/default.prop", NULL);
-    load_properties_from_file("/vendor/default.prop", NULL);
-
-    update_sys_usb_config();
-}
-
 static void load_override_properties() {
     if (ALLOW_LOCAL_PROP_OVERRIDE) {
         load_properties_from_file("/data/local.prop", NULL);
@@ -779,12 +763,29 @@
     close(fd);
 }
 
-void load_system_props() {
+void property_load_boot_defaults() {
+    // TODO(b/117892318): merge prop.default and build.prop files into one
+    // TODO(b/122864654): read the prop files from all partitions and then
+    // resolve the duplication by their origin so that RO and non-RO properties
+    // have a consistent overriding order.
+    if (!load_properties_from_file("/system/etc/prop.default", NULL)) {
+        // Try recovery path
+        if (!load_properties_from_file("/prop.default", NULL)) {
+            // Try legacy path
+            load_properties_from_file("/default.prop", NULL);
+        }
+    }
+    load_properties_from_file("/product/build.prop", NULL);
+    load_properties_from_file("/product_services/build.prop", NULL);
+    load_properties_from_file("/odm/default.prop", NULL);
+    load_properties_from_file("/vendor/default.prop", NULL);
     load_properties_from_file("/system/build.prop", NULL);
     load_properties_from_file("/odm/build.prop", NULL);
     load_properties_from_file("/vendor/build.prop", NULL);
     load_properties_from_file("/factory/factory.prop", "ro.*");
     load_recovery_id_prop();
+
+    update_sys_usb_config();
 }
 
 static int SelinuxAuditCallback(void* data, security_class_t /*cls*/, char* buf, size_t len) {
diff --git a/init/service.cpp b/init/service.cpp
index eec55c3..f3eafe4 100644
--- a/init/service.cpp
+++ b/init/service.cpp
@@ -406,7 +406,7 @@
 
     // If we crash > 4 times in 4 minutes, reboot into bootloader or set crashing property
     boot_clock::time_point now = boot_clock::now();
-    if (((flags_ & SVC_CRITICAL) || classnames_.count("updatable")) && !(flags_ & SVC_RESTART)) {
+    if (((flags_ & SVC_CRITICAL) || !pre_apexd_) && !(flags_ & SVC_RESTART)) {
         if (now < time_crashed_ + 4min) {
             if (++crash_count_ > 4) {
                 if (flags_ & SVC_CRITICAL) {
diff --git a/janitors/OWNERS b/janitors/OWNERS
new file mode 100644
index 0000000..0610b41
--- /dev/null
+++ b/janitors/OWNERS
@@ -0,0 +1,4 @@
+# OWNERS file for projects that don't really have owners so much as volunteer janitors.
+enh@google.com
+hhb@google.com
+narayan@google.com
diff --git a/libmeminfo/include/meminfo/meminfo.h b/libmeminfo/include/meminfo/meminfo.h
index 5ee32d4..2fc7867 100644
--- a/libmeminfo/include/meminfo/meminfo.h
+++ b/libmeminfo/include/meminfo/meminfo.h
@@ -72,15 +72,10 @@
         : start(s), end(e), offset(off), flags(f), name(n) {}
     ~Vma() = default;
 
-    void clear() {
-        memset(&usage, 0, sizeof(usage));
-        memset(&wss, 0, sizeof(wss));
-    }
+    void clear() { memset(&usage, 0, sizeof(usage)); }
 
     // Memory usage of this mapping.
     MemUsage usage;
-    // Working set within this mapping.
-    MemUsage wss;
 };
 
 }  // namespace meminfo
diff --git a/libmeminfo/include/meminfo/procmeminfo.h b/libmeminfo/include/meminfo/procmeminfo.h
index 0bfd80f..0b66074 100644
--- a/libmeminfo/include/meminfo/procmeminfo.h
+++ b/libmeminfo/include/meminfo/procmeminfo.h
@@ -64,7 +64,12 @@
     //   private_dirty
     //   SwapPss
     // All other fields of MemUsage are zeroed.
-    bool SmapsOrRollup(bool use_rollup, MemUsage* stats) const;
+    bool SmapsOrRollup(MemUsage* stats) const;
+
+    // Used to parse either of /proc/<pid>/{smaps, smaps_rollup} and record the process's
+    // Pss.
+    // Returns 'true' on success and the value of Pss in the out parameter.
+    bool SmapsOrRollupPss(uint64_t* pss) const;
 
     const std::vector<uint16_t>& SwapOffsets();
 
@@ -82,7 +87,6 @@
     std::vector<Vma> maps_;
 
     MemUsage usage_;
-    MemUsage wss_;
     std::vector<uint16_t> swap_offsets_;
 };
 
@@ -90,10 +94,21 @@
 // same format as /proc/<pid>/smaps. Returns 'false' if the file is malformed.
 bool ForEachVmaFromFile(const std::string& path, const VmaCallback& callback);
 
+// Returns if the kernel supports /proc/<pid>/smaps_rollup. Assumes that the
+// calling process has access to the /proc/<pid>/smaps_rollup.
+// Returns 'false' if the calling process has no permission to read the file if it exists
+// of if the file doesn't exist.
+bool IsSmapsRollupSupported(pid_t pid);
+
 // Same as ProcMemInfo::SmapsOrRollup but reads the statistics directly
 // from a file. The file MUST be in the same format as /proc/<pid>/smaps
 // or /proc/<pid>/smaps_rollup
 bool SmapsOrRollupFromFile(const std::string& path, MemUsage* stats);
 
+// Same as ProcMemInfo::SmapsOrRollupPss but reads the statistics directly
+// from a file and returns total Pss in kB. The file MUST be in the same format
+// as /proc/<pid>/smaps or /proc/<pid>/smaps_rollup
+bool SmapsOrRollupPssFromFile(const std::string& path, uint64_t* pss);
+
 }  // namespace meminfo
 }  // namespace android
diff --git a/libmeminfo/libmeminfo_test.cpp b/libmeminfo/libmeminfo_test.cpp
index 20ed3bf..7d85dd2 100644
--- a/libmeminfo/libmeminfo_test.cpp
+++ b/libmeminfo/libmeminfo_test.cpp
@@ -284,13 +284,13 @@
     EXPECT_EQ(swap_offsets.size(), 0);
 }
 
-TEST(TestProcMemInfo, SmapsOrRollupReturn) {
-    // if /proc/<pid>/smaps_rollup file exists, .SmapsRollup() must return true;
-    // false otherwise
+TEST(TestProcMemInfo, IsSmapsSupportedTest) {
     std::string path = ::android::base::StringPrintf("/proc/%d/smaps_rollup", pid);
-    ProcMemInfo proc_mem(pid);
-    MemUsage stats;
-    EXPECT_EQ(!access(path.c_str(), F_OK), proc_mem.SmapsOrRollup(true, &stats));
+    bool supported = IsSmapsRollupSupported(pid);
+    EXPECT_EQ(!access(path.c_str(), F_OK | R_OK), supported);
+    // Second call must return what the first one returned regardless of the pid parameter.
+    // So, deliberately pass invalid pid.
+    EXPECT_EQ(supported, IsSmapsRollupSupported(-1));
 }
 
 TEST(TestProcMemInfo, SmapsOrRollupTest) {
@@ -365,6 +365,50 @@
     EXPECT_EQ(stats.swap_pss, 70);
 }
 
+TEST(TestProcMemInfo, SmapsOrRollupPssRollupTest) {
+    // This is a made up smaps for the test
+    std::string smaps =
+            R"smaps(12c00000-13440000 rw-p 00000000 00:00 0                                  [anon:dalvik-main space (region space)]
+Name:           [anon:dalvik-main space (region space)]
+Size:               8448 kB
+KernelPageSize:        4 kB
+MMUPageSize:           4 kB
+Rss:                2652 kB
+Pss:                2652 kB
+Shared_Clean:        840 kB
+Shared_Dirty:         40 kB
+Private_Clean:        84 kB
+Private_Dirty:      2652 kB
+Referenced:         2652 kB
+Anonymous:          2652 kB
+AnonHugePages:         0 kB
+ShmemPmdMapped:        0 kB
+Shared_Hugetlb:        0 kB
+Private_Hugetlb:       0 kB
+Swap:                102 kB
+SwapPss:              70 kB
+Locked:             2652 kB
+VmFlags: rd wr mr mw me ac 
+)smaps";
+
+    TemporaryFile tf;
+    ASSERT_TRUE(tf.fd != -1);
+    ASSERT_TRUE(::android::base::WriteStringToFd(smaps, tf.fd));
+
+    uint64_t pss;
+    ASSERT_EQ(SmapsOrRollupPssFromFile(tf.path, &pss), true);
+    EXPECT_EQ(pss, 2652);
+}
+
+TEST(TestProcMemInfo, SmapsOrRollupPssSmapsTest) {
+    std::string exec_dir = ::android::base::GetExecutableDirectory();
+    std::string path = ::android::base::StringPrintf("%s/testdata1/smaps_short", exec_dir.c_str());
+
+    uint64_t pss;
+    ASSERT_EQ(SmapsOrRollupPssFromFile(path, &pss), true);
+    EXPECT_EQ(pss, 19119);
+}
+
 TEST(TestProcMemInfo, ForEachVmaFromFileTest) {
     std::string exec_dir = ::android::base::GetExecutableDirectory();
     std::string path = ::android::base::StringPrintf("%s/testdata1/smaps_short", exec_dir.c_str());
@@ -374,6 +418,9 @@
     auto collect_vmas = [&](const Vma& v) { vmas.push_back(v); };
     ASSERT_TRUE(ForEachVmaFromFile(path, collect_vmas));
 
+    // We should get a total of 6 vmas
+    ASSERT_EQ(vmas.size(), 6);
+
     // Expect values to be equal to what we have in testdata1/smaps_short
     // Check for sizes first
     ASSERT_EQ(vmas[0].usage.vss, 32768);
@@ -468,6 +515,8 @@
     auto vmas = proc_mem.Smaps(path);
 
     ASSERT_FALSE(vmas.empty());
+    // We should get a total of 6 vmas
+    ASSERT_EQ(vmas.size(), 6);
 
     // Expect values to be equal to what we have in testdata1/smaps_short
     // Check for sizes first
diff --git a/libmeminfo/procmeminfo.cpp b/libmeminfo/procmeminfo.cpp
index 1f8db1a..d6332a3 100644
--- a/libmeminfo/procmeminfo.cpp
+++ b/libmeminfo/procmeminfo.cpp
@@ -21,6 +21,7 @@
 #include <stdio.h>
 #include <unistd.h>
 
+#include <atomic>
 #include <fstream>
 #include <iostream>
 #include <memory>
@@ -157,14 +158,14 @@
     if (!get_wss_) {
         LOG(WARNING) << "Trying to read process working set for " << pid_
                      << " using invalid object";
-        return wss_;
+        return usage_;
     }
 
     if (maps_.empty() && !ReadMaps(get_wss_)) {
         LOG(ERROR) << "Failed to get working set for Process " << pid_;
     }
 
-    return wss_;
+    return usage_;
 }
 
 bool ProcMemInfo::ForEachVma(const VmaCallback& callback) {
@@ -172,11 +173,17 @@
     return ForEachVmaFromFile(path, callback);
 }
 
-bool ProcMemInfo::SmapsOrRollup(bool use_rollup, MemUsage* stats) const {
-    std::string path = ::android::base::StringPrintf("/proc/%d/%s", pid_,
-                                                     use_rollup ? "smaps_rollup" : "smaps");
+bool ProcMemInfo::SmapsOrRollup(MemUsage* stats) const {
+    std::string path = ::android::base::StringPrintf(
+            "/proc/%d/%s", pid_, IsSmapsRollupSupported(pid_) ? "smaps_rollup" : "smaps");
     return SmapsOrRollupFromFile(path, stats);
-};
+}
+
+bool ProcMemInfo::SmapsOrRollupPss(uint64_t* pss) const {
+    std::string path = ::android::base::StringPrintf(
+            "/proc/%d/%s", pid_, IsSmapsRollupSupported(pid_) ? "smaps_rollup" : "smaps");
+    return SmapsOrRollupPssFromFile(path, pss);
+}
 
 const std::vector<uint16_t>& ProcMemInfo::SwapOffsets() {
     if (get_wss_) {
@@ -228,11 +235,7 @@
             maps_.clear();
             return false;
         }
-        if (get_wss) {
-            add_mem_usage(&wss_, vma.wss);
-        } else {
-            add_mem_usage(&usage_, vma.usage);
-        }
+        add_mem_usage(&usage_, vma.usage);
     }
 
     return true;
@@ -300,31 +303,20 @@
             // This effectively makes vss = rss for the working set is requested.
             // The libpagemap implementation returns vss > rss for
             // working set, which doesn't make sense.
-            vma.wss.vss += pagesz;
-            vma.wss.rss += pagesz;
-            vma.wss.uss += is_private ? pagesz : 0;
-            vma.wss.pss += pagesz / pg_counts[i];
-            if (is_private) {
-                vma.wss.private_dirty += is_dirty ? pagesz : 0;
-                vma.wss.private_clean += is_dirty ? 0 : pagesz;
-            } else {
-                vma.wss.shared_dirty += is_dirty ? pagesz : 0;
-                vma.wss.shared_clean += is_dirty ? 0 : pagesz;
-            }
+            vma.usage.vss += pagesz;
+        }
+
+        vma.usage.rss += pagesz;
+        vma.usage.uss += is_private ? pagesz : 0;
+        vma.usage.pss += pagesz / pg_counts[i];
+        if (is_private) {
+            vma.usage.private_dirty += is_dirty ? pagesz : 0;
+            vma.usage.private_clean += is_dirty ? 0 : pagesz;
         } else {
-            vma.usage.rss += pagesz;
-            vma.usage.uss += is_private ? pagesz : 0;
-            vma.usage.pss += pagesz / pg_counts[i];
-            if (is_private) {
-                vma.usage.private_dirty += is_dirty ? pagesz : 0;
-                vma.usage.private_clean += is_dirty ? 0 : pagesz;
-            } else {
-                vma.usage.shared_dirty += is_dirty ? pagesz : 0;
-                vma.usage.shared_clean += is_dirty ? 0 : pagesz;
-            }
+            vma.usage.shared_dirty += is_dirty ? pagesz : 0;
+            vma.usage.shared_clean += is_dirty ? 0 : pagesz;
         }
     }
-
     return true;
 }
 
@@ -338,8 +330,9 @@
     char* line = nullptr;
     bool parsing_vma = false;
     ssize_t line_len;
+    size_t line_alloc = 0;
     Vma vma;
-    while ((line_len = getline(&line, 0, fp.get())) > 0) {
+    while ((line_len = getline(&line, &line_alloc, fp.get())) > 0) {
         // Make sure the line buffer terminates like a C string for ReadMapFile
         line[line_len] = '\0';
 
@@ -382,15 +375,41 @@
     return true;
 }
 
+enum smaps_rollup_support { UNTRIED, SUPPORTED, UNSUPPORTED };
+
+static std::atomic<smaps_rollup_support> g_rollup_support = UNTRIED;
+
+bool IsSmapsRollupSupported(pid_t pid) {
+    // Similar to OpenSmapsOrRollup checks from android_os_Debug.cpp, except
+    // the method only checks if rollup is supported and returns the status
+    // right away.
+    enum smaps_rollup_support rollup_support = g_rollup_support.load(std::memory_order_relaxed);
+    if (rollup_support != UNTRIED) {
+        return rollup_support == SUPPORTED;
+    }
+    std::string rollup_file = ::android::base::StringPrintf("/proc/%d/smaps_rollup", pid);
+    if (access(rollup_file.c_str(), F_OK | R_OK)) {
+        // No check for errno = ENOENT necessary here. The caller MUST fallback to
+        // using /proc/<pid>/smaps instead anyway.
+        g_rollup_support.store(UNSUPPORTED, std::memory_order_relaxed);
+        return false;
+    }
+
+    g_rollup_support.store(SUPPORTED, std::memory_order_relaxed);
+    LOG(INFO) << "Using smaps_rollup for pss collection";
+    return true;
+}
+
 bool SmapsOrRollupFromFile(const std::string& path, MemUsage* stats) {
     auto fp = std::unique_ptr<FILE, decltype(&fclose)>{fopen(path.c_str(), "re"), fclose};
     if (fp == nullptr) {
         return false;
     }
 
-    char line[1024];
+    char* line = nullptr;
+    size_t line_alloc = 0;
     stats->clear();
-    while (fgets(line, sizeof(line), fp.get()) != nullptr) {
+    while (getline(&line, &line_alloc, fp.get()) > 0) {
         switch (line[0]) {
             case 'P':
                 if (strncmp(line, "Pss:", 4) == 0) {
@@ -423,6 +442,28 @@
         }
     }
 
+    // free getline() managed buffer
+    free(line);
+    return true;
+}
+
+bool SmapsOrRollupPssFromFile(const std::string& path, uint64_t* pss) {
+    auto fp = std::unique_ptr<FILE, decltype(&fclose)>{fopen(path.c_str(), "re"), fclose};
+    if (fp == nullptr) {
+        return false;
+    }
+    *pss = 0;
+    char* line = nullptr;
+    size_t line_alloc = 0;
+    while (getline(&line, &line_alloc, fp.get()) > 0) {
+        uint64_t v;
+        if (sscanf(line, "Pss: %" SCNu64 " kB", &v) == 1) {
+            *pss += v;
+        }
+    }
+
+    // free getline() managed buffer
+    free(line);
     return true;
 }
 
diff --git a/libmeminfo/tools/procmem.cpp b/libmeminfo/tools/procmem.cpp
index b9b174d..47881ed 100644
--- a/libmeminfo/tools/procmem.cpp
+++ b/libmeminfo/tools/procmem.cpp
@@ -98,7 +98,7 @@
     std::stringstream ss;
     print_header(ss);
     for (auto& vma : maps) {
-        const MemUsage& vma_stats = show_wss ? vma.wss : vma.usage;
+        const MemUsage& vma_stats = vma.usage;
         if (hide_zeroes && vma_stats.rss == 0) {
             continue;
         }
@@ -116,14 +116,14 @@
 int main(int argc, char* argv[]) {
     int opt;
     auto pss_sort = [](const Vma& a, const Vma& b) {
-        uint64_t pss_a = show_wss ? a.wss.pss : a.usage.pss;
-        uint64_t pss_b = show_wss ? b.wss.pss : b.usage.pss;
+        uint64_t pss_a = a.usage.pss;
+        uint64_t pss_b = b.usage.pss;
         return pss_a > pss_b;
     };
 
     auto uss_sort = [](const Vma& a, const Vma& b) {
-        uint64_t uss_a = show_wss ? a.wss.uss : a.usage.uss;
-        uint64_t uss_b = show_wss ? b.wss.uss : b.usage.uss;
+        uint64_t uss_a = a.usage.uss;
+        uint64_t uss_b = b.usage.uss;
         return uss_a > uss_b;
     };
 
@@ -182,7 +182,7 @@
     }
 
     ProcMemInfo proc(pid, show_wss);
-    const MemUsage& proc_stats = show_wss ? proc.Wss() : proc.Usage();
+    const MemUsage& proc_stats = proc.Usage();
     std::vector<Vma> maps(proc.Maps());
     if (sort_func != nullptr) {
         std::sort(maps.begin(), maps.end(), sort_func);
diff --git a/libmeminfo/tools/procrank.cpp b/libmeminfo/tools/procrank.cpp
index a751722..21a684c 100644
--- a/libmeminfo/tools/procrank.cpp
+++ b/libmeminfo/tools/procrank.cpp
@@ -465,7 +465,7 @@
         }
 
         // Skip processes with no memory mappings
-        uint64_t vss = show_wss ? proc.Wss().vss : proc.Usage().vss;
+        uint64_t vss = proc.Usage().vss;
         if (vss == 0) return true;
 
         // collect swap_offset counts from all processes in 1st pass
diff --git a/libnativebridge/Android.bp b/libnativebridge/Android.bp
index 92fd2a2..c54570e 100644
--- a/libnativebridge/Android.bp
+++ b/libnativebridge/Android.bp
@@ -17,6 +17,20 @@
         "liblog",
     ],
 
+    target: {
+        android: {
+            version_script: "libnativebridge.map.txt",
+        },
+        linux: {
+            version_script: "libnativebridge.map.txt",
+        },
+    },
+
+    stubs: {
+        symbol_file: "libnativebridge.map.txt",
+        versions: ["1"],
+    },
+
     export_include_dirs: ["include"],
 
     cflags: [
diff --git a/libnativebridge/OWNERS b/libnativebridge/OWNERS
index f2cc942..6f0824b 100644
--- a/libnativebridge/OWNERS
+++ b/libnativebridge/OWNERS
@@ -1 +1,2 @@
 dimitry@google.com
+eaeltsin@google.com
diff --git a/libnativebridge/include/nativebridge/native_bridge.h b/libnativebridge/include/nativebridge/native_bridge.h
index 28f1927..5aea967 100644
--- a/libnativebridge/include/nativebridge/native_bridge.h
+++ b/libnativebridge/include/nativebridge/native_bridge.h
@@ -17,12 +17,17 @@
 #ifndef NATIVE_BRIDGE_H_
 #define NATIVE_BRIDGE_H_
 
-#include "jni.h"
 #include <signal.h>
+#include <stdbool.h>
 #include <stdint.h>
 #include <sys/types.h>
 
+#include "jni.h"
+
+#ifdef __cplusplus
 namespace android {
+extern "C" {
+#endif  // __cplusplus
 
 struct NativeBridgeRuntimeCallbacks;
 struct NativeBridgeRuntimeValues;
@@ -32,11 +37,10 @@
 // to the chain.
 typedef bool (*NativeBridgeSignalHandlerFn)(int, siginfo_t*, void*);
 
-
 // Open the native bridge, if any. Should be called by Runtime::Init(). A null library filename
 // signals that we do not want to load a native bridge.
 bool LoadNativeBridge(const char* native_bridge_library_filename,
-                      const NativeBridgeRuntimeCallbacks* runtime_callbacks);
+                      const struct NativeBridgeRuntimeCallbacks* runtime_callbacks);
 
 // Quick check whether a native bridge will be needed. This is based off of the instruction set
 // of the process.
@@ -138,19 +142,17 @@
 //
 // Starting with v3, NativeBridge has two scenarios: with/without namespace.
 // Should not use in non-namespace scenario.
-native_bridge_namespace_t* NativeBridgeCreateNamespace(const char* name,
-                                                       const char* ld_library_path,
-                                                       const char* default_library_path,
-                                                       uint64_t type,
-                                                       const char* permitted_when_isolated_path,
-                                                       native_bridge_namespace_t* parent_ns);
+struct native_bridge_namespace_t* NativeBridgeCreateNamespace(
+    const char* name, const char* ld_library_path, const char* default_library_path, uint64_t type,
+    const char* permitted_when_isolated_path, struct native_bridge_namespace_t* parent_ns);
 
 // Creates a link which shares some libraries from one namespace to another.
 // NativeBridge's peer of android_link_namespaces() of dynamic linker.
 //
 // Starting with v3, NativeBridge has two scenarios: with/without namespace.
 // Should not use in non-namespace scenario.
-bool NativeBridgeLinkNamespaces(native_bridge_namespace_t* from, native_bridge_namespace_t* to,
+bool NativeBridgeLinkNamespaces(struct native_bridge_namespace_t* from,
+                                struct native_bridge_namespace_t* to,
                                 const char* shared_libs_sonames);
 
 // Load a shared library with namespace key that is supported by the native bridge.
@@ -159,10 +161,11 @@
 //
 // Starting with v3, NativeBridge has two scenarios: with/without namespace.
 // Use NativeBridgeLoadLibrary() instead in non-namespace scenario.
-void* NativeBridgeLoadLibraryExt(const char* libpath, int flag, native_bridge_namespace_t* ns);
+void* NativeBridgeLoadLibraryExt(const char* libpath, int flag,
+                                 struct native_bridge_namespace_t* ns);
 
 // Returns vendor namespace if it is enabled for the device and null otherwise
-native_bridge_namespace_t* NativeBridgeGetVendorNamespace();
+struct native_bridge_namespace_t* NativeBridgeGetVendorNamespace();
 
 // Native bridge interfaces to runtime.
 struct NativeBridgeCallbacks {
@@ -177,8 +180,8 @@
   //   runtime_cbs [IN] the pointer to NativeBridgeRuntimeCallbacks.
   // Returns:
   //   true if initialization was successful.
-  bool (*initialize)(const NativeBridgeRuntimeCallbacks* runtime_cbs, const char* private_dir,
-                     const char* instruction_set);
+  bool (*initialize)(const struct NativeBridgeRuntimeCallbacks* runtime_cbs,
+                     const char* private_dir, const char* instruction_set);
 
   // Load a shared library that is supported by the native bridge.
   //
@@ -314,12 +317,12 @@
   //
   // Starting with v3, NativeBridge has two scenarios: with/without namespace.
   // Should not use in non-namespace scenario.
-  native_bridge_namespace_t* (*createNamespace)(const char* name,
-                                                const char* ld_library_path,
-                                                const char* default_library_path,
-                                                uint64_t type,
-                                                const char* permitted_when_isolated_path,
-                                                native_bridge_namespace_t* parent_ns);
+  struct native_bridge_namespace_t* (*createNamespace)(const char* name,
+                                                       const char* ld_library_path,
+                                                       const char* default_library_path,
+                                                       uint64_t type,
+                                                       const char* permitted_when_isolated_path,
+                                                       struct native_bridge_namespace_t* parent_ns);
 
   // Creates a link which shares some libraries from one namespace to another.
   // NativeBridge's peer of android_link_namespaces() of dynamic linker.
@@ -334,8 +337,8 @@
   //
   // Starting with v3, NativeBridge has two scenarios: with/without namespace.
   // Should not use in non-namespace scenario.
-  bool (*linkNamespaces)(native_bridge_namespace_t* from, native_bridge_namespace_t* to,
-                         const char* shared_libs_sonames);
+  bool (*linkNamespaces)(struct native_bridge_namespace_t* from,
+                         struct native_bridge_namespace_t* to, const char* shared_libs_sonames);
 
   // Load a shared library within a namespace.
   // NativeBridge's peer of android_dlopen_ext() of dynamic linker, only supports namespace
@@ -350,7 +353,7 @@
   //
   // Starting with v3, NativeBridge has two scenarios: with/without namespace.
   // Use loadLibrary instead in non-namespace scenario.
-  void* (*loadLibraryExt)(const char* libpath, int flag, native_bridge_namespace_t* ns);
+  void* (*loadLibraryExt)(const char* libpath, int flag, struct native_bridge_namespace_t* ns);
 
   // Get native bridge version of vendor namespace.
   // The vendor namespace is the namespace used to load vendor public libraries.
@@ -359,7 +362,7 @@
   //
   // Returns:
   //   vendor namespace or null if it was not set up for the device
-  native_bridge_namespace_t* (*getVendorNamespace)();
+  struct native_bridge_namespace_t* (*getVendorNamespace)();
 };
 
 // Runtime interfaces to native bridge.
@@ -396,6 +399,9 @@
                                uint32_t method_count);
 };
 
-};  // namespace android
+#ifdef __cplusplus
+}  // extern "C"
+}  // namespace android
+#endif  // __cplusplus
 
 #endif  // NATIVE_BRIDGE_H_
diff --git a/libnativebridge/libnativebridge.map.txt b/libnativebridge/libnativebridge.map.txt
new file mode 100644
index 0000000..a616b85
--- /dev/null
+++ b/libnativebridge/libnativebridge.map.txt
@@ -0,0 +1,45 @@
+#
+# Copyright (C) 2019 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+#  Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+# TODO(b/122710865): Most of these uses come from libnativeloader, which should be bundled
+# together with libnativebridge in the APEX. Once this happens, prune this list.
+LIBNATIVEBRIDGE_1 {
+  global:
+    NativeBridgeIsSupported;
+    NativeBridgeLoadLibrary;
+    NativeBridgeUnloadLibrary;
+    NativeBridgeGetError;
+    NativeBridgeIsPathSupported;
+    NativeBridgeCreateNamespace;
+    NativeBridgeGetVendorNamespace;
+    NativeBridgeLinkNamespaces;
+    NativeBridgeLoadLibraryExt;
+    NativeBridgeInitAnonymousNamespace;
+    NativeBridgeInitialized;
+    NativeBridgeGetTrampoline;
+    LoadNativeBridge;
+    PreInitializeNativeBridge;
+    InitializeNativeBridge;
+    NativeBridgeGetVersion;
+    NativeBridgeGetSignalHandler;
+    UnloadNativeBridge;
+    NativeBridgeAvailable;
+    NeedsNativeBridge;
+    NativeBridgeError;
+    NativeBridgeNameAcceptable;
+  local:
+    *;
+};
diff --git a/libnativebridge/native_bridge.cc b/libnativebridge/native_bridge.cc
index e24307a..a2d8d81 100644
--- a/libnativebridge/native_bridge.cc
+++ b/libnativebridge/native_bridge.cc
@@ -33,6 +33,13 @@
 
 namespace android {
 
+#ifdef __APPLE__
+template <typename T>
+void UNUSED(const T&) {}
+#endif
+
+extern "C" {
+
 // Environment values required by the apps running with native bridge.
 struct NativeBridgeRuntimeValues {
     const char* os_arch;
@@ -252,10 +259,6 @@
   return strncmp(instruction_set, ABI_STRING, strlen(ABI_STRING) + 1) != 0;
 }
 
-#ifdef __APPLE__
-template<typename T> void UNUSED(const T&) {}
-#endif
-
 bool PreInitializeNativeBridge(const char* app_data_dir_in, const char* instruction_set) {
   if (state != NativeBridgeState::kOpened) {
     ALOGE("Invalid state: native bridge is expected to be opened.");
@@ -626,4 +629,6 @@
   return nullptr;
 }
 
-};  // namespace android
+}  // extern "C"
+
+}  // namespace android
diff --git a/libnativebridge/tests/Android.bp b/libnativebridge/tests/Android.bp
index 222bc4c..744a4a8 100644
--- a/libnativebridge/tests/Android.bp
+++ b/libnativebridge/tests/Android.bp
@@ -86,3 +86,14 @@
     ],
     header_libs: ["libbase_headers"],
 }
+
+// Build the test for the C API.
+cc_test {
+    name: "libnativebridge-api-tests",
+    host_supported: true,
+    test_per_src: true,
+    srcs: [
+        "NativeBridgeApi.c",
+    ],
+    header_libs: ["libnativebridge-dummy-headers"],
+}
diff --git a/libnativebridge/tests/NativeBridgeApi.c b/libnativebridge/tests/NativeBridgeApi.c
new file mode 100644
index 0000000..7ab71fe
--- /dev/null
+++ b/libnativebridge/tests/NativeBridgeApi.c
@@ -0,0 +1,25 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/* The main purpose of this test is to ensure this C header compiles in C, so
+ * that no C++ features inadvertently leak into the C ABI. */
+#include "nativebridge/native_bridge.h"
+
+int main(int argc, char** argv) {
+  (void)argc;
+  (void)argv;
+  return 0;
+}
diff --git a/libunwindstack/Android.bp b/libunwindstack/Android.bp
index 89d4fc0..e267f58 100644
--- a/libunwindstack/Android.bp
+++ b/libunwindstack/Android.bp
@@ -221,7 +221,6 @@
         "liblog",
         "liblzma",
         "libunwindstack",
-        "libdexfile",
         "libdexfile_support",
     ],
 
diff --git a/libunwindstack/tests/DexFileTest.cpp b/libunwindstack/tests/DexFileTest.cpp
index 21ca47b..0149a42 100644
--- a/libunwindstack/tests/DexFileTest.cpp
+++ b/libunwindstack/tests/DexFileTest.cpp
@@ -21,7 +21,6 @@
 #include <unordered_map>
 
 #include <android-base/file.h>
-#include <dex/dex_file.h>
 #include <gtest/gtest.h>
 #include <unwindstack/MapInfo.h>
 #include <unwindstack/Memory.h>
@@ -40,17 +39,15 @@
   TemporaryFile tf;
   ASSERT_TRUE(tf.fd != -1);
 
-  ASSERT_EQ(sizeof(art::DexFile::Header) - 1,
-            static_cast<size_t>(
-                TEMP_FAILURE_RETRY(write(tf.fd, kDexData, sizeof(art::DexFile::Header) - 1))));
+  ASSERT_EQ(size_t{10}, static_cast<size_t>(TEMP_FAILURE_RETRY(write(tf.fd, kDexData, 10))));
 
   // Header too small.
   EXPECT_TRUE(DexFileFromFile::Create(0, tf.path) == nullptr);
 
   // Header correct, file too small.
   ASSERT_EQ(0, lseek(tf.fd, 0, SEEK_SET));
-  ASSERT_EQ(sizeof(art::DexFile::Header), static_cast<size_t>(TEMP_FAILURE_RETRY(write(
-                                              tf.fd, kDexData, sizeof(art::DexFile::Header)))));
+  ASSERT_EQ(sizeof(kDexData) - 1,
+            static_cast<size_t>(TEMP_FAILURE_RETRY(write(tf.fd, kDexData, sizeof(kDexData) - 1))));
   EXPECT_TRUE(DexFileFromFile::Create(0, tf.path) == nullptr);
 }
 
@@ -78,7 +75,7 @@
 TEST(DexFileTest, from_memory_fail_too_small_for_header) {
   MemoryFake memory;
 
-  memory.SetMemory(0x1000, kDexData, sizeof(art::DexFile::Header) - 1);
+  memory.SetMemory(0x1000, kDexData, 10);
 
   EXPECT_TRUE(DexFileFromMemory::Create(0x1000, &memory, "") == nullptr);
 }
@@ -187,15 +184,6 @@
   ASSERT_TRUE(dex_file->GetMethodInformation(0x118, &method, &method_offset));
   EXPECT_EQ("Main.main", method);
   EXPECT_EQ(0U, method_offset);
-
-  // Make sure that any data that is cached is still retrievable.
-  ASSERT_TRUE(dex_file->GetMethodInformation(0x104, &method, &method_offset));
-  EXPECT_EQ("Main.<init>", method);
-  EXPECT_EQ(4U, method_offset);
-
-  ASSERT_TRUE(dex_file->GetMethodInformation(0x119, &method, &method_offset));
-  EXPECT_EQ("Main.main", method);
-  EXPECT_EQ(1U, method_offset);
 }
 
 TEST(DexFileTest, get_method_empty) {
@@ -210,12 +198,6 @@
   EXPECT_FALSE(dex_file->GetMethodInformation(0x100000, &method, &method_offset));
 
   EXPECT_FALSE(dex_file->GetMethodInformation(0x98, &method, &method_offset));
-
-  // Make sure that once the whole dex file has been cached, no problems occur.
-  EXPECT_FALSE(dex_file->GetMethodInformation(0x98, &method, &method_offset));
-
-  // Choose a value that is in the cached map, but not in a valid method.
-  EXPECT_FALSE(dex_file->GetMethodInformation(0x110, &method, &method_offset));
 }
 
 }  // namespace unwindstack
diff --git a/lmkd/lmkd.c b/lmkd/lmkd.c
index 7794f81..ca78c38 100644
--- a/lmkd/lmkd.c
+++ b/lmkd/lmkd.c
@@ -16,6 +16,7 @@
 
 #define LOG_TAG "lowmemorykiller"
 
+#include <dirent.h>
 #include <errno.h>
 #include <inttypes.h>
 #include <pwd.h>
@@ -28,18 +29,22 @@
 #include <sys/epoll.h>
 #include <sys/eventfd.h>
 #include <sys/mman.h>
+#include <sys/resource.h>
 #include <sys/socket.h>
 #include <sys/sysinfo.h>
+#include <sys/time.h>
 #include <sys/types.h>
 #include <time.h>
 #include <unistd.h>
 
 #include <cutils/properties.h>
+#include <cutils/sched_policy.h>
 #include <cutils/sockets.h>
 #include <lmkd.h>
 #include <log/log.h>
 #include <log/log_event_list.h>
 #include <log/log_time.h>
+#include <system/thread_defs.h>
 
 #ifdef LMKD_LOG_STATS
 #include "statslog.h"
@@ -1261,6 +1266,41 @@
     return maxprocp;
 }
 
+static void set_process_group_and_prio(int pid, SchedPolicy sp, int prio) {
+    DIR* d;
+    char proc_path[PATH_MAX];
+    struct dirent* de;
+
+    snprintf(proc_path, sizeof(proc_path), "/proc/%d/task", pid);
+    if (!(d = opendir(proc_path))) {
+        ALOGW("Failed to open %s; errno=%d: process pid(%d) might have died", proc_path, errno,
+              pid);
+        return;
+    }
+
+    while ((de = readdir(d))) {
+        int t_pid;
+
+        if (de->d_name[0] == '.') continue;
+        t_pid = atoi(de->d_name);
+
+        if (!t_pid) {
+            ALOGW("Failed to get t_pid for '%s' of pid(%d)", de->d_name, pid);
+            continue;
+        }
+
+        if (setpriority(PRIO_PROCESS, t_pid, prio) && errno != ESRCH) {
+            ALOGW("Unable to raise priority of killing t_pid (%d): errno=%d", t_pid, errno);
+        }
+
+        if (set_cpuset_policy(t_pid, sp)) {
+            ALOGW("Failed to set_cpuset_policy on pid(%d) t_pid(%d) to %d", pid, t_pid, (int)sp);
+            continue;
+        }
+    }
+    closedir(d);
+}
+
 static int last_killed_pid = -1;
 
 /* Kill one process specified by procp.  Returns the size of the process killed */
@@ -1301,6 +1341,9 @@
 
     /* CAP_KILL required */
     r = kill(pid, SIGKILL);
+
+    set_process_group_and_prio(pid, SP_FOREGROUND, ANDROID_PRIORITY_HIGHEST);
+
     inc_killcnt(procp->oomadj);
     ALOGI("Kill '%s' (%d), uid %d, oom_adj %d to free %ldkB",
         taskname, pid, uid, procp->oomadj, tasksize * page_k);
diff --git a/lmkd/tests/Android.bp b/lmkd/tests/Android.bp
index cbf44e9..4e845fd 100644
--- a/lmkd/tests/Android.bp
+++ b/lmkd/tests/Android.bp
@@ -18,6 +18,7 @@
     shared_libs: [
         "libbase",
         "liblog",
+        "libcutils",
     ],
 
     static_libs: [
diff --git a/rootdir/init.rc b/rootdir/init.rc
index b34399d..9b20964 100644
--- a/rootdir/init.rc
+++ b/rootdir/init.rc
@@ -346,12 +346,6 @@
     trigger boot
 
 on post-fs
-    # Load properties from
-    #     /system/build.prop,
-    #     /odm/build.prop,
-    #     /vendor/build.prop and
-    #     /factory/factory.prop
-    load_system_props
     start vold
     exec - system system -- /system/bin/vdc checkpoint markBootAttempt