Merge "Fixes broken build on crosshatch-userdebug when enable LOG_NDEBUG"
diff --git a/cmds/installd/InstalldNativeService.cpp b/cmds/installd/InstalldNativeService.cpp
index 157d259..39ef0b5 100644
--- a/cmds/installd/InstalldNativeService.cpp
+++ b/cmds/installd/InstalldNativeService.cpp
@@ -422,9 +422,131 @@
     return true;
 }
 
+static bool chown_app_dir(const std::string& path, uid_t uid, uid_t previousUid, gid_t cacheGid) {
+    FTS* fts;
+    char *argv[] = { (char*) path.c_str(), nullptr };
+    if (!(fts = fts_open(argv, FTS_PHYSICAL | FTS_NOCHDIR | FTS_XDEV, nullptr))) {
+        return false;
+    }
+    for (FTSENT* p; (p = fts_read(fts)) != nullptr;) {
+        if (p->fts_info == FTS_D && p->fts_level == 1
+            && (strcmp(p->fts_name, "cache") == 0
+                || strcmp(p->fts_name, "code_cache") == 0)) {
+            // Mark cache dirs
+            p->fts_number = 1;
+        } else {
+            // Inherit parent's number
+            p->fts_number = p->fts_parent->fts_number;
+        }
+
+        switch (p->fts_info) {
+        case FTS_D:
+        case FTS_F:
+        case FTS_SL:
+        case FTS_SLNONE:
+            if (p->fts_statp->st_uid == previousUid) {
+                if (lchown(p->fts_path, uid, p->fts_number ? cacheGid : uid) != 0) {
+                    PLOG(WARNING) << "Failed to lchown " << p->fts_path;
+                }
+            } else {
+                LOG(WARNING) << "Ignoring " << p->fts_path << " with unexpected UID "
+                        << p->fts_statp->st_uid << " instead of " << previousUid;
+            }
+            break;
+        }
+    }
+    fts_close(fts);
+    return true;
+}
+
+static void chown_app_profile_dir(const std::string &packageName, int32_t appId, int32_t userId) {
+    uid_t uid = multiuser_get_uid(userId, appId);
+    gid_t sharedGid = multiuser_get_shared_gid(userId, appId);
+
+    const std::string profile_dir =
+            create_primary_current_profile_package_dir_path(userId, packageName);
+    char *argv[] = { (char*) profile_dir.c_str(), nullptr };
+    if (FTS* fts = fts_open(argv, FTS_PHYSICAL | FTS_NOCHDIR | FTS_XDEV, nullptr)) {
+        for (FTSENT* p; (p = fts_read(fts)) != nullptr;) {
+            switch (p->fts_info) {
+            case FTS_D:
+            case FTS_F:
+            case FTS_SL:
+            case FTS_SLNONE:
+                if (lchown(p->fts_path, uid, uid) != 0) {
+                    PLOG(WARNING) << "Failed to lchown " << p->fts_path;
+                }
+                break;
+            }
+        }
+        fts_close(fts);
+    }
+
+    const std::string ref_profile_path =
+            create_primary_reference_profile_package_dir_path(packageName);
+    argv[0] = (char *) ref_profile_path.c_str();
+    if (FTS* fts = fts_open(argv, FTS_PHYSICAL | FTS_NOCHDIR | FTS_XDEV, nullptr)) {
+        for (FTSENT* p; (p = fts_read(fts)) != nullptr;) {
+            if (p->fts_info == FTS_D && p->fts_level == 0) {
+                if (chown(p->fts_path, AID_SYSTEM, sharedGid) != 0) {
+                    PLOG(WARNING) << "Failed to chown " << p->fts_path;
+                }
+                continue;
+            }
+            switch (p->fts_info) {
+            case FTS_D:
+            case FTS_F:
+            case FTS_SL:
+            case FTS_SLNONE:
+                if (lchown(p->fts_path, sharedGid, sharedGid) != 0) {
+                    PLOG(WARNING) << "Failed to lchown " << p->fts_path;
+                }
+                break;
+            }
+        }
+        fts_close(fts);
+    }
+}
+
+static binder::Status createAppDataDirs(const std::string& path,
+        int32_t uid, int32_t* previousUid, int32_t cacheGid,
+        const std::string& seInfo, mode_t targetMode) {
+    struct stat st{};
+    bool existing = (stat(path.c_str(), &st) == 0);
+    if (existing) {
+        if (*previousUid < 0) {
+            // If previousAppId is -1 in CreateAppDataArgs, we will assume the current owner
+            // of the directory as previousUid. This is required because it is not always possible
+            // to chown app data during app upgrade (e.g. secondary users' CE storage not unlocked)
+            *previousUid = st.st_uid;
+        }
+        if (*previousUid != uid) {
+            if (!chown_app_dir(path, uid, *previousUid, cacheGid)) {
+                return error("Failed to chown " + path);
+            }
+        }
+    }
+
+    if (prepare_app_dir(path, targetMode, uid) ||
+            prepare_app_cache_dir(path, "cache", 02771, uid, cacheGid) ||
+            prepare_app_cache_dir(path, "code_cache", 02771, uid, cacheGid)) {
+        return error("Failed to prepare " + path);
+    }
+
+    // Consider restorecon over contents if label changed
+    if (restorecon_app_data_lazy(path, seInfo, uid, existing) ||
+            restorecon_app_data_lazy(path, "cache", seInfo, uid, existing) ||
+            restorecon_app_data_lazy(path, "code_cache", seInfo, uid, existing)) {
+        return error("Failed to restorecon " + path);
+    }
+
+    return ok();
+}
+
 binder::Status InstalldNativeService::createAppData(const std::optional<std::string>& uuid,
         const std::string& packageName, int32_t userId, int32_t flags, int32_t appId,
-        const std::string& seInfo, int32_t targetSdkVersion, int64_t* _aidl_return) {
+        int32_t previousAppId, const std::string& seInfo, int32_t targetSdkVersion,
+        int64_t* _aidl_return) {
     ENFORCE_UID(AID_SYSTEM);
     CHECK_ARGUMENT_UUID(uuid);
     CHECK_ARGUMENT_PACKAGE_NAME(packageName);
@@ -437,6 +559,14 @@
     if (_aidl_return != nullptr) *_aidl_return = -1;
 
     int32_t uid = multiuser_get_uid(userId, appId);
+
+    // If previousAppId < 0, we will use the existing app data owner as previousAppUid
+    // If previousAppId == 0, we use uid as previousUid (no data migration will happen)
+    // if previousAppId > 0, an app is upgrading and changing its app ID
+    int32_t previousUid = previousAppId > 0
+        ? (int32_t) multiuser_get_uid(userId, previousAppId)
+        : (previousAppId == 0 ? uid : -1);
+
     int32_t cacheGid = multiuser_get_cache_gid(userId, appId);
     mode_t targetMode = targetSdkVersion >= MIN_RESTRICTED_HOME_SDK_VERSION ? 0700 : 0751;
 
@@ -447,19 +577,13 @@
 
     if (flags & FLAG_STORAGE_CE) {
         auto path = create_data_user_ce_package_path(uuid_, userId, pkgname);
-        bool existing = (access(path.c_str(), F_OK) == 0);
 
-        if (prepare_app_dir(path, targetMode, uid) ||
-                prepare_app_cache_dir(path, "cache", 02771, uid, cacheGid) ||
-                prepare_app_cache_dir(path, "code_cache", 02771, uid, cacheGid)) {
-            return error("Failed to prepare " + path);
+        auto status = createAppDataDirs(path, uid, &previousUid, cacheGid, seInfo, targetMode);
+        if (!status.isOk()) {
+            return status;
         }
-
-        // Consider restorecon over contents if label changed
-        if (restorecon_app_data_lazy(path, seInfo, uid, existing) ||
-                restorecon_app_data_lazy(path, "cache", seInfo, uid, existing) ||
-                restorecon_app_data_lazy(path, "code_cache", seInfo, uid, existing)) {
-            return error("Failed to restorecon " + path);
+        if (previousUid != uid) {
+            chown_app_profile_dir(packageName, appId, userId);
         }
 
         // Remember inode numbers of cache directories so that we can clear
@@ -481,19 +605,10 @@
     }
     if (flags & FLAG_STORAGE_DE) {
         auto path = create_data_user_de_package_path(uuid_, userId, pkgname);
-        bool existing = (access(path.c_str(), F_OK) == 0);
 
-        if (prepare_app_dir(path, targetMode, uid) ||
-                prepare_app_cache_dir(path, "cache", 02771, uid, cacheGid) ||
-                prepare_app_cache_dir(path, "code_cache", 02771, uid, cacheGid)) {
-            return error("Failed to prepare " + path);
-        }
-
-        // Consider restorecon over contents if label changed
-        if (restorecon_app_data_lazy(path, seInfo, uid, existing) ||
-                restorecon_app_data_lazy(path, "cache", seInfo, uid, existing) ||
-                restorecon_app_data_lazy(path, "code_cache", seInfo, uid, existing)) {
-            return error("Failed to restorecon " + path);
+        auto status = createAppDataDirs(path, uid, &previousUid, cacheGid, seInfo, targetMode);
+        if (!status.isOk()) {
+            return status;
         }
 
         if (!prepare_app_profile_dir(packageName, appId, userId)) {
@@ -503,7 +618,6 @@
     return ok();
 }
 
-
 binder::Status InstalldNativeService::createAppData(
         const android::os::CreateAppDataArgs& args,
         android::os::CreateAppDataResult* _aidl_return) {
@@ -512,7 +626,7 @@
 
     int64_t ceDataInode = -1;
     auto status = createAppData(args.uuid, args.packageName, args.userId, args.flags, args.appId,
-                                args.seInfo, args.targetSdkVersion, &ceDataInode);
+            args.previousAppId, args.seInfo, args.targetSdkVersion, &ceDataInode);
     _aidl_return->ceDataInode = ceDataInode;
     _aidl_return->exceptionCode = status.exceptionCode();
     _aidl_return->exceptionMessage = status.exceptionMessage();
@@ -526,7 +640,7 @@
     std::lock_guard<std::recursive_mutex> lock(mLock);
 
     std::vector<android::os::CreateAppDataResult> results;
-    for (auto arg : args) {
+    for (const auto &arg : args) {
         android::os::CreateAppDataResult result;
         createAppData(arg, &result);
         results.push_back(result);
@@ -624,14 +738,11 @@
         }
     }
     if (flags & FLAG_STORAGE_DE) {
-        std::string suffix = "";
-        bool only_cache = false;
+        std::string suffix;
         if (flags & FLAG_CLEAR_CACHE_ONLY) {
             suffix = CACHE_DIR_POSTFIX;
-            only_cache = true;
         } else if (flags & FLAG_CLEAR_CODE_CACHE_ONLY) {
             suffix = CODE_CACHE_DIR_POSTFIX;
-            only_cache = true;
         }
 
         auto path = create_data_user_de_package_path(uuid_, userId, pkgname) + suffix;
@@ -1226,7 +1337,7 @@
         }
 
         if (!createAppData(toUuid, packageName, user, FLAG_STORAGE_CE | FLAG_STORAGE_DE, appId,
-                seInfo, targetSdkVersion, nullptr).isOk()) {
+                /* previousAppId */ -1, seInfo, targetSdkVersion, nullptr).isOk()) {
             res = error("Failed to create package target");
             goto fail;
         }
diff --git a/cmds/installd/InstalldNativeService.h b/cmds/installd/InstalldNativeService.h
index ae257df..8cfda01 100644
--- a/cmds/installd/InstalldNativeService.h
+++ b/cmds/installd/InstalldNativeService.h
@@ -47,7 +47,8 @@
 
     binder::Status createAppData(const std::optional<std::string>& uuid,
             const std::string& packageName, int32_t userId, int32_t flags, int32_t appId,
-            const std::string& seInfo, int32_t targetSdkVersion, int64_t* _aidl_return);
+            int32_t previousAppId, const std::string& seInfo, int32_t targetSdkVersion,
+            int64_t* _aidl_return);
 
     binder::Status createAppData(
             const android::os::CreateAppDataArgs& args,
diff --git a/cmds/installd/binder/android/os/CreateAppDataArgs.aidl b/cmds/installd/binder/android/os/CreateAppDataArgs.aidl
index 96d7faa..d5e8ee5 100644
--- a/cmds/installd/binder/android/os/CreateAppDataArgs.aidl
+++ b/cmds/installd/binder/android/os/CreateAppDataArgs.aidl
@@ -23,6 +23,7 @@
     int userId;
     int flags;
     int appId;
+    int previousAppId;
     @utf8InCpp String seInfo;
     int targetSdkVersion;
 }
diff --git a/cmds/installd/tests/installd_dexopt_test.cpp b/cmds/installd/tests/installd_dexopt_test.cpp
index ea26955..a937436 100644
--- a/cmds/installd/tests/installd_dexopt_test.cpp
+++ b/cmds/installd/tests/installd_dexopt_test.cpp
@@ -287,6 +287,7 @@
                 kTestUserId,
                 kAppDataFlags,
                 kTestAppUid,
+                0 /* previousAppId */,
                 se_info_,
                 kOSdkVersion,
                 &ce_data_inode_);
@@ -1257,6 +1258,7 @@
             kTestUserId,
             kAppDataFlags,
             kTestAppUid,
+            0 /* previousAppId */,
             se_info_,
             kOSdkVersion,
             &ce_data_inode_));
