Merge "lmkd: set PSI_POLL_PERIOD to 40ms"
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/libunwindstack/Android.bp b/libunwindstack/Android.bp
index a49fd9e..b7650a1 100644
--- a/libunwindstack/Android.bp
+++ b/libunwindstack/Android.bp
@@ -248,6 +248,7 @@
         "tests/files/offline/offset_arm/*",
         "tests/files/offline/shared_lib_in_apk_arm64/*",
         "tests/files/offline/shared_lib_in_apk_memory_only_arm64/*",
+        "tests/files/offline/shared_lib_in_apk_single_map_arm64/*",
         "tests/files/offline/straddle_arm/*",
         "tests/files/offline/straddle_arm64/*",
     ],
diff --git a/libunwindstack/MapInfo.cpp b/libunwindstack/MapInfo.cpp
index 89a6a79..a38236c 100644
--- a/libunwindstack/MapInfo.cpp
+++ b/libunwindstack/MapInfo.cpp
@@ -88,6 +88,7 @@
   // Check if the start of this map is an embedded elf.
   uint64_t max_size = 0;
   if (Elf::GetInfo(memory.get(), &max_size)) {
+    elf_start_offset = offset;
     if (max_size > map_size) {
       if (memory->Init(name, offset, max_size)) {
         return memory.release();
@@ -96,6 +97,7 @@
       if (memory->Init(name, offset, map_size)) {
         return memory.release();
       }
+      elf_start_offset = 0;
       return nullptr;
     }
     return memory.release();
diff --git a/libunwindstack/tests/MapInfoCreateMemoryTest.cpp b/libunwindstack/tests/MapInfoCreateMemoryTest.cpp
index a66685a..2ddadef 100644
--- a/libunwindstack/tests/MapInfoCreateMemoryTest.cpp
+++ b/libunwindstack/tests/MapInfoCreateMemoryTest.cpp
@@ -178,7 +178,7 @@
   std::unique_ptr<Memory> memory(info.CreateMemory(process_memory_));
   ASSERT_TRUE(memory.get() != nullptr);
   ASSERT_EQ(0U, info.elf_offset);
-  EXPECT_EQ(0U, info.elf_start_offset);
+  EXPECT_EQ(0x1000U, info.elf_start_offset);
 
   // Read the valid part of the file.
   std::vector<uint8_t> buffer(0x100);
@@ -202,7 +202,7 @@
   std::unique_ptr<Memory> memory(info.CreateMemory(process_memory_));
   ASSERT_TRUE(memory.get() != nullptr);
   ASSERT_EQ(0U, info.elf_offset);
-  EXPECT_EQ(0U, info.elf_start_offset);
+  EXPECT_EQ(0x1000U, info.elf_start_offset);
 
   // Verify the memory is a valid elf.
   uint8_t e_ident[SELFMAG + 1];
@@ -219,7 +219,7 @@
   std::unique_ptr<Memory> memory(info.CreateMemory(process_memory_));
   ASSERT_TRUE(memory.get() != nullptr);
   ASSERT_EQ(0U, info.elf_offset);
-  EXPECT_EQ(0U, info.elf_start_offset);
+  EXPECT_EQ(0x2000U, info.elf_start_offset);
 
   // Verify the memory is a valid elf.
   uint8_t e_ident[SELFMAG + 1];
diff --git a/libunwindstack/tests/UnwindOfflineTest.cpp b/libunwindstack/tests/UnwindOfflineTest.cpp
index b5feb38..86bc465 100644
--- a/libunwindstack/tests/UnwindOfflineTest.cpp
+++ b/libunwindstack/tests/UnwindOfflineTest.cpp
@@ -1372,4 +1372,56 @@
   // Ignore top frame since the test code was modified to end in __libc_init.
 }
 
+TEST_F(UnwindOfflineTest, shared_lib_in_apk_single_map_arm64) {
+  ASSERT_NO_FATAL_FAILURE(Init("shared_lib_in_apk_single_map_arm64/", ARCH_ARM64));
+
+  Unwinder unwinder(128, maps_.get(), regs_.get(), process_memory_);
+  unwinder.Unwind();
+
+  std::string frame_info(DumpFrames(unwinder));
+  ASSERT_EQ(13U, unwinder.NumFrames()) << "Unwind:\n" << frame_info;
+  EXPECT_EQ(
+      "  #00 pc 00000000000814bc  libc.so (syscall+28)\n"
+      "  #01 pc 00000000008cdf5c  test.apk (offset 0x5000)\n"
+      "  #02 pc 00000000008cde9c  test.apk (offset 0x5000)\n"
+      "  #03 pc 00000000008cdd70  test.apk (offset 0x5000)\n"
+      "  #04 pc 00000000008ce408  test.apk (offset 0x5000)\n"
+      "  #05 pc 00000000008ce8d8  test.apk (offset 0x5000)\n"
+      "  #06 pc 00000000008ce814  test.apk (offset 0x5000)\n"
+      "  #07 pc 00000000008bcf60  test.apk (offset 0x5000)\n"
+      "  #08 pc 0000000000133024  test.apk (offset 0x5000)\n"
+      "  #09 pc 0000000000134ad0  test.apk (offset 0x5000)\n"
+      "  #10 pc 0000000000134b64  test.apk (offset 0x5000)\n"
+      "  #11 pc 00000000000e406c  libc.so (__pthread_start(void*)+36)\n"
+      "  #12 pc 0000000000085e18  libc.so (__start_thread+64)\n",
+      frame_info);
+
+  EXPECT_EQ(0x7cbe0b14bcULL, unwinder.frames()[0].pc);
+  EXPECT_EQ(0x7be4f077d0ULL, unwinder.frames()[0].sp);
+  EXPECT_EQ(0x7be6715f5cULL, unwinder.frames()[1].pc);
+  EXPECT_EQ(0x7be4f077d0ULL, unwinder.frames()[1].sp);
+  EXPECT_EQ(0x7be6715e9cULL, unwinder.frames()[2].pc);
+  EXPECT_EQ(0x7be4f07800ULL, unwinder.frames()[2].sp);
+  EXPECT_EQ(0x7be6715d70ULL, unwinder.frames()[3].pc);
+  EXPECT_EQ(0x7be4f07840ULL, unwinder.frames()[3].sp);
+  EXPECT_EQ(0x7be6716408ULL, unwinder.frames()[4].pc);
+  EXPECT_EQ(0x7be4f07860ULL, unwinder.frames()[4].sp);
+  EXPECT_EQ(0x7be67168d8ULL, unwinder.frames()[5].pc);
+  EXPECT_EQ(0x7be4f07880ULL, unwinder.frames()[5].sp);
+  EXPECT_EQ(0x7be6716814ULL, unwinder.frames()[6].pc);
+  EXPECT_EQ(0x7be4f078f0ULL, unwinder.frames()[6].sp);
+  EXPECT_EQ(0x7be6704f60ULL, unwinder.frames()[7].pc);
+  EXPECT_EQ(0x7be4f07910ULL, unwinder.frames()[7].sp);
+  EXPECT_EQ(0x7be5f7b024ULL, unwinder.frames()[8].pc);
+  EXPECT_EQ(0x7be4f07950ULL, unwinder.frames()[8].sp);
+  EXPECT_EQ(0x7be5f7cad0ULL, unwinder.frames()[9].pc);
+  EXPECT_EQ(0x7be4f07aa0ULL, unwinder.frames()[9].sp);
+  EXPECT_EQ(0x7be5f7cb64ULL, unwinder.frames()[10].pc);
+  EXPECT_EQ(0x7be4f07ce0ULL, unwinder.frames()[10].sp);
+  EXPECT_EQ(0x7cbe11406cULL, unwinder.frames()[11].pc);
+  EXPECT_EQ(0x7be4f07d00ULL, unwinder.frames()[11].sp);
+  EXPECT_EQ(0x7cbe0b5e18ULL, unwinder.frames()[12].pc);
+  EXPECT_EQ(0x7be4f07d20ULL, unwinder.frames()[12].sp);
+}
+
 }  // namespace unwindstack
