Merge "libpermission" into sc-dev
diff --git a/cmds/dumpstate/dumpstate.cpp b/cmds/dumpstate/dumpstate.cpp
index 7ab2a8d..e2ffd02 100644
--- a/cmds/dumpstate/dumpstate.cpp
+++ b/cmds/dumpstate/dumpstate.cpp
@@ -2175,14 +2175,13 @@
     }
 
     /*
-     * mount debugfs for non-user builds which launch with S and unmount it
-     * after invoking dumpstateBoard_* methods. This is to enable debug builds
-     * to not have debugfs mounted during runtime. It will also ensure that
-     * debugfs is only accessed by the dumpstate HAL.
+     * mount debugfs for non-user builds with ro.product.enforce_debugfs_restrictions
+     * set to true and unmount it after invoking dumpstateBoard_* methods.
+     * This is to enable debug builds to not have debugfs mounted during runtime.
+     * It will also ensure that debugfs is only accessed by the dumpstate HAL.
      */
-    auto api_level = android::base::GetIntProperty("ro.product.first_api_level", 0);
-    bool mount_debugfs = !PropertiesHelper::IsUserBuild() && api_level >= 31;
-
+    auto mount_debugfs =
+        android::base::GetBoolProperty("ro.product.enforce_debugfs_restrictions", false);
     if (mount_debugfs) {
         RunCommand("mount debugfs", {"mount", "-t", "debugfs", "debugfs", "/sys/kernel/debug"},
                    AS_ROOT_20);
@@ -2290,7 +2289,10 @@
     }
 
     if (mount_debugfs) {
-        RunCommand("unmount debugfs", {"umount", "/sys/kernel/debug"}, AS_ROOT_20);
+        auto keep_debugfs_mounted =
+            android::base::GetProperty("persist.dbg.keep_debugfs_mounted", "");
+        if (keep_debugfs_mounted.empty())
+            RunCommand("unmount debugfs", {"umount", "/sys/kernel/debug"}, AS_ROOT_20);
     }
 
     auto file_sizes = std::make_unique<ssize_t[]>(paths.size());
diff --git a/cmds/dumpstate/tests/dumpstate_test.cpp b/cmds/dumpstate/tests/dumpstate_test.cpp
index 2c573e4..db508b5 100644
--- a/cmds/dumpstate/tests/dumpstate_test.cpp
+++ b/cmds/dumpstate/tests/dumpstate_test.cpp
@@ -1032,12 +1032,12 @@
     ZipArchiveHandle handle_;
 };
 
-// Generate a quick wifi report redirected to a file, open it and verify entry exist.
-TEST_F(ZippedBugReportStreamTest, StreamWifiReport) {
-    std::string out_path = kTestDataPath + "out.zip";
+// Generate a quick LimitedOnly report redirected to a file, open it and verify entry exist.
+TEST_F(ZippedBugReportStreamTest, StreamLimitedOnlyReport) {
+    std::string out_path = kTestDataPath + "StreamLimitedOnlyReportOut.zip";
     android::base::unique_fd out_fd;
     CreateFd(out_path, &out_fd);
-    ds_.options_->wifi_only = true;
+    ds_.options_->limited_only = true;
     ds_.options_->stream_to_socket = true;
     RedirectOutputToFd(out_fd);
 
@@ -1051,7 +1051,7 @@
     ExtractToMemory(handle_, &entry, reinterpret_cast<uint8_t*>(bugreport_txt_name.data()),
                     entry.uncompressed_length);
     EXPECT_THAT(bugreport_txt_name,
-                testing::ContainsRegex("(bugreport-.+-wifi(-[[:digit:]]+){6}\\.txt)"));
+                testing::ContainsRegex("(bugreport-.+(-[[:digit:]]+){6}\\.txt)"));
     VerifyEntry(handle_, bugreport_txt_name, &entry);
 }
 
diff --git a/include/android/bitmap.h b/include/android/bitmap.h
index a70dffd..6704a1d 100644
--- a/include/android/bitmap.h
+++ b/include/android/bitmap.h
@@ -241,6 +241,7 @@
  *
  *  Available since API level 30.
  *
+ *  @param env Handle to the JNI environment pointer.
  *  @param bitmap Handle to an android.graphics.Bitmap.
  *  @param outBuffer On success, is set to a pointer to the
  *         {@link AHardwareBuffer} associated with bitmap. This acquires
diff --git a/include/android/choreographer.h b/include/android/choreographer.h
index cc5420e..b743f49 100644
--- a/include/android/choreographer.h
+++ b/include/android/choreographer.h
@@ -32,6 +32,11 @@
 __BEGIN_DECLS
 
 struct AChoreographer;
+/**
+ * Opaque type that provides access to an AChoreographer object.
+ *
+ * A pointer can be obtained using {@link AChoreographer_getInstance()}.
+ */
 typedef struct AChoreographer AChoreographer;
 
 /**
diff --git a/include/android/font.h b/include/android/font.h
index a172618..8a3a474 100644
--- a/include/android/font.h
+++ b/include/android/font.h
@@ -189,7 +189,7 @@
  * Available since API level 29.
  *
  * \param font a font object. Passing NULL is not allowed.
- * \return a positive integer less than or equal to {@link ASYSTEM_FONT_MAX_WEIGHT} is returned.
+ * \return a positive integer less than or equal to {@link AFONT_WEIGHT_MAX} is returned.
  */
 uint16_t AFont_getWeight(const AFont* _Nonnull font) __INTRODUCED_IN(29);
 
@@ -241,7 +241,7 @@
  * In this case, AFont_getAxisCount returns 2 and AFont_getAxisTag
  * and AFont_getAxisValue will return following values.
  * \code{.cpp}
- *     AFont* font = AFontIterator_next(ite);
+ *     AFont* font = ASystemFontIterator_next(ite);
  *
  *     // Returns the number of axes
  *     AFont_getAxisCount(font);  // Returns 2
@@ -289,7 +289,7 @@
  *
  * \param font a font object. Passing NULL is not allowed.
  * \param axisIndex an index to the font variation settings. Passing value larger than or
- *         equal to {@link ASYstemFont_getAxisCount} is not allwed.
+ *         equal to {@link AFont_getAxisCount} is not allowed.
  * \return a float value for the given font variation setting.
  */
 float AFont_getAxisValue(const AFont* _Nonnull font, uint32_t axisIndex)
diff --git a/include/android/font_matcher.h b/include/android/font_matcher.h
index 49e478c..4417422 100644
--- a/include/android/font_matcher.h
+++ b/include/android/font_matcher.h
@@ -36,7 +36,7 @@
  *  // Simple font query for the ASCII character.
  *  std::vector<uint16_t> text = { 'A' };
  *  AFontMatcher* matcher = AFontMatcher_create("sans-serif");
- *  ASystemFont* font = AFontMatcher_match(text.data(), text.length(), &runLength);
+ *  AFont* font = AFontMatcher_match(text.data(), text.length(), &runLength);
  *  // runLength will be 1 and the font will points a valid font file.
  *  AFontMatcher_destroy(matcher);
  *
@@ -44,17 +44,17 @@
  *  std::vector<uint16_t> text = { 0x9AA8 };
  *  AFontMatcher* matcher = AFontMatcher_create("sans-serif");
  *  AFontMatcher_setLocales(matcher, "zh-CN,ja-JP");
- *  ASystemFont* font = AFontMatcher_match(text.data(), text.length(), &runLength);
+ *  AFont* font = AFontMatcher_match(text.data(), text.length(), &runLength);
  *  // runLength will be 1 and the font will points a Simplified Chinese font.
  *  AFontMatcher_setLocales(matcher, "ja-JP,zh-CN");
- *  ASystemFont* font = AFontMatcher_match(text.data(), text.length(), &runLength);
+ *  AFont* font = AFontMatcher_match(text.data(), text.length(), &runLength);
  *  // runLength will be 1 and the font will points a Japanese font.
  *  AFontMatcher_destroy(matcher);
  *
  *  // Querying font for text/color emoji
  *  std::vector<uint16_t> text = { 0xD83D, 0xDC68, 0x200D, 0x2764, 0xFE0F, 0x200D, 0xD83D, 0xDC68 };
  *  AFontMatcher* matcher = AFontMatcher_create("sans-serif");
- *  ASystemFont* font = AFontMatcher_match(text.data(), text.length(), &runLength);
+ *  AFont* font = AFontMatcher_match(text.data(), text.length(), &runLength);
  *  // runLength will be 8 and the font will points a color emoji font.
  *  AFontMatcher_destroy(matcher);
  *
@@ -62,7 +62,7 @@
  *  // 0x05D0 is a Hebrew character and 0x0E01 is a Thai character.
  *  std::vector<uint16_t> text = { 0x05D0, 0x0E01 };
  *  AFontMatcher* matcher = AFontMatcher_create("sans-serif");
- *  ASystemFont* font = AFontMatcher_match(text.data(), text.length(), &runLength);
+ *  AFont* font = AFontMatcher_match(text.data(), text.length(), &runLength);
  *  // runLength will be 1 and the font will points a Hebrew font.
  *  AFontMatcher_destroy(matcher);
  * \endcode
