diff --git a/libcamera2/Android.mk b/libcamera2/Android.mk
deleted file mode 100644
index 80e24fe..0000000
--- a/libcamera2/Android.mk
+++ /dev/null
@@ -1,35 +0,0 @@
-BUILD_LIBCAMERA:=
-ifeq ($(BUILD_LIBCAMERA),true)
-
-# When zero we link against libmmcamera; when 1, we dlopen libmmcamera.
-DLOPEN_LIBMMCAMERA:=1
-
-ifneq ($(BUILD_TINY_ANDROID),true)
-
-LOCAL_PATH:= $(call my-dir)
-
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES:= QualcommCameraHardware.cpp
-
-LOCAL_CFLAGS:= -DDLOPEN_LIBMMCAMERA=$(DLOPEN_LIBMMCAMERA)
-
-LOCAL_C_INCLUDES+= \
-	vendor/qcom/proprietary/mm-camera/common \
-	vendor/qcom/proprietary/mm-camera/apps/appslib \
-	vendor/qcom/proprietary/mm-camera/jpeg \
-	vendor/qcom/proprietary/mm-camera/jpeg/inc
-
-LOCAL_SHARED_LIBRARIES:= libutils libui liblog
-
-ifneq ($(DLOPEN_LIBMMCAMERA),1)
-LOCAL_SHARED_LIBRARIES+= libqcamera
-else
-LOCAL_SHARED_LIBRARIES+= libdl
-endif
-
-LOCAL_MODULE:= libcamera
-include $(BUILD_SHARED_LIBRARY)
-
-endif # BUILD_TINY_ANDROID
-endif # BUILD_LIBCAMERA
diff --git a/libcamera2/QualcommCameraHardware.cpp b/libcamera2/QualcommCameraHardware.cpp
deleted file mode 100644
index 2a39f20..0000000
--- a/libcamera2/QualcommCameraHardware.cpp
+++ /dev/null
@@ -1,1946 +0,0 @@
-/*
-** Copyright 2008, Google Inc.
-**
-** 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_NDEBUG 0
-#define LOG_TAG "QualcommCameraHardware"
-#include <utils/Log.h>
-
-#include "QualcommCameraHardware.h"
-
-#include <utils/threads.h>
-#include <utils/MemoryHeapPmem.h>
-#include <utils/String16.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <unistd.h>
-#if HAVE_ANDROID_OS
-#include <linux/android_pmem.h>
-#endif
-#include <linux/ioctl.h>
-
-#define LIKELY(exp)   __builtin_expect(!!(exp), 1)
-#define UNLIKELY(exp) __builtin_expect(!!(exp), 0)
-
-extern "C" {
-
-#include <fcntl.h>
-#include <time.h>
-#include <pthread.h>
-#include <stdio.h>
-#include <string.h>
-#include <unistd.h>
-#include <termios.h>
-#include <assert.h>
-#include <stdlib.h>
-#include <ctype.h>
-#include <signal.h>
-#include <errno.h>
-#include <sys/mman.h>
-#include <sys/time.h>
-#include <stdlib.h>
-
-#include <media/msm_camera.h>
-
-#include <camera.h>
-#include <camframe.h>
-#include <jpeg_encoder.h>
-
-#define THUMBNAIL_WIDTH        512
-#define THUMBNAIL_HEIGHT       384
-#define THUMBNAIL_WIDTH_STR   "512"
-#define THUMBNAIL_HEIGHT_STR  "384"
-#define DEFAULT_PICTURE_WIDTH  2048 // 1280
-#define DEFAULT_PICTURE_HEIGHT 1536 // 768
-#define THUMBNAIL_BUFFER_SIZE (THUMBNAIL_WIDTH * THUMBNAIL_HEIGHT * 3/2)
-
-#define DEFAULT_PREVIEW_SETTING 2 // HVGA
-#define PREVIEW_SIZE_COUNT (sizeof(preview_sizes)/sizeof(preview_size_type))
-
-#define NOT_FOUND -1
-
-#if DLOPEN_LIBMMCAMERA
-#include <dlfcn.h>
-
-void* (*LINK_cam_conf)(void *data);
-void* (*LINK_cam_frame)(void *data);
-bool  (*LINK_jpeg_encoder_init)();
-void  (*LINK_jpeg_encoder_join)();
-bool  (*LINK_jpeg_encoder_encode)(const cam_ctrl_dimension_t *dimen,
-                                  const uint8_t *thumbnailbuf, int thumbnailfd,
-                                  const uint8_t *snapshotbuf, int snapshotfd,
-                                  common_crop_t *scaling_parms);
-int  (*LINK_camframe_terminate)(void);
-int8_t (*LINK_jpeg_encoder_setMainImageQuality)(uint32_t quality);
-int8_t (*LINK_jpeg_encoder_setThumbnailQuality)(uint32_t quality);
-int8_t (*LINK_jpeg_encoder_setRotation)(uint32_t rotation);
-int8_t (*LINK_jpeg_encoder_setLocation)(const camera_position_type *location);
-// callbacks
-void  (**LINK_mmcamera_camframe_callback)(struct msm_frame *frame);
-void  (**LINK_mmcamera_jpegfragment_callback)(uint8_t *buff_ptr,
-                                              uint32_t buff_size);
-void  (**LINK_mmcamera_jpeg_callback)(jpeg_event_t status);
-void  (**LINK_mmcamera_shutter_callback)();
-#else
-#define LINK_cam_conf cam_conf
-#define LINK_cam_frame cam_frame
-#define LINK_jpeg_encoder_init jpeg_encoder_init
-#define LINK_jpeg_encoder_join jpeg_encoder_join
-#define LINK_jpeg_encoder_encode jpeg_encoder_encode
-#define LINK_camframe_terminate camframe_terminate
-#define LINK_jpeg_encoder_setMainImageQuality jpeg_encoder_setMainImageQuality
-#define LINK_jpeg_encoder_setThumbnailQuality jpeg_encoder_setThumbnailQuality
-#define LINK_jpeg_encoder_setRotation jpeg_encoder_setRotation
-#define LINK_jpeg_encoder_setLocation jpeg_encoder_setLocation
-extern void (*mmcamera_camframe_callback)(struct msm_frame *frame);
-extern void (*mmcamera_jpegfragment_callback)(uint8_t *buff_ptr,
-                                      uint32_t buff_size);
-extern void (*mmcamera_jpeg_callback)(jpeg_event_t status);
-extern void (*mmcamera_shutter_callback)();
-#endif
-
-} // extern "C"
-
-struct preview_size_type {
-    int width;
-    int height;
-};
-
-static preview_size_type preview_sizes[] = {
-    { 800, 480 }, // WVGA
-    { 640, 480 }, // VGA
-    { 480, 320 }, // HVGA
-    { 384, 288 },
-    { 352, 288 }, // CIF
-    { 320, 240 }, // QVGA
-    { 240, 160 }, // SQVGA
-    { 176, 144 }, // QCIF
-};
-
-static int attr_lookup(const struct str_map *const arr, const char *name)
-{
-    if (name) {
-        const struct str_map *trav = arr;
-        while (trav->desc) {
-            if (!strcmp(trav->desc, name))
-                return trav->val;
-            trav++;
-        }
-    }
-    return NOT_FOUND;
-}
-
-#define INIT_VALUES_FOR(parm) do {                               \
-    if (!parm##_values) {                                        \
-        parm##_values = (char *)malloc(sizeof(parm)/             \
-                                       sizeof(parm[0])*30);      \
-        char *ptr = parm##_values;                               \
-        const str_map *trav;                                     \
-        for (trav = parm; trav->desc; trav++) {                  \
-            int len = strlen(trav->desc);                        \
-            strcpy(ptr, trav->desc);                             \
-            ptr += len;                                          \
-            *ptr++ = ',';                                        \
-        }                                                        \
-        *--ptr = 0;                                              \
-    }                                                            \
-} while(0)
-
-// from aeecamera.h
-static const str_map whitebalance[] = {
-    { "auto",         CAMERA_WB_AUTO },
-    { "incandescent", CAMERA_WB_INCANDESCENT },
-    { "florescent",   CAMERA_WB_FLUORESCENT },
-    { "daylight",     CAMERA_WB_DAYLIGHT },
-    { "cloudy",       CAMERA_WB_CLOUDY_DAYLIGHT },
-    { "twilight",     CAMERA_WB_TWILIGHT },
-    { "shade",        CAMERA_WB_SHADE },
-    { NULL, 0 }
-};
-static char *whitebalance_values;
-
-// from camera_effect_t
-static const str_map effect[] = {
-    { "none",       CAMERA_EFFECT_OFF },  /* This list must match aeecamera.h */
-    { "mono",       CAMERA_EFFECT_MONO },
-    { "negative",   CAMERA_EFFECT_NEGATIVE },
-    { "solarize",   CAMERA_EFFECT_SOLARIZE },
-    { "sepia",      CAMERA_EFFECT_SEPIA },
-    { "posterize",  CAMERA_EFFECT_POSTERIZE },
-    { "whiteboard", CAMERA_EFFECT_WHITEBOARD },
-    { "blackboard", CAMERA_EFFECT_BLACKBOARD },
-    { "aqua",       CAMERA_EFFECT_AQUA },
-    { NULL, 0 }
-};
-static char *effect_values;
-
-// from qcamera/common/camera.h
-static const str_map antibanding[] = {
-    { "off",  CAMERA_ANTIBANDING_OFF },
-    { NULL, 0 }
-};
-static char *antibanding_values;
-
-// round to the next power of two
-static inline unsigned clp2(unsigned x)
-{
-    x = x - 1;
-    x = x | (x >> 1);
-    x = x | (x >> 2);
-    x = x | (x >> 4);
-    x = x | (x >> 8);
-    x = x | (x >>16);
-    return x + 1;
-}
-
-namespace android {
-
-static Mutex singleton_lock;
-static bool singleton_releasing;
-static Condition singleton_wait;
-
-static void receive_camframe_callback(struct msm_frame *frame);
-static void receive_jpeg_fragment_callback(uint8_t *buff_ptr, uint32_t buff_size);
-static void receive_jpeg_callback(jpeg_event_t status);
-static void receive_shutter_callback();
-
-QualcommCameraHardware::QualcommCameraHardware()
-    : mParameters(),
-      mPreviewHeight(-1),
-      mPreviewWidth(-1),
-      mRawHeight(-1),
-      mRawWidth(-1),
-      mCameraRunning(false),
-      mPreviewInitialized(false),
-      mFrameThreadRunning(false),
-      mSnapshotThreadRunning(false),
-      mReleasedRecordingFrame(false),
-      mShutterCallback(0),
-      mRawPictureCallback(0),
-      mJpegPictureCallback(0),
-      mPictureCallbackCookie(0),
-      mAutoFocusCallback(0),
-      mAutoFocusCallbackCookie(0),
-      mPreviewCallback(0),
-      mPreviewCallbackCookie(0),
-      mRecordingCallback(0),
-      mRecordingCallbackCookie(0),
-      mPreviewFrameSize(0),
-      mRawSize(0),
-      mCameraControlFd(-1),
-      mAutoFocusThreadRunning(false),
-      mAutoFocusFd(-1),
-      mInPreviewCallback(false)
-{
-    memset(&mDimension, 0, sizeof(mDimension));
-    memset(&mCrop, 0, sizeof(mCrop));
-    LOGV("constructor EX");
-}
-
-void QualcommCameraHardware::initDefaultParameters()
-{
-    CameraParameters p;
-
-    LOGV("initDefaultParameters E");
-
-    preview_size_type *ps = &preview_sizes[DEFAULT_PREVIEW_SETTING];
-    p.setPreviewSize(ps->width, ps->height);
-    p.setPreviewFrameRate(15);
-    p.setPreviewFormat("yuv420sp"); // informative
-    p.setPictureFormat("jpeg"); // informative
-
-    p.set("jpeg-quality", "100"); // maximum quality
-    p.set("jpeg-thumbnail-width", THUMBNAIL_WIDTH_STR); // informative
-    p.set("jpeg-thumbnail-height", THUMBNAIL_HEIGHT_STR); // informative
-    p.set("jpeg-thumbnail-quality", "90");
-
-    p.setPictureSize(DEFAULT_PICTURE_WIDTH, DEFAULT_PICTURE_HEIGHT);
-    p.set("antibanding", "off");
-    p.set("effect", "none");
-    p.set("whitebalance", "auto");
-
-#if 0
-    p.set("gps-timestamp", "1199145600"); // Jan 1, 2008, 00:00:00
-    p.set("gps-latitude", "37.736071"); // A little house in San Francisco
-    p.set("gps-longitude", "-122.441983");
-    p.set("gps-altitude", "21"); // meters
-#endif
-
-    // This will happen only one in the lifetime of the mediaserver process.
-    // We do not free the _values arrays when we destroy the camera object.
-    INIT_VALUES_FOR(antibanding);
-    INIT_VALUES_FOR(effect);
-    INIT_VALUES_FOR(whitebalance);
-
-    p.set("antibanding-values", antibanding_values);
-    p.set("effect-values", effect_values);
-    p.set("whitebalance-values", whitebalance_values);
-    p.set("picture-size-values", "2048x1536,1600x1200,1024x768");
-
-    if (setParameters(p) != NO_ERROR) {
-        LOGE("Failed to set default parameters?!");
-    }
-
-    LOGV("initDefaultParameters X");
-}
-
-#define ROUND_TO_PAGE(x)  (((x)+0xfff)&~0xfff)
-
-void QualcommCameraHardware::startCamera()
-{
-    LOGV("startCamera E");
-#if DLOPEN_LIBMMCAMERA
-    libmmcamera = ::dlopen("libqcamera.so", RTLD_NOW);
-    LOGV("loading libqcamera at %p", libmmcamera);
-    if (!libmmcamera) {
-        LOGE("FATAL ERROR: could not dlopen libqcamera.so: %s", dlerror());
-        return;
-    }
-
-    *(void **)&LINK_cam_frame =
-        ::dlsym(libmmcamera, "cam_frame");
-    *(void **)&LINK_camframe_terminate =
-        ::dlsym(libmmcamera, "camframe_terminate");
-
-    *(void **)&LINK_jpeg_encoder_init =
-        ::dlsym(libmmcamera, "jpeg_encoder_init");
-
-    *(void **)&LINK_jpeg_encoder_encode =
-        ::dlsym(libmmcamera, "jpeg_encoder_encode");
-
-    *(void **)&LINK_jpeg_encoder_join =
-        ::dlsym(libmmcamera, "jpeg_encoder_join");
-
-    *(void **)&LINK_mmcamera_camframe_callback =
-        ::dlsym(libmmcamera, "mmcamera_camframe_callback");
-
-    *LINK_mmcamera_camframe_callback = receive_camframe_callback;
-
-    *(void **)&LINK_mmcamera_jpegfragment_callback =
-        ::dlsym(libmmcamera, "mmcamera_jpegfragment_callback");
-
-    *LINK_mmcamera_jpegfragment_callback = receive_jpeg_fragment_callback;
-
-    *(void **)&LINK_mmcamera_jpeg_callback =
-        ::dlsym(libmmcamera, "mmcamera_jpeg_callback");
-
-    *LINK_mmcamera_jpeg_callback = receive_jpeg_callback;
-
-    *(void **)&LINK_mmcamera_shutter_callback =
-        ::dlsym(libmmcamera, "mmcamera_shutter_callback");
-
-    *LINK_mmcamera_shutter_callback = receive_shutter_callback;
-
-    *(void**)&LINK_jpeg_encoder_setMainImageQuality =
-        ::dlsym(libmmcamera, "jpeg_encoder_setMainImageQuality");
-
-    *(void**)&LINK_jpeg_encoder_setThumbnailQuality =
-        ::dlsym(libmmcamera, "jpeg_encoder_setThumbnailQuality");
-
-    *(void**)&LINK_jpeg_encoder_setRotation =
-        ::dlsym(libmmcamera, "jpeg_encoder_setRotation");
-
-    *(void**)&LINK_jpeg_encoder_setLocation =
-        ::dlsym(libmmcamera, "jpeg_encoder_setLocation");
-
-    *(void **)&LINK_cam_conf =
-        ::dlsym(libmmcamera, "cam_conf");
-#else
-    mmcamera_camframe_callback = receive_camframe_callback;
-    mmcamera_jpegfragment_callback = receive_jpeg_fragment_callback;
-    mmcamera_jpeg_callback = receive_jpeg_callback;
-    mmcamera_shutter_callback = receive_shutter_callback;
-#endif // DLOPEN_LIBMMCAMERA
-
-    /* The control thread is in libcamera itself. */
-    mCameraControlFd = open(MSM_CAMERA_CONTROL, O_RDWR);
-    if (mCameraControlFd < 0) {
-        LOGE("startCamera X: %s open failed: %s!",
-             MSM_CAMERA_CONTROL,
-             strerror(errno));
-        return;
-    }
-
-    pthread_create(&mCamConfigThread, NULL,
-                   LINK_cam_conf, NULL);
-
-    LOGV("startCamera X");
-}
-
-status_t QualcommCameraHardware::dump(int fd,
-                                      const Vector<String16>& args) const
-{
-    const size_t SIZE = 256;
-    char buffer[SIZE];
-    String8 result;
-
-    // Dump internal primitives.
-    result.append("QualcommCameraHardware::dump");
-    snprintf(buffer, 255, "preview width(%d) x height (%d)\n",
-             mPreviewWidth, mPreviewHeight);
-    result.append(buffer);
-    snprintf(buffer, 255, "raw width(%d) x height (%d)\n",
-             mRawWidth, mRawHeight);
-    result.append(buffer);
-    snprintf(buffer, 255,
-             "preview frame size(%d), raw size (%d), jpeg size (%d) "
-             "and jpeg max size (%d)\n", mPreviewFrameSize, mRawSize,
-             mJpegSize, mJpegMaxSize);
-    result.append(buffer);
-    write(fd, result.string(), result.size());
-
-    // Dump internal objects.
-    if (mPreviewHeap != 0) {
-        mPreviewHeap->dump(fd, args);
-    }
-    if (mRawHeap != 0) {
-        mRawHeap->dump(fd, args);
-    }
-    if (mJpegHeap != 0) {
-        mJpegHeap->dump(fd, args);
-    }
-    mParameters.dump(fd, args);
-    return NO_ERROR;
-}
-
-static bool native_set_afmode(int camfd, isp3a_af_mode_t af_type)
-{
-    int rc;
-    struct msm_ctrl_cmd ctrlCmd;
-
-    ctrlCmd.timeout_ms = 5000;
-    ctrlCmd.type = CAMERA_SET_PARM_AUTO_FOCUS;
-    ctrlCmd.length = sizeof(af_type);
-    ctrlCmd.value = &af_type;
-    ctrlCmd.resp_fd = camfd; // FIXME: this will be put in by the kernel
-
-    if ((rc = ioctl(camfd, MSM_CAM_IOCTL_CTRL_COMMAND, &ctrlCmd)) < 0)
-        LOGE("native_set_afmode: ioctl fd %d error %s\n",
-             camfd,
-             strerror(errno));
-
-    LOGV("native_set_afmode: ctrlCmd.status == %d\n", ctrlCmd.status);
-    return rc >= 0 && ctrlCmd.status == CAMERA_EXIT_CB_DONE;
-}
-
-static bool native_cancel_afmode(int camfd, int af_fd)
-{
-    int rc;
-    struct msm_ctrl_cmd ctrlCmd;
-
-    ctrlCmd.timeout_ms = 5000;
-    ctrlCmd.type = CAMERA_AUTO_FOCUS_CANCEL;
-    ctrlCmd.length = 0;
-    ctrlCmd.resp_fd = af_fd;
-
-    if ((rc = ioctl(camfd, MSM_CAM_IOCTL_CTRL_COMMAND_2, &ctrlCmd)) < 0)
-        LOGE("native_cancel_afmode: ioctl fd %d error %s\n",
-             camfd,
-             strerror(errno));
-    return rc >= 0;
-}
-
-static bool native_start_preview(int camfd)
-{
-    struct msm_ctrl_cmd ctrlCmd;
-
-    ctrlCmd.timeout_ms = 5000;
-    ctrlCmd.type       = CAMERA_START_PREVIEW;
-    ctrlCmd.length     = 0;
-    ctrlCmd.resp_fd    = camfd; // FIXME: this will be put in by the kernel
-
-    if (ioctl(camfd, MSM_CAM_IOCTL_CTRL_COMMAND, &ctrlCmd) < 0) {
-        LOGE("native_start_preview: MSM_CAM_IOCTL_CTRL_COMMAND fd %d error %s",
-             camfd,
-             strerror(errno));
-        return false;
-    }
-
-    return true;
-}
-
-static bool native_get_picture (int camfd, common_crop_t *crop)
-{
-    struct msm_ctrl_cmd ctrlCmd;
-
-    ctrlCmd.timeout_ms = 5000;
-    ctrlCmd.length     = sizeof(common_crop_t);
-    ctrlCmd.value      = crop;
-
-    if(ioctl(camfd, MSM_CAM_IOCTL_GET_PICTURE, &ctrlCmd) < 0) {
-        LOGE("native_get_picture: MSM_CAM_IOCTL_GET_PICTURE fd %d error %s",
-             camfd,
-             strerror(errno));
-        return false;
-    }
-
-    LOGV("crop: in1_w %d", crop->in1_w);
-    LOGV("crop: in1_h %d", crop->in1_h);
-    LOGV("crop: out1_w %d", crop->out1_w);
-    LOGV("crop: out1_h %d", crop->out1_h);
-
-    LOGV("crop: in2_w %d", crop->in2_w);
-    LOGV("crop: in2_h %d", crop->in2_h);
-    LOGV("crop: out2_w %d", crop->out2_w);
-    LOGV("crop: out2_h %d", crop->out2_h);
-
-    LOGV("crop: update %d", crop->update_flag);
-
-    return true;
-}
-
-static bool native_stop_preview(int camfd)
-{
-    struct msm_ctrl_cmd ctrlCmd;
-    ctrlCmd.timeout_ms = 5000;
-    ctrlCmd.type       = CAMERA_STOP_PREVIEW;
-    ctrlCmd.length     = 0;
-    ctrlCmd.resp_fd    = camfd; // FIXME: this will be put in by the kernel
-
-    if(ioctl(camfd, MSM_CAM_IOCTL_CTRL_COMMAND, &ctrlCmd) < 0) {
-        LOGE("native_stop_preview: ioctl fd %d error %s",
-             camfd,
-             strerror(errno));
-        return false;
-    }
-
-    return true;
-}
-
-static bool native_start_snapshot(int camfd)
-{
-    struct msm_ctrl_cmd ctrlCmd;
-
-    ctrlCmd.timeout_ms = 5000;
-    ctrlCmd.type       = CAMERA_START_SNAPSHOT;
-    ctrlCmd.length     = 0;
-    ctrlCmd.resp_fd    = camfd; // FIXME: this will be put in by the kernel
-
-    if(ioctl(camfd, MSM_CAM_IOCTL_CTRL_COMMAND, &ctrlCmd) < 0) {
-        LOGE("native_start_snapshot: ioctl fd %d error %s",
-             camfd,
-             strerror(errno));
-        return false;
-    }
-
-    return true;
-}
-
-static bool native_stop_snapshot (int camfd)
-{
-    struct msm_ctrl_cmd ctrlCmd;
-
-    ctrlCmd.timeout_ms = 5000;
-    ctrlCmd.type       = CAMERA_STOP_SNAPSHOT;
-    ctrlCmd.length     = 0;
-    ctrlCmd.resp_fd    = camfd; // FIXME: this will be put in by the kernel
-
-    if (ioctl(camfd, MSM_CAM_IOCTL_CTRL_COMMAND, &ctrlCmd) < 0) {
-        LOGE("native_stop_snapshot: ioctl fd %d error %s",
-             camfd,
-             strerror(errno));
-        return false;
-    }
-
-    return true;
-}
-
-bool QualcommCameraHardware::native_jpeg_encode(void)
-{
-    int jpeg_quality = mParameters.getInt("jpeg-quality");
-    if (jpeg_quality >= 0) {
-        LOGV("native_jpeg_encode, current jpeg main img quality =%d",
-             jpeg_quality);
-        if(!LINK_jpeg_encoder_setMainImageQuality(jpeg_quality)) {
-            LOGE("native_jpeg_encode set jpeg-quality failed");
-            return false;
-        }
-    }
-
-    int thumbnail_quality = mParameters.getInt("jpeg-thumbnail-quality");
-    if (thumbnail_quality >= 0) {
-        LOGV("native_jpeg_encode, current jpeg thumbnail quality =%d",
-             thumbnail_quality);
-        if(!LINK_jpeg_encoder_setThumbnailQuality(thumbnail_quality)) {
-            LOGE("native_jpeg_encode set thumbnail-quality failed");
-            return false;
-        }
-    }
-
-    int rotation = mParameters.getInt("rotation");
-    if (rotation >= 0) {
-        LOGV("native_jpeg_encode, rotation = %d", rotation);
-        if(!LINK_jpeg_encoder_setRotation(rotation)) {
-            LOGE("native_jpeg_encode set rotation failed");
-            return false;
-        }
-    }
-
-    jpeg_set_location();
-
-    if (!LINK_jpeg_encoder_encode(&mDimension,
-                                  (uint8_t *)mThumbnailHeap->mHeap->base(),
-                                  mThumbnailHeap->mHeap->getHeapID(),
-                                  (uint8_t *)mRawHeap->mHeap->base(),
-                                  mRawHeap->mHeap->getHeapID(),
-                                  &mCrop)) {
-        LOGE("native_jpeg_encode: jpeg_encoder_encode failed.");
-        return false;
-    }
-    return true;
-}
-
-bool QualcommCameraHardware::native_set_dimension(cam_ctrl_dimension_t *value)
-{
-    return native_set_parm(CAMERA_SET_PARM_DIMENSION,
-                           sizeof(cam_ctrl_dimension_t), value);
-}
-
-bool QualcommCameraHardware::native_set_parm(
-    cam_ctrl_type type, uint16_t length, void *value)
-{
-    int rc = true;
-    struct msm_ctrl_cmd ctrlCmd;
-
-    ctrlCmd.timeout_ms = 5000;
-    ctrlCmd.type       = (uint16_t)type;
-    ctrlCmd.length     = length;
-    // FIXME: this will be put in by the kernel
-    ctrlCmd.resp_fd    = mCameraControlFd;
-    ctrlCmd.value = value;
-
-    LOGV("native_set_parm. camfd=%d, type=%d, length=%d",
-         mCameraControlFd, type, length);
-    rc = ioctl(mCameraControlFd, MSM_CAM_IOCTL_CTRL_COMMAND, &ctrlCmd);
-    if(rc < 0 || ctrlCmd.status != CAM_CTRL_SUCCESS) {
-        LOGE("ioctl error. camfd=%d, type=%d, length=%d, rc=%d, ctrlCmd.status=%d, %s",
-             mCameraControlFd, type, length, rc, ctrlCmd.status, strerror(errno));
-        return false;
-    }
-    return true;
-}
-
-void QualcommCameraHardware::jpeg_set_location()
-{
-    bool encode_location = true;
-    camera_position_type pt;
-
-#define PARSE_LOCATION(what,type,fmt,desc) do {                                \
-        pt.what = 0;                                                           \
-        const char *what##_str = mParameters.get("gps-"#what);                 \
-        LOGV("GPS PARM %s --> [%s]", "gps-"#what, what##_str);                 \
-        if (what##_str) {                                                      \
-            type what = 0;                                                     \
-            if (sscanf(what##_str, fmt, &what) == 1)                           \
-                pt.what = what;                                                \
-            else {                                                             \
-                LOGE("GPS " #what " %s could not"                              \
-                     " be parsed as a " #desc, what##_str);                    \
-                encode_location = false;                                       \
-            }                                                                  \
-        }                                                                      \
-        else {                                                                 \
-            LOGV("GPS " #what " not specified: "                               \
-                 "defaulting to zero in EXIF header.");                        \
-            encode_location = false;                                           \
-       }                                                                       \
-    } while(0)
-
-    PARSE_LOCATION(timestamp, long, "%ld", "long");
-    if (!pt.timestamp) pt.timestamp = time(NULL);
-    PARSE_LOCATION(altitude, short, "%hd", "short");
-    PARSE_LOCATION(latitude, double, "%lf", "double float");
-    PARSE_LOCATION(longitude, double, "%lf", "double float");
-
-#undef PARSE_LOCATION
-
-    if (encode_location) {
-        LOGD("setting image location ALT %d LAT %lf LON %lf",
-             pt.altitude, pt.latitude, pt.longitude);
-        if (!LINK_jpeg_encoder_setLocation(&pt)) {
-            LOGE("jpeg_set_location: LINK_jpeg_encoder_setLocation failed.");
-        }
-    }
-    else LOGV("not setting image location");
-}
-
-void QualcommCameraHardware::runFrameThread(void *data)
-{
-    LOGV("runFrameThread E");
-
-    int cnt;
-
-#if DLOPEN_LIBMMCAMERA
-    // We need to maintain a reference to libqcamera.so for the duration of the
-    // frame thread, because we do not know when it will exit relative to the
-    // lifetime of this object.  We do not want to dlclose() libqcamera while
-    // LINK_cam_frame is still running.
-    void *libhandle = ::dlopen("libqcamera.so", RTLD_NOW);
-    LOGV("FRAME: loading libqcamera at %p", libhandle);
-    if (!libhandle) {
-        LOGE("FATAL ERROR: could not dlopen libqcamera.so: %s", dlerror());
-    }
-    if (libhandle)
-#endif
-    {
-        LINK_cam_frame(data);
-    }
-
-    mPreviewHeap.clear();
-
-#if DLOPEN_LIBMMCAMERA
-    if (libhandle) {
-        ::dlclose(libhandle);
-        LOGV("FRAME: dlclose(libqcamera)");
-    }
-#endif
-
-    mFrameThreadWaitLock.lock();
-    mFrameThreadRunning = false;
-    mFrameThreadWait.signal();
-    mFrameThreadWaitLock.unlock();
-
-    LOGV("runFrameThread X");
-}
-
-void *frame_thread(void *user)
-{
-    LOGD("frame_thread E");
-    sp<QualcommCameraHardware> obj = QualcommCameraHardware::getInstance();
-    if (obj != 0) {
-        obj->runFrameThread(user);
-    }
-    else LOGW("not starting frame thread: the object went away!");
-    LOGD("frame_thread X");
-    return NULL;
-}
-
-bool QualcommCameraHardware::initPreview()
-{
-    // See comments in deinitPreview() for why we have to wait for the frame
-    // thread here, and why we can't use pthread_join().
-    LOGI("initPreview E: preview size=%dx%d", mPreviewWidth, mPreviewHeight);
-    mFrameThreadWaitLock.lock();
-    while (mFrameThreadRunning) {
-        LOGV("initPreview: waiting for old frame thread to complete.");
-        mFrameThreadWait.wait(mFrameThreadWaitLock);
-        LOGV("initPreview: old frame thread completed.");
-    }
-    mFrameThreadWaitLock.unlock();
-
-    mSnapshotThreadWaitLock.lock();
-    while (mSnapshotThreadRunning) {
-        LOGV("initPreview: waiting for old snapshot thread to complete.");
-        mSnapshotThreadWait.wait(mSnapshotThreadWaitLock);
-        LOGV("initPreview: old snapshot thread completed.");
-    }
-    mSnapshotThreadWaitLock.unlock();
-
-    int cnt = 0;
-    mPreviewFrameSize = mPreviewWidth * mPreviewHeight * 3/2;
-    mPreviewHeap = new PmemPool("/dev/pmem_adsp",
-                                mCameraControlFd,
-                                MSM_PMEM_OUTPUT2,
-                                mPreviewFrameSize,
-                                kPreviewBufferCount,
-                                mPreviewFrameSize,
-                                0,
-                                "preview");
-
-    if (!mPreviewHeap->initialized()) {
-        mPreviewHeap.clear();
-        LOGE("initPreview X: could not initialize preview heap.");
-        return false;
-    }
-
-    mDimension.picture_width  = DEFAULT_PICTURE_WIDTH;
-    mDimension.picture_height = DEFAULT_PICTURE_HEIGHT;
-
-    bool ret = native_set_dimension(&mDimension);
-
-    if (ret) {
-        for (cnt = 0; cnt < kPreviewBufferCount; cnt++) {
-            frames[cnt].fd = mPreviewHeap->mHeap->getHeapID();
-            frames[cnt].buffer =
-                (uint32_t)mPreviewHeap->mHeap->base() + mPreviewFrameSize * cnt;
-            frames[cnt].y_off = 0;
-            frames[cnt].cbcr_off = mPreviewWidth * mPreviewHeight;
-            frames[cnt].path = MSM_FRAME_ENC;
-        }
-
-        mFrameThreadWaitLock.lock();
-        pthread_attr_t attr;
-        pthread_attr_init(&attr);
-        pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
-        mFrameThreadRunning = !pthread_create(&mFrameThread,
-                                              &attr,
-                                              frame_thread,
-                                              &frames[kPreviewBufferCount-1]);
-        ret = mFrameThreadRunning;
-        mFrameThreadWaitLock.unlock();
-    }
-
-    LOGV("initPreview X: %d", ret);
-    return ret;
-}
-
-void QualcommCameraHardware::deinitPreview(void)
-{
-    LOGI("deinitPreview E");
-
-    // When we call deinitPreview(), we signal to the frame thread that it
-    // needs to exit, but we DO NOT WAIT for it to complete here.  The problem
-    // is that deinitPreview is sometimes called from the frame-thread's
-    // callback, when the refcount on the Camera client reaches zero.  If we
-    // called pthread_join(), we would deadlock.  So, we just call
-    // LINK_camframe_terminate() in deinitPreview(), which makes sure that
-    // after the preview callback returns, the camframe thread will exit.  We
-    // could call pthread_join() in initPreview() to join the last frame
-    // thread.  However, we would also have to call pthread_join() in release
-    // as well, shortly before we destoy the object; this would cause the same
-    // deadlock, since release(), like deinitPreview(), may also be called from
-    // the frame-thread's callback.  This we have to make the frame thread
-    // detached, and use a separate mechanism to wait for it to complete.
-
-    if (LINK_camframe_terminate() < 0)
-        LOGE("failed to stop the camframe thread: %s",
-             strerror(errno));
-    LOGI("deinitPreview X");
-}
-
-bool QualcommCameraHardware::initRaw(bool initJpegHeap)
-{
-    LOGV("initRaw E: picture size=%dx%d",
-         mRawWidth, mRawHeight);
-
-    mDimension.picture_width   = mRawWidth;
-    mDimension.picture_height  = mRawHeight;
-    mRawSize = mRawWidth * mRawHeight * 3 / 2;
-    mJpegMaxSize = mRawWidth * mRawHeight * 3 / 2;
-
-    if(!native_set_dimension(&mDimension)) {
-        LOGE("initRaw X: failed to set dimension");
-        return false;
-    }
-
-    if (mJpegHeap != NULL) {
-        LOGV("initRaw: clearing old mJpegHeap.");
-        mJpegHeap.clear();
-    }
-
-    // Snapshot
-
-    LOGV("initRaw: initializing mRawHeap.");
-    mRawHeap =
-        new PmemPool("/dev/pmem_camera",
-                     mCameraControlFd,
-                     MSM_PMEM_MAINIMG,
-                     mJpegMaxSize,
-                     kRawBufferCount,
-                     mRawSize,
-                     0,
-                     "snapshot camera");
-
-    if (!mRawHeap->initialized()) {
-        LOGE("initRaw X failed with pmem_camera, trying with pmem_adsp");
-        mRawHeap =
-            new PmemPool("/dev/pmem_adsp",
-                         mCameraControlFd,
-                         MSM_PMEM_MAINIMG,
-                         mJpegMaxSize,
-                         kRawBufferCount,
-                         mRawSize,
-                         0,
-                         "snapshot camera");
-        if (!mRawHeap->initialized()) {
-            mRawHeap.clear();
-            LOGE("initRaw X: error initializing mRawHeap");
-            return false;
-        }
-    }
-
-    LOGV("do_mmap snapshot pbuf = %p, pmem_fd = %d",
-         (uint8_t *)mRawHeap->mHeap->base(), mRawHeap->mHeap->getHeapID());
-
-    // Jpeg
-
-    if (initJpegHeap) {
-        LOGV("initRaw: initializing mJpegHeap.");
-        mJpegHeap =
-            new AshmemPool(mJpegMaxSize,
-                           kJpegBufferCount,
-                           0, // we do not know how big the picture wil be
-                           0,
-                           "jpeg");
-
-        if (!mJpegHeap->initialized()) {
-            mJpegHeap.clear();
-            mRawHeap.clear();
-            LOGE("initRaw X failed: error initializing mJpegHeap.");
-            return false;
-        }
-
-        // Thumbnails
-
-        mThumbnailHeap =
-            new PmemPool("/dev/pmem_adsp",
-                         mCameraControlFd,
-                         MSM_PMEM_THUMBAIL,
-                         THUMBNAIL_BUFFER_SIZE,
-                         1,
-                         THUMBNAIL_BUFFER_SIZE,
-                         0,
-                         "thumbnail");
-
-        if (!mThumbnailHeap->initialized()) {
-            mThumbnailHeap.clear();
-            mJpegHeap.clear();
-            mRawHeap.clear();
-            LOGE("initRaw X failed: error initializing mThumbnailHeap.");
-            return false;
-        }
-    }
-
-    LOGV("initRaw X");
-    return true;
-}
-
-void QualcommCameraHardware::deinitRaw()
-{
-    LOGV("deinitRaw E");
-
-    mThumbnailHeap.clear();
-    mJpegHeap.clear();
-    mRawHeap.clear();
-
-    LOGV("deinitRaw X");
-}
-
-void QualcommCameraHardware::release()
-{
-    LOGD("release E");
-    Mutex::Autolock l(&mLock);
-
-#if DLOPEN_LIBMMCAMERA
-    if (libmmcamera == NULL) {
-        LOGE("ERROR: multiple release!");
-        return;
-    }
-#else
-#warning "Cannot detect multiple release when not dlopen()ing libqcamera!"
-#endif
-
-    int cnt, rc;
-    struct msm_ctrl_cmd ctrlCmd;
-
-    if (mCameraRunning) {
-        if(mRecordingCallback != NULL) {
-            mRecordFrameLock.lock();
-            mReleasedRecordingFrame = true;
-            mRecordWait.signal();
-            mRecordFrameLock.unlock();
-        }
-        stopPreviewInternal();
-    }
-
-    LINK_jpeg_encoder_join();
-    deinitRaw();
-
-    ctrlCmd.timeout_ms = 5000;
-    ctrlCmd.length = 0;
-    ctrlCmd.type = (uint16_t)CAMERA_EXIT;
-    ctrlCmd.resp_fd = mCameraControlFd; // FIXME: this will be put in by the kernel
-    if (ioctl(mCameraControlFd, MSM_CAM_IOCTL_CTRL_COMMAND, &ctrlCmd) < 0)
-        LOGE("ioctl CAMERA_EXIT fd %d error %s",
-             mCameraControlFd, strerror(errno));
-    rc = pthread_join(mCamConfigThread, NULL);
-    if (rc)
-        LOGE("config_thread exit failure: %s", strerror(errno));
-    else
-        LOGV("pthread_join succeeded on config_thread");
-
-    close(mCameraControlFd);
-    mCameraControlFd = -1;
-
-#if DLOPEN_LIBMMCAMERA
-    if (libmmcamera) {
-        ::dlclose(libmmcamera);
-        LOGV("dlclose(libqcamera)");
-        libmmcamera = NULL;
-    }
-#endif
-
-    Mutex::Autolock lock(&singleton_lock);
-    singleton_releasing = true;
-
-    LOGD("release X");
-}
-
-QualcommCameraHardware::~QualcommCameraHardware()
-{
-    LOGD("~QualcommCameraHardware E");
-    Mutex::Autolock lock(&singleton_lock);
-    singleton.clear();
-    singleton_releasing = false;
-    singleton_wait.signal();
-    LOGD("~QualcommCameraHardware X");
-}
-
-sp<IMemoryHeap> QualcommCameraHardware::getRawHeap() const
-{
-    LOGV("getRawHeap");
-    return mRawHeap != NULL ? mRawHeap->mHeap : NULL;
-}
-
-sp<IMemoryHeap> QualcommCameraHardware::getPreviewHeap() const
-{
-    LOGV("getPreviewHeap");
-    return mPreviewHeap != NULL ? mPreviewHeap->mHeap : NULL;
-}
-
-status_t QualcommCameraHardware::startPreviewInternal()
-{
-    if(mCameraRunning) {
-        LOGV("startPreview X: preview already running.");
-        return NO_ERROR;
-    }
-
-    if (!mPreviewInitialized) {
-        mPreviewInitialized = initPreview();
-        if (!mPreviewInitialized) {
-            LOGE("startPreview X initPreview failed.  Not starting preview.");
-            return UNKNOWN_ERROR;
-        }
-    }
-
-    mCameraRunning = native_start_preview(mCameraControlFd);
-    if(!mCameraRunning) {
-        deinitPreview();
-        mPreviewInitialized = false;
-        LOGE("startPreview X: native_start_preview failed!");
-        return UNKNOWN_ERROR;
-    }
-
-    LOGV("startPreview X");
-    return NO_ERROR;
-}
-
-status_t QualcommCameraHardware::startPreview(preview_callback cb, void *user)
-{
-    LOGV("startPreview E");
-    Mutex::Autolock l(&mLock);
-
-    {
-        Mutex::Autolock cbLock(&mCallbackLock);
-        mPreviewCallback = cb;
-        mPreviewCallbackCookie = user;
-    }
-
-    return startPreviewInternal();
-}
-
-void QualcommCameraHardware::stopPreviewInternal()
-{
-    LOGV("stopPreviewInternal E: %d", mCameraRunning);
-    if (mCameraRunning) {
-        // Cancel auto focus.
-        if (mAutoFocusCallback) {
-            {
-                Mutex::Autolock cbLock(&mCallbackLock);
-                mAutoFocusCallback = NULL;
-                mAutoFocusCallbackCookie = NULL;
-            }
-            cancelAutoFocus();
-        }
-
-        mCameraRunning = !native_stop_preview(mCameraControlFd);
-        if (!mCameraRunning && mPreviewInitialized) {
-            deinitPreview();
-            mPreviewInitialized = false;
-        }
-        else LOGE("stopPreviewInternal: failed to stop preview");
-    }
-    LOGV("stopPreviewInternal X: %d", mCameraRunning);
-}
-
-void QualcommCameraHardware::stopPreview()
-{
-    LOGV("stopPreview: E");
-    Mutex::Autolock l(&mLock);
-
-    {
-        Mutex::Autolock cbLock(&mCallbackLock);
-        mPreviewCallback = NULL;
-        mPreviewCallbackCookie = NULL;
-        if(mRecordingCallback != NULL)
-           return;
-    }
-
-    stopPreviewInternal();
-
-    LOGV("stopPreview: X");
-}
-
-void QualcommCameraHardware::runAutoFocus()
-{
-    mAutoFocusThreadLock.lock();
-    mAutoFocusFd = open(MSM_CAMERA_CONTROL, O_RDWR);
-    if (mAutoFocusFd < 0) {
-        LOGE("autofocus: cannot open %s: %s",
-             MSM_CAMERA_CONTROL,
-             strerror(errno));
-        mAutoFocusThreadRunning = false;
-        mAutoFocusThreadLock.unlock();
-        return;
-    }
-
-#if DLOPEN_LIBMMCAMERA
-    // We need to maintain a reference to libqcamera.so for the duration of the
-    // AF thread, because we do not know when it will exit relative to the
-    // lifetime of this object.  We do not want to dlclose() libqcamera while
-    // LINK_cam_frame is still running.
-    void *libhandle = ::dlopen("libqcamera.so", RTLD_NOW);
-    LOGV("AF: loading libqcamera at %p", libhandle);
-    if (!libhandle) {
-        LOGE("FATAL ERROR: could not dlopen libqcamera.so: %s", dlerror());
-        close(mAutoFocusFd);
-        mAutoFocusFd = -1;
-        mAutoFocusThreadRunning = false;
-        mAutoFocusThreadLock.unlock();
-        return;
-    }
-#endif
-
-    /* This will block until either AF completes or is cancelled. */
-    LOGV("af start (fd %d)", mAutoFocusFd);
-    bool status = native_set_afmode(mAutoFocusFd, AF_MODE_AUTO);
-    LOGV("af done: %d", (int)status);
-    mAutoFocusThreadRunning = false;
-    close(mAutoFocusFd);
-    mAutoFocusFd = -1;
-    mAutoFocusThreadLock.unlock();
-
-    mCallbackLock.lock();
-    autofocus_callback cb = mAutoFocusCallback;
-    void *data = mAutoFocusCallbackCookie;
-    mCallbackLock.unlock();
-    if (cb != NULL)
-        cb(status, data);
-
-    mCallbackLock.lock();
-    mAutoFocusCallback = NULL;
-    mAutoFocusCallbackCookie = NULL;
-    mCallbackLock.unlock();
-
-#if DLOPEN_LIBMMCAMERA
-    if (libhandle) {
-        ::dlclose(libhandle);
-        LOGV("AF: dlclose(libqcamera)");
-    }
-#endif
-}
-
-void QualcommCameraHardware::cancelAutoFocus()
-{
-    LOGV("cancelAutoFocus E");
-    native_cancel_afmode(mCameraControlFd, mAutoFocusFd);
-    LOGV("cancelAutoFocus X");
-}
-
-void *auto_focus_thread(void *user)
-{
-    LOGV("auto_focus_thread E");
-    sp<QualcommCameraHardware> obj = QualcommCameraHardware::getInstance();
-    if (obj != 0) {
-        obj->runAutoFocus();
-    }
-    else LOGW("not starting autofocus: the object went away!");
-    LOGV("auto_focus_thread X");
-    return NULL;
-}
-
-status_t QualcommCameraHardware::autoFocus(autofocus_callback af_cb,
-                                           void *user)
-{
-    LOGV("autoFocus E");
-    Mutex::Autolock l(&mLock);
-
-    if (mCameraControlFd < 0) {
-        LOGE("not starting autofocus: main control fd %d", mCameraControlFd);
-        return UNKNOWN_ERROR;
-    }
-
-    if (mAutoFocusCallback != NULL) {
-        LOGW("Auto focus is already in progress");
-        return mAutoFocusCallback == af_cb ? NO_ERROR : INVALID_OPERATION;
-    }
-
-    {
-        Mutex::Autolock cbl(&mCallbackLock);
-        mAutoFocusCallback = af_cb;
-        mAutoFocusCallbackCookie = user;
-    }
-
-    {
-        mAutoFocusThreadLock.lock();
-        if (!mAutoFocusThreadRunning) {
-            // Create a detatched thread here so that we don't have to wait
-            // for it when we cancel AF.
-            pthread_t thr;
-            pthread_attr_t attr;
-            pthread_attr_init(&attr);
-            pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
-            mAutoFocusThreadRunning =
-                !pthread_create(&thr, &attr,
-                                auto_focus_thread, NULL);
-            if (!mAutoFocusThreadRunning) {
-                LOGE("failed to start autofocus thread");
-                mAutoFocusThreadLock.unlock();
-                return UNKNOWN_ERROR;
-            }
-        }
-        mAutoFocusThreadLock.unlock();
-    }
-
-    LOGV("autoFocus X");
-    return NO_ERROR;
-}
-
-void QualcommCameraHardware::runSnapshotThread(void *data)
-{
-    LOGV("runSnapshotThread E");
-    if (native_start_snapshot(mCameraControlFd))
-        receiveRawPicture();
-    else
-        LOGE("main: native_start_snapshot failed!");
-
-    mSnapshotThreadWaitLock.lock();
-    mSnapshotThreadRunning = false;
-    mSnapshotThreadWait.signal();
-    mSnapshotThreadWaitLock.unlock();
-
-    LOGV("runSnapshotThread X");
-}
-
-void *snapshot_thread(void *user)
-{
-    LOGD("snapshot_thread E");
-    sp<QualcommCameraHardware> obj = QualcommCameraHardware::getInstance();
-    if (obj != 0) {
-        obj->runSnapshotThread(user);
-    }
-    else LOGW("not starting snapshot thread: the object went away!");
-    LOGD("snapshot_thread X");
-    return NULL;
-}
-
-status_t QualcommCameraHardware::takePicture(shutter_callback shutter_cb,
-                                             raw_callback raw_cb,
-                                             jpeg_callback jpeg_cb,
-                                             void *user)
-{
-    LOGV("takePicture: E raw_cb = %p, jpeg_cb = %p",
-         raw_cb, jpeg_cb);
-    Mutex::Autolock l(&mLock);
-
-    // Wait for old snapshot thread to complete.
-    mSnapshotThreadWaitLock.lock();
-    while (mSnapshotThreadRunning) {
-        LOGV("takePicture: waiting for old snapshot thread to complete.");
-        mSnapshotThreadWait.wait(mSnapshotThreadWaitLock);
-        LOGV("takePicture: old snapshot thread completed.");
-    }
-
-    stopPreviewInternal();
-
-    if (!initRaw(jpeg_cb != NULL)) {
-        LOGE("initRaw failed.  Not taking picture.");
-        return UNKNOWN_ERROR;
-    }
-
-    {
-        Mutex::Autolock cbLock(&mCallbackLock);
-        mShutterCallback = shutter_cb;
-        mRawPictureCallback = raw_cb;
-        mJpegPictureCallback = jpeg_cb;
-        mPictureCallbackCookie = user;
-    }
-
-    mShutterLock.lock();
-    mShutterPending = true;
-    mShutterLock.unlock();
-
-    pthread_attr_t attr;
-    pthread_attr_init(&attr);
-    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
-    mSnapshotThreadRunning = !pthread_create(&mSnapshotThread,
-                                             &attr,
-                                             snapshot_thread,
-                                             NULL);
-    mSnapshotThreadWaitLock.unlock();
-
-    LOGV("takePicture: X");
-    return mSnapshotThreadRunning ? NO_ERROR : UNKNOWN_ERROR;
-}
-
-status_t QualcommCameraHardware::cancelPicture(
-     bool cancel_shutter, bool cancel_raw, bool cancel_jpeg)
-{
-    LOGV("cancelPicture: E cancel_shutter = %d, "
-         "cancel_raw = %d, cancel_jpeg = %d",
-         cancel_shutter, cancel_raw, cancel_jpeg);
-    Mutex::Autolock l(&mLock);
-
-    {
-        Mutex::Autolock cbLock(&mCallbackLock);
-        if (cancel_shutter) mShutterCallback = NULL;
-        if (cancel_raw) mRawPictureCallback = NULL;
-        if (cancel_jpeg) mJpegPictureCallback = NULL;
-    }
-
-    LOGV("cancelPicture: X");
-    return NO_ERROR;
-}
-
-status_t QualcommCameraHardware::setParameters(
-        const CameraParameters& params)
-{
-    LOGV("setParameters: E params = %p", &params);
-
-    Mutex::Autolock l(&mLock);
-
-    // Set preview size.
-    preview_size_type *ps = preview_sizes;
-    {
-        int width, height;
-        params.getPreviewSize(&width, &height);
-        LOGV("requested size %d x %d", width, height);
-        // Validate the preview size
-        size_t i;
-        for (i = 0; i < PREVIEW_SIZE_COUNT; ++i, ++ps) {
-            if (width == ps->width && height == ps->height)
-                break;
-        }
-        if (i == PREVIEW_SIZE_COUNT) {
-            LOGE("Invalid preview size requested: %dx%d",
-                 width, height);
-            return BAD_VALUE;
-        }
-    }
-    mPreviewWidth = mDimension.display_width = ps->width;
-    mPreviewHeight = mDimension.display_height = ps->height;
-
-    // FIXME: validate snapshot sizes,
-    params.getPictureSize(&mRawWidth, &mRawHeight);
-    mDimension.picture_width = mRawWidth;
-    mDimension.picture_height = mRawHeight;
-
-    // Set up the jpeg-thumbnail-size parameters.
-    {
-        int val;
-
-        val = params.getInt("jpeg-thumbnail-width");
-        if (val < 0) {
-            mDimension.ui_thumbnail_width= THUMBNAIL_WIDTH;
-            LOGW("jpeg-thumbnail-width is not specified: defaulting to %d",
-                 THUMBNAIL_WIDTH);
-        }
-        else mDimension.ui_thumbnail_width = val;
-
-        val = params.getInt("jpeg-thumbnail-height");
-        if (val < 0) {
-            mDimension.ui_thumbnail_height= THUMBNAIL_HEIGHT;
-            LOGW("jpeg-thumbnail-height is not specified: defaulting to %d",
-                 THUMBNAIL_HEIGHT);
-        }
-        else mDimension.ui_thumbnail_height = val;
-    }
-
-    mParameters = params;
-
-    setAntibanding();
-    setEffect();
-    setWhiteBalance();
-    // FIXME: set nightshot and luma adaptatiom
-
-    LOGV("setParameters: X");
-    return NO_ERROR ;
-}
-
-CameraParameters QualcommCameraHardware::getParameters() const
-{
-    LOGV("getParameters: EX");
-    return mParameters;
-}
-
-extern "C" sp<CameraHardwareInterface> openCameraHardware()
-{
-    LOGV("openCameraHardware: call createInstance");
-    return QualcommCameraHardware::createInstance();
-}
-
-wp<QualcommCameraHardware> QualcommCameraHardware::singleton;
-
-// If the hardware already exists, return a strong pointer to the current
-// object. If not, create a new hardware object, put it in the singleton,
-// and return it.
-sp<CameraHardwareInterface> QualcommCameraHardware::createInstance()
-{
-    LOGD("createInstance: E");
-
-    Mutex::Autolock lock(&singleton_lock);
-
-    // Wait until the previous release is done.
-    while (singleton_releasing) {
-        LOGD("Wait for previous release.");
-        singleton_wait.wait(singleton_lock);
-    }
-
-    if (singleton != 0) {
-        sp<CameraHardwareInterface> hardware = singleton.promote();
-        if (hardware != 0) {
-            LOGD("createInstance: X return existing hardware=%p", &(*hardware));
-            return hardware;
-        }
-    }
-
-    {
-        struct stat st;
-        int rc = stat("/dev/oncrpc", &st);
-        if (rc < 0) {
-            LOGD("createInstance: X failed to create hardware: %s", strerror(errno));
-            return NULL;
-        }
-    }
-
-    QualcommCameraHardware *cam = new QualcommCameraHardware();
-    sp<QualcommCameraHardware> hardware(cam);
-    singleton = hardware;
-
-    cam->startCamera();
-    cam->initDefaultParameters();
-    LOGD("createInstance: X created hardware=%p", &(*hardware));
-    return hardware;
-}
-
-// For internal use only, hence the strong pointer to the derived type.
-sp<QualcommCameraHardware> QualcommCameraHardware::getInstance()
-{
-    sp<CameraHardwareInterface> hardware = singleton.promote();
-    if (hardware != 0) {
-        //    LOGV("getInstance: X old instance of hardware");
-        return sp<QualcommCameraHardware>(static_cast<QualcommCameraHardware*>(hardware.get()));
-    } else {
-        LOGV("getInstance: X new instance of hardware");
-        return sp<QualcommCameraHardware>();
-    }
-}
-
-void QualcommCameraHardware::receivePreviewFrame(struct msm_frame *frame)
-{
-//    LOGV("receivePreviewFrame E");
-
-    if (!mCameraRunning) {
-        LOGE("ignoring preview callback--camera has been stopped");
-        return;
-    }
-
-    mCallbackLock.lock();
-    preview_callback pcb = mPreviewCallback;
-    void *pdata = mPreviewCallbackCookie;
-    recording_callback rcb = mRecordingCallback;
-    void *rdata = mRecordingCallbackCookie;
-    mCallbackLock.unlock();
-
-    // Find the offset within the heap of the current buffer.
-    ssize_t offset =
-        (ssize_t)frame->buffer - (ssize_t)mPreviewHeap->mHeap->base();
-    offset /= mPreviewFrameSize;
-
-    //LOGV("%d\n", offset);
-
-    mInPreviewCallback = true;
-    if (pcb != NULL)
-        pcb(mPreviewHeap->mBuffers[offset],
-            pdata);
-
-    if(rcb != NULL) {
-        Mutex::Autolock rLock(&mRecordFrameLock);
-        rcb(systemTime(), mPreviewHeap->mBuffers[offset], rdata);
-        if (mReleasedRecordingFrame != true) {
-            LOGV("block for release frame request/command");
-            mRecordWait.wait(mRecordFrameLock);
-        }
-        mReleasedRecordingFrame = false;
-    }
-    mInPreviewCallback = false;
-
-//    LOGV("receivePreviewFrame X");
-}
-
-status_t QualcommCameraHardware::startRecording(
-    recording_callback rcb, void *ruser)
-{
-    LOGV("startRecording E");
-    Mutex::Autolock l(&mLock);
-
-    {
-        Mutex::Autolock cbLock(&mCallbackLock);
-        mRecordingCallback = rcb;
-        mRecordingCallbackCookie = ruser;
-    }
-
-    mReleasedRecordingFrame = false;
-
-    return startPreviewInternal();
-}
-
-void QualcommCameraHardware::stopRecording()
-{
-    LOGV("stopRecording: E");
-    Mutex::Autolock l(&mLock);
-
-    {
-        Mutex::Autolock cbLock(&mCallbackLock);
-        mRecordingCallback = NULL;
-        mRecordingCallbackCookie = NULL;
-
-        mRecordFrameLock.lock();
-        mReleasedRecordingFrame = true;
-        mRecordWait.signal();
-        mRecordFrameLock.unlock();
-
-        if(mPreviewCallback != NULL) {
-            LOGV("stopRecording: X, preview still in progress");
-            return;
-        }
-    }
-
-    stopPreviewInternal();
-    LOGV("stopRecording: X");
-}
-
-void QualcommCameraHardware::releaseRecordingFrame(
-       const sp<IMemory>& mem __attribute__((unused)))
-{
-    LOGV("releaseRecordingFrame E");
-    Mutex::Autolock l(&mLock);
-    Mutex::Autolock rLock(&mRecordFrameLock);
-    mReleasedRecordingFrame = true;
-    mRecordWait.signal();
-    LOGV("releaseRecordingFrame X");
-}
-
-bool QualcommCameraHardware::recordingEnabled()
-{
-    Mutex::Autolock l(&mLock);
-    return mCameraRunning && mRecordingCallback != NULL;
-}
-
-void QualcommCameraHardware::notifyShutter()
-{
-    mShutterLock.lock();
-    if (mShutterPending && mShutterCallback) {
-        mShutterCallback(mPictureCallbackCookie);
-        mShutterPending = false;
-    }
-    mShutterLock.unlock();
-}
-
-static void receive_shutter_callback()
-{
-    LOGV("receive_shutter_callback: E");
-    sp<QualcommCameraHardware> obj = QualcommCameraHardware::getInstance();
-    if (obj != 0) {
-        obj->notifyShutter();
-    }
-    LOGV("receive_shutter_callback: X");
-}
-
-void QualcommCameraHardware::receiveRawPicture()
-{
-    LOGV("receiveRawPicture: E");
-
-    Mutex::Autolock cbLock(&mCallbackLock);
-
-    if (mRawPictureCallback != NULL) {
-        if(native_get_picture(mCameraControlFd, &mCrop) == false) {
-            LOGE("getPicture failed!");
-            return;
-        }
-
-        // By the time native_get_picture returns, picture is taken. Call
-        // shutter callback if cam config thread has not done that.
-        notifyShutter();
-        mRawPictureCallback(mRawHeap->mBuffers[0],
-                            mPictureCallbackCookie);
-    }
-    else LOGV("Raw-picture callback was canceled--skipping.");
-
-    if (mJpegPictureCallback != NULL) {
-        mJpegSize = 0;
-        if (LINK_jpeg_encoder_init()) {
-            if(native_jpeg_encode()) {
-                LOGV("receiveRawPicture: X (success)");
-                return;
-            }
-            LOGE("jpeg encoding failed");
-        }
-        else LOGE("receiveRawPicture X: jpeg_encoder_init failed.");
-    }
-    else LOGV("JPEG callback is NULL, not encoding image.");
-    deinitRaw();
-    LOGV("receiveRawPicture: X");
-}
-
-void QualcommCameraHardware::receiveJpegPictureFragment(
-    uint8_t *buff_ptr, uint32_t buff_size)
-{
-    uint32_t remaining = mJpegHeap->mHeap->virtualSize();
-    remaining -= mJpegSize;
-    uint8_t *base = (uint8_t *)mJpegHeap->mHeap->base();
-
-    LOGV("receiveJpegPictureFragment size %d", buff_size);
-    if (buff_size > remaining) {
-        LOGE("receiveJpegPictureFragment: size %d exceeds what "
-             "remains in JPEG heap (%d), truncating",
-             buff_size,
-             remaining);
-        buff_size = remaining;
-    }
-    memcpy(base + mJpegSize, buff_ptr, buff_size);
-    mJpegSize += buff_size;
-}
-
-void QualcommCameraHardware::receiveJpegPicture(void)
-{
-    LOGV("receiveJpegPicture: E image (%d uint8_ts out of %d)",
-         mJpegSize, mJpegHeap->mBufferSize);
-    Mutex::Autolock cbLock(&mCallbackLock);
-
-    int index = 0, rc;
-
-    if (mJpegPictureCallback) {
-        // The reason we do not allocate into mJpegHeap->mBuffers[offset] is
-        // that the JPEG image's size will probably change from one snapshot
-        // to the next, so we cannot reuse the MemoryBase object.
-        sp<MemoryBase> buffer = new
-            MemoryBase(mJpegHeap->mHeap,
-                       index * mJpegHeap->mBufferSize +
-                       mJpegHeap->mFrameOffset,
-                       mJpegSize);
-
-        mJpegPictureCallback(buffer, mPictureCallbackCookie);
-        buffer = NULL;
-    }
-    else LOGV("JPEG callback was cancelled--not delivering image.");
-
-    LINK_jpeg_encoder_join();
-    deinitRaw();
-
-    LOGV("receiveJpegPicture: X callback done.");
-}
-
-bool QualcommCameraHardware::previewEnabled()
-{
-//  Mutex::Autolock l(&mLock);
-    return mCameraRunning && mPreviewCallback != NULL;
-}
-
-int QualcommCameraHardware::getParm(
-    const char *parm_str, const struct str_map *const parm_map)
-{
-    // Check if the parameter exists.
-    const char *str = mParameters.get(parm_str);
-    if (str == NULL) return NOT_FOUND;
-
-    // Look up the parameter value.
-    return attr_lookup(parm_map, str);
-}
-
-void QualcommCameraHardware::setEffect()
-{
-    int32_t value = getParm("effect", effect);
-    if (value != NOT_FOUND) {
-        native_set_parm(CAMERA_SET_PARM_EFFECT, sizeof(value), (void *)&value);
-    }    
-}
-
-void QualcommCameraHardware::setWhiteBalance()
-{
-    int32_t value = getParm("whitebalance", whitebalance);
-    if (value != NOT_FOUND) {
-        native_set_parm(CAMERA_SET_PARM_WB, sizeof(value), (void *)&value);
-    }
-}
-
-void QualcommCameraHardware::setAntibanding()
-{
-    camera_antibanding_type value =
-        (camera_antibanding_type) getParm("antibanding", antibanding);
-    native_set_parm(CAMERA_SET_PARM_ANTIBANDING, sizeof(value), (void *)&value);
-}
-
-QualcommCameraHardware::MemPool::MemPool(int buffer_size, int num_buffers,
-                                         int frame_size,
-                                         int frame_offset,
-                                         const char *name) :
-    mBufferSize(buffer_size),
-    mNumBuffers(num_buffers),
-    mFrameSize(frame_size),
-    mFrameOffset(frame_offset),
-    mBuffers(NULL), mName(name)
-{
-    // empty
-}
-
-void QualcommCameraHardware::MemPool::completeInitialization()
-{
-    // If we do not know how big the frame will be, we wait to allocate
-    // the buffers describing the individual frames until we do know their
-    // size.
-
-    if (mFrameSize > 0) {
-        mBuffers = new sp<MemoryBase>[mNumBuffers];
-        for (int i = 0; i < mNumBuffers; i++) {
-            mBuffers[i] = new
-                MemoryBase(mHeap,
-                           i * mBufferSize + mFrameOffset,
-                           mFrameSize);
-        }
-    }
-}
-
-QualcommCameraHardware::AshmemPool::AshmemPool(int buffer_size, int num_buffers,
-                                               int frame_size,
-                                               int frame_offset,
-                                               const char *name) :
-    QualcommCameraHardware::MemPool(buffer_size,
-                                    num_buffers,
-                                    frame_size,
-                                    frame_offset,
-                                    name)
-{
-    LOGV("constructing MemPool %s backed by ashmem: "
-         "%d frames @ %d uint8_ts, offset %d, "
-         "buffer size %d",
-         mName,
-         num_buffers, frame_size, frame_offset, buffer_size);
-
-    int page_mask = getpagesize() - 1;
-    int ashmem_size = buffer_size * num_buffers;
-    ashmem_size += page_mask;
-    ashmem_size &= ~page_mask;
-
-    mHeap = new MemoryHeapBase(ashmem_size);
-
-    completeInitialization();
-}
-
-static bool register_buf(int camfd,
-                         int size,
-                         int pmempreviewfd,
-                         uint32_t offset,
-                         uint8_t *buf,
-                         int pmem_type,
-                         bool register_buffer = true);
-
-QualcommCameraHardware::PmemPool::PmemPool(const char *pmem_pool,
-                                           int camera_control_fd,
-                                           int pmem_type,
-                                           int buffer_size, int num_buffers,
-                                           int frame_size,
-                                           int frame_offset,
-                                           const char *name) :
-    QualcommCameraHardware::MemPool(buffer_size,
-                                    num_buffers,
-                                    frame_size,
-                                    frame_offset,
-                                    name),
-    mPmemType(pmem_type),
-    mCameraControlFd(dup(camera_control_fd))
-{
-    LOGV("constructing MemPool %s backed by pmem pool %s: "
-         "%d frames @ %d bytes, offset %d, buffer size %d",
-         mName,
-         pmem_pool, num_buffers, frame_size, frame_offset,
-         buffer_size);
-
-    LOGV("%s: duplicating control fd %d --> %d",
-         __FUNCTION__,
-         camera_control_fd, mCameraControlFd);
-
-    // Make a new mmap'ed heap that can be shared across processes.
-
-    mAlignedSize = clp2(buffer_size * num_buffers);
-
-    sp<MemoryHeapBase> masterHeap =
-        new MemoryHeapBase(pmem_pool, mAlignedSize, 0);
-    sp<MemoryHeapPmem> pmemHeap = new MemoryHeapPmem(masterHeap, 0);
-    if (pmemHeap->getHeapID() >= 0) {
-        pmemHeap->slap();
-        masterHeap.clear();
-        mHeap = pmemHeap;
-        pmemHeap.clear();
-
-        mFd = mHeap->getHeapID();
-        if (::ioctl(mFd, PMEM_GET_SIZE, &mSize)) {
-            LOGE("pmem pool %s ioctl(PMEM_GET_SIZE) error %s (%d)",
-                 pmem_pool,
-                 ::strerror(errno), errno);
-            mHeap.clear();
-            return;
-        }
-
-        LOGV("pmem pool %s ioctl(fd = %d, PMEM_GET_SIZE) is %ld",
-             pmem_pool,
-             mFd,
-             mSize.len);
-
-        // Unregister preview buffers with the camera drivers.
-        for (int cnt = 0; cnt < num_buffers; ++cnt) {
-            register_buf(mCameraControlFd,
-                         buffer_size,
-                         mHeap->getHeapID(),
-                         buffer_size * cnt,
-                         (uint8_t *)mHeap->base() + buffer_size * cnt,
-                         pmem_type);
-        }
-
-        completeInitialization();
-    }
-    else LOGE("pmem pool %s error: could not create master heap!",
-              pmem_pool);
-}
-
-QualcommCameraHardware::PmemPool::~PmemPool()
-{
-    LOGV("%s: %s E", __FUNCTION__, mName);
-    // Unregister preview buffers with the camera drivers.
-    for (int cnt = 0; cnt < mNumBuffers; ++cnt) {
-        register_buf(mCameraControlFd,
-                     mBufferSize,
-                     mHeap->getHeapID(),
-                     mBufferSize * cnt,
-                     (uint8_t *)mHeap->base() + mBufferSize * cnt,
-                     mPmemType,
-                     false /* unregister */);
-    }
-    LOGV("destroying PmemPool %s: closing control fd %d",
-         mName,
-         mCameraControlFd);
-    close(mCameraControlFd);
-    LOGV("%s: %s X", __FUNCTION__, mName);
-}
-
-QualcommCameraHardware::MemPool::~MemPool()
-{
-    LOGV("destroying MemPool %s", mName);
-    if (mFrameSize > 0)
-        delete [] mBuffers;
-    mHeap.clear();
-    LOGV("destroying MemPool %s completed", mName);
-}
-
-static bool register_buf(int camfd,
-                         int size,
-                         int pmempreviewfd,
-                         uint32_t offset,
-                         uint8_t *buf,
-                         int pmem_type,
-                         bool register_buffer)
-{
-    struct msm_pmem_info pmemBuf;
-
-    pmemBuf.type     = pmem_type;
-    pmemBuf.fd       = pmempreviewfd;
-    pmemBuf.offset   = offset;
-    pmemBuf.len      = size;
-    pmemBuf.vaddr    = buf;
-    pmemBuf.y_off    = 0;
-    pmemBuf.cbcr_off = PAD_TO_WORD(size * 2 / 3);
-    pmemBuf.active   = true;
-
-    LOGV("register_buf: camfd = %d, reg = %d buffer = %p",
-         camfd, !register_buffer, buf);
-    if (ioctl(camfd,
-              register_buffer ?
-              MSM_CAM_IOCTL_REGISTER_PMEM :
-              MSM_CAM_IOCTL_UNREGISTER_PMEM,
-              &pmemBuf) < 0) {
-        LOGE("register_buf: MSM_CAM_IOCTL_(UN)REGISTER_PMEM fd %d error %s",
-             camfd,
-             strerror(errno));
-        return false;
-    }
-    return true;
-}
-
-status_t QualcommCameraHardware::MemPool::dump(int fd, const Vector<String16>& args) const
-{
-    const size_t SIZE = 256;
-    char buffer[SIZE];
-    String8 result;
-    snprintf(buffer, 255, "QualcommCameraHardware::AshmemPool::dump\n");
-    result.append(buffer);
-    if (mName) {
-        snprintf(buffer, 255, "mem pool name (%s)\n", mName);
-        result.append(buffer);
-    }
-    if (mHeap != 0) {
-        snprintf(buffer, 255, "heap base(%p), size(%d), flags(%d), device(%s)\n",
-                 mHeap->getBase(), mHeap->getSize(),
-                 mHeap->getFlags(), mHeap->getDevice());
-        result.append(buffer);
-    }
-    snprintf(buffer, 255, "buffer size (%d), number of buffers (%d),"
-             " frame size(%d), and frame offset(%d)\n",
-             mBufferSize, mNumBuffers, mFrameSize, mFrameOffset);
-    result.append(buffer);
-    write(fd, result.string(), result.size());
-    return NO_ERROR;
-}
-
-static void receive_camframe_callback(struct msm_frame *frame)
-{
-    sp<QualcommCameraHardware> obj = QualcommCameraHardware::getInstance();
-    if (obj != 0) {
-        obj->receivePreviewFrame(frame);
-    }
-}
-
-static void receive_jpeg_fragment_callback(uint8_t *buff_ptr, uint32_t buff_size)
-{
-    LOGV("receive_jpeg_fragment_callback E");
-    sp<QualcommCameraHardware> obj = QualcommCameraHardware::getInstance();
-    if (obj != 0) {
-        obj->receiveJpegPictureFragment(buff_ptr, buff_size);
-    }
-    LOGV("receive_jpeg_fragment_callback X");
-}
-
-static void receive_jpeg_callback(jpeg_event_t status)
-{
-    LOGV("receive_jpeg_callback E (completion status %d)", status);
-    if (status == JPEG_EVENT_DONE) {
-        sp<QualcommCameraHardware> obj = QualcommCameraHardware::getInstance();
-        if (obj != 0) {
-            obj->receiveJpegPicture();
-        }
-    }
-    LOGV("receive_jpeg_callback X");
-}
-
-}; // namespace android
diff --git a/libcamera2/QualcommCameraHardware.h b/libcamera2/QualcommCameraHardware.h
deleted file mode 100644
index a4fe43b..0000000
--- a/libcamera2/QualcommCameraHardware.h
+++ /dev/null
@@ -1,241 +0,0 @@
-/*
-** Copyright 2008, Google Inc.
-**
-** 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_HARDWARE_QUALCOMM_CAMERA_HARDWARE_H
-#define ANDROID_HARDWARE_QUALCOMM_CAMERA_HARDWARE_H
-
-#include <ui/CameraHardwareInterface.h>
-#include <utils/MemoryBase.h>
-#include <utils/MemoryHeapBase.h>
-#include <stdint.h>
-
-extern "C" {
-#include <linux/android_pmem.h>
-#include <media/msm_camera.h>
-#include <camera.h>
-}
-
-struct str_map {
-    const char *const desc;
-    int val;
-};
-
-namespace android {
-
-class QualcommCameraHardware : public CameraHardwareInterface {
-public:
-
-    virtual sp<IMemoryHeap> getPreviewHeap() const;
-    virtual sp<IMemoryHeap> getRawHeap() const;
-
-    virtual status_t dump(int fd, const Vector<String16>& args) const;
-    virtual status_t startPreview(preview_callback cb, void* user);
-    virtual void stopPreview();
-    virtual bool previewEnabled();
-    virtual status_t startRecording(recording_callback cb, void* user);
-    virtual void stopRecording();
-    virtual bool recordingEnabled();
-    virtual void releaseRecordingFrame(const sp<IMemory>& mem);
-    virtual status_t autoFocus(autofocus_callback, void *user);
-    virtual status_t takePicture(shutter_callback, raw_callback,
-                                 jpeg_callback, void *);
-    virtual status_t cancelPicture(bool cancel_shutter,
-                                   bool cancel_raw, bool cancel_jpeg);
-    virtual status_t setParameters(const CameraParameters& params);
-    virtual CameraParameters getParameters() const;
-    virtual void release();
-
-    static sp<CameraHardwareInterface> createInstance();
-    static sp<QualcommCameraHardware> getInstance();
-
-    void receivePreviewFrame(struct msm_frame *frame);
-    void receiveJpegPicture(void);
-    void jpeg_set_location();
-    void receiveJpegPictureFragment(uint8_t *buf, uint32_t size);
-    void notifyShutter();
-
-private:
-    QualcommCameraHardware();
-    virtual ~QualcommCameraHardware();
-    status_t startPreviewInternal();
-    void stopPreviewInternal();
-    friend void *auto_focus_thread(void *user);
-    void runAutoFocus();
-    void cancelAutoFocus();
-    bool native_set_dimension (int camfd);
-    bool native_jpeg_encode (void);
-    bool native_set_parm(cam_ctrl_type type, uint16_t length, void *value);
-    bool native_set_dimension(cam_ctrl_dimension_t *value);
-    int getParm(const char *parm_str, const str_map *parm_map);
-
-    static wp<QualcommCameraHardware> singleton;
-
-    /* These constants reflect the number of buffers that libmmcamera requires
-       for preview and raw, and need to be updated when libmmcamera
-       changes.
-    */
-    static const int kPreviewBufferCount = 4;
-    static const int kRawBufferCount = 1;
-    static const int kJpegBufferCount = 1;
-
-    //TODO: put the picture dimensions in the CameraParameters object;
-    CameraParameters mParameters;
-    int mPreviewHeight;
-    int mPreviewWidth;
-    int mRawHeight;
-    int mRawWidth;
-    unsigned int frame_size;
-    bool mCameraRunning;
-    bool mPreviewInitialized;
-
-    // This class represents a heap which maintains several contiguous
-    // buffers.  The heap may be backed by pmem (when pmem_pool contains
-    // the name of a /dev/pmem* file), or by ashmem (when pmem_pool == NULL).
-
-    struct MemPool : public RefBase {
-        MemPool(int buffer_size, int num_buffers,
-                int frame_size,
-                int frame_offset,
-                const char *name);
-
-        virtual ~MemPool() = 0;
-
-        void completeInitialization();
-        bool initialized() const {
-            return mHeap != NULL && mHeap->base() != MAP_FAILED;
-        }
-
-        virtual status_t dump(int fd, const Vector<String16>& args) const;
-
-        int mBufferSize;
-        int mNumBuffers;
-        int mFrameSize;
-        int mFrameOffset;
-        sp<MemoryHeapBase> mHeap;
-        sp<MemoryBase> *mBuffers;
-
-        const char *mName;
-    };
-
-    struct AshmemPool : public MemPool {
-        AshmemPool(int buffer_size, int num_buffers,
-                   int frame_size,
-                   int frame_offset,
-                   const char *name);
-    };
-
-    struct PmemPool : public MemPool {
-        PmemPool(const char *pmem_pool,
-                 int control_camera_fd, int pmem_type,
-                 int buffer_size, int num_buffers,
-                 int frame_size, int frame_offset,
-                 const char *name);
-        virtual ~PmemPool();
-        int mFd;
-        int mPmemType;
-        int mCameraControlFd;
-        uint32_t mAlignedSize;
-        struct pmem_region mSize;
-    };
-
-    sp<PmemPool> mPreviewHeap;
-    sp<PmemPool> mThumbnailHeap;
-    sp<PmemPool> mRawHeap;
-    sp<AshmemPool> mJpegHeap;
-
-    void startCamera();
-    bool initPreview();
-    void deinitPreview();
-    bool initRaw(bool initJpegHeap);
-    void deinitRaw();
-
-    bool mFrameThreadRunning;
-    Mutex mFrameThreadWaitLock;
-    Condition mFrameThreadWait;
-    friend void *frame_thread(void *user);
-    void runFrameThread(void *data);
-
-    bool mShutterPending;
-    Mutex mShutterLock;
-
-    bool mSnapshotThreadRunning;
-    Mutex mSnapshotThreadWaitLock;
-    Condition mSnapshotThreadWait;
-    friend void *snapshot_thread(void *user);
-    void runSnapshotThread(void *data);
-
-    void initDefaultParameters();
-
-    void setAntibanding();
-    void setEffect();
-    void setWhiteBalance();
-
-    Mutex mLock;
-    bool mReleasedRecordingFrame;
-
-    void receiveRawPicture(void);
-
-    Mutex mCallbackLock;
-	Mutex mRecordLock;
-	Mutex mRecordFrameLock;
-	Condition mRecordWait;
-    Condition mStateWait;
-
-    /* mJpegSize keeps track of the size of the accumulated JPEG.  We clear it
-       when we are about to take a picture, so at any time it contains either
-       zero, or the size of the last JPEG picture taken.
-    */
-    uint32_t mJpegSize;
-
-    shutter_callback    mShutterCallback;
-    raw_callback        mRawPictureCallback;
-    jpeg_callback       mJpegPictureCallback;
-    void                *mPictureCallbackCookie;
-
-    autofocus_callback  mAutoFocusCallback;
-    void                *mAutoFocusCallbackCookie;
-
-    preview_callback    mPreviewCallback;
-    void                *mPreviewCallbackCookie;
-    recording_callback  mRecordingCallback;
-    void                *mRecordingCallbackCookie;
-    unsigned int        mPreviewFrameSize;
-    int                 mRawSize;
-    int                 mJpegMaxSize;
-
-#if DLOPEN_LIBMMCAMERA
-    void *libmmcamera;
-#endif
-
-    int mCameraControlFd;
-    cam_ctrl_dimension_t mDimension;
-    bool mAutoFocusThreadRunning;
-    Mutex mAutoFocusThreadLock;
-    int mAutoFocusFd;
-
-    pthread_t mCamConfigThread;
-    pthread_t mFrameThread;
-    pthread_t mSnapshotThread;
-
-    common_crop_t mCrop;
-
-    struct msm_frame frames[kPreviewBufferCount];
-    bool mInPreviewCallback;
-};
-
-}; // namespace android
-
-#endif
diff --git a/libcopybit/Android.mk b/libcopybit/Android.mk
index f6a1b4b..36b1416 100644
--- a/libcopybit/Android.mk
+++ b/libcopybit/Android.mk
@@ -16,10 +16,27 @@
 LOCAL_PATH:= $(call my-dir)
 # HAL module implemenation, not prelinked and stored in
 # hw/<COPYPIX_HARDWARE_MODULE_ID>.<ro.board.platform>.so
+
+ifeq ($(TARGET_BOARD_PLATFORM),msm7k)
 include $(CLEAR_VARS)
 LOCAL_PRELINK_MODULE := false
 LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/hw
 LOCAL_SHARED_LIBRARIES := liblog
-LOCAL_SRC_FILES := copybit.c
+LOCAL_SRC_FILES := copybit.cpp
 LOCAL_MODULE := copybit.msm7k
+LOCAL_C_INCLUDES += hardware/msm7k/libgralloc
+LOCAL_CFLAGS += -DCOPYBIT_MSM7K=1
 include $(BUILD_SHARED_LIBRARY)
+endif
+
+ifeq ($(TARGET_BOARD_PLATFORM),qsd8k)
+include $(CLEAR_VARS)
+LOCAL_PRELINK_MODULE := false
+LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/hw
+LOCAL_SHARED_LIBRARIES := liblog
+LOCAL_SRC_FILES := copybit.cpp
+LOCAL_MODULE := copybit.qsd8k
+LOCAL_C_INCLUDES += hardware/libhardware/modules/gralloc
+LOCAL_CFLAGS += -DCOPYBIT_QSD8K=1
+include $(BUILD_SHARED_LIBRARY)
+endif
diff --git a/libcopybit/copybit.c b/libcopybit/copybit.cpp
similarity index 77%
rename from libcopybit/copybit.c
rename to libcopybit/copybit.cpp
index 3565074..ba8531b 100644
--- a/libcopybit/copybit.c
+++ b/libcopybit/copybit.cpp
@@ -34,6 +34,20 @@
 
 #include <hardware/copybit.h>
 
+#include "gralloc_priv.h"
+
+#define DEBUG_MDP_ERRORS 1
+
+/******************************************************************************/
+
+#if defined(COPYBIT_MSM7K)
+#define MAX_SCALE_FACTOR    (4)
+#elif defined(COPYBIT_QSD8K)
+#define MAX_SCALE_FACTOR    (8)
+#else
+#error "Unsupported MDP version"
+#endif
+
 /******************************************************************************/
 
 /** State information for each device instance */
@@ -52,21 +66,21 @@ static int open_copybit(const struct hw_module_t* module, const char* name,
         struct hw_device_t** device);
 
 static struct hw_module_methods_t copybit_module_methods = {
-    .open =  open_copybit
+    open:  open_copybit
 };
 
 /*
  * The COPYBIT Module
  */
-const struct copybit_module_t HAL_MODULE_INFO_SYM = {
-    .common = {
-        .tag = HARDWARE_MODULE_TAG,
-        .version_major = 1,
-        .version_minor = 0,
-        .id = COPYBIT_HARDWARE_MODULE_ID,
-        .name = "QCT MSM7K COPYBIT Module",
-        .author = "Google, Inc.",
-        .methods = &copybit_module_methods,
+struct copybit_module_t HAL_MODULE_INFO_SYM = {
+    common: {
+        tag: HARDWARE_MODULE_TAG,
+        version_major: 1,
+        version_minor: 0,
+        id: COPYBIT_HARDWARE_MODULE_ID,
+        name: "QCT MSM7K COPYBIT Module",
+        author: "Google, Inc.",
+        methods: &copybit_module_methods
     }
 };
 
@@ -103,9 +117,11 @@ static void intersect(struct copybit_rect_t *out,
 /** convert COPYBIT_FORMAT to MDP format */
 static int get_format(int format) {
     switch (format) {
+    case COPYBIT_FORMAT_RGB_565:       return MDP_RGB_565;
+    case COPYBIT_FORMAT_RGBX_8888:     return MDP_RGBX_8888;
+    case COPYBIT_FORMAT_RGB_888:       return MDP_RGB_888;
     case COPYBIT_FORMAT_RGBA_8888:     return MDP_RGBA_8888;
     case COPYBIT_FORMAT_BGRA_8888:     return MDP_BGRA_8888;
-    case COPYBIT_FORMAT_RGB_565:       return MDP_RGB_565;
     case COPYBIT_FORMAT_YCbCr_422_SP:  return MDP_Y_CBCR_H2V1;
     case COPYBIT_FORMAT_YCbCr_420_SP:  return MDP_Y_CBCR_H2V2;
     }
@@ -113,15 +129,27 @@ static int get_format(int format) {
 }
 
 /** convert from copybit image to mdp image structure */
-static void set_image(struct mdp_img *img,
-                      const struct copybit_image_t *rhs) {
+static void set_image(struct mdp_img *img, const struct copybit_image_t *rhs) 
+{
+    private_handle_t* hnd = (private_handle_t*)rhs->handle;
     img->width      = rhs->w;
     img->height     = rhs->h;
     img->format     = get_format(rhs->format);
-    img->offset     = rhs->offset;
-    img->memory_id  = rhs->fd;
+    img->offset     = hnd->offset;
+#if defined(COPYBIT_MSM7K)
+    if (hnd->flags & private_handle_t::PRIV_FLAGS_USES_GPU) {
+        img->memory_id = hnd->gpu_fd;
+        if (img->format == MDP_RGBA_8888) {
+            // msm7201A GPU only supports BGRA_8888 destinations
+            img->format = MDP_BGRA_8888;
+        }
+    } else {
+        img->memory_id = hnd->fd;
+    }
+#else
+    img->memory_id  = hnd->fd;
+#endif
 }
-
 /** setup rectangles */
 static void set_rects(struct copybit_context_t *dev,
                       struct mdp_blit_req *e,
@@ -166,7 +194,7 @@ static void set_rects(struct copybit_context_t *dev,
 static void set_infos(struct copybit_context_t *dev, struct mdp_blit_req *req) {
     req->alpha = dev->mAlpha;
     req->transp_mask = MDP_TRANSP_NOP;
-    req->flags = dev->mFlags;
+    req->flags = dev->mFlags | MDP_BLEND_FG_PREMULT;
 }
 
 /** copy the bits */
@@ -175,10 +203,37 @@ static int msm_copybit(struct copybit_context_t *dev, void const *list)
     int err = ioctl(dev->mFD, MSMFB_BLIT,
                     (struct mdp_blit_req_list const*)list);
     LOGE_IF(err<0, "copyBits failed (%s)", strerror(errno));
-    if (err == 0)
+    if (err == 0) {
         return 0;
-    else
+    } else {
+#if DEBUG_MDP_ERRORS
+        struct mdp_blit_req_list const* l = (struct mdp_blit_req_list const*)list;
+        for (int i=0 ; i<l->count ; i++) {
+            LOGD("%d: src={w=%d, h=%d, f=%d, rect={%d,%d,%d,%d}}\n"
+                 "    dst={w=%d, h=%d, f=%d, rect={%d,%d,%d,%d}}\n"
+                 "    flags=%08lx"
+                    ,
+                    i,
+                    l->req[i].src.width,
+                    l->req[i].src.height,
+                    l->req[i].src.format,
+                    l->req[i].src_rect.x,
+                    l->req[i].src_rect.y,
+                    l->req[i].src_rect.w,
+                    l->req[i].src_rect.h,
+                    l->req[i].dst.width,
+                    l->req[i].dst.height,
+                    l->req[i].dst.format,
+                    l->req[i].dst_rect.x,
+                    l->req[i].dst_rect.y,
+                    l->req[i].dst_rect.w,
+                    l->req[i].dst_rect.h,
+                    l->req[i].flags
+            );
+        }
+#endif
         return -errno;
+    }
 }
 
 /*****************************************************************************/
@@ -257,10 +312,10 @@ static int get(struct copybit_device_t *dev, int name)
     if (ctx) {
         switch(name) {
         case COPYBIT_MINIFICATION_LIMIT:
-            value = 4;
+            value = MAX_SCALE_FACTOR;
             break;
         case COPYBIT_MAGNIFICATION_LIMIT:
-            value = 4;
+            value = MAX_SCALE_FACTOR;
             break;
         case COPYBIT_SCALING_FRAC_BITS:
             value = 32;
@@ -304,7 +359,13 @@ static int stretch_copybit(
                     return -EINVAL;
             }
         }
-        
+
+        if (src_rect->l < 0 || src_rect->r > src->w ||
+            src_rect->t < 0 || src_rect->b > src->h) {
+            // this is always invalid
+            return -EINVAL;
+        }
+
         const uint32_t maxCount = sizeof(list.req)/sizeof(list.req[0]);
         const struct copybit_rect_t bounds = { 0, 0, dst->w, dst->h };
         struct copybit_rect_t clip;
@@ -312,10 +373,18 @@ static int stretch_copybit(
         status = 0;
         while ((status == 0) && region->next(region, &clip)) {
             intersect(&clip, &bounds, &clip);
-            set_infos(ctx, &list.req[list.count]);
-            set_image(&list.req[list.count].dst, dst);
-            set_image(&list.req[list.count].src, src);
-            set_rects(ctx, &list.req[list.count], dst_rect, src_rect, &clip);
+            mdp_blit_req* req = &list.req[list.count];
+            set_infos(ctx, req);
+            set_image(&req->dst, dst);
+            set_image(&req->src, src);
+            set_rects(ctx, req, dst_rect, src_rect, &clip);
+
+            if (req->src_rect.w<=0 || req->src_rect.h<=0)
+                continue;
+
+            if (req->dst_rect.w<=0 || req->dst_rect.h<=0)
+                continue;
+
             if (++list.count == maxCount) {
                 status = msm_copybit(ctx, &list);
                 list.count = 0;
@@ -360,12 +429,13 @@ static int open_copybit(const struct hw_module_t* module, const char* name,
         struct hw_device_t** device)
 {
     int status = -EINVAL;
-    struct copybit_context_t *ctx = malloc(sizeof(struct copybit_context_t));
+    copybit_context_t *ctx;
+    ctx = (copybit_context_t *)malloc(sizeof(copybit_context_t));
     memset(ctx, 0, sizeof(*ctx));
 
     ctx->device.common.tag = HARDWARE_DEVICE_TAG;
-    ctx->device.common.version = 0;
-    ctx->device.common.module = module;
+    ctx->device.common.version = 1;
+    ctx->device.common.module = const_cast<hw_module_t*>(module);
     ctx->device.common.close = close_copybit;
     ctx->device.set_parameter = set_parameter_copybit;
     ctx->device.get = get;
diff --git a/libgralloc-qsd8k/Android.mk b/libgralloc-qsd8k/Android.mk
new file mode 100644
index 0000000..d5ffa42
--- /dev/null
+++ b/libgralloc-qsd8k/Android.mk
@@ -0,0 +1,32 @@
+# 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.
+
+LOCAL_PATH := $(call my-dir)
+
+# HAL module implemenation, not prelinked and stored in
+# hw/<OVERLAY_HARDWARE_MODULE_ID>.<ro.product.board>.so
+include $(CLEAR_VARS)
+LOCAL_PRELINK_MODULE := false
+LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/hw
+LOCAL_SHARED_LIBRARIES := liblog libcutils libGLESv1_CM
+
+LOCAL_SRC_FILES := 	\
+	allocator.cpp 	\
+	gralloc.cpp 	\
+	framebuffer.cpp \
+	mapper.cpp
+	
+LOCAL_MODULE := gralloc.$(TARGET_BOARD_PLATFORM)
+LOCAL_CFLAGS:= -DLOG_TAG=\"$(TARGET_BOARD_PLATFORM).gralloc\"
+include $(BUILD_SHARED_LIBRARY)
diff --git a/libgralloc-qsd8k/allocator.cpp b/libgralloc-qsd8k/allocator.cpp
new file mode 100644
index 0000000..4dad6a1
--- /dev/null
+++ b/libgralloc-qsd8k/allocator.cpp
@@ -0,0 +1,170 @@
+/*
+ * Copyright (C) 2009 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 <cutils/log.h>
+
+#include "allocator.h"
+
+
+// align all the memory blocks on a cache-line boundary
+const int SimpleBestFitAllocator::kMemoryAlign = 32;
+
+SimpleBestFitAllocator::SimpleBestFitAllocator()
+    : mHeapSize(0)
+{
+}
+
+SimpleBestFitAllocator::SimpleBestFitAllocator(size_t size)
+    : mHeapSize(0)
+{
+    setSize(size);
+}
+
+SimpleBestFitAllocator::~SimpleBestFitAllocator()
+{
+    while(!mList.isEmpty()) {
+        delete mList.remove(mList.head());
+    }
+}
+
+ssize_t SimpleBestFitAllocator::setSize(size_t size)
+{
+    Locker::Autolock _l(mLock);
+    if (mHeapSize != 0) return -EINVAL;
+    size_t pagesize = getpagesize();
+    mHeapSize = ((size + pagesize-1) & ~(pagesize-1));
+    chunk_t* node = new chunk_t(0, mHeapSize / kMemoryAlign);
+    mList.insertHead(node);
+    return size;
+}
+    
+    
+size_t SimpleBestFitAllocator::size() const
+{
+    return mHeapSize;
+}
+
+ssize_t SimpleBestFitAllocator::allocate(size_t size, uint32_t flags)
+{
+    Locker::Autolock _l(mLock);
+    if (mHeapSize == 0) return -EINVAL;
+    ssize_t offset = alloc(size, flags);
+    return offset;
+}
+
+ssize_t SimpleBestFitAllocator::deallocate(size_t offset)
+{
+    Locker::Autolock _l(mLock);
+    if (mHeapSize == 0) return -EINVAL;
+    chunk_t const * const freed = dealloc(offset);
+    if (freed) {
+        return 0;
+    }
+    return -ENOENT;
+}
+
+ssize_t SimpleBestFitAllocator::alloc(size_t size, uint32_t flags)
+{
+    if (size == 0) {
+        return 0;
+    }
+    size = (size + kMemoryAlign-1) / kMemoryAlign;
+    chunk_t* free_chunk = 0;
+    chunk_t* cur = mList.head();
+
+    size_t pagesize = getpagesize();
+    while (cur) {
+        int extra = ( -cur->start & ((pagesize/kMemoryAlign)-1) ) ;
+
+        // best fit
+        if (cur->free && (cur->size >= (size+extra))) {
+            if ((!free_chunk) || (cur->size < free_chunk->size)) {
+                free_chunk = cur;
+            }
+            if (cur->size == size) {
+                break;
+            }
+        }
+        cur = cur->next;
+    }
+
+    if (free_chunk) {
+        const size_t free_size = free_chunk->size;
+        free_chunk->free = 0;
+        free_chunk->size = size;
+        if (free_size > size) {
+            int extra = ( -free_chunk->start & ((pagesize/kMemoryAlign)-1) ) ;
+            if (extra) {
+                chunk_t* split = new chunk_t(free_chunk->start, extra);
+                free_chunk->start += extra;
+                mList.insertBefore(free_chunk, split);
+            }
+
+            LOGE_IF(((free_chunk->start*kMemoryAlign)&(pagesize-1)),
+                    "page is not aligned!!!");
+
+            const ssize_t tail_free = free_size - (size+extra);
+            if (tail_free > 0) {
+                chunk_t* split = new chunk_t(
+                        free_chunk->start + free_chunk->size, tail_free);
+                mList.insertAfter(free_chunk, split);
+            }
+        }
+        return (free_chunk->start)*kMemoryAlign;
+    }
+    return -ENOMEM;
+}
+
+SimpleBestFitAllocator::chunk_t* SimpleBestFitAllocator::dealloc(size_t start)
+{
+    start = start / kMemoryAlign;
+    chunk_t* cur = mList.head();
+    while (cur) {
+        if (cur->start == start) {
+            LOG_FATAL_IF(cur->free,
+                "block at offset 0x%08lX of size 0x%08lX already freed",
+                cur->start*kMemoryAlign, cur->size*kMemoryAlign);
+
+            // merge freed blocks together
+            chunk_t* freed = cur;
+            cur->free = 1;
+            do {
+                chunk_t* const p = cur->prev;
+                chunk_t* const n = cur->next;
+                if (p && (p->free || !cur->size)) {
+                    freed = p;
+                    p->size += cur->size;
+                    mList.remove(cur);
+                    delete cur;
+                }
+                cur = n;
+            } while (cur && cur->free);
+
+            #ifndef NDEBUG
+                if (!freed->free) {
+                    dump_l("dealloc (!freed->free)");
+                }
+            #endif
+            LOG_FATAL_IF(!freed->free,
+                "freed block at offset 0x%08lX of size 0x%08lX is not free!",
+                freed->start * kMemoryAlign, freed->size * kMemoryAlign);
+
+            return freed;
+        }
+        cur = cur->next;
+    }
+    return 0;
+}
diff --git a/libgralloc-qsd8k/allocator.h b/libgralloc-qsd8k/allocator.h
new file mode 100644
index 0000000..b0d89e9
--- /dev/null
+++ b/libgralloc-qsd8k/allocator.h
@@ -0,0 +1,129 @@
+/*
+ * Copyright (C) 2009 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 GRALLOC_ALLOCATOR_H_
+#define GRALLOC_ALLOCATOR_H_
+
+#include <stdint.h>
+#include <sys/types.h>
+
+#include "gr.h"
+
+// ----------------------------------------------------------------------------
+
+/*
+ * A simple templatized doubly linked-list implementation
+ */
+
+template <typename NODE>
+class LinkedList
+{
+    NODE*  mFirst;
+    NODE*  mLast;
+
+public:
+                LinkedList() : mFirst(0), mLast(0) { }
+    bool        isEmpty() const { return mFirst == 0; }
+    NODE const* head() const { return mFirst; }
+    NODE*       head() { return mFirst; }
+    NODE const* tail() const { return mLast; }
+    NODE*       tail() { return mLast; }
+
+    void insertAfter(NODE* node, NODE* newNode) {
+        newNode->prev = node;
+        newNode->next = node->next;
+        if (node->next == 0) mLast = newNode;
+        else                 node->next->prev = newNode;
+        node->next = newNode;
+    }
+
+    void insertBefore(NODE* node, NODE* newNode) {
+         newNode->prev = node->prev;
+         newNode->next = node;
+         if (node->prev == 0)   mFirst = newNode;
+         else                   node->prev->next = newNode;
+         node->prev = newNode;
+    }
+
+    void insertHead(NODE* newNode) {
+        if (mFirst == 0) {
+            mFirst = mLast = newNode;
+            newNode->prev = newNode->next = 0;
+        } else {
+            newNode->prev = 0;
+            newNode->next = mFirst;
+            mFirst->prev = newNode;
+            mFirst = newNode;
+        }
+    }
+    
+    void insertTail(NODE* newNode) {
+        if (mLast == 0) {
+            insertHead(newNode);
+        } else {
+            newNode->prev = mLast;
+            newNode->next = 0;
+            mLast->next = newNode;
+            mLast = newNode;
+        }
+    }
+
+    NODE* remove(NODE* node) {
+        if (node->prev == 0)    mFirst = node->next;
+        else                    node->prev->next = node->next;
+        if (node->next == 0)    mLast = node->prev;
+        else                    node->next->prev = node->prev;
+        return node;
+    }
+};
+
+class SimpleBestFitAllocator
+{
+public:
+
+    SimpleBestFitAllocator();
+    SimpleBestFitAllocator(size_t size);
+    ~SimpleBestFitAllocator();
+
+    ssize_t     setSize(size_t size);
+
+    ssize_t     allocate(size_t size, uint32_t flags = 0);
+    ssize_t     deallocate(size_t offset);
+    size_t      size() const;
+
+private:
+    struct chunk_t {
+        chunk_t(size_t start, size_t size) 
+            : start(start), size(size), free(1), prev(0), next(0) {
+        }
+        size_t              start;
+        size_t              size : 28;
+        int                 free : 4;
+        mutable chunk_t*    prev;
+        mutable chunk_t*    next;
+    };
+
+    ssize_t  alloc(size_t size, uint32_t flags);
+    chunk_t* dealloc(size_t start);
+
+    static const int    kMemoryAlign;
+    mutable Locker      mLock;
+    LinkedList<chunk_t> mList;
+    size_t              mHeapSize;
+};
+
+#endif /* GRALLOC_ALLOCATOR_H_ */
diff --git a/libgralloc-qsd8k/framebuffer.cpp b/libgralloc-qsd8k/framebuffer.cpp
new file mode 100644
index 0000000..797982f
--- /dev/null
+++ b/libgralloc-qsd8k/framebuffer.cpp
@@ -0,0 +1,437 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <sys/mman.h>
+
+#include <dlfcn.h>
+
+#include <cutils/ashmem.h>
+#include <cutils/log.h>
+
+#include <hardware/hardware.h>
+#include <hardware/gralloc.h>
+
+#include <fcntl.h>
+#include <errno.h>
+#include <sys/ioctl.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include <cutils/log.h>
+#include <cutils/atomic.h>
+
+#include <linux/fb.h>
+#include <linux/msm_mdp.h>
+
+#include <GLES/gl.h>
+
+#include "gralloc_priv.h"
+#include "gr.h"
+
+/*****************************************************************************/
+
+// numbers of buffers for page flipping
+#define NUM_BUFFERS 2
+
+
+enum {
+    PAGE_FLIP = 0x00000001,
+    LOCKED = 0x00000002
+};
+
+struct fb_context_t {
+    framebuffer_device_t  device;
+};
+
+/*****************************************************************************/
+
+static void
+msm_copy_buffer(buffer_handle_t handle, int fd, int width, int height,
+                int x, int y, int w, int h);
+
+static int fb_setSwapInterval(struct framebuffer_device_t* dev,
+            int interval)
+{
+    fb_context_t* ctx = (fb_context_t*)dev;
+    if (interval < dev->minSwapInterval || interval > dev->maxSwapInterval)
+        return -EINVAL;
+    // FIXME: implement fb_setSwapInterval
+    return 0;
+}
+
+static int fb_setUpdateRect(struct framebuffer_device_t* dev,
+        int l, int t, int w, int h)
+{
+    if (((w|h) <= 0) || ((l|t)<0))
+        return -EINVAL;
+        
+    fb_context_t* ctx = (fb_context_t*)dev;
+    private_module_t* m = reinterpret_cast<private_module_t*>(
+            dev->common.module);
+    m->info.reserved[0] = 0x54445055; // "UPDT";
+    m->info.reserved[1] = (uint16_t)l | ((uint32_t)t << 16);
+    m->info.reserved[2] = (uint16_t)(l+w) | ((uint32_t)(t+h) << 16);
+    return 0;
+}
+
+static int fb_post(struct framebuffer_device_t* dev, buffer_handle_t buffer)
+{
+    if (private_handle_t::validate(buffer) < 0)
+        return -EINVAL;
+
+    fb_context_t* ctx = (fb_context_t*)dev;
+
+    private_handle_t const* hnd = reinterpret_cast<private_handle_t const*>(buffer);
+    private_module_t* m = reinterpret_cast<private_module_t*>(
+            dev->common.module);
+    
+    if (m->currentBuffer) {
+        m->base.unlock(&m->base, m->currentBuffer);
+        m->currentBuffer = 0;
+    }
+
+    if (hnd->flags & private_handle_t::PRIV_FLAGS_FRAMEBUFFER) {
+
+        m->base.lock(&m->base, buffer, 
+                private_module_t::PRIV_USAGE_LOCKED_FOR_POST, 
+                0, 0, m->info.xres, m->info.yres, NULL);
+
+        const size_t offset = hnd->base - m->framebuffer->base;
+        m->info.activate = FB_ACTIVATE_VBL;
+        m->info.yoffset = offset / m->finfo.line_length;
+        if (ioctl(m->framebuffer->fd, FBIOPUT_VSCREENINFO, &m->info) == -1) {
+            LOGE("FBIOPUT_VSCREENINFO failed");
+            m->base.unlock(&m->base, buffer); 
+            return -errno;
+        }
+        m->currentBuffer = buffer;
+        
+    } else {
+        // If we can't do the page_flip, just copy the buffer to the front 
+        // FIXME: use copybit HAL instead of memcpy
+        
+        void* fb_vaddr;
+        void* buffer_vaddr;
+        
+        m->base.lock(&m->base, m->framebuffer, 
+                GRALLOC_USAGE_SW_WRITE_RARELY, 
+                0, 0, m->info.xres, m->info.yres,
+                &fb_vaddr);
+
+        m->base.lock(&m->base, buffer, 
+                GRALLOC_USAGE_SW_READ_RARELY, 
+                0, 0, m->info.xres, m->info.yres,
+                &buffer_vaddr);
+
+        //memcpy(fb_vaddr, buffer_vaddr, m->finfo.line_length * m->info.yres);
+
+        msm_copy_buffer(m->framebuffer, m->framebuffer->fd,
+                m->info.xres, m->info.yres,
+                m->info.xoffset, m->info.yoffset,
+                m->info.width, m->info.height);
+
+        m->base.unlock(&m->base, buffer); 
+        m->base.unlock(&m->base, m->framebuffer); 
+    }
+
+    return 0;
+}
+
+static int fb_compositionComplete(struct framebuffer_device_t* dev)
+{
+    // STOPSHIP: Properly implement composition complete callback
+    glFinish();
+
+    return 0;
+}
+
+/*****************************************************************************/
+
+int mapFrameBufferLocked(struct private_module_t* module)
+{
+    // already initialized...
+    if (module->framebuffer) {
+        return 0;
+    }
+        
+    char const * const device_template[] = {
+            "/dev/graphics/fb%u",
+            "/dev/fb%u",
+            0 };
+
+    int fd = -1;
+    int i=0;
+    char name[64];
+
+    while ((fd==-1) && device_template[i]) {
+        snprintf(name, 64, device_template[i], 0);
+        fd = open(name, O_RDWR, 0);
+        i++;
+    }
+    if (fd < 0)
+        return -errno;
+
+    struct fb_fix_screeninfo finfo;
+    if (ioctl(fd, FBIOGET_FSCREENINFO, &finfo) == -1)
+        return -errno;
+
+    struct fb_var_screeninfo info;
+    if (ioctl(fd, FBIOGET_VSCREENINFO, &info) == -1)
+        return -errno;
+
+    info.reserved[0] = 0;
+    info.reserved[1] = 0;
+    info.reserved[2] = 0;
+    info.xoffset = 0;
+    info.yoffset = 0;
+    info.activate = FB_ACTIVATE_NOW;
+
+    /*
+     * Explicitly request 5/6/5
+     */
+    info.bits_per_pixel = 16;
+    info.red.offset     = 11;
+    info.red.length     = 5;
+    info.green.offset   = 5;
+    info.green.length   = 6;
+    info.blue.offset    = 0;
+    info.blue.length    = 5;
+    info.transp.offset  = 0;
+    info.transp.length  = 0;
+
+    /*
+     * Request NUM_BUFFERS screens (at lest 2 for page flipping)
+     */
+    info.yres_virtual = info.yres * NUM_BUFFERS;
+
+
+    uint32_t flags = PAGE_FLIP;
+    if (ioctl(fd, FBIOPUT_VSCREENINFO, &info) == -1) {
+        info.yres_virtual = info.yres;
+        flags &= ~PAGE_FLIP;
+        LOGW("FBIOPUT_VSCREENINFO failed, page flipping not supported");
+    }
+
+    if (info.yres_virtual < info.yres * 2) {
+        // we need at least 2 for page-flipping
+        info.yres_virtual = info.yres;
+        flags &= ~PAGE_FLIP;
+        LOGW("page flipping not supported (yres_virtual=%d, requested=%d)",
+                info.yres_virtual, info.yres*2);
+    }
+
+    if (ioctl(fd, FBIOGET_VSCREENINFO, &info) == -1)
+        return -errno;
+
+    int refreshRate = 1000000000000000LLU /
+    (
+            uint64_t( info.upper_margin + info.lower_margin + info.yres )
+            * ( info.left_margin  + info.right_margin + info.xres )
+            * info.pixclock
+    );
+
+    if (refreshRate == 0) {
+        // bleagh, bad info from the driver
+        refreshRate = 60*1000;  // 60 Hz
+    }
+
+    if (int(info.width) <= 0 || int(info.height) <= 0) {
+        // the driver doesn't return that information
+        // default to 160 dpi
+        info.width  = ((info.xres * 25.4f)/160.0f + 0.5f);
+        info.height = ((info.yres * 25.4f)/160.0f + 0.5f);
+    }
+
+    float xdpi = (info.xres * 25.4f) / info.width;
+    float ydpi = (info.yres * 25.4f) / info.height;
+    float fps  = refreshRate / 1000.0f;
+
+    LOGI(   "using (fd=%d)\n"
+            "id           = %s\n"
+            "xres         = %d px\n"
+            "yres         = %d px\n"
+            "xres_virtual = %d px\n"
+            "yres_virtual = %d px\n"
+            "bpp          = %d\n"
+            "r            = %2u:%u\n"
+            "g            = %2u:%u\n"
+            "b            = %2u:%u\n",
+            fd,
+            finfo.id,
+            info.xres,
+            info.yres,
+            info.xres_virtual,
+            info.yres_virtual,
+            info.bits_per_pixel,
+            info.red.offset, info.red.length,
+            info.green.offset, info.green.length,
+            info.blue.offset, info.blue.length
+    );
+
+    LOGI(   "width        = %d mm (%f dpi)\n"
+            "height       = %d mm (%f dpi)\n"
+            "refresh rate = %.2f Hz\n",
+            info.width,  xdpi,
+            info.height, ydpi,
+            fps
+    );
+
+
+    if (ioctl(fd, FBIOGET_FSCREENINFO, &finfo) == -1)
+        return -errno;
+
+    if (finfo.smem_len <= 0)
+        return -errno;
+
+
+    module->flags = flags;
+    module->info = info;
+    module->finfo = finfo;
+    module->xdpi = xdpi;
+    module->ydpi = ydpi;
+    module->fps = fps;
+
+    /*
+     * map the framebuffer
+     */
+
+    int err;
+    size_t fbSize = roundUpToPageSize(finfo.line_length * info.yres_virtual);
+    module->framebuffer = new private_handle_t(dup(fd), fbSize,
+            private_handle_t::PRIV_FLAGS_USES_PMEM);
+
+    module->numBuffers = info.yres_virtual / info.yres;
+    module->bufferMask = 0;
+
+    void* vaddr = mmap(0, fbSize, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
+    if (vaddr == MAP_FAILED) {
+        LOGE("Error mapping the framebuffer (%s)", strerror(errno));
+        return -errno;
+    }
+    module->framebuffer->base = intptr_t(vaddr);
+    module->framebuffer->phys = intptr_t(finfo.smem_start);
+    memset(vaddr, 0, fbSize);
+    return 0;
+}
+
+static int mapFrameBuffer(struct private_module_t* module)
+{
+    pthread_mutex_lock(&module->lock);
+    int err = mapFrameBufferLocked(module);
+    pthread_mutex_unlock(&module->lock);
+    return err;
+}
+
+/*****************************************************************************/
+
+static int fb_close(struct hw_device_t *dev)
+{
+    fb_context_t* ctx = (fb_context_t*)dev;
+    if (ctx) {
+        free(ctx);
+    }
+    return 0;
+}
+
+int fb_device_open(hw_module_t const* module, const char* name,
+        hw_device_t** device)
+{
+    int status = -EINVAL;
+    if (!strcmp(name, GRALLOC_HARDWARE_FB0)) {
+        alloc_device_t* gralloc_device;
+        status = gralloc_open(module, &gralloc_device);
+        if (status < 0)
+            return status;
+
+        /* initialize our state here */
+        fb_context_t *dev = (fb_context_t*)malloc(sizeof(*dev));
+        memset(dev, 0, sizeof(*dev));
+
+        /* initialize the procs */
+        dev->device.common.tag = HARDWARE_DEVICE_TAG;
+        dev->device.common.version = 0;
+        dev->device.common.module = const_cast<hw_module_t*>(module);
+        dev->device.common.close = fb_close;
+        dev->device.setSwapInterval = fb_setSwapInterval;
+        dev->device.post            = fb_post;
+        dev->device.setUpdateRect = 0;
+        dev->device.compositionComplete = fb_compositionComplete;
+
+        private_module_t* m = (private_module_t*)module;
+        status = mapFrameBuffer(m);
+        if (status >= 0) {
+            int stride = m->finfo.line_length / (m->info.bits_per_pixel >> 3);
+            const_cast<uint32_t&>(dev->device.flags) = 0;
+            const_cast<uint32_t&>(dev->device.width) = m->info.xres;
+            const_cast<uint32_t&>(dev->device.height) = m->info.yres;
+            const_cast<int&>(dev->device.stride) = stride;
+            const_cast<int&>(dev->device.format) = HAL_PIXEL_FORMAT_RGB_565;
+            const_cast<float&>(dev->device.xdpi) = m->xdpi;
+            const_cast<float&>(dev->device.ydpi) = m->ydpi;
+            const_cast<float&>(dev->device.fps) = m->fps;
+            const_cast<int&>(dev->device.minSwapInterval) = 1;
+            const_cast<int&>(dev->device.maxSwapInterval) = 1;
+
+            if (m->finfo.reserved[0] == 0x5444 &&
+                    m->finfo.reserved[1] == 0x5055) {
+                dev->device.setUpdateRect = fb_setUpdateRect;
+                LOGD("UPDATE_ON_DEMAND supported");
+            }
+
+            *device = &dev->device.common;
+        }
+    }
+    return status;
+}
+
+/* Copy a pmem buffer to the framebuffer */
+
+static void
+msm_copy_buffer(buffer_handle_t handle, int fd, int width, int height,
+                int x, int y, int w, int h)
+{
+    struct {
+        unsigned int count;
+        mdp_blit_req req;
+    } blit;
+    private_handle_t *priv = (private_handle_t*) handle;
+
+    memset(&blit, 0, sizeof(blit));
+    blit.count = 1;
+
+    blit.req.flags = 0;
+    blit.req.alpha = 0xff;
+    blit.req.transp_mask = 0xffffffff;
+
+    blit.req.src.width = width;
+    blit.req.src.height = height;
+    blit.req.src.offset = 0;
+    blit.req.src.memory_id = priv->fd;
+
+    blit.req.dst.width = width;
+    blit.req.dst.height = height;
+    blit.req.dst.offset = 0;
+    blit.req.dst.memory_id = fd; 
+    blit.req.dst.format = MDP_RGB_565;
+
+    blit.req.src_rect.x = blit.req.dst_rect.x = x;
+    blit.req.src_rect.y = blit.req.dst_rect.y = y;
+    blit.req.src_rect.w = blit.req.dst_rect.w = w;
+    blit.req.src_rect.h = blit.req.dst_rect.h = h;
+
+    if (ioctl(fd, MSMFB_BLIT, &blit))
+        LOGE("MSMFB_BLIT failed = %d", -errno);
+}
diff --git a/libgralloc-qsd8k/gr.h b/libgralloc-qsd8k/gr.h
new file mode 100644
index 0000000..1775bfa
--- /dev/null
+++ b/libgralloc-qsd8k/gr.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 GR_H_
+#define GR_H_
+
+#include <stdint.h>
+#ifdef HAVE_ANDROID_OS      // just want PAGE_SIZE define
+# include <asm/page.h>
+#else
+# include <sys/user.h>
+#endif
+#include <limits.h>
+#include <sys/cdefs.h>
+#include <hardware/gralloc.h>
+#include <pthread.h>
+#include <errno.h>
+
+#include <cutils/native_handle.h>
+
+/*****************************************************************************/
+
+struct private_module_t;
+struct private_handle_t;
+
+inline size_t roundUpToPageSize(size_t x) {
+    return (x + (PAGE_SIZE-1)) & ~(PAGE_SIZE-1);
+}
+
+int mapFrameBufferLocked(struct private_module_t* module);
+int terminateBuffer(gralloc_module_t const* module, private_handle_t* hnd);
+
+/*****************************************************************************/
+
+class Locker {
+    pthread_mutex_t mutex;
+public:
+    class Autolock {
+        Locker& locker;
+    public:
+        inline Autolock(Locker& locker) : locker(locker) {  locker.lock(); }
+        inline ~Autolock() { locker.unlock(); }
+    };
+    inline Locker()        { pthread_mutex_init(&mutex, 0); }
+    inline ~Locker()       { pthread_mutex_destroy(&mutex); }
+    inline void lock()     { pthread_mutex_lock(&mutex); }
+    inline void unlock()   { pthread_mutex_unlock(&mutex); }
+};
+
+#endif /* GR_H_ */
diff --git a/libgralloc-qsd8k/gralloc.cpp b/libgralloc-qsd8k/gralloc.cpp
new file mode 100644
index 0000000..45746ef
--- /dev/null
+++ b/libgralloc-qsd8k/gralloc.cpp
@@ -0,0 +1,490 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <limits.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <pthread.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <sys/mman.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <sys/ioctl.h>
+
+#include <cutils/ashmem.h>
+#include <cutils/log.h>
+#include <cutils/atomic.h>
+
+#include <hardware/hardware.h>
+#include <hardware/gralloc.h>
+
+#include "gralloc_priv.h"
+#include "allocator.h"
+
+#if HAVE_ANDROID_OS
+#include <linux/android_pmem.h>
+#endif
+
+/*****************************************************************************/
+
+static SimpleBestFitAllocator sAllocator;
+
+/*****************************************************************************/
+
+struct gralloc_context_t {
+    alloc_device_t  device;
+    /* our private data here */
+};
+
+static int gralloc_alloc_buffer(alloc_device_t* dev,
+        size_t size, int usage, buffer_handle_t* pHandle);
+
+/*****************************************************************************/
+
+int fb_device_open(const hw_module_t* module, const char* name,
+        hw_device_t** device);
+
+static int gralloc_device_open(const hw_module_t* module, const char* name,
+        hw_device_t** device);
+
+extern int gralloc_lock(gralloc_module_t const* module,
+        buffer_handle_t handle, int usage,
+        int l, int t, int w, int h,
+        void** vaddr);
+
+extern int gralloc_unlock(gralloc_module_t const* module, 
+        buffer_handle_t handle);
+
+extern int gralloc_register_buffer(gralloc_module_t const* module,
+        buffer_handle_t handle);
+
+extern int gralloc_unregister_buffer(gralloc_module_t const* module,
+        buffer_handle_t handle);
+
+extern int gralloc_perform(struct gralloc_module_t const* module,
+        int operation, ... );
+
+/*****************************************************************************/
+
+static struct hw_module_methods_t gralloc_module_methods = {
+        open: gralloc_device_open
+};
+
+struct private_module_t HAL_MODULE_INFO_SYM = {
+    base: {
+        common: {
+            tag: HARDWARE_MODULE_TAG,
+            version_major: 1,
+            version_minor: 0,
+            id: GRALLOC_HARDWARE_MODULE_ID,
+            name: "Graphics Memory Allocator Module",
+            author: "The Android Open Source Project",
+            methods: &gralloc_module_methods
+        },
+        registerBuffer: gralloc_register_buffer,
+        unregisterBuffer: gralloc_unregister_buffer,
+        lock: gralloc_lock,
+        unlock: gralloc_unlock,
+        perform: gralloc_perform,
+    },
+    framebuffer: 0,
+    flags: 0,
+    numBuffers: 0,
+    bufferMask: 0,
+    lock: PTHREAD_MUTEX_INITIALIZER,
+    currentBuffer: 0,
+    pmem_master: -1,
+    pmem_master_base: 0,
+    master_phys: 0
+};
+
+/*****************************************************************************/
+
+static int gralloc_alloc_framebuffer_locked(alloc_device_t* dev,
+        size_t size, int usage, buffer_handle_t* pHandle)
+{
+    private_module_t* m = reinterpret_cast<private_module_t*>(
+            dev->common.module);
+
+    // allocate the framebuffer
+    if (m->framebuffer == NULL) {
+        // initialize the framebuffer, the framebuffer is mapped once
+        // and forever.
+        int err = mapFrameBufferLocked(m);
+        if (err < 0) {
+            return err;
+        }
+    }
+
+    const uint32_t bufferMask = m->bufferMask;
+    const uint32_t numBuffers = m->numBuffers;
+    const size_t bufferSize = m->finfo.line_length * m->info.yres;
+    if (numBuffers == 1) {
+        // If we have only one buffer, we never use page-flipping. Instead,
+        // we return a regular buffer which will be memcpy'ed to the main
+        // screen when post is called.
+        int newUsage = (usage & ~GRALLOC_USAGE_HW_FB) | GRALLOC_USAGE_HW_2D;
+        return gralloc_alloc_buffer(dev, bufferSize, newUsage, pHandle);
+    }
+
+    if (bufferMask >= ((1LU<<numBuffers)-1)) {
+        // We ran out of buffers.
+        return -ENOMEM;
+    }
+
+    // create a "fake" handles for it
+    intptr_t vaddr = intptr_t(m->framebuffer->base);
+    private_handle_t* hnd = new private_handle_t(dup(m->framebuffer->fd), size,
+            private_handle_t::PRIV_FLAGS_USES_PMEM |
+            private_handle_t::PRIV_FLAGS_FRAMEBUFFER);
+
+    // find a free slot
+    for (uint32_t i=0 ; i<numBuffers ; i++) {
+        if ((bufferMask & (1LU<<i)) == 0) {
+            m->bufferMask |= (1LU<<i);
+            break;
+        }
+        vaddr += bufferSize;
+    }
+    
+    hnd->base = vaddr;
+    hnd->offset = vaddr - intptr_t(m->framebuffer->base);
+    hnd->phys = intptr_t(m->framebuffer->phys) + hnd->offset;
+    *pHandle = hnd;
+
+    return 0;
+}
+
+static int gralloc_alloc_framebuffer(alloc_device_t* dev,
+        size_t size, int usage, buffer_handle_t* pHandle)
+{
+    private_module_t* m = reinterpret_cast<private_module_t*>(
+            dev->common.module);
+    pthread_mutex_lock(&m->lock);
+    int err = gralloc_alloc_framebuffer_locked(dev, size, usage, pHandle);
+    pthread_mutex_unlock(&m->lock);
+    return err;
+}
+
+
+static int init_pmem_area_locked(private_module_t* m)
+{
+    int err = 0;
+    int master_fd = open("/dev/pmem", O_RDWR, 0);
+    if (master_fd >= 0) {
+        size_t size;
+        pmem_region region;
+        if (ioctl(master_fd, PMEM_GET_TOTAL_SIZE, &region) < 0) {
+            LOGE("PMEM_GET_TOTAL_SIZE failed, limp mode");
+            size = 8<<20;   // 8 MiB
+        } else {
+            size = region.len;
+        }
+        sAllocator.setSize(size);
+
+        void* base = mmap(0, size, 
+                PROT_READ|PROT_WRITE, MAP_SHARED, master_fd, 0);
+        if (base == MAP_FAILED) {
+            err = -errno;
+            base = 0;
+            close(master_fd);
+            master_fd = -1;
+        } else {
+            // FIXME: get physical address, eventually this will have to go away
+            pmem_region region;
+            err = ioctl(master_fd, PMEM_GET_PHYS, &region);
+            if (err < 0) {
+                LOGE("PMEM_GET_PHYS failed (%s)", strerror(-errno));
+            } else {
+                m->master_phys = (unsigned long)region.offset;
+            }
+        }
+        m->pmem_master = master_fd;
+        m->pmem_master_base = base;
+    } else {
+        err = -errno;
+    }
+    return err;
+}
+
+static int init_pmem_area(private_module_t* m)
+{
+    pthread_mutex_lock(&m->lock);
+    int err = m->pmem_master;
+    if (err == -1) {
+        // first time, try to initialize pmem
+        err = init_pmem_area_locked(m);
+        if (err) {
+            m->pmem_master = err;
+        }
+    } else if (err < 0) {
+        // pmem couldn't be initialized, never use it
+    } else {
+        // pmem OK
+        err = 0;
+    }
+    pthread_mutex_unlock(&m->lock);
+    return err;
+}
+
+static int gralloc_alloc_buffer(alloc_device_t* dev,
+        size_t size, int usage, buffer_handle_t* pHandle)
+{
+    int err = 0;
+    int flags = 0;
+
+    int fd = -1;
+    void* base = 0;
+    int offset = 0;
+    int lockState = 0;
+
+    size = roundUpToPageSize(size);
+    
+    if (usage & GRALLOC_USAGE_HW_TEXTURE) {
+        // enable pmem in that case, so our software GL can fallback to
+        // the copybit module.
+        flags |= private_handle_t::PRIV_FLAGS_USES_PMEM;
+    }
+    
+    if (usage & GRALLOC_USAGE_HW_2D) {
+        flags |= private_handle_t::PRIV_FLAGS_USES_PMEM;
+    }
+
+    if ((flags & private_handle_t::PRIV_FLAGS_USES_PMEM) == 0) {
+try_ashmem:
+        fd = ashmem_create_region("gralloc-buffer", size);
+        if (fd < 0) {
+            LOGE("couldn't create ashmem (%s)", strerror(errno));
+            err = -errno;
+        }
+    } else {
+        private_module_t* m = reinterpret_cast<private_module_t*>(
+                dev->common.module);
+
+        err = init_pmem_area(m);
+        if (err == 0) {
+            // PMEM buffers are always mmapped
+            base = m->pmem_master_base;
+            lockState |= private_handle_t::LOCK_STATE_MAPPED;
+
+            offset = sAllocator.allocate(size);
+            if (offset < 0) {
+                // no more pmem memory
+                err = -ENOMEM;
+            } else {
+                struct pmem_region sub = { offset, size };
+                
+                // now create the "sub-heap"
+                fd = open("/dev/pmem", O_RDWR, 0);
+                err = fd < 0 ? fd : 0;
+                
+                // and connect to it
+                if (err == 0)
+                    err = ioctl(fd, PMEM_CONNECT, m->pmem_master);
+
+                // and make it available to the client process
+                if (err == 0)
+                    err = ioctl(fd, PMEM_MAP, &sub);
+
+                if (err < 0) {
+                    err = -errno;
+                    close(fd);
+                    sAllocator.deallocate(offset);
+                    fd = -1;
+                }
+                memset((char*)base + offset, 0, size);
+                //LOGD_IF(!err, "allocating pmem size=%d, offset=%d", size, offset);
+            }
+        } else {
+            if ((usage & GRALLOC_USAGE_HW_2D) == 0) {
+                // the caller didn't request PMEM, so we can try something else
+                flags &= ~private_handle_t::PRIV_FLAGS_USES_PMEM;
+                err = 0;
+                goto try_ashmem;
+            } else {
+                LOGE("couldn't open pmem (%s)", strerror(errno));
+            }
+        }
+    }
+
+    if (err == 0) {
+        private_handle_t* hnd = new private_handle_t(fd, size, flags);
+        hnd->offset = offset;
+        hnd->base = int(base)+offset;
+        hnd->lockState = lockState;
+        if (flags & private_handle_t::PRIV_FLAGS_USES_PMEM) {
+            private_module_t* m = reinterpret_cast<private_module_t*>(
+                    dev->common.module);
+            hnd->phys = m->master_phys + offset;
+        }
+        *pHandle = hnd;
+    }
+    
+    LOGE_IF(err, "gralloc failed err=%s", strerror(-err));
+    
+    return err;
+}
+
+/*****************************************************************************/
+
+static int gralloc_alloc(alloc_device_t* dev,
+        int w, int h, int format, int usage,
+        buffer_handle_t* pHandle, int* pStride)
+{
+    if (!pHandle || !pStride)
+        return -EINVAL;
+
+    size_t size, alignedw, alignedh;
+    if (format == HAL_PIXEL_FORMAT_YCbCr_420_SP || 
+            format == HAL_PIXEL_FORMAT_YCbCr_422_SP) 
+    {
+        // FIXME: there is no way to return the alignedh
+        alignedw = (w + 1) & ~1;
+        switch (format) {
+            case HAL_PIXEL_FORMAT_YCbCr_420_SP:
+                size = alignedw * h * 2;
+                break;
+            case HAL_PIXEL_FORMAT_YCbCr_422_SP:
+                alignedh = (h+1) & ~1;
+                size = (alignedw * alignedh) + (w/2 * h/2) * 2;
+                break;
+            default:
+                return -EINVAL;
+        }
+    } else {
+        alignedw = (w + 31) & ~31;
+        alignedh = (h + 31) & ~31;
+        int bpp = 0;
+        switch (format) {
+            case HAL_PIXEL_FORMAT_RGBA_8888:
+            case HAL_PIXEL_FORMAT_RGBX_8888:
+            case HAL_PIXEL_FORMAT_BGRA_8888:
+                bpp = 4;
+                break;
+            case HAL_PIXEL_FORMAT_RGB_888:
+                bpp = 3;
+                break;
+            case HAL_PIXEL_FORMAT_RGB_565:
+            case HAL_PIXEL_FORMAT_RGBA_5551:
+            case HAL_PIXEL_FORMAT_RGBA_4444:
+                bpp = 2;
+                break;
+            default:
+                return -EINVAL;
+        }
+        size = alignedw * alignedh * bpp;
+    }
+
+    int err;
+    if (usage & GRALLOC_USAGE_HW_FB) {
+        err = gralloc_alloc_framebuffer(dev, size, usage, pHandle);
+    } else {
+        err = gralloc_alloc_buffer(dev, size, usage, pHandle);
+    }
+
+    if (err < 0) {
+        return err;
+    }
+
+    *pStride = alignedw;
+    return 0;
+}
+
+static int gralloc_free(alloc_device_t* dev,
+        buffer_handle_t handle)
+{
+    if (private_handle_t::validate(handle) < 0)
+        return -EINVAL;
+
+    private_handle_t const* hnd = reinterpret_cast<private_handle_t const*>(handle);
+    if (hnd->flags & private_handle_t::PRIV_FLAGS_FRAMEBUFFER) {
+        // free this buffer
+        private_module_t* m = reinterpret_cast<private_module_t*>(
+                dev->common.module);
+        const size_t bufferSize = m->finfo.line_length * m->info.yres;
+        int index = (hnd->base - m->framebuffer->base) / bufferSize;
+        m->bufferMask &= ~(1<<index); 
+    } else { 
+        if (hnd->flags & private_handle_t::PRIV_FLAGS_USES_PMEM) {
+            if (hnd->fd >= 0) {
+                struct pmem_region sub = { hnd->offset, hnd->size };
+                int err = ioctl(hnd->fd, PMEM_UNMAP, &sub);
+                LOGE_IF(err<0, "PMEM_UNMAP failed (%s), "
+                        "fd=%d, sub.offset=%lu, sub.size=%lu",
+                        strerror(errno), hnd->fd, hnd->offset, hnd->size);
+                if (err == 0) {
+                    // we can't deallocate the memory in case of UNMAP failure
+                    // because it would give that process access to someone else's
+                    // surfaces, which would be a security breach.
+                    sAllocator.deallocate(hnd->offset);
+                }
+            }
+        }
+
+        gralloc_module_t* module = reinterpret_cast<gralloc_module_t*>(
+                dev->common.module);
+        terminateBuffer(module, const_cast<private_handle_t*>(hnd));
+    }
+
+    close(hnd->fd);
+    delete hnd;
+    return 0;
+}
+
+/*****************************************************************************/
+
+static int gralloc_close(struct hw_device_t *dev)
+{
+    gralloc_context_t* ctx = reinterpret_cast<gralloc_context_t*>(dev);
+    if (ctx) {
+        /* TODO: keep a list of all buffer_handle_t created, and free them
+         * all here.
+         */
+        free(ctx);
+    }
+    return 0;
+}
+
+int gralloc_device_open(const hw_module_t* module, const char* name,
+        hw_device_t** device)
+{
+    int status = -EINVAL;
+    if (!strcmp(name, GRALLOC_HARDWARE_GPU0)) {
+        gralloc_context_t *dev;
+        dev = (gralloc_context_t*)malloc(sizeof(*dev));
+
+        /* initialize our state here */
+        memset(dev, 0, sizeof(*dev));
+
+        /* initialize the procs */
+        dev->device.common.tag = HARDWARE_DEVICE_TAG;
+        dev->device.common.version = 0;
+        dev->device.common.module = const_cast<hw_module_t*>(module);
+        dev->device.common.close = gralloc_close;
+
+        dev->device.alloc   = gralloc_alloc;
+        dev->device.free    = gralloc_free;
+
+        *device = &dev->device.common;
+        status = 0;
+    } else {
+        status = fb_device_open(module, name, device);
+    }
+    return status;
+}
diff --git a/libgralloc-qsd8k/gralloc_priv.h b/libgralloc-qsd8k/gralloc_priv.h
new file mode 100644
index 0000000..534b4c0
--- /dev/null
+++ b/libgralloc-qsd8k/gralloc_priv.h
@@ -0,0 +1,140 @@
+/*
+ * 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 GRALLOC_PRIV_H_
+#define GRALLOC_PRIV_H_
+
+#include <stdint.h>
+#include <limits.h>
+#include <sys/cdefs.h>
+#include <hardware/gralloc.h>
+#include <pthread.h>
+#include <errno.h>
+#include <unistd.h>
+
+#include <cutils/native_handle.h>
+
+#include <linux/fb.h>
+
+/*****************************************************************************/
+
+struct private_module_t;
+struct private_handle_t;
+
+struct private_module_t {
+    gralloc_module_t base;
+
+    struct private_handle_t* framebuffer;
+    uint32_t flags;
+    uint32_t numBuffers;
+    uint32_t bufferMask;
+    pthread_mutex_t lock;
+    buffer_handle_t currentBuffer;
+    int pmem_master;
+    void* pmem_master_base;
+    unsigned long master_phys;
+
+    struct fb_var_screeninfo info;
+    struct fb_fix_screeninfo finfo;
+    float xdpi;
+    float ydpi;
+    float fps;
+    
+    enum {
+        // flag to indicate we'll post this buffer
+        PRIV_USAGE_LOCKED_FOR_POST = 0x80000000
+    };
+};
+
+/*****************************************************************************/
+
+#ifdef __cplusplus
+struct private_handle_t : public native_handle {
+#else
+struct private_handle_t {
+    native_handle_t nativeHandle;
+#endif
+    
+    enum {
+        PRIV_FLAGS_FRAMEBUFFER = 0x00000001,
+        PRIV_FLAGS_USES_PMEM   = 0x00000002,
+    };
+
+    enum {
+        LOCK_STATE_WRITE     =   1<<31,
+        LOCK_STATE_MAPPED    =   1<<30,
+        LOCK_STATE_READ_MASK =   0x3FFFFFFF
+    };
+
+    // file-descriptors
+    int     fd;
+    // ints
+    int     magic;
+    int     flags;
+    int     size;
+    int     offset;
+    int     gpu_fd; // stored as an int, b/c we don't want it marshalled
+
+    // FIXME: the attributes below should be out-of-line
+    int     base;
+    int     lockState;
+    int     writeOwner;
+    int     phys; // The physical address of that chunk of memory. If using ashmem, set to 0 They don't care
+    int     pid;
+
+#ifdef __cplusplus
+    static const int sNumInts = 10;
+    static const int sNumFds = 1;
+    static const int sMagic = 'gmsm';
+
+    private_handle_t(int fd, int size, int flags) :
+        fd(fd), magic(sMagic), flags(flags), size(size), offset(0), gpu_fd(-1),
+        base(0), lockState(0), writeOwner(0), phys(0), pid(getpid())
+    {
+        version = sizeof(native_handle);
+        numInts = sNumInts;
+        numFds = sNumFds;
+    }
+    ~private_handle_t() {
+        magic = 0;
+    }
+
+    bool usesPhysicallyContiguousMemory() {
+        return (flags & PRIV_FLAGS_USES_PMEM) != 0;
+    }
+
+    static int validate(const native_handle* h) {
+        const private_handle_t* hnd = (const private_handle_t*)h;
+        if (!h || h->version != sizeof(native_handle) ||
+                h->numInts != sNumInts || h->numFds != sNumFds ||
+                hnd->magic != sMagic) 
+        {
+            LOGE("invalid gralloc handle (at %p)", h);
+            return -EINVAL;
+        }
+        return 0;
+    }
+
+    static private_handle_t* dynamicCast(const native_handle* in) {
+        if (validate(in) == 0) {
+            return (private_handle_t*) in;
+        }
+        return NULL;
+    }
+#endif
+};
+
+#endif /* GRALLOC_PRIV_H_ */
diff --git a/libgralloc-qsd8k/mapper.cpp b/libgralloc-qsd8k/mapper.cpp
new file mode 100644
index 0000000..8c199b3
--- /dev/null
+++ b/libgralloc-qsd8k/mapper.cpp
@@ -0,0 +1,322 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <limits.h>
+#include <errno.h>
+#include <pthread.h>
+#include <unistd.h>
+#include <string.h>
+#include <stdarg.h>
+
+#include <sys/mman.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+
+#include <cutils/log.h>
+#include <cutils/atomic.h>
+
+#include <hardware/hardware.h>
+#include <hardware/gralloc.h>
+
+#include "gralloc_priv.h"
+
+
+// we need this for now because pmem cannot mmap at an offset
+#define PMEM_HACK   1
+
+/* desktop Linux needs a little help with gettid() */
+#if defined(ARCH_X86) && !defined(HAVE_ANDROID_OS)
+#define __KERNEL__
+# include <linux/unistd.h>
+pid_t gettid() { return syscall(__NR_gettid);}
+#undef __KERNEL__
+#endif
+
+/*****************************************************************************/
+
+static int gralloc_map(gralloc_module_t const* module,
+        buffer_handle_t handle,
+        void** vaddr)
+{
+    private_handle_t* hnd = (private_handle_t*)handle;
+    if (!(hnd->flags & private_handle_t::PRIV_FLAGS_FRAMEBUFFER)) {
+        size_t size = hnd->size;
+#if PMEM_HACK
+        size += hnd->offset;
+#endif
+        void* mappedAddress = mmap(0, size,
+                PROT_READ|PROT_WRITE, MAP_SHARED, hnd->fd, 0);
+        if (mappedAddress == MAP_FAILED) {
+            LOGE("Could not mmap handle %p, fd=%d (%s)",
+                    handle, hnd->fd, strerror(errno));
+            hnd->base = 0;
+            return -errno;
+        }
+        hnd->base = intptr_t(mappedAddress) + hnd->offset;
+        //LOGD("gralloc_map() succeeded fd=%d, off=%d, size=%d, vaddr=%p", 
+        //        hnd->fd, hnd->offset, hnd->size, mappedAddress);
+    }
+    *vaddr = (void*)hnd->base;
+    return 0;
+}
+
+static int gralloc_unmap(gralloc_module_t const* module,
+        buffer_handle_t handle)
+{
+    private_handle_t* hnd = (private_handle_t*)handle;
+    if (!(hnd->flags & private_handle_t::PRIV_FLAGS_FRAMEBUFFER)) {
+        void* base = (void*)hnd->base;
+        size_t size = hnd->size;
+#if PMEM_HACK
+        base = (void*)(intptr_t(base) - hnd->offset);
+        size += hnd->offset;
+#endif
+        //LOGD("unmapping from %p, size=%d", base, size);
+        if (munmap(base, size) < 0) {
+            LOGE("Could not unmap %s", strerror(errno));
+        }
+    }
+    hnd->base = 0;
+    return 0;
+}
+
+/*****************************************************************************/
+
+static pthread_mutex_t sMapLock = PTHREAD_MUTEX_INITIALIZER; 
+
+/*****************************************************************************/
+
+int gralloc_register_buffer(gralloc_module_t const* module,
+        buffer_handle_t handle)
+{
+    if (private_handle_t::validate(handle) < 0)
+        return -EINVAL;
+
+    // In this implementation, we don't need to do anything here
+
+    /* NOTE: we need to initialize the buffer as not mapped/not locked
+     * because it shouldn't when this function is called the first time
+     * in a new process. Ideally these flags shouldn't be part of the
+     * handle, but instead maintained in the kernel or at least 
+     * out-of-line
+     */ 
+
+    // if this handle was created in this process, then we keep it as is.
+    private_handle_t* hnd = (private_handle_t*)handle;
+    if (hnd->pid != getpid()) {
+        hnd->base = 0;
+        hnd->lockState  = 0;
+        hnd->writeOwner = 0;
+    }
+    return 0;
+}
+
+int gralloc_unregister_buffer(gralloc_module_t const* module,
+        buffer_handle_t handle)
+{
+    if (private_handle_t::validate(handle) < 0)
+        return -EINVAL;
+
+    /*
+     * If the buffer has been mapped during a lock operation, it's time
+     * to un-map it. It's an error to be here with a locked buffer.
+     * NOTE: the framebuffer is handled differently and is never unmapped.
+     */
+
+    private_handle_t* hnd = (private_handle_t*)handle;
+    
+    LOGE_IF(hnd->lockState & private_handle_t::LOCK_STATE_READ_MASK,
+            "[unregister] handle %p still locked (state=%08x)",
+            hnd, hnd->lockState);
+
+    // never unmap buffers that were created in this process
+    if (hnd->pid != getpid()) {
+        if (hnd->lockState & private_handle_t::LOCK_STATE_MAPPED) {
+            gralloc_unmap(module, handle);
+        }
+        hnd->base = 0;
+        hnd->lockState  = 0;
+        hnd->writeOwner = 0;
+    }
+    return 0;
+}
+
+int terminateBuffer(gralloc_module_t const* module,
+        private_handle_t* hnd)
+{
+    /*
+     * If the buffer has been mapped during a lock operation, it's time
+     * to un-map it. It's an error to be here with a locked buffer.
+     */
+
+    LOGE_IF(hnd->lockState & private_handle_t::LOCK_STATE_READ_MASK,
+            "[terminate] handle %p still locked (state=%08x)",
+            hnd, hnd->lockState);
+
+    if (hnd->lockState & private_handle_t::LOCK_STATE_MAPPED) {
+        // this buffer was mapped, unmap it now
+        if (hnd->flags & private_handle_t::PRIV_FLAGS_USES_PMEM) {
+            if (hnd->pid != getpid()) {
+                // ... unless it's a "master" pmem buffer, that is a buffer
+                // mapped in the process it's been allocated.
+                // (see gralloc_alloc_buffer())
+                gralloc_unmap(module, hnd);
+            }
+        } else {
+            gralloc_unmap(module, hnd);
+        }
+    }
+
+    return 0;
+}
+
+int gralloc_lock(gralloc_module_t const* module,
+        buffer_handle_t handle, int usage,
+        int l, int t, int w, int h,
+        void** vaddr)
+{
+    if (private_handle_t::validate(handle) < 0)
+        return -EINVAL;
+
+    int err = 0;
+    private_handle_t* hnd = (private_handle_t*)handle;
+    int32_t current_value, new_value;
+    int retry;
+
+    do {
+        current_value = hnd->lockState;
+        new_value = current_value;
+
+        if (current_value & private_handle_t::LOCK_STATE_WRITE) {
+            // already locked for write 
+            LOGE("handle %p already locked for write", handle);
+            return -EBUSY;
+        } else if (current_value & private_handle_t::LOCK_STATE_READ_MASK) {
+            // already locked for read
+            if (usage & (GRALLOC_USAGE_SW_WRITE_MASK | GRALLOC_USAGE_HW_RENDER)) {
+                LOGE("handle %p already locked for read", handle);
+                return -EBUSY;
+            } else {
+                // this is not an error
+                //LOGD("%p already locked for read... count = %d", 
+                //        handle, (current_value & ~(1<<31)));
+            }
+        }
+
+        // not currently locked
+        if (usage & (GRALLOC_USAGE_SW_WRITE_MASK | GRALLOC_USAGE_HW_RENDER)) {
+            // locking for write
+            new_value |= private_handle_t::LOCK_STATE_WRITE;
+        }
+        new_value++;
+
+        retry = android_atomic_cmpxchg(current_value, new_value, 
+                (volatile int32_t*)&hnd->lockState);
+    } while (retry);
+
+    if (new_value & private_handle_t::LOCK_STATE_WRITE) {
+        // locking for write, store the tid
+        hnd->writeOwner = gettid();
+    }
+
+    if (usage & (GRALLOC_USAGE_SW_READ_MASK | GRALLOC_USAGE_SW_WRITE_MASK)) {
+        if (!(current_value & private_handle_t::LOCK_STATE_MAPPED)) {
+            // we need to map for real
+            pthread_mutex_t* const lock = &sMapLock;
+            pthread_mutex_lock(lock);
+            if (!(hnd->lockState & private_handle_t::LOCK_STATE_MAPPED)) {
+                err = gralloc_map(module, handle, vaddr);
+                if (err == 0) {
+                    android_atomic_or(private_handle_t::LOCK_STATE_MAPPED,
+                            (volatile int32_t*)&(hnd->lockState));
+                }
+            }
+            pthread_mutex_unlock(lock);
+        }
+        *vaddr = (void*)hnd->base;
+    }
+
+    return err;
+}
+
+int gralloc_unlock(gralloc_module_t const* module, 
+        buffer_handle_t handle)
+{
+    if (private_handle_t::validate(handle) < 0)
+        return -EINVAL;
+
+    private_handle_t* hnd = (private_handle_t*)handle;
+    int32_t current_value, new_value;
+
+    do {
+        current_value = hnd->lockState;
+        new_value = current_value;
+
+        if (current_value & private_handle_t::LOCK_STATE_WRITE) {
+            // locked for write
+            if (hnd->writeOwner == gettid()) {
+                hnd->writeOwner = 0;
+                new_value &= ~private_handle_t::LOCK_STATE_WRITE;
+            }
+        }
+
+        if ((new_value & private_handle_t::LOCK_STATE_READ_MASK) == 0) {
+            LOGE("handle %p not locked", handle);
+            return -EINVAL;
+        }
+
+        new_value--;
+
+    } while (android_atomic_cmpxchg(current_value, new_value, 
+            (volatile int32_t*)&hnd->lockState));
+
+    return 0;
+}
+
+/*****************************************************************************/
+
+int gralloc_perform(struct gralloc_module_t const* module,
+        int operation, ... )
+{
+    int res = -EINVAL;
+    va_list args;
+    va_start(args, operation);
+
+    switch (operation) {
+        case GRALLOC_MODULE_PERFORM_CREATE_HANDLE_FROM_BUFFER: {
+            int fd = va_arg(args, int);
+            size_t size = va_arg(args, size_t);
+            size_t offset = va_arg(args, size_t);
+            void* base = va_arg(args, void*);
+            native_handle_t** handle = va_arg(args, native_handle_t**);
+            private_handle_t* hnd = (private_handle_t*)native_handle_create(
+                    private_handle_t::sNumFds, private_handle_t::sNumInts);
+            hnd->magic = private_handle_t::sMagic;
+            hnd->fd = fd;
+            hnd->flags = private_handle_t::PRIV_FLAGS_USES_PMEM;
+            hnd->size = size;
+            hnd->offset = offset;
+            hnd->base = intptr_t(base) + offset;
+            hnd->lockState = private_handle_t::LOCK_STATE_MAPPED;
+            *handle = (native_handle_t *)hnd;
+            res = 0;
+            break;
+        }
+    }
+
+    va_end(args);
+    return res;
+}