M7350v1_en_gpl

This commit is contained in:
T
2024-09-09 08:52:07 +00:00
commit f9cc65cfda
65988 changed files with 26357421 additions and 0 deletions
+59
View File
@@ -0,0 +1,59 @@
# 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.
# we have the common sources, plus some device-specific stuff
sources := \
Binder.cpp \
BpBinder.cpp \
IInterface.cpp \
IMemory.cpp \
IPCThreadState.cpp \
IPermissionController.cpp \
IServiceManager.cpp \
MemoryDealer.cpp \
MemoryBase.cpp \
MemoryHeapBase.cpp \
MemoryHeapPmem.cpp \
Parcel.cpp \
Permission.cpp \
ProcessState.cpp \
Static.cpp
ifeq ($(TARGET_USES_ION),true)
sources += MemoryHeapIon.cpp
endif
LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
LOCAL_LDLIBS += -lpthread
LOCAL_MODULE := libbinder
ifeq ($(TARGET_USES_ION),true)
LOCAL_C_INCLUDES += $(TARGET_OUT_INTERMEDIATES)/KERNEL_OBJ/usr/include
LOCAL_ADDITIONAL_DEPENDENCIES += $(TARGET_OUT_INTERMEDIATES)/KERNEL_OBJ/usr/
endif
LOCAL_SHARED_LIBRARIES := liblog libcutils libutils
LOCAL_SRC_FILES := $(sources)
include $(BUILD_SHARED_LIBRARY)
include $(CLEAR_VARS)
LOCAL_LDLIBS += -lpthread
ifeq ($(TARGET_USES_ION),true)
LOCAL_C_INCLUDES += $(TARGET_OUT_INTERMEDIATES)/KERNEL_OBJ/usr/include
LOCAL_ADDITIONAL_DEPENDENCIES += $(TARGET_OUT_INTERMEDIATES)/KERNEL_OBJ/usr/
endif
LOCAL_MODULE := libbinder
LOCAL_SRC_FILES := $(sources)
include $(BUILD_STATIC_LIBRARY)
+256
View File
@@ -0,0 +1,256 @@
/*
* 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 <utils/Atomic.h>
#include <binder/BpBinder.h>
#include <binder/IInterface.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;
}
// ---------------------------------------------------------------------------
class BBinder::Extras
{
public:
Mutex mLock;
BpBinder::ObjectManager mObjects;
};
// ---------------------------------------------------------------------------
BBinder::BBinder()
: mExtras(NULL)
{
}
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;
LOGW("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;
if (!e) {
e = new Extras;
if (android_atomic_cmpxchg(0, reinterpret_cast<int32_t>(e),
reinterpret_cast<volatile int32_t*>(&mExtras)) != 0) {
delete e;
e = mExtras;
}
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;
if (!e) return NULL;
AutoMutex _l(e->mLock);
return e->mObjects.find(objectID);
}
void BBinder::detachObject(const void* objectID)
{
Extras* e = mExtras;
if (!e) return;
AutoMutex _l(e->mLock);
e->mObjects.detach(objectID);
}
BBinder* BBinder::localBinder()
{
return this;
}
BBinder::~BBinder()
{
if (mExtras) delete mExtras;
}
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);
}
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&kRemoteAcquired)) {
mRemote->decStrong(this);
}
mRefs->decWeak(this);
}
}
void BpRefBase::onFirstRef()
{
android_atomic_or(kRemoteAcquired, &mState);
}
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
+365
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 <utils/Log.h>
#include <stdio.h>
//#undef LOGV
//#define LOGV(...) 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) {
LOGE("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();
LOGV("Killing %d 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)
{
LOGV("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;
}
LOGV("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) {
const uint32_t allFlags = obit.flags|flags;
if (outRecipient != NULL) {
*outRecipient = mObituaries->itemAt(i).recipient;
}
mObituaries->removeAt(i);
if (mObituaries->size() == 0) {
LOGV("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()
{
LOGV("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) {
LOGV("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();
LOGV("Reporting death of proxy %p for %d recipients\n",
this, obits ? obits->size() : 0);
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();
LOGV("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);
LOGV("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()
{
LOGV("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()
{
LOGV("onFirstRef BpBinder %p handle %d\n", this, mHandle);
IPCThreadState* ipc = IPCThreadState::self();
if (ipc) ipc->incStrongHandle(mHandle);
}
void BpBinder::onLastStrongRef(const void* id)
{
LOGV("onLastStrongRef BpBinder %p handle %d\n", this, mHandle);
IF_LOGV() {
printRefs();
}
IPCThreadState* ipc = IPCThreadState::self();
if (ipc) ipc->decStrongHandle(mHandle);
}
bool BpBinder::onIncStrongAttempted(uint32_t flags, const void* id)
{
LOGV("onIncStrongAttempted BpBinder %p handle %d\n", this, mHandle);
IPCThreadState* ipc = IPCThreadState::self();
return ipc ? ipc->attemptIncStrongHandle(mHandle) == NO_ERROR : false;
}
// ---------------------------------------------------------------------------
}; // namespace android
+42
View File
@@ -0,0 +1,42 @@
/*
* 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/IInterface.h>
namespace android {
// ---------------------------------------------------------------------------
IInterface::IInterface()
: RefBase() {
}
IInterface::~IInterface() {
}
sp<IBinder> IInterface::asBinder()
{
return this ? onAsBinder() : NULL;
}
sp<const IBinder> IInterface::asBinder() const
{
return this ? const_cast<IInterface*>(this)->onAsBinder() : NULL;
}
// ---------------------------------------------------------------------------
}; // namespace android
+473
View File
@@ -0,0 +1,473 @@
/*
* 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 <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/mman.h>
#include <binder/IMemory.h>
#include <utils/KeyedVector.h>
#include <utils/threads.h>
#include <utils/Atomic.h>
#include <binder/Parcel.h>
#include <utils/CallStack.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;
};
void free_heap(const wp<IBinder>& binder);
Mutex mHeapCacheLock;
KeyedVector< wp<IBinder>, heap_info_t > mHeapCache;
};
static sp<HeapCache> gHeapCache = new HeapCache();
/******************************************************************************/
enum {
HEAP_ID = IBinder::FIRST_CALL_TRANSACTION
};
class BpMemoryHeap : public BpInterface<IMemoryHeap>
{
public:
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;
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 volatile int32_t mHeapId;
mutable void* mBase;
mutable size_t mSize;
mutable uint32_t mFlags;
mutable bool mRealHeap;
mutable Mutex mLock;
mutable int mIonFd;
};
// ----------------------------------------------------------------------------
enum {
GET_MEMORY = IBinder::FIRST_CALL_TRANSACTION
};
class BpMemory : public BpInterface<IMemory>
{
public:
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) {
mOffset = o;
mSize = s;
}
}
}
}
if (offset) *offset = mOffset;
if (size) *size = mSize;
return mHeap;
}
// ---------------------------------------------------------------------------
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( getMemory(&offset, &size)->asBinder() );
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), mRealHeap(false)
{
mIonFd = open("/dev/ion", O_RDONLY);
}
BpMemoryHeap::~BpMemoryHeap() {
if (mHeapId != -1) {
close(mHeapId);
if (mRealHeap) {
// by construction we're the last one
if (mBase != MAP_FAILED) {
sp<IBinder> binder = const_cast<BpMemoryHeap*>(this)->asBinder();
if (VERBOSE) {
LOGD("UNMAPPING binder=%p, heap=%p, size=%d, fd=%d",
binder.get(), this, mSize, mHeapId);
CallStack stack;
stack.update();
stack.dump("callstack");
}
munmap(mBase, mSize);
}
} else {
// remove from list only if it was mapped before
sp<IBinder> binder = const_cast<BpMemoryHeap*>(this)->asBinder();
free_heap(binder);
}
}
if (mIonFd > 0)
close(mIonFd);
}
void BpMemoryHeap::assertMapped() const
{
if (mHeapId == -1) {
sp<IBinder> binder(const_cast<BpMemoryHeap*>(this)->asBinder());
sp<BpMemoryHeap> heap(static_cast<BpMemoryHeap*>(find_heap(binder).get()));
heap->assertReallyMapped();
if (heap->mBase != MAP_FAILED) {
Mutex::Autolock _l(mLock);
if (mHeapId == -1) {
mBase = heap->mBase;
mSize = heap->mSize;
android_atomic_write( dup( heap->mHeapId ), &mHeapId );
}
} else {
// something went wrong
free_heap(binder);
}
}
}
void BpMemoryHeap::assertReallyMapped() const
{
if (mHeapId == -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();
LOGE_IF(err, "binder=%p transaction failed fd=%d, size=%ld, err=%d (%s)",
asBinder().get(), parcel_fd, size, err, strerror(-err));
int fd = dup( parcel_fd );
LOGE_IF(fd==-1, "cannot dup fd=%d, size=%ld, err=%d (%s)",
parcel_fd, size, err, strerror(errno));
int access = PROT_READ;
if (!(flags & READ_ONLY)) {
access |= PROT_WRITE;
}
Mutex::Autolock _l(mLock);
if (mHeapId == -1) {
mRealHeap = true;
mBase = mmap(0, size, access, MAP_SHARED, fd, 0);
if (mBase == MAP_FAILED) {
LOGE("cannot map BpMemoryHeap (binder=%p), size=%ld, fd=%d (%s)",
asBinder().get(), size, fd, strerror(errno));
close(fd);
} else {
mSize = size;
mFlags = flags;
android_atomic_write(fd, &mHeapId);
}
}
}
}
int BpMemoryHeap::getHeapID() const {
assertMapped();
return mHeapId;
}
void* BpMemoryHeap::getBase() const {
assertMapped();
return mBase;
}
size_t BpMemoryHeap::getSize() const {
assertMapped();
return mSize;
}
uint32_t BpMemoryHeap::getFlags() const {
assertMapped();
return mFlags;
}
// ---------------------------------------------------------------------------
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());
return NO_ERROR;
} break;
default:
return BBinder::onTransact(code, data, reply, flags);
}
}
/*****************************************************************************/
HeapCache::HeapCache()
: DeathRecipient()
{
}
HeapCache::~HeapCache()
{
}
void HeapCache::binderDied(const wp<IBinder>& binder)
{
//LOGD("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);
LOGD_IF(VERBOSE,
"found binder=%p, heap=%p, size=%d, fd=%d, count=%d",
binder.get(), info.heap.get(),
static_cast<BpMemoryHeap*>(info.heap.get())->mSize,
static_cast<BpMemoryHeap*>(info.heap.get())->mHeapId,
info.count);
android_atomic_inc(&info.count);
return info.heap;
} else {
heap_info_t info;
info.heap = interface_cast<IMemoryHeap>(binder);
info.count = 1;
//LOGD("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));
int32_t c = android_atomic_dec(&info.count);
if (c == 1) {
LOGD_IF(VERBOSE,
"removing binder=%p, heap=%p, size=%d, fd=%d, count=%d",
binder.unsafe_get(), info.heap.get(),
static_cast<BpMemoryHeap*>(info.heap.get())->mSize,
static_cast<BpMemoryHeap*>(info.heap.get())->mHeapId,
info.count);
rel = mHeapCache.valueAt(i).heap;
mHeapCache.removeItemsAt(i);
}
} else {
LOGE("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()));
LOGD("hey=%p, heap=%p, count=%d, (fd=%d, base=%p, size=%d)",
mHeapCache.keyAt(i).unsafe_get(),
info.heap.get(), info.count,
h->mHeapId, h->mBase, h->mSize);
}
}
// ---------------------------------------------------------------------------
}; // namespace android
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,78 @@
/*
* 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/Debug.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:
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;
}
};
IMPLEMENT_META_INTERFACE(PermissionController, "android.os.IPermissionController");
// ----------------------------------------------------------------------
status_t BnPermissionController::onTransact(
uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
{
//printf("PermissionController received: "); data.print();
switch(code) {
case CHECK_PERMISSION_TRANSACTION: {
CHECK_INTERFACE(IPermissionController, data, reply);
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;
default:
return BBinder::onTransact(code, data, reply, flags);
}
}
}; // namespace android
+228
View File
@@ -0,0 +1,228 @@
/*
* 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/Debug.h>
#include <utils/Log.h>
#include <binder/IPCThreadState.h>
#include <binder/Parcel.h>
#include <utils/String8.h>
#include <utils/SystemClock.h>
#include <private/binder/Static.h>
#include <unistd.h>
namespace android {
sp<IServiceManager> defaultServiceManager()
{
if (gDefaultServiceManager != NULL) return gDefaultServiceManager;
{
AutoMutex _l(gDefaultServiceManagerLock);
if (gDefaultServiceManager == NULL) {
gDefaultServiceManager = interface_cast<IServiceManager>(
ProcessState::self()->getContextObject(NULL));
}
}
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) {
LOGI("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 (pc->asBinder()->isBinderAlive()) {
LOGW("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();
LOGI("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:
BpServiceManager(const sp<IBinder>& impl)
: BpInterface<IServiceManager>(impl)
{
}
virtual sp<IBinder> getService(const String16& name) const
{
unsigned n;
for (n = 0; n < 5; n++){
sp<IBinder> svc = checkService(name);
if (svc != NULL) return svc;
LOGI("Waiting for service %s...\n", String8(name).string());
sleep(1);
}
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)
{
Parcel data, reply;
data.writeInterfaceToken(IServiceManager::getInterfaceDescriptor());
data.writeString16(name);
data.writeStrongBinder(service);
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");
// ----------------------------------------------------------------------
status_t BnServiceManager::onTransact(
uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
{
//printf("ServiceManager received: "); data.print();
switch(code) {
case GET_SERVICE_TRANSACTION: {
CHECK_INTERFACE(IServiceManager, data, reply);
String16 which = data.readString16();
sp<IBinder> b = const_cast<BnServiceManager*>(this)->getService(which);
reply->writeStrongBinder(b);
return NO_ERROR;
} break;
case CHECK_SERVICE_TRANSACTION: {
CHECK_INTERFACE(IServiceManager, data, reply);
String16 which = data.readString16();
sp<IBinder> b = const_cast<BnServiceManager*>(this)->checkService(which);
reply->writeStrongBinder(b);
return NO_ERROR;
} break;
case ADD_SERVICE_TRANSACTION: {
CHECK_INTERFACE(IServiceManager, data, reply);
String16 which = data.readString16();
sp<IBinder> b = data.readStrongBinder();
status_t err = addService(which, b);
reply->writeInt32(err);
return NO_ERROR;
} break;
case LIST_SERVICES_TRANSACTION: {
CHECK_INTERFACE(IServiceManager, data, reply);
Vector<String16> list = listServices();
const size_t N = list.size();
reply->writeInt32(N);
for (size_t i=0; i<N; i++) {
reply->writeString16(list[i]);
}
return NO_ERROR;
} break;
default:
return BBinder::onTransact(code, data, reply, flags);
}
}
}; // namespace android
+38
View File
@@ -0,0 +1,38 @@
#libbinder from Android.
LOCAL_SRC_FILES := \
Binder.cpp \
BpBinder.cpp \
IInterface.cpp \
IMemory.cpp \
IPCThreadState.cpp \
IPermissionController.cpp \
IServiceManager.cpp \
MemoryDealer.cpp \
MemoryBase.cpp \
MemoryHeapBase.cpp \
MemoryHeapPmem.cpp \
Parcel.cpp \
Permission.cpp \
ProcessState.cpp \
Static.cpp
LOCAL_LIBS += -lpthread -llog -lcutils -lutils
LOCAL_CFLAGS += -I./
#we should use autoconf later.
LOCAL_CFLAGS += -DHAVE_ENDIAN_H -DHAVE_PTHREADS -DHAVE_SYS_UIO_H -DHAVE_POSIX_FILEMAP
LIB_OBJECTS := $(LOCAL_SRC_FILES:.cpp=.o)
.PHONY: all
TARGET = libbinder.so
all:${TARGET}
%.o:%.cpp
${CC} -fPIC ${CFLAGS} ${LOCAL_CFLAGS} -c $< -o $@
${TARGET}:${LIB_OBJECTS}
${CC} -shared ${LDFLAGS} ${LOCAL_LIBS} ${LIB_OBJECTS} -o $@
+46
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
+464
View File
@@ -0,0 +1,464 @@
/*
* 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:
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;
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). */
mDealer->deallocate(freedOffset);
// 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);
LOGW_IF(err, "madvise(%p, %u, MADV_REMOVE) returned %s",
start_ptr, size, err<0 ? strerror(errno) : "Ok");
}
#endif
}
}
}
// ----------------------------------------------------------------------------
MemoryDealer::MemoryDealer(size_t size, const char* name)
: mHeap(new MemoryHeapBase(size, 0, 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;
}
// ----------------------------------------------------------------------------
// 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);
}
LOGE_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);
LOGD("%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: %08x | 0x%08X | 0x%08X | %s %s\n",
i, int(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
+190
View File
@@ -0,0 +1,190 @@
/*
* 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 <stdlib.h>
#include <stdint.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <cutils/log.h>
#include <cutils/ashmem.h>
#include <cutils/atomic.h>
#include <binder/MemoryHeapBase.h>
#if HAVE_ANDROID_OS
#include <linux/android_pmem.h>
#endif
namespace android {
// ---------------------------------------------------------------------------
MemoryHeapBase::MemoryHeapBase()
: mFD(-1), mSize(0), mBase(MAP_FAILED),
mDevice(NULL), mNeedUnmap(false)
{
}
MemoryHeapBase::MemoryHeapBase(size_t size, uint32_t flags, char const * name)
: mFD(-1), mSize(0), mBase(MAP_FAILED), mFlags(flags),
mDevice(0), mNeedUnmap(false)
{
const size_t pagesize = getpagesize();
size = ((size + pagesize-1) & ~(pagesize-1));
int fd = ashmem_create_region(name == NULL ? "MemoryHeapBase" : name, size);
LOGE_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)
{
int open_flags = O_RDWR;
if (flags & NO_CACHING)
open_flags |= O_SYNC;
int fd = open(device, open_flags);
LOGE_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)
{
const size_t pagesize = getpagesize();
size = ((size + pagesize-1) & ~(pagesize-1));
mapfd(dup(fd), 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
#if HAVE_ANDROID_OS
// first try the PMEM ioctl
pmem_region reg;
int err = ioctl(fd, PMEM_GET_TOTAL_SIZE, &reg);
if (err == 0)
size = reg.len;
#endif
if (size == 0) { // try fstat
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) {
int flags = (mFlags & MAP_LOCKED_MAP_POPULATE) ?
MAP_POPULATE|MAP_LOCKED : 0;
void* base = (uint8_t*)mmap(0, size,
PROT_READ|PROT_WRITE, MAP_SHARED|flags, fd, offset);
if (base == MAP_FAILED) {
LOGE("mmap(fd=%d, size=%u) failed (%s)",
fd, uint32_t(size), strerror(errno));
close(fd);
return -errno;
}
//LOGD("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;
return NO_ERROR;
}
MemoryHeapBase::~MemoryHeapBase()
{
dispose();
}
void MemoryHeapBase::dispose()
{
int fd = android_atomic_or(-1, &mFD);
if (fd >= 0) {
if (mNeedUnmap) {
//LOGD("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;
}
// ---------------------------------------------------------------------------
}; // namespace android
+145
View File
@@ -0,0 +1,145 @@
/*
* Copyright (C) 2008 The Android Open Source Project
* Copyright (c) 2011, The Linux Foundation. All rights reserved.
*
* 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 "MemoryHeapIon"
#include <stdlib.h>
#include <stdint.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <cutils/log.h>
#include <binder/MemoryHeapIon.h>
#include <binder/MemoryHeapBase.h>
#include <linux/ion.h>
namespace android {
MemoryHeapIon::MemoryHeapIon() : mIonDeviceFd(-1), mIonHandle(NULL)
{
}
MemoryHeapIon::MemoryHeapIon(const char* device, size_t size,
uint32_t flags, unsigned long memory_types)
: MemoryHeapBase()
{
int open_flags = O_RDWR;
if (flags & NO_CACHING)
open_flags |= O_DSYNC;
int fd = open(device, open_flags);
if (fd >= 0) {
const size_t pagesize = getpagesize();
size = ((size + pagesize-1) & ~(pagesize-1));
if (mapIonFd(fd, size, memory_types, flags) == NO_ERROR) {
MemoryHeapBase::setDevice(device);
}
}
}
status_t MemoryHeapIon::ionInit(int ionFd, void *base, int size, int flags,
const char* device, struct ion_handle *handle,
int ionMapFd) {
mIonDeviceFd = ionFd;
mIonHandle = handle;
MemoryHeapBase::init(ionMapFd, base, size, flags, device);
return NO_ERROR;
}
status_t MemoryHeapIon::mapIonFd(int fd, size_t size, unsigned long memory_type, int uflags)
{
/* If size is 0, just fail the mmap. There is no way to get the size
* with ion
*/
int map_fd;
struct ion_allocation_data data;
struct ion_fd_data fd_data;
struct ion_handle_data handle_data;
void *base = NULL;
data.len = size;
data.align = getpagesize();
data.flags = memory_type;
if (ioctl(fd, ION_IOC_ALLOC, &data) < 0) {
close(fd);
return -errno;
}
if ((uflags & DONT_MAP_LOCALLY) == 0) {
int flags = (uflags & MAP_LOCKED_MAP_POPULATE) ?
MAP_POPULATE|MAP_LOCKED : 0;
fd_data.handle = data.handle;
if (ioctl(fd, ION_IOC_MAP, &fd_data) < 0) {
handle_data.handle = data.handle;
ioctl(fd, ION_IOC_FREE, &handle_data);
close(fd);
return -errno;
}
base = (uint8_t*)mmap(0, size,
PROT_READ|PROT_WRITE, MAP_SHARED|flags, fd_data.fd, 0);
if (base == MAP_FAILED) {
LOGE("mmap(fd=%d, size=%u) failed (%s)",
fd, uint32_t(size), strerror(errno));
handle_data.handle = data.handle;
ioctl(fd, ION_IOC_FREE, &handle_data);
close(fd);
return -errno;
}
}
mIonHandle = data.handle;
mIonDeviceFd = fd;
/*
* Call this with NULL now and set device with set_device
* above for consistency sake with how MemoryHeapPmem works.
*/
MemoryHeapBase::init(fd_data.fd, base, size, uflags, NULL);
return NO_ERROR;
}
MemoryHeapIon::~MemoryHeapIon()
{
struct ion_handle_data data;
data.handle = mIonHandle;
/*
* Due to the way MemoryHeapBase is set up, munmap will never
* be called so we need to call it ourselves here.
*/
munmap(MemoryHeapBase::getBase(), MemoryHeapBase::getSize());
if (mIonDeviceFd > 0) {
ioctl(mIonDeviceFd, ION_IOC_FREE, &data);
close(mIonDeviceFd);
}
}
// ---------------------------------------------------------------------------
}; // namespace android
+248
View File
@@ -0,0 +1,248 @@
/*
* 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 "MemoryHeapPmem"
#include <stdlib.h>
#include <stdint.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <cutils/log.h>
#include <binder/MemoryHeapPmem.h>
#include <binder/MemoryHeapBase.h>
#if HAVE_ANDROID_OS
#include <linux/android_pmem.h>
#endif
namespace android {
// ---------------------------------------------------------------------------
MemoryHeapPmem::MemoryPmem::MemoryPmem(const sp<MemoryHeapPmem>& heap)
: BnMemory(), mClientHeap(heap)
{
}
MemoryHeapPmem::MemoryPmem::~MemoryPmem() {
if (mClientHeap != NULL) {
mClientHeap->remove(this);
}
}
// ---------------------------------------------------------------------------
class SubRegionMemory : public MemoryHeapPmem::MemoryPmem {
public:
SubRegionMemory(const sp<MemoryHeapPmem>& heap, ssize_t offset, size_t size);
virtual ~SubRegionMemory();
virtual sp<IMemoryHeap> getMemory(ssize_t* offset, size_t* size) const;
private:
friend class MemoryHeapPmem;
void revoke();
size_t mSize;
ssize_t mOffset;
};
SubRegionMemory::SubRegionMemory(const sp<MemoryHeapPmem>& heap,
ssize_t offset, size_t size)
: MemoryHeapPmem::MemoryPmem(heap), mSize(size), mOffset(offset)
{
#ifndef NDEBUG
void* const start_ptr = (void*)(intptr_t(getHeap()->base()) + offset);
memset(start_ptr, 0xda, size);
#endif
#if HAVE_ANDROID_OS
if (size > 0) {
const size_t pagesize = getpagesize();
size = (size + pagesize-1) & ~(pagesize-1);
int our_fd = heap->heapID();
struct pmem_region sub = { offset, size };
int err = ioctl(our_fd, PMEM_MAP, &sub);
LOGE_IF(err<0, "PMEM_MAP failed (%s), "
"mFD=%d, sub.offset=%lu, sub.size=%lu",
strerror(errno), our_fd, sub.offset, sub.len);
}
#endif
}
sp<IMemoryHeap> SubRegionMemory::getMemory(ssize_t* offset, size_t* size) const
{
if (offset) *offset = mOffset;
if (size) *size = mSize;
return getHeap();
}
SubRegionMemory::~SubRegionMemory()
{
revoke();
}
void SubRegionMemory::revoke()
{
// NOTE: revoke() doesn't need to be protected by a lock because it
// can only be called from MemoryHeapPmem::revoke(), which means
// that we can't be in ~SubRegionMemory(), or in ~SubRegionMemory(),
// which means MemoryHeapPmem::revoke() wouldn't have been able to
// promote() it.
#if HAVE_ANDROID_OS
if (mSize != 0) {
const sp<MemoryHeapPmem>& heap(getHeap());
int our_fd = heap->heapID();
struct pmem_region sub;
sub.offset = mOffset;
sub.len = mSize;
int err = ioctl(our_fd, PMEM_UNMAP, &sub);
LOGE_IF(err<0, "PMEM_UNMAP failed (%s), "
"mFD=%d, sub.offset=%lu, sub.size=%lu",
strerror(errno), our_fd, sub.offset, sub.len);
mSize = 0;
}
#endif
}
// ---------------------------------------------------------------------------
MemoryHeapPmem::MemoryHeapPmem(const sp<MemoryHeapBase>& pmemHeap,
uint32_t flags)
: MemoryHeapBase()
{
char const * const device = pmemHeap->getDevice();
#if HAVE_ANDROID_OS
if (device) {
int fd = open(device, O_RDWR | (flags & NO_CACHING ? O_SYNC : 0));
LOGE_IF(fd<0, "couldn't open %s (%s)", device, strerror(errno));
if (fd >= 0) {
int err = ioctl(fd, PMEM_CONNECT, pmemHeap->heapID());
if (err < 0) {
LOGE("PMEM_CONNECT failed (%s), mFD=%d, sub-fd=%d",
strerror(errno), fd, pmemHeap->heapID());
close(fd);
} else {
// everything went well...
mParentHeap = pmemHeap;
MemoryHeapBase::init(fd,
pmemHeap->getBase(),
pmemHeap->getSize(),
pmemHeap->getFlags() | flags,
device);
}
}
}
#else
mParentHeap = pmemHeap;
MemoryHeapBase::init(
dup(pmemHeap->heapID()),
pmemHeap->getBase(),
pmemHeap->getSize(),
pmemHeap->getFlags() | flags,
device);
#endif
}
MemoryHeapPmem::~MemoryHeapPmem()
{
}
sp<IMemory> MemoryHeapPmem::mapMemory(size_t offset, size_t size)
{
sp<MemoryPmem> memory = createMemory(offset, size);
if (memory != 0) {
Mutex::Autolock _l(mLock);
mAllocations.add(memory);
}
return memory;
}
sp<MemoryHeapPmem::MemoryPmem> MemoryHeapPmem::createMemory(
size_t offset, size_t size)
{
sp<SubRegionMemory> memory;
if (heapID() > 0)
memory = new SubRegionMemory(this, offset, size);
return memory;
}
status_t MemoryHeapPmem::slap()
{
#if HAVE_ANDROID_OS
size_t size = getSize();
const size_t pagesize = getpagesize();
size = (size + pagesize-1) & ~(pagesize-1);
int our_fd = getHeapID();
struct pmem_region sub = { 0, size };
int err = ioctl(our_fd, PMEM_MAP, &sub);
LOGE_IF(err<0, "PMEM_MAP failed (%s), "
"mFD=%d, sub.offset=%lu, sub.size=%lu",
strerror(errno), our_fd, sub.offset, sub.len);
return -errno;
#else
return NO_ERROR;
#endif
}
status_t MemoryHeapPmem::unslap()
{
#if HAVE_ANDROID_OS
size_t size = getSize();
const size_t pagesize = getpagesize();
size = (size + pagesize-1) & ~(pagesize-1);
int our_fd = getHeapID();
struct pmem_region sub = { 0, size };
int err = ioctl(our_fd, PMEM_UNMAP, &sub);
LOGE_IF(err<0, "PMEM_UNMAP failed (%s), "
"mFD=%d, sub.offset=%lu, sub.size=%lu",
strerror(errno), our_fd, sub.offset, sub.len);
return -errno;
#else
return NO_ERROR;
#endif
}
void MemoryHeapPmem::revoke()
{
SortedVector< wp<MemoryPmem> > allocations;
{ // scope for lock
Mutex::Autolock _l(mLock);
allocations = mAllocations;
}
ssize_t count = allocations.size();
for (ssize_t i=0 ; i<count ; i++) {
sp<MemoryPmem> memory(allocations[i].promote());
if (memory != 0)
memory->revoke();
}
}
void MemoryHeapPmem::remove(const wp<MemoryPmem>& memory)
{
Mutex::Autolock _l(mLock);
mAllocations.remove(memory);
}
// ---------------------------------------------------------------------------
}; // namespace android
+1450
View File
File diff suppressed because it is too large Load Diff
+88
View File
@@ -0,0 +1,88 @@
/*
* 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.
*/
#include <stdint.h>
#include <utils/Log.h>
#include <binder/IPCThreadState.h>
#include <binder/IServiceManager.h>
#include <binder/Permission.h>
namespace android {
// ---------------------------------------------------------------------------
Permission::Permission(char const* name)
: mPermissionName(name), mPid(getpid())
{
}
Permission::Permission(const String16& name)
: mPermissionName(name), mPid(getpid())
{
}
Permission::Permission(const Permission& rhs)
: mPermissionName(rhs.mPermissionName),
mGranted(rhs.mGranted),
mPid(rhs.mPid)
{
}
Permission::~Permission()
{
}
bool Permission::operator < (const Permission& rhs) const
{
return mPermissionName < rhs.mPermissionName;
}
bool Permission::checkCalling() const
{
IPCThreadState* ipcState = IPCThreadState::self();
pid_t pid = ipcState->getCallingPid();
uid_t uid = ipcState->getCallingUid();
return doCheckPermission(pid, uid);
}
bool Permission::check(pid_t pid, uid_t uid) const
{
return doCheckPermission(pid, uid);
}
bool Permission::doCheckPermission(pid_t pid, uid_t uid) const
{
if ((uid == 0) || (pid == mPid)) {
// root and ourselves is always okay
return true;
} else {
// see if we already granted this permission for this uid
Mutex::Autolock _l(mLock);
if (mGranted.indexOf(uid) >= 0)
return true;
}
bool granted = checkPermission(mPermissionName, pid, uid);
if (granted) {
Mutex::Autolock _l(mLock);
// no need to check again, the old item will be replaced if it is
// already there.
mGranted.add(uid);
}
return granted;
}
// ---------------------------------------------------------------------------
}; // namespace android
+398
View File
@@ -0,0 +1,398 @@
/*
* 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 <cutils/process_name.h>
#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>
#define BINDER_VM_SIZE ((1*1024*1024) - (4096 *2))
static bool gSingleProcess = false;
// ---------------------------------------------------------------------------
namespace android {
// Global variables
int mArgC;
const char* const* mArgV;
int mArgLen;
class PoolThread : public Thread
{
public:
PoolThread(bool isMain)
: mIsMain(isMain)
{
}
protected:
virtual bool threadLoop()
{
IPCThreadState::self()->joinThreadPool(mIsMain);
return false;
}
const bool mIsMain;
};
sp<ProcessState> ProcessState::self()
{
if (gProcess != NULL) return gProcess;
AutoMutex _l(gProcessMutex);
if (gProcess == NULL) gProcess = new ProcessState;
return gProcess;
}
void ProcessState::setSingleProcess(bool singleProcess)
{
gSingleProcess = singleProcess;
}
void ProcessState::setContextObject(const sp<IBinder>& object)
{
setContextObject(object, String16("default"));
}
sp<IBinder> ProcessState::getContextObject(const sp<IBinder>& caller)
{
if (supportsProcesses()) {
return getStrongProxyForHandle(0);
} else {
return getContextObject(String16("default"), caller);
}
}
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) {
LOGE("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;
}
bool ProcessState::supportsProcesses() const
{
return mDriverFD >= 0;
}
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;
if (mDriverFD >= 0) {
int dummy = 0;
#if defined(HAVE_ANDROID_OS)
status_t result = ioctl(mDriverFD, BINDER_SET_CONTEXT_MGR, &dummy);
#else
status_t result = INVALID_OPERATION;
#endif
if (result == 0) {
mManagesContexts = true;
} else if (result == -1) {
mBinderContextCheckFunc = NULL;
mBinderContextUserData = NULL;
LOGE("Binder ioctl to become context manager failed: %s\n", strerror(errno));
}
} else {
// If there is no driver, our only world is the local
// process so we can always become the context manager there.
mManagesContexts = true;
}
}
return mManagesContexts;
}
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)) {
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;
}
void ProcessState::setArgs(int argc, const char* const argv[])
{
mArgC = argc;
mArgV = (const char **)argv;
mArgLen = 0;
for (int i=0; i<argc; i++) {
mArgLen += strlen(argv[i]) + 1;
}
mArgLen--;
}
int ProcessState::getArgC() const
{
return mArgC;
}
const char* const* ProcessState::getArgV() const
{
return mArgV;
}
void ProcessState::setArgV0(const char* txt)
{
if (mArgV != NULL) {
strncpy((char*)mArgV[0], txt, mArgLen);
set_process_name(txt);
}
}
void ProcessState::spawnPooledThread(bool isMain)
{
if (mThreadPoolStarted) {
int32_t s = android_atomic_add(1, &mThreadPoolSeq);
char buf[32];
sprintf(buf, "Binder Thread #%d", s);
LOGV("Spawning new pooled thread, name=%s\n", buf);
sp<Thread> t = new PoolThread(isMain);
t->run(buf);
}
}
static int open_driver()
{
if (gSingleProcess) {
return -1;
}
int fd = open("/dev/binder", O_RDWR);
if (fd >= 0) {
fcntl(fd, F_SETFD, FD_CLOEXEC);
int vers;
#if defined(HAVE_ANDROID_OS)
status_t result = ioctl(fd, BINDER_VERSION, &vers);
#else
status_t result = -1;
errno = EPERM;
#endif
if (result == -1) {
LOGE("Binder ioctl to obtain version failed: %s", strerror(errno));
close(fd);
fd = -1;
}
if (result != 0 || vers != BINDER_CURRENT_PROTOCOL_VERSION) {
LOGE("Binder driver protocol does not match user space protocol!");
close(fd);
fd = -1;
}
#if defined(HAVE_ANDROID_OS)
size_t maxThreads = 15;
result = ioctl(fd, BINDER_SET_MAX_THREADS, &maxThreads);
if (result == -1) {
LOGE("Binder ioctl to set max threads failed: %s", strerror(errno));
}
#endif
} else {
LOGW("Opening '/dev/binder' failed: %s\n", strerror(errno));
}
return fd;
}
ProcessState::ProcessState()
: mDriverFD(open_driver())
, mVMStart(MAP_FAILED)
, mManagesContexts(false)
, mBinderContextCheckFunc(NULL)
, mBinderContextUserData(NULL)
, mThreadPoolStarted(false)
, mThreadPoolSeq(1)
{
if (mDriverFD >= 0) {
// XXX Ideally, there should be a specific define for whether we
// have mmap (or whether we could possibly have the kernel module
// availabla).
#if !defined(HAVE_WIN32_IPC)
// 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*
LOGE("Using /dev/binder failed: unable to mmap transaction memory.\n");
close(mDriverFD);
mDriverFD = -1;
}
#else
mDriverFD = -1;
#endif
}
if (mDriverFD < 0) {
// Need to run without the driver, starting our own thread pool.
}
}
ProcessState::~ProcessState()
{
}
}; // namespace android
+53
View File
@@ -0,0 +1,53 @@
/*
* 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/IPCThreadState.h>
#include <utils/Log.h>
namespace android {
// ------------ ProcessState.cpp
Mutex gProcessMutex;
sp<ProcessState> gProcess;
class LibUtilsIPCtStatics
{
public:
LibUtilsIPCtStatics()
{
}
~LibUtilsIPCtStatics()
{
IPCThreadState::shutdown();
}
};
static LibUtilsIPCtStatics gIPCStatics;
// ------------ ServiceManager.cpp
Mutex gDefaultServiceManagerLock;
sp<IServiceManager> gDefaultServiceManager;
sp<IPermissionController> gPermissionController;
} // namespace android
+103
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_BINDER_H
#define ANDROID_BINDER_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;
Extras* mExtras;
void* mReserved0;
};
// ---------------------------------------------------------------------------
class BpRefBase : public virtual RefBase
{
protected:
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;
volatile int32_t mState;
};
}; // namespace android
// ---------------------------------------------------------------------------
#endif // ANDROID_BINDER_H
@@ -0,0 +1,60 @@
/*
* 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() {
sp<IServiceManager> sm(defaultServiceManager());
return sm->addService(String16(SERVICE::getServiceName()), new SERVICE());
}
static void publishAndJoinThreadPool() {
sp<ProcessState> proc(ProcessState::self());
sp<IServiceManager> sm(defaultServiceManager());
sm->addService(String16(SERVICE::getServiceName()), new SERVICE());
ProcessState::self()->startThreadPool();
IPCThreadState::self()->joinThreadPool();
}
static void instantiate() { publish(); }
static status_t shutdown() {
return NO_ERROR;
}
};
}; // namespace android
// ---------------------------------------------------------------------------
#endif // ANDROID_BINDER_SERVICE_H
+124
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
+159
View File
@@ -0,0 +1,159 @@
/*
* 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>
#define B_PACK_CHARS(c1, c2, c3, c4) \
((((c1)<<24)) | (((c2)<<16)) | (((c3)<<8)) | (c4))
// ---------------------------------------------------------------------------
namespace android {
class BBinder;
class BpBinder;
class IInterface;
class Parcel;
/**
* 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'),
INTERFACE_TRANSACTION = B_PACK_CHARS('_', 'N', 'T', 'F'),
// 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;
virtual status_t transact( uint32_t code,
const Parcel& data,
Parcel* reply,
uint32_t flags = 0) = 0;
/**
* This method allows you to add data that is transported through
* IPC along with your IBinder pointer. When implementing a Binder
* object, override it to write your desired data in to @a outData.
* You can then call getConstantData() on your IBinder to retrieve
* that data, from any process. You MUST return the number of bytes
* written in to the parcel (including padding).
*/
class DeathRecipient : public virtual RefBase
{
public:
virtual void binderDied(const wp<IBinder>& who) = 0;
};
/**
* 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 referene
* 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
+150
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();
sp<IBinder> asBinder();
sp<const IBinder> asBinder() const;
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:
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
+101
View File
@@ -0,0 +1,101 @@
/*
* 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;
// 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
@@ -0,0 +1,126 @@
/*
* 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>
#ifdef HAVE_WIN32_PROC
typedef int uid_t;
#endif
// ---------------------------------------------------------------------------
namespace android {
class IPCThreadState
{
public:
static IPCThreadState* self();
sp<ProcessState> process();
status_t clearLastError();
int getCallingPid();
int getCallingUid();
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);
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);
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 executeCommand(int32_t command);
void clearCaller();
static void threadDestructor(void *st);
static void freeBuffer(Parcel* parcel,
const uint8_t* data, size_t dataSize,
const size_t* objects, size_t objectsSize,
void* cookie);
const sp<ProcessState> mProcess;
const pid_t mMyThreadId;
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
@@ -0,0 +1,56 @@
/*
* 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>
namespace android {
// ----------------------------------------------------------------------
class IPermissionController : public IInterface
{
public:
DECLARE_META_INTERFACE(PermissionController);
virtual bool checkPermission(const String16& permission,
int32_t pid, int32_t uid) = 0;
enum {
CHECK_PERMISSION_TRANSACTION = IBinder::FIRST_CALL_TRANSACTION
};
};
// ----------------------------------------------------------------------
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
@@ -0,0 +1,100 @@
/*
* 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) = 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);
// ----------------------------------------------------------------------
class BnServiceManager : public BnInterface<IServiceManager>
{
public:
virtual status_t onTransact( uint32_t code,
const Parcel& data,
Parcel* reply,
uint32_t flags = 0);
};
// ----------------------------------------------------------------------
}; // namespace android
#endif // ANDROID_ISERVICE_MANAGER_H
@@ -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
@@ -0,0 +1,60 @@
/*
* 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);
virtual sp<IMemory> allocate(size_t size);
virtual void deallocate(size_t offset);
virtual void dump(const char* what) const;
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
@@ -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.
*/
#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,
MAP_LOCKED_MAP_POPULATE = 0x00000400,
};
/*
* 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 void* getBase() const;
virtual size_t getSize() const;
virtual uint32_t getFlags() 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;
};
// ---------------------------------------------------------------------------
}; // namespace android
#endif // ANDROID_MEMORY_HEAP_BASE_H
@@ -0,0 +1,56 @@
/*
* Copyright (C) 2008 The Android Open Source Project
* Copyright (c) 2011, The Linux Foundation. All rights reserved.
*
* 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_ION_H
#define ANDROID_MEMORY_HEAP_ION_H
#include <stdlib.h>
#include <stdint.h>
#include <binder/MemoryHeapBase.h>
#include <binder/IMemory.h>
#include <utils/SortedVector.h>
#include <utils/threads.h>
#include <linux/ion.h>
namespace android {
class MemoryHeapBase;
// ---------------------------------------------------------------------------
class MemoryHeapIon : public MemoryHeapBase
{
public:
MemoryHeapIon(const char*, size_t, uint32_t, long unsigned int);
MemoryHeapIon();
~MemoryHeapIon();
status_t mapIonFd(int fd, size_t size, unsigned long memory_type, int flags);
status_t ionInit(int ionFd, void *base, int size, int flags,
const char* device, struct ion_handle *handle,
int ionMapFd);
private:
int mIonDeviceFd; /*fd we get from open("/dev/ion")*/
struct ion_handle *mIonHandle; /*handle we get from ION_IOC_ALLOC*/ };
// ---------------------------------------------------------------------------
}; // namespace android
#endif // ANDROID_MEMORY_HEAP_ION_H
@@ -0,0 +1,79 @@
/*
* 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_PMEM_H
#define ANDROID_MEMORY_HEAP_PMEM_H
#include <stdlib.h>
#include <stdint.h>
#include <binder/MemoryHeapBase.h>
#include <binder/IMemory.h>
#include <utils/SortedVector.h>
#include <utils/threads.h>
namespace android {
class MemoryHeapBase;
// ---------------------------------------------------------------------------
class MemoryHeapPmem : public MemoryHeapBase
{
public:
class MemoryPmem : public BnMemory {
public:
MemoryPmem(const sp<MemoryHeapPmem>& heap);
~MemoryPmem();
protected:
const sp<MemoryHeapPmem>& getHeap() const { return mClientHeap; }
private:
friend class MemoryHeapPmem;
virtual void revoke() = 0;
sp<MemoryHeapPmem> mClientHeap;
};
MemoryHeapPmem(const sp<MemoryHeapBase>& pmemHeap, uint32_t flags = 0);
~MemoryHeapPmem();
/* HeapInterface additions */
virtual sp<IMemory> mapMemory(size_t offset, size_t size);
/* make the whole heap visible (you know who you are) */
virtual status_t slap();
/* hide (revoke) the whole heap (the client will see the garbage page) */
virtual status_t unslap();
/* revoke all allocations made by this heap */
virtual void revoke();
private:
/* use this to create your own IMemory for mapMemory */
virtual sp<MemoryPmem> createMemory(size_t offset, size_t size);
void remove(const wp<MemoryPmem>& memory);
private:
sp<MemoryHeapBase> mParentHeap;
mutable Mutex mLock;
SortedVector< wp<MemoryPmem> > mAllocations;
};
// ---------------------------------------------------------------------------
}; // namespace android
#endif // ANDROID_MEMORY_HEAP_PMEM_H
+248
View File
@@ -0,0 +1,248 @@
/*
* 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 <cutils/native_handle.h>
#include <utils/Errors.h>
#include <utils/RefBase.h>
#include <utils/String16.h>
#include <utils/Vector.h>
// ---------------------------------------------------------------------------
namespace android {
class Flattenable;
class IBinder;
class IPCThreadState;
class ProcessState;
class String8;
class TextOutput;
struct flat_binder_object; // defined in support_p/binder_module.h
class Parcel
{
public:
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(Parcel *parcel, size_t start, size_t len);
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();
const size_t* objects() const;
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 writeInt64(int64_t val);
status_t writeFloat(float val);
status_t writeDouble(double val);
status_t writeIntPtr(intptr_t val);
status_t writeCString(const char* str);
status_t writeString8(const String8& str);
status_t writeString16(const 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 write(const Flattenable& val);
// 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.
status_t writeFileDescriptor(int fd);
// 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);
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;
int64_t readInt64() const;
status_t readInt64(int64_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;
const char* readCString() const;
String8 readString8() const;
String16 readString16() const;
const char16_t* readString16Inplace(size_t* outLen) const;
sp<IBinder> readStrongBinder() const;
wp<IBinder> readWeakBinder() const;
status_t read(Flattenable& val) 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;
const flat_binder_object* readObject(bool nullMetaData) const;
// Explicitly close all file descriptors in the parcel.
void closeFileDescriptors();
typedef void (*release_func)(Parcel* parcel,
const uint8_t* data, size_t dataSize,
const size_t* objects, size_t objectsSize,
void* cookie);
const uint8_t* ipcData() const;
size_t ipcDataSize() const;
const size_t* ipcObjects() const;
size_t ipcObjectsCount() const;
void ipcSetDataReference(const uint8_t* data, size_t dataSize,
const size_t* objects, size_t objectsCount,
release_func relFunc, void* relCookie);
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);
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 mError;
uint8_t* mData;
size_t mDataSize;
size_t mDataCapacity;
mutable size_t mDataPos;
size_t* mObjects;
size_t mObjectsSize;
size_t mObjectsCapacity;
mutable size_t mNextObjectHint;
mutable bool mFdsKnown;
mutable bool mHasFds;
release_func mOwner;
void* mOwnerCookie;
};
// ---------------------------------------------------------------------------
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
@@ -0,0 +1,68 @@
/*
* 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/SortedVector.h>
#include <utils/String16.h>
#include <utils/threads.h>
namespace android {
// ---------------------------------------------------------------------------
/*
* Permission caches the result of the permission check for the given
* permission name and the provided uid/pid. It also handles a few
* known cases efficiently (caller is in the same process or is root).
* The package manager does something similar but lives in dalvik world
* and is therefore extremely slow to access.
*/
class Permission
{
public:
Permission(char const* name);
Permission(const String16& name);
Permission(const Permission& rhs);
virtual ~Permission();
bool operator < (const Permission& rhs) const;
// checks the current binder call's caller has access to this permission
bool checkCalling() const;
// checks the specified pid/uid has access to this permission
bool check(pid_t pid, uid_t uid) const;
protected:
virtual bool doCheckPermission(pid_t pid, uid_t uid) const;
private:
Permission& operator = (const Permission& rhs) const;
const String16 mPermissionName;
mutable SortedVector<uid_t> mGranted;
const pid_t mPid;
mutable Mutex mLock;
};
// ---------------------------------------------------------------------------
}; // namespace android
#endif /* BINDER_PERMISSION_H */
@@ -0,0 +1,117 @@
/*
* 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>
// ---------------------------------------------------------------------------
namespace android {
// Global variables
extern int mArgC;
extern const char* const* mArgV;
extern int mArgLen;
class IPCThreadState;
class ProcessState : public virtual RefBase
{
public:
static sp<ProcessState> self();
static void setSingleProcess(bool singleProcess);
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);
bool supportsProcesses() const;
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 setArgs(int argc, const char* const argv[]);
int getArgC() const;
const char* const* getArgV() const;
void setArgV0(const char* txt);
void spawnPooledThread(bool isMain);
private:
friend class IPCThreadState;
ProcessState();
~ProcessState();
ProcessState(const ProcessState& o);
ProcessState& operator=(const ProcessState& o);
struct handle_entry {
IBinder* binder;
RefBase::weakref_type* refs;
};
handle_entry* lookupHandleLocked(int32_t handle);
int mDriverFD;
void* mVMStart;
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
+39
View File
@@ -0,0 +1,39 @@
/*
* 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/IMemory.h>
#include <binder/ProcessState.h>
#include <binder/IPermissionController.h>
#include <binder/IServiceManager.h>
namespace android {
// For ProcessState.cpp
extern Mutex gProcessMutex;
extern sp<ProcessState> gProcess;
// For ServiceManager.cpp
extern Mutex gDefaultServiceManagerLock;
extern sp<IServiceManager> gDefaultServiceManager;
extern sp<IPermissionController> gPermissionController;
} // namespace android
@@ -0,0 +1,148 @@
/*
* 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
#if defined(HAVE_ANDROID_OS)
/* obtain structures and constants from the kernel header */
#include <sys/ioctl.h>
#include <linux/binder.h>
#else
/* Some parts of the simulator need fake versions of this
* stuff in order to compile. Really this should go away
* entirely...
*/
#define BINDER_CURRENT_PROTOCOL_VERSION 7
#define BINDER_TYPE_BINDER 1
#define BINDER_TYPE_WEAK_BINDER 2
#define BINDER_TYPE_HANDLE 3
#define BINDER_TYPE_WEAK_HANDLE 4
#define BINDER_TYPE_FD 5
struct flat_binder_object {
unsigned long type;
unsigned long flags;
union {
void *binder;
signed long handle;
};
void *cookie;
};
struct binder_write_read {
signed long write_size;
signed long write_consumed;
unsigned long write_buffer;
signed long read_size;
signed long read_consumed;
unsigned long read_buffer;
};
struct binder_transaction_data {
union {
size_t handle;
void *ptr;
} target;
void *cookie;
unsigned int code;
unsigned int flags;
pid_t sender_pid;
uid_t sender_euid;
size_t data_size;
size_t offsets_size;
union {
struct {
const void *buffer;
const void *offsets;
} ptr;
uint8_t buf[8];
} data;
};
enum transaction_flags {
TF_ONE_WAY = 0x01,
TF_ROOT_OBJECT = 0x04,
TF_STATUS_CODE = 0x08,
TF_ACCEPT_FDS = 0x10,
};
enum {
FLAT_BINDER_FLAG_PRIORITY_MASK = 0xff,
FLAT_BINDER_FLAG_ACCEPTS_FDS = 0x100,
};
enum BinderDriverReturnProtocol {
BR_ERROR,
BR_OK,
BR_TRANSACTION,
BR_REPLY,
BR_ACQUIRE_RESULT,
BR_DEAD_REPLY,
BR_TRANSACTION_COMPLETE,
BR_INCREFS,
BR_ACQUIRE,
BR_RELEASE,
BR_DECREFS,
BR_ATTEMPT_ACQUIRE,
BR_NOOP,
BR_SPAWN_LOOPER,
BR_FINISHED,
BR_DEAD_BINDER,
BR_CLEAR_DEATH_NOTIFICATION_DONE,
BR_FAILED_REPLY,
};
enum BinderDriverCommandProtocol {
BC_TRANSACTION,
BC_REPLY,
BC_ACQUIRE_RESULT,
BC_FREE_BUFFER,
BC_INCREFS,
BC_ACQUIRE,
BC_RELEASE,
BC_DECREFS,
BC_INCREFS_DONE,
BC_ACQUIRE_DONE,
BC_ATTEMPT_ACQUIRE,
BC_REGISTER_LOOPER,
BC_ENTER_LOOPER,
BC_EXIT_LOOPER,
BC_REQUEST_DEATH_NOTIFICATION,
BC_CLEAR_DEATH_NOTIFICATION,
BC_DEAD_BINDER_DONE,
};
#endif
#ifdef __cplusplus
} // namespace android
#endif
#endif // _BINDER_MODULE_H_
@@ -0,0 +1,39 @@
/*
* 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/IMemory.h>
#include <binder/ProcessState.h>
#include <binder/IPermissionController.h>
#include <binder/IServiceManager.h>
namespace android {
// For ProcessState.cpp
extern Mutex gProcessMutex;
extern sp<ProcessState> gProcess;
// For ServiceManager.cpp
extern Mutex gDefaultServiceManagerLock;
extern sp<IServiceManager> gDefaultServiceManager;
extern sp<IPermissionController> gPermissionController;
} // namespace android
@@ -0,0 +1,148 @@
/*
* 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
#if defined(HAVE_ANDROID_OS)
/* obtain structures and constants from the kernel header */
#include <sys/ioctl.h>
#include <linux/binder.h>
#else
/* Some parts of the simulator need fake versions of this
* stuff in order to compile. Really this should go away
* entirely...
*/
#define BINDER_CURRENT_PROTOCOL_VERSION 7
#define BINDER_TYPE_BINDER 1
#define BINDER_TYPE_WEAK_BINDER 2
#define BINDER_TYPE_HANDLE 3
#define BINDER_TYPE_WEAK_HANDLE 4
#define BINDER_TYPE_FD 5
struct flat_binder_object {
unsigned long type;
unsigned long flags;
union {
void *binder;
signed long handle;
};
void *cookie;
};
struct binder_write_read {
signed long write_size;
signed long write_consumed;
unsigned long write_buffer;
signed long read_size;
signed long read_consumed;
unsigned long read_buffer;
};
struct binder_transaction_data {
union {
size_t handle;
void *ptr;
} target;
void *cookie;
unsigned int code;
unsigned int flags;
pid_t sender_pid;
uid_t sender_euid;
size_t data_size;
size_t offsets_size;
union {
struct {
const void *buffer;
const void *offsets;
} ptr;
uint8_t buf[8];
} data;
};
enum transaction_flags {
TF_ONE_WAY = 0x01,
TF_ROOT_OBJECT = 0x04,
TF_STATUS_CODE = 0x08,
TF_ACCEPT_FDS = 0x10,
};
enum {
FLAT_BINDER_FLAG_PRIORITY_MASK = 0xff,
FLAT_BINDER_FLAG_ACCEPTS_FDS = 0x100,
};
enum BinderDriverReturnProtocol {
BR_ERROR,
BR_OK,
BR_TRANSACTION,
BR_REPLY,
BR_ACQUIRE_RESULT,
BR_DEAD_REPLY,
BR_TRANSACTION_COMPLETE,
BR_INCREFS,
BR_ACQUIRE,
BR_RELEASE,
BR_DECREFS,
BR_ATTEMPT_ACQUIRE,
BR_NOOP,
BR_SPAWN_LOOPER,
BR_FINISHED,
BR_DEAD_BINDER,
BR_CLEAR_DEATH_NOTIFICATION_DONE,
BR_FAILED_REPLY,
};
enum BinderDriverCommandProtocol {
BC_TRANSACTION,
BC_REPLY,
BC_ACQUIRE_RESULT,
BC_FREE_BUFFER,
BC_INCREFS,
BC_ACQUIRE,
BC_RELEASE,
BC_DECREFS,
BC_INCREFS_DONE,
BC_ACQUIRE_DONE,
BC_ATTEMPT_ACQUIRE,
BC_REGISTER_LOOPER,
BC_ENTER_LOOPER,
BC_EXIT_LOOPER,
BC_REQUEST_DEATH_NOTIFICATION,
BC_CLEAR_DEATH_NOTIFICATION,
BC_DEAD_BINDER_DONE,
};
#endif
#ifdef __cplusplus
} // namespace android
#endif
#endif // _BINDER_MODULE_H_