Add support for sending and receiving ParcelFileDescriptors from native Binder code
Change-Id: I7f308e28ebac0755628e19c9b4d0d7399341b435
diff --git a/include/binder/Parcel.h b/include/binder/Parcel.h
index 7a782f5..0e20da9 100644
--- a/include/binder/Parcel.h
+++ b/include/binder/Parcel.h
@@ -124,6 +124,11 @@
// 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 @@
// 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 7a5919f..d130d7c 100644
--- a/libs/binder/Parcel.cpp
+++ b/libs/binder/Parcel.cpp
@@ -750,6 +750,32 @@
return err;
}
+// WARNING: This method must stay in sync with
+// Parcelable.Creator<ParcelFileDescriptor> 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 @@
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;