diff options
Diffstat (limited to 'libs/utils')
-rw-r--r-- | libs/utils/Android.mk | 13 | ||||
-rw-r--r-- | libs/utils/AssetManager.cpp | 59 | ||||
-rw-r--r-- | libs/utils/Binder.cpp | 242 | ||||
-rw-r--r-- | libs/utils/BpBinder.cpp | 348 | ||||
-rw-r--r-- | libs/utils/IDataConnection.cpp | 89 | ||||
-rw-r--r-- | libs/utils/IInterface.cpp | 35 | ||||
-rw-r--r-- | libs/utils/IMemory.cpp | 486 | ||||
-rw-r--r-- | libs/utils/IPCThreadState.cpp | 1030 | ||||
-rw-r--r-- | libs/utils/IPermissionController.cpp | 86 | ||||
-rw-r--r-- | libs/utils/IServiceManager.cpp | 230 | ||||
-rw-r--r-- | libs/utils/MemoryBase.cpp | 46 | ||||
-rw-r--r-- | libs/utils/MemoryDealer.cpp | 409 | ||||
-rw-r--r-- | libs/utils/MemoryHeapBase.cpp | 183 | ||||
-rw-r--r-- | libs/utils/MemoryHeapPmem.cpp | 248 | ||||
-rw-r--r-- | libs/utils/Parcel.cpp | 1359 | ||||
-rw-r--r-- | libs/utils/ProcessState.cpp | 398 | ||||
-rw-r--r-- | libs/utils/Static.cpp | 31 | ||||
-rw-r--r-- | libs/utils/backup_data.cpp | 253 | ||||
-rw-r--r-- | libs/utils/backup_helper_file.cpp | 341 |
19 files changed, 576 insertions, 5310 deletions
diff --git a/libs/utils/Android.mk b/libs/utils/Android.mk index 5a1a89b..30b6733 100644 --- a/libs/utils/Android.mk +++ b/libs/utils/Android.mk @@ -103,19 +103,6 @@ include $(CLEAR_VARS) # we have the common sources, plus some device-specific stuff LOCAL_SRC_FILES:= \ $(commonSources) \ - Binder.cpp \ - BpBinder.cpp \ - IInterface.cpp \ - IMemory.cpp \ - IPCThreadState.cpp \ - MemoryDealer.cpp \ - MemoryBase.cpp \ - MemoryHeapBase.cpp \ - MemoryHeapPmem.cpp \ - Parcel.cpp \ - ProcessState.cpp \ - IPermissionController.cpp \ - IServiceManager.cpp \ Unicode.cpp \ backup_data.cpp \ backup_helper_file.cpp diff --git a/libs/utils/AssetManager.cpp b/libs/utils/AssetManager.cpp index 447b801..4126bfb 100644 --- a/libs/utils/AssetManager.cpp +++ b/libs/utils/AssetManager.cpp @@ -901,6 +901,60 @@ AssetDir* AssetManager::openDir(const char* dirName) } /* + * Open a directory in the non-asset namespace. + * + * An "asset directory" is simply the combination of all files in all + * locations, with ".gz" stripped for loose files. With app, locale, and + * vendor defined, we have 8 directories and 2 Zip archives to scan. + * + * Pass in "" for the root dir. + */ +AssetDir* AssetManager::openNonAssetDir(void* cookie, const char* dirName) +{ + AutoMutex _l(mLock); + + AssetDir* pDir = NULL; + SortedVector<AssetDir::FileInfo>* pMergedInfo = NULL; + + LOG_FATAL_IF(mAssetPaths.size() == 0, "No assets added to AssetManager"); + assert(dirName != NULL); + + //printf("+++ openDir(%s) in '%s'\n", dirName, (const char*) mAssetBase); + + if (mCacheMode != CACHE_OFF && !mCacheValid) + loadFileNameCacheLocked(); + + pDir = new AssetDir; + + pMergedInfo = new SortedVector<AssetDir::FileInfo>; + + const size_t which = ((size_t)cookie)-1; + + if (which < mAssetPaths.size()) { + const asset_path& ap = mAssetPaths.itemAt(which); + if (ap.type == kFileTypeRegular) { + LOGV("Adding directory %s from zip %s", dirName, ap.path.string()); + scanAndMergeZipLocked(pMergedInfo, ap, NULL, dirName); + } else { + LOGV("Adding directory %s from dir %s", dirName, ap.path.string()); + scanAndMergeDirLocked(pMergedInfo, ap, NULL, dirName); + } + } + +#if 0 + printf("FILE LIST:\n"); + for (i = 0; i < (size_t) pMergedInfo->size(); i++) { + printf(" %d: (%d) '%s'\n", i, + pMergedInfo->itemAt(i).getFileType(), + (const char*) pMergedInfo->itemAt(i).getFileName()); + } +#endif + + pDir->setFileList(pMergedInfo); + return pDir; +} + +/* * Scan the contents of the specified directory and merge them into the * "pMergedInfo" vector, removing previous entries if we find "exclude" * directives. @@ -1143,6 +1197,7 @@ bool AssetManager::scanAndMergeZipLocked(SortedVector<AssetDir::FileInfo>* pMerg LOGE("ARGH: name too long?\n"); continue; } + //printf("Comparing %s in %s?\n", nameBuf, dirName.string()); if (dirNameLen == 0 || (strncmp(nameBuf, dirName.string(), dirNameLen) == 0 && nameBuf[dirNameLen] == '/')) @@ -1165,7 +1220,7 @@ bool AssetManager::scanAndMergeZipLocked(SortedVector<AssetDir::FileInfo>* pMerg createZipSourceNameLocked(zipName, dirName, info.getFileName())); contents.add(info); - //printf("FOUND: file '%s'\n", (const char*) info.mFileName); + //printf("FOUND: file '%s'\n", info.getFileName().string()); } else { /* this is a subdir; add it if we don't already have it*/ String8 subdirName(cp, nextSlash - cp); @@ -1181,7 +1236,7 @@ bool AssetManager::scanAndMergeZipLocked(SortedVector<AssetDir::FileInfo>* pMerg dirs.add(subdirName); } - //printf("FOUND: dir '%s'\n", (const char*) subdirName); + //printf("FOUND: dir '%s'\n", subdirName.string()); } } } 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/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/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 e74ad4a..0000000 --- a/libs/utils/Parcel.cpp +++ /dev/null @@ -1,1359 +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++; - - const flat_binder_object* flat - = reinterpret_cast<flat_binder_object*>(mData + off); - acquire_object(proc, *flat, this); - - // take note if the object is a file descriptor - if (flat->type == BINDER_TYPE_FD) { - 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/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/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/backup_data.cpp b/libs/utils/backup_data.cpp index c7f1fdb..95c05b7 100644 --- a/libs/utils/backup_data.cpp +++ b/libs/utils/backup_data.cpp @@ -14,12 +14,16 @@ * limitations under the License. */ +#define LOG_TAG "backup_data" + #include <utils/backup_helpers.h> #include <utils/ByteOrder.h> #include <stdio.h> #include <unistd.h> +#include <cutils/log.h> + namespace android { /* @@ -35,26 +39,6 @@ namespace android { * - The value, padded to 4 byte boundary */ -#define APP_MAGIC_V1 0x31707041 // App1 (little endian) -#define ENTITY_MAGIC_V1 0x61746144 // Data (little endian) -#define FOOTER_MAGIC_V1 0x746f6f46 // Foot (little endian) - -typedef struct { - int type; // == APP_MAGIC_V1 - int packageLen; // length of the name of the package that follows, not including the null. -} app_header_v1; - -typedef struct { - int type; // ENTITY_MAGIC_V1 - int keyLen; // length of the key name, not including the null terminator - int dataSize; // size of the data, not including the padding -} entity_header_v1; - -typedef struct { - int type; // FOOTER_MAGIC_V1 - int entityCount; // the number of entities that were written -} app_footer_v1; - const static int ROUND_UP[4] = { 0, 3, 2, 1 }; static inline size_t @@ -102,7 +86,7 @@ BackupDataWriter::write_padding_for(int n) } status_t -BackupDataWriter::WriteAppHeader(const String8& packageName) +BackupDataWriter::WriteAppHeader(const String8& packageName, int cookie) { if (m_status != NO_ERROR) { return m_status; @@ -120,8 +104,9 @@ BackupDataWriter::WriteAppHeader(const String8& packageName) nameLen = packageName.length(); - header.type = tolel(APP_MAGIC_V1); + header.type = tolel(BACKUP_HEADER_APP_V1); header.packageLen = tolel(nameLen); + header.cookie = cookie; amt = write(m_fd, &header, sizeof(app_header_v1)); if (amt != sizeof(app_header_v1)) { @@ -159,7 +144,7 @@ BackupDataWriter::WriteEntityHeader(const String8& key, size_t dataSize) keyLen = key.length(); - header.type = tolel(ENTITY_MAGIC_V1); + header.type = tolel(BACKUP_HEADER_ENTITY_V1); header.keyLen = tolel(keyLen); header.dataSize = tolel(dataSize); @@ -204,7 +189,7 @@ BackupDataWriter::WriteEntityData(const void* data, size_t size) } status_t -BackupDataWriter::WriteAppFooter() +BackupDataWriter::WriteAppFooter(int cookie) { if (m_status != NO_ERROR) { return m_status; @@ -220,8 +205,9 @@ BackupDataWriter::WriteAppFooter() app_footer_v1 footer; ssize_t nameLen; - footer.type = tolel(FOOTER_MAGIC_V1); + footer.type = tolel(BACKUP_FOOTER_APP_V1); footer.entityCount = tolel(m_entityCount); + footer.cookie = cookie; amt = write(m_fd, &footer, sizeof(app_footer_v1)); if (amt != sizeof(app_footer_v1)) { @@ -233,4 +219,221 @@ BackupDataWriter::WriteAppFooter() return NO_ERROR; } + +BackupDataReader::BackupDataReader(int fd) + :m_fd(fd), + m_status(NO_ERROR), + m_pos(0), + m_entityCount(0) +{ + memset(&m_header, 0, sizeof(m_header)); +} + +BackupDataReader::~BackupDataReader() +{ +} + +status_t +BackupDataReader::Status() +{ + return m_status; +} + +#define CHECK_SIZE(actual, expected) \ + do { \ + if ((actual) != (expected)) { \ + if ((actual) == 0) { \ + m_status = EIO; \ + } else { \ + m_status = errno; \ + } \ + return m_status; \ + } \ + } while(0) +#define SKIP_PADDING() \ + do { \ + status_t err = skip_padding(); \ + if (err != NO_ERROR) { \ + m_status = err; \ + return err; \ + } \ + } while(0) + +status_t +BackupDataReader::ReadNextHeader(int* type) +{ + if (m_status != NO_ERROR) { + return m_status; + } + + int amt; + + SKIP_PADDING(); + amt = read(m_fd, &m_header, sizeof(m_header)); + CHECK_SIZE(amt, sizeof(m_header)); + + // validate and fix up the fields. + m_header.type = fromlel(m_header.type); + switch (m_header.type) + { + case BACKUP_HEADER_APP_V1: + m_header.app.packageLen = fromlel(m_header.app.packageLen); + if (m_header.app.packageLen < 0) { + LOGD("App header at %d has packageLen<0: 0x%08x\n", (int)m_pos, + (int)m_header.app.packageLen); + m_status = EINVAL; + } + m_header.app.cookie = m_header.app.cookie; + break; + case BACKUP_HEADER_ENTITY_V1: + m_header.entity.keyLen = fromlel(m_header.entity.keyLen); + if (m_header.entity.keyLen <= 0) { + LOGD("Entity header at %d has keyLen<=0: 0x%08x\n", (int)m_pos, + (int)m_header.entity.keyLen); + m_status = EINVAL; + } + m_header.entity.dataSize = fromlel(m_header.entity.dataSize); + m_entityCount++; + break; + case BACKUP_FOOTER_APP_V1: + m_header.footer.entityCount = fromlel(m_header.footer.entityCount); + if (m_header.footer.entityCount < 0) { + LOGD("Entity header at %d has entityCount<0: 0x%08x\n", (int)m_pos, + (int)m_header.footer.entityCount); + m_status = EINVAL; + } + m_header.footer.cookie = m_header.footer.cookie; + break; + default: + LOGD("Chunk header at %d has invalid type: 0x%08x", (int)m_pos, (int)m_header.type); + m_status = EINVAL; + } + m_pos += sizeof(m_header); + if (type) { + *type = m_header.type; + } + + return m_status; +} + +status_t +BackupDataReader::ReadAppHeader(String8* packageName, int* cookie) +{ + if (m_status != NO_ERROR) { + return m_status; + } + if (m_header.type != BACKUP_HEADER_APP_V1) { + return EINVAL; + } + size_t size = m_header.app.packageLen; + char* buf = packageName->lockBuffer(size); + if (packageName == NULL) { + packageName->unlockBuffer(); + m_status = ENOMEM; + return m_status; + } + int amt = read(m_fd, buf, size+1); + CHECK_SIZE(amt, (int)size+1); + packageName->unlockBuffer(size); + m_pos += size+1; + *cookie = m_header.app.cookie; + return NO_ERROR; +} + +bool +BackupDataReader::HasEntities() +{ + return m_status == NO_ERROR && m_header.type == BACKUP_HEADER_ENTITY_V1; +} + +status_t +BackupDataReader::ReadEntityHeader(String8* key, size_t* dataSize) +{ + if (m_status != NO_ERROR) { + return m_status; + } + if (m_header.type != BACKUP_HEADER_ENTITY_V1) { + return EINVAL; + } + size_t size = m_header.entity.keyLen; + char* buf = key->lockBuffer(size); + if (key == NULL) { + key->unlockBuffer(); + m_status = ENOMEM; + return m_status; + } + int amt = read(m_fd, buf, size+1); + CHECK_SIZE(amt, (int)size+1); + key->unlockBuffer(size); + m_pos += size+1; + *dataSize = m_header.entity.dataSize; + SKIP_PADDING(); + return NO_ERROR; +} + +status_t +BackupDataReader::SkipEntityData() +{ + if (m_status != NO_ERROR) { + return m_status; + } + if (m_header.type != BACKUP_HEADER_ENTITY_V1) { + return EINVAL; + } + if (m_header.entity.dataSize > 0) { + int pos = lseek(m_fd, m_header.entity.dataSize, SEEK_CUR); + return pos == -1 ? (int)errno : (int)NO_ERROR; + } else { + return NO_ERROR; + } +} + +status_t +BackupDataReader::ReadEntityData(void* data, size_t size) +{ + if (m_status != NO_ERROR) { + return m_status; + } + int amt = read(m_fd, data, size); + CHECK_SIZE(amt, (int)size); + m_pos += size; + return NO_ERROR; +} + +status_t +BackupDataReader::ReadAppFooter(int* cookie) +{ + if (m_status != NO_ERROR) { + return m_status; + } + if (m_header.type != BACKUP_FOOTER_APP_V1) { + return EINVAL; + } + if (m_header.footer.entityCount != m_entityCount) { + LOGD("entity count mismatch actual=%d expected=%d", m_entityCount, + m_header.footer.entityCount); + m_status = EINVAL; + return m_status; + } + *cookie = m_header.footer.cookie; + return NO_ERROR; +} + +status_t +BackupDataReader::skip_padding() +{ + ssize_t amt; + ssize_t paddingSize; + + paddingSize = padding_extra(m_pos); + if (paddingSize > 0) { + uint32_t padding; + amt = read(m_fd, &padding, paddingSize); + CHECK_SIZE(amt, paddingSize); + m_pos += amt; + } + return NO_ERROR; +} + + } // namespace android diff --git a/libs/utils/backup_helper_file.cpp b/libs/utils/backup_helper_file.cpp index 1fa6a0f..8efb3eb 100644 --- a/libs/utils/backup_helper_file.cpp +++ b/libs/utils/backup_helper_file.cpp @@ -40,7 +40,7 @@ namespace android { #define MAGIC0 0x70616e53 // Snap #define MAGIC1 0x656c6946 // File -#if TEST_BACKUP_HELPERS +#if 0 // TEST_BACKUP_HELPERS #define LOGP(x...) printf(x) #else #define LOGP(x...) LOGD(x) @@ -181,45 +181,105 @@ write_snapshot_file(int fd, const KeyedVector<String8,FileState>& snapshot) } static int -write_delete_file(const String8& key) +write_delete_file(BackupDataWriter* dataStream, const String8& key) { LOGP("write_delete_file %s\n", key.string()); - return 0; + return dataStream->WriteEntityHeader(key, -1); } static int -write_update_file(const String8& realFilename, const String8& key) +write_update_file(BackupDataWriter* dataStream, int fd, const String8& key, + const String8& realFilename) { LOGP("write_update_file %s (%s)\n", realFilename.string(), key.string()); - return 0; -} -static int -compute_crc32(const String8& filename) -{ const int bufsize = 4*1024; + int err; int amt; + int fileSize; + int bytesLeft; + + char* buf = (char*)malloc(bufsize); + int crc = crc32(0L, Z_NULL, 0); - int fd = open(filename.string(), O_RDONLY); + + bytesLeft = fileSize = lseek(fd, 0, SEEK_END); + lseek(fd, 0, SEEK_SET); + + err = dataStream->WriteEntityHeader(key, bytesLeft); + if (err != 0) { + return err; + } + + while ((amt = read(fd, buf, bufsize)) != 0 && bytesLeft > 0) { + bytesLeft -= amt; + if (bytesLeft < 0) { + amt += bytesLeft; // Plus a negative is minus. Don't write more than we promised. + } + err = dataStream->WriteEntityData(buf, amt); + if (err != 0) { + return err; + } + } + if (bytesLeft != 0) { + if (bytesLeft > 0) { + // Pad out the space we promised in the buffer. We can't corrupt the buffer, + // even though the data we're sending is probably bad. + memset(buf, 0, bufsize); + while (bytesLeft > 0) { + amt = bytesLeft < bufsize ? bytesLeft : bufsize; + bytesLeft -= amt; + err = dataStream->WriteEntityData(buf, amt); + if (err != 0) { + return err; + } + } + } + LOGE("write_update_file size mismatch for %s. expected=%d actual=%d." + " You aren't doing proper locking!", + realFilename.string(), fileSize, fileSize-bytesLeft); + } + + free(buf); + + return NO_ERROR; +} + +static int +write_update_file(BackupDataWriter* dataStream, const String8& key, const String8& realFilename) +{ + int err; + int fd = open(realFilename.string(), O_RDONLY); if (fd == -1) { - return -1; + return errno; } + err = write_update_file(dataStream, fd, key, realFilename); + close(fd); + return err; +} + +static int +compute_crc32(int fd) +{ + const int bufsize = 4*1024; + int amt; char* buf = (char*)malloc(bufsize); int crc = crc32(0L, Z_NULL, 0); + lseek(fd, 0, SEEK_SET); + while ((amt = read(fd, buf, bufsize)) != 0) { crc = crc32(crc, (Bytef*)buf, amt); } - close(fd); free(buf); return crc; } int -back_up_files(int oldSnapshotFD, int oldDataStream, int newSnapshotFD, +back_up_files(int oldSnapshotFD, BackupDataWriter* dataStream, int newSnapshotFD, char const* fileBase, char const* const* files, int fileCount) { int err; @@ -252,7 +312,8 @@ back_up_files(int oldSnapshotFD, int oldDataStream, int newSnapshotFD, s.modTime_nsec = 0; // workaround sim breakage //s.modTime_nsec = st.st_mtime_nsec; s.size = st.st_size; - s.crc32 = compute_crc32(realFilename); + + // we compute the crc32 later down below, when we already have the file open. newSnapshot.add(name, s); } @@ -270,30 +331,42 @@ back_up_files(int oldSnapshotFD, int oldDataStream, int newSnapshotFD, String8 realFilename(base); realFilename.appendPath(q); LOGP("file added: %s\n", realFilename.string()); - write_update_file(realFilename, q); + write_update_file(dataStream, q, realFilename); m++; } else if (cmp < 0) { // file removed LOGP("file removed: %s\n", p.string()); - write_delete_file(p); + dataStream->WriteEntityHeader(p, -1); n++; } else { + // both files exist, check them String8 realFilename(base); realFilename.appendPath(q); const FileState& f = oldSnapshot.valueAt(n); - const FileState& g = newSnapshot.valueAt(m); - - LOGP("%s\n", q.string()); - LOGP(" new: modTime=%d,%d size=%-3d crc32=0x%08x\n", - f.modTime_sec, f.modTime_nsec, f.size, f.crc32); - LOGP(" old: modTime=%d,%d size=%-3d crc32=0x%08x\n", - g.modTime_sec, g.modTime_nsec, g.size, g.crc32); - if (f.modTime_sec != g.modTime_sec || f.modTime_nsec != g.modTime_nsec - || f.size != g.size || f.crc32 != g.crc32) { - write_update_file(realFilename, p); + FileState& g = newSnapshot.editValueAt(m); + + int fd = open(realFilename.string(), O_RDONLY); + if (fd != -1) { + // We can't open the file. Don't report it as a delete either. Let the + // server keep the old version. Maybe they'll be able to deal with it + // on restore. + } else { + g.crc32 = compute_crc32(fd); + + LOGP("%s\n", q.string()); + LOGP(" new: modTime=%d,%d size=%-3d crc32=0x%08x\n", + f.modTime_sec, f.modTime_nsec, f.size, f.crc32); + LOGP(" old: modTime=%d,%d size=%-3d crc32=0x%08x\n", + g.modTime_sec, g.modTime_nsec, g.size, g.crc32); + if (f.modTime_sec != g.modTime_sec || f.modTime_nsec != g.modTime_nsec + || f.size != g.size || f.crc32 != g.crc32) { + write_update_file(dataStream, fd, p, realFilename); + } + + close(fd); } n++; m++; @@ -302,7 +375,7 @@ back_up_files(int oldSnapshotFD, int oldDataStream, int newSnapshotFD, // these were deleted while (n<N) { - write_delete_file(oldSnapshot.keyAt(n)); + dataStream->WriteEntityHeader(oldSnapshot.keyAt(n), -1); n++; } @@ -311,7 +384,7 @@ back_up_files(int oldSnapshotFD, int oldDataStream, int newSnapshotFD, const String8& q = newSnapshot.keyAt(m); String8 realFilename(base); realFilename.appendPath(q); - write_update_file(realFilename, q); + write_update_file(dataStream, q, realFilename); m++; } @@ -599,13 +672,14 @@ backup_helper_test_four() // hexdump -v -e '" " 8/1 " 0x%02x," "\n"' data_writer.data const unsigned char DATA_GOLDEN_FILE[] = { 0x41, 0x70, 0x70, 0x31, 0x0b, 0x00, 0x00, 0x00, - 0x6e, 0x6f, 0x5f, 0x70, 0x61, 0x64, 0x64, 0x69, - 0x6e, 0x67, 0x5f, 0x00, 0x44, 0x61, 0x74, 0x61, - 0x0b, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, - 0x6e, 0x6f, 0x5f, 0x70, 0x61, 0x64, 0x64, 0x69, - 0x6e, 0x67, 0x5f, 0x00, 0x6e, 0x6f, 0x5f, 0x70, + 0xdd, 0xcc, 0xbb, 0xaa, 0x6e, 0x6f, 0x5f, 0x70, + 0x61, 0x64, 0x64, 0x69, 0x6e, 0x67, 0x5f, 0x00, + 0x44, 0x61, 0x74, 0x61, 0x0b, 0x00, 0x00, 0x00, + 0x0c, 0x00, 0x00, 0x00, 0x6e, 0x6f, 0x5f, 0x70, 0x61, 0x64, 0x64, 0x69, 0x6e, 0x67, 0x5f, 0x00, - 0x41, 0x70, 0x70, 0x31, 0x0c, 0x00, 0x00, 0x00, + 0x6e, 0x6f, 0x5f, 0x70, 0x61, 0x64, 0x64, 0x69, + 0x6e, 0x67, 0x5f, 0x00, 0x41, 0x70, 0x70, 0x31, + 0x0c, 0x00, 0x00, 0x00, 0xdd, 0xcc, 0xbb, 0xaa, 0x70, 0x61, 0x64, 0x64, 0x65, 0x64, 0x5f, 0x74, 0x6f, 0x5f, 0x5f, 0x33, 0x00, 0xbc, 0xbc, 0xbc, 0x44, 0x61, 0x74, 0x61, 0x0c, 0x00, 0x00, 0x00, @@ -614,15 +688,16 @@ const unsigned char DATA_GOLDEN_FILE[] = { 0x00, 0xbc, 0xbc, 0xbc, 0x70, 0x61, 0x64, 0x64, 0x65, 0x64, 0x5f, 0x74, 0x6f, 0x5f, 0x5f, 0x33, 0x00, 0xbc, 0xbc, 0xbc, 0x41, 0x70, 0x70, 0x31, - 0x0d, 0x00, 0x00, 0x00, 0x70, 0x61, 0x64, 0x64, - 0x65, 0x64, 0x5f, 0x74, 0x6f, 0x5f, 0x32, 0x5f, - 0x5f, 0x00, 0xbc, 0xbc, 0x44, 0x61, 0x74, 0x61, - 0x0d, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, - 0x70, 0x61, 0x64, 0x64, 0x65, 0x64, 0x5f, 0x74, - 0x6f, 0x5f, 0x32, 0x5f, 0x5f, 0x00, 0xbc, 0xbc, + 0x0d, 0x00, 0x00, 0x00, 0xdd, 0xcc, 0xbb, 0xaa, 0x70, 0x61, 0x64, 0x64, 0x65, 0x64, 0x5f, 0x74, 0x6f, 0x5f, 0x32, 0x5f, 0x5f, 0x00, 0xbc, 0xbc, - 0x41, 0x70, 0x70, 0x31, 0x0a, 0x00, 0x00, 0x00, + 0x44, 0x61, 0x74, 0x61, 0x0d, 0x00, 0x00, 0x00, + 0x0e, 0x00, 0x00, 0x00, 0x70, 0x61, 0x64, 0x64, + 0x65, 0x64, 0x5f, 0x74, 0x6f, 0x5f, 0x32, 0x5f, + 0x5f, 0x00, 0xbc, 0xbc, 0x70, 0x61, 0x64, 0x64, + 0x65, 0x64, 0x5f, 0x74, 0x6f, 0x5f, 0x32, 0x5f, + 0x5f, 0x00, 0xbc, 0xbc, 0x41, 0x70, 0x70, 0x31, + 0x0a, 0x00, 0x00, 0x00, 0xdd, 0xcc, 0xbb, 0xaa, 0x70, 0x61, 0x64, 0x64, 0x65, 0x64, 0x5f, 0x74, 0x6f, 0x31, 0x00, 0xbc, 0x44, 0x61, 0x74, 0x61, 0x0a, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x00, 0x00, @@ -630,6 +705,7 @@ const unsigned char DATA_GOLDEN_FILE[] = { 0x6f, 0x31, 0x00, 0xbc, 0x70, 0x61, 0x64, 0x64, 0x65, 0x64, 0x5f, 0x74, 0x6f, 0x31, 0x00, 0xbc, 0x46, 0x6f, 0x6f, 0x74, 0x04, 0x00, 0x00, 0x00, + 0x99, 0x99, 0x77, 0x77 }; const int DATA_GOLDEN_FILE_SIZE = sizeof(DATA_GOLDEN_FILE); @@ -639,7 +715,7 @@ test_write_header_and_entity(BackupDataWriter& writer, const char* str) int err; String8 text(str); - err = writer.WriteAppHeader(text); + err = writer.WriteAppHeader(text, 0xaabbccdd); if (err != 0) { fprintf(stderr, "WriteAppHeader failed with %s\n", strerror(err)); return err; @@ -685,7 +761,7 @@ backup_helper_test_data_writer() err |= test_write_header_and_entity(writer, "padded_to_2__"); err |= test_write_header_and_entity(writer, "padded_to1"); - writer.WriteAppFooter(); + writer.WriteAppFooter(0x77779999); close(fd); @@ -697,6 +773,162 @@ backup_helper_test_data_writer() return err; } +int +test_read_header_and_entity(BackupDataReader& reader, const char* str) +{ + int err; + int bufSize = strlen(str)+1; + char* buf = (char*)malloc(bufSize); + String8 string; + int cookie = 0x11111111; + size_t actualSize; + + // printf("\n\n---------- test_read_header_and_entity -- %s\n\n", str); + + err = reader.ReadNextHeader(); + if (err != 0) { + fprintf(stderr, "ReadNextHeader (for app header) failed with %s\n", strerror(err)); + goto done; + } + + err = reader.ReadAppHeader(&string, &cookie); + if (err != 0) { + fprintf(stderr, "ReadAppHeader failed with %s\n", strerror(err)); + goto done; + } + if (string != str) { + fprintf(stderr, "ReadAppHeader expected packageName '%s' got '%s'\n", str, string.string()); + err = EINVAL; + goto done; + } + if (cookie != (int)0xaabbccdd) { + fprintf(stderr, "ReadAppHeader expected cookie 0x%08x got 0x%08x\n", 0xaabbccdd, cookie); + err = EINVAL; + goto done; + } + + err = reader.ReadNextHeader(); + if (err != 0) { + fprintf(stderr, "ReadNextHeader (for entity header) failed with %s\n", strerror(err)); + goto done; + } + + err = reader.ReadEntityHeader(&string, &actualSize); + if (err != 0) { + fprintf(stderr, "ReadEntityHeader failed with %s\n", strerror(err)); + goto done; + } + if (string != str) { + fprintf(stderr, "ReadEntityHeader expected key '%s' got '%s'\n", str, string.string()); + err = EINVAL; + goto done; + } + if ((int)actualSize != bufSize) { + fprintf(stderr, "ReadEntityHeader expected dataSize 0x%08x got 0x%08x\n", bufSize, + actualSize); + err = EINVAL; + goto done; + } + + err = reader.ReadEntityData(buf, bufSize); + if (err != NO_ERROR) { + fprintf(stderr, "ReadEntityData failed with %s\n", strerror(err)); + goto done; + } + + if (0 != memcmp(buf, str, bufSize)) { + fprintf(stderr, "ReadEntityData expected '%s' but got something starting with " + "%02x %02x %02x %02x\n", str, buf[0], buf[1], buf[2], buf[3]); + err = EINVAL; + goto done; + } + + // The next read will confirm whether it got the right amount of data. + +done: + if (err != NO_ERROR) { + fprintf(stderr, "test_read_header_and_entity failed with %s\n", strerror(err)); + } + free(buf); + return err; +} + +int +backup_helper_test_data_reader() +{ + int err; + int fd; + const char* filename = SCRATCH_DIR "data_reader.data"; + + system("rm -r " SCRATCH_DIR); + mkdir(SCRATCH_DIR, 0777); + mkdir(SCRATCH_DIR "data", 0777); + + fd = creat(filename, 0666); + if (fd == -1) { + fprintf(stderr, "error creating: %s\n", strerror(errno)); + return errno; + } + + err = write(fd, DATA_GOLDEN_FILE, DATA_GOLDEN_FILE_SIZE); + if (err != DATA_GOLDEN_FILE_SIZE) { + fprintf(stderr, "Error \"%s\" writing golden file %s\n", strerror(errno), filename); + return errno; + } + + close(fd); + + fd = open(filename, O_RDONLY); + if (fd == -1) { + fprintf(stderr, "Error \"%s\" opening golden file %s for read\n", strerror(errno), + filename); + return errno; + } + + { + BackupDataReader reader(fd); + + err = 0; + + if (err == NO_ERROR) { + err = test_read_header_and_entity(reader, "no_padding_"); + } + + if (err == NO_ERROR) { + err = test_read_header_and_entity(reader, "padded_to__3"); + } + + if (err == NO_ERROR) { + err = test_read_header_and_entity(reader, "padded_to_2__"); + } + + if (err == NO_ERROR) { + err = test_read_header_and_entity(reader, "padded_to1"); + } + + if (err == NO_ERROR) { + err = reader.ReadNextHeader(); + if (err != 0) { + fprintf(stderr, "ReadNextHeader (for app header) failed with %s\n", strerror(err)); + } + + if (err == NO_ERROR) { + int cookie; + err |= reader.ReadAppFooter(&cookie); + if (cookie != 0x77779999) { + fprintf(stderr, "app footer cookie expected=0x%08x actual=0x%08x\n", + 0x77779999, cookie); + err = EINVAL; + } + } + } + } + + close(fd); + + return err; +} + static int get_mod_time(const char* filename, struct timeval times[2]) { @@ -752,10 +984,14 @@ backup_helper_test_files() fprintf(stderr, "error creating: %s\n", strerror(errno)); return errno; } + + { + BackupDataWriter dataStream(dataStreamFD); - err = back_up_files(-1, dataStreamFD, newSnapshotFD, SCRATCH_DIR, files_before, 5); - if (err != 0) { - return err; + err = back_up_files(-1, &dataStream, newSnapshotFD, SCRATCH_DIR, files_before, 5); + if (err != 0) { + return err; + } } close(dataStreamFD); @@ -809,10 +1045,15 @@ backup_helper_test_files() return errno; } - err = back_up_files(oldSnapshotFD, dataStreamFD, newSnapshotFD, SCRATCH_DIR, files_after, 6); - if (err != 0) { - return err; - } + { + BackupDataWriter dataStream(dataStreamFD); + + err = back_up_files(oldSnapshotFD, &dataStream, newSnapshotFD, SCRATCH_DIR, + files_after, 6); + if (err != 0) { + return err; + } +} close(oldSnapshotFD); close(dataStreamFD); |