diff --git a/libunwindstack/tests/files/offline/shared_lib_in_apk_single_map_arm64/libc.so b/libunwindstack/tests/files/offline/shared_lib_in_apk_single_map_arm64/libc.so
new file mode 100644
index 0000000..cac1dd9
--- /dev/null
+++ b/libunwindstack/tests/files/offline/shared_lib_in_apk_single_map_arm64/libc.so
Binary files differ
diff --git a/libunwindstack/tests/files/offline/shared_lib_in_apk_single_map_arm64/maps.txt b/libunwindstack/tests/files/offline/shared_lib_in_apk_single_map_arm64/maps.txt
new file mode 100644
index 0000000..2c5ca62
--- /dev/null
+++ b/libunwindstack/tests/files/offline/shared_lib_in_apk_single_map_arm64/maps.txt
@@ -0,0 +1,3 @@
+7be5e48000-7be6b2b000 r-xp 5000 00:00 0   test.apk
+7cbe030000-7cbe070000 r--p 0 00:00 0   libc.so
+7cbe070000-7cbe11a000 r-xp 40000 00:00 0   libc.so
diff --git a/libunwindstack/tests/files/offline/shared_lib_in_apk_single_map_arm64/regs.txt b/libunwindstack/tests/files/offline/shared_lib_in_apk_single_map_arm64/regs.txt
new file mode 100644
index 0000000..090aeda
--- /dev/null
+++ b/libunwindstack/tests/files/offline/shared_lib_in_apk_single_map_arm64/regs.txt
@@ -0,0 +1,33 @@
+x0: 7c326f6568
+x1: 80
+x2: 0
+x3: 0
+x4: 0
+x5: 0
+x6: 0
+x7: 7f7f7f7f7f7f7f7f
+x8: 62
+x9: 1
+x10: 1
+x11: 0
+x12: ffffffffc4653600
+x13: 17645696f
+x14: 2742ed97ca77a3
+x15: 3ab49084
+x16: 7be6b6bdb8
+x17: 7cbe0b14a0
+x18: 7c2b02a000
+x19: 0
+x20: 7c326f6568
+x21: 7be69c827c
+x22: 7be69c8272
+x23: 1
+x24: 7be74f7100
+x25: 881
+x26: 7be4f07a00
+x27: c479c000
+x28: 7be4f07998
+x29: 7be4f079b4
+sp: 7be4f077d0
+lr: 7be6715f60
+pc: 7cbe0b14bc
diff --git a/libunwindstack/tests/files/offline/shared_lib_in_apk_single_map_arm64/stack.data b/libunwindstack/tests/files/offline/shared_lib_in_apk_single_map_arm64/stack.data
new file mode 100644
index 0000000..27d5bf3
--- /dev/null
+++ b/libunwindstack/tests/files/offline/shared_lib_in_apk_single_map_arm64/stack.data
Binary files differ
diff --git a/libunwindstack/tests/files/offline/shared_lib_in_apk_single_map_arm64/test.apk b/libunwindstack/tests/files/offline/shared_lib_in_apk_single_map_arm64/test.apk
new file mode 100644
index 0000000..70a9c71
--- /dev/null
+++ b/libunwindstack/tests/files/offline/shared_lib_in_apk_single_map_arm64/test.apk
Binary files differ
diff --git a/libutils/RefBase_test.cpp b/libutils/RefBase_test.cpp
index b594ca5..2e0cf6e 100644
--- a/libutils/RefBase_test.cpp
+++ b/libutils/RefBase_test.cpp
@@ -45,44 +45,6 @@
     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);
