auto import from //depot/cupcake/@135843
diff --git a/libs/surfaceflinger/GPUHardware/GPUHardware.cpp b/libs/surfaceflinger/GPUHardware/GPUHardware.cpp
new file mode 100644
index 0000000..eb75f99
--- /dev/null
+++ b/libs/surfaceflinger/GPUHardware/GPUHardware.cpp
@@ -0,0 +1,581 @@
+/*
+ * 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 "SurfaceFlinger"
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <math.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/ioctl.h>
+
+#include <cutils/log.h>
+#include <cutils/properties.h>
+
+#include <utils/IBinder.h>
+#include <utils/MemoryDealer.h>
+#include <utils/MemoryBase.h>
+#include <utils/MemoryHeapPmem.h>
+#include <utils/MemoryHeapBase.h>
+#include <utils/IPCThreadState.h>
+#include <utils/StopWatch.h>
+
+#include <ui/ISurfaceComposer.h>
+
+#include "VRamHeap.h"
+#include "GPUHardware.h"
+
+#if HAVE_ANDROID_OS
+#include <linux/android_pmem.h>
+#endif
+
+#include "GPUHardware/GPUHardware.h"
+
+
+/* 
+ * Manage the GPU. This implementation is very specific to the G1.
+ * There are no abstraction here. 
+ * 
+ * All this code will soon go-away and be replaced by a new architecture
+ * for managing graphics accelerators.
+ * 
+ * In the meantime, it is conceptually possible to instantiate a
+ * GPUHardwareInterface for another GPU (see GPUFactory at the bottom
+ * of this file); practically... doubtful.
+ * 
+ */
+
+namespace android {
+
+// ---------------------------------------------------------------------------
+
+class GPUClientHeap;
+class GPUAreaHeap;
+
+class GPUHardware : public GPUHardwareInterface, public IBinder::DeathRecipient
+{
+public:
+    static const int GPU_RESERVED_SIZE;
+    static const int GPUR_SIZE;
+
+            GPUHardware();
+    virtual ~GPUHardware();
+    
+    virtual void revoke(int pid);
+    virtual sp<MemoryDealer> request(int pid);
+    virtual status_t request(int pid, 
+            const sp<IGPUCallback>& callback,
+            ISurfaceComposer::gpu_info_t* gpu);
+
+    virtual status_t friendlyRevoke();
+    virtual void unconditionalRevoke();
+    
+    virtual pid_t getOwner() const { return mOwner; }
+
+    // used for debugging only...
+    virtual sp<SimpleBestFitAllocator> getAllocator() const;
+
+private:
+    
+    
+    enum {
+        NO_OWNER = -1,
+    };
+        
+    struct GPUArea {
+        sp<GPUAreaHeap>     heap;
+        sp<MemoryHeapPmem>  clientHeap;
+        sp<IMemory> map();
+    };
+    
+    struct Client {
+        pid_t       pid;
+        GPUArea     smi;
+        GPUArea     ebi;
+        GPUArea     reg;
+        void createClientHeaps();
+        void revokeAllHeaps();
+    };
+    
+    Client& getClientLocked(pid_t pid);
+    status_t requestLocked(int pid);
+    void releaseLocked();
+    void takeBackGPULocked();
+    void registerCallbackLocked(const sp<IGPUCallback>& callback,
+            Client& client);
+
+    virtual void binderDied(const wp<IBinder>& who);
+
+    mutable Mutex           mLock;
+    sp<GPUAreaHeap>         mSMIHeap;
+    sp<GPUAreaHeap>         mEBIHeap;
+    sp<GPUAreaHeap>         mREGHeap;
+
+    KeyedVector<pid_t, Client> mClients;
+    DefaultKeyedVector< wp<IBinder>, pid_t > mRegisteredClients;
+    
+    pid_t                   mOwner;
+
+    sp<MemoryDealer>        mCurrentAllocator;
+    sp<IGPUCallback>        mCallback;
+    
+    sp<SimpleBestFitAllocator>  mAllocator;
+
+    Condition               mCondition;
+};
+
+// size reserved for GPU surfaces
+// 1200 KB fits exactly:
+//  - two 320*480 16-bits double-buffered surfaces
+//  - one 320*480 32-bits double-buffered surface
+//  - one 320*240 16-bits double-buffered, 4x anti-aliased surface
+const int GPUHardware::GPU_RESERVED_SIZE  = 1200 * 1024;
+const int GPUHardware::GPUR_SIZE          = 1 * 1024 * 1024;
+
+// ---------------------------------------------------------------------------
+
+/* 
+ * GPUHandle is a special IMemory given to the client. It represents their
+ * handle to the GPU. Once they give it up, they loose GPU access, or if
+ * they explicitly revoke their access through the binder code 1000.
+ * In both cases, this triggers a callback to revoke()
+ * first, and then actually powers down the chip.
+ * 
+ * In the case of a misbehaving app, GPUHardware can ask for an immediate
+ * release of the GPU to the target process which should answer by calling
+ * code 1000 on GPUHandle. If it doesn't in a timely manner, the GPU will
+ * be revoked from under their feet.
+ * 
+ * We should never hold a strong reference on GPUHandle. In practice this
+ * shouldn't be a big issue though because clients should use code 1000 and
+ * not rely on the dtor being called.
+ * 
+ */
+
+class GPUClientHeap : public MemoryHeapPmem
+{
+public:
+    GPUClientHeap(const wp<GPUHardware>& gpu, 
+            const sp<MemoryHeapBase>& heap)
+        :  MemoryHeapPmem(heap), mGPU(gpu) { }
+protected:
+    wp<GPUHardware> mGPU;
+};
+
+class GPUAreaHeap : public MemoryHeapBase
+{
+public:
+    GPUAreaHeap(const wp<GPUHardware>& gpu,
+            const char* const vram, size_t size=0, size_t reserved=0)
+    : MemoryHeapBase(vram, size), mGPU(gpu) { 
+        if (base() != MAP_FAILED) {
+            if (reserved == 0)
+                reserved = virtualSize();
+            mAllocator = new SimpleBestFitAllocator(reserved);
+        }
+    }
+    virtual sp<MemoryHeapPmem> createClientHeap() {
+        sp<MemoryHeapBase> parentHeap(this);
+        return new GPUClientHeap(mGPU, parentHeap);
+    }
+    virtual const sp<SimpleBestFitAllocator>& getAllocator() const {
+        return mAllocator; 
+    }
+private:
+    sp<SimpleBestFitAllocator>  mAllocator;
+protected:
+    wp<GPUHardware> mGPU;
+};
+
+class GPURegisterHeap : public GPUAreaHeap
+{
+public:
+    GPURegisterHeap(const sp<GPUHardware>& gpu)
+        : GPUAreaHeap(gpu, "/dev/hw3d", GPUHardware::GPUR_SIZE) { }
+    virtual sp<MemoryHeapPmem> createClientHeap() {
+        sp<MemoryHeapBase> parentHeap(this);
+        return new MemoryHeapRegs(mGPU, parentHeap);
+    }
+private:
+    class MemoryHeapRegs : public GPUClientHeap  {
+    public:
+        MemoryHeapRegs(const wp<GPUHardware>& gpu, 
+             const sp<MemoryHeapBase>& heap)
+            : GPUClientHeap(gpu, heap) { }
+        sp<MemoryHeapPmem::MemoryPmem> createMemory(size_t offset, size_t size);
+        virtual void revoke();
+    private:
+        class GPUHandle : public MemoryHeapPmem::MemoryPmem {
+        public:
+            GPUHandle(const sp<GPUHardware>& gpu,
+                    const sp<MemoryHeapPmem>& heap)
+                : MemoryHeapPmem::MemoryPmem(heap), 
+                  mGPU(gpu), mOwner(gpu->getOwner()) { }
+            virtual ~GPUHandle();
+            virtual sp<IMemoryHeap> getMemory(
+                    ssize_t* offset, size_t* size) const;
+            virtual void revoke() { };
+            virtual status_t onTransact(
+                    uint32_t code, const Parcel& data, 
+                    Parcel* reply, uint32_t flags);
+        private:
+            void revokeNotification();
+            wp<GPUHardware> mGPU;
+            pid_t mOwner;
+        };
+    };
+};
+
+GPURegisterHeap::MemoryHeapRegs::GPUHandle::~GPUHandle() { 
+    //LOGD("GPUHandle %p released, revoking GPU", this);
+    revokeNotification(); 
+}
+void GPURegisterHeap::MemoryHeapRegs::GPUHandle::revokeNotification()  {
+    sp<GPUHardware> hw(mGPU.promote());
+    if (hw != 0) {
+        hw->revoke(mOwner);
+    }
+}
+sp<IMemoryHeap> GPURegisterHeap::MemoryHeapRegs::GPUHandle::getMemory(
+        ssize_t* offset, size_t* size) const
+{
+    sp<MemoryHeapPmem> heap = getHeap();
+    if (offset) *offset = 0;
+    if (size)   *size = heap !=0 ? heap->virtualSize() : 0;
+    return heap;
+}
+status_t GPURegisterHeap::MemoryHeapRegs::GPUHandle::onTransact(
+        uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
+{
+    status_t err = BnMemory::onTransact(code, data, reply, flags);
+    if (err == UNKNOWN_TRANSACTION && code == 1000) {
+        int callingPid = IPCThreadState::self()->getCallingPid();
+        //LOGD("pid %d voluntarily revoking gpu", callingPid);
+        if (callingPid == mOwner) {
+            revokeNotification();
+            // we've revoked the GPU, don't do it again later when we
+            // are destroyed.
+            mGPU.clear();
+        } else {
+            LOGW("%d revoking someone else's gpu? (owner=%d)",
+                    callingPid, mOwner);            
+        }
+        err = NO_ERROR;
+    }
+    return err;
+}
+
+// ---------------------------------------------------------------------------
+
+
+sp<MemoryHeapPmem::MemoryPmem> GPURegisterHeap::MemoryHeapRegs::createMemory(
+        size_t offset, size_t size)
+{
+    sp<GPUHandle> memory;
+    sp<GPUHardware> gpu = mGPU.promote();
+    if (heapID()>0 && gpu!=0) {
+#if HAVE_ANDROID_OS
+        /* this is where the GPU is powered on and the registers are mapped
+         * in the client */
+        //LOGD("ioctl(HW3D_GRANT_GPU)");
+        int err = ioctl(heapID(), HW3D_GRANT_GPU, base());
+        if (err) {
+            // it can happen if the master heap has been closed already
+            // in which case the GPU already is revoked (app crash for
+            // instance).
+            LOGW("HW3D_GRANT_GPU failed (%s), mFD=%d, base=%p",
+                    strerror(errno), heapID(), base());
+        }
+        memory = new GPUHandle(gpu, this);
+#endif
+    }
+    return memory;
+}
+
+void GPURegisterHeap::MemoryHeapRegs::revoke() 
+{
+    MemoryHeapPmem::revoke();
+#if HAVE_ANDROID_OS
+    if (heapID() > 0) {
+        //LOGD("ioctl(HW3D_REVOKE_GPU)");
+        int err = ioctl(heapID(), HW3D_REVOKE_GPU, base());
+        LOGE_IF(err, "HW3D_REVOKE_GPU failed (%s), mFD=%d, base=%p",
+                strerror(errno), heapID(), base());
+    }
+#endif
+}
+
+/*****************************************************************************/
+
+GPUHardware::GPUHardware()
+    : mOwner(NO_OWNER)
+{
+}
+
+GPUHardware::~GPUHardware()
+{
+}
+
+status_t GPUHardware::requestLocked(int pid)
+{
+    const int self_pid = getpid();
+    if (pid == self_pid) {
+        // can't use GPU from surfaceflinger's process
+        return PERMISSION_DENIED;
+    }
+
+    if (mOwner != pid) {
+        if (mREGHeap != 0) {
+            if (mOwner != NO_OWNER) {
+                // someone already has the gpu.
+                takeBackGPULocked();
+                releaseLocked();
+            }
+        } else {
+            // first time, initialize the stuff.
+            if (mSMIHeap == 0)
+                mSMIHeap = new GPUAreaHeap(this, "/dev/pmem_gpu0");
+            if (mEBIHeap == 0)
+                mEBIHeap = new GPUAreaHeap(this, 
+                        "/dev/pmem_gpu1", 0, GPU_RESERVED_SIZE);
+            mREGHeap = new GPURegisterHeap(this);
+            mAllocator = mEBIHeap->getAllocator();
+            if (mAllocator == NULL) {
+                // something went terribly wrong.
+                mSMIHeap.clear();
+                mEBIHeap.clear();
+                mREGHeap.clear();
+                return INVALID_OPERATION;
+            }
+        }
+        Client& client = getClientLocked(pid);
+        mCurrentAllocator = new MemoryDealer(client.ebi.clientHeap, mAllocator);
+        mOwner = pid;
+    }
+    return NO_ERROR;
+}
+
+sp<MemoryDealer> GPUHardware::request(int pid)
+{
+    sp<MemoryDealer> dealer;
+    Mutex::Autolock _l(mLock);
+    Client* client;
+    LOGD("pid %d requesting gpu surface (current owner = %d)", pid, mOwner);
+    if (requestLocked(pid) == NO_ERROR) {
+        dealer = mCurrentAllocator;
+        LOGD_IF(dealer!=0, "gpu surface granted to pid %d", mOwner);
+    }
+    return dealer;
+}
+
+status_t GPUHardware::request(int pid, const sp<IGPUCallback>& callback,
+        ISurfaceComposer::gpu_info_t* gpu)
+{
+    if (callback == 0)
+        return BAD_VALUE;
+
+    sp<IMemory> gpuHandle;
+    LOGD("pid %d requesting gpu core (owner = %d)", pid, mOwner);
+    Mutex::Autolock _l(mLock);
+    status_t err = requestLocked(pid);
+    if (err == NO_ERROR) {
+        // it's guaranteed to be there, be construction
+        Client& client = mClients.editValueFor(pid);
+        registerCallbackLocked(callback, client);
+        gpu->count = 2;
+        gpu->regions[0].region = client.smi.map();
+        gpu->regions[1].region = client.ebi.map();
+        gpu->regs              = client.reg.map();
+        gpu->regions[0].reserved = 0;
+        gpu->regions[1].reserved = GPU_RESERVED_SIZE;
+        if (gpu->regs != 0) {
+            //LOGD("gpu core granted to pid %d, handle base=%p",
+            //        mOwner, gpu->regs->pointer());
+        }
+        mCallback = callback;
+    } else {
+        LOGW("couldn't grant gpu core to pid %d", pid);
+    }
+    return err;
+}
+
+void GPUHardware::revoke(int pid)
+{
+    Mutex::Autolock _l(mLock);
+    if (mOwner > 0) {
+        if (pid != mOwner) {
+            LOGW("GPU owned by %d, revoke from %d", mOwner, pid);
+            return;
+        }
+        //LOGD("revoke pid=%d, owner=%d", pid, mOwner);
+        // mOwner could be <0 if the same process acquired the GPU
+        // several times without releasing it first.
+        mCondition.signal();
+        releaseLocked();
+    }
+}
+
+status_t GPUHardware::friendlyRevoke()
+{
+    Mutex::Autolock _l(mLock);
+    //LOGD("friendlyRevoke owner=%d", mOwner);
+    takeBackGPULocked();
+    releaseLocked();
+    return NO_ERROR;
+}
+
+void GPUHardware::takeBackGPULocked()
+{
+    sp<IGPUCallback> callback = mCallback;
+    mCallback.clear();
+    if (callback != 0) {
+        callback->gpuLost(); // one-way
+        mCondition.waitRelative(mLock, ms2ns(250));
+    }
+}
+
+void GPUHardware::releaseLocked()
+{
+    //LOGD("revoking gpu from pid %d", mOwner);
+    if (mOwner != NO_OWNER) {
+        // this may fail because the client might have died, and have
+        // been removed from the list.
+        ssize_t index = mClients.indexOfKey(mOwner);
+        if (index >= 0) {
+            Client& client(mClients.editValueAt(index));
+            client.revokeAllHeaps();
+        }
+        mOwner = NO_OWNER;
+        mCurrentAllocator.clear();
+        mCallback.clear();
+    }
+}
+
+GPUHardware::Client& GPUHardware::getClientLocked(pid_t pid)
+{
+    ssize_t index = mClients.indexOfKey(pid);
+    if (index < 0) {
+        Client client;
+        client.pid = pid;
+        client.smi.heap = mSMIHeap;
+        client.ebi.heap = mEBIHeap;
+        client.reg.heap = mREGHeap;
+        index = mClients.add(pid, client);
+    }
+    Client& client(mClients.editValueAt(index));
+    client.createClientHeaps();
+    return client;
+}
+
+// ----------------------------------------------------------------------------
+// for debugging / testing ...
+
+sp<SimpleBestFitAllocator> GPUHardware::getAllocator() const {
+    Mutex::Autolock _l(mLock);
+    return mAllocator;
+}
+
+void GPUHardware::unconditionalRevoke()
+{
+    Mutex::Autolock _l(mLock);
+    releaseLocked();
+}
+
+// ---------------------------------------------------------------------------
+
+sp<IMemory> GPUHardware::GPUArea::map() {
+    sp<IMemory> memory;
+    if (clientHeap != 0 && heap != 0) {
+        memory = clientHeap->mapMemory(0, heap->virtualSize());
+    }
+    return memory;
+}
+
+void GPUHardware::Client::createClientHeaps() 
+{
+    if (smi.clientHeap == 0)
+        smi.clientHeap = smi.heap->createClientHeap();
+    if (ebi.clientHeap == 0)
+        ebi.clientHeap = ebi.heap->createClientHeap();
+    if (reg.clientHeap == 0)
+        reg.clientHeap = reg.heap->createClientHeap();
+}
+
+void GPUHardware::Client::revokeAllHeaps() 
+{
+    if (smi.clientHeap != 0)
+        smi.clientHeap->revoke();
+    if (ebi.clientHeap != 0)
+        ebi.clientHeap->revoke();
+    if (reg.clientHeap != 0)
+        reg.clientHeap->revoke();
+}
+
+void GPUHardware::registerCallbackLocked(const sp<IGPUCallback>& callback,
+        Client& client)
+{
+    sp<IBinder> binder = callback->asBinder();
+    if (mRegisteredClients.add(binder, client.pid) >= 0) {
+        binder->linkToDeath(this);
+    }
+}
+
+void GPUHardware::binderDied(const wp<IBinder>& who)
+{
+    Mutex::Autolock _l(mLock);
+    pid_t pid = mRegisteredClients.valueFor(who);
+    if (pid != 0) {
+        ssize_t index = mClients.indexOfKey(pid);
+        if (index >= 0) {
+            //LOGD("*** removing client at %d", index);
+            Client& client(mClients.editValueAt(index));
+            client.revokeAllHeaps(); // not really needed in theory
+            mClients.removeItemsAt(index);
+            if (mClients.size() == 0) {
+                //LOGD("*** was last client closing everything");
+                mCallback.clear();
+                mAllocator.clear();
+                mCurrentAllocator.clear();
+                mSMIHeap.clear();
+                mREGHeap.clear();
+                
+                // NOTE: we cannot clear the EBI heap because surfaceflinger
+                // itself may be using it, since this is where surfaces
+                // are allocated. if we're in the middle of compositing 
+                // a surface (even if its process just died), we cannot
+                // rip the heap under our feet.
+                
+                mOwner = NO_OWNER;
+            }
+        }
+    }
+}
+
+// ---------------------------------------------------------------------------
+
+sp<GPUHardwareInterface> GPUFactory::getGPU()
+{
+    return new GPUHardware();
+}
+
+// ---------------------------------------------------------------------------
+}; // namespace android
+
diff --git a/libs/surfaceflinger/GPUHardware/GPUHardware.h b/libs/surfaceflinger/GPUHardware/GPUHardware.h
new file mode 100644
index 0000000..3354528
--- /dev/null
+++ b/libs/surfaceflinger/GPUHardware/GPUHardware.h
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_GPU_HARDWARE_H
+#define ANDROID_GPU_HARDWARE_H
+
+#include <stdint.h>
+#include <sys/types.h>
+
+#include <utils/RefBase.h>
+#include <utils/threads.h>
+#include <utils/KeyedVector.h>
+
+#include <ui/ISurfaceComposer.h>
+
+namespace android {
+
+// ---------------------------------------------------------------------------
+
+class IGPUCallback;
+
+class GPUHardwareInterface : public virtual RefBase
+{
+public:
+    virtual void                revoke(int pid) = 0;
+    virtual sp<MemoryDealer>    request(int pid) = 0;
+    virtual status_t            request(int pid, const sp<IGPUCallback>& callback,
+            ISurfaceComposer::gpu_info_t* gpu) = 0;
+
+    virtual status_t            friendlyRevoke() = 0;
+    
+    // used for debugging only...
+    virtual sp<SimpleBestFitAllocator> getAllocator() const  = 0;
+    virtual pid_t getOwner() const = 0;
+    virtual void unconditionalRevoke() = 0;
+};
+
+// ---------------------------------------------------------------------------
+
+class GPUFactory
+{    
+public:
+    // the gpu factory
+    static sp<GPUHardwareInterface> getGPU();
+};
+
+// ---------------------------------------------------------------------------
+}; // namespace android
+
+#endif // ANDROID_GPU_HARDWARE_H