void BufferManager::deinitialize()
{
    mInitialized = false;

    if (mBufferPool) {
        // unmap & delete all cached buffer mappers
        for (size_t i = 0; i < mBufferPool->getCacheSize(); i++) {
            BufferMapper *mapper = mBufferPool->getMapper(i);
            mapper->unmap();
            delete mapper;
        }

        delete mBufferPool;
        mBufferPool = NULL;
    }

    for (size_t j = 0; j < mFrameBuffers.size(); j++) {
        BufferMapper *mapper = mFrameBuffers.valueAt(j);
        mapper->unmap();
        delete mapper;
    }
    mFrameBuffers.clear();

    if (mGralloc) {
        gralloc_close_img(mGralloc);
        mGralloc = NULL;
    }

    if (mDataBuffer) {
        delete mDataBuffer;
        mDataBuffer = NULL;
    }
}
bool DisplayPlane::isActiveBuffer(BufferMapper *mapper)
{
    for (size_t i = 0; i < mActiveBuffers.size(); i++) {
        BufferMapper *activeMapper = mActiveBuffers.itemAt(i);
        if (!activeMapper)
            continue;
        if (activeMapper->getKey() == mapper->getKey())
            return true;
    }

    return false;
}
BufferMapper* BufferManager::map(DataBuffer& buffer)
{
    bool ret;
    BufferMapper* mapper;

    CTRACE();
    Mutex::Autolock _l(mLock);
    //try to get mapper from pool
    mapper = mBufferPool->getMapper(buffer.getKey());
    if (mapper) {
        // increase mapper ref count
        mapper->incRef();
        return mapper;
    }

    // create a new buffer mapper and add it to pool
    do {
        VLOGTRACE("new buffer, will add it");
        mapper = createBufferMapper(buffer);
        if (!mapper) {
            ELOGTRACE("failed to allocate mapper");
            break;
        }
        ret = mapper->map();
        if (!ret) {
            ELOGTRACE("failed to map");
            delete mapper;
            mapper = NULL;
            break;
        }
        ret = mBufferPool->addMapper(buffer.getKey(), mapper);
        if (!ret) {
            ELOGTRACE("failed to add mapper");
            break;
        }
        // increase mapper ref count
        mapper->incRef();
        return mapper;
    } while (0);

    // error handling
    if (mapper) {
        mapper->unmap();
        delete mapper;
    }
    return NULL;
}
void BufferManager::freeFrameBuffer(uint32_t fbHandle)
{
    RETURN_VOID_IF_NOT_INIT();

    if (!mGralloc) {
        WLOGTRACE("Alloc device is not available");
        return;
    }

    ssize_t index = mFrameBuffers.indexOfKey(fbHandle);
    if (index < 0) {
        ELOGTRACE("invalid kernel handle");
        return;
    }

    BufferMapper *mapper = mFrameBuffers.valueAt(index);
    uint32_t handle = mapper->getHandle();
    mapper->putFbHandle();
    delete mapper;
    mFrameBuffers.removeItem(fbHandle);
    gralloc_device_free_img(mGralloc, (buffer_handle_t)handle);
}
void BufferManager::dump(Dump& d)
{
    d.append("Buffer Manager status: pool size %d\n", mBufferPool->getCacheSize());
    d.append("-------------------------------------------------------------\n");
    for (size_t i = 0; i < mBufferPool->getCacheSize(); i++) {
        BufferMapper *mapper = mBufferPool->getMapper(i);
        d.append("Buffer %d: handle %#x, (%dx%d), format %d, refCount %d\n",
                 i,
                 mapper->getHandle(),
                 mapper->getWidth(),
                 mapper->getHeight(),
                 mapper->getFormat(),
                 mapper->getRef());
    }
    return;
}
bool TngSpritePlane::setDataBuffer(BufferMapper& mapper)
{
    int bpp;
    int srcX, srcY;
    int dstX, dstY, dstW, dstH;
    uint32_t spriteFormat;
    uint32_t stride;
    uint32_t linoff;
    uint32_t planeAlpha;

    CTRACE();

    // setup plane position
    dstX = mPosition.x;
    dstY = mPosition.y;
    dstW = mPosition.w;
    dstH = mPosition.h;

    checkPosition(dstX, dstY, dstW, dstH);

    // setup plane format
    if (!PixelFormat::convertFormat(mapper.getFormat(), spriteFormat, bpp)) {
        ETRACE("unsupported format %#x", mapper.getFormat());
        return false;
    }

    // setup stride and source buffer crop
    srcX = mapper.getCrop().x;
    srcY = mapper.getCrop().y;
    stride = mapper.getStride().rgb.stride;
    linoff = srcY * stride + srcX * bpp;

    // setup plane alpha
    if ((mBlending == HWC_BLENDING_PREMULT) && (mPlaneAlpha == 0)) {
       planeAlpha = mPlaneAlpha | 0x80000000;
    } else {
       // disable plane alpha to offload HW
       planeAlpha = 0;
    }

    // unlikely happen, but still we need make sure linoff is valid
    if (linoff > (stride * mapper.getHeight())) {
        ETRACE("invalid source crop");
        return false;
    }

    // update context
    mContext.type = DC_SPRITE_PLANE;
    mContext.ctx.sp_ctx.index = mIndex;
    mContext.ctx.sp_ctx.pipe = mDevice;
    // none blending and BRGA format layer,set format to BGRX8888
    if (mBlending == HWC_BLENDING_NONE && spriteFormat == PixelFormat::PLANE_PIXEL_FORMAT_BGRA8888)
	mContext.ctx.sp_ctx.cntr = PixelFormat::PLANE_PIXEL_FORMAT_BGRX8888
					| 0x80000000;
    else
	mContext.ctx.sp_ctx.cntr = spriteFormat | 0x80000000;
    mContext.ctx.sp_ctx.linoff = linoff;
    mContext.ctx.sp_ctx.stride = stride;
    mContext.ctx.sp_ctx.surf = mapper.getGttOffsetInPage(0) << 12;
    mContext.ctx.sp_ctx.pos = (dstY & 0xfff) << 16 | (dstX & 0xfff);
    mContext.ctx.sp_ctx.size =
        ((dstH - 1) & 0xfff) << 16 | ((dstW - 1) & 0xfff);
    mContext.ctx.sp_ctx.contalpa = planeAlpha;
    mContext.ctx.sp_ctx.update_mask = SPRITE_UPDATE_ALL;
    mContext.gtt_key = (uint64_t)mapper.getCpuAddress(0);

    VTRACE("cntr = %#x, linoff = %#x, stride = %#x,"
          "surf = %#x, pos = %#x, size = %#x, contalpa = %#x",
          mContext.ctx.sp_ctx.cntr,
          mContext.ctx.sp_ctx.linoff,
          mContext.ctx.sp_ctx.stride,
          mContext.ctx.sp_ctx.surf,
          mContext.ctx.sp_ctx.pos,
          mContext.ctx.sp_ctx.size,
          mContext.ctx.sp_ctx.contalpa);
    return true;
}
uint32_t BufferManager::allocFrameBuffer(int width, int height, int *stride)
{
    RETURN_NULL_IF_NOT_INIT();

    if (!mGralloc) {
        WLOGTRACE("Alloc device is not available");
        return 0;
    }

    if (!width || !height || !stride) {
        ELOGTRACE("invalid input parameter");
        return 0;
    }

    ILOGTRACE("size of frame buffer to create: %dx%d", width, height);
    uint32_t handle = 0;
    status_t err = gralloc_device_alloc_img(
            mGralloc,
            width,
            height,
            DrmConfig::getFrameBufferFormat(),
            0, // GRALLOC_USAGE_HW_FB
            (buffer_handle_t *)&handle,
            stride);

    if (err != 0) {
        ELOGTRACE("failed to allocate frame buffer, error = %d", err);
        return 0;
    }

    DataBuffer *buffer = NULL;
    BufferMapper *mapper = NULL;

    do {
        buffer = lockDataBuffer(handle);
        if (!buffer) {
            ELOGTRACE("failed to get data buffer, handle = %#x", handle);
            break;
        }

        mapper = createBufferMapper(*buffer);
        if (!mapper) {
            ELOGTRACE("failed to create buffer mapper");
            break;
        }

        uint32_t fbHandle;
         if (!(fbHandle = mapper->getFbHandle(0))) {
             ELOGTRACE("failed to get Fb handle");
             break;
         }

        mFrameBuffers.add(fbHandle, mapper);
        unlockDataBuffer(buffer);
        return fbHandle;
    } while (0);

    // error handling, release all allocated resources
    if (buffer) {
        unlockDataBuffer(buffer);
    }
    if (mapper) {
        delete mapper;
    }
    gralloc_device_free_img(mGralloc, (buffer_handle_t)handle);
    return 0;
}
bool DisplayPlane::setDataBuffer(uint32_t handle)
{
    DataBuffer *buffer;
    BufferMapper *mapper;
    ssize_t index;
    bool ret;
    bool isCompression;
    BufferManager *bm = Hwcomposer::getInstance().getBufferManager();

    RETURN_FALSE_IF_NOT_INIT();
    ALOGTRACE("handle = %#x", handle);

    if (!handle) {
        WLOGTRACE("invalid buffer handle");
        return false;
    }

    // do not need to update the buffer handle
    if (mCurrentDataBuffer != handle)
        mUpdateMasks |= PLANE_BUFFER_CHANGED;

    // if no update then do Not need set data buffer
    if (!mUpdateMasks)
        return true;

    buffer = bm->lockDataBuffer(handle);
    if (!buffer) {
        ELOGTRACE("failed to get buffer");
        return false;
    }

    mIsProtectedBuffer = GraphicBuffer::isProtectedBuffer((GraphicBuffer*)buffer);
    isCompression = GraphicBuffer::isCompressionBuffer((GraphicBuffer*)buffer);

    // map buffer if it's not in cache
    index = mDataBuffers.indexOfKey(buffer->getKey());
    if (index < 0) {
        VLOGTRACE("unmapped buffer, mapping...");
        mapper = mapBuffer(buffer);
        if (!mapper) {
            ELOGTRACE("failed to map buffer %#x", handle);
            bm->unlockDataBuffer(buffer);
            return false;
        }
    } else {
        VLOGTRACE("got mapper in saved data buffers and update source Crop");
        mapper = mDataBuffers.valueAt(index);
    }

    // always update source crop to mapper
    mapper->setCrop(mSrcCrop.x, mSrcCrop.y, mSrcCrop.w, mSrcCrop.h);

    mapper->setIsCompression(isCompression);

    // unlock buffer after getting mapper
    bm->unlockDataBuffer(buffer);
    buffer = NULL;

    ret = setDataBuffer(*mapper);
    if (ret) {
        mCurrentDataBuffer = handle;
        // update active buffers
        updateActiveBuffers(mapper);
    }
    return ret;
}