checkpoint: split libutils into libutils + libbinder

This commit is contained in:
Mathias Agopian 2009-05-18 15:08:03 -07:00 committed by Alex Ray
parent a393a7dd94
commit b8db306e1a
16 changed files with 0 additions and 5233 deletions

View File

@ -103,19 +103,6 @@ include $(CLEAR_VARS)
# we have the common sources, plus some device-specific stuff
LOCAL_SRC_FILES:= \
$(commonSources) \
Binder.cpp \
BpBinder.cpp \
IInterface.cpp \
IMemory.cpp \
IPCThreadState.cpp \
MemoryDealer.cpp \
MemoryBase.cpp \
MemoryHeapBase.cpp \
MemoryHeapPmem.cpp \
Parcel.cpp \
ProcessState.cpp \
IPermissionController.cpp \
IServiceManager.cpp \
Unicode.cpp \
backup_data.cpp \
backup_helper_file.cpp

View File

@ -1,242 +0,0 @@
/*
* 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 <utils/Binder.h>
#include <utils/Atomic.h>
#include <utils/BpBinder.h>
#include <utils/IInterface.h>
#include <utils/Parcel.h>
#include <stdio.h>
namespace android {
// ---------------------------------------------------------------------------
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;
}
String16 BBinder::getInterfaceDescriptor() const
{
LOGW("reached BBinder::getInterfaceDescriptor (this=%p)", this);
return String16();
}
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

View File

@ -1,348 +0,0 @@
/*
* 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 <utils/BpBinder.h>
#include <utils/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);
}
String16 BpBinder::getInterfaceDescriptor() const
{
String16 res;
Parcel send, reply;
status_t err = const_cast<BpBinder*>(this)->transact(
INTERFACE_TRANSACTION, send, &reply);
if (err == NO_ERROR) {
res = reply.readString16();
}
return res;
}
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

View File

@ -1,89 +0,0 @@
/*
* Copyright (C) 2006 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <stdint.h>
#include <sys/types.h>
#include <utils/Parcel.h>
#include <utils/IDataConnection.h>
namespace android {
// ---------------------------------------------------------------------------
enum
{
CONNECT_TRANSACTION = IBinder::FIRST_CALL_TRANSACTION,
DISCONNECT_TRANSACTION = IBinder::FIRST_CALL_TRANSACTION + 1
};
class BpDataConnection : public BpInterface<IDataConnection>
{
public:
BpDataConnection::BpDataConnection(const sp<IBinder>& impl)
: BpInterface<IDataConnection>(impl)
{
}
virtual void connect()
{
Parcel data, reply;
data.writeInterfaceToken(IDataConnection::descriptor());
remote()->transact(CONNECT_TRANSACTION, data, &reply);
}
virtual void disconnect()
{
Parcel data, reply;
remote()->transact(DISCONNECT_TRANSACTION, data, &reply);
}
};
IMPLEMENT_META_INTERFACE(DataConnection, "android.utils.IDataConnection");
#define CHECK_INTERFACE(interface, data, reply) \
do { if (!data.enforceInterface(interface::getInterfaceDescriptor())) { \
LOGW("Call incorrectly routed to " #interface); \
return PERMISSION_DENIED; \
} } while (0)
status_t BnDataConnection::onTransact(uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
{
switch(code)
{
case CONNECT_TRANSACTION:
{
CHECK_INTERFACE(IDataConnection, data, reply);
connect();
return NO_ERROR;
}
case DISCONNECT_TRANSACTION:
{
CHECK_INTERFACE(IDataConnection, data, reply);
disconnect();
return NO_ERROR;
}
default:
return BBinder::onTransact(code, data, reply, flags);
}
}
// ----------------------------------------------------------------------------
}; // namespace android

View File

@ -1,35 +0,0 @@
/*
* 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 <utils/IInterface.h>
namespace android {
// ---------------------------------------------------------------------------
sp<IBinder> IInterface::asBinder()
{
return this ? onAsBinder() : NULL;
}
sp<const IBinder> IInterface::asBinder() const
{
return this ? const_cast<IInterface*>(this)->onAsBinder() : NULL;
}
// ---------------------------------------------------------------------------
}; // namespace android

View File

@ -1,486 +0,0 @@
/*
* 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 <utils/IMemory.h>
#include <utils/KeyedVector.h>
#include <utils/threads.h>
#include <utils/Atomic.h>
#include <utils/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 pin_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 inline pin_heap() const {
gHeapCache->pin_heap(const_cast<BpMemoryHeap*>(this)->asBinder());
}
void assertMapped() const;
void assertReallyMapped() const;
void pinHeap() const;
mutable volatile int32_t mHeapId;
mutable void* mBase;
mutable size_t mSize;
mutable uint32_t mFlags;
mutable bool mRealHeap;
mutable Mutex mLock;
};
// ----------------------------------------------------------------------------
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");
#define CHECK_INTERFACE(interface, data, reply) \
do { if (!data.enforceInterface(interface::getInterfaceDescriptor())) { \
LOGW("Call incorrectly routed to " #interface); \
return PERMISSION_DENIED; \
} } while (0)
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)
{
}
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);
}
}
}
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=%d, 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=%d, 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=%d, fd=%d (%s)",
asBinder().get(), size, fd, strerror(errno));
close(fd);
} else {
if (flags & MAP_ONCE) {
//LOGD("pinning heap (binder=%p, size=%d, fd=%d",
// asBinder().get(), size, fd);
pin_heap();
}
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");
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::pin_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));
android_atomic_inc(&info.count);
binder->linkToDeath(this);
} else {
LOGE("pin_heap binder=%p not found!!!", binder.get());
}
}
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

View File

@ -1,86 +0,0 @@
/*
* 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 <utils/IPermissionController.h>
#include <utils/Debug.h>
#include <utils/Log.h>
#include <utils/Parcel.h>
#include <utils/String8.h>
#include <private/utils/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.readInt32() != 0) return 0;
return reply.readInt32() != 0;
}
};
IMPLEMENT_META_INTERFACE(PermissionController, "android.os.IPermissionController");
// ----------------------------------------------------------------------
#define CHECK_INTERFACE(interface, data, reply) \
do { if (!data.enforceInterface(interface::getInterfaceDescriptor())) { \
LOGW("Call incorrectly routed to " #interface); \
return PERMISSION_DENIED; \
} } while (0)
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);
// write exception
reply->writeInt32(0);
reply->writeInt32(res ? 1 : 0);
return NO_ERROR;
} break;
default:
return BBinder::onTransact(code, data, reply, flags);
}
}
}; // namespace android

View File

@ -1,230 +0,0 @@
/*
* 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 <utils/IServiceManager.h>
#include <utils/Debug.h>
#include <utils/IPCThreadState.h>
#include <utils/Log.h>
#include <utils/Parcel.h>
#include <utils/String8.h>
#include <utils/SystemClock.h>
#include <private/utils/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();
int32_t pid = ipcState->getCallingPid();
int32_t uid = ipcState->getCallingUid();
if (outPid) *outPid = pid;
if (outUid) *outUid= 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 sevice %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.readInt32() : 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");
// ----------------------------------------------------------------------
#define CHECK_INTERFACE(interface, data, reply) \
do { if (!data.enforceInterface(interface::getInterfaceDescriptor())) { \
LOGW("Call incorrectly routed to " #interface); \
return PERMISSION_DENIED; \
} } while (0)
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

View File

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

View File

@ -1,409 +0,0 @@
/*
* 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 <utils/MemoryDealer.h>
#include <utils/Log.h>
#include <utils/IPCThreadState.h>
#include <utils/SortedVector.h>
#include <utils/String8.h>
#include <utils/MemoryBase.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 {
// ----------------------------------------------------------------------------
class SimpleMemory : public MemoryBase {
public:
SimpleMemory(const sp<IMemoryHeap>& heap, ssize_t offset, size_t size);
virtual ~SimpleMemory();
};
// ----------------------------------------------------------------------------
MemoryDealer::Allocation::Allocation(
const sp<MemoryDealer>& dealer, ssize_t offset, size_t size,
const sp<IMemory>& memory)
: mDealer(dealer), mOffset(offset), mSize(size), mMemory(memory)
{
}
MemoryDealer::Allocation::~Allocation()
{
if (mSize) {
/* 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(mOffset);
}
}
sp<IMemoryHeap> MemoryDealer::Allocation::getMemory(
ssize_t* offset, size_t* size) const
{
return mMemory->getMemory(offset, size);
}
// ----------------------------------------------------------------------------
MemoryDealer::MemoryDealer(size_t size, uint32_t flags, const char* name)
: mHeap(new SharedHeap(size, flags, name)),
mAllocator(new SimpleBestFitAllocator(size))
{
}
MemoryDealer::MemoryDealer(const sp<HeapInterface>& heap)
: mHeap(heap),
mAllocator(new SimpleBestFitAllocator(heap->virtualSize()))
{
}
MemoryDealer::MemoryDealer( const sp<HeapInterface>& heap,
const sp<AllocatorInterface>& allocator)
: mHeap(heap), mAllocator(allocator)
{
}
MemoryDealer::~MemoryDealer()
{
}
sp<IMemory> MemoryDealer::allocate(size_t size, uint32_t flags)
{
sp<IMemory> memory;
const ssize_t offset = allocator()->allocate(size, flags);
if (offset >= 0) {
sp<IMemory> new_memory = heap()->mapMemory(offset, size);
if (new_memory != 0) {
memory = new Allocation(this, offset, size, new_memory);
} else {
LOGE("couldn't map [%8x, %d]", offset, size);
if (size) {
/* 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). */
allocator()->deallocate(offset);
}
}
}
return memory;
}
void MemoryDealer::deallocate(size_t offset)
{
allocator()->deallocate(offset);
}
void MemoryDealer::dump(const char* what, uint32_t flags) const
{
allocator()->dump(what, flags);
}
const sp<HeapInterface>& MemoryDealer::heap() const {
return mHeap;
}
const sp<AllocatorInterface>& 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, uint32_t flags) const
{
Mutex::Autolock _l(mLock);
dump_l(what, flags);
}
void SimpleBestFitAllocator::dump_l(const char* what, uint32_t flags) const
{
String8 result;
dump_l(result, what, flags);
LOGD("%s", result.string());
}
void SimpleBestFitAllocator::dump(String8& result,
const char* what, uint32_t flags) const
{
Mutex::Autolock _l(mLock);
dump_l(result, what, flags);
}
void SimpleBestFitAllocator::dump_l(String8& result,
const char* what, uint32_t flags) 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);
}
// ----------------------------------------------------------------------------
SharedHeap::SharedHeap(size_t size, uint32_t flags, char const * name)
: MemoryHeapBase(size, flags, name)
{
}
SharedHeap::~SharedHeap()
{
}
sp<IMemory> SharedHeap::mapMemory(size_t offset, size_t size)
{
return new SimpleMemory(this, offset, size);
}
SimpleMemory::SimpleMemory(const sp<IMemoryHeap>& heap,
ssize_t offset, size_t size)
: MemoryBase(heap, offset, size)
{
#ifndef NDEBUG
void* const start_ptr = (void*)(intptr_t(heap->base()) + offset);
memset(start_ptr, 0xda, size);
#endif
}
SimpleMemory::~SimpleMemory()
{
size_t freedOffset = getOffset();
size_t freedSize = getSize();
// 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
}
}
}; // namespace android

