diff options
Diffstat (limited to 'libs/utils')
30 files changed, 128 insertions, 8905 deletions
diff --git a/libs/utils/Android.mk b/libs/utils/Android.mk index 9bdd64a..3f5cb85 100644 --- a/libs/utils/Android.mk +++ b/libs/utils/Android.mk @@ -32,51 +32,30 @@ commonSources:= \ StopWatch.cpp \ String8.cpp \ String16.cpp \ + StringArray.cpp \ SystemClock.cpp \ TextOutput.cpp \ Threads.cpp \ - TimerProbe.cpp \ Timers.cpp \ VectorImpl.cpp \ ZipFileCRO.cpp \ ZipFileRO.cpp \ ZipUtils.cpp \ - misc.cpp \ - ported.cpp \ - LogSocket.cpp + misc.cpp -# -# The cpp files listed here do not belong in the device -# build. Consult with the swetland before even thinking about -# putting them in commonSources. -# -# They're used by the simulator runtime and by host-side tools like -# aapt and the simulator front-end. -# -hostSources:= \ - InetAddress.cpp \ - Pipe.cpp \ - Socket.cpp \ - ZipEntry.cpp \ - ZipFile.cpp # For the host # ===================================================== include $(CLEAR_VARS) -LOCAL_SRC_FILES:= $(commonSources) $(hostSources) +LOCAL_SRC_FILES:= $(commonSources) ifeq ($(HOST_OS),linux) # Use the futex based mutex and condition variable # implementation from android-arm because it's shared mem safe LOCAL_SRC_FILES += \ - futex_synchro.c \ - executablepath_linux.cpp -endif -ifeq ($(HOST_OS),darwin) - LOCAL_SRC_FILES += \ - executablepath_darwin.cpp + futex_synchro.c endif LOCAL_MODULE:= libutils @@ -103,27 +82,10 @@ 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 \ BackupData.cpp \ BackupHelpers.cpp -ifeq ($(TARGET_SIMULATOR),true) -LOCAL_SRC_FILES += $(hostSources) -endif - ifeq ($(TARGET_OS),linux) # Use the futex based mutex and condition variable # implementation from android-arm because it's shared mem safe @@ -150,9 +112,5 @@ endif # linux-x86 endif # sim LOCAL_MODULE:= libutils - -#LOCAL_CFLAGS+= -#LOCAL_LDFLAGS:= - include $(BUILD_SHARED_LIBRARY) diff --git a/libs/utils/Binder.cpp b/libs/utils/Binder.cpp deleted file mode 100644 index 37e4685..0000000 --- a/libs/utils/Binder.cpp +++ /dev/null @@ -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 diff --git a/libs/utils/BpBinder.cpp b/libs/utils/BpBinder.cpp deleted file mode 100644 index 69ab195..0000000 --- a/libs/utils/BpBinder.cpp +++ /dev/null @@ -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 diff --git a/libs/utils/CallStack.cpp b/libs/utils/CallStack.cpp index 2fdaa71..55b6024 100644 --- a/libs/utils/CallStack.cpp +++ b/libs/utils/CallStack.cpp @@ -311,7 +311,8 @@ String8 CallStack::toStringSingleLevel(const char* prefix, int32_t level) const } else { void const* start = 0; name = MapInfo::mapAddressToName(ip, "<unknown>", &start); - snprintf(tmp, 256, "pc %08lx %s", uintptr_t(ip)-uintptr_t(start), name); + snprintf(tmp, 256, "pc %08lx %s", + long(uintptr_t(ip)-uintptr_t(start)), name); res.append(tmp); } res.append("\n"); diff --git a/libs/utils/IDataConnection.cpp b/libs/utils/IDataConnection.cpp deleted file mode 100644 index c6d49aa..0000000 --- a/libs/utils/IDataConnection.cpp +++ /dev/null @@ -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 diff --git a/libs/utils/IInterface.cpp b/libs/utils/IInterface.cpp deleted file mode 100644 index 6ea8178..0000000 --- a/libs/utils/IInterface.cpp +++ /dev/null @@ -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 diff --git a/libs/utils/IMemory.cpp b/libs/utils/IMemory.cpp deleted file mode 100644 index 429bc2b..0000000 --- a/libs/utils/IMemory.cpp +++ /dev/null @@ -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 diff --git a/libs/utils/IPCThreadState.cpp b/libs/utils/IPCThreadState.cpp deleted file mode 100644 index 04ae142..0000000 --- a/libs/utils/IPCThreadState.cpp +++ /dev/null @@ -1,1030 +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/IPCThreadState.h> - -#include <utils/Binder.h> -#include <utils/BpBinder.h> -#include <utils/Debug.h> -#include <utils/Log.h> -#include <utils/TextOutput.h> -#include <utils/threads.h> - -#include <private/utils/binder_module.h> -#include <private/utils/Static.h> - -#include <sys/ioctl.h> -#include <signal.h> -#include <errno.h> -#include <stdio.h> -#include <unistd.h> - -#ifdef HAVE_PTHREADS -#include <pthread.h> -#include <sched.h> -#include <sys/resource.h> -#endif -#ifdef HAVE_WIN32_THREADS -#include <windows.h> -#endif - - -#if LOG_NDEBUG - -#define IF_LOG_TRANSACTIONS() if (false) -#define IF_LOG_COMMANDS() if (false) -#define LOG_REMOTEREFS(...) -#define IF_LOG_REMOTEREFS() if (false) -#define LOG_THREADPOOL(...) -#define LOG_ONEWAY(...) - -#else - -#define IF_LOG_TRANSACTIONS() IF_LOG(LOG_VERBOSE, "transact") -#define IF_LOG_COMMANDS() IF_LOG(LOG_VERBOSE, "ipc") -#define LOG_REMOTEREFS(...) LOG(LOG_DEBUG, "remoterefs", __VA_ARGS__) -#define IF_LOG_REMOTEREFS() IF_LOG(LOG_DEBUG, "remoterefs") -#define LOG_THREADPOOL(...) LOG(LOG_DEBUG, "threadpool", __VA_ARGS__) -#define LOG_ONEWAY(...) LOG(LOG_DEBUG, "ipc", __VA_ARGS__) - -#endif - -// --------------------------------------------------------------------------- - -namespace android { - -static const char* getReturnString(size_t idx); -static const char* getCommandString(size_t idx); -static const void* printReturnCommand(TextOutput& out, const void* _cmd); -static const void* printCommand(TextOutput& out, const void* _cmd); - -// This will result in a missing symbol failure if the IF_LOG_COMMANDS() -// conditionals don't get stripped... but that is probably what we want. -#if !LOG_NDEBUG -static const char *kReturnStrings[] = { -#if 1 /* TODO: error update strings */ - "unknown", -#else - "BR_OK", - "BR_TIMEOUT", - "BR_WAKEUP", - "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_EVENT_OCCURRED", - "BR_NOOP", - "BR_SPAWN_LOOPER", - "BR_FINISHED", - "BR_DEAD_BINDER", - "BR_CLEAR_DEATH_NOTIFICATION_DONE" -#endif -}; - -static const char *kCommandStrings[] = { -#if 1 /* TODO: error update strings */ - "unknown", -#else - "BC_NOOP", - "BC_TRANSACTION", - "BC_REPLY", - "BC_ACQUIRE_RESULT", - "BC_FREE_BUFFER", - "BC_TRANSACTION_COMPLETE", - "BC_INCREFS", - "BC_ACQUIRE", - "BC_RELEASE", - "BC_DECREFS", - "BC_INCREFS_DONE", - "BC_ACQUIRE_DONE", - "BC_ATTEMPT_ACQUIRE", - "BC_RETRIEVE_ROOT_OBJECT", - "BC_SET_THREAD_ENTRY", - "BC_REGISTER_LOOPER", - "BC_ENTER_LOOPER", - "BC_EXIT_LOOPER", - "BC_SYNC", - "BC_STOP_PROCESS", - "BC_STOP_SELF", - "BC_REQUEST_DEATH_NOTIFICATION", - "BC_CLEAR_DEATH_NOTIFICATION", - "BC_DEAD_BINDER_DONE" -#endif -}; - -static const char* getReturnString(size_t idx) -{ - if (idx < sizeof(kReturnStrings) / sizeof(kReturnStrings[0])) - return kReturnStrings[idx]; - else - return "unknown"; -} - -static const char* getCommandString(size_t idx) -{ - if (idx < sizeof(kCommandStrings) / sizeof(kCommandStrings[0])) - return kCommandStrings[idx]; - else - return "unknown"; -} - -static const void* printBinderTransactionData(TextOutput& out, const void* data) -{ - const binder_transaction_data* btd = - (const binder_transaction_data*)data; - out << "target=" << btd->target.ptr << " (cookie " << btd->cookie << ")" << endl - << "code=" << TypeCode(btd->code) << ", flags=" << (void*)btd->flags << endl - << "data=" << btd->data.ptr.buffer << " (" << (void*)btd->data_size - << " bytes)" << endl - << "offsets=" << btd->data.ptr.offsets << " (" << (void*)btd->offsets_size - << " bytes)" << endl; - return btd+1; -} - -static const void* printReturnCommand(TextOutput& out, const void* _cmd) -{ - static const int32_t N = sizeof(kReturnStrings)/sizeof(kReturnStrings[0]); - - const int32_t* cmd = (const int32_t*)_cmd; - int32_t code = *cmd++; - if (code == BR_ERROR) { - out << "BR_ERROR: " << (void*)(*cmd++) << endl; - return cmd; - } else if (code < 0 || code >= N) { - out << "Unknown reply: " << code << endl; - return cmd; - } - - out << kReturnStrings[code]; - switch (code) { - case BR_TRANSACTION: - case BR_REPLY: { - out << ": " << indent; - cmd = (const int32_t *)printBinderTransactionData(out, cmd); - out << dedent; - } break; - - case BR_ACQUIRE_RESULT: { - const int32_t res = *cmd++; - out << ": " << res << (res ? " (SUCCESS)" : " (FAILURE)"); - } break; - - case BR_INCREFS: - case BR_ACQUIRE: - case BR_RELEASE: - case BR_DECREFS: { - const int32_t b = *cmd++; - const int32_t c = *cmd++; - out << ": target=" << (void*)b << " (cookie " << (void*)c << ")"; - } break; - - case BR_ATTEMPT_ACQUIRE: { - const int32_t p = *cmd++; - const int32_t b = *cmd++; - const int32_t c = *cmd++; - out << ": target=" << (void*)b << " (cookie " << (void*)c - << "), pri=" << p; - } break; - - case BR_DEAD_BINDER: - case BR_CLEAR_DEATH_NOTIFICATION_DONE: { - const int32_t c = *cmd++; - out << ": death cookie " << (void*)c; - } break; - } - - out << endl; - return cmd; -} - -static const void* printCommand(TextOutput& out, const void* _cmd) -{ - static const int32_t N = sizeof(kCommandStrings)/sizeof(kCommandStrings[0]); - - const int32_t* cmd = (const int32_t*)_cmd; - int32_t code = *cmd++; - if (code < 0 || code >= N) { - out << "Unknown command: " << code << endl; - return cmd; - } - - out << kCommandStrings[code]; - switch (code) { - case BC_TRANSACTION: - case BC_REPLY: { - out << ": " << indent; - cmd = (const int32_t *)printBinderTransactionData(out, cmd); - out << dedent; - } break; - - case BC_ACQUIRE_RESULT: { - const int32_t res = *cmd++; - out << ": " << res << (res ? " (SUCCESS)" : " (FAILURE)"); - } break; - - case BC_FREE_BUFFER: { - const int32_t buf = *cmd++; - out << ": buffer=" << (void*)buf; - } break; - - case BC_INCREFS: - case BC_ACQUIRE: - case BC_RELEASE: - case BC_DECREFS: { - const int32_t d = *cmd++; - out << ": descriptor=" << (void*)d; - } break; - - case BC_INCREFS_DONE: - case BC_ACQUIRE_DONE: { - const int32_t b = *cmd++; - const int32_t c = *cmd++; - out << ": target=" << (void*)b << " (cookie " << (void*)c << ")"; - } break; - - case BC_ATTEMPT_ACQUIRE: { - const int32_t p = *cmd++; - const int32_t d = *cmd++; - out << ": decriptor=" << (void*)d << ", pri=" << p; - } break; - - case BC_REQUEST_DEATH_NOTIFICATION: - case BC_CLEAR_DEATH_NOTIFICATION: { - const int32_t h = *cmd++; - const int32_t c = *cmd++; - out << ": handle=" << h << " (death cookie " << (void*)c << ")"; - } break; - - case BC_DEAD_BINDER_DONE: { - const int32_t c = *cmd++; - out << ": death cookie " << (void*)c; - } break; - } - - out << endl; - return cmd; -} -#endif - -static pthread_mutex_t gTLSMutex = PTHREAD_MUTEX_INITIALIZER; -static bool gHaveTLS = false; -static pthread_key_t gTLS = 0; -static bool gShutdown = false; - -IPCThreadState* IPCThreadState::self() -{ - if (gHaveTLS) { -restart: - const pthread_key_t k = gTLS; - IPCThreadState* st = (IPCThreadState*)pthread_getspecific(k); - if (st) return st; - return new IPCThreadState; - } - - if (gShutdown) return NULL; - - pthread_mutex_lock(&gTLSMutex); - if (!gHaveTLS) { - if (pthread_key_create(&gTLS, threadDestructor) != 0) { - pthread_mutex_unlock(&gTLSMutex); - return NULL; - } - gHaveTLS = true; - } - pthread_mutex_unlock(&gTLSMutex); - goto restart; -} - -void IPCThreadState::shutdown() -{ - gShutdown = true; - - if (gHaveTLS) { - // XXX Need to wait for all thread pool threads to exit! - IPCThreadState* st = (IPCThreadState*)pthread_getspecific(gTLS); - if (st) { - delete st; - pthread_setspecific(gTLS, NULL); - } - gHaveTLS = false; - } -} - -sp<ProcessState> IPCThreadState::process() -{ - return mProcess; -} - -status_t IPCThreadState::clearLastError() -{ - const status_t err = mLastError; - mLastError = NO_ERROR; - return err; -} - -int IPCThreadState::getCallingPid() -{ - return mCallingPid; -} - -int IPCThreadState::getCallingUid() -{ - return mCallingUid; -} - -int64_t IPCThreadState::clearCallingIdentity() -{ - int64_t token = ((int64_t)mCallingUid<<32) | mCallingPid; - clearCaller(); - return token; -} - -void IPCThreadState::restoreCallingIdentity(int64_t token) -{ - mCallingUid = (int)(token>>32); - mCallingPid = (int)token; -} - -void IPCThreadState::clearCaller() -{ - if (mProcess->supportsProcesses()) { - mCallingPid = getpid(); - mCallingUid = getuid(); - } else { - mCallingPid = -1; - mCallingUid = -1; - } -} - -void IPCThreadState::flushCommands() -{ - if (mProcess->mDriverFD <= 0) - return; - talkWithDriver(false); -} - -void IPCThreadState::joinThreadPool(bool isMain) -{ - LOG_THREADPOOL("**** THREAD %p (PID %d) IS JOINING THE THREAD POOL\n", (void*)pthread_self(), getpid()); - - mOut.writeInt32(isMain ? BC_ENTER_LOOPER : BC_REGISTER_LOOPER); - - status_t result; - do { - int32_t cmd; - - // When we've cleared the incoming command queue, process any pending derefs - if (mIn.dataPosition() >= mIn.dataSize()) { - size_t numPending = mPendingWeakDerefs.size(); - if (numPending > 0) { - for (size_t i = 0; i < numPending; i++) { - RefBase::weakref_type* refs = mPendingWeakDerefs[i]; - refs->decWeak(mProcess.get()); - } - mPendingWeakDerefs.clear(); - } - - numPending = mPendingStrongDerefs.size(); - if (numPending > 0) { - for (size_t i = 0; i < numPending; i++) { - BBinder* obj = mPendingStrongDerefs[i]; - obj->decStrong(mProcess.get()); - } - mPendingStrongDerefs.clear(); - } - } - - // now get the next command to be processed, waiting if necessary - result = talkWithDriver(); - if (result >= NO_ERROR) { - size_t IN = mIn.dataAvail(); - if (IN < sizeof(int32_t)) continue; - cmd = mIn.readInt32(); - IF_LOG_COMMANDS() { - alog << "Processing top-level Command: " - << getReturnString(cmd) << endl; - } - result = executeCommand(cmd); - } - - // Let this thread exit the thread pool if it is no longer - // needed and it is not the main process thread. - if(result == TIMED_OUT && !isMain) { - break; - } - } while (result != -ECONNREFUSED && result != -EBADF); - - LOG_THREADPOOL("**** THREAD %p (PID %d) IS LEAVING THE THREAD POOL err=%p\n", - (void*)pthread_self(), getpid(), (void*)result); - - mOut.writeInt32(BC_EXIT_LOOPER); - talkWithDriver(false); -} - -void IPCThreadState::stopProcess(bool immediate) -{ - //LOGI("**** STOPPING PROCESS"); - flushCommands(); - int fd = mProcess->mDriverFD; - mProcess->mDriverFD = -1; - close(fd); - //kill(getpid(), SIGKILL); -} - -status_t IPCThreadState::transact(int32_t handle, - uint32_t code, const Parcel& data, - Parcel* reply, uint32_t flags) -{ - status_t err = data.errorCheck(); - - flags |= TF_ACCEPT_FDS; - - IF_LOG_TRANSACTIONS() { - TextOutput::Bundle _b(alog); - alog << "BC_TRANSACTION thr " << (void*)pthread_self() << " / hand " - << handle << " / code " << TypeCode(code) << ": " - << indent << data << dedent << endl; - } - - if (err == NO_ERROR) { - LOG_ONEWAY(">>>> SEND from pid %d uid %d %s", getpid(), getuid(), - (flags & TF_ONE_WAY) == 0 ? "READ REPLY" : "ONE WAY"); - err = writeTransactionData(BC_TRANSACTION, flags, handle, code, data, NULL); - } - - if (err != NO_ERROR) { - if (reply) reply->setError(err); - return (mLastError = err); - } - - if ((flags & TF_ONE_WAY) == 0) { - if (reply) { - err = waitForResponse(reply); - } else { - Parcel fakeReply; - err = waitForResponse(&fakeReply); - } - - IF_LOG_TRANSACTIONS() { - TextOutput::Bundle _b(alog); - alog << "BR_REPLY thr " << (void*)pthread_self() << " / hand " - << handle << ": "; - if (reply) alog << indent << *reply << dedent << endl; - else alog << "(none requested)" << endl; - } - } else { - err = waitForResponse(NULL, NULL); - } - - return err; -} - -void IPCThreadState::incStrongHandle(int32_t handle) -{ - LOG_REMOTEREFS("IPCThreadState::incStrongHandle(%d)\n", handle); - mOut.writeInt32(BC_ACQUIRE); - mOut.writeInt32(handle); -} - -void IPCThreadState::decStrongHandle(int32_t handle) -{ - LOG_REMOTEREFS("IPCThreadState::decStrongHandle(%d)\n", handle); - mOut.writeInt32(BC_RELEASE); - mOut.writeInt32(handle); -} - -void IPCThreadState::incWeakHandle(int32_t handle) -{ - LOG_REMOTEREFS("IPCThreadState::incWeakHandle(%d)\n", handle); - mOut.writeInt32(BC_INCREFS); - mOut.writeInt32(handle); -} - -void IPCThreadState::decWeakHandle(int32_t handle) -{ - LOG_REMOTEREFS("IPCThreadState::decWeakHandle(%d)\n", handle); - mOut.writeInt32(BC_DECREFS); - mOut.writeInt32(handle); -} - -status_t IPCThreadState::attemptIncStrongHandle(int32_t handle) -{ - mOut.writeInt32(BC_ATTEMPT_ACQUIRE); - mOut.writeInt32(0); // xxx was thread priority - mOut.writeInt32(handle); - status_t result = UNKNOWN_ERROR; - - waitForResponse(NULL, &result); - -#if LOG_REFCOUNTS - printf("IPCThreadState::attemptIncStrongHandle(%ld) = %s\n", - handle, result == NO_ERROR ? "SUCCESS" : "FAILURE"); -#endif - - return result; -} - -void IPCThreadState::expungeHandle(int32_t handle, IBinder* binder) -{ -#if LOG_REFCOUNTS - printf("IPCThreadState::expungeHandle(%ld)\n", handle); -#endif - self()->mProcess->expungeHandle(handle, binder); -} - -status_t IPCThreadState::requestDeathNotification(int32_t handle, BpBinder* proxy) -{ - mOut.writeInt32(BC_REQUEST_DEATH_NOTIFICATION); - mOut.writeInt32((int32_t)handle); - mOut.writeInt32((int32_t)proxy); - return NO_ERROR; -} - -status_t IPCThreadState::clearDeathNotification(int32_t handle, BpBinder* proxy) -{ - mOut.writeInt32(BC_CLEAR_DEATH_NOTIFICATION); - mOut.writeInt32((int32_t)handle); - mOut.writeInt32((int32_t)proxy); - return NO_ERROR; -} - -IPCThreadState::IPCThreadState() - : mProcess(ProcessState::self()) -{ - pthread_setspecific(gTLS, this); - clearCaller(); - mIn.setDataCapacity(256); - mOut.setDataCapacity(256); -} - -IPCThreadState::~IPCThreadState() -{ -} - -status_t IPCThreadState::sendReply(const Parcel& reply, uint32_t flags) -{ - status_t err; - status_t statusBuffer; - err = writeTransactionData(BC_REPLY, flags, -1, 0, reply, &statusBuffer); - if (err < NO_ERROR) return err; - - return waitForResponse(NULL, NULL); -} - -status_t IPCThreadState::waitForResponse(Parcel *reply, status_t *acquireResult) -{ - int32_t cmd; - int32_t err; - - while (1) { - if ((err=talkWithDriver()) < NO_ERROR) break; - err = mIn.errorCheck(); - if (err < NO_ERROR) break; - if (mIn.dataAvail() == 0) continue; - - cmd = mIn.readInt32(); - - IF_LOG_COMMANDS() { - alog << "Processing waitForResponse Command: " - << getReturnString(cmd) << endl; - } - - switch (cmd) { - case BR_TRANSACTION_COMPLETE: - if (!reply && !acquireResult) goto finish; - break; - - case BR_DEAD_REPLY: - err = DEAD_OBJECT; - goto finish; - - case BR_FAILED_REPLY: - err = FAILED_TRANSACTION; - goto finish; - - case BR_ACQUIRE_RESULT: - { - LOG_ASSERT(acquireResult != NULL, "Unexpected brACQUIRE_RESULT"); - const int32_t result = mIn.readInt32(); - if (!acquireResult) continue; - *acquireResult = result ? NO_ERROR : INVALID_OPERATION; - } - goto finish; - - case BR_REPLY: - { - binder_transaction_data tr; - err = mIn.read(&tr, sizeof(tr)); - LOG_ASSERT(err == NO_ERROR, "Not enough command data for brREPLY"); - if (err != NO_ERROR) goto finish; - - if (reply) { - if ((tr.flags & TF_STATUS_CODE) == 0) { - reply->ipcSetDataReference( - reinterpret_cast<const uint8_t*>(tr.data.ptr.buffer), - tr.data_size, - reinterpret_cast<const size_t*>(tr.data.ptr.offsets), - tr.offsets_size/sizeof(size_t), - freeBuffer, this); - } else { - err = *static_cast<const status_t*>(tr.data.ptr.buffer); - freeBuffer(NULL, - reinterpret_cast<const uint8_t*>(tr.data.ptr.buffer), - tr.data_size, - reinterpret_cast<const size_t*>(tr.data.ptr.offsets), - tr.offsets_size/sizeof(size_t), this); - } - } else { - freeBuffer(NULL, - reinterpret_cast<const uint8_t*>(tr.data.ptr.buffer), - tr.data_size, - reinterpret_cast<const size_t*>(tr.data.ptr.offsets), - tr.offsets_size/sizeof(size_t), this); - continue; - } - } - goto finish; - - default: - err = executeCommand(cmd); - if (err != NO_ERROR) goto finish; - break; - } - } - -finish: - if (err != NO_ERROR) { - if (acquireResult) *acquireResult = err; - if (reply) reply->setError(err); - mLastError = err; - } - - return err; -} - -status_t IPCThreadState::talkWithDriver(bool doReceive) -{ - LOG_ASSERT(mProcess->mDriverFD >= 0, "Binder driver is not opened"); - - binder_write_read bwr; - - // Is the read buffer empty? - const bool needRead = mIn.dataPosition() >= mIn.dataSize(); - - // We don't want to write anything if we are still reading - // from data left in the input buffer and the caller - // has requested to read the next data. - const size_t outAvail = (!doReceive || needRead) ? mOut.dataSize() : 0; - - bwr.write_size = outAvail; - bwr.write_buffer = (long unsigned int)mOut.data(); - - // This is what we'll read. - if (doReceive && needRead) { - bwr.read_size = mIn.dataCapacity(); - bwr.read_buffer = (long unsigned int)mIn.data(); - } else { - bwr.read_size = 0; - } - - IF_LOG_COMMANDS() { - TextOutput::Bundle _b(alog); - if (outAvail != 0) { - alog << "Sending commands to driver: " << indent; - const void* cmds = (const void*)bwr.write_buffer; - const void* end = ((const uint8_t*)cmds)+bwr.write_size; - alog << HexDump(cmds, bwr.write_size) << endl; - while (cmds < end) cmds = printCommand(alog, cmds); - alog << dedent; - } - alog << "Size of receive buffer: " << bwr.read_size - << ", needRead: " << needRead << ", doReceive: " << doReceive << endl; - } - - // Return immediately if there is nothing to do. - if ((bwr.write_size == 0) && (bwr.read_size == 0)) return NO_ERROR; - - bwr.write_consumed = 0; - bwr.read_consumed = 0; - status_t err; - do { - IF_LOG_COMMANDS() { - alog << "About to read/write, write size = " << mOut.dataSize() << endl; - } -#if defined(HAVE_ANDROID_OS) - if (ioctl(mProcess->mDriverFD, BINDER_WRITE_READ, &bwr) >= 0) - err = NO_ERROR; - else - err = -errno; -#else - err = INVALID_OPERATION; -#endif - IF_LOG_COMMANDS() { - alog << "Finished read/write, write size = " << mOut.dataSize() << endl; - } - } while (err == -EINTR); - - IF_LOG_COMMANDS() { - alog << "Our err: " << (void*)err << ", write consumed: " - << bwr.write_consumed << " (of " << mOut.dataSize() - << "), read consumed: " << bwr.read_consumed << endl; - } - - if (err >= NO_ERROR) { - if (bwr.write_consumed > 0) { - if (bwr.write_consumed < (ssize_t)mOut.dataSize()) - mOut.remove(0, bwr.write_consumed); - else - mOut.setDataSize(0); - } - if (bwr.read_consumed > 0) { - mIn.setDataSize(bwr.read_consumed); - mIn.setDataPosition(0); - } - IF_LOG_COMMANDS() { - TextOutput::Bundle _b(alog); - alog << "Remaining data size: " << mOut.dataSize() << endl; - alog << "Received commands from driver: " << indent; - const void* cmds = mIn.data(); - const void* end = mIn.data() + mIn.dataSize(); - alog << HexDump(cmds, mIn.dataSize()) << endl; - while (cmds < end) cmds = printReturnCommand(alog, cmds); - alog << dedent; - } - return NO_ERROR; - } - - return err; -} - -status_t IPCThreadState::writeTransactionData(int32_t cmd, uint32_t binderFlags, - int32_t handle, uint32_t code, const Parcel& data, status_t* statusBuffer) -{ - binder_transaction_data tr; - - tr.target.handle = handle; - tr.code = code; - tr.flags = binderFlags; - - const status_t err = data.errorCheck(); - if (err == NO_ERROR) { - tr.data_size = data.ipcDataSize(); - tr.data.ptr.buffer = data.ipcData(); - tr.offsets_size = data.ipcObjectsCount()*sizeof(size_t); - tr.data.ptr.offsets = data.ipcObjects(); - } else if (statusBuffer) { - tr.flags |= TF_STATUS_CODE; - *statusBuffer = err; - tr.data_size = sizeof(status_t); - tr.data.ptr.buffer = statusBuffer; - tr.offsets_size = 0; - tr.data.ptr.offsets = NULL; - } else { - return (mLastError = err); - } - - mOut.writeInt32(cmd); - mOut.write(&tr, sizeof(tr)); - - return NO_ERROR; -} - -sp<BBinder> the_context_object; - -void setTheContextObject(sp<BBinder> obj) -{ - the_context_object = obj; -} - -status_t IPCThreadState::executeCommand(int32_t cmd) -{ - BBinder* obj; - RefBase::weakref_type* refs; - status_t result = NO_ERROR; - - switch (cmd) { - case BR_ERROR: - result = mIn.readInt32(); - break; - - case BR_OK: - break; - - case BR_ACQUIRE: - refs = (RefBase::weakref_type*)mIn.readInt32(); - obj = (BBinder*)mIn.readInt32(); - LOG_ASSERT(refs->refBase() == obj, - "BR_ACQUIRE: object %p does not match cookie %p (expected %p)", - refs, obj, refs->refBase()); - obj->incStrong(mProcess.get()); - IF_LOG_REMOTEREFS() { - LOG_REMOTEREFS("BR_ACQUIRE from driver on %p", obj); - obj->printRefs(); - } - mOut.writeInt32(BC_ACQUIRE_DONE); - mOut.writeInt32((int32_t)refs); - mOut.writeInt32((int32_t)obj); - break; - - case BR_RELEASE: - refs = (RefBase::weakref_type*)mIn.readInt32(); - obj = (BBinder*)mIn.readInt32(); - LOG_ASSERT(refs->refBase() == obj, - "BR_RELEASE: object %p does not match cookie %p (expected %p)", - refs, obj, refs->refBase()); - IF_LOG_REMOTEREFS() { - LOG_REMOTEREFS("BR_RELEASE from driver on %p", obj); - obj->printRefs(); - } - mPendingStrongDerefs.push(obj); - break; - - case BR_INCREFS: - refs = (RefBase::weakref_type*)mIn.readInt32(); - obj = (BBinder*)mIn.readInt32(); - refs->incWeak(mProcess.get()); - mOut.writeInt32(BC_INCREFS_DONE); - mOut.writeInt32((int32_t)refs); - mOut.writeInt32((int32_t)obj); - break; - - case BR_DECREFS: - refs = (RefBase::weakref_type*)mIn.readInt32(); - obj = (BBinder*)mIn.readInt32(); - // NOTE: This assertion is not valid, because the object may no - // longer exist (thus the (BBinder*)cast above resulting in a different - // memory address). - //LOG_ASSERT(refs->refBase() == obj, - // "BR_DECREFS: object %p does not match cookie %p (expected %p)", - // refs, obj, refs->refBase()); - mPendingWeakDerefs.push(refs); - break; - - case BR_ATTEMPT_ACQUIRE: - refs = (RefBase::weakref_type*)mIn.readInt32(); - obj = (BBinder*)mIn.readInt32(); - - { - const bool success = refs->attemptIncStrong(mProcess.get()); - LOG_ASSERT(success && refs->refBase() == obj, - "BR_ATTEMPT_ACQUIRE: object %p does not match cookie %p (expected %p)", - refs, obj, refs->refBase()); - - mOut.writeInt32(BC_ACQUIRE_RESULT); - mOut.writeInt32((int32_t)success); - } - break; - - case BR_TRANSACTION: - { - binder_transaction_data tr; - result = mIn.read(&tr, sizeof(tr)); - LOG_ASSERT(result == NO_ERROR, - "Not enough command data for brTRANSACTION"); - if (result != NO_ERROR) break; - - Parcel buffer; - buffer.ipcSetDataReference( - reinterpret_cast<const uint8_t*>(tr.data.ptr.buffer), - tr.data_size, - reinterpret_cast<const size_t*>(tr.data.ptr.offsets), - tr.offsets_size/sizeof(size_t), freeBuffer, this); - - const pid_t origPid = mCallingPid; - const uid_t origUid = mCallingUid; - - mCallingPid = tr.sender_pid; - mCallingUid = tr.sender_euid; - - //LOGI(">>>> TRANSACT from pid %d uid %d\n", mCallingPid, mCallingUid); - - Parcel reply; - IF_LOG_TRANSACTIONS() { - TextOutput::Bundle _b(alog); - alog << "BR_TRANSACTION thr " << (void*)pthread_self() - << " / obj " << tr.target.ptr << " / code " - << TypeCode(tr.code) << ": " << indent << buffer - << dedent << endl - << "Data addr = " - << reinterpret_cast<const uint8_t*>(tr.data.ptr.buffer) - << ", offsets addr=" - << reinterpret_cast<const size_t*>(tr.data.ptr.offsets) << endl; - } - if (tr.target.ptr) { - sp<BBinder> b((BBinder*)tr.cookie); - const status_t error = b->transact(tr.code, buffer, &reply, 0); - if (error < NO_ERROR) reply.setError(error); - - } else { - const status_t error = the_context_object->transact(tr.code, buffer, &reply, 0); - if (error < NO_ERROR) reply.setError(error); - } - - //LOGI("<<<< TRANSACT from pid %d restore pid %d uid %d\n", - // mCallingPid, origPid, origUid); - - if ((tr.flags & TF_ONE_WAY) == 0) { - LOG_ONEWAY("Sending reply to %d!", mCallingPid); - sendReply(reply, 0); - } else { - LOG_ONEWAY("NOT sending reply to %d!", mCallingPid); - } - - mCallingPid = origPid; - mCallingUid = origUid; - - IF_LOG_TRANSACTIONS() { - TextOutput::Bundle _b(alog); - alog << "BC_REPLY thr " << (void*)pthread_self() << " / obj " - << tr.target.ptr << ": " << indent << reply << dedent << endl; - } - - } - break; - - case BR_DEAD_BINDER: - { - BpBinder *proxy = (BpBinder*)mIn.readInt32(); - proxy->sendObituary(); - mOut.writeInt32(BC_DEAD_BINDER_DONE); - mOut.writeInt32((int32_t)proxy); - } break; - - case BR_CLEAR_DEATH_NOTIFICATION_DONE: - { - BpBinder *proxy = (BpBinder*)mIn.readInt32(); - proxy->getWeakRefs()->decWeak(proxy); - } break; - - case BR_FINISHED: - result = TIMED_OUT; - break; - - case BR_NOOP: - break; - - case BR_SPAWN_LOOPER: - mProcess->spawnPooledThread(false); - break; - - default: - printf("*** BAD COMMAND %d received from Binder driver\n", cmd); - result = UNKNOWN_ERROR; - break; - } - - if (result != NO_ERROR) { - mLastError = result; - } - - return result; -} - -void IPCThreadState::threadDestructor(void *st) -{ - IPCThreadState* const self = static_cast<IPCThreadState*>(st); - if (self) { - self->flushCommands(); -#if defined(HAVE_ANDROID_OS) - ioctl(self->mProcess->mDriverFD, BINDER_THREAD_EXIT, 0); -#endif - delete self; - } -} - - -void IPCThreadState::freeBuffer(Parcel* parcel, const uint8_t* data, size_t dataSize, - const size_t* objects, size_t objectsSize, - void* cookie) -{ - //LOGI("Freeing parcel %p", &parcel); - IF_LOG_COMMANDS() { - alog << "Writing BC_FREE_BUFFER for " << data << endl; - } - LOG_ASSERT(data != NULL, "Called with NULL data"); - if (parcel != NULL) parcel->closeFileDescriptors(); - IPCThreadState* state = self(); - state->mOut.writeInt32(BC_FREE_BUFFER); - state->mOut.writeInt32((int32_t)data); -} - -}; // namespace android diff --git a/libs/utils/IPermissionController.cpp b/libs/utils/IPermissionController.cpp deleted file mode 100644 index f01d38f..0000000 --- a/libs/utils/IPermissionController.cpp +++ /dev/null @@ -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 - diff --git a/libs/utils/IServiceManager.cpp b/libs/utils/IServiceManager.cpp deleted file mode 100644 index 9beeadd..0000000 --- a/libs/utils/IServiceManager.cpp +++ /dev/null @@ -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 - diff --git a/libs/utils/InetAddress.cpp b/libs/utils/InetAddress.cpp deleted file mode 100644 index 39a0a68..0000000 --- a/libs/utils/InetAddress.cpp +++ /dev/null @@ -1,236 +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. - */ - -// -// Internet address class. -// -#ifdef HAVE_WINSOCK -# include <winsock2.h> -#else -# include <sys/types.h> -# include <sys/socket.h> -# include <netinet/in.h> -//# include <arpa/inet.h> -# include <netdb.h> -#endif - -#include <utils/inet_address.h> -#include <utils/threads.h> -#include <utils/Log.h> - -#include <errno.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <assert.h> - -using namespace android; - - -/* - * =========================================================================== - * InetAddress - * =========================================================================== - */ - -// lock for the next couple of functions; could tuck into InetAddress -static Mutex* gGHBNLock; - -/* - * Lock/unlock access to the hostent struct returned by gethostbyname(). - */ -static inline void lock_gethostbyname(void) -{ - if (gGHBNLock == NULL) - gGHBNLock = new Mutex; - gGHBNLock->lock(); -} -static inline void unlock_gethostbyname(void) -{ - assert(gGHBNLock != NULL); - gGHBNLock->unlock(); -} - - -/* - * Constructor -- just init members. This is private so that callers - * are required to use getByName(). - */ -InetAddress::InetAddress(void) - : mAddress(NULL), mLength(-1), mName(NULL) -{ -} - -/* - * Destructor -- free address storage. - */ -InetAddress::~InetAddress(void) -{ - delete[] (char*) mAddress; - delete[] mName; -} - -/* - * Copy constructor. - */ -InetAddress::InetAddress(const InetAddress& orig) -{ - *this = orig; // use assignment code -} - -/* - * Assignment operator. - */ -InetAddress& InetAddress::operator=(const InetAddress& addr) -{ - // handle self-assignment - if (this == &addr) - return *this; - // copy mLength and mAddress - mLength = addr.mLength; - if (mLength > 0) { - mAddress = new char[mLength]; - memcpy(mAddress, addr.mAddress, mLength); - LOG(LOG_DEBUG, "socket", - "HEY: copied %d bytes in assignment operator\n", mLength); - } else { - mAddress = NULL; - } - // copy mName - mName = new char[strlen(addr.mName)+1]; - strcpy(mName, addr.mName); - - return *this; -} - -/* - * Create a new object from a name or a dotted-number IP notation. - * - * Returns NULL on failure. - */ -InetAddress* -InetAddress::getByName(const char* host) -{ - InetAddress* newAddr = NULL; - struct sockaddr_in addr; - struct hostent* he; - DurationTimer hostTimer, lockTimer; - - // gethostbyname() isn't reentrant, so we need to lock things until - // we can copy the data out. - lockTimer.start(); - lock_gethostbyname(); - hostTimer.start(); - - he = gethostbyname(host); - if (he == NULL) { - LOG(LOG_WARN, "socket", "WARNING: cannot resolve host %s\n", host); - unlock_gethostbyname(); - return NULL; - } - - memcpy(&addr.sin_addr, he->h_addr, he->h_length); - addr.sin_family = he->h_addrtype; - addr.sin_port = 0; - - // got it, unlock us - hostTimer.stop(); - he = NULL; - unlock_gethostbyname(); - - lockTimer.stop(); - if ((long) lockTimer.durationUsecs() > 100000) { - long lockTime = (long) lockTimer.durationUsecs(); - long hostTime = (long) hostTimer.durationUsecs(); - LOG(LOG_DEBUG, "socket", - "Lookup of %s took %.3fs (gethostbyname=%.3fs lock=%.3fs)\n", - host, lockTime / 1000000.0, hostTime / 1000000.0, - (lockTime - hostTime) / 1000000.0); - } - - // Alloc storage and copy it over. - newAddr = new InetAddress(); - if (newAddr == NULL) - return NULL; - - newAddr->mLength = sizeof(struct sockaddr_in); - newAddr->mAddress = new char[sizeof(struct sockaddr_in)]; - if (newAddr->mAddress == NULL) { - delete newAddr; - return NULL; - } - memcpy(newAddr->mAddress, &addr, newAddr->mLength); - - // Keep this for debug messages. - newAddr->mName = new char[strlen(host)+1]; - if (newAddr->mName == NULL) { - delete newAddr; - return NULL; - } - strcpy(newAddr->mName, host); - - return newAddr; -} - - -/* - * =========================================================================== - * InetSocketAddress - * =========================================================================== - */ - -/* - * Create an address with the host wildcard (INADDR_ANY). - */ -bool InetSocketAddress::create(int port) -{ - assert(mAddress == NULL); - - mAddress = InetAddress::getByName("0.0.0.0"); - if (mAddress == NULL) - return false; - mPort = port; - return true; -} - -/* - * Create address with host and port specified. - */ -bool InetSocketAddress::create(const InetAddress* addr, int port) -{ - assert(mAddress == NULL); - - mAddress = new InetAddress(*addr); // make a copy - if (mAddress == NULL) - return false; - mPort = port; - return true; -} - -/* - * Create address with host and port specified. - */ -bool InetSocketAddress::create(const char* host, int port) -{ - assert(mAddress == NULL); - - mAddress = InetAddress::getByName(host); - if (mAddress == NULL) - return false; - mPort = port; - return true; -} - diff --git a/libs/utils/LogSocket.cpp b/libs/utils/LogSocket.cpp deleted file mode 100644 index 55c1b99..0000000 --- a/libs/utils/LogSocket.cpp +++ /dev/null @@ -1,129 +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. - */ - - -#ifndef HAVE_WINSOCK -//#define SOCKETLOG -#endif - -#ifdef SOCKETLOG - -#define LOG_TAG "SOCKETLOG" - -#include <string.h> -#include <cutils/log.h> -#include "utils/LogSocket.h" -#include "utils/logger.h" -#include "cutils/hashmap.h" - -// defined in //device/data/etc/event-log-tags -#define SOCKET_CLOSE_LOG 51000 - -static Hashmap* statsMap = NULL; - -#define LOG_LIST_NUMBER 5 - -typedef struct SocketStats { - int fd; - unsigned int send; - unsigned int recv; - unsigned int ip; - unsigned short port; - short reason; -}SocketStats; - -SocketStats *get_socket_stats(int fd) { - if (statsMap == NULL) { - statsMap = hashmapCreate(8, &hashmapIntHash, &hashmapIntEquals); - } - - SocketStats *s = (SocketStats*) hashmapGet(statsMap, &fd); - if (s == NULL) { - // LOGD("create SocketStats for fd %d", fd); - s = (SocketStats*) malloc(sizeof(SocketStats)); - memset(s, 0, sizeof(SocketStats)); - s->fd = fd; - hashmapPut(statsMap, &s->fd, s); - } - return s; -} - -void log_socket_connect(int fd, unsigned int ip, unsigned short port) { - // LOGD("log_socket_connect for fd %d ip %d port%d", fd, ip, port); - SocketStats *s = get_socket_stats(fd); - s->ip = ip; - s->port = port; -} - -void add_send_stats(int fd, int send) { - if (send <=0) { - LOGE("add_send_stats send %d", send); - return; - } - SocketStats *s = get_socket_stats(fd); - s->send += send; - // LOGD("add_send_stats for fd %d ip %d port%d", fd, s->ip, s->port); -} - -void add_recv_stats(int fd, int recv) { - if (recv <=0) { - LOGE("add_recv_stats recv %d", recv); - return; - } - SocketStats *s = get_socket_stats(fd); - s->recv += recv; - // LOGD("add_recv_stats for fd %d ip %d port%d", fd, s->ip, s->port); -} - -char* put_int(char* buf, int value) { - *buf = EVENT_TYPE_INT; - buf++; - memcpy(buf, &value, sizeof(int)); - return buf + sizeof(int); -} - -void log_socket_close(int fd, short reason) { - if (statsMap) { - SocketStats *s = (SocketStats*) hashmapGet(statsMap, &fd); - if (s != NULL) { - if (s->send != 0 || s->recv != 0) { - s->reason = reason; - // 5 int + list type need 2 bytes - char buf[LOG_LIST_NUMBER * 5 + 2]; - buf[0] = EVENT_TYPE_LIST; - buf[1] = LOG_LIST_NUMBER; - char* writePos = buf + 2; - writePos = put_int(writePos, s->send); - writePos = put_int(writePos, s->recv); - writePos = put_int(writePos, s->ip); - writePos = put_int(writePos, s->port); - writePos = put_int(writePos, s->reason); - - android_bWriteLog(SOCKET_CLOSE_LOG, buf, sizeof(buf)); - // LOGD("send %d recv %d reason %d", s->send, s->recv, s->reason); - } - hashmapRemove(statsMap, &s->fd); - free(s); - } - } -} - -#else -void add_send_stats(int fd, int send) {} -void add_recv_stats(int fd, int recv) {} -void log_socket_close(int fd, short reason) {} -void log_socket_connect(int fd, unsigned int ip, unsigned short port) {} -#endif diff --git a/libs/utils/MemoryBase.cpp b/libs/utils/MemoryBase.cpp deleted file mode 100644 index f25e11c..0000000 --- a/libs/utils/MemoryBase.cpp +++ /dev/null @@ -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 diff --git a/libs/utils/MemoryDealer.cpp b/libs/utils/MemoryDealer.cpp deleted file mode 100644 index cf8201b..0000000 --- a/libs/utils/MemoryDealer.cpp +++ /dev/null @@ -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 diff --git a/libs/utils/MemoryHeapBase.cpp b/libs/utils/MemoryHeapBase.cpp deleted file mode 100644 index 8251728..0000000 --- a/libs/utils/MemoryHeapBase.cpp +++ /dev/null @@ -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, ®); - 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 diff --git a/libs/utils/MemoryHeapPmem.cpp b/libs/utils/MemoryHeapPmem.cpp deleted file mode 100644 index eba2b30..0000000 --- a/libs/utils/MemoryHeapPmem.cpp +++ /dev/null @@ -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 diff --git a/libs/utils/Parcel.cpp b/libs/utils/Parcel.cpp deleted file mode 100644 index b0e3750..0000000 --- a/libs/utils/Parcel.cpp +++ /dev/null @@ -1,1363 +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 "Parcel" -//#define LOG_NDEBUG 0 - -#include <utils/Parcel.h> - -#include <utils/Binder.h> -#include <utils/BpBinder.h> -#include <utils/Debug.h> -#include <utils/ProcessState.h> -#include <utils/Log.h> -#include <utils/String8.h> -#include <utils/String16.h> -#include <utils/TextOutput.h> -#include <utils/misc.h> - -#include <private/utils/binder_module.h> - -#include <stdio.h> -#include <stdlib.h> -#include <stdint.h> - -#ifndef INT32_MAX -#define INT32_MAX ((int32_t)(2147483647)) -#endif - -#define LOG_REFS(...) -//#define LOG_REFS(...) LOG(LOG_DEBUG, "Parcel", __VA_ARGS__) - -// --------------------------------------------------------------------------- - -#define PAD_SIZE(s) (((s)+3)&~3) - -// XXX This can be made public if we want to provide -// support for typed data. -struct small_flat_data -{ - uint32_t type; - uint32_t data; -}; - -namespace android { - -void acquire_object(const sp<ProcessState>& proc, - const flat_binder_object& obj, const void* who) -{ - switch (obj.type) { - case BINDER_TYPE_BINDER: - if (obj.binder) { - LOG_REFS("Parcel %p acquiring reference on local %p", who, obj.cookie); - static_cast<IBinder*>(obj.cookie)->incStrong(who); - } - return; - case BINDER_TYPE_WEAK_BINDER: - if (obj.binder) - static_cast<RefBase::weakref_type*>(obj.binder)->incWeak(who); - return; - case BINDER_TYPE_HANDLE: { - const sp<IBinder> b = proc->getStrongProxyForHandle(obj.handle); - if (b != NULL) { - LOG_REFS("Parcel %p acquiring reference on remote %p", who, b.get()); - b->incStrong(who); - } - return; - } - case BINDER_TYPE_WEAK_HANDLE: { - const wp<IBinder> b = proc->getWeakProxyForHandle(obj.handle); - if (b != NULL) b.get_refs()->incWeak(who); - return; - } - case BINDER_TYPE_FD: { - // intentionally blank -- nothing to do to acquire this, but we do - // recognize it as a legitimate object type. - return; - } - } - - LOGD("Invalid object type 0x%08lx", obj.type); -} - -void release_object(const sp<ProcessState>& proc, - const flat_binder_object& obj, const void* who) -{ - switch (obj.type) { - case BINDER_TYPE_BINDER: - if (obj.binder) { - LOG_REFS("Parcel %p releasing reference on local %p", who, obj.cookie); - static_cast<IBinder*>(obj.cookie)->decStrong(who); - } - return; - case BINDER_TYPE_WEAK_BINDER: - if (obj.binder) - static_cast<RefBase::weakref_type*>(obj.binder)->decWeak(who); - return; - case BINDER_TYPE_HANDLE: { - const sp<IBinder> b = proc->getStrongProxyForHandle(obj.handle); - if (b != NULL) { - LOG_REFS("Parcel %p releasing reference on remote %p", who, b.get()); - b->decStrong(who); - } - return; - } - case BINDER_TYPE_WEAK_HANDLE: { - const wp<IBinder> b = proc->getWeakProxyForHandle(obj.handle); - if (b != NULL) b.get_refs()->decWeak(who); - return; - } - case BINDER_TYPE_FD: { - if (obj.cookie != (void*)0) close(obj.handle); - return; - } - } - - LOGE("Invalid object type 0x%08lx", obj.type); -} - -inline static status_t finish_flatten_binder( - const sp<IBinder>& binder, const flat_binder_object& flat, Parcel* out) -{ - return out->writeObject(flat, false); -} - -status_t flatten_binder(const sp<ProcessState>& proc, - const sp<IBinder>& binder, Parcel* out) -{ - flat_binder_object obj; - - obj.flags = 0x7f | FLAT_BINDER_FLAG_ACCEPTS_FDS; - if (binder != NULL) { - IBinder *local = binder->localBinder(); - if (!local) { - BpBinder *proxy = binder->remoteBinder(); - if (proxy == NULL) { - LOGE("null proxy"); - } - const int32_t handle = proxy ? proxy->handle() : 0; - obj.type = BINDER_TYPE_HANDLE; - obj.handle = handle; - obj.cookie = NULL; - } else { - obj.type = BINDER_TYPE_BINDER; - obj.binder = local->getWeakRefs(); - obj.cookie = local; - } - } else { - obj.type = BINDER_TYPE_BINDER; - obj.binder = NULL; - obj.cookie = NULL; - } - - return finish_flatten_binder(binder, obj, out); -} - -status_t flatten_binder(const sp<ProcessState>& proc, - const wp<IBinder>& binder, Parcel* out) -{ - flat_binder_object obj; - - obj.flags = 0x7f | FLAT_BINDER_FLAG_ACCEPTS_FDS; - if (binder != NULL) { - sp<IBinder> real = binder.promote(); - if (real != NULL) { - IBinder *local = real->localBinder(); - if (!local) { - BpBinder *proxy = real->remoteBinder(); - if (proxy == NULL) { - LOGE("null proxy"); - } - const int32_t handle = proxy ? proxy->handle() : 0; - obj.type = BINDER_TYPE_WEAK_HANDLE; - obj.handle = handle; - obj.cookie = NULL; - } else { - obj.type = BINDER_TYPE_WEAK_BINDER; - obj.binder = binder.get_refs(); - obj.cookie = binder.unsafe_get(); - } - return finish_flatten_binder(real, obj, out); - } - - // XXX How to deal? In order to flatten the given binder, - // we need to probe it for information, which requires a primary - // reference... but we don't have one. - // - // The OpenBinder implementation uses a dynamic_cast<> here, - // but we can't do that with the different reference counting - // implementation we are using. - LOGE("Unable to unflatten Binder weak reference!"); - obj.type = BINDER_TYPE_BINDER; - obj.binder = NULL; - obj.cookie = NULL; - return finish_flatten_binder(NULL, obj, out); - - } else { - obj.type = BINDER_TYPE_BINDER; - obj.binder = NULL; - obj.cookie = NULL; - return finish_flatten_binder(NULL, obj, out); - } -} - -inline static status_t finish_unflatten_binder( - BpBinder* proxy, const flat_binder_object& flat, const Parcel& in) -{ - return NO_ERROR; -} - -status_t unflatten_binder(const sp<ProcessState>& proc, - const Parcel& in, sp<IBinder>* out) -{ - const flat_binder_object* flat = in.readObject(false); - - if (flat) { - switch (flat->type) { - case BINDER_TYPE_BINDER: - *out = static_cast<IBinder*>(flat->cookie); - return finish_unflatten_binder(NULL, *flat, in); - case BINDER_TYPE_HANDLE: - *out = proc->getStrongProxyForHandle(flat->handle); - return finish_unflatten_binder( - static_cast<BpBinder*>(out->get()), *flat, in); - } - } - return BAD_TYPE; -} - -status_t unflatten_binder(const sp<ProcessState>& proc, - const Parcel& in, wp<IBinder>* out) -{ - const flat_binder_object* flat = in.readObject(false); - - if (flat) { - switch (flat->type) { - case BINDER_TYPE_BINDER: - *out = static_cast<IBinder*>(flat->cookie); - return finish_unflatten_binder(NULL, *flat, in); - case BINDER_TYPE_WEAK_BINDER: - if (flat->binder != NULL) { - out->set_object_and_refs( - static_cast<IBinder*>(flat->cookie), - static_cast<RefBase::weakref_type*>(flat->binder)); - } else { - *out = NULL; - } - return finish_unflatten_binder(NULL, *flat, in); - case BINDER_TYPE_HANDLE: - case BINDER_TYPE_WEAK_HANDLE: - *out = proc->getWeakProxyForHandle(flat->handle); - return finish_unflatten_binder( - static_cast<BpBinder*>(out->unsafe_get()), *flat, in); - } - } - return BAD_TYPE; -} - -// --------------------------------------------------------------------------- - -Parcel::Parcel() -{ - initState(); -} - -Parcel::~Parcel() -{ - freeDataNoInit(); -} - -const uint8_t* Parcel::data() const -{ - return mData; -} - -size_t Parcel::dataSize() const -{ - return (mDataSize > mDataPos ? mDataSize : mDataPos); -} - -size_t Parcel::dataAvail() const -{ - // TODO: decide what to do about the possibility that this can - // report an available-data size that exceeds a Java int's max - // positive value, causing havoc. Fortunately this will only - // happen if someone constructs a Parcel containing more than two - // gigabytes of data, which on typical phone hardware is simply - // not possible. - return dataSize() - dataPosition(); -} - -size_t Parcel::dataPosition() const -{ - return mDataPos; -} - -size_t Parcel::dataCapacity() const -{ - return mDataCapacity; -} - -status_t Parcel::setDataSize(size_t size) -{ - status_t err; - err = continueWrite(size); - if (err == NO_ERROR) { - mDataSize = size; - LOGV("setDataSize Setting data size of %p to %d\n", this, mDataSize); - } - return err; -} - -void Parcel::setDataPosition(size_t pos) const -{ - mDataPos = pos; - mNextObjectHint = 0; -} - -status_t Parcel::setDataCapacity(size_t size) -{ - if (size > mDataSize) return continueWrite(size); - return NO_ERROR; -} - -status_t Parcel::setData(const uint8_t* buffer, size_t len) -{ - status_t err = restartWrite(len); - if (err == NO_ERROR) { - memcpy(const_cast<uint8_t*>(data()), buffer, len); - mDataSize = len; - mFdsKnown = false; - } - return err; -} - -status_t Parcel::appendFrom(Parcel *parcel, size_t offset, size_t len) -{ - const sp<ProcessState> proc(ProcessState::self()); - status_t err; - uint8_t *data = parcel->mData; - size_t *objects = parcel->mObjects; - size_t size = parcel->mObjectsSize; - int startPos = mDataPos; - int firstIndex = -1, lastIndex = -2; - - if (len == 0) { - return NO_ERROR; - } - - // range checks against the source parcel size - if ((offset > parcel->mDataSize) - || (len > parcel->mDataSize) - || (offset + len > parcel->mDataSize)) { - return BAD_VALUE; - } - - // Count objects in range - for (int i = 0; i < (int) size; i++) { - size_t off = objects[i]; - if ((off >= offset) && (off < offset + len)) { - if (firstIndex == -1) { - firstIndex = i; - } - lastIndex = i; - } - } - int numObjects = lastIndex - firstIndex + 1; - - // grow data - err = growData(len); - if (err != NO_ERROR) { - return err; - } - - // append data - memcpy(mData + mDataPos, data + offset, len); - mDataPos += len; - mDataSize += len; - - if (numObjects > 0) { - // grow objects - if (mObjectsCapacity < mObjectsSize + numObjects) { - int newSize = ((mObjectsSize + numObjects)*3)/2; - size_t *objects = - (size_t*)realloc(mObjects, newSize*sizeof(size_t)); - if (objects == (size_t*)0) { - return NO_MEMORY; - } - mObjects = objects; - mObjectsCapacity = newSize; - } - - // append and acquire objects - int idx = mObjectsSize; - for (int i = firstIndex; i <= lastIndex; i++) { - size_t off = objects[i] - offset + startPos; - mObjects[idx++] = off; - mObjectsSize++; - - flat_binder_object* flat - = reinterpret_cast<flat_binder_object*>(mData + off); - acquire_object(proc, *flat, this); - - if (flat->type == BINDER_TYPE_FD) { - // If this is a file descriptor, we need to dup it so the - // new Parcel now owns its own fd, and can declare that we - // officially know we have fds. - flat->handle = dup(flat->handle); - flat->cookie = (void*)1; - mHasFds = mFdsKnown = true; - } - } - } - - return NO_ERROR; -} - -bool Parcel::hasFileDescriptors() const -{ - if (!mFdsKnown) { - scanForFds(); - } - return mHasFds; -} - -status_t Parcel::writeInterfaceToken(const String16& interface) -{ - // currently the interface identification token is just its name as a string - return writeString16(interface); -} - -bool Parcel::enforceInterface(const String16& interface) const -{ - String16 str = readString16(); - if (str == interface) { - return true; - } else { - LOGW("**** enforceInterface() expected '%s' but read '%s'\n", - String8(interface).string(), String8(str).string()); - return false; - } -} - -const size_t* Parcel::objects() const -{ - return mObjects; -} - -size_t Parcel::objectsCount() const -{ - return mObjectsSize; -} - -status_t Parcel::errorCheck() const -{ - return mError; -} - -void Parcel::setError(status_t err) -{ - mError = err; -} - -status_t Parcel::finishWrite(size_t len) -{ - //printf("Finish write of %d\n", len); - mDataPos += len; - LOGV("finishWrite Setting data pos of %p to %d\n", this, mDataPos); - if (mDataPos > mDataSize) { - mDataSize = mDataPos; - LOGV("finishWrite Setting data size of %p to %d\n", this, mDataSize); - } - //printf("New pos=%d, size=%d\n", mDataPos, mDataSize); - return NO_ERROR; -} - -status_t Parcel::writeUnpadded(const void* data, size_t len) -{ - size_t end = mDataPos + len; - if (end < mDataPos) { - // integer overflow - return BAD_VALUE; - } - - if (end <= mDataCapacity) { -restart_write: - memcpy(mData+mDataPos, data, len); - return finishWrite(len); - } - - status_t err = growData(len); - if (err == NO_ERROR) goto restart_write; - return err; -} - -status_t Parcel::write(const void* data, size_t len) -{ - void* const d = writeInplace(len); - if (d) { - memcpy(d, data, len); - return NO_ERROR; - } - return mError; -} - -void* Parcel::writeInplace(size_t len) -{ - const size_t padded = PAD_SIZE(len); - - // sanity check for integer overflow - if (mDataPos+padded < mDataPos) { - return NULL; - } - - if ((mDataPos+padded) <= mDataCapacity) { -restart_write: - //printf("Writing %ld bytes, padded to %ld\n", len, padded); - uint8_t* const data = mData+mDataPos; - - // Need to pad at end? - if (padded != len) { -#if BYTE_ORDER == BIG_ENDIAN - static const uint32_t mask[4] = { - 0x00000000, 0xffffff00, 0xffff0000, 0xff000000 - }; -#endif -#if BYTE_ORDER == LITTLE_ENDIAN - static const uint32_t mask[4] = { - 0x00000000, 0x00ffffff, 0x0000ffff, 0x000000ff - }; -#endif - //printf("Applying pad mask: %p to %p\n", (void*)mask[padded-len], - // *reinterpret_cast<void**>(data+padded-4)); - *reinterpret_cast<uint32_t*>(data+padded-4) &= mask[padded-len]; - } - - finishWrite(padded); - return data; - } - - status_t err = growData(padded); - if (err == NO_ERROR) goto restart_write; - return NULL; -} - -status_t Parcel::writeInt32(int32_t val) -{ - if ((mDataPos+sizeof(val)) <= mDataCapacity) { -restart_write: - *reinterpret_cast<int32_t*>(mData+mDataPos) = val; - return finishWrite(sizeof(val)); - } - - status_t err = growData(sizeof(val)); - if (err == NO_ERROR) goto restart_write; - return err; -} - -status_t Parcel::writeInt64(int64_t val) -{ - if ((mDataPos+sizeof(val)) <= mDataCapacity) { -restart_write: - *reinterpret_cast<int64_t*>(mData+mDataPos) = val; - return finishWrite(sizeof(val)); - } - - status_t err = growData(sizeof(val)); - if (err == NO_ERROR) goto restart_write; - return err; -} - -status_t Parcel::writeFloat(float val) -{ - if ((mDataPos+sizeof(val)) <= mDataCapacity) { -restart_write: - *reinterpret_cast<float*>(mData+mDataPos) = val; - return finishWrite(sizeof(val)); - } - - status_t err = growData(sizeof(val)); - if (err == NO_ERROR) goto restart_write; - return err; -} - -status_t Parcel::writeDouble(double val) -{ - if ((mDataPos+sizeof(val)) <= mDataCapacity) { -restart_write: - *reinterpret_cast<double*>(mData+mDataPos) = val; - return finishWrite(sizeof(val)); - } - - status_t err = growData(sizeof(val)); - if (err == NO_ERROR) goto restart_write; - return err; -} - -status_t Parcel::writeCString(const char* str) -{ - return write(str, strlen(str)+1); -} - -status_t Parcel::writeString8(const String8& str) -{ - status_t err = writeInt32(str.bytes()); - if (err == NO_ERROR) { - err = write(str.string(), str.bytes()+1); - } - return err; -} - -status_t Parcel::writeString16(const String16& str) -{ - return writeString16(str.string(), str.size()); -} - -status_t Parcel::writeString16(const char16_t* str, size_t len) -{ - if (str == NULL) return writeInt32(-1); - - status_t err = writeInt32(len); - if (err == NO_ERROR) { - len *= sizeof(char16_t); - uint8_t* data = (uint8_t*)writeInplace(len+sizeof(char16_t)); - if (data) { - memcpy(data, str, len); - *reinterpret_cast<char16_t*>(data+len) = 0; - return NO_ERROR; - } - err = mError; - } - return err; -} - -status_t Parcel::writeStrongBinder(const sp<IBinder>& val) -{ - return flatten_binder(ProcessState::self(), val, this); -} - -status_t Parcel::writeWeakBinder(const wp<IBinder>& val) -{ - return flatten_binder(ProcessState::self(), val, this); -} - -status_t Parcel::writeNativeHandle(const native_handle* handle) -{ - if (handle->version != sizeof(native_handle)) - return BAD_TYPE; - - status_t err; - err = writeInt32(handle->numFds); - if (err != NO_ERROR) return err; - - err = writeInt32(handle->numInts); - if (err != NO_ERROR) return err; - - for (int i=0 ; err==NO_ERROR && i<handle->numFds ; i++) - err = writeDupFileDescriptor(handle->data[i]); - - if (err != NO_ERROR) { - LOGD("write native handle, write dup fd failed"); - return err; - } - err = write(handle->data + handle->numFds, sizeof(int)*handle->numInts); - return err; -} - -status_t Parcel::writeFileDescriptor(int fd) -{ - flat_binder_object obj; - obj.type = BINDER_TYPE_FD; - obj.flags = 0x7f | FLAT_BINDER_FLAG_ACCEPTS_FDS; - obj.handle = fd; - obj.cookie = (void*)0; - return writeObject(obj, true); -} - -status_t Parcel::writeDupFileDescriptor(int fd) -{ - flat_binder_object obj; - obj.type = BINDER_TYPE_FD; - obj.flags = 0x7f | FLAT_BINDER_FLAG_ACCEPTS_FDS; - obj.handle = dup(fd); - obj.cookie = (void*)1; - return writeObject(obj, true); -} - -status_t Parcel::writeObject(const flat_binder_object& val, bool nullMetaData) -{ - const bool enoughData = (mDataPos+sizeof(val)) <= mDataCapacity; - const bool enoughObjects = mObjectsSize < mObjectsCapacity; - if (enoughData && enoughObjects) { -restart_write: - *reinterpret_cast<flat_binder_object*>(mData+mDataPos) = val; - - // Need to write meta-data? - if (nullMetaData || val.binder != NULL) { - mObjects[mObjectsSize] = mDataPos; - acquire_object(ProcessState::self(), val, this); - mObjectsSize++; - } - - // remember if it's a file descriptor - if (val.type == BINDER_TYPE_FD) { - mHasFds = mFdsKnown = true; - } - - return finishWrite(sizeof(flat_binder_object)); - } - - if (!enoughData) { - const status_t err = growData(sizeof(val)); - if (err != NO_ERROR) return err; - } - if (!enoughObjects) { - size_t newSize = ((mObjectsSize+2)*3)/2; - size_t* objects = (size_t*)realloc(mObjects, newSize*sizeof(size_t)); - if (objects == NULL) return NO_MEMORY; - mObjects = objects; - mObjectsCapacity = newSize; - } - - goto restart_write; -} - - -void Parcel::remove(size_t start, size_t amt) -{ - LOG_ALWAYS_FATAL("Parcel::remove() not yet implemented!"); -} - -status_t Parcel::read(void* outData, size_t len) const -{ - if ((mDataPos+PAD_SIZE(len)) >= mDataPos && (mDataPos+PAD_SIZE(len)) <= mDataSize) { - memcpy(outData, mData+mDataPos, len); - mDataPos += PAD_SIZE(len); - LOGV("read Setting data pos of %p to %d\n", this, mDataPos); - return NO_ERROR; - } - return NOT_ENOUGH_DATA; -} - -const void* Parcel::readInplace(size_t len) const -{ - if ((mDataPos+PAD_SIZE(len)) >= mDataPos && (mDataPos+PAD_SIZE(len)) <= mDataSize) { - const void* data = mData+mDataPos; - mDataPos += PAD_SIZE(len); - LOGV("readInplace Setting data pos of %p to %d\n", this, mDataPos); - return data; - } - return NULL; -} - -status_t Parcel::readInt32(int32_t *pArg) const -{ - if ((mDataPos+sizeof(int32_t)) <= mDataSize) { - const void* data = mData+mDataPos; - mDataPos += sizeof(int32_t); - *pArg = *reinterpret_cast<const int32_t*>(data); - return NO_ERROR; - } else { - return NOT_ENOUGH_DATA; - } -} - -int32_t Parcel::readInt32() const -{ - if ((mDataPos+sizeof(int32_t)) <= mDataSize) { - const void* data = mData+mDataPos; - mDataPos += sizeof(int32_t); - LOGV("readInt32 Setting data pos of %p to %d\n", this, mDataPos); - return *reinterpret_cast<const int32_t*>(data); - } - return 0; -} - - -status_t Parcel::readInt64(int64_t *pArg) const -{ - if ((mDataPos+sizeof(int64_t)) <= mDataSize) { - const void* data = mData+mDataPos; - mDataPos += sizeof(int64_t); - *pArg = *reinterpret_cast<const int64_t*>(data); - LOGV("readInt64 Setting data pos of %p to %d\n", this, mDataPos); - return NO_ERROR; - } else { - return NOT_ENOUGH_DATA; - } -} - - -int64_t Parcel::readInt64() const -{ - if ((mDataPos+sizeof(int64_t)) <= mDataSize) { - const void* data = mData+mDataPos; - mDataPos += sizeof(int64_t); - LOGV("readInt64 Setting data pos of %p to %d\n", this, mDataPos); - return *reinterpret_cast<const int64_t*>(data); - } - return 0; -} - -status_t Parcel::readFloat(float *pArg) const -{ - if ((mDataPos+sizeof(float)) <= mDataSize) { - const void* data = mData+mDataPos; - mDataPos += sizeof(float); - LOGV("readFloat Setting data pos of %p to %d\n", this, mDataPos); - *pArg = *reinterpret_cast<const float*>(data); - return NO_ERROR; - } else { - return NOT_ENOUGH_DATA; - } -} - - -float Parcel::readFloat() const -{ - if ((mDataPos+sizeof(float)) <= mDataSize) { - const void* data = mData+mDataPos; - mDataPos += sizeof(float); - LOGV("readFloat Setting data pos of %p to %d\n", this, mDataPos); - return *reinterpret_cast<const float*>(data); - } - return 0; -} - -status_t Parcel::readDouble(double *pArg) const -{ - if ((mDataPos+sizeof(double)) <= mDataSize) { - const void* data = mData+mDataPos; - mDataPos += sizeof(double); - LOGV("readDouble Setting data pos of %p to %d\n", this, mDataPos); - *pArg = *reinterpret_cast<const double*>(data); - return NO_ERROR; - } else { - return NOT_ENOUGH_DATA; - } -} - - -double Parcel::readDouble() const -{ - if ((mDataPos+sizeof(double)) <= mDataSize) { - const void* data = mData+mDataPos; - mDataPos += sizeof(double); - LOGV("readDouble Setting data pos of %p to %d\n", this, mDataPos); - return *reinterpret_cast<const double*>(data); - } - return 0; -} - - -const char* Parcel::readCString() const -{ - const size_t avail = mDataSize-mDataPos; - if (avail > 0) { - const char* str = reinterpret_cast<const char*>(mData+mDataPos); - // is the string's trailing NUL within the parcel's valid bounds? - const char* eos = reinterpret_cast<const char*>(memchr(str, 0, avail)); - if (eos) { - const size_t len = eos - str; - mDataPos += PAD_SIZE(len+1); - LOGV("readCString Setting data pos of %p to %d\n", this, mDataPos); - return str; - } - } - return NULL; -} - -String8 Parcel::readString8() const -{ - int32_t size = readInt32(); - // watch for potential int overflow adding 1 for trailing NUL - if (size > 0 && size < INT32_MAX) { - const char* str = (const char*)readInplace(size+1); - if (str) return String8(str, size); - } - return String8(); -} - -String16 Parcel::readString16() const -{ - size_t len; - const char16_t* str = readString16Inplace(&len); - if (str) return String16(str, len); - LOGE("Reading a NULL string not supported here."); - return String16(); -} - -const char16_t* Parcel::readString16Inplace(size_t* outLen) const -{ - int32_t size = readInt32(); - // watch for potential int overflow from size+1 - if (size >= 0 && size < INT32_MAX) { - *outLen = size; - const char16_t* str = (const char16_t*)readInplace((size+1)*sizeof(char16_t)); - if (str != NULL) { - return str; - } - } - *outLen = 0; - return NULL; -} - -sp<IBinder> Parcel::readStrongBinder() const -{ - sp<IBinder> val; - unflatten_binder(ProcessState::self(), *this, &val); - return val; -} - -wp<IBinder> Parcel::readWeakBinder() const -{ - wp<IBinder> val; - unflatten_binder(ProcessState::self(), *this, &val); - return val; -} - - -native_handle* Parcel::readNativeHandle() const -{ - int numFds, numInts; - status_t err; - err = readInt32(&numFds); - if (err != NO_ERROR) return 0; - err = readInt32(&numInts); - if (err != NO_ERROR) return 0; - - native_handle* h = native_handle_create(numFds, numInts); - for (int i=0 ; err==NO_ERROR && i<numFds ; i++) { - h->data[i] = dup(readFileDescriptor()); - if (h->data[i] < 0) err = BAD_VALUE; - } - err = read(h->data + numFds, sizeof(int)*numInts); - if (err != NO_ERROR) { - native_handle_close(h); - native_handle_delete(h); - h = 0; - } - return h; -} - - -int Parcel::readFileDescriptor() const -{ - const flat_binder_object* flat = readObject(true); - if (flat) { - switch (flat->type) { - case BINDER_TYPE_FD: - //LOGI("Returning file descriptor %ld from parcel %p\n", flat->handle, this); - return flat->handle; - } - } - return BAD_TYPE; -} - -const flat_binder_object* Parcel::readObject(bool nullMetaData) const -{ - const size_t DPOS = mDataPos; - if ((DPOS+sizeof(flat_binder_object)) <= mDataSize) { - const flat_binder_object* obj - = reinterpret_cast<const flat_binder_object*>(mData+DPOS); - mDataPos = DPOS + sizeof(flat_binder_object); - if (!nullMetaData && (obj->cookie == NULL && obj->binder == NULL)) { - // When transferring a NULL object, we don't write it into - // the object list, so we don't want to check for it when - // reading. - LOGV("readObject Setting data pos of %p to %d\n", this, mDataPos); - return obj; - } - - // Ensure that this object is valid... - size_t* const OBJS = mObjects; - const size_t N = mObjectsSize; - size_t opos = mNextObjectHint; - - if (N > 0) { - LOGV("Parcel %p looking for obj at %d, hint=%d\n", - this, DPOS, opos); - - // Start at the current hint position, looking for an object at - // the current data position. - if (opos < N) { - while (opos < (N-1) && OBJS[opos] < DPOS) { - opos++; - } - } else { - opos = N-1; - } - if (OBJS[opos] == DPOS) { - // Found it! - LOGV("Parcel found obj %d at index %d with forward search", - this, DPOS, opos); - mNextObjectHint = opos+1; - LOGV("readObject Setting data pos of %p to %d\n", this, mDataPos); - return obj; - } - - // Look backwards for it... - while (opos > 0 && OBJS[opos] > DPOS) { - opos--; - } - if (OBJS[opos] == DPOS) { - // Found it! - LOGV("Parcel found obj %d at index %d with backward search", - this, DPOS, opos); - mNextObjectHint = opos+1; - LOGV("readObject Setting data pos of %p to %d\n", this, mDataPos); - return obj; - } - } - LOGW("Attempt to read object from Parcel %p at offset %d that is not in the object list", - this, DPOS); - } - return NULL; -} - -void Parcel::closeFileDescriptors() -{ - size_t i = mObjectsSize; - if (i > 0) { - //LOGI("Closing file descriptors for %d objects...", mObjectsSize); - } - while (i > 0) { - i--; - const flat_binder_object* flat - = reinterpret_cast<flat_binder_object*>(mData+mObjects[i]); - if (flat->type == BINDER_TYPE_FD) { - //LOGI("Closing fd: %ld\n", flat->handle); - close(flat->handle); - } - } -} - -const uint8_t* Parcel::ipcData() const -{ - return mData; -} - -size_t Parcel::ipcDataSize() const -{ - return (mDataSize > mDataPos ? mDataSize : mDataPos); -} - -const size_t* Parcel::ipcObjects() const -{ - return mObjects; -} - -size_t Parcel::ipcObjectsCount() const -{ - return mObjectsSize; -} - -void Parcel::ipcSetDataReference(const uint8_t* data, size_t dataSize, - const size_t* objects, size_t objectsCount, release_func relFunc, void* relCookie) -{ - freeDataNoInit(); - mError = NO_ERROR; - mData = const_cast<uint8_t*>(data); - mDataSize = mDataCapacity = dataSize; - //LOGI("setDataReference Setting data size of %p to %lu (pid=%d)\n", this, mDataSize, getpid()); - mDataPos = 0; - LOGV("setDataReference Setting data pos of %p to %d\n", this, mDataPos); - mObjects = const_cast<size_t*>(objects); - mObjectsSize = mObjectsCapacity = objectsCount; - mNextObjectHint = 0; - mOwner = relFunc; - mOwnerCookie = relCookie; - scanForFds(); -} - -void Parcel::print(TextOutput& to, uint32_t flags) const -{ - to << "Parcel("; - - if (errorCheck() != NO_ERROR) { - const status_t err = errorCheck(); - to << "Error: " << (void*)err << " \"" << strerror(-err) << "\""; - } else if (dataSize() > 0) { - const uint8_t* DATA = data(); - to << indent << HexDump(DATA, dataSize()) << dedent; - const size_t* OBJS = objects(); - const size_t N = objectsCount(); - for (size_t i=0; i<N; i++) { - const flat_binder_object* flat - = reinterpret_cast<const flat_binder_object*>(DATA+OBJS[i]); - to << endl << "Object #" << i << " @ " << (void*)OBJS[i] << ": " - << TypeCode(flat->type & 0x7f7f7f00) - << " = " << flat->binder; - } - } else { - to << "NULL"; - } - - to << ")"; -} - -void Parcel::releaseObjects() -{ - const sp<ProcessState> proc(ProcessState::self()); - size_t i = mObjectsSize; - uint8_t* const data = mData; - size_t* const objects = mObjects; - while (i > 0) { - i--; - const flat_binder_object* flat - = reinterpret_cast<flat_binder_object*>(data+objects[i]); - release_object(proc, *flat, this); - } -} - -void Parcel::acquireObjects() -{ - const sp<ProcessState> proc(ProcessState::self()); - size_t i = mObjectsSize; - uint8_t* const data = mData; - size_t* const objects = mObjects; - while (i > 0) { - i--; - const flat_binder_object* flat - = reinterpret_cast<flat_binder_object*>(data+objects[i]); - acquire_object(proc, *flat, this); - } -} - -void Parcel::freeData() -{ - freeDataNoInit(); - initState(); -} - -void Parcel::freeDataNoInit() -{ - if (mOwner) { - //LOGI("Freeing data ref of %p (pid=%d)\n", this, getpid()); - mOwner(this, mData, mDataSize, mObjects, mObjectsSize, mOwnerCookie); - } else { - releaseObjects(); - if (mData) free(mData); - if (mObjects) free(mObjects); - } -} - -status_t Parcel::growData(size_t len) -{ - size_t newSize = ((mDataSize+len)*3)/2; - return (newSize <= mDataSize) - ? (status_t) NO_MEMORY - : continueWrite(newSize); -} - -status_t Parcel::restartWrite(size_t desired) -{ - if (mOwner) { - freeData(); - return continueWrite(desired); - } - - uint8_t* data = (uint8_t*)realloc(mData, desired); - if (!data && desired > mDataCapacity) { - mError = NO_MEMORY; - return NO_MEMORY; - } - - releaseObjects(); - - if (data) { - mData = data; - mDataCapacity = desired; - } - - mDataSize = mDataPos = 0; - LOGV("restartWrite Setting data size of %p to %d\n", this, mDataSize); - LOGV("restartWrite Setting data pos of %p to %d\n", this, mDataPos); - - free(mObjects); - mObjects = NULL; - mObjectsSize = mObjectsCapacity = 0; - mNextObjectHint = 0; - mHasFds = false; - mFdsKnown = true; - - return NO_ERROR; -} - -status_t Parcel::continueWrite(size_t desired) -{ - // If shrinking, first adjust for any objects that appear - // after the new data size. - size_t objectsSize = mObjectsSize; - if (desired < mDataSize) { - if (desired == 0) { - objectsSize = 0; - } else { - while (objectsSize > 0) { - if (mObjects[objectsSize-1] < desired) - break; - objectsSize--; - } - } - } - - if (mOwner) { - // If the size is going to zero, just release the owner's data. - if (desired == 0) { - freeData(); - return NO_ERROR; - } - - // If there is a different owner, we need to take - // posession. - uint8_t* data = (uint8_t*)malloc(desired); - if (!data) { - mError = NO_MEMORY; - return NO_MEMORY; - } - size_t* objects = NULL; - - if (objectsSize) { - objects = (size_t*)malloc(objectsSize*sizeof(size_t)); - if (!objects) { - mError = NO_MEMORY; - return NO_MEMORY; - } - - // Little hack to only acquire references on objects - // we will be keeping. - size_t oldObjectsSize = mObjectsSize; - mObjectsSize = objectsSize; - acquireObjects(); - mObjectsSize = oldObjectsSize; - } - - if (mData) { - memcpy(data, mData, mDataSize < desired ? mDataSize : desired); - } - if (objects && mObjects) { - memcpy(objects, mObjects, objectsSize*sizeof(size_t)); - } - //LOGI("Freeing data ref of %p (pid=%d)\n", this, getpid()); - mOwner(this, mData, mDataSize, mObjects, mObjectsSize, mOwnerCookie); - mOwner = NULL; - - mData = data; - mObjects = objects; - mDataSize = (mDataSize < desired) ? mDataSize : desired; - LOGV("continueWrite Setting data size of %p to %d\n", this, mDataSize); - mDataCapacity = desired; - mObjectsSize = mObjectsCapacity = objectsSize; - mNextObjectHint = 0; - - } else if (mData) { - if (objectsSize < mObjectsSize) { - // Need to release refs on any objects we are dropping. - const sp<ProcessState> proc(ProcessState::self()); - for (size_t i=objectsSize; i<mObjectsSize; i++) { - const flat_binder_object* flat - = reinterpret_cast<flat_binder_object*>(mData+mObjects[i]); - if (flat->type == BINDER_TYPE_FD) { - // will need to rescan because we may have lopped off the only FDs - mFdsKnown = false; - } - release_object(proc, *flat, this); - } - size_t* objects = - (size_t*)realloc(mObjects, objectsSize*sizeof(size_t)); - if (objects) { - mObjects = objects; - } - mObjectsSize = objectsSize; - mNextObjectHint = 0; - } - - // We own the data, so we can just do a realloc(). - if (desired > mDataCapacity) { - uint8_t* data = (uint8_t*)realloc(mData, desired); - if (data) { - mData = data; - mDataCapacity = desired; - } else if (desired > mDataCapacity) { - mError = NO_MEMORY; - return NO_MEMORY; - } - } else { - mDataSize = desired; - LOGV("continueWrite Setting data size of %p to %d\n", this, mDataSize); - if (mDataPos > desired) { - mDataPos = desired; - LOGV("continueWrite Setting data pos of %p to %d\n", this, mDataPos); - } - } - - } else { - // This is the first data. Easy! - uint8_t* data = (uint8_t*)malloc(desired); - if (!data) { - mError = NO_MEMORY; - return NO_MEMORY; - } - - if(!(mDataCapacity == 0 && mObjects == NULL - && mObjectsCapacity == 0)) { - LOGE("continueWrite: %d/%p/%d/%d", mDataCapacity, mObjects, mObjectsCapacity, desired); - } - - mData = data; - mDataSize = mDataPos = 0; - LOGV("continueWrite Setting data size of %p to %d\n", this, mDataSize); - LOGV("continueWrite Setting data pos of %p to %d\n", this, mDataPos); - mDataCapacity = desired; - } - - return NO_ERROR; -} - -void Parcel::initState() -{ - mError = NO_ERROR; - mData = 0; - mDataSize = 0; - mDataCapacity = 0; - mDataPos = 0; - LOGV("initState Setting data size of %p to %d\n", this, mDataSize); - LOGV("initState Setting data pos of %p to %d\n", this, mDataPos); - mObjects = NULL; - mObjectsSize = 0; - mObjectsCapacity = 0; - mNextObjectHint = 0; - mHasFds = false; - mFdsKnown = true; - mOwner = NULL; -} - -void Parcel::scanForFds() const -{ - bool hasFds = false; - for (size_t i=0; i<mObjectsSize; i++) { - const flat_binder_object* flat - = reinterpret_cast<const flat_binder_object*>(mData + mObjects[i]); - if (flat->type == BINDER_TYPE_FD) { - hasFds = true; - break; - } - } - mHasFds = hasFds; - mFdsKnown = true; -} - -}; // namespace android diff --git a/libs/utils/Pipe.cpp b/libs/utils/Pipe.cpp deleted file mode 100644 index 613906b..0000000 --- a/libs/utils/Pipe.cpp +++ /dev/null @@ -1,465 +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. - */ - -// -// Unidirectional pipe. -// - -#include <utils/Pipe.h> -#include <utils/Log.h> - -#if defined(HAVE_WIN32_IPC) -# include <windows.h> -#else -# include <fcntl.h> -# include <unistd.h> -# include <errno.h> -#endif - -#include <stdlib.h> -#include <stdio.h> -#include <assert.h> -#include <string.h> - -using namespace android; - -const unsigned long kInvalidHandle = (unsigned long) -1; - - -/* - * Constructor. Do little. - */ -Pipe::Pipe(void) - : mReadNonBlocking(false), mReadHandle(kInvalidHandle), - mWriteHandle(kInvalidHandle) -{ -} - -/* - * Destructor. Use the system-appropriate close call. - */ -Pipe::~Pipe(void) -{ -#if defined(HAVE_WIN32_IPC) - if (mReadHandle != kInvalidHandle) { - if (!CloseHandle((HANDLE)mReadHandle)) - LOG(LOG_WARN, "pipe", "failed closing read handle (%ld)\n", - mReadHandle); - } - if (mWriteHandle != kInvalidHandle) { - FlushFileBuffers((HANDLE)mWriteHandle); - if (!CloseHandle((HANDLE)mWriteHandle)) - LOG(LOG_WARN, "pipe", "failed closing write handle (%ld)\n", - mWriteHandle); - } -#else - if (mReadHandle != kInvalidHandle) { - if (close((int) mReadHandle) != 0) - LOG(LOG_WARN, "pipe", "failed closing read fd (%d)\n", - (int) mReadHandle); - } - if (mWriteHandle != kInvalidHandle) { - if (close((int) mWriteHandle) != 0) - LOG(LOG_WARN, "pipe", "failed closing write fd (%d)\n", - (int) mWriteHandle); - } -#endif -} - -/* - * Create the pipe. - * - * Use the POSIX stuff for everything but Windows. - */ -bool Pipe::create(void) -{ - assert(mReadHandle == kInvalidHandle); - assert(mWriteHandle == kInvalidHandle); - -#if defined(HAVE_WIN32_IPC) - /* we use this across processes, so they need to be inheritable */ - HANDLE handles[2]; - SECURITY_ATTRIBUTES saAttr; - - saAttr.nLength = sizeof(SECURITY_ATTRIBUTES); - saAttr.bInheritHandle = TRUE; - saAttr.lpSecurityDescriptor = NULL; - - if (!CreatePipe(&handles[0], &handles[1], &saAttr, 0)) { - LOG(LOG_ERROR, "pipe", "unable to create pipe\n"); - return false; - } - mReadHandle = (unsigned long) handles[0]; - mWriteHandle = (unsigned long) handles[1]; - return true; -#else - int fds[2]; - - if (pipe(fds) != 0) { - LOG(LOG_ERROR, "pipe", "unable to create pipe\n"); - return false; - } - mReadHandle = fds[0]; - mWriteHandle = fds[1]; - return true; -#endif -} - -/* - * Create a "half pipe". Please, no Segway riding. - */ -bool Pipe::createReader(unsigned long handle) -{ - mReadHandle = handle; - assert(mWriteHandle == kInvalidHandle); - return true; -} - -/* - * Create a "half pipe" for writing. - */ -bool Pipe::createWriter(unsigned long handle) -{ - mWriteHandle = handle; - assert(mReadHandle == kInvalidHandle); - return true; -} - -/* - * Return "true" if create() has been called successfully. - */ -bool Pipe::isCreated(void) -{ - // one or the other should be open - return (mReadHandle != kInvalidHandle || mWriteHandle != kInvalidHandle); -} - - -/* - * Read data from the pipe. - * - * For Linux and Darwin, just call read(). For Windows, implement - * non-blocking reads by calling PeekNamedPipe first. - */ -int Pipe::read(void* buf, int count) -{ - assert(mReadHandle != kInvalidHandle); - -#if defined(HAVE_WIN32_IPC) - DWORD totalBytesAvail = count; - DWORD bytesRead; - - if (mReadNonBlocking) { - // use PeekNamedPipe to adjust read count expectations - if (!PeekNamedPipe((HANDLE) mReadHandle, NULL, 0, NULL, - &totalBytesAvail, NULL)) - { - LOG(LOG_ERROR, "pipe", "PeekNamedPipe failed\n"); - return -1; - } - - if (totalBytesAvail == 0) - return 0; - } - - if (!ReadFile((HANDLE) mReadHandle, buf, totalBytesAvail, &bytesRead, - NULL)) - { - DWORD err = GetLastError(); - if (err == ERROR_HANDLE_EOF || err == ERROR_BROKEN_PIPE) - return 0; - LOG(LOG_ERROR, "pipe", "ReadFile failed (err=%ld)\n", err); - return -1; - } - - return (int) bytesRead; -#else - int cc; - cc = ::read(mReadHandle, buf, count); - if (cc < 0 && errno == EAGAIN) - return 0; - return cc; -#endif -} - -/* - * Write data to the pipe. - * - * POSIX systems are trivial, Windows uses a different call and doesn't - * handle non-blocking writes. - * - * If we add non-blocking support here, we probably want to make it an - * all-or-nothing write. - * - * DO NOT use LOG() here, we could be writing a log message. - */ -int Pipe::write(const void* buf, int count) -{ - assert(mWriteHandle != kInvalidHandle); - -#if defined(HAVE_WIN32_IPC) - DWORD bytesWritten; - - if (mWriteNonBlocking) { - // BUG: can't use PeekNamedPipe() to get the amount of space - // left. Looks like we need to use "overlapped I/O" functions. - // I just don't care that much. - } - - if (!WriteFile((HANDLE) mWriteHandle, buf, count, &bytesWritten, NULL)) { - // can't LOG, use stderr - fprintf(stderr, "WriteFile failed (err=%ld)\n", GetLastError()); - return -1; - } - - return (int) bytesWritten; -#else - int cc; - cc = ::write(mWriteHandle, buf, count); - if (cc < 0 && errno == EAGAIN) - return 0; - return cc; -#endif -} - -/* - * Figure out if there is data available on the read fd. - * - * We return "true" on error because we want the caller to try to read - * from the pipe. They'll notice the read failure and do something - * appropriate. - */ -bool Pipe::readReady(void) -{ - assert(mReadHandle != kInvalidHandle); - -#if defined(HAVE_WIN32_IPC) - DWORD totalBytesAvail; - - if (!PeekNamedPipe((HANDLE) mReadHandle, NULL, 0, NULL, - &totalBytesAvail, NULL)) - { - LOG(LOG_ERROR, "pipe", "PeekNamedPipe failed\n"); - return true; - } - - return (totalBytesAvail != 0); -#else - errno = 0; - fd_set readfds; - struct timeval tv = { 0, 0 }; - int cc; - - FD_ZERO(&readfds); - FD_SET(mReadHandle, &readfds); - - cc = select(mReadHandle+1, &readfds, NULL, NULL, &tv); - if (cc < 0) { - LOG(LOG_ERROR, "pipe", "select() failed\n"); - return true; - } else if (cc == 0) { - /* timed out, nothing available */ - return false; - } else if (cc == 1) { - /* our fd is ready */ - return true; - } else { - LOG(LOG_ERROR, "pipe", "HUH? select() returned > 1\n"); - return true; - } -#endif -} - -/* - * Enable or disable non-blocking mode for the read descriptor. - * - * NOTE: the calls succeed under Mac OS X, but the pipe doesn't appear to - * actually be in non-blocking mode. If this matters -- i.e. you're not - * using a select() call -- put a call to readReady() in front of the - * ::read() call, with a PIPE_NONBLOCK_BROKEN #ifdef in the Makefile for - * Darwin. - */ -bool Pipe::setReadNonBlocking(bool val) -{ - assert(mReadHandle != kInvalidHandle); - -#if defined(HAVE_WIN32_IPC) - // nothing to do -#else - int flags; - - if (fcntl(mReadHandle, F_GETFL, &flags) == -1) { - LOG(LOG_ERROR, "pipe", "couldn't get flags for pipe read fd\n"); - return false; - } - if (val) - flags |= O_NONBLOCK; - else - flags &= ~(O_NONBLOCK); - if (fcntl(mReadHandle, F_SETFL, &flags) == -1) { - LOG(LOG_ERROR, "pipe", "couldn't set flags for pipe read fd\n"); - return false; - } -#endif - - mReadNonBlocking = val; - return true; -} - -/* - * Enable or disable non-blocking mode for the write descriptor. - * - * As with setReadNonBlocking(), this does not work on the Mac. - */ -bool Pipe::setWriteNonBlocking(bool val) -{ - assert(mWriteHandle != kInvalidHandle); - -#if defined(HAVE_WIN32_IPC) - // nothing to do -#else - int flags; - - if (fcntl(mWriteHandle, F_GETFL, &flags) == -1) { - LOG(LOG_WARN, "pipe", - "Warning: couldn't get flags for pipe write fd (errno=%d)\n", - errno); - return false; - } - if (val) - flags |= O_NONBLOCK; - else - flags &= ~(O_NONBLOCK); - if (fcntl(mWriteHandle, F_SETFL, &flags) == -1) { - LOG(LOG_WARN, "pipe", - "Warning: couldn't set flags for pipe write fd (errno=%d)\n", - errno); - return false; - } -#endif - - mWriteNonBlocking = val; - return true; -} - -/* - * Specify whether a file descriptor can be inherited by a child process. - * Under Linux this means setting the close-on-exec flag, under Windows - * this is SetHandleInformation(HANDLE_FLAG_INHERIT). - */ -bool Pipe::disallowReadInherit(void) -{ - if (mReadHandle == kInvalidHandle) - return false; - -#if defined(HAVE_WIN32_IPC) - if (SetHandleInformation((HANDLE) mReadHandle, HANDLE_FLAG_INHERIT, 0) == 0) - return false; -#else - if (fcntl((int) mReadHandle, F_SETFD, FD_CLOEXEC) != 0) - return false; -#endif - return true; -} -bool Pipe::disallowWriteInherit(void) -{ - if (mWriteHandle == kInvalidHandle) - return false; - -#if defined(HAVE_WIN32_IPC) - if (SetHandleInformation((HANDLE) mWriteHandle, HANDLE_FLAG_INHERIT, 0) == 0) - return false; -#else - if (fcntl((int) mWriteHandle, F_SETFD, FD_CLOEXEC) != 0) - return false; -#endif - return true; -} - -/* - * Close read descriptor. - */ -bool Pipe::closeRead(void) -{ - if (mReadHandle == kInvalidHandle) - return false; - -#if defined(HAVE_WIN32_IPC) - if (mReadHandle != kInvalidHandle) { - if (!CloseHandle((HANDLE)mReadHandle)) { - LOG(LOG_WARN, "pipe", "failed closing read handle\n"); - return false; - } - } -#else - if (mReadHandle != kInvalidHandle) { - if (close((int) mReadHandle) != 0) { - LOG(LOG_WARN, "pipe", "failed closing read fd\n"); - return false; - } - } -#endif - mReadHandle = kInvalidHandle; - return true; -} - -/* - * Close write descriptor. - */ -bool Pipe::closeWrite(void) -{ - if (mWriteHandle == kInvalidHandle) - return false; - -#if defined(HAVE_WIN32_IPC) - if (mWriteHandle != kInvalidHandle) { - if (!CloseHandle((HANDLE)mWriteHandle)) { - LOG(LOG_WARN, "pipe", "failed closing write handle\n"); - return false; - } - } -#else - if (mWriteHandle != kInvalidHandle) { - if (close((int) mWriteHandle) != 0) { - LOG(LOG_WARN, "pipe", "failed closing write fd\n"); - return false; - } - } -#endif - mWriteHandle = kInvalidHandle; - return true; -} - -/* - * Get the read handle. - */ -unsigned long Pipe::getReadHandle(void) -{ - assert(mReadHandle != kInvalidHandle); - - return mReadHandle; -} - -/* - * Get the write handle. - */ -unsigned long Pipe::getWriteHandle(void) -{ - assert(mWriteHandle != kInvalidHandle); - - return mWriteHandle; -} - diff --git a/libs/utils/ProcessState.cpp b/libs/utils/ProcessState.cpp deleted file mode 100644 index 4567df6..0000000 --- a/libs/utils/ProcessState.cpp +++ /dev/null @@ -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 diff --git a/libs/utils/Socket.cpp b/libs/utils/Socket.cpp deleted file mode 100644 index 51509a3..0000000 --- a/libs/utils/Socket.cpp +++ /dev/null @@ -1,388 +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. - */ - -// -// Internet address class. -// - -#ifdef HAVE_WINSOCK -// This needs to come first, or Cygwin gets concerned about a potential -// clash between WinSock and <sys/types.h>. -# include <winsock2.h> -#endif - -#include <utils/Socket.h> -#include <utils/inet_address.h> -#include <utils/Log.h> -#include <utils/Timers.h> - -#ifndef HAVE_WINSOCK -# include <sys/types.h> -# include <sys/socket.h> -# include <netinet/in.h> -# include <arpa/inet.h> -#endif - -#include <stdlib.h> -#include <stdio.h> -#include <unistd.h> -#include <string.h> -#include <errno.h> -#include <assert.h> - -using namespace android; - - -/* - * =========================================================================== - * Socket - * =========================================================================== - */ - -#ifndef INVALID_SOCKET -# define INVALID_SOCKET (-1) -#endif -#define UNDEF_SOCKET ((unsigned long) INVALID_SOCKET) - -/*static*/ bool Socket::mBootInitialized = false; - -/* - * Extract system-dependent error code. - */ -static inline int getSocketError(void) { -#ifdef HAVE_WINSOCK - return WSAGetLastError(); -#else - return errno; -#endif -} - -/* - * One-time initialization for socket code. - */ -/*static*/ bool Socket::bootInit(void) -{ -#ifdef HAVE_WINSOCK - WSADATA wsaData; - int err; - - err = WSAStartup(MAKEWORD(2, 0), &wsaData); - if (err != 0) { - LOG(LOG_ERROR, "socket", "Unable to start WinSock\n"); - return false; - } - - LOG(LOG_INFO, "socket", "Using WinSock v%d.%d\n", - LOBYTE(wsaData.wVersion), HIBYTE(wsaData.wVersion)); -#endif - - mBootInitialized = true; - return true; -} - -/* - * One-time shutdown for socket code. - */ -/*static*/ void Socket::finalShutdown(void) -{ -#ifdef HAVE_WINSOCK - WSACleanup(); -#endif - mBootInitialized = false; -} - - -/* - * Simple constructor. Allow the application to create us and then make - * bind/connect calls. - */ -Socket::Socket(void) - : mSock(UNDEF_SOCKET) -{ - if (!mBootInitialized) - LOG(LOG_WARN, "socket", "WARNING: sockets not initialized\n"); -} - -/* - * Destructor. Closes the socket and resets our storage. - */ -Socket::~Socket(void) -{ - close(); -} - - -/* - * Create a socket and connect to the specified host and port. - */ -int Socket::connect(const char* host, int port) -{ - if (mSock != UNDEF_SOCKET) { - LOG(LOG_WARN, "socket", "Socket already connected\n"); - return -1; - } - - InetSocketAddress sockAddr; - if (!sockAddr.create(host, port)) - return -1; - - //return doConnect(sockAddr); - int foo; - foo = doConnect(sockAddr); - return foo; -} - -/* - * Create a socket and connect to the specified host and port. - */ -int Socket::connect(const InetAddress* addr, int port) -{ - if (mSock != UNDEF_SOCKET) { - LOG(LOG_WARN, "socket", "Socket already connected\n"); - return -1; - } - - InetSocketAddress sockAddr; - if (!sockAddr.create(addr, port)) - return -1; - - return doConnect(sockAddr); -} - -/* - * Finish creating a socket by connecting to the remote host. - * - * Returns 0 on success. - */ -int Socket::doConnect(const InetSocketAddress& sockAddr) -{ -#ifdef HAVE_WINSOCK - SOCKET sock; -#else - int sock; -#endif - const InetAddress* addr = sockAddr.getAddress(); - int port = sockAddr.getPort(); - struct sockaddr_in inaddr; - DurationTimer connectTimer; - - assert(sizeof(struct sockaddr_in) == addr->getAddressLength()); - memcpy(&inaddr, addr->getAddress(), addr->getAddressLength()); - inaddr.sin_port = htons(port); - - //fprintf(stderr, "--- connecting to %s:%d\n", - // sockAddr.getHostName(), port); - - sock = ::socket(PF_INET, SOCK_STREAM, IPPROTO_TCP); - if (sock == INVALID_SOCKET) { - int err = getSocketError(); - LOG(LOG_ERROR, "socket", "Unable to create socket (err=%d)\n", err); - return (err != 0) ? err : -1; - } - - connectTimer.start(); - - if (::connect(sock, (struct sockaddr*) &inaddr, sizeof(inaddr)) != 0) { - int err = getSocketError(); - LOG(LOG_WARN, "socket", "Connect to %s:%d failed: %d\n", - sockAddr.getHostName(), port, err); - return (err != 0) ? err : -1; - } - - connectTimer.stop(); - if ((long) connectTimer.durationUsecs() > 100000) { - LOG(LOG_INFO, "socket", - "Connect to %s:%d took %.3fs\n", sockAddr.getHostName(), - port, ((long) connectTimer.durationUsecs()) / 1000000.0); - } - - mSock = (unsigned long) sock; - LOG(LOG_VERBOSE, "socket", - "--- connected to %s:%d\n", sockAddr.getHostName(), port); - return 0; -} - - -/* - * Close the socket if it needs closing. - */ -bool Socket::close(void) -{ - if (mSock != UNDEF_SOCKET) { - //fprintf(stderr, "--- closing socket %lu\n", mSock); -#ifdef HAVE_WINSOCK - if (::closesocket((SOCKET) mSock) != 0) - return false; -#else - if (::close((int) mSock) != 0) - return false; -#endif - } - - mSock = UNDEF_SOCKET; - - return true; -} - -/* - * Read data from socket. - * - * Standard semantics: read up to "len" bytes into "buf". Returns the - * number of bytes read, or less than zero on error. - */ -int Socket::read(void* buf, ssize_t len) const -{ - if (mSock == UNDEF_SOCKET) { - LOG(LOG_ERROR, "socket", "ERROR: read on invalid socket\n"); - return -500; - } - -#ifdef HAVE_WINSOCK - SOCKET sock = (SOCKET) mSock; -#else - int sock = (int) mSock; -#endif - int cc; - - cc = recv(sock, (char*)buf, len, 0); - if (cc < 0) { - int err = getSocketError(); - return (err > 0) ? -err : -1; - } - - return cc; -} - -/* - * Write data to a socket. - * - * Standard semantics: write up to "len" bytes into "buf". Returns the - * number of bytes written, or less than zero on error. - */ -int Socket::write(const void* buf, ssize_t len) const -{ - if (mSock == UNDEF_SOCKET) { - LOG(LOG_ERROR, "socket", "ERROR: write on invalid socket\n"); - return -500; - } - -#ifdef HAVE_WINSOCK - SOCKET sock = (SOCKET) mSock; -#else - int sock = (int) mSock; -#endif - int cc; - - cc = send(sock, (const char*)buf, len, 0); - if (cc < 0) { - int err = getSocketError(); - return (err > 0) ? -err : -1; - } - - return cc; -} - - -/* - * =========================================================================== - * Socket tests - * =========================================================================== - */ - -/* - * Read all data from the socket. The data is read into a buffer that - * expands as needed. - * - * On exit, the buffer is returned, and the length of the data is stored - * in "*sz". A null byte is added to the end, but is not included in - * the length. - */ -static char* socketReadAll(const Socket& s, int *sz) -{ - int max, r; - char *data, *ptr, *tmp; - - data = (char*) malloc(max = 32768); - if (data == NULL) - return NULL; - - ptr = data; - - for (;;) { - if ((ptr - data) == max) { - tmp = (char*) realloc(data, max *= 2); - if(tmp == 0) { - free(data); - return 0; - } - } - r = s.read(ptr, max - (ptr - data)); - if (r == 0) - break; - if (r < 0) { - LOG(LOG_WARN, "socket", "WARNING: socket read failed (res=%d)\n",r); - break; - } - ptr += r; - } - - if ((ptr - data) == max) { - tmp = (char*) realloc(data, max + 1); - if (tmp == NULL) { - free(data); - return NULL; - } - } - *ptr = '\0'; - *sz = (ptr - data); - return data; -} - -/* - * Exercise the Socket class. - */ -void android::TestSockets(void) -{ - printf("----- SOCKET TEST ------\n"); - Socket::bootInit(); - - char* buf = NULL; - int len, cc; - const char* kTestStr = - "GET / HTTP/1.0\n" - "Connection: close\n" - "\n"; - - Socket sock; - if (sock.connect("www.google.com", 80) != 0) { - fprintf(stderr, "socket connected failed\n"); - goto bail; - } - - cc = sock.write(kTestStr, strlen(kTestStr)); - if (cc != (int) strlen(kTestStr)) { - fprintf(stderr, "write failed, res=%d\n", cc); - goto bail; - } - buf = socketReadAll(sock, &len); - - printf("GOT '%s'\n", buf); - -bail: - sock.close(); - free(buf); -} - diff --git a/libs/utils/Static.cpp b/libs/utils/Static.cpp index 93f7e4f..4dfa578 100644 --- a/libs/utils/Static.cpp +++ b/libs/utils/Static.cpp @@ -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 diff --git a/libs/utils/StringArray.cpp b/libs/utils/StringArray.cpp new file mode 100644 index 0000000..aa42d68 --- /dev/null +++ b/libs/utils/StringArray.cpp @@ -0,0 +1,113 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// +// Sortable array of strings. STL-ish, but STL-free. +// + +#include <stdlib.h> +#include <string.h> + +#include <utils/StringArray.h> + +namespace android { + +// +// An expanding array of strings. Add, get, sort, delete. +// +StringArray::StringArray() + : mMax(0), mCurrent(0), mArray(NULL) +{ +} + +StringArray:: ~StringArray() { + for (int i = 0; i < mCurrent; i++) + delete[] mArray[i]; + delete[] mArray; +} + +// +// Add a string. A copy of the string is made. +// +bool StringArray::push_back(const char* str) { + if (mCurrent >= mMax) { + char** tmp; + + if (mMax == 0) + mMax = 16; // initial storage + else + mMax *= 2; + + tmp = new char*[mMax]; + if (tmp == NULL) + return false; + + memcpy(tmp, mArray, mCurrent * sizeof(char*)); + delete[] mArray; + mArray = tmp; + } + + int len = strlen(str); + mArray[mCurrent] = new char[len+1]; + memcpy(mArray[mCurrent], str, len+1); + mCurrent++; + + return true; +} + +// +// Delete an entry. +// +void StringArray::erase(int idx) { + if (idx < 0 || idx >= mCurrent) + return; + delete[] mArray[idx]; + if (idx < mCurrent-1) { + memmove(&mArray[idx], &mArray[idx+1], + (mCurrent-1 - idx) * sizeof(char*)); + } + mCurrent--; +} + +// +// Sort the array. +// +void StringArray::sort(int (*compare)(const void*, const void*)) { + qsort(mArray, mCurrent, sizeof(char*), compare); +} + +// +// Pass this to the sort routine to do an ascending alphabetical sort. +// +int StringArray::cmpAscendingAlpha(const void* pstr1, const void* pstr2) { + return strcmp(*(const char**)pstr1, *(const char**)pstr2); +} + +// +// Set entry N to specified string. +// [should use operator[] here] +// +void StringArray::setEntry(int idx, const char* str) { + if (idx < 0 || idx >= mCurrent) + return; + delete[] mArray[idx]; + int len = strlen(str); + mArray[idx] = new char[len+1]; + memcpy(mArray[idx], str, len+1); +} + + +}; // namespace android diff --git a/libs/utils/TextOutput.cpp b/libs/utils/TextOutput.cpp index cebee99..e04823d 100644 --- a/libs/utils/TextOutput.cpp +++ b/libs/utils/TextOutput.cpp @@ -22,9 +22,17 @@ #include <stdlib.h> #include <string.h> +namespace android { + // --------------------------------------------------------------------------- -namespace android { +TextOutput::TextOutput() { +} + +TextOutput::~TextOutput() { +} + +// --------------------------------------------------------------------------- TextOutput& operator<<(TextOutput& to, bool val) { diff --git a/libs/utils/TimerProbe.cpp b/libs/utils/TimerProbe.cpp deleted file mode 100644 index 835480d..0000000 --- a/libs/utils/TimerProbe.cpp +++ /dev/null @@ -1,131 +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 <utils/TimerProbe.h> - -#if ENABLE_TIMER_PROBE - -#ifdef LOG_TAG -#undef LOG_TAG -#endif -#define LOG_TAG "time" - -namespace android { - -Vector<TimerProbe::Bucket> TimerProbe::gBuckets; -TimerProbe* TimerProbe::gExecuteChain; -int TimerProbe::gIndent; -timespec TimerProbe::gRealBase; - -TimerProbe::TimerProbe(const char tag[], int* slot) : mTag(tag) -{ - mNext = gExecuteChain; - gExecuteChain = this; - mIndent = gIndent; - gIndent += 1; - if (mIndent > 0) { - if (*slot == 0) { - int count = gBuckets.add(); - *slot = count; - Bucket& bucket = gBuckets.editItemAt(count); - memset(&bucket, 0, sizeof(Bucket)); - bucket.mTag = tag; - bucket.mSlotPtr = slot; - bucket.mIndent = mIndent; - } - mBucket = *slot; - } - clock_gettime(CLOCK_REALTIME, &mRealStart); - if (gRealBase.tv_sec == 0) - gRealBase = mRealStart; - clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &mPStart); - clock_gettime(CLOCK_THREAD_CPUTIME_ID, &mTStart); -} - -void TimerProbe::end() -{ - timespec realEnd, pEnd, tEnd; - clock_gettime(CLOCK_REALTIME, &realEnd); - clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &pEnd); - clock_gettime(CLOCK_THREAD_CPUTIME_ID, &tEnd); - print(realEnd, pEnd, tEnd); - mTag = NULL; -} - -TimerProbe::~TimerProbe() -{ - if (mTag != NULL) - end(); - gExecuteChain = mNext; - gIndent--; -} - - -uint32_t TimerProbe::ElapsedTime(const timespec& start, const timespec& end) -{ - int sec = end.tv_sec - start.tv_sec; - int nsec = end.tv_nsec - start.tv_nsec; - if (nsec < 0) { - sec--; - nsec += 1000000000; - } - return sec * 1000000 + nsec / 1000; -} - -void TimerProbe::print(const timespec& r, const timespec& p, - const timespec& t) const -{ - uint32_t es = ElapsedTime(gRealBase, mRealStart); - uint32_t er = ElapsedTime(mRealStart, r); - uint32_t ep = ElapsedTime(mPStart, p); - uint32_t et = ElapsedTime(mTStart, t); - if (mIndent > 0) { - Bucket& bucket = gBuckets.editItemAt(mBucket); - if (bucket.mStart == 0) - bucket.mStart = es; - bucket.mReal += er; - bucket.mProcess += ep; - bucket.mThread += et; - bucket.mCount++; - return; - } - int index = 0; - int buckets = gBuckets.size(); - int count = 1; - const char* tag = mTag; - int indent = mIndent; - do { - LOGD("%-30.30s: (%3d) %-5.*s time=%-10.3f real=%7dus process=%7dus (%3d%%) thread=%7dus (%3d%%)\n", - tag, count, indent > 5 ? 5 : indent, "+++++", es / 1000000.0, - er, ep, ep * 100 / er, et, et * 100 / er); - if (index >= buckets) - break; - Bucket& bucket = gBuckets.editItemAt(index); - count = bucket.mCount; - es = bucket.mStart; - er = bucket.mReal; - ep = bucket.mProcess; - et = bucket.mThread; - tag = bucket.mTag; - indent = bucket.mIndent; - *bucket.mSlotPtr = 0; - } while (++index); // always true - gBuckets.clear(); -} - -}; // namespace android - -#endif diff --git a/libs/utils/Timers.cpp b/libs/utils/Timers.cpp index 2abc811..784f035 100644 --- a/libs/utils/Timers.cpp +++ b/libs/utils/Timers.cpp @@ -18,7 +18,6 @@ // Timer functions. // #include <utils/Timers.h> -#include <utils/ported.h> // may need usleep #include <utils/Log.h> #include <stdlib.h> @@ -54,130 +53,6 @@ nsecs_t systemTime(int clock) #endif } -//#define MONITOR_USLEEP - -/* - * Sleep long enough that we'll wake up "interval" milliseconds after - * the previous snooze. - * - * The "nextTick" argument is updated on each call, and should be passed - * in every time. Set its fields to zero on the first call. - * - * Returns the #of intervals we have overslept, which will be zero if we're - * on time. [Currently just returns 0 or 1.] - */ -int sleepForInterval(long interval, struct timeval* pNextTick) -{ - struct timeval now; - long long timeBeforeNext; - long sleepTime = 0; - bool overSlept = false; - //int usleepBias = 0; - -#ifdef USLEEP_BIAS - /* - * Linux likes to add 9000ms or so. - * [not using this for now] - */ - //usleepBias = USLEEP_BIAS; -#endif - - gettimeofday(&now, NULL); - - if (pNextTick->tv_sec == 0) { - /* special-case for first time through */ - *pNextTick = now; - sleepTime = interval; - android::DurationTimer::addToTimeval(pNextTick, interval); - } else { - /* - * Compute how much time there is before the next tick. If this - * value is negative, we've run over. If we've run over a little - * bit we can shorten the next frame to keep the pace steady, but - * if we've dramatically overshot we need to re-sync. - */ - timeBeforeNext = android::DurationTimer::subtractTimevals(pNextTick, &now); - //printf("TOP: now=%ld.%ld next=%ld.%ld diff=%ld\n", - // now.tv_sec, now.tv_usec, pNextTick->tv_sec, pNextTick->tv_usec, - // (long) timeBeforeNext); - if (timeBeforeNext < -interval) { - /* way over */ - overSlept = true; - sleepTime = 0; - *pNextTick = now; - } else if (timeBeforeNext <= 0) { - /* slightly over, keep the pace steady */ - overSlept = true; - sleepTime = 0; - } else if (timeBeforeNext <= interval) { - /* right on schedule */ - sleepTime = timeBeforeNext; - } else if (timeBeforeNext > interval && timeBeforeNext <= 2*interval) { - /* sleep call returned early; do a longer sleep this time */ - sleepTime = timeBeforeNext; - } else if (timeBeforeNext > interval) { - /* we went back in time -- somebody updated system clock? */ - /* (could also be a *seriously* broken usleep()) */ - LOG(LOG_DEBUG, "", - " Impossible: timeBeforeNext = %ld\n", (long)timeBeforeNext); - sleepTime = 0; - *pNextTick = now; - } - android::DurationTimer::addToTimeval(pNextTick, interval); - } - //printf(" Before sleep: now=%ld.%ld next=%ld.%ld sleepTime=%ld\n", - // now.tv_sec, now.tv_usec, pNextTick->tv_sec, pNextTick->tv_usec, - // sleepTime); - - /* - * Sleep for the designated period of time. - * - * Linux tends to sleep for longer than requested, often by 17-18ms. - * MinGW tends to sleep for less than requested, by as much as 14ms, - * but occasionally oversleeps for 40+ms (looks like some external - * factors plus round-off on a 64Hz clock). Cygwin is pretty steady. - * - * If you start the MinGW version, and then launch the Cygwin version, - * the MinGW clock becomes more erratic. Not entirely sure why. - * - * (There's a lot of stuff here; it's really just a usleep() call with - * a bunch of instrumentation.) - */ - if (sleepTime > 0) { -#if defined(MONITOR_USLEEP) - struct timeval before, after; - long long actual; - - gettimeofday(&before, NULL); - usleep((long) sleepTime); - gettimeofday(&after, NULL); - - /* check usleep() accuracy; default Linux threads are pretty sloppy */ - actual = android::DurationTimer::subtractTimevals(&after, &before); - if ((long) actual < sleepTime - 14000 /*(sleepTime/10)*/ || - (long) actual > sleepTime + 20000 /*(sleepTime/10)*/) - { - LOG(LOG_DEBUG, "", " Odd usleep: req=%ld, actual=%ld\n", sleepTime, - (long) actual); - } -#else -#ifdef HAVE_WIN32_THREADS - Sleep( sleepTime/1000 ); -#else - usleep((long) sleepTime); -#endif -#endif - } - - //printf("slept %d\n", sleepTime); - - if (overSlept) - return 1; // close enough - else - return 0; -} - - /* * =========================================================================== * DurationTimer diff --git a/libs/utils/ZipEntry.cpp b/libs/utils/ZipEntry.cpp deleted file mode 100644 index 96f9fc4..0000000 --- a/libs/utils/ZipEntry.cpp +++ /dev/null @@ -1,696 +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. - */ - -// -// Access to entries in a Zip archive. -// - -#define LOG_TAG "zip" - -#include <utils/ZipEntry.h> -#include <utils/Log.h> - -#include <stdio.h> -#include <string.h> -#include <assert.h> - -using namespace android; - -/* - * Initialize a new ZipEntry structure from a FILE* positioned at a - * CentralDirectoryEntry. - * - * On exit, the file pointer will be at the start of the next CDE or - * at the EOCD. - */ -status_t ZipEntry::initFromCDE(FILE* fp) -{ - status_t result; - long posn; - bool hasDD; - - //LOGV("initFromCDE ---\n"); - - /* read the CDE */ - result = mCDE.read(fp); - if (result != NO_ERROR) { - LOGD("mCDE.read failed\n"); - return result; - } - - //mCDE.dump(); - - /* using the info in the CDE, go load up the LFH */ - posn = ftell(fp); - if (fseek(fp, mCDE.mLocalHeaderRelOffset, SEEK_SET) != 0) { - LOGD("local header seek failed (%ld)\n", - mCDE.mLocalHeaderRelOffset); - return UNKNOWN_ERROR; - } - - result = mLFH.read(fp); - if (result != NO_ERROR) { - LOGD("mLFH.read failed\n"); - return result; - } - - if (fseek(fp, posn, SEEK_SET) != 0) - return UNKNOWN_ERROR; - - //mLFH.dump(); - - /* - * We *might* need to read the Data Descriptor at this point and - * integrate it into the LFH. If this bit is set, the CRC-32, - * compressed size, and uncompressed size will be zero. In practice - * these seem to be rare. - */ - hasDD = (mLFH.mGPBitFlag & kUsesDataDescr) != 0; - if (hasDD) { - // do something clever - //LOGD("+++ has data descriptor\n"); - } - - /* - * Sanity-check the LFH. Note that this will fail if the "kUsesDataDescr" - * flag is set, because the LFH is incomplete. (Not a problem, since we - * prefer the CDE values.) - */ - if (!hasDD && !compareHeaders()) { - LOGW("WARNING: header mismatch\n"); - // keep going? - } - - /* - * If the mVersionToExtract is greater than 20, we may have an - * issue unpacking the record -- could be encrypted, compressed - * with something we don't support, or use Zip64 extensions. We - * can defer worrying about that to when we're extracting data. - */ - - return NO_ERROR; -} - -/* - * Initialize a new entry. Pass in the file name and an optional comment. - * - * Initializes the CDE and the LFH. - */ -void ZipEntry::initNew(const char* fileName, const char* comment) -{ - assert(fileName != NULL && *fileName != '\0'); // name required - - /* most fields are properly initialized by constructor */ - mCDE.mVersionMadeBy = kDefaultMadeBy; - mCDE.mVersionToExtract = kDefaultVersion; - mCDE.mCompressionMethod = kCompressStored; - mCDE.mFileNameLength = strlen(fileName); - if (comment != NULL) - mCDE.mFileCommentLength = strlen(comment); - mCDE.mExternalAttrs = 0x81b60020; // matches what WinZip does - - if (mCDE.mFileNameLength > 0) { - mCDE.mFileName = new unsigned char[mCDE.mFileNameLength+1]; - strcpy((char*) mCDE.mFileName, fileName); - } - if (mCDE.mFileCommentLength > 0) { - /* TODO: stop assuming null-terminated ASCII here? */ - mCDE.mFileComment = new unsigned char[mCDE.mFileCommentLength+1]; - strcpy((char*) mCDE.mFileComment, comment); - } - - copyCDEtoLFH(); -} - -/* - * Initialize a new entry, starting with the ZipEntry from a different - * archive. - * - * Initializes the CDE and the LFH. - */ -status_t ZipEntry::initFromExternal(const ZipFile* pZipFile, - const ZipEntry* pEntry) -{ - /* - * Copy everything in the CDE over, then fix up the hairy bits. - */ - memcpy(&mCDE, &pEntry->mCDE, sizeof(mCDE)); - - if (mCDE.mFileNameLength > 0) { - mCDE.mFileName = new unsigned char[mCDE.mFileNameLength+1]; - if (mCDE.mFileName == NULL) - return NO_MEMORY; - strcpy((char*) mCDE.mFileName, (char*)pEntry->mCDE.mFileName); - } - if (mCDE.mFileCommentLength > 0) { - mCDE.mFileComment = new unsigned char[mCDE.mFileCommentLength+1]; - if (mCDE.mFileComment == NULL) - return NO_MEMORY; - strcpy((char*) mCDE.mFileComment, (char*)pEntry->mCDE.mFileComment); - } - if (mCDE.mExtraFieldLength > 0) { - /* we null-terminate this, though it may not be a string */ - mCDE.mExtraField = new unsigned char[mCDE.mExtraFieldLength+1]; - if (mCDE.mExtraField == NULL) - return NO_MEMORY; - memcpy(mCDE.mExtraField, pEntry->mCDE.mExtraField, - mCDE.mExtraFieldLength+1); - } - - /* construct the LFH from the CDE */ - copyCDEtoLFH(); - - /* - * The LFH "extra" field is independent of the CDE "extra", so we - * handle it here. - */ - assert(mLFH.mExtraField == NULL); - mLFH.mExtraFieldLength = pEntry->mLFH.mExtraFieldLength; - if (mLFH.mExtraFieldLength > 0) { - mLFH.mExtraField = new unsigned char[mLFH.mExtraFieldLength+1]; - if (mLFH.mExtraField == NULL) - return NO_MEMORY; - memcpy(mLFH.mExtraField, pEntry->mLFH.mExtraField, - mLFH.mExtraFieldLength+1); - } - - return NO_ERROR; -} - -/* - * Insert pad bytes in the LFH by tweaking the "extra" field. This will - * potentially confuse something that put "extra" data in here earlier, - * but I can't find an actual problem. - */ -status_t ZipEntry::addPadding(int padding) -{ - if (padding <= 0) - return INVALID_OPERATION; - - //LOGI("HEY: adding %d pad bytes to existing %d in %s\n", - // padding, mLFH.mExtraFieldLength, mCDE.mFileName); - - if (mLFH.mExtraFieldLength > 0) { - /* extend existing field */ - unsigned char* newExtra; - - newExtra = new unsigned char[mLFH.mExtraFieldLength + padding]; - if (newExtra == NULL) - return NO_MEMORY; - memset(newExtra + mLFH.mExtraFieldLength, 0, padding); - memcpy(newExtra, mLFH.mExtraField, mLFH.mExtraFieldLength); - - delete[] mLFH.mExtraField; - mLFH.mExtraField = newExtra; - mLFH.mExtraFieldLength += padding; - } else { - /* create new field */ - mLFH.mExtraField = new unsigned char[padding]; - memset(mLFH.mExtraField, 0, padding); - mLFH.mExtraFieldLength = padding; - } - - return NO_ERROR; -} - -/* - * Set the fields in the LFH equal to the corresponding fields in the CDE. - * - * This does not touch the LFH "extra" field. - */ -void ZipEntry::copyCDEtoLFH(void) -{ - mLFH.mVersionToExtract = mCDE.mVersionToExtract; - mLFH.mGPBitFlag = mCDE.mGPBitFlag; - mLFH.mCompressionMethod = mCDE.mCompressionMethod; - mLFH.mLastModFileTime = mCDE.mLastModFileTime; - mLFH.mLastModFileDate = mCDE.mLastModFileDate; - mLFH.mCRC32 = mCDE.mCRC32; - mLFH.mCompressedSize = mCDE.mCompressedSize; - mLFH.mUncompressedSize = mCDE.mUncompressedSize; - mLFH.mFileNameLength = mCDE.mFileNameLength; - // the "extra field" is independent - - delete[] mLFH.mFileName; - if (mLFH.mFileNameLength > 0) { - mLFH.mFileName = new unsigned char[mLFH.mFileNameLength+1]; - strcpy((char*) mLFH.mFileName, (const char*) mCDE.mFileName); - } else { - mLFH.mFileName = NULL; - } -} - -/* - * Set some information about a file after we add it. - */ -void ZipEntry::setDataInfo(long uncompLen, long compLen, unsigned long crc32, - int compressionMethod) -{ - mCDE.mCompressionMethod = compressionMethod; - mCDE.mCRC32 = crc32; - mCDE.mCompressedSize = compLen; - mCDE.mUncompressedSize = uncompLen; - mCDE.mCompressionMethod = compressionMethod; - if (compressionMethod == kCompressDeflated) { - mCDE.mGPBitFlag |= 0x0002; // indicates maximum compression used - } - copyCDEtoLFH(); -} - -/* - * See if the data in mCDE and mLFH match up. This is mostly useful for - * debugging these classes, but it can be used to identify damaged - * archives. - * - * Returns "false" if they differ. - */ -bool ZipEntry::compareHeaders(void) const -{ - if (mCDE.mVersionToExtract != mLFH.mVersionToExtract) { - LOGV("cmp: VersionToExtract\n"); - return false; - } - if (mCDE.mGPBitFlag != mLFH.mGPBitFlag) { - LOGV("cmp: GPBitFlag\n"); - return false; - } - if (mCDE.mCompressionMethod != mLFH.mCompressionMethod) { - LOGV("cmp: CompressionMethod\n"); - return false; - } - if (mCDE.mLastModFileTime != mLFH.mLastModFileTime) { - LOGV("cmp: LastModFileTime\n"); - return false; - } - if (mCDE.mLastModFileDate != mLFH.mLastModFileDate) { - LOGV("cmp: LastModFileDate\n"); - return false; - } - if (mCDE.mCRC32 != mLFH.mCRC32) { - LOGV("cmp: CRC32\n"); - return false; - } - if (mCDE.mCompressedSize != mLFH.mCompressedSize) { - LOGV("cmp: CompressedSize\n"); - return false; - } - if (mCDE.mUncompressedSize != mLFH.mUncompressedSize) { - LOGV("cmp: UncompressedSize\n"); - return false; - } - if (mCDE.mFileNameLength != mLFH.mFileNameLength) { - LOGV("cmp: FileNameLength\n"); - return false; - } -#if 0 // this seems to be used for padding, not real data - if (mCDE.mExtraFieldLength != mLFH.mExtraFieldLength) { - LOGV("cmp: ExtraFieldLength\n"); - return false; - } -#endif - if (mCDE.mFileName != NULL) { - if (strcmp((char*) mCDE.mFileName, (char*) mLFH.mFileName) != 0) { - LOGV("cmp: FileName\n"); - return false; - } - } - - return true; -} - - -/* - * Convert the DOS date/time stamp into a UNIX time stamp. - */ -time_t ZipEntry::getModWhen(void) const -{ - struct tm parts; - - parts.tm_sec = (mCDE.mLastModFileTime & 0x001f) << 1; - parts.tm_min = (mCDE.mLastModFileTime & 0x07e0) >> 5; - parts.tm_hour = (mCDE.mLastModFileTime & 0xf800) >> 11; - parts.tm_mday = (mCDE.mLastModFileDate & 0x001f); - parts.tm_mon = ((mCDE.mLastModFileDate & 0x01e0) >> 5) -1; - parts.tm_year = ((mCDE.mLastModFileDate & 0xfe00) >> 9) + 80; - parts.tm_wday = parts.tm_yday = 0; - parts.tm_isdst = -1; // DST info "not available" - - return mktime(&parts); -} - -/* - * Set the CDE/LFH timestamp from UNIX time. - */ -void ZipEntry::setModWhen(time_t when) -{ -#ifdef HAVE_LOCALTIME_R - struct tm tmResult; -#endif - time_t even; - unsigned short zdate, ztime; - - struct tm* ptm; - - /* round up to an even number of seconds */ - even = (time_t)(((unsigned long)(when) + 1) & (~1)); - - /* expand */ -#ifdef HAVE_LOCALTIME_R - ptm = localtime_r(&even, &tmResult); -#else - ptm = localtime(&even); -#endif - - int year; - year = ptm->tm_year; - if (year < 80) - year = 80; - - zdate = (year - 80) << 9 | (ptm->tm_mon+1) << 5 | ptm->tm_mday; - ztime = ptm->tm_hour << 11 | ptm->tm_min << 5 | ptm->tm_sec >> 1; - - mCDE.mLastModFileTime = mLFH.mLastModFileTime = ztime; - mCDE.mLastModFileDate = mLFH.mLastModFileDate = zdate; -} - - -/* - * =========================================================================== - * ZipEntry::LocalFileHeader - * =========================================================================== - */ - -/* - * Read a local file header. - * - * On entry, "fp" points to the signature at the start of the header. - * On exit, "fp" points to the start of data. - */ -status_t ZipEntry::LocalFileHeader::read(FILE* fp) -{ - status_t result = NO_ERROR; - unsigned char buf[kLFHLen]; - - assert(mFileName == NULL); - assert(mExtraField == NULL); - - if (fread(buf, 1, kLFHLen, fp) != kLFHLen) { - result = UNKNOWN_ERROR; - goto bail; - } - - if (ZipEntry::getLongLE(&buf[0x00]) != kSignature) { - LOGD("whoops: didn't find expected signature\n"); - result = UNKNOWN_ERROR; - goto bail; - } - - mVersionToExtract = ZipEntry::getShortLE(&buf[0x04]); - mGPBitFlag = ZipEntry::getShortLE(&buf[0x06]); - mCompressionMethod = ZipEntry::getShortLE(&buf[0x08]); - mLastModFileTime = ZipEntry::getShortLE(&buf[0x0a]); - mLastModFileDate = ZipEntry::getShortLE(&buf[0x0c]); - mCRC32 = ZipEntry::getLongLE(&buf[0x0e]); - mCompressedSize = ZipEntry::getLongLE(&buf[0x12]); - mUncompressedSize = ZipEntry::getLongLE(&buf[0x16]); - mFileNameLength = ZipEntry::getShortLE(&buf[0x1a]); - mExtraFieldLength = ZipEntry::getShortLE(&buf[0x1c]); - - // TODO: validate sizes - - /* grab filename */ - if (mFileNameLength != 0) { - mFileName = new unsigned char[mFileNameLength+1]; - if (mFileName == NULL) { - result = NO_MEMORY; - goto bail; - } - if (fread(mFileName, 1, mFileNameLength, fp) != mFileNameLength) { - result = UNKNOWN_ERROR; - goto bail; - } - mFileName[mFileNameLength] = '\0'; - } - - /* grab extra field */ - if (mExtraFieldLength != 0) { - mExtraField = new unsigned char[mExtraFieldLength+1]; - if (mExtraField == NULL) { - result = NO_MEMORY; - goto bail; - } - if (fread(mExtraField, 1, mExtraFieldLength, fp) != mExtraFieldLength) { - result = UNKNOWN_ERROR; - goto bail; - } - mExtraField[mExtraFieldLength] = '\0'; - } - -bail: - return result; -} - -/* - * Write a local file header. - */ -status_t ZipEntry::LocalFileHeader::write(FILE* fp) -{ - unsigned char buf[kLFHLen]; - - ZipEntry::putLongLE(&buf[0x00], kSignature); - ZipEntry::putShortLE(&buf[0x04], mVersionToExtract); - ZipEntry::putShortLE(&buf[0x06], mGPBitFlag); - ZipEntry::putShortLE(&buf[0x08], mCompressionMethod); - ZipEntry::putShortLE(&buf[0x0a], mLastModFileTime); - ZipEntry::putShortLE(&buf[0x0c], mLastModFileDate); - ZipEntry::putLongLE(&buf[0x0e], mCRC32); - ZipEntry::putLongLE(&buf[0x12], mCompressedSize); - ZipEntry::putLongLE(&buf[0x16], mUncompressedSize); - ZipEntry::putShortLE(&buf[0x1a], mFileNameLength); - ZipEntry::putShortLE(&buf[0x1c], mExtraFieldLength); - - if (fwrite(buf, 1, kLFHLen, fp) != kLFHLen) - return UNKNOWN_ERROR; - - /* write filename */ - if (mFileNameLength != 0) { - if (fwrite(mFileName, 1, mFileNameLength, fp) != mFileNameLength) - return UNKNOWN_ERROR; - } - - /* write "extra field" */ - if (mExtraFieldLength != 0) { - if (fwrite(mExtraField, 1, mExtraFieldLength, fp) != mExtraFieldLength) - return UNKNOWN_ERROR; - } - - return NO_ERROR; -} - - -/* - * Dump the contents of a LocalFileHeader object. - */ -void ZipEntry::LocalFileHeader::dump(void) const -{ - LOGD(" LocalFileHeader contents:\n"); - LOGD(" versToExt=%u gpBits=0x%04x compression=%u\n", - mVersionToExtract, mGPBitFlag, mCompressionMethod); - LOGD(" modTime=0x%04x modDate=0x%04x crc32=0x%08lx\n", - mLastModFileTime, mLastModFileDate, mCRC32); - LOGD(" compressedSize=%lu uncompressedSize=%lu\n", - mCompressedSize, mUncompressedSize); - LOGD(" filenameLen=%u extraLen=%u\n", - mFileNameLength, mExtraFieldLength); - if (mFileName != NULL) - LOGD(" filename: '%s'\n", mFileName); -} - - -/* - * =========================================================================== - * ZipEntry::CentralDirEntry - * =========================================================================== - */ - -/* - * Read the central dir entry that appears next in the file. - * - * On entry, "fp" should be positioned on the signature bytes for the - * entry. On exit, "fp" will point at the signature word for the next - * entry or for the EOCD. - */ -status_t ZipEntry::CentralDirEntry::read(FILE* fp) -{ - status_t result = NO_ERROR; - unsigned char buf[kCDELen]; - - /* no re-use */ - assert(mFileName == NULL); - assert(mExtraField == NULL); - assert(mFileComment == NULL); - - if (fread(buf, 1, kCDELen, fp) != kCDELen) { - result = UNKNOWN_ERROR; - goto bail; - } - - if (ZipEntry::getLongLE(&buf[0x00]) != kSignature) { - LOGD("Whoops: didn't find expected signature\n"); - result = UNKNOWN_ERROR; - goto bail; - } - - mVersionMadeBy = ZipEntry::getShortLE(&buf[0x04]); - mVersionToExtract = ZipEntry::getShortLE(&buf[0x06]); - mGPBitFlag = ZipEntry::getShortLE(&buf[0x08]); - mCompressionMethod = ZipEntry::getShortLE(&buf[0x0a]); - mLastModFileTime = ZipEntry::getShortLE(&buf[0x0c]); - mLastModFileDate = ZipEntry::getShortLE(&buf[0x0e]); - mCRC32 = ZipEntry::getLongLE(&buf[0x10]); - mCompressedSize = ZipEntry::getLongLE(&buf[0x14]); - mUncompressedSize = ZipEntry::getLongLE(&buf[0x18]); - mFileNameLength = ZipEntry::getShortLE(&buf[0x1c]); - mExtraFieldLength = ZipEntry::getShortLE(&buf[0x1e]); - mFileCommentLength = ZipEntry::getShortLE(&buf[0x20]); - mDiskNumberStart = ZipEntry::getShortLE(&buf[0x22]); - mInternalAttrs = ZipEntry::getShortLE(&buf[0x24]); - mExternalAttrs = ZipEntry::getLongLE(&buf[0x26]); - mLocalHeaderRelOffset = ZipEntry::getLongLE(&buf[0x2a]); - - // TODO: validate sizes and offsets - - /* grab filename */ - if (mFileNameLength != 0) { - mFileName = new unsigned char[mFileNameLength+1]; - if (mFileName == NULL) { - result = NO_MEMORY; - goto bail; - } - if (fread(mFileName, 1, mFileNameLength, fp) != mFileNameLength) { - result = UNKNOWN_ERROR; - goto bail; - } - mFileName[mFileNameLength] = '\0'; - } - - /* read "extra field" */ - if (mExtraFieldLength != 0) { - mExtraField = new unsigned char[mExtraFieldLength+1]; - if (mExtraField == NULL) { - result = NO_MEMORY; - goto bail; - } - if (fread(mExtraField, 1, mExtraFieldLength, fp) != mExtraFieldLength) { - result = UNKNOWN_ERROR; - goto bail; - } - mExtraField[mExtraFieldLength] = '\0'; - } - - - /* grab comment, if any */ - if (mFileCommentLength != 0) { - mFileComment = new unsigned char[mFileCommentLength+1]; - if (mFileComment == NULL) { - result = NO_MEMORY; - goto bail; - } - if (fread(mFileComment, 1, mFileCommentLength, fp) != mFileCommentLength) - { - result = UNKNOWN_ERROR; - goto bail; - } - mFileComment[mFileCommentLength] = '\0'; - } - -bail: - return result; -} - -/* - * Write a central dir entry. - */ -status_t ZipEntry::CentralDirEntry::write(FILE* fp) -{ - unsigned char buf[kCDELen]; - - ZipEntry::putLongLE(&buf[0x00], kSignature); - ZipEntry::putShortLE(&buf[0x04], mVersionMadeBy); - ZipEntry::putShortLE(&buf[0x06], mVersionToExtract); - ZipEntry::putShortLE(&buf[0x08], mGPBitFlag); - ZipEntry::putShortLE(&buf[0x0a], mCompressionMethod); - ZipEntry::putShortLE(&buf[0x0c], mLastModFileTime); - ZipEntry::putShortLE(&buf[0x0e], mLastModFileDate); - ZipEntry::putLongLE(&buf[0x10], mCRC32); - ZipEntry::putLongLE(&buf[0x14], mCompressedSize); - ZipEntry::putLongLE(&buf[0x18], mUncompressedSize); - ZipEntry::putShortLE(&buf[0x1c], mFileNameLength); - ZipEntry::putShortLE(&buf[0x1e], mExtraFieldLength); - ZipEntry::putShortLE(&buf[0x20], mFileCommentLength); - ZipEntry::putShortLE(&buf[0x22], mDiskNumberStart); - ZipEntry::putShortLE(&buf[0x24], mInternalAttrs); - ZipEntry::putLongLE(&buf[0x26], mExternalAttrs); - ZipEntry::putLongLE(&buf[0x2a], mLocalHeaderRelOffset); - - if (fwrite(buf, 1, kCDELen, fp) != kCDELen) - return UNKNOWN_ERROR; - - /* write filename */ - if (mFileNameLength != 0) { - if (fwrite(mFileName, 1, mFileNameLength, fp) != mFileNameLength) - return UNKNOWN_ERROR; - } - - /* write "extra field" */ - if (mExtraFieldLength != 0) { - if (fwrite(mExtraField, 1, mExtraFieldLength, fp) != mExtraFieldLength) - return UNKNOWN_ERROR; - } - - /* write comment */ - if (mFileCommentLength != 0) { - if (fwrite(mFileComment, 1, mFileCommentLength, fp) != mFileCommentLength) - return UNKNOWN_ERROR; - } - - return NO_ERROR; -} - -/* - * Dump the contents of a CentralDirEntry object. - */ -void ZipEntry::CentralDirEntry::dump(void) const -{ - LOGD(" CentralDirEntry contents:\n"); - LOGD(" versMadeBy=%u versToExt=%u gpBits=0x%04x compression=%u\n", - mVersionMadeBy, mVersionToExtract, mGPBitFlag, mCompressionMethod); - LOGD(" modTime=0x%04x modDate=0x%04x crc32=0x%08lx\n", - mLastModFileTime, mLastModFileDate, mCRC32); - LOGD(" compressedSize=%lu uncompressedSize=%lu\n", - mCompressedSize, mUncompressedSize); - LOGD(" filenameLen=%u extraLen=%u commentLen=%u\n", - mFileNameLength, mExtraFieldLength, mFileCommentLength); - LOGD(" diskNumStart=%u intAttr=0x%04x extAttr=0x%08lx relOffset=%lu\n", - mDiskNumberStart, mInternalAttrs, mExternalAttrs, - mLocalHeaderRelOffset); - - if (mFileName != NULL) - LOGD(" filename: '%s'\n", mFileName); - if (mFileComment != NULL) - LOGD(" comment: '%s'\n", mFileComment); -} - diff --git a/libs/utils/ZipFile.cpp b/libs/utils/ZipFile.cpp deleted file mode 100644 index 6f27d17..0000000 --- a/libs/utils/ZipFile.cpp +++ /dev/null @@ -1,1296 +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. - */ - -// -// Access to Zip archives. -// - -#define LOG_TAG "zip" - -#include <utils/ZipFile.h> -#include <utils/ZipUtils.h> -#include <utils/Log.h> - -#include <zlib.h> -#define DEF_MEM_LEVEL 8 // normally in zutil.h? - -#include <memory.h> -#include <sys/stat.h> -#include <errno.h> -#include <assert.h> - -using namespace android; - -/* - * Some environments require the "b", some choke on it. - */ -#define FILE_OPEN_RO "rb" -#define FILE_OPEN_RW "r+b" -#define FILE_OPEN_RW_CREATE "w+b" - -/* should live somewhere else? */ -static status_t errnoToStatus(int err) -{ - if (err == ENOENT) - return NAME_NOT_FOUND; - else if (err == EACCES) - return PERMISSION_DENIED; - else - return UNKNOWN_ERROR; -} - -/* - * Open a file and parse its guts. - */ -status_t ZipFile::open(const char* zipFileName, int flags) -{ - bool newArchive = false; - - assert(mZipFp == NULL); // no reopen - - if ((flags & kOpenTruncate)) - flags |= kOpenCreate; // trunc implies create - - if ((flags & kOpenReadOnly) && (flags & kOpenReadWrite)) - return INVALID_OPERATION; // not both - if (!((flags & kOpenReadOnly) || (flags & kOpenReadWrite))) - return INVALID_OPERATION; // not neither - if ((flags & kOpenCreate) && !(flags & kOpenReadWrite)) - return INVALID_OPERATION; // create requires write - - if (flags & kOpenTruncate) { - newArchive = true; - } else { - newArchive = (access(zipFileName, F_OK) != 0); - if (!(flags & kOpenCreate) && newArchive) { - /* not creating, must already exist */ - LOGD("File %s does not exist", zipFileName); - return NAME_NOT_FOUND; - } - } - - /* open the file */ - const char* openflags; - if (flags & kOpenReadWrite) { - if (newArchive) - openflags = FILE_OPEN_RW_CREATE; - else - openflags = FILE_OPEN_RW; - } else { - openflags = FILE_OPEN_RO; - } - mZipFp = fopen(zipFileName, openflags); - if (mZipFp == NULL) { - int err = errno; - LOGD("fopen failed: %d\n", err); - return errnoToStatus(err); - } - - status_t result; - if (!newArchive) { - /* - * Load the central directory. If that fails, then this probably - * isn't a Zip archive. - */ - result = readCentralDir(); - } else { - /* - * Newly-created. The EndOfCentralDir constructor actually - * sets everything to be the way we want it (all zeroes). We - * set mNeedCDRewrite so that we create *something* if the - * caller doesn't add any files. (We could also just unlink - * the file if it's brand new and nothing was added, but that's - * probably doing more than we really should -- the user might - * have a need for empty zip files.) - */ - mNeedCDRewrite = true; - result = NO_ERROR; - } - - if (flags & kOpenReadOnly) - mReadOnly = true; - else - assert(!mReadOnly); - - return result; -} - -/* - * Return the Nth entry in the archive. - */ -ZipEntry* ZipFile::getEntryByIndex(int idx) const -{ - if (idx < 0 || idx >= (int) mEntries.size()) - return NULL; - - return mEntries[idx]; -} - -/* - * Find an entry by name. - */ -ZipEntry* ZipFile::getEntryByName(const char* fileName) const -{ - /* - * Do a stupid linear string-compare search. - * - * There are various ways to speed this up, especially since it's rare - * to intermingle changes to the archive with "get by name" calls. We - * don't want to sort the mEntries vector itself, however, because - * it's used to recreate the Central Directory. - * - * (Hash table works, parallel list of pointers in sorted order is good.) - */ - int idx; - - for (idx = mEntries.size()-1; idx >= 0; idx--) { - ZipEntry* pEntry = mEntries[idx]; - if (!pEntry->getDeleted() && - strcmp(fileName, pEntry->getFileName()) == 0) - { - return pEntry; - } - } - - return NULL; -} - -/* - * Empty the mEntries vector. - */ -void ZipFile::discardEntries(void) -{ - int count = mEntries.size(); - - while (--count >= 0) - delete mEntries[count]; - - mEntries.clear(); -} - - -/* - * Find the central directory and read the contents. - * - * The fun thing about ZIP archives is that they may or may not be - * readable from start to end. In some cases, notably for archives - * that were written to stdout, the only length information is in the - * central directory at the end of the file. - * - * Of course, the central directory can be followed by a variable-length - * comment field, so we have to scan through it backwards. The comment - * is at most 64K, plus we have 18 bytes for the end-of-central-dir stuff - * itself, plus apparently sometimes people throw random junk on the end - * just for the fun of it. - * - * This is all a little wobbly. If the wrong value ends up in the EOCD - * area, we're hosed. This appears to be the way that everbody handles - * it though, so we're in pretty good company if this fails. - */ -status_t ZipFile::readCentralDir(void) -{ - status_t result = NO_ERROR; - unsigned char* buf = NULL; - off_t fileLength, seekStart; - long readAmount; - int i; - - fseek(mZipFp, 0, SEEK_END); - fileLength = ftell(mZipFp); - rewind(mZipFp); - - /* too small to be a ZIP archive? */ - if (fileLength < EndOfCentralDir::kEOCDLen) { - LOGD("Length is %ld -- too small\n", (long)fileLength); - result = INVALID_OPERATION; - goto bail; - } - - buf = new unsigned char[EndOfCentralDir::kMaxEOCDSearch]; - if (buf == NULL) { - LOGD("Failure allocating %d bytes for EOCD search", - EndOfCentralDir::kMaxEOCDSearch); - result = NO_MEMORY; - goto bail; - } - - if (fileLength > EndOfCentralDir::kMaxEOCDSearch) { - seekStart = fileLength - EndOfCentralDir::kMaxEOCDSearch; - readAmount = EndOfCentralDir::kMaxEOCDSearch; - } else { - seekStart = 0; - readAmount = (long) fileLength; - } - if (fseek(mZipFp, seekStart, SEEK_SET) != 0) { - LOGD("Failure seeking to end of zip at %ld", (long) seekStart); - result = UNKNOWN_ERROR; - goto bail; - } - - /* read the last part of the file into the buffer */ - if (fread(buf, 1, readAmount, mZipFp) != (size_t) readAmount) { - LOGD("short file? wanted %ld\n", readAmount); - result = UNKNOWN_ERROR; - goto bail; - } - - /* find the end-of-central-dir magic */ - for (i = readAmount - 4; i >= 0; i--) { - if (buf[i] == 0x50 && - ZipEntry::getLongLE(&buf[i]) == EndOfCentralDir::kSignature) - { - LOGV("+++ Found EOCD at buf+%d\n", i); - break; - } - } - if (i < 0) { - LOGD("EOCD not found, not Zip\n"); - result = INVALID_OPERATION; - goto bail; - } - - /* extract eocd values */ - result = mEOCD.readBuf(buf + i, readAmount - i); - if (result != NO_ERROR) { - LOGD("Failure reading %ld bytes of EOCD values", readAmount - i); - goto bail; - } - //mEOCD.dump(); - - if (mEOCD.mDiskNumber != 0 || mEOCD.mDiskWithCentralDir != 0 || - mEOCD.mNumEntries != mEOCD.mTotalNumEntries) - { - LOGD("Archive spanning not supported\n"); - result = INVALID_OPERATION; - goto bail; - } - - /* - * So far so good. "mCentralDirSize" is the size in bytes of the - * central directory, so we can just seek back that far to find it. - * We can also seek forward mCentralDirOffset bytes from the - * start of the file. - * - * We're not guaranteed to have the rest of the central dir in the - * buffer, nor are we guaranteed that the central dir will have any - * sort of convenient size. We need to skip to the start of it and - * read the header, then the other goodies. - * - * The only thing we really need right now is the file comment, which - * we're hoping to preserve. - */ - if (fseek(mZipFp, mEOCD.mCentralDirOffset, SEEK_SET) != 0) { - LOGD("Failure seeking to central dir offset %ld\n", - mEOCD.mCentralDirOffset); - result = UNKNOWN_ERROR; - goto bail; - } - - /* - * Loop through and read the central dir entries. - */ - LOGV("Scanning %d entries...\n", mEOCD.mTotalNumEntries); - int entry; - for (entry = 0; entry < mEOCD.mTotalNumEntries; entry++) { - ZipEntry* pEntry = new ZipEntry; - - result = pEntry->initFromCDE(mZipFp); - if (result != NO_ERROR) { - LOGD("initFromCDE failed\n"); - delete pEntry; - goto bail; - } - - mEntries.add(pEntry); - } - - - /* - * If all went well, we should now be back at the EOCD. - */ - { - unsigned char checkBuf[4]; - if (fread(checkBuf, 1, 4, mZipFp) != 4) { - LOGD("EOCD check read failed\n"); - result = INVALID_OPERATION; - goto bail; - } - if (ZipEntry::getLongLE(checkBuf) != EndOfCentralDir::kSignature) { - LOGD("EOCD read check failed\n"); - result = UNKNOWN_ERROR; - goto bail; - } - LOGV("+++ EOCD read check passed\n"); - } - -bail: - delete[] buf; - return result; -} - - -/* - * Add a new file to the archive. - * - * This requires creating and populating a ZipEntry structure, and copying - * the data into the file at the appropriate position. The "appropriate - * position" is the current location of the central directory, which we - * casually overwrite (we can put it back later). - * - * If we were concerned about safety, we would want to make all changes - * in a temp file and then overwrite the original after everything was - * safely written. Not really a concern for us. - */ -status_t ZipFile::addCommon(const char* fileName, const void* data, size_t size, - const char* storageName, int sourceType, int compressionMethod, - ZipEntry** ppEntry) -{ - ZipEntry* pEntry = NULL; - status_t result = NO_ERROR; - long lfhPosn, startPosn, endPosn, uncompressedLen; - FILE* inputFp = NULL; - unsigned long crc; - time_t modWhen; - - if (mReadOnly) - return INVALID_OPERATION; - - assert(compressionMethod == ZipEntry::kCompressDeflated || - compressionMethod == ZipEntry::kCompressStored); - - /* make sure we're in a reasonable state */ - assert(mZipFp != NULL); - assert(mEntries.size() == mEOCD.mTotalNumEntries); - - /* make sure it doesn't already exist */ - if (getEntryByName(storageName) != NULL) - return ALREADY_EXISTS; - - if (!data) { - inputFp = fopen(fileName, FILE_OPEN_RO); - if (inputFp == NULL) - return errnoToStatus(errno); - } - - if (fseek(mZipFp, mEOCD.mCentralDirOffset, SEEK_SET) != 0) { - result = UNKNOWN_ERROR; - goto bail; - } - - pEntry = new ZipEntry; - pEntry->initNew(storageName, NULL); - - /* - * From here on out, failures are more interesting. - */ - mNeedCDRewrite = true; - - /* - * Write the LFH, even though it's still mostly blank. We need it - * as a place-holder. In theory the LFH isn't necessary, but in - * practice some utilities demand it. - */ - lfhPosn = ftell(mZipFp); - pEntry->mLFH.write(mZipFp); - startPosn = ftell(mZipFp); - - /* - * Copy the data in, possibly compressing it as we go. - */ - if (sourceType == ZipEntry::kCompressStored) { - if (compressionMethod == ZipEntry::kCompressDeflated) { - bool failed = false; - result = compressFpToFp(mZipFp, inputFp, data, size, &crc); - if (result != NO_ERROR) { - LOGD("compression failed, storing\n"); - failed = true; - } else { - /* - * Make sure it has compressed "enough". This probably ought - * to be set through an API call, but I don't expect our - * criteria to change over time. - */ - long src = inputFp ? ftell(inputFp) : size; - long dst = ftell(mZipFp) - startPosn; - if (dst + (dst / 10) > src) { - LOGD("insufficient compression (src=%ld dst=%ld), storing\n", - src, dst); - failed = true; - } - } - - if (failed) { - compressionMethod = ZipEntry::kCompressStored; - if (inputFp) rewind(inputFp); - fseek(mZipFp, startPosn, SEEK_SET); - /* fall through to kCompressStored case */ - } - } - /* handle "no compression" request, or failed compression from above */ - if (compressionMethod == ZipEntry::kCompressStored) { - if (inputFp) { - result = copyFpToFp(mZipFp, inputFp, &crc); - } else { - result = copyDataToFp(mZipFp, data, size, &crc); - } - if (result != NO_ERROR) { - // don't need to truncate; happens in CDE rewrite - LOGD("failed copying data in\n"); - goto bail; - } - } - - // currently seeked to end of file - uncompressedLen = inputFp ? ftell(inputFp) : size; - } else if (sourceType == ZipEntry::kCompressDeflated) { - /* we should support uncompressed-from-compressed, but it's not - * important right now */ - assert(compressionMethod == ZipEntry::kCompressDeflated); - - bool scanResult; - int method; - long compressedLen; - - scanResult = ZipUtils::examineGzip(inputFp, &method, &uncompressedLen, - &compressedLen, &crc); - if (!scanResult || method != ZipEntry::kCompressDeflated) { - LOGD("this isn't a deflated gzip file?"); - result = UNKNOWN_ERROR; - goto bail; - } - - result = copyPartialFpToFp(mZipFp, inputFp, compressedLen, NULL); - if (result != NO_ERROR) { - LOGD("failed copying gzip data in\n"); - goto bail; - } - } else { - assert(false); - result = UNKNOWN_ERROR; - goto bail; - } - - /* - * We could write the "Data Descriptor", but there doesn't seem to - * be any point since we're going to go back and write the LFH. - * - * Update file offsets. - */ - endPosn = ftell(mZipFp); // seeked to end of compressed data - - /* - * Success! Fill out new values. - */ - pEntry->setDataInfo(uncompressedLen, endPosn - startPosn, crc, - compressionMethod); - modWhen = getModTime(inputFp ? fileno(inputFp) : fileno(mZipFp)); - pEntry->setModWhen(modWhen); - pEntry->setLFHOffset(lfhPosn); - mEOCD.mNumEntries++; - mEOCD.mTotalNumEntries++; - mEOCD.mCentralDirSize = 0; // mark invalid; set by flush() - mEOCD.mCentralDirOffset = endPosn; - - /* - * Go back and write the LFH. - */ - if (fseek(mZipFp, lfhPosn, SEEK_SET) != 0) { - result = UNKNOWN_ERROR; - goto bail; - } - pEntry->mLFH.write(mZipFp); - - /* - * Add pEntry to the list. - */ - mEntries.add(pEntry); - if (ppEntry != NULL) - *ppEntry = pEntry; - pEntry = NULL; - -bail: - if (inputFp != NULL) - fclose(inputFp); - delete pEntry; - return result; -} - -/* - * Add an entry by copying it from another zip file. If "padding" is - * nonzero, the specified number of bytes will be added to the "extra" - * field in the header. - * - * If "ppEntry" is non-NULL, a pointer to the new entry will be returned. - */ -status_t ZipFile::add(const ZipFile* pSourceZip, const ZipEntry* pSourceEntry, - int padding, ZipEntry** ppEntry) -{ - ZipEntry* pEntry = NULL; - status_t result; - long lfhPosn, endPosn; - - if (mReadOnly) - return INVALID_OPERATION; - - /* make sure we're in a reasonable state */ - assert(mZipFp != NULL); - assert(mEntries.size() == mEOCD.mTotalNumEntries); - - if (fseek(mZipFp, mEOCD.mCentralDirOffset, SEEK_SET) != 0) { - result = UNKNOWN_ERROR; - goto bail; - } - - pEntry = new ZipEntry; - if (pEntry == NULL) { - result = NO_MEMORY; - goto bail; - } - - result = pEntry->initFromExternal(pSourceZip, pSourceEntry); - if (result != NO_ERROR) - goto bail; - if (padding != 0) { - result = pEntry->addPadding(padding); - if (result != NO_ERROR) - goto bail; - } - - /* - * From here on out, failures are more interesting. - */ - mNeedCDRewrite = true; - - /* - * Write the LFH. Since we're not recompressing the data, we already - * have all of the fields filled out. - */ - lfhPosn = ftell(mZipFp); - pEntry->mLFH.write(mZipFp); - - /* - * Copy the data over. - * - * If the "has data descriptor" flag is set, we want to copy the DD - * fields as well. This is a fixed-size area immediately following - * the data. - */ - if (fseek(pSourceZip->mZipFp, pSourceEntry->getFileOffset(), SEEK_SET) != 0) - { - result = UNKNOWN_ERROR; - goto bail; - } - - off_t copyLen; - copyLen = pSourceEntry->getCompressedLen(); - if ((pSourceEntry->mLFH.mGPBitFlag & ZipEntry::kUsesDataDescr) != 0) - copyLen += ZipEntry::kDataDescriptorLen; - - if (copyPartialFpToFp(mZipFp, pSourceZip->mZipFp, copyLen, NULL) - != NO_ERROR) - { - LOGW("copy of '%s' failed\n", pEntry->mCDE.mFileName); - result = UNKNOWN_ERROR; - goto bail; - } - - /* - * Update file offsets. - */ - endPosn = ftell(mZipFp); - - /* - * Success! Fill out new values. - */ - pEntry->setLFHOffset(lfhPosn); // sets mCDE.mLocalHeaderRelOffset - mEOCD.mNumEntries++; - mEOCD.mTotalNumEntries++; - mEOCD.mCentralDirSize = 0; // mark invalid; set by flush() - mEOCD.mCentralDirOffset = endPosn; - - /* - * Add pEntry to the list. - */ - mEntries.add(pEntry); - if (ppEntry != NULL) - *ppEntry = pEntry; - pEntry = NULL; - - result = NO_ERROR; - -bail: - delete pEntry; - return result; -} - -/* - * Copy all of the bytes in "src" to "dst". - * - * On exit, "srcFp" will be seeked to the end of the file, and "dstFp" - * will be seeked immediately past the data. - */ -status_t ZipFile::copyFpToFp(FILE* dstFp, FILE* srcFp, unsigned long* pCRC32) -{ - unsigned char tmpBuf[32768]; - size_t count; - - *pCRC32 = crc32(0L, Z_NULL, 0); - - while (1) { - count = fread(tmpBuf, 1, sizeof(tmpBuf), srcFp); - if (ferror(srcFp) || ferror(dstFp)) - return errnoToStatus(errno); - if (count == 0) - break; - - *pCRC32 = crc32(*pCRC32, tmpBuf, count); - - if (fwrite(tmpBuf, 1, count, dstFp) != count) { - LOGD("fwrite %d bytes failed\n", (int) count); - return UNKNOWN_ERROR; - } - } - - return NO_ERROR; -} - -/* - * Copy all of the bytes in "src" to "dst". - * - * On exit, "dstFp" will be seeked immediately past the data. - */ -status_t ZipFile::copyDataToFp(FILE* dstFp, - const void* data, size_t size, unsigned long* pCRC32) -{ - size_t count; - - *pCRC32 = crc32(0L, Z_NULL, 0); - if (size > 0) { - *pCRC32 = crc32(*pCRC32, (const unsigned char*)data, size); - if (fwrite(data, 1, size, dstFp) != size) { - LOGD("fwrite %d bytes failed\n", (int) size); - return UNKNOWN_ERROR; - } - } - - return NO_ERROR; -} - -/* - * Copy some of the bytes in "src" to "dst". - * - * If "pCRC32" is NULL, the CRC will not be computed. - * - * On exit, "srcFp" will be seeked to the end of the file, and "dstFp" - * will be seeked immediately past the data just written. - */ -status_t ZipFile::copyPartialFpToFp(FILE* dstFp, FILE* srcFp, long length, - unsigned long* pCRC32) -{ - unsigned char tmpBuf[32768]; - size_t count; - - if (pCRC32 != NULL) - *pCRC32 = crc32(0L, Z_NULL, 0); - - while (length) { - long readSize; - - readSize = sizeof(tmpBuf); - if (readSize > length) - readSize = length; - - count = fread(tmpBuf, 1, readSize, srcFp); - if ((long) count != readSize) { // error or unexpected EOF - LOGD("fread %d bytes failed\n", (int) readSize); - return UNKNOWN_ERROR; - } - - if (pCRC32 != NULL) - *pCRC32 = crc32(*pCRC32, tmpBuf, count); - - if (fwrite(tmpBuf, 1, count, dstFp) != count) { - LOGD("fwrite %d bytes failed\n", (int) count); - return UNKNOWN_ERROR; - } - - length -= readSize; - } - - return NO_ERROR; -} - -/* - * Compress all of the data in "srcFp" and write it to "dstFp". - * - * On exit, "srcFp" will be seeked to the end of the file, and "dstFp" - * will be seeked immediately past the compressed data. - */ -status_t ZipFile::compressFpToFp(FILE* dstFp, FILE* srcFp, - const void* data, size_t size, unsigned long* pCRC32) -{ - status_t result = NO_ERROR; - const size_t kBufSize = 32768; - unsigned char* inBuf = NULL; - unsigned char* outBuf = NULL; - z_stream zstream; - bool atEof = false; // no feof() aviailable yet - unsigned long crc; - int zerr; - - /* - * Create an input buffer and an output buffer. - */ - inBuf = new unsigned char[kBufSize]; - outBuf = new unsigned char[kBufSize]; - if (inBuf == NULL || outBuf == NULL) { - result = NO_MEMORY; - goto bail; - } - - /* - * Initialize the zlib stream. - */ - memset(&zstream, 0, sizeof(zstream)); - zstream.zalloc = Z_NULL; - zstream.zfree = Z_NULL; - zstream.opaque = Z_NULL; - zstream.next_in = NULL; - zstream.avail_in = 0; - zstream.next_out = outBuf; - zstream.avail_out = kBufSize; - zstream.data_type = Z_UNKNOWN; - - zerr = deflateInit2(&zstream, Z_BEST_COMPRESSION, - Z_DEFLATED, -MAX_WBITS, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY); - if (zerr != Z_OK) { - result = UNKNOWN_ERROR; - if (zerr == Z_VERSION_ERROR) { - LOGE("Installed zlib is not compatible with linked version (%s)\n", - ZLIB_VERSION); - } else { - LOGD("Call to deflateInit2 failed (zerr=%d)\n", zerr); - } - goto bail; - } - - crc = crc32(0L, Z_NULL, 0); - - /* - * Loop while we have data. - */ - do { - size_t getSize; - int flush; - - /* only read if the input buffer is empty */ - if (zstream.avail_in == 0 && !atEof) { - LOGV("+++ reading %d bytes\n", (int)kBufSize); - if (data) { - getSize = size > kBufSize ? kBufSize : size; - memcpy(inBuf, data, getSize); - data = ((const char*)data) + getSize; - size -= getSize; - } else { - getSize = fread(inBuf, 1, kBufSize, srcFp); - if (ferror(srcFp)) { - LOGD("deflate read failed (errno=%d)\n", errno); - goto z_bail; - } - } - if (getSize < kBufSize) { - LOGV("+++ got %d bytes, EOF reached\n", - (int)getSize); - atEof = true; - } - - crc = crc32(crc, inBuf, getSize); - - zstream.next_in = inBuf; - zstream.avail_in = getSize; - } - - if (atEof) - flush = Z_FINISH; /* tell zlib that we're done */ - else - flush = Z_NO_FLUSH; /* more to come! */ - - zerr = deflate(&zstream, flush); - if (zerr != Z_OK && zerr != Z_STREAM_END) { - LOGD("zlib deflate call failed (zerr=%d)\n", zerr); - result = UNKNOWN_ERROR; - goto z_bail; - } - - /* write when we're full or when we're done */ - if (zstream.avail_out == 0 || - (zerr == Z_STREAM_END && zstream.avail_out != (uInt) kBufSize)) - { - LOGV("+++ writing %d bytes\n", (int) (zstream.next_out - outBuf)); - if (fwrite(outBuf, 1, zstream.next_out - outBuf, dstFp) != - (size_t)(zstream.next_out - outBuf)) - { - LOGD("write %d failed in deflate\n", - (int) (zstream.next_out - outBuf)); - goto z_bail; - } - - zstream.next_out = outBuf; - zstream.avail_out = kBufSize; - } - } while (zerr == Z_OK); - - assert(zerr == Z_STREAM_END); /* other errors should've been caught */ - - *pCRC32 = crc; - -z_bail: - deflateEnd(&zstream); /* free up any allocated structures */ - -bail: - delete[] inBuf; - delete[] outBuf; - - return result; -} - -/* - * Mark an entry as deleted. - * - * We will eventually need to crunch the file down, but if several files - * are being removed (perhaps as part of an "update" process) we can make - * things considerably faster by deferring the removal to "flush" time. - */ -status_t ZipFile::remove(ZipEntry* pEntry) -{ - /* - * Should verify that pEntry is actually part of this archive, and - * not some stray ZipEntry from a different file. - */ - - /* mark entry as deleted, and mark archive as dirty */ - pEntry->setDeleted(); - mNeedCDRewrite = true; - return NO_ERROR; -} - -/* - * Flush any pending writes. - * - * In particular, this will crunch out deleted entries, and write the - * Central Directory and EOCD if we have stomped on them. - */ -status_t ZipFile::flush(void) -{ - status_t result = NO_ERROR; - long eocdPosn; - int i, count; - - if (mReadOnly) - return INVALID_OPERATION; - if (!mNeedCDRewrite) - return NO_ERROR; - - assert(mZipFp != NULL); - - result = crunchArchive(); - if (result != NO_ERROR) - return result; - - if (fseek(mZipFp, mEOCD.mCentralDirOffset, SEEK_SET) != 0) - return UNKNOWN_ERROR; - - count = mEntries.size(); - for (i = 0; i < count; i++) { - ZipEntry* pEntry = mEntries[i]; - pEntry->mCDE.write(mZipFp); - } - - eocdPosn = ftell(mZipFp); - mEOCD.mCentralDirSize = eocdPosn - mEOCD.mCentralDirOffset; - - mEOCD.write(mZipFp); - - /* - * If we had some stuff bloat up during compression and get replaced - * with plain files, or if we deleted some entries, there's a lot - * of wasted space at the end of the file. Remove it now. - */ - if (ftruncate(fileno(mZipFp), ftell(mZipFp)) != 0) { - LOGW("ftruncate failed %ld: %s\n", ftell(mZipFp), strerror(errno)); - // not fatal - } - - /* should we clear the "newly added" flag in all entries now? */ - - mNeedCDRewrite = false; - return NO_ERROR; -} - -/* - * Crunch deleted files out of an archive by shifting the later files down. - * - * Because we're not using a temp file, we do the operation inside the - * current file. - */ -status_t ZipFile::crunchArchive(void) -{ - status_t result = NO_ERROR; - int i, count; - long delCount, adjust; - -#if 0 - printf("CONTENTS:\n"); - for (i = 0; i < (int) mEntries.size(); i++) { - printf(" %d: lfhOff=%ld del=%d\n", - i, mEntries[i]->getLFHOffset(), mEntries[i]->getDeleted()); - } - printf(" END is %ld\n", (long) mEOCD.mCentralDirOffset); -#endif - - /* - * Roll through the set of files, shifting them as appropriate. We - * could probably get a slight performance improvement by sliding - * multiple files down at once (because we could use larger reads - * when operating on batches of small files), but it's not that useful. - */ - count = mEntries.size(); - delCount = adjust = 0; - for (i = 0; i < count; i++) { - ZipEntry* pEntry = mEntries[i]; - long span; - - if (pEntry->getLFHOffset() != 0) { - long nextOffset; - - /* Get the length of this entry by finding the offset - * of the next entry. Directory entries don't have - * file offsets, so we need to find the next non-directory - * entry. - */ - nextOffset = 0; - for (int ii = i+1; nextOffset == 0 && ii < count; ii++) - nextOffset = mEntries[ii]->getLFHOffset(); - if (nextOffset == 0) - nextOffset = mEOCD.mCentralDirOffset; - span = nextOffset - pEntry->getLFHOffset(); - - assert(span >= ZipEntry::LocalFileHeader::kLFHLen); - } else { - /* This is a directory entry. It doesn't have - * any actual file contents, so there's no need to - * move anything. - */ - span = 0; - } - - //printf("+++ %d: off=%ld span=%ld del=%d [count=%d]\n", - // i, pEntry->getLFHOffset(), span, pEntry->getDeleted(), count); - - if (pEntry->getDeleted()) { - adjust += span; - delCount++; - - delete pEntry; - mEntries.removeAt(i); - - /* adjust loop control */ - count--; - i--; - } else if (span != 0 && adjust > 0) { - /* shuffle this entry back */ - //printf("+++ Shuffling '%s' back %ld\n", - // pEntry->getFileName(), adjust); - result = filemove(mZipFp, pEntry->getLFHOffset() - adjust, - pEntry->getLFHOffset(), span); - if (result != NO_ERROR) { - /* this is why you use a temp file */ - LOGE("error during crunch - archive is toast\n"); - return result; - } - - pEntry->setLFHOffset(pEntry->getLFHOffset() - adjust); - } - } - - /* - * Fix EOCD info. We have to wait until the end to do some of this - * because we use mCentralDirOffset to determine "span" for the - * last entry. - */ - mEOCD.mCentralDirOffset -= adjust; - mEOCD.mNumEntries -= delCount; - mEOCD.mTotalNumEntries -= delCount; - mEOCD.mCentralDirSize = 0; // mark invalid; set by flush() - - assert(mEOCD.mNumEntries == mEOCD.mTotalNumEntries); - assert(mEOCD.mNumEntries == count); - - return result; -} - -/* - * Works like memmove(), but on pieces of a file. - */ -status_t ZipFile::filemove(FILE* fp, off_t dst, off_t src, size_t n) -{ - if (dst == src || n <= 0) - return NO_ERROR; - - unsigned char readBuf[32768]; - - if (dst < src) { - /* shift stuff toward start of file; must read from start */ - while (n != 0) { - size_t getSize = sizeof(readBuf); - if (getSize > n) - getSize = n; - - if (fseek(fp, (long) src, SEEK_SET) != 0) { - LOGD("filemove src seek %ld failed\n", (long) src); - return UNKNOWN_ERROR; - } - - if (fread(readBuf, 1, getSize, fp) != getSize) { - LOGD("filemove read %ld off=%ld failed\n", - (long) getSize, (long) src); - return UNKNOWN_ERROR; - } - - if (fseek(fp, (long) dst, SEEK_SET) != 0) { - LOGD("filemove dst seek %ld failed\n", (long) dst); - return UNKNOWN_ERROR; - } - - if (fwrite(readBuf, 1, getSize, fp) != getSize) { - LOGD("filemove write %ld off=%ld failed\n", - (long) getSize, (long) dst); - return UNKNOWN_ERROR; - } - - src += getSize; - dst += getSize; - n -= getSize; - } - } else { - /* shift stuff toward end of file; must read from end */ - assert(false); // write this someday, maybe - return UNKNOWN_ERROR; - } - - return NO_ERROR; -} - - -/* - * Get the modification time from a file descriptor. - */ -time_t ZipFile::getModTime(int fd) -{ - struct stat sb; - - if (fstat(fd, &sb) < 0) { - LOGD("HEY: fstat on fd %d failed\n", fd); - return (time_t) -1; - } - - return sb.st_mtime; -} - - -#if 0 /* this is a bad idea */ -/* - * Get a copy of the Zip file descriptor. - * - * We don't allow this if the file was opened read-write because we tend - * to leave the file contents in an uncertain state between calls to - * flush(). The duplicated file descriptor should only be valid for reads. - */ -int ZipFile::getZipFd(void) const -{ - if (!mReadOnly) - return INVALID_OPERATION; - assert(mZipFp != NULL); - - int fd; - fd = dup(fileno(mZipFp)); - if (fd < 0) { - LOGD("didn't work, errno=%d\n", errno); - } - - return fd; -} -#endif - - -#if 0 -/* - * Expand data. - */ -bool ZipFile::uncompress(const ZipEntry* pEntry, void* buf) const -{ - return false; -} -#endif - -// free the memory when you're done -void* ZipFile::uncompress(const ZipEntry* entry) -{ - size_t unlen = entry->getUncompressedLen(); - size_t clen = entry->getCompressedLen(); - - void* buf = malloc(unlen); - if (buf == NULL) { - return NULL; - } - - fseek(mZipFp, 0, SEEK_SET); - - off_t offset = entry->getFileOffset(); - if (fseek(mZipFp, offset, SEEK_SET) != 0) { - goto bail; - } - - switch (entry->getCompressionMethod()) - { - case ZipEntry::kCompressStored: { - ssize_t amt = fread(buf, 1, unlen, mZipFp); - if (amt != (ssize_t)unlen) { - goto bail; - } -#if 0 - printf("data...\n"); - const unsigned char* p = (unsigned char*)buf; - const unsigned char* end = p+unlen; - for (int i=0; i<32 && p < end; i++) { - printf("0x%08x ", (int)(offset+(i*0x10))); - for (int j=0; j<0x10 && p < end; j++) { - printf(" %02x", *p); - p++; - } - printf("\n"); - } -#endif - - } - break; - case ZipEntry::kCompressDeflated: { - if (!ZipUtils::inflateToBuffer(mZipFp, buf, unlen, clen)) { - goto bail; - } - } - break; - default: - goto bail; - } - return buf; - -bail: - free(buf); - return NULL; -} - - -/* - * =========================================================================== - * ZipFile::EndOfCentralDir - * =========================================================================== - */ - -/* - * Read the end-of-central-dir fields. - * - * "buf" should be positioned at the EOCD signature, and should contain - * the entire EOCD area including the comment. - */ -status_t ZipFile::EndOfCentralDir::readBuf(const unsigned char* buf, int len) -{ - /* don't allow re-use */ - assert(mComment == NULL); - - if (len < kEOCDLen) { - /* looks like ZIP file got truncated */ - LOGD(" Zip EOCD: expected >= %d bytes, found %d\n", - kEOCDLen, len); - return INVALID_OPERATION; - } - - /* this should probably be an assert() */ - if (ZipEntry::getLongLE(&buf[0x00]) != kSignature) - return UNKNOWN_ERROR; - - mDiskNumber = ZipEntry::getShortLE(&buf[0x04]); - mDiskWithCentralDir = ZipEntry::getShortLE(&buf[0x06]); - mNumEntries = ZipEntry::getShortLE(&buf[0x08]); - mTotalNumEntries = ZipEntry::getShortLE(&buf[0x0a]); - mCentralDirSize = ZipEntry::getLongLE(&buf[0x0c]); - mCentralDirOffset = ZipEntry::getLongLE(&buf[0x10]); - mCommentLen = ZipEntry::getShortLE(&buf[0x14]); - - // TODO: validate mCentralDirOffset - - if (mCommentLen > 0) { - if (kEOCDLen + mCommentLen > len) { - LOGD("EOCD(%d) + comment(%d) exceeds len (%d)\n", - kEOCDLen, mCommentLen, len); - return UNKNOWN_ERROR; - } - mComment = new unsigned char[mCommentLen]; - memcpy(mComment, buf + kEOCDLen, mCommentLen); - } - - return NO_ERROR; -} - -/* - * Write an end-of-central-directory section. - */ -status_t ZipFile::EndOfCentralDir::write(FILE* fp) -{ - unsigned char buf[kEOCDLen]; - - ZipEntry::putLongLE(&buf[0x00], kSignature); - ZipEntry::putShortLE(&buf[0x04], mDiskNumber); - ZipEntry::putShortLE(&buf[0x06], mDiskWithCentralDir); - ZipEntry::putShortLE(&buf[0x08], mNumEntries); - ZipEntry::putShortLE(&buf[0x0a], mTotalNumEntries); - ZipEntry::putLongLE(&buf[0x0c], mCentralDirSize); - ZipEntry::putLongLE(&buf[0x10], mCentralDirOffset); - ZipEntry::putShortLE(&buf[0x14], mCommentLen); - - if (fwrite(buf, 1, kEOCDLen, fp) != kEOCDLen) - return UNKNOWN_ERROR; - if (mCommentLen > 0) { - assert(mComment != NULL); - if (fwrite(mComment, mCommentLen, 1, fp) != mCommentLen) - return UNKNOWN_ERROR; - } - - return NO_ERROR; -} - -/* - * Dump the contents of an EndOfCentralDir object. - */ -void ZipFile::EndOfCentralDir::dump(void) const -{ - LOGD(" EndOfCentralDir contents:\n"); - LOGD(" diskNum=%u diskWCD=%u numEnt=%u totalNumEnt=%u\n", - mDiskNumber, mDiskWithCentralDir, mNumEntries, mTotalNumEntries); - LOGD(" centDirSize=%lu centDirOff=%lu commentLen=%u\n", - mCentralDirSize, mCentralDirOffset, mCommentLen); -} - diff --git a/libs/utils/executablepath_darwin.cpp b/libs/utils/executablepath_darwin.cpp deleted file mode 100644 index 2e3c3a0..0000000 --- a/libs/utils/executablepath_darwin.cpp +++ /dev/null @@ -1,31 +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 <utils/executablepath.h> -#import <Carbon/Carbon.h> -#include <unistd.h> - -void executablepath(char s[PATH_MAX]) -{ - ProcessSerialNumber psn; - GetCurrentProcess(&psn); - CFDictionaryRef dict; - dict = ProcessInformationCopyDictionary(&psn, 0xffffffff); - CFStringRef value = (CFStringRef)CFDictionaryGetValue(dict, - CFSTR("CFBundleExecutable")); - CFStringGetCString(value, s, PATH_MAX+1, kCFStringEncodingUTF8); -} - diff --git a/libs/utils/executablepath_linux.cpp b/libs/utils/executablepath_linux.cpp deleted file mode 100644 index b8d2a3d..0000000 --- a/libs/utils/executablepath_linux.cpp +++ /dev/null @@ -1,30 +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 <utils/executablepath.h> -#include <sys/types.h> -#include <unistd.h> -#include <limits.h> -#include <stdio.h> - -void executablepath(char exe[PATH_MAX]) -{ - char proc[100]; - sprintf(proc, "/proc/%d/exe", getpid()); - - int err = readlink(proc, exe, PATH_MAX); -} - diff --git a/libs/utils/ported.cpp b/libs/utils/ported.cpp deleted file mode 100644 index 656e46f..0000000 --- a/libs/utils/ported.cpp +++ /dev/null @@ -1,106 +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. - */ - -// -// Ports of standard functions that don't exist on a specific platform. -// -// Note these are NOT in the "android" namespace. -// -#include <utils/ported.h> - -#if defined(NEED_GETTIMEOFDAY) || defined(NEED_USLEEP) -# include <sys/time.h> -# include <windows.h> -#endif - - -#if defined(NEED_GETTIMEOFDAY) -/* - * Replacement gettimeofday() for Windows environments (primarily MinGW). - * - * Ignores "tz". - */ -int gettimeofday(struct timeval* ptv, struct timezone* tz) -{ - long long nsTime; // time in 100ns units since Jan 1 1601 - FILETIME ft; - - if (tz != NULL) { - // oh well - } - - ::GetSystemTimeAsFileTime(&ft); - nsTime = (long long) ft.dwHighDateTime << 32 | - (long long) ft.dwLowDateTime; - // convert to time in usec since Jan 1 1970 - ptv->tv_usec = (long) ((nsTime / 10LL) % 1000000LL); - ptv->tv_sec = (long) ((nsTime - 116444736000000000LL) / 10000000LL); - - return 0; -} -#endif - -#if defined(NEED_USLEEP) -// -// Replacement usleep for Windows environments (primarily MinGW). -// -void usleep(unsigned long usec) -{ - // Win32 API function Sleep() takes milliseconds - ::Sleep((usec + 500) / 1000); -} -#endif - -#if 0 //defined(NEED_PIPE) -// -// Replacement pipe() command for MinGW -// -// The _O_NOINHERIT flag sets bInheritHandle to FALSE in the -// SecurityAttributes argument to CreatePipe(). This means the handles -// aren't inherited when a new process is created. The examples I've seen -// use it, possibly because there's a lot of junk going on behind the -// scenes. (I'm assuming "process" and "thread" are different here, so -// we should be okay spinning up a thread.) The recommended practice is -// to dup() the descriptor you want the child to have. -// -// It appears that unnamed pipes can't do non-blocking ("overlapped") I/O. -// You can't use select() either, since that only works on sockets. The -// Windows API calls that are useful here all operate on a HANDLE, not -// an integer file descriptor, and I don't think you can get there from -// here. The "named pipe" stuff is insane. -// -int pipe(int filedes[2]) -{ - return _pipe(filedes, 0, _O_BINARY | _O_NOINHERIT); -} -#endif - -#if defined(NEED_SETENV) -/* - * MinGW lacks these. For now, just stub them out so the code compiles. - */ -int setenv(const char* name, const char* value, int overwrite) -{ - return 0; -} -void unsetenv(const char* name) -{ -} -char* getenv(const char* name) -{ - return NULL; -} -#endif |