Merge "libbinder_ndk: fwd fuzzing status to NDK binders"
diff --git a/libs/binder/Parcel.cpp b/libs/binder/Parcel.cpp
index 2c2a1b6..9b685f9 100644
--- a/libs/binder/Parcel.cpp
+++ b/libs/binder/Parcel.cpp
@@ -992,6 +992,10 @@
     mServiceFuzzing = true;
 }
 
+bool Parcel::isServiceFuzzing() const {
+    return mServiceFuzzing;
+}
+
 binder::Status Parcel::enforceNoDataAvail() const {
     if (!mEnforceNoDataAvail) {
         return binder::Status::ok();
diff --git a/libs/binder/include/binder/Parcel.h b/libs/binder/include/binder/Parcel.h
index 15bb325..87b63e5 100644
--- a/libs/binder/include/binder/Parcel.h
+++ b/libs/binder/include/binder/Parcel.h
@@ -152,6 +152,7 @@
     // When fuzzing, we want to remove certain ABI checks that cause significant
     // lost coverage, and we also want to avoid logs that cost too much to write.
     void setServiceFuzzing();
+    bool isServiceFuzzing() const;
 
     void                freeData();
 
diff --git a/libs/binder/ndk/ibinder.cpp b/libs/binder/ndk/ibinder.cpp
index d0de7b9..f7dd9c9 100644
--- a/libs/binder/ndk/ibinder.cpp
+++ b/libs/binder/ndk/ibinder.cpp
@@ -137,7 +137,7 @@
     // since it's an error condition. Do the comparison after we take the lock and
     // check the pointer equality fast path. By always taking the lock, it's also
     // more flake-proof. However, the check is not dependent on the lock.
-    if (descriptor != newDescriptor) {
+    if (descriptor != newDescriptor && !(asABpBinder() && asABpBinder()->isServiceFuzzing())) {
         if (getBinder()->isBinderAlive()) {
             LOG(ERROR) << __func__ << ": Expecting binder to have class '" << newDescriptor
                        << "' but descriptor is actually '" << SanitizeString(descriptor) << "'.";
diff --git a/libs/binder/ndk/ibinder_internal.h b/libs/binder/ndk/ibinder_internal.h
index 67bb092..9d5368f 100644
--- a/libs/binder/ndk/ibinder_internal.h
+++ b/libs/binder/ndk/ibinder_internal.h
@@ -104,10 +104,14 @@
     ::android::sp<::android::IBinder> getBinder() override { return mRemote; }
     ABpBinder* asABpBinder() override { return this; }
 
+    bool isServiceFuzzing() const { return mServiceFuzzing; }
+    void setServiceFuzzing() { mServiceFuzzing = true; }
+
    private:
     friend android::sp<ABpBinder>;
     explicit ABpBinder(const ::android::sp<::android::IBinder>& binder);
     ::android::sp<::android::IBinder> mRemote;
+    bool mServiceFuzzing = false;
 };
 
 struct AIBinder_Class {
diff --git a/libs/binder/ndk/parcel.cpp b/libs/binder/ndk/parcel.cpp
index b5a2e2f..037aa2e 100644
--- a/libs/binder/ndk/parcel.cpp
+++ b/libs/binder/ndk/parcel.cpp
@@ -270,6 +270,13 @@
     }
     sp<AIBinder> ret = ABpBinder::lookupOrCreateFromBinder(readBinder);
     AIBinder_incStrong(ret.get());
+
+    if (ret.get() != nullptr && parcel->get()->isServiceFuzzing()) {
+        if (auto bp = ret->asABpBinder(); bp != nullptr) {
+            bp->setServiceFuzzing();
+        }
+    }
+
     *binder = ret.get();
     return PruneStatusT(status);
 }