/*
 * 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.
 */

#include <stdlib.h>
#include <stdio.h>
#include <stdint.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <math.h>
#include <limits.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/ioctl.h>

#include <cutils/log.h>
#include <cutils/properties.h>

#include <binder/IPCThreadState.h>
#include <binder/IServiceManager.h>
#include <binder/MemoryHeapBase.h>

#include <utils/String8.h>
#include <utils/String16.h>
#include <utils/StopWatch.h>

#include <ui/PixelFormat.h>
#include <ui/DisplayInfo.h>

#include <pixelflinger/pixelflinger.h>
#include <GLES/gl.h>

#include "clz.h"
#include "BufferAllocator.h"
#include "Layer.h"
#include "LayerBlur.h"
#include "LayerBuffer.h"
#include "LayerDim.h"
#include "LayerBitmap.h"
#include "SurfaceFlinger.h"

#include "DisplayHardware/DisplayHardware.h"

/* ideally AID_GRAPHICS would be in a semi-public header
 * or there would be a way to map a user/group name to its id
 */
#ifndef AID_GRAPHICS
#define AID_GRAPHICS 1003
#endif

#define DISPLAY_COUNT       1

namespace android {

// ---------------------------------------------------------------------------

void SurfaceFlinger::instantiate() {
    defaultServiceManager()->addService(
            String16("SurfaceFlinger"), new SurfaceFlinger());
}

void SurfaceFlinger::shutdown() {
    // we should unregister here, but not really because
    // when (if) the service manager goes away, all the services
    // it has a reference to will leave too.
}

// ---------------------------------------------------------------------------

SurfaceFlinger::LayerVector::LayerVector(const SurfaceFlinger::LayerVector& rhs)
    : lookup(rhs.lookup), layers(rhs.layers)
{
}

ssize_t SurfaceFlinger::LayerVector::indexOf(
        const sp<LayerBase>& key, size_t guess) const
{
    if (guess<size() && lookup.keyAt(guess) == key)
        return guess;
    const ssize_t i = lookup.indexOfKey(key);
    if (i>=0) {
        const size_t idx = lookup.valueAt(i);
        LOGE_IF(layers[idx]!=key,
            "LayerVector[%p]: layers[%d]=%p, key=%p",
            this, int(idx), layers[idx].get(), key.get());
        return idx;
    }
    return i;
}

ssize_t SurfaceFlinger::LayerVector::add(
        const sp<LayerBase>& layer,
        Vector< sp<LayerBase> >::compar_t cmp)
{
    size_t count = layers.size();
    ssize_t l = 0;
    ssize_t h = count-1;
    ssize_t mid;
    sp<LayerBase> const* a = layers.array();
    while (l <= h) {
        mid = l + (h - l)/2;
        const int c = cmp(a+mid, &layer);
        if (c == 0)     { l = mid; break; }
        else if (c<0)   { l = mid+1; }
        else            { h = mid-1; }
    }
    size_t order = l;
    while (order<count && !cmp(&layer, a+order)) {
        order++;
    }
    count = lookup.size();
    for (size_t i=0 ; i<count ; i++) {
        if (lookup.valueAt(i) >= order) {
            lookup.editValueAt(i)++;
        }
    }
    layers.insertAt(layer, order);
    lookup.add(layer, order);
    return order;
}

ssize_t SurfaceFlinger::LayerVector::remove(const sp<LayerBase>& layer)
{
    const ssize_t keyIndex = lookup.indexOfKey(layer);
    if (keyIndex >= 0) {
        const size_t index = lookup.valueAt(keyIndex);
        LOGE_IF(layers[index]!=layer,
                "LayerVector[%p]: layers[%u]=%p, layer=%p",
                this, int(index), layers[index].get(), layer.get());
        layers.removeItemsAt(index);
        lookup.removeItemsAt(keyIndex);
        const size_t count = lookup.size();
        for (size_t i=0 ; i<count ; i++) {
            if (lookup.valueAt(i) >= size_t(index)) {
                lookup.editValueAt(i)--;
            }
        }
        return index;
    }
    return NAME_NOT_FOUND;
}

ssize_t SurfaceFlinger::LayerVector::reorder(
        const sp<LayerBase>& layer,
        Vector< sp<LayerBase> >::compar_t cmp)
{
    // XXX: it's a little lame. but oh well...
    ssize_t err = remove(layer);
    if (err >=0)
        err = add(layer, cmp);
    return err;
}

// ---------------------------------------------------------------------------
#if 0
#pragma mark -
#endif

SurfaceFlinger::SurfaceFlinger()
    :   BnSurfaceComposer(), Thread(false),
        mTransactionFlags(0),
        mTransactionCount(0),
        mLayersRemoved(false),
        mBootTime(systemTime()),
        mHardwareTest("android.permission.HARDWARE_TEST"),
        mAccessSurfaceFlinger("android.permission.ACCESS_SURFACE_FLINGER"),
        mDump("android.permission.DUMP"),
        mLastScheduledBroadcast(NULL),
        mVisibleRegionsDirty(false),
        mDeferReleaseConsole(false),
        mFreezeDisplay(false),
        mFreezeCount(0),
        mFreezeDisplayTime(0),
        mDebugRegion(0),
        mDebugBackground(0),
        mConsoleSignals(0),
        mSecureFrameBuffer(0)
{
    init();
}

void SurfaceFlinger::init()
{
    LOGI("SurfaceFlinger is starting");

    // debugging stuff...
    char value[PROPERTY_VALUE_MAX];
    property_get("debug.sf.showupdates", value, "0");
    mDebugRegion = atoi(value);
    property_get("debug.sf.showbackground", value, "0");
    mDebugBackground = atoi(value);

    LOGI_IF(mDebugRegion,           "showupdates enabled");
    LOGI_IF(mDebugBackground,       "showbackground enabled");
}

SurfaceFlinger::~SurfaceFlinger()
{
    glDeleteTextures(1, &mWormholeTexName);
}

overlay_control_device_t* SurfaceFlinger::getOverlayEngine() const
{
    return graphicPlane(0).displayHardware().getOverlayEngine();
}

sp<IMemoryHeap> SurfaceFlinger::getCblk() const
{
    return mServerHeap;
}

sp<ISurfaceFlingerClient> SurfaceFlinger::createConnection()
{
    Mutex::Autolock _l(mStateLock);
    uint32_t token = mTokens.acquire();

    sp<Client> client = new Client(token, this);
    if (client->ctrlblk == 0) {
        mTokens.release(token);
        return 0;
    }
    status_t err = mClientsMap.add(token, client);
    if (err < 0) {
        mTokens.release(token);
        return 0;
    }
    sp<BClient> bclient =
        new BClient(this, token, client->getControlBlockMemory());
    return bclient;
}

void SurfaceFlinger::destroyConnection(ClientID cid)
{
    Mutex::Autolock _l(mStateLock);
    sp<Client> client = mClientsMap.valueFor(cid);
    if (client != 0) {
        // free all the layers this client owns
        Vector< wp<LayerBaseClient> > layers(client->getLayers());
        const size_t count = layers.size();
        for (size_t i=0 ; i<count ; i++) {
            sp<LayerBaseClient> layer(layers[i].promote());
            if (layer != 0) {
                purgatorizeLayer_l(layer);
            }
        }

        // the resources associated with this client will be freed
        // during the next transaction, after these surfaces have been
        // properly removed from the screen

        // remove this client from our ClientID->Client mapping.
        mClientsMap.removeItem(cid);

        // and add it to the list of disconnected clients
        mDisconnectedClients.add(client);

        // request a transaction
        setTransactionFlags(eTransactionNeeded);
    }
}

const GraphicPlane& SurfaceFlinger::graphicPlane(int dpy) const
{
    LOGE_IF(uint32_t(dpy) >= DISPLAY_COUNT, "Invalid DisplayID %d", dpy);
    const GraphicPlane& plane(mGraphicPlanes[dpy]);
    return plane;
}

GraphicPlane& SurfaceFlinger::graphicPlane(int dpy)
{
    return const_cast<GraphicPlane&>(
        const_cast<SurfaceFlinger const *>(this)->graphicPlane(dpy));
}

void SurfaceFlinger::bootFinished()
{
    const nsecs_t now = systemTime();
    const nsecs_t duration = now - mBootTime;
    LOGI("Boot is finished (%ld ms)", long(ns2ms(duration)) );  
    property_set("ctl.stop", "bootanim");
}

void SurfaceFlinger::onFirstRef()
{
    run("SurfaceFlinger", PRIORITY_URGENT_DISPLAY);

    // Wait for the main thread to be done with its initialization
    mReadyToRunBarrier.wait();
}

static inline uint16_t pack565(int r, int g, int b) {
    return (r<<11)|(g<<5)|b;
}

status_t SurfaceFlinger::readyToRun()
{
    LOGI(   "SurfaceFlinger's main thread ready to run. "
            "Initializing graphics H/W...");

    // we only support one display currently
    int dpy = 0;

    {
        // initialize the main display
        GraphicPlane& plane(graphicPlane(dpy));
        DisplayHardware* const hw = new DisplayHardware(this, dpy);
        plane.setDisplayHardware(hw);
    }

    // create the shared control-block
    mServerHeap = new MemoryHeapBase(4096,
            MemoryHeapBase::READ_ONLY, "SurfaceFlinger read-only heap");
    LOGE_IF(mServerHeap==0, "can't create shared memory dealer");
    
    mServerCblk = static_cast<surface_flinger_cblk_t*>(mServerHeap->getBase());
    LOGE_IF(mServerCblk==0, "can't get to shared control block's address");
    
    new(mServerCblk) surface_flinger_cblk_t;

    // initialize primary screen
    // (other display should be initialized in the same manner, but
    // asynchronously, as they could come and go. None of this is supported
    // yet).
    const GraphicPlane& plane(graphicPlane(dpy));
    const DisplayHardware& hw = plane.displayHardware();
    const uint32_t w = hw.getWidth();
    const uint32_t h = hw.getHeight();
    const uint32_t f = hw.getFormat();
    hw.makeCurrent();

    // initialize the shared control block
    mServerCblk->connected |= 1<<dpy;
    display_cblk_t* dcblk = mServerCblk->displays + dpy;
    memset(dcblk, 0, sizeof(display_cblk_t));
    dcblk->w            = w;
    dcblk->h            = h;
    dcblk->format       = f;
    dcblk->orientation  = ISurfaceComposer::eOrientationDefault;
    dcblk->xdpi         = hw.getDpiX();
    dcblk->ydpi         = hw.getDpiY();
    dcblk->fps          = hw.getRefreshRate();
    dcblk->density      = hw.getDensity();
    asm volatile ("":::"memory");

    // Initialize OpenGL|ES
    glActiveTexture(GL_TEXTURE0);
    glBindTexture(GL_TEXTURE_2D, 0);
    glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
    glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
    glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
    glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
    glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
    glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
    glPixelStorei(GL_PACK_ALIGNMENT, 4); 
    glEnableClientState(GL_VERTEX_ARRAY);
    glEnable(GL_SCISSOR_TEST);
    glShadeModel(GL_FLAT);
    glDisable(GL_DITHER);
    glDisable(GL_CULL_FACE);

    const uint16_t g0 = pack565(0x0F,0x1F,0x0F);
    const uint16_t g1 = pack565(0x17,0x2f,0x17);
    const uint16_t textureData[4] = { g0, g1, g1, g0 };
    glGenTextures(1, &mWormholeTexName);
    glBindTexture(GL_TEXTURE_2D, mWormholeTexName);
    glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
    glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
    glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
    glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 2, 2, 0,
            GL_RGB, GL_UNSIGNED_SHORT_5_6_5, textureData);

