libbinder_ndk: set/getExtension

Similar to what is on IBinder. See comment on AIBinder_setExtension for
detailed information on usage.

This allows downstream codebases to tag on data to binders for their
extensions rather than having to modify the interface directly (which
breaks ABI compatibility and may cause more merge conflicts).

Bug: 136027762
Test: atest CtsNdkBinderTestCases
Change-Id: I2d1bb6cd906ff1974df8e81475d5fa8f569e9b6e
diff --git a/libs/binder/ndk/ibinder.cpp b/libs/binder/ndk/ibinder.cpp
index bd6886d..b06ca86 100644
--- a/libs/binder/ndk/ibinder.cpp
+++ b/libs/binder/ndk/ibinder.cpp
@@ -589,3 +589,40 @@
 
     recipient->decStrong(nullptr);
 }
+
+binder_status_t AIBinder_getExtension(AIBinder* binder, AIBinder** outExt) {
+    if (binder == nullptr || outExt == nullptr) {
+        if (outExt != nullptr) {
+            *outExt = nullptr;
+        }
+        return STATUS_UNEXPECTED_NULL;
+    }
+
+    sp<IBinder> ext;
+    status_t res = binder->getBinder()->getExtension(&ext);
+
+    if (res != android::OK) {
+        *outExt = nullptr;
+        return PruneStatusT(res);
+    }
+
+    sp<AIBinder> ret = ABpBinder::lookupOrCreateFromBinder(ext);
+    if (ret != nullptr) ret->incStrong(binder);
+
+    *outExt = ret.get();
+    return STATUS_OK;
+}
+
+binder_status_t AIBinder_setExtension(AIBinder* binder, AIBinder* ext) {
+    if (binder == nullptr || ext == nullptr) {
+        return STATUS_UNEXPECTED_NULL;
+    }
+
+    ABBinder* rawBinder = binder->asABBinder();
+    if (rawBinder == nullptr) {
+        return STATUS_INVALID_OPERATION;
+    }
+
+    rawBinder->setExtension(ext->getBinder());
+    return STATUS_OK;
+}