Merge "Remove -fwhole-program-vtables flags from librenderengine static library"
diff --git a/cmds/dumpstate/dumpstate.cpp b/cmds/dumpstate/dumpstate.cpp
index 2044943..a8e6738 100644
--- a/cmds/dumpstate/dumpstate.cpp
+++ b/cmds/dumpstate/dumpstate.cpp
@@ -1287,7 +1287,6 @@
     dump_dev_files("TRUSTY VERSION", "/sys/bus/platform/drivers/trusty", "trusty_version");
     RunCommand("UPTIME", {"uptime"});
     DumpBlockStatFiles();
-    dump_emmc_ecsd("/d/mmc0/mmc0:0001/ext_csd");
     DumpFile("MEMORY INFO", "/proc/meminfo");
     RunCommand("CPU INFO", {"top", "-b", "-n", "1", "-H", "-s", "6", "-o",
                             "pid,tid,user,pr,ni,%cpu,s,virt,res,pcy,cmd,name"});
@@ -3672,110 +3671,3 @@
     }
     return info.st_mtime;
 }
-
-void dump_emmc_ecsd(const char *ext_csd_path) {
-    // List of interesting offsets
-    struct hex {
-        char str[2];
-    };
-    static const size_t EXT_CSD_REV = 192 * sizeof(hex);
-    static const size_t EXT_PRE_EOL_INFO = 267 * sizeof(hex);
-    static const size_t EXT_DEVICE_LIFE_TIME_EST_TYP_A = 268 * sizeof(hex);
-    static const size_t EXT_DEVICE_LIFE_TIME_EST_TYP_B = 269 * sizeof(hex);
-
-    std::string buffer;
-    if (!android::base::ReadFileToString(ext_csd_path, &buffer)) {
-        return;
-    }
-
-    printf("------ %s Extended CSD ------\n", ext_csd_path);
-
-    if (buffer.length() < (EXT_CSD_REV + sizeof(hex))) {
-        printf("*** %s: truncated content %zu\n\n", ext_csd_path, buffer.length());
-        return;
-    }
-
-    int ext_csd_rev = 0;
-    std::string sub = buffer.substr(EXT_CSD_REV, sizeof(hex));
-    if (sscanf(sub.c_str(), "%2x", &ext_csd_rev) != 1) {
-        printf("*** %s: EXT_CSD_REV parse error \"%s\"\n\n", ext_csd_path, sub.c_str());
-        return;
-    }
-
-    static const char *ver_str[] = {
-        "4.0", "4.1", "4.2", "4.3", "Obsolete", "4.41", "4.5", "5.0"
-    };
-    printf("rev 1.%d (MMC %s)\n", ext_csd_rev,
-           (ext_csd_rev < (int)(sizeof(ver_str) / sizeof(ver_str[0]))) ? ver_str[ext_csd_rev]
-                                                                       : "Unknown");
-    if (ext_csd_rev < 7) {
-        printf("\n");
-        return;
-    }
-
-    if (buffer.length() < (EXT_PRE_EOL_INFO + sizeof(hex))) {
-        printf("*** %s: truncated content %zu\n\n", ext_csd_path, buffer.length());
-        return;
-    }
-
-    int ext_pre_eol_info = 0;
-    sub = buffer.substr(EXT_PRE_EOL_INFO, sizeof(hex));
-    if (sscanf(sub.c_str(), "%2x", &ext_pre_eol_info) != 1) {
-        printf("*** %s: PRE_EOL_INFO parse error \"%s\"\n\n", ext_csd_path, sub.c_str());
-        return;
-    }
-
-    static const char *eol_str[] = {
-        "Undefined",
-        "Normal",
-        "Warning (consumed 80% of reserve)",
-        "Urgent (consumed 90% of reserve)"
-    };
-    printf(
-        "PRE_EOL_INFO %d (MMC %s)\n", ext_pre_eol_info,
-        eol_str[(ext_pre_eol_info < (int)(sizeof(eol_str) / sizeof(eol_str[0]))) ? ext_pre_eol_info
-                                                                                 : 0]);
-
-    for (size_t lifetime = EXT_DEVICE_LIFE_TIME_EST_TYP_A;
-            lifetime <= EXT_DEVICE_LIFE_TIME_EST_TYP_B;
-            lifetime += sizeof(hex)) {
-        int ext_device_life_time_est;
-        static const char *est_str[] = {
-            "Undefined",
-            "0-10% of device lifetime used",
-            "10-20% of device lifetime used",
-            "20-30% of device lifetime used",
-            "30-40% of device lifetime used",
-            "40-50% of device lifetime used",
-            "50-60% of device lifetime used",
-            "60-70% of device lifetime used",
-            "70-80% of device lifetime used",
-            "80-90% of device lifetime used",
-            "90-100% of device lifetime used",
-            "Exceeded the maximum estimated device lifetime",
-        };
-
-        if (buffer.length() < (lifetime + sizeof(hex))) {
-            printf("*** %s: truncated content %zu\n", ext_csd_path, buffer.length());
-            break;
-        }
-
-        ext_device_life_time_est = 0;
-        sub = buffer.substr(lifetime, sizeof(hex));
-        if (sscanf(sub.c_str(), "%2x", &ext_device_life_time_est) != 1) {
-            printf("*** %s: DEVICE_LIFE_TIME_EST_TYP_%c parse error \"%s\"\n", ext_csd_path,
-                   (unsigned)((lifetime - EXT_DEVICE_LIFE_TIME_EST_TYP_A) / sizeof(hex)) + 'A',
-                   sub.c_str());
-            continue;
-        }
-        printf("DEVICE_LIFE_TIME_EST_TYP_%c %d (MMC %s)\n",
-               (unsigned)((lifetime - EXT_DEVICE_LIFE_TIME_EST_TYP_A) / sizeof(hex)) + 'A',
-               ext_device_life_time_est,
-               est_str[(ext_device_life_time_est < (int)(sizeof(est_str) / sizeof(est_str[0])))
-                           ? ext_device_life_time_est
-                           : 0]);
-    }
-
-    printf("\n");
-}
-
diff --git a/cmds/dumpstate/dumpstate.h b/cmds/dumpstate/dumpstate.h
index ccc9f42..5ba84ca 100644
--- a/cmds/dumpstate/dumpstate.h
+++ b/cmds/dumpstate/dumpstate.h
@@ -589,9 +589,6 @@
 /** Gets the last modification time of a file, or default time if file is not found. */
 time_t get_mtime(int fd, time_t default_mtime);
 
-/* Dumps eMMC Extended CSD data. */
-void dump_emmc_ecsd(const char *ext_csd_path);
-
 /** Gets command-line arguments. */
 void format_args(int argc, const char *argv[], std::string *args);
 