    glViewport(0, 0, w, h);
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    glOrthof(0, w, h, 0, 0, 1);

   LayerDim::initDimmer(this, w, h);

    mReadyToRunBarrier.open();

    /*
     *  We're now ready to accept clients...
     */

    // start boot animation
    property_set("ctl.start", "bootanim");
    
    return NO_ERROR;
}

// ----------------------------------------------------------------------------
#if 0
#pragma mark -
#pragma mark Events Handler
#endif

void SurfaceFlinger::waitForEvent()
{
    while (true) {
        nsecs_t timeout = -1;
        if (UNLIKELY(isFrozen())) {
            // wait 5 seconds
            const nsecs_t freezeDisplayTimeout = ms2ns(5000);
            const nsecs_t now = systemTime();
            if (mFreezeDisplayTime == 0) {
                mFreezeDisplayTime = now;
            }
            nsecs_t waitTime = freezeDisplayTimeout - (now - mFreezeDisplayTime);
            timeout = waitTime>0 ? waitTime : 0;
        }

        MessageList::value_type msg = mEventQueue.waitMessage(timeout);
        if (msg != 0) {
            mFreezeDisplayTime = 0;
            switch (msg->what) {
                case MessageQueue::INVALIDATE:
                    // invalidate message, just return to the main loop
                    return;
            }
        } else {
            // we timed out
            if (isFrozen()) {
                // we timed out and are still frozen
                LOGW("timeout expired mFreezeDisplay=%d, mFreezeCount=%d",
                        mFreezeDisplay, mFreezeCount);
                mFreezeCount = 0;
                mFreezeDisplay = false;
                return;
            }
        }
    }
}

void SurfaceFlinger::signalEvent() {
    mEventQueue.invalidate();
}

void SurfaceFlinger::signal() const {
    // this is the IPC call
    const_cast<SurfaceFlinger*>(this)->signalEvent();
}

void SurfaceFlinger::signalDelayedEvent(nsecs_t delay)
{
    mEventQueue.postMessage( new MessageBase(MessageQueue::INVALIDATE), delay);
}

// ----------------------------------------------------------------------------
#if 0
#pragma mark -
#pragma mark Main loop
#endif

bool SurfaceFlinger::threadLoop()
{
    waitForEvent();

    // check for transactions
    if (UNLIKELY(mConsoleSignals)) {
        handleConsoleEvents();
    }

    if (LIKELY(mTransactionCount == 0)) {
        // if we're in a global transaction, don't do anything.
        const uint32_t mask = eTransactionNeeded | eTraversalNeeded;
        uint32_t transactionFlags = getTransactionFlags(mask);
        if (LIKELY(transactionFlags)) {
            handleTransaction(transactionFlags);
        }
    }

    // post surfaces (if needed)
    handlePageFlip();

    const DisplayHardware& hw(graphicPlane(0).displayHardware());
    if (LIKELY(hw.canDraw())) {
        // repaint the framebuffer (if needed)
        handleRepaint();

        // release the clients before we flip ('cause flip might block)
        unlockClients();
        executeScheduledBroadcasts();

        postFramebuffer();
    } else {
        // pretend we did the post
        unlockClients();
        executeScheduledBroadcasts();
        usleep(16667); // 60 fps period
    }
    return true;
}

void SurfaceFlinger::postFramebuffer()
{
    if (isFrozen()) {
        // we are not allowed to draw, but pause a bit to make sure
        // apps don't end up using the whole CPU, if they depend on
        // surfaceflinger for synchronization.
        usleep(8333); // 8.3ms ~ 120fps
        return;
    }

    if (!mInvalidRegion.isEmpty()) {
        const DisplayHardware& hw(graphicPlane(0).displayHardware());
        hw.flip(mInvalidRegion);
        mInvalidRegion.clear();
    }
}