@@ -1320,6 +1322,7 @@
                     kTestUserId,
                     kAppDataFlags,
                     kTestAppUid,
+                    0 /* previousAppId */,
                     se_info_,
                     kOSdkVersion,
                     &ce_data_inode));
diff --git a/cmds/service/service.cpp b/cmds/service/service.cpp
index fdbe85b..fe417a3 100644
--- a/cmds/service/service.cpp
+++ b/cmds/service/service.cpp
@@ -45,33 +45,6 @@
     }
 }
 
-// get the name of the generic interface we hold a reference to
-static String16 get_interface_name(sp<IBinder> service)
-{
-    if (service != nullptr) {
-        Parcel data, reply;
-        data.markForBinder(service);
-        status_t err = service->transact(IBinder::INTERFACE_TRANSACTION, data, &reply);
-        if (err == NO_ERROR) {
-            return reply.readString16();
-        }
-    }
-    return String16();
-}
-
-static String8 good_old_string(const String16& src)
-{
-    String8 name8;
-    char ch8[2];
-    ch8[1] = 0;
-    for (unsigned j = 0; j < src.size(); j++) {
-        char16_t ch = src[j];
-        if (ch < 128) ch8[0] = (char)ch;
-        name8.append(ch8);
-    }
-    return name8;
-}
-
 int main(int argc, char* const argv[])
 {
     bool wantsUsage = false;
@@ -132,8 +105,8 @@
                 String16 name = services[i];
                 sp<IBinder> service = sm->checkService(name);
                 aout << i
-                     << "\t" << good_old_string(name)
-                     << ": [" << good_old_string(get_interface_name(service)) << "]"
+                     << "\t" << name
+                     << ": [" << (service ? service->getInterfaceDescriptor() : String16()) << "]"
                      << endl;
             }
         } else if (strcmp(argv[optind], "call") == 0) {
@@ -141,7 +114,7 @@
             if (optind+1 < argc) {
                 int serviceArg = optind;
                 sp<IBinder> service = sm->checkService(String16(argv[optind++]));
-                String16 ifName = get_interface_name(service);
+                String16 ifName = (service ? service->getInterfaceDescriptor() : String16());
                 int32_t code = atoi(argv[optind++]);
                 if (service != nullptr && ifName.size() > 0) {
                     Parcel data, reply;
diff --git a/libs/binder/Android.bp b/libs/binder/Android.bp
index dc153c9..8270ae5 100644
--- a/libs/binder/Android.bp
+++ b/libs/binder/Android.bp
@@ -149,6 +149,11 @@
                 "UtilsHost.cpp",
             ],
         },
+        recovery: {
+            exclude_header_libs: [
+                "libandroid_runtime_vm_headers",
+            ],
+        },
     },
 
     aidl: {
diff --git a/libs/binder/Parcel.cpp b/libs/binder/Parcel.cpp
index 631a4b6..8f4f0f0 100644
--- a/libs/binder/Parcel.cpp
+++ b/libs/binder/Parcel.cpp
@@ -521,6 +521,25 @@
     return memcmp(data(), other.data(), size);
 }
 