diff --git a/include/input/InputTransport.h b/include/input/InputTransport.h
index 690e0a1..28b8d80 100644
--- a/include/input/InputTransport.h
+++ b/include/input/InputTransport.h
@@ -42,6 +42,8 @@
 #include <utils/Timers.h>
 #include <utils/Vector.h>
 
+#include <android-base/unique_fd.h>
+
 namespace android {
 class Parcel;
 
@@ -166,8 +168,7 @@
     virtual ~InputChannel();
 
 public:
-    InputChannel() = default;
-    InputChannel(const std::string& name, int fd);
+    static sp<InputChannel> create(const std::string& name, android::base::unique_fd fd);
 
     /* Creates a pair of input channels.
      *
@@ -177,7 +178,7 @@
             sp<InputChannel>& outServerChannel, sp<InputChannel>& outClientChannel);
 
     inline std::string getName() const { return mName; }
-    inline int getFd() const { return mFd; }
+    inline int getFd() const { return mFd.get(); }
 
     /* Sends a message to the other endpoint.
      *
@@ -208,16 +209,15 @@
     sp<InputChannel> dup() const;
 
     status_t write(Parcel& out) const;
-    status_t read(const Parcel& from);
+    static sp<InputChannel> read(const Parcel& from);
 
     sp<IBinder> getToken() const;
     void setToken(const sp<IBinder>& token);
 
 private:
-    void setFd(int fd);
-
+    InputChannel(const std::string& name, android::base::unique_fd fd);
     std::string mName;
-    int mFd = -1;
+    android::base::unique_fd mFd;
 
     sp<IBinder> mToken = nullptr;
 };
diff --git a/libs/binder/Binder.cpp b/libs/binder/Binder.cpp
index f3483ca..693045e 100644
--- a/libs/binder/Binder.cpp
+++ b/libs/binder/Binder.cpp
@@ -81,6 +81,24 @@
     return target->transact(SHELL_COMMAND_TRANSACTION, send, &reply);
 }
 
+status_t IBinder::getExtension(sp<IBinder>* out) {
+    BBinder* local = this->localBinder();
+    if (local != nullptr) {
+        *out = local->getExtension();
+        return OK;
+    }
+
+    BpBinder* proxy = this->remoteBinder();
+    LOG_ALWAYS_FATAL_IF(proxy == nullptr);
+
+    Parcel data;
+    Parcel reply;
+    status_t status = transact(EXTENSION_TRANSACTION, data, &reply);
+    if (status != OK) return status;
+
+    return reply.readNullableStrongBinder(out);
+}
+
 // ---------------------------------------------------------------------------
 
 class BBinder::Extras
@@ -88,6 +106,7 @@
 public:
     // unlocked objects
     bool mRequestingSid = false;
+    sp<IBinder> mExtension;
 
     // for below objects
     Mutex mLock;
@@ -130,6 +149,9 @@
         case PING_TRANSACTION:
             err = pingBinder();
             break;
+        case EXTENSION_TRANSACTION:
+            err = reply->writeStrongBinder(getExtension());
+            break;
         default:
             err = onTransact(code, data, reply, flags);
             break;
@@ -222,6 +244,17 @@
     e->mRequestingSid = requestingSid;
 }
 
+sp<IBinder> BBinder::getExtension() {
+    Extras* e = mExtras.load(std::memory_order_acquire);
+    if (e == nullptr) return nullptr;
+    return e->mExtension;
+}
+
+void BBinder::setExtension(const sp<IBinder>& extension) {
+    Extras* e = getOrCreateExtras();
+    e->mExtension = extension;
+}
+
 BBinder::~BBinder()
 {
     Extras* e = mExtras.load(std::memory_order_relaxed);
diff --git a/libs/binder/Parcel.cpp b/libs/binder/Parcel.cpp
index ed6c834..3a7a7a9 100644
--- a/libs/binder/Parcel.cpp
+++ b/libs/binder/Parcel.cpp
@@ -2354,6 +2354,22 @@
             mObjectsSize = 0;
             break;
         }
+        const flat_binder_object* flat
+            = reinterpret_cast<const flat_binder_object*>(mData + offset);
+        uint32_t type = flat->hdr.type;
+        if (!(type == BINDER_TYPE_BINDER || type == BINDER_TYPE_HANDLE ||
+              type == BINDER_TYPE_FD)) {
+            // We should never receive other types (eg BINDER_TYPE_FDA) as long as we don't support
+            // them in libbinder. If we do receive them, it probably means a kernel bug; try to
+            // recover gracefully by clearing out the objects, and releasing the objects we do
+            // know about.
+            android_errorWriteLog(0x534e4554, "135930648");
+            ALOGE("%s: unsupported type object (%" PRIu32 ") at offset %" PRIu64 "\n",
+                  __func__, type, (uint64_t)offset);
+            releaseObjects();
+            mObjectsSize = 0;
+            break;
+        }
         minOffset = offset + sizeof(flat_binder_object);
     }
     scanForFds();
diff --git a/libs/binder/include/binder/Binder.h b/libs/binder/include/binder/Binder.h
index dec75f5..1095c7f 100644
--- a/libs/binder/include/binder/Binder.h
+++ b/libs/binder/include/binder/Binder.h
@@ -64,6 +64,10 @@
     // This must be called before the object is sent to another process. Not thread safe.
     void                setRequestingSid(bool requestSid);
 
+    sp<IBinder>         getExtension();
+    // This must be called before the object is sent to another process. Not thread safe.
+    void                setExtension(const sp<IBinder>& extension);
+
 protected:
     virtual             ~BBinder();
 
diff --git a/libs/binder/include/binder/IBinder.h b/libs/binder/include/binder/IBinder.h
index aa44285..408037e 100644
--- a/libs/binder/include/binder/IBinder.h
+++ b/libs/binder/include/binder/IBinder.h
@@ -59,6 +59,7 @@
         SHELL_COMMAND_TRANSACTION = B_PACK_CHARS('_','C','M','D'),
         INTERFACE_TRANSACTION   = B_PACK_CHARS('_', 'N', 'T', 'F'),
         SYSPROPS_TRANSACTION    = B_PACK_CHARS('_', 'S', 'P', 'R'),
+        EXTENSION_TRANSACTION   = B_PACK_CHARS('_', 'E', 'X', 'T'),
 
         // Corresponds to TF_ONE_WAY -- an asynchronous call.
         FLAG_ONEWAY             = 0x00000001
@@ -86,6 +87,49 @@
                                          Vector<String16>& args, const sp<IShellCallback>& callback,
                                          const sp<IResultReceiver>& resultReceiver);
 
+    /**
+     * This allows someone to add their own additions to an interface without
+     * having to modify the original interface.
+     *
+     * For instance, imagine if we have this interface:
+     *     interface IFoo { void doFoo(); }
+     *
+     * If an unrelated owner (perhaps in a downstream codebase) wants to make a
+     * change to the interface, they have two options:
+     *
+     * A). Historical option that has proven to be BAD! Only the original
+     *     author of an interface should change an interface. If someone
+     *     downstream wants additional functionality, they should not ever
+     *     change the interface or use this method.
+     *
+     *    BAD TO DO:  interface IFoo {                       BAD TO DO
+     *    BAD TO DO:      void doFoo();                      BAD TO DO
+     *    BAD TO DO: +    void doBar(); // adding a method   BAD TO DO
+     *    BAD TO DO:  }                                      BAD TO DO
+     *
+     * B). Option that this method enables!
+     *     Leave the original interface unchanged (do not change IFoo!).
+     *     Instead, create a new interface in a downstream package:
+     *
+     *         package com.<name>; // new functionality in a new package
+     *         interface IBar { void doBar(); }
+     *
+     *     When registering the interface, add:
+     *         sp<MyFoo> foo = new MyFoo; // class in AOSP codebase
+     *         sp<MyBar> bar = new MyBar; // custom extension class
+     *         foo->setExtension(bar);    // use method in BBinder
+     *
+     *     Then, clients of IFoo can get this extension:
+     *         sp<IBinder> binder = ...;
+     *         sp<IFoo> foo = interface_cast<IFoo>(binder); // handle if null
+     *         sp<IBinder> barBinder;
+     *         ... handle error ... = binder->getExtension(&barBinder);
+     *         sp<IBar> bar = interface_cast<IBar>(barBinder);
+     *         // if bar is null, then there is no extension or a different
+     *         // type of extension
+     */
+    status_t                getExtension(sp<IBinder>* out);
+
     // NOLINTNEXTLINE(google-default-arguments)
     virtual status_t        transact(   uint32_t code,
                                         const Parcel& data,
diff --git a/libs/binder/tests/binderLibTest.cpp b/libs/binder/tests/binderLibTest.cpp
index 9de3460..5c6cf9d 100644
--- a/libs/binder/tests/binderLibTest.cpp
+++ b/libs/binder/tests/binderLibTest.cpp
@@ -72,6 +72,7 @@
     BINDER_LIB_TEST_CREATE_BINDER_TRANSACTION,
     BINDER_LIB_TEST_GET_WORK_SOURCE_TRANSACTION,
     BINDER_LIB_TEST_ECHO_VECTOR,
+    BINDER_LIB_TEST_REJECT_BUF,
 };
 
 pid_t start_server_process(int arg2, bool usePoll = false)
@@ -769,6 +770,24 @@
     EXPECT_TRUE(strong_from_weak == nullptr);
 }
 
