Sanity check IMemory access versus underlying mmap am: 94b0d4e3ab am: ef6908e2b3 am: 97f49e50de am: 84f488f354
am: ebdad60d6b

* commit 'ebdad60d6b0560493e50092c30888d3a7b5cc8c9':
  Sanity check IMemory access versus underlying mmap
diff --git a/Android.mk b/Android.mk
index 79decfe..d5860ef 100644
--- a/Android.mk
+++ b/Android.mk
@@ -26,6 +26,8 @@
     IMemory.cpp \
     IPCThreadState.cpp \
     IPermissionController.cpp \
+    IProcessInfoService.cpp \
+    ProcessInfoService.cpp \
     IServiceManager.cpp \
     MemoryDealer.cpp \
     MemoryBase.cpp \
diff --git a/AppOpsManager.cpp b/AppOpsManager.cpp
index c562c30..e4d8201 100644
--- a/AppOpsManager.cpp
+++ b/AppOpsManager.cpp
@@ -104,4 +104,13 @@
     }
 }
 
+int32_t AppOpsManager::permissionToOpCode(const String16& permission) {
+    sp<IAppOpsService> service = getService();
+    if (service != NULL) {
+        return service->permissionToOpCode(permission);
+    }
+    return -1;
+}
+
+
 }; // namespace android
diff --git a/BufferedTextOutput.cpp b/BufferedTextOutput.cpp
index 2d493c1..1339a67 100644
--- a/BufferedTextOutput.cpp
+++ b/BufferedTextOutput.cpp
@@ -49,9 +49,12 @@
     
     status_t append(const char* txt, size_t len) {
         if ((len+bufferPos) > bufferSize) {
-            void* b = realloc(buffer, ((len+bufferPos)*3)/2);
+            size_t newSize = ((len+bufferPos)*3)/2;
+            if (newSize < (len+bufferPos)) return NO_MEMORY;    // overflow
+            void* b = realloc(buffer, newSize);
             if (!b) return NO_MEMORY;
             buffer = (char*)b;
+            bufferSize = newSize;
         }
         memcpy(buffer+bufferPos, txt, len);
         bufferPos += len;
diff --git a/IAppOpsService.cpp b/IAppOpsService.cpp
index 86abdc0..9558376 100644
--- a/IAppOpsService.cpp
+++ b/IAppOpsService.cpp
@@ -111,6 +111,17 @@
         if (reply.readExceptionCode() != 0) return NULL;
         return reply.readStrongBinder();
     }
+
+
+    virtual int32_t permissionToOpCode(const String16& permission) {
+        Parcel data, reply;
+        data.writeInterfaceToken(IAppOpsService::getInterfaceDescriptor());
+        data.writeString16(permission);
+        remote()->transact(PERMISSION_TO_OP_CODE_TRANSACTION, data, &reply);
+        // fail on exception
+        if (reply.readExceptionCode() != 0) return -1;
+        return reply.readInt32();
+    }
 };
 
 IMPLEMENT_META_INTERFACE(AppOpsService, "com.android.internal.app.IAppOpsService");
@@ -187,6 +198,14 @@
             reply->writeStrongBinder(token);
             return NO_ERROR;
         } break;
+        case PERMISSION_TO_OP_CODE_TRANSACTION: {
+            CHECK_INTERFACE(IAppOpsService, data, reply);
+            String16 permission = data.readString16();
+            const int32_t opCode = permissionToOpCode(permission);
+            reply->writeNoException();
+            reply->writeInt32(opCode);
+            return NO_ERROR;
+        } break;
         default:
             return BBinder::onTransact(code, data, reply, flags);
     }
diff --git a/IBatteryStats.cpp b/IBatteryStats.cpp
index 8f3b7b4..e32c628 100644
--- a/IBatteryStats.cpp
+++ b/IBatteryStats.cpp
@@ -89,6 +89,47 @@
         data.writeInterfaceToken(IBatteryStats::getInterfaceDescriptor());
         remote()->transact(NOTE_RESET_AUDIO_TRANSACTION, data, &reply);
     }
+
+    virtual void noteFlashlightOn(int uid) {
+        Parcel data, reply;
+        data.writeInterfaceToken(IBatteryStats::getInterfaceDescriptor());
+        data.writeInt32(uid);
+        remote()->transact(NOTE_FLASHLIGHT_ON_TRANSACTION, data, &reply);
+    }
+
+    virtual void noteFlashlightOff(int uid) {
+        Parcel data, reply;
+        data.writeInterfaceToken(IBatteryStats::getInterfaceDescriptor());
+        data.writeInt32(uid);
+        remote()->transact(NOTE_FLASHLIGHT_OFF_TRANSACTION, data, &reply);
+    }
+
+    virtual void noteStartCamera(int uid) {
+        Parcel data, reply;
+        data.writeInterfaceToken(IBatteryStats::getInterfaceDescriptor());
+        data.writeInt32(uid);
+        remote()->transact(NOTE_START_CAMERA_TRANSACTION, data, &reply);
+    }
+
+    virtual void noteStopCamera(int uid) {
+        Parcel data, reply;
+        data.writeInterfaceToken(IBatteryStats::getInterfaceDescriptor());
+        data.writeInt32(uid);
+        remote()->transact(NOTE_STOP_CAMERA_TRANSACTION, data, &reply);
+    }
+
+    virtual void noteResetCamera() {
+        Parcel data, reply;
+        data.writeInterfaceToken(IBatteryStats::getInterfaceDescriptor());
+        remote()->transact(NOTE_RESET_CAMERA_TRANSACTION, data, &reply);
+    }
+
+    virtual void noteResetFlashlight() {
+        Parcel data, reply;
+        data.writeInterfaceToken(IBatteryStats::getInterfaceDescriptor());
+        remote()->transact(NOTE_RESET_FLASHLIGHT_TRANSACTION, data, &reply);
+    }
+
 };
 
 IMPLEMENT_META_INTERFACE(BatteryStats, "com.android.internal.app.IBatteryStats");
@@ -155,6 +196,46 @@
             reply->writeNoException();
             return NO_ERROR;
         } break;
+        case NOTE_FLASHLIGHT_ON_TRANSACTION: {
+            CHECK_INTERFACE(IBatteryStats, data, reply);
+            int uid = data.readInt32();
+            noteFlashlightOn(uid);
+            reply->writeNoException();
+            return NO_ERROR;
+        } break;
+        case NOTE_FLASHLIGHT_OFF_TRANSACTION: {
+            CHECK_INTERFACE(IBatteryStats, data, reply);
+            int uid = data.readInt32();
+            noteFlashlightOff(uid);
+            reply->writeNoException();
+            return NO_ERROR;
+        } break;
+        case NOTE_START_CAMERA_TRANSACTION: {
+            CHECK_INTERFACE(IBatteryStats, data, reply);
+            int uid = data.readInt32();
+            noteStartCamera(uid);
+            reply->writeNoException();
+            return NO_ERROR;
+        } break;
+        case NOTE_STOP_CAMERA_TRANSACTION: {
+            CHECK_INTERFACE(IBatteryStats, data, reply);
+            int uid = data.readInt32();
+            noteStopCamera(uid);
+            reply->writeNoException();
+            return NO_ERROR;
+        } break;
+        case NOTE_RESET_CAMERA_TRANSACTION: {
+            CHECK_INTERFACE(IBatteryStats, data, reply);
+            noteResetCamera();
+            reply->writeNoException();
+            return NO_ERROR;
+        } break;
+        case NOTE_RESET_FLASHLIGHT_TRANSACTION: {
+            CHECK_INTERFACE(IBatteryStats, data, reply);
+            noteResetFlashlight();
+            reply->writeNoException();
+            return NO_ERROR;
+        } break;
         default:
             return BBinder::onTransact(code, data, reply, flags);
     }
