From cbe36fe1ec21e22e6649d47144c91260ba51d753 Mon Sep 17 00:00:00 2001 From: Mike Lockwood Date: Thu, 5 Sep 2013 08:41:06 -0700 Subject: [PATCH] Add support for sending and receiving ParcelFileDescriptors from native Binder code Change-Id: I7f308e28ebac0755628e19c9b4d0d7399341b435 --- include/binder/Parcel.h | 10 ++++++++++ libs/binder/Parcel.cpp | 43 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 53 insertions(+) diff --git a/include/binder/Parcel.h b/include/binder/Parcel.h index 7a782f569..0e20da910 100644 --- a/include/binder/Parcel.h +++ b/include/binder/Parcel.h @@ -124,6 +124,11 @@ public: // will be closed once the parcel is destroyed. status_t writeDupFileDescriptor(int fd); + // Writes a raw fd and optional comm channel fd to the parcel as a ParcelFileDescriptor. + // A dup's of the fds are made, which will be closed once the parcel is destroyed. + // Null values are passed as -1. + status_t writeParcelFileDescriptor(int fd, int commChannel = -1); + // 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. @@ -183,6 +188,11 @@ public: // in the parcel, which you do not own -- use dup() to get your own copy. int readFileDescriptor() const; + // Reads a ParcelFileDescriptor from the parcel. Returns the raw fd as + // the result, and the optional comm channel fd in outCommChannel. + // Null values are returned as -1. + int readParcelFileDescriptor(int& outCommChannel) 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/Parcel.cpp b/libs/binder/Parcel.cpp index 7a5919f43..d130d7cfe 100644 --- a/libs/binder/Parcel.cpp +++ b/libs/binder/Parcel.cpp @@ -750,6 +750,32 @@ status_t Parcel::writeDupFileDescriptor(int fd) return err; } +// WARNING: This method must stay in sync with +// Parcelable.Creator CREATOR +// in frameworks/base/core/java/android/os/ParcelFileDescriptor.java +status_t Parcel::writeParcelFileDescriptor(int fd, int commChannel) { + status_t status; + + if (fd < 0) { + status = writeInt32(0); // ParcelFileDescriptor is null + if (status) return status; + } else { + status = writeInt32(1); // ParcelFileDescriptor is not null + if (status) return status; + status = writeDupFileDescriptor(fd); + if (status) return status; + if (commChannel < 0) { + status = writeInt32(0); // commChannel is null + if (status) return status; + } else { + status = writeInt32(1); // commChannel is not null + if (status) return status; + status = writeDupFileDescriptor(commChannel); + } + } + return status; +} + status_t Parcel::writeBlob(size_t len, WritableBlob* outBlob) { status_t status; @@ -1148,6 +1174,23 @@ int Parcel::readFileDescriptor() const return BAD_TYPE; } +// WARNING: This method must stay in sync with writeToParcel() +// in frameworks/base/core/java/android/os/ParcelFileDescriptor.java +int Parcel::readParcelFileDescriptor(int& outCommChannel) const { + int fd; + outCommChannel = -1; + + if (readInt32() == 0) { + fd = -1; + } else { + fd = readFileDescriptor(); + if (fd >= 0 && readInt32() != 0) { + outCommChannel = readFileDescriptor(); + } + } + return fd; +} + status_t Parcel::readBlob(size_t len, ReadableBlob* outBlob) const { int32_t useAshmem;