+TEST_F(BinderLibTest, LocalGetExtension) {
+    sp<BBinder> binder = new BBinder();
+    sp<IBinder> ext = new BBinder();
+    binder->setExtension(ext);
+    EXPECT_EQ(ext, binder->getExtension());
+}
+
+TEST_F(BinderLibTest, RemoteGetExtension) {
+    sp<IBinder> server = addServer();
+    ASSERT_TRUE(server != nullptr);
+
+    sp<IBinder> extension;
+    EXPECT_EQ(NO_ERROR, server->getExtension(&extension));
+    ASSERT_NE(nullptr, extension.get());
+
+    EXPECT_EQ(NO_ERROR, extension->pingBinder());
+}
+
 TEST_F(BinderLibTest, CheckHandleZeroBinderHighBitsZeroCookie) {
     status_t ret;
     Parcel data, reply;
@@ -1006,6 +1025,34 @@
     EXPECT_EQ(readValue, testValue);
 }
 
+TEST_F(BinderLibTest, BufRejected) {
+    Parcel data, reply;
+    uint32_t buf;
+    sp<IBinder> server = addServer();
+    ASSERT_TRUE(server != nullptr);
+
+    binder_buffer_object obj {
+        .hdr = { .type = BINDER_TYPE_PTR },
+        .buffer = reinterpret_cast<binder_uintptr_t>((void*)&buf),
+        .length = 4,
+        .flags = 0,
+    };
+    data.setDataCapacity(1024);
+    // Write a bogus object at offset 0 to get an entry in the offset table
+    data.writeFileDescriptor(0);
+    EXPECT_EQ(data.objectsCount(), 1);
+    uint8_t *parcelData = const_cast<uint8_t*>(data.data());
+    // And now, overwrite it with the buffer object
+    memcpy(parcelData, &obj, sizeof(obj));
+    data.setDataSize(sizeof(obj));
+
+    status_t ret = server->transact(BINDER_LIB_TEST_REJECT_BUF, data, &reply);
+    // Either the kernel should reject this transaction (if it's correct), but
+    // if it's not, the server implementation should return an error if it
+    // finds an object in the received Parcel.
+    EXPECT_NE(NO_ERROR, ret);
+}
+
 class BinderLibTestService : public BBinder
 {
     public:
@@ -1288,6 +1335,9 @@
                 reply->writeUint64Vector(vector);
                 return NO_ERROR;
             }
+            case BINDER_LIB_TEST_REJECT_BUF: {
+                return data.objectsCount() == 0 ? BAD_VALUE : NO_ERROR;
+            }
             default:
                 return UNKNOWN_TRANSACTION;
             };