diff --git a/IInterface.cpp b/IInterface.cpp
index 8c60dc4..2fcd3d9 100644
--- a/IInterface.cpp
+++ b/IInterface.cpp
@@ -14,6 +14,8 @@
  * limitations under the License.
  */
 
+#define LOG_TAG "IInterface"
+#include <utils/Log.h>
 #include <binder/IInterface.h>
 
 namespace android {
@@ -41,6 +43,25 @@
     return iface->onAsBinder();
 }
 
+
 // ---------------------------------------------------------------------------
 
 }; // namespace android
+
+extern "C" {
+
+void _ZN7android10IInterface8asBinderEv(void *retval, void* self) {
+    ALOGW("deprecated asBinder call, please update your code");
+    //ALOGI("self: %p, retval: %p", self, retval);
+    android::sp<android::IBinder> *ret = new(retval) android::sp<android::IBinder>;
+    *ret = android::IInterface::asBinder((android::IInterface*)self);
+}
+
+void _ZNK7android10IInterface8asBinderEv(void *retval, void *self) {
+    ALOGW("deprecated asBinder call, please update your code");
+    //ALOGI("self: %p, retval: %p", self, retval);
+    android::sp<android::IBinder> *ret = new(retval) android::sp<android::IBinder>;
+    *ret = android::IInterface::asBinder((android::IInterface*)self);
+}
+
+} // extern "C"
diff --git a/IPCThreadState.cpp b/IPCThreadState.cpp
index 9f68aa8..ef88181 100644
--- a/IPCThreadState.cpp
+++ b/IPCThreadState.cpp
@@ -399,6 +399,18 @@
     talkWithDriver(false);
 }
 
+void IPCThreadState::blockUntilThreadAvailable()
+{
+    pthread_mutex_lock(&mProcess->mThreadCountLock);
+    while (mProcess->mExecutingThreadsCount >= mProcess->mMaxThreads) {
+        ALOGW("Waiting for thread to be free. mExecutingThreadsCount=%lu mMaxThreads=%lu\n",
+                static_cast<unsigned long>(mProcess->mExecutingThreadsCount),
+                static_cast<unsigned long>(mProcess->mMaxThreads));
+        pthread_cond_wait(&mProcess->mThreadCountDecrement, &mProcess->mThreadCountLock);
+    }
+    pthread_mutex_unlock(&mProcess->mThreadCountLock);
+}
+
 status_t IPCThreadState::getAndExecuteCommand()
 {
     status_t result;
@@ -414,8 +426,17 @@
                  << getReturnString(cmd) << endl;
         }
 
+        pthread_mutex_lock(&mProcess->mThreadCountLock);
+        mProcess->mExecutingThreadsCount++;
+        pthread_mutex_unlock(&mProcess->mThreadCountLock);
+
         result = executeCommand(cmd);
 
+        pthread_mutex_lock(&mProcess->mThreadCountLock);
+        mProcess->mExecutingThreadsCount--;
+        pthread_cond_broadcast(&mProcess->mThreadCountDecrement);
+        pthread_mutex_unlock(&mProcess->mThreadCountLock);
+
         // After executing the command, ensure that the thread is returned to the
         // foreground cgroup before rejoining the pool.  The driver takes care of
         // restoring the priority, but doesn't do anything with cgroups so we
diff --git a/IPermissionController.cpp b/IPermissionController.cpp
index 437113d..6bba996 100644
--- a/IPermissionController.cpp
+++ b/IPermissionController.cpp
@@ -48,6 +48,36 @@
         if (reply.readExceptionCode() != 0) return 0;
         return reply.readInt32() != 0;
     }
+
+    virtual void getPackagesForUid(const uid_t uid, Vector<String16>& packages)
+    {
+        Parcel data, reply;
+        data.writeInterfaceToken(IPermissionController::getInterfaceDescriptor());
+        data.writeInt32(uid);
+        remote()->transact(GET_PACKAGES_FOR_UID_TRANSACTION, data, &reply);
+        // fail on exception
+        if (reply.readExceptionCode() != 0) {
+            return;
+        }
+        const int32_t size = reply.readInt32();
+        if (size <= 0) {
+            return;
+        }
+        for (int i = 0; i < size; i++) {
+            packages.push(reply.readString16());
+        }
+    }
+
+    virtual bool isRuntimePermission(const String16& permission)
+    {
+        Parcel data, reply;
+        data.writeInterfaceToken(IPermissionController::getInterfaceDescriptor());
+        data.writeString16(permission);
+        remote()->transact(IS_RUNTIME_PERMISSION_TRANSACTION, data, &reply);
+        // fail on exception
+        if (reply.readExceptionCode() != 0) return false;
+        return reply.readInt32() != 0;
+    }
 };
 
 IMPLEMENT_META_INTERFACE(PermissionController, "android.os.IPermissionController");
