upload android base code part1

This commit is contained in:
August 2018-08-08 15:50:00 +08:00
parent e02f198e2d
commit 0a1de6c4b3
48159 changed files with 9071466 additions and 0 deletions

View file

@ -0,0 +1,111 @@
// Copyright (C) 2009 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.
cc_library_headers {
name: "libbinder_headers",
export_include_dirs: ["include"],
vendor_available: true,
header_libs: [
"libbase_headers",
"libcutils_headers",
"libutils_headers",
],
export_header_lib_headers: [
"libbase_headers",
"libcutils_headers",
"libutils_headers",
],
}
cc_library {
name: "libbinder",
// for vndbinder
vendor_available: true,
vndk: {
enabled: true,
},
srcs: [
"AppOpsManager.cpp",
"Binder.cpp",
"BpBinder.cpp",
"BufferedTextOutput.cpp",
"Debug.cpp",
"IActivityManager.cpp",
"IAppOpsCallback.cpp",
"IAppOpsService.cpp",
"IBatteryStats.cpp",
"IInterface.cpp",
"IMediaResourceMonitor.cpp",
"IMemory.cpp",
"IPCThreadState.cpp",
"IPermissionController.cpp",
"IProcessInfoService.cpp",
"IResultReceiver.cpp",
"IServiceManager.cpp",
"IShellCallback.cpp",
"MemoryBase.cpp",
"MemoryDealer.cpp",
"MemoryHeapBase.cpp",
"Parcel.cpp",
"PermissionCache.cpp",
"PersistableBundle.cpp",
"ProcessInfoService.cpp",
"ProcessState.cpp",
"Static.cpp",
"Status.cpp",
"TextOutput.cpp",
"IpPrefix.cpp",
"Value.cpp",
"aidl/android/content/pm/IPackageManagerNative.aidl",
],
aidl: {
export_aidl_headers: true,
},
cflags: [
"-Wall",
"-Wextra",
"-Werror",
],
product_variables: {
binder32bit: {
cflags: ["-DBINDER_IPC_32BIT=1"],
},
},
shared_libs: [
"libbase",
"liblog",
"libcutils",
"libutils",
],
header_libs: [
"libbinder_headers",
],
export_header_lib_headers: [
"libbinder_headers",
],
clang: true,
sanitize: {
misc_undefined: ["integer"],
},
}
subdirs = ["tests"]

View file

@ -0,0 +1,141 @@
/*
* Copyright (C) 2013 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 <mutex>
#include <binder/AppOpsManager.h>
#include <binder/Binder.h>
#include <binder/IServiceManager.h>
#include <utils/SystemClock.h>
namespace android {
namespace {
#if defined(__BRILLO__)
// Because Brillo has no application model, security policy is managed
// statically (at build time) with SELinux controls.
// As a consequence, it also never runs the AppOpsManager service.
const int APP_OPS_MANAGER_UNAVAILABLE_MODE = AppOpsManager::MODE_ALLOWED;
#else
const int APP_OPS_MANAGER_UNAVAILABLE_MODE = AppOpsManager::MODE_IGNORED;
#endif // defined(__BRILLO__)
} // namespace
static String16 _appops("appops");
static pthread_mutex_t gTokenMutex = PTHREAD_MUTEX_INITIALIZER;
static sp<IBinder> gToken;
static const sp<IBinder>& getToken(const sp<IAppOpsService>& service) {
pthread_mutex_lock(&gTokenMutex);
if (gToken == NULL || gToken->pingBinder() != NO_ERROR) {
gToken = service->getToken(new BBinder());
}
pthread_mutex_unlock(&gTokenMutex);
return gToken;
}
AppOpsManager::AppOpsManager()
{
}
#if defined(__BRILLO__)
// There is no AppOpsService on Brillo
sp<IAppOpsService> AppOpsManager::getService() { return NULL; }
#else
sp<IAppOpsService> AppOpsManager::getService()
{
std::lock_guard<Mutex> scoped_lock(mLock);
int64_t startTime = 0;
sp<IAppOpsService> service = mService;
while (service == NULL || !IInterface::asBinder(service)->isBinderAlive()) {
sp<IBinder> binder = defaultServiceManager()->checkService(_appops);
if (binder == NULL) {
// Wait for the app ops service to come back...
if (startTime == 0) {
startTime = uptimeMillis();
ALOGI("Waiting for app ops service");
} else if ((uptimeMillis()-startTime) > 10000) {
ALOGW("Waiting too long for app ops service, giving up");
service = NULL;
break;
}
sleep(1);
} else {
service = interface_cast<IAppOpsService>(binder);
mService = service;
}
}
return service;
}
#endif // defined(__BRILLO__)
int32_t AppOpsManager::checkOp(int32_t op, int32_t uid, const String16& callingPackage)
{
sp<IAppOpsService> service = getService();
return service != NULL
? service->checkOperation(op, uid, callingPackage)
: APP_OPS_MANAGER_UNAVAILABLE_MODE;
}
int32_t AppOpsManager::noteOp(int32_t op, int32_t uid, const String16& callingPackage) {
sp<IAppOpsService> service = getService();
return service != NULL
? service->noteOperation(op, uid, callingPackage)
: APP_OPS_MANAGER_UNAVAILABLE_MODE;
}
int32_t AppOpsManager::startOp(int32_t op, int32_t uid, const String16& callingPackage) {
sp<IAppOpsService> service = getService();
return service != NULL
? service->startOperation(getToken(service), op, uid, callingPackage)
: APP_OPS_MANAGER_UNAVAILABLE_MODE;
}
void AppOpsManager::finishOp(int32_t op, int32_t uid, const String16& callingPackage) {
sp<IAppOpsService> service = getService();
if (service != NULL) {
service->finishOperation(getToken(service), op, uid, callingPackage);
}
}
void AppOpsManager::startWatchingMode(int32_t op, const String16& packageName,
const sp<IAppOpsCallback>& callback) {
sp<IAppOpsService> service = getService();
if (service != NULL) {
service->startWatchingMode(op, packageName, callback);
}
}
void AppOpsManager::stopWatchingMode(const sp<IAppOpsCallback>& callback) {
sp<IAppOpsService> service = getService();
if (service != NULL) {
service->stopWatchingMode(callback);
}
}
int32_t AppOpsManager::permissionToOpCode(const String16& permission) {
sp<IAppOpsService> service = getService();
if (service != NULL) {
return service->permissionToOpCode(permission);
}
return -1;
}
}; // namespace android

View file

@ -0,0 +1,313 @@
/*
* Copyright (C) 2005 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/Binder.h>
#include <atomic>
#include <utils/misc.h>
#include <binder/BpBinder.h>
#include <binder/IInterface.h>
#include <binder/IResultReceiver.h>
#include <binder/IShellCallback.h>
#include <binder/Parcel.h>
#include <stdio.h>
namespace android {
// ---------------------------------------------------------------------------
IBinder::IBinder()
: RefBase()
{
}
IBinder::~IBinder()
{
}
// ---------------------------------------------------------------------------
sp<IInterface> IBinder::queryLocalInterface(const String16& /*descriptor*/)
{
return NULL;
}
BBinder* IBinder::localBinder()
{
return NULL;
}
BpBinder* IBinder::remoteBinder()
{
return NULL;
}
bool IBinder::checkSubclass(const void* /*subclassID*/) const
{
return false;
}
status_t IBinder::shellCommand(const sp<IBinder>& target, int in, int out, int err,
Vector<String16>& args, const sp<IShellCallback>& callback,
const sp<IResultReceiver>& resultReceiver)
{
Parcel send;
Parcel reply;
send.writeFileDescriptor(in);
send.writeFileDescriptor(out);
send.writeFileDescriptor(err);
const size_t numArgs = args.size();
send.writeInt32(numArgs);
for (size_t i = 0; i < numArgs; i++) {
send.writeString16(args[i]);
}
send.writeStrongBinder(callback != NULL ? IInterface::asBinder(callback) : NULL);
send.writeStrongBinder(resultReceiver != NULL ? IInterface::asBinder(resultReceiver) : NULL);
return target->transact(SHELL_COMMAND_TRANSACTION, send, &reply);
}
// ---------------------------------------------------------------------------
class BBinder::Extras
{
public:
Mutex mLock;
BpBinder::ObjectManager mObjects;
};
// ---------------------------------------------------------------------------
BBinder::BBinder() : mExtras(nullptr)
{
}
bool BBinder::isBinderAlive() const
{
return true;
}
status_t BBinder::pingBinder()
{
return NO_ERROR;
}
const String16& BBinder::getInterfaceDescriptor() const
{
// This is a local static rather than a global static,
// to avoid static initializer ordering issues.
static String16 sEmptyDescriptor;
ALOGW("reached BBinder::getInterfaceDescriptor (this=%p)", this);
return sEmptyDescriptor;
}
status_t BBinder::transact(
uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
{
data.setDataPosition(0);
status_t err = NO_ERROR;
switch (code) {
case PING_TRANSACTION:
reply->writeInt32(pingBinder());
break;
default:
err = onTransact(code, data, reply, flags);
break;
}
if (reply != NULL) {
reply->setDataPosition(0);
}
return err;
}
status_t BBinder::linkToDeath(
const sp<DeathRecipient>& /*recipient*/, void* /*cookie*/,
uint32_t /*flags*/)
{
return INVALID_OPERATION;
}
status_t BBinder::unlinkToDeath(
const wp<DeathRecipient>& /*recipient*/, void* /*cookie*/,
uint32_t /*flags*/, wp<DeathRecipient>* /*outRecipient*/)
{
return INVALID_OPERATION;
}
status_t BBinder::dump(int /*fd*/, const Vector<String16>& /*args*/)
{
return NO_ERROR;
}
void BBinder::attachObject(
const void* objectID, void* object, void* cleanupCookie,
object_cleanup_func func)
{
Extras* e = mExtras.load(std::memory_order_acquire);
if (!e) {
e = new Extras;
Extras* expected = nullptr;
if (!mExtras.compare_exchange_strong(expected, e,
std::memory_order_release,
std::memory_order_acquire)) {
delete e;
e = expected; // Filled in by CAS
}
if (e == 0) return; // out of memory
}
AutoMutex _l(e->mLock);
e->mObjects.attach(objectID, object, cleanupCookie, func);
}
void* BBinder::findObject(const void* objectID) const
{
Extras* e = mExtras.load(std::memory_order_acquire);
if (!e) return NULL;
AutoMutex _l(e->mLock);
return e->mObjects.find(objectID);
}
void BBinder::detachObject(const void* objectID)
{
Extras* e = mExtras.load(std::memory_order_acquire);
if (!e) return;
AutoMutex _l(e->mLock);
e->mObjects.detach(objectID);
}
BBinder* BBinder::localBinder()
{
return this;
}
BBinder::~BBinder()
{
Extras* e = mExtras.load(std::memory_order_relaxed);
if (e) delete e;
}
status_t BBinder::onTransact(
uint32_t code, const Parcel& data, Parcel* reply, uint32_t /*flags*/)
{
switch (code) {
case INTERFACE_TRANSACTION:
reply->writeString16(getInterfaceDescriptor());
return NO_ERROR;
case DUMP_TRANSACTION: {
int fd = data.readFileDescriptor();
int argc = data.readInt32();
Vector<String16> args;
for (int i = 0; i < argc && data.dataAvail() > 0; i++) {
args.add(data.readString16());
}
return dump(fd, args);
}
case SHELL_COMMAND_TRANSACTION: {
int in = data.readFileDescriptor();
int out = data.readFileDescriptor();
int err = data.readFileDescriptor();
int argc = data.readInt32();
Vector<String16> args;
for (int i = 0; i < argc && data.dataAvail() > 0; i++) {
args.add(data.readString16());
}
sp<IShellCallback> shellCallback = IShellCallback::asInterface(
data.readStrongBinder());
sp<IResultReceiver> resultReceiver = IResultReceiver::asInterface(
data.readStrongBinder());
// XXX can't add virtuals until binaries are updated.
//return shellCommand(in, out, err, args, resultReceiver);
(void)in;
(void)out;
(void)err;
if (resultReceiver != NULL) {
resultReceiver->send(INVALID_OPERATION);
}
}
case SYSPROPS_TRANSACTION: {
report_sysprop_change();
return NO_ERROR;
}
default:
return UNKNOWN_TRANSACTION;
}
}
// ---------------------------------------------------------------------------
enum {
// This is used to transfer ownership of the remote binder from
// the BpRefBase object holding it (when it is constructed), to the
// owner of the BpRefBase object when it first acquires that BpRefBase.
kRemoteAcquired = 0x00000001
};
BpRefBase::BpRefBase(const sp<IBinder>& o)
: mRemote(o.get()), mRefs(NULL), mState(0)
{
extendObjectLifetime(OBJECT_LIFETIME_WEAK);
if (mRemote) {
mRemote->incStrong(this); // Removed on first IncStrong().
mRefs = mRemote->createWeak(this); // Held for our entire lifetime.
}
}
BpRefBase::~BpRefBase()
{
if (mRemote) {
if (!(mState.load(std::memory_order_relaxed)&kRemoteAcquired)) {
mRemote->decStrong(this);
}
mRefs->decWeak(this);
}
}
void BpRefBase::onFirstRef()
{
mState.fetch_or(kRemoteAcquired, std::memory_order_relaxed);
}
void BpRefBase::onLastStrongRef(const void* /*id*/)
{
if (mRemote) {
mRemote->decStrong(this);
}
}
bool BpRefBase::onIncStrongAttempted(uint32_t /*flags*/, const void* /*id*/)
{
return mRemote ? mRefs->attemptIncStrong(this) : false;
}
// ---------------------------------------------------------------------------
}; // namespace android

View file

@ -0,0 +1,365 @@
/*
* Copyright (C) 2005 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.
*/
#define LOG_TAG "BpBinder"
//#define LOG_NDEBUG 0
#include <binder/BpBinder.h>
#include <binder/IPCThreadState.h>
#include <binder/IResultReceiver.h>
#include <utils/Log.h>
#include <stdio.h>
//#undef ALOGV
//#define ALOGV(...) fprintf(stderr, __VA_ARGS__)
namespace android {
// ---------------------------------------------------------------------------
BpBinder::ObjectManager::ObjectManager()
{
}
BpBinder::ObjectManager::~ObjectManager()
{
kill();
}
void BpBinder::ObjectManager::attach(
const void* objectID, void* object, void* cleanupCookie,
IBinder::object_cleanup_func func)
{
entry_t e;
e.object = object;
e.cleanupCookie = cleanupCookie;
e.func = func;
if (mObjects.indexOfKey(objectID) >= 0) {
ALOGE("Trying to attach object ID %p to binder ObjectManager %p with object %p, but object ID already in use",
objectID, this, object);
return;
}
mObjects.add(objectID, e);
}
void* BpBinder::ObjectManager::find(const void* objectID) const
{
const ssize_t i = mObjects.indexOfKey(objectID);
if (i < 0) return NULL;
return mObjects.valueAt(i).object;
}
void BpBinder::ObjectManager::detach(const void* objectID)
{
mObjects.removeItem(objectID);
}
void BpBinder::ObjectManager::kill()
{
const size_t N = mObjects.size();
ALOGV("Killing %zu objects in manager %p", N, this);
for (size_t i=0; i<N; i++) {
const entry_t& e = mObjects.valueAt(i);
if (e.func != NULL) {
e.func(mObjects.keyAt(i), e.object, e.cleanupCookie);
}
}
mObjects.clear();
}
// ---------------------------------------------------------------------------
BpBinder::BpBinder(int32_t handle)
: mHandle(handle)
, mAlive(1)
, mObitsSent(0)
, mObituaries(NULL)
{
ALOGV("Creating BpBinder %p handle %d\n", this, mHandle);
extendObjectLifetime(OBJECT_LIFETIME_WEAK);
IPCThreadState::self()->incWeakHandle(handle);
}
bool BpBinder::isDescriptorCached() const {
Mutex::Autolock _l(mLock);
return mDescriptorCache.size() ? true : false;
}
const String16& BpBinder::getInterfaceDescriptor() const
{
if (isDescriptorCached() == false) {
Parcel send, reply;
// do the IPC without a lock held.
status_t err = const_cast<BpBinder*>(this)->transact(
INTERFACE_TRANSACTION, send, &reply);
if (err == NO_ERROR) {
String16 res(reply.readString16());
Mutex::Autolock _l(mLock);
// mDescriptorCache could have been assigned while the lock was
// released.
if (mDescriptorCache.size() == 0)
mDescriptorCache = res;
}
}
// we're returning a reference to a non-static object here. Usually this
// is not something smart to do, however, with binder objects it is
// (usually) safe because they are reference-counted.
return mDescriptorCache;
}
bool BpBinder::isBinderAlive() const
{
return mAlive != 0;
}
status_t BpBinder::pingBinder()
{
Parcel send;
Parcel reply;
status_t err = transact(PING_TRANSACTION, send, &reply);
if (err != NO_ERROR) return err;
if (reply.dataSize() < sizeof(status_t)) return NOT_ENOUGH_DATA;
return (status_t)reply.readInt32();
}
status_t BpBinder::dump(int fd, const Vector<String16>& args)
{
Parcel send;
Parcel reply;
send.writeFileDescriptor(fd);
const size_t numArgs = args.size();
send.writeInt32(numArgs);
for (size_t i = 0; i < numArgs; i++) {
send.writeString16(args[i]);
}
status_t err = transact(DUMP_TRANSACTION, send, &reply);
return err;
}
status_t BpBinder::transact(
uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
{
// Once a binder has died, it will never come back to life.
if (mAlive) {
status_t status = IPCThreadState::self()->transact(
mHandle, code, data, reply, flags);
if (status == DEAD_OBJECT) mAlive = 0;
return status;
}
return DEAD_OBJECT;
}
status_t BpBinder::linkToDeath(
const sp<DeathRecipient>& recipient, void* cookie, uint32_t flags)
{
Obituary ob;
ob.recipient = recipient;
ob.cookie = cookie;
ob.flags = flags;
LOG_ALWAYS_FATAL_IF(recipient == NULL,
"linkToDeath(): recipient must be non-NULL");
{
AutoMutex _l(mLock);
if (!mObitsSent) {
if (!mObituaries) {
mObituaries = new Vector<Obituary>;
if (!mObituaries) {
return NO_MEMORY;
}
ALOGV("Requesting death notification: %p handle %d\n", this, mHandle);
getWeakRefs()->incWeak(this);
IPCThreadState* self = IPCThreadState::self();
self->requestDeathNotification(mHandle, this);
self->flushCommands();
}
ssize_t res = mObituaries->add(ob);
return res >= (ssize_t)NO_ERROR ? (status_t)NO_ERROR : res;
}
}
return DEAD_OBJECT;
}
status_t BpBinder::unlinkToDeath(
const wp<DeathRecipient>& recipient, void* cookie, uint32_t flags,
wp<DeathRecipient>* outRecipient)
{
AutoMutex _l(mLock);
if (mObitsSent) {
return DEAD_OBJECT;
}
const size_t N = mObituaries ? mObituaries->size() : 0;
for (size_t i=0; i<N; i++) {
const Obituary& obit = mObituaries->itemAt(i);
if ((obit.recipient == recipient
|| (recipient == NULL && obit.cookie == cookie))
&& obit.flags == flags) {
if (outRecipient != NULL) {
*outRecipient = mObituaries->itemAt(i).recipient;
}
mObituaries->removeAt(i);
if (mObituaries->size() == 0) {
ALOGV("Clearing death notification: %p handle %d\n", this, mHandle);
IPCThreadState* self = IPCThreadState::self();
self->clearDeathNotification(mHandle, this);
self->flushCommands();
delete mObituaries;
mObituaries = NULL;
}
return NO_ERROR;
}
}
return NAME_NOT_FOUND;
}
void BpBinder::sendObituary()
{
ALOGV("Sending obituary for proxy %p handle %d, mObitsSent=%s\n",
this, mHandle, mObitsSent ? "true" : "false");
mAlive = 0;
if (mObitsSent) return;
mLock.lock();
Vector<Obituary>* obits = mObituaries;
if(obits != NULL) {
ALOGV("Clearing sent death notification: %p handle %d\n", this, mHandle);
IPCThreadState* self = IPCThreadState::self();
self->clearDeathNotification(mHandle, this);
self->flushCommands();
mObituaries = NULL;
}
mObitsSent = 1;
mLock.unlock();
ALOGV("Reporting death of proxy %p for %zu recipients\n",
this, obits ? obits->size() : 0U);
if (obits != NULL) {
const size_t N = obits->size();
for (size_t i=0; i<N; i++) {
reportOneDeath(obits->itemAt(i));
}
delete obits;
}
}
void BpBinder::reportOneDeath(const Obituary& obit)
{
sp<DeathRecipient> recipient = obit.recipient.promote();
ALOGV("Reporting death to recipient: %p\n", recipient.get());
if (recipient == NULL) return;
recipient->binderDied(this);
}
void BpBinder::attachObject(
const void* objectID, void* object, void* cleanupCookie,
object_cleanup_func func)
{
AutoMutex _l(mLock);
ALOGV("Attaching object %p to binder %p (manager=%p)", object, this, &mObjects);
mObjects.attach(objectID, object, cleanupCookie, func);
}
void* BpBinder::findObject(const void* objectID) const
{
AutoMutex _l(mLock);
return mObjects.find(objectID);
}
void BpBinder::detachObject(const void* objectID)
{
AutoMutex _l(mLock);
mObjects.detach(objectID);
}
BpBinder* BpBinder::remoteBinder()
{
return this;
}
BpBinder::~BpBinder()
{
ALOGV("Destroying BpBinder %p handle %d\n", this, mHandle);
IPCThreadState* ipc = IPCThreadState::self();
mLock.lock();
Vector<Obituary>* obits = mObituaries;
if(obits != NULL) {
if (ipc) ipc->clearDeathNotification(mHandle, this);
mObituaries = NULL;
}
mLock.unlock();
if (obits != NULL) {
// XXX Should we tell any remaining DeathRecipient
// objects that the last strong ref has gone away, so they
// are no longer linked?
delete obits;
}
if (ipc) {
ipc->expungeHandle(mHandle, this);
ipc->decWeakHandle(mHandle);
}
}
void BpBinder::onFirstRef()
{
ALOGV("onFirstRef BpBinder %p handle %d\n", this, mHandle);
IPCThreadState* ipc = IPCThreadState::self();
if (ipc) ipc->incStrongHandle(mHandle);
}
void BpBinder::onLastStrongRef(const void* /*id*/)
{
ALOGV("onLastStrongRef BpBinder %p handle %d\n", this, mHandle);
IF_ALOGV() {
printRefs();
}
IPCThreadState* ipc = IPCThreadState::self();
if (ipc) ipc->decStrongHandle(mHandle);
}
bool BpBinder::onIncStrongAttempted(uint32_t /*flags*/, const void* /*id*/)
{
ALOGV("onIncStrongAttempted BpBinder %p handle %d\n", this, mHandle);
IPCThreadState* ipc = IPCThreadState::self();
return ipc ? ipc->attemptIncStrongHandle(mHandle) == NO_ERROR : false;
}
// ---------------------------------------------------------------------------
}; // namespace android

View file

@ -0,0 +1,282 @@
/*
* Copyright (C) 2006 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/BufferedTextOutput.h>
#include <binder/Debug.h>
#include <utils/Atomic.h>
#include <utils/Log.h>
#include <utils/RefBase.h>
#include <utils/Vector.h>
#include <cutils/threads.h>
#include <private/binder/Static.h>
#include <stdio.h>
#include <stdlib.h>
// ---------------------------------------------------------------------------
namespace android {
struct BufferedTextOutput::BufferState : public RefBase
{
explicit BufferState(int32_t _seq)
: seq(_seq)
, buffer(NULL)
, bufferPos(0)
, bufferSize(0)
, atFront(true)
, indent(0)
, bundle(0) {
}
~BufferState() {
free(buffer);
}
status_t append(const char* txt, size_t len) {
if ((len+bufferPos) > bufferSize) {
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;
return NO_ERROR;
}
void restart() {
bufferPos = 0;
atFront = true;
if (bufferSize > 256) {
void* b = realloc(buffer, 256);
if (b) {
buffer = (char*)b;
bufferSize = 256;
}
}
}
const int32_t seq;
char* buffer;
size_t bufferPos;
size_t bufferSize;
bool atFront;
int32_t indent;
int32_t bundle;
};
struct BufferedTextOutput::ThreadState
{
Vector<sp<BufferedTextOutput::BufferState> > states;
};
static mutex_t gMutex;
static thread_store_t tls;
BufferedTextOutput::ThreadState* BufferedTextOutput::getThreadState()
{
ThreadState* ts = (ThreadState*) thread_store_get( &tls );
if (ts) return ts;
ts = new ThreadState;
thread_store_set( &tls, ts, threadDestructor );
return ts;
}
void BufferedTextOutput::threadDestructor(void *st)
{
delete ((ThreadState*)st);
}
static volatile int32_t gSequence = 0;
static volatile int32_t gFreeBufferIndex = -1;
static int32_t allocBufferIndex()
{
int32_t res = -1;
mutex_lock(&gMutex);
if (gFreeBufferIndex >= 0) {
res = gFreeBufferIndex;
gFreeBufferIndex = gTextBuffers[res];
gTextBuffers.editItemAt(res) = -1;
} else {
res = gTextBuffers.size();
gTextBuffers.add(-1);
}
mutex_unlock(&gMutex);
return res;
}
static void freeBufferIndex(int32_t idx)
{
mutex_lock(&gMutex);
gTextBuffers.editItemAt(idx) = gFreeBufferIndex;
gFreeBufferIndex = idx;
mutex_unlock(&gMutex);
}
// ---------------------------------------------------------------------------
BufferedTextOutput::BufferedTextOutput(uint32_t flags)
: mFlags(flags)
, mSeq(android_atomic_inc(&gSequence))
, mIndex(allocBufferIndex())
{
mGlobalState = new BufferState(mSeq);
if (mGlobalState) mGlobalState->incStrong(this);
}
BufferedTextOutput::~BufferedTextOutput()
{
if (mGlobalState) mGlobalState->decStrong(this);
freeBufferIndex(mIndex);
}
status_t BufferedTextOutput::print(const char* txt, size_t len)
{
//printf("BufferedTextOutput: printing %d\n", len);
AutoMutex _l(mLock);
BufferState* b = getBuffer();
const char* const end = txt+len;
status_t err;
while (txt < end) {
// Find the next line.
const char* first = txt;
while (txt < end && *txt != '\n') txt++;
// Include this and all following empty lines.
while (txt < end && *txt == '\n') txt++;
// Special cases for first data on a line.
if (b->atFront) {
if (b->indent > 0) {
// If this is the start of a line, add the indent.
const char* prefix = stringForIndent(b->indent);
err = b->append(prefix, strlen(prefix));
if (err != NO_ERROR) return err;
} else if (*(txt-1) == '\n' && !b->bundle) {
// Fast path: if we are not indenting or bundling, and
// have been given one or more complete lines, just write
// them out without going through the buffer.
// Slurp up all of the lines.
const char* lastLine = txt+1;
while (txt < end) {
if (*txt++ == '\n') lastLine = txt;
}
struct iovec vec;
vec.iov_base = (void*)first;
vec.iov_len = lastLine-first;
//printf("Writing %d bytes of data!\n", vec.iov_len);
writeLines(vec, 1);
txt = lastLine;
continue;
}
}
// Append the new text to the buffer.
err = b->append(first, txt-first);
if (err != NO_ERROR) return err;
b->atFront = *(txt-1) == '\n';
// If we have finished a line and are not bundling, write
// it out.
//printf("Buffer is now %d bytes\n", b->bufferPos);
if (b->atFront && !b->bundle) {
struct iovec vec;
vec.iov_base = b->buffer;
vec.iov_len = b->bufferPos;
//printf("Writing %d bytes of data!\n", vec.iov_len);
writeLines(vec, 1);
b->restart();
}
}
return NO_ERROR;
}
void BufferedTextOutput::moveIndent(int delta)
{
AutoMutex _l(mLock);
BufferState* b = getBuffer();
b->indent += delta;
if (b->indent < 0) b->indent = 0;
}
void BufferedTextOutput::pushBundle()
{
AutoMutex _l(mLock);
BufferState* b = getBuffer();
b->bundle++;
}
void BufferedTextOutput::popBundle()
{
AutoMutex _l(mLock);
BufferState* b = getBuffer();
b->bundle--;
LOG_FATAL_IF(b->bundle < 0,
"TextOutput::popBundle() called more times than pushBundle()");
if (b->bundle < 0) b->bundle = 0;
if (b->bundle == 0) {
// Last bundle, write out data if it is complete. If it is not
// complete, don't write until the last line is done... this may
// or may not be the write thing to do, but it's the easiest.
if (b->bufferPos > 0 && b->atFront) {
struct iovec vec;
vec.iov_base = b->buffer;
vec.iov_len = b->bufferPos;
writeLines(vec, 1);
b->restart();
}
}
}
BufferedTextOutput::BufferState* BufferedTextOutput::getBuffer() const
{
if ((mFlags&MULTITHREADED) != 0) {
ThreadState* ts = getThreadState();
if (ts) {
while (ts->states.size() <= (size_t)mIndex) ts->states.add(NULL);
BufferState* bs = ts->states[mIndex].get();
if (bs != NULL && bs->seq == mSeq) return bs;
ts->states.editItemAt(mIndex) = new BufferState(mIndex);
bs = ts->states[mIndex].get();
if (bs != NULL) return bs;
}
}
return mGlobalState;
}
}; // namespace android

View file

@ -0,0 +1,308 @@
/*
* Copyright (C) 2005 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/Debug.h>
#include <binder/ProcessState.h>
#include <utils/misc.h>
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
namespace android {
// ---------------------------------------------------------------------
static const char indentStr[] =
" "
" ";
const char* stringForIndent(int32_t indentLevel)
{
ssize_t off = sizeof(indentStr)-1-(indentLevel*2);
return indentStr + (off < 0 ? 0 : off);
}
// ---------------------------------------------------------------------
static void defaultPrintFunc(void* /*cookie*/, const char* txt)
{
printf("%s", txt);
}
// ---------------------------------------------------------------------
static inline int isident(int c)
{
return isalnum(c) || c == '_';
}
static inline bool isasciitype(char c)
{
if( c >= ' ' && c < 127 && c != '\'' && c != '\\' ) return true;
return false;
}
static inline char makehexdigit(uint32_t val)
{
return "0123456789abcdef"[val&0xF];
}
static char* appendhexnum(uint32_t val, char* out)
{
for( int32_t i=28; i>=0; i-=4 ) {
*out++ = makehexdigit( val>>i );
}
*out = 0;
return out;
}
static char* appendcharornum(char c, char* out, bool skipzero = true)
{
if (skipzero && c == 0) return out;
if (isasciitype(c)) {
*out++ = c;
return out;
}
*out++ = '\\';
*out++ = 'x';
*out++ = makehexdigit(c>>4);
*out++ = makehexdigit(c);
return out;
}
static char* typetostring(uint32_t type, char* out,
bool fullContext = true,
bool strict = false)
{
char* pos = out;
char c[4];
c[0] = (char)((type>>24)&0xFF);
c[1] = (char)((type>>16)&0xFF);
c[2] = (char)((type>>8)&0xFF);
c[3] = (char)(type&0xFF);
bool valid;
if( !strict ) {
// now even less strict!
// valid = isasciitype(c[3]);
valid = true;
int32_t i = 0;
bool zero = true;
while (valid && i<3) {
if (c[i] == 0) {
if (!zero) valid = false;
} else {
zero = false;
//if (!isasciitype(c[i])) valid = false;
}
i++;
}
// if all zeros, not a valid type code.
if (zero) valid = false;
} else {
valid = isident(c[3]) ? true : false;
int32_t i = 0;
bool zero = true;
while (valid && i<3) {
if (c[i] == 0) {
if (!zero) valid = false;
} else {
zero = false;
if (!isident(c[i])) valid = false;
}
i++;
}
}
if( valid && (!fullContext || c[0] != '0' || c[1] != 'x') ) {
if( fullContext ) *pos++ = '\'';
pos = appendcharornum(c[0], pos);
pos = appendcharornum(c[1], pos);
pos = appendcharornum(c[2], pos);
pos = appendcharornum(c[3], pos);
if( fullContext ) *pos++ = '\'';
*pos = 0;
return pos;
}
if( fullContext ) {
*pos++ = '0';
*pos++ = 'x';
}
return appendhexnum(type, pos);
}
void printTypeCode(uint32_t typeCode, debugPrintFunc func, void* cookie)
{
char buffer[32];
char* end = typetostring(typeCode, buffer);
*end = 0;
func ? (*func)(cookie, buffer) : defaultPrintFunc(cookie, buffer);
}
void printHexData(int32_t indent, const void *buf, size_t length,
size_t bytesPerLine, int32_t singleLineBytesCutoff,
size_t alignment, bool cStyle,
debugPrintFunc func, void* cookie)
{
if (alignment == 0) {
if (bytesPerLine >= 16) alignment = 4;
else if (bytesPerLine >= 8) alignment = 2;
else alignment = 1;
}
if (func == NULL) func = defaultPrintFunc;
size_t offset;
unsigned char *pos = (unsigned char *)buf;
if (pos == NULL) {
if (singleLineBytesCutoff < 0) func(cookie, "\n");
func(cookie, "(NULL)");
return;
}
if (length == 0) {
if (singleLineBytesCutoff < 0) func(cookie, "\n");
func(cookie, "(empty)");
return;
}
if ((int32_t)length < 0) {
if (singleLineBytesCutoff < 0) func(cookie, "\n");
char buf[64];
sprintf(buf, "(bad length: %zu)", length);
func(cookie, buf);
return;
}
char buffer[256];
static const size_t maxBytesPerLine = (sizeof(buffer)-1-11-4)/(3+1);
if (bytesPerLine > maxBytesPerLine) bytesPerLine = maxBytesPerLine;
const bool oneLine = (int32_t)length <= singleLineBytesCutoff;
bool newLine = false;
if (cStyle) {
indent++;
func(cookie, "{\n");
newLine = true;
} else if (!oneLine) {
func(cookie, "\n");
newLine = true;
}
for (offset = 0; ; offset += bytesPerLine, pos += bytesPerLine) {
long remain = length;
char* c = buffer;
if (!oneLine && !cStyle) {
sprintf(c, "0x%08x: ", (int)offset);
c += 12;
}
size_t index;
size_t word;
for (word = 0; word < bytesPerLine; ) {
const size_t startIndex = word+(alignment-(alignment?1:0));
for (index = 0; index < alignment || (alignment == 0 && index < bytesPerLine); index++) {
if (!cStyle) {
if (index == 0 && word > 0 && alignment > 0) {
*c++ = ' ';
}
if (remain-- > 0) {
const unsigned char val = *(pos+startIndex-index);
*c++ = makehexdigit(val>>4);
*c++ = makehexdigit(val);
} else if (!oneLine) {
*c++ = ' ';
*c++ = ' ';
}
} else {
if (remain > 0) {
if (index == 0 && word > 0) {
*c++ = ',';
*c++ = ' ';
}
if (index == 0) {
*c++ = '0';
*c++ = 'x';
}
const unsigned char val = *(pos+startIndex-index);
*c++ = makehexdigit(val>>4);
*c++ = makehexdigit(val);
remain--;
}
}
}
word += index;
}
if (!cStyle) {
remain = length;
*c++ = ' ';
*c++ = '\'';
for (index = 0; index < bytesPerLine; index++) {
if (remain-- > 0) {
const unsigned char val = pos[index];
*c++ = (val >= ' ' && val < 127) ? val : '.';
} else if (!oneLine) {
*c++ = ' ';
}
}
*c++ = '\'';
if (length > bytesPerLine) *c++ = '\n';
} else {
if (remain > 0) *c++ = ',';
*c++ = '\n';
}
if (newLine && indent) func(cookie, stringForIndent(indent));
*c = 0;
func(cookie, buffer);
newLine = true;
if (length <= bytesPerLine) break;
length -= bytesPerLine;
}
if (cStyle) {
if (indent > 0) func(cookie, stringForIndent(indent-1));
func(cookie, "};");
}
}
ssize_t getBinderKernelReferences(size_t count, uintptr_t* buf) {
sp<ProcessState> proc = ProcessState::selfOrNull();
if (proc.get() == NULL) {
return 0;
}
return proc->getKernelReferences(count, buf);
}
}; // namespace android

View file

@ -0,0 +1,65 @@
/*
* Copyright (C) 2016 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 <unistd.h>
#include <fcntl.h>
#include <binder/IActivityManager.h>
#include <binder/Parcel.h>
namespace android {
// ------------------------------------------------------------------------------------
class BpActivityManager : public BpInterface<IActivityManager>
{
public:
explicit BpActivityManager(const sp<IBinder>& impl)
: BpInterface<IActivityManager>(impl)
{
}
virtual int openContentUri(const String16& stringUri)
{
Parcel data, reply;
data.writeInterfaceToken(IActivityManager::getInterfaceDescriptor());
data.writeString16(stringUri);
status_t ret = remote()->transact(OPEN_CONTENT_URI_TRANSACTION, data, & reply);
int fd = -1;
if (ret == NO_ERROR) {
int32_t exceptionCode = reply.readExceptionCode();
if (!exceptionCode) {
// Success is indicated here by a nonzero int followed by the fd;
// failure by a zero int with no data following.
if (reply.readInt32() != 0) {
fd = fcntl(reply.readParcelFileDescriptor(), F_DUPFD_CLOEXEC, 0);
}
} else {
// An exception was thrown back; fall through to return failure
ALOGD("openContentUri(%s) caught exception %d\n",
String8(stringUri).string(), exceptionCode);
}
}
return fd;
}
};
// ------------------------------------------------------------------------------------
IMPLEMENT_META_INTERFACE(ActivityManager, "android.app.IActivityManager");
}; // namespace android

View file

@ -0,0 +1,69 @@
/*
* Copyright (C) 2013 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.
*/
#define LOG_TAG "AppOpsCallback"
#include <binder/IAppOpsCallback.h>
#include <utils/Log.h>
#include <binder/Parcel.h>
#include <utils/String8.h>
#include <private/binder/Static.h>
namespace android {
// ----------------------------------------------------------------------
class BpAppOpsCallback : public BpInterface<IAppOpsCallback>
{
public:
explicit BpAppOpsCallback(const sp<IBinder>& impl)
: BpInterface<IAppOpsCallback>(impl)
{
}
virtual void opChanged(int32_t op, const String16& packageName) {
Parcel data, reply;
data.writeInterfaceToken(IAppOpsCallback::getInterfaceDescriptor());
data.writeInt32(op);
data.writeString16(packageName);
remote()->transact(OP_CHANGED_TRANSACTION, data, &reply);
}
};
IMPLEMENT_META_INTERFACE(AppOpsCallback, "com.android.internal.app.IAppOpsCallback");
// ----------------------------------------------------------------------
status_t BnAppOpsCallback::onTransact(
uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
{
switch(code) {
case OP_CHANGED_TRANSACTION: {
CHECK_INTERFACE(IAppOpsCallback, data, reply);
int32_t op = data.readInt32();
String16 packageName = data.readString16();
opChanged(op, packageName);
reply->writeNoException();
return NO_ERROR;
} break;
default:
return BBinder::onTransact(code, data, reply, flags);
}
}
}; // namespace android

View file

@ -0,0 +1,214 @@
/*
* Copyright (C) 2013 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.
*/
#define LOG_TAG "AppOpsService"
#include <binder/IAppOpsService.h>
#include <utils/Log.h>
#include <binder/Parcel.h>
#include <utils/String8.h>
#include <private/binder/Static.h>
namespace android {
// ----------------------------------------------------------------------
class BpAppOpsService : public BpInterface<IAppOpsService>
{
public:
explicit BpAppOpsService(const sp<IBinder>& impl)
: BpInterface<IAppOpsService>(impl)
{
}
virtual int32_t checkOperation(int32_t code, int32_t uid, const String16& packageName) {
Parcel data, reply;
data.writeInterfaceToken(IAppOpsService::getInterfaceDescriptor());
data.writeInt32(code);
data.writeInt32(uid);
data.writeString16(packageName);
remote()->transact(CHECK_OPERATION_TRANSACTION, data, &reply);
// fail on exception
if (reply.readExceptionCode() != 0) return MODE_ERRORED;
return reply.readInt32();
}
virtual int32_t noteOperation(int32_t code, int32_t uid, const String16& packageName) {
Parcel data, reply;
data.writeInterfaceToken(IAppOpsService::getInterfaceDescriptor());
data.writeInt32(code);
data.writeInt32(uid);
data.writeString16(packageName);
remote()->transact(NOTE_OPERATION_TRANSACTION, data, &reply);
// fail on exception
if (reply.readExceptionCode() != 0) return MODE_ERRORED;
return reply.readInt32();
}
virtual int32_t startOperation(const sp<IBinder>& token, int32_t code, int32_t uid,
const String16& packageName) {
Parcel data, reply;
data.writeInterfaceToken(IAppOpsService::getInterfaceDescriptor());
data.writeStrongBinder(token);
data.writeInt32(code);
data.writeInt32(uid);
data.writeString16(packageName);
remote()->transact(START_OPERATION_TRANSACTION, data, &reply);
// fail on exception
if (reply.readExceptionCode() != 0) return MODE_ERRORED;
return reply.readInt32();
}
virtual void finishOperation(const sp<IBinder>& token, int32_t code, int32_t uid,
const String16& packageName) {
Parcel data, reply;
data.writeInterfaceToken(IAppOpsService::getInterfaceDescriptor());
data.writeStrongBinder(token);
data.writeInt32(code);
data.writeInt32(uid);
data.writeString16(packageName);
remote()->transact(FINISH_OPERATION_TRANSACTION, data, &reply);
}
virtual void startWatchingMode(int32_t op, const String16& packageName,
const sp<IAppOpsCallback>& callback) {
Parcel data, reply;
data.writeInterfaceToken(IAppOpsService::getInterfaceDescriptor());
data.writeInt32(op);
data.writeString16(packageName);
data.writeStrongBinder(IInterface::asBinder(callback));
remote()->transact(START_WATCHING_MODE_TRANSACTION, data, &reply);
}
virtual void stopWatchingMode(const sp<IAppOpsCallback>& callback) {
Parcel data, reply;
data.writeInterfaceToken(IAppOpsService::getInterfaceDescriptor());
data.writeStrongBinder(IInterface::asBinder(callback));
remote()->transact(STOP_WATCHING_MODE_TRANSACTION, data, &reply);
}
virtual sp<IBinder> getToken(const sp<IBinder>& clientToken) {
Parcel data, reply;
data.writeInterfaceToken(IAppOpsService::getInterfaceDescriptor());
data.writeStrongBinder(clientToken);
remote()->transact(GET_TOKEN_TRANSACTION, data, &reply);
// fail on exception
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");
// ----------------------------------------------------------------------
status_t BnAppOpsService::onTransact(
uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
{
//printf("AppOpsService received: "); data.print();
switch(code) {
case CHECK_OPERATION_TRANSACTION: {
CHECK_INTERFACE(IAppOpsService, data, reply);
int32_t code = data.readInt32();
int32_t uid = data.readInt32();
String16 packageName = data.readString16();
int32_t res = checkOperation(code, uid, packageName);
reply->writeNoException();
reply->writeInt32(res);
return NO_ERROR;
} break;
case NOTE_OPERATION_TRANSACTION: {
CHECK_INTERFACE(IAppOpsService, data, reply);
int32_t code = data.readInt32();
int32_t uid = data.readInt32();
String16 packageName = data.readString16();
int32_t res = noteOperation(code, uid, packageName);
reply->writeNoException();
reply->writeInt32(res);
return NO_ERROR;
} break;
case START_OPERATION_TRANSACTION: {
CHECK_INTERFACE(IAppOpsService, data, reply);
sp<IBinder> token = data.readStrongBinder();
int32_t code = data.readInt32();
int32_t uid = data.readInt32();
String16 packageName = data.readString16();
int32_t res = startOperation(token, code, uid, packageName);
reply->writeNoException();
reply->writeInt32(res);
return NO_ERROR;
} break;
case FINISH_OPERATION_TRANSACTION: {
CHECK_INTERFACE(IAppOpsService, data, reply);
sp<IBinder> token = data.readStrongBinder();
int32_t code = data.readInt32();
int32_t uid = data.readInt32();
String16 packageName = data.readString16();
finishOperation(token, code, uid, packageName);
reply->writeNoException();
return NO_ERROR;
} break;
case START_WATCHING_MODE_TRANSACTION: {
CHECK_INTERFACE(IAppOpsService, data, reply);
int32_t op = data.readInt32();
String16 packageName = data.readString16();
sp<IAppOpsCallback> callback = interface_cast<IAppOpsCallback>(data.readStrongBinder());
startWatchingMode(op, packageName, callback);
reply->writeNoException();
return NO_ERROR;
} break;
case STOP_WATCHING_MODE_TRANSACTION: {
CHECK_INTERFACE(IAppOpsService, data, reply);
sp<IAppOpsCallback> callback = interface_cast<IAppOpsCallback>(data.readStrongBinder());
stopWatchingMode(callback);
reply->writeNoException();
return NO_ERROR;
} break;
case GET_TOKEN_TRANSACTION: {
CHECK_INTERFACE(IAppOpsService, data, reply);
sp<IBinder> clientToken = data.readStrongBinder();
sp<IBinder> token = getToken(clientToken);
reply->writeNoException();
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);
}
}
}; // namespace android

View file

@ -0,0 +1,244 @@
/*
* Copyright (C) 2013 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/IBatteryStats.h>
#include <utils/Log.h>
#include <binder/Parcel.h>
#include <utils/String8.h>
#include <private/binder/Static.h>
namespace android {
// ----------------------------------------------------------------------
class BpBatteryStats : public BpInterface<IBatteryStats>
{
public:
explicit BpBatteryStats(const sp<IBinder>& impl)
: BpInterface<IBatteryStats>(impl)
{
}
virtual void noteStartSensor(int uid, int sensor) {
Parcel data, reply;
data.writeInterfaceToken(IBatteryStats::getInterfaceDescriptor());
data.writeInt32(uid);
data.writeInt32(sensor);
remote()->transact(NOTE_START_SENSOR_TRANSACTION, data, &reply);
}
virtual void noteStopSensor(int uid, int sensor) {
Parcel data, reply;
data.writeInterfaceToken(IBatteryStats::getInterfaceDescriptor());
data.writeInt32(uid);
data.writeInt32(sensor);
remote()->transact(NOTE_STOP_SENSOR_TRANSACTION, data, &reply);
}
virtual void noteStartVideo(int uid) {
Parcel data, reply;
data.writeInterfaceToken(IBatteryStats::getInterfaceDescriptor());
data.writeInt32(uid);
remote()->transact(NOTE_START_VIDEO_TRANSACTION, data, &reply);
}
virtual void noteStopVideo(int uid) {
Parcel data, reply;
data.writeInterfaceToken(IBatteryStats::getInterfaceDescriptor());
data.writeInt32(uid);
remote()->transact(NOTE_STOP_VIDEO_TRANSACTION, data, &reply);
}
virtual void noteStartAudio(int uid) {
Parcel data, reply;
data.writeInterfaceToken(IBatteryStats::getInterfaceDescriptor());
data.writeInt32(uid);
remote()->transact(NOTE_START_AUDIO_TRANSACTION, data, &reply);
}
virtual void noteStopAudio(int uid) {
Parcel data, reply;
data.writeInterfaceToken(IBatteryStats::getInterfaceDescriptor());
data.writeInt32(uid);
remote()->transact(NOTE_STOP_AUDIO_TRANSACTION, data, &reply);
}
virtual void noteResetVideo() {
Parcel data, reply;
data.writeInterfaceToken(IBatteryStats::getInterfaceDescriptor());
remote()->transact(NOTE_RESET_VIDEO_TRANSACTION, data, &reply);
}
virtual void noteResetAudio() {
Parcel data, reply;
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");
// ----------------------------------------------------------------------
status_t BnBatteryStats::onTransact(
uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
{
switch(code) {
case NOTE_START_SENSOR_TRANSACTION: {
CHECK_INTERFACE(IBatteryStats, data, reply);
int uid = data.readInt32();
int sensor = data.readInt32();
noteStartSensor(uid, sensor);
reply->writeNoException();
return NO_ERROR;
} break;
case NOTE_STOP_SENSOR_TRANSACTION: {
CHECK_INTERFACE(IBatteryStats, data, reply);
int uid = data.readInt32();
int sensor = data.readInt32();
noteStopSensor(uid, sensor);
reply->writeNoException();
return NO_ERROR;
} break;
case NOTE_START_VIDEO_TRANSACTION: {
CHECK_INTERFACE(IBatteryStats, data, reply);
int uid = data.readInt32();
noteStartVideo(uid);
reply->writeNoException();
return NO_ERROR;
} break;
case NOTE_STOP_VIDEO_TRANSACTION: {
CHECK_INTERFACE(IBatteryStats, data, reply);
int uid = data.readInt32();
noteStopVideo(uid);
reply->writeNoException();
return NO_ERROR;
} break;
case NOTE_START_AUDIO_TRANSACTION: {
CHECK_INTERFACE(IBatteryStats, data, reply);
int uid = data.readInt32();
noteStartAudio(uid);
reply->writeNoException();
return NO_ERROR;
} break;
case NOTE_STOP_AUDIO_TRANSACTION: {
CHECK_INTERFACE(IBatteryStats, data, reply);
int uid = data.readInt32();
noteStopAudio(uid);
reply->writeNoException();
return NO_ERROR;
} break;
case NOTE_RESET_VIDEO_TRANSACTION: {
CHECK_INTERFACE(IBatteryStats, data, reply);
noteResetVideo();
reply->writeNoException();
return NO_ERROR;
} break;
case NOTE_RESET_AUDIO_TRANSACTION: {
CHECK_INTERFACE(IBatteryStats, data, reply);
noteResetAudio();
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);
}
}
}; // namespace android

View file

@ -0,0 +1,67 @@
/*
* Copyright (C) 2005 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.
*/
#define LOG_TAG "IInterface"
#include <utils/Log.h>
#include <binder/IInterface.h>
namespace android {
// ---------------------------------------------------------------------------
IInterface::IInterface()
: RefBase() {
}
IInterface::~IInterface() {
}
// static
sp<IBinder> IInterface::asBinder(const IInterface* iface)
{
if (iface == NULL) return NULL;
return const_cast<IInterface*>(iface)->onAsBinder();
}
// static
sp<IBinder> IInterface::asBinder(const sp<IInterface>& iface)
{
if (iface == NULL) return NULL;
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"

View file

@ -0,0 +1,62 @@
/*
* Copyright 2016 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/IMediaResourceMonitor.h>
#include <binder/Parcel.h>
#include <utils/Errors.h>
#include <sys/types.h>
namespace android {
// ----------------------------------------------------------------------
class BpMediaResourceMonitor : public BpInterface<IMediaResourceMonitor> {
public:
explicit BpMediaResourceMonitor(const sp<IBinder>& impl)
: BpInterface<IMediaResourceMonitor>(impl) {}
virtual void notifyResourceGranted(/*in*/ int32_t pid, /*in*/ const int32_t type)
{
Parcel data, reply;
data.writeInterfaceToken(IMediaResourceMonitor::getInterfaceDescriptor());
data.writeInt32(pid);
data.writeInt32(type);
remote()->transact(NOTIFY_RESOURCE_GRANTED, data, &reply, IBinder::FLAG_ONEWAY);
}
};
IMPLEMENT_META_INTERFACE(MediaResourceMonitor, "android.media.IMediaResourceMonitor");
// ----------------------------------------------------------------------
status_t BnMediaResourceMonitor::onTransact( uint32_t code, const Parcel& data, Parcel* reply,
uint32_t flags) {
switch(code) {
case NOTIFY_RESOURCE_GRANTED: {
CHECK_INTERFACE(IMediaResourceMonitor, data, reply);
int32_t pid = data.readInt32();
const int32_t type = data.readInt32();
notifyResourceGranted(/*in*/ pid, /*in*/ type);
return NO_ERROR;
} break;
default:
return BBinder::onTransact(code, data, reply, flags);
}
}
// ----------------------------------------------------------------------
}; // namespace android

View file

@ -0,0 +1,503 @@
/*
* Copyright (C) 2008 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.
*/
#define LOG_TAG "IMemory"
#include <atomic>
#include <stdatomic.h>
#include <fcntl.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/mman.h>
#include <unistd.h>
#include <binder/IMemory.h>
#include <binder/Parcel.h>
#include <log/log.h>
#include <utils/CallStack.h>
#include <utils/KeyedVector.h>
#include <utils/threads.h>
#define VERBOSE 0
namespace android {
// ---------------------------------------------------------------------------
class HeapCache : public IBinder::DeathRecipient
{
public:
HeapCache();
virtual ~HeapCache();
virtual void binderDied(const wp<IBinder>& who);
sp<IMemoryHeap> find_heap(const sp<IBinder>& binder);
void free_heap(const sp<IBinder>& binder);
sp<IMemoryHeap> get_heap(const sp<IBinder>& binder);
void dump_heaps();
private:
// For IMemory.cpp
struct heap_info_t {
sp<IMemoryHeap> heap;
int32_t count;
// Note that this cannot be meaningfully copied.
};
void free_heap(const wp<IBinder>& binder);
Mutex mHeapCacheLock; // Protects entire vector below.
KeyedVector< wp<IBinder>, heap_info_t > mHeapCache;
// We do not use the copy-on-write capabilities of KeyedVector.
// TODO: Reimplemement based on standard C++ container?
};
static sp<HeapCache> gHeapCache = new HeapCache();
/******************************************************************************/
enum {
HEAP_ID = IBinder::FIRST_CALL_TRANSACTION
};
class BpMemoryHeap : public BpInterface<IMemoryHeap>
{
public:
explicit BpMemoryHeap(const sp<IBinder>& impl);
virtual ~BpMemoryHeap();
virtual int getHeapID() const;
virtual void* getBase() const;
virtual size_t getSize() const;
virtual uint32_t getFlags() const;
virtual uint32_t getOffset() const;
private:
friend class IMemory;
friend class HeapCache;
// for debugging in this module
static inline sp<IMemoryHeap> find_heap(const sp<IBinder>& binder) {
return gHeapCache->find_heap(binder);
}
static inline void free_heap(const sp<IBinder>& binder) {
gHeapCache->free_heap(binder);
}
static inline sp<IMemoryHeap> get_heap(const sp<IBinder>& binder) {
return gHeapCache->get_heap(binder);
}
static inline void dump_heaps() {
gHeapCache->dump_heaps();
}
void assertMapped() const;
void assertReallyMapped() const;
mutable std::atomic<int32_t> mHeapId;
mutable void* mBase;
mutable size_t mSize;
mutable uint32_t mFlags;
mutable uint32_t mOffset;
mutable bool mRealHeap;
mutable Mutex mLock;
};
// ----------------------------------------------------------------------------
enum {
GET_MEMORY = IBinder::FIRST_CALL_TRANSACTION
};
class BpMemory : public BpInterface<IMemory>
{
public:
explicit BpMemory(const sp<IBinder>& impl);
virtual ~BpMemory();
virtual sp<IMemoryHeap> getMemory(ssize_t* offset=0, size_t* size=0) const;
private:
mutable sp<IMemoryHeap> mHeap;
mutable ssize_t mOffset;
mutable size_t mSize;
};
/******************************************************************************/
void* IMemory::fastPointer(const sp<IBinder>& binder, ssize_t offset) const
{
sp<IMemoryHeap> realHeap = BpMemoryHeap::get_heap(binder);
void* const base = realHeap->base();
if (base == MAP_FAILED)
return 0;
return static_cast<char*>(base) + offset;
}
void* IMemory::pointer() const {
ssize_t offset;
sp<IMemoryHeap> heap = getMemory(&offset);
void* const base = heap!=0 ? heap->base() : MAP_FAILED;
if (base == MAP_FAILED)
return 0;
return static_cast<char*>(base) + offset;
}
size_t IMemory::size() const {
size_t size;
getMemory(NULL, &size);
return size;
}
ssize_t IMemory::offset() const {
ssize_t offset;
getMemory(&offset);
return offset;
}
/******************************************************************************/
BpMemory::BpMemory(const sp<IBinder>& impl)
: BpInterface<IMemory>(impl), mOffset(0), mSize(0)
{
}
BpMemory::~BpMemory()
{
}
sp<IMemoryHeap> BpMemory::getMemory(ssize_t* offset, size_t* size) const
{
if (mHeap == 0) {
Parcel data, reply;
data.writeInterfaceToken(IMemory::getInterfaceDescriptor());
if (remote()->transact(GET_MEMORY, data, &reply) == NO_ERROR) {
sp<IBinder> heap = reply.readStrongBinder();
ssize_t o = reply.readInt32();
size_t s = reply.readInt32();
if (heap != 0) {
mHeap = interface_cast<IMemoryHeap>(heap);
if (mHeap != 0) {
size_t heapSize = mHeap->getSize();
if (s <= heapSize
&& o >= 0
&& (static_cast<size_t>(o) <= heapSize - s)) {
mOffset = o;
mSize = s;
} else {
// Hm.
android_errorWriteWithInfoLog(0x534e4554,
"26877992", -1, NULL, 0);
mOffset = 0;
mSize = 0;
}
}
}
}
}
if (offset) *offset = mOffset;
if (size) *size = mSize;
return (mSize > 0) ? mHeap : 0;
}
// ---------------------------------------------------------------------------
IMPLEMENT_META_INTERFACE(Memory, "android.utils.IMemory");
BnMemory::BnMemory() {
}
BnMemory::~BnMemory() {
}
status_t BnMemory::onTransact(
uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
{
switch(code) {
case GET_MEMORY: {
CHECK_INTERFACE(IMemory, data, reply);
ssize_t offset;
size_t size;
reply->writeStrongBinder( IInterface::asBinder(getMemory(&offset, &size)) );
reply->writeInt32(offset);
reply->writeInt32(size);
return NO_ERROR;
} break;
default:
return BBinder::onTransact(code, data, reply, flags);
}
}
/******************************************************************************/
BpMemoryHeap::BpMemoryHeap(const sp<IBinder>& impl)
: BpInterface<IMemoryHeap>(impl),
mHeapId(-1), mBase(MAP_FAILED), mSize(0), mFlags(0), mOffset(0), mRealHeap(false)
{
}
BpMemoryHeap::~BpMemoryHeap() {
int32_t heapId = mHeapId.load(memory_order_relaxed);
if (heapId != -1) {
close(heapId);
if (mRealHeap) {
// by construction we're the last one
if (mBase != MAP_FAILED) {
sp<IBinder> binder = IInterface::asBinder(this);
if (VERBOSE) {
ALOGD("UNMAPPING binder=%p, heap=%p, size=%zu, fd=%d",
binder.get(), this, mSize, heapId);
CallStack stack(LOG_TAG);
}
munmap(mBase, mSize);
}
} else {
// remove from list only if it was mapped before
sp<IBinder> binder = IInterface::asBinder(this);
free_heap(binder);
}
}
}
void BpMemoryHeap::assertMapped() const
{
int32_t heapId = mHeapId.load(memory_order_acquire);
if (heapId == -1) {
sp<IBinder> binder(IInterface::asBinder(const_cast<BpMemoryHeap*>(this)));
sp<BpMemoryHeap> heap(static_cast<BpMemoryHeap*>(find_heap(binder).get()));
heap->assertReallyMapped();
if (heap->mBase != MAP_FAILED) {
Mutex::Autolock _l(mLock);
if (mHeapId.load(memory_order_relaxed) == -1) {
mBase = heap->mBase;
mSize = heap->mSize;
mOffset = heap->mOffset;
int fd = fcntl(heap->mHeapId.load(memory_order_relaxed), F_DUPFD_CLOEXEC, 0);
ALOGE_IF(fd==-1, "cannot dup fd=%d",
heap->mHeapId.load(memory_order_relaxed));
mHeapId.store(fd, memory_order_release);
}
} else {
// something went wrong
free_heap(binder);
}
}
}
void BpMemoryHeap::assertReallyMapped() const
{
int32_t heapId = mHeapId.load(memory_order_acquire);
if (heapId == -1) {
// remote call without mLock held, worse case scenario, we end up
// calling transact() from multiple threads, but that's not a problem,
// only mmap below must be in the critical section.
Parcel data, reply;
data.writeInterfaceToken(IMemoryHeap::getInterfaceDescriptor());
status_t err = remote()->transact(HEAP_ID, data, &reply);
int parcel_fd = reply.readFileDescriptor();
ssize_t size = reply.readInt32();
uint32_t flags = reply.readInt32();
uint32_t offset = reply.readInt32();
ALOGE_IF(err, "binder=%p transaction failed fd=%d, size=%zd, err=%d (%s)",
IInterface::asBinder(this).get(),
parcel_fd, size, err, strerror(-err));
Mutex::Autolock _l(mLock);
if (mHeapId.load(memory_order_relaxed) == -1) {
int fd = fcntl(parcel_fd, F_DUPFD_CLOEXEC, 0);
ALOGE_IF(fd==-1, "cannot dup fd=%d, size=%zd, err=%d (%s)",
parcel_fd, size, err, strerror(errno));
int access = PROT_READ;
if (!(flags & READ_ONLY)) {
access |= PROT_WRITE;
}
mRealHeap = true;
mBase = mmap(0, size, access, MAP_SHARED, fd, offset);
if (mBase == MAP_FAILED) {
ALOGE("cannot map BpMemoryHeap (binder=%p), size=%zd, fd=%d (%s)",
IInterface::asBinder(this).get(), size, fd, strerror(errno));
close(fd);
} else {
mSize = size;
mFlags = flags;
mOffset = offset;
mHeapId.store(fd, memory_order_release);
}
}
}
}
int BpMemoryHeap::getHeapID() const {
assertMapped();
// We either stored mHeapId ourselves, or loaded it with acquire semantics.
return mHeapId.load(memory_order_relaxed);
}
void* BpMemoryHeap::getBase() const {
assertMapped();
return mBase;
}
size_t BpMemoryHeap::getSize() const {
assertMapped();
return mSize;
}
uint32_t BpMemoryHeap::getFlags() const {
assertMapped();
return mFlags;
}
uint32_t BpMemoryHeap::getOffset() const {
assertMapped();
return mOffset;
}
// ---------------------------------------------------------------------------
IMPLEMENT_META_INTERFACE(MemoryHeap, "android.utils.IMemoryHeap");
BnMemoryHeap::BnMemoryHeap() {
}
BnMemoryHeap::~BnMemoryHeap() {
}
status_t BnMemoryHeap::onTransact(
uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
{
switch(code) {
case HEAP_ID: {
CHECK_INTERFACE(IMemoryHeap, data, reply);
reply->writeFileDescriptor(getHeapID());
reply->writeInt32(getSize());
reply->writeInt32(getFlags());
reply->writeInt32(getOffset());
return NO_ERROR;
} break;
default:
return BBinder::onTransact(code, data, reply, flags);
}
}
/*****************************************************************************/
HeapCache::HeapCache()
: DeathRecipient()
{
}
HeapCache::~HeapCache()
{
}
void HeapCache::binderDied(const wp<IBinder>& binder)
{
//ALOGD("binderDied binder=%p", binder.unsafe_get());
free_heap(binder);
}
sp<IMemoryHeap> HeapCache::find_heap(const sp<IBinder>& binder)
{
Mutex::Autolock _l(mHeapCacheLock);
ssize_t i = mHeapCache.indexOfKey(binder);
if (i>=0) {
heap_info_t& info = mHeapCache.editValueAt(i);
ALOGD_IF(VERBOSE,
"found binder=%p, heap=%p, size=%zu, fd=%d, count=%d",
binder.get(), info.heap.get(),
static_cast<BpMemoryHeap*>(info.heap.get())->mSize,
static_cast<BpMemoryHeap*>(info.heap.get())
->mHeapId.load(memory_order_relaxed),
info.count);
++info.count;
return info.heap;
} else {
heap_info_t info;
info.heap = interface_cast<IMemoryHeap>(binder);
info.count = 1;
//ALOGD("adding binder=%p, heap=%p, count=%d",
// binder.get(), info.heap.get(), info.count);
mHeapCache.add(binder, info);
return info.heap;
}
}
void HeapCache::free_heap(const sp<IBinder>& binder) {
free_heap( wp<IBinder>(binder) );
}
void HeapCache::free_heap(const wp<IBinder>& binder)
{
sp<IMemoryHeap> rel;
{
Mutex::Autolock _l(mHeapCacheLock);
ssize_t i = mHeapCache.indexOfKey(binder);
if (i>=0) {
heap_info_t& info(mHeapCache.editValueAt(i));
if (--info.count == 0) {
ALOGD_IF(VERBOSE,
"removing binder=%p, heap=%p, size=%zu, fd=%d, count=%d",
binder.unsafe_get(), info.heap.get(),
static_cast<BpMemoryHeap*>(info.heap.get())->mSize,
static_cast<BpMemoryHeap*>(info.heap.get())
->mHeapId.load(memory_order_relaxed),
info.count);
rel = mHeapCache.valueAt(i).heap;
mHeapCache.removeItemsAt(i);
}
} else {
ALOGE("free_heap binder=%p not found!!!", binder.unsafe_get());
}
}
}
sp<IMemoryHeap> HeapCache::get_heap(const sp<IBinder>& binder)
{
sp<IMemoryHeap> realHeap;
Mutex::Autolock _l(mHeapCacheLock);
ssize_t i = mHeapCache.indexOfKey(binder);
if (i>=0) realHeap = mHeapCache.valueAt(i).heap;
else realHeap = interface_cast<IMemoryHeap>(binder);
return realHeap;
}
void HeapCache::dump_heaps()
{
Mutex::Autolock _l(mHeapCacheLock);
int c = mHeapCache.size();
for (int i=0 ; i<c ; i++) {
const heap_info_t& info = mHeapCache.valueAt(i);
BpMemoryHeap const* h(static_cast<BpMemoryHeap const *>(info.heap.get()));
ALOGD("hey=%p, heap=%p, count=%d, (fd=%d, base=%p, size=%zu)",
mHeapCache.keyAt(i).unsafe_get(),
info.heap.get(), info.count,
h->mHeapId.load(memory_order_relaxed), h->mBase, h->mSize);
}
}
// ---------------------------------------------------------------------------
}; // namespace android

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,130 @@
/*
* Copyright (C) 2005 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.
*/
#define LOG_TAG "PermissionController"
#include <binder/IPermissionController.h>
#include <utils/Log.h>
#include <binder/Parcel.h>
#include <utils/String8.h>
#include <private/binder/Static.h>
namespace android {
// ----------------------------------------------------------------------
class BpPermissionController : public BpInterface<IPermissionController>
{
public:
explicit BpPermissionController(const sp<IBinder>& impl)
: BpInterface<IPermissionController>(impl)
{
}
virtual bool checkPermission(const String16& permission, int32_t pid, int32_t uid)
{
Parcel data, reply;
data.writeInterfaceToken(IPermissionController::getInterfaceDescriptor());
data.writeString16(permission);
data.writeInt32(pid);
data.writeInt32(uid);
remote()->transact(CHECK_PERMISSION_TRANSACTION, data, &reply);
// fail on exception
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");
// ----------------------------------------------------------------------
status_t BnPermissionController::onTransact(
uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
{
switch(code) {
case CHECK_PERMISSION_TRANSACTION: {
CHECK_INTERFACE(IPermissionController, data, reply);
String16 permission = data.readString16();
int32_t pid = data.readInt32();
int32_t uid = data.readInt32();
bool res = checkPermission(permission, pid, uid);
reply->writeNoException();
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);
}
}
}; // namespace android

View file

@ -0,0 +1,91 @@
/*
* 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:
explicit 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();
}
virtual status_t getProcessStatesAndOomScoresFromPids(size_t length,
/*in*/ int32_t* pids, /*out*/ int32_t* states, /*out*/ int32_t* scores)
{
Parcel data, reply;
data.writeInterfaceToken(IProcessInfoService::getInterfaceDescriptor());
data.writeInt32Array(length, pids);
// write length of output arrays, used by java AIDL stubs
data.writeInt32(length);
data.writeInt32(length);
status_t err = remote()->transact(
GET_PROCESS_STATES_AND_OOM_SCORES_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;
}
replyLen = reply.readInt32();
if (static_cast<size_t>(replyLen) != length) {
return NOT_ENOUGH_DATA;
}
if (replyLen > 0 && (err = reply.read(
scores, length * sizeof(*scores))) != NO_ERROR) {
return err;
}
return reply.readInt32();
}
};
IMPLEMENT_META_INTERFACE(ProcessInfoService, "android.os.IProcessInfoService");
// ----------------------------------------------------------------------
}; // namespace android

View file

@ -0,0 +1,69 @@
/*
* Copyright (C) 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.
*/
#define LOG_TAG "ResultReceiver"
#include <binder/IResultReceiver.h>
#include <utils/Log.h>
#include <binder/Parcel.h>
#include <utils/String8.h>
#include <private/binder/Static.h>
namespace android {
// ----------------------------------------------------------------------
class BpResultReceiver : public BpInterface<IResultReceiver>
{
public:
explicit BpResultReceiver(const sp<IBinder>& impl)
: BpInterface<IResultReceiver>(impl)
{
}
virtual void send(int32_t resultCode) {
Parcel data;
data.writeInterfaceToken(IResultReceiver::getInterfaceDescriptor());
data.writeInt32(resultCode);
remote()->transact(OP_SEND, data, NULL, IBinder::FLAG_ONEWAY);
}
};
IMPLEMENT_META_INTERFACE(ResultReceiver, "com.android.internal.os.IResultReceiver");
// ----------------------------------------------------------------------
status_t BnResultReceiver::onTransact(
uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
{
switch(code) {
case OP_SEND: {
CHECK_INTERFACE(IResultReceiver, data, reply);
int32_t resultCode = data.readInt32();
send(resultCode);
if (reply != NULL) {
reply->writeNoException();
}
return NO_ERROR;
} break;
default:
return BBinder::onTransact(code, data, reply, flags);
}
}
}; // namespace android

View file

@ -0,0 +1,195 @@
/*
* Copyright (C) 2005 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.
*/
#define LOG_TAG "ServiceManager"
#include <binder/IServiceManager.h>
#include <utils/Log.h>
#include <binder/IPCThreadState.h>
#include <binder/Parcel.h>
#include <utils/String8.h>
#include <utils/SystemClock.h>
#include <utils/CallStack.h>
#include <private/binder/Static.h>
#include <unistd.h>
namespace android {
sp<IServiceManager> defaultServiceManager()
{
if (gDefaultServiceManager != NULL) return gDefaultServiceManager;
{
AutoMutex _l(gDefaultServiceManagerLock);
while (gDefaultServiceManager == NULL) {
gDefaultServiceManager = interface_cast<IServiceManager>(
ProcessState::self()->getContextObject(NULL));
if (gDefaultServiceManager == NULL)
sleep(1);
}
}
return gDefaultServiceManager;
}
bool checkCallingPermission(const String16& permission)
{
return checkCallingPermission(permission, NULL, NULL);
}
static String16 _permission("permission");
bool checkCallingPermission(const String16& permission, int32_t* outPid, int32_t* outUid)
{
IPCThreadState* ipcState = IPCThreadState::self();
pid_t pid = ipcState->getCallingPid();
uid_t uid = ipcState->getCallingUid();
if (outPid) *outPid = pid;
if (outUid) *outUid = uid;
return checkPermission(permission, pid, uid);
}
bool checkPermission(const String16& permission, pid_t pid, uid_t uid)
{
sp<IPermissionController> pc;
gDefaultServiceManagerLock.lock();
pc = gPermissionController;
gDefaultServiceManagerLock.unlock();
int64_t startTime = 0;
while (true) {
if (pc != NULL) {
bool res = pc->checkPermission(permission, pid, uid);
if (res) {
if (startTime != 0) {
ALOGI("Check passed after %d seconds for %s from uid=%d pid=%d",
(int)((uptimeMillis()-startTime)/1000),
String8(permission).string(), uid, pid);
}
return res;
}
// Is this a permission failure, or did the controller go away?
if (IInterface::asBinder(pc)->isBinderAlive()) {
ALOGW("Permission failure: %s from uid=%d pid=%d",
String8(permission).string(), uid, pid);
return false;
}
// Object is dead!
gDefaultServiceManagerLock.lock();
if (gPermissionController == pc) {
gPermissionController = NULL;
}
gDefaultServiceManagerLock.unlock();
}
// Need to retrieve the permission controller.
sp<IBinder> binder = defaultServiceManager()->checkService(_permission);
if (binder == NULL) {
// Wait for the permission controller to come back...
if (startTime == 0) {
startTime = uptimeMillis();
ALOGI("Waiting to check permission %s from uid=%d pid=%d",
String8(permission).string(), uid, pid);
}
sleep(1);
} else {
pc = interface_cast<IPermissionController>(binder);
// Install the new permission controller, and try again.
gDefaultServiceManagerLock.lock();
gPermissionController = pc;
gDefaultServiceManagerLock.unlock();
}
}
}
// ----------------------------------------------------------------------
class BpServiceManager : public BpInterface<IServiceManager>
{
public:
explicit BpServiceManager(const sp<IBinder>& impl)
: BpInterface<IServiceManager>(impl)
{
}
virtual sp<IBinder> getService(const String16& name) const
{
unsigned n;
for (n = 0; n < 5; n++){
if (n > 0) {
if (!strcmp(ProcessState::self()->getDriverName().c_str(), "/dev/vndbinder")) {
ALOGI("Waiting for vendor service %s...", String8(name).string());
CallStack stack(LOG_TAG);
} else {
ALOGI("Waiting for service %s...", String8(name).string());
}
sleep(1);
}
sp<IBinder> svc = checkService(name);
if (svc != NULL) return svc;
}
return NULL;
}
virtual sp<IBinder> checkService( const String16& name) const
{
Parcel data, reply;
data.writeInterfaceToken(IServiceManager::getInterfaceDescriptor());
data.writeString16(name);
remote()->transact(CHECK_SERVICE_TRANSACTION, data, &reply);
return reply.readStrongBinder();
}
virtual status_t addService(const String16& name, const sp<IBinder>& service,
bool allowIsolated)
{
Parcel data, reply;
data.writeInterfaceToken(IServiceManager::getInterfaceDescriptor());
data.writeString16(name);
data.writeStrongBinder(service);
data.writeInt32(allowIsolated ? 1 : 0);
status_t err = remote()->transact(ADD_SERVICE_TRANSACTION, data, &reply);
return err == NO_ERROR ? reply.readExceptionCode() : err;
}
virtual Vector<String16> listServices()
{
Vector<String16> res;
int n = 0;
for (;;) {
Parcel data, reply;
data.writeInterfaceToken(IServiceManager::getInterfaceDescriptor());
data.writeInt32(n++);
status_t err = remote()->transact(LIST_SERVICES_TRANSACTION, data, &reply);
if (err != NO_ERROR)
break;
res.add(reply.readString16());
}
return res;
}
};
IMPLEMENT_META_INTERFACE(ServiceManager, "android.os.IServiceManager");
}; // namespace android

View file

@ -0,0 +1,86 @@
/*
* Copyright (C) 2016 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.
*/
#define LOG_TAG "ShellCallback"
#include <unistd.h>
#include <fcntl.h>
#include <binder/IShellCallback.h>
#include <utils/Log.h>
#include <binder/Parcel.h>
#include <utils/String8.h>
#include <private/binder/Static.h>
namespace android {
// ----------------------------------------------------------------------
class BpShellCallback : public BpInterface<IShellCallback>
{
public:
explicit BpShellCallback(const sp<IBinder>& impl)
: BpInterface<IShellCallback>(impl)
{
}
virtual int openOutputFile(const String16& path, const String16& seLinuxContext) {
Parcel data, reply;
data.writeInterfaceToken(IShellCallback::getInterfaceDescriptor());
data.writeString16(path);
data.writeString16(seLinuxContext);
remote()->transact(OP_OPEN_OUTPUT_FILE, data, &reply, 0);
reply.readExceptionCode();
int fd = reply.readParcelFileDescriptor();
return fd >= 0 ? fcntl(fd, F_DUPFD_CLOEXEC, 0) : fd;
}
};
IMPLEMENT_META_INTERFACE(ShellCallback, "com.android.internal.os.IShellCallback");
// ----------------------------------------------------------------------
status_t BnShellCallback::onTransact(
uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
{
switch(code) {
case OP_OPEN_OUTPUT_FILE: {
CHECK_INTERFACE(IShellCallback, data, reply);
String16 path(data.readString16());
String16 seLinuxContext(data.readString16());
int fd = openOutputFile(path, seLinuxContext);
if (reply != NULL) {
reply->writeNoException();
if (fd >= 0) {
reply->writeInt32(1);
reply->writeParcelFileDescriptor(fd, true);
} else {
reply->writeInt32(0);
}
} else if (fd >= 0) {
close(fd);
}
return NO_ERROR;
} break;
default:
return BBinder::onTransact(code, data, reply, flags);
}
}
}; // namespace android

View file

@ -0,0 +1,174 @@
/*
* Copyright (C) 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.
*/
#define LOG_TAG "IpPrefix"
#include <binder/IpPrefix.h>
#include <vector>
#include <binder/IBinder.h>
#include <binder/Parcel.h>
#include <log/log.h>
#include <utils/Errors.h>
using android::BAD_TYPE;
using android::BAD_VALUE;
using android::NO_ERROR;
using android::Parcel;
using android::status_t;
using android::UNEXPECTED_NULL;
using namespace ::android::binder;
namespace android {
namespace net {
#define RETURN_IF_FAILED(calledOnce) \
{ \
status_t returnStatus = calledOnce; \
if (returnStatus) { \
ALOGE("Failed at %s:%d (%s)", __FILE__, __LINE__, __func__); \
return returnStatus; \
} \
}
status_t IpPrefix::writeToParcel(Parcel* parcel) const {
/*
* Keep implementation in sync with writeToParcel() in
* frameworks/base/core/java/android/net/IpPrefix.java.
*/
std::vector<uint8_t> byte_vector;
if (mIsIpv6) {
const uint8_t* bytes = reinterpret_cast<const uint8_t*>(&mUnion.mIn6Addr);
byte_vector.insert(byte_vector.end(), bytes, bytes+sizeof(mUnion.mIn6Addr));
} else {
const uint8_t* bytes = reinterpret_cast<const uint8_t*>(&mUnion.mInAddr);
byte_vector.insert(byte_vector.end(), bytes, bytes+sizeof(mUnion.mIn6Addr));
}
RETURN_IF_FAILED(parcel->writeByteVector(byte_vector));
RETURN_IF_FAILED(parcel->writeInt32(static_cast<int32_t>(mPrefixLength)));
return NO_ERROR;
}
status_t IpPrefix::readFromParcel(const Parcel* parcel) {
/*
* Keep implementation in sync with readFromParcel() in
* frameworks/base/core/java/android/net/IpPrefix.java.
*/
std::vector<uint8_t> byte_vector;
RETURN_IF_FAILED(parcel->readByteVector(&byte_vector));
RETURN_IF_FAILED(parcel->readInt32(&mPrefixLength));
if (byte_vector.size() == 16) {
mIsIpv6 = true;
memcpy((void*)&mUnion.mIn6Addr, &byte_vector[0], sizeof(mUnion.mIn6Addr));
} else if (byte_vector.size() == 4) {
mIsIpv6 = false;
memcpy((void*)&mUnion.mInAddr, &byte_vector[0], sizeof(mUnion.mInAddr));
} else {
ALOGE("Failed at %s:%d (%s)", __FILE__, __LINE__, __func__); \
return BAD_VALUE;
}
return NO_ERROR;
}
const struct in6_addr& IpPrefix::getAddressAsIn6Addr() const
{
return mUnion.mIn6Addr;
}
const struct in_addr& IpPrefix::getAddressAsInAddr() const
{
return mUnion.mInAddr;
}
bool IpPrefix::getAddressAsIn6Addr(struct in6_addr* addr) const
{
if (isIpv6()) {
*addr = mUnion.mIn6Addr;
return true;
}
return false;
}
bool IpPrefix::getAddressAsInAddr(struct in_addr* addr) const
{
if (isIpv4()) {
*addr = mUnion.mInAddr;
return true;
}
return false;
}
bool IpPrefix::isIpv6() const
{
return mIsIpv6;
}
bool IpPrefix::isIpv4() const
{
return !mIsIpv6;
}
int32_t IpPrefix::getPrefixLength() const
{
return mPrefixLength;
}
void IpPrefix::setAddress(const struct in6_addr& addr)
{
mUnion.mIn6Addr = addr;
mIsIpv6 = true;
}
void IpPrefix::setAddress(const struct in_addr& addr)
{
mUnion.mInAddr = addr;
mIsIpv6 = false;
}
void IpPrefix::setPrefixLength(int32_t prefix)
{
mPrefixLength = prefix;
}
bool operator==(const IpPrefix& lhs, const IpPrefix& rhs)
{
if (lhs.mIsIpv6 != rhs.mIsIpv6) {
return false;
}
if (lhs.mPrefixLength != rhs.mPrefixLength) {
return false;
}
if (lhs.mIsIpv6) {
return 0 == memcmp(lhs.mUnion.mIn6Addr.s6_addr, rhs.mUnion.mIn6Addr.s6_addr, sizeof(struct in6_addr));
}
return 0 == memcmp(&lhs.mUnion.mInAddr, &rhs.mUnion.mInAddr, sizeof(struct in_addr));
}
} // namespace net
} // namespace android

View file

@ -0,0 +1,46 @@
/*
* Copyright (C) 2008 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 <stdlib.h>
#include <stdint.h>
#include <binder/MemoryBase.h>
namespace android {
// ---------------------------------------------------------------------------
MemoryBase::MemoryBase(const sp<IMemoryHeap>& heap,
ssize_t offset, size_t size)
: mSize(size), mOffset(offset), mHeap(heap)
{
}
sp<IMemoryHeap> MemoryBase::getMemory(ssize_t* offset, size_t* size) const
{
if (offset) *offset = mOffset;
if (size) *size = mSize;
return mHeap;
}
MemoryBase::~MemoryBase()
{
}
// ---------------------------------------------------------------------------
}; // namespace android

View file

@ -0,0 +1,476 @@
/*
* Copyright (C) 2007 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.
*/
#define LOG_TAG "MemoryDealer"
#include <binder/MemoryDealer.h>
#include <binder/IPCThreadState.h>
#include <binder/MemoryBase.h>
#include <utils/Log.h>
#include <utils/SortedVector.h>
#include <utils/String8.h>
#include <utils/threads.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/mman.h>
#include <sys/file.h>
namespace android {
// ----------------------------------------------------------------------------
/*
* A simple templatized doubly linked-list implementation
*/
template <typename NODE>
class LinkedList
{
NODE* mFirst;
NODE* mLast;
public:
LinkedList() : mFirst(0), mLast(0) { }
bool isEmpty() const { return mFirst == 0; }
NODE const* head() const { return mFirst; }
NODE* head() { return mFirst; }
NODE const* tail() const { return mLast; }
NODE* tail() { return mLast; }
void insertAfter(NODE* node, NODE* newNode) {
newNode->prev = node;
newNode->next = node->next;
if (node->next == 0) mLast = newNode;
else node->next->prev = newNode;
node->next = newNode;
}
void insertBefore(NODE* node, NODE* newNode) {
newNode->prev = node->prev;
newNode->next = node;
if (node->prev == 0) mFirst = newNode;
else node->prev->next = newNode;
node->prev = newNode;
}
void insertHead(NODE* newNode) {
if (mFirst == 0) {
mFirst = mLast = newNode;
newNode->prev = newNode->next = 0;
} else {
newNode->prev = 0;
newNode->next = mFirst;
mFirst->prev = newNode;
mFirst = newNode;
}
}
void insertTail(NODE* newNode) {
if (mLast == 0) {
insertHead(newNode);
} else {
newNode->prev = mLast;
newNode->next = 0;
mLast->next = newNode;
mLast = newNode;
}
}
NODE* remove(NODE* node) {
if (node->prev == 0) mFirst = node->next;
else node->prev->next = node->next;
if (node->next == 0) mLast = node->prev;
else node->next->prev = node->prev;
return node;
}
};
// ----------------------------------------------------------------------------
class Allocation : public MemoryBase {
public:
Allocation(const sp<MemoryDealer>& dealer,
const sp<IMemoryHeap>& heap, ssize_t offset, size_t size);
virtual ~Allocation();
private:
sp<MemoryDealer> mDealer;
};
// ----------------------------------------------------------------------------
class SimpleBestFitAllocator
{
enum {
PAGE_ALIGNED = 0x00000001
};
public:
explicit SimpleBestFitAllocator(size_t size);
~SimpleBestFitAllocator();
size_t allocate(size_t size, uint32_t flags = 0);
status_t deallocate(size_t offset);
size_t size() const;
void dump(const char* what) const;
void dump(String8& res, const char* what) const;
static size_t getAllocationAlignment() { return kMemoryAlign; }
private:
struct chunk_t {
chunk_t(size_t start, size_t size)
: start(start), size(size), free(1), prev(0), next(0) {
}
size_t start;
size_t size : 28;
int free : 4;
mutable chunk_t* prev;
mutable chunk_t* next;
};
ssize_t alloc(size_t size, uint32_t flags);
chunk_t* dealloc(size_t start);
void dump_l(const char* what) const;
void dump_l(String8& res, const char* what) const;
static const int kMemoryAlign;
mutable Mutex mLock;
LinkedList<chunk_t> mList;
size_t mHeapSize;
};
// ----------------------------------------------------------------------------
Allocation::Allocation(
const sp<MemoryDealer>& dealer,
const sp<IMemoryHeap>& heap, ssize_t offset, size_t size)
: MemoryBase(heap, offset, size), mDealer(dealer)
{
#ifndef NDEBUG
void* const start_ptr = (void*)(intptr_t(heap->base()) + offset);
memset(start_ptr, 0xda, size);
#endif
}
Allocation::~Allocation()
{
size_t freedOffset = getOffset();
size_t freedSize = getSize();
if (freedSize) {
/* NOTE: it's VERY important to not free allocations of size 0 because
* they're special as they don't have any record in the allocator
* and could alias some real allocation (their offset is zero). */
// keep the size to unmap in excess
size_t pagesize = getpagesize();
size_t start = freedOffset;
size_t end = start + freedSize;
start &= ~(pagesize-1);
end = (end + pagesize-1) & ~(pagesize-1);
// give back to the kernel the pages we don't need
size_t free_start = freedOffset;
size_t free_end = free_start + freedSize;
if (start < free_start)
start = free_start;
if (end > free_end)
end = free_end;
start = (start + pagesize-1) & ~(pagesize-1);
end &= ~(pagesize-1);
if (start < end) {
void* const start_ptr = (void*)(intptr_t(getHeap()->base()) + start);
size_t size = end-start;
#ifndef NDEBUG
memset(start_ptr, 0xdf, size);
#endif
// MADV_REMOVE is not defined on Dapper based Goobuntu
#ifdef MADV_REMOVE
if (size) {
int err = madvise(start_ptr, size, MADV_REMOVE);
ALOGW_IF(err, "madvise(%p, %zu, MADV_REMOVE) returned %s",
start_ptr, size, err<0 ? strerror(errno) : "Ok");
}
#endif
}
// This should be done after madvise(MADV_REMOVE), otherwise madvise()
// might kick out the memory region that's allocated and/or written
// right after the deallocation.
mDealer->deallocate(freedOffset);
}
}
// ----------------------------------------------------------------------------
MemoryDealer::MemoryDealer(size_t size, const char* name, uint32_t flags)
: mHeap(new MemoryHeapBase(size, flags, name)),
mAllocator(new SimpleBestFitAllocator(size))
{
}
MemoryDealer::~MemoryDealer()
{
delete mAllocator;
}
sp<IMemory> MemoryDealer::allocate(size_t size)
{
sp<IMemory> memory;
const ssize_t offset = allocator()->allocate(size);
if (offset >= 0) {
memory = new Allocation(this, heap(), offset, size);
}
return memory;
}
void MemoryDealer::deallocate(size_t offset)
{
allocator()->deallocate(offset);
}
void MemoryDealer::dump(const char* what) const
{
allocator()->dump(what);
}
const sp<IMemoryHeap>& MemoryDealer::heap() const {
return mHeap;
}
SimpleBestFitAllocator* MemoryDealer::allocator() const {
return mAllocator;
}
// static
size_t MemoryDealer::getAllocationAlignment()
{
return SimpleBestFitAllocator::getAllocationAlignment();
}
// ----------------------------------------------------------------------------
// align all the memory blocks on a cache-line boundary
const int SimpleBestFitAllocator::kMemoryAlign = 32;
SimpleBestFitAllocator::SimpleBestFitAllocator(size_t size)
{
size_t pagesize = getpagesize();
mHeapSize = ((size + pagesize-1) & ~(pagesize-1));
chunk_t* node = new chunk_t(0, mHeapSize / kMemoryAlign);
mList.insertHead(node);
}
SimpleBestFitAllocator::~SimpleBestFitAllocator()
{
while(!mList.isEmpty()) {
delete mList.remove(mList.head());
}
}
size_t SimpleBestFitAllocator::size() const
{
return mHeapSize;
}
size_t SimpleBestFitAllocator::allocate(size_t size, uint32_t flags)
{
Mutex::Autolock _l(mLock);
ssize_t offset = alloc(size, flags);
return offset;
}
status_t SimpleBestFitAllocator::deallocate(size_t offset)
{
Mutex::Autolock _l(mLock);
chunk_t const * const freed = dealloc(offset);
if (freed) {
return NO_ERROR;
}
return NAME_NOT_FOUND;
}
ssize_t SimpleBestFitAllocator::alloc(size_t size, uint32_t flags)
{
if (size == 0) {
return 0;
}
size = (size + kMemoryAlign-1) / kMemoryAlign;
chunk_t* free_chunk = 0;
chunk_t* cur = mList.head();
size_t pagesize = getpagesize();
while (cur) {
int extra = 0;
if (flags & PAGE_ALIGNED)
extra = ( -cur->start & ((pagesize/kMemoryAlign)-1) ) ;
// best fit
if (cur->free && (cur->size >= (size+extra))) {
if ((!free_chunk) || (cur->size < free_chunk->size)) {
free_chunk = cur;
}
if (cur->size == size) {
break;
}
}
cur = cur->next;
}
if (free_chunk) {
const size_t free_size = free_chunk->size;
free_chunk->free = 0;
free_chunk->size = size;
if (free_size > size) {
int extra = 0;
if (flags & PAGE_ALIGNED)
extra = ( -free_chunk->start & ((pagesize/kMemoryAlign)-1) ) ;
if (extra) {
chunk_t* split = new chunk_t(free_chunk->start, extra);
free_chunk->start += extra;
mList.insertBefore(free_chunk, split);
}
ALOGE_IF((flags&PAGE_ALIGNED) &&
((free_chunk->start*kMemoryAlign)&(pagesize-1)),
"PAGE_ALIGNED requested, but page is not aligned!!!");
const ssize_t tail_free = free_size - (size+extra);
if (tail_free > 0) {
chunk_t* split = new chunk_t(
free_chunk->start + free_chunk->size, tail_free);
mList.insertAfter(free_chunk, split);
}
}
return (free_chunk->start)*kMemoryAlign;
}
return NO_MEMORY;
}
SimpleBestFitAllocator::chunk_t* SimpleBestFitAllocator::dealloc(size_t start)
{
start = start / kMemoryAlign;
chunk_t* cur = mList.head();
while (cur) {
if (cur->start == start) {
LOG_FATAL_IF(cur->free,
"block at offset 0x%08lX of size 0x%08lX already freed",
cur->start*kMemoryAlign, cur->size*kMemoryAlign);
// merge freed blocks together
chunk_t* freed = cur;
cur->free = 1;
do {
chunk_t* const p = cur->prev;
chunk_t* const n = cur->next;
if (p && (p->free || !cur->size)) {
freed = p;
p->size += cur->size;
mList.remove(cur);
delete cur;
}
cur = n;
} while (cur && cur->free);
#ifndef NDEBUG
if (!freed->free) {
dump_l("dealloc (!freed->free)");
}
#endif
LOG_FATAL_IF(!freed->free,
"freed block at offset 0x%08lX of size 0x%08lX is not free!",
freed->start * kMemoryAlign, freed->size * kMemoryAlign);
return freed;
}
cur = cur->next;
}
return 0;
}
void SimpleBestFitAllocator::dump(const char* what) const
{
Mutex::Autolock _l(mLock);
dump_l(what);
}
void SimpleBestFitAllocator::dump_l(const char* what) const
{
String8 result;
dump_l(result, what);
ALOGD("%s", result.string());
}
void SimpleBestFitAllocator::dump(String8& result,
const char* what) const
{
Mutex::Autolock _l(mLock);
dump_l(result, what);
}
void SimpleBestFitAllocator::dump_l(String8& result,
const char* what) const
{
size_t size = 0;
int32_t i = 0;
chunk_t const* cur = mList.head();
const size_t SIZE = 256;
char buffer[SIZE];
snprintf(buffer, SIZE, " %s (%p, size=%u)\n",
what, this, (unsigned int)mHeapSize);
result.append(buffer);
while (cur) {
const char* errs[] = {"", "| link bogus NP",
"| link bogus PN", "| link bogus NP+PN" };
int np = ((cur->next) && cur->next->prev != cur) ? 1 : 0;
int pn = ((cur->prev) && cur->prev->next != cur) ? 2 : 0;
snprintf(buffer, SIZE, " %3u: %p | 0x%08X | 0x%08X | %s %s\n",
i, cur, int(cur->start*kMemoryAlign),
int(cur->size*kMemoryAlign),
int(cur->free) ? "F" : "A",
errs[np|pn]);
result.append(buffer);
if (!cur->free)
size += cur->size*kMemoryAlign;
i++;
cur = cur->next;
}
snprintf(buffer, SIZE,
" size allocated: %u (%u KB)\n", int(size), int(size/1024));
result.append(buffer);
}
}; // namespace android

View file

@ -0,0 +1,177 @@
/*
* Copyright (C) 2008 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.
*/
#define LOG_TAG "MemoryHeapBase"
#include <errno.h>
#include <fcntl.h>
#include <stdint.h>
#include <stdlib.h>
#include <sys/ioctl.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#include <binder/MemoryHeapBase.h>
#include <cutils/ashmem.h>
#include <cutils/atomic.h>
#include <log/log.h>
namespace android {
// ---------------------------------------------------------------------------
MemoryHeapBase::MemoryHeapBase()
: mFD(-1), mSize(0), mBase(MAP_FAILED),
mDevice(NULL), mNeedUnmap(false), mOffset(0)
{
}
MemoryHeapBase::MemoryHeapBase(size_t size, uint32_t flags, char const * name)
: mFD(-1), mSize(0), mBase(MAP_FAILED), mFlags(flags),
mDevice(0), mNeedUnmap(false), mOffset(0)
{
const size_t pagesize = getpagesize();
size = ((size + pagesize-1) & ~(pagesize-1));
int fd = ashmem_create_region(name == NULL ? "MemoryHeapBase" : name, size);
ALOGE_IF(fd<0, "error creating ashmem region: %s", strerror(errno));
if (fd >= 0) {
if (mapfd(fd, size) == NO_ERROR) {
if (flags & READ_ONLY) {
ashmem_set_prot_region(fd, PROT_READ);
}
}
}
}
MemoryHeapBase::MemoryHeapBase(const char* device, size_t size, uint32_t flags)
: mFD(-1), mSize(0), mBase(MAP_FAILED), mFlags(flags),
mDevice(0), mNeedUnmap(false), mOffset(0)
{
int open_flags = O_RDWR;
if (flags & NO_CACHING)
open_flags |= O_SYNC;
int fd = open(device, open_flags);
ALOGE_IF(fd<0, "error opening %s: %s", device, strerror(errno));
if (fd >= 0) {
const size_t pagesize = getpagesize();
size = ((size + pagesize-1) & ~(pagesize-1));
if (mapfd(fd, size) == NO_ERROR) {
mDevice = device;
}
}
}
MemoryHeapBase::MemoryHeapBase(int fd, size_t size, uint32_t flags, uint32_t offset)
: mFD(-1), mSize(0), mBase(MAP_FAILED), mFlags(flags),
mDevice(0), mNeedUnmap(false), mOffset(0)
{
const size_t pagesize = getpagesize();
size = ((size + pagesize-1) & ~(pagesize-1));
mapfd(fcntl(fd, F_DUPFD_CLOEXEC, 0), size, offset);
}
status_t MemoryHeapBase::init(int fd, void *base, int size, int flags, const char* device)
{
if (mFD != -1) {
return INVALID_OPERATION;
}
mFD = fd;
mBase = base;
mSize = size;
mFlags = flags;
mDevice = device;
return NO_ERROR;
}
status_t MemoryHeapBase::mapfd(int fd, size_t size, uint32_t offset)
{
if (size == 0) {
// try to figure out the size automatically
struct stat sb;
if (fstat(fd, &sb) == 0)
size = sb.st_size;
// if it didn't work, let mmap() fail.
}
if ((mFlags & DONT_MAP_LOCALLY) == 0) {
void* base = (uint8_t*)mmap(0, size,
PROT_READ|PROT_WRITE, MAP_SHARED, fd, offset);
if (base == MAP_FAILED) {
ALOGE("mmap(fd=%d, size=%u) failed (%s)",
fd, uint32_t(size), strerror(errno));
close(fd);
return -errno;
}
//ALOGD("mmap(fd=%d, base=%p, size=%lu)", fd, base, size);
mBase = base;
mNeedUnmap = true;
} else {
mBase = 0; // not MAP_FAILED
mNeedUnmap = false;
}
mFD = fd;
mSize = size;
mOffset = offset;
return NO_ERROR;
}
MemoryHeapBase::~MemoryHeapBase()
{
dispose();
}
void MemoryHeapBase::dispose()
{
int fd = android_atomic_or(-1, &mFD);
if (fd >= 0) {
if (mNeedUnmap) {
//ALOGD("munmap(fd=%d, base=%p, size=%lu)", fd, mBase, mSize);
munmap(mBase, mSize);
}
mBase = 0;
mSize = 0;
close(fd);
}
}
int MemoryHeapBase::getHeapID() const {
return mFD;
}
void* MemoryHeapBase::getBase() const {
return mBase;
}
size_t MemoryHeapBase::getSize() const {
return mSize;
}
uint32_t MemoryHeapBase::getFlags() const {
return mFlags;
}
const char* MemoryHeapBase::getDevice() const {
return mDevice;
}
uint32_t MemoryHeapBase::getOffset() const {
return mOffset;
}
// ---------------------------------------------------------------------------
}; // namespace android

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,113 @@
/*
* Copyright (C) 2009 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.
*/
#define LOG_TAG "PermissionCache"
#include <stdint.h>
#include <utils/Log.h>
#include <binder/IPCThreadState.h>
#include <binder/IServiceManager.h>
#include <binder/PermissionCache.h>
#include <utils/String8.h>
namespace android {
// ----------------------------------------------------------------------------
ANDROID_SINGLETON_STATIC_INSTANCE(PermissionCache) ;
// ----------------------------------------------------------------------------
PermissionCache::PermissionCache() {
}
status_t PermissionCache::check(bool* granted,
const String16& permission, uid_t uid) const {
Mutex::Autolock _l(mLock);
Entry e;
e.name = permission;
e.uid = uid;
ssize_t index = mCache.indexOf(e);
if (index >= 0) {
*granted = mCache.itemAt(index).granted;
return NO_ERROR;
}
return NAME_NOT_FOUND;
}
void PermissionCache::cache(const String16& permission,
uid_t uid, bool granted) {
Mutex::Autolock _l(mLock);
Entry e;
ssize_t index = mPermissionNamesPool.indexOf(permission);
if (index > 0) {
e.name = mPermissionNamesPool.itemAt(index);
} else {
mPermissionNamesPool.add(permission);
e.name = permission;
}
// note, we don't need to store the pid, which is not actually used in
// permission checks
e.uid = uid;
e.granted = granted;
index = mCache.indexOf(e);
if (index < 0) {
mCache.add(e);
}
}
void PermissionCache::purge() {
Mutex::Autolock _l(mLock);
mCache.clear();
}
bool PermissionCache::checkCallingPermission(const String16& permission) {
return PermissionCache::checkCallingPermission(permission, NULL, NULL);
}
bool PermissionCache::checkCallingPermission(
const String16& permission, int32_t* outPid, int32_t* outUid) {
IPCThreadState* ipcState = IPCThreadState::self();
pid_t pid = ipcState->getCallingPid();
uid_t uid = ipcState->getCallingUid();
if (outPid) *outPid = pid;
if (outUid) *outUid = uid;
return PermissionCache::checkPermission(permission, pid, uid);
}
bool PermissionCache::checkPermission(
const String16& permission, pid_t pid, uid_t uid) {
if ((uid == 0) || (pid == getpid())) {
// root and ourselves is always okay
return true;
}
PermissionCache& pc(PermissionCache::getInstance());
bool granted = false;
if (pc.check(&granted, permission, uid) != NO_ERROR) {
nsecs_t t = -systemTime();
granted = android::checkPermission(permission, pid, uid);
t += systemTime();
ALOGD("checking %s for uid=%d => %s (%d us)",
String8(permission).string(), uid,
granted?"granted":"denied", (int)ns2us(t));
pc.cache(permission, uid, granted);
}
return granted;
}
// ---------------------------------------------------------------------------
}; // namespace android

View file

@ -0,0 +1,477 @@
/*
* Copyright (C) 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.
*/
#define LOG_TAG "PersistableBundle"
#include <binder/PersistableBundle.h>
#include <private/binder/ParcelValTypes.h>
#include <limits>
#include <binder/IBinder.h>
#include <binder/Parcel.h>
#include <log/log.h>
#include <utils/Errors.h>
using android::BAD_TYPE;
using android::BAD_VALUE;
using android::NO_ERROR;
using android::Parcel;
using android::sp;
using android::status_t;
using android::UNEXPECTED_NULL;
using std::map;
using std::set;
using std::vector;
using namespace ::android::binder;
enum {
// Keep in sync with BUNDLE_MAGIC in frameworks/base/core/java/android/os/BaseBundle.java.
BUNDLE_MAGIC = 0x4C444E42,
};
namespace {
template <typename T>
bool getValue(const android::String16& key, T* out, const map<android::String16, T>& map) {
const auto& it = map.find(key);
if (it == map.end()) return false;
*out = it->second;
return true;
}
template <typename T>
set<android::String16> getKeys(const map<android::String16, T>& map) {
if (map.empty()) return set<android::String16>();
set<android::String16> keys;
for (const auto& key_value_pair : map) {
keys.emplace(key_value_pair.first);
}
return keys;
}
} // namespace
namespace android {
namespace os {
#define RETURN_IF_FAILED(calledOnce) \
{ \
status_t returnStatus = calledOnce; \
if (returnStatus) { \
ALOGE("Failed at %s:%d (%s)", __FILE__, __LINE__, __func__); \
return returnStatus; \
} \
}
#define RETURN_IF_ENTRY_ERASED(map, key) \
{ \
size_t num_erased = (map).erase(key); \
if (num_erased) { \
ALOGE("Failed at %s:%d (%s)", __FILE__, __LINE__, __func__); \
return num_erased; \
} \
}
status_t PersistableBundle::writeToParcel(Parcel* parcel) const {
/*
* Keep implementation in sync with writeToParcelInner() in
* frameworks/base/core/java/android/os/BaseBundle.java.
*/
// Special case for empty bundles.
if (empty()) {
RETURN_IF_FAILED(parcel->writeInt32(0));
return NO_ERROR;
}
size_t length_pos = parcel->dataPosition();
RETURN_IF_FAILED(parcel->writeInt32(1)); // dummy, will hold length
RETURN_IF_FAILED(parcel->writeInt32(BUNDLE_MAGIC));
size_t start_pos = parcel->dataPosition();
RETURN_IF_FAILED(writeToParcelInner(parcel));
size_t end_pos = parcel->dataPosition();
// Backpatch length. This length value includes the length header.
parcel->setDataPosition(length_pos);
size_t length = end_pos - start_pos;
if (length > std::numeric_limits<int32_t>::max()) {
ALOGE("Parcel length (%zu) too large to store in 32-bit signed int", length);
return BAD_VALUE;
}
RETURN_IF_FAILED(parcel->writeInt32(static_cast<int32_t>(length)));
parcel->setDataPosition(end_pos);
return NO_ERROR;
}
status_t PersistableBundle::readFromParcel(const Parcel* parcel) {
/*
* Keep implementation in sync with readFromParcelInner() in
* frameworks/base/core/java/android/os/BaseBundle.java.
*/
int32_t length = parcel->readInt32();
if (length < 0) {
ALOGE("Bad length in parcel: %d", length);
return UNEXPECTED_NULL;
}
return readFromParcelInner(parcel, static_cast<size_t>(length));
}
bool PersistableBundle::empty() const {
return size() == 0u;
}
size_t PersistableBundle::size() const {
return (mBoolMap.size() +
mIntMap.size() +
mLongMap.size() +
mDoubleMap.size() +
mStringMap.size() +
mBoolVectorMap.size() +
mIntVectorMap.size() +
mLongVectorMap.size() +
mDoubleVectorMap.size() +
mStringVectorMap.size() +
mPersistableBundleMap.size());
}
size_t PersistableBundle::erase(const String16& key) {
RETURN_IF_ENTRY_ERASED(mBoolMap, key);
RETURN_IF_ENTRY_ERASED(mIntMap, key);
RETURN_IF_ENTRY_ERASED(mLongMap, key);
RETURN_IF_ENTRY_ERASED(mDoubleMap, key);
RETURN_IF_ENTRY_ERASED(mStringMap, key);
RETURN_IF_ENTRY_ERASED(mBoolVectorMap, key);
RETURN_IF_ENTRY_ERASED(mIntVectorMap, key);
RETURN_IF_ENTRY_ERASED(mLongVectorMap, key);
RETURN_IF_ENTRY_ERASED(mDoubleVectorMap, key);
RETURN_IF_ENTRY_ERASED(mStringVectorMap, key);
return mPersistableBundleMap.erase(key);
}
void PersistableBundle::putBoolean(const String16& key, bool value) {
erase(key);
mBoolMap[key] = value;
}
void PersistableBundle::putInt(const String16& key, int32_t value) {
erase(key);
mIntMap[key] = value;
}
void PersistableBundle::putLong(const String16& key, int64_t value) {
erase(key);
mLongMap[key] = value;
}
void PersistableBundle::putDouble(const String16& key, double value) {
erase(key);
mDoubleMap[key] = value;
}
void PersistableBundle::putString(const String16& key, const String16& value) {
erase(key);
mStringMap[key] = value;
}
void PersistableBundle::putBooleanVector(const String16& key, const vector<bool>& value) {
erase(key);
mBoolVectorMap[key] = value;
}
void PersistableBundle::putIntVector(const String16& key, const vector<int32_t>& value) {
erase(key);
mIntVectorMap[key] = value;
}
void PersistableBundle::putLongVector(const String16& key, const vector<int64_t>& value) {
erase(key);
mLongVectorMap[key] = value;
}
void PersistableBundle::putDoubleVector(const String16& key, const vector<double>& value) {
erase(key);
mDoubleVectorMap[key] = value;
}
void PersistableBundle::putStringVector(const String16& key, const vector<String16>& value) {
erase(key);
mStringVectorMap[key] = value;
}
void PersistableBundle::putPersistableBundle(const String16& key, const PersistableBundle& value) {
erase(key);
mPersistableBundleMap[key] = value;
}
bool PersistableBundle::getBoolean(const String16& key, bool* out) const {
return getValue(key, out, mBoolMap);
}
bool PersistableBundle::getInt(const String16& key, int32_t* out) const {
return getValue(key, out, mIntMap);
}
bool PersistableBundle::getLong(const String16& key, int64_t* out) const {
return getValue(key, out, mLongMap);
}
bool PersistableBundle::getDouble(const String16& key, double* out) const {
return getValue(key, out, mDoubleMap);
}
bool PersistableBundle::getString(const String16& key, String16* out) const {
return getValue(key, out, mStringMap);
}
bool PersistableBundle::getBooleanVector(const String16& key, vector<bool>* out) const {
return getValue(key, out, mBoolVectorMap);
}
bool PersistableBundle::getIntVector(const String16& key, vector<int32_t>* out) const {
return getValue(key, out, mIntVectorMap);
}
bool PersistableBundle::getLongVector(const String16& key, vector<int64_t>* out) const {
return getValue(key, out, mLongVectorMap);
}
bool PersistableBundle::getDoubleVector(const String16& key, vector<double>* out) const {
return getValue(key, out, mDoubleVectorMap);
}
bool PersistableBundle::getStringVector(const String16& key, vector<String16>* out) const {
return getValue(key, out, mStringVectorMap);
}
bool PersistableBundle::getPersistableBundle(const String16& key, PersistableBundle* out) const {
return getValue(key, out, mPersistableBundleMap);
}
set<String16> PersistableBundle::getBooleanKeys() const {
return getKeys(mBoolMap);
}
set<String16> PersistableBundle::getIntKeys() const {
return getKeys(mIntMap);
}
set<String16> PersistableBundle::getLongKeys() const {
return getKeys(mLongMap);
}
set<String16> PersistableBundle::getDoubleKeys() const {
return getKeys(mDoubleMap);
}
set<String16> PersistableBundle::getStringKeys() const {
return getKeys(mStringMap);
}
set<String16> PersistableBundle::getBooleanVectorKeys() const {
return getKeys(mBoolVectorMap);
}
set<String16> PersistableBundle::getIntVectorKeys() const {
return getKeys(mIntVectorMap);
}
set<String16> PersistableBundle::getLongVectorKeys() const {
return getKeys(mLongVectorMap);
}
set<String16> PersistableBundle::getDoubleVectorKeys() const {
return getKeys(mDoubleVectorMap);
}
set<String16> PersistableBundle::getStringVectorKeys() const {
return getKeys(mStringVectorMap);
}
set<String16> PersistableBundle::getPersistableBundleKeys() const {
return getKeys(mPersistableBundleMap);
}
status_t PersistableBundle::writeToParcelInner(Parcel* parcel) const {
/*
* To keep this implementation in sync with writeArrayMapInternal() in
* frameworks/base/core/java/android/os/Parcel.java, the number of key
* value pairs must be written into the parcel before writing the key-value
* pairs themselves.
*/
size_t num_entries = size();
if (num_entries > std::numeric_limits<int32_t>::max()) {
ALOGE("The size of this PersistableBundle (%zu) too large to store in 32-bit signed int",
num_entries);
return BAD_VALUE;
}
RETURN_IF_FAILED(parcel->writeInt32(static_cast<int32_t>(num_entries)));
for (const auto& key_val_pair : mBoolMap) {
RETURN_IF_FAILED(parcel->writeString16(key_val_pair.first));
RETURN_IF_FAILED(parcel->writeInt32(VAL_BOOLEAN));
RETURN_IF_FAILED(parcel->writeBool(key_val_pair.second));
}
for (const auto& key_val_pair : mIntMap) {
RETURN_IF_FAILED(parcel->writeString16(key_val_pair.first));
RETURN_IF_FAILED(parcel->writeInt32(VAL_INTEGER));
RETURN_IF_FAILED(parcel->writeInt32(key_val_pair.second));
}
for (const auto& key_val_pair : mLongMap) {
RETURN_IF_FAILED(parcel->writeString16(key_val_pair.first));
RETURN_IF_FAILED(parcel->writeInt32(VAL_LONG));
RETURN_IF_FAILED(parcel->writeInt64(key_val_pair.second));
}
for (const auto& key_val_pair : mDoubleMap) {
RETURN_IF_FAILED(parcel->writeString16(key_val_pair.first));
RETURN_IF_FAILED(parcel->writeInt32(VAL_DOUBLE));
RETURN_IF_FAILED(parcel->writeDouble(key_val_pair.second));
}
for (const auto& key_val_pair : mStringMap) {
RETURN_IF_FAILED(parcel->writeString16(key_val_pair.first));
RETURN_IF_FAILED(parcel->writeInt32(VAL_STRING));
RETURN_IF_FAILED(parcel->writeString16(key_val_pair.second));
}
for (const auto& key_val_pair : mBoolVectorMap) {
RETURN_IF_FAILED(parcel->writeString16(key_val_pair.first));
RETURN_IF_FAILED(parcel->writeInt32(VAL_BOOLEANARRAY));
RETURN_IF_FAILED(parcel->writeBoolVector(key_val_pair.second));
}
for (const auto& key_val_pair : mIntVectorMap) {
RETURN_IF_FAILED(parcel->writeString16(key_val_pair.first));
RETURN_IF_FAILED(parcel->writeInt32(VAL_INTARRAY));
RETURN_IF_FAILED(parcel->writeInt32Vector(key_val_pair.second));
}
for (const auto& key_val_pair : mLongVectorMap) {
RETURN_IF_FAILED(parcel->writeString16(key_val_pair.first));
RETURN_IF_FAILED(parcel->writeInt32(VAL_LONGARRAY));
RETURN_IF_FAILED(parcel->writeInt64Vector(key_val_pair.second));
}
for (const auto& key_val_pair : mDoubleVectorMap) {
RETURN_IF_FAILED(parcel->writeString16(key_val_pair.first));
RETURN_IF_FAILED(parcel->writeInt32(VAL_DOUBLEARRAY));
RETURN_IF_FAILED(parcel->writeDoubleVector(key_val_pair.second));
}
for (const auto& key_val_pair : mStringVectorMap) {
RETURN_IF_FAILED(parcel->writeString16(key_val_pair.first));
RETURN_IF_FAILED(parcel->writeInt32(VAL_STRINGARRAY));
RETURN_IF_FAILED(parcel->writeString16Vector(key_val_pair.second));
}
for (const auto& key_val_pair : mPersistableBundleMap) {
RETURN_IF_FAILED(parcel->writeString16(key_val_pair.first));
RETURN_IF_FAILED(parcel->writeInt32(VAL_PERSISTABLEBUNDLE));
RETURN_IF_FAILED(key_val_pair.second.writeToParcel(parcel));
}
return NO_ERROR;
}
status_t PersistableBundle::readFromParcelInner(const Parcel* parcel, size_t length) {
/*
* Note: we don't actually use length for anything other than an empty PersistableBundle
* check, since we do not actually need to copy in an entire Parcel, unlike in the Java
* implementation.
*/
if (length == 0) {
// Empty PersistableBundle or end of data.
return NO_ERROR;
}
int32_t magic;
RETURN_IF_FAILED(parcel->readInt32(&magic));
if (magic != BUNDLE_MAGIC) {
ALOGE("Bad magic number for PersistableBundle: 0x%08x", magic);
return BAD_VALUE;
}
/*
* To keep this implementation in sync with unparcel() in
* frameworks/base/core/java/android/os/BaseBundle.java, the number of
* key-value pairs must be read from the parcel before reading the key-value
* pairs themselves.
*/
int32_t num_entries;
RETURN_IF_FAILED(parcel->readInt32(&num_entries));
for (; num_entries > 0; --num_entries) {
String16 key;
int32_t value_type;
RETURN_IF_FAILED(parcel->readString16(&key));
RETURN_IF_FAILED(parcel->readInt32(&value_type));
/*
* We assume that both the C++ and Java APIs ensure that all keys in a PersistableBundle
* are unique.
*/
switch (value_type) {
case VAL_STRING: {
RETURN_IF_FAILED(parcel->readString16(&mStringMap[key]));
break;
}
case VAL_INTEGER: {
RETURN_IF_FAILED(parcel->readInt32(&mIntMap[key]));
break;
}
case VAL_LONG: {
RETURN_IF_FAILED(parcel->readInt64(&mLongMap[key]));
break;
}
case VAL_DOUBLE: {
RETURN_IF_FAILED(parcel->readDouble(&mDoubleMap[key]));
break;
}
case VAL_BOOLEAN: {
RETURN_IF_FAILED(parcel->readBool(&mBoolMap[key]));
break;
}
case VAL_STRINGARRAY: {
RETURN_IF_FAILED(parcel->readString16Vector(&mStringVectorMap[key]));
break;
}
case VAL_INTARRAY: {
RETURN_IF_FAILED(parcel->readInt32Vector(&mIntVectorMap[key]));
break;
}
case VAL_LONGARRAY: {
RETURN_IF_FAILED(parcel->readInt64Vector(&mLongVectorMap[key]));
break;
}
case VAL_BOOLEANARRAY: {
RETURN_IF_FAILED(parcel->readBoolVector(&mBoolVectorMap[key]));
break;
}
case VAL_PERSISTABLEBUNDLE: {
RETURN_IF_FAILED(mPersistableBundleMap[key].readFromParcel(parcel));
break;
}
case VAL_DOUBLEARRAY: {
RETURN_IF_FAILED(parcel->readDoubleVector(&mDoubleVectorMap[key]));
break;
}
default: {
ALOGE("Unrecognized type: %d", value_type);
return BAD_TYPE;
break;
}
}
}
return NO_ERROR;
}
} // namespace os
} // namespace android

View file

@ -0,0 +1,104 @@
/*
* 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;
}
status_t ProcessInfoService::getProcessStatesScoresImpl(size_t length,
/*in*/ int32_t* pids, /*out*/ int32_t* states,
/*out*/ int32_t *scores) {
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->getProcessStatesAndOomScoresFromPids(length,
/*in*/ pids, /*out*/ states, /*out*/ scores);
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 and scores "
"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

View file

@ -0,0 +1,444 @@
/*
* Copyright (C) 2005 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.
*/
#define LOG_TAG "ProcessState"
#include <binder/ProcessState.h>
#include <utils/Atomic.h>
#include <binder/BpBinder.h>
#include <binder/IPCThreadState.h>
#include <utils/Log.h>
#include <utils/String8.h>
#include <binder/IServiceManager.h>
#include <utils/String8.h>
#include <utils/threads.h>
#include <private/binder/binder_module.h>
#include <private/binder/Static.h>
#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <sys/types.h>
#define BINDER_VM_SIZE ((1 * 1024 * 1024) - sysconf(_SC_PAGE_SIZE) * 2)
#define DEFAULT_MAX_BINDER_THREADS 15
// -------------------------------------------------------------------------
namespace android {
class PoolThread : public Thread
{
public:
explicit PoolThread(bool isMain)
: mIsMain(isMain)
{
}
protected:
virtual bool threadLoop()
{
IPCThreadState::self()->joinThreadPool(mIsMain);
return false;
}
const bool mIsMain;
};
sp<ProcessState> ProcessState::self()
{
Mutex::Autolock _l(gProcessMutex);
if (gProcess != NULL) {
return gProcess;
}
gProcess = new ProcessState("/dev/binder");
return gProcess;
}
sp<ProcessState> ProcessState::initWithDriver(const char* driver)
{
Mutex::Autolock _l(gProcessMutex);
if (gProcess != NULL) {
// Allow for initWithDriver to be called repeatedly with the same
// driver.
if (!strcmp(gProcess->getDriverName().c_str(), driver)) {
return gProcess;
}
LOG_ALWAYS_FATAL("ProcessState was already initialized.");
}
gProcess = new ProcessState(driver);
return gProcess;
}
sp<ProcessState> ProcessState::selfOrNull()
{
Mutex::Autolock _l(gProcessMutex);
return gProcess;
}
void ProcessState::setContextObject(const sp<IBinder>& object)
{
setContextObject(object, String16("default"));
}
sp<IBinder> ProcessState::getContextObject(const sp<IBinder>& /*caller*/)
{
return getStrongProxyForHandle(0);
}
void ProcessState::setContextObject(const sp<IBinder>& object, const String16& name)
{
AutoMutex _l(mLock);
mContexts.add(name, object);
}
sp<IBinder> ProcessState::getContextObject(const String16& name, const sp<IBinder>& caller)
{
mLock.lock();
sp<IBinder> object(
mContexts.indexOfKey(name) >= 0 ? mContexts.valueFor(name) : NULL);
mLock.unlock();
//printf("Getting context object %s for %p\n", String8(name).string(), caller.get());
if (object != NULL) return object;
// Don't attempt to retrieve contexts if we manage them
if (mManagesContexts) {
ALOGE("getContextObject(%s) failed, but we manage the contexts!\n",
String8(name).string());
return NULL;
}
IPCThreadState* ipc = IPCThreadState::self();
{
Parcel data, reply;
// no interface token on this magic transaction
data.writeString16(name);
data.writeStrongBinder(caller);
status_t result = ipc->transact(0 /*magic*/, 0, data, &reply, 0);
if (result == NO_ERROR) {
object = reply.readStrongBinder();
}
}
ipc->flushCommands();
if (object != NULL) setContextObject(object, name);
return object;
}
void ProcessState::startThreadPool()
{
AutoMutex _l(mLock);
if (!mThreadPoolStarted) {
mThreadPoolStarted = true;
spawnPooledThread(true);
}
}
bool ProcessState::isContextManager(void) const
{
return mManagesContexts;
}
bool ProcessState::becomeContextManager(context_check_func checkFunc, void* userData)
{
if (!mManagesContexts) {
AutoMutex _l(mLock);
mBinderContextCheckFunc = checkFunc;
mBinderContextUserData = userData;
int dummy = 0;
status_t result = ioctl(mDriverFD, BINDER_SET_CONTEXT_MGR, &dummy);
if (result == 0) {
mManagesContexts = true;
} else if (result == -1) {
mBinderContextCheckFunc = NULL;
mBinderContextUserData = NULL;
ALOGE("Binder ioctl to become context manager failed: %s\n", strerror(errno));
}
}
return mManagesContexts;
}
// Get references to userspace objects held by the kernel binder driver
// Writes up to count elements into buf, and returns the total number
// of references the kernel has, which may be larger than count.
// buf may be NULL if count is 0. The pointers returned by this method
// should only be used for debugging and not dereferenced, they may
// already be invalid.
ssize_t ProcessState::getKernelReferences(size_t buf_count, uintptr_t* buf)
{
// TODO: remove these when they are defined by bionic's binder.h
struct binder_node_debug_info {
binder_uintptr_t ptr;
binder_uintptr_t cookie;
__u32 has_strong_ref;
__u32 has_weak_ref;
};
#define BINDER_GET_NODE_DEBUG_INFO _IOWR('b', 11, struct binder_node_debug_info)
binder_node_debug_info info = {};
uintptr_t* end = buf ? buf + buf_count : NULL;
size_t count = 0;
do {
status_t result = ioctl(mDriverFD, BINDER_GET_NODE_DEBUG_INFO, &info);
if (result < 0) {
return -1;
}
if (info.ptr != 0) {
if (buf && buf < end)
*buf++ = info.ptr;
count++;
if (buf && buf < end)
*buf++ = info.cookie;
count++;
}
} while (info.ptr != 0);
return count;
}
ProcessState::handle_entry* ProcessState::lookupHandleLocked(int32_t handle)
{
const size_t N=mHandleToObject.size();
if (N <= (size_t)handle) {
handle_entry e;
e.binder = NULL;
e.refs = NULL;
status_t err = mHandleToObject.insertAt(e, N, handle+1-N);
if (err < NO_ERROR) return NULL;
}
return &mHandleToObject.editItemAt(handle);
}
sp<IBinder> ProcessState::getStrongProxyForHandle(int32_t handle)
{
sp<IBinder> result;
AutoMutex _l(mLock);
handle_entry* e = lookupHandleLocked(handle);
if (e != NULL) {
// We need to create a new BpBinder if there isn't currently one, OR we
// are unable to acquire a weak reference on this current one. See comment
// in getWeakProxyForHandle() for more info about this.
IBinder* b = e->binder;
if (b == NULL || !e->refs->attemptIncWeak(this)) {
if (handle == 0) {
// Special case for context manager...
// The context manager is the only object for which we create
// a BpBinder proxy without already holding a reference.
// Perform a dummy transaction to ensure the context manager
// is registered before we create the first local reference
// to it (which will occur when creating the BpBinder).
// If a local reference is created for the BpBinder when the
// context manager is not present, the driver will fail to
// provide a reference to the context manager, but the
// driver API does not return status.
//
// Note that this is not race-free if the context manager
// dies while this code runs.
//
// TODO: add a driver API to wait for context manager, or
// stop special casing handle 0 for context manager and add
// a driver API to get a handle to the context manager with
// proper reference counting.
Parcel data;
status_t status = IPCThreadState::self()->transact(
0, IBinder::PING_TRANSACTION, data, NULL, 0);
if (status == DEAD_OBJECT)
return NULL;
}
b = new BpBinder(handle);
e->binder = b;
if (b) e->refs = b->getWeakRefs();
result = b;
} else {
// This little bit of nastyness is to allow us to add a primary
// reference to the remote proxy when this team doesn't have one
// but another team is sending the handle to us.
result.force_set(b);
e->refs->decWeak(this);
}
}
return result;
}
wp<IBinder> ProcessState::getWeakProxyForHandle(int32_t handle)
{
wp<IBinder> result;
AutoMutex _l(mLock);
handle_entry* e = lookupHandleLocked(handle);
if (e != NULL) {
// We need to create a new BpBinder if there isn't currently one, OR we
// are unable to acquire a weak reference on this current one. The
// attemptIncWeak() is safe because we know the BpBinder destructor will always
// call expungeHandle(), which acquires the same lock we are holding now.
// We need to do this because there is a race condition between someone
// releasing a reference on this BpBinder, and a new reference on its handle
// arriving from the driver.
IBinder* b = e->binder;
if (b == NULL || !e->refs->attemptIncWeak(this)) {
b = new BpBinder(handle);
result = b;
e->binder = b;
if (b) e->refs = b->getWeakRefs();
} else {
result = b;
e->refs->decWeak(this);
}
}
return result;
}
void ProcessState::expungeHandle(int32_t handle, IBinder* binder)
{
AutoMutex _l(mLock);
handle_entry* e = lookupHandleLocked(handle);
// This handle may have already been replaced with a new BpBinder
// (if someone failed the AttemptIncWeak() above); we don't want
// to overwrite it.
if (e && e->binder == binder) e->binder = NULL;
}
String8 ProcessState::makeBinderThreadName() {
int32_t s = android_atomic_add(1, &mThreadPoolSeq);
pid_t pid = getpid();
String8 name;
name.appendFormat("Binder:%d_%X", pid, s);
return name;
}
void ProcessState::spawnPooledThread(bool isMain)
{
if (mThreadPoolStarted) {
String8 name = makeBinderThreadName();
ALOGV("Spawning new pooled thread, name=%s\n", name.string());
sp<Thread> t = new PoolThread(isMain);
t->run(name.string());
}
}
status_t ProcessState::setThreadPoolMaxThreadCount(size_t maxThreads) {
status_t result = NO_ERROR;
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));
}
return result;
}
void ProcessState::giveThreadPoolName() {
androidSetThreadName( makeBinderThreadName().string() );
}
String8 ProcessState::getDriverName() {
return mDriverName;
}
static int open_driver(const char *driver)
{
int fd = open(driver, O_RDWR | O_CLOEXEC);
if (fd >= 0) {
int vers = 0;
status_t result = ioctl(fd, BINDER_VERSION, &vers);
if (result == -1) {
ALOGE("Binder ioctl to obtain version failed: %s", strerror(errno));
close(fd);
fd = -1;
}
if (result != 0 || vers != BINDER_CURRENT_PROTOCOL_VERSION) {
ALOGE("Binder driver protocol(%d) does not match user space protocol(%d)! ioctl() return value: %d",
vers, BINDER_CURRENT_PROTOCOL_VERSION, result);
close(fd);
fd = -1;
}
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));
}
} else {
ALOGW("Opening '%s' failed: %s\n", driver, strerror(errno));
}
return fd;
}
ProcessState::ProcessState(const char *driver)
: mDriverName(String8(driver))
, mDriverFD(open_driver(driver))
, mVMStart(MAP_FAILED)
, mThreadCountLock(PTHREAD_MUTEX_INITIALIZER)
, mThreadCountDecrement(PTHREAD_COND_INITIALIZER)
, mExecutingThreadsCount(0)
, mMaxThreads(DEFAULT_MAX_BINDER_THREADS)
, mStarvationStartTimeMs(0)
, mManagesContexts(false)
, mBinderContextCheckFunc(NULL)
, mBinderContextUserData(NULL)
, mThreadPoolStarted(false)
, mThreadPoolSeq(1)
{
if (mDriverFD >= 0) {
// mmap the binder, providing a chunk of virtual address space to receive transactions.
mVMStart = mmap(0, BINDER_VM_SIZE, PROT_READ, MAP_PRIVATE | MAP_NORESERVE, mDriverFD, 0);
if (mVMStart == MAP_FAILED) {
// *sigh*
ALOGE("Using /dev/binder failed: unable to mmap transaction memory.\n");
close(mDriverFD);
mDriverFD = -1;
mDriverName.clear();
}
}
LOG_ALWAYS_FATAL_IF(mDriverFD < 0, "Binder driver could not be opened. Terminating.");
}
ProcessState::~ProcessState()
{
if (mDriverFD >= 0) {
if (mVMStart != MAP_FAILED) {
munmap(mVMStart, BINDER_VM_SIZE);
}
close(mDriverFD);
}
mDriverFD = -1;
}
}; // namespace android

View file

@ -0,0 +1,99 @@
/*
* Copyright (C) 2008 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.
*/
// All static variables go here, to control initialization and
// destruction order in the library.
#include <private/binder/Static.h>
#include <binder/BufferedTextOutput.h>
#include <binder/IPCThreadState.h>
#include <utils/Log.h>
namespace android {
// ------------ Text output streams
Vector<int32_t> gTextBuffers;
class LogTextOutput : public BufferedTextOutput
{
public:
LogTextOutput() : BufferedTextOutput(MULTITHREADED) { }
virtual ~LogTextOutput() { };
protected:
virtual status_t writeLines(const struct iovec& vec, size_t N)
{
//android_writevLog(&vec, N); <-- this is now a no-op
if (N != 1) ALOGI("WARNING: writeLines N=%zu\n", N);
ALOGI("%.*s", (int)vec.iov_len, (const char*) vec.iov_base);
return NO_ERROR;
}
};
class FdTextOutput : public BufferedTextOutput
{
public:
explicit FdTextOutput(int fd) : BufferedTextOutput(MULTITHREADED), mFD(fd) { }
virtual ~FdTextOutput() { };
protected:
virtual status_t writeLines(const struct iovec& vec, size_t N)
{
writev(mFD, &vec, N);
return NO_ERROR;
}
private:
int mFD;
};
static LogTextOutput gLogTextOutput;
static FdTextOutput gStdoutTextOutput(STDOUT_FILENO);
static FdTextOutput gStderrTextOutput(STDERR_FILENO);
TextOutput& alog(gLogTextOutput);
TextOutput& aout(gStdoutTextOutput);
TextOutput& aerr(gStderrTextOutput);
// ------------ ProcessState.cpp
Mutex gProcessMutex;
sp<ProcessState> gProcess;
class LibBinderIPCtStatics
{
public:
LibBinderIPCtStatics()
{
}
~LibBinderIPCtStatics()
{
IPCThreadState::shutdown();
}
};
static LibBinderIPCtStatics gIPCStatics;
// ------------ IServiceManager.cpp
Mutex gDefaultServiceManagerLock;
sp<IServiceManager> gDefaultServiceManager;
sp<IPermissionController> gPermissionController;
} // namespace android

View file

@ -0,0 +1,188 @@
/*
* Copyright (C) 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/Status.h>
namespace android {
namespace binder {
Status Status::ok() {
return Status();
}
Status Status::fromExceptionCode(int32_t exceptionCode) {
return Status(exceptionCode, OK);
}
Status Status::fromExceptionCode(int32_t exceptionCode,
const String8& message) {
return Status(exceptionCode, OK, message);
}
Status Status::fromExceptionCode(int32_t exceptionCode,
const char* message) {
return fromExceptionCode(exceptionCode, String8(message));
}
Status Status::fromServiceSpecificError(int32_t serviceSpecificErrorCode) {
return Status(EX_SERVICE_SPECIFIC, serviceSpecificErrorCode);
}
Status Status::fromServiceSpecificError(int32_t serviceSpecificErrorCode,
const String8& message) {
return Status(EX_SERVICE_SPECIFIC, serviceSpecificErrorCode, message);
}
Status Status::fromServiceSpecificError(int32_t serviceSpecificErrorCode,
const char* message) {
return fromServiceSpecificError(serviceSpecificErrorCode, String8(message));
}
Status Status::fromStatusT(status_t status) {
Status ret;
ret.setFromStatusT(status);
return ret;
}
Status::Status(int32_t exceptionCode, int32_t errorCode)
: mException(exceptionCode),
mErrorCode(errorCode) {}
Status::Status(int32_t exceptionCode, int32_t errorCode, const String8& message)
: mException(exceptionCode),
mErrorCode(errorCode),
mMessage(message) {}
status_t Status::readFromParcel(const Parcel& parcel) {
status_t status = parcel.readInt32(&mException);
if (status != OK) {
setFromStatusT(status);
return status;
}
// Skip over fat response headers. Not used (or propagated) in native code.
if (mException == EX_HAS_REPLY_HEADER) {
// Note that the header size includes the 4 byte size field.
const int32_t header_start = parcel.dataPosition();
int32_t header_size;
status = parcel.readInt32(&header_size);
if (status != OK) {
setFromStatusT(status);
return status;
}
parcel.setDataPosition(header_start + header_size);
// And fat response headers are currently only used when there are no
// exceptions, so act like there was no error.
mException = EX_NONE;
}
if (mException == EX_NONE) {
return status;
}
// The remote threw an exception. Get the message back.
String16 message;
status = parcel.readString16(&message);
if (status != OK) {
setFromStatusT(status);
return status;
}
mMessage = String8(message);
if (mException == EX_SERVICE_SPECIFIC) {
status = parcel.readInt32(&mErrorCode);
} else if (mException == EX_PARCELABLE) {
// Skip over the blob of Parcelable data
const int32_t header_start = parcel.dataPosition();
int32_t header_size;
status = parcel.readInt32(&header_size);
if (status != OK) {
setFromStatusT(status);
return status;
}
parcel.setDataPosition(header_start + header_size);
}
if (status != OK) {
setFromStatusT(status);
return status;
}
return status;
}
status_t Status::writeToParcel(Parcel* parcel) const {
// Something really bad has happened, and we're not going to even
// try returning rich error data.
if (mException == EX_TRANSACTION_FAILED) {
return mErrorCode;
}
status_t status = parcel->writeInt32(mException);
if (status != OK) { return status; }
if (mException == EX_NONE) {
// We have no more information to write.
return status;
}
status = parcel->writeString16(String16(mMessage));
if (mException == EX_SERVICE_SPECIFIC) {
status = parcel->writeInt32(mErrorCode);
} else if (mException == EX_PARCELABLE) {
// Sending Parcelable blobs currently not supported
status = parcel->writeInt32(0);
}
return status;
}
void Status::setException(int32_t ex, const String8& message) {
mException = ex;
mErrorCode = NO_ERROR; // an exception, not a transaction failure.
mMessage.setTo(message);
}
void Status::setServiceSpecificError(int32_t errorCode, const String8& message) {
setException(EX_SERVICE_SPECIFIC, message);
mErrorCode = errorCode;
}
void Status::setFromStatusT(status_t status) {
mException = (status == NO_ERROR) ? EX_NONE : EX_TRANSACTION_FAILED;
mErrorCode = status;
mMessage.clear();
}
String8 Status::toString8() const {
String8 ret;
if (mException == EX_NONE) {
ret.append("No error");
} else {
ret.appendFormat("Status(%d): '", mException);
if (mException == EX_SERVICE_SPECIFIC ||
mException == EX_TRANSACTION_FAILED) {
ret.appendFormat("%d: ", mErrorCode);
}
ret.append(String8(mMessage));
ret.append("'");
}
return ret;
}
std::stringstream& operator<< (std::stringstream& stream, const Status& s) {
stream << s.toString8().string();
return stream;
}
} // namespace binder
} // namespace android

View file

@ -0,0 +1,72 @@
/*
* Copyright (C) 2005 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/TextOutput.h>
#include <binder/Debug.h>
#include <utils/String8.h>
#include <utils/String16.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
namespace android {
// ---------------------------------------------------------------------------
TextOutput::TextOutput() {
}
TextOutput::~TextOutput() {
}
// ---------------------------------------------------------------------------
static void textOutputPrinter(void* cookie, const char* txt)
{
((TextOutput*)cookie)->print(txt, strlen(txt));
}
TextOutput& operator<<(TextOutput& to, const TypeCode& val)
{
printTypeCode(val.typeCode(), textOutputPrinter, (void*)&to);
return to;
}
HexDump::HexDump(const void *buf, size_t size, size_t bytesPerLine)
: mBuffer(buf)
, mSize(size)
, mBytesPerLine(bytesPerLine)
, mSingleLineCutoff(16)
, mAlignment(4)
, mCArrayStyle(false)
{
if (bytesPerLine >= 16) mAlignment = 4;
else if (bytesPerLine >= 8) mAlignment = 2;
else mAlignment = 1;
}
TextOutput& operator<<(TextOutput& to, const HexDump& val)
{
printHexData(0, val.buffer(), val.size(), val.bytesPerLine(),
val.singleLineCutoff(), val.alignment(), val.carrayStyle(),
textOutputPrinter, (void*)&to);
return to;
}
}; // namespace android

View file

@ -0,0 +1,418 @@
/*
* Copyright (C) 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.
*/
#define LOG_TAG "Value"
#include <binder/Value.h>
#include <limits>
#include <binder/IBinder.h>
#include <binder/Parcel.h>
#include <binder/Map.h>
#include <private/binder/ParcelValTypes.h>
#include <log/log.h>
#include <utils/Errors.h>
using android::BAD_TYPE;
using android::BAD_VALUE;
using android::NO_ERROR;
using android::UNEXPECTED_NULL;
using android::Parcel;
using android::sp;
using android::status_t;
using std::map;
using std::set;
using std::vector;
using android::binder::Value;
using android::IBinder;
using android::os::PersistableBundle;
using namespace android::binder;
// ====================================================================
#define RETURN_IF_FAILED(calledOnce) \
do { \
status_t returnStatus = calledOnce; \
if (returnStatus) { \
ALOGE("Failed at %s:%d (%s)", __FILE__, __LINE__, __func__); \
return returnStatus; \
} \
} while(false)
// ====================================================================
/* These `internal_type_ptr()` functions allow this
* class to work without C++ RTTI support. This technique
* only works properly when called directly from this file,
* but that is OK because that is the only place we will
* be calling them from. */
template<class T> const void* internal_type_ptr()
{
static const T *marker;
return (void*)&marker;
}
/* Allows the type to be specified by the argument
* instead of inside angle brackets. */
template<class T> const void* internal_type_ptr(const T&)
{
return internal_type_ptr<T>();
}
// ====================================================================
namespace android {
namespace binder {
class Value::ContentBase {
public:
virtual ~ContentBase() = default;
virtual const void* type_ptr() const = 0;
virtual ContentBase * clone() const = 0;
virtual bool operator==(const ContentBase& rhs) const = 0;
#ifdef LIBBINDER_VALUE_SUPPORTS_TYPE_INFO
virtual const std::type_info &type() const = 0;
#endif
template<typename T> bool get(T* out) const;
};
/* This is the actual class that holds the value. */
template<typename T> class Value::Content : public Value::ContentBase {
public:
Content() = default;
Content(const T & value) : mValue(value) { }
virtual ~Content() = default;
#ifdef LIBBINDER_VALUE_SUPPORTS_TYPE_INFO
virtual const std::type_info &type() const override
{
return typeid(T);
}
#endif
virtual const void* type_ptr() const override
{
return internal_type_ptr<T>();
}
virtual ContentBase * clone() const override
{
return new Content(mValue);
};
virtual bool operator==(const ContentBase& rhs) const override
{
if (type_ptr() != rhs.type_ptr()) {
return false;
}
return mValue == static_cast<const Content<T>* >(&rhs)->mValue;
}
T mValue;
};
template<typename T> bool Value::ContentBase::get(T* out) const
{
if (internal_type_ptr(*out) != type_ptr())
{
return false;
}
*out = static_cast<const Content<T>*>(this)->mValue;
return true;
}
// ====================================================================
Value::Value() : mContent(NULL)
{
}
Value::Value(const Value& value)
: mContent(value.mContent ? value.mContent->clone() : NULL)
{
}
Value::~Value()
{
delete mContent;
}
bool Value::operator==(const Value& rhs) const
{
const Value& lhs(*this);
if (lhs.empty() && rhs.empty()) {
return true;
}
if ( (lhs.mContent == NULL)
|| (rhs.mContent == NULL)
) {
return false;
}
return *lhs.mContent == *rhs.mContent;
}
Value& Value::swap(Value &rhs)
{
std::swap(mContent, rhs.mContent);
return *this;
}
Value& Value::operator=(const Value& rhs)
{
delete mContent;
mContent = rhs.mContent
? rhs.mContent->clone()
: NULL;
return *this;
}
bool Value::empty() const
{
return mContent == NULL;
}
void Value::clear()
{
delete mContent;
mContent = NULL;
}
int32_t Value::parcelType() const
{
const void* t_info(mContent ? mContent->type_ptr() : NULL);
if (t_info == internal_type_ptr<bool>()) return VAL_BOOLEAN;
if (t_info == internal_type_ptr<uint8_t>()) return VAL_BYTE;
if (t_info == internal_type_ptr<int32_t>()) return VAL_INTEGER;
if (t_info == internal_type_ptr<int64_t>()) return VAL_LONG;
if (t_info == internal_type_ptr<double>()) return VAL_DOUBLE;
if (t_info == internal_type_ptr<String16>()) return VAL_STRING;
if (t_info == internal_type_ptr<vector<bool>>()) return VAL_BOOLEANARRAY;
if (t_info == internal_type_ptr<vector<uint8_t>>()) return VAL_BYTEARRAY;
if (t_info == internal_type_ptr<vector<int32_t>>()) return VAL_INTARRAY;
if (t_info == internal_type_ptr<vector<int64_t>>()) return VAL_LONGARRAY;
if (t_info == internal_type_ptr<vector<double>>()) return VAL_DOUBLEARRAY;
if (t_info == internal_type_ptr<vector<String16>>()) return VAL_STRINGARRAY;
if (t_info == internal_type_ptr<Map>()) return VAL_MAP;
if (t_info == internal_type_ptr<PersistableBundle>()) return VAL_PERSISTABLEBUNDLE;
return VAL_NULL;
}
#ifdef LIBBINDER_VALUE_SUPPORTS_TYPE_INFO
const std::type_info& Value::type() const
{
return mContent != NULL
? mContent->type()
: typeid(void);
}
#endif // ifdef LIBBINDER_VALUE_SUPPORTS_TYPE_INFO
#define DEF_TYPE_ACCESSORS(T, TYPENAME) \
bool Value::is ## TYPENAME() const \
{ \
return mContent \
? internal_type_ptr<T>() == mContent->type_ptr() \
: false; \
} \
bool Value::get ## TYPENAME(T* out) const \
{ \
return mContent \
? mContent->get(out) \
: false; \
} \
void Value::put ## TYPENAME(const T& in) \
{ \
*this = in; \
} \
Value& Value::operator=(const T& rhs) \
{ \
delete mContent; \
mContent = new Content< T >(rhs); \
return *this; \
} \
Value::Value(const T& value) \
: mContent(new Content< T >(value)) \
{ }
DEF_TYPE_ACCESSORS(bool, Boolean)
DEF_TYPE_ACCESSORS(int8_t, Byte)
DEF_TYPE_ACCESSORS(int32_t, Int)
DEF_TYPE_ACCESSORS(int64_t, Long)
DEF_TYPE_ACCESSORS(double, Double)
DEF_TYPE_ACCESSORS(String16, String)
DEF_TYPE_ACCESSORS(std::vector<bool>, BooleanVector)
DEF_TYPE_ACCESSORS(std::vector<uint8_t>, ByteVector)
DEF_TYPE_ACCESSORS(std::vector<int32_t>, IntVector)
DEF_TYPE_ACCESSORS(std::vector<int64_t>, LongVector)
DEF_TYPE_ACCESSORS(std::vector<double>, DoubleVector)
DEF_TYPE_ACCESSORS(std::vector<String16>, StringVector)
DEF_TYPE_ACCESSORS(::android::binder::Map, Map)
DEF_TYPE_ACCESSORS(PersistableBundle, PersistableBundle)
bool Value::getString(String8* out) const
{
String16 val;
bool ret = getString(&val);
if (ret) {
*out = String8(val);
}
return ret;
}
bool Value::getString(::std::string* out) const
{
String8 val;
bool ret = getString(&val);
if (ret) {
*out = val.string();
}
return ret;
}
status_t Value::writeToParcel(Parcel* parcel) const
{
// This implementation needs to be kept in sync with the writeValue
// implementation in frameworks/base/core/java/android/os/Parcel.java
#define BEGIN_HANDLE_WRITE() \
do { \
const void* t_info(mContent?mContent->type_ptr():NULL); \
if (false) { }
#define HANDLE_WRITE_TYPE(T, TYPEVAL, TYPEMETHOD) \
else if (t_info == internal_type_ptr<T>()) { \
RETURN_IF_FAILED(parcel->writeInt32(TYPEVAL)); \
RETURN_IF_FAILED(parcel->TYPEMETHOD(static_cast<const Content<T>*>(mContent)->mValue)); \
}
#define HANDLE_WRITE_PARCELABLE(T, TYPEVAL) \
else if (t_info == internal_type_ptr<T>()) { \
RETURN_IF_FAILED(parcel->writeInt32(TYPEVAL)); \
RETURN_IF_FAILED(static_cast<const Content<T>*>(mContent)->mValue.writeToParcel(parcel)); \
}
#define END_HANDLE_WRITE() \
else { \
ALOGE("writeToParcel: Type not supported"); \
return BAD_TYPE; \
} \
} while (false);
BEGIN_HANDLE_WRITE()
HANDLE_WRITE_TYPE(bool, VAL_BOOLEAN, writeBool)
HANDLE_WRITE_TYPE(int8_t, VAL_BYTE, writeByte)
HANDLE_WRITE_TYPE(int8_t, VAL_BYTE, writeByte)
HANDLE_WRITE_TYPE(int32_t, VAL_INTEGER, writeInt32)
HANDLE_WRITE_TYPE(int64_t, VAL_LONG, writeInt64)
HANDLE_WRITE_TYPE(double, VAL_DOUBLE, writeDouble)
HANDLE_WRITE_TYPE(String16, VAL_STRING, writeString16)
HANDLE_WRITE_TYPE(vector<bool>, VAL_BOOLEANARRAY, writeBoolVector)
HANDLE_WRITE_TYPE(vector<uint8_t>, VAL_BYTEARRAY, writeByteVector)
HANDLE_WRITE_TYPE(vector<int8_t>, VAL_BYTEARRAY, writeByteVector)
HANDLE_WRITE_TYPE(vector<int32_t>, VAL_INTARRAY, writeInt32Vector)
HANDLE_WRITE_TYPE(vector<int64_t>, VAL_LONGARRAY, writeInt64Vector)
HANDLE_WRITE_TYPE(vector<double>, VAL_DOUBLEARRAY, writeDoubleVector)
HANDLE_WRITE_TYPE(vector<String16>, VAL_STRINGARRAY, writeString16Vector)
HANDLE_WRITE_PARCELABLE(PersistableBundle, VAL_PERSISTABLEBUNDLE)
END_HANDLE_WRITE()
return NO_ERROR;
#undef BEGIN_HANDLE_WRITE
#undef HANDLE_WRITE_TYPE
#undef HANDLE_WRITE_PARCELABLE
#undef END_HANDLE_WRITE
}
status_t Value::readFromParcel(const Parcel* parcel)
{
// This implementation needs to be kept in sync with the readValue
// implementation in frameworks/base/core/java/android/os/Parcel.javai
#define BEGIN_HANDLE_READ() \
switch(value_type) { \
default: \
ALOGE("readFromParcel: Parcel type %d is not supported", value_type); \
return BAD_TYPE;
#define HANDLE_READ_TYPE(T, TYPEVAL, TYPEMETHOD) \
case TYPEVAL: \
mContent = new Content<T>(); \
RETURN_IF_FAILED(parcel->TYPEMETHOD(&static_cast<Content<T>*>(mContent)->mValue)); \
break;
#define HANDLE_READ_PARCELABLE(T, TYPEVAL) \
case TYPEVAL: \
mContent = new Content<T>(); \
RETURN_IF_FAILED(static_cast<Content<T>*>(mContent)->mValue.readFromParcel(parcel)); \
break;
#define END_HANDLE_READ() \
}
int32_t value_type = VAL_NULL;
delete mContent;
mContent = NULL;
RETURN_IF_FAILED(parcel->readInt32(&value_type));
BEGIN_HANDLE_READ()
HANDLE_READ_TYPE(bool, VAL_BOOLEAN, readBool)
HANDLE_READ_TYPE(int8_t, VAL_BYTE, readByte)
HANDLE_READ_TYPE(int32_t, VAL_INTEGER, readInt32)
HANDLE_READ_TYPE(int64_t, VAL_LONG, readInt64)
HANDLE_READ_TYPE(double, VAL_DOUBLE, readDouble)
HANDLE_READ_TYPE(String16, VAL_STRING, readString16)
HANDLE_READ_TYPE(vector<bool>, VAL_BOOLEANARRAY, readBoolVector)
HANDLE_READ_TYPE(vector<uint8_t>, VAL_BYTEARRAY, readByteVector)
HANDLE_READ_TYPE(vector<int32_t>, VAL_INTARRAY, readInt32Vector)
HANDLE_READ_TYPE(vector<int64_t>, VAL_LONGARRAY, readInt64Vector)
HANDLE_READ_TYPE(vector<double>, VAL_DOUBLEARRAY, readDoubleVector)
HANDLE_READ_TYPE(vector<String16>, VAL_STRINGARRAY, readString16Vector)
HANDLE_READ_PARCELABLE(PersistableBundle, VAL_PERSISTABLEBUNDLE)
END_HANDLE_READ()
return NO_ERROR;
#undef BEGIN_HANDLE_READ
#undef HANDLE_READ_TYPE
#undef HANDLE_READ_PARCELABLE
#undef END_HANDLE_READ
}
} // namespace binder
} // namespace android
/* vim: set ts=4 sw=4 tw=0 et :*/

View file

@ -0,0 +1,57 @@
/*
**
** Copyright 2017, 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.
*/
package android.content.pm;
/**
* Parallel implementation of certain {@link PackageManager} APIs that need to
* be exposed to native code.
* <p>These APIs are a parallel definition to the APIs in PackageManager, so,
* they can technically diverge. However, it's good practice to keep these
* APIs in sync with each other.
* <p>Because these APIs are exposed to native code, it's possible they will
* be exposed to privileged components [such as UID 0]. Care should be taken
* to avoid exposing potential security holes for methods where permission
* checks are bypassed based upon UID alone.
*
* @hide
*/
interface IPackageManagerNative {
/**
* Returns a set of names for the given UIDs.
* IMPORTANT: Unlike the Java version of this API, unknown UIDs are
* not represented by 'null's. Instead, they are represented by empty
* strings.
*/
@utf8InCpp String[] getNamesForUids(in int[] uids);
/**
* Returns the name of the installer (a package) which installed the named
* package. Preloaded packages return the string "preload". Sideloaded packages
* return an empty string. Unknown or unknowable are returned as empty strings.
*/
@utf8InCpp String getInstallerForPackage(in String packageName);
/**
* Returns the version code of the named package.
* Unknown or unknowable versions are returned as 0.
*/
int getVersionCodeForPackage(in String packageName);
}

View file

@ -0,0 +1,119 @@
/*
* Copyright (C) 2013 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_APP_OPS_MANAGER_H
#define ANDROID_APP_OPS_MANAGER_H
#include <binder/IAppOpsService.h>
#include <utils/threads.h>
// ---------------------------------------------------------------------------
namespace android {
class AppOpsManager
{
public:
enum {
MODE_ALLOWED = IAppOpsService::MODE_ALLOWED,
MODE_IGNORED = IAppOpsService::MODE_IGNORED,
MODE_ERRORED = IAppOpsService::MODE_ERRORED
};
enum {
OP_NONE = -1,
OP_COARSE_LOCATION = 0,
OP_FINE_LOCATION = 1,
OP_GPS = 2,
OP_VIBRATE = 3,
OP_READ_CONTACTS = 4,
OP_WRITE_CONTACTS = 5,
OP_READ_CALL_LOG = 6,
OP_WRITE_CALL_LOG = 7,
OP_READ_CALENDAR = 8,
OP_WRITE_CALENDAR = 9,
OP_WIFI_SCAN = 10,
OP_POST_NOTIFICATION = 11,
OP_NEIGHBORING_CELLS = 12,
OP_CALL_PHONE = 13,
OP_READ_SMS = 14,
OP_WRITE_SMS = 15,
OP_RECEIVE_SMS = 16,
OP_RECEIVE_EMERGECY_SMS = 17,
OP_RECEIVE_MMS = 18,
OP_RECEIVE_WAP_PUSH = 19,
OP_SEND_SMS = 20,
OP_READ_ICC_SMS = 21,
OP_WRITE_ICC_SMS = 22,
OP_WRITE_SETTINGS = 23,
OP_SYSTEM_ALERT_WINDOW = 24,
OP_ACCESS_NOTIFICATIONS = 25,
OP_CAMERA = 26,
OP_RECORD_AUDIO = 27,
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,
OP_AUDIO_ACCESSIBILITY_VOLUME = 64,
};
AppOpsManager();
int32_t checkOp(int32_t op, int32_t uid, const String16& callingPackage);
int32_t noteOp(int32_t op, int32_t uid, const String16& callingPackage);
int32_t startOp(int32_t op, int32_t uid, const String16& callingPackage);
void finishOp(int32_t op, int32_t uid, const String16& callingPackage);
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;
sp<IAppOpsService> mService;
sp<IAppOpsService> getService();
};
}; // namespace android
// ---------------------------------------------------------------------------
#endif // ANDROID_APP_OPS_MANAGER_H

View file

@ -0,0 +1,105 @@
/*
* Copyright (C) 2008 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_BINDER_H
#define ANDROID_BINDER_H
#include <atomic>
#include <stdint.h>
#include <binder/IBinder.h>
// ---------------------------------------------------------------------------
namespace android {
class BBinder : public IBinder
{
public:
BBinder();
virtual const String16& getInterfaceDescriptor() const;
virtual bool isBinderAlive() const;
virtual status_t pingBinder();
virtual status_t dump(int fd, const Vector<String16>& args);
virtual status_t transact( uint32_t code,
const Parcel& data,
Parcel* reply,
uint32_t flags = 0);
virtual status_t linkToDeath(const sp<DeathRecipient>& recipient,
void* cookie = NULL,
uint32_t flags = 0);
virtual status_t unlinkToDeath( const wp<DeathRecipient>& recipient,
void* cookie = NULL,
uint32_t flags = 0,
wp<DeathRecipient>* outRecipient = NULL);
virtual void attachObject( const void* objectID,
void* object,
void* cleanupCookie,
object_cleanup_func func);
virtual void* findObject(const void* objectID) const;
virtual void detachObject(const void* objectID);
virtual BBinder* localBinder();
protected:
virtual ~BBinder();
virtual status_t onTransact( uint32_t code,
const Parcel& data,
Parcel* reply,
uint32_t flags = 0);
private:
BBinder(const BBinder& o);
BBinder& operator=(const BBinder& o);
class Extras;
std::atomic<Extras*> mExtras;
void* mReserved0;
};
// ---------------------------------------------------------------------------
class BpRefBase : public virtual RefBase
{
protected:
explicit BpRefBase(const sp<IBinder>& o);
virtual ~BpRefBase();
virtual void onFirstRef();
virtual void onLastStrongRef(const void* id);
virtual bool onIncStrongAttempted(uint32_t flags, const void* id);
inline IBinder* remote() { return mRemote; }
inline IBinder* remote() const { return mRemote; }
private:
BpRefBase(const BpRefBase& o);
BpRefBase& operator=(const BpRefBase& o);
IBinder* const mRemote;
RefBase::weakref_type* mRefs;
std::atomic<int32_t> mState;
};
}; // namespace android
// ---------------------------------------------------------------------------
#endif // ANDROID_BINDER_H

View file

@ -0,0 +1,65 @@
/*
* Copyright (C) 2010 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_BINDER_SERVICE_H
#define ANDROID_BINDER_SERVICE_H
#include <stdint.h>
#include <utils/Errors.h>
#include <utils/String16.h>
#include <binder/IServiceManager.h>
#include <binder/IPCThreadState.h>
#include <binder/ProcessState.h>
#include <binder/IServiceManager.h>
// ---------------------------------------------------------------------------
namespace android {
template<typename SERVICE>
class BinderService
{
public:
static status_t publish(bool allowIsolated = false) {
sp<IServiceManager> sm(defaultServiceManager());
return sm->addService(
String16(SERVICE::getServiceName()),
new SERVICE(), allowIsolated);
}
static void publishAndJoinThreadPool(bool allowIsolated = false) {
publish(allowIsolated);
joinThreadPool();
}
static void instantiate() { publish(); }
static status_t shutdown() { return NO_ERROR; }
private:
static void joinThreadPool() {
sp<ProcessState> ps(ProcessState::self());
ps->startThreadPool();
ps->giveThreadPoolName();
IPCThreadState::self()->joinThreadPool();
}
};
}; // namespace android
// ---------------------------------------------------------------------------
#endif // ANDROID_BINDER_SERVICE_H

View file

@ -0,0 +1,124 @@
/*
* Copyright (C) 2005 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_BPBINDER_H
#define ANDROID_BPBINDER_H
#include <binder/IBinder.h>
#include <utils/KeyedVector.h>
#include <utils/threads.h>
// ---------------------------------------------------------------------------
namespace android {
class BpBinder : public IBinder
{
public:
BpBinder(int32_t handle);
inline int32_t handle() const { return mHandle; }
virtual const String16& getInterfaceDescriptor() const;
virtual bool isBinderAlive() const;
virtual status_t pingBinder();
virtual status_t dump(int fd, const Vector<String16>& args);
virtual status_t transact( uint32_t code,
const Parcel& data,
Parcel* reply,
uint32_t flags = 0);
virtual status_t linkToDeath(const sp<DeathRecipient>& recipient,
void* cookie = NULL,
uint32_t flags = 0);
virtual status_t unlinkToDeath( const wp<DeathRecipient>& recipient,
void* cookie = NULL,
uint32_t flags = 0,
wp<DeathRecipient>* outRecipient = NULL);
virtual void attachObject( const void* objectID,
void* object,
void* cleanupCookie,
object_cleanup_func func);
virtual void* findObject(const void* objectID) const;
virtual void detachObject(const void* objectID);
virtual BpBinder* remoteBinder();
status_t setConstantData(const void* data, size_t size);
void sendObituary();
class ObjectManager
{
public:
ObjectManager();
~ObjectManager();
void attach( const void* objectID,
void* object,
void* cleanupCookie,
IBinder::object_cleanup_func func);
void* find(const void* objectID) const;
void detach(const void* objectID);
void kill();
private:
ObjectManager(const ObjectManager&);
ObjectManager& operator=(const ObjectManager&);
struct entry_t
{
void* object;
void* cleanupCookie;
IBinder::object_cleanup_func func;
};
KeyedVector<const void*, entry_t> mObjects;
};
protected:
virtual ~BpBinder();
virtual void onFirstRef();
virtual void onLastStrongRef(const void* id);
virtual bool onIncStrongAttempted(uint32_t flags, const void* id);
private:
const int32_t mHandle;
struct Obituary {
wp<DeathRecipient> recipient;
void* cookie;
uint32_t flags;
};
void reportOneDeath(const Obituary& obit);
bool isDescriptorCached() const;
mutable Mutex mLock;
volatile int32_t mAlive;
volatile int32_t mObitsSent;
Vector<Obituary>* mObituaries;
ObjectManager mObjects;
Parcel* mConstantData;
mutable String16 mDescriptorCache;
};
}; // namespace android
// ---------------------------------------------------------------------------
#endif // ANDROID_BPBINDER_H

View file

@ -0,0 +1,67 @@
/*
* Copyright (C) 2006 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_BUFFEREDTEXTOUTPUT_H
#define ANDROID_BUFFEREDTEXTOUTPUT_H
#include <binder/TextOutput.h>
#include <utils/threads.h>
#include <sys/uio.h>
// ---------------------------------------------------------------------------
namespace android {
class BufferedTextOutput : public TextOutput
{
public:
//** Flags for constructor */
enum {
MULTITHREADED = 0x0001
};
BufferedTextOutput(uint32_t flags = 0);
virtual ~BufferedTextOutput();
virtual status_t print(const char* txt, size_t len);
virtual void moveIndent(int delta);
virtual void pushBundle();
virtual void popBundle();
protected:
virtual status_t writeLines(const struct iovec& vec, size_t N) = 0;
private:
struct BufferState;
struct ThreadState;
static ThreadState*getThreadState();
static void threadDestructor(void *st);
BufferState*getBuffer() const;
uint32_t mFlags;
const int32_t mSeq;
const int32_t mIndex;
Mutex mLock;
BufferState* mGlobalState;
};
// ---------------------------------------------------------------------------
}; // namespace android
#endif // ANDROID_BUFFEREDTEXTOUTPUT_H

View file

@ -0,0 +1,49 @@
/*
* Copyright (C) 2005 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_BINDER_DEBUG_H
#define ANDROID_BINDER_DEBUG_H
#include <stdint.h>
#include <sys/cdefs.h>
#include <sys/types.h>
namespace android {
// ---------------------------------------------------------------------------
__BEGIN_DECLS
const char* stringForIndent(int32_t indentLevel);
typedef void (*debugPrintFunc)(void* cookie, const char* txt);
void printTypeCode(uint32_t typeCode,
debugPrintFunc func = 0, void* cookie = 0);
void printHexData(int32_t indent, const void *buf, size_t length,
size_t bytesPerLine=16, int32_t singleLineBytesCutoff=16,
size_t alignment=0, bool cArrayStyle=false,
debugPrintFunc func = 0, void* cookie = 0);
ssize_t getBinderKernelReferences(size_t count, uintptr_t* buf);
__END_DECLS
// ---------------------------------------------------------------------------
}; // namespace android
#endif // ANDROID_BINDER_DEBUG_H

View file

@ -0,0 +1,42 @@
/*
* Copyright (C) 2016 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_IACTIVITY_MANAGER_H
#define ANDROID_IACTIVITY_MANAGER_H
#include <binder/IInterface.h>
namespace android {
// ------------------------------------------------------------------------------------
class IActivityManager : public IInterface
{
public:
DECLARE_META_INTERFACE(ActivityManager)
virtual int openContentUri(const String16& /* stringUri */) = 0;
enum {
OPEN_CONTENT_URI_TRANSACTION = IBinder::FIRST_CALL_TRANSACTION
};
};
// ------------------------------------------------------------------------------------
}; // namespace android
#endif // ANDROID_IACTIVITY_MANAGER_H

View file

@ -0,0 +1,55 @@
/*
* Copyright (C) 2013 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_IAPP_OPS_CALLBACK_H
#define ANDROID_IAPP_OPS_CALLBACK_H
#include <binder/IInterface.h>
namespace android {
// ----------------------------------------------------------------------
class IAppOpsCallback : public IInterface
{
public:
DECLARE_META_INTERFACE(AppOpsCallback)
virtual void opChanged(int32_t op, const String16& packageName) = 0;
enum {
OP_CHANGED_TRANSACTION = IBinder::FIRST_CALL_TRANSACTION
};
};
// ----------------------------------------------------------------------
class BnAppOpsCallback : public BnInterface<IAppOpsCallback>
{
public:
virtual status_t onTransact( uint32_t code,
const Parcel& data,
Parcel* reply,
uint32_t flags = 0);
};
// ----------------------------------------------------------------------
}; // namespace android
#endif // ANDROID_IAPP_OPS_CALLBACK_H

View file

@ -0,0 +1,78 @@
/*
* Copyright (C) 2013 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_IAPP_OPS_SERVICE_H
#define ANDROID_IAPP_OPS_SERVICE_H
#include <binder/IAppOpsCallback.h>
#include <binder/IInterface.h>
namespace android {
// ----------------------------------------------------------------------
class IAppOpsService : public IInterface
{
public:
DECLARE_META_INTERFACE(AppOpsService)
virtual int32_t checkOperation(int32_t code, int32_t uid, const String16& packageName) = 0;
virtual int32_t noteOperation(int32_t code, int32_t uid, const String16& packageName) = 0;
virtual int32_t startOperation(const sp<IBinder>& token, int32_t code, int32_t uid,
const String16& packageName) = 0;
virtual void finishOperation(const sp<IBinder>& token, int32_t code, int32_t uid,
const String16& packageName) = 0;
virtual void startWatchingMode(int32_t op, const String16& packageName,
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,
NOTE_OPERATION_TRANSACTION = IBinder::FIRST_CALL_TRANSACTION+1,
START_OPERATION_TRANSACTION = IBinder::FIRST_CALL_TRANSACTION+2,
FINISH_OPERATION_TRANSACTION = IBinder::FIRST_CALL_TRANSACTION+3,
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 {
MODE_ALLOWED = 0,
MODE_IGNORED = 1,
MODE_ERRORED = 2
};
};
// ----------------------------------------------------------------------
class BnAppOpsService : public BnInterface<IAppOpsService>
{
public:
virtual status_t onTransact( uint32_t code,
const Parcel& data,
Parcel* reply,
uint32_t flags = 0);
};
// ----------------------------------------------------------------------
}; // namespace android
#endif // ANDROID_IAPP_OPS_SERVICE_H

View file

@ -0,0 +1,79 @@
/*
* Copyright (C) 2013 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_IBATTERYSTATS_H
#define ANDROID_IBATTERYSTATS_H
#include <binder/IInterface.h>
namespace android {
// ----------------------------------------------------------------------
class IBatteryStats : public IInterface
{
public:
DECLARE_META_INTERFACE(BatteryStats)
virtual void noteStartSensor(int uid, int sensor) = 0;
virtual void noteStopSensor(int uid, int sensor) = 0;
virtual void noteStartVideo(int uid) = 0;
virtual void noteStopVideo(int uid) = 0;
virtual void noteStartAudio(int uid) = 0;
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,
NOTE_STOP_SENSOR_TRANSACTION,
NOTE_START_VIDEO_TRANSACTION,
NOTE_STOP_VIDEO_TRANSACTION,
NOTE_START_AUDIO_TRANSACTION,
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
};
};
// ----------------------------------------------------------------------
class BnBatteryStats : public BnInterface<IBatteryStats>
{
public:
virtual status_t onTransact( uint32_t code,
const Parcel& data,
Parcel* reply,
uint32_t flags = 0);
};
// ----------------------------------------------------------------------
}; // namespace android
#endif // ANDROID_IBATTERYSTATS_H

View file

@ -0,0 +1,174 @@
/*
* Copyright (C) 2008 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_IBINDER_H
#define ANDROID_IBINDER_H
#include <utils/Errors.h>
#include <utils/RefBase.h>
#include <utils/String16.h>
#include <utils/Vector.h>
// linux/binder.h already defines this, but we can't just include it from there
// because there are host builds that include this file.
#ifndef B_PACK_CHARS
#define B_PACK_CHARS(c1, c2, c3, c4) \
((((c1)<<24)) | (((c2)<<16)) | (((c3)<<8)) | (c4))
#endif // B_PACK_CHARS
// ---------------------------------------------------------------------------
namespace android {
class BBinder;
class BpBinder;
class IInterface;
class Parcel;
class IResultReceiver;
class IShellCallback;
/**
* Base class and low-level protocol for a remotable object.
* You can derive from this class to create an object for which other
* processes can hold references to it. Communication between processes
* (method calls, property get and set) is down through a low-level
* protocol implemented on top of the transact() API.
*/
class IBinder : public virtual RefBase
{
public:
enum {
FIRST_CALL_TRANSACTION = 0x00000001,
LAST_CALL_TRANSACTION = 0x00ffffff,
PING_TRANSACTION = B_PACK_CHARS('_','P','N','G'),
DUMP_TRANSACTION = B_PACK_CHARS('_','D','M','P'),
SHELL_COMMAND_TRANSACTION = B_PACK_CHARS('_','C','M','D'),
INTERFACE_TRANSACTION = B_PACK_CHARS('_', 'N', 'T', 'F'),
SYSPROPS_TRANSACTION = B_PACK_CHARS('_', 'S', 'P', 'R'),
// Corresponds to TF_ONE_WAY -- an asynchronous call.
FLAG_ONEWAY = 0x00000001
};
IBinder();
/**
* Check if this IBinder implements the interface named by
* @a descriptor. If it does, the base pointer to it is returned,
* which you can safely static_cast<> to the concrete C++ interface.
*/
virtual sp<IInterface> queryLocalInterface(const String16& descriptor);
/**
* Return the canonical name of the interface provided by this IBinder
* object.
*/
virtual const String16& getInterfaceDescriptor() const = 0;
virtual bool isBinderAlive() const = 0;
virtual status_t pingBinder() = 0;
virtual status_t dump(int fd, const Vector<String16>& args) = 0;
static status_t shellCommand(const sp<IBinder>& target, int in, int out, int err,
Vector<String16>& args, const sp<IShellCallback>& callback,
const sp<IResultReceiver>& resultReceiver);
virtual status_t transact( uint32_t code,
const Parcel& data,
Parcel* reply,
uint32_t flags = 0) = 0;
// DeathRecipient is pure abstract, there is no virtual method
// implementation to put in a translation unit in order to silence the
// weak vtables warning.
#if defined(__clang__)
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wweak-vtables"
#endif
class DeathRecipient : public virtual RefBase
{
public:
virtual void binderDied(const wp<IBinder>& who) = 0;
};
#if defined(__clang__)
#pragma clang diagnostic pop
#endif
/**
* Register the @a recipient for a notification if this binder
* goes away. If this binder object unexpectedly goes away
* (typically because its hosting process has been killed),
* then DeathRecipient::binderDied() will be called with a reference
* to this.
*
* The @a cookie is optional -- if non-NULL, it should be a
* memory address that you own (that is, you know it is unique).
*
* @note You will only receive death notifications for remote binders,
* as local binders by definition can't die without you dying as well.
* Trying to use this function on a local binder will result in an
* INVALID_OPERATION code being returned and nothing happening.
*
* @note This link always holds a weak reference to its recipient.
*
* @note You will only receive a weak reference to the dead
* binder. You should not try to promote this to a strong reference.
* (Nor should you need to, as there is nothing useful you can
* directly do with it now that it has passed on.)
*/
virtual status_t linkToDeath(const sp<DeathRecipient>& recipient,
void* cookie = NULL,
uint32_t flags = 0) = 0;
/**
* Remove a previously registered death notification.
* The @a recipient will no longer be called if this object
* dies. The @a cookie is optional. If non-NULL, you can
* supply a NULL @a recipient, and the recipient previously
* added with that cookie will be unlinked.
*/
virtual status_t unlinkToDeath( const wp<DeathRecipient>& recipient,
void* cookie = NULL,
uint32_t flags = 0,
wp<DeathRecipient>* outRecipient = NULL) = 0;
virtual bool checkSubclass(const void* subclassID) const;
typedef void (*object_cleanup_func)(const void* id, void* obj, void* cleanupCookie);
virtual void attachObject( const void* objectID,
void* object,
void* cleanupCookie,
object_cleanup_func func) = 0;
virtual void* findObject(const void* objectID) const = 0;
virtual void detachObject(const void* objectID) = 0;
virtual BBinder* localBinder();
virtual BpBinder* remoteBinder();
protected:
virtual ~IBinder();
private:
};
}; // namespace android
// ---------------------------------------------------------------------------
#endif // ANDROID_IBINDER_H

View file

@ -0,0 +1,150 @@
/*
* Copyright (C) 2005 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_IINTERFACE_H
#define ANDROID_IINTERFACE_H
#include <binder/Binder.h>
namespace android {
// ----------------------------------------------------------------------
class IInterface : public virtual RefBase
{
public:
IInterface();
static sp<IBinder> asBinder(const IInterface*);
static sp<IBinder> asBinder(const sp<IInterface>&);
protected:
virtual ~IInterface();
virtual IBinder* onAsBinder() = 0;
};
// ----------------------------------------------------------------------
template<typename INTERFACE>
inline sp<INTERFACE> interface_cast(const sp<IBinder>& obj)
{
return INTERFACE::asInterface(obj);
}
// ----------------------------------------------------------------------
template<typename INTERFACE>
class BnInterface : public INTERFACE, public BBinder
{
public:
virtual sp<IInterface> queryLocalInterface(const String16& _descriptor);
virtual const String16& getInterfaceDescriptor() const;
protected:
virtual IBinder* onAsBinder();
};
// ----------------------------------------------------------------------
template<typename INTERFACE>
class BpInterface : public INTERFACE, public BpRefBase
{
public:
explicit BpInterface(const sp<IBinder>& remote);
protected:
virtual IBinder* onAsBinder();
};
// ----------------------------------------------------------------------
#define DECLARE_META_INTERFACE(INTERFACE) \
static const ::android::String16 descriptor; \
static ::android::sp<I##INTERFACE> asInterface( \
const ::android::sp<::android::IBinder>& obj); \
virtual const ::android::String16& getInterfaceDescriptor() const; \
I##INTERFACE(); \
virtual ~I##INTERFACE(); \
#define IMPLEMENT_META_INTERFACE(INTERFACE, NAME) \
const ::android::String16 I##INTERFACE::descriptor(NAME); \
const ::android::String16& \
I##INTERFACE::getInterfaceDescriptor() const { \
return I##INTERFACE::descriptor; \
} \
::android::sp<I##INTERFACE> I##INTERFACE::asInterface( \
const ::android::sp<::android::IBinder>& obj) \
{ \
::android::sp<I##INTERFACE> intr; \
if (obj != NULL) { \
intr = static_cast<I##INTERFACE*>( \
obj->queryLocalInterface( \
I##INTERFACE::descriptor).get()); \
if (intr == NULL) { \
intr = new Bp##INTERFACE(obj); \
} \
} \
return intr; \
} \
I##INTERFACE::I##INTERFACE() { } \
I##INTERFACE::~I##INTERFACE() { } \
#define CHECK_INTERFACE(interface, data, reply) \
if (!(data).checkInterface(this)) { return PERMISSION_DENIED; } \
// ----------------------------------------------------------------------
// No user-serviceable parts after this...
template<typename INTERFACE>
inline sp<IInterface> BnInterface<INTERFACE>::queryLocalInterface(
const String16& _descriptor)
{
if (_descriptor == INTERFACE::descriptor) return this;
return NULL;
}
template<typename INTERFACE>
inline const String16& BnInterface<INTERFACE>::getInterfaceDescriptor() const
{
return INTERFACE::getInterfaceDescriptor();
}
template<typename INTERFACE>
IBinder* BnInterface<INTERFACE>::onAsBinder()
{
return this;
}
template<typename INTERFACE>
inline BpInterface<INTERFACE>::BpInterface(const sp<IBinder>& remote)
: BpRefBase(remote)
{
}
template<typename INTERFACE>
inline IBinder* BpInterface<INTERFACE>::onAsBinder()
{
return remote();
}
// ----------------------------------------------------------------------
}; // namespace android
#endif // ANDROID_IINTERFACE_H

View file

@ -0,0 +1,55 @@
/*
* Copyright 2016 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_MEDIA_RESOURCE_MONITOR_H
#define ANDROID_I_MEDIA_RESOURCE_MONITOR_H
#include <binder/IInterface.h>
namespace android {
// ----------------------------------------------------------------------
class IMediaResourceMonitor : public IInterface {
public:
DECLARE_META_INTERFACE(MediaResourceMonitor)
// Values should be in sync with Intent.EXTRA_MEDIA_RESOURCE_TYPE_XXX.
enum {
TYPE_VIDEO_CODEC = 0,
TYPE_AUDIO_CODEC = 1,
};
virtual void notifyResourceGranted(/*in*/ int32_t pid, /*in*/ const int32_t type) = 0;
enum {
NOTIFY_RESOURCE_GRANTED = IBinder::FIRST_CALL_TRANSACTION,
};
};
// ----------------------------------------------------------------------
class BnMediaResourceMonitor : public BnInterface<IMediaResourceMonitor> {
public:
virtual status_t onTransact(uint32_t code, const Parcel& data, Parcel* reply,
uint32_t flags = 0);
};
// ----------------------------------------------------------------------
}; // namespace android
#endif // ANDROID_I_MEDIA_RESOURCE_MONITOR_H

View file

@ -0,0 +1,102 @@
/*
* Copyright (C) 2007 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_IMEMORY_H
#define ANDROID_IMEMORY_H
#include <stdint.h>
#include <sys/types.h>
#include <sys/mman.h>
#include <utils/RefBase.h>
#include <utils/Errors.h>
#include <binder/IInterface.h>
namespace android {
// ----------------------------------------------------------------------------
class IMemoryHeap : public IInterface
{
public:
DECLARE_META_INTERFACE(MemoryHeap)
// flags returned by getFlags()
enum {
READ_ONLY = 0x00000001
};
virtual int getHeapID() const = 0;
virtual void* getBase() const = 0;
virtual size_t getSize() const = 0;
virtual uint32_t getFlags() const = 0;
virtual uint32_t getOffset() const = 0;
// these are there just for backward source compatibility
int32_t heapID() const { return getHeapID(); }
void* base() const { return getBase(); }
size_t virtualSize() const { return getSize(); }
};
class BnMemoryHeap : public BnInterface<IMemoryHeap>
{
public:
virtual status_t onTransact(
uint32_t code,
const Parcel& data,
Parcel* reply,
uint32_t flags = 0);
BnMemoryHeap();
protected:
virtual ~BnMemoryHeap();
};
// ----------------------------------------------------------------------------
class IMemory : public IInterface
{
public:
DECLARE_META_INTERFACE(Memory)
virtual sp<IMemoryHeap> getMemory(ssize_t* offset=0, size_t* size=0) const = 0;
// helpers
void* fastPointer(const sp<IBinder>& heap, ssize_t offset) const;
void* pointer() const;
size_t size() const;
ssize_t offset() const;
};
class BnMemory : public BnInterface<IMemory>
{
public:
virtual status_t onTransact(
uint32_t code,
const Parcel& data,
Parcel* reply,
uint32_t flags = 0);
BnMemory();
protected:
virtual ~BnMemory();
};
// ----------------------------------------------------------------------------
}; // namespace android
#endif // ANDROID_IMEMORY_H

View file

@ -0,0 +1,135 @@
/*
* Copyright (C) 2005 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_IPC_THREAD_STATE_H
#define ANDROID_IPC_THREAD_STATE_H
#include <utils/Errors.h>
#include <binder/Parcel.h>
#include <binder/ProcessState.h>
#include <utils/Vector.h>
#if defined(_WIN32)
typedef int uid_t;
#endif
// ---------------------------------------------------------------------------
namespace android {
class IPCThreadState
{
public:
static IPCThreadState* self();
static IPCThreadState* selfOrNull(); // self(), but won't instantiate
sp<ProcessState> process();
status_t clearLastError();
pid_t getCallingPid() const;
uid_t getCallingUid() const;
void setStrictModePolicy(int32_t policy);
int32_t getStrictModePolicy() const;
void setLastTransactionBinderFlags(int32_t flags);
int32_t getLastTransactionBinderFlags() const;
int64_t clearCallingIdentity();
void restoreCallingIdentity(int64_t token);
int setupPolling(int* fd);
status_t handlePolledCommands();
void flushCommands();
void joinThreadPool(bool isMain = true);
// Stop the local process.
void stopProcess(bool immediate = true);
status_t transact(int32_t handle,
uint32_t code, const Parcel& data,
Parcel* reply, uint32_t flags);
void incStrongHandle(int32_t handle);
void decStrongHandle(int32_t handle);
void incWeakHandle(int32_t handle);
void decWeakHandle(int32_t handle);
status_t attemptIncStrongHandle(int32_t handle);
static void expungeHandle(int32_t handle, IBinder* binder);
status_t requestDeathNotification( int32_t handle,
BpBinder* proxy);
status_t clearDeathNotification( int32_t handle,
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);
bool backgroundSchedulingDisabled();
// 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();
status_t sendReply(const Parcel& reply, uint32_t flags);
status_t waitForResponse(Parcel *reply,
status_t *acquireResult=NULL);
status_t talkWithDriver(bool doReceive=true);
status_t writeTransactionData(int32_t cmd,
uint32_t binderFlags,
int32_t handle,
uint32_t code,
const Parcel& data,
status_t* statusBuffer);
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,
const binder_size_t* objects, size_t objectsSize,
void* cookie);
const sp<ProcessState> mProcess;
Vector<BBinder*> mPendingStrongDerefs;
Vector<RefBase::weakref_type*> mPendingWeakDerefs;
Parcel mIn;
Parcel mOut;
status_t mLastError;
pid_t mCallingPid;
uid_t mCallingUid;
int32_t mStrictModePolicy;
int32_t mLastTransactionBinderFlags;
};
}; // namespace android
// ---------------------------------------------------------------------------
#endif // ANDROID_IPC_THREAD_STATE_H

View file

@ -0,0 +1,62 @@
/*
* Copyright (C) 2005 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_IPERMISSION_CONTROLLER_H
#define ANDROID_IPERMISSION_CONTROLLER_H
#include <binder/IInterface.h>
#include <stdlib.h>
namespace android {
// ----------------------------------------------------------------------
class IPermissionController : public IInterface
{
public:
DECLARE_META_INTERFACE(PermissionController)
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,
GET_PACKAGES_FOR_UID_TRANSACTION = IBinder::FIRST_CALL_TRANSACTION + 1,
IS_RUNTIME_PERMISSION_TRANSACTION = IBinder::FIRST_CALL_TRANSACTION + 2
};
};
// ----------------------------------------------------------------------
class BnPermissionController : public BnInterface<IPermissionController>
{
public:
virtual status_t onTransact( uint32_t code,
const Parcel& data,
Parcel* reply,
uint32_t flags = 0);
};
// ----------------------------------------------------------------------
}; // namespace android
#endif // ANDROID_IPERMISSION_CONTROLLER_H

View file

@ -0,0 +1,49 @@
/*
* 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;
virtual status_t getProcessStatesAndOomScoresFromPids( size_t length,
/*in*/ int32_t* pids,
/*out*/ int32_t* states,
/*out*/ int32_t* scores) = 0;
enum {
GET_PROCESS_STATES_FROM_PIDS = IBinder::FIRST_CALL_TRANSACTION,
GET_PROCESS_STATES_AND_OOM_SCORES_FROM_PIDS,
};
};
// ----------------------------------------------------------------------
}; // namespace android
#endif // ANDROID_I_PROCESS_INFO_SERVICE_H

View file

@ -0,0 +1,55 @@
/*
* Copyright (C) 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_IRESULT_RECEIVER_H
#define ANDROID_IRESULT_RECEIVER_H
#include <binder/IInterface.h>
namespace android {
// ----------------------------------------------------------------------
class IResultReceiver : public IInterface
{
public:
DECLARE_META_INTERFACE(ResultReceiver)
virtual void send(int32_t resultCode) = 0;
enum {
OP_SEND = IBinder::FIRST_CALL_TRANSACTION
};
};
// ----------------------------------------------------------------------
class BnResultReceiver : public BnInterface<IResultReceiver>
{
public:
virtual status_t onTransact( uint32_t code,
const Parcel& data,
Parcel* reply,
uint32_t flags = 0);
};
// ----------------------------------------------------------------------
}; // namespace android
#endif // ANDROID_IRESULT_RECEIVER_H

View file

@ -0,0 +1,87 @@
/*
* Copyright (C) 2005 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_ISERVICE_MANAGER_H
#define ANDROID_ISERVICE_MANAGER_H
#include <binder/IInterface.h>
#include <binder/IPermissionController.h>
#include <utils/Vector.h>
#include <utils/String16.h>
namespace android {
// ----------------------------------------------------------------------
class IServiceManager : public IInterface
{
public:
DECLARE_META_INTERFACE(ServiceManager)
/**
* Retrieve an existing service, blocking for a few seconds
* if it doesn't yet exist.
*/
virtual sp<IBinder> getService( const String16& name) const = 0;
/**
* Retrieve an existing service, non-blocking.
*/
virtual sp<IBinder> checkService( const String16& name) const = 0;
/**
* Register a service.
*/
virtual status_t addService( const String16& name,
const sp<IBinder>& service,
bool allowIsolated = false) = 0;
/**
* Return list of all existing services.
*/
virtual Vector<String16> listServices() = 0;
enum {
GET_SERVICE_TRANSACTION = IBinder::FIRST_CALL_TRANSACTION,
CHECK_SERVICE_TRANSACTION,
ADD_SERVICE_TRANSACTION,
LIST_SERVICES_TRANSACTION,
};
};
sp<IServiceManager> defaultServiceManager();
template<typename INTERFACE>
status_t getService(const String16& name, sp<INTERFACE>* outService)
{
const sp<IServiceManager> sm = defaultServiceManager();
if (sm != NULL) {
*outService = interface_cast<INTERFACE>(sm->getService(name));
if ((*outService) != NULL) return NO_ERROR;
}
return NAME_NOT_FOUND;
}
bool checkCallingPermission(const String16& permission);
bool checkCallingPermission(const String16& permission,
int32_t* outPid, int32_t* outUid);
bool checkPermission(const String16& permission, pid_t pid, uid_t uid);
}; // namespace android
#endif // ANDROID_ISERVICE_MANAGER_H

View file

@ -0,0 +1,55 @@
/*
* Copyright (C) 2016 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_ISHELL_CALLBACK_H
#define ANDROID_ISHELL_CALLBACK_H
#include <binder/IInterface.h>
namespace android {
// ----------------------------------------------------------------------
class IShellCallback : public IInterface
{
public:
DECLARE_META_INTERFACE(ShellCallback);
virtual int openOutputFile(const String16& path, const String16& seLinuxContext) = 0;
enum {
OP_OPEN_OUTPUT_FILE = IBinder::FIRST_CALL_TRANSACTION
};
};
// ----------------------------------------------------------------------
class BnShellCallback : public BnInterface<IShellCallback>
{
public:
virtual status_t onTransact( uint32_t code,
const Parcel& data,
Parcel* reply,
uint32_t flags = 0);
};
// ----------------------------------------------------------------------
}; // namespace android
#endif // ANDROID_ISHELL_CALLBACK_H

View file

@ -0,0 +1,88 @@
/*
* Copyright (C) 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_IP_PREFIX_H
#define ANDROID_IP_PREFIX_H
#include <netinet/in.h>
#include <binder/Parcelable.h>
#include <utils/String16.h>
#include <utils/StrongPointer.h>
namespace android {
namespace net {
/*
* C++ implementation of the Java class android.net.IpPrefix
*/
class IpPrefix : public Parcelable {
public:
IpPrefix() = default;
virtual ~IpPrefix() = default;
IpPrefix(const IpPrefix& prefix) = default;
IpPrefix(const struct in6_addr& addr, int32_t plen):
mUnion(addr), mPrefixLength(plen), mIsIpv6(true) { }
IpPrefix(const struct in_addr& addr, int32_t plen):
mUnion(addr), mPrefixLength(plen), mIsIpv6(false) { }
bool getAddressAsIn6Addr(struct in6_addr* addr) const;
bool getAddressAsInAddr(struct in_addr* addr) const;
const struct in6_addr& getAddressAsIn6Addr() const;
const struct in_addr& getAddressAsInAddr() const;
bool isIpv6() const;
bool isIpv4() const;
int32_t getPrefixLength() const;
void setAddress(const struct in6_addr& addr);
void setAddress(const struct in_addr& addr);
void setPrefixLength(int32_t prefix);
friend bool operator==(const IpPrefix& lhs, const IpPrefix& rhs);
friend bool operator!=(const IpPrefix& lhs, const IpPrefix& rhs) {
return !(lhs == rhs);
}
public:
// Overrides
status_t writeToParcel(Parcel* parcel) const override;
status_t readFromParcel(const Parcel* parcel) override;
private:
union InternalUnion {
InternalUnion() = default;
InternalUnion(const struct in6_addr &addr):mIn6Addr(addr) { };
InternalUnion(const struct in_addr &addr):mInAddr(addr) { };
struct in6_addr mIn6Addr;
struct in_addr mInAddr;
} mUnion;
int32_t mPrefixLength;
bool mIsIpv6;
};
} // namespace net
} // namespace android
#endif // ANDROID_IP_PREFIX_H

View file

@ -0,0 +1,39 @@
/*
* Copyright (C) 2005 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_MAP_H
#define ANDROID_MAP_H
#include <map>
#include <string>
// ---------------------------------------------------------------------------
namespace android {
namespace binder {
class Value;
/**
* Convenience typedef for ::std::map<::std::string,::android::binder::Value>
*/
typedef ::std::map<::std::string, Value> Map;
} // namespace binder
} // namespace android
// ---------------------------------------------------------------------------
#endif // ANDROID_MAP_H

View file

@ -0,0 +1,51 @@
/*
* Copyright (C) 2008 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_MEMORY_BASE_H
#define ANDROID_MEMORY_BASE_H
#include <stdlib.h>
#include <stdint.h>
#include <binder/IMemory.h>
namespace android {
// ---------------------------------------------------------------------------
class MemoryBase : public BnMemory
{
public:
MemoryBase(const sp<IMemoryHeap>& heap, ssize_t offset, size_t size);
virtual ~MemoryBase();
virtual sp<IMemoryHeap> getMemory(ssize_t* offset, size_t* size) const;
protected:
size_t getSize() const { return mSize; }
ssize_t getOffset() const { return mOffset; }
const sp<IMemoryHeap>& getHeap() const { return mHeap; }
private:
size_t mSize;
ssize_t mOffset;
sp<IMemoryHeap> mHeap;
};
// ---------------------------------------------------------------------------
}; // namespace android
#endif // ANDROID_MEMORY_BASE_H

View file

@ -0,0 +1,64 @@
/*
* Copyright (C) 2007 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_MEMORY_DEALER_H
#define ANDROID_MEMORY_DEALER_H
#include <stdint.h>
#include <sys/types.h>
#include <binder/IMemory.h>
#include <binder/MemoryHeapBase.h>
namespace android {
// ----------------------------------------------------------------------------
class SimpleBestFitAllocator;
// ----------------------------------------------------------------------------
class MemoryDealer : public RefBase
{
public:
MemoryDealer(size_t size, const char* name = 0,
uint32_t flags = 0 /* or bits such as MemoryHeapBase::READ_ONLY */ );
virtual sp<IMemory> allocate(size_t size);
virtual void deallocate(size_t offset);
virtual void dump(const char* what) const;
// allocations are aligned to some value. return that value so clients can account for it.
static size_t getAllocationAlignment();
sp<IMemoryHeap> getMemoryHeap() const { return heap(); }
protected:
virtual ~MemoryDealer();
private:
const sp<IMemoryHeap>& heap() const;
SimpleBestFitAllocator* allocator() const;
sp<IMemoryHeap> mHeap;
SimpleBestFitAllocator* mAllocator;
};
// ----------------------------------------------------------------------------
}; // namespace android
#endif // ANDROID_MEMORY_DEALER_H

View file

@ -0,0 +1,103 @@
/*
* Copyright (C) 2008 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_MEMORY_HEAP_BASE_H
#define ANDROID_MEMORY_HEAP_BASE_H
#include <stdlib.h>
#include <stdint.h>
#include <binder/IMemory.h>
namespace android {
// ---------------------------------------------------------------------------
class MemoryHeapBase : public virtual BnMemoryHeap
{
public:
enum {
READ_ONLY = IMemoryHeap::READ_ONLY,
// memory won't be mapped locally, but will be mapped in the remote
// process.
DONT_MAP_LOCALLY = 0x00000100,
NO_CACHING = 0x00000200
};
/*
* maps the memory referenced by fd. but DOESN'T take ownership
* of the filedescriptor (it makes a copy with dup()
*/
MemoryHeapBase(int fd, size_t size, uint32_t flags = 0, uint32_t offset = 0);
/*
* maps memory from the given device
*/
MemoryHeapBase(const char* device, size_t size = 0, uint32_t flags = 0);
/*
* maps memory from ashmem, with the given name for debugging
*/
MemoryHeapBase(size_t size, uint32_t flags = 0, char const* name = NULL);
virtual ~MemoryHeapBase();
/* implement IMemoryHeap interface */
virtual int getHeapID() const;
/* virtual address of the heap. returns MAP_FAILED in case of error */
virtual void* getBase() const;
virtual size_t getSize() const;
virtual uint32_t getFlags() const;
virtual uint32_t getOffset() const;
const char* getDevice() const;
/* this closes this heap -- use carefully */
void dispose();
/* this is only needed as a workaround, use only if you know
* what you are doing */
status_t setDevice(const char* device) {
if (mDevice == 0)
mDevice = device;
return mDevice ? NO_ERROR : ALREADY_EXISTS;
}
protected:
MemoryHeapBase();
// init() takes ownership of fd
status_t init(int fd, void *base, int size,
int flags = 0, const char* device = NULL);
private:
status_t mapfd(int fd, size_t size, uint32_t offset = 0);
int mFD;
size_t mSize;
void* mBase;
uint32_t mFlags;
const char* mDevice;
bool mNeedUnmap;
uint32_t mOffset;
};
// ---------------------------------------------------------------------------
}; // namespace android
#endif // ANDROID_MEMORY_HEAP_BASE_H

View file

@ -0,0 +1,932 @@
/*
* Copyright (C) 2005 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_PARCEL_H
#define ANDROID_PARCEL_H
#include <string>
#include <vector>
#include <android-base/unique_fd.h>
#include <cutils/native_handle.h>
#include <utils/Errors.h>
#include <utils/RefBase.h>
#include <utils/String16.h>
#include <utils/Vector.h>
#include <utils/Flattenable.h>
#include <linux/android/binder.h>
#include <binder/IInterface.h>
#include <binder/Parcelable.h>
#include <binder/Map.h>
// ---------------------------------------------------------------------------
namespace android {
template <typename T> class Flattenable;
template <typename T> class LightFlattenable;
class IBinder;
class IPCThreadState;
class ProcessState;
class String8;
class TextOutput;
namespace binder {
class Value;
};
class Parcel {
friend class IPCThreadState;
public:
class ReadableBlob;
class WritableBlob;
Parcel();
~Parcel();
const uint8_t* data() const;
size_t dataSize() const;
size_t dataAvail() const;
size_t dataPosition() const;
size_t dataCapacity() const;
status_t setDataSize(size_t size);
void setDataPosition(size_t pos) const;
status_t setDataCapacity(size_t size);
status_t setData(const uint8_t* buffer, size_t len);
status_t appendFrom(const Parcel *parcel,
size_t start, size_t len);
int compareData(const Parcel& other);
bool allowFds() const;
bool pushAllowFds(bool allowFds);
void restoreAllowFds(bool lastValue);
bool hasFileDescriptors() const;
// Writes the RPC header.
status_t writeInterfaceToken(const String16& interface);
// Parses the RPC header, returning true if the interface name
// in the header matches the expected interface from the caller.
//
// Additionally, enforceInterface does part of the work of
// propagating the StrictMode policy mask, populating the current
// IPCThreadState, which as an optimization may optionally be
// passed in.
bool enforceInterface(const String16& interface,
IPCThreadState* threadState = NULL) const;
bool checkInterface(IBinder*) const;
void freeData();
private:
const binder_size_t* objects() const;
public:
size_t objectsCount() const;
status_t errorCheck() const;
void setError(status_t err);
status_t write(const void* data, size_t len);
void* writeInplace(size_t len);
status_t writeUnpadded(const void* data, size_t len);
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);
status_t writeString8(const String8& str);
status_t writeString16(const String16& str);
status_t writeString16(const std::unique_ptr<String16>& str);
status_t writeString16(const char16_t* str, size_t len);
status_t writeStrongBinder(const sp<IBinder>& val);
status_t writeWeakBinder(const wp<IBinder>& val);
status_t writeInt32Array(size_t len, const int32_t *val);
status_t writeByteArray(size_t len, const uint8_t *val);
status_t writeBool(bool val);
status_t writeChar(char16_t val);
status_t writeByte(int8_t val);
// Take a UTF8 encoded string, convert to UTF16, write it to the parcel.
status_t writeUtf8AsUtf16(const std::string& str);
status_t writeUtf8AsUtf16(const std::unique_ptr<std::string>& str);
status_t writeByteVector(const std::unique_ptr<std::vector<int8_t>>& val);
status_t writeByteVector(const std::vector<int8_t>& val);
status_t writeByteVector(const std::unique_ptr<std::vector<uint8_t>>& val);
status_t writeByteVector(const std::vector<uint8_t>& val);
status_t writeInt32Vector(const std::unique_ptr<std::vector<int32_t>>& val);
status_t writeInt32Vector(const std::vector<int32_t>& val);
status_t writeInt64Vector(const std::unique_ptr<std::vector<int64_t>>& val);
status_t writeInt64Vector(const std::vector<int64_t>& val);
status_t writeFloatVector(const std::unique_ptr<std::vector<float>>& val);
status_t writeFloatVector(const std::vector<float>& val);
status_t writeDoubleVector(const std::unique_ptr<std::vector<double>>& val);
status_t writeDoubleVector(const std::vector<double>& val);
status_t writeBoolVector(const std::unique_ptr<std::vector<bool>>& val);
status_t writeBoolVector(const std::vector<bool>& val);
status_t writeCharVector(const std::unique_ptr<std::vector<char16_t>>& val);
status_t writeCharVector(const std::vector<char16_t>& val);
status_t writeString16Vector(
const std::unique_ptr<std::vector<std::unique_ptr<String16>>>& val);
status_t writeString16Vector(const std::vector<String16>& val);
status_t writeUtf8VectorAsUtf16Vector(
const std::unique_ptr<std::vector<std::unique_ptr<std::string>>>& val);
status_t writeUtf8VectorAsUtf16Vector(const std::vector<std::string>& val);
status_t writeStrongBinderVector(const std::unique_ptr<std::vector<sp<IBinder>>>& val);
status_t writeStrongBinderVector(const std::vector<sp<IBinder>>& val);
template<typename T>
status_t writeParcelableVector(const std::unique_ptr<std::vector<std::unique_ptr<T>>>& val);
template<typename T>
status_t writeParcelableVector(const std::shared_ptr<std::vector<std::unique_ptr<T>>>& val);
template<typename T>
status_t writeParcelableVector(const std::vector<T>& val);
template<typename T>
status_t writeNullableParcelable(const std::unique_ptr<T>& parcelable);
status_t writeParcelable(const Parcelable& parcelable);
status_t writeValue(const binder::Value& value);
template<typename T>
status_t write(const Flattenable<T>& val);
template<typename T>
status_t write(const LightFlattenable<T>& val);
template<typename T>
status_t writeVectorSize(const std::vector<T>& val);
template<typename T>
status_t writeVectorSize(const std::unique_ptr<std::vector<T>>& val);
status_t writeMap(const binder::Map& map);
status_t writeNullableMap(const std::unique_ptr<binder::Map>& map);
// Place a native_handle into the parcel (the native_handle's file-
// descriptors are dup'ed, so it is safe to delete the native_handle
// when this function returns).
// Doesn't take ownership of the native_handle.
status_t writeNativeHandle(const native_handle* handle);
// Place a file descriptor into the parcel. The given fd must remain
// valid for the lifetime of the parcel.
// The Parcel does not take ownership of the given fd unless you ask it to.
status_t writeFileDescriptor(int fd, bool takeOwnership = false);
// Place a file descriptor into the parcel. A dup of the fd is made, which
// will be closed once the parcel is destroyed.
status_t writeDupFileDescriptor(int fd);
// Place a Java "parcel file descriptor" into the parcel. The given fd must remain
// valid for the lifetime of the parcel.
// The Parcel does not take ownership of the given fd unless you ask it to.
status_t writeParcelFileDescriptor(int fd, bool takeOwnership = false);
// Place a file descriptor into the parcel. This will not affect the
// semantics of the smart file descriptor. A new descriptor will be
// created, and will be closed when the parcel is destroyed.
status_t writeUniqueFileDescriptor(
const base::unique_fd& fd);
// Place a vector of file desciptors into the parcel. Each descriptor is
// dup'd as in writeDupFileDescriptor
status_t writeUniqueFileDescriptorVector(
const std::unique_ptr<std::vector<base::unique_fd>>& val);
status_t writeUniqueFileDescriptorVector(
const std::vector<base::unique_fd>& val);
// 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. 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, 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);
// Like Parcel.java's writeNoException(). Just writes a zero int32.
// Currently the native implementation doesn't do any of the StrictMode
// stack gathering and serialization that the Java implementation does.
status_t writeNoException();
void remove(size_t start, size_t amt);
status_t read(void* outData, size_t len) const;
const void* readInplace(size_t len) const;
int32_t readInt32() const;
status_t readInt32(int32_t *pArg) const;
uint32_t readUint32() const;
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;
status_t readDouble(double *pArg) const;
intptr_t readIntPtr() const;
status_t readIntPtr(intptr_t *pArg) const;
bool readBool() const;
status_t readBool(bool *pArg) const;
char16_t readChar() const;
status_t readChar(char16_t *pArg) const;
int8_t readByte() const;
status_t readByte(int8_t *pArg) const;
// Read a UTF16 encoded string, convert to UTF8
status_t readUtf8FromUtf16(std::string* str) const;
status_t readUtf8FromUtf16(std::unique_ptr<std::string>* str) const;
const char* readCString() const;
String8 readString8() const;
status_t readString8(String8* pArg) const;
String16 readString16() const;
status_t readString16(String16* pArg) const;
status_t readString16(std::unique_ptr<String16>* pArg) const;
const char16_t* readString16Inplace(size_t* outLen) const;
sp<IBinder> readStrongBinder() const;
status_t readStrongBinder(sp<IBinder>* val) const;
status_t readNullableStrongBinder(sp<IBinder>* val) const;
wp<IBinder> readWeakBinder() const;
template<typename T>
status_t readParcelableVector(
std::unique_ptr<std::vector<std::unique_ptr<T>>>* val) const;
template<typename T>
status_t readParcelableVector(std::vector<T>* val) const;
status_t readParcelable(Parcelable* parcelable) const;
template<typename T>
status_t readParcelable(std::unique_ptr<T>* parcelable) const;
status_t readValue(binder::Value* value) const;
template<typename T>
status_t readStrongBinder(sp<T>* val) const;
template<typename T>
status_t readNullableStrongBinder(sp<T>* val) const;
status_t readStrongBinderVector(std::unique_ptr<std::vector<sp<IBinder>>>* val) const;
status_t readStrongBinderVector(std::vector<sp<IBinder>>* val) const;
status_t readByteVector(std::unique_ptr<std::vector<int8_t>>* val) const;
status_t readByteVector(std::vector<int8_t>* val) const;
status_t readByteVector(std::unique_ptr<std::vector<uint8_t>>* val) const;
status_t readByteVector(std::vector<uint8_t>* val) const;
status_t readInt32Vector(std::unique_ptr<std::vector<int32_t>>* val) const;
status_t readInt32Vector(std::vector<int32_t>* val) const;
status_t readInt64Vector(std::unique_ptr<std::vector<int64_t>>* val) const;
status_t readInt64Vector(std::vector<int64_t>* val) const;
status_t readFloatVector(std::unique_ptr<std::vector<float>>* val) const;
status_t readFloatVector(std::vector<float>* val) const;
status_t readDoubleVector(std::unique_ptr<std::vector<double>>* val) const;
status_t readDoubleVector(std::vector<double>* val) const;
status_t readBoolVector(std::unique_ptr<std::vector<bool>>* val) const;
status_t readBoolVector(std::vector<bool>* val) const;
status_t readCharVector(std::unique_ptr<std::vector<char16_t>>* val) const;
status_t readCharVector(std::vector<char16_t>* val) const;
status_t readString16Vector(
std::unique_ptr<std::vector<std::unique_ptr<String16>>>* val) const;
status_t readString16Vector(std::vector<String16>* val) const;
status_t readUtf8VectorFromUtf16Vector(
std::unique_ptr<std::vector<std::unique_ptr<std::string>>>* val) const;
status_t readUtf8VectorFromUtf16Vector(std::vector<std::string>* val) const;
template<typename T>
status_t read(Flattenable<T>& val) const;
template<typename T>
status_t read(LightFlattenable<T>& val) const;
template<typename T>
status_t resizeOutVector(std::vector<T>* val) const;
template<typename T>
status_t resizeOutVector(std::unique_ptr<std::vector<T>>* val) const;
status_t readMap(binder::Map* map)const;
status_t readNullableMap(std::unique_ptr<binder::Map>* map) const;
// Like Parcel.java's readExceptionCode(). Reads the first int32
// off of a Parcel's header, returning 0 or the negative error
// code on exceptions, but also deals with skipping over rich
// response headers. Callers should use this to read & parse the
// response headers rather than doing it by hand.
int32_t readExceptionCode() const;
// Retrieve native_handle from the parcel. This returns a copy of the
// parcel's native_handle (the caller takes ownership). The caller
// must free the native_handle with native_handle_close() and
// native_handle_delete().
native_handle* readNativeHandle() const;
// Retrieve a file descriptor from the parcel. This returns the raw fd
// in the parcel, which you do not own -- use dup() to get your own copy.
int readFileDescriptor() const;
// Retrieve a Java "parcel file descriptor" from the parcel. This returns the raw fd
// in the parcel, which you do not own -- use dup() to get your own copy.
int readParcelFileDescriptor() const;
// Retrieve a smart file descriptor from the parcel.
status_t readUniqueFileDescriptor(
base::unique_fd* val) const;
// Retrieve a vector of smart file descriptors from the parcel.
status_t readUniqueFileDescriptorVector(
std::unique_ptr<std::vector<base::unique_fd>>* val) const;
status_t readUniqueFileDescriptorVector(
std::vector<base::unique_fd>* val) 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;
const flat_binder_object* readObject(bool nullMetaData) const;
// Explicitly close all file descriptors in the parcel.
void closeFileDescriptors();
// Debugging: get metrics on current allocations.
static size_t getGlobalAllocSize();
static size_t getGlobalAllocCount();
private:
typedef void (*release_func)(Parcel* parcel,
const uint8_t* data, size_t dataSize,
const binder_size_t* objects, size_t objectsSize,
void* cookie);
uintptr_t ipcData() const;
size_t ipcDataSize() const;
uintptr_t ipcObjects() const;
size_t ipcObjectsCount() const;
void ipcSetDataReference(const uint8_t* data, size_t dataSize,
const binder_size_t* objects, size_t objectsCount,
release_func relFunc, void* relCookie);
public:
void print(TextOutput& to, uint32_t flags = 0) const;
private:
Parcel(const Parcel& o);
Parcel& operator=(const Parcel& o);
status_t finishWrite(size_t len);
void releaseObjects();
void acquireObjects();
status_t growData(size_t len);
status_t restartWrite(size_t desired);
status_t continueWrite(size_t desired);
status_t writePointer(uintptr_t val);
status_t readPointer(uintptr_t *pArg) const;
uintptr_t readPointer() const;
void freeDataNoInit();
void initState();
void scanForFds() const;
template<class T>
status_t readAligned(T *pArg) const;
template<class T> T readAligned() const;
template<class T>
status_t writeAligned(T val);
status_t writeRawNullableParcelable(const Parcelable*
parcelable);
template<typename T, typename U>
status_t unsafeReadTypedVector(std::vector<T>* val,
status_t(Parcel::*read_func)(U*) const) const;
template<typename T>
status_t readNullableTypedVector(std::unique_ptr<std::vector<T>>* val,
status_t(Parcel::*read_func)(T*) const) const;
template<typename T>
status_t readTypedVector(std::vector<T>* val,
status_t(Parcel::*read_func)(T*) const) const;
template<typename T, typename U>
status_t unsafeWriteTypedVector(const std::vector<T>& val,
status_t(Parcel::*write_func)(U));
template<typename T>
status_t writeNullableTypedVector(const std::unique_ptr<std::vector<T>>& val,
status_t(Parcel::*write_func)(const T&));
template<typename T>
status_t writeNullableTypedVector(const std::unique_ptr<std::vector<T>>& val,
status_t(Parcel::*write_func)(T));
template<typename T>
status_t writeTypedVector(const std::vector<T>& val,
status_t(Parcel::*write_func)(const T&));
template<typename T>
status_t writeTypedVector(const std::vector<T>& val,
status_t(Parcel::*write_func)(T));
status_t mError;
uint8_t* mData;
size_t mDataSize;
size_t mDataCapacity;
mutable size_t mDataPos;
binder_size_t* mObjects;
size_t mObjectsSize;
size_t mObjectsCapacity;
mutable size_t mNextObjectHint;
mutable bool mFdsKnown;
mutable bool mHasFds;
bool mAllowFds;
release_func mOwner;
void* mOwnerCookie;
class Blob {
public:
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(int fd, void* data, size_t size, bool isMutable);
int mFd; // owned by parcel so not closed when released
void* mData;
size_t mSize;
bool mMutable;
};
#if defined(__clang__)
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wweak-vtables"
#endif
// FlattenableHelperInterface and FlattenableHelper avoid generating a vtable entry in objects
// following Flattenable template/protocol.
class FlattenableHelperInterface {
protected:
~FlattenableHelperInterface() { }
public:
virtual size_t getFlattenedSize() const = 0;
virtual size_t getFdCount() const = 0;
virtual status_t flatten(void* buffer, size_t size, int* fds, size_t count) const = 0;
virtual status_t unflatten(void const* buffer, size_t size, int const* fds, size_t count) = 0;
};
#if defined(__clang__)
#pragma clang diagnostic pop
#endif
// Concrete implementation of FlattenableHelperInterface that delegates virtual calls to the
// specified class T implementing the Flattenable protocol. It "virtualizes" a compile-time
// protocol.
template<typename T>
class FlattenableHelper : public FlattenableHelperInterface {
friend class Parcel;
const Flattenable<T>& val;
explicit FlattenableHelper(const Flattenable<T>& _val) : val(_val) { }
protected:
~FlattenableHelper() = default;
public:
virtual size_t getFlattenedSize() const {
return val.getFlattenedSize();
}
virtual size_t getFdCount() const {
return val.getFdCount();
}
virtual status_t flatten(void* buffer, size_t size, int* fds, size_t count) const {
return val.flatten(buffer, size, fds, count);
}
virtual status_t unflatten(void const* buffer, size_t size, int const* fds, size_t count) {
return const_cast<Flattenable<T>&>(val).unflatten(buffer, size, fds, count);
}
};
status_t write(const FlattenableHelperInterface& val);
status_t read(FlattenableHelperInterface& val) const;
public:
class ReadableBlob : public Blob {
friend class Parcel;
public:
inline const void* data() const { return mData; }
inline void* mutableData() { return isMutable() ? mData : NULL; }
};
class WritableBlob : public Blob {
friend class Parcel;
public:
inline void* data() { return mData; }
};
private:
size_t mOpenAshmemSize;
public:
// TODO: Remove once ABI can be changed.
size_t getBlobAshmemSize() const;
size_t getOpenAshmemSize() const;
};
// ---------------------------------------------------------------------------
template<typename T>
status_t Parcel::write(const Flattenable<T>& val) {
const FlattenableHelper<T> helper(val);
return write(helper);
}
template<typename T>
status_t Parcel::write(const LightFlattenable<T>& val) {
size_t size(val.getFlattenedSize());
if (!val.isFixedSize()) {
if (size > INT32_MAX) {
return BAD_VALUE;
}
status_t err = writeInt32(static_cast<int32_t>(size));
if (err != NO_ERROR) {
return err;
}
}
if (size) {
void* buffer = writeInplace(size);
if (buffer == NULL)
return NO_MEMORY;
return val.flatten(buffer, size);
}
return NO_ERROR;
}
template<typename T>
status_t Parcel::read(Flattenable<T>& val) const {
FlattenableHelper<T> helper(val);
return read(helper);
}
template<typename T>
status_t Parcel::read(LightFlattenable<T>& val) const {
size_t size;
if (val.isFixedSize()) {
size = val.getFlattenedSize();
} else {
int32_t s;
status_t err = readInt32(&s);
if (err != NO_ERROR) {
return err;
}
size = static_cast<size_t>(s);
}
if (size) {
void const* buffer = readInplace(size);
return buffer == NULL ? NO_MEMORY :
val.unflatten(buffer, size);
}
return NO_ERROR;
}
template<typename T>
status_t Parcel::writeVectorSize(const std::vector<T>& val) {
if (val.size() > INT32_MAX) {
return BAD_VALUE;
}
return writeInt32(static_cast<int32_t>(val.size()));
}
template<typename T>
status_t Parcel::writeVectorSize(const std::unique_ptr<std::vector<T>>& val) {
if (!val) {
return writeInt32(-1);
}
return writeVectorSize(*val);
}
template<typename T>
status_t Parcel::resizeOutVector(std::vector<T>* val) const {
int32_t size;
status_t err = readInt32(&size);
if (err != NO_ERROR) {
return err;
}
if (size < 0) {
return UNEXPECTED_NULL;
}
val->resize(size_t(size));
return OK;
}
template<typename T>
status_t Parcel::resizeOutVector(std::unique_ptr<std::vector<T>>* val) const {
int32_t size;
status_t err = readInt32(&size);
if (err != NO_ERROR) {
return err;
}
val->reset();
if (size >= 0) {
val->reset(new std::vector<T>(size_t(size)));
}
return OK;
}
template<typename T>
status_t Parcel::readStrongBinder(sp<T>* val) const {
sp<IBinder> tmp;
status_t ret = readStrongBinder(&tmp);
if (ret == OK) {
*val = interface_cast<T>(tmp);
if (val->get() == nullptr) {
return UNKNOWN_ERROR;
}
}
return ret;
}
template<typename T>
status_t Parcel::readNullableStrongBinder(sp<T>* val) const {
sp<IBinder> tmp;
status_t ret = readNullableStrongBinder(&tmp);
if (ret == OK) {
*val = interface_cast<T>(tmp);
if (val->get() == nullptr && tmp.get() != nullptr) {
ret = UNKNOWN_ERROR;
}
}
return ret;
}
template<typename T, typename U>
status_t Parcel::unsafeReadTypedVector(
std::vector<T>* val,
status_t(Parcel::*read_func)(U*) const) const {
int32_t size;
status_t status = this->readInt32(&size);
if (status != OK) {
return status;
}
if (size < 0) {
return UNEXPECTED_NULL;
}
if (val->max_size() < static_cast<size_t>(size)) {
return NO_MEMORY;
}
val->resize(static_cast<size_t>(size));
if (val->size() < static_cast<size_t>(size)) {
return NO_MEMORY;
}
for (auto& v: *val) {
status = (this->*read_func)(&v);
if (status != OK) {
return status;
}
}
return OK;
}
template<typename T>
status_t Parcel::readTypedVector(std::vector<T>* val,
status_t(Parcel::*read_func)(T*) const) const {
return unsafeReadTypedVector(val, read_func);
}
template<typename T>
status_t Parcel::readNullableTypedVector(std::unique_ptr<std::vector<T>>* val,
status_t(Parcel::*read_func)(T*) const) const {
const size_t start = dataPosition();
int32_t size;
status_t status = readInt32(&size);
val->reset();
if (status != OK || size < 0) {
return status;
}
setDataPosition(start);
val->reset(new std::vector<T>());
status = unsafeReadTypedVector(val->get(), read_func);
if (status != OK) {
val->reset();
}
return status;
}
template<typename T, typename U>
status_t Parcel::unsafeWriteTypedVector(const std::vector<T>& val,
status_t(Parcel::*write_func)(U)) {
if (val.size() > std::numeric_limits<int32_t>::max()) {
return BAD_VALUE;
}
status_t status = this->writeInt32(static_cast<int32_t>(val.size()));
if (status != OK) {
return status;
}
for (const auto& item : val) {
status = (this->*write_func)(item);
if (status != OK) {
return status;
}
}
return OK;
}
template<typename T>
status_t Parcel::writeTypedVector(const std::vector<T>& val,
status_t(Parcel::*write_func)(const T&)) {
return unsafeWriteTypedVector(val, write_func);
}
template<typename T>
status_t Parcel::writeTypedVector(const std::vector<T>& val,
status_t(Parcel::*write_func)(T)) {
return unsafeWriteTypedVector(val, write_func);
}
template<typename T>
status_t Parcel::writeNullableTypedVector(const std::unique_ptr<std::vector<T>>& val,
status_t(Parcel::*write_func)(const T&)) {
if (val.get() == nullptr) {
return this->writeInt32(-1);
}
return unsafeWriteTypedVector(*val, write_func);
}
template<typename T>
status_t Parcel::writeNullableTypedVector(const std::unique_ptr<std::vector<T>>& val,
status_t(Parcel::*write_func)(T)) {
if (val.get() == nullptr) {
return this->writeInt32(-1);
}
return unsafeWriteTypedVector(*val, write_func);
}
template<typename T>
status_t Parcel::readParcelableVector(std::vector<T>* val) const {
return unsafeReadTypedVector<T, Parcelable>(val, &Parcel::readParcelable);
}
template<typename T>
status_t Parcel::readParcelableVector(std::unique_ptr<std::vector<std::unique_ptr<T>>>* val) const {
const size_t start = dataPosition();
int32_t size;
status_t status = readInt32(&size);
val->reset();
if (status != OK || size < 0) {
return status;
}
setDataPosition(start);
val->reset(new std::vector<std::unique_ptr<T>>());
status = unsafeReadTypedVector(val->get(), &Parcel::readParcelable<T>);
if (status != OK) {
val->reset();
}
return status;
}
template<typename T>
status_t Parcel::readParcelable(std::unique_ptr<T>* parcelable) const {
const size_t start = dataPosition();
int32_t present;
status_t status = readInt32(&present);
parcelable->reset();
if (status != OK || !present) {
return status;
}
setDataPosition(start);
parcelable->reset(new T());
status = readParcelable(parcelable->get());
if (status != OK) {
parcelable->reset();
}
return status;
}
template<typename T>
status_t Parcel::writeNullableParcelable(const std::unique_ptr<T>& parcelable) {
return writeRawNullableParcelable(parcelable.get());
}
template<typename T>
status_t Parcel::writeParcelableVector(const std::vector<T>& val) {
return unsafeWriteTypedVector<T,const Parcelable&>(val, &Parcel::writeParcelable);
}
template<typename T>
status_t Parcel::writeParcelableVector(const std::unique_ptr<std::vector<std::unique_ptr<T>>>& val) {
if (val.get() == nullptr) {
return this->writeInt32(-1);
}
return unsafeWriteTypedVector(*val, &Parcel::writeNullableParcelable<T>);
}
template<typename T>
status_t Parcel::writeParcelableVector(const std::shared_ptr<std::vector<std::unique_ptr<T>>>& val) {
if (val.get() == nullptr) {
return this->writeInt32(-1);
}
return unsafeWriteTypedVector(*val, &Parcel::writeNullableParcelable<T>);
}
// ---------------------------------------------------------------------------
inline TextOutput& operator<<(TextOutput& to, const Parcel& parcel)
{
parcel.print(to);
return to;
}
// ---------------------------------------------------------------------------
// Generic acquire and release of objects.
void acquire_object(const sp<ProcessState>& proc,
const flat_binder_object& obj, const void* who);
void release_object(const sp<ProcessState>& proc,
const flat_binder_object& obj, const void* who);
void flatten_binder(const sp<ProcessState>& proc,
const sp<IBinder>& binder, flat_binder_object* out);
void flatten_binder(const sp<ProcessState>& proc,
const wp<IBinder>& binder, flat_binder_object* out);
status_t unflatten_binder(const sp<ProcessState>& proc,
const flat_binder_object& flat, sp<IBinder>* out);
status_t unflatten_binder(const sp<ProcessState>& proc,
const flat_binder_object& flat, wp<IBinder>* out);
}; // namespace android
// ---------------------------------------------------------------------------
#endif // ANDROID_PARCEL_H

View file

@ -0,0 +1,63 @@
/*
* Copyright (C) 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_PARCELABLE_H
#define ANDROID_PARCELABLE_H
#include <vector>
#include <utils/Errors.h>
#include <utils/String16.h>
namespace android {
class Parcel;
#if defined(__clang__)
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wweak-vtables"
#endif
// Abstract interface of all parcelables.
class Parcelable {
public:
virtual ~Parcelable() = default;
Parcelable() = default;
Parcelable(const Parcelable&) = default;
// Write |this| parcelable to the given |parcel|. Keep in mind that
// implementations of writeToParcel must be manually kept in sync
// with readFromParcel and the Java equivalent versions of these methods.
//
// Returns android::OK on success and an appropriate error otherwise.
virtual status_t writeToParcel(Parcel* parcel) const = 0;
// Read data from the given |parcel| into |this|. After readFromParcel
// completes, |this| should have equivalent state to the object that
// wrote itself to the parcel.
//
// Returns android::OK on success and an appropriate error otherwise.
virtual status_t readFromParcel(const Parcel* parcel) = 0;
}; // class Parcelable
#if defined(__clang__)
#pragma clang diagnostic pop
#endif
} // namespace android
#endif // ANDROID_PARCELABLE_H

View file

@ -0,0 +1,80 @@
/*
* Copyright (C) 2009 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 BINDER_PERMISSION_H
#define BINDER_PERMISSION_H
#include <stdint.h>
#include <unistd.h>
#include <utils/String16.h>
#include <utils/Singleton.h>
#include <utils/SortedVector.h>
namespace android {
// ---------------------------------------------------------------------------
/*
* PermissionCache caches permission checks for a given uid.
*
* Currently the cache is not updated when there is a permission change,
* for instance when an application is uninstalled.
*
* IMPORTANT: for the reason stated above, only system permissions are safe
* to cache. This restriction may be lifted at a later time.
*
*/
class PermissionCache : Singleton<PermissionCache> {
struct Entry {
String16 name;
uid_t uid;
bool granted;
inline bool operator < (const Entry& e) const {
return (uid == e.uid) ? (name < e.name) : (uid < e.uid);
}
};
mutable Mutex mLock;
// we pool all the permission names we see, as many permissions checks
// will have identical names
SortedVector< String16 > mPermissionNamesPool;
// this is our cache per say. it stores pooled names.
SortedVector< Entry > mCache;
// free the whole cache, but keep the permission name pool
void purge();
status_t check(bool* granted,
const String16& permission, uid_t uid) const;
void cache(const String16& permission, uid_t uid, bool granted);
public:
PermissionCache();
static bool checkCallingPermission(const String16& permission);
static bool checkCallingPermission(const String16& permission,
int32_t* outPid, int32_t* outUid);
static bool checkPermission(const String16& permission,
pid_t pid, uid_t uid);
};
// ---------------------------------------------------------------------------
}; // namespace android
#endif /* BINDER_PERMISSION_H */

View file

@ -0,0 +1,132 @@
/*
* Copyright (C) 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_PERSISTABLE_BUNDLE_H
#define ANDROID_PERSISTABLE_BUNDLE_H
#include <map>
#include <set>
#include <vector>
#include <binder/Parcelable.h>
#include <utils/String16.h>
#include <utils/StrongPointer.h>
namespace android {
namespace os {
/*
* C++ implementation of PersistableBundle, a mapping from String values to
* various types that can be saved to persistent and later restored.
*/
class PersistableBundle : public Parcelable {
public:
PersistableBundle() = default;
virtual ~PersistableBundle() = default;
PersistableBundle(const PersistableBundle& bundle) = default;
status_t writeToParcel(Parcel* parcel) const override;
status_t readFromParcel(const Parcel* parcel) override;
bool empty() const;
size_t size() const;
size_t erase(const String16& key);
/*
* Setters for PersistableBundle. Adds a a key-value pair instantiated with
* |key| and |value| into the member map appropriate for the type of |value|.
* If there is already an existing value for |key|, |value| will replace it.
*/
void putBoolean(const String16& key, bool value);
void putInt(const String16& key, int32_t value);
void putLong(const String16& key, int64_t value);
void putDouble(const String16& key, double value);
void putString(const String16& key, const String16& value);
void putBooleanVector(const String16& key, const std::vector<bool>& value);
void putIntVector(const String16& key, const std::vector<int32_t>& value);
void putLongVector(const String16& key, const std::vector<int64_t>& value);
void putDoubleVector(const String16& key, const std::vector<double>& value);
void putStringVector(const String16& key, const std::vector<String16>& value);
void putPersistableBundle(const String16& key, const PersistableBundle& value);
/*
* Getters for PersistableBundle. If |key| exists, these methods write the
* value associated with |key| into |out|, and return true. Otherwise, these
* methods return false.
*/
bool getBoolean(const String16& key, bool* out) const;
bool getInt(const String16& key, int32_t* out) const;
bool getLong(const String16& key, int64_t* out) const;
bool getDouble(const String16& key, double* out) const;
bool getString(const String16& key, String16* out) const;
bool getBooleanVector(const String16& key, std::vector<bool>* out) const;
bool getIntVector(const String16& key, std::vector<int32_t>* out) const;
bool getLongVector(const String16& key, std::vector<int64_t>* out) const;
bool getDoubleVector(const String16& key, std::vector<double>* out) const;
bool getStringVector(const String16& key, std::vector<String16>* out) const;
bool getPersistableBundle(const String16& key, PersistableBundle* out) const;
/* Getters for all keys for each value type */
std::set<String16> getBooleanKeys() const;
std::set<String16> getIntKeys() const;
std::set<String16> getLongKeys() const;
std::set<String16> getDoubleKeys() const;
std::set<String16> getStringKeys() const;
std::set<String16> getBooleanVectorKeys() const;
std::set<String16> getIntVectorKeys() const;
std::set<String16> getLongVectorKeys() const;
std::set<String16> getDoubleVectorKeys() const;
std::set<String16> getStringVectorKeys() const;
std::set<String16> getPersistableBundleKeys() const;
friend bool operator==(const PersistableBundle& lhs, const PersistableBundle& rhs) {
return (lhs.mBoolMap == rhs.mBoolMap && lhs.mIntMap == rhs.mIntMap &&
lhs.mLongMap == rhs.mLongMap && lhs.mDoubleMap == rhs.mDoubleMap &&
lhs.mStringMap == rhs.mStringMap && lhs.mBoolVectorMap == rhs.mBoolVectorMap &&
lhs.mIntVectorMap == rhs.mIntVectorMap &&
lhs.mLongVectorMap == rhs.mLongVectorMap &&
lhs.mDoubleVectorMap == rhs.mDoubleVectorMap &&
lhs.mStringVectorMap == rhs.mStringVectorMap &&
lhs.mPersistableBundleMap == rhs.mPersistableBundleMap);
}
friend bool operator!=(const PersistableBundle& lhs, const PersistableBundle& rhs) {
return !(lhs == rhs);
}
private:
status_t writeToParcelInner(Parcel* parcel) const;
status_t readFromParcelInner(const Parcel* parcel, size_t length);
std::map<String16, bool> mBoolMap;
std::map<String16, int32_t> mIntMap;
std::map<String16, int64_t> mLongMap;
std::map<String16, double> mDoubleMap;
std::map<String16, String16> mStringMap;
std::map<String16, std::vector<bool>> mBoolVectorMap;
std::map<String16, std::vector<int32_t>> mIntVectorMap;
std::map<String16, std::vector<int64_t>> mLongVectorMap;
std::map<String16, std::vector<double>> mDoubleVectorMap;
std::map<String16, std::vector<String16>> mStringVectorMap;
std::map<String16, PersistableBundle> mPersistableBundleMap;
};
} // namespace os
} // namespace android
#endif // ANDROID_PERSISTABLE_BUNDLE_H

View file

@ -0,0 +1,82 @@
/*
* 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);
status_t getProcessStatesScoresImpl(size_t length, /*in*/ int32_t* pids,
/*out*/ int32_t* states, /*out*/ int32_t *scores);
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);
}
/**
* 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. OoM scores will also be written in the "scores" output array.
* Please also note that clients calling this method need to have
* "GET_PROCESS_STATE_AND_OOM_SCORE" permission.
*
* Returns NO_ERROR if this operation was successful, or a negative error code otherwise.
*/
static status_t getProcessStatesScoresFromPids(size_t length, /*in*/ int32_t* pids,
/*out*/ int32_t* states, /*out*/ int32_t *scores) {
return ProcessInfoService::getInstance().getProcessStatesScoresImpl(
length, /*in*/ pids, /*out*/ states, /*out*/ scores);
}
};
// ----------------------------------------------------------------------
}; // namespace android
#endif // ANDROID_PROCESS_INFO_SERVICE_H

View file

@ -0,0 +1,129 @@
/*
* Copyright (C) 2005 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_STATE_H
#define ANDROID_PROCESS_STATE_H
#include <binder/IBinder.h>
#include <utils/KeyedVector.h>
#include <utils/String8.h>
#include <utils/String16.h>
#include <utils/threads.h>
#include <pthread.h>
// ---------------------------------------------------------------------------
namespace android {
class IPCThreadState;
class ProcessState : public virtual RefBase
{
public:
static sp<ProcessState> self();
static sp<ProcessState> selfOrNull();
/* initWithDriver() can be used to configure libbinder to use
* a different binder driver dev node. It must be called *before*
* any call to ProcessState::self(). /dev/binder remains the default.
*/
static sp<ProcessState> initWithDriver(const char *driver);
void setContextObject(const sp<IBinder>& object);
sp<IBinder> getContextObject(const sp<IBinder>& caller);
void setContextObject(const sp<IBinder>& object,
const String16& name);
sp<IBinder> getContextObject(const String16& name,
const sp<IBinder>& caller);
void startThreadPool();
typedef bool (*context_check_func)(const String16& name,
const sp<IBinder>& caller,
void* userData);
bool isContextManager(void) const;
bool becomeContextManager(
context_check_func checkFunc,
void* userData);
sp<IBinder> getStrongProxyForHandle(int32_t handle);
wp<IBinder> getWeakProxyForHandle(int32_t handle);
void expungeHandle(int32_t handle, IBinder* binder);
void spawnPooledThread(bool isMain);
status_t setThreadPoolMaxThreadCount(size_t maxThreads);
void giveThreadPoolName();
String8 getDriverName();
ssize_t getKernelReferences(size_t count, uintptr_t* buf);
private:
friend class IPCThreadState;
ProcessState(const char* driver);
~ProcessState();
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);
String8 mDriverName;
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;
// Time when thread pool was emptied
int64_t mStarvationStartTimeMs;
mutable Mutex mLock; // protects everything below.
Vector<handle_entry>mHandleToObject;
bool mManagesContexts;
context_check_func mBinderContextCheckFunc;
void* mBinderContextUserData;
KeyedVector<String16, sp<IBinder> >
mContexts;
String8 mRootDir;
bool mThreadPoolStarted;
volatile int32_t mThreadPoolSeq;
};
}; // namespace android
// ---------------------------------------------------------------------------
#endif // ANDROID_PROCESS_STATE_H

View file

@ -0,0 +1,705 @@
/*
* Copyright 2016 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.
*/
#pragma once
#include <binder/IInterface.h>
#include <binder/Parcel.h>
#include <cutils/compiler.h>
// Set to 1 to enable CallStacks when logging errors
#define SI_DUMP_CALLSTACKS 0
#if SI_DUMP_CALLSTACKS
#include <utils/CallStack.h>
#endif
#include <utils/NativeHandle.h>
#include <functional>
#include <type_traits>
namespace android {
namespace SafeInterface {
// ParcelHandler is responsible for writing/reading various types to/from a Parcel in a generic way
class ParcelHandler {
public:
explicit ParcelHandler(const char* logTag) : mLogTag(logTag) {}
// Specializations for types with dedicated handling in Parcel
status_t read(const Parcel& parcel, bool* b) const {
return callParcel("readBool", [&]() { return parcel.readBool(b); });
}
status_t write(Parcel* parcel, bool b) const {
return callParcel("writeBool", [&]() { return parcel->writeBool(b); });
}
template <typename E>
typename std::enable_if<std::is_enum<E>::value, status_t>::type read(const Parcel& parcel,
E* e) const {
typename std::underlying_type<E>::type u{};
status_t result = read(parcel, &u);
*e = static_cast<E>(u);
return result;
}
template <typename E>
typename std::enable_if<std::is_enum<E>::value, status_t>::type write(Parcel* parcel,
E e) const {
return write(parcel, static_cast<typename std::underlying_type<E>::type>(e));
}
template <typename T>
typename std::enable_if<std::is_base_of<Flattenable<T>, T>::value, status_t>::type read(
const Parcel& parcel, T* t) const {
return callParcel("read(Flattenable)", [&]() { return parcel.read(*t); });
}
template <typename T>
typename std::enable_if<std::is_base_of<Flattenable<T>, T>::value, status_t>::type write(
Parcel* parcel, const T& t) const {
return callParcel("write(Flattenable)", [&]() { return parcel->write(t); });
}
template <typename T>
typename std::enable_if<std::is_base_of<Flattenable<T>, T>::value, status_t>::type read(
const Parcel& parcel, sp<T>* t) const {
*t = new T{};
return callParcel("read(sp<Flattenable>)", [&]() { return parcel.read(*(t->get())); });
}
template <typename T>
typename std::enable_if<std::is_base_of<Flattenable<T>, T>::value, status_t>::type write(
Parcel* parcel, const sp<T>& t) const {
return callParcel("write(sp<Flattenable>)", [&]() { return parcel->write(*(t.get())); });
}
template <typename T>
typename std::enable_if<std::is_base_of<LightFlattenable<T>, T>::value, status_t>::type read(
const Parcel& parcel, T* t) const {
return callParcel("read(LightFlattenable)", [&]() { return parcel.read(*t); });
}
template <typename T>
typename std::enable_if<std::is_base_of<LightFlattenable<T>, T>::value, status_t>::type write(
Parcel* parcel, const T& t) const {
return callParcel("write(LightFlattenable)", [&]() { return parcel->write(t); });
}
template <typename NH>
typename std::enable_if<std::is_same<NH, sp<NativeHandle>>::value, status_t>::type read(
const Parcel& parcel, NH* nh) {
*nh = NativeHandle::create(parcel.readNativeHandle(), true);
return NO_ERROR;
}
template <typename NH>
typename std::enable_if<std::is_same<NH, sp<NativeHandle>>::value, status_t>::type write(
Parcel* parcel, const NH& nh) {
return callParcel("write(sp<NativeHandle>)",
[&]() { return parcel->writeNativeHandle(nh->handle()); });
}
template <typename T>
typename std::enable_if<std::is_base_of<Parcelable, T>::value, status_t>::type read(
const Parcel& parcel, T* t) const {
return callParcel("readParcelable", [&]() { return parcel.readParcelable(t); });
}
template <typename T>
typename std::enable_if<std::is_base_of<Parcelable, T>::value, status_t>::type write(
Parcel* parcel, const T& t) const {
return callParcel("writeParcelable", [&]() { return parcel->writeParcelable(t); });
}
status_t read(const Parcel& parcel, String8* str) const {
return callParcel("readString8", [&]() { return parcel.readString8(str); });
}
status_t write(Parcel* parcel, const String8& str) const {
return callParcel("writeString8", [&]() { return parcel->writeString8(str); });
}
template <typename T>
typename std::enable_if<std::is_same<IBinder, T>::value, status_t>::type read(
const Parcel& parcel, sp<T>* pointer) const {
return callParcel("readNullableStrongBinder",
[&]() { return parcel.readNullableStrongBinder(pointer); });
}
template <typename T>
typename std::enable_if<std::is_same<IBinder, T>::value, status_t>::type write(
Parcel* parcel, const sp<T>& pointer) const {
return callParcel("writeStrongBinder",
[&]() { return parcel->writeStrongBinder(pointer); });
}
template <typename T>
typename std::enable_if<std::is_base_of<IInterface, T>::value, status_t>::type read(
const Parcel& parcel, sp<T>* pointer) const {
return callParcel("readNullableStrongBinder[IInterface]",
[&]() { return parcel.readNullableStrongBinder(pointer); });
}
template <typename T>
typename std::enable_if<std::is_base_of<IInterface, T>::value, status_t>::type write(
Parcel* parcel, const sp<T>& interface) const {
return write(parcel, IInterface::asBinder(interface));
}
template <typename T>
typename std::enable_if<std::is_base_of<Parcelable, T>::value, status_t>::type read(
const Parcel& parcel, std::vector<T>* v) const {
return callParcel("readParcelableVector", [&]() { return parcel.readParcelableVector(v); });
}
template <typename T>
typename std::enable_if<std::is_base_of<Parcelable, T>::value, status_t>::type write(
Parcel* parcel, const std::vector<T>& v) const {
return callParcel("writeParcelableVector",
[&]() { return parcel->writeParcelableVector(v); });
}
// Templates to handle integral types. We use a struct template to require that the called
// function exactly matches the signedness and size of the argument (e.g., the argument isn't
// silently widened).
template <bool isSigned, size_t size, typename I>
struct HandleInt;
template <typename I>
struct HandleInt<true, 4, I> {
static status_t read(const ParcelHandler& handler, const Parcel& parcel, I* i) {
return handler.callParcel("readInt32", [&]() { return parcel.readInt32(i); });
}
static status_t write(const ParcelHandler& handler, Parcel* parcel, I i) {
return handler.callParcel("writeInt32", [&]() { return parcel->writeInt32(i); });
}
};
template <typename I>
struct HandleInt<false, 4, I> {
static status_t read(const ParcelHandler& handler, const Parcel& parcel, I* i) {
return handler.callParcel("readUint32", [&]() { return parcel.readUint32(i); });
}
static status_t write(const ParcelHandler& handler, Parcel* parcel, I i) {
return handler.callParcel("writeUint32", [&]() { return parcel->writeUint32(i); });
}
};
template <typename I>
struct HandleInt<true, 8, I> {
static status_t read(const ParcelHandler& handler, const Parcel& parcel, I* i) {
return handler.callParcel("readInt64", [&]() { return parcel.readInt64(i); });
}
static status_t write(const ParcelHandler& handler, Parcel* parcel, I i) {
return handler.callParcel("writeInt64", [&]() { return parcel->writeInt64(i); });
}
};
template <typename I>
struct HandleInt<false, 8, I> {
static status_t read(const ParcelHandler& handler, const Parcel& parcel, I* i) {
return handler.callParcel("readUint64", [&]() { return parcel.readUint64(i); });
}
static status_t write(const ParcelHandler& handler, Parcel* parcel, I i) {
return handler.callParcel("writeUint64", [&]() { return parcel->writeUint64(i); });
}
};
template <typename I>
typename std::enable_if<std::is_integral<I>::value, status_t>::type read(const Parcel& parcel,
I* i) const {
return HandleInt<std::is_signed<I>::value, sizeof(I), I>::read(*this, parcel, i);
}
template <typename I>
typename std::enable_if<std::is_integral<I>::value, status_t>::type write(Parcel* parcel,
I i) const {
return HandleInt<std::is_signed<I>::value, sizeof(I), I>::write(*this, parcel, i);
}
private:
const char* const mLogTag;
// Helper to encapsulate error handling while calling the various Parcel methods
template <typename Function>
status_t callParcel(const char* name, Function f) const {
status_t error = f();
if (CC_UNLIKELY(error != NO_ERROR)) {
ALOG(LOG_ERROR, mLogTag, "Failed to %s, (%d: %s)", name, error, strerror(-error));
#if SI_DUMP_CALLSTACKS
CallStack callStack(mLogTag);
#endif
}
return error;
}
};
// Utility struct template which allows us to retrieve the types of the parameters of a member
// function pointer
template <typename T>
struct ParamExtractor;
template <typename Class, typename Return, typename... Params>
struct ParamExtractor<Return (Class::*)(Params...)> {
using ParamTuple = std::tuple<Params...>;
};
template <typename Class, typename Return, typename... Params>
struct ParamExtractor<Return (Class::*)(Params...) const> {
using ParamTuple = std::tuple<Params...>;
};
} // namespace SafeInterface
template <typename Interface>
class SafeBpInterface : public BpInterface<Interface> {
protected:
SafeBpInterface(const sp<IBinder>& impl, const char* logTag)
: BpInterface<Interface>(impl), mLogTag(logTag) {}
~SafeBpInterface() override = default;
// callRemote is used to invoke a synchronous procedure call over Binder
template <typename Method, typename TagType, typename... Args>
status_t callRemote(TagType tag, Args&&... args) const {
static_assert(sizeof(TagType) <= sizeof(uint32_t), "Tag must fit inside uint32_t");
// Verify that the arguments are compatible with the parameters
using ParamTuple = typename SafeInterface::ParamExtractor<Method>::ParamTuple;
static_assert(ArgsMatchParams<std::tuple<Args...>, ParamTuple>::value,
"Invalid argument type");
// Write the input arguments to the data Parcel
Parcel data;
data.writeInterfaceToken(this->getInterfaceDescriptor());
status_t error = writeInputs(&data, std::forward<Args>(args)...);
if (CC_UNLIKELY(error != NO_ERROR)) {
// A message will have been logged by writeInputs
return error;
}
// Send the data Parcel to the remote and retrieve the reply parcel
Parcel reply;
error = this->remote()->transact(static_cast<uint32_t>(tag), data, &reply);
if (CC_UNLIKELY(error != NO_ERROR)) {
ALOG(LOG_ERROR, mLogTag, "Failed to transact (%d)", error);
#if SI_DUMP_CALLSTACKS
CallStack callStack(mLogTag);
#endif
return error;
}
// Read the outputs from the reply Parcel into the output arguments
error = readOutputs(reply, std::forward<Args>(args)...);
if (CC_UNLIKELY(error != NO_ERROR)) {
// A message will have been logged by readOutputs
return error;
}
// Retrieve the result code from the reply Parcel
status_t result = NO_ERROR;
error = reply.readInt32(&result);
if (CC_UNLIKELY(error != NO_ERROR)) {
ALOG(LOG_ERROR, mLogTag, "Failed to obtain result");
#if SI_DUMP_CALLSTACKS
CallStack callStack(mLogTag);
#endif
return error;
}
return result;
}
// callRemoteAsync is used to invoke an asynchronous procedure call over Binder
template <typename Method, typename TagType, typename... Args>
void callRemoteAsync(TagType tag, Args&&... args) const {
static_assert(sizeof(TagType) <= sizeof(uint32_t), "Tag must fit inside uint32_t");
// Verify that the arguments are compatible with the parameters
using ParamTuple = typename SafeInterface::ParamExtractor<Method>::ParamTuple;
static_assert(ArgsMatchParams<std::tuple<Args...>, ParamTuple>::value,
"Invalid argument type");
// Write the input arguments to the data Parcel
Parcel data;
data.writeInterfaceToken(this->getInterfaceDescriptor());
status_t error = writeInputs(&data, std::forward<Args>(args)...);
if (CC_UNLIKELY(error != NO_ERROR)) {
// A message will have been logged by writeInputs
return;
}
// There will be no data in the reply Parcel since the call is one-way
Parcel reply;
error = this->remote()->transact(static_cast<uint32_t>(tag), data, &reply,
IBinder::FLAG_ONEWAY);
if (CC_UNLIKELY(error != NO_ERROR)) {
ALOG(LOG_ERROR, mLogTag, "Failed to transact (%d)", error);
#if SI_DUMP_CALLSTACKS
CallStack callStack(mLogTag);
#endif
}
}
private:
const char* const mLogTag;
// This struct provides information on whether the decayed types of the elements at Index in the
// tuple types T and U (that is, the types after stripping cv-qualifiers, removing references,
// and a few other less common operations) are the same
template <size_t Index, typename T, typename U>
struct DecayedElementsMatch {
private:
using FirstT = typename std::tuple_element<Index, T>::type;
using DecayedT = typename std::decay<FirstT>::type;
using FirstU = typename std::tuple_element<Index, U>::type;
using DecayedU = typename std::decay<FirstU>::type;
public:
static constexpr bool value = std::is_same<DecayedT, DecayedU>::value;
};
// When comparing whether the argument types match the parameter types, we first decay them (see
// DecayedElementsMatch) to avoid falsely flagging, say, T&& against T even though they are
// equivalent enough for our purposes
template <typename T, typename U>
struct ArgsMatchParams {};
template <typename... Args, typename... Params>
struct ArgsMatchParams<std::tuple<Args...>, std::tuple<Params...>> {
static_assert(sizeof...(Args) <= sizeof...(Params), "Too many arguments");
static_assert(sizeof...(Args) >= sizeof...(Params), "Not enough arguments");
private:
template <size_t Index>
static constexpr typename std::enable_if<(Index < sizeof...(Args)), bool>::type
elementsMatch() {
if (!DecayedElementsMatch<Index, std::tuple<Args...>, std::tuple<Params...>>::value) {
return false;
}
return elementsMatch<Index + 1>();
}
template <size_t Index>
static constexpr typename std::enable_if<(Index >= sizeof...(Args)), bool>::type
elementsMatch() {
return true;
}
public:
static constexpr bool value = elementsMatch<0>();
};
// Since we assume that pointer arguments are outputs, we can use this template struct to
// determine whether or not a given argument is fundamentally a pointer type and thus an output
template <typename T>
struct IsPointerIfDecayed {
private:
using Decayed = typename std::decay<T>::type;
public:
static constexpr bool value = std::is_pointer<Decayed>::value;
};
template <typename T>
typename std::enable_if<!IsPointerIfDecayed<T>::value, status_t>::type writeIfInput(
Parcel* data, T&& t) const {
return SafeInterface::ParcelHandler{mLogTag}.write(data, std::forward<T>(t));
}
template <typename T>
typename std::enable_if<IsPointerIfDecayed<T>::value, status_t>::type writeIfInput(
Parcel* /*data*/, T&& /*t*/) const {
return NO_ERROR;
}
// This method iterates through all of the arguments, writing them to the data Parcel if they
// are an input (i.e., if they are not a pointer type)
template <typename T, typename... Remaining>
status_t writeInputs(Parcel* data, T&& t, Remaining&&... remaining) const {
status_t error = writeIfInput(data, std::forward<T>(t));
if (CC_UNLIKELY(error != NO_ERROR)) {
// A message will have been logged by writeIfInput
return error;
}
return writeInputs(data, std::forward<Remaining>(remaining)...);
}
static status_t writeInputs(Parcel* /*data*/) { return NO_ERROR; }
template <typename T>
typename std::enable_if<IsPointerIfDecayed<T>::value, status_t>::type readIfOutput(
const Parcel& reply, T&& t) const {
return SafeInterface::ParcelHandler{mLogTag}.read(reply, std::forward<T>(t));
}
template <typename T>
static typename std::enable_if<!IsPointerIfDecayed<T>::value, status_t>::type readIfOutput(
const Parcel& /*reply*/, T&& /*t*/) {
return NO_ERROR;
}
// Similar to writeInputs except that it reads output arguments from the reply Parcel
template <typename T, typename... Remaining>
status_t readOutputs(const Parcel& reply, T&& t, Remaining&&... remaining) const {
status_t error = readIfOutput(reply, std::forward<T>(t));
if (CC_UNLIKELY(error != NO_ERROR)) {
// A message will have been logged by readIfOutput
return error;
}
return readOutputs(reply, std::forward<Remaining>(remaining)...);
}
static status_t readOutputs(const Parcel& /*data*/) { return NO_ERROR; }
};
template <typename Interface>
class SafeBnInterface : public BnInterface<Interface> {
public:
explicit SafeBnInterface(const char* logTag) : mLogTag(logTag) {}
protected:
template <typename Method>
status_t callLocal(const Parcel& data, Parcel* reply, Method method) {
CHECK_INTERFACE(this, data, reply);
// Since we need to both pass inputs into the call as well as retrieve outputs, we create a
// "raw" tuple, where the inputs are interleaved with actual, non-pointer versions of the
// outputs. When we ultimately call into the method, we will pass the addresses of the
// output arguments instead of their tuple members directly, but the storage will live in
// the tuple.
using ParamTuple = typename SafeInterface::ParamExtractor<Method>::ParamTuple;
typename RawConverter<std::tuple<>, ParamTuple>::type rawArgs{};
// Read the inputs from the data Parcel into the argument tuple
status_t error = InputReader<ParamTuple>{mLogTag}.readInputs(data, &rawArgs);
if (CC_UNLIKELY(error != NO_ERROR)) {
// A message will have been logged by read
return error;
}
// Call the local method
status_t result = MethodCaller<ParamTuple>::call(this, method, &rawArgs);
// Extract the outputs from the argument tuple and write them into the reply Parcel
error = OutputWriter<ParamTuple>{mLogTag}.writeOutputs(reply, &rawArgs);
if (CC_UNLIKELY(error != NO_ERROR)) {
// A message will have been logged by write
return error;
}
// Return the result code in the reply Parcel
error = reply->writeInt32(result);
if (CC_UNLIKELY(error != NO_ERROR)) {
ALOG(LOG_ERROR, mLogTag, "Failed to write result");
#if SI_DUMP_CALLSTACKS
CallStack callStack(mLogTag);
#endif
return error;
}
return NO_ERROR;
}
template <typename Method>
status_t callLocalAsync(const Parcel& data, Parcel* /*reply*/, Method method) {
// reply is not actually used by CHECK_INTERFACE
CHECK_INTERFACE(this, data, reply);
// Since we need to both pass inputs into the call as well as retrieve outputs, we create a
// "raw" tuple, where the inputs are interleaved with actual, non-pointer versions of the
// outputs. When we ultimately call into the method, we will pass the addresses of the
// output arguments instead of their tuple members directly, but the storage will live in
// the tuple.
using ParamTuple = typename SafeInterface::ParamExtractor<Method>::ParamTuple;
typename RawConverter<std::tuple<>, ParamTuple>::type rawArgs{};
// Read the inputs from the data Parcel into the argument tuple
status_t error = InputReader<ParamTuple>{mLogTag}.readInputs(data, &rawArgs);
if (CC_UNLIKELY(error != NO_ERROR)) {
// A message will have been logged by read
return error;
}
// Call the local method
MethodCaller<ParamTuple>::callVoid(this, method, &rawArgs);
// After calling, there is nothing more to do since asynchronous calls do not return a value
// to the caller
return NO_ERROR;
}
private:
const char* const mLogTag;
// RemoveFirst strips the first element from a tuple.
// For example, given T = std::tuple<A, B, C>, RemoveFirst<T>::type = std::tuple<B, C>
template <typename T, typename... Args>
struct RemoveFirst;
template <typename T, typename... Args>
struct RemoveFirst<std::tuple<T, Args...>> {
using type = std::tuple<Args...>;
};
// RawConverter strips a tuple down to its fundamental types, discarding both pointers and
// references. This allows us to allocate storage for both input (non-pointer) arguments and
// output (pointer) arguments in one tuple.
// For example, given T = std::tuple<const A&, B*>, RawConverter<T>::type = std::tuple<A, B>
template <typename Unconverted, typename... Converted>
struct RawConverter;
template <typename Unconverted, typename... Converted>
struct RawConverter<std::tuple<Converted...>, Unconverted> {
private:
using ElementType = typename std::tuple_element<0, Unconverted>::type;
using Decayed = typename std::decay<ElementType>::type;
using WithoutPointer = typename std::remove_pointer<Decayed>::type;
public:
using type = typename RawConverter<std::tuple<Converted..., WithoutPointer>,
typename RemoveFirst<Unconverted>::type>::type;
};
template <typename... Converted>
struct RawConverter<std::tuple<Converted...>, std::tuple<>> {
using type = std::tuple<Converted...>;
};
// This provides a simple way to determine whether the indexed element of Args... is a pointer
template <size_t I, typename... Args>
struct ElementIsPointer {
private:
using ElementType = typename std::tuple_element<I, std::tuple<Args...>>::type;
public:
static constexpr bool value = std::is_pointer<ElementType>::value;
};
// This class iterates over the parameter types, and if a given parameter is an input
// (i.e., is not a pointer), reads the corresponding argument tuple element from the data Parcel
template <typename... Params>
class InputReader;
template <typename... Params>
class InputReader<std::tuple<Params...>> {
public:
explicit InputReader(const char* logTag) : mLogTag(logTag) {}
// Note that in this case (as opposed to in SafeBpInterface), we iterate using an explicit
// index (starting with 0 here) instead of using recursion and stripping the first element.
// This is because in SafeBpInterface we aren't actually operating on a real tuple, but are
// instead just using a tuple as a convenient container for variadic types, whereas here we
// can't modify the argument tuple without causing unnecessary copies or moves of the data
// contained therein.
template <typename RawTuple>
status_t readInputs(const Parcel& data, RawTuple* args) {
return dispatchArg<0>(data, args);
}
private:
const char* const mLogTag;
template <std::size_t I, typename RawTuple>
typename std::enable_if<!ElementIsPointer<I, Params...>::value, status_t>::type readIfInput(
const Parcel& data, RawTuple* args) {
return SafeInterface::ParcelHandler{mLogTag}.read(data, &std::get<I>(*args));
}
template <std::size_t I, typename RawTuple>
typename std::enable_if<ElementIsPointer<I, Params...>::value, status_t>::type readIfInput(
const Parcel& /*data*/, RawTuple* /*args*/) {
return NO_ERROR;
}
// Recursively iterate through the arguments
template <std::size_t I, typename RawTuple>
typename std::enable_if<(I < sizeof...(Params)), status_t>::type dispatchArg(
const Parcel& data, RawTuple* args) {
status_t error = readIfInput<I>(data, args);
if (CC_UNLIKELY(error != NO_ERROR)) {
// A message will have been logged in read
return error;
}
return dispatchArg<I + 1>(data, args);
}
template <std::size_t I, typename RawTuple>
typename std::enable_if<(I >= sizeof...(Params)), status_t>::type dispatchArg(
const Parcel& /*data*/, RawTuple* /*args*/) {
return NO_ERROR;
}
};
// getForCall uses the types of the parameters to determine whether a given element of the
// argument tuple is an input, which should be passed directly into the call, or an output, for
// which its address should be passed into the call
template <size_t I, typename RawTuple, typename... Params>
static typename std::enable_if<
ElementIsPointer<I, Params...>::value,
typename std::tuple_element<I, std::tuple<Params...>>::type>::type
getForCall(RawTuple* args) {
return &std::get<I>(*args);
}
template <size_t I, typename RawTuple, typename... Params>
static typename std::enable_if<
!ElementIsPointer<I, Params...>::value,
typename std::tuple_element<I, std::tuple<Params...>>::type>::type&
getForCall(RawTuple* args) {
return std::get<I>(*args);
}
// This template class uses std::index_sequence and parameter pack expansion to call the given
// method using the elements of the argument tuple (after those arguments are passed through
// getForCall to get addresses instead of values for output arguments)
template <typename... Params>
struct MethodCaller;
template <typename... Params>
struct MethodCaller<std::tuple<Params...>> {
public:
// The calls through these to the helper methods are necessary to generate the
// std::index_sequences used to unpack the argument tuple into the method call
template <typename Class, typename MemberFunction, typename RawTuple>
static status_t call(Class* instance, MemberFunction function, RawTuple* args) {
return callHelper(instance, function, args, std::index_sequence_for<Params...>{});
}
template <typename Class, typename MemberFunction, typename RawTuple>
static void callVoid(Class* instance, MemberFunction function, RawTuple* args) {
callVoidHelper(instance, function, args, std::index_sequence_for<Params...>{});
}
private:
template <typename Class, typename MemberFunction, typename RawTuple, std::size_t... I>
static status_t callHelper(Class* instance, MemberFunction function, RawTuple* args,
std::index_sequence<I...> /*unused*/) {
return (instance->*function)(getForCall<I, RawTuple, Params...>(args)...);
}
template <typename Class, typename MemberFunction, typename RawTuple, std::size_t... I>
static void callVoidHelper(Class* instance, MemberFunction function, RawTuple* args,
std::index_sequence<I...> /*unused*/) {
(instance->*function)(getForCall<I, RawTuple, Params...>(args)...);
}
};
// This class iterates over the parameter types, and if a given parameter is an output
// (i.e., is a pointer), writes the corresponding argument tuple element into the reply Parcel
template <typename... Params>
struct OutputWriter;
template <typename... Params>
struct OutputWriter<std::tuple<Params...>> {
public:
explicit OutputWriter(const char* logTag) : mLogTag(logTag) {}
// See the note on InputReader::readInputs for why this differs from the arguably simpler
// RemoveFirst approach in SafeBpInterface
template <typename RawTuple>
status_t writeOutputs(Parcel* reply, RawTuple* args) {
return dispatchArg<0>(reply, args);
}
private:
const char* const mLogTag;
template <std::size_t I, typename RawTuple>
typename std::enable_if<ElementIsPointer<I, Params...>::value, status_t>::type
writeIfOutput(Parcel* reply, RawTuple* args) {
return SafeInterface::ParcelHandler{mLogTag}.write(reply, std::get<I>(*args));
}
template <std::size_t I, typename RawTuple>
typename std::enable_if<!ElementIsPointer<I, Params...>::value, status_t>::type
writeIfOutput(Parcel* /*reply*/, RawTuple* /*args*/) {
return NO_ERROR;
}
// Recursively iterate through the arguments
template <std::size_t I, typename RawTuple>
typename std::enable_if<(I < sizeof...(Params)), status_t>::type dispatchArg(
Parcel* reply, RawTuple* args) {
status_t error = writeIfOutput<I>(reply, args);
if (CC_UNLIKELY(error != NO_ERROR)) {
// A message will have been logged in read
return error;
}
return dispatchArg<I + 1>(reply, args);
}
template <std::size_t I, typename RawTuple>
typename std::enable_if<(I >= sizeof...(Params)), status_t>::type dispatchArg(
Parcel* /*reply*/, RawTuple* /*args*/) {
return NO_ERROR;
}
};
};
} // namespace android

View file

@ -0,0 +1,159 @@
/*
* Copyright (C) 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_BINDER_STATUS_H
#define ANDROID_BINDER_STATUS_H
#include <cstdint>
#include <sstream>
#include <binder/Parcel.h>
#include <utils/String8.h>
namespace android {
namespace binder {
// An object similar in function to a status_t except that it understands
// how exceptions are encoded in the prefix of a Parcel. Used like:
//
// Parcel data;
// Parcel reply;
// status_t status;
// binder::Status remote_exception;
// if ((status = data.writeInterfaceToken(interface_descriptor)) != OK ||
// (status = data.writeInt32(function_input)) != OK) {
// // We failed to write into the memory of our local parcel?
// }
// if ((status = remote()->transact(transaction, data, &reply)) != OK) {
// // Something has gone wrong in the binder driver or libbinder.
// }
// if ((status = remote_exception.readFromParcel(reply)) != OK) {
// // The remote didn't correctly write the exception header to the
// // reply.
// }
// if (!remote_exception.isOk()) {
// // The transaction went through correctly, but the remote reported an
// // exception during handling.
// }
//
class Status final {
public:
// Keep the exception codes in sync with android/os/Parcel.java.
enum Exception {
EX_NONE = 0,
EX_SECURITY = -1,
EX_BAD_PARCELABLE = -2,
EX_ILLEGAL_ARGUMENT = -3,
EX_NULL_POINTER = -4,
EX_ILLEGAL_STATE = -5,
EX_NETWORK_MAIN_THREAD = -6,
EX_UNSUPPORTED_OPERATION = -7,
EX_SERVICE_SPECIFIC = -8,
EX_PARCELABLE = -9,
// This is special and Java specific; see Parcel.java.
EX_HAS_REPLY_HEADER = -128,
// This is special, and indicates to C++ binder proxies that the
// transaction has failed at a low level.
EX_TRANSACTION_FAILED = -129,
};
// A more readable alias for the default constructor.
static Status ok();
// Authors should explicitly pick whether their integer is:
// - an exception code (EX_* above)
// - service specific error code
// - status_t
//
// Prefer a generic exception code when possible, then a service specific
// code, and finally a status_t for low level failures or legacy support.
// Exception codes and service specific errors map to nicer exceptions for
// Java clients.
static Status fromExceptionCode(int32_t exceptionCode);
static Status fromExceptionCode(int32_t exceptionCode,
const String8& message);
static Status fromExceptionCode(int32_t exceptionCode,
const char* message);
static Status fromServiceSpecificError(int32_t serviceSpecificErrorCode);
static Status fromServiceSpecificError(int32_t serviceSpecificErrorCode,
const String8& message);
static Status fromServiceSpecificError(int32_t serviceSpecificErrorCode,
const char* message);
static Status fromStatusT(status_t status);
Status() = default;
~Status() = default;
// Status objects are copyable and contain just simple data.
Status(const Status& status) = default;
Status(Status&& status) = default;
Status& operator=(const Status& status) = default;
// Bear in mind that if the client or service is a Java endpoint, this
// is not the logic which will provide/interpret the data here.
status_t readFromParcel(const Parcel& parcel);
status_t writeToParcel(Parcel* parcel) const;
// Set one of the pre-defined exception types defined above.
void setException(int32_t ex, const String8& message);
// Set a service specific exception with error code.
void setServiceSpecificError(int32_t errorCode, const String8& message);
// Setting a |status| != OK causes generated code to return |status|
// from Binder transactions, rather than writing an exception into the
// reply Parcel. This is the least preferable way of reporting errors.
void setFromStatusT(status_t status);
// Get information about an exception.
int32_t exceptionCode() const { return mException; }
const String8& exceptionMessage() const { return mMessage; }
status_t transactionError() const {
return mException == EX_TRANSACTION_FAILED ? mErrorCode : OK;
}
int32_t serviceSpecificErrorCode() const {
return mException == EX_SERVICE_SPECIFIC ? mErrorCode : 0;
}
bool isOk() const { return mException == EX_NONE; }
// For logging.
String8 toString8() const;
private:
Status(int32_t exceptionCode, int32_t errorCode);
Status(int32_t exceptionCode, int32_t errorCode, const String8& message);
// If |mException| == EX_TRANSACTION_FAILED, generated code will return
// |mErrorCode| as the result of the transaction rather than write an
// exception to the reply parcel.
//
// Otherwise, we always write |mException| to the parcel.
// If |mException| != EX_NONE, we write |mMessage| as well.
// If |mException| == EX_SERVICE_SPECIFIC we write |mErrorCode| as well.
int32_t mException = EX_NONE;
int32_t mErrorCode = 0;
String8 mMessage;
}; // class Status
// For gtest output logging
std::stringstream& operator<< (std::stringstream& stream, const Status& s);
} // namespace binder
} // namespace android
#endif // ANDROID_BINDER_STATUS_H

View file

@ -0,0 +1,204 @@
/*
* Copyright (C) 2006 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_TEXTOUTPUT_H
#define ANDROID_TEXTOUTPUT_H
#include <utils/Errors.h>
#include <utils/String8.h>
#include <stdint.h>
#include <string.h>
#include <sstream>
// ---------------------------------------------------------------------------
namespace android {
class TextOutput
{
public:
TextOutput();
virtual ~TextOutput();
virtual status_t print(const char* txt, size_t len) = 0;
virtual void moveIndent(int delta) = 0;
class Bundle {
public:
inline Bundle(TextOutput& to) : mTO(to) { to.pushBundle(); }
inline ~Bundle() { mTO.popBundle(); }
private:
TextOutput& mTO;
};
virtual void pushBundle() = 0;
virtual void popBundle() = 0;
};
// ---------------------------------------------------------------------------
// Text output stream for printing to the log (via utils/Log.h).
extern TextOutput& alog;
// Text output stream for printing to stdout.
extern TextOutput& aout;
// Text output stream for printing to stderr.
extern TextOutput& aerr;
typedef TextOutput& (*TextOutputManipFunc)(TextOutput&);
TextOutput& endl(TextOutput& to);
TextOutput& indent(TextOutput& to);
TextOutput& dedent(TextOutput& to);
template<typename T>
TextOutput& operator<<(TextOutput& to, const T& val)
{
std::stringstream strbuf;
strbuf << val;
std::string str = strbuf.str();
to.print(str.c_str(), str.size());
return to;
}
TextOutput& operator<<(TextOutput& to, TextOutputManipFunc func);
class TypeCode
{
public:
inline TypeCode(uint32_t code);
inline ~TypeCode();
inline uint32_t typeCode() const;
private:
uint32_t mCode;
};
TextOutput& operator<<(TextOutput& to, const TypeCode& val);
class HexDump
{
public:
HexDump(const void *buf, size_t size, size_t bytesPerLine=16);
inline ~HexDump();
inline HexDump& setBytesPerLine(size_t bytesPerLine);
inline HexDump& setSingleLineCutoff(int32_t bytes);
inline HexDump& setAlignment(size_t alignment);
inline HexDump& setCArrayStyle(bool enabled);
inline const void* buffer() const;
inline size_t size() const;
inline size_t bytesPerLine() const;
inline int32_t singleLineCutoff() const;
inline size_t alignment() const;
inline bool carrayStyle() const;
private:
const void* mBuffer;
size_t mSize;
size_t mBytesPerLine;
int32_t mSingleLineCutoff;
size_t mAlignment;
bool mCArrayStyle;
};
TextOutput& operator<<(TextOutput& to, const HexDump& val);
inline TextOutput& operator<<(TextOutput& to,
decltype(std::endl<char,
std::char_traits<char>>)
/*val*/) {
endl(to);
return to;
}
inline TextOutput& operator<<(TextOutput& to, const char &c)
{
to.print(&c, 1);
return to;
}
inline TextOutput& operator<<(TextOutput& to, const bool &val)
{
if (val) to.print("true", 4);
else to.print("false", 5);
return to;
}
inline TextOutput& operator<<(TextOutput& to, const String16& val)
{
to << String8(val).string();
return to;
}
// ---------------------------------------------------------------------------
// No user servicable parts below.
inline TextOutput& endl(TextOutput& to)
{
to.print("\n", 1);
return to;
}
inline TextOutput& indent(TextOutput& to)
{
to.moveIndent(1);
return to;
}
inline TextOutput& dedent(TextOutput& to)
{
to.moveIndent(-1);
return to;
}
inline TextOutput& operator<<(TextOutput& to, TextOutputManipFunc func)
{
return (*func)(to);
}
inline TypeCode::TypeCode(uint32_t code) : mCode(code) { }
inline TypeCode::~TypeCode() { }
inline uint32_t TypeCode::typeCode() const { return mCode; }
inline HexDump::~HexDump() { }
inline HexDump& HexDump::setBytesPerLine(size_t bytesPerLine) {
mBytesPerLine = bytesPerLine; return *this;
}
inline HexDump& HexDump::setSingleLineCutoff(int32_t bytes) {
mSingleLineCutoff = bytes; return *this;
}
inline HexDump& HexDump::setAlignment(size_t alignment) {
mAlignment = alignment; return *this;
}
inline HexDump& HexDump::setCArrayStyle(bool enabled) {
mCArrayStyle = enabled; return *this;
}
inline const void* HexDump::buffer() const { return mBuffer; }
inline size_t HexDump::size() const { return mSize; }
inline size_t HexDump::bytesPerLine() const { return mBytesPerLine; }
inline int32_t HexDump::singleLineCutoff() const { return mSingleLineCutoff; }
inline size_t HexDump::alignment() const { return mAlignment; }
inline bool HexDump::carrayStyle() const { return mCArrayStyle; }
// ---------------------------------------------------------------------------
}; // namespace android
#endif // ANDROID_TEXTOUTPUT_H

View file

@ -0,0 +1,186 @@
/*
* Copyright (C) 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_VALUE_H
#define ANDROID_VALUE_H
#include <stdint.h>
#include <map>
#include <set>
#include <vector>
#include <string>
#include <binder/Parcelable.h>
#include <binder/PersistableBundle.h>
#include <binder/Map.h>
#include <utils/String8.h>
#include <utils/String16.h>
#include <utils/StrongPointer.h>
namespace android {
class Parcel;
namespace binder {
/**
* A limited C++ generic type. The purpose of this class is to allow C++
* programs to make use of (or implement) Binder interfaces which make use
* the Java "Object" generic type (either via the use of the Map type or
* some other mechanism).
*
* This class only supports a limited set of types, but additional types
* may be easily added to this class in the future as needed---without
* breaking binary compatability.
*
* This class was written in such a way as to help avoid type errors by
* giving each type their own explicity-named accessor methods (rather than
* overloaded methods).
*
* When reading or writing this class to a Parcel, use the `writeValue()`
* and `readValue()` methods.
*/
class Value {
public:
Value();
virtual ~Value();
Value& swap(Value &);
bool empty() const;
void clear();
#ifdef LIBBINDER_VALUE_SUPPORTS_TYPE_INFO
const std::type_info& type() const;
#endif
int32_t parcelType() const;
bool operator==(const Value& rhs) const;
bool operator!=(const Value& rhs) const { return !this->operator==(rhs); }
Value(const Value& value);
Value(const bool& value);
Value(const int8_t& value);
Value(const int32_t& value);
Value(const int64_t& value);
Value(const double& value);
Value(const String16& value);
Value(const std::vector<bool>& value);
Value(const std::vector<uint8_t>& value);
Value(const std::vector<int32_t>& value);
Value(const std::vector<int64_t>& value);
Value(const std::vector<double>& value);
Value(const std::vector<String16>& value);
Value(const os::PersistableBundle& value);
Value(const binder::Map& value);
Value& operator=(const Value& rhs);
Value& operator=(const int8_t& rhs);
Value& operator=(const bool& rhs);
Value& operator=(const int32_t& rhs);
Value& operator=(const int64_t& rhs);
Value& operator=(const double& rhs);
Value& operator=(const String16& rhs);
Value& operator=(const std::vector<bool>& rhs);
Value& operator=(const std::vector<uint8_t>& rhs);
Value& operator=(const std::vector<int32_t>& rhs);
Value& operator=(const std::vector<int64_t>& rhs);
Value& operator=(const std::vector<double>& rhs);
Value& operator=(const std::vector<String16>& rhs);
Value& operator=(const os::PersistableBundle& rhs);
Value& operator=(const binder::Map& rhs);
void putBoolean(const bool& value);
void putByte(const int8_t& value);
void putInt(const int32_t& value);
void putLong(const int64_t& value);
void putDouble(const double& value);
void putString(const String16& value);
void putBooleanVector(const std::vector<bool>& value);
void putByteVector(const std::vector<uint8_t>& value);
void putIntVector(const std::vector<int32_t>& value);
void putLongVector(const std::vector<int64_t>& value);
void putDoubleVector(const std::vector<double>& value);
void putStringVector(const std::vector<String16>& value);
void putPersistableBundle(const os::PersistableBundle& value);
void putMap(const binder::Map& value);
bool getBoolean(bool* out) const;
bool getByte(int8_t* out) const;
bool getInt(int32_t* out) const;
bool getLong(int64_t* out) const;
bool getDouble(double* out) const;
bool getString(String16* out) const;
bool getBooleanVector(std::vector<bool>* out) const;
bool getByteVector(std::vector<uint8_t>* out) const;
bool getIntVector(std::vector<int32_t>* out) const;
bool getLongVector(std::vector<int64_t>* out) const;
bool getDoubleVector(std::vector<double>* out) const;
bool getStringVector(std::vector<String16>* out) const;
bool getPersistableBundle(os::PersistableBundle* out) const;
bool getMap(binder::Map* out) const;
bool isBoolean() const;
bool isByte() const;
bool isInt() const;
bool isLong() const;
bool isDouble() const;
bool isString() const;
bool isBooleanVector() const;
bool isByteVector() const;
bool isIntVector() const;
bool isLongVector() const;
bool isDoubleVector() const;
bool isStringVector() const;
bool isPersistableBundle() const;
bool isMap() const;
// String Convenience Adapters
// ---------------------------
Value(const String8& value): Value(String16(value)) { }
Value(const ::std::string& value): Value(String8(value.c_str())) { }
void putString(const String8& value) { return putString(String16(value)); }
void putString(const ::std::string& value) { return putString(String8(value.c_str())); }
Value& operator=(const String8& rhs) { return *this = String16(rhs); }
Value& operator=(const ::std::string& rhs) { return *this = String8(rhs.c_str()); }
bool getString(String8* out) const;
bool getString(::std::string* out) const;
private:
// This allows ::android::Parcel to call the two methods below.
friend class ::android::Parcel;
// This is called by ::android::Parcel::writeValue()
status_t writeToParcel(Parcel* parcel) const;
// This is called by ::android::Parcel::readValue()
status_t readFromParcel(const Parcel* parcel);
template<typename T> class Content;
class ContentBase;
ContentBase* mContent;
};
} // namespace binder
} // namespace android
#endif // ANDROID_VALUE_H

View file

@ -0,0 +1,45 @@
/*
* Copyright (C) 2008 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.
*/
namespace android {
namespace binder {
// Keep in sync with frameworks/base/core/java/android/os/Parcel.java.
enum {
VAL_NULL = -1,
VAL_STRING = 0,
VAL_INTEGER = 1,
VAL_MAP = 2,
VAL_BUNDLE = 3,
VAL_PARCELABLE = 4,
VAL_SHORT = 5,
VAL_LONG = 6,
VAL_DOUBLE = 8,
VAL_BOOLEAN = 9,
VAL_BYTEARRAY = 13,
VAL_STRINGARRAY = 14,
VAL_IBINDER = 15,
VAL_INTARRAY = 18,
VAL_LONGARRAY = 19,
VAL_BYTE = 20,
VAL_SERIALIZABLE = 21,
VAL_BOOLEANARRAY = 23,
VAL_PERSISTABLEBUNDLE = 25,
VAL_DOUBLEARRAY = 28,
};
} // namespace binder
} // namespace android

View file

@ -0,0 +1,41 @@
/*
* Copyright (C) 2008 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.
*/
// All static variables go here, to control initialization and
// destruction order in the library.
#include <utils/threads.h>
#include <binder/IBinder.h>
#include <binder/ProcessState.h>
#include <binder/IPermissionController.h>
#include <binder/IServiceManager.h>
namespace android {
// For TextStream.cpp
extern Vector<int32_t> gTextBuffers;
// For ProcessState.cpp
extern Mutex gProcessMutex;
extern sp<ProcessState> gProcess;
// For IServiceManager.cpp
extern Mutex gDefaultServiceManagerLock;
extern sp<IServiceManager> gDefaultServiceManager;
extern sp<IPermissionController> gPermissionController;
} // namespace android

View file

@ -0,0 +1,33 @@
/*
* Copyright (C) 2008 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 _BINDER_MODULE_H_
#define _BINDER_MODULE_H_
#ifdef __cplusplus
namespace android {
#endif
/* obtain structures and constants from the kernel header */
#include <sys/ioctl.h>
#include <linux/android/binder.h>
#ifdef __cplusplus
} // namespace android
#endif
#endif // _BINDER_MODULE_H_

View file

@ -0,0 +1,131 @@
//
// Copyright (C) 2014 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.
//
cc_test {
name: "binderDriverInterfaceTest_IPC_32",
srcs: ["binderDriverInterfaceTest.cpp"],
compile_multilib: "32",
cflags: ["-DBINDER_IPC_32BIT=1"],
}
cc_test {
product_variables: {
binder32bit: {
cflags: ["-DBINDER_IPC_32BIT=1"],
},
},
name: "binderDriverInterfaceTest",
srcs: ["binderDriverInterfaceTest.cpp"],
}
cc_test {
name: "binderValueTypeTest",
srcs: ["binderValueTypeTest.cpp"],
shared_libs: [
"libbinder",
"libutils",
],
}
cc_test {
name: "binderLibTest_IPC_32",
srcs: ["binderLibTest.cpp"],
shared_libs: [
"libbinder",
"libutils",
],
compile_multilib: "32",
cflags: ["-DBINDER_IPC_32BIT=1"],
}
cc_test {
product_variables: {
binder32bit: {
cflags: ["-DBINDER_IPC_32BIT=1"],
},
},
name: "binderLibTest",
srcs: ["binderLibTest.cpp"],
shared_libs: [
"libbinder",
"libutils",
],
}
cc_test {
name: "binderThroughputTest",
srcs: ["binderThroughputTest.cpp"],
shared_libs: [
"libbinder",
"libutils",
],
clang: true,
cflags: [
"-g",
"-Wall",
"-Werror",
"-Wno-missing-field-initializers",
"-Wno-sign-compare",
"-O3",
],
}
cc_test {
name: "binderTextOutputTest",
srcs: ["binderTextOutputTest.cpp"],
shared_libs: [
"libbinder",
"libutils",
"libbase",
],
}
cc_test {
name: "schd-dbg",
srcs: ["schd-dbg.cpp"],
shared_libs: [
"libbinder",
"libutils",
"libbase",
],
}
cc_test {
name: "binderSafeInterfaceTest",
srcs: ["binderSafeInterfaceTest.cpp"],
cppflags: [
"-Werror",
"-Weverything",
"-Wno-c++98-compat",
"-Wno-c++98-compat-pedantic",
"-Wno-global-constructors",
"-Wno-padded",
"-Wno-weak-vtables",
],
cpp_std: "experimental",
gnu_extensions: false,
shared_libs: [
"libbinder",
"libcutils",
"liblog",
"libutils",
],
}

View file

@ -0,0 +1,354 @@
/*
* Copyright (C) 2014 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 <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <gtest/gtest.h>
#include <linux/android/binder.h>
#include <binder/IBinder.h>
#include <sys/mman.h>
#include <poll.h>
#define BINDER_DEV_NAME "/dev/binder"
testing::Environment* binder_env;
class BinderDriverInterfaceTestEnv : public ::testing::Environment {
virtual void SetUp() {
int ret;
uint32_t max_threads = 0;
m_binderFd = open(BINDER_DEV_NAME, O_RDWR | O_NONBLOCK | O_CLOEXEC);
ASSERT_GE(m_binderFd, 0);
m_buffer = mmap(NULL, 64*1024, PROT_READ, MAP_SHARED, m_binderFd, 0);
ASSERT_NE(m_buffer, (void *)NULL);
ret = ioctl(m_binderFd, BINDER_SET_MAX_THREADS, &max_threads);
EXPECT_EQ(0, ret);
EnterLooper();
}
virtual void TearDown() {
close(m_binderFd);
}
private:
int m_binderFd;
void *m_buffer;
public:
int getBinderFd(void) {
return m_binderFd;
}
void EnterLooper(void) {
int ret;
const uint32_t bc[] = {
BC_ENTER_LOOPER,
};
struct binder_write_read bwr = binder_write_read();
bwr.write_buffer = (uintptr_t)bc;
bwr.write_size = sizeof(bc);
ret = ioctl(m_binderFd, BINDER_WRITE_READ, &bwr);
EXPECT_EQ(0, ret);
if (ret < 0) {
EXPECT_EQ(0, errno);
}
EXPECT_EQ(sizeof(bc), bwr.write_consumed);
}
};
class BinderDriverInterfaceTest : public ::testing::Test {
public:
virtual void SetUp() {
m_binderFd = static_cast<BinderDriverInterfaceTestEnv *>(binder_env)->getBinderFd();
}
virtual void TearDown() {
}
protected:
void binderTestIoctlRetErr2(int cmd, void *arg, int expect_ret, int expect_errno, int accept_errno) {
int ret;
ret = ioctl(m_binderFd, cmd, arg);
EXPECT_EQ(expect_ret, ret);
if (ret < 0) {
if (errno != accept_errno)
EXPECT_EQ(expect_errno, errno);
}
}
void binderTestIoctlErr2(int cmd, void *arg, int expect_errno, int accept_errno) {
binderTestIoctlRetErr2(cmd, arg, -1, expect_errno, accept_errno);
}
void binderTestIoctlErr1(int cmd, void *arg, int expect_errno) {
binderTestIoctlErr2(cmd, arg, expect_errno, expect_errno);
}
void binderTestIoctl(int cmd, void *arg) {
binderTestIoctlRetErr2(cmd, arg, 0, 0, 0);
}
void binderTestIoctlUnimplemented(int cmd, void *arg) {
int ret;
ret = ioctl(m_binderFd, cmd, arg);
if (ret < 0) {
/* Not currently implmented. Allow ret == -1, errno == EINVAL */
EXPECT_EQ(-1, ret);
EXPECT_EQ(EINVAL, errno);
}
}
void binderTestReadEmpty(void) {
size_t i;
uint32_t br[32];
struct binder_write_read bwr = binder_write_read();
SCOPED_TRACE("TestReadEmpty");
bwr.read_buffer = (uintptr_t)br;
bwr.read_size = sizeof(br);
binderTestIoctlErr1(BINDER_WRITE_READ, &bwr, EAGAIN);
EXPECT_EQ(0u, bwr.read_consumed);
for (i = 0; i * sizeof(uint32_t) < bwr.read_consumed; i++) {
SCOPED_TRACE(testing::Message() << "i = " << i);
EXPECT_EQ(BR_NOOP, br[i]);
}
}
void binderWaitForReadData(int timeout_ms) {
int ret;
pollfd pfd = pollfd();
pfd.fd = m_binderFd;
pfd.events = POLLIN;
ret = poll(&pfd, 1, timeout_ms);
EXPECT_EQ(1, ret);
}
private:
int m_binderFd;
};
TEST_F(BinderDriverInterfaceTest, Version) {
struct binder_version version;
binderTestIoctl(BINDER_VERSION, &version);
ASSERT_EQ(BINDER_CURRENT_PROTOCOL_VERSION, version.protocol_version);
}
TEST_F(BinderDriverInterfaceTest, WriteReadNull) {
binderTestIoctlErr1(BINDER_WRITE_READ, NULL, EFAULT);
}
TEST_F(BinderDriverInterfaceTest, SetIdleTimeoutNull) {
binderTestIoctlErr2(BINDER_SET_IDLE_TIMEOUT, NULL, EFAULT, EINVAL);
}
TEST_F(BinderDriverInterfaceTest, SetMaxThreadsNull) {
binderTestIoctlErr2(BINDER_SET_MAX_THREADS, NULL, EFAULT, EINVAL); /* TODO: don't accept EINVAL */
}
TEST_F(BinderDriverInterfaceTest, SetIdlePriorityNull) {
binderTestIoctlErr2(BINDER_SET_IDLE_PRIORITY, NULL, EFAULT, EINVAL);
}
TEST_F(BinderDriverInterfaceTest, VersionNull) {
binderTestIoctlErr2(BINDER_VERSION, NULL, EFAULT, EINVAL); /* TODO: don't accept EINVAL */
}
TEST_F(BinderDriverInterfaceTest, SetIdleTimeoutNoTest) {
int64_t idle_timeout = 100000;
binderTestIoctlUnimplemented(BINDER_SET_IDLE_TIMEOUT, &idle_timeout);
}
TEST_F(BinderDriverInterfaceTest, SetMaxThreads) {
uint32_t max_threads = 0;
binderTestIoctl(BINDER_SET_MAX_THREADS, &max_threads);
}
TEST_F(BinderDriverInterfaceTest, SetIdlePriorityNoTest) {
int idle_priority = 0;
binderTestIoctlUnimplemented(BINDER_SET_IDLE_PRIORITY, &idle_priority);
}
TEST_F(BinderDriverInterfaceTest, SetContextMgrBusy) {
int32_t dummy = 0;
binderTestIoctlErr1(BINDER_SET_CONTEXT_MGR, &dummy, EBUSY);
}
TEST_F(BinderDriverInterfaceTest, ThreadExit) {
int32_t dummy = 0;
binderTestIoctl(BINDER_THREAD_EXIT, &dummy);
static_cast<BinderDriverInterfaceTestEnv *>(binder_env)->EnterLooper();
}
TEST_F(BinderDriverInterfaceTest, WriteReadEmpty) {
struct binder_write_read bwr = binder_write_read();
binderTestIoctl(BINDER_WRITE_READ, &bwr);
}
TEST_F(BinderDriverInterfaceTest, Read) {
binderTestReadEmpty();
}
TEST_F(BinderDriverInterfaceTest, IncRefsAcquireReleaseDecRefs) {
const uint32_t bc[] = {
BC_INCREFS,
0,
BC_ACQUIRE,
0,
BC_RELEASE,
0,
BC_DECREFS,
0,
};
struct binder_write_read bwr = binder_write_read();
bwr.write_buffer = (uintptr_t)bc;
bwr.write_size = sizeof(bc);
binderTestIoctl(BINDER_WRITE_READ, &bwr);
EXPECT_EQ(sizeof(bc), bwr.write_consumed);
binderTestReadEmpty();
}
TEST_F(BinderDriverInterfaceTest, Transaction) {
binder_uintptr_t cookie = 1234;
struct {
uint32_t cmd1;
struct binder_transaction_data arg1;
} __attribute__((packed)) bc1 = {
.cmd1 = BC_TRANSACTION,
.arg1 = {
.target = { 0 },
.cookie = 0,
.code = android::IBinder::PING_TRANSACTION,
.flags = 0,
.sender_pid = 0,
.sender_euid = 0,
.data_size = 0,
.offsets_size = 0,
.data = {
.ptr = {0, 0},
},
},
};
struct {
uint32_t cmd0;
uint32_t cmd1;
uint32_t cmd2;
binder_transaction_data arg2;
uint32_t pad[16];
} __attribute__((packed)) br;
struct binder_write_read bwr = binder_write_read();
bwr.write_buffer = (uintptr_t)&bc1;
bwr.write_size = sizeof(bc1);
bwr.read_buffer = (uintptr_t)&br;
bwr.read_size = sizeof(br);
{
SCOPED_TRACE("1st WriteRead");
binderTestIoctl(BINDER_WRITE_READ, &bwr);
}
EXPECT_EQ(sizeof(bc1), bwr.write_consumed);
if (bwr.read_consumed < offsetof(typeof(br), pad)) {
SCOPED_TRACE("2nd WriteRead");
binderWaitForReadData(10000);
binderTestIoctl(BINDER_WRITE_READ, &bwr);
}
EXPECT_EQ(offsetof(typeof(br), pad), bwr.read_consumed);
if (bwr.read_consumed > offsetof(typeof(br), cmd0))
EXPECT_EQ(BR_NOOP, br.cmd0);
if (bwr.read_consumed > offsetof(typeof(br), cmd1))
EXPECT_EQ(BR_TRANSACTION_COMPLETE, br.cmd1);
if (bwr.read_consumed > offsetof(typeof(br), cmd2))
EXPECT_EQ(BR_REPLY, br.cmd2);
if (bwr.read_consumed >= offsetof(typeof(br), pad)) {
EXPECT_EQ(0u, br.arg2.target.ptr);
EXPECT_EQ(0u, br.arg2.cookie);
EXPECT_EQ(0u, br.arg2.code);
EXPECT_EQ(0u, br.arg2.flags);
EXPECT_EQ(0u, br.arg2.data_size);
EXPECT_EQ(0u, br.arg2.offsets_size);
SCOPED_TRACE("3rd WriteRead");
binderTestReadEmpty();
struct {
uint32_t cmd1;
binder_uintptr_t arg1;
} __attribute__((packed)) bc2 = {
.cmd1 = BC_FREE_BUFFER,
.arg1 = br.arg2.data.ptr.buffer,
};
bwr.write_buffer = (uintptr_t)&bc2;
bwr.write_size = sizeof(bc2);
bwr.write_consumed = 0;
bwr.read_size = 0;
binderTestIoctl(BINDER_WRITE_READ, &bwr);
EXPECT_EQ(sizeof(bc2), bwr.write_consumed);
}
binderTestReadEmpty();
}
TEST_F(BinderDriverInterfaceTest, RequestDeathNotification) {
binder_uintptr_t cookie = 1234;
struct {
uint32_t cmd0;
uint32_t arg0;
uint32_t cmd1;
struct binder_handle_cookie arg1;
uint32_t cmd2;
struct binder_handle_cookie arg2;
uint32_t cmd3;
uint32_t arg3;
} __attribute__((packed)) bc = {
.cmd0 = BC_INCREFS,
.arg0 = 0,
.cmd1 = BC_REQUEST_DEATH_NOTIFICATION,
.arg1 = {
.handle = 0,
.cookie = cookie,
},
.cmd2 = BC_CLEAR_DEATH_NOTIFICATION,
.arg2 = {
.handle = 0,
.cookie = cookie,
},
.cmd3 = BC_DECREFS,
.arg3 = 0,
};
struct {
uint32_t cmd0;
uint32_t cmd1;
binder_uintptr_t arg1;
uint32_t pad[16];
} __attribute__((packed)) br;
struct binder_write_read bwr = binder_write_read();
bwr.write_buffer = (uintptr_t)&bc;
bwr.write_size = sizeof(bc);
bwr.read_buffer = (uintptr_t)&br;
bwr.read_size = sizeof(br);
binderTestIoctl(BINDER_WRITE_READ, &bwr);
EXPECT_EQ(sizeof(bc), bwr.write_consumed);
EXPECT_EQ(sizeof(br) - sizeof(br.pad), bwr.read_consumed);
EXPECT_EQ(BR_NOOP, br.cmd0);
EXPECT_EQ(BR_CLEAR_DEATH_NOTIFICATION_DONE, br.cmd1);
EXPECT_EQ(cookie, br.arg1);
binderTestReadEmpty();
}
int main(int argc, char **argv) {
::testing::InitGoogleTest(&argc, argv);
binder_env = AddGlobalTestEnvironment(new BinderDriverInterfaceTestEnv());
return RUN_ALL_TESTS();
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,819 @@
/*
* Copyright 2016 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/SafeInterface.h>
#include <binder/IInterface.h>
#include <binder/IPCThreadState.h>
#include <binder/IServiceManager.h>
#include <binder/Parcel.h>
#include <binder/Parcelable.h>
#include <binder/ProcessState.h>
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Weverything"
#include <gtest/gtest.h>
#pragma clang diagnostic pop
#include <utils/LightRefBase.h>
#include <utils/NativeHandle.h>
#include <cutils/native_handle.h>
#include <optional>
#include <sys/eventfd.h>
using namespace std::chrono_literals; // NOLINT - google-build-using-namespace
namespace android {
namespace tests {
enum class TestEnum : uint32_t {
INVALID = 0,
INITIAL = 1,
FINAL = 2,
};
// This class serves two purposes:
// 1) It ensures that the implementation doesn't require copying or moving the data (for
// efficiency purposes)
// 2) It tests that Parcelables can be passed correctly
class NoCopyNoMove : public Parcelable {
public:
NoCopyNoMove() = default;
explicit NoCopyNoMove(int32_t value) : mValue(value) {}
~NoCopyNoMove() override = default;
// Not copyable
NoCopyNoMove(const NoCopyNoMove&) = delete;
NoCopyNoMove& operator=(const NoCopyNoMove&) = delete;
// Not movable
NoCopyNoMove(NoCopyNoMove&&) = delete;
NoCopyNoMove& operator=(NoCopyNoMove&&) = delete;
// Parcelable interface
status_t writeToParcel(Parcel* parcel) const override { return parcel->writeInt32(mValue); }
status_t readFromParcel(const Parcel* parcel) override { return parcel->readInt32(&mValue); }
int32_t getValue() const { return mValue; }
void setValue(int32_t value) { mValue = value; }
private:
int32_t mValue = 0;
uint8_t mPadding[4] = {}; // Avoids a warning from -Wpadded
};
struct TestFlattenable : Flattenable<TestFlattenable> {
TestFlattenable() = default;
explicit TestFlattenable(int32_t v) : value(v) {}
// Flattenable protocol
size_t getFlattenedSize() const { return sizeof(value); }
size_t getFdCount() const { return 0; }
status_t flatten(void*& buffer, size_t& size, int*& /*fds*/, size_t& /*count*/) const {
FlattenableUtils::write(buffer, size, value);
return NO_ERROR;
}
status_t unflatten(void const*& buffer, size_t& size, int const*& /*fds*/, size_t& /*count*/) {
FlattenableUtils::read(buffer, size, value);
return NO_ERROR;
}
int32_t value = 0;
};
struct TestLightFlattenable : LightFlattenablePod<TestLightFlattenable> {
TestLightFlattenable() = default;
explicit TestLightFlattenable(int32_t v) : value(v) {}
int32_t value = 0;
};
// It seems like this should be able to inherit from TestFlattenable (to avoid duplicating code),
// but the SafeInterface logic can't easily be extended to find an indirect Flattenable<T>
// base class
class TestLightRefBaseFlattenable : public Flattenable<TestLightRefBaseFlattenable>,
public LightRefBase<TestLightRefBaseFlattenable> {
public:
TestLightRefBaseFlattenable() = default;
explicit TestLightRefBaseFlattenable(int32_t v) : value(v) {}
// Flattenable protocol
size_t getFlattenedSize() const { return sizeof(value); }
size_t getFdCount() const { return 0; }
status_t flatten(void*& buffer, size_t& size, int*& /*fds*/, size_t& /*count*/) const {
FlattenableUtils::write(buffer, size, value);
return NO_ERROR;
}
status_t unflatten(void const*& buffer, size_t& size, int const*& /*fds*/, size_t& /*count*/) {
FlattenableUtils::read(buffer, size, value);
return NO_ERROR;
}
int32_t value = 0;
};
class TestParcelable : public Parcelable {
public:
TestParcelable() = default;
explicit TestParcelable(int32_t value) : mValue(value) {}
TestParcelable(const TestParcelable& other) : TestParcelable(other.mValue) {}
TestParcelable(TestParcelable&& other) : TestParcelable(other.mValue) {}
// Parcelable interface
status_t writeToParcel(Parcel* parcel) const override { return parcel->writeInt32(mValue); }
status_t readFromParcel(const Parcel* parcel) override { return parcel->readInt32(&mValue); }
int32_t getValue() const { return mValue; }
void setValue(int32_t value) { mValue = value; }
private:
int32_t mValue = 0;
};
class ExitOnDeath : public IBinder::DeathRecipient {
public:
~ExitOnDeath() override = default;
void binderDied(const wp<IBinder>& /*who*/) override {
ALOG(LOG_INFO, "ExitOnDeath", "Exiting");
exit(0);
}
};
// This callback class is used to test both one-way transactions and that sp<IInterface> can be
// passed correctly
class ICallback : public IInterface {
public:
DECLARE_META_INTERFACE(Callback)
enum class Tag : uint32_t {
OnCallback = IBinder::FIRST_CALL_TRANSACTION,
Last,
};
virtual void onCallback(int32_t aPlusOne) = 0;
};
class BpCallback : public SafeBpInterface<ICallback> {
public:
explicit BpCallback(const sp<IBinder>& impl) : SafeBpInterface<ICallback>(impl, getLogTag()) {}
void onCallback(int32_t aPlusOne) override {
ALOG(LOG_INFO, getLogTag(), "%s", __PRETTY_FUNCTION__);
return callRemoteAsync<decltype(&ICallback::onCallback)>(Tag::OnCallback, aPlusOne);
}
private:
static constexpr const char* getLogTag() { return "BpCallback"; }
};
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wexit-time-destructors"
IMPLEMENT_META_INTERFACE(Callback, "android.gfx.tests.ICallback");
#pragma clang diagnostic pop
class BnCallback : public SafeBnInterface<ICallback> {
public:
BnCallback() : SafeBnInterface("BnCallback") {}
status_t onTransact(uint32_t code, const Parcel& data, Parcel* reply,
uint32_t /*flags*/) override {
EXPECT_GE(code, IBinder::FIRST_CALL_TRANSACTION);
EXPECT_LT(code, static_cast<uint32_t>(ICallback::Tag::Last));
ICallback::Tag tag = static_cast<ICallback::Tag>(code);
switch (tag) {
case ICallback::Tag::OnCallback: {
return callLocalAsync(data, reply, &ICallback::onCallback);
}
case ICallback::Tag::Last:
// Should not be possible because of the asserts at the beginning of the method
[&]() { FAIL(); }();
return UNKNOWN_ERROR;
}
}
};
class ISafeInterfaceTest : public IInterface {
public:
DECLARE_META_INTERFACE(SafeInterfaceTest)
enum class Tag : uint32_t {
SetDeathToken = IBinder::FIRST_CALL_TRANSACTION,
ReturnsNoMemory,
LogicalNot,
ModifyEnum,
IncrementFlattenable,
IncrementLightFlattenable,
IncrementLightRefBaseFlattenable,
IncrementNativeHandle,
IncrementNoCopyNoMove,
IncrementParcelableVector,
ToUpper,
CallMeBack,
IncrementInt32,
IncrementUint32,
IncrementInt64,
IncrementUint64,
IncrementTwo,
Last,
};
// This is primarily so that the remote service dies when the test does, but it also serves to
// test the handling of sp<IBinder> and non-const methods
virtual status_t setDeathToken(const sp<IBinder>& token) = 0;
// This is the most basic test since it doesn't require parceling any arguments
virtual status_t returnsNoMemory() const = 0;
// These are ordered according to their corresponding methods in SafeInterface::ParcelHandler
virtual status_t logicalNot(bool a, bool* notA) const = 0;
virtual status_t modifyEnum(TestEnum a, TestEnum* b) const = 0;
virtual status_t increment(const TestFlattenable& a, TestFlattenable* aPlusOne) const = 0;
virtual status_t increment(const TestLightFlattenable& a,
TestLightFlattenable* aPlusOne) const = 0;
virtual status_t increment(const sp<TestLightRefBaseFlattenable>& a,
sp<TestLightRefBaseFlattenable>* aPlusOne) const = 0;
virtual status_t increment(const sp<NativeHandle>& a, sp<NativeHandle>* aPlusOne) const = 0;
virtual status_t increment(const NoCopyNoMove& a, NoCopyNoMove* aPlusOne) const = 0;
virtual status_t increment(const std::vector<TestParcelable>& a,
std::vector<TestParcelable>* aPlusOne) const = 0;
virtual status_t toUpper(const String8& str, String8* upperStr) const = 0;
// As mentioned above, sp<IBinder> is already tested by setDeathToken
virtual void callMeBack(const sp<ICallback>& callback, int32_t a) const = 0;
virtual status_t increment(int32_t a, int32_t* aPlusOne) const = 0;
virtual status_t increment(uint32_t a, uint32_t* aPlusOne) const = 0;
virtual status_t increment(int64_t a, int64_t* aPlusOne) const = 0;
virtual status_t increment(uint64_t a, uint64_t* aPlusOne) const = 0;
// This tests that input/output parameter interleaving works correctly
virtual status_t increment(int32_t a, int32_t* aPlusOne, int32_t b,
int32_t* bPlusOne) const = 0;
};
class BpSafeInterfaceTest : public SafeBpInterface<ISafeInterfaceTest> {
public:
explicit BpSafeInterfaceTest(const sp<IBinder>& impl)
: SafeBpInterface<ISafeInterfaceTest>(impl, getLogTag()) {}
status_t setDeathToken(const sp<IBinder>& token) override {
ALOG(LOG_INFO, getLogTag(), "%s", __PRETTY_FUNCTION__);
return callRemote<decltype(&ISafeInterfaceTest::setDeathToken)>(Tag::SetDeathToken, token);
}
status_t returnsNoMemory() const override {
ALOG(LOG_INFO, getLogTag(), "%s", __PRETTY_FUNCTION__);
return callRemote<decltype(&ISafeInterfaceTest::returnsNoMemory)>(Tag::ReturnsNoMemory);
}
status_t logicalNot(bool a, bool* notA) const override {
ALOG(LOG_INFO, getLogTag(), "%s", __PRETTY_FUNCTION__);
return callRemote<decltype(&ISafeInterfaceTest::logicalNot)>(Tag::LogicalNot, a, notA);
}
status_t modifyEnum(TestEnum a, TestEnum* b) const override {
ALOG(LOG_INFO, getLogTag(), "%s", __PRETTY_FUNCTION__);
return callRemote<decltype(&ISafeInterfaceTest::modifyEnum)>(Tag::ModifyEnum, a, b);
}
status_t increment(const TestFlattenable& a, TestFlattenable* aPlusOne) const override {
using Signature =
status_t (ISafeInterfaceTest::*)(const TestFlattenable&, TestFlattenable*) const;
ALOG(LOG_INFO, getLogTag(), "%s", __PRETTY_FUNCTION__);
return callRemote<Signature>(Tag::IncrementFlattenable, a, aPlusOne);
}
status_t increment(const TestLightFlattenable& a,
TestLightFlattenable* aPlusOne) const override {
using Signature = status_t (ISafeInterfaceTest::*)(const TestLightFlattenable&,
TestLightFlattenable*) const;
ALOG(LOG_INFO, getLogTag(), "%s", __PRETTY_FUNCTION__);
return callRemote<Signature>(Tag::IncrementLightFlattenable, a, aPlusOne);
}
status_t increment(const sp<TestLightRefBaseFlattenable>& a,
sp<TestLightRefBaseFlattenable>* aPlusOne) const override {
using Signature = status_t (ISafeInterfaceTest::*)(const sp<TestLightRefBaseFlattenable>&,
sp<TestLightRefBaseFlattenable>*) const;
return callRemote<Signature>(Tag::IncrementLightRefBaseFlattenable, a, aPlusOne);
}
status_t increment(const sp<NativeHandle>& a, sp<NativeHandle>* aPlusOne) const override {
ALOG(LOG_INFO, getLogTag(), "%s", __PRETTY_FUNCTION__);
using Signature =
status_t (ISafeInterfaceTest::*)(const sp<NativeHandle>&, sp<NativeHandle>*) const;
return callRemote<Signature>(Tag::IncrementNativeHandle, a, aPlusOne);
}
status_t increment(const NoCopyNoMove& a, NoCopyNoMove* aPlusOne) const override {
ALOG(LOG_INFO, getLogTag(), "%s", __PRETTY_FUNCTION__);
using Signature = status_t (ISafeInterfaceTest::*)(const NoCopyNoMove& a,
NoCopyNoMove* aPlusOne) const;
return callRemote<Signature>(Tag::IncrementNoCopyNoMove, a, aPlusOne);
}
status_t increment(const std::vector<TestParcelable>& a,
std::vector<TestParcelable>* aPlusOne) const override {
ALOG(LOG_INFO, getLogTag(), "%s", __PRETTY_FUNCTION__);
using Signature = status_t (ISafeInterfaceTest::*)(const std::vector<TestParcelable>&,
std::vector<TestParcelable>*);
return callRemote<Signature>(Tag::IncrementParcelableVector, a, aPlusOne);
}
status_t toUpper(const String8& str, String8* upperStr) const override {
ALOG(LOG_INFO, getLogTag(), "%s", __PRETTY_FUNCTION__);
return callRemote<decltype(&ISafeInterfaceTest::toUpper)>(Tag::ToUpper, str, upperStr);
}
void callMeBack(const sp<ICallback>& callback, int32_t a) const override {
ALOG(LOG_INFO, getLogTag(), "%s", __PRETTY_FUNCTION__);
return callRemoteAsync<decltype(&ISafeInterfaceTest::callMeBack)>(Tag::CallMeBack, callback,
a);
}
status_t increment(int32_t a, int32_t* aPlusOne) const override {
ALOG(LOG_INFO, getLogTag(), "%s", __PRETTY_FUNCTION__);
using Signature = status_t (ISafeInterfaceTest::*)(int32_t, int32_t*) const;
return callRemote<Signature>(Tag::IncrementInt32, a, aPlusOne);
}
status_t increment(uint32_t a, uint32_t* aPlusOne) const override {
ALOG(LOG_INFO, getLogTag(), "%s", __PRETTY_FUNCTION__);
using Signature = status_t (ISafeInterfaceTest::*)(uint32_t, uint32_t*) const;
return callRemote<Signature>(Tag::IncrementUint32, a, aPlusOne);
}
status_t increment(int64_t a, int64_t* aPlusOne) const override {
ALOG(LOG_INFO, getLogTag(), "%s", __PRETTY_FUNCTION__);
using Signature = status_t (ISafeInterfaceTest::*)(int64_t, int64_t*) const;
return callRemote<Signature>(Tag::IncrementInt64, a, aPlusOne);
}
status_t increment(uint64_t a, uint64_t* aPlusOne) const override {
ALOG(LOG_INFO, getLogTag(), "%s", __PRETTY_FUNCTION__);
using Signature = status_t (ISafeInterfaceTest::*)(uint64_t, uint64_t*) const;
return callRemote<Signature>(Tag::IncrementUint64, a, aPlusOne);
}
status_t increment(int32_t a, int32_t* aPlusOne, int32_t b, int32_t* bPlusOne) const override {
ALOG(LOG_INFO, getLogTag(), "%s", __PRETTY_FUNCTION__);
using Signature =
status_t (ISafeInterfaceTest::*)(int32_t, int32_t*, int32_t, int32_t*) const;
return callRemote<Signature>(Tag::IncrementTwo, a, aPlusOne, b, bPlusOne);
}
private:
static constexpr const char* getLogTag() { return "BpSafeInterfaceTest"; }
};
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wexit-time-destructors"
IMPLEMENT_META_INTERFACE(SafeInterfaceTest, "android.gfx.tests.ISafeInterfaceTest");
static sp<IBinder::DeathRecipient> getDeathRecipient() {
static sp<IBinder::DeathRecipient> recipient = new ExitOnDeath;
return recipient;
}
#pragma clang diagnostic pop
class BnSafeInterfaceTest : public SafeBnInterface<ISafeInterfaceTest> {
public:
BnSafeInterfaceTest() : SafeBnInterface(getLogTag()) {}
status_t setDeathToken(const sp<IBinder>& token) override {
ALOG(LOG_INFO, getLogTag(), "%s", __PRETTY_FUNCTION__);
token->linkToDeath(getDeathRecipient());
return NO_ERROR;
}
status_t returnsNoMemory() const override {
ALOG(LOG_INFO, getLogTag(), "%s", __PRETTY_FUNCTION__);
return NO_MEMORY;
}
status_t logicalNot(bool a, bool* notA) const override {
ALOG(LOG_INFO, getLogTag(), "%s", __PRETTY_FUNCTION__);
*notA = !a;
return NO_ERROR;
}
status_t modifyEnum(TestEnum a, TestEnum* b) const override {
ALOG(LOG_INFO, getLogTag(), "%s", __PRETTY_FUNCTION__);
*b = (a == TestEnum::INITIAL) ? TestEnum::FINAL : TestEnum::INVALID;
return NO_ERROR;
}
status_t increment(const TestFlattenable& a, TestFlattenable* aPlusOne) const override {
ALOG(LOG_INFO, getLogTag(), "%s", __PRETTY_FUNCTION__);
aPlusOne->value = a.value + 1;
return NO_ERROR;
}
status_t increment(const TestLightFlattenable& a,
TestLightFlattenable* aPlusOne) const override {
ALOG(LOG_INFO, getLogTag(), "%s", __PRETTY_FUNCTION__);
aPlusOne->value = a.value + 1;
return NO_ERROR;
}
status_t increment(const sp<TestLightRefBaseFlattenable>& a,
sp<TestLightRefBaseFlattenable>* aPlusOne) const override {
ALOG(LOG_INFO, getLogTag(), "%s", __PRETTY_FUNCTION__);
*aPlusOne = new TestLightRefBaseFlattenable(a->value + 1);
return NO_ERROR;
}
status_t increment(const sp<NativeHandle>& a, sp<NativeHandle>* aPlusOne) const override {
ALOG(LOG_INFO, getLogTag(), "%s", __PRETTY_FUNCTION__);
native_handle* rawHandle = native_handle_create(1 /*numFds*/, 1 /*numInts*/);
if (rawHandle == nullptr) return NO_MEMORY;
// Copy the fd over directly
rawHandle->data[0] = dup(a->handle()->data[0]);
// Increment the int
rawHandle->data[1] = a->handle()->data[1] + 1;
// This cannot fail, as it is just the sp<NativeHandle> taking responsibility for closing
// the native_handle when it goes out of scope
*aPlusOne = NativeHandle::create(rawHandle, true);
return NO_ERROR;
}
status_t increment(const NoCopyNoMove& a, NoCopyNoMove* aPlusOne) const override {
ALOG(LOG_INFO, getLogTag(), "%s", __PRETTY_FUNCTION__);
aPlusOne->setValue(a.getValue() + 1);
return NO_ERROR;
}
status_t increment(const std::vector<TestParcelable>& a,
std::vector<TestParcelable>* aPlusOne) const override {
ALOG(LOG_INFO, getLogTag(), "%s", __PRETTY_FUNCTION__);
aPlusOne->resize(a.size());
for (size_t i = 0; i < a.size(); ++i) {
(*aPlusOne)[i].setValue(a[i].getValue() + 1);
}
return NO_ERROR;
}
status_t toUpper(const String8& str, String8* upperStr) const override {
ALOG(LOG_INFO, getLogTag(), "%s", __PRETTY_FUNCTION__);
*upperStr = str;
upperStr->toUpper();
return NO_ERROR;
}
void callMeBack(const sp<ICallback>& callback, int32_t a) const override {
ALOG(LOG_INFO, getLogTag(), "%s", __PRETTY_FUNCTION__);
callback->onCallback(a + 1);
}
status_t increment(int32_t a, int32_t* aPlusOne) const override {
ALOG(LOG_INFO, getLogTag(), "%s", __PRETTY_FUNCTION__);
*aPlusOne = a + 1;
return NO_ERROR;
}
status_t increment(uint32_t a, uint32_t* aPlusOne) const override {
ALOG(LOG_INFO, getLogTag(), "%s", __PRETTY_FUNCTION__);
*aPlusOne = a + 1;
return NO_ERROR;
}
status_t increment(int64_t a, int64_t* aPlusOne) const override {
ALOG(LOG_INFO, getLogTag(), "%s", __PRETTY_FUNCTION__);
*aPlusOne = a + 1;
return NO_ERROR;
}
status_t increment(uint64_t a, uint64_t* aPlusOne) const override {
ALOG(LOG_INFO, getLogTag(), "%s", __PRETTY_FUNCTION__);
*aPlusOne = a + 1;
return NO_ERROR;
}
status_t increment(int32_t a, int32_t* aPlusOne, int32_t b, int32_t* bPlusOne) const override {
ALOG(LOG_INFO, getLogTag(), "%s", __PRETTY_FUNCTION__);
*aPlusOne = a + 1;
*bPlusOne = b + 1;
return NO_ERROR;
}
// BnInterface
status_t onTransact(uint32_t code, const Parcel& data, Parcel* reply,
uint32_t /*flags*/) override {
EXPECT_GE(code, IBinder::FIRST_CALL_TRANSACTION);
EXPECT_LT(code, static_cast<uint32_t>(Tag::Last));
ISafeInterfaceTest::Tag tag = static_cast<ISafeInterfaceTest::Tag>(code);
switch (tag) {
case ISafeInterfaceTest::Tag::SetDeathToken: {
return callLocal(data, reply, &ISafeInterfaceTest::setDeathToken);
}
case ISafeInterfaceTest::Tag::ReturnsNoMemory: {
return callLocal(data, reply, &ISafeInterfaceTest::returnsNoMemory);
}
case ISafeInterfaceTest::Tag::LogicalNot: {
return callLocal(data, reply, &ISafeInterfaceTest::logicalNot);
}
case ISafeInterfaceTest::Tag::ModifyEnum: {
return callLocal(data, reply, &ISafeInterfaceTest::modifyEnum);
}
case ISafeInterfaceTest::Tag::IncrementFlattenable: {
using Signature = status_t (ISafeInterfaceTest::*)(const TestFlattenable& a,
TestFlattenable* aPlusOne) const;
return callLocal<Signature>(data, reply, &ISafeInterfaceTest::increment);
}
case ISafeInterfaceTest::Tag::IncrementLightFlattenable: {
using Signature =
status_t (ISafeInterfaceTest::*)(const TestLightFlattenable& a,
TestLightFlattenable* aPlusOne) const;
return callLocal<Signature>(data, reply, &ISafeInterfaceTest::increment);
}
case ISafeInterfaceTest::Tag::IncrementLightRefBaseFlattenable: {
using Signature =
status_t (ISafeInterfaceTest::*)(const sp<TestLightRefBaseFlattenable>&,
sp<TestLightRefBaseFlattenable>*) const;
return callLocal<Signature>(data, reply, &ISafeInterfaceTest::increment);
}
case ISafeInterfaceTest::Tag::IncrementNativeHandle: {
using Signature = status_t (ISafeInterfaceTest::*)(const sp<NativeHandle>&,
sp<NativeHandle>*) const;
return callLocal<Signature>(data, reply, &ISafeInterfaceTest::increment);
}
case ISafeInterfaceTest::Tag::IncrementNoCopyNoMove: {
using Signature = status_t (ISafeInterfaceTest::*)(const NoCopyNoMove& a,
NoCopyNoMove* aPlusOne) const;
return callLocal<Signature>(data, reply, &ISafeInterfaceTest::increment);
}
case ISafeInterfaceTest::Tag::IncrementParcelableVector: {
using Signature =
status_t (ISafeInterfaceTest::*)(const std::vector<TestParcelable>&,
std::vector<TestParcelable>*) const;
return callLocal<Signature>(data, reply, &ISafeInterfaceTest::increment);
}
case ISafeInterfaceTest::Tag::ToUpper: {
return callLocal(data, reply, &ISafeInterfaceTest::toUpper);
}
case ISafeInterfaceTest::Tag::CallMeBack: {
return callLocalAsync(data, reply, &ISafeInterfaceTest::callMeBack);
}
case ISafeInterfaceTest::Tag::IncrementInt32: {
using Signature = status_t (ISafeInterfaceTest::*)(int32_t, int32_t*) const;
return callLocal<Signature>(data, reply, &ISafeInterfaceTest::increment);
}
case ISafeInterfaceTest::Tag::IncrementUint32: {
using Signature = status_t (ISafeInterfaceTest::*)(uint32_t, uint32_t*) const;
return callLocal<Signature>(data, reply, &ISafeInterfaceTest::increment);
}
case ISafeInterfaceTest::Tag::IncrementInt64: {
using Signature = status_t (ISafeInterfaceTest::*)(int64_t, int64_t*) const;
return callLocal<Signature>(data, reply, &ISafeInterfaceTest::increment);
}
case ISafeInterfaceTest::Tag::IncrementUint64: {
using Signature = status_t (ISafeInterfaceTest::*)(uint64_t, uint64_t*) const;
return callLocal<Signature>(data, reply, &ISafeInterfaceTest::increment);
}
case ISafeInterfaceTest::Tag::IncrementTwo: {
using Signature = status_t (ISafeInterfaceTest::*)(int32_t, int32_t*, int32_t,
int32_t*) const;
return callLocal<Signature>(data, reply, &ISafeInterfaceTest::increment);
}
case ISafeInterfaceTest::Tag::Last:
// Should not be possible because of the asserts at the beginning of the method
[&]() { FAIL(); }();
return UNKNOWN_ERROR;
}
}
private:
static constexpr const char* getLogTag() { return "BnSafeInterfaceTest"; }
};
class SafeInterfaceTest : public ::testing::Test {
public:
SafeInterfaceTest() : mSafeInterfaceTest(getRemoteService()) {
ProcessState::self()->startThreadPool();
}
~SafeInterfaceTest() override = default;
protected:
sp<ISafeInterfaceTest> mSafeInterfaceTest;
private:
static constexpr const char* getLogTag() { return "SafeInterfaceTest"; }
sp<ISafeInterfaceTest> getRemoteService() {
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wexit-time-destructors"
static std::mutex sMutex;
static sp<ISafeInterfaceTest> sService;
static sp<IBinder> sDeathToken = new BBinder;
#pragma clang diagnostic pop
std::unique_lock<decltype(sMutex)> lock;
if (sService == nullptr) {
ALOG(LOG_INFO, getLogTag(), "Forking remote process");
pid_t forkPid = fork();
EXPECT_NE(forkPid, -1);
const String16 serviceName("SafeInterfaceTest");
if (forkPid == 0) {
ALOG(LOG_INFO, getLogTag(), "Remote process checking in");
sp<ISafeInterfaceTest> nativeService = new BnSafeInterfaceTest;
defaultServiceManager()->addService(serviceName,
IInterface::asBinder(nativeService));
ProcessState::self()->startThreadPool();
IPCThreadState::self()->joinThreadPool();
// We shouldn't get to this point
[&]() { FAIL(); }();
}
sp<IBinder> binder = defaultServiceManager()->getService(serviceName);
sService = interface_cast<ISafeInterfaceTest>(binder);
EXPECT_TRUE(sService != nullptr);
sService->setDeathToken(sDeathToken);
}
return sService;
}
};
TEST_F(SafeInterfaceTest, TestReturnsNoMemory) {
status_t result = mSafeInterfaceTest->returnsNoMemory();
ASSERT_EQ(NO_MEMORY, result);
}
TEST_F(SafeInterfaceTest, TestLogicalNot) {
const bool a = true;
bool notA = true;
status_t result = mSafeInterfaceTest->logicalNot(a, &notA);
ASSERT_EQ(NO_ERROR, result);
ASSERT_EQ(!a, notA);
// Test both since we don't want to accidentally catch a default false somewhere
const bool b = false;
bool notB = false;
result = mSafeInterfaceTest->logicalNot(b, &notB);
ASSERT_EQ(NO_ERROR, result);
ASSERT_EQ(!b, notB);
}
TEST_F(SafeInterfaceTest, TestModifyEnum) {
const TestEnum a = TestEnum::INITIAL;
TestEnum b = TestEnum::INVALID;
status_t result = mSafeInterfaceTest->modifyEnum(a, &b);
ASSERT_EQ(NO_ERROR, result);
ASSERT_EQ(TestEnum::FINAL, b);
}
TEST_F(SafeInterfaceTest, TestIncrementFlattenable) {
const TestFlattenable a{1};
TestFlattenable aPlusOne{0};
status_t result = mSafeInterfaceTest->increment(a, &aPlusOne);
ASSERT_EQ(NO_ERROR, result);
ASSERT_EQ(a.value + 1, aPlusOne.value);
}
TEST_F(SafeInterfaceTest, TestIncrementLightFlattenable) {
const TestLightFlattenable a{1};
TestLightFlattenable aPlusOne{0};
status_t result = mSafeInterfaceTest->increment(a, &aPlusOne);
ASSERT_EQ(NO_ERROR, result);
ASSERT_EQ(a.value + 1, aPlusOne.value);
}
TEST_F(SafeInterfaceTest, TestIncrementLightRefBaseFlattenable) {
sp<TestLightRefBaseFlattenable> a = new TestLightRefBaseFlattenable{1};
sp<TestLightRefBaseFlattenable> aPlusOne;
status_t result = mSafeInterfaceTest->increment(a, &aPlusOne);
ASSERT_EQ(NO_ERROR, result);
ASSERT_NE(nullptr, aPlusOne.get());
ASSERT_EQ(a->value + 1, aPlusOne->value);
}
namespace { // Anonymous namespace
bool fdsAreEquivalent(int a, int b) {
struct stat statA {};
struct stat statB {};
if (fstat(a, &statA) != 0) return false;
if (fstat(b, &statB) != 0) return false;
return (statA.st_dev == statB.st_dev) && (statA.st_ino == statB.st_ino);
}
} // Anonymous namespace
TEST_F(SafeInterfaceTest, TestIncrementNativeHandle) {
// Create an fd we can use to send and receive from the remote process
base::unique_fd eventFd{eventfd(0 /*initval*/, 0 /*flags*/)};
ASSERT_NE(-1, eventFd);
// Determine the maximum number of fds this process can have open
struct rlimit limit {};
ASSERT_EQ(0, getrlimit(RLIMIT_NOFILE, &limit));
uint32_t maxFds = static_cast<uint32_t>(limit.rlim_cur);
// Perform this test enough times to rule out fd leaks
for (uint32_t iter = 0; iter < (2 * maxFds); ++iter) {
native_handle* handle = native_handle_create(1 /*numFds*/, 1 /*numInts*/);
ASSERT_NE(nullptr, handle);
handle->data[0] = dup(eventFd.get());
handle->data[1] = 1;
// This cannot fail, as it is just the sp<NativeHandle> taking responsibility for closing
// the native_handle when it goes out of scope
sp<NativeHandle> a = NativeHandle::create(handle, true);
sp<NativeHandle> aPlusOne;
status_t result = mSafeInterfaceTest->increment(a, &aPlusOne);
ASSERT_EQ(NO_ERROR, result);
ASSERT_TRUE(fdsAreEquivalent(a->handle()->data[0], aPlusOne->handle()->data[0]));
ASSERT_EQ(a->handle()->data[1] + 1, aPlusOne->handle()->data[1]);
}
}
TEST_F(SafeInterfaceTest, TestIncrementNoCopyNoMove) {
const NoCopyNoMove a{1};
NoCopyNoMove aPlusOne{0};
status_t result = mSafeInterfaceTest->increment(a, &aPlusOne);
ASSERT_EQ(NO_ERROR, result);
ASSERT_EQ(a.getValue() + 1, aPlusOne.getValue());
}
TEST_F(SafeInterfaceTest, TestIncremementParcelableVector) {
const std::vector<TestParcelable> a{TestParcelable{1}, TestParcelable{2}};
std::vector<TestParcelable> aPlusOne;
status_t result = mSafeInterfaceTest->increment(a, &aPlusOne);
ASSERT_EQ(a.size(), aPlusOne.size());
for (size_t i = 0; i < a.size(); ++i) {
ASSERT_EQ(a[i].getValue() + 1, aPlusOne[i].getValue());
}
}
TEST_F(SafeInterfaceTest, TestToUpper) {
const String8 str{"Hello, world!"};
String8 upperStr;
status_t result = mSafeInterfaceTest->toUpper(str, &upperStr);
ASSERT_EQ(NO_ERROR, result);
ASSERT_TRUE(upperStr == String8{"HELLO, WORLD!"});
}
TEST_F(SafeInterfaceTest, TestCallMeBack) {
class CallbackReceiver : public BnCallback {
public:
void onCallback(int32_t aPlusOne) override {
ALOG(LOG_INFO, "CallbackReceiver", "%s", __PRETTY_FUNCTION__);
std::unique_lock<decltype(mMutex)> lock(mMutex);
mValue = aPlusOne;
mCondition.notify_one();
}
std::optional<int32_t> waitForCallback() {
std::unique_lock<decltype(mMutex)> lock(mMutex);
bool success =
mCondition.wait_for(lock, 100ms, [&]() { return static_cast<bool>(mValue); });
return success ? mValue : std::nullopt;
}
private:
std::mutex mMutex;
std::condition_variable mCondition;
std::optional<int32_t> mValue;
};
sp<CallbackReceiver> receiver = new CallbackReceiver;
const int32_t a = 1;
mSafeInterfaceTest->callMeBack(receiver, a);
auto result = receiver->waitForCallback();
ASSERT_TRUE(result);
ASSERT_EQ(a + 1, *result);
}
TEST_F(SafeInterfaceTest, TestIncrementInt32) {
const int32_t a = 1;
int32_t aPlusOne = 0;
status_t result = mSafeInterfaceTest->increment(a, &aPlusOne);
ASSERT_EQ(NO_ERROR, result);
ASSERT_EQ(a + 1, aPlusOne);
}
TEST_F(SafeInterfaceTest, TestIncrementUint32) {
const uint32_t a = 1;
uint32_t aPlusOne = 0;
status_t result = mSafeInterfaceTest->increment(a, &aPlusOne);
ASSERT_EQ(NO_ERROR, result);
ASSERT_EQ(a + 1, aPlusOne);
}
TEST_F(SafeInterfaceTest, TestIncrementInt64) {
const int64_t a = 1;
int64_t aPlusOne = 0;
status_t result = mSafeInterfaceTest->increment(a, &aPlusOne);
ASSERT_EQ(NO_ERROR, result);
ASSERT_EQ(a + 1, aPlusOne);
}
TEST_F(SafeInterfaceTest, TestIncrementUint64) {
const uint64_t a = 1;
uint64_t aPlusOne = 0;
status_t result = mSafeInterfaceTest->increment(a, &aPlusOne);
ASSERT_EQ(NO_ERROR, result);
ASSERT_EQ(a + 1, aPlusOne);
}
TEST_F(SafeInterfaceTest, TestIncrementTwo) {
const int32_t a = 1;
int32_t aPlusOne = 0;
const int32_t b = 2;
int32_t bPlusOne = 0;
status_t result = mSafeInterfaceTest->increment(1, &aPlusOne, 2, &bPlusOne);
ASSERT_EQ(NO_ERROR, result);
ASSERT_EQ(a + 1, aPlusOne);
ASSERT_EQ(b + 1, bPlusOne);
}
} // namespace tests
} // namespace android

View file

@ -0,0 +1,176 @@
/*
* Copyright (C) 2016 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 <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <limits>
#include <cstddef>
#include "android-base/file.h"
#include "android-base/test_utils.h"
#include <gtest/gtest.h>
#include <binder/Parcel.h>
#include <binder/TextOutput.h>
#include <binder/Debug.h>
static void CheckMessage(const CapturedStderr& cap,
const char* expected,
bool singleline) {
std::string output;
ASSERT_EQ(0, lseek(cap.fd(), 0, SEEK_SET));
android::base::ReadFdToString(cap.fd(), &output);
if (singleline)
output.erase(std::remove(output.begin(), output.end(), '\n'));
ASSERT_STREQ(output.c_str(), expected);
}
#define CHECK_LOG_(input, expect, singleline) \
{ \
CapturedStderr cap; \
android::aerr << input << android::endl; \
CheckMessage(cap, expect, singleline); \
} \
#define CHECK_VAL_(val, singleline) \
{ \
std::stringstream ss; \
ss << val; \
std::string s = ss.str(); \
CHECK_LOG_(val, s.c_str(), singleline); \
} \
#define CHECK_LOG(input, expect) CHECK_LOG_(input, expect, true)
#define CHECK_VAL(val) CHECK_VAL_(val, true)
TEST(TextOutput, HandlesStdEndl) {
CapturedStderr cap;
android::aerr << "foobar" << std::endl;
std::string output;
ASSERT_EQ(0, lseek(cap.fd(), 0, SEEK_SET));
android::base::ReadFdToString(cap.fd(), &output);
ASSERT_STREQ(output.c_str(), "foobar\n");
}
TEST(TextOutput, HandlesCEndl) {
CapturedStderr cap;
android::aerr << "foobar" << "\n";
std::string output;
ASSERT_EQ(0, lseek(cap.fd(), 0, SEEK_SET));
android::base::ReadFdToString(cap.fd(), &output);
ASSERT_STREQ(output.c_str(), "foobar\n");
}
TEST(TextOutput, HandlesAndroidEndl) {
CapturedStderr cap;
android::aerr << "foobar" << android::endl;
std::string output;
ASSERT_EQ(0, lseek(cap.fd(), 0, SEEK_SET));
android::base::ReadFdToString(cap.fd(), &output);
ASSERT_STREQ(output.c_str(), "foobar\n");
}
TEST(TextOutput, HandleEmptyString) {
CHECK_LOG("", "");
}
TEST(TextOutput, HandleString) {
CHECK_LOG("foobar", "foobar");
}
TEST(TextOutput, HandleNum) {
CHECK_LOG(12345, "12345");
}
TEST(TextOutput, HandleBool) {
CHECK_LOG(false, "false");
}
TEST(TextOutput, HandleChar) {
CHECK_LOG('T', "T");
}
TEST(TextOutput, HandleParcel) {
android::Parcel val;
CHECK_LOG(val, "Parcel(NULL)");
}
TEST(TextOutput, HandleHexDump) {
const char buf[16] = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15};
android::HexDump val(buf, sizeof(buf));
CHECK_LOG(val, "03020100 07060504 0b0a0908 0f0e0d0c '................'");
}
TEST(TextOutput, HandleHexDumpCustom) {
const char buf[4] = {0x11,0x22,0x33,0x44};
android::HexDump val(buf, sizeof(buf), 4);
CHECK_LOG(val, "11 22 33 44 '.\"3D'");
}
TEST(TextOutput, HandleTypeCode) {
android::TypeCode val(1234);
CHECK_LOG(val, "'\\x04\\xd2'");
}
TEST(TextOutput, HandleCookie) {
int32_t val = 321; //0x141
CHECK_LOG((void*)(long)val, "0x141");
}
TEST(TextOutput, HandleString8) {
android::String8 val("foobar");
CHECK_LOG(val, "foobar");
}
TEST(TextOutput, HandleString16) {
android::String16 val("foobar");
CHECK_LOG(val, "foobar");
}
template <typename T>
class TextTest : public testing::Test {};
typedef testing::Types<short, unsigned short,
int, unsigned int,
long, unsigned long,
long long, unsigned long long,
float, double, long double> TestTypes;
TYPED_TEST_CASE(TextTest, TestTypes);
TYPED_TEST(TextTest, TextMax)
{
TypeParam max = std::numeric_limits<TypeParam>::max();
CHECK_VAL(max);
}
TYPED_TEST(TextTest, TestMin)
{
TypeParam min = std::numeric_limits<TypeParam>::min();
CHECK_VAL(min);
}
TYPED_TEST(TextTest, TestDenom)
{
TypeParam min = std::numeric_limits<TypeParam>::denorm_min();
CHECK_VAL(min);
}
TYPED_TEST(TextTest, TestEpsilon)
{
TypeParam eps = std::numeric_limits<TypeParam>::epsilon();
CHECK_VAL(eps);
}

View file

@ -0,0 +1,400 @@
#include <binder/Binder.h>
#include <binder/IBinder.h>
#include <binder/IPCThreadState.h>
#include <binder/IServiceManager.h>
#include <string>
#include <cstring>
#include <cstdlib>
#include <cstdio>
#include <iostream>
#include <vector>
#include <tuple>
#include <unistd.h>
#include <sys/wait.h>
using namespace std;
using namespace android;
enum BinderWorkerServiceCode {
BINDER_NOP = IBinder::FIRST_CALL_TRANSACTION,
};
#define ASSERT_TRUE(cond) \
do { \
if (!(cond)) {\
cerr << __func__ << ":" << __LINE__ << " condition:" << #cond << " failed\n" << endl; \
exit(EXIT_FAILURE); \
} \
} while (0)
class BinderWorkerService : public BBinder
{
public:
BinderWorkerService() {}
~BinderWorkerService() {}
virtual status_t onTransact(uint32_t code,
const Parcel& data, Parcel* reply,
uint32_t flags = 0) {
(void)flags;
(void)data;
(void)reply;
switch (code) {
case BINDER_NOP:
return NO_ERROR;
default:
return UNKNOWN_TRANSACTION;
};
}
};
class Pipe {
int m_readFd;
int m_writeFd;
Pipe(int readFd, int writeFd) : m_readFd{readFd}, m_writeFd{writeFd} {}
Pipe(const Pipe &) = delete;
Pipe& operator=(const Pipe &) = delete;
Pipe& operator=(const Pipe &&) = delete;
public:
Pipe(Pipe&& rval) noexcept {
m_readFd = rval.m_readFd;
m_writeFd = rval.m_writeFd;
rval.m_readFd = 0;
rval.m_writeFd = 0;
}
~Pipe() {
if (m_readFd)
close(m_readFd);
if (m_writeFd)
close(m_writeFd);
}
void signal() {
bool val = true;
int error = write(m_writeFd, &val, sizeof(val));
ASSERT_TRUE(error >= 0);
};
void wait() {
bool val = false;
int error = read(m_readFd, &val, sizeof(val));
ASSERT_TRUE(error >= 0);
}
template <typename T> void send(const T& v) {
int error = write(m_writeFd, &v, sizeof(T));
ASSERT_TRUE(error >= 0);
}
template <typename T> void recv(T& v) {
int error = read(m_readFd, &v, sizeof(T));
ASSERT_TRUE(error >= 0);
}
static tuple<Pipe, Pipe> createPipePair() {
int a[2];
int b[2];
int error1 = pipe(a);
int error2 = pipe(b);
ASSERT_TRUE(error1 >= 0);
ASSERT_TRUE(error2 >= 0);
return make_tuple(Pipe(a[0], b[1]), Pipe(b[0], a[1]));
}
};
static const uint32_t num_buckets = 128;
static uint64_t max_time_bucket = 50ull * 1000000;
static uint64_t time_per_bucket = max_time_bucket / num_buckets;
struct ProcResults {
uint64_t m_worst = 0;
uint32_t m_buckets[num_buckets] = {0};
uint64_t m_transactions = 0;
uint64_t m_long_transactions = 0;
uint64_t m_total_time = 0;
uint64_t m_best = max_time_bucket;
void add_time(uint64_t time) {
if (time > max_time_bucket) {
m_long_transactions++;
}
m_buckets[min(time, max_time_bucket-1) / time_per_bucket] += 1;
m_best = min(time, m_best);
m_worst = max(time, m_worst);
m_transactions += 1;
m_total_time += time;
}
static ProcResults combine(const ProcResults& a, const ProcResults& b) {
ProcResults ret;
for (int i = 0; i < num_buckets; i++) {
ret.m_buckets[i] = a.m_buckets[i] + b.m_buckets[i];
}
ret.m_worst = max(a.m_worst, b.m_worst);
ret.m_best = min(a.m_best, b.m_best);
ret.m_transactions = a.m_transactions + b.m_transactions;
ret.m_long_transactions = a.m_long_transactions + b.m_long_transactions;
ret.m_total_time = a.m_total_time + b.m_total_time;
return ret;
}
void dump() {
if (m_long_transactions > 0) {
cout << (double)m_long_transactions / m_transactions << "% of transactions took longer "
"than estimated max latency. Consider setting -m to be higher than "
<< m_worst / 1000 << " microseconds" << endl;
}
double best = (double)m_best / 1.0E6;
double worst = (double)m_worst / 1.0E6;
double average = (double)m_total_time / m_transactions / 1.0E6;
cout << "average:" << average << "ms worst:" << worst << "ms best:" << best << "ms" << endl;
uint64_t cur_total = 0;
float time_per_bucket_ms = time_per_bucket / 1.0E6;
for (int i = 0; i < num_buckets; i++) {
float cur_time = time_per_bucket_ms * i + 0.5f * time_per_bucket_ms;
if ((cur_total < 0.5f * m_transactions) && (cur_total + m_buckets[i] >= 0.5f * m_transactions)) {
cout << "50%: " << cur_time << " ";
}
if ((cur_total < 0.9f * m_transactions) && (cur_total + m_buckets[i] >= 0.9f * m_transactions)) {
cout << "90%: " << cur_time << " ";
}
if ((cur_total < 0.95f * m_transactions) && (cur_total + m_buckets[i] >= 0.95f * m_transactions)) {
cout << "95%: " << cur_time << " ";
}
if ((cur_total < 0.99f * m_transactions) && (cur_total + m_buckets[i] >= 0.99f * m_transactions)) {
cout << "99%: " << cur_time << " ";
}
cur_total += m_buckets[i];
}
cout << endl;
}
};
String16 generateServiceName(int num)
{
char num_str[32];
snprintf(num_str, sizeof(num_str), "%d", num);
String16 serviceName = String16("binderWorker") + String16(num_str);
return serviceName;
}
void worker_fx(int num,
int worker_count,
int iterations,
int payload_size,
bool cs_pair,
Pipe p)
{
// Create BinderWorkerService and for go.
ProcessState::self()->startThreadPool();
sp<IServiceManager> serviceMgr = defaultServiceManager();
sp<BinderWorkerService> service = new BinderWorkerService;
serviceMgr->addService(generateServiceName(num), service);
srand(num);
p.signal();
p.wait();
// If client/server pairs, then half the workers are
// servers and half are clients
int server_count = cs_pair ? worker_count / 2 : worker_count;
// Get references to other binder services.
cout << "Created BinderWorker" << num << endl;
(void)worker_count;
vector<sp<IBinder> > workers;
for (int i = 0; i < server_count; i++) {
if (num == i)
continue;
workers.push_back(serviceMgr->getService(generateServiceName(i)));
}
// Run the benchmark if client
ProcResults results;
chrono::time_point<chrono::high_resolution_clock> start, end;
for (int i = 0; (!cs_pair || num >= server_count) && i < iterations; i++) {
Parcel data, reply;
int target = cs_pair ? num % server_count : rand() % workers.size();
int sz = payload_size;
while (sz > sizeof(uint32_t)) {
data.writeInt32(0);
sz -= sizeof(uint32_t);
}
start = chrono::high_resolution_clock::now();
status_t ret = workers[target]->transact(BINDER_NOP, data, &reply);
end = chrono::high_resolution_clock::now();
uint64_t cur_time = uint64_t(chrono::duration_cast<chrono::nanoseconds>(end - start).count());
results.add_time(cur_time);
if (ret != NO_ERROR) {
cout << "thread " << num << " failed " << ret << "i : " << i << endl;
exit(EXIT_FAILURE);
}
}
// Signal completion to master and wait.
p.signal();
p.wait();
// Send results to master and wait for go to exit.
p.send(results);
p.wait();
exit(EXIT_SUCCESS);
}
Pipe make_worker(int num, int iterations, int worker_count, int payload_size, bool cs_pair)
{
auto pipe_pair = Pipe::createPipePair();
pid_t pid = fork();
if (pid) {
/* parent */
return move(get<0>(pipe_pair));
} else {
/* child */
worker_fx(num, worker_count, iterations, payload_size, cs_pair, move(get<1>(pipe_pair)));
/* never get here */
return move(get<0>(pipe_pair));
}
}
void wait_all(vector<Pipe>& v)
{
for (int i = 0; i < v.size(); i++) {
v[i].wait();
}
}
void signal_all(vector<Pipe>& v)
{
for (int i = 0; i < v.size(); i++) {
v[i].signal();
}
}
void run_main(int iterations,
int workers,
int payload_size,
int cs_pair,
bool training_round=false)
{
vector<Pipe> pipes;
// Create all the workers and wait for them to spawn.
for (int i = 0; i < workers; i++) {
pipes.push_back(make_worker(i, iterations, workers, payload_size, cs_pair));
}
wait_all(pipes);
// Run the workers and wait for completion.
chrono::time_point<chrono::high_resolution_clock> start, end;
cout << "waiting for workers to complete" << endl;
start = chrono::high_resolution_clock::now();
signal_all(pipes);
wait_all(pipes);
end = chrono::high_resolution_clock::now();
// Calculate overall throughput.
double iterations_per_sec = double(iterations * workers) / (chrono::duration_cast<chrono::nanoseconds>(end - start).count() / 1.0E9);
cout << "iterations per sec: " << iterations_per_sec << endl;
// Collect all results from the workers.
cout << "collecting results" << endl;
signal_all(pipes);
ProcResults tot_results;
for (int i = 0; i < workers; i++) {
ProcResults tmp_results;
pipes[i].recv(tmp_results);
tot_results = ProcResults::combine(tot_results, tmp_results);
}
// Kill all the workers.
cout << "killing workers" << endl;
signal_all(pipes);
for (int i = 0; i < workers; i++) {
int status;
wait(&status);
if (status != 0) {
cout << "nonzero child status" << status << endl;
}
}
if (training_round) {
// sets max_time_bucket to 2 * m_worst from the training round.
// Also needs to adjust time_per_bucket accordingly.
max_time_bucket = 2 * tot_results.m_worst;
time_per_bucket = max_time_bucket / num_buckets;
cout << "Max latency during training: " << tot_results.m_worst / 1.0E6 << "ms" << endl;
} else {
tot_results.dump();
}
}
int main(int argc, char *argv[])
{
int workers = 2;
int iterations = 10000;
int payload_size = 0;
bool cs_pair = false;
bool training_round = false;
(void)argc;
(void)argv;
// Parse arguments.
for (int i = 1; i < argc; i++) {
if (string(argv[i]) == "--help") {
cout << "Usage: binderThroughputTest [OPTIONS]" << endl;
cout << "\t-i N : Specify number of iterations." << endl;
cout << "\t-m N : Specify expected max latency in microseconds." << endl;
cout << "\t-p : Split workers into client/server pairs." << endl;
cout << "\t-s N : Specify payload size." << endl;
cout << "\t-t N : Run training round." << endl;
cout << "\t-w N : Specify total number of workers." << endl;
return 0;
}
if (string(argv[i]) == "-w") {
workers = atoi(argv[i+1]);
i++;
continue;
}
if (string(argv[i]) == "-i") {
iterations = atoi(argv[i+1]);
i++;
continue;
}
if (string(argv[i]) == "-s") {
payload_size = atoi(argv[i+1]);
i++;
}
if (string(argv[i]) == "-p") {
// client/server pairs instead of spreading
// requests to all workers. If true, half
// the workers become clients and half servers
cs_pair = true;
}
if (string(argv[i]) == "-t") {
// Run one training round before actually collecting data
// to get an approximation of max latency.
training_round = true;
}
if (string(argv[i]) == "-m") {
// Caller specified the max latency in microseconds.
// No need to run training round in this case.
if (atoi(argv[i+1]) > 0) {
max_time_bucket = strtoull(argv[i+1], (char **)NULL, 10) * 1000;
i++;
} else {
cout << "Max latency -m must be positive." << endl;
exit(EXIT_FAILURE);
}
}
}
if (training_round) {
cout << "Start training round" << endl;
run_main(iterations, workers, payload_size, cs_pair, training_round=true);
cout << "Completed training round" << endl << endl;
}
run_main(iterations, workers, payload_size, cs_pair);
return 0;
}

View file

@ -0,0 +1,111 @@
/*
* Copyright (C) 2016 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 <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <limits>
#include <cstddef>
#include <vector>
#include "android-base/file.h"
#include "android-base/test_utils.h"
#include <gtest/gtest.h>
#include <binder/Parcel.h>
#include <binder/Value.h>
#include <binder/Debug.h>
using ::android::binder::Value;
using ::android::os::PersistableBundle;
using ::android::String16;
using ::std::vector;
#define VALUE_TYPE_TEST(T, TYPENAME, VAL) \
TEST(ValueType, Handles ## TYPENAME) { \
T x = VAL; \
T y = T(); \
Value value = VAL; \
ASSERT_FALSE(value.empty()); \
ASSERT_TRUE(value.is ## TYPENAME ()); \
ASSERT_TRUE(value.get ## TYPENAME (&y)); \
ASSERT_EQ(x, y); \
ASSERT_EQ(value, Value(y)); \
value.put ## TYPENAME (x); \
ASSERT_EQ(value, Value(y)); \
value = Value(); \
ASSERT_TRUE(value.empty()); \
ASSERT_NE(value, Value(y)); \
value = y; \
ASSERT_EQ(value, Value(x)); \
}
#define VALUE_TYPE_VECTOR_TEST(T, TYPENAME, VAL) \
TEST(ValueType, Handles ## TYPENAME ## Vector) { \
vector<T> x; \
vector<T> y; \
x.push_back(VAL); \
x.push_back(T()); \
Value value(x); \
ASSERT_FALSE(value.empty()); \
ASSERT_TRUE(value.is ## TYPENAME ## Vector()); \
ASSERT_TRUE(value.get ## TYPENAME ## Vector(&y)); \
ASSERT_EQ(x, y); \
ASSERT_EQ(value, Value(y)); \
value.put ## TYPENAME ## Vector(x); \
ASSERT_EQ(value, Value(y)); \
value = Value(); \
ASSERT_TRUE(value.empty()); \
ASSERT_NE(value, Value(y)); \
value = y; \
ASSERT_EQ(value, Value(x)); \
}
VALUE_TYPE_TEST(bool, Boolean, true)
VALUE_TYPE_TEST(int32_t, Int, 31337)
VALUE_TYPE_TEST(int64_t, Long, 13370133701337l)
VALUE_TYPE_TEST(double, Double, 3.14159265358979323846)
VALUE_TYPE_TEST(String16, String, String16("Lovely"))
VALUE_TYPE_VECTOR_TEST(bool, Boolean, true)
VALUE_TYPE_VECTOR_TEST(int32_t, Int, 31337)
VALUE_TYPE_VECTOR_TEST(int64_t, Long, 13370133701337l)
VALUE_TYPE_VECTOR_TEST(double, Double, 3.14159265358979323846)
VALUE_TYPE_VECTOR_TEST(String16, String, String16("Lovely"))
VALUE_TYPE_TEST(PersistableBundle, PersistableBundle, PersistableBundle())
TEST(ValueType, HandlesClear) {
Value value;
ASSERT_TRUE(value.empty());
value.putInt(31337);
ASSERT_FALSE(value.empty());
value.clear();
ASSERT_TRUE(value.empty());
}
TEST(ValueType, HandlesSwap) {
Value value_a, value_b;
int32_t int_x;
value_a.putInt(31337);
ASSERT_FALSE(value_a.empty());
ASSERT_TRUE(value_b.empty());
value_a.swap(value_b);
ASSERT_FALSE(value_b.empty());
ASSERT_TRUE(value_a.empty());
ASSERT_TRUE(value_b.getInt(&int_x));
ASSERT_EQ(31337, int_x);
}

View file

@ -0,0 +1,502 @@
#include <binder/Binder.h>
#include <binder/IBinder.h>
#include <binder/IPCThreadState.h>
#include <binder/IServiceManager.h>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <string>
#include <iomanip>
#include <iostream>
#include <tuple>
#include <vector>
#include <pthread.h>
#include <sys/wait.h>
#include <unistd.h>
#include <fstream>
using namespace std;
using namespace android;
enum BinderWorkerServiceCode {
BINDER_NOP = IBinder::FIRST_CALL_TRANSACTION,
};
#define ASSERT(cond) \
do { \
if (!(cond)) { \
cerr << __func__ << ":" << __LINE__ << " condition:" << #cond \
<< " failed\n" \
<< endl; \
exit(EXIT_FAILURE); \
} \
} while (0)
vector<sp<IBinder> > workers;
// the ratio that the service is synced on the same cpu beyond
// GOOD_SYNC_MIN is considered as good
#define GOOD_SYNC_MIN (0.6)
#define DUMP_PRESICION 2
string trace_path = "/sys/kernel/debug/tracing";
// the default value
int no_process = 2;
int iterations = 100;
int payload_size = 16;
int no_inherent = 0;
int no_sync = 0;
int verbose = 0;
int trace;
bool traceIsOn() {
fstream file;
file.open(trace_path + "/tracing_on", ios::in);
char on;
file >> on;
file.close();
return on == '1';
}
void traceStop() {
ofstream file;
file.open(trace_path + "/tracing_on", ios::out | ios::trunc);
file << '0' << endl;
file.close();
}
// the deadline latency that we are interested in
uint64_t deadline_us = 2500;
int thread_pri() {
struct sched_param param;
int policy;
ASSERT(!pthread_getschedparam(pthread_self(), &policy, &param));
return param.sched_priority;
}
void thread_dump(const char* prefix) {
struct sched_param param;
int policy;
if (!verbose) return;
cout << "--------------------------------------------------" << endl;
cout << setw(12) << left << prefix << " pid: " << getpid()
<< " tid: " << gettid() << " cpu: " << sched_getcpu() << endl;
ASSERT(!pthread_getschedparam(pthread_self(), &policy, &param));
string s = (policy == SCHED_OTHER)
? "SCHED_OTHER"
: (policy == SCHED_FIFO)
? "SCHED_FIFO"
: (policy == SCHED_RR) ? "SCHED_RR" : "???";
cout << setw(12) << left << s << param.sched_priority << endl;
return;
}
class BinderWorkerService : public BBinder {
public:
BinderWorkerService() {
}
~BinderWorkerService() {
}
virtual status_t onTransact(uint32_t code, const Parcel& data, Parcel* reply,
uint32_t flags = 0) {
(void)flags;
(void)data;
(void)reply;
switch (code) {
// The transaction format is like
//
// data[in]: int32: caller priority
// int32: caller cpu
//
// reply[out]: int32: 1 if caller's priority != callee's priority
// int32: 1 if caller's cpu != callee's cpu
//
// note the caller cpu read here is not always correct
// there're still chances that the caller got switched out
// right after it read the cpu number and still before the transaction.
case BINDER_NOP: {
thread_dump("binder");
int priority = thread_pri();
int priority_caller = data.readInt32();
int h = 0, s = 0;
if (priority_caller != priority) {
h++;
if (verbose) {
cout << "err priority_caller:" << priority_caller
<< ", priority:" << priority << endl;
}
}
if (priority == sched_get_priority_max(SCHED_FIFO)) {
int cpu = sched_getcpu();
int cpu_caller = data.readInt32();
if (cpu != cpu_caller) {
s++;
}
}
reply->writeInt32(h);
reply->writeInt32(s);
return NO_ERROR;
}
default:
return UNKNOWN_TRANSACTION;
};
}
};
class Pipe {
int m_readFd;
int m_writeFd;
Pipe(int readFd, int writeFd) : m_readFd{readFd}, m_writeFd{writeFd} {
}
Pipe(const Pipe&) = delete;
Pipe& operator=(const Pipe&) = delete;
Pipe& operator=(const Pipe&&) = delete;
public:
Pipe(Pipe&& rval) noexcept {
m_readFd = rval.m_readFd;
m_writeFd = rval.m_writeFd;
rval.m_readFd = 0;
rval.m_writeFd = 0;
}
~Pipe() {
if (m_readFd) close(m_readFd);
if (m_writeFd) close(m_writeFd);
}
void signal() {
bool val = true;
int error = write(m_writeFd, &val, sizeof(val));
ASSERT(error >= 0);
};
void wait() {
bool val = false;
int error = read(m_readFd, &val, sizeof(val));
ASSERT(error >= 0);
}
template <typename T>
void send(const T& v) {
int error = write(m_writeFd, &v, sizeof(T));
ASSERT(error >= 0);
}
template <typename T>
void recv(T& v) {
int error = read(m_readFd, &v, sizeof(T));
ASSERT(error >= 0);
}
static tuple<Pipe, Pipe> createPipePair() {
int a[2];
int b[2];
int error1 = pipe(a);
int error2 = pipe(b);
ASSERT(error1 >= 0);
ASSERT(error2 >= 0);
return make_tuple(Pipe(a[0], b[1]), Pipe(b[0], a[1]));
}
};
typedef chrono::time_point<chrono::high_resolution_clock> Tick;
static inline Tick tickNow() {
return chrono::high_resolution_clock::now();
}
static inline uint64_t tickNano(Tick& sta, Tick& end) {
return uint64_t(chrono::duration_cast<chrono::nanoseconds>(end - sta).count());
}
struct Results {
uint64_t m_best = 0xffffffffffffffffULL;
uint64_t m_worst = 0;
uint64_t m_transactions = 0;
uint64_t m_total_time = 0;
uint64_t m_miss = 0;
bool tracing;
Results(bool _tracing) : tracing(_tracing) {
}
inline bool miss_deadline(uint64_t nano) {
return nano > deadline_us * 1000;
}
void add_time(uint64_t nano) {
m_best = min(nano, m_best);
m_worst = max(nano, m_worst);
m_transactions += 1;
m_total_time += nano;
if (miss_deadline(nano)) m_miss++;
if (miss_deadline(nano) && tracing) {
// There might be multiple process pair running the test concurrently
// each may execute following statements and only the first one actually
// stop the trace and any traceStop() afterthen has no effect.
traceStop();
cout << endl;
cout << "deadline triggered: halt & stop trace" << endl;
cout << "log:" + trace_path + "/trace" << endl;
cout << endl;
exit(1);
}
}
void dump() {
double best = (double)m_best / 1.0E6;
double worst = (double)m_worst / 1.0E6;
double average = (double)m_total_time / m_transactions / 1.0E6;
// FIXME: libjson?
int W = DUMP_PRESICION + 2;
cout << setprecision(DUMP_PRESICION) << "{ \"avg\":" << setw(W) << left
<< average << ",\"wst\":" << setw(W) << left << worst
<< ",\"bst\":" << setw(W) << left << best << ",\"miss\":" << left
<< m_miss << ",\"meetR\":" << left << setprecision(DUMP_PRESICION + 3)
<< (1.0 - (double)m_miss / m_transactions) << "}";
}
};
String16 generateServiceName(int num) {
char num_str[32];
snprintf(num_str, sizeof(num_str), "%d", num);
String16 serviceName = String16("binderWorker") + String16(num_str);
return serviceName;
}
static void parcel_fill(Parcel& data, int sz, int priority, int cpu) {
ASSERT(sz >= (int)sizeof(uint32_t) * 2);
data.writeInt32(priority);
data.writeInt32(cpu);
sz -= sizeof(uint32_t);
while (sz > (int)sizeof(uint32_t)) {
data.writeInt32(0);
sz -= sizeof(uint32_t);
}
}
typedef struct {
void* result;
int target;
} thread_priv_t;
static void* thread_start(void* p) {
thread_priv_t* priv = (thread_priv_t*)p;
int target = priv->target;
Results* results_fifo = (Results*)priv->result;
Parcel data, reply;
Tick sta, end;
parcel_fill(data, payload_size, thread_pri(), sched_getcpu());
thread_dump("fifo-caller");
sta = tickNow();
status_t ret = workers[target]->transact(BINDER_NOP, data, &reply);
end = tickNow();
results_fifo->add_time(tickNano(sta, end));
no_inherent += reply.readInt32();
no_sync += reply.readInt32();
return 0;
}
// create a fifo thread to transact and wait it to finished
static void thread_transaction(int target, Results* results_fifo) {
thread_priv_t thread_priv;
void* dummy;
pthread_t thread;
pthread_attr_t attr;
struct sched_param param;
thread_priv.target = target;
thread_priv.result = results_fifo;
ASSERT(!pthread_attr_init(&attr));
ASSERT(!pthread_attr_setschedpolicy(&attr, SCHED_FIFO));
param.sched_priority = sched_get_priority_max(SCHED_FIFO);
ASSERT(!pthread_attr_setschedparam(&attr, &param));
ASSERT(!pthread_create(&thread, &attr, &thread_start, &thread_priv));
ASSERT(!pthread_join(thread, &dummy));
}
#define is_client(_num) ((_num) >= (no_process / 2))
void worker_fx(int num, int no_process, int iterations, int payload_size,
Pipe p) {
int dummy;
Results results_other(false), results_fifo(trace);
// Create BinderWorkerService and for go.
ProcessState::self()->startThreadPool();
sp<IServiceManager> serviceMgr = defaultServiceManager();
sp<BinderWorkerService> service = new BinderWorkerService;
serviceMgr->addService(generateServiceName(num), service);
// init done
p.signal();
// wait for kick-off
p.wait();
// If client/server pairs, then half the workers are
// servers and half are clients
int server_count = no_process / 2;
for (int i = 0; i < server_count; i++) {
// self service is in-process so just skip
if (num == i) continue;
workers.push_back(serviceMgr->getService(generateServiceName(i)));
}
// Client for each pair iterates here
// each iterations contains exatcly 2 transactions
for (int i = 0; is_client(num) && i < iterations; i++) {
Parcel data, reply;
Tick sta, end;
// the target is paired to make it easier to diagnose
int target = num % server_count;
// 1. transaction by fifo thread
thread_transaction(target, &results_fifo);
parcel_fill(data, payload_size, thread_pri(), sched_getcpu());
thread_dump("other-caller");
// 2. transaction by other thread
sta = tickNow();
ASSERT(NO_ERROR == workers[target]->transact(BINDER_NOP, data, &reply));
end = tickNow();
results_other.add_time(tickNano(sta, end));
no_inherent += reply.readInt32();
no_sync += reply.readInt32();
}
// Signal completion to master and wait.
p.signal();
p.wait();
p.send(&dummy);
// wait for kill
p.wait();
// Client for each pair dump here
if (is_client(num)) {
int no_trans = iterations * 2;
double sync_ratio = (1.0 - (double)no_sync / no_trans);
// FIXME: libjson?
cout << "\"P" << (num - server_count) << "\":{\"SYNC\":\""
<< ((sync_ratio > GOOD_SYNC_MIN) ? "GOOD" : "POOR") << "\","
<< "\"S\":" << (no_trans - no_sync) << ",\"I\":" << no_trans << ","
<< "\"R\":" << sync_ratio << "," << endl;
cout << " \"other_ms\":";
results_other.dump();
cout << "," << endl;
cout << " \"fifo_ms\": ";
results_fifo.dump();
cout << endl;
cout << "}," << endl;
}
exit(no_inherent);
}
Pipe make_process(int num, int iterations, int no_process, int payload_size) {
auto pipe_pair = Pipe::createPipePair();
pid_t pid = fork();
if (pid) {
// parent
return move(get<0>(pipe_pair));
} else {
// child
thread_dump(is_client(num) ? "client" : "server");
worker_fx(num, no_process, iterations, payload_size,
move(get<1>(pipe_pair)));
// never get here
return move(get<0>(pipe_pair));
}
}
void wait_all(vector<Pipe>& v) {
for (size_t i = 0; i < v.size(); i++) {
v[i].wait();
}
}
void signal_all(vector<Pipe>& v) {
for (size_t i = 0; i < v.size(); i++) {
v[i].signal();
}
}
// This test is modified from binderThroughputTest.cpp
int main(int argc, char** argv) {
for (int i = 1; i < argc; i++) {
if (string(argv[i]) == "-i") {
iterations = atoi(argv[i + 1]);
i++;
continue;
}
if (string(argv[i]) == "-pair") {
no_process = 2 * atoi(argv[i + 1]);
i++;
continue;
}
if (string(argv[i]) == "-deadline_us") {
deadline_us = atoi(argv[i + 1]);
i++;
continue;
}
if (string(argv[i]) == "-v") {
verbose = 1;
}
// The -trace argument is used like that:
//
// First start trace with atrace command as usual
// >atrace --async_start sched freq
//
// then use schd-dbg with -trace arguments
//./schd-dbg -trace -deadline_us 2500
//
// This makes schd-dbg to stop trace once it detects a transaction
// duration over the deadline. By writing '0' to
// /sys/kernel/debug/tracing and halt the process. The tracelog is
// then available on /sys/kernel/debug/trace
if (string(argv[i]) == "-trace") {
trace = 1;
}
}
if (trace && !traceIsOn()) {
cout << "trace is not running" << endl;
cout << "check " << trace_path + "/tracing_on" << endl;
cout << "use atrace --async_start first" << endl;
exit(-1);
}
vector<Pipe> pipes;
thread_dump("main");
// FIXME: libjson?
cout << "{" << endl;
cout << "\"cfg\":{\"pair\":" << (no_process / 2)
<< ",\"iterations\":" << iterations << ",\"deadline_us\":" << deadline_us
<< "}," << endl;
// the main process fork 2 processes for each pairs
// 1 server + 1 client
// each has a pipe to communicate with
for (int i = 0; i < no_process; i++) {
pipes.push_back(make_process(i, iterations, no_process, payload_size));
}
// wait for init done
wait_all(pipes);
// kick-off iterations
signal_all(pipes);
// wait for completion
wait_all(pipes);
// start to send result
signal_all(pipes);
for (int i = 0; i < no_process; i++) {
int status;
// kill
pipes[i].signal();
wait(&status);
// the exit status is number of transactions without priority inheritance
// detected in the child process
no_inherent += status;
}
// FIXME: libjson?
cout << "\"inheritance\": " << (no_inherent == 0 ? "\"PASS\"" : "\"FAIL\"")
<< endl;
cout << "}" << endl;
return -no_inherent;
}