+status_t Parcel::compareDataInRange(size_t thisOffset, const Parcel& other, size_t otherOffset,
+                                    size_t len, int* result) const {
+    if (len > INT32_MAX || thisOffset > INT32_MAX || otherOffset > INT32_MAX) {
+        // Don't accept size_t values which may have come from an inadvertent conversion from a
+        // negative int.
+        return BAD_VALUE;
+    }
+    size_t thisLimit;
+    if (__builtin_add_overflow(thisOffset, len, &thisLimit) || thisLimit > mDataSize) {
+        return BAD_VALUE;
+    }
+    size_t otherLimit;
+    if (__builtin_add_overflow(otherOffset, len, &otherLimit) || otherLimit > other.mDataSize) {
+        return BAD_VALUE;
+    }
+    *result = memcmp(data() + thisOffset, other.data() + otherOffset, len);
+    return NO_ERROR;
+}
+
 bool Parcel::allowFds() const
 {
     return mAllowFds;
diff --git a/libs/binder/RpcSession.cpp b/libs/binder/RpcSession.cpp
index 53c9b78..a5a2bb1 100644
--- a/libs/binder/RpcSession.cpp
+++ b/libs/binder/RpcSession.cpp
@@ -29,13 +29,11 @@
 #include <android-base/hex.h>
 #include <android-base/macros.h>
 #include <android-base/scopeguard.h>
-#include <android_runtime/vm.h>
 #include <binder/BpBinder.h>
 #include <binder/Parcel.h>
 #include <binder/RpcServer.h>
 #include <binder/RpcTransportRaw.h>
 #include <binder/Stability.h>
-#include <jni.h>
 #include <utils/String8.h>
 
 #include "FdTrigger.h"
@@ -48,6 +46,11 @@
 extern "C" pid_t gettid();
 #endif
 
+#ifndef __ANDROID_RECOVERY__
+#include <android_runtime/vm.h>
+#include <jni.h>
+#endif
+
 namespace android {
 
 using base::unique_fd;
@@ -315,6 +318,9 @@
 }
 
 namespace {
+#ifdef __ANDROID_RECOVERY__
+class JavaThreadAttacher {};
+#else
 // RAII object for attaching / detaching current thread to JVM if Android Runtime exists. If
 // Android Runtime doesn't exist, no-op.
 class JavaThreadAttacher {
@@ -367,6 +373,7 @@
         return fn();
     }
 };
+#endif
 } // namespace
 
 void RpcSession::join(sp<RpcSession>&& session, PreJoinSetupResult&& setupResult) {
@@ -374,7 +381,7 @@
 
     if (setupResult.status == OK) {
         LOG_ALWAYS_FATAL_IF(!connection, "must have connection if setup succeeded");
-        JavaThreadAttacher javaThreadAttacher;
+        [[maybe_unused]] JavaThreadAttacher javaThreadAttacher;
         while (true) {
             status_t status = session->state()->getAndExecuteCommand(connection, session,
                                                                      RpcState::CommandType::ANY);
diff --git a/libs/binder/aidl/android/content/pm/StagedApexInfo.aidl b/libs/binder/aidl/android/content/pm/StagedApexInfo.aidl
index ece7989..bffab5e 100644
--- a/libs/binder/aidl/android/content/pm/StagedApexInfo.aidl
+++ b/libs/binder/aidl/android/content/pm/StagedApexInfo.aidl
@@ -27,4 +27,7 @@
   @utf8InCpp String diskImagePath;
   long versionCode;
   @utf8InCpp String versionName;
+  boolean hasBootClassPathJars;
+  boolean hasDex2OatBootClassPathJars;
+  boolean hasSystemServerClassPathJars;
 }
diff --git a/libs/binder/include/binder/IInterface.h b/libs/binder/include/binder/IInterface.h
index ff90b30..7d14315 100644
--- a/libs/binder/include/binder/IInterface.h
+++ b/libs/binder/include/binder/IInterface.h
@@ -129,48 +129,50 @@
 
 #endif
 
-#define DO_NOT_DIRECTLY_USE_ME_IMPLEMENT_META_INTERFACE(INTERFACE, NAME)\
-    const ::android::StaticString16                                     \
-        I##INTERFACE##_descriptor_static_str16(__IINTF_CONCAT(u, NAME));\
-    const ::android::String16 I##INTERFACE::descriptor(                 \
-        I##INTERFACE##_descriptor_static_str16);                        \
-    const ::android::String16&                                          \
-            I##INTERFACE::getInterfaceDescriptor() const {              \
-        return I##INTERFACE::descriptor;                                \
-    }                                                                   \
-    ::android::sp<I##INTERFACE> I##INTERFACE::asInterface(              \
-            const ::android::sp<::android::IBinder>& obj)               \
-    {                                                                   \
-        ::android::sp<I##INTERFACE> intr;                               \
-        if (obj != nullptr) {                                           \
-            intr = ::android::sp<I##INTERFACE>::cast(                   \
-                obj->queryLocalInterface(I##INTERFACE::descriptor));    \
-            if (intr == nullptr) {                                      \
-                intr = ::android::sp<Bp##INTERFACE>::make(obj);         \
-            }                                                           \
-        }                                                               \
-        return intr;                                                    \
-    }                                                                   \
-    std::unique_ptr<I##INTERFACE> I##INTERFACE::default_impl;           \
-    bool I##INTERFACE::setDefaultImpl(std::unique_ptr<I##INTERFACE> impl)\
-    {                                                                   \
-        /* Only one user of this interface can use this function     */ \
-        /* at a time. This is a heuristic to detect if two different */ \
-        /* users in the same process use this function.              */ \
-        assert(!I##INTERFACE::default_impl);                            \
-        if (impl) {                                                     \
-            I##INTERFACE::default_impl = std::move(impl);               \
-            return true;                                                \
-        }                                                               \
-        return false;                                                   \
-    }                                                                   \
-    const std::unique_ptr<I##INTERFACE>& I##INTERFACE::getDefaultImpl() \
-    {                                                                   \
-        return I##INTERFACE::default_impl;                              \
-    }                                                                   \
-    I##INTERFACE::I##INTERFACE() { }                                    \
-    I##INTERFACE::~I##INTERFACE() { }                                   \
+// Macro to be used by both IMPLEMENT_META_INTERFACE and IMPLEMENT_META_NESTED_INTERFACE
+#define DO_NOT_DIRECTLY_USE_ME_IMPLEMENT_META_INTERFACE0(ITYPE, INAME, BPTYPE)                     \
+    const ::android::String16& ITYPE::getInterfaceDescriptor() const { return ITYPE::descriptor; } \
+    ::android::sp<ITYPE> ITYPE::asInterface(const ::android::sp<::android::IBinder>& obj) {        \
+        ::android::sp<ITYPE> intr;                                                                 \
+        if (obj != nullptr) {                                                                      \
+            intr = ::android::sp<ITYPE>::cast(obj->queryLocalInterface(ITYPE::descriptor));        \
+            if (intr == nullptr) {                                                                 \
+                intr = ::android::sp<BPTYPE>::make(obj);                                           \
+            }                                                                                      \
+        }                                                                                          \
+        return intr;                                                                               \
+    }                                                                                              \
+    std::unique_ptr<ITYPE> ITYPE::default_impl;                                                    \
+    bool ITYPE::setDefaultImpl(std::unique_ptr<ITYPE> impl) {                                      \
+        /* Only one user of this interface can use this function     */                            \
+        /* at a time. This is a heuristic to detect if two different */                            \
+        /* users in the same process use this function.              */                            \
+        assert(!ITYPE::default_impl);                                                              \
+        if (impl) {                                                                                \
+            ITYPE::default_impl = std::move(impl);                                                 \
+            return true;                                                                           \
+        }                                                                                          \
+        return false;                                                                              \
+    }                                                                                              \
+    const std::unique_ptr<ITYPE>& ITYPE::getDefaultImpl() { return ITYPE::default_impl; }          \
+    ITYPE::INAME() {}                                                                              \
+    ITYPE::~INAME() {}
 
+// Macro for an interface type.
+#define DO_NOT_DIRECTLY_USE_ME_IMPLEMENT_META_INTERFACE(INTERFACE, NAME)                        \
+    const ::android::StaticString16 I##INTERFACE##_descriptor_static_str16(                     \
+            __IINTF_CONCAT(u, NAME));                                                           \
+    const ::android::String16 I##INTERFACE::descriptor(I##INTERFACE##_descriptor_static_str16); \
+    DO_NOT_DIRECTLY_USE_ME_IMPLEMENT_META_INTERFACE0(I##INTERFACE, I##INTERFACE, Bp##INTERFACE)
+
+// Macro for "nested" interface type.
+// For example,
+//   class Parent .. { class INested .. { }; };
+// DO_NOT_DIRECTLY_USE_ME_IMPLEMENT_META_NESTED_INTERFACE(Parent, Nested, "Parent.INested")
+#define DO_NOT_DIRECTLY_USE_ME_IMPLEMENT_META_NESTED_INTERFACE(PARENT, INTERFACE, NAME)  \
+    const ::android::String16 PARENT::I##INTERFACE::descriptor(NAME);                    \
+    DO_NOT_DIRECTLY_USE_ME_IMPLEMENT_META_INTERFACE0(PARENT::I##INTERFACE, I##INTERFACE, \
+                                                     PARENT::Bp##INTERFACE)
 
 #define CHECK_INTERFACE(interface, data, reply)                         \
     do {                                                                \
diff --git a/libs/binder/include/binder/Parcel.h b/libs/binder/include/binder/Parcel.h
index d90e803..8fb4a37 100644
--- a/libs/binder/include/binder/Parcel.h
+++ b/libs/binder/include/binder/Parcel.h
@@ -81,6 +81,8 @@
                                    size_t start, size_t len);
 
     int                 compareData(const Parcel& other);
+    status_t compareDataInRange(size_t thisOffset, const Parcel& other, size_t otherOffset,
+                                size_t length, int* result) const;
 
     bool                allowFds() const;
     bool                pushAllowFds(bool allowFds);
diff --git a/libs/binder/ndk/ibinder.cpp b/libs/binder/ndk/ibinder.cpp
index 81aa551..8ffa735 100644
--- a/libs/binder/ndk/ibinder.cpp
+++ b/libs/binder/ndk/ibinder.cpp
@@ -555,6 +555,10 @@
     return ::android::IPCThreadState::self()->getCallingPid();
 }
 
+bool AIBinder_isHandlingTransaction() {
+    return ::android::IPCThreadState::self()->getServingStackPointer() != nullptr;
+}
+
 void AIBinder_incStrong(AIBinder* binder) {
     if (binder == nullptr) {
         return;
diff --git a/libs/binder/ndk/include_ndk/android/binder_ibinder.h b/libs/binder/ndk/include_ndk/android/binder_ibinder.h
index 43533c5..565542b 100644
--- a/libs/binder/ndk/include_ndk/android/binder_ibinder.h
+++ b/libs/binder/ndk/include_ndk/android/binder_ibinder.h
@@ -393,6 +393,14 @@
 pid_t AIBinder_getCallingPid() __INTRODUCED_IN(29);
 
 /**
+ * Determine whether the current thread is currently executing an incoming transaction.
+ *
+ * \return true if the current thread is currently executing an incoming transaction, and false
+ * otherwise.
+ */
+bool AIBinder_isHandlingTransaction() __INTRODUCED_IN(33);
+
+/**
  * This can only be called if a strong reference to this object already exists in process.
  *
  * Available since API level 29.
diff --git a/libs/binder/ndk/libbinder_ndk.map.txt b/libs/binder/ndk/libbinder_ndk.map.txt
index 64170af..d63a8d0 100644
--- a/libs/binder/ndk/libbinder_ndk.map.txt
+++ b/libs/binder/ndk/libbinder_ndk.map.txt
@@ -145,6 +145,7 @@
   global:
     AIBinder_Class_disableInterfaceTokenHeader;
     AIBinder_DeathRecipient_setOnUnlinked;
+    AIBinder_isHandlingTransaction;
     AIBinder_setMinSchedulerPolicy; # llndk
     AParcel_marshal;
     AParcel_unmarshal;
diff --git a/libs/binder/rust/Android.bp b/libs/binder/rust/Android.bp
index ecb044e..d323022 100644
--- a/libs/binder/rust/Android.bp
+++ b/libs/binder/rust/Android.bp
@@ -33,6 +33,27 @@
 }
 
 rust_library {
+    name: "libbinder_tokio_rs",
+    crate_name: "binder_tokio",
+    srcs: ["binder_tokio/lib.rs"],
+    rustlibs: [
+        "libbinder_rs",
+        "libtokio",
+    ],
+    host_supported: true,
+    target: {
+        darwin: {
+            enabled: false,
+        }
+    },
+    apex_available: [
+        "//apex_available:platform",
+        "com.android.compos",
+        "com.android.virt",
+    ],
+}
+
+rust_library {
     name: "libbinder_ndk_sys",
     crate_name: "binder_ndk_sys",
     srcs: [
diff --git a/libs/binder/rust/binder_tokio/lib.rs b/libs/binder/rust/binder_tokio/lib.rs
new file mode 100644
index 0000000..64833b6
--- /dev/null
+++ b/libs/binder/rust/binder_tokio/lib.rs
@@ -0,0 +1,103 @@
+/*
+ * 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.
+ */
+
+//! This crate lets you use the Tokio `spawn_blocking` pool with AIDL in async
+//! Rust code.
+//!
+//! This crate works by defining a type [`Tokio`], which you can use as the
+//! generic parameter in the async version of the trait generated by the AIDL
+//! compiler.
+//! ```text
+//! use binder_tokio::Tokio;
+//!
+//! binder::get_interface::<dyn SomeAsyncInterface<Tokio>>("...").
+//! ```
+//!
+//! [`Tokio`]: crate::Tokio
+
+use binder::public_api::{BinderAsyncPool, BoxFuture, Strong};
+use binder::{FromIBinder, StatusCode};
+use std::future::Future;
+
+/// Retrieve an existing service for a particular interface, sleeping for a few
+/// seconds if it doesn't yet exist.
+pub async fn get_interface<T: FromIBinder + ?Sized + 'static>(name: &str) -> Result<Strong<T>, StatusCode> {
+    let name = name.to_string();
+    let res = tokio::task::spawn_blocking(move || {
+        binder::public_api::get_interface::<T>(&name)
+    }).await;
+
+    // The `is_panic` branch is not actually reachable in Android as we compile
+    // with `panic = abort`.
+    match res {
+        Ok(Ok(service)) => Ok(service),
+        Ok(Err(err)) => Err(err),
+        Err(e) if e.is_panic() => std::panic::resume_unwind(e.into_panic()),
+        Err(e) if e.is_cancelled() => Err(StatusCode::FAILED_TRANSACTION),
+        Err(_) => Err(StatusCode::UNKNOWN_ERROR),
+    }
+}
+
+/// Retrieve an existing service for a particular interface, or start it if it
+/// is configured as a dynamic service and isn't yet started.
+pub async fn wait_for_interface<T: FromIBinder + ?Sized + 'static>(name: &str) -> Result<Strong<T>, StatusCode> {
+    let name = name.to_string();
+    let res = tokio::task::spawn_blocking(move || {
+        binder::public_api::wait_for_interface::<T>(&name)
+    }).await;
+
+    // The `is_panic` branch is not actually reachable in Android as we compile
+    // with `panic = abort`.
+    match res {
+        Ok(Ok(service)) => Ok(service),
+        Ok(Err(err)) => Err(err),
+        Err(e) if e.is_panic() => std::panic::resume_unwind(e.into_panic()),
+        Err(e) if e.is_cancelled() => Err(StatusCode::FAILED_TRANSACTION),
+        Err(_) => Err(StatusCode::UNKNOWN_ERROR),
+    }
+}
+
+/// Use the Tokio `spawn_blocking` pool with AIDL.
+pub enum Tokio {}
+
+impl BinderAsyncPool for Tokio {
+    fn spawn<'a, F1, F2, Fut, A, B, E>(spawn_me: F1, after_spawn: F2) -> BoxFuture<'a, Result<B, E>>
+    where
+        F1: FnOnce() -> A,
+        F2: FnOnce(A) -> Fut,
+        Fut: Future<Output = Result<B, E>>,
+        F1: Send + 'static,
+        F2: Send + 'a,
+        Fut: Send + 'a,
+        A: Send + 'static,
+        B: Send + 'a,
+        E: From<crate::StatusCode>,
+    {
+        let handle = tokio::task::spawn_blocking(spawn_me);
+        Box::pin(async move {
+            // The `is_panic` branch is not actually reachable in Android as we compile
+            // with `panic = abort`.
+            match handle.await {
+                Ok(res) => after_spawn(res).await,
+                Err(e) if e.is_panic() => std::panic::resume_unwind(e.into_panic()),
+                Err(e) if e.is_cancelled() => Err(StatusCode::FAILED_TRANSACTION.into()),
+                Err(_) => Err(StatusCode::UNKNOWN_ERROR.into()),
+            }
+        })
+    }
+}
+
+
diff --git a/libs/binder/rust/src/binder.rs b/libs/binder/rust/src/binder.rs
index cc5dd06..4e048d7 100644
--- a/libs/binder/rust/src/binder.rs
+++ b/libs/binder/rust/src/binder.rs
@@ -713,12 +713,14 @@
         $interface:path[$descriptor:expr] {
             native: $native:ident($on_transact:path),
             proxy: $proxy:ident,
+            $(async: $async_interface:ident,)?
         }
     } => {
         $crate::declare_binder_interface! {
             $interface[$descriptor] {
                 native: $native($on_transact),
                 proxy: $proxy {},
+                $(async: $async_interface,)?
                 stability: $crate::Stability::default(),
             }
         }
@@ -728,6 +730,7 @@
         $interface:path[$descriptor:expr] {
             native: $native:ident($on_transact:path),
             proxy: $proxy:ident,
+            $(async: $async_interface:ident,)?
             stability: $stability:expr,
         }
     } => {
@@ -735,6 +738,7 @@
             $interface[$descriptor] {
                 native: $native($on_transact),
                 proxy: $proxy {},
+                $(async: $async_interface,)?
                 stability: $stability,
             }
         }
@@ -746,6 +750,7 @@
             proxy: $proxy:ident {
                 $($fname:ident: $fty:ty = $finit:expr),*
             },
+            $(async: $async_interface:ident,)?
         }
     } => {
         $crate::declare_binder_interface! {
@@ -754,6 +759,7 @@
                 proxy: $proxy {
                     $($fname: $fty = $finit),*
                 },
+                $(async: $async_interface,)?
                 stability: $crate::Stability::default(),
             }
         }
