Merge changes from topic "more-ndk-binder" am: 72021ee221
am: 59915bd741

Change-Id: I958306416861a8031842c3979ae994020212a731
diff --git a/libs/binder/ndk/include_ndk/android/binder_parcel.h b/libs/binder/ndk/include_ndk/android/binder_parcel.h
index b021c23..3594349 100644
--- a/libs/binder/ndk/include_ndk/android/binder_parcel.h
+++ b/libs/binder/ndk/include_ndk/android/binder_parcel.h
@@ -347,7 +347,7 @@
  * This corresponds to the SDK's android.os.ParcelFileDescriptor.
  *
  * \param parcel the parcel to write to.
- * \param fd the value to write to the parcel.
+ * \param fd the value to write to the parcel (-1 to represent a null ParcelFileDescriptor).
  *
  * \return STATUS_OK on successful write.
  */
@@ -361,7 +361,8 @@
  * This corresponds to the SDK's android.os.ParcelFileDescriptor.
  *
  * \param parcel the parcel to read from.
- * \param binder the out parameter for what is read from the parcel.
+ * \param fd the out parameter for what is read from the parcel (or -1 to represent a null
+ * ParcelFileDescriptor)
  *
  * \return STATUS_OK on successful write.
  */
diff --git a/libs/binder/ndk/include_ndk/android/binder_parcel_utils.h b/libs/binder/ndk/include_ndk/android/binder_parcel_utils.h
index a478ee0..f99c3a9 100644
--- a/libs/binder/ndk/include_ndk/android/binder_parcel_utils.h
+++ b/libs/binder/ndk/include_ndk/android/binder_parcel_utils.h
@@ -26,6 +26,7 @@
 
 #pragma once
 
+#include <android/binder_auto_utils.h>
 #include <android/binder_parcel.h>
 
 #include <optional>
@@ -152,28 +153,103 @@
 }
 
 /**
+ * Convenience method to write a nullable strong binder.
+ */
+static inline binder_status_t AParcel_writeNullableStrongBinder(AParcel* parcel,
+                                                                const SpAIBinder& binder) {
+    return AParcel_writeStrongBinder(parcel, binder.get());
+}
+
+/**
+ * Convenience method to read a nullable strong binder.
+ */
+static inline binder_status_t AParcel_readNullableStrongBinder(const AParcel* parcel,
+                                                               SpAIBinder* binder) {
+    AIBinder* readBinder;
+    binder_status_t status = AParcel_readStrongBinder(parcel, &readBinder);
+    if (status == STATUS_OK) {
+        binder->set(readBinder);
+    }
+    return status;
+}
+
+/**
  * Convenience method to write a strong binder but return an error if it is null.
  */