@@ -146,7 +146,7 @@
 /**
  * Set font style to matcher.
  *
- * If this function is not called, the matcher performs with {@link ASYSTEM_FONT_WEIGHT_NORMAL}
+ * If this function is not called, the matcher performs with {@link AFONT_WEIGHT_NORMAL}
  * with non-italic style.
  *
  * Available since API level 29.
@@ -206,7 +206,7 @@
  * \param textLength a length of the given text buffer. This must not be zero.
  * \param runLengthOut if not null, the font run length will be filled.
  * \return a font to be used for given text and params. You need to release the returned font by
- *         ASystemFont_close when it is no longer needed.
+ *         AFont_close when it is no longer needed.
  */
 AFont* _Nonnull AFontMatcher_match(
         const AFontMatcher* _Nonnull matcher,
diff --git a/libs/binder/Android.bp b/libs/binder/Android.bp
index e980dd0..6da4e9e 100644
--- a/libs/binder/Android.bp
+++ b/libs/binder/Android.bp
@@ -160,6 +160,7 @@
         "-Werror",
         "-Wzero-as-null-pointer-constant",
         "-DANDROID_BASE_UNIQUE_FD_DISABLE_IMPLICIT_CONVERSION",
+        "-DANDROID_UTILS_REF_BASE_DISABLE_IMPLICIT_CONSTRUCTION",
     ],
     product_variables: {
         binder32bit: {
diff --git a/libs/binder/AppOpsManager.cpp b/libs/binder/AppOpsManager.cpp
index de42f36..baa9d75 100644
--- a/libs/binder/AppOpsManager.cpp
+++ b/libs/binder/AppOpsManager.cpp
@@ -37,7 +37,7 @@
 
     pthread_mutex_lock(&gClientIdMutex);
     if (gClientId == nullptr) {
-        gClientId = new BBinder();
+        gClientId = sp<BBinder>::make();
     }
     pthread_mutex_unlock(&gClientIdMutex);
     return gClientId;
diff --git a/libs/binder/BpBinder.cpp b/libs/binder/BpBinder.cpp
index 53b36ff..fdcf94a 100644
--- a/libs/binder/BpBinder.cpp
+++ b/libs/binder/BpBinder.cpp
@@ -107,8 +107,7 @@
 
 // ---------------------------------------------------------------------------
 
-
-BpBinder* BpBinder::create(int32_t handle) {
+sp<BpBinder> BpBinder::create(int32_t handle) {
     int32_t trackedUid = -1;
     if (sCountByUidEnabled) {
         trackedUid = IPCThreadState::self()->getCallingUid();
@@ -134,10 +133,10 @@
         }
         sTrackingMap[trackedUid]++;
     }
-    return new BpBinder(BinderHandle{handle}, trackedUid);
+    return sp<BpBinder>::make(BinderHandle{handle}, trackedUid);
 }
 
-BpBinder* BpBinder::create(const sp<RpcConnection>& connection, const RpcAddress& address) {
+sp<BpBinder> BpBinder::create(const sp<RpcConnection>& connection, const RpcAddress& address) {
     LOG_ALWAYS_FATAL_IF(connection == nullptr, "BpBinder::create null connection");
 
     // These are not currently tracked, since there is no UID or other
@@ -145,7 +144,7 @@
     // needed, connection objects keep track of all BpBinder objects on a
     // per-connection basis.
 
-    return new BpBinder(SocketHandle{connection, address});
+    return sp<BpBinder>::make(SocketHandle{connection, address});
 }
 
 BpBinder::BpBinder(Handle&& handle)
@@ -194,7 +193,7 @@
 const String16& BpBinder::getInterfaceDescriptor() const
 {
     if (isDescriptorCached() == false) {
-        sp<BpBinder> thiz = const_cast<BpBinder*>(this);
+        sp<BpBinder> thiz = sp<BpBinder>::fromExisting(const_cast<BpBinder*>(this));
 
         Parcel data;
         data.markForBinder(thiz);
@@ -226,7 +225,7 @@
 status_t BpBinder::pingBinder()
 {
     Parcel data;
-    data.markForBinder(this);
+    data.markForBinder(sp<BpBinder>::fromExisting(this));
     Parcel reply;
     return transact(PING_TRANSACTION, data, &reply);
 }
@@ -403,7 +402,7 @@
     ALOGV("Reporting death to recipient: %p\n", recipient.get());
     if (recipient == nullptr) return;
 
-    recipient->binderDied(this);
+    recipient->binderDied(wp<BpBinder>::fromExisting(this));
 }
 
 
diff --git a/libs/binder/BufferedTextOutput.cpp b/libs/binder/BufferedTextOutput.cpp
index 349658e..a90bfd2 100644
--- a/libs/binder/BufferedTextOutput.cpp
+++ b/libs/binder/BufferedTextOutput.cpp
@@ -254,7 +254,7 @@
         BufferState* bs = ts.states[mIndex].get();
         if (bs != nullptr && bs->seq == mSeq) return bs;
 
-        ts.states.editItemAt(mIndex) = new BufferState(mIndex);
+        ts.states.editItemAt(mIndex) = sp<BufferState>::make(mIndex);
         bs = ts.states[mIndex].get();
         if (bs != nullptr) return bs;
     }
diff --git a/libs/binder/IInterface.cpp b/libs/binder/IInterface.cpp
index b19004d..2780bd4 100644
--- a/libs/binder/IInterface.cpp
+++ b/libs/binder/IInterface.cpp
@@ -33,14 +33,14 @@
 sp<IBinder> IInterface::asBinder(const IInterface* iface)
 {
     if (iface == nullptr) return nullptr;
-    return const_cast<IInterface*>(iface)->onAsBinder();
+    return sp<IBinder>::fromExisting(const_cast<IInterface*>(iface)->onAsBinder());
 }
 
 // static
 sp<IBinder> IInterface::asBinder(const sp<IInterface>& iface)
 {
     if (iface == nullptr) return nullptr;
-    return iface->onAsBinder();
+    return sp<IBinder>::fromExisting(iface->onAsBinder());
 }
 
 
diff --git a/libs/binder/IMemory.cpp b/libs/binder/IMemory.cpp
index cca8f81..bd974b0 100644
--- a/libs/binder/IMemory.cpp
+++ b/libs/binder/IMemory.cpp
@@ -68,7 +68,7 @@
     // TODO: Reimplemement based on standard C++ container?
 };
 
-static sp<HeapCache> gHeapCache = new HeapCache();
+static sp<HeapCache> gHeapCache = sp<HeapCache>::make();
 
 /******************************************************************************/
 
@@ -288,7 +288,7 @@
     int32_t heapId = mHeapId.load(memory_order_acquire);
     if (heapId == -1) {
         sp<IBinder> binder(IInterface::asBinder(const_cast<BpMemoryHeap*>(this)));
-        sp<BpMemoryHeap> heap(static_cast<BpMemoryHeap*>(find_heap(binder).get()));
+        sp<BpMemoryHeap> heap = sp<BpMemoryHeap>::cast(find_heap(binder));
         heap->assertReallyMapped();
         if (heap->mBase != MAP_FAILED) {
             Mutex::Autolock _l(mLock);
diff --git a/libs/binder/IServiceManager.cpp b/libs/binder/IServiceManager.cpp
index ca067e2..61f4581 100644
--- a/libs/binder/IServiceManager.cpp
+++ b/libs/binder/IServiceManager.cpp
@@ -102,7 +102,7 @@
             }
         }
 
-        gDefaultServiceManager = new ServiceManagerShim(sm);
+        gDefaultServiceManager = sp<ServiceManagerShim>::make(sm);
     });
 
     return gDefaultServiceManager;
@@ -324,7 +324,7 @@
     }
     if (out != nullptr) return out;
 