@@ -57,7 +87,6 @@
 status_t BnPermissionController::onTransact(
     uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
 {
-    //printf("PermissionController received: "); data.print();
     switch(code) {
         case CHECK_PERMISSION_TRANSACTION: {
             CHECK_INTERFACE(IPermissionController, data, reply);
@@ -69,6 +98,30 @@
             reply->writeInt32(res ? 1 : 0);
             return NO_ERROR;
         } break;
+
+        case GET_PACKAGES_FOR_UID_TRANSACTION: {
+            CHECK_INTERFACE(IPermissionController, data, reply);
+            int32_t uid = data.readInt32();
+            Vector<String16> packages;
+            getPackagesForUid(uid, packages);
+            reply->writeNoException();
+            size_t size = packages.size();
+            reply->writeInt32(size);
+            for (size_t i = 0; i < size; i++) {
+                reply->writeString16(packages[i]);
+            }
+            return NO_ERROR;
+        } break;
+
+        case IS_RUNTIME_PERMISSION_TRANSACTION: {
+            CHECK_INTERFACE(IPermissionController, data, reply);
+            String16 permission = data.readString16();
+            const bool res = isRuntimePermission(permission);
+            reply->writeNoException();
+            reply->writeInt32(res ? 1 : 0);
+            return NO_ERROR;
+        } break;
+
         default:
             return BBinder::onTransact(code, data, reply, flags);
     }
diff --git a/IProcessInfoService.cpp b/IProcessInfoService.cpp
new file mode 100644
index 0000000..d86eb27
--- /dev/null
+++ b/IProcessInfoService.cpp
@@ -0,0 +1,94 @@
+/*
+ * Copyright 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <binder/IProcessInfoService.h>
+#include <binder/Parcel.h>
+#include <utils/Errors.h>
+#include <sys/types.h>
+
+namespace android {
+
+// ----------------------------------------------------------------------
+
+class BpProcessInfoService : public BpInterface<IProcessInfoService> {
+public:
+    BpProcessInfoService(const sp<IBinder>& impl)
+        : BpInterface<IProcessInfoService>(impl) {}
+
+    virtual status_t getProcessStatesFromPids(size_t length, /*in*/ int32_t* pids,
+            /*out*/ int32_t* states)
+    {
+        Parcel data, reply;
+        data.writeInterfaceToken(IProcessInfoService::getInterfaceDescriptor());
+        data.writeInt32Array(length, pids);
+        data.writeInt32(length); // write length of output array, used by java AIDL stubs
+        status_t err = remote()->transact(GET_PROCESS_STATES_FROM_PIDS, data, &reply);
+        if (err != NO_ERROR || ((err = reply.readExceptionCode()) != NO_ERROR)) {
+            return err;
+        }
+        int32_t replyLen = reply.readInt32();
+        if (static_cast<size_t>(replyLen) != length) {
+            return NOT_ENOUGH_DATA;
+        }
+        if (replyLen > 0 && (err = reply.read(states, length * sizeof(*states))) != NO_ERROR) {
+            return err;
+        }
+        return reply.readInt32();
+    }
+
+};
+
+IMPLEMENT_META_INTERFACE(ProcessInfoService, "android.os.IProcessInfoService");
+
+// ----------------------------------------------------------------------
+
+status_t BnProcessInfoService::onTransact( uint32_t code, const Parcel& data, Parcel* reply,
+        uint32_t flags) {
+    switch(code) {
+        case GET_PROCESS_STATES_FROM_PIDS: {
+            CHECK_INTERFACE(IProcessInfoService, data, reply);
+            int32_t arrayLen = data.readInt32();
+            if (arrayLen <= 0) {
+                reply->writeNoException();
+                reply->writeInt32(0);
+                reply->writeInt32(NOT_ENOUGH_DATA);
+                return NO_ERROR;
+            }
+
+            size_t len = static_cast<size_t>(arrayLen);
+            int32_t pids[len];
+            status_t res = data.read(pids, len * sizeof(*pids));
+
+            // Ignore output array length returned in the parcel here, as the states array must
+            // always be the same length as the input PIDs array.
+            int32_t states[len];
+            for (size_t i = 0; i < len; i++) states[i] = -1;
+            if (res == NO_ERROR) {
+                res = getProcessStatesFromPids(len, /*in*/ pids, /*out*/ states);
+            }
+            reply->writeNoException();
+            reply->writeInt32Array(len, states);
+            reply->writeInt32(res);
+            return NO_ERROR;
+        } break;
+        default:
+            return BBinder::onTransact(code, data, reply, flags);
+    }
+}
+
+// ----------------------------------------------------------------------
+
+}; // namespace android
diff --git a/Parcel.cpp b/Parcel.cpp
index d769caa..7a4ddc4 100644
--- a/Parcel.cpp
+++ b/Parcel.cpp
@@ -54,7 +54,17 @@
 
 // ---------------------------------------------------------------------------
 
-#define PAD_SIZE(s) (((s)+3)&~3)
+// This macro should never be used at runtime, as a too large value
+// of s could cause an integer overflow. Instead, you should always
+// use the wrapper function pad_size()
+#define PAD_SIZE_UNSAFE(s) (((s)+3)&~3)
+
+static size_t pad_size(size_t s) {
+    if (s > (SIZE_T_MAX - 3)) {
+        abort();
+    }
+    return PAD_SIZE_UNSAFE(s);
+}
 
 // Note: must be kept in sync with android/os/StrictMode.java's PENALTY_GATHER
 #define STRICT_MODE_PENALTY_GATHER (0x40 << 16)
@@ -62,9 +72,6 @@
 // Note: must be kept in sync with android/os/Parcel.java's EX_HAS_REPLY_HEADER
 #define EX_HAS_REPLY_HEADER -128
 
-// Maximum size of a blob to transfer in-place.
-static const size_t IN_PLACE_BLOB_LIMIT = 40 * 1024;
-
 // XXX This can be made public if we want to provide
 // support for typed data.
 struct small_flat_data
@@ -79,6 +86,15 @@
 static size_t gParcelGlobalAllocSize = 0;
 static size_t gParcelGlobalAllocCount = 0;
 
