auto import from //depot/cupcake/@135843
diff --git a/libs/utils/BpBinder.cpp b/libs/utils/BpBinder.cpp
new file mode 100644
index 0000000..69ab195
--- /dev/null
+++ b/libs/utils/BpBinder.cpp
@@ -0,0 +1,348 @@
+/*
+ * 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