Merge "libbinder_ndk: Add ScopedAResource release" am: 48165b9c32

Original change: https://android-review.googlesource.com/c/platform/frameworks/native/+/1948948

Change-Id: Ia958bdad8a4fa89b1ec4a47402062c87a1f5ea26
diff --git a/libs/binder/ndk/include_cpp/android/binder_auto_utils.h b/libs/binder/ndk/include_cpp/android/binder_auto_utils.h
index c903998..2c471c6 100644
--- a/libs/binder/ndk/include_cpp/android/binder_auto_utils.h
+++ b/libs/binder/ndk/include_cpp/android/binder_auto_utils.h
@@ -163,6 +163,15 @@
     const T get() const { return mT; }
 
     /**
+     * Release the underlying resource.
+     */
+    [[nodiscard]] T release() {
+        T a = mT;
+        mT = DEFAULT;
+        return a;
+    }
+
+    /**
      * This allows the value in this class to be set from beneath it. If you call this method and
      * then change the value of T*, you must take ownership of the value you are replacing and add
      * ownership to the object that is put in here.
diff --git a/libs/binder/ndk/tests/libbinder_ndk_unit_test.cpp b/libs/binder/ndk/tests/libbinder_ndk_unit_test.cpp
index 58fa13a..357b454 100644
--- a/libs/binder/ndk/tests/libbinder_ndk_unit_test.cpp
+++ b/libs/binder/ndk/tests/libbinder_ndk_unit_test.cpp
@@ -752,6 +752,29 @@
     ASSERT_STREQ(IFoo::kIFooDescriptor, AIBinder_Class_getDescriptor(IFoo::kClass));
 }
 
+static void addOne(int* to) {
+    if (!to) return;
+    ++(*to);
+}
+struct FakeResource : public ndk::impl::ScopedAResource<int*, addOne, nullptr> {
+    explicit FakeResource(int* a) : ScopedAResource(a) {}
+};
+
+TEST(NdkBinder_ScopedAResource, GetDelete) {
+    int deleteCount = 0;
+    { FakeResource resource(&deleteCount); }
+    EXPECT_EQ(deleteCount, 1);
+}
+
+TEST(NdkBinder_ScopedAResource, Release) {
+    int deleteCount = 0;
+    {
+        FakeResource resource(&deleteCount);
+        (void)resource.release();
+    }
+    EXPECT_EQ(deleteCount, 0);
+}
+
 int main(int argc, char* argv[]) {
     ::testing::InitGoogleTest(&argc, argv);