@@ -765,6 +771,7 @@
             proxy: $proxy:ident {
                 $($fname:ident: $fty:ty = $finit:expr),*
             },
+            $(async: $async_interface:ident,)?
             stability: $stability:expr,
         }
     } => {
@@ -776,6 +783,7 @@
                 proxy: $proxy {
                     $($fname: $fty = $finit),*
                 },
+                $(async: $async_interface,)?
                 stability: $stability,
             }
         }
@@ -791,6 +799,8 @@
                 $($fname:ident: $fty:ty = $finit:expr),*
             },
 
+            $( async: $async_interface:ident, )?
+
             stability: $stability:expr,
         }
     } => {
@@ -924,7 +934,7 @@
             }
         }
 
-        impl std::fmt::Debug for dyn $interface {
+        impl std::fmt::Debug for dyn $interface + '_ {
             fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
                 f.pad(stringify!($interface))
             }
@@ -938,6 +948,73 @@
                     .expect(concat!("Error cloning interface ", stringify!($interface)))
             }
         }
+
+        $(
+        // Async interface trait implementations.
+        impl<P: $crate::BinderAsyncPool> $crate::FromIBinder for dyn $async_interface<P> {
+            fn try_from(mut ibinder: $crate::SpIBinder) -> $crate::Result<$crate::Strong<dyn $async_interface<P>>> {
+                use $crate::AssociateClass;
+
+                let existing_class = ibinder.get_class();
+                if let Some(class) = existing_class {
+                    if class != <$native as $crate::Remotable>::get_class() &&
+                        class.get_descriptor() == <$native as $crate::Remotable>::get_descriptor()
+                    {
+                        // The binder object's descriptor string matches what we
+                        // expect. We still need to treat this local or already
+                        // associated object as remote, because we can't cast it
+                        // into a Rust service object without a matching class
+                        // pointer.
+                        return Ok($crate::Strong::new(Box::new(<$proxy as $crate::Proxy>::from_binder(ibinder)?)));
+                    }
+                }
+
+                if ibinder.associate_class(<$native as $crate::Remotable>::get_class()) {
+                    let service: $crate::Result<$crate::Binder<$native>> =
+                        std::convert::TryFrom::try_from(ibinder.clone());
+                    if let Ok(service) = service {
+                        // We were able to associate with our expected class and
+                        // the service is local.
+                        todo!()
+                        //return Ok($crate::Strong::new(Box::new(service)));
+                    } else {
+                        // Service is remote
+                        return Ok($crate::Strong::new(Box::new(<$proxy as $crate::Proxy>::from_binder(ibinder)?)));
+                    }
+                }
+
+                Err($crate::StatusCode::BAD_TYPE.into())
+            }
+        }
+
+        impl<P: $crate::BinderAsyncPool> $crate::parcel::Serialize for dyn $async_interface<P> + '_ {
+            fn serialize(&self, parcel: &mut $crate::parcel::Parcel) -> $crate::Result<()> {
+                let binder = $crate::Interface::as_binder(self);
+                parcel.write(&binder)
+            }
+        }
+
+        impl<P: $crate::BinderAsyncPool> $crate::parcel::SerializeOption for dyn $async_interface<P> + '_ {
+            fn serialize_option(this: Option<&Self>, parcel: &mut $crate::parcel::Parcel) -> $crate::Result<()> {
+                parcel.write(&this.map($crate::Interface::as_binder))
+            }
+        }
+
+        impl<P: $crate::BinderAsyncPool> std::fmt::Debug for dyn $async_interface<P> + '_ {
+            fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+                f.pad(stringify!($async_interface))
+            }
+        }
+
+        /// Convert a &dyn $async_interface to Strong<dyn $async_interface>
+        impl<P: $crate::BinderAsyncPool> std::borrow::ToOwned for dyn $async_interface<P> {
+            type Owned = $crate::Strong<dyn $async_interface<P>>;
+            fn to_owned(&self) -> Self::Owned {
+                self.as_binder().into_interface()
+                    .expect(concat!("Error cloning interface ", stringify!($async_interface)))
+            }
+        }
+        )?
     };
 }
 
