diff options
Diffstat (limited to 'libs/binder/Parcel.cpp')
-rw-r--r-- | libs/binder/Parcel.cpp | 88 |
1 files changed, 79 insertions, 9 deletions
diff --git a/libs/binder/Parcel.cpp b/libs/binder/Parcel.cpp index 4a660d1..65e67d6 100644 --- a/libs/binder/Parcel.cpp +++ b/libs/binder/Parcel.cpp @@ -18,6 +18,8 @@ //#define LOG_NDEBUG 0 #include <binder/Parcel.h> +#include <fcntl.h> +#include <pthread.h> #include <binder/IPCThreadState.h> #include <binder/Binder.h> @@ -42,6 +44,9 @@ #include <stdlib.h> #include <stdint.h> #include <sys/mman.h> +#include <sys/stat.h> +#include <sys/types.h> +#include <unistd.h> #ifndef INT32_MAX #define INT32_MAX ((int32_t)(2147483647)) @@ -95,6 +100,32 @@ enum { BLOB_ASHMEM_MUTABLE = 2, }; +static dev_t ashmem_rdev() +{ + static dev_t __ashmem_rdev; + static pthread_mutex_t __ashmem_rdev_lock = PTHREAD_MUTEX_INITIALIZER; + + pthread_mutex_lock(&__ashmem_rdev_lock); + + dev_t rdev = __ashmem_rdev; + if (!rdev) { + int fd = TEMP_FAILURE_RETRY(open("/dev/ashmem", O_RDONLY)); + if (fd >= 0) { + struct stat st; + + int ret = TEMP_FAILURE_RETRY(fstat(fd, &st)); + close(fd); + if ((ret >= 0) && S_ISCHR(st.st_mode)) { + rdev = __ashmem_rdev = st.st_rdev; + } + } + } + + pthread_mutex_unlock(&__ashmem_rdev_lock); + + return rdev; +} + void acquire_object(const sp<ProcessState>& proc, const flat_binder_object& obj, const void* who, size_t* outAshmemSize) { @@ -123,8 +154,10 @@ void acquire_object(const sp<ProcessState>& proc, return; } case BINDER_TYPE_FD: { - if (obj.cookie != 0) { - if (outAshmemSize != NULL) { + if ((obj.cookie != 0) && (outAshmemSize != NULL)) { + struct stat st; + int ret = fstat(obj.handle, &st); + if (!ret && S_ISCHR(st.st_mode) && (st.st_rdev == ashmem_rdev())) { // If we own an ashmem fd, keep track of how much memory it refers to. int size = ashmem_get_size_region(obj.handle); if (size > 0) { @@ -173,15 +206,22 @@ static void release_object(const sp<ProcessState>& proc, return; } case BINDER_TYPE_FD: { - if (outAshmemSize != NULL) { - if (obj.cookie != 0) { - int size = ashmem_get_size_region(obj.handle); - if (size > 0) { - *outAshmemSize -= size; + if (obj.cookie != 0) { // owned + if (outAshmemSize != NULL) { + struct stat st; + int ret = fstat(obj.handle, &st); + if (!ret && S_ISCHR(st.st_mode) && (st.st_rdev == ashmem_rdev())) { + int size = ashmem_get_size_region(obj.handle); + if (size > 0) { + *outAshmemSize -= size; + } } - - close(obj.handle); } + close(obj.handle); +#ifdef DISABLE_ASHMEM_TRACKING + } else if (obj.cookie != 0) { + close(obj.handle); +#endif } return; } @@ -532,7 +572,11 @@ status_t Parcel::appendFrom(const Parcel *parcel, size_t offset, size_t len) flat_binder_object* flat = reinterpret_cast<flat_binder_object*>(mData + off); +#ifndef DISABLE_ASHMEM_TRACKING acquire_object(proc, *flat, this, &mOpenAshmemSize); +#else + acquire_object(proc, *flat, this); +#endif if (flat->type == BINDER_TYPE_FD) { // If this is a file descriptor, we need to dup it so the @@ -1052,7 +1096,11 @@ restart_write: // Need to write meta-data? if (nullMetaData || val.binder != 0) { mObjects[mObjectsSize] = mDataPos; +#ifndef DISABLE_ASHMEM_TRACKING acquire_object(ProcessState::self(), val, this, &mOpenAshmemSize); +#else + acquire_object(ProcessState::self(), val, this); +#endif mObjectsSize++; } @@ -1641,7 +1689,11 @@ void Parcel::releaseObjects() i--; const flat_binder_object* flat = reinterpret_cast<flat_binder_object*>(data+objects[i]); +#ifndef DISABLE_ASHMEM_TRACKING release_object(proc, *flat, this, &mOpenAshmemSize); +#else + release_object(proc, *flat, this); +#endif } } @@ -1655,7 +1707,11 @@ void Parcel::acquireObjects() i--; const flat_binder_object* flat = reinterpret_cast<flat_binder_object*>(data+objects[i]); +#ifndef DISABLE_ASHMEM_TRACKING acquire_object(proc, *flat, this, &mOpenAshmemSize); +#else + acquire_object(proc, *flat, this); +#endif } } @@ -1837,7 +1893,11 @@ status_t Parcel::continueWrite(size_t desired) // will need to rescan because we may have lopped off the only FDs mFdsKnown = false; } +#ifndef DISABLE_ASHMEM_TRACKING release_object(proc, *flat, this, &mOpenAshmemSize); +#else + release_object(proc, *flat, this); +#endif } binder_size_t* objects = (binder_size_t*)realloc(mObjects, objectsSize*sizeof(binder_size_t)); @@ -1922,7 +1982,9 @@ void Parcel::initState() mFdsKnown = true; mAllowFds = true; mOwner = NULL; +#ifndef DISABLE_ASHMEM_TRACKING mOpenAshmemSize = 0; +#endif } void Parcel::scanForFds() const @@ -1945,12 +2007,20 @@ size_t Parcel::getBlobAshmemSize() const // This used to return the size of all blobs that were written to ashmem, now we're returning // the ashmem currently referenced by this Parcel, which should be equivalent. // TODO: Remove method once ABI can be changed. +#ifndef DISABLE_ASHMEM_TRACKING return mOpenAshmemSize; +#else + return 0; +#endif } size_t Parcel::getOpenAshmemSize() const { +#ifndef DISABLE_ASHMEM_TRACKING return mOpenAshmemSize; +#else + return 0; +#endif } // --- Parcel::Blob --- |