-static inline binder_status_t AParcel_writeRequiredStrongBinder(AParcel* parcel, AIBinder* binder) {
-    if (binder == nullptr) {
+static inline binder_status_t AParcel_writeRequiredStrongBinder(AParcel* parcel,
+                                                                const SpAIBinder& binder) {
+    if (binder.get() == nullptr) {
         return STATUS_UNEXPECTED_NULL;
     }
-    return AParcel_writeStrongBinder(parcel, binder);
+    return AParcel_writeStrongBinder(parcel, binder.get());
 }
 
 /**
  * Convenience method to read a strong binder but return an error if it is null.
  */
 static inline binder_status_t AParcel_readRequiredStrongBinder(const AParcel* parcel,
-                                                               AIBinder** binder) {
-    binder_status_t ret = AParcel_readStrongBinder(parcel, binder);
-    if (ret == STATUS_OK && *binder == nullptr) {
-        return STATUS_UNEXPECTED_NULL;
+                                                               SpAIBinder* binder) {
+    AIBinder* readBinder;
+    binder_status_t ret = AParcel_readStrongBinder(parcel, &readBinder);
+    if (ret == STATUS_OK) {
+        if (readBinder == nullptr) {
+            return STATUS_UNEXPECTED_NULL;
+        }
+
+        binder->set(readBinder);
     }
     return ret;
 }
 
 /**
+ * Convenience method to write a ParcelFileDescriptor where -1 represents a null value.
+ */
+static inline binder_status_t AParcel_writeNullableParcelFileDescriptor(
+        AParcel* parcel, const ScopedFileDescriptor& fd) {
+    return AParcel_writeParcelFileDescriptor(parcel, fd.get());
+}
+
+/**
+ * Convenience method to read a ParcelFileDescriptor where -1 represents a null value.
+ */
+static inline binder_status_t AParcel_readNullableParcelFileDescriptor(const AParcel* parcel,
+                                                                       ScopedFileDescriptor* fd) {
+    int readFd;
+    binder_status_t status = AParcel_readParcelFileDescriptor(parcel, &readFd);
+    if (status == STATUS_OK) {
+        fd->set(readFd);
+    }
+    return status;
+}
+
+/**
+ * Convenience method to write a valid ParcelFileDescriptor.
+ */
+static inline binder_status_t AParcel_writeRequiredParcelFileDescriptor(
+        AParcel* parcel, const ScopedFileDescriptor& fd) {
+    if (fd.get() < 0) {
+        return STATUS_UNEXPECTED_NULL;
+    }
+    return AParcel_writeParcelFileDescriptor(parcel, fd.get());
+}
+
+/**
+ * Convenience method to read a valid ParcelFileDescriptor.
+ */
+static inline binder_status_t AParcel_readRequiredParcelFileDescriptor(const AParcel* parcel,
+                                                                       ScopedFileDescriptor* fd) {
+    int readFd;
+    binder_status_t status = AParcel_readParcelFileDescriptor(parcel, &readFd);
+    if (status == STATUS_OK) {
+        if (readFd < 0) {
+            return STATUS_UNEXPECTED_NULL;
+        }
+        fd->set(readFd);
+    }
+    return status;
+}
+
+/**
  * Allocates a std::string to length and returns the underlying buffer. For use with
  * AParcel_readString. See use below in AParcel_readString(const AParcel*, std::string*).
  */
diff --git a/libs/binder/ndk/parcel.cpp b/libs/binder/ndk/parcel.cpp
index b1a2955..3c32100 100644
--- a/libs/binder/ndk/parcel.cpp
+++ b/libs/binder/ndk/parcel.cpp
@@ -229,23 +229,39 @@
 }
 
 binder_status_t AParcel_writeParcelFileDescriptor(AParcel* parcel, int fd) {
-    ParcelFileDescriptor parcelFd((unique_fd(fd)));
+    std::unique_ptr<ParcelFileDescriptor> parcelFd;
 
-    status_t status = parcel->get()->writeParcelable(parcelFd);
+    if (fd < 0) {
+        if (fd != -1) {
+            return STATUS_UNKNOWN_ERROR;
+        }
+        // parcelFd = nullptr
+    } else {  // fd >= 0
+        parcelFd = std::make_unique<ParcelFileDescriptor>(unique_fd(fd));
+    }
+
+    status_t status = parcel->get()->writeNullableParcelable(parcelFd);
 
     // ownership is retained by caller
-    (void)parcelFd.release().release();
+    if (parcelFd != nullptr) {
+        (void)parcelFd->release().release();
+    }
 
     return PruneStatusT(status);
 }
 
 binder_status_t AParcel_readParcelFileDescriptor(const AParcel* parcel, int* fd) {
-    ParcelFileDescriptor parcelFd;
-    // status_t status = parcelFd.readFromParcel(parcel->get());
+    std::unique_ptr<ParcelFileDescriptor> parcelFd;
+
     status_t status = parcel->get()->readParcelable(&parcelFd);
     if (status != STATUS_OK) return PruneStatusT(status);
 
-    *fd = parcelFd.release().release();
+    if (parcelFd) {
+        *fd = parcelFd->release().release();
+    } else {
+        *fd = -1;
+    }
+
     return STATUS_OK;
 }