+// Maximum size of a blob to transfer in-place.
+static const size_t BLOB_INPLACE_LIMIT = 16 * 1024;
+
+enum {
+    BLOB_INPLACE = 0,
+    BLOB_ASHMEM_IMMUTABLE = 1,
+    BLOB_ASHMEM_MUTABLE = 2,
+};
+
 void acquire_object(const sp<ProcessState>& proc,
     const flat_binder_object& obj, const void* who)
 {
@@ -355,6 +371,12 @@
 
 status_t Parcel::setDataSize(size_t size)
 {
+    if (size > INT32_MAX) {
+        // don't accept size_t values which may have come from an
+        // inadvertent conversion from a negative int.
+        return BAD_VALUE;
+    }
+
     status_t err;
     err = continueWrite(size);
     if (err == NO_ERROR) {
@@ -366,18 +388,36 @@
 
 void Parcel::setDataPosition(size_t pos) const
 {
+    if (pos > INT32_MAX) {
+        // don't accept size_t values which may have come from an
+        // inadvertent conversion from a negative int.
+        abort();
+    }
+
     mDataPos = pos;
     mNextObjectHint = 0;
 }
 
 status_t Parcel::setDataCapacity(size_t size)
 {
+    if (size > INT32_MAX) {
+        // don't accept size_t values which may have come from an
+        // inadvertent conversion from a negative int.
+        return BAD_VALUE;
+    }
+
     if (size > mDataCapacity) return continueWrite(size);
     return NO_ERROR;
 }
 
 status_t Parcel::setData(const uint8_t* buffer, size_t len)
 {
+    if (len > INT32_MAX) {
+        // don't accept size_t values which may have come from an
+        // inadvertent conversion from a negative int.
+        return BAD_VALUE;
+    }
+
     status_t err = restartWrite(len);
     if (err == NO_ERROR) {
         memcpy(const_cast<uint8_t*>(data()), buffer, len);
@@ -401,6 +441,12 @@
         return NO_ERROR;
     }
 
+    if (len > INT32_MAX) {
+        // don't accept size_t values which may have come from an
+        // inadvertent conversion from a negative int.
+        return BAD_VALUE;
+    }
+
     // range checks against the source parcel size
     if ((offset > parcel->mDataSize)
             || (len > parcel->mDataSize)
@@ -438,7 +484,8 @@
     if (numObjects > 0) {
         // grow objects
         if (mObjectsCapacity < mObjectsSize + numObjects) {
-            int newSize = ((mObjectsSize + numObjects)*3)/2;
+            size_t newSize = ((mObjectsSize + numObjects)*3)/2;
+            if (newSize < mObjectsSize) return NO_MEMORY;   // overflow
             binder_size_t *objects =
                 (binder_size_t*)realloc(mObjects, newSize*sizeof(binder_size_t));
             if (objects == (binder_size_t*)0) {
@@ -476,6 +523,11 @@
     return err;
 }
 
+bool Parcel::allowFds() const
+{
+    return mAllowFds;
+}
+
 bool Parcel::pushAllowFds(bool allowFds)
 {
     const bool origValue = mAllowFds;
@@ -561,6 +613,12 @@
 
 status_t Parcel::finishWrite(size_t len)
 {
+    if (len > INT32_MAX) {
+        // don't accept size_t values which may have come from an
+        // inadvertent conversion from a negative int.
+        return BAD_VALUE;
+    }
+
     //printf("Finish write of %d\n", len);
     mDataPos += len;
     ALOGV("finishWrite Setting data pos of %p to %zu", this, mDataPos);
@@ -574,6 +632,12 @@
 
 status_t Parcel::writeUnpadded(const void* data, size_t len)
 {
+    if (len > INT32_MAX) {
+        // don't accept size_t values which may have come from an
+        // inadvertent conversion from a negative int.
+        return BAD_VALUE;
+    }
+
     size_t end = mDataPos + len;
     if (end < mDataPos) {
         // integer overflow
@@ -593,6 +657,12 @@
 
 status_t Parcel::write(const void* data, size_t len)
 {
+    if (len > INT32_MAX) {
+        // don't accept size_t values which may have come from an
+        // inadvertent conversion from a negative int.
+        return BAD_VALUE;
+    }
+
     void* const d = writeInplace(len);
     if (d) {
         memcpy(d, data, len);
@@ -603,7 +673,13 @@
 
 void* Parcel::writeInplace(size_t len)
 {
-    const size_t padded = PAD_SIZE(len);
+    if (len > INT32_MAX) {
+        // don't accept size_t values which may have come from an
+        // inadvertent conversion from a negative int.
+        return NULL;
+    }
+
+    const size_t padded = pad_size(len);
 
     // sanity check for integer overflow
     if (mDataPos+padded < mDataPos) {
@@ -652,20 +728,32 @@
 }
 
 status_t Parcel::writeInt32Array(size_t len, const int32_t *val) {
-    if (!val) {
-        return writeAligned(-1);
+    if (len > INT32_MAX) {
+        // don't accept size_t values which may have come from an
+        // inadvertent conversion from a negative int.
+        return BAD_VALUE;
     }
-    status_t ret = writeAligned(len);
+
+    if (!val) {
+        return writeInt32(-1);
+    }
+    status_t ret = writeInt32(static_cast<uint32_t>(len));
     if (ret == NO_ERROR) {
         ret = write(val, len * sizeof(*val));
     }
     return ret;
 }
 status_t Parcel::writeByteArray(size_t len, const uint8_t *val) {
-    if (!val) {
-        return writeAligned(-1);
+    if (len > INT32_MAX) {
+        // don't accept size_t values which may have come from an
+        // inadvertent conversion from a negative int.
+        return BAD_VALUE;
     }
-    status_t ret = writeAligned(len);
+
+    if (!val) {
+        return writeInt32(-1);
+    }
+    status_t ret = writeInt32(static_cast<uint32_t>(len));
     if (ret == NO_ERROR) {
         ret = write(val, len * sizeof(*val));
     }
@@ -677,6 +765,11 @@
     return writeAligned(val);
 }
 
+status_t Parcel::writeUint64(uint64_t val)
+{
+    return writeAligned(val);
+}
+
 status_t Parcel::writePointer(uintptr_t val)
 {
     return writeAligned<binder_uintptr_t>(val);
@@ -805,45 +898,24 @@
     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 Parcel::writeBlob(size_t len, bool mutableCopy, WritableBlob* outBlob)
 {
-    status_t status;
+    if (len > INT32_MAX) {
+        // don't accept size_t values which may have come from an
+        // inadvertent conversion from a negative int.
+        return BAD_VALUE;
+    }
 
-    if (!mAllowFds || len <= IN_PLACE_BLOB_LIMIT) {
+    status_t status;
+    if (!mAllowFds || len <= BLOB_INPLACE_LIMIT) {
         ALOGV("writeBlob: write in place");
-        status = writeInt32(0);
+        status = writeInt32(BLOB_INPLACE);
         if (status) return status;
 
         void* ptr = writeInplace(len);
         if (!ptr) return NO_MEMORY;
 
-        outBlob->init(false /*mapped*/, ptr, len);
+        outBlob->init(-1, ptr, len, false);
         return NO_ERROR;
     }
 
@@ -851,6 +923,8 @@
     int fd = ashmem_create_region("Parcel Blob", len);
     if (fd < 0) return NO_MEMORY;
 
+    mBlobAshmemSize += len;
+
     int result = ashmem_set_prot_region(fd, PROT_READ | PROT_WRITE);
     if (result < 0) {
         status = result;
@@ -859,15 +933,17 @@
         if (ptr == MAP_FAILED) {
             status = -errno;
         } else {
-            result = ashmem_set_prot_region(fd, PROT_READ);
+            if (!mutableCopy) {
+                result = ashmem_set_prot_region(fd, PROT_READ);
+            }
             if (result < 0) {
                 status = result;
             } else {
-                status = writeInt32(1);
+                status = writeInt32(mutableCopy ? BLOB_ASHMEM_MUTABLE : BLOB_ASHMEM_IMMUTABLE);
                 if (!status) {
                     status = writeFileDescriptor(fd, true /*takeOwnership*/);
                     if (!status) {
-                        outBlob->init(true /*mapped*/, ptr, len);
+                        outBlob->init(fd, ptr, len, mutableCopy);
                         return NO_ERROR;
                     }
                 }
@@ -879,6 +955,15 @@
     return status;
 }
 
+status_t Parcel::writeDupImmutableBlobFileDescriptor(int fd)
+{
+    // Must match up with what's done in writeBlob.
+    if (!mAllowFds) return FDS_NOT_ALLOWED;
+    status_t status = writeInt32(BLOB_ASHMEM_IMMUTABLE);
+    if (status) return status;
+    return writeDupFileDescriptor(fd);
+}
+
 status_t Parcel::write(const FlattenableHelperInterface& val)
 {
     status_t err;
@@ -887,6 +972,12 @@
     const size_t len = val.getFlattenedSize();
     const size_t fd_count = val.getFdCount();
 
+    if ((len > INT32_MAX) || (fd_count > INT32_MAX)) {
+        // don't accept size_t values which may have come from an
+        // inadvertent conversion from a negative int.
+        return BAD_VALUE;
+    }
+
     err = this->writeInt32(len);
     if (err) return err;
 
@@ -894,7 +985,7 @@
     if (err) return err;
 
     // payload
-    void* const buf = this->writeInplace(PAD_SIZE(len));
+    void* const buf = this->writeInplace(pad_size(len));
     if (buf == NULL)
         return BAD_VALUE;
 
@@ -923,6 +1014,15 @@
 restart_write:
         *reinterpret_cast<flat_binder_object*>(mData+mDataPos) = val;
 
+        // remember if it's a file descriptor
+        if (val.type == BINDER_TYPE_FD) {
+            if (!mAllowFds) {
+                // fail before modifying our object index
+                return FDS_NOT_ALLOWED;
+            }
+            mHasFds = mFdsKnown = true;
+        }
+
         // Need to write meta-data?
         if (nullMetaData || val.binder != 0) {
             mObjects[mObjectsSize] = mDataPos;
@@ -930,14 +1030,6 @@
             mObjectsSize++;
         }
 
-        // remember if it's a file descriptor
-        if (val.type == BINDER_TYPE_FD) {
-            if (!mAllowFds) {
-                return FDS_NOT_ALLOWED;
-            }
-            mHasFds = mFdsKnown = true;
-        }
-
         return finishWrite(sizeof(flat_binder_object));
     }
 
@@ -947,6 +1039,7 @@
     }
     if (!enoughObjects) {
         size_t newSize = ((mObjectsSize+2)*3)/2;
+        if (newSize < mObjectsSize) return NO_MEMORY;   // overflow
         binder_size_t* objects = (binder_size_t*)realloc(mObjects, newSize*sizeof(binder_size_t));
         if (objects == NULL) return NO_MEMORY;
         mObjects = objects;
@@ -968,10 +1061,16 @@
 
 status_t Parcel::read(void* outData, size_t len) const
 {
-    if ((mDataPos+PAD_SIZE(len)) >= mDataPos && (mDataPos+PAD_SIZE(len)) <= mDataSize
-            && len <= PAD_SIZE(len)) {
+    if (len > INT32_MAX) {
+        // don't accept size_t values which may have come from an
+        // inadvertent conversion from a negative int.
+        return BAD_VALUE;
+    }
+
+    if ((mDataPos+pad_size(len)) >= mDataPos && (mDataPos+pad_size(len)) <= mDataSize
+            && len <= pad_size(len)) {
         memcpy(outData, mData+mDataPos, len);
-        mDataPos += PAD_SIZE(len);
+        mDataPos += pad_size(len);
         ALOGV("read Setting data pos of %p to %zu", this, mDataPos);
         return NO_ERROR;
     }
@@ -980,10 +1079,16 @@
 
 const void* Parcel::readInplace(size_t len) const
 {
-    if ((mDataPos+PAD_SIZE(len)) >= mDataPos && (mDataPos+PAD_SIZE(len)) <= mDataSize
-            && len <= PAD_SIZE(len)) {
+    if (len > INT32_MAX) {
+        // don't accept size_t values which may have come from an
+        // inadvertent conversion from a negative int.
+        return NULL;
+    }
+
+    if ((mDataPos+pad_size(len)) >= mDataPos && (mDataPos+pad_size(len)) <= mDataSize
+            && len <= pad_size(len)) {
         const void* data = mData+mDataPos;
-        mDataPos += PAD_SIZE(len);
+        mDataPos += pad_size(len);
         ALOGV("readInplace Setting data pos of %p to %zu", this, mDataPos);
         return data;
     }
@@ -992,7 +1097,7 @@
 
 template<class T>
 status_t Parcel::readAligned(T *pArg) const {
-    COMPILE_TIME_ASSERT_FUNCTION_SCOPE(PAD_SIZE(sizeof(T)) == sizeof(T));
+    COMPILE_TIME_ASSERT_FUNCTION_SCOPE(PAD_SIZE_UNSAFE(sizeof(T)) == sizeof(T));
 
     if ((mDataPos+sizeof(T)) <= mDataSize) {
         const void* data = mData+mDataPos;
@@ -1016,7 +1121,7 @@
 
 template<class T>
 status_t Parcel::writeAligned(T val) {
-    COMPILE_TIME_ASSERT_FUNCTION_SCOPE(PAD_SIZE(sizeof(T)) == sizeof(T));
+    COMPILE_TIME_ASSERT_FUNCTION_SCOPE(PAD_SIZE_UNSAFE(sizeof(T)) == sizeof(T));
 
     if ((mDataPos+sizeof(val)) <= mDataCapacity) {
 restart_write:
@@ -1060,6 +1165,16 @@
     return readAligned<int64_t>();
 }
 
+status_t Parcel::readUint64(uint64_t *pArg) const
+{
+    return readAligned(pArg);
+}
+
+uint64_t Parcel::readUint64() const
+{
+    return readAligned<uint64_t>();
+}
+
 status_t Parcel::readPointer(uintptr_t *pArg) const
 {
     status_t ret;
@@ -1147,7 +1262,7 @@
         const char* eos = reinterpret_cast<const char*>(memchr(str, 0, avail));
         if (eos) {
             const size_t len = eos - str;
-            mDataPos += PAD_SIZE(len+1);
+            mDataPos += pad_size(len+1);
             ALOGV("readCString Setting data pos of %p to %zu", this, mDataPos);
             return str;
         }
@@ -1261,46 +1376,31 @@
     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;
-    status_t status = readInt32(&useAshmem);
+    int32_t blobType;
+    status_t status = readInt32(&blobType);
     if (status) return status;
 
-    if (!useAshmem) {
+    if (blobType == BLOB_INPLACE) {
         ALOGV("readBlob: read in place");
         const void* ptr = readInplace(len);
         if (!ptr) return BAD_VALUE;
 
-        outBlob->init(false /*mapped*/, const_cast<void*>(ptr), len);
+        outBlob->init(-1, const_cast<void*>(ptr), len, false);
         return NO_ERROR;
     }
 
     ALOGV("readBlob: read from ashmem");
+    bool isMutable = (blobType == BLOB_ASHMEM_MUTABLE);
     int fd = readFileDescriptor();
     if (fd == int(BAD_TYPE)) return BAD_VALUE;
 
-    void* ptr = ::mmap(NULL, len, PROT_READ, MAP_SHARED, fd, 0);
+    void* ptr = ::mmap(NULL, len, isMutable ? PROT_READ | PROT_WRITE : PROT_READ,
+            MAP_SHARED, fd, 0);
     if (ptr == MAP_FAILED) return NO_MEMORY;
 
-    outBlob->init(true /*mapped*/, ptr, len);
+    outBlob->init(fd, ptr, len, isMutable);
     return NO_ERROR;
 }
 
@@ -1310,8 +1410,14 @@
     const size_t len = this->readInt32();
     const size_t fd_count = this->readInt32();
 
+    if (len > INT32_MAX) {
+        // don't accept size_t values which may have come from an
+        // inadvertent conversion from a negative int.
+        return BAD_VALUE;
+    }
+
     // payload
-    void const* const buf = this->readInplace(PAD_SIZE(len));
+    void const* const buf = this->readInplace(pad_size(len));
     if (buf == NULL)
         return BAD_VALUE;
 
@@ -1550,6 +1656,12 @@
 
 status_t Parcel::growData(size_t len)
 {
+    if (len > INT32_MAX) {
+        // don't accept size_t values which may have come from an
+        // inadvertent conversion from a negative int.
+        return BAD_VALUE;
+    }
+
     size_t newSize = ((mDataSize+len)*3)/2;
     return (newSize <= mDataSize)
             ? (status_t) NO_MEMORY
@@ -1558,6 +1670,12 @@
 
 status_t Parcel::restartWrite(size_t desired)
 {
+    if (desired > INT32_MAX) {
+        // don't accept size_t values which may have come from an
+        // inadvertent conversion from a negative int.
+        return BAD_VALUE;
+    }
+
     if (mOwner) {
         freeData();
         return continueWrite(desired);
@@ -1598,6 +1716,12 @@
 
 status_t Parcel::continueWrite(size_t desired)
 {
+    if (desired > INT32_MAX) {
+        // don't accept size_t values which may have come from an
+        // inadvertent conversion from a negative int.
+        return BAD_VALUE;
+    }
+
     // If shrinking, first adjust for any objects that appear
     // after the new data size.
     size_t objectsSize = mObjectsSize;
@@ -1630,7 +1754,7 @@
         binder_size_t* objects = NULL;
 
         if (objectsSize) {
-            objects = (binder_size_t*)malloc(objectsSize*sizeof(binder_size_t));
+            objects = (binder_size_t*)calloc(objectsSize, sizeof(binder_size_t));
             if (!objects) {
                 free(data);
 
@@ -1766,6 +1890,7 @@
     mFdsKnown = true;
     mAllowFds = true;
     mOwner = NULL;
+    mBlobAshmemSize = 0;
 }
 
 void Parcel::scanForFds() const
@@ -1783,10 +1908,15 @@
     mFdsKnown = true;
 }
 
+size_t Parcel::getBlobAshmemSize() const
+{
+    return mBlobAshmemSize;
+}
+
 // --- Parcel::Blob ---
 
 Parcel::Blob::Blob() :
-        mMapped(false), mData(NULL), mSize(0) {
+        mFd(-1), mData(NULL), mSize(0), mMutable(false) {
 }
 
 Parcel::Blob::~Blob() {
@@ -1794,22 +1924,24 @@
 }
 
 void Parcel::Blob::release() {
-    if (mMapped && mData) {
+    if (mFd != -1 && mData) {
         ::munmap(mData, mSize);
     }
     clear();
 }
 
-void Parcel::Blob::init(bool mapped, void* data, size_t size) {
-    mMapped = mapped;
+void Parcel::Blob::init(int fd, void* data, size_t size, bool isMutable) {
+    mFd = fd;
     mData = data;
     mSize = size;
+    mMutable = isMutable;
 }
 
 void Parcel::Blob::clear() {
-    mMapped = false;
+    mFd = -1;
     mData = NULL;
     mSize = 0;
+    mMutable = false;
 }
 
 }; // namespace android
diff --git a/ProcessInfoService.cpp b/ProcessInfoService.cpp
new file mode 100644
index 0000000..fb28643
--- /dev/null
+++ b/ProcessInfoService.cpp
@@ -0,0 +1,70 @@
+/*
+ * Copyright 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <binder/ProcessInfoService.h>
+#include <binder/IServiceManager.h>
+
+#include <utils/Log.h>
+#include <utils/String16.h>
+
+namespace android {
+
+ProcessInfoService::ProcessInfoService() {
+    updateBinderLocked();
+}
+
+status_t ProcessInfoService::getProcessStatesImpl(size_t length, /*in*/ int32_t* pids,
+        /*out*/ int32_t* states) {
+    status_t err = NO_ERROR;
+    sp<IProcessInfoService> pis;
+    mProcessInfoLock.lock();
+    pis = mProcessInfoService;
+    mProcessInfoLock.unlock();
+
+    for (int i = 0; i < BINDER_ATTEMPT_LIMIT; i++) {
+
+        if (pis != NULL) {
+            err = pis->getProcessStatesFromPids(length, /*in*/ pids, /*out*/ states);
+            if (err == NO_ERROR) return NO_ERROR; // success
+            if (IInterface::asBinder(pis)->isBinderAlive()) return err;
+        }
+        sleep(1);
+
+        mProcessInfoLock.lock();
+        if (pis == mProcessInfoService) {
+            updateBinderLocked();
+        }
+        pis = mProcessInfoService;
+        mProcessInfoLock.unlock();
+    }
+
+    ALOGW("%s: Could not retrieve process states from ProcessInfoService after %d retries.",
+            __FUNCTION__, BINDER_ATTEMPT_LIMIT);
+
+    return TIMED_OUT;
+}
+
+void ProcessInfoService::updateBinderLocked() {
+    const sp<IServiceManager> sm(defaultServiceManager());
+    if (sm != NULL) {
+        const String16 name("processinfo");
+        mProcessInfoService = interface_cast<IProcessInfoService>(sm->checkService(name));
+    }
+}
+
+ANDROID_SINGLETON_STATIC_INSTANCE(ProcessInfoService);
+
+}; // namespace android
diff --git a/ProcessState.cpp b/ProcessState.cpp
index 303d6cf..016d3c5 100644
--- a/ProcessState.cpp
+++ b/ProcessState.cpp
@@ -42,12 +42,13 @@
 #include <sys/stat.h>
 
 #define BINDER_VM_SIZE ((1*1024*1024) - (4096 *2))
+#define DEFAULT_MAX_BINDER_THREADS 15
 
 
 // ---------------------------------------------------------------------------
 
 namespace android {
- 
+
 class PoolThread : public Thread
 {
 public:
@@ -294,7 +295,9 @@
 
 status_t ProcessState::setThreadPoolMaxThreadCount(size_t maxThreads) {
     status_t result = NO_ERROR;
-    if (ioctl(mDriverFD, BINDER_SET_MAX_THREADS, &maxThreads) == -1) {
+    if (ioctl(mDriverFD, BINDER_SET_MAX_THREADS, &maxThreads) != -1) {
+        mMaxThreads = maxThreads;
+    } else {
         result = -errno;
         ALOGE("Binder ioctl to set max threads failed: %s", strerror(-result));
     }
@@ -322,7 +325,7 @@
             close(fd);
             fd = -1;
         }
-        size_t maxThreads = 15;
+        size_t maxThreads = DEFAULT_MAX_BINDER_THREADS;
         result = ioctl(fd, BINDER_SET_MAX_THREADS, &maxThreads);
         if (result == -1) {
             ALOGE("Binder ioctl to set max threads failed: %s", strerror(errno));
@@ -336,6 +339,10 @@
 ProcessState::ProcessState()
     : mDriverFD(open_driver())
     , mVMStart(MAP_FAILED)
+    , mThreadCountLock(PTHREAD_MUTEX_INITIALIZER)
+    , mThreadCountDecrement(PTHREAD_COND_INITIALIZER)
+    , mExecutingThreadsCount(0)
+    , mMaxThreads(DEFAULT_MAX_BINDER_THREADS)
     , mManagesContexts(false)
     , mBinderContextCheckFunc(NULL)
     , mBinderContextUserData(NULL)
diff --git a/include/hwbinder/AppOpsManager.h b/include/hwbinder/AppOpsManager.h
index 256cb94..042927c 100644
--- a/include/hwbinder/AppOpsManager.h
+++ b/include/hwbinder/AppOpsManager.h
@@ -63,7 +63,35 @@
         OP_ACCESS_NOTIFICATIONS = 25,
         OP_CAMERA = 26,
         OP_RECORD_AUDIO = 27,
-        OP_PLAY_AUDIO = 28
+        OP_PLAY_AUDIO = 28,
+        OP_READ_CLIPBOARD = 29,
+        OP_WRITE_CLIPBOARD = 30,
+        OP_TAKE_MEDIA_BUTTONS = 31,
+        OP_TAKE_AUDIO_FOCUS = 32,
+        OP_AUDIO_MASTER_VOLUME = 33,
+        OP_AUDIO_VOICE_VOLUME = 34,
+        OP_AUDIO_RING_VOLUME = 35,
+        OP_AUDIO_MEDIA_VOLUME = 36,
+        OP_AUDIO_ALARM_VOLUME = 37,
+        OP_AUDIO_NOTIFICATION_VOLUME = 38,
+        OP_AUDIO_BLUETOOTH_VOLUME = 39,
+        OP_WAKE_LOCK = 40,
+        OP_MONITOR_LOCATION = 41,
+        OP_MONITOR_HIGH_POWER_LOCATION = 42,
+        OP_GET_USAGE_STATS = 43,
+        OP_MUTE_MICROPHONE = 44,
+        OP_TOAST_WINDOW = 45,
+        OP_PROJECT_MEDIA = 46,
+        OP_ACTIVATE_VPN = 47,
+        OP_WRITE_WALLPAPER = 48,
+        OP_ASSIST_STRUCTURE = 49,
+        OP_ASSIST_SCREENSHOT = 50,
+        OP_READ_PHONE_STATE = 51,
+        OP_ADD_VOICEMAIL = 52,
+        OP_USE_SIP = 53,
+        OP_PROCESS_OUTGOING_CALLS = 54,
+        OP_USE_FINGERPRINT = 55,
+        OP_BODY_SENSORS = 56
     };
 
     AppOpsManager();
@@ -75,6 +103,7 @@
     void startWatchingMode(int32_t op, const String16& packageName,
             const sp<IAppOpsCallback>& callback);
     void stopWatchingMode(const sp<IAppOpsCallback>& callback);
+    int32_t permissionToOpCode(const String16& permission);
 
 private:
     Mutex mLock;
diff --git a/include/hwbinder/IAppOpsService.h b/include/hwbinder/IAppOpsService.h
index 193e9cc..cd81efa 100644
--- a/include/hwbinder/IAppOpsService.h
+++ b/include/hwbinder/IAppOpsService.h
@@ -40,6 +40,7 @@
             const sp<IAppOpsCallback>& callback) = 0;
     virtual void stopWatchingMode(const sp<IAppOpsCallback>& callback) = 0;
     virtual sp<IBinder> getToken(const sp<IBinder>& clientToken) = 0;
+    virtual int32_t permissionToOpCode(const String16& permission) = 0;
 
     enum {
         CHECK_OPERATION_TRANSACTION = IBinder::FIRST_CALL_TRANSACTION,
@@ -49,6 +50,7 @@
         START_WATCHING_MODE_TRANSACTION = IBinder::FIRST_CALL_TRANSACTION+4,
         STOP_WATCHING_MODE_TRANSACTION = IBinder::FIRST_CALL_TRANSACTION+5,
         GET_TOKEN_TRANSACTION = IBinder::FIRST_CALL_TRANSACTION+6,
+        PERMISSION_TO_OP_CODE_TRANSACTION = IBinder::FIRST_CALL_TRANSACTION+7,
     };
 
     enum {
diff --git a/include/hwbinder/IBatteryStats.h b/include/hwbinder/IBatteryStats.h
index 7ddac57..5f38186 100644
--- a/include/hwbinder/IBatteryStats.h
+++ b/include/hwbinder/IBatteryStats.h
@@ -36,6 +36,12 @@
     virtual void noteStopAudio(int uid) = 0;
     virtual void noteResetVideo() = 0;
     virtual void noteResetAudio() = 0;
+    virtual void noteFlashlightOn(int uid) = 0;
+    virtual void noteFlashlightOff(int uid) = 0;
+    virtual void noteStartCamera(int uid) = 0;
+    virtual void noteStopCamera(int uid) = 0;
+    virtual void noteResetCamera() = 0;
+    virtual void noteResetFlashlight() = 0;
 
     enum {
         NOTE_START_SENSOR_TRANSACTION = IBinder::FIRST_CALL_TRANSACTION,
@@ -46,6 +52,12 @@
         NOTE_STOP_AUDIO_TRANSACTION,
         NOTE_RESET_VIDEO_TRANSACTION,
         NOTE_RESET_AUDIO_TRANSACTION,
+        NOTE_FLASHLIGHT_ON_TRANSACTION,
+        NOTE_FLASHLIGHT_OFF_TRANSACTION,
+        NOTE_START_CAMERA_TRANSACTION,
+        NOTE_STOP_CAMERA_TRANSACTION,
+        NOTE_RESET_CAMERA_TRANSACTION,
+        NOTE_RESET_FLASHLIGHT_TRANSACTION
     };
 };
 
diff --git a/include/hwbinder/IPCThreadState.h b/include/hwbinder/IPCThreadState.h
index 60c2242..1853cff 100644
--- a/include/hwbinder/IPCThreadState.h
+++ b/include/hwbinder/IPCThreadState.h
@@ -76,14 +76,18 @@
                                                         BpBinder* proxy); 
 
     static  void                shutdown();
-    
+
     // Call this to disable switching threads to background scheduling when
     // receiving incoming IPC calls.  This is specifically here for the
     // Android system process, since it expects to have background apps calling
     // in to it but doesn't want to acquire locks in its services while in
     // the background.
     static  void                disableBackgroundScheduling(bool disable);
-    
+
+            // Call blocks until the number of executing binder threads is less than
+            // the maximum number of binder threads threads allowed for this process.
+            void                blockUntilThreadAvailable();
+
 private:
                                 IPCThreadState();
                                 ~IPCThreadState();
@@ -101,9 +105,9 @@
             status_t            getAndExecuteCommand();
             status_t            executeCommand(int32_t command);
             void                processPendingDerefs();
-            
+
             void                clearCaller();
-            
+
     static  void                threadDestructor(void *st);
     static  void                freeBuffer(Parcel* parcel,
                                            const uint8_t* data, size_t dataSize,
@@ -114,7 +118,7 @@
     const   pid_t               mMyThreadId;
             Vector<BBinder*>    mPendingStrongDerefs;
             Vector<RefBase::weakref_type*> mPendingWeakDerefs;
-            
+
             Parcel              mIn;
             Parcel              mOut;
             status_t            mLastError;
diff --git a/include/hwbinder/IPermissionController.h b/include/hwbinder/IPermissionController.h
index f9d371b..4e5fb34 100644
--- a/include/hwbinder/IPermissionController.h
+++ b/include/hwbinder/IPermissionController.h
@@ -19,6 +19,7 @@
 #define ANDROID_IPERMISSION_CONTROLLER_H
 
 #include <binder/IInterface.h>
+#include <stdlib.h>
 
 namespace android {
 
@@ -29,11 +30,16 @@
 public:
     DECLARE_META_INTERFACE(PermissionController);
 
-    virtual bool                checkPermission(const String16& permission,
-                                                int32_t pid, int32_t uid) = 0;
-    
+    virtual bool checkPermission(const String16& permission, int32_t pid, int32_t uid) = 0;
+
+    virtual void getPackagesForUid(const uid_t uid, Vector<String16> &packages) = 0;
+
+    virtual bool isRuntimePermission(const String16& permission) = 0;
+
     enum {
-        CHECK_PERMISSION_TRANSACTION = IBinder::FIRST_CALL_TRANSACTION
+        CHECK_PERMISSION_TRANSACTION = IBinder::FIRST_CALL_TRANSACTION,
+        GET_PACKAGES_FOR_UID_TRANSACTION = IBinder::FIRST_CALL_TRANSACTION + 1,
+        IS_RUNTIME_PERMISSION_TRANSACTION = IBinder::FIRST_CALL_TRANSACTION + 2
     };
 };
 
diff --git a/include/hwbinder/IProcessInfoService.h b/include/hwbinder/IProcessInfoService.h
new file mode 100644
index 0000000..dc62f45
--- /dev/null
+++ b/include/hwbinder/IProcessInfoService.h
@@ -0,0 +1,53 @@
+/*
+ * Copyright 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_I_PROCESS_INFO_SERVICE_H
+#define ANDROID_I_PROCESS_INFO_SERVICE_H
+
+#include <binder/IInterface.h>
+
+namespace android {
+
+// ----------------------------------------------------------------------
+
+class IProcessInfoService : public IInterface {
+public:
+    DECLARE_META_INTERFACE(ProcessInfoService);
+
+    virtual status_t    getProcessStatesFromPids( size_t length,
+                                                  /*in*/ int32_t* pids,
+                                                  /*out*/ int32_t* states) = 0;
+
+    enum {
+        GET_PROCESS_STATES_FROM_PIDS = IBinder::FIRST_CALL_TRANSACTION,
+    };
+};
+
+// ----------------------------------------------------------------------
+
+class BnProcessInfoService : public BnInterface<IProcessInfoService> {
+public:
+    virtual status_t    onTransact( uint32_t code,
+                                    const Parcel& data,
+                                    Parcel* reply,
+                                    uint32_t flags = 0);
+};
+
+// ----------------------------------------------------------------------
+
+}; // namespace android
+
+#endif // ANDROID_I_PROCESS_INFO_SERVICE_H
diff --git a/include/hwbinder/Parcel.h b/include/hwbinder/Parcel.h
index a52e044..3ada1e9 100644
--- a/include/hwbinder/Parcel.h
+++ b/include/hwbinder/Parcel.h
@@ -60,6 +60,7 @@
     status_t            appendFrom(const Parcel *parcel,
                                    size_t start, size_t len);
 
+    bool                allowFds() const;
     bool                pushAllowFds(bool allowFds);
     void                restoreAllowFds(bool lastValue);
 
@@ -96,6 +97,7 @@
     status_t            writeInt32(int32_t val);
     status_t            writeUint32(uint32_t val);
     status_t            writeInt64(int64_t val);
+    status_t            writeUint64(uint64_t val);
     status_t            writeFloat(float val);
     status_t            writeDouble(double val);
     status_t            writeCString(const char* str);
@@ -129,16 +131,18 @@
     // 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.
+    // transferred by way of an anonymous shared memory region.  Prefer sending
+    // immutable blobs if possible since they may be subsequently transferred between
+    // processes without further copying whereas mutable blobs always need to be copied.
     // The caller should call release() on the blob after writing its contents.
-    status_t            writeBlob(size_t len, WritableBlob* outBlob);
+    status_t            writeBlob(size_t len, bool mutableCopy, WritableBlob* outBlob);
+
+    // Write an existing immutable blob file descriptor to the parcel.
+    // This allows the client to send the same blob to multiple processes
+    // as long as it keeps a dup of the blob file descriptor handy for later.
+    status_t            writeDupImmutableBlobFileDescriptor(int fd);
 
     status_t            writeObject(const flat_binder_object& val, bool nullMetaData);
 
@@ -157,6 +161,8 @@
     status_t            readUint32(uint32_t *pArg) const;
     int64_t             readInt64() const;
     status_t            readInt64(int64_t *pArg) const;
+    uint64_t            readUint64() const;
+    status_t            readUint64(uint64_t *pArg) const;
     float               readFloat() const;
     status_t            readFloat(float *pArg) const;
     double              readDouble() const;
@@ -195,11 +201,6 @@
     // 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;
@@ -277,16 +278,19 @@
         Blob();
         ~Blob();
 
+        void clear();
         void release();
         inline size_t size() const { return mSize; }
+        inline int fd() const { return mFd; };
+        inline bool isMutable() const { return mMutable; }
 
     protected:
-        void init(bool mapped, void* data, size_t size);
-        void clear();
+        void init(int fd, void* data, size_t size, bool isMutable);
 
-        bool mMapped;
+        int mFd; // owned by parcel so not closed when released
         void* mData;
         size_t mSize;
+        bool mMutable;
     };
 
     class FlattenableHelperInterface {
@@ -327,6 +331,7 @@
         friend class Parcel;
     public:
         inline const void* data() const { return mData; }
+        inline void* mutableData() { return isMutable() ? mData : NULL; }
     };
 
     class WritableBlob : public Blob {
@@ -334,6 +339,12 @@
     public:
         inline void* data() { return mData; }
     };
+
+private:
+    size_t mBlobAshmemSize;
+
+public:
+    size_t getBlobAshmemSize() const;
 };
 
 // ---------------------------------------------------------------------------
diff --git a/include/hwbinder/ProcessInfoService.h b/include/hwbinder/ProcessInfoService.h
new file mode 100644
index 0000000..c5ead20
--- /dev/null
+++ b/include/hwbinder/ProcessInfoService.h
@@ -0,0 +1,65 @@
+/*
+ * Copyright 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_PROCESS_INFO_SERVICE_H
+#define ANDROID_PROCESS_INFO_SERVICE_H
+
+#include <binder/IProcessInfoService.h>
+#include <utils/Errors.h>
+#include <utils/Singleton.h>
+#include <sys/types.h>
+
+namespace android {
+
+// ----------------------------------------------------------------------
+
+class ProcessInfoService : public Singleton<ProcessInfoService> {
+
+    friend class Singleton<ProcessInfoService>;
+    sp<IProcessInfoService> mProcessInfoService;
+    Mutex mProcessInfoLock;
+
+    ProcessInfoService();
+
+    status_t getProcessStatesImpl(size_t length, /*in*/ int32_t* pids, /*out*/ int32_t* states);
+    void updateBinderLocked();
+
+    static const int BINDER_ATTEMPT_LIMIT = 5;
+
+public:
+
+    /**
+     * For each PID in the given "pids" input array, write the current process state
+     * for that process into the "states" output array, or
+     * ActivityManager.PROCESS_STATE_NONEXISTENT * to indicate that no process with the given PID
+     * exists.
+     *
+     * Returns NO_ERROR if this operation was successful, or a negative error code otherwise.
+     */
+    static status_t getProcessStatesFromPids(size_t length, /*in*/ int32_t* pids,
+            /*out*/ int32_t* states) {
+        return ProcessInfoService::getInstance().getProcessStatesImpl(length, /*in*/ pids,
+                /*out*/ states);
+    }
+
+};
+
+// ----------------------------------------------------------------------
+
+}; // namespace android
+
+#endif // ANDROID_PROCESS_INFO_SERVICE_H
+
diff --git a/include/hwbinder/ProcessState.h b/include/hwbinder/ProcessState.h
index 3bc978d..f9edc2a 100644
--- a/include/hwbinder/ProcessState.h
+++ b/include/hwbinder/ProcessState.h
@@ -24,6 +24,8 @@
 
 #include <utils/threads.h>
 
+#include <pthread.h>
+
 // ---------------------------------------------------------------------------
 namespace android {
 
@@ -71,25 +73,33 @@
                                 ProcessState(const ProcessState& o);
             ProcessState&       operator=(const ProcessState& o);
             String8             makeBinderThreadName();
-            
+
             struct handle_entry {
                 IBinder* binder;
                 RefBase::weakref_type* refs;
             };
-            
+
             handle_entry*       lookupHandleLocked(int32_t handle);
 
             int                 mDriverFD;
             void*               mVMStart;
-            
+
+            // Protects thread count variable below.
+            pthread_mutex_t     mThreadCountLock;
+            pthread_cond_t      mThreadCountDecrement;
+            // Number of binder threads current executing a command.
+            size_t              mExecutingThreadsCount;
+            // Maximum number for binder threads allowed for this process.
+            size_t              mMaxThreads;
+
     mutable Mutex               mLock;  // protects everything below.
-            
+
             Vector<handle_entry>mHandleToObject;
 
             bool                mManagesContexts;
             context_check_func  mBinderContextCheckFunc;
             void*               mBinderContextUserData;
-            
+
             KeyedVector<String16, sp<IBinder> >
                                 mContexts;