-    sp<Waiter> waiter = new Waiter;
+    sp<Waiter> waiter = sp<Waiter>::make();
     if (!mTheRealServiceManager->registerForNotifications(
             name, waiter).isOk()) {
         return nullptr;
diff --git a/libs/binder/LazyServiceRegistrar.cpp b/libs/binder/LazyServiceRegistrar.cpp
index f96b6bb..b503beb 100644
--- a/libs/binder/LazyServiceRegistrar.cpp
+++ b/libs/binder/LazyServiceRegistrar.cpp
@@ -129,7 +129,9 @@
     }
 
     if (!reRegister) {
-        if(!manager->registerClientCallback(name, service, this).isOk()) {
+        if (!manager->registerClientCallback(name, service,
+                                             sp<android::os::IClientCallback>::fromExisting(this))
+                     .isOk()) {
             ALOGE("Failed to add client callback for service %s", name.c_str());
             return false;
         }
diff --git a/libs/binder/MemoryDealer.cpp b/libs/binder/MemoryDealer.cpp
index b46b3e8..c4475c7 100644
--- a/libs/binder/MemoryDealer.cpp
+++ b/libs/binder/MemoryDealer.cpp
@@ -228,10 +228,8 @@
 // ----------------------------------------------------------------------------
 
 MemoryDealer::MemoryDealer(size_t size, const char* name, uint32_t flags)
-    : mHeap(new MemoryHeapBase(size, flags, name)),
-    mAllocator(new SimpleBestFitAllocator(size))
-{    
-}
+      : mHeap(sp<MemoryHeapBase>::make(size, flags, name)),
+        mAllocator(new SimpleBestFitAllocator(size)) {}
 
 MemoryDealer::~MemoryDealer()
 {
@@ -243,7 +241,7 @@
     sp<IMemory> memory;
     const ssize_t offset = allocator()->allocate(size);
     if (offset >= 0) {
-        memory = new Allocation(this, heap(), offset, size);
+        memory = sp<Allocation>::make(sp<MemoryDealer>::fromExisting(this), heap(), offset, size);
     }
     return memory;
 }
diff --git a/libs/binder/Parcel.cpp b/libs/binder/Parcel.cpp
index 0425159..a735309 100644
--- a/libs/binder/Parcel.cpp
+++ b/libs/binder/Parcel.cpp
@@ -293,7 +293,8 @@
     if (flat) {
         switch (flat->hdr.type) {
             case BINDER_TYPE_BINDER: {
-                sp<IBinder> binder = reinterpret_cast<IBinder*>(flat->cookie);
+                sp<IBinder> binder =
+                        sp<IBinder>::fromExisting(reinterpret_cast<IBinder*>(flat->cookie));
                 return finishUnflattenBinder(binder, out);
             }
             case BINDER_TYPE_HANDLE: {
diff --git a/libs/binder/ProcessState.cpp b/libs/binder/ProcessState.cpp
index abb792e..7647a8c 100644
--- a/libs/binder/ProcessState.cpp
+++ b/libs/binder/ProcessState.cpp
@@ -105,7 +105,7 @@
         }
 
         std::lock_guard<std::mutex> l(gProcessMutex);
-        gProcess = new ProcessState(driver);
+        gProcess = sp<ProcessState>::make(driver);
     });
 
     if (requireDefault) {
@@ -299,8 +299,8 @@
                    return nullptr;
             }
 
-            b = BpBinder::create(handle);
-            e->binder = b;
+            sp<BpBinder> b = BpBinder::create(handle);
+            e->binder = b.get();
             if (b) e->refs = b->getWeakRefs();
             result = b;
         } else {
@@ -340,7 +340,7 @@
     if (mThreadPoolStarted) {
         String8 name = makeBinderThreadName();
         ALOGV("Spawning new pooled thread, name=%s\n", name.string());
-        sp<Thread> t = new PoolThread(isMain);
+        sp<Thread> t = sp<PoolThread>::make(isMain);
         t->run(name.string());
     }
 }
diff --git a/libs/binder/RpcConnection.cpp b/libs/binder/RpcConnection.cpp
index dab3246..1bf3d88 100644
--- a/libs/binder/RpcConnection.cpp
+++ b/libs/binder/RpcConnection.cpp
@@ -54,7 +54,7 @@
 }
 
 sp<RpcConnection> RpcConnection::make() {
-    return new RpcConnection;
+    return sp<RpcConnection>::make();
 }
 
 class UnixSocketAddress : public RpcConnection::SocketAddress {
@@ -120,20 +120,21 @@
 #endif // __BIONIC__
 
 sp<IBinder> RpcConnection::getRootObject() {
-    ExclusiveSocket socket(this, SocketUse::CLIENT);
-    return state()->getRootObject(socket.fd(), this);
+    ExclusiveSocket socket(sp<RpcConnection>::fromExisting(this), SocketUse::CLIENT);
+    return state()->getRootObject(socket.fd(), sp<RpcConnection>::fromExisting(this));
 }
 
 status_t RpcConnection::transact(const RpcAddress& address, uint32_t code, const Parcel& data,
                                  Parcel* reply, uint32_t flags) {
-    ExclusiveSocket socket(this,
+    ExclusiveSocket socket(sp<RpcConnection>::fromExisting(this),
                            (flags & IBinder::FLAG_ONEWAY) ? SocketUse::CLIENT_ASYNC
                                                           : SocketUse::CLIENT);
-    return state()->transact(socket.fd(), address, code, data, this, reply, flags);
+    return state()->transact(socket.fd(), address, code, data,
+                             sp<RpcConnection>::fromExisting(this), reply, flags);
 }
 
 status_t RpcConnection::sendDecStrong(const RpcAddress& address) {
-    ExclusiveSocket socket(this, SocketUse::CLIENT_REFCOUNT);
+    ExclusiveSocket socket(sp<RpcConnection>::fromExisting(this), SocketUse::CLIENT_REFCOUNT);
     return state()->sendDecStrong(socket.fd(), address);
 }
 
@@ -157,10 +158,11 @@
     // We may not use the connection we just established (two threads might
     // establish connections for each other), but for now, just use one
     // server/socket connection.
-    ExclusiveSocket socket(this, SocketUse::SERVER);
+    ExclusiveSocket socket(sp<RpcConnection>::fromExisting(this), SocketUse::SERVER);
 
     while (true) {
-        status_t error = state()->getAndExecuteCommand(socket.fd(), this);
+        status_t error =
+                state()->getAndExecuteCommand(socket.fd(), sp<RpcConnection>::fromExisting(this));
 
         if (error != OK) {
             ALOGI("Binder socket thread closing w/ status %s", statusToString(error).c_str());
@@ -221,7 +223,7 @@
     LOG_RPC_DETAIL("Socket at %s client with fd %d", addr.toString().c_str(), serverFd.get());
 
     std::lock_guard<std::mutex> _l(mSocketMutex);
-    sp<ConnectionSocket> connection = new ConnectionSocket();
+    sp<ConnectionSocket> connection = sp<ConnectionSocket>::make();
     connection->fd = std::move(serverFd);
     mClients.push_back(connection);
     return true;
@@ -229,7 +231,7 @@
 
 void RpcConnection::assignServerToThisThread(base::unique_fd&& fd) {
     std::lock_guard<std::mutex> _l(mSocketMutex);
-    sp<ConnectionSocket> connection = new ConnectionSocket();
+    sp<ConnectionSocket> connection = sp<ConnectionSocket>::make();
     connection->fd = std::move(fd);
     mServers.push_back(connection);
 }
diff --git a/libs/binder/RpcServer.cpp b/libs/binder/RpcServer.cpp
index df07916..1fa37ba 100644
--- a/libs/binder/RpcServer.cpp
+++ b/libs/binder/RpcServer.cpp
@@ -36,7 +36,7 @@
 RpcServer::~RpcServer() {}
 
 sp<RpcServer> RpcServer::make() {
-    return new RpcServer;
+    return sp<RpcServer>::make();
 }
 
 void RpcServer::iUnderstandThisCodeIsExperimentalAndIWillNotUseItInProduction() {
@@ -47,7 +47,7 @@
     LOG_ALWAYS_FATAL_IF(!mAgreedExperimental, "no!");
 
     auto connection = RpcConnection::make();
-    connection->setForServer(this);
+    connection->setForServer(sp<RpcServer>::fromExisting(this));
     mConnections.push_back(connection);
     return connection;
 }
diff --git a/libs/binder/include/binder/Binder.h b/libs/binder/include/binder/Binder.h
index 7079544..7e9be41 100644
--- a/libs/binder/include/binder/Binder.h
+++ b/libs/binder/include/binder/Binder.h
@@ -131,8 +131,8 @@
     virtual void            onLastStrongRef(const void* id);
     virtual bool            onIncStrongAttempted(uint32_t flags, const void* id);
 
-    inline  IBinder*        remote()                { return mRemote; }
-    inline  IBinder*        remote() const          { return mRemote; }
+    inline IBinder* remote() const { return mRemote; }
+    inline sp<IBinder> remoteStrong() const { return sp<IBinder>::fromExisting(mRemote); }
 
 private:
                             BpRefBase(const BpRefBase& o);
diff --git a/libs/binder/include/binder/BpBinder.h b/libs/binder/include/binder/BpBinder.h
index 8ab7893..ad618f9 100644
--- a/libs/binder/include/binder/BpBinder.h
+++ b/libs/binder/include/binder/BpBinder.h
@@ -40,8 +40,8 @@
 class BpBinder : public IBinder
 {
 public:
-    static BpBinder*    create(int32_t handle);
-    static BpBinder* create(const sp<RpcConnection>& connection, const RpcAddress& address);
+    static sp<BpBinder> create(int32_t handle);
+    static sp<BpBinder> create(const sp<RpcConnection>& connection, const RpcAddress& address);
 
     /**
      * Return value:
@@ -143,6 +143,7 @@
 
 private:
     friend PrivateAccessorForId;
+    friend class sp<BpBinder>;
 
     struct BinderHandle {
         int32_t handle;
diff --git a/libs/binder/include/binder/IInterface.h b/libs/binder/include/binder/IInterface.h
index b86fc0b..ff90b30 100644
--- a/libs/binder/include/binder/IInterface.h
+++ b/libs/binder/include/binder/IInterface.h
@@ -143,11 +143,10 @@
     {                                                                   \
         ::android::sp<I##INTERFACE> intr;                               \
         if (obj != nullptr) {                                           \
-            intr = static_cast<I##INTERFACE*>(                          \
-                obj->queryLocalInterface(                               \
-                        I##INTERFACE::descriptor).get());               \
+            intr = ::android::sp<I##INTERFACE>::cast(                   \
+                obj->queryLocalInterface(I##INTERFACE::descriptor));    \
             if (intr == nullptr) {                                      \
-                intr = new Bp##INTERFACE(obj);                          \
+                intr = ::android::sp<Bp##INTERFACE>::make(obj);         \
             }                                                           \
         }                                                               \
         return intr;                                                    \
diff --git a/libs/binder/include/binder/ProcessState.h b/libs/binder/include/binder/ProcessState.h
index ca29440..0919648 100644
--- a/libs/binder/include/binder/ProcessState.h
+++ b/libs/binder/include/binder/ProcessState.h
@@ -88,7 +88,8 @@
     static  sp<ProcessState>    init(const char *defaultDriver, bool requireDefault);
 
     friend class IPCThreadState;
-    
+    friend class sp<ProcessState>;
+
             explicit            ProcessState(const char* driver);
                                 ~ProcessState();
 
diff --git a/libs/binder/include/binder/RpcServer.h b/libs/binder/include/binder/RpcServer.h
index a2c2aee..d29b651 100644
--- a/libs/binder/include/binder/RpcServer.h
+++ b/libs/binder/include/binder/RpcServer.h
@@ -72,6 +72,7 @@
     ~RpcServer();
 
 private:
+    friend sp<RpcServer>;
     RpcServer();
 
     bool mAgreedExperimental = false;
diff --git a/libs/gui/Android.bp b/libs/gui/Android.bp
index ff059d7..64203f7 100644
--- a/libs/gui/Android.bp
+++ b/libs/gui/Android.bp
@@ -39,12 +39,50 @@
     min_sdk_version: "29",
 }
 
+cc_library_headers {
+    name: "libgui_aidl_headers",
+    vendor_available: true,
+    static_libs: [
+        "libgui_aidl_static",
+    ],
+
+    export_static_lib_headers: [
+        "libgui_aidl_static",
+    ],
+}
+
 filegroup {
     name: "libgui_aidl",
     srcs: ["aidl/**/*.aidl"],
     path: "aidl/",
 }
 
+cc_library_static {
+    name: "libgui_aidl_static",
+    vendor_available: true,
+    srcs: [
+        ":libgui_aidl",
+    ],
+
+    shared_libs: [
+        "libbinder",
+        "libui",
+    ],
+
+    local_include_dirs: [
+        "include",
+    ],
+
+    export_shared_lib_headers: [
+        "libbinder",
+    ],
+
+    aidl: {
+        export_aidl_headers: true
+    }
+}
+
+
 cc_library_shared {
     name: "libgui",
     vendor_available: true,
@@ -56,10 +94,16 @@
 
     defaults: ["libgui_bufferqueue-defaults"],
 
+    static_libs: [
+        "libgui_aidl_static",
+    ],
+    export_static_lib_headers: [
+        "libgui_aidl_static",
+    ],
+
     srcs: [
         ":framework_native_aidl",
         ":inputconstants_aidl",
-        ":libgui_aidl",
         ":libgui_bufferqueue_sources",
 
         "BitTube.cpp",
@@ -115,6 +159,10 @@
         "libinput",
     ],
 
+    export_header_lib_headers: [
+        "libgui_aidl_headers",
+    ],
+
     // bufferhub is not used when building libgui for vendors
     target: {
         vendor: {
@@ -136,15 +184,16 @@
         },
     },
 
-    header_libs: [
-        "libdvr_headers",
-        "libpdx_headers",
-    ],
-
     aidl: {
         export_aidl_headers: true,
     },
 
+    header_libs: [
+        "libdvr_headers",
+        "libgui_aidl_headers",
+        "libpdx_headers",
+    ],
+
     pgo: {
         sampling: true,
         profile_file: "libgui/libgui.profdata",
@@ -175,8 +224,8 @@
 
     srcs: [
         ":inputconstants_aidl",
-        ":libgui_aidl",
         ":libgui_bufferqueue_sources",
+        ":libgui_aidl",
     ],
 }
 
diff --git a/libs/gui/include/gui/FrameTimelineInfo.h b/libs/gui/include/gui/FrameTimelineInfo.h
index 3b4c009..a23c202 100644
--- a/libs/gui/include/gui/FrameTimelineInfo.h
+++ b/libs/gui/include/gui/FrameTimelineInfo.h
@@ -18,7 +18,6 @@
 
 #include <stdint.h>
 
-#include <android/os/IInputConstants.h>
 #include <binder/Parcel.h>
 
 namespace android {
@@ -31,7 +30,11 @@
     int64_t vsyncId = INVALID_VSYNC_ID;
 
     // The id of the input event that caused this buffer
-    int32_t inputEventId = android::os::IInputConstants::INVALID_INPUT_EVENT_ID;
+    // Default is android::os::IInputConstants::INVALID_INPUT_EVENT_ID = 0
+    // We copy the value of the input event ID instead of including the header, because libgui
+    // header libraries containing FrameTimelineInfo must be available to vendors, but libinput is
+    // not directly vendor available.
+    int32_t inputEventId = 0;
 
     status_t write(Parcel& output) const;
     status_t read(const Parcel& input);
diff --git a/libs/nativewindow/include/android/native_window.h b/libs/nativewindow/include/android/native_window.h
index 50e9d53..61b3f94 100644
--- a/libs/nativewindow/include/android/native_window.h
+++ b/libs/nativewindow/include/android/native_window.h
@@ -157,6 +157,7 @@
  * For all of these parameters, if 0 is supplied then the window's base
  * value will come back in force.
  *
+ * \param window pointer to an ANativeWindow object.
  * \param width width of the buffers in pixels.
  * \param height height of the buffers in pixels.
  * \param format one of the AHardwareBuffer_Format constants.
@@ -191,6 +192,7 @@
  *
  * Available since API level 26.
  *
+ * \param window pointer to an ANativeWindow object.
  * \param transform combination of {@link ANativeWindowTransform} flags
  * \return 0 for success, or -EINVAL if \p transform is invalid
  */
@@ -208,6 +210,7 @@
  *
  * Available since API level 28.
  *
+ * \param window pointer to an ANativeWindow object.
  * \param dataSpace data space of all buffers queued after this call.
  * \return 0 for success, -EINVAL if window is invalid or the dataspace is not
  * supported.
@@ -306,6 +309,8 @@
  * valid refresh rate for this device's display - e.g., it's fine to pass 30fps
  * to a device that can only run the display at 60fps.
  *
+ * \param window pointer to an ANativeWindow object.
+ *
  * \param compatibility The frame rate compatibility of this window. The
  * compatibility value may influence the system's choice of display refresh
  * rate. See the ANATIVEWINDOW_FRAME_RATE_COMPATIBILITY_* values for more info.
diff --git a/libs/renderengine/Android.bp b/libs/renderengine/Android.bp
index 026b19a..ec39137 100644
--- a/libs/renderengine/Android.bp
+++ b/libs/renderengine/Android.bp
@@ -91,6 +91,7 @@
         "skia/debug/CaptureTimer.cpp",
         "skia/debug/CommonPool.cpp",
         "skia/debug/SkiaCapture.cpp",
+        "skia/debug/SkiaMemoryReporter.cpp",
         "skia/filters/BlurFilter.cpp",
         "skia/filters/LinearEffect.cpp",
     ],
diff --git a/libs/renderengine/include/renderengine/RenderEngine.h b/libs/renderengine/include/renderengine/RenderEngine.h
index a69d1f0..8dd98c3 100644
--- a/libs/renderengine/include/renderengine/RenderEngine.h
+++ b/libs/renderengine/include/renderengine/RenderEngine.h
@@ -141,7 +141,7 @@
     // do any work.
     virtual bool cleanupPostRender(CleanupMode mode = CleanupMode::CLEAN_OUTPUT_RESOURCES) = 0;
 
-    // queries
+    // queries that are required to be thread safe
     virtual size_t getMaxTextureSize() const = 0;
     virtual size_t getMaxViewportDims() const = 0;
 
@@ -149,8 +149,11 @@
 
     // ----- BEGIN NEW INTERFACE -----
 
+    // queries that are required to be thread safe
     virtual bool isProtected() const = 0;
     virtual bool supportsProtectedContent() const = 0;
+
+    // Attempt to switch RenderEngine into and out of protectedContext mode
     virtual bool useProtectedContext(bool useProtectedContext) = 0;
 
     // Notify RenderEngine of changes to the dimensions of the primary display
@@ -197,7 +200,8 @@
     virtual int getContextPriority() = 0;
 
     // Returns true if blur was requested in the RenderEngineCreationArgs and the implementation
-    // also supports background blur.  If false, no blur will be applied when drawing layers.
+    // also supports background blur.  If false, no blur will be applied when drawing layers. This
+    // query is required to be thread safe.
     virtual bool supportsBackgroundBlur() = 0;
 
     // Returns the current type of RenderEngine instance that was created.
diff --git a/libs/renderengine/skia/Cache.cpp b/libs/renderengine/skia/Cache.cpp
index 0cd3b62..1db20c0 100644
--- a/libs/renderengine/skia/Cache.cpp
+++ b/libs/renderengine/skia/Cache.cpp
@@ -25,8 +25,6 @@
 #include "ui/Rect.h"
 #include "utils/Timers.h"
 
-#include <android/hardware_buffer.h>
-
 namespace android::renderengine::skia {
 
 namespace {
@@ -183,41 +181,6 @@
     }
 }
 
-namespace {
-
-struct AHardwareBuffer_deleter {
-    void operator()(AHardwareBuffer* ahb) const { AHardwareBuffer_release(ahb); }
-};
-
-std::unique_ptr<AHardwareBuffer, AHardwareBuffer_deleter> makeAHardwareBuffer() {
-    AHardwareBuffer* buffer = nullptr;
-
-    int w = 32;
-    int h = 32;
-
-    AHardwareBuffer_Desc hwbDesc;
-    hwbDesc.width = w;
-    hwbDesc.height = h;
-    hwbDesc.layers = 1;
-    hwbDesc.usage = AHARDWAREBUFFER_USAGE_CPU_READ_NEVER | AHARDWAREBUFFER_USAGE_CPU_WRITE_NEVER |
-            AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE;
-    hwbDesc.format = AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM;
-    // The following three are not used in the allocate
-    hwbDesc.stride = 0;
-    hwbDesc.rfu0 = 0;
-    hwbDesc.rfu1 = 0;
-
-    if (int error = AHardwareBuffer_allocate(&hwbDesc, &buffer)) {
-        ALOGE("Failed to allocated hardware buffer, error: %d", error);
-        if (buffer) {
-            AHardwareBuffer_release(buffer);
-        }
-        return nullptr;
-    }
-    return std::unique_ptr<AHardwareBuffer, AHardwareBuffer_deleter>(buffer);
-}
-} // namespace
-
 //
 // The collection of shaders cached here were found by using perfetto to record shader compiles
 // during actions that involve RenderEngine, logging the layer settings, and the shader code
@@ -265,14 +228,16 @@
     // The majority of shaders are related to sampling images.
     drawImageLayers(renderengine, display, dstBuffer, srcBuffer);
 
-    // Draw image layers again sampling from an AHardwareBuffer if it is possible to create one.
-    if (auto ahb = makeAHardwareBuffer()) {
-        sp<GraphicBuffer> externalBuffer = GraphicBuffer::fromAHardwareBuffer(ahb.get());
-        // TODO(b/184665179) doubles number of image shader compilations, but only somewhere
-        // between 6 and 8 will occur in real uses.
-        drawImageLayers(renderengine, display, dstBuffer, externalBuffer);
-        renderengine->unbindExternalTextureBuffer(externalBuffer->getId());
-    }
+    // should be the same as AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE;
+    const int64_t usageExternal = GRALLOC_USAGE_HW_TEXTURE;
+
+    sp<GraphicBuffer> externalBuffer =
+            new GraphicBuffer(displayRect.width(), displayRect.height(), PIXEL_FORMAT_RGBA_8888, 1,
+                              usageExternal, "primeShaderCache_external");
+    // TODO(b/184665179) doubles number of image shader compilations, but only somewhere
+    // between 6 and 8 will occur in real uses.
+    drawImageLayers(renderengine, display, dstBuffer, externalBuffer);
+    renderengine->unbindExternalTextureBuffer(externalBuffer->getId());
 
     renderengine->unbindExternalTextureBuffer(srcBuffer->getId());
 
diff --git a/libs/renderengine/skia/SkiaGLRenderEngine.cpp b/libs/renderengine/skia/SkiaGLRenderEngine.cpp
index fb7e285..3b2c7e5 100644
--- a/libs/renderengine/skia/SkiaGLRenderEngine.cpp
+++ b/libs/renderengine/skia/SkiaGLRenderEngine.cpp
@@ -28,6 +28,7 @@
 #include <SkColorFilter.h>
 #include <SkColorMatrix.h>
 #include <SkColorSpace.h>
+#include <SkGraphics.h>
 #include <SkImage.h>
 #include <SkImageFilters.h>
 #include <SkRegion.h>
@@ -40,13 +41,13 @@
 #include <ui/DebugUtils.h>
 #include <ui/GraphicBuffer.h>
 #include <utils/Trace.h>
-#include "Cache.h"
 
 #include <cmath>
 #include <cstdint>
 #include <memory>
 
 #include "../gl/GLExtensions.h"
+#include "Cache.h"
 #include "ColorSpaces.h"
 #include "SkBlendMode.h"
 #include "SkImageInfo.h"
@@ -54,6 +55,7 @@
 #include "filters/LinearEffect.h"
 #include "log/log_main.h"
 #include "skia/debug/SkiaCapture.h"
+#include "skia/debug/SkiaMemoryReporter.h"
 #include "system/graphics-base-v1.0.h"
 
 namespace {
@@ -1249,9 +1251,38 @@
     StringAppendF(&result, "RenderEngine shaders cached since last dump/primeCache: %d\n",
                   mSkSLCacheMonitor.shadersCachedSinceLastCall());
 
+    std::vector<ResourcePair> cpuResourceMap = {
+            {"skia/sk_resource_cache/bitmap_", "Bitmaps"},
+            {"skia/sk_resource_cache/rrect-blur_", "Masks"},
+            {"skia/sk_resource_cache/rects-blur_", "Masks"},
+            {"skia/sk_resource_cache/tessellated", "Shadows"},
+            {"skia", "Other"},
+    };
+    SkiaMemoryReporter cpuReporter(cpuResourceMap, false);
+    SkGraphics::DumpMemoryStatistics(&cpuReporter);
+    StringAppendF(&result, "Skia CPU Caches: ");
+    cpuReporter.logTotals(result);
+    cpuReporter.logOutput(result);
+
     {
         std::lock_guard<std::mutex> lock(mRenderingMutex);
-        StringAppendF(&result, "RenderEngine texture cache size: %zu\n", mTextureCache.size());
+
+        std::vector<ResourcePair> gpuResourceMap = {
+                {"texture_renderbuffer", "Texture/RenderBuffer"},
+                {"texture", "Texture"},
+                {"gr_text_blob_cache", "Text"},
+                {"skia", "Other"},
+        };
+        SkiaMemoryReporter gpuReporter(gpuResourceMap, true);
+        mGrContext->dumpMemoryStatistics(&gpuReporter);
+        StringAppendF(&result, "Skia's GPU Caches: ");
+        gpuReporter.logTotals(result);
+        gpuReporter.logOutput(result);
+        StringAppendF(&result, "Skia's Wrapped Objects:\n");
+        gpuReporter.logOutput(result, true);
+
+        StringAppendF(&result, "RenderEngine AHB/BackendTexture cache size: %zu\n",
+                      mTextureCache.size());
         StringAppendF(&result, "Dumping buffer ids...\n");
         // TODO(178539829): It would be nice to know which layer these are coming from and what
         // the texture sizes are.
@@ -1259,7 +1290,16 @@
             StringAppendF(&result, "- 0x%" PRIx64 "\n", id);
         }
         StringAppendF(&result, "\n");
-        StringAppendF(&result, "RenderEngine protected texture cache size: %zu\n",
+
+        SkiaMemoryReporter gpuProtectedReporter(gpuResourceMap, true);
+        mProtectedGrContext->dumpMemoryStatistics(&gpuProtectedReporter);
+        StringAppendF(&result, "Skia's GPU Protected Caches: ");
+        gpuProtectedReporter.logTotals(result);
+        gpuProtectedReporter.logOutput(result);
+        StringAppendF(&result, "Skia's Protected Wrapped Objects:\n");
+        gpuProtectedReporter.logOutput(result, true);
+
+        StringAppendF(&result, "RenderEngine protected AHB/BackendTexture cache size: %zu\n",
                       mProtectedTextureCache.size());
         StringAppendF(&result, "Dumping buffer ids...\n");
         for (const auto& [id, unused] : mProtectedTextureCache) {
diff --git a/libs/renderengine/skia/debug/SkiaMemoryReporter.cpp b/libs/renderengine/skia/debug/SkiaMemoryReporter.cpp
new file mode 100644
index 0000000..f24a4f1
--- /dev/null
+++ b/libs/renderengine/skia/debug/SkiaMemoryReporter.cpp
@@ -0,0 +1,205 @@
+/*
+ * Copyright (C) 2021 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.
+ */
+#undef LOG_TAG
+#define LOG_TAG "RenderEngine"
+
+#include "SkiaMemoryReporter.h"
+
+#include <SkString.h>
+#include <android-base/stringprintf.h>
+#include <log/log_main.h>
+
+namespace android {
+namespace renderengine {
+namespace skia {
+
+using base::StringAppendF;
+
+SkiaMemoryReporter::SkiaMemoryReporter(const std::vector<ResourcePair>& resourceMap, bool itemize)
+      : mResourceMap(resourceMap),
+        mItemize(itemize),
+        mTotalSize("bytes", 0),
+        mPurgeableSize("bytes", 0) {}
+
+const char* SkiaMemoryReporter::mapName(const char* resourceName) {
+    for (auto& resource : mResourceMap) {
+        if (SkStrContains(resourceName, resource.first)) {
+            return resource.second;
+        }
+    }
+    return nullptr;
+}
+
+void SkiaMemoryReporter::resetCurrentElement() {
+    mCurrentElement.clear();
+    mCurrentValues.clear();
+    mIsCurrentValueWrapped = false;
+}
+
+void SkiaMemoryReporter::processCurrentElement() {
+    // compute the top level element name using the map
+    const char* resourceName = mCurrentElement.empty() ? nullptr : mapName(mCurrentElement.c_str());
+
+    // if we don't have a resource name then we don't know how to label the
+    // data and should abort.
+    if (resourceName == nullptr) {
+        resetCurrentElement();
+        return;
+    }
+
+    // Only count elements that contain "size"; other values just provide metadata.
+    auto sizeResult = mCurrentValues.find("size");
+    if (sizeResult != mCurrentValues.end() && sizeResult->second.value > 0) {
+        if (!mIsCurrentValueWrapped) {
+            mTotalSize.value += sizeResult->second.value;
+            mTotalSize.count++;
+        }
+    } else {
+        resetCurrentElement();
+        return;
+    }
+
+    // find the purgeable size if one exists
+    auto purgeableResult = mCurrentValues.find("purgeable_size");
+    if (!mIsCurrentValueWrapped && purgeableResult != mCurrentValues.end()) {
+        mPurgeableSize.value += purgeableResult->second.value;
+        mPurgeableSize.count++;
+    }
+
+    // do we store this element in the wrapped list or the skia managed list
+    auto& results = mIsCurrentValueWrapped ? mWrappedResults : mResults;
+
+    // insert a copy of the element and all of its keys. We must make a copy here instead of
+    // std::move() as we will continue to use these values later in the function and again
+    // when we move on to process the next element.
+    results.insert({mCurrentElement, mCurrentValues});
+
+    // insert the item into its mapped category
+    auto result = results.find(resourceName);
+    if (result != results.end()) {
+        auto& resourceValues = result->second;
+        auto totalResult = resourceValues.find(sizeResult->first);
+        if (totalResult != resourceValues.end()) {
+            ALOGE_IF(sizeResult->second.units != totalResult->second.units,
+                     "resource units do not match so the sum of resource type (%s) will be invalid",
+                     resourceName);
+            totalResult->second.value += sizeResult->second.value;
+            totalResult->second.count++;
+        } else {
+            ALOGE("an entry (%s) should not exist in the results without a size", resourceName);
+        }
+    } else {
+        // only store the size for the top level resource
+        results.insert({resourceName, {{sizeResult->first, sizeResult->second}}});
+    }
+
+    resetCurrentElement();
+}
+
+void SkiaMemoryReporter::dumpNumericValue(const char* dumpName, const char* valueName,
+                                          const char* units, uint64_t value) {
+    if (mCurrentElement != dumpName) {
+        processCurrentElement();
+        mCurrentElement = dumpName;
+    }
+    mCurrentValues.insert({valueName, {units, value}});
+}
+
+void SkiaMemoryReporter::dumpWrappedState(const char* dumpName, bool isWrappedObject) {
+    if (mCurrentElement != dumpName) {
+        processCurrentElement();
+        mCurrentElement = dumpName;
+    }
+    mIsCurrentValueWrapped = isWrappedObject;
+}
+
+void SkiaMemoryReporter::logOutput(std::string& log, bool wrappedResources) {
+    // process the current element before logging
+    processCurrentElement();
+
+    const auto& resultsMap = wrappedResources ? mWrappedResults : mResults;
+
+    // log each individual element based on the resource map
+    for (const auto& resourceCategory : mResourceMap) {
+        // find the named item and print the totals
+        const auto categoryItem = resultsMap.find(resourceCategory.second);
+        if (categoryItem != resultsMap.end()) {
+            auto result = categoryItem->second.find("size");
+            if (result != categoryItem->second.end()) {
+                TraceValue traceValue = convertUnits(result->second);
+                const char* entry = (traceValue.count > 1) ? "entries" : "entry";
+                StringAppendF(&log, "  %s: %.2f %s (%d %s)\n", categoryItem->first.c_str(),
+                              traceValue.value, traceValue.units, traceValue.count, entry);
+            }
+            if (mItemize) {
+                for (const auto& individualItem : resultsMap) {
+                    // if the individual item matches the category then print all its details or
+                    // in the case of wrapped resources just print the wrapped size
+                    const char* categoryMatch = mapName(individualItem.first.c_str());
+                    if (categoryMatch && strcmp(categoryMatch, resourceCategory.second) == 0) {
+                        auto result = individualItem.second.find("size");
+                        TraceValue size = convertUnits(result->second);
+                        StringAppendF(&log, "    %s: size[%.2f %s]", individualItem.first.c_str(),
+                                      size.value, size.units);
+                        if (!wrappedResources) {
+                            for (const auto& itemValues : individualItem.second) {
+                                if (strcmp("size", itemValues.first) == 0) {
+                                    continue;
+                                }
+                                TraceValue traceValue = convertUnits(itemValues.second);
+                                if (traceValue.value == 0.0f) {
+                                    StringAppendF(&log, " %s[%s]", itemValues.first,
+                                                  traceValue.units);
+                                } else {
+                                    StringAppendF(&log, " %s[%.2f %s]", itemValues.first,
+                                                  traceValue.value, traceValue.units);
+                                }
+                            }
+                        }
+                        StringAppendF(&log, "\n");
+                    }
+                }
+            }
+        }
+    }
+}
+
+void SkiaMemoryReporter::logTotals(std::string& log) {
+    // process the current element before logging
+    processCurrentElement();
+
+    TraceValue total = convertUnits(mTotalSize);
+    TraceValue purgeable = convertUnits(mPurgeableSize);
+    StringAppendF(&log, " %.0f bytes, %.2f %s (%.2f %s is purgeable)\n", mTotalSize.value,
+                  total.value, total.units, purgeable.value, purgeable.units);
+}
+
+SkiaMemoryReporter::TraceValue SkiaMemoryReporter::convertUnits(const TraceValue& value) {
+    TraceValue output(value);
+    if (SkString("bytes") == SkString(output.units) && output.value >= 1024) {
+        output.value = output.value / 1024.0f;
+        output.units = "KB";
+    }
+    if (SkString("KB") == SkString(output.units) && output.value >= 1024) {
+        output.value = output.value / 1024.0f;
+        output.units = "MB";
+    }
+    return output;
+}
+
+} /* namespace skia */
+} /* namespace renderengine */
+} /* namespace android */
diff --git a/libs/renderengine/skia/debug/SkiaMemoryReporter.h b/libs/renderengine/skia/debug/SkiaMemoryReporter.h
new file mode 100644
index 0000000..dbbd65b
--- /dev/null
+++ b/libs/renderengine/skia/debug/SkiaMemoryReporter.h
@@ -0,0 +1,107 @@
+/*
+ * Copyright (C) 2021 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.
+ */
+
+#pragma once
+
+#include <SkTraceMemoryDump.h>
+
+#include <string>
+#include <unordered_map>
+#include <vector>
+
+namespace android {
+namespace renderengine {
+namespace skia {
+
+// Mapping of resource substrings (1st element) that if found within a trace "dumpName"
+// should be mapped to the category name (2nd element). All char* used in a resourcePair
+// are expected to have a lifetime longer than the SkiaMemoryReporter in which they are used.
+typedef std::pair<const char*, const char*> ResourcePair;
+
+/*
+ * Utility class for logging the CPU/GPU usage of Skia caches in a format that is specific
+ * to RenderEngine.  HWUI has a similar logging class, but the data collected and the way
+ * it is formatted and reported on are intended to be unique to each use case.
+ */
+class SkiaMemoryReporter : public SkTraceMemoryDump {
+public:
+    /**
+     * Creates the reporter class that can be populated by various Skia entry points, like
+     * SkGraphics and GrContext, as well as format and log the results.
+     * @param resourceMap An array of values that maps a Skia dumpName into a user defined category.
+     *                    The first vector entry that matches the dumpName is used for the mapping.
+     * @param itemize if true when logging the categories the individual elements will be printed
+     *                directly after the category details are printed.  Otherwise, only the category
+     *                totals will be printed.
+     */
+    SkiaMemoryReporter(const std::vector<ResourcePair>& resourceMap, bool itemize);
+    ~SkiaMemoryReporter() override {}
+
+    void logOutput(std::string& log, bool wrappedResources = false);
+    void logTotals(std::string& log);
+
+    void dumpNumericValue(const char* dumpName, const char* valueName, const char* units,
+                          uint64_t value) override;
+
+    void dumpStringValue(const char* dumpName, const char* valueName, const char* value) override {
+        // for convenience we just store this in the same format as numerical values
+        dumpNumericValue(dumpName, valueName, value, 0);
+    }
+    void dumpWrappedState(const char* dumpName, bool isWrappedObject) override;
+
+    LevelOfDetail getRequestedDetails() const override {
+        return SkTraceMemoryDump::kLight_LevelOfDetail;
+    }
+
+    bool shouldDumpWrappedObjects() const override { return true; }
+    void setMemoryBacking(const char*, const char*, const char*) override {}
+    void setDiscardableMemoryBacking(const char*, const SkDiscardableMemory&) override {}
+
+private:
+    struct TraceValue {
+        TraceValue(const char* units, uint64_t value) : units(units), value(value), count(1) {}
+        TraceValue(const TraceValue& v) : units(v.units), value(v.value), count(v.count) {}
+
+        const char* units;
+        float value;
+        int count;
+    };
+
+    const char* mapName(const char* resourceName);
+    void processCurrentElement();
+    void resetCurrentElement();
+    TraceValue convertUnits(const TraceValue& value);
+
+    const std::vector<ResourcePair>& mResourceMap;
+    const bool mItemize;
+
+    // variables storing the size of all non-wrapped elements being dumped
+    TraceValue mTotalSize;
+    TraceValue mPurgeableSize;
+
+    // variables storing information on the current node being dumped
+    std::string mCurrentElement;
+    std::unordered_map<const char*, TraceValue> mCurrentValues;
+    bool mIsCurrentValueWrapped = false;
+
+    // variable that stores the final format of the data after the individual elements are processed
+    std::unordered_map<std::string, std::unordered_map<const char*, TraceValue>> mResults;
+    std::unordered_map<std::string, std::unordered_map<const char*, TraceValue>> mWrappedResults;
+};
+
+} /* namespace skia */
+} /* namespace renderengine */
+} /* namespace android */
\ No newline at end of file
diff --git a/libs/renderengine/tests/RenderEngineThreadedTest.cpp b/libs/renderengine/tests/RenderEngineThreadedTest.cpp
index 63aa4c8..b093e88 100644
--- a/libs/renderengine/tests/RenderEngineThreadedTest.cpp
+++ b/libs/renderengine/tests/RenderEngineThreadedTest.cpp
@@ -49,6 +49,9 @@
 TEST_F(RenderEngineThreadedTest, primeCache) {
     EXPECT_CALL(*mRenderEngine, primeCache());
     mThreadedRE->primeCache();
+    // need to call ANY synchronous function after primeCache to ensure that primeCache has
+    // completed asynchronously before the test completes execution.
+    mThreadedRE->getContextPriority();
 }
 
 TEST_F(RenderEngineThreadedTest, genTextures) {
diff --git a/libs/renderengine/threaded/RenderEngineThreaded.cpp b/libs/renderengine/threaded/RenderEngineThreaded.cpp
index 783e37f..194c7da 100644
--- a/libs/renderengine/threaded/RenderEngineThreaded.cpp
+++ b/libs/renderengine/threaded/RenderEngineThreaded.cpp
@@ -74,6 +74,12 @@
     std::unique_lock<std::mutex> lock(mThreadMutex);
     pthread_setname_np(pthread_self(), mThreadName);
 
+    {
+        std::unique_lock<std::mutex> lock(mInitializedMutex);
+        mIsInitialized = true;
+    }
+    mInitializedCondition.notify_all();
+
     while (mRunning) {
         if (!mFunctionCalls.empty()) {
             auto task = mFunctionCalls.front();
@@ -86,19 +92,22 @@
     }
 }
 
+void RenderEngineThreaded::waitUntilInitialized() const {
+    std::unique_lock<std::mutex> lock(mInitializedMutex);
+    mInitializedCondition.wait(lock, [=] { return mIsInitialized; });
+}
+
 void RenderEngineThreaded::primeCache() {
-    std::promise<void> resultPromise;
-    std::future<void> resultFuture = resultPromise.get_future();
+    // This function is designed so it can run asynchronously, so we do not need to wait
+    // for the futures.
     {
         std::lock_guard lock(mThreadMutex);
-        mFunctionCalls.push([&resultPromise](renderengine::RenderEngine& instance) {
+        mFunctionCalls.push([](renderengine::RenderEngine& instance) {
             ATRACE_NAME("REThreaded::primeCache");
             instance.primeCache();
-            resultPromise.set_value();
         });
     }
     mCondition.notify_one();
-    resultFuture.wait();
 }
 
 void RenderEngineThreaded::dump(std::string& result) {
@@ -175,63 +184,26 @@
 }
 
 size_t RenderEngineThreaded::getMaxTextureSize() const {
-    std::promise<size_t> resultPromise;
-    std::future<size_t> resultFuture = resultPromise.get_future();
-    {
-        std::lock_guard lock(mThreadMutex);
-        mFunctionCalls.push([&resultPromise](renderengine::RenderEngine& instance) {
-            ATRACE_NAME("REThreaded::getMaxTextureSize");
-            size_t size = instance.getMaxTextureSize();
-            resultPromise.set_value(size);
-        });
-    }
-    mCondition.notify_one();
-    return resultFuture.get();
+    waitUntilInitialized();
+    return mRenderEngine->getMaxTextureSize();
 }
 
 size_t RenderEngineThreaded::getMaxViewportDims() const {
-    std::promise<size_t> resultPromise;
-    std::future<size_t> resultFuture = resultPromise.get_future();
-    {
-        std::lock_guard lock(mThreadMutex);
-        mFunctionCalls.push([&resultPromise](renderengine::RenderEngine& instance) {
-            ATRACE_NAME("REThreaded::getMaxViewportDims");
-            size_t size = instance.getMaxViewportDims();
-            resultPromise.set_value(size);
-        });
-    }
-    mCondition.notify_one();
-    return resultFuture.get();
+    waitUntilInitialized();
+    return mRenderEngine->getMaxViewportDims();
 }
 
 bool RenderEngineThreaded::isProtected() const {
-    std::promise<bool> resultPromise;
-    std::future<bool> resultFuture = resultPromise.get_future();
-    {
-        std::lock_guard lock(mThreadMutex);
-        mFunctionCalls.push([&resultPromise](renderengine::RenderEngine& instance) {
-            ATRACE_NAME("REThreaded::isProtected");
-            bool returnValue = instance.isProtected();
-            resultPromise.set_value(returnValue);
-        });
-    }
-    mCondition.notify_one();
-    return resultFuture.get();
+    waitUntilInitialized();
+    // ensure that useProtectedContext is not currently being changed by some
+    // other thread.
+    std::lock_guard lock(mThreadMutex);
+    return mRenderEngine->isProtected();
 }
 
 bool RenderEngineThreaded::supportsProtectedContent() const {
-    std::promise<bool> resultPromise;
-    std::future<bool> resultFuture = resultPromise.get_future();
-    {
-        std::lock_guard lock(mThreadMutex);
-        mFunctionCalls.push([&resultPromise](renderengine::RenderEngine& instance) {
-            ATRACE_NAME("REThreaded::supportsProtectedContent");
-            bool returnValue = instance.supportsProtectedContent();
-            resultPromise.set_value(returnValue);
-        });
-    }
-    mCondition.notify_one();
-    return resultFuture.get();
+    waitUntilInitialized();
+    return mRenderEngine->supportsProtectedContent();
 }
 
 bool RenderEngineThreaded::useProtectedContext(bool useProtectedContext) {
@@ -288,18 +260,16 @@
 }
 
 void RenderEngineThreaded::cleanFramebufferCache() {
-    std::promise<void> resultPromise;
-    std::future<void> resultFuture = resultPromise.get_future();
+    // This function is designed so it can run asynchronously, so we do not need to wait
+    // for the futures.
     {
         std::lock_guard lock(mThreadMutex);
-        mFunctionCalls.push([&resultPromise](renderengine::RenderEngine& instance) {
+        mFunctionCalls.push([](renderengine::RenderEngine& instance) {
             ATRACE_NAME("REThreaded::cleanFramebufferCache");
             instance.cleanFramebufferCache();
-            resultPromise.set_value();
         });
     }
     mCondition.notify_one();
-    resultFuture.wait();
 }
 
 int RenderEngineThreaded::getContextPriority() {
@@ -318,33 +288,21 @@
 }
 
 bool RenderEngineThreaded::supportsBackgroundBlur() {
-    std::promise<bool> resultPromise;
-    std::future<bool> resultFuture = resultPromise.get_future();
-    {
-        std::lock_guard lock(mThreadMutex);
-        mFunctionCalls.push([&resultPromise](renderengine::RenderEngine& instance) {
-            ATRACE_NAME("REThreaded::supportsBackgroundBlur");
-            bool returnValue = instance.supportsBackgroundBlur();
-            resultPromise.set_value(returnValue);
-        });
-    }
-    mCondition.notify_one();
-    return resultFuture.get();
+    waitUntilInitialized();
+    return mRenderEngine->supportsBackgroundBlur();
 }
 
 void RenderEngineThreaded::onPrimaryDisplaySizeChanged(ui::Size size) {
-    std::promise<void> resultPromise;
-    std::future<void> resultFuture = resultPromise.get_future();
+    // This function is designed so it can run asynchronously, so we do not need to wait
+    // for the futures.
     {
         std::lock_guard lock(mThreadMutex);
-        mFunctionCalls.push([&resultPromise, size](renderengine::RenderEngine& instance) {
+        mFunctionCalls.push([size](renderengine::RenderEngine& instance) {
             ATRACE_NAME("REThreaded::onPrimaryDisplaySizeChanged");
             instance.onPrimaryDisplaySizeChanged(size);
-            resultPromise.set_value();
         });
     }
     mCondition.notify_one();
-    resultFuture.wait();
 }
 
 } // namespace threaded
diff --git a/libs/renderengine/threaded/RenderEngineThreaded.h b/libs/renderengine/threaded/RenderEngineThreaded.h
index 117257a..61ae9b8 100644
--- a/libs/renderengine/threaded/RenderEngineThreaded.h
+++ b/libs/renderengine/threaded/RenderEngineThreaded.h
@@ -70,6 +70,7 @@
 
 private:
     void threadMain(CreateInstanceFactory factory);
+    void waitUntilInitialized() const;
 
     /* ------------------------------------------------------------------------
      * Threading
@@ -83,6 +84,12 @@
             GUARDED_BY(mThreadMutex);
     mutable std::condition_variable mCondition;
 
+    // Used to allow select thread safe methods to be accessed without requiring the
+    // method to be invoked on the RenderEngine thread
+    bool mIsInitialized = false;
+    mutable std::mutex mInitializedMutex;
+    mutable std::condition_variable mInitializedCondition;
+
     /* ------------------------------------------------------------------------
      * Render Engine
      */
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/planner/CachedSet.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/planner/CachedSet.h
index afa02cd..c5d03a7 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/planner/CachedSet.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/planner/CachedSet.h
@@ -108,7 +108,7 @@
 private:
     CachedSet() = default;
 
-    NonBufferHash mFingerprint = 0;
+    const NonBufferHash mFingerprint;
     std::chrono::steady_clock::time_point mLastUpdate = std::chrono::steady_clock::now();
     std::vector<Layer> mLayers;
     Rect mBounds = Rect::EMPTY_RECT;
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/planner/Flattener.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/planner/Flattener.h
index 313a180..2f2ad4c 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/planner/Flattener.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/planner/Flattener.h
@@ -54,7 +54,7 @@
 
     void resetActivities(NonBufferHash, std::chrono::steady_clock::time_point now);
 
-    void updateLayersHash();
+    NonBufferHash computeLayersHash() const;
 
     bool mergeWithCachedSets(const std::vector<const LayerState*>& layers,
                              std::chrono::steady_clock::time_point now);
@@ -69,7 +69,6 @@
     std::chrono::steady_clock::time_point mLastGeometryUpdate;
 
     std::vector<CachedSet> mLayers;
-    NonBufferHash mLayersHash = 0;
     std::optional<CachedSet> mNewCachedSet;
 
     // Statistics
diff --git a/services/surfaceflinger/CompositionEngine/src/planner/Flattener.cpp b/services/surfaceflinger/CompositionEngine/src/planner/Flattener.cpp
index ffca5ba..9c9649c 100644
--- a/services/surfaceflinger/CompositionEngine/src/planner/Flattener.cpp
+++ b/services/surfaceflinger/CompositionEngine/src/planner/Flattener.cpp
@@ -40,13 +40,17 @@
 
     ++mInitialLayerCounts[layers.size()];
 
-    if (mergeWithCachedSets(layers, now)) {
-        hash = mLayersHash;
-    }
+    // Only buildCachedSets if these layers are already stored in mLayers.
+    // Otherwise (i.e. mergeWithCachedSets returns false), the time has not
+    // changed, so buildCachedSets will never find any runs.
+    const bool alreadyHadCachedSets = mergeWithCachedSets(layers, now);
 
     ++mFinalLayerCounts[mLayers.size()];
 
-    buildCachedSets(now);
+    if (alreadyHadCachedSets) {
+        buildCachedSets(now);
+        hash = computeLayersHash();
+    }
 
     return hash;
 }
@@ -157,14 +161,17 @@
     }
 }
 
-void Flattener::updateLayersHash() {
+NonBufferHash Flattener::computeLayersHash() const{
     size_t hash = 0;
     for (const auto& layer : mLayers) {
         android::hashCombineSingleHashed(hash, layer.getNonBufferHash());
     }
-    mLayersHash = hash;
+    return hash;
 }
 
+// Only called if the geometry matches the last frame. Return true if mLayers
+// was already populated with these layers, i.e. on the second and following
+// calls with the same geometry.
 bool Flattener::mergeWithCachedSets(const std::vector<const LayerState*>& layers, time_point now) {
     std::vector<CachedSet> merged;
 
@@ -272,7 +279,6 @@
     }
 
     mLayers = std::move(merged);
-    updateLayersHash();
     return true;
 }
 
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index 6038658..829b916 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -2264,8 +2264,13 @@
     return parentAlpha * getDrawingState().backgroundBlurRadius;
 }
 
-const std::vector<BlurRegion>& Layer::getBlurRegions() const {
-    return getDrawingState().blurRegions;
+const std::vector<BlurRegion> Layer::getBlurRegions() const {
+    auto regionsCopy(getDrawingState().blurRegions);
+    int layerAlpha = getAlpha();
+    for (auto& region : regionsCopy) {
+        region.alpha = region.alpha * layerAlpha;
+    }
+    return regionsCopy;
 }
 
 Layer::RoundedCornerState Layer::getRoundedCornerState() const {
diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h
index 5528a81..64986af 100644
--- a/services/surfaceflinger/Layer.h
+++ b/services/surfaceflinger/Layer.h
@@ -1191,7 +1191,7 @@
     float mEffectiveShadowRadius = 0.f;
 
     // A list of regions on this layer that should have blurs.
-    const std::vector<BlurRegion>& getBlurRegions() const;
+    const std::vector<BlurRegion> getBlurRegions() const;
 };
 
 std::ostream& operator<<(std::ostream& stream, const Layer::FrameRate& rate);
diff --git a/services/surfaceflinger/main_surfaceflinger.cpp b/services/surfaceflinger/main_surfaceflinger.cpp
index 2b8424c..9686523 100644
--- a/services/surfaceflinger/main_surfaceflinger.cpp
+++ b/services/surfaceflinger/main_surfaceflinger.cpp
@@ -89,13 +89,47 @@
     // binder threads to 4.
     ProcessState::self()->setThreadPoolMaxThreadCount(4);
 
+    // The binder threadpool we start will inherit sched policy and priority
+    // of (this) creating thread. We want the binder thread pool to have
+    // SCHED_FIFO policy and priority 1 (lowest RT priority)
+    // Once the pool is created we reset this thread's priority back to
+    // original.
+    int newPriority = 0;
+    int origPolicy = sched_getscheduler(0);
+    struct sched_param origSchedParam;
+
+    int errorInPriorityModification = sched_getparam(0, &origSchedParam);
+    if (errorInPriorityModification == 0) {
+        int policy = SCHED_FIFO;
+        newPriority = sched_get_priority_min(policy);
+
+        struct sched_param param;
+        param.sched_priority = newPriority;
+
+        errorInPriorityModification = sched_setscheduler(0, policy, &param);
+    }
+
     // start the thread pool
     sp<ProcessState> ps(ProcessState::self());
     ps->startThreadPool();
 
+    // Reset current thread's policy and priority
+    if (errorInPriorityModification == 0) {
+        errorInPriorityModification = sched_setscheduler(0, origPolicy, &origSchedParam);
+    } else {
+        ALOGE("Failed to set SurfaceFlinger binder threadpool priority to SCHED_FIFO");
+    }
+
     // instantiate surfaceflinger
     sp<SurfaceFlinger> flinger = surfaceflinger::createSurfaceFlinger();
 
+    // Set the minimum policy of surfaceflinger node to be SCHED_FIFO.
+    // So any thread with policy/priority lower than {SCHED_FIFO, 1}, will run
+    // at least with SCHED_FIFO policy and priority 1.
+    if (errorInPriorityModification == 0) {
+        flinger->setMinSchedulerPolicy(SCHED_FIFO, newPriority);
+    }
+
     setpriority(PRIO_PROCESS, 0, PRIORITY_URGENT_DISPLAY);
 
     set_sched_policy(0, SP_FOREGROUND);
diff --git a/vulkan/libvulkan/swapchain.cpp b/vulkan/libvulkan/swapchain.cpp
index 020b520..8d6681c 100644
--- a/vulkan/libvulkan/swapchain.cpp
+++ b/vulkan/libvulkan/swapchain.cpp
@@ -1086,7 +1086,8 @@
     ALOGW_IF(err != android::OK, "native_window_api_connect failed: %s (%d)",
              strerror(-err), err);
 
-    err = window->perform(window, NATIVE_WINDOW_SET_DEQUEUE_TIMEOUT, -1);
+    err =
+        window->perform(window, NATIVE_WINDOW_SET_DEQUEUE_TIMEOUT, nsecs_t{-1});
     if (err != android::OK) {
         ALOGE("window->perform(SET_DEQUEUE_TIMEOUT) failed: %s (%d)",
               strerror(-err), err);