View File

@ -1,183 +0,0 @@
/*
* 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 <utils/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 fd = open(device, O_RDWR);
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)
: 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);
}
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)
{
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) {
void* base = (uint8_t*)mmap(0, size,
PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
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

View File

@ -1,248 +0,0 @@
/*
* 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 <utils/MemoryHeapPmem.h>
#include <utils/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 != NULL) {
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)
: HeapInterface(), MemoryHeapBase()
{
char const * const device = pmemHeap->getDevice();
#if HAVE_ANDROID_OS
if (device) {
int fd = open(device, O_RDWR);
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

File diff suppressed because it is too large Load Diff

View File

@ -1,398 +0,0 @@
/*
* 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 <utils/ProcessState.h>
#include <utils/Atomic.h>
#include <utils/BpBinder.h>
#include <utils/IPCThreadState.h>
#include <utils/Log.h>
#include <utils/String8.h>
#include <utils/IServiceManager.h>
#include <utils/String8.h>
#include <utils/threads.h>
#include <private/utils/binder_module.h>
#include <private/utils/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)
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

View File

@ -20,7 +20,6 @@
#include <private/utils/Static.h>
#include <utils/BufferedTextOutput.h>
#include <utils/IPCThreadState.h>
#include <utils/Log.h>
namespace android {
@ -87,34 +86,4 @@ TextOutput& alog(gLogTextOutput);
TextOutput& aout(gStdoutTextOutput);
TextOutput& aerr(gStderrTextOutput);
#ifndef LIBUTILS_NATIVE
// ------------ 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;
#endif
} // namespace android