@@ -1312,6 +1362,16 @@
     BinderLibTestService* testServicePtr;
     {
         sp<BinderLibTestService> testService = new BinderLibTestService(index);
+
+        /*
+         * Normally would also contain functionality as well, but we are only
+         * testing the extension mechanism.
+         */
+        testService->setExtension(new BBinder());
+
+        // Required for test "BufRejected'
+        testService->setRequestingSid(true);
+
         /*
          * We need this below, but can't hold a sp<> because it prevents the
          * node from being cleaned up automatically. It's safe in this case
diff --git a/libs/gui/ISurfaceComposer.cpp b/libs/gui/ISurfaceComposer.cpp
index 12deaf0..dc161b7 100644
--- a/libs/gui/ISurfaceComposer.cpp
+++ b/libs/gui/ISurfaceComposer.cpp
@@ -93,7 +93,7 @@
 
         if (data.writeVectorSize(listenerCallbacks) == NO_ERROR) {
             for (const auto& [listener, callbackIds] : listenerCallbacks) {
-                data.writeStrongBinder(IInterface::asBinder(listener));
+                data.writeStrongBinder(listener);
                 data.writeInt64Vector(callbackIds);
             }
         }
@@ -1042,8 +1042,7 @@
             std::vector<ListenerCallbacks> listenerCallbacks;
             int32_t listenersSize = data.readInt32();
             for (int32_t i = 0; i < listenersSize; i++) {
-                auto listener =
-                        interface_cast<ITransactionCompletedListener>(data.readStrongBinder());
+                auto listener = data.readStrongBinder();
                 std::vector<CallbackId> callbackIds;
                 data.readInt64Vector(&callbackIds);
                 listenerCallbacks.emplace_back(listener, callbackIds);
diff --git a/libs/gui/ITransactionCompletedListener.cpp b/libs/gui/ITransactionCompletedListener.cpp
index 74cd4f1..acda600 100644
--- a/libs/gui/ITransactionCompletedListener.cpp
+++ b/libs/gui/ITransactionCompletedListener.cpp
@@ -151,7 +151,7 @@
     return NO_ERROR;
 }
 
-ListenerStats ListenerStats::createEmpty(const sp<ITransactionCompletedListener>& listener,
+ListenerStats ListenerStats::createEmpty(const sp<IBinder>& listener,
                                          const std::unordered_set<CallbackId>& callbackIds) {
     ListenerStats listenerStats;
     listenerStats.listener = listener;
diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp
index 40621e3..5faf010 100644
--- a/libs/gui/SurfaceComposerClient.cpp
+++ b/libs/gui/SurfaceComposerClient.cpp
@@ -548,7 +548,7 @@
             continue;
         }
 
-        listenerCallbacks.emplace_back(listener, std::move(callbackIds));
+        listenerCallbacks.emplace_back(IInterface::asBinder(listener), std::move(callbackIds));
 
         // If the listener has any SurfaceControls set on this Transaction update the surface state
         for (const auto& surfaceControl : surfaceControls) {
diff --git a/libs/gui/include/gui/ITransactionCompletedListener.h b/libs/gui/include/gui/ITransactionCompletedListener.h
index cbfd365..178ca2d 100644
--- a/libs/gui/include/gui/ITransactionCompletedListener.h
+++ b/libs/gui/include/gui/ITransactionCompletedListener.h
@@ -31,6 +31,7 @@
 namespace android {
 
 class ITransactionCompletedListener;
+class ListenerCallbacks;
 
 using CallbackId = int64_t;
 
@@ -72,10 +73,10 @@
     status_t writeToParcel(Parcel* output) const override;
     status_t readFromParcel(const Parcel* input) override;
 
-    static ListenerStats createEmpty(const sp<ITransactionCompletedListener>& listener,
+    static ListenerStats createEmpty(const sp<IBinder>& listener,
                                      const std::unordered_set<CallbackId>& callbackIds);
 
-    sp<ITransactionCompletedListener> listener;
+    sp<IBinder> listener;
     std::vector<TransactionStats> transactionStats;
 };
 
@@ -97,13 +98,11 @@
 
 class ListenerCallbacks {
 public:
-    ListenerCallbacks(const sp<ITransactionCompletedListener>& listener,
-                      const std::unordered_set<CallbackId>& callbacks)
+    ListenerCallbacks(const sp<IBinder>& listener, const std::unordered_set<CallbackId>& callbacks)
           : transactionCompletedListener(listener),
             callbackIds(callbacks.begin(), callbacks.end()) {}
 
-    ListenerCallbacks(const sp<ITransactionCompletedListener>& listener,
-                      const std::vector<CallbackId>& ids)
+    ListenerCallbacks(const sp<IBinder>& listener, const std::vector<CallbackId>& ids)
           : transactionCompletedListener(listener), callbackIds(ids) {}
 
     bool operator==(const ListenerCallbacks& rhs) const {
@@ -116,8 +115,42 @@
         return callbackIds.front() == rhs.callbackIds.front();
     }
 
-    sp<ITransactionCompletedListener> transactionCompletedListener;
+    sp<IBinder> transactionCompletedListener;
     std::vector<CallbackId> callbackIds;
 };
 
+struct IListenerHash {
+    std::size_t operator()(const sp<IBinder>& strongPointer) const {
+        return std::hash<IBinder*>{}(strongPointer.get());
+    }
+};
+
+struct CallbackIdsHash {
+    // CallbackId vectors have several properties that let us get away with this simple hash.
+    // 1) CallbackIds are never 0 so if something has gone wrong and our CallbackId vector is
+    // empty we can still hash 0.
+    // 2) CallbackId vectors for the same listener either are identical or contain none of the
+    // same members. It is sufficient to just check the first CallbackId in the vectors. If
+    // they match, they are the same. If they do not match, they are not the same.
+    std::size_t operator()(const std::vector<CallbackId>& callbackIds) const {
+        return std::hash<CallbackId>{}((callbackIds.empty()) ? 0 : callbackIds.front());
+    }
+};
+
+struct ListenerCallbacksHash {
+    std::size_t HashCombine(size_t value1, size_t value2) const {
+        return value1 ^ (value2 + 0x9e3779b9 + (value1 << 6) + (value1 >> 2));
+    }
+
+    std::size_t operator()(const ListenerCallbacks& listenerCallbacks) const {
+        struct IListenerHash listenerHasher;
+        struct CallbackIdsHash callbackIdsHasher;
+
+        std::size_t listenerHash = listenerHasher(listenerCallbacks.transactionCompletedListener);
+        std::size_t callbackIdsHash = callbackIdsHasher(listenerCallbacks.callbackIds);
+
+        return HashCombine(listenerHash, callbackIdsHash);
+    }
+};
+
 } // namespace android
diff --git a/libs/input/IInputFlinger.cpp b/libs/input/IInputFlinger.cpp
index d6a73bf..90f6e09 100644
--- a/libs/input/IInputFlinger.cpp
+++ b/libs/input/IInputFlinger.cpp
@@ -92,15 +92,13 @@
     }
     case REGISTER_INPUT_CHANNEL_TRANSACTION: {
         CHECK_INTERFACE(IInputFlinger, data, reply);
-        sp<InputChannel> channel = new InputChannel();
-        channel->read(data);
+        sp<InputChannel> channel = InputChannel::read(data);
         registerInputChannel(channel);
         break;
     }
     case UNREGISTER_INPUT_CHANNEL_TRANSACTION: {
         CHECK_INTERFACE(IInputFlinger, data, reply);
-        sp<InputChannel> channel = new InputChannel();
-        channel->read(data);
+        sp<InputChannel> channel = InputChannel::read(data);
         unregisterInputChannel(channel);
         break;
     }
diff --git a/libs/input/InputTransport.cpp b/libs/input/InputTransport.cpp
index 2ff301e..7835651 100644
--- a/libs/input/InputTransport.cpp
+++ b/libs/input/InputTransport.cpp
@@ -227,35 +227,28 @@
 
 // --- InputChannel ---
 
-InputChannel::InputChannel(const std::string& name, int fd) :
-        mName(name) {
+sp<InputChannel> InputChannel::create(const std::string& name, android::base::unique_fd fd) {
+    const int result = fcntl(fd, F_SETFL, O_NONBLOCK);
+    if (result != 0) {
+        LOG_ALWAYS_FATAL("channel '%s' ~ Could not make socket non-blocking: %s", name.c_str(),
+                         strerror(errno));
+        return nullptr;
+    }
+    return new InputChannel(name, std::move(fd));
+}
+
+InputChannel::InputChannel(const std::string& name, android::base::unique_fd fd)
+      : mName(name), mFd(std::move(fd)) {
 #if DEBUG_CHANNEL_LIFECYCLE
     ALOGD("Input channel constructed: name='%s', fd=%d",
             mName.c_str(), fd);
 #endif
-
-    setFd(fd);
 }
 
 InputChannel::~InputChannel() {
 #if DEBUG_CHANNEL_LIFECYCLE
-    ALOGD("Input channel destroyed: name='%s', fd=%d",
-            mName.c_str(), mFd);
+    ALOGD("Input channel destroyed: name='%s', fd=%d", mName.c_str(), mFd.get());
 #endif
-
-    ::close(mFd);
-}
-
-void InputChannel::setFd(int fd) {
-    if (mFd > 0) {
-        ::close(mFd);
-    }
-    mFd = fd;
-    if (mFd > 0) {
-        int result = fcntl(mFd, F_SETFL, O_NONBLOCK);
-        LOG_ALWAYS_FATAL_IF(result != 0, "channel '%s' ~ Could not make socket "
-            "non-blocking.  errno=%d", mName.c_str(), errno);
-    }
 }
 
 status_t InputChannel::openInputChannelPair(const std::string& name,
@@ -276,13 +269,13 @@
     setsockopt(sockets[1], SOL_SOCKET, SO_SNDBUF, &bufferSize, sizeof(bufferSize));
     setsockopt(sockets[1], SOL_SOCKET, SO_RCVBUF, &bufferSize, sizeof(bufferSize));
 
-    std::string serverChannelName = name;
-    serverChannelName += " (server)";
-    outServerChannel = new InputChannel(serverChannelName, sockets[0]);
+    std::string serverChannelName = name + " (server)";
+    android::base::unique_fd serverFd(sockets[0]);
+    outServerChannel = InputChannel::create(serverChannelName, std::move(serverFd));
 
-    std::string clientChannelName = name;
-    clientChannelName += " (client)";
-    outClientChannel = new InputChannel(clientChannelName, sockets[1]);
+    std::string clientChannelName = name + " (client)";
+    android::base::unique_fd clientFd(sockets[1]);
+    outClientChannel = InputChannel::create(clientChannelName, std::move(clientFd));
     return OK;
 }
 
@@ -292,7 +285,7 @@
     msg->getSanitizedCopy(&cleanMsg);
     ssize_t nWrite;
     do {
-        nWrite = ::send(mFd, &cleanMsg, msgLength, MSG_DONTWAIT | MSG_NOSIGNAL);
+        nWrite = ::send(mFd.get(), &cleanMsg, msgLength, MSG_DONTWAIT | MSG_NOSIGNAL);
     } while (nWrite == -1 && errno == EINTR);
 
     if (nWrite < 0) {
@@ -327,7 +320,7 @@
 status_t InputChannel::receiveMessage(InputMessage* msg) {
     ssize_t nRead;
     do {
-        nRead = ::recv(mFd, msg, sizeof(InputMessage), MSG_DONTWAIT);
+        nRead = ::recv(mFd.get(), msg, sizeof(InputMessage), MSG_DONTWAIT);
     } while (nRead == -1 && errno == EINTR);
 
     if (nRead < 0) {
@@ -365,39 +358,44 @@
 }
 
 sp<InputChannel> InputChannel::dup() const {
-    int fd = ::dup(getFd());
-    return fd >= 0 ? new InputChannel(getName(), fd) : nullptr;
+    android::base::unique_fd newFd(::dup(getFd()));
+    if (!newFd.ok()) {
+        ALOGE("Could not duplicate fd %i for channel %s: %s", getFd(), mName.c_str(),
+              strerror(errno));
+        return nullptr;
+    }
+    return InputChannel::create(mName, std::move(newFd));
 }
 
-
 status_t InputChannel::write(Parcel& out) const {
-    status_t s = out.writeString8(String8(getName().c_str()));
-
+    status_t s = out.writeCString(getName().c_str());
     if (s != OK) {
         return s;
     }
+
     s = out.writeStrongBinder(mToken);
     if (s != OK) {
         return s;
     }
 
-    s = out.writeDupFileDescriptor(getFd());
-
+    s = out.writeUniqueFileDescriptor(mFd);
     return s;
 }
 
-status_t InputChannel::read(const Parcel& from) {
-    mName = from.readString8();
-    mToken = from.readStrongBinder();
-
-    int rawFd = from.readFileDescriptor();
-    setFd(::dup(rawFd));
-
-    if (mFd < 0) {
-        return BAD_VALUE;
+sp<InputChannel> InputChannel::read(const Parcel& from) {
+    std::string name = from.readCString();
+    sp<IBinder> token = from.readStrongBinder();
+    android::base::unique_fd rawFd;
+    status_t fdResult = from.readUniqueFileDescriptor(&rawFd);
+    if (fdResult != OK) {
+        return nullptr;
     }
 
-    return OK;
+    sp<InputChannel> channel = InputChannel::create(name, std::move(rawFd));
+    if (channel != nullptr) {
+        channel->setToken(token);
+    }
+    return channel;
 }
 
 sp<IBinder> InputChannel::getToken() const {
diff --git a/libs/input/tests/InputChannel_test.cpp b/libs/input/tests/InputChannel_test.cpp
index f1675c0..af74edd 100644
--- a/libs/input/tests/InputChannel_test.cpp
+++ b/libs/input/tests/InputChannel_test.cpp
@@ -22,11 +22,12 @@
 #include <time.h>
 #include <errno.h>
 
+#include <binder/Binder.h>
 #include <gtest/gtest.h>
 #include <input/InputTransport.h>
-#include <utils/Timers.h>
 #include <utils/StopWatch.h>
 #include <utils/StrongPointer.h>
+#include <utils/Timers.h>
 
 namespace android {
 
@@ -43,20 +44,28 @@
     // of a pipe and to check for EPIPE on the other end after the channel is destroyed.
     Pipe pipe;
 
-    sp<InputChannel> inputChannel = new InputChannel("channel name", pipe.sendFd);
+    android::base::unique_fd sendFd(pipe.sendFd);
 
+    sp<InputChannel> inputChannel = InputChannel::create("channel name", std::move(sendFd));
+
+    EXPECT_NE(inputChannel, nullptr) << "channel should be successfully created";
     EXPECT_STREQ("channel name", inputChannel->getName().c_str())
             << "channel should have provided name";
-    EXPECT_EQ(pipe.sendFd, inputChannel->getFd())
-            << "channel should have provided fd";
+    EXPECT_NE(-1, inputChannel->getFd()) << "channel should have valid fd";
 
-    inputChannel.clear(); // destroys input channel
+    // InputChannel should be the owner of the file descriptor now
+    ASSERT_FALSE(sendFd.ok());
+}
 
-    EXPECT_EQ(-EPIPE, pipe.readSignal())
-            << "channel should have closed fd when destroyed";
+TEST_F(InputChannelTest, SetAndGetToken) {
+    Pipe pipe;
+    sp<InputChannel> channel =
+            InputChannel::create("test channel", android::base::unique_fd(pipe.sendFd));
+    EXPECT_EQ(channel->getToken(), nullptr);
 
-    // clean up fds of Pipe endpoints that were closed so we don't try to close them again
-    pipe.sendFd = -1;
+    sp<IBinder> token = new BBinder();
+    channel->setToken(token);
+    EXPECT_EQ(token, channel->getToken());
 }
 
 TEST_F(InputChannelTest, OpenInputChannelPair_ReturnsAPairOfConnectedChannels) {
diff --git a/services/gpuservice/GpuService.cpp b/services/gpuservice/GpuService.cpp
index e50dfca..42d566f 100644
--- a/services/gpuservice/GpuService.cpp
+++ b/services/gpuservice/GpuService.cpp
@@ -261,7 +261,7 @@
                     dumpDriverInfo = true;
                 } else if (args[index] == String16("--gpumem")) {
                     dumpMemory = true;
-                } else if (args[index].compare(String16("--gpumem=")) > 0) {
+                } else if (args[index].startsWith(String16("--gpumem="))) {
                     dumpMemory = true;
                     pid = atoi(String8(&args[index][9]));
                 }
diff --git a/services/surfaceflinger/BufferLayer.h b/services/surfaceflinger/BufferLayer.h
index fb8d7d0..ee44cbe 100644
--- a/services/surfaceflinger/BufferLayer.h
+++ b/services/surfaceflinger/BufferLayer.h
@@ -62,10 +62,6 @@
     void useSurfaceDamage() override;
     void useEmptyDamage() override;
 
-    // getTypeId - Provide unique string for each class type in the Layer
-    // hierarchy
-    const char* getTypeId() const override { return "BufferLayer"; }
-
     bool isOpaque(const Layer::State& s) const override;
 
     // isVisible - true if this layer is visible, false otherwise
diff --git a/services/surfaceflinger/BufferQueueLayer.h b/services/surfaceflinger/BufferQueueLayer.h
index 392b706..3bc625e 100644
--- a/services/surfaceflinger/BufferQueueLayer.h
+++ b/services/surfaceflinger/BufferQueueLayer.h
@@ -38,6 +38,8 @@
     // Interface implementation for Layer
     // -----------------------------------------------------------------------
 public:
+    const char* getType() const override { return "BufferQueueLayer"; }
+
     void onLayerDisplayed(const sp<Fence>& releaseFence) override;
 
     void setTransformHint(uint32_t orientation) const override;
diff --git a/services/surfaceflinger/BufferStateLayer.cpp b/services/surfaceflinger/BufferStateLayer.cpp
index 611decf..e0804ff 100644
--- a/services/surfaceflinger/BufferStateLayer.cpp
+++ b/services/surfaceflinger/BufferStateLayer.cpp
@@ -227,10 +227,10 @@
     setTransactionFlags(eTransactionNeeded);
 
     mFlinger->mTimeStats->setPostTime(getSequence(), mFrameNumber, getName().c_str(), postTime);
-    mDesiredPresentTime = desiredPresentTime;
+    mCurrentState.desiredPresentTime = desiredPresentTime;
 
     if (mFlinger->mUseSmart90ForVideo) {
-        const nsecs_t presentTime = (mDesiredPresentTime == -1) ? 0 : mDesiredPresentTime;
+        const nsecs_t presentTime = (desiredPresentTime == -1) ? 0 : desiredPresentTime;
         mFlinger->mScheduler->addLayerPresentTimeAndHDR(mSchedulerLayerHandle, presentTime,
                                                         mCurrentState.hdrMetadata.validTypes != 0);
     }
@@ -384,11 +384,11 @@
         return true;
     }
 
-    return mDesiredPresentTime <= expectedPresentTime;
+    return mCurrentState.desiredPresentTime <= expectedPresentTime;
 }
 
 nsecs_t BufferStateLayer::getDesiredPresentTime() {
-    return mDesiredPresentTime;
+    return getDrawingState().desiredPresentTime;
 }
 
 std::shared_ptr<FenceTime> BufferStateLayer::getCurrentFenceTime() const {
diff --git a/services/surfaceflinger/BufferStateLayer.h b/services/surfaceflinger/BufferStateLayer.h
index 6db91ef..cc67008 100644
--- a/services/surfaceflinger/BufferStateLayer.h
+++ b/services/surfaceflinger/BufferStateLayer.h
@@ -40,6 +40,8 @@
     // -----------------------------------------------------------------------
     // Interface implementation for Layer
     // -----------------------------------------------------------------------
+    const char* getType() const override { return "BufferStateLayer"; }
+
     void onLayerDisplayed(const sp<Fence>& releaseFence) override;
     void setTransformHint(uint32_t orientation) const override;
     void releasePendingBuffer(nsecs_t dequeueReadyTime) override;
@@ -159,8 +161,6 @@
     bool mReleasePreviousBuffer = false;
     nsecs_t mCallbackHandleAcquireTime = -1;
 
-    nsecs_t mDesiredPresentTime = -1;
-
     // TODO(marissaw): support sticky transform for LEGACY camera mode
 
     class HwcSlotGenerator : public ClientCache::ErasedRecipient {
diff --git a/services/surfaceflinger/ColorLayer.h b/services/surfaceflinger/ColorLayer.h
index c793142..57c54c7 100644
--- a/services/surfaceflinger/ColorLayer.h
+++ b/services/surfaceflinger/ColorLayer.h
@@ -30,7 +30,7 @@
 
     std::shared_ptr<compositionengine::Layer> getCompositionLayer() const override;
 
-    virtual const char* getTypeId() const { return "ColorLayer"; }
+    const char* getType() const override { return "ColorLayer"; }
     bool isVisible() const override;
 
     bool setColor(const half3& color) override;
diff --git a/services/surfaceflinger/CompositionEngine/Android.bp b/services/surfaceflinger/CompositionEngine/Android.bp
index ae6bdbc..580bde8 100644
--- a/services/surfaceflinger/CompositionEngine/Android.bp
+++ b/services/surfaceflinger/CompositionEngine/Android.bp
@@ -119,6 +119,13 @@
         //
         // You can either "make dist tests" before flashing, or set this
         // option to false temporarily.
-        address: true,
+
+
+        // FIXME: ASAN build is broken for a while, but was not discovered
+        // since new PM silently suppressed ASAN. Temporarily turn off ASAN
+        // to unblock the compiler upgrade process.
+        // address: true,
+        // http://b/139747256
+        address: false,
     },
 }
diff --git a/services/surfaceflinger/ContainerLayer.h b/services/surfaceflinger/ContainerLayer.h
index a1607ff..f0fbb61 100644
--- a/services/surfaceflinger/ContainerLayer.h
+++ b/services/surfaceflinger/ContainerLayer.h
@@ -28,7 +28,7 @@
     explicit ContainerLayer(const LayerCreationArgs&);
     ~ContainerLayer() override;
 
-    const char* getTypeId() const override { return "ContainerLayer"; }
+    const char* getType() const override { return "ContainerLayer"; }
     bool isVisible() const override;
 
     bool canReceiveInput() const override;
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index db4ae41..5121835 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -1217,7 +1217,7 @@
     info.mName = getName();
     sp<Layer> parent = getParent();
     info.mParentName = (parent == nullptr ? std::string("none") : parent->getName().string());
-    info.mType = std::string(getTypeId());
+    info.mType = getType();
     info.mTransparentRegion = ds.activeTransparentRegion_legacy;
     info.mVisibleRegion = visibleRegion;
     info.mSurfaceDamageRegion = surfaceDamageRegion;
@@ -1334,7 +1334,7 @@
 }
 
 void Layer::dumpFrameEvents(std::string& result) {
-    StringAppendF(&result, "- Layer %s (%s, %p)\n", getName().string(), getTypeId(), this);
+    StringAppendF(&result, "- Layer %s (%s, %p)\n", getName().string(), getType(), this);
     Mutex::Autolock lock(mFrameEventHistoryMutex);
     mFrameEventHistory.checkFencesForCompletion();
     mFrameEventHistory.dump(result);
@@ -1868,7 +1868,7 @@
     if (traceFlags & SurfaceTracing::TRACE_CRITICAL) {
         layerInfo->set_id(sequence);
         layerInfo->set_name(getName().c_str());
-        layerInfo->set_type(String8(getTypeId()));
+        layerInfo->set_type(getType());
 
         for (const auto& child : children) {
             layerInfo->add_children(child->sequence);
diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h
index 2a1564a..9107189 100644
--- a/services/surfaceflinger/Layer.h
+++ b/services/surfaceflinger/Layer.h
@@ -217,6 +217,7 @@
         // recent callback handle.
         std::deque<sp<CallbackHandle>> callbackHandles;
         bool colorSpaceAgnostic;
+        nsecs_t desiredPresentTime = -1;
     };
 
     explicit Layer(const LayerCreationArgs& args);
@@ -377,7 +378,9 @@
 
     // -----------------------------------------------------------------------
     // Virtuals
-    virtual const char* getTypeId() const = 0;
+
+    // Provide unique string for each class type in the Layer hierarchy
+    virtual const char* getType() const = 0;
 
     /*
      * isOpaque - true if this surface is opaque
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index 27a0f6b..05ba234 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -29,6 +29,7 @@
 #include <gui/FrameTimestamps.h>
 #include <gui/ISurfaceComposer.h>
 #include <gui/ISurfaceComposerClient.h>
+#include <gui/ITransactionCompletedListener.h>
 #include <gui/LayerState.h>
 #include <gui/OccupancyTracker.h>
 #include <hardware/hwcomposer_defs.h>
@@ -1024,11 +1025,6 @@
     uint32_t mTexturePoolSize = 0;
     std::vector<uint32_t> mTexturePool;
 
-    struct IBinderHash {
-        std::size_t operator()(const sp<IBinder>& strongPointer) const {
-            return std::hash<IBinder*>{}(strongPointer.get());
-        }
-    };
     struct TransactionState {
         TransactionState(const Vector<ComposerState>& composerStates,
                          const Vector<DisplayState>& displayStates, uint32_t transactionFlags,
@@ -1053,7 +1049,7 @@
         const int64_t postTime;
         bool privileged;
     };
-    std::unordered_map<sp<IBinder>, std::queue<TransactionState>, IBinderHash> mTransactionQueues;
+    std::unordered_map<sp<IBinder>, std::queue<TransactionState>, IListenerHash> mTransactionQueues;
 
     /* ------------------------------------------------------------------------
      * Feature prototyping
diff --git a/services/surfaceflinger/TransactionCompletedThread.cpp b/services/surfaceflinger/TransactionCompletedThread.cpp
index c519f8d..1324f20 100644
--- a/services/surfaceflinger/TransactionCompletedThread.cpp
+++ b/services/surfaceflinger/TransactionCompletedThread.cpp
@@ -24,7 +24,6 @@
 #include <cinttypes>
 
 #include <binder/IInterface.h>
-#include <gui/ITransactionCompletedListener.h>
 #include <utils/RefBase.h>
 
 namespace android {
@@ -58,7 +57,7 @@
     {
         std::lock_guard lock(mMutex);
         for (const auto& [listener, transactionStats] : mCompletedTransactions) {
-            IInterface::asBinder(listener)->unlinkToDeath(mDeathRecipient);
+            listener->unlinkToDeath(mDeathRecipient);
         }
     }
 }
@@ -85,7 +84,7 @@
     auto& [listener, callbackIds] = listenerCallbacks;
 
     if (mCompletedTransactions.count(listener) == 0) {
-        status_t err = IInterface::asBinder(listener)->linkToDeath(mDeathRecipient);
+        status_t err = listener->linkToDeath(mDeathRecipient);
         if (err != NO_ERROR) {
             ALOGE("cannot add callback because linkToDeath failed, err: %d", err);
             return err;
@@ -119,8 +118,7 @@
 }
 
 bool TransactionCompletedThread::isRegisteringTransaction(
-        const sp<ITransactionCompletedListener>& transactionListener,
-        const std::vector<CallbackId>& callbackIds) {
+        const sp<IBinder>& transactionListener, const std::vector<CallbackId>& callbackIds) {
     ListenerCallbacks listenerCallbacks(transactionListener, callbackIds);
 
     auto itr = mRegisteringTransactions.find(listenerCallbacks);
@@ -201,8 +199,8 @@
 }
 
 status_t TransactionCompletedThread::findTransactionStats(
-        const sp<ITransactionCompletedListener>& listener,
-        const std::vector<CallbackId>& callbackIds, TransactionStats** outTransactionStats) {
+        const sp<IBinder>& listener, const std::vector<CallbackId>& callbackIds,
+        TransactionStats** outTransactionStats) {
     auto& transactionStatsDeque = mCompletedTransactions[listener];
 
     // Search back to front because the most recent transactions are at the back of the deque
@@ -300,10 +298,16 @@
             // If the listener has completed transactions
             if (!listenerStats.transactionStats.empty()) {
                 // If the listener is still alive
-                if (IInterface::asBinder(listener)->isBinderAlive()) {
-                    // Send callback
-                    listenerStats.listener->onTransactionCompleted(listenerStats);
-                    IInterface::asBinder(listener)->unlinkToDeath(mDeathRecipient);
+                if (listener->isBinderAlive()) {
+                    // Send callback.  The listener stored in listenerStats
+                    // comes from the cross-process setTransactionState call to
+                    // SF.  This MUST be an ITransactionCompletedListener.  We
+                    // keep it as an IBinder due to consistency reasons: if we
+                    // interface_cast at the IPC boundary when reading a Parcel,
+                    // we get pointers that compare unequal in the SF process.
+                    interface_cast<ITransactionCompletedListener>(listenerStats.listener)
+                            ->onTransactionCompleted(listenerStats);
+                    listener->unlinkToDeath(mDeathRecipient);
                 }
                 completedTransactionsItr = mCompletedTransactions.erase(completedTransactionsItr);
             } else {
@@ -335,7 +339,7 @@
 
 // -----------------------------------------------------------------------
 
-CallbackHandle::CallbackHandle(const sp<ITransactionCompletedListener>& transactionListener,
+CallbackHandle::CallbackHandle(const sp<IBinder>& transactionListener,
                                const std::vector<CallbackId>& ids, const sp<IBinder>& sc)
       : listener(transactionListener), callbackIds(ids), surfaceControl(sc) {}
 
diff --git a/services/surfaceflinger/TransactionCompletedThread.h b/services/surfaceflinger/TransactionCompletedThread.h
index e255e50..a85ad1e 100644
--- a/services/surfaceflinger/TransactionCompletedThread.h
+++ b/services/surfaceflinger/TransactionCompletedThread.h
@@ -31,46 +31,12 @@
 
 namespace android {
 
-struct ITransactionCompletedListenerHash {
-    std::size_t operator()(const sp<ITransactionCompletedListener>& listener) const {
-        return std::hash<IBinder*>{}((listener) ? IInterface::asBinder(listener).get() : nullptr);
-    }
-};
-
-struct CallbackIdsHash {
-    // CallbackId vectors have several properties that let us get away with this simple hash.
-    // 1) CallbackIds are never 0 so if something has gone wrong and our CallbackId vector is
-    // empty we can still hash 0.
-    // 2) CallbackId vectors for the same listener either are identical or contain none of the
-    // same members. It is sufficient to just check the first CallbackId in the vectors. If
-    // they match, they are the same. If they do not match, they are not the same.
-    std::size_t operator()(const std::vector<CallbackId>& callbackIds) const {
-        return std::hash<CallbackId>{}((callbackIds.empty()) ? 0 : callbackIds.front());
-    }
-};
-
-struct ListenerCallbacksHash {
-    std::size_t HashCombine(size_t value1, size_t value2) const {
-        return value1 ^ (value2 + 0x9e3779b9 + (value1 << 6) + (value1 >> 2));
-    }
-
-    std::size_t operator()(const ListenerCallbacks& listenerCallbacks) const {
-        struct ITransactionCompletedListenerHash listenerHasher;
-        struct CallbackIdsHash callbackIdsHasher;
-
-        std::size_t listenerHash = listenerHasher(listenerCallbacks.transactionCompletedListener);
-        std::size_t callbackIdsHash = callbackIdsHasher(listenerCallbacks.callbackIds);
-
-        return HashCombine(listenerHash, callbackIdsHash);
-    }
-};
-
 class CallbackHandle : public RefBase {
 public:
-    CallbackHandle(const sp<ITransactionCompletedListener>& transactionListener,
-                   const std::vector<CallbackId>& ids, const sp<IBinder>& sc);
+    CallbackHandle(const sp<IBinder>& transactionListener, const std::vector<CallbackId>& ids,
+                   const sp<IBinder>& sc);
 
-    sp<ITransactionCompletedListener> listener;
+    sp<IBinder> listener;
     std::vector<CallbackId> callbackIds;
     wp<IBinder> surfaceControl;
 
@@ -114,10 +80,10 @@
 private:
     void threadMain();
 
-    bool isRegisteringTransaction(const sp<ITransactionCompletedListener>& transactionListener,
+    bool isRegisteringTransaction(const sp<IBinder>& transactionListener,
                                   const std::vector<CallbackId>& callbackIds) REQUIRES(mMutex);
 
-    status_t findTransactionStats(const sp<ITransactionCompletedListener>& listener,
+    status_t findTransactionStats(const sp<IBinder>& listener,
                                   const std::vector<CallbackId>& callbackIds,
                                   TransactionStats** outTransactionStats) REQUIRES(mMutex);
 
@@ -146,13 +112,12 @@
             GUARDED_BY(mMutex);
 
     std::unordered_map<
-            sp<ITransactionCompletedListener>,
+            sp<IBinder>,
             std::unordered_map<std::vector<CallbackId>, uint32_t /*count*/, CallbackIdsHash>,
-            ITransactionCompletedListenerHash>
+            IListenerHash>
             mPendingTransactions GUARDED_BY(mMutex);
 
-    std::unordered_map<sp<ITransactionCompletedListener>, std::deque<TransactionStats>,
-                       ITransactionCompletedListenerHash>
+    std::unordered_map<sp<IBinder>, std::deque<TransactionStats>, IListenerHash>
             mCompletedTransactions GUARDED_BY(mMutex);
 
     bool mRunning GUARDED_BY(mMutex) = false;
diff --git a/services/surfaceflinger/tests/fakehwc/Android.bp b/services/surfaceflinger/tests/fakehwc/Android.bp
index a2c0611..f359550 100644
--- a/services/surfaceflinger/tests/fakehwc/Android.bp
+++ b/services/surfaceflinger/tests/fakehwc/Android.bp
@@ -10,6 +10,7 @@
     ],
     shared_libs: [
         "android.hardware.graphics.composer@2.1",
+        "android.hardware.graphics.composer@2.1-resources",
         "android.hardware.graphics.mapper@2.0",
         "android.hardware.graphics.mapper@3.0",
         "android.hardware.power@1.3",
diff --git a/services/vr/hardware_composer/Android.bp b/services/vr/hardware_composer/Android.bp
index 1604775..bc7cc1c 100644
--- a/services/vr/hardware_composer/Android.bp
+++ b/services/vr/hardware_composer/Android.bp
@@ -14,6 +14,7 @@
     shared_libs: [
         "android.frameworks.vr.composer@1.0",
         "android.hardware.graphics.composer@2.1",
+        "android.hardware.graphics.composer@2.1-resources",
         "android.hardware.graphics.mapper@2.0",
         "android.hardware.graphics.mapper@3.0",
         "libbase",