diff --git a/libs/binder/rust/src/binder_async.rs b/libs/binder/rust/src/binder_async.rs
new file mode 100644
index 0000000..214c0b5
--- /dev/null
+++ b/libs/binder/rust/src/binder_async.rs
@@ -0,0 +1,55 @@
+/*
+ * 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.
+ */
+
+use std::future::Future;
+use std::pin::Pin;
+
+/// A type alias for a pinned, boxed future that lets you write shorter code without littering it
+/// with Pin and Send bounds.
+pub type BoxFuture<'a, T> = Pin<Box<dyn Future<Output = T> + Send + 'a>>;
+
+/// A thread pool for running binder transactions.
+pub trait BinderAsyncPool {
+    /// This function should conceptually behave like this:
+    ///
+    /// ```text
+    /// let result = spawn_thread(|| spawn_me()).await;
+    /// return after_spawn(result).await;
+    /// ```
+    ///
+    /// If the spawning fails for some reason, the method may also skip the `after_spawn` closure
+    /// and immediately return an error.
+    ///
+    /// The only difference between different implementations should be which
+    /// `spawn_thread` method is used. For Tokio, it would be `tokio::task::spawn_blocking`.
+    ///
+    /// This method has the design it has because the only way to define a trait that
+    /// allows the return type of the spawn to be chosen by the caller is to return a
+    /// boxed `Future` trait object, and including `after_spawn` in the trait function
+    /// allows the caller to avoid double-boxing if they want to do anything to the value
+    /// returned from the spawned thread.
+    fn spawn<'a, F1, F2, Fut, A, B, E>(spawn_me: F1, after_spawn: F2) -> BoxFuture<'a, Result<B, E>>
+    where
+        F1: FnOnce() -> A,
+        F2: FnOnce(A) -> Fut,
+        Fut: Future<Output = Result<B, E>>,
+        F1: Send + 'static,
+        F2: Send + 'a,
+        Fut: Send + 'a,
+        A: Send + 'static,
+        B: Send + 'a,
+        E: From<crate::StatusCode>;
+}
diff --git a/libs/binder/rust/src/lib.rs b/libs/binder/rust/src/lib.rs
index 81b620e..2ac2d2f 100644
--- a/libs/binder/rust/src/lib.rs
+++ b/libs/binder/rust/src/lib.rs
@@ -98,6 +98,7 @@
 
 #[macro_use]
 mod binder;