void SurfaceFlinger::handleConsoleEvents()
{
    // something to do with the console
    const DisplayHardware& hw = graphicPlane(0).displayHardware();

    int what = android_atomic_and(0, &mConsoleSignals);
    if (what & eConsoleAcquired) {
        hw.acquireScreen();
    }

    if (mDeferReleaseConsole && hw.canDraw()) {
        // We got the release signal before the acquire signal
        mDeferReleaseConsole = false;
        hw.releaseScreen();
    }

    if (what & eConsoleReleased) {
        if (hw.canDraw()) {
            hw.releaseScreen();
        } else {
            mDeferReleaseConsole = true;
        }
    }

    mDirtyRegion.set(hw.bounds());
}

void SurfaceFlinger::handleTransaction(uint32_t transactionFlags)
{
    Vector< sp<LayerBase> > ditchedLayers;

    { // scope for the lock
        Mutex::Autolock _l(mStateLock);
        handleTransactionLocked(transactionFlags, ditchedLayers);
    }

    // do this without lock held
    const size_t count = ditchedLayers.size();
    for (size_t i=0 ; i<count ; i++) {
        //LOGD("ditching layer %p", ditchedLayers[i].get());
        ditchedLayers[i]->ditch();
    }
}

void SurfaceFlinger::handleTransactionLocked(
        uint32_t transactionFlags, Vector< sp<LayerBase> >& ditchedLayers)
{
    const LayerVector& currentLayers(mCurrentState.layersSortedByZ);
    const size_t count = currentLayers.size();

    /*
     * Traversal of the children
     * (perform the transaction for each of them if needed)
     */

    const bool layersNeedTransaction = transactionFlags & eTraversalNeeded;
    if (layersNeedTransaction) {
        for (size_t i=0 ; i<count ; i++) {
            const sp<LayerBase>& layer = currentLayers[i];
            uint32_t trFlags = layer->getTransactionFlags(eTransactionNeeded);
            if (!trFlags) continue;

            const uint32_t flags = layer->doTransaction(0);
            if (flags & Layer::eVisibleRegion)
                mVisibleRegionsDirty = true;

            if (flags & Layer::eRestartTransaction) {
                // restart the transaction, but back-off a little
                layer->setTransactionFlags(eTransactionNeeded);
                setTransactionFlags(eTraversalNeeded, ms2ns(8));
            }
        }
    }

    /*
     * Perform our own transaction if needed
     */

    if (transactionFlags & eTransactionNeeded) {
        if (mCurrentState.orientation != mDrawingState.orientation) {
            // the orientation has changed, recompute all visible regions
            // and invalidate everything.

            const int dpy = 0;
            const int orientation = mCurrentState.orientation;
            const uint32_t type = mCurrentState.orientationType;
            GraphicPlane& plane(graphicPlane(dpy));
            plane.setOrientation(orientation);

            // update the shared control block
            const DisplayHardware& hw(plane.displayHardware());
            volatile display_cblk_t* dcblk = mServerCblk->displays + dpy;
            dcblk->orientation = orientation;
            if (orientation & eOrientationSwapMask) {
                // 90 or 270 degrees orientation
                dcblk->w = hw.getHeight();
                dcblk->h = hw.getWidth();
            } else {
                dcblk->w = hw.getWidth();
                dcblk->h = hw.getHeight();
            }

            mVisibleRegionsDirty = true;
            mDirtyRegion.set(hw.bounds());
            mFreezeDisplayTime = 0;
        }

        if (mCurrentState.freezeDisplay != mDrawingState.freezeDisplay) {
            // freezing or unfreezing the display -> trigger animation if needed
            mFreezeDisplay = mCurrentState.freezeDisplay;
        }

        if (currentLayers.size() > mDrawingState.layersSortedByZ.size()) {
            // layers have been added
            mVisibleRegionsDirty = true;
        }

        // some layers might have been removed, so
        // we need to update the regions they're exposing.
        if (mLayersRemoved) {
            mVisibleRegionsDirty = true;
            const LayerVector& previousLayers(mDrawingState.layersSortedByZ);
            const size_t count = previousLayers.size();
            for (size_t i=0 ; i<count ; i++) {
                const sp<LayerBase>& layer(previousLayers[i]);
                if (currentLayers.indexOf( layer ) < 0) {
                    // this layer is not visible anymore
                    ditchedLayers.add(layer);
                    mDirtyRegionRemovedLayer.orSelf(layer->visibleRegionScreen);
                }
            }
        }

        // get rid of all resources we don't need anymore
        // (layers and clients)
        free_resources_l();
    }

    commitTransaction();
}

sp<FreezeLock> SurfaceFlinger::getFreezeLock() const
{
    return new FreezeLock(const_cast<SurfaceFlinger *>(this));
}

void SurfaceFlinger::computeVisibleRegions(
    LayerVector& currentLayers, Region& dirtyRegion, Region& opaqueRegion)
{
    const GraphicPlane& plane(graphicPlane(0));
    const Transform& planeTransform(plane.transform());

    Region aboveOpaqueLayers;
    Region aboveCoveredLayers;
    Region dirty;

    bool secureFrameBuffer = false;

    size_t i = currentLayers.size();
    while (i--) {
        const sp<LayerBase>& layer = currentLayers[i];
        layer->validateVisibility(planeTransform);

        // start with the whole surface at its current location
        const Layer::State& s(layer->drawingState());

        // handle hidden surfaces by setting the visible region to empty
        Region opaqueRegion;
        Region visibleRegion;
        Region coveredRegion;
        if (LIKELY(!(s.flags & ISurfaceComposer::eLayerHidden) && s.alpha)) {
            const bool translucent = layer->needsBlending();
            const Rect bounds(layer->visibleBounds());
            visibleRegion.set(bounds);
            coveredRegion = visibleRegion;

            // Remove the transparent area from the visible region
            if (translucent) {
                visibleRegion.subtractSelf(layer->transparentRegionScreen);
            }

            // compute the opaque region
            if (s.alpha==255 && !translucent && layer->getOrientation()>=0) {
                // the opaque region is the visible region
                opaqueRegion = visibleRegion;
            }
        }

        // subtract the opaque region covered by the layers above us
        visibleRegion.subtractSelf(aboveOpaqueLayers);
        coveredRegion.andSelf(aboveCoveredLayers);

        // compute this layer's dirty region
        if (layer->contentDirty) {
            // we need to invalidate the whole region
            dirty = visibleRegion;
            // as well, as the old visible region
            dirty.orSelf(layer->visibleRegionScreen);
            layer->contentDirty = false;
        } else {
            /* compute the exposed region:
             *    exposed = what's VISIBLE and NOT COVERED now 
             *    but was COVERED before
             */
            dirty = (visibleRegion - coveredRegion) & layer->coveredRegionScreen;
        }
        dirty.subtractSelf(aboveOpaqueLayers);

        // accumulate to the screen dirty region
        dirtyRegion.orSelf(dirty);

        // Update aboveOpaqueLayers/aboveCoveredLayers for next (lower) layer
        aboveOpaqueLayers.orSelf(opaqueRegion);
        aboveCoveredLayers.orSelf(visibleRegion);
        
        // Store the visible region is screen space
        layer->setVisibleRegion(visibleRegion);
        layer->setCoveredRegion(coveredRegion);

        // If a secure layer is partially visible, lock-down the screen!
        if (layer->isSecure() && !visibleRegion.isEmpty()) {
            secureFrameBuffer = true;
        }
    }

    // invalidate the areas where a layer was removed
    dirtyRegion.orSelf(mDirtyRegionRemovedLayer);
    mDirtyRegionRemovedLayer.clear();

    mSecureFrameBuffer = secureFrameBuffer;
    opaqueRegion = aboveOpaqueLayers;
}