@@ -128,91 +90,6 @@
     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 730d631..1780cf2 100644
--- a/libutils/include/utils/RefBase.h
+++ b/libutils/include/utils/RefBase.h
@@ -171,8 +171,6 @@
 #define ANDROID_REF_BASE_H
 
 #include <atomic>
-#include <functional>
-#include <type_traits>  // for common_type.
 
 #include <stdint.h>
 #include <sys/types.h>
@@ -194,26 +192,19 @@
 // ---------------------------------------------------------------------------
 
 #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);                    \
 }
 
 // ---------------------------------------------------------------------------
@@ -404,51 +395,39 @@
 
     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)
+    COMPARE_WEAK(>)
+    COMPARE_WEAK(<)
+    COMPARE_WEAK(<=)
+    COMPARE_WEAK(>=)
 
+    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_refs == o.m_refs;  // Implies m_ptr == o.mptr; see invariants below.
+        return 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.
-        }
+    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 {
-        return !(*this == o);
-    }
-
     template<typename U>
     inline bool operator > (const wp<U>& o) const {
-        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);
-        }
+        return (m_ptr == o.m_ptr) ? (m_refs > o.m_refs) : (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 {
-        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);
-        }
+        return (m_ptr == o.m_ptr) ? (m_refs < o.m_refs) : (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:
@@ -467,22 +446,6 @@
 // ---------------------------------------------------------------------------
 // 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)
@@ -632,7 +595,6 @@
 {
     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 9cd7c75..1571129 100644
--- a/libutils/include/utils/StrongPointer.h
+++ b/libutils/include/utils/StrongPointer.h
@@ -17,9 +17,6 @@
 #ifndef ANDROID_STRONG_POINTER_H
 #define ANDROID_STRONG_POINTER_H
 
-#include <functional>
-#include <type_traits>  // for common_type.
-
 // ---------------------------------------------------------------------------
 namespace android {
 
@@ -27,12 +24,13 @@
 
 // ---------------------------------------------------------------------------
 
-// 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_)                                           \
+#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;                                        \
+}                                                               \
 template<typename U>                                            \
 inline bool operator _op_ (const sp<U>& o) const {              \
     return m_ptr _op_ o.m_ptr;                                  \
@@ -41,27 +39,14 @@
 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;                                        \
+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;                                  \
 }
 
-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>
@@ -104,23 +89,12 @@
 
     // Operators
 
-    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;
-    }
+    COMPARE(==)
+    COMPARE(!=)
+    COMPARE(>)
+    COMPARE(<)
+    COMPARE(<=)
+    COMPARE(>=)
 
 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.environ.rc.in b/rootdir/init.environ.rc.in
index 5d6cd2d..455c9a8 100644
--- a/rootdir/init.environ.rc.in
+++ b/rootdir/init.environ.rc.in
@@ -6,6 +6,7 @@
     export ANDROID_DATA /data
     export ANDROID_STORAGE /storage
     export ANDROID_RUNTIME_ROOT /apex/com.android.runtime
+    export ANDROID_TZDATA_ROOT /apex/com.android.tzdata
     export EXTERNAL_STORAGE /sdcard
     export ASEC_MOUNTPOINT /mnt/asec
     export BOOTCLASSPATH %BOOTCLASSPATH%
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.