Merge "Add an env variable for the tzdata module root"
diff --git a/adb/client/commandline.cpp b/adb/client/commandline.cpp
index 2b328ab..3d5d9db 100644
--- a/adb/client/commandline.cpp
+++ b/adb/client/commandline.cpp
@@ -1005,7 +1005,8 @@
 #endif /* !defined(_WIN32) */
 }
 
-static bool wait_for_device(const char* service) {
+static bool wait_for_device(const char* service,
+                            std::optional<std::chrono::milliseconds> timeout = std::nullopt) {
     std::vector<std::string> components = android::base::Split(service, "-");
     if (components.size() < 3 || components.size() > 4) {
         fprintf(stderr, "adb: couldn't parse 'wait-for' command: %s\n", service);
@@ -1043,6 +1044,13 @@
     }
 
     std::string cmd = format_host_command(android::base::Join(components, "-").c_str());
+    if (timeout) {
+        std::thread([timeout]() {
+            std::this_thread::sleep_for(*timeout);
+            fprintf(stderr, "timeout expired while waiting for device\n");
+            _exit(1);
+        }).detach();
+    }
     return adb_command(cmd);
 }
 
@@ -1084,8 +1092,21 @@
     }
 
     // Wait for the device to go away.
+    TransportType previous_type;
+    const char* previous_serial;
+    TransportId previous_id;
+    adb_get_transport(&previous_type, &previous_serial, &previous_id);
+
     adb_set_transport(kTransportAny, nullptr, transport_id);
     wait_for_device("wait-for-disconnect");
+
+    // Wait for the device to come back.
+    // If we were using a specific transport ID, there's nothing we can wait for.
+    if (previous_id == 0) {
+        adb_set_transport(previous_type, previous_serial, 0);
+        wait_for_device("wait-for-device", 3000ms);
+    }
+
     return true;
 }
 
diff --git a/adb/daemon/usb.cpp b/adb/daemon/usb.cpp
index a44ff43..f4458a2 100644
--- a/adb/daemon/usb.cpp
+++ b/adb/daemon/usb.cpp
@@ -270,29 +270,15 @@
             bool started = false;
             bool running = true;
             while (running) {
-                int timeout = -1;
-                if (!bound || !started) {
-                    timeout = 5000 /*ms*/;
-                }
-
                 adb_pollfd pfd[2] = {
                   { .fd = control_fd_.get(), .events = POLLIN, .revents = 0 },
                   { .fd = monitor_event_fd_.get(), .events = POLLIN, .revents = 0 },
                 };
-                int rc = TEMP_FAILURE_RETRY(adb_poll(pfd, 2, timeout));
+                int rc = TEMP_FAILURE_RETRY(adb_poll(pfd, 2, -1));
                 if (rc == -1) {
                     PLOG(FATAL) << "poll on USB control fd failed";
                 } else if (rc == 0) {
-                    // Something in the kernel presumably went wrong.
-                    // Close our endpoints, wait for a bit, and then try again.
-                    StopWorker();
-                    aio_context_.reset();
-                    read_fd_.reset();
-                    write_fd_.reset();
-                    control_fd_.reset();
-                    std::this_thread::sleep_for(5s);
-                    HandleError("didn't receive FUNCTIONFS_ENABLE, retrying");
-                    return;
+                    LOG(FATAL) << "poll on USB control fd returned 0";
                 }
 
                 if (pfd[1].revents) {
diff --git a/base/mapped_file.cpp b/base/mapped_file.cpp
index faa845d..7c65dc3 100644
--- a/base/mapped_file.cpp
+++ b/base/mapped_file.cpp
@@ -41,7 +41,14 @@
   HANDLE handle =
       CreateFileMapping(reinterpret_cast<HANDLE>(_get_osfhandle(fd)), nullptr,
                         (prot & PROT_WRITE) ? PAGE_READWRITE : PAGE_READONLY, 0, 0, nullptr);
-  if (handle == nullptr) return nullptr;
+  if (handle == nullptr) {
+    // http://b/119818070 "app crashes when reading asset of zero length".
+    // Return a MappedFile that's only valid for reading the size.
+    if (length == 0) {
+      return std::unique_ptr<MappedFile>(new MappedFile{nullptr, 0, 0, nullptr});
+    }
+    return nullptr;
+  }
   void* base = MapViewOfFile(handle, (prot & PROT_WRITE) ? FILE_MAP_ALL_ACCESS : FILE_MAP_READ, 0,
                              file_offset, file_length);
   if (base == nullptr) {
diff --git a/bootstat/bootstat.cpp b/bootstat/bootstat.cpp
index ed955ea..ea49798 100644
--- a/bootstat/bootstat.cpp
+++ b/bootstat/bootstat.cpp
@@ -293,6 +293,8 @@
     {"kernel_panic,dsps", 166},
     {"kernel_panic,wcnss", 167},
     {"kernel_panic,_sde_encoder_phys_cmd_handle_ppdone_timeout", 168},
+    {"recovery,quiescent", 169},
+    {"reboot,quiescent", 170},
 };
 
 // Converts a string value representing the reason the system booted to an
diff --git a/fs_mgr/libfiemap_writer/fiemap_writer.cpp b/fs_mgr/libfiemap_writer/fiemap_writer.cpp
index 99a1a2f..5b77280 100644
--- a/fs_mgr/libfiemap_writer/fiemap_writer.cpp
+++ b/fs_mgr/libfiemap_writer/fiemap_writer.cpp
@@ -501,12 +501,13 @@
         }
 
         if (!extents->empty() && block == last_block + 1) {
-            extents->back().fe_length++;
+            extents->back().fe_length += s.st_blksize;
         } else {
-            extents->push_back(fiemap_extent{.fe_logical = block_number,
-                                             .fe_physical = block,
-                                             .fe_length = 1,
-                                             .fe_flags = 0});
+            extents->push_back(
+                    fiemap_extent{.fe_logical = block_number,
+                                  .fe_physical = static_cast<uint64_t>(block) * s.st_blksize,
+                                  .fe_length = static_cast<uint64_t>(s.st_blksize),
+                                  .fe_flags = 0});
         }
         last_block = block;
     }