void SurfaceFlinger::commitTransaction()
{
    mDrawingState = mCurrentState;
    mTransactionCV.signal();
}

void SurfaceFlinger::handlePageFlip()
{
    bool visibleRegions = mVisibleRegionsDirty;
    LayerVector& currentLayers = const_cast<LayerVector&>(mDrawingState.layersSortedByZ);
    visibleRegions |= lockPageFlip(currentLayers);

        const DisplayHardware& hw = graphicPlane(0).displayHardware();
        const Region screenRegion(hw.bounds());
        if (visibleRegions) {
            Region opaqueRegion;
            computeVisibleRegions(currentLayers, mDirtyRegion, opaqueRegion);
            mWormholeRegion = screenRegion.subtract(opaqueRegion);
            mVisibleRegionsDirty = false;
        }

    unlockPageFlip(currentLayers);
    mDirtyRegion.andSelf(screenRegion);
}

bool SurfaceFlinger::lockPageFlip(const LayerVector& currentLayers)
{
    bool recomputeVisibleRegions = false;
    size_t count = currentLayers.size();
    sp<LayerBase> const* layers = currentLayers.array();
    for (size_t i=0 ; i<count ; i++) {
        const sp<LayerBase>& layer = layers[i];
        layer->lockPageFlip(recomputeVisibleRegions);
    }
    return recomputeVisibleRegions;
}

void SurfaceFlinger::unlockPageFlip(const LayerVector& currentLayers)
{
    const GraphicPlane& plane(graphicPlane(0));
    const Transform& planeTransform(plane.transform());
    size_t count = currentLayers.size();
    sp<LayerBase> const* layers = currentLayers.array();
    for (size_t i=0 ; i<count ; i++) {
        const sp<LayerBase>& layer = layers[i];
        layer->unlockPageFlip(planeTransform, mDirtyRegion);
    }
}


void SurfaceFlinger::handleRepaint()
{
    // compute the invalid region
    mInvalidRegion.orSelf(mDirtyRegion);
    if (mInvalidRegion.isEmpty()) {
        // nothing to do
        return;
    }

    if (UNLIKELY(mDebugRegion)) {
        debugFlashRegions();
    }

    // set the frame buffer
    const DisplayHardware& hw(graphicPlane(0).displayHardware());
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();

    uint32_t flags = hw.getFlags();
    if ((flags & DisplayHardware::SWAP_RECTANGLE) || 
        (flags & DisplayHardware::BUFFER_PRESERVED)) 
    {
        // we can redraw only what's dirty, but since SWAP_RECTANGLE only
        // takes a rectangle, we must make sure to update that whole
        // rectangle in that case
        if (flags & DisplayHardware::SWAP_RECTANGLE) {
            // FIXME: we really should be able to pass a region to
            // SWAP_RECTANGLE so that we don't have to redraw all this.
            mDirtyRegion.set(mInvalidRegion.bounds());
        } else {
            // in the BUFFER_PRESERVED case, obviously, we can update only
            // what's needed and nothing more.
            // NOTE: this is NOT a common case, as preserving the backbuffer
            // is costly and usually involves copying the whole update back.
        }
    } else {
        if (flags & DisplayHardware::UPDATE_ON_DEMAND) {
            // We need to redraw the rectangle that will be updated
            // (pushed to the framebuffer).
            // This is needed because UPDATE_ON_DEMAND only takes one
            // rectangle instead of a region (see DisplayHardware::flip())
            mDirtyRegion.set(mInvalidRegion.bounds());
        } else {
            // we need to redraw everything (the whole screen)
            mDirtyRegion.set(hw.bounds());
            mInvalidRegion = mDirtyRegion;
        }
    }

    // compose all surfaces
    composeSurfaces(mDirtyRegion);

    // clear the dirty regions
    mDirtyRegion.clear();
}

void SurfaceFlinger::composeSurfaces(const Region& dirty)
{
    if (UNLIKELY(!mWormholeRegion.isEmpty())) {
        // should never happen unless the window manager has a bug
        // draw something...
        drawWormhole();
    }
    const SurfaceFlinger& flinger(*this);
    const LayerVector& drawingLayers(mDrawingState.layersSortedByZ);
    const size_t count = drawingLayers.size();
    sp<LayerBase> const* const layers = drawingLayers.array();
    for (size_t i=0 ; i<count ; ++i) {
        const sp<LayerBase>& layer = layers[i];
        const Region& visibleRegion(layer->visibleRegionScreen);
        if (!visibleRegion.isEmpty())  {
            const Region clip(dirty.intersect(visibleRegion));
            if (!clip.isEmpty()) {
                layer->draw(clip);
            }
        }
    }
}

void SurfaceFlinger::unlockClients()
{
    const LayerVector& drawingLayers(mDrawingState.layersSortedByZ);
    const size_t count = drawingLayers.size();
    sp<LayerBase> const* const layers = drawingLayers.array();
    for (size_t i=0 ; i<count ; ++i) {
        const sp<LayerBase>& layer = layers[i];
        layer->finishPageFlip();
    }
}

void SurfaceFlinger::scheduleBroadcast(const sp<Client>& client)
{
    if (mLastScheduledBroadcast != client) {
        mLastScheduledBroadcast = client;
        mScheduledBroadcasts.add(client);
    }
}

void SurfaceFlinger::executeScheduledBroadcasts()
{
    SortedVector< wp<Client> >& list(mScheduledBroadcasts);
    size_t count = list.size();
    while (count--) {
        sp<Client> client = list[count].promote();
        if (client != 0) {
            per_client_cblk_t* const cblk = client->ctrlblk;
            if (cblk->lock.tryLock() == NO_ERROR) {
                cblk->cv.broadcast();
                list.removeAt(count);
                cblk->lock.unlock();
            } else {
                // schedule another round
                LOGW("executeScheduledBroadcasts() skipped, "
                        "contention on the client. We'll try again later...");
                signalDelayedEvent(ms2ns(4));
            }
        }
    }
    mLastScheduledBroadcast = 0;
}

void SurfaceFlinger::debugFlashRegions()
{
     const DisplayHardware& hw(graphicPlane(0).displayHardware());
     const uint32_t flags = hw.getFlags();

     if (!((flags & DisplayHardware::SWAP_RECTANGLE) ||
             (flags & DisplayHardware::BUFFER_PRESERVED))) {
         const Region repaint((flags & DisplayHardware::UPDATE_ON_DEMAND) ?
                 mDirtyRegion.bounds() : hw.bounds());
         composeSurfaces(repaint);
     }
    
    glDisable(GL_TEXTURE_2D);
    glDisable(GL_BLEND);
    glDisable(GL_DITHER);
    glDisable(GL_SCISSOR_TEST);

    static int toggle = 0;
    toggle = 1 - toggle;
    if (toggle) {
        glColor4x(0x10000, 0, 0x10000, 0x10000);
    } else {
        glColor4x(0x10000, 0x10000, 0, 0x10000);
    }

    Region::const_iterator it = mDirtyRegion.begin();
    Region::const_iterator const end = mDirtyRegion.end();
    while (it != end) {
        const Rect& r = *it++;
        GLfloat vertices[][2] = {
                { r.left,  r.top },
                { r.left,  r.bottom },
                { r.right, r.bottom },
                { r.right, r.top }
        };
        glVertexPointer(2, GL_FLOAT, 0, vertices);
        glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
    }
    
    if (mInvalidRegion.isEmpty()) {
        mDirtyRegion.dump("mDirtyRegion");
        mInvalidRegion.dump("mInvalidRegion");
    }
    hw.flip(mInvalidRegion);

    if (mDebugRegion > 1)
       usleep(mDebugRegion * 1000);

    glEnable(GL_SCISSOR_TEST);
    //mDirtyRegion.dump("mDirtyRegion");
}

