Merge "Add support for unique_fds and vectors of file descriptors" am: b1819fc295
am: 0dd1a5d2f4

* commit '0dd1a5d2f4e69c5df233fa9468191c03dc9b639f':
  Add support for unique_fds and vectors of file descriptors
diff --git a/include/binder/Parcel.h b/include/binder/Parcel.h
index 430c3ff..ed30239 100644
--- a/include/binder/Parcel.h
+++ b/include/binder/Parcel.h
@@ -19,6 +19,7 @@
 
 #include <vector>
 
+#include <base/unique_fd.h>
 #include <cutils/native_handle.h>
 #include <utils/Errors.h>
 #include <utils/RefBase.h>
@@ -149,6 +150,17 @@
     // will be closed once the parcel is destroyed.
     status_t            writeDupFileDescriptor(int fd);
 
+    // Place a file descriptor into the parcel.  This will not affect the
+    // semantics of the smart file descriptor. A new descriptor will be
+    // created, and will be closed when the parcel is destroyed.
+    status_t            writeUniqueFileDescriptor(
+                            const android::base::unique_fd& fd);
+
+    // Place a vector of file desciptors into the parcel. Each descriptor is
+    // dup'd as in writeDupFileDescriptor
+    status_t            writeUniqueFileDescriptorVector(
+                            const std::vector<android::base::unique_fd>& val);
+
     // Writes a blob to the parcel.
     // If the blob is small, then it is stored in-place, otherwise it is
     // transferred by way of an anonymous shared memory region.  Prefer sending
@@ -241,6 +253,15 @@
     // in the parcel, which you do not own -- use dup() to get your own copy.
     int                 readFileDescriptor() const;
 
+    // Retrieve a smart file descriptor from the parcel.
+    status_t            readUniqueFileDescriptor(
+                            android::base::unique_fd* val) const;
+
+
+    // Retrieve a vector of smart file descriptors from the parcel.
+    status_t            readUniqueFileDescriptorVector(
+                            std::vector<android::base::unique_fd>* val) const;
+
     // Reads a blob from the parcel.
     // The caller should call release() on the blob after reading its contents.
     status_t            readBlob(size_t len, ReadableBlob* outBlob) const;
diff --git a/libs/binder/Android.mk b/libs/binder/Android.mk
index bd11177..5e85afd 100644
--- a/libs/binder/Android.mk
+++ b/libs/binder/Android.mk
@@ -43,7 +43,7 @@
 
 include $(CLEAR_VARS)
 LOCAL_MODULE := libbinder
-LOCAL_SHARED_LIBRARIES := liblog libcutils libutils
+LOCAL_SHARED_LIBRARIES := liblog libcutils libutils libbase
 
 LOCAL_CLANG := true
 LOCAL_SANITIZE := integer
@@ -58,7 +58,7 @@
 
 include $(CLEAR_VARS)
 LOCAL_MODULE := libbinder
-LOCAL_STATIC_LIBRARIES += libutils
+LOCAL_STATIC_LIBRARIES += libutils libbase
 LOCAL_SRC_FILES := $(sources)
 ifneq ($(TARGET_USES_64_BIT_BINDER),true)
 ifneq ($(TARGET_IS_64_BIT),true)
diff --git a/libs/binder/Parcel.cpp b/libs/binder/Parcel.cpp
index 1b41eae..92b80e9 100644
--- a/libs/binder/Parcel.cpp
+++ b/libs/binder/Parcel.cpp
@@ -80,6 +80,8 @@
 
 namespace android {
 
+using android::base::unique_fd;
+
 static pthread_mutex_t gParcelGlobalAllocSizeLock = PTHREAD_MUTEX_INITIALIZER;
 static size_t gParcelGlobalAllocSize = 0;
 static size_t gParcelGlobalAllocCount = 0;
@@ -1073,12 +1075,20 @@
         return -errno;
     }
     status_t err = writeFileDescriptor(dupFd, true /*takeOwnership*/);
-    if (err) {
+    if (err != OK) {
         close(dupFd);
     }
     return err;
 }
 
+status_t Parcel::writeUniqueFileDescriptor(const unique_fd& fd) {
+    return writeDupFileDescriptor(fd.get());
+}
+
+status_t Parcel::writeUniqueFileDescriptorVector(const std::vector<unique_fd>& val) {
+    return writeTypedVector(val, this, &Parcel::writeUniqueFileDescriptor);
+}
+
 status_t Parcel::writeBlob(size_t len, bool mutableCopy, WritableBlob* outBlob)
 {
     if (len > INT32_MAX) {
@@ -1680,16 +1690,36 @@
 int Parcel::readFileDescriptor() const
 {
     const flat_binder_object* flat = readObject(true);
-    if (flat) {
-        switch (flat->type) {
-            case BINDER_TYPE_FD:
-                //ALOGI("Returning file descriptor %ld from parcel %p", flat->handle, this);
-                return flat->handle;
-        }
+
+    if (flat && flat->type == BINDER_TYPE_FD) {
+        return flat->handle;
     }
+
     return BAD_TYPE;
 }
 
+status_t Parcel::readUniqueFileDescriptor(unique_fd* val) const
+{
+    int got = readFileDescriptor();
+
+    if (got == BAD_TYPE) {
+        return BAD_TYPE;
+    }
+
+    val->reset(dup(got));
+
+    if (val->get() < 0) {
+        return BAD_VALUE;
+    }
+
+    return OK;
+}
+
+
+status_t Parcel::readUniqueFileDescriptorVector(std::vector<unique_fd>* val) const {
+    return readTypedVector(val, this, &Parcel::readUniqueFileDescriptor);
+}
+
 status_t Parcel::readBlob(size_t len, ReadableBlob* outBlob) const
 {
     int32_t blobType;