diff --git a/libasyncio/Android.bp b/libasyncio/Android.bp
index 0fd2a3a..4ab439d 100644
--- a/libasyncio/Android.bp
+++ b/libasyncio/Android.bp
@@ -27,7 +27,6 @@
     name: "libasyncio",
     defaults: ["libasyncio_defaults"],
     vendor_available: true,
-    double_loadable: true,
     recovery_available: true,
     host_supported: true,
     srcs: [
diff --git a/libcutils/include/cutils/native_handle.h b/libcutils/include/cutils/native_handle.h
index 10f5bc0..f6cae36 100644
--- a/libcutils/include/cutils/native_handle.h
+++ b/libcutils/include/cutils/native_handle.h
@@ -23,6 +23,9 @@
 extern "C" {
 #endif
 
+#define NATIVE_HANDLE_MAX_FDS 1024
+#define NATIVE_HANDLE_MAX_INTS 1024
+
 /* Declare a char array for use with native_handle_init */
 #define NATIVE_HANDLE_DECLARE_STORAGE(name, maxFds, maxInts) \
     alignas(native_handle_t) char (name)[                            \
diff --git a/libcutils/native_handle.cpp b/libcutils/native_handle.cpp
index 66f7a3d..b409e5b 100644
--- a/libcutils/native_handle.cpp
+++ b/libcutils/native_handle.cpp
@@ -22,9 +22,6 @@
 #include <string.h>
 #include <unistd.h>
 
-static const int kMaxNativeFds = 1024;
-static const int kMaxNativeInts = 1024;
-
 native_handle_t* native_handle_init(char* storage, int numFds, int numInts) {
     if ((uintptr_t) storage % alignof(native_handle_t)) {
         errno = EINVAL;
@@ -39,7 +36,8 @@
 }
 
 native_handle_t* native_handle_create(int numFds, int numInts) {
-    if (numFds < 0 || numInts < 0 || numFds > kMaxNativeFds || numInts > kMaxNativeInts) {
+    if (numFds < 0 || numInts < 0 || numFds > NATIVE_HANDLE_MAX_FDS ||
+        numInts > NATIVE_HANDLE_MAX_INTS) {
         errno = EINVAL;
         return NULL;
     }
diff --git a/libmemtrack/Android.bp b/libmemtrack/Android.bp
index 320b851..4e4554a 100644
--- a/libmemtrack/Android.bp
+++ b/libmemtrack/Android.bp
@@ -6,7 +6,6 @@
     vndk: {
         enabled: true,
     },
-    double_loadable: true,
     srcs: ["memtrack.cpp"],
     export_include_dirs: ["include"],
     local_include_dirs: ["include"],
diff --git a/libnativeloader/include/nativeloader/native_loader.h b/libnativeloader/include/nativeloader/native_loader.h
index 260f655..51fb875 100644
--- a/libnativeloader/include/nativeloader/native_loader.h
+++ b/libnativeloader/include/nativeloader/native_loader.h
@@ -36,14 +36,9 @@
 __attribute__((visibility("default")))
 void InitializeNativeLoader();
 
-__attribute__((visibility("default")))
-jstring CreateClassLoaderNamespace(JNIEnv* env,
-                                   int32_t target_sdk_version,
-                                   jobject class_loader,
-                                   bool is_shared,
-                                   bool is_for_vendor,
-                                   jstring library_path,
-                                   jstring permitted_path);
+__attribute__((visibility("default"))) jstring CreateClassLoaderNamespace(
+    JNIEnv* env, int32_t target_sdk_version, jobject class_loader, bool is_shared, jstring dex_path,
+    jstring library_path, jstring permitted_path);
 
 __attribute__((visibility("default"))) void* OpenNativeLibrary(
     JNIEnv* env, int32_t target_sdk_version, const char* path, jobject class_loader,
diff --git a/libnativeloader/native_loader.cpp b/libnativeloader/native_loader.cpp
index 043f038..1c2581f 100644
--- a/libnativeloader/native_loader.cpp
+++ b/libnativeloader/native_loader.cpp
@@ -31,6 +31,7 @@
 #include <list>
 #include <memory>
 #include <mutex>
+#include <regex>
 #include <string>
 #include <vector>
 
@@ -140,10 +141,24 @@
 
 #if defined(__LP64__)
 static constexpr const char* kRuntimeApexLibPath = "/apex/com.android.runtime/lib64";
+static constexpr const char* kVendorLibPath = "/vendor/lib64";
+static constexpr const char* kProductLibPath = "/product/lib64:/system/product/lib64";
 #else
 static constexpr const char* kRuntimeApexLibPath = "/apex/com.android.runtime/lib";
+static constexpr const char* kVendorLibPath = "/vendor/lib";
+static constexpr const char* kProductLibPath = "/product/lib:/system/product/lib";
 #endif
 
+static const std::regex kVendorDexPathRegex("(^|:)/vendor/");
+static const std::regex kProductDexPathRegex("(^|:)(/system)?/product/");
+
+// Define origin of APK if it is from vendor partition or product partition
+typedef enum {
+  APK_ORIGIN_DEFAULT = 0,
+  APK_ORIGIN_VENDOR = 1,
+  APK_ORIGIN_PRODUCT = 2,
+} ApkOrigin;
+
 static bool is_debuggable() {
   bool debuggable = false;
 #ifdef __BIONIC__
@@ -179,7 +194,7 @@
   LibraryNamespaces() : initialized_(false) { }
 
   NativeLoaderNamespace* Create(JNIEnv* env, uint32_t target_sdk_version, jobject class_loader,
-                                bool is_shared, bool is_for_vendor, jstring java_library_path,
+                                bool is_shared, jstring dex_path, jstring java_library_path,
                                 jstring java_permitted_path, std::string* error_msg) {
     std::string library_path; // empty string by default.
 
@@ -188,6 +203,8 @@
       library_path = library_path_utf_chars.c_str();
     }
 
+    ApkOrigin apk_origin = GetApkOriginFromDexPath(env, dex_path);
+
     // (http://b/27588281) This is a workaround for apps using custom
     // classloaders and calling System.load() with an absolute path which
     // is outside of the classloader library search path.
@@ -234,31 +251,50 @@
     std::string system_exposed_libraries = system_public_libraries_;
     const char* namespace_name = kClassloaderNamespaceName;
     android_namespace_t* vndk_ns = nullptr;
-    if (is_for_vendor && !is_shared) {
-      LOG_FATAL_IF(is_native_bridge, "Unbundled vendor apk must not use translated architecture");
+    if ((apk_origin == APK_ORIGIN_VENDOR ||
+         (apk_origin == APK_ORIGIN_PRODUCT && target_sdk_version > 29)) &&
+        !is_shared) {
+      LOG_FATAL_IF(is_native_bridge,
+                   "Unbundled vendor / product apk must not use translated architecture");
 
-      // For vendor apks, give access to the vendor lib even though
+      // For vendor / product apks, give access to the vendor / product lib even though
       // they are treated as unbundled; the libs and apks are still bundled
-      // together in the vendor partition.
-#if defined(__LP64__)
-      std::string vendor_lib_path = "/vendor/lib64";
-#else
-      std::string vendor_lib_path = "/vendor/lib";
-#endif
-      library_path = library_path + ":" + vendor_lib_path.c_str();
-      permitted_path = permitted_path + ":" + vendor_lib_path.c_str();
+      // together in the vendor / product partition.
+      const char* origin_partition;
+      const char* origin_lib_path;
+
+      switch (apk_origin) {
+        case APK_ORIGIN_VENDOR:
+          origin_partition = "vendor";
+          origin_lib_path = kVendorLibPath;
+          break;
+        case APK_ORIGIN_PRODUCT:
+          origin_partition = "product";
+          origin_lib_path = kProductLibPath;
+          break;
+        default:
+          origin_partition = "unknown";
+          origin_lib_path = "";
+      }
+
+      LOG_FATAL_IF(is_native_bridge, "Unbundled %s apk must not use translated architecture",
+                   origin_partition);
+
+      library_path = library_path + ":" + origin_lib_path;
+      permitted_path = permitted_path + ":" + origin_lib_path;
 
       // Also give access to LLNDK libraries since they are available to vendors
       system_exposed_libraries = system_exposed_libraries + ":" + system_llndk_libraries_.c_str();
 
       // Give access to VNDK-SP libraries from the 'vndk' namespace.
       vndk_ns = android_get_exported_namespace(kVndkNamespaceName);
-      LOG_ALWAYS_FATAL_IF(vndk_ns == nullptr,
-                          "Cannot find \"%s\" namespace for vendor apks", kVndkNamespaceName);
+      LOG_ALWAYS_FATAL_IF(vndk_ns == nullptr, "Cannot find \"%s\" namespace for %s apks",
+                          kVndkNamespaceName, origin_partition);
 
       // Different name is useful for debugging
       namespace_name = kVendorClassloaderNamespaceName;
-      ALOGD("classloader namespace configured for unbundled vendor apk. library_path=%s", library_path.c_str());
+      ALOGD("classloader namespace configured for unbundled %s apk. library_path=%s",
+            origin_partition, library_path.c_str());
     } else {
       // oem and product public libraries are NOT available to vendor apks, otherwise it
       // would be system->vendor violation.
@@ -660,6 +696,28 @@
     return nullptr;
   }
 
+  ApkOrigin GetApkOriginFromDexPath(JNIEnv* env, jstring dex_path) {
+    ApkOrigin apk_origin = APK_ORIGIN_DEFAULT;
+
+    if (dex_path != nullptr) {
+      ScopedUtfChars dex_path_utf_chars(env, dex_path);
+
+      if (std::regex_search(dex_path_utf_chars.c_str(), kVendorDexPathRegex)) {
+        apk_origin = APK_ORIGIN_VENDOR;
+      }
+
+      if (std::regex_search(dex_path_utf_chars.c_str(), kProductDexPathRegex)) {
+        LOG_ALWAYS_FATAL_IF(apk_origin == APK_ORIGIN_VENDOR,
+                            "Dex path contains both vendor and product partition : %s",
+                            dex_path_utf_chars.c_str());
+
+        apk_origin = APK_ORIGIN_PRODUCT;
+      }
+    }
+
+    return apk_origin;
+  }
+
   bool initialized_;
   std::list<std::pair<jweak, NativeLoaderNamespace>> namespaces_;
   std::string system_public_libraries_;
@@ -690,31 +748,20 @@
 #endif
 }
 
-jstring CreateClassLoaderNamespace(JNIEnv* env,
-                                   int32_t target_sdk_version,
-                                   jobject class_loader,
-                                   bool is_shared,
-                                   bool is_for_vendor,
-                                   jstring library_path,
+jstring CreateClassLoaderNamespace(JNIEnv* env, int32_t target_sdk_version, jobject class_loader,
+                                   bool is_shared, jstring dex_path, jstring library_path,
                                    jstring permitted_path) {
 #if defined(__ANDROID__)
   std::lock_guard<std::mutex> guard(g_namespaces_mutex);
 
   std::string error_msg;
-  bool success = g_namespaces->Create(env,
-                                      target_sdk_version,
-                                      class_loader,
-                                      is_shared,
-                                      is_for_vendor,
-                                      library_path,
-                                      permitted_path,
-                                      &error_msg) != nullptr;
+  bool success = g_namespaces->Create(env, target_sdk_version, class_loader, is_shared, dex_path,
+                                      library_path, permitted_path, &error_msg) != nullptr;
   if (!success) {
     return env->NewStringUTF(error_msg.c_str());
   }
 #else
-  UNUSED(env, target_sdk_version, class_loader, is_shared, is_for_vendor,
-         library_path, permitted_path);
+  UNUSED(env, target_sdk_version, class_loader, is_shared, dex_path, library_path, permitted_path);
 #endif
   return nullptr;
 }
@@ -779,8 +826,7 @@
     // In this case we create an isolated not-shared namespace for it.
     std::string create_error_msg;
     if ((ns = g_namespaces->Create(env, target_sdk_version, class_loader, false /* is_shared */,
-                                   false /* is_for_vendor */, library_path, nullptr,
-                                   &create_error_msg)) == nullptr) {
+                                   nullptr, library_path, nullptr, &create_error_msg)) == nullptr) {
       *error_msg = strdup(create_error_msg.c_str());
       return nullptr;
     }
diff --git a/libnativeloader/native_loader_lazy.cpp b/libnativeloader/native_loader_lazy.cpp
index 11ecc43..2eb1203 100644
--- a/libnativeloader/native_loader_lazy.cpp
+++ b/libnativeloader/native_loader_lazy.cpp
@@ -50,10 +50,10 @@
 }
 
 jstring CreateClassLoaderNamespace(JNIEnv* env, int32_t target_sdk_version, jobject class_loader,
-                                   bool is_shared, bool is_for_vendor, jstring library_path,
+                                   bool is_shared, jstring dex_path, jstring library_path,
                                    jstring permitted_path) {
   static auto f = GET_FUNC_PTR(CreateClassLoaderNamespace);
-  return f(env, target_sdk_version, class_loader, is_shared, is_for_vendor, library_path,
+  return f(env, target_sdk_version, class_loader, is_shared, dex_path, library_path,
            permitted_path);
 }
 
diff --git a/libprocinfo/Android.bp b/libprocinfo/Android.bp
index 27cda93..15f03d0 100644
--- a/libprocinfo/Android.bp
+++ b/libprocinfo/Android.bp
@@ -31,7 +31,6 @@
     vndk: {
         enabled: true,
     },
-    double_loadable: true,
     host_supported: true,
     srcs: [
         "process.cpp",
diff --git a/libunwindstack/include/unwindstack/Memory.h b/libunwindstack/include/unwindstack/Memory.h
index dba41d1..b3beb6e 100644
--- a/libunwindstack/include/unwindstack/Memory.h
+++ b/libunwindstack/include/unwindstack/Memory.h
@@ -101,7 +101,7 @@
 
   size_t Size() { return size_; }
 
-  void Clear();
+  void Clear() override;
 
  protected:
   size_t size_ = 0;
diff --git a/libusbhost/Android.bp b/libusbhost/Android.bp
index 39bf3a5..fc6f305 100644
--- a/libusbhost/Android.bp
+++ b/libusbhost/Android.bp
@@ -20,7 +20,6 @@
     vndk: {
         enabled: true,
     },
-    double_loadable: true,
     host_supported: true,
     srcs: ["usbhost.c"],
     cflags: ["-Werror"],
diff --git a/libutils/RefBase_test.cpp b/libutils/RefBase_test.cpp
index 2e0cf6e..b594ca5 100644
--- a/libutils/RefBase_test.cpp
+++ b/libutils/RefBase_test.cpp
@@ -45,6 +45,44 @@
     bool* mDeleted;
 };
 
+// A version of Foo that ensures that all objects are allocated at the same
+// address. No more than one can be allocated at a time. Thread-hostile.
+class FooFixedAlloc : public RefBase {
+public:
+    static void* operator new(size_t size) {
+        if (mAllocCount != 0) {
+            abort();
+        }
+        mAllocCount = 1;
+        if (theMemory == nullptr) {
+            theMemory = malloc(size);
+        }
+        return theMemory;
+    }
+
+    static void operator delete(void *p) {
+        if (mAllocCount != 1 || p != theMemory) {
+            abort();
+        }
+        mAllocCount = 0;
+    }
+
+    FooFixedAlloc(bool* deleted_check) : mDeleted(deleted_check) {
+        *mDeleted = false;
+    }
+
+    ~FooFixedAlloc() {
+        *mDeleted = true;
+    }
+private:
+    bool* mDeleted;
+    static int mAllocCount;
+    static void* theMemory;
+};
+
+int FooFixedAlloc::mAllocCount(0);
+void* FooFixedAlloc::theMemory(nullptr);
+
 TEST(RefBase, StrongMoves) {
     bool isDeleted;
     Foo* foo = new Foo(&isDeleted);
@@ -90,6 +128,91 @@
     ASSERT_FALSE(isDeleted) << "Deletion on wp destruction should no longer occur";
 }
 
+TEST(RefBase, Comparisons) {
+    bool isDeleted, isDeleted2;
+    Foo* foo = new Foo(&isDeleted);
+    Foo* foo2 = new Foo(&isDeleted2);
+    sp<Foo> sp1(foo);
+    sp<Foo> sp2(foo2);
+    wp<Foo> wp1(sp1);
+    wp<Foo> wp2(sp1);
+    wp<Foo> wp3(sp2);
+    ASSERT_TRUE(wp1 == wp2);
+    ASSERT_TRUE(wp1 == sp1);
+    ASSERT_TRUE(wp3 == sp2);
+    ASSERT_TRUE(wp1 != sp2);
+    ASSERT_TRUE(wp1 <= wp2);
+    ASSERT_TRUE(wp1 >= wp2);
+    ASSERT_FALSE(wp1 != wp2);
+    ASSERT_FALSE(wp1 > wp2);
+    ASSERT_FALSE(wp1 < wp2);
+    ASSERT_FALSE(sp1 == sp2);
+    ASSERT_TRUE(sp1 != sp2);
+    bool sp1_smaller = sp1 < sp2;
+    wp<Foo>wp_smaller = sp1_smaller ? wp1 : wp3;
+    wp<Foo>wp_larger = sp1_smaller ? wp3 : wp1;
+    ASSERT_TRUE(wp_smaller < wp_larger);
+    ASSERT_TRUE(wp_smaller != wp_larger);
+    ASSERT_TRUE(wp_smaller <= wp_larger);
+    ASSERT_FALSE(wp_smaller == wp_larger);
+    ASSERT_FALSE(wp_smaller > wp_larger);
+    ASSERT_FALSE(wp_smaller >= wp_larger);
+    sp2 = nullptr;
+    ASSERT_TRUE(isDeleted2);
+    ASSERT_FALSE(isDeleted);
+    ASSERT_FALSE(wp3 == sp2);
+    // Comparison results on weak pointers should not be affected.
+    ASSERT_TRUE(wp_smaller < wp_larger);
+    ASSERT_TRUE(wp_smaller != wp_larger);
+    ASSERT_TRUE(wp_smaller <= wp_larger);
+    ASSERT_FALSE(wp_smaller == wp_larger);
+    ASSERT_FALSE(wp_smaller > wp_larger);
+    ASSERT_FALSE(wp_smaller >= wp_larger);
+    wp2 = nullptr;
+    ASSERT_FALSE(wp1 == wp2);
+    ASSERT_TRUE(wp1 != wp2);
+    wp1.clear();
+    ASSERT_TRUE(wp1 == wp2);
+    ASSERT_FALSE(wp1 != wp2);
+    wp3.clear();
+    ASSERT_TRUE(wp1 == wp3);
+    ASSERT_FALSE(wp1 != wp3);
+    ASSERT_FALSE(isDeleted);
+    sp1.clear();
+    ASSERT_TRUE(isDeleted);
+    ASSERT_TRUE(sp1 == sp2);
+}
+
+// Check whether comparison against dead wp works, even if the object referenced
+// by the new wp happens to be at the same address.
+TEST(RefBase, ReplacedComparison) {
+    bool isDeleted, isDeleted2;
+    FooFixedAlloc* foo = new FooFixedAlloc(&isDeleted);
+    sp<FooFixedAlloc> sp1(foo);
+    wp<FooFixedAlloc> wp1(sp1);
+    ASSERT_TRUE(wp1 == sp1);
+    sp1.clear();  // Deallocates the object.
+    ASSERT_TRUE(isDeleted);
+    FooFixedAlloc* foo2 = new FooFixedAlloc(&isDeleted2);
+    ASSERT_FALSE(isDeleted2);
+    ASSERT_EQ(foo, foo2);  // Not technically a legal comparison, but ...
+    sp<FooFixedAlloc> sp2(foo2);
+    wp<FooFixedAlloc> wp2(sp2);
+    ASSERT_TRUE(sp2 == wp2);
+    ASSERT_FALSE(sp2 != wp2);
+    ASSERT_TRUE(sp2 != wp1);
+    ASSERT_FALSE(sp2 == wp1);
+    ASSERT_FALSE(sp2 == sp1);  // sp1 is null.
+    ASSERT_FALSE(wp1 == wp2);  // wp1 refers to old object.
+    ASSERT_TRUE(wp1 != wp2);
+    ASSERT_TRUE(wp1 > wp2 || wp1 < wp2);
+    ASSERT_TRUE(wp1 >= wp2 || wp1 <= wp2);
+    ASSERT_FALSE(wp1 >= wp2 && wp1 <= wp2);
+    ASSERT_FALSE(wp1 == nullptr);
+    wp1 = sp2;
+    ASSERT_TRUE(wp1 == wp2);
+    ASSERT_FALSE(wp1 != wp2);
+}
 
 // Set up a situation in which we race with visit2AndRremove() to delete
 // 2 strong references.  Bar destructor checks that there are no early
diff --git a/libutils/include/utils/RefBase.h b/libutils/include/utils/RefBase.h
index 1780cf2..730d631 100644
--- a/libutils/include/utils/RefBase.h
+++ b/libutils/include/utils/RefBase.h
@@ -171,6 +171,8 @@
 #define ANDROID_REF_BASE_H
 
 #include <atomic>
+#include <functional>
+#include <type_traits>  // for common_type.
 
 #include <stdint.h>
 #include <sys/types.h>
@@ -192,19 +194,26 @@
 // ---------------------------------------------------------------------------
 
 #define COMPARE_WEAK(_op_)                                      \
-inline bool operator _op_ (const sp<T>& o) const {              \
-    return m_ptr _op_ o.m_ptr;                                  \
-}                                                               \
-inline bool operator _op_ (const T* o) const {                  \
-    return m_ptr _op_ o;                                        \
-}                                                               \
-template<typename U>                                            \
-inline bool operator _op_ (const sp<U>& o) const {              \
-    return m_ptr _op_ o.m_ptr;                                  \
-}                                                               \
 template<typename U>                                            \
 inline bool operator _op_ (const U* o) const {                  \
     return m_ptr _op_ o;                                        \
+}                                                               \
+/* Needed to handle type inference for nullptr: */              \
+inline bool operator _op_ (const T* o) const {                  \
+    return m_ptr _op_ o;                                        \
+}
+
+template<template<typename C> class comparator, typename T, typename U>
+static inline bool _wp_compare_(T* a, U* b) {
+    return comparator<typename std::common_type<T*, U*>::type>()(a, b);
+}
+
+// Use std::less and friends to avoid undefined behavior when ordering pointers
+// to different objects.
+#define COMPARE_WEAK_FUNCTIONAL(_op_, _compare_)                 \
+template<typename U>                                             \
+inline bool operator _op_ (const U* o) const {                   \
+    return _wp_compare_<_compare_>(m_ptr, o);                    \
 }
 
 // ---------------------------------------------------------------------------
@@ -395,39 +404,51 @@
 
     COMPARE_WEAK(==)
     COMPARE_WEAK(!=)
-    COMPARE_WEAK(>)
-    COMPARE_WEAK(<)
-    COMPARE_WEAK(<=)
-    COMPARE_WEAK(>=)
+    COMPARE_WEAK_FUNCTIONAL(>, std::greater)
+    COMPARE_WEAK_FUNCTIONAL(<, std::less)
+    COMPARE_WEAK_FUNCTIONAL(<=, std::less_equal)
+    COMPARE_WEAK_FUNCTIONAL(>=, std::greater_equal)
 
-    inline bool operator == (const wp<T>& o) const {
-        return (m_ptr == o.m_ptr) && (m_refs == o.m_refs);
-    }
     template<typename U>
     inline bool operator == (const wp<U>& o) const {
-        return m_ptr == o.m_ptr;
+        return m_refs == o.m_refs;  // Implies m_ptr == o.mptr; see invariants below.
     }
 
-    inline bool operator > (const wp<T>& o) const {
-        return (m_ptr == o.m_ptr) ? (m_refs > o.m_refs) : (m_ptr > o.m_ptr);
+    template<typename U>
+    inline bool operator == (const sp<U>& o) const {
+        // Just comparing m_ptr fields is often dangerous, since wp<> may refer to an older
+        // object at the same address.
+        if (o == nullptr) {
+          return m_ptr == nullptr;
+        } else {
+          return m_refs == o->getWeakRefs();  // Implies m_ptr == o.mptr.
+        }
     }
+
+    template<typename U>
+    inline bool operator != (const sp<U>& o) const {
+        return !(*this == o);
+    }
+
     template<typename U>
     inline bool operator > (const wp<U>& o) const {
-        return (m_ptr == o.m_ptr) ? (m_refs > o.m_refs) : (m_ptr > o.m_ptr);
+        if (m_ptr == o.m_ptr) {
+            return _wp_compare_<std::greater>(m_refs, o.m_refs);
+        } else {
+            return _wp_compare_<std::greater>(m_ptr, o.m_ptr);
+        }
     }
 
-    inline bool operator < (const wp<T>& o) const {
-        return (m_ptr == o.m_ptr) ? (m_refs < o.m_refs) : (m_ptr < o.m_ptr);
-    }
     template<typename U>
     inline bool operator < (const wp<U>& o) const {
-        return (m_ptr == o.m_ptr) ? (m_refs < o.m_refs) : (m_ptr < o.m_ptr);
+        if (m_ptr == o.m_ptr) {
+            return _wp_compare_<std::less>(m_refs, o.m_refs);
+        } else {
+            return _wp_compare_<std::less>(m_ptr, o.m_ptr);
+        }
     }
-                         inline bool operator != (const wp<T>& o) const { return m_refs != o.m_refs; }
     template<typename U> inline bool operator != (const wp<U>& o) const { return !operator == (o); }
-                         inline bool operator <= (const wp<T>& o) const { return !operator > (o); }
     template<typename U> inline bool operator <= (const wp<U>& o) const { return !operator > (o); }
-                         inline bool operator >= (const wp<T>& o) const { return !operator < (o); }
     template<typename U> inline bool operator >= (const wp<U>& o) const { return !operator < (o); }
 
 private:
@@ -446,6 +467,22 @@
 // ---------------------------------------------------------------------------
 // No user serviceable parts below here.
 
+// Implementation invariants:
+// Either
+// 1) m_ptr and m_refs are both null, or
+// 2) m_refs == m_ptr->mRefs, or
+// 3) *m_ptr is no longer live, and m_refs points to the weakref_type object that corresponded
+//    to m_ptr while it was live. *m_refs remains live while a wp<> refers to it.
+//
+// The m_refs field in a RefBase object is allocated on construction, unique to that RefBase
+// object, and never changes. Thus if two wp's have identical m_refs fields, they are either both
+// null or point to the same object. If two wp's have identical m_ptr fields, they either both
+// point to the same live object and thus have the same m_ref fields, or at least one of the
+// objects is no longer live.
+//
+// Note that the above comparison operations go out of their way to provide an ordering consistent
+// with ordinary pointer comparison; otherwise they could ignore m_ptr, and just compare m_refs.
+
 template<typename T>
 wp<T>::wp(T* other)
     : m_ptr(other)
@@ -595,6 +632,7 @@
 {
     if (m_ptr) {
         m_refs->decWeak(this);
+        m_refs = 0;
         m_ptr = 0;
     }
 }
diff --git a/libutils/include/utils/StrongPointer.h b/libutils/include/utils/StrongPointer.h
index 1571129..9cd7c75 100644
--- a/libutils/include/utils/StrongPointer.h
+++ b/libutils/include/utils/StrongPointer.h
@@ -17,6 +17,9 @@
 #ifndef ANDROID_STRONG_POINTER_H
 #define ANDROID_STRONG_POINTER_H
 
+#include <functional>
+#include <type_traits>  // for common_type.
+
 // ---------------------------------------------------------------------------
 namespace android {
 
@@ -24,13 +27,12 @@
 
 // ---------------------------------------------------------------------------
 
-#define COMPARE(_op_)                                           \
-inline bool operator _op_ (const sp<T>& o) const {              \
-    return m_ptr _op_ o.m_ptr;                                  \
-}                                                               \
-inline bool operator _op_ (const T* o) const {                  \
-    return m_ptr _op_ o;                                        \
-}                                                               \
+// TODO: Maybe remove sp<> ? wp<> comparison? These are dangerous: If the wp<>
+// was created before the sp<>, and they point to different objects, they may
+// compare equal even if they are entirely unrelated. E.g. CameraService
+// currently performa such comparisons.
+
+#define COMPARE_STRONG(_op_)                                           \
 template<typename U>                                            \
 inline bool operator _op_ (const sp<U>& o) const {              \
     return m_ptr _op_ o.m_ptr;                                  \
@@ -39,14 +41,27 @@
 inline bool operator _op_ (const U* o) const {                  \
     return m_ptr _op_ o;                                        \
 }                                                               \
-inline bool operator _op_ (const wp<T>& o) const {              \
-    return m_ptr _op_ o.m_ptr;                                  \
-}                                                               \
-template<typename U>                                            \
-inline bool operator _op_ (const wp<U>& o) const {              \
-    return m_ptr _op_ o.m_ptr;                                  \
+/* Needed to handle type inference for nullptr: */              \
+inline bool operator _op_ (const T* o) const {                  \
+    return m_ptr _op_ o;                                        \
 }
 
+template<template<typename C> class comparator, typename T, typename U>
+static inline bool _sp_compare_(T* a, U* b) {
+    return comparator<typename std::common_type<T*, U*>::type>()(a, b);
+}
+
+// Use std::less and friends to avoid undefined behavior when ordering pointers
+// to different objects.
+#define COMPARE_STRONG_FUNCTIONAL(_op_, _compare_)               \
+template<typename U>                                             \
+inline bool operator _op_ (const sp<U>& o) const {               \
+    return _sp_compare_<_compare_>(m_ptr, o.m_ptr);              \
+}                                                                \
+template<typename U>                                             \
+inline bool operator _op_ (const U* o) const {                   \
+    return _sp_compare_<_compare_>(m_ptr, o);                    \
+}
 // ---------------------------------------------------------------------------
 
 template<typename T>
@@ -89,12 +104,23 @@
 
     // Operators
 
-    COMPARE(==)
-    COMPARE(!=)
-    COMPARE(>)
-    COMPARE(<)
-    COMPARE(<=)
-    COMPARE(>=)
+    COMPARE_STRONG(==)
+    COMPARE_STRONG(!=)
+    COMPARE_STRONG_FUNCTIONAL(>, std::greater)
+    COMPARE_STRONG_FUNCTIONAL(<, std::less)
+    COMPARE_STRONG_FUNCTIONAL(<=, std::less_equal)
+    COMPARE_STRONG_FUNCTIONAL(>=, std::greater_equal)
+
+    // Punt these to the wp<> implementation.
+    template<typename U>
+    inline bool operator == (const wp<U>& o) const {
+        return o == *this;
+    }
+
+    template<typename U>
+    inline bool operator != (const wp<U>& o) const {
+        return o != *this;
+    }
 
 private:    
     template<typename Y> friend class sp;
diff --git a/libvndksupport/linker.c b/libvndksupport/linker.c
index 821940a..84c2132 100644
--- a/libvndksupport/linker.c
+++ b/libvndksupport/linker.c
@@ -20,6 +20,8 @@
 
 #define LOG_TAG "vndksupport"
 #include <log/log.h>
+#include <sys/types.h>
+#include <unistd.h>
 
 __attribute__((weak)) extern struct android_namespace_t* android_get_exported_namespace(const char*);
 __attribute__((weak)) extern void* android_dlopen_ext(const char*, int, const android_dlextinfo*);
@@ -46,6 +48,11 @@
 }
 
 int android_is_in_vendor_process() {
+    // Special case init, since when init runs, ld.config.<ver>.txt hasn't been
+    // loaded (sysprop service isn't up for init to know <ver>).
+    if (getpid() == 1) {
+        return 0;
+    }
     if (android_get_exported_namespace == NULL) {
         ALOGD("android_get_exported_namespace() not available. Assuming system process.");
         return 0;
diff --git a/rootdir/init.rc b/rootdir/init.rc
index b769b94..7cac972 100644
--- a/rootdir/init.rc
+++ b/rootdir/init.rc
@@ -389,6 +389,8 @@
     chmod 0700 /metadata/vold
     mkdir /metadata/password_slots 0771 root system
 
+    mkdir /metadata/apex 0700 root system
+    mkdir /metadata/apex/sessions 0700 root system
 on late-fs
     # Ensure that tracefs has the correct permissions.
     # This does not work correctly if it is called in post-fs.