void SurfaceFlinger::drawWormhole() const
{
    const Region region(mWormholeRegion.intersect(mDirtyRegion));
    if (region.isEmpty())
        return;

    const DisplayHardware& hw(graphicPlane(0).displayHardware());
    const int32_t width = hw.getWidth();
    const int32_t height = hw.getHeight();

    glDisable(GL_BLEND);
    glDisable(GL_DITHER);

    if (LIKELY(!mDebugBackground)) {
        glClearColorx(0,0,0,0);
        Region::const_iterator it = region.begin();
        Region::const_iterator const end = region.end();
        while (it != end) {
            const Rect& r = *it++;
            const GLint sy = height - (r.top + r.height());
            glScissor(r.left, sy, r.width(), r.height());
            glClear(GL_COLOR_BUFFER_BIT);
        }
    } else {
        const GLshort vertices[][2] = { { 0, 0 }, { width, 0 },
                { width, height }, { 0, height }  };
        const GLshort tcoords[][2] = { { 0, 0 }, { 1, 0 },  { 1, 1 }, { 0, 1 } };
        glVertexPointer(2, GL_SHORT, 0, vertices);
        glTexCoordPointer(2, GL_SHORT, 0, tcoords);
        glEnableClientState(GL_TEXTURE_COORD_ARRAY);
        glEnable(GL_TEXTURE_2D);
        glBindTexture(GL_TEXTURE_2D, mWormholeTexName);
        glTexEnvx(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
        glMatrixMode(GL_TEXTURE);
        glLoadIdentity();
        glScalef(width*(1.0f/32.0f), height*(1.0f/32.0f), 1);
        Region::const_iterator it = region.begin();
        Region::const_iterator const end = region.end();
        while (it != end) {
            const Rect& r = *it++;
            const GLint sy = height - (r.top + r.height());
            glScissor(r.left, sy, r.width(), r.height());
            glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
        }
        glDisableClientState(GL_TEXTURE_COORD_ARRAY);
    }
}

void SurfaceFlinger::debugShowFPS() const
{
    static int mFrameCount;
    static int mLastFrameCount = 0;
    static nsecs_t mLastFpsTime = 0;
    static float mFps = 0;
    mFrameCount++;
    nsecs_t now = systemTime();
    nsecs_t diff = now - mLastFpsTime;
    if (diff > ms2ns(250)) {
        mFps =  ((mFrameCount - mLastFrameCount) * float(s2ns(1))) / diff;
        mLastFpsTime = now;
        mLastFrameCount = mFrameCount;
    }
    // XXX: mFPS has the value we want
 }

status_t SurfaceFlinger::addLayer(const sp<LayerBase>& layer)
{
    Mutex::Autolock _l(mStateLock);
    addLayer_l(layer);
    setTransactionFlags(eTransactionNeeded|eTraversalNeeded);
    return NO_ERROR;
}

status_t SurfaceFlinger::removeLayer(const sp<LayerBase>& layer)
{
    Mutex::Autolock _l(mStateLock);
    status_t err = purgatorizeLayer_l(layer);
    if (err == NO_ERROR)
        setTransactionFlags(eTransactionNeeded);
    return err;
}

status_t SurfaceFlinger::invalidateLayerVisibility(const sp<LayerBase>& layer)
{
    layer->forceVisibilityTransaction();
    setTransactionFlags(eTraversalNeeded);
    return NO_ERROR;
}

status_t SurfaceFlinger::addLayer_l(const sp<LayerBase>& layer)
{
    ssize_t i = mCurrentState.layersSortedByZ.add(
                layer, &LayerBase::compareCurrentStateZ);
    sp<LayerBaseClient> lbc = LayerBase::dynamicCast< LayerBaseClient* >(layer.get());
    if (lbc != 0) {
        mLayerMap.add(lbc->serverIndex(), lbc);
    }
    return NO_ERROR;
}

status_t SurfaceFlinger::removeLayer_l(const sp<LayerBase>& layerBase)
{
    ssize_t index = mCurrentState.layersSortedByZ.remove(layerBase);
    if (index >= 0) {
        mLayersRemoved = true;
        sp<LayerBaseClient> layer =
            LayerBase::dynamicCast< LayerBaseClient* >(layerBase.get());
        if (layer != 0) {
            mLayerMap.removeItem(layer->serverIndex());
        }
        return NO_ERROR;
    }
    return status_t(index);
}

status_t SurfaceFlinger::purgatorizeLayer_l(const sp<LayerBase>& layerBase)
{
    // remove the layer from the main list (through a transaction).
    ssize_t err = removeLayer_l(layerBase);

    // it's possible that we don't find a layer, because it might
    // have been destroyed already -- this is not technically an error
    // from the user because there is a race between BClient::destroySurface(),
    // ~BClient() and ~ISurface().
    return (err == NAME_NOT_FOUND) ? status_t(NO_ERROR) : err;
}


void SurfaceFlinger::free_resources_l()
{
    // Destroy layers that were removed
    mLayersRemoved = false;
    
    // free resources associated with disconnected clients
    SortedVector< wp<Client> >& scheduledBroadcasts(mScheduledBroadcasts);
    Vector< sp<Client> >& disconnectedClients(mDisconnectedClients);
    const size_t count = disconnectedClients.size();
    for (size_t i=0 ; i<count ; i++) {
        sp<Client> client = disconnectedClients[i];
        // if this client is the scheduled broadcast list,
        // remove it from there (and we don't need to signal it
        // since it is dead).
        int32_t index = scheduledBroadcasts.indexOf(client);
        if (index >= 0) {
            scheduledBroadcasts.removeItemsAt(index);
        }
        mTokens.release(client->cid);
    }
    disconnectedClients.clear();
}

uint32_t SurfaceFlinger::getTransactionFlags(uint32_t flags)
{
    return android_atomic_and(~flags, &mTransactionFlags) & flags;
}

uint32_t SurfaceFlinger::setTransactionFlags(uint32_t flags, nsecs_t delay)
{
    uint32_t old = android_atomic_or(flags, &mTransactionFlags);
    if ((old & flags)==0) { // wake the server up
        if (delay > 0) {
            signalDelayedEvent(delay);
        } else {
            signalEvent();
        }
    }
    return old;
}

void SurfaceFlinger::openGlobalTransaction()
{
    android_atomic_inc(&mTransactionCount);
}

void SurfaceFlinger::closeGlobalTransaction()
{
    if (android_atomic_dec(&mTransactionCount) == 1) {
        signalEvent();
    }
}

status_t SurfaceFlinger::freezeDisplay(DisplayID dpy, uint32_t flags)
{
    if (UNLIKELY(uint32_t(dpy) >= DISPLAY_COUNT))
        return BAD_VALUE;

    Mutex::Autolock _l(mStateLock);
    mCurrentState.freezeDisplay = 1;
    setTransactionFlags(eTransactionNeeded);

    // flags is intended to communicate some sort of animation behavior
    // (for instance fading)
    return NO_ERROR;
}

status_t SurfaceFlinger::unfreezeDisplay(DisplayID dpy, uint32_t flags)
{
    if (UNLIKELY(uint32_t(dpy) >= DISPLAY_COUNT))
        return BAD_VALUE;

    Mutex::Autolock _l(mStateLock);
    mCurrentState.freezeDisplay = 0;
    setTransactionFlags(eTransactionNeeded);

    // flags is intended to communicate some sort of animation behavior
    // (for instance fading)
    return NO_ERROR;
}

int SurfaceFlinger::setOrientation(DisplayID dpy, 
        int orientation, uint32_t flags)
{
    if (UNLIKELY(uint32_t(dpy) >= DISPLAY_COUNT))
        return BAD_VALUE;

    Mutex::Autolock _l(mStateLock);
    if (mCurrentState.orientation != orientation) {
        if (uint32_t(orientation)<=eOrientation270 || orientation==42) {
            mCurrentState.orientationType = flags;
            mCurrentState.orientation = orientation;
            setTransactionFlags(eTransactionNeeded);
            mTransactionCV.wait(mStateLock);
        } else {
            orientation = BAD_VALUE;
        }
    }
    return orientation;
}

sp<ISurface> SurfaceFlinger::createSurface(ClientID clientId, int pid,
        ISurfaceFlingerClient::surface_data_t* params,
        DisplayID d, uint32_t w, uint32_t h, PixelFormat format,
        uint32_t flags)
{
    sp<LayerBaseClient> layer;
    sp<LayerBaseClient::Surface> surfaceHandle;

    if (int32_t(w|h) < 0) {
        LOGE("createSurface() failed, w or h is negative (w=%d, h=%d)",
                int(w), int(h));
        return surfaceHandle;
    }
    
    Mutex::Autolock _l(mStateLock);
    sp<Client> client = mClientsMap.valueFor(clientId);
    if (UNLIKELY(client == 0)) {
        LOGE("createSurface() failed, client not found (id=%d)", clientId);
        return surfaceHandle;
    }

    //LOGD("createSurface for pid %d (%d x %d)", pid, w, h);
    int32_t id = client->generateId(pid);
    if (uint32_t(id) >= NUM_LAYERS_MAX) {
        LOGE("createSurface() failed, generateId = %d", id);
        return surfaceHandle;
    }

    switch (flags & eFXSurfaceMask) {
        case eFXSurfaceNormal:
            if (UNLIKELY(flags & ePushBuffers)) {
                layer = createPushBuffersSurfaceLocked(client, d, id,
                        w, h, flags);
            } else {
                layer = createNormalSurfaceLocked(client, d, id,
                        w, h, flags, format);
            }
            break;
        case eFXSurfaceBlur:
            layer = createBlurSurfaceLocked(client, d, id, w, h, flags);
            break;
        case eFXSurfaceDim:
            layer = createDimSurfaceLocked(client, d, id, w, h, flags);
            break;
    }

    if (layer != 0) {
        setTransactionFlags(eTransactionNeeded);
        surfaceHandle = layer->getSurface();
        if (surfaceHandle != 0) { 
            params->token = surfaceHandle->getToken();
            params->identity = surfaceHandle->getIdentity();
            params->width = w;
            params->height = h;
            params->format = format;
        }
    }

    return surfaceHandle;
}

sp<LayerBaseClient> SurfaceFlinger::createNormalSurfaceLocked(
        const sp<Client>& client, DisplayID display,
        int32_t id, uint32_t w, uint32_t h, uint32_t flags,
        PixelFormat& format)
{
    // initialize the surfaces
    switch (format) { // TODO: take h/w into account
    case PIXEL_FORMAT_TRANSPARENT:
    case PIXEL_FORMAT_TRANSLUCENT:
        format = PIXEL_FORMAT_RGBA_8888;
        break;
    case PIXEL_FORMAT_OPAQUE:
        format = PIXEL_FORMAT_RGB_565;
        break;
    }

    sp<Layer> layer = new Layer(this, display, client, id);
    status_t err = layer->setBuffers(w, h, format, flags);
    if (LIKELY(err == NO_ERROR)) {
        layer->initStates(w, h, flags);
        addLayer_l(layer);
    } else {
        LOGE("createNormalSurfaceLocked() failed (%s)", strerror(-err));
        layer.clear();
    }
    return layer;
}

sp<LayerBaseClient> SurfaceFlinger::createBlurSurfaceLocked(
        const sp<Client>& client, DisplayID display,
        int32_t id, uint32_t w, uint32_t h, uint32_t flags)
{
    sp<LayerBlur> layer = new LayerBlur(this, display, client, id);
    layer->initStates(w, h, flags);
    addLayer_l(layer);
    return layer;
}

sp<LayerBaseClient> SurfaceFlinger::createDimSurfaceLocked(
        const sp<Client>& client, DisplayID display,
        int32_t id, uint32_t w, uint32_t h, uint32_t flags)
{
    sp<LayerDim> layer = new LayerDim(this, display, client, id);
    layer->initStates(w, h, flags);
    addLayer_l(layer);
    return layer;
}

sp<LayerBaseClient> SurfaceFlinger::createPushBuffersSurfaceLocked(
        const sp<Client>& client, DisplayID display,
        int32_t id, uint32_t w, uint32_t h, uint32_t flags)
{
    sp<LayerBuffer> layer = new LayerBuffer(this, display, client, id);
    layer->initStates(w, h, flags);
    addLayer_l(layer);
    return layer;
}

status_t SurfaceFlinger::removeSurface(SurfaceID index)
{
    /*
     * called by the window manager, when a surface should be marked for
     * destruction.
     * 
     * The surface is removed from the current and drawing lists, but placed
     * in the purgatory queue, so it's not destroyed right-away (we need
     * to wait for all client's references to go away first).
     */

    Mutex::Autolock _l(mStateLock);
    sp<LayerBaseClient> layer = getLayerUser_l(index);
    status_t err = purgatorizeLayer_l(layer);
    if (err == NO_ERROR) {
        setTransactionFlags(eTransactionNeeded);
    }
    return err;
}

status_t SurfaceFlinger::destroySurface(const sp<LayerBaseClient>& layer)
{
    // called by ~ISurface() when all references are gone
    
    class MessageDestroySurface : public MessageBase {
        SurfaceFlinger* flinger;
        sp<LayerBaseClient> layer;
    public:
        MessageDestroySurface(
                SurfaceFlinger* flinger, const sp<LayerBaseClient>& layer)
            : flinger(flinger), layer(layer) { }
        virtual bool handler() {
            sp<LayerBaseClient> l(layer);
            layer.clear(); // clear it outside of the lock;
            Mutex::Autolock _l(flinger->mStateLock);
            /*
             * remove the layer from the current list -- chances are that it's 
             * not in the list anyway, because it should have been removed 
             * already upon request of the client (eg: window manager). 
             * However, a buggy client could have not done that.
             * Since we know we don't have any more clients, we don't need
             * to use the purgatory.
             */
            status_t err = flinger->removeLayer_l(l);
            LOGE_IF(err<0 && err != NAME_NOT_FOUND,
                    "error removing layer=%p (%s)", l.get(), strerror(-err));
            return true;
        }
    };

    mEventQueue.postMessage( new MessageDestroySurface(this, layer) );
    return NO_ERROR;
}

status_t SurfaceFlinger::setClientState(
        ClientID cid,
        int32_t count,
        const layer_state_t* states)
{
    Mutex::Autolock _l(mStateLock);
    uint32_t flags = 0;
    cid <<= 16;
    for (int i=0 ; i<count ; i++) {
        const layer_state_t& s = states[i];
        sp<LayerBaseClient> layer(getLayerUser_l(s.surface | cid));
        if (layer != 0) {
            const uint32_t what = s.what;
            if (what & ePositionChanged) {
                if (layer->setPosition(s.x, s.y))
                    flags |= eTraversalNeeded;
            }
            if (what & eLayerChanged) {
                if (layer->setLayer(s.z)) {
                    mCurrentState.layersSortedByZ.reorder(
                            layer, &Layer::compareCurrentStateZ);
                    // we need traversal (state changed)
                    // AND transaction (list changed)
                    flags |= eTransactionNeeded|eTraversalNeeded;
                }
            }
            if (what & eSizeChanged) {
                if (layer->setSize(s.w, s.h))
                    flags |= eTraversalNeeded;
            }
            if (what & eAlphaChanged) {
                if (layer->setAlpha(uint8_t(255.0f*s.alpha+0.5f)))
                    flags |= eTraversalNeeded;
            }
            if (what & eMatrixChanged) {
                if (layer->setMatrix(s.matrix))
                    flags |= eTraversalNeeded;
            }
            if (what & eTransparentRegionChanged) {
                if (layer->setTransparentRegionHint(s.transparentRegion))
                    flags |= eTraversalNeeded;
            }
            if (what & eVisibilityChanged) {
                if (layer->setFlags(s.flags, s.mask))
                    flags |= eTraversalNeeded;
            }
        }
    }
    if (flags) {
        setTransactionFlags(flags);
    }
    return NO_ERROR;
}

sp<LayerBaseClient> SurfaceFlinger::getLayerUser_l(SurfaceID s) const
{
    sp<LayerBaseClient> layer = mLayerMap.valueFor(s);
    return layer;
}

void SurfaceFlinger::screenReleased(int dpy)
{
    // this may be called by a signal handler, we can't do too much in here
    android_atomic_or(eConsoleReleased, &mConsoleSignals);
    signalEvent();
}

void SurfaceFlinger::screenAcquired(int dpy)
{
    // this may be called by a signal handler, we can't do too much in here
    android_atomic_or(eConsoleAcquired, &mConsoleSignals);
    signalEvent();
}

status_t SurfaceFlinger::dump(int fd, const Vector<String16>& args)
{
    const size_t SIZE = 1024;
    char buffer[SIZE];
    String8 result;
    if (!mDump.checkCalling()) {
        snprintf(buffer, SIZE, "Permission Denial: "
                "can't dump SurfaceFlinger from pid=%d, uid=%d\n",
                IPCThreadState::self()->getCallingPid(),
                IPCThreadState::self()->getCallingUid());
        result.append(buffer);
    } else {
        Mutex::Autolock _l(mStateLock);
        size_t s = mClientsMap.size();
        char name[64];
        for (size_t i=0 ; i<s ; i++) {
            sp<Client> client = mClientsMap.valueAt(i);
            sprintf(name, "  Client (id=0x%08x)", client->cid);
            client->dump(name);
        }
        const LayerVector& currentLayers = mCurrentState.layersSortedByZ;
        const size_t count = currentLayers.size();
        for (size_t i=0 ; i<count ; i++) {
            /*** LayerBase ***/
            const sp<LayerBase>& layer = currentLayers[i];
            const Layer::State& s = layer->drawingState();
            snprintf(buffer, SIZE,
                    "+ %s %p\n"
                    "      "
                    "z=%9d, pos=(%4d,%4d), size=(%4d,%4d), "
                    "needsBlending=%1d, invalidate=%1d, "
                    "alpha=0x%02x, flags=0x%08x, tr=[%.2f, %.2f][%.2f, %.2f]\n",
                    layer->getTypeID(), layer.get(),
                    s.z, layer->tx(), layer->ty(), s.w, s.h,
                    layer->needsBlending(), layer->contentDirty,
                    s.alpha, s.flags,
                    s.transform[0], s.transform[1],
                    s.transform[2], s.transform[3]);
            result.append(buffer);
            buffer[0] = 0;
            /*** LayerBaseClient ***/
            sp<LayerBaseClient> lbc =
                LayerBase::dynamicCast< LayerBaseClient* >(layer.get());
            if (lbc != 0) {
                sp<Client> client(lbc->client.promote());
                snprintf(buffer, SIZE,
                        "      "
                        "id=0x%08x, client=0x%08x, identity=%u\n",
                        lbc->clientIndex(), client.get() ? client->cid : 0,
                        lbc->getIdentity());
            }
            result.append(buffer);
            buffer[0] = 0;
            /*** Layer ***/
            sp<Layer> l = LayerBase::dynamicCast< Layer* >(layer.get());
            if (l != 0) {
                const LayerBitmap& buf0(l->getBuffer(0));
                const LayerBitmap& buf1(l->getBuffer(1));
                snprintf(buffer, SIZE,
                        "      "
                        "format=%2d, [%3ux%3u:%3u] [%3ux%3u:%3u],"
                        " freezeLock=%p, swapState=0x%08x\n",
                        l->pixelFormat(),
                        buf0.getWidth(), buf0.getHeight(), 
                        buf0.getBuffer()->getStride(),
                        buf1.getWidth(), buf1.getHeight(), 
                        buf1.getBuffer()->getStride(),
                        l->getFreezeLock().get(),
                        l->lcblk->swapState);
            }
            result.append(buffer);
            buffer[0] = 0;
            s.transparentRegion.dump(result, "transparentRegion");
            layer->transparentRegionScreen.dump(result, "transparentRegionScreen");
            layer->visibleRegionScreen.dump(result, "visibleRegionScreen");
        }
        mWormholeRegion.dump(result, "WormholeRegion");
        const DisplayHardware& hw(graphicPlane(0).displayHardware());
        snprintf(buffer, SIZE,
                "  display frozen: %s, freezeCount=%d, orientation=%d, canDraw=%d\n",
                mFreezeDisplay?"yes":"no", mFreezeCount,
                mCurrentState.orientation, hw.canDraw());
        result.append(buffer);
        snprintf(buffer, SIZE, "  client count: %d\n", mClientsMap.size());
        result.append(buffer);
        const BufferAllocator& alloc(BufferAllocator::get());
        alloc.dump(result);
    }
    write(fd, result.string(), result.size());
    return NO_ERROR;
}

status_t SurfaceFlinger::onTransact(
    uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
{
    switch (code) {
        case CREATE_CONNECTION:
        case OPEN_GLOBAL_TRANSACTION:
        case CLOSE_GLOBAL_TRANSACTION:
        case SET_ORIENTATION:
        case FREEZE_DISPLAY:
        case UNFREEZE_DISPLAY:
        case BOOT_FINISHED:
        {
            // codes that require permission check
            IPCThreadState* ipc = IPCThreadState::self();
            const int pid = ipc->getCallingPid();
            const int uid = ipc->getCallingUid();
            if ((uid != AID_GRAPHICS) && !mAccessSurfaceFlinger.check(pid, uid)) {
                LOGE("Permission Denial: "
                        "can't access SurfaceFlinger pid=%d, uid=%d", pid, uid);
                return PERMISSION_DENIED;
            }
        }
    }
    status_t err = BnSurfaceComposer::onTransact(code, data, reply, flags);
    if (err == UNKNOWN_TRANSACTION || err == PERMISSION_DENIED) {
        CHECK_INTERFACE(ISurfaceComposer, data, reply);
        if (UNLIKELY(!mHardwareTest.checkCalling())) {
            IPCThreadState* ipc = IPCThreadState::self();
            const int pid = ipc->getCallingPid();
            const int uid = ipc->getCallingUid();
            LOGE("Permission Denial: "
                    "can't access SurfaceFlinger pid=%d, uid=%d", pid, uid);
            return PERMISSION_DENIED;
        }
        int n;
        switch (code) {
            case 1000: // SHOW_CPU, NOT SUPPORTED ANYMORE
                return NO_ERROR;
            case 1001:  // SHOW_FPS, NOT SUPPORTED ANYMORE
                return NO_ERROR;
            case 1002:  // SHOW_UPDATES
                n = data.readInt32();
                mDebugRegion = n ? n : (mDebugRegion ? 0 : 1);
                return NO_ERROR;
            case 1003:  // SHOW_BACKGROUND
                n = data.readInt32();
                mDebugBackground = n ? 1 : 0;
                return NO_ERROR;
            case 1004:{ // repaint everything
                Mutex::Autolock _l(mStateLock);
                const DisplayHardware& hw(graphicPlane(0).displayHardware());
                mDirtyRegion.set(hw.bounds()); // careful that's not thread-safe
                signalEvent();
            }
            return NO_ERROR;
            case 1007: // set mFreezeCount
                mFreezeCount = data.readInt32();
                return NO_ERROR;
            case 1010:  // interrogate.
                reply->writeInt32(0);
                reply->writeInt32(0);
                reply->writeInt32(mDebugRegion);
                reply->writeInt32(mDebugBackground);
                return NO_ERROR;
            case 1013: {
                Mutex::Autolock _l(mStateLock);
                const DisplayHardware& hw(graphicPlane(0).displayHardware());
                reply->writeInt32(hw.getPageFlipCount());
            }
            return NO_ERROR;
        }
    }
    return err;
}

// ---------------------------------------------------------------------------
#if 0
#pragma mark -
#endif

Client::Client(ClientID clientID, const sp<SurfaceFlinger>& flinger)
    : ctrlblk(0), cid(clientID), mPid(0), mBitmap(0), mFlinger(flinger)
{
    const int pgsize = getpagesize();
    const int cblksize = ((sizeof(per_client_cblk_t)+(pgsize-1))&~(pgsize-1));

    mCblkHeap = new MemoryHeapBase(cblksize, 0,
            "SurfaceFlinger Client control-block");

    ctrlblk = static_cast<per_client_cblk_t *>(mCblkHeap->getBase());
    if (ctrlblk) { // construct the shared structure in-place.
        new(ctrlblk) per_client_cblk_t;
    }
}

Client::~Client() {
    if (ctrlblk) {
        const int pgsize = getpagesize();
        ctrlblk->~per_client_cblk_t();  // destroy our shared-structure.
    }
}

int32_t Client::generateId(int pid)
{
    const uint32_t i = clz( ~mBitmap );
    if (i >= NUM_LAYERS_MAX) {
        return NO_MEMORY;
    }
    mPid = pid;
    mInUse.add(uint8_t(i));
    mBitmap |= 1<<(31-i);
    return i;
}

status_t Client::bindLayer(const sp<LayerBaseClient>& layer, int32_t id)
{
    ssize_t idx = mInUse.indexOf(id);
    if (idx < 0)
        return NAME_NOT_FOUND;
    return mLayers.insertAt(layer, idx);
}

void Client::free(int32_t id)
{
    ssize_t idx = mInUse.remove(uint8_t(id));
    if (idx >= 0) {
        mBitmap &= ~(1<<(31-id));
        mLayers.removeItemsAt(idx);
    }
}

bool Client::isValid(int32_t i) const {
    return (uint32_t(i)<NUM_LAYERS_MAX) && (mBitmap & (1<<(31-i)));
}

sp<LayerBaseClient> Client::getLayerUser(int32_t i) const {
    sp<LayerBaseClient> lbc;
    ssize_t idx = mInUse.indexOf(uint8_t(i));
    if (idx >= 0) {
        lbc = mLayers[idx].promote();
        LOGE_IF(lbc==0, "getLayerUser(i=%d), idx=%d is dead", int(i), int(idx));
    }
    return lbc;
}

void Client::dump(const char* what)
{
}

// ---------------------------------------------------------------------------
#if 0
#pragma mark -
#endif

BClient::BClient(SurfaceFlinger *flinger, ClientID cid, const sp<IMemoryHeap>& cblk)
    : mId(cid), mFlinger(flinger), mCblk(cblk)
{
}

BClient::~BClient() {
    // destroy all resources attached to this client
    mFlinger->destroyConnection(mId);
}

sp<IMemoryHeap> BClient::getControlBlock() const {
    return mCblk;
}

sp<ISurface> BClient::createSurface(
        ISurfaceFlingerClient::surface_data_t* params, int pid,
        DisplayID display, uint32_t w, uint32_t h, PixelFormat format,
        uint32_t flags)
{
    return mFlinger->createSurface(mId, pid, params, display, w, h, format, flags);
}

status_t BClient::destroySurface(SurfaceID sid)
{
    sid |= (mId << 16); // add the client-part to id
    return mFlinger->removeSurface(sid);
}

status_t BClient::setState(int32_t count, const layer_state_t* states)
{
    return mFlinger->setClientState(mId, count, states);
}

// ---------------------------------------------------------------------------

GraphicPlane::GraphicPlane()
    : mHw(0)
{
}

GraphicPlane::~GraphicPlane() {
    delete mHw;
}

bool GraphicPlane::initialized() const {
    return mHw ? true : false;
}

void GraphicPlane::setDisplayHardware(DisplayHardware *hw) {
    mHw = hw;
}

void GraphicPlane::setTransform(const Transform& tr) {
    mTransform = tr;
    mGlobalTransform = mOrientationTransform * mTransform;
}

status_t GraphicPlane::orientationToTransfrom(
        int orientation, int w, int h, Transform* tr)
{    
    float a, b, c, d, x, y;
    switch (orientation) {
    case ISurfaceComposer::eOrientationDefault:
        a=1; b=0; c=0; d=1; x=0; y=0;
        break;
    case ISurfaceComposer::eOrientation90:
        a=0; b=-1; c=1; d=0; x=w; y=0;
        break;
    case ISurfaceComposer::eOrientation180:
        a=-1; b=0; c=0; d=-1; x=w; y=h;
        break;
    case ISurfaceComposer::eOrientation270:
        a=0; b=1; c=-1; d=0; x=0; y=h;
        break;
    default:
        return BAD_VALUE;
    }
    tr->set(a, b, c, d);
    tr->set(x, y);
    return NO_ERROR;
}

status_t GraphicPlane::setOrientation(int orientation)
{
    const DisplayHardware& hw(displayHardware());
    const float w = hw.getWidth();
    const float h = hw.getHeight();

    if (orientation == ISurfaceComposer::eOrientationDefault) {
        // make sure the default orientation is optimal
        mOrientationTransform.reset();
        mOrientation = orientation;
        mGlobalTransform = mTransform;
        return NO_ERROR;
    }

    // If the rotation can be handled in hardware, this is where
    // the magic should happen.
    if (UNLIKELY(orientation == 42)) {
        float a, b, c, d, x, y;
        const float r = (3.14159265f / 180.0f) * 42.0f;
        const float si = sinf(r);
        const float co = cosf(r);
        a=co; b=-si; c=si; d=co;
        x = si*(h*0.5f) + (1-co)*(w*0.5f);
        y =-si*(w*0.5f) + (1-co)*(h*0.5f);
        mOrientationTransform.set(a, b, c, d);
        mOrientationTransform.set(x, y);
    } else {
        GraphicPlane::orientationToTransfrom(orientation, w, h,
                &mOrientationTransform);
    }
    mOrientation = orientation;
    mGlobalTransform = mOrientationTransform * mTransform;
    return NO_ERROR;
}

const DisplayHardware& GraphicPlane::displayHardware() const {
    return *mHw;
}

const Transform& GraphicPlane::transform() const {
    return mGlobalTransform;
}

EGLDisplay GraphicPlane::getEGLDisplay() const {
    return mHw->getEGLDisplay();
}

// ---------------------------------------------------------------------------

}; // namespace android
