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;