+mod binder_async;
 mod error;
 mod native;
 mod state;
@@ -111,6 +112,7 @@
     Stability, Strong, TransactionCode, TransactionFlags, Weak, FIRST_CALL_TRANSACTION,
     FLAG_CLEAR_BUF, FLAG_ONEWAY, FLAG_PRIVATE_LOCAL, LAST_CALL_TRANSACTION,
 };
+pub use crate::binder_async::{BoxFuture, BinderAsyncPool};
 pub use error::{status_t, ExceptionCode, Result, Status, StatusCode};
 pub use native::{add_service, force_lazy_services_persist, register_lazy_service, Binder};
 pub use parcel::{OwnedParcel, Parcel};
@@ -133,8 +135,9 @@
         wait_for_interface,
     };
     pub use super::{
-        BinderFeatures, DeathRecipient, ExceptionCode, IBinder, Interface, ProcessState, SpIBinder,
-        Status, StatusCode, Strong, ThreadState, Weak, WpIBinder,
+        BinderAsyncPool, BinderFeatures, BoxFuture, DeathRecipient, ExceptionCode, IBinder,
+        Interface, ProcessState, SpIBinder, Status, StatusCode, Strong, ThreadState, Weak,
+        WpIBinder,
     };
 
     /// Binder result containing a [`Status`] on error.
diff --git a/libs/binder/rust/src/parcel.rs b/libs/binder/rust/src/parcel.rs
index 9dba950..a0e1478 100644
--- a/libs/binder/rust/src/parcel.rs
+++ b/libs/binder/rust/src/parcel.rs
@@ -83,6 +83,19 @@
         Self { ptr }
     }
 
+    /// Convert the provided parcel to an owned parcel, or return `None` if it
+    /// is borrowed.
+    pub fn try_from(parcel: Parcel) -> Option<OwnedParcel> {
+        match &parcel {
+            Parcel::Owned(ptr) => {
+                let ptr = *ptr;
+                std::mem::forget(parcel);
+                Some(OwnedParcel { ptr })
+            }
+            Parcel::Borrowed(_) => None,
+        }
+    }
+
     /// Create an owned reference to a parcel object from a raw pointer.
     ///
     /// # Safety
diff --git a/libs/binder/rust/src/state.rs b/libs/binder/rust/src/state.rs
index 0e05f10..0aef744 100644
--- a/libs/binder/rust/src/state.rs
+++ b/libs/binder/rust/src/state.rs
@@ -99,6 +99,17 @@
         }
     }
 
+    /// Determine whether the current thread is currently executing an incoming transaction.
+    ///
+    /// \return true if the current thread is currently executing an incoming transaction, and false
+    /// otherwise.
+    pub fn is_handling_transaction() -> bool {
+        unsafe {
+            // Safety: Safe FFI
+            sys::AIBinder_isHandlingTransaction()
+        }
+    }
+
     /// This function makes the client's security context available to the
     /// service calling this function. This can be used for access control.
     /// It does not suffer from the TOCTOU issues of get_calling_pid.
diff --git a/libs/binder/rust/tests/Android.bp b/libs/binder/rust/tests/Android.bp
index ecc61f4..2d1175b 100644
--- a/libs/binder/rust/tests/Android.bp
+++ b/libs/binder/rust/tests/Android.bp
@@ -13,6 +13,8 @@
     rustlibs: [
         "libbinder_rs",
         "libselinux_bindgen",
+        "libbinder_tokio_rs",
+        "libtokio",
     ],
     shared_libs: [
         "libselinux",
diff --git a/libs/binder/rust/tests/integration.rs b/libs/binder/rust/tests/integration.rs
index 335e8d8..ebfe879 100644
--- a/libs/binder/rust/tests/integration.rs
+++ b/libs/binder/rust/tests/integration.rs
@@ -17,7 +17,7 @@
 //! Rust Binder crate integration tests
 
 use binder::declare_binder_interface;
-use binder::parcel::Parcel;
+use binder::parcel::{Parcel, OwnedParcel};
 use binder::{
     Binder, BinderFeatures, IBinderInternal, Interface, StatusCode, ThreadState, TransactionCode,
     FIRST_CALL_TRANSACTION,
@@ -154,12 +154,25 @@
     fn get_selinux_context(&self) -> binder::Result<String>;
 }
 
+/// Async trivial testing binder interface
+pub trait IATest<P>: Interface {
+    /// Returns a test string
+    fn test(&self) -> binder::BoxFuture<'static, binder::Result<String>>;
+
+    /// Return the arguments sent via dump
+    fn get_dump_args(&self) -> binder::BoxFuture<'static, binder::Result<Vec<String>>>;
+
+    /// Returns the caller's SELinux context
+    fn get_selinux_context(&self) -> binder::BoxFuture<'static, binder::Result<String>>;
+}
+
 declare_binder_interface! {
     ITest["android.os.ITest"] {
         native: BnTest(on_transact),
         proxy: BpTest {
             x: i32 = 100
         },
+        async: IATest,
     }
 }
 
@@ -201,6 +214,32 @@
     }
 }
 
+impl<P: binder::BinderAsyncPool> IATest<P> for BpTest {
+    fn test(&self) -> binder::BoxFuture<'static, binder::Result<String>> {
+        let binder = self.binder.clone();
+        P::spawn(
+            move || binder.transact(TestTransactionCode::Test as TransactionCode, 0, |_| Ok(())).map(|p| OwnedParcel::try_from(p).unwrap()),
+            |reply| async move { reply?.into_parcel().read() }
+        )
+    }
+
+    fn get_dump_args(&self) -> binder::BoxFuture<'static, binder::Result<Vec<String>>> {
+        let binder = self.binder.clone();
+        P::spawn(
+            move || binder.transact(TestTransactionCode::GetDumpArgs as TransactionCode, 0, |_| Ok(())).map(|p| OwnedParcel::try_from(p).unwrap()),
+            |reply| async move { reply?.into_parcel().read() }
+        )
+    }
+
+    fn get_selinux_context(&self) -> binder::BoxFuture<'static, binder::Result<String>> {
+        let binder = self.binder.clone();
+        P::spawn(
+            move || binder.transact(TestTransactionCode::GetSelinuxContext as TransactionCode, 0, |_| Ok(())).map(|p| OwnedParcel::try_from(p).unwrap()),
+            |reply| async move { reply?.into_parcel().read() }
+        )
+    }
+}
+
 impl ITest for Binder<BnTest> {
     fn test(&self) -> binder::Result<String> {
         self.0.test()
@@ -215,6 +254,23 @@
     }
 }
 
+impl<P: binder::BinderAsyncPool> IATest<P> for Binder<BnTest> {
+    fn test(&self) -> binder::BoxFuture<'static, binder::Result<String>> {
+        let res = self.0.test();
+        Box::pin(async move { res })
+    }
+
+    fn get_dump_args(&self) -> binder::BoxFuture<'static, binder::Result<Vec<String>>> {
+        let res = self.0.get_dump_args();
+        Box::pin(async move { res })
+    }
+
+    fn get_selinux_context(&self) -> binder::BoxFuture<'static, binder::Result<String>> {
+        let res = self.0.get_selinux_context();
+        Box::pin(async move { res })
+    }
+}
+
 /// Trivial testing binder interface
 pub trait ITestSameDescriptor: Interface {}
 
@@ -255,7 +311,9 @@
         SpIBinder, StatusCode, Strong,
     };
 
-    use super::{BnTest, ITest, ITestSameDescriptor, TestService, RUST_SERVICE_BINARY};
+    use binder_tokio::Tokio;
+
+    use super::{BnTest, ITest, IATest, ITestSameDescriptor, TestService, RUST_SERVICE_BINARY};
 
     pub struct ScopedServiceProcess(Child);
 
@@ -303,12 +361,47 @@
             binder::get_interface::<dyn ITest>("this_service_does_not_exist").err(),
             Some(StatusCode::NAME_NOT_FOUND)
         );
+        assert_eq!(
+            binder::get_interface::<dyn IATest<Tokio>>("this_service_does_not_exist").err(),
+            Some(StatusCode::NAME_NOT_FOUND)
+        );
 
         // The service manager service isn't an ITest, so this must fail.
         assert_eq!(
             binder::get_interface::<dyn ITest>("manager").err(),
             Some(StatusCode::BAD_TYPE)
         );
+        assert_eq!(
+            binder::get_interface::<dyn IATest<Tokio>>("manager").err(),
+            Some(StatusCode::BAD_TYPE)
+        );
+    }
+
+    #[tokio::test]
+    async fn check_services_async() {
+        let mut sm = binder::get_service("manager").expect("Did not get manager binder service");
+        assert!(sm.is_binder_alive());
+        assert!(sm.ping_binder().is_ok());
+
+        assert!(binder::get_service("this_service_does_not_exist").is_none());
+        assert_eq!(
+            binder_tokio::get_interface::<dyn ITest>("this_service_does_not_exist").await.err(),
+            Some(StatusCode::NAME_NOT_FOUND)
+        );
+        assert_eq!(
+            binder_tokio::get_interface::<dyn IATest<Tokio>>("this_service_does_not_exist").await.err(),
+            Some(StatusCode::NAME_NOT_FOUND)
+        );
+
+        // The service manager service isn't an ITest, so this must fail.
+        assert_eq!(
+            binder_tokio::get_interface::<dyn ITest>("manager").await.err(),
+            Some(StatusCode::BAD_TYPE)
+        );
+        assert_eq!(
+            binder_tokio::get_interface::<dyn IATest<Tokio>>("manager").await.err(),
+            Some(StatusCode::BAD_TYPE)
+        );
     }
 
     #[test]
@@ -323,6 +416,10 @@
             binder::wait_for_interface::<dyn ITest>("manager").err(),
             Some(StatusCode::BAD_TYPE)
         );
+        assert_eq!(
+            binder::wait_for_interface::<dyn IATest<Tokio>>("manager").err(),
+            Some(StatusCode::BAD_TYPE)
+        );
     }
 
     #[test]
@@ -334,6 +431,15 @@
         assert_eq!(test_client.test().unwrap(), "trivial_client_test");
     }
 
+    #[tokio::test]
+    async fn trivial_client_async() {
+        let service_name = "trivial_client_test";
+        let _process = ScopedServiceProcess::new(service_name);
+        let test_client: Strong<dyn IATest<Tokio>> =
+            binder_tokio::get_interface(service_name).await.expect("Did not get manager binder service");
+        assert_eq!(test_client.test().await.unwrap(), "trivial_client_test");
+    }
+
     #[test]
     fn wait_for_trivial_client() {
         let service_name = "wait_for_trivial_client_test";
@@ -343,23 +449,47 @@
         assert_eq!(test_client.test().unwrap(), "wait_for_trivial_client_test");
     }
 
+    #[tokio::test]
+    async fn wait_for_trivial_client_async() {
+        let service_name = "wait_for_trivial_client_test";
+        let _process = ScopedServiceProcess::new(service_name);
+        let test_client: Strong<dyn IATest<Tokio>> =
+            binder_tokio::wait_for_interface(service_name).await.expect("Did not get manager binder service");
+        assert_eq!(test_client.test().await.unwrap(), "wait_for_trivial_client_test");
+    }
+
+    fn get_expected_selinux_context() -> &'static str {
+        unsafe {
+            let mut out_ptr = ptr::null_mut();
+            assert_eq!(selinux_sys::getcon(&mut out_ptr), 0);
+            assert!(!out_ptr.is_null());
+            CStr::from_ptr(out_ptr)
+                .to_str()
+                .expect("context was invalid UTF-8")
+        }
+    }
+
     #[test]
     fn get_selinux_context() {
         let service_name = "get_selinux_context";
         let _process = ScopedServiceProcess::new(service_name);
         let test_client: Strong<dyn ITest> =
             binder::get_interface(service_name).expect("Did not get manager binder service");
-        let expected_context = unsafe {
-            let mut out_ptr = ptr::null_mut();
-            assert_eq!(selinux_sys::getcon(&mut out_ptr), 0);
-            assert!(!out_ptr.is_null());
-            CStr::from_ptr(out_ptr)
-        };
         assert_eq!(
             test_client.get_selinux_context().unwrap(),
-            expected_context
-                .to_str()
-                .expect("context was invalid UTF-8"),
+            get_expected_selinux_context()
+        );
+    }
+
+    #[tokio::test]
+    async fn get_selinux_context_async() {
+        let service_name = "get_selinux_context";
+        let _process = ScopedServiceProcess::new(service_name);
+        let test_client: Strong<dyn IATest<Tokio>> =
+            binder_tokio::get_interface(service_name).await.expect("Did not get manager binder service");
+        assert_eq!(
+            test_client.get_selinux_context().await.unwrap(),
+            get_expected_selinux_context()
         );
     }
 
diff --git a/libs/binder/tests/parcel_fuzzer/binder.cpp b/libs/binder/tests/parcel_fuzzer/binder.cpp
index e4f57b0..155a25b 100644
--- a/libs/binder/tests/parcel_fuzzer/binder.cpp
+++ b/libs/binder/tests/parcel_fuzzer/binder.cpp
@@ -308,6 +308,15 @@
         status_t status = p.hasFileDescriptorsInRange(offset, length, &result);
         FUZZ_LOG() << " status: " << status  << " result: " << result;
     },
+    [] (const ::android::Parcel& p, uint8_t /* data */) {
+        FUZZ_LOG() << "about to call compareDataInRange() with status";
+        size_t thisOffset = p.readUint32();
+        size_t otherOffset = p.readUint32();
+        size_t length = p.readUint32();
+        int result;
+        status_t status = p.compareDataInRange(thisOffset, p, otherOffset, length, &result);
+        FUZZ_LOG() << " status: " << status  << " result: " << result;
+    },
 };
 // clang-format on
 #pragma clang diagnostic pop
diff --git a/libs/gui/GLConsumer.cpp b/libs/gui/GLConsumer.cpp
index 30d19e3..b3647d6 100644
--- a/libs/gui/GLConsumer.cpp
+++ b/libs/gui/GLConsumer.cpp
@@ -301,7 +301,7 @@
         // continues to use it.
         sp<GraphicBuffer> buffer = new GraphicBuffer(
                 kDebugData.width, kDebugData.height, PIXEL_FORMAT_RGBA_8888,
-                GraphicBuffer::USAGE_SW_WRITE_RARELY,
+                DEFAULT_USAGE_FLAGS | GraphicBuffer::USAGE_SW_WRITE_RARELY,
                 "[GLConsumer debug texture]");
         uint32_t* bits;
         buffer->lock(GraphicBuffer::USAGE_SW_WRITE_RARELY, reinterpret_cast<void**>(&bits));
diff --git a/libs/nativedisplay/surfacetexture/EGLConsumer.cpp b/libs/nativedisplay/surfacetexture/EGLConsumer.cpp
index 2f31888..6882ea3 100644
--- a/libs/nativedisplay/surfacetexture/EGLConsumer.cpp
+++ b/libs/nativedisplay/surfacetexture/EGLConsumer.cpp
@@ -191,7 +191,7 @@
         // continues to use it.
         sp<GraphicBuffer> buffer =
                 new GraphicBuffer(kDebugData.width, kDebugData.height, PIXEL_FORMAT_RGBA_8888,
-                                  GraphicBuffer::USAGE_SW_WRITE_RARELY,
+                                  DEFAULT_USAGE_FLAGS | GraphicBuffer::USAGE_SW_WRITE_RARELY,
                                   "[EGLConsumer debug texture]");
         uint32_t* bits;
         buffer->lock(GraphicBuffer::USAGE_SW_WRITE_RARELY, reinterpret_cast<void**>(&bits));