am 5ca15ccf: Reconcile with jb-release

* commit '5ca15ccf7336d5aa5a7b563742757fa37092eb48':
  Revert input buffer count for the SoftAAC* decoders back to 4.
diff --git a/libvideoeditor/lvpp/Android.mk b/libvideoeditor/lvpp/Android.mk
index c018d74..0ed7e6c 100755
--- a/libvideoeditor/lvpp/Android.mk
+++ b/libvideoeditor/lvpp/Android.mk
@@ -59,6 +59,7 @@
     libstagefright            \
     libstagefright_foundation \
     libstagefright_omx        \
+    libsync                   \
     libui                     \
     libutils                  \
     libvideoeditor_osal       \
diff --git a/libvideoeditor/lvpp/NativeWindowRenderer.cpp b/libvideoeditor/lvpp/NativeWindowRenderer.cpp
index b2c2675..2e15ff9 100755
--- a/libvideoeditor/lvpp/NativeWindowRenderer.cpp
+++ b/libvideoeditor/lvpp/NativeWindowRenderer.cpp
@@ -22,9 +22,9 @@
 #include <cutils/log.h>
 #include <gui/SurfaceTexture.h>
 #include <gui/SurfaceTextureClient.h>
-#include <media/stagefright/foundation/ADebug.h>
 #include <media/stagefright/MediaBuffer.h>
 #include <media/stagefright/MetaData.h>
+#include <media/stagefright/foundation/ADebug.h>
 #include "VideoEditorTools.h"
 
 #define CHECK_EGL_ERROR CHECK(EGL_SUCCESS == eglGetError())
@@ -382,7 +382,7 @@
     int64_t timeUs;
     CHECK(buffer->meta_data()->findInt64(kKeyTime, &timeUs));
     native_window_set_buffers_timestamp(anw, timeUs * 1000);
-    status_t err = anw->queueBuffer(anw, buffer->graphicBuffer().get());
+    status_t err = anw->queueBuffer(anw, buffer->graphicBuffer().get(), -1);
     if (err != 0) {
         ALOGE("queueBuffer failed with error %s (%d)", strerror(-err), -err);
         return;
@@ -399,18 +399,16 @@
     native_window_set_usage(anw, GRALLOC_USAGE_SW_WRITE_OFTEN);
 
     ANativeWindowBuffer* anb;
-    anw->dequeueBuffer(anw, &anb);
+    CHECK(NO_ERROR == native_window_dequeue_buffer_and_wait(anw, &anb));
     CHECK(anb != NULL);
 
-    sp<GraphicBuffer> buf(new GraphicBuffer(anb, false));
-    CHECK(NO_ERROR == anw->lockBuffer(anw, buf->getNativeBuffer()));
-
     // Copy the buffer
     uint8_t* img = NULL;
+    sp<GraphicBuffer> buf(new GraphicBuffer(anb, false));
     buf->lock(GRALLOC_USAGE_SW_WRITE_OFTEN, (void**)(&img));
     copyI420Buffer(buffer, img, width, height, buf->getStride());
     buf->unlock();
-    CHECK(NO_ERROR == anw->queueBuffer(anw, buf->getNativeBuffer()));
+    CHECK(NO_ERROR == anw->queueBuffer(anw, buf->getNativeBuffer(), -1));
 }
 
 void NativeWindowRenderer::copyI420Buffer(MediaBuffer* src, uint8_t* dst,
diff --git a/libvideoeditor/lvpp/PreviewRenderer.cpp b/libvideoeditor/lvpp/PreviewRenderer.cpp
index 4aa4eb3..b1cfc8e 100755
--- a/libvideoeditor/lvpp/PreviewRenderer.cpp
+++ b/libvideoeditor/lvpp/PreviewRenderer.cpp
@@ -97,13 +97,12 @@
 void PreviewRenderer::getBufferYV12(uint8_t **data, size_t *stride) {
     int err = OK;
 
-    if ((err = mSurface->ANativeWindow::dequeueBuffer(mSurface.get(), &mBuf)) != 0) {
-        ALOGW("Surface::dequeueBuffer returned error %d", err);
+    if ((err = native_window_dequeue_buffer_and_wait(mSurface.get(),
+            &mBuf)) != 0) {
+        ALOGW("native_window_dequeue_buffer_and_wait returned error %d", err);
         return;
     }
 
-    CHECK_EQ(0, mSurface->ANativeWindow::lockBuffer(mSurface.get(), mBuf));
-
     GraphicBufferMapper &mapper = GraphicBufferMapper::get();
 
     Rect bounds(mWidth, mHeight);
@@ -131,7 +130,7 @@
     if (mBuf!= NULL) {
         CHECK_EQ(0, mapper.unlock(mBuf->handle));
 
-        if ((err = mSurface->ANativeWindow::queueBuffer(mSurface.get(), mBuf)) != 0) {
+        if ((err = mSurface->ANativeWindow::queueBuffer(mSurface.get(), mBuf, -1)) != 0) {
             ALOGW("Surface::queueBuffer returned error %d", err);
         }
     }
diff --git a/media/libstagefright/ACodec.cpp b/media/libstagefright/ACodec.cpp
index c4743a1..b4894e9 100644
--- a/media/libstagefright/ACodec.cpp
+++ b/media/libstagefright/ACodec.cpp
@@ -595,7 +595,7 @@
     // Dequeue buffers and send them to OMX
     for (OMX_U32 i = 0; i < def.nBufferCountActual; i++) {
         ANativeWindowBuffer *buf;
-        err = mNativeWindow->dequeueBuffer(mNativeWindow.get(), &buf);
+        err = native_window_dequeue_buffer_and_wait(mNativeWindow.get(), &buf);
         if (err != 0) {
             ALOGE("dequeueBuffer failed: %s (%d)", strerror(-err), -err);
             break;
@@ -653,7 +653,7 @@
          mComponentName.c_str(), info->mBufferID);
 
     int err = mNativeWindow->cancelBuffer(
-        mNativeWindow.get(), info->mGraphicBuffer.get());
+        mNativeWindow.get(), info->mGraphicBuffer.get(), -1);
 
     CHECK_EQ(err, 0);
 
@@ -664,7 +664,8 @@
 
 ACodec::BufferInfo *ACodec::dequeueBufferFromNativeWindow() {
     ANativeWindowBuffer *buf;
-    if (mNativeWindow->dequeueBuffer(mNativeWindow.get(), &buf) != 0) {
+    int fenceFd = -1;
+    if (native_window_dequeue_buffer_and_wait(mNativeWindow.get(), &buf) != 0) {
         ALOGE("dequeueBuffer failed.");
         return NULL;
     }
@@ -2188,7 +2189,8 @@
     // on the screen and then been replaced, so an previous video frames are
     // guaranteed NOT to be currently displayed.
     for (int i = 0; i < numBufs + 1; i++) {
-        err = mNativeWindow->dequeueBuffer(mNativeWindow.get(), &anb);
+        int fenceFd = -1;
+        err = native_window_dequeue_buffer_and_wait(mNativeWindow.get(), &anb);
         if (err != NO_ERROR) {
             ALOGE("error pushing blank frames: dequeueBuffer failed: %s (%d)",
                     strerror(-err), -err);
@@ -2196,13 +2198,6 @@
         }
 
         sp<GraphicBuffer> buf(new GraphicBuffer(anb, false));
-        err = mNativeWindow->lockBuffer(mNativeWindow.get(),
-                buf->getNativeBuffer());
-        if (err != NO_ERROR) {
-            ALOGE("error pushing blank frames: lockBuffer failed: %s (%d)",
-                    strerror(-err), -err);
-            goto error;
-        }
 
         // Fill the buffer with the a 1x1 checkerboard pattern ;)
         uint32_t* img = NULL;
@@ -2223,7 +2218,7 @@
         }
 
         err = mNativeWindow->queueBuffer(mNativeWindow.get(),
-                buf->getNativeBuffer());
+                buf->getNativeBuffer(), -1);
         if (err != NO_ERROR) {
             ALOGE("error pushing blank frames: queueBuffer failed: %s (%d)",
                     strerror(-err), -err);
@@ -2238,7 +2233,7 @@
     if (err != NO_ERROR) {
         // Clean up after an error.
         if (anb != NULL) {
-            mNativeWindow->cancelBuffer(mNativeWindow.get(), anb);
+            mNativeWindow->cancelBuffer(mNativeWindow.get(), anb, -1);
         }
 
         native_window_api_disconnect(mNativeWindow.get(),
@@ -2751,7 +2746,7 @@
         status_t err;
         if ((err = mCodec->mNativeWindow->queueBuffer(
                     mCodec->mNativeWindow.get(),
-                    info->mGraphicBuffer.get())) == OK) {
+                    info->mGraphicBuffer.get(), -1)) == OK) {
             info->mStatus = BufferInfo::OWNED_BY_NATIVE_WINDOW;
         } else {
             mCodec->signalError(OMX_ErrorUndefined, err);
@@ -3253,11 +3248,6 @@
             if (info->mStatus == BufferInfo::OWNED_BY_NATIVE_WINDOW) {
                 continue;
             }
-
-            status_t err = mCodec->mNativeWindow->lockBuffer(
-                    mCodec->mNativeWindow.get(),
-                    info->mGraphicBuffer.get());
-            CHECK_EQ(err, (status_t)OK);
         } else {
             CHECK_EQ((int)info->mStatus, (int)BufferInfo::OWNED_BY_US);
         }
diff --git a/media/libstagefright/Android.mk b/media/libstagefright/Android.mk
index 8ad1cb9..e5b4d75 100644
--- a/media/libstagefright/Android.mk
+++ b/media/libstagefright/Android.mk
@@ -81,6 +81,7 @@
         libssl \
         libstagefright_omx \
         libstagefright_yuv \
+        libsync \
         libui \
         libutils \
         libvorbisidec \
@@ -97,12 +98,12 @@
         libstagefright_id3 \
         libFLAC \
 
-ifneq ($(TARGET_BUILD_PDK), true)
-LOCAL_STATIC_LIBRARIES += \
-	libstagefright_chromium_http
-LOCAL_SHARED_LIBRARIES += \
-        libchromium_net
+LOCAL_SRC_FILES += \
+        chromium_http_stub.cpp
 LOCAL_CPPFLAGS += -DCHROMIUM_AVAILABLE=1
+
+ifneq ($(TARGET_BUILD_PDK), true)
+LOCAL_REQUIRED_MODULES := libstagefright_chromium_http
 endif
 
 LOCAL_SHARED_LIBRARIES += libstlport
diff --git a/media/libstagefright/AwesomePlayer.cpp b/media/libstagefright/AwesomePlayer.cpp
index 0f346d8..2c68075 100644
--- a/media/libstagefright/AwesomePlayer.cpp
+++ b/media/libstagefright/AwesomePlayer.cpp
@@ -130,7 +130,7 @@
         CHECK(buffer->meta_data()->findInt64(kKeyTime, &timeUs));
         native_window_set_buffers_timestamp(mNativeWindow.get(), timeUs * 1000);
         status_t err = mNativeWindow->queueBuffer(
-                mNativeWindow.get(), buffer->graphicBuffer().get());
+                mNativeWindow.get(), buffer->graphicBuffer().get(), -1);
         if (err != 0) {
             ALOGE("queueBuffer failed with error %s (%d)", strerror(-err),
                     -err);
diff --git a/media/libstagefright/DataSource.cpp b/media/libstagefright/DataSource.cpp
index c75f100..1de808e 100644
--- a/media/libstagefright/DataSource.cpp
+++ b/media/libstagefright/DataSource.cpp
@@ -17,7 +17,7 @@
 #include "include/AMRExtractor.h"
 
 #if CHROMIUM_AVAILABLE
-#include "include/DataUriSource.h"
+#include "include/chromium_http_stub.h"
 #endif
 
 #include "include/MP3Extractor.h"
@@ -173,7 +173,7 @@
 
 # if CHROMIUM_AVAILABLE
     } else if (!strncasecmp("data:", uri, 5)) {
-        source = new DataUriSource(uri);
+        source = createDataUriSource(uri);
 #endif
     } else {
         // Assume it's a filename.
diff --git a/media/libstagefright/FLACExtractor.cpp b/media/libstagefright/FLACExtractor.cpp
index 668d7f7..29bb056 100644
--- a/media/libstagefright/FLACExtractor.cpp
+++ b/media/libstagefright/FLACExtractor.cpp
@@ -350,7 +350,7 @@
         for (FLAC__uint32 i = 0; i < vc->num_comments; ++i) {
             FLAC__StreamMetadata_VorbisComment_Entry *vce;
             vce = &vc->comments[i];
-            if (mFileMetadata != 0) {
+            if (mFileMetadata != 0 && vce->entry != NULL) {
                 parseVorbisComment(mFileMetadata, (const char *) vce->entry,
                         vce->length);
             }
diff --git a/media/libstagefright/HTTPBase.cpp b/media/libstagefright/HTTPBase.cpp
index d7eea3f..40bfc55 100644
--- a/media/libstagefright/HTTPBase.cpp
+++ b/media/libstagefright/HTTPBase.cpp
@@ -21,7 +21,7 @@
 #include "include/HTTPBase.h"
 
 #if CHROMIUM_AVAILABLE
-#include "include/ChromiumHTTPDataSource.h"
+#include "include/chromium_http_stub.h"
 #endif
 
 #include <media/stagefright/foundation/ADebug.h>
@@ -46,7 +46,10 @@
 // static
 sp<HTTPBase> HTTPBase::Create(uint32_t flags) {
 #if CHROMIUM_AVAILABLE
-        return new ChromiumHTTPDataSource(flags);
+        HTTPBase *dataSource = createChromiumHTTPDataSource(flags);
+        if (dataSource) {
+           return dataSource;
+        }
 #endif
     {
         TRESPASS();
diff --git a/media/libstagefright/OMXCodec.cpp b/media/libstagefright/OMXCodec.cpp
index fde7ebf..1d4ab32 100755
--- a/media/libstagefright/OMXCodec.cpp
+++ b/media/libstagefright/OMXCodec.cpp
@@ -1776,7 +1776,7 @@
     // Dequeue buffers and send them to OMX
     for (OMX_U32 i = 0; i < def.nBufferCountActual; i++) {
         ANativeWindowBuffer* buf;
-        err = mNativeWindow->dequeueBuffer(mNativeWindow.get(), &buf);
+        err = native_window_dequeue_buffer_and_wait(mNativeWindow.get(), &buf);
         if (err != 0) {
             ALOGE("dequeueBuffer failed: %s (%d)", strerror(-err), -err);
             break;
@@ -1832,7 +1832,7 @@
     CHECK_EQ((int)info->mStatus, (int)OWNED_BY_US);
     CODEC_LOGV("Calling cancelBuffer on buffer %p", info->mBuffer);
     int err = mNativeWindow->cancelBuffer(
-        mNativeWindow.get(), info->mMediaBuffer->graphicBuffer().get());
+        mNativeWindow.get(), info->mMediaBuffer->graphicBuffer().get(), -1);
     if (err != 0) {
       CODEC_LOGE("cancelBuffer failed w/ error 0x%08x", err);
 
@@ -1846,7 +1846,8 @@
 OMXCodec::BufferInfo* OMXCodec::dequeueBufferFromNativeWindow() {
     // Dequeue the next buffer from the native window.
     ANativeWindowBuffer* buf;
-    int err = mNativeWindow->dequeueBuffer(mNativeWindow.get(), &buf);
+    int fenceFd = -1;
+    int err = native_window_dequeue_buffer_and_wait(mNativeWindow.get(), &buf);
     if (err != 0) {
       CODEC_LOGE("dequeueBuffer failed w/ error 0x%08x", err);
 
@@ -1950,7 +1951,8 @@
     // on the screen and then been replaced, so an previous video frames are
     // guaranteed NOT to be currently displayed.
     for (int i = 0; i < numBufs + 1; i++) {
-        err = mNativeWindow->dequeueBuffer(mNativeWindow.get(), &anb);
+        int fenceFd = -1;
+        err = native_window_dequeue_buffer_and_wait(mNativeWindow.get(), &anb);
         if (err != NO_ERROR) {
             ALOGE("error pushing blank frames: dequeueBuffer failed: %s (%d)",
                     strerror(-err), -err);
@@ -1958,13 +1960,6 @@
         }
 
         sp<GraphicBuffer> buf(new GraphicBuffer(anb, false));
-        err = mNativeWindow->lockBuffer(mNativeWindow.get(),
-                buf->getNativeBuffer());
-        if (err != NO_ERROR) {
-            ALOGE("error pushing blank frames: lockBuffer failed: %s (%d)",
-                    strerror(-err), -err);
-            goto error;
-        }
 
         // Fill the buffer with the a 1x1 checkerboard pattern ;)
         uint32_t* img = NULL;
@@ -1985,7 +1980,7 @@
         }
 
         err = mNativeWindow->queueBuffer(mNativeWindow.get(),
-                buf->getNativeBuffer());
+                buf->getNativeBuffer(), -1);
         if (err != NO_ERROR) {
             ALOGE("error pushing blank frames: queueBuffer failed: %s (%d)",
                     strerror(-err), -err);
@@ -2000,7 +1995,7 @@
     if (err != NO_ERROR) {
         // Clean up after an error.
         if (anb != NULL) {
-            mNativeWindow->cancelBuffer(mNativeWindow.get(), anb);
+            mNativeWindow->cancelBuffer(mNativeWindow.get(), anb, -1);
         }
 
         native_window_api_disconnect(mNativeWindow.get(),
@@ -3199,23 +3194,6 @@
         return;
     }
 
-    if (info->mMediaBuffer != NULL) {
-        sp<GraphicBuffer> graphicBuffer = info->mMediaBuffer->graphicBuffer();
-        if (graphicBuffer != 0) {
-            // When using a native buffer we need to lock the buffer before
-            // giving it to OMX.
-            CODEC_LOGV("Calling lockBuffer on %p", info->mBuffer);
-            int err = mNativeWindow->lockBuffer(mNativeWindow.get(),
-                    graphicBuffer.get());
-            if (err != 0) {
-                CODEC_LOGE("lockBuffer failed w/ error 0x%08x", err);
-
-                setState(ERROR);
-                return;
-            }
-        }
-    }
-
     CODEC_LOGV("Calling fillBuffer on buffer %p", info->mBuffer);
     status_t err = mOMX->fillBuffer(mNode, info->mBuffer);
 
diff --git a/media/libstagefright/chromium_http/Android.mk b/media/libstagefright/chromium_http/Android.mk
index 6ab2a00..2c6d84c 100644
--- a/media/libstagefright/chromium_http/Android.mk
+++ b/media/libstagefright/chromium_http/Android.mk
@@ -6,7 +6,8 @@
 LOCAL_SRC_FILES:=       \
         DataUriSource.cpp \
         ChromiumHTTPDataSource.cpp \
-        support.cpp
+        support.cpp \
+        chromium_http_stub.cpp
 
 LOCAL_C_INCLUDES:= \
         $(TOP)/frameworks/av/media/libstagefright \
@@ -16,10 +17,20 @@
 
 LOCAL_CFLAGS += -Wno-multichar
 
-LOCAL_SHARED_LIBRARIES += libstlport
+LOCAL_SHARED_LIBRARIES += \
+        libstlport \
+        libchromium_net \
+        libutils \
+        libcutils \
+        libstagefright_foundation \
+        libstagefright \
+        libdrmframework
+
 include external/stlport/libstlport.mk
 
 LOCAL_MODULE:= libstagefright_chromium_http
 
-include $(BUILD_STATIC_LIBRARY)
+LOCAL_MODULE_TAGS := optional
+
+include $(BUILD_SHARED_LIBRARY)
 endif
diff --git a/media/libstagefright/chromium_http/chromium_http_stub.cpp b/media/libstagefright/chromium_http/chromium_http_stub.cpp
new file mode 100644
index 0000000..560a61f
--- /dev/null
+++ b/media/libstagefright/chromium_http/chromium_http_stub.cpp
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2012 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 <dlfcn.h>
+
+#include <include/chromium_http_stub.h>
+#include <include/ChromiumHTTPDataSource.h>
+#include <include/DataUriSource.h>
+
+namespace android {
+
+HTTPBase *createChromiumHTTPDataSource(uint32_t flags) {
+    return new ChromiumHTTPDataSource(flags);
+}
+
+DataSource *createDataUriSource(const char *uri) {
+    return new DataUriSource(uri);
+}
+
+}
diff --git a/media/libstagefright/chromium_http_stub.cpp b/media/libstagefright/chromium_http_stub.cpp
new file mode 100644
index 0000000..cbd8796
--- /dev/null
+++ b/media/libstagefright/chromium_http_stub.cpp
@@ -0,0 +1,81 @@
+/*
+ * Copyright (C) 2012 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 <dlfcn.h>
+
+#include <media/stagefright/DataSource.h>
+
+#include "include/chromium_http_stub.h"
+#include "include/HTTPBase.h"
+
+namespace android {
+
+static bool gFirst = true;
+static void *gHandle;
+static Mutex gLibMutex;
+
+HTTPBase *(*gLib_createChromiumHTTPDataSource)(uint32_t flags);
+DataSource *(*gLib_createDataUriSource)(const char *uri);
+
+static bool load_libstagefright_chromium_http() {
+    Mutex::Autolock autoLock(gLibMutex);
+    void *sym;
+
+    if (!gFirst) {
+        return (gHandle != NULL);
+    }
+
+    gFirst = false;
+
+    gHandle = dlopen("libstagefright_chromium_http.so", RTLD_NOW);
+    if (gHandle == NULL) {
+        return false;
+    }
+
+    sym = dlsym(gHandle, "createChromiumHTTPDataSource");
+    if (sym == NULL) {
+        gHandle = NULL;
+        return false;
+    }
+    gLib_createChromiumHTTPDataSource = (HTTPBase *(*)(uint32_t))sym;
+
+    sym = dlsym(gHandle, "createDataUriSource");
+    if (sym == NULL) {
+        gHandle = NULL;
+        return false;
+    }
+    gLib_createDataUriSource = (DataSource *(*)(const char *))sym;
+
+    return true;
+}
+
+HTTPBase *createChromiumHTTPDataSource(uint32_t flags) {
+    if (!load_libstagefright_chromium_http()) {
+        return NULL;
+    }
+
+    return gLib_createChromiumHTTPDataSource(flags);
+}
+
+DataSource *createDataUriSource(const char *uri) {
+    if (!load_libstagefright_chromium_http()) {
+        return NULL;
+    }
+
+    return gLib_createDataUriSource(uri);
+}
+
+}
diff --git a/media/libstagefright/colorconversion/SoftwareRenderer.cpp b/media/libstagefright/colorconversion/SoftwareRenderer.cpp
index 8673bad..2704a37 100644
--- a/media/libstagefright/colorconversion/SoftwareRenderer.cpp
+++ b/media/libstagefright/colorconversion/SoftwareRenderer.cpp
@@ -141,13 +141,12 @@
         const void *data, size_t size, void *platformPrivate) {
     ANativeWindowBuffer *buf;
     int err;
-    if ((err = mNativeWindow->dequeueBuffer(mNativeWindow.get(), &buf)) != 0) {
+    if ((err = native_window_dequeue_buffer_and_wait(mNativeWindow.get(),
+            &buf)) != 0) {
         ALOGW("Surface::dequeueBuffer returned error %d", err);
         return;
     }
 
-    CHECK_EQ(0, mNativeWindow->lockBuffer(mNativeWindow.get(), buf));
-
     GraphicBufferMapper &mapper = GraphicBufferMapper::get();
 
     Rect bounds(mCropWidth, mCropHeight);
@@ -231,7 +230,8 @@
 
     CHECK_EQ(0, mapper.unlock(buf->handle));
 
-    if ((err = mNativeWindow->queueBuffer(mNativeWindow.get(), buf)) != 0) {
+    if ((err = mNativeWindow->queueBuffer(mNativeWindow.get(), buf,
+            -1)) != 0) {
         ALOGW("Surface::queueBuffer returned error %d", err);
     }
     buf = NULL;
diff --git a/media/libstagefright/include/chromium_http_stub.h b/media/libstagefright/include/chromium_http_stub.h
new file mode 100644
index 0000000..869d4ac
--- /dev/null
+++ b/media/libstagefright/include/chromium_http_stub.h
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2012 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 CHROMIUM_HTTP_STUB_H_
+#define CHROMIUM_HTTP_STUB_H_
+
+#include <include/HTTPBase.h>
+#include <media/stagefright/DataSource.h>
+
+namespace android {
+extern "C" {
+HTTPBase *createChromiumHTTPDataSource(uint32_t flags);
+DataSource *createDataUriSource(const char *uri);
+}
+}
+
+#endif
diff --git a/media/libstagefright/tests/Android.mk b/media/libstagefright/tests/Android.mk
index a1e6be7..57fff0b 100644
--- a/media/libstagefright/tests/Android.mk
+++ b/media/libstagefright/tests/Android.mk
@@ -20,9 +20,10 @@
 	libgui \
 	libmedia \
 	libstagefright \
-	libstagefright_omx \
 	libstagefright_foundation \
+	libstagefright_omx \
 	libstlport \
+	libsync \
 	libui \
 	libutils \
 
diff --git a/media/libstagefright/tests/SurfaceMediaSource_test.cpp b/media/libstagefright/tests/SurfaceMediaSource_test.cpp
index 466f521..cc2aca7 100644
--- a/media/libstagefright/tests/SurfaceMediaSource_test.cpp
+++ b/media/libstagefright/tests/SurfaceMediaSource_test.cpp
@@ -509,31 +509,31 @@
 // cpu YV12 buffer
 void SurfaceMediaSourceTest::oneBufferPass(int width, int height ) {
     ANativeWindowBuffer* anb;
-    ASSERT_EQ(NO_ERROR, mANW->dequeueBuffer(mANW.get(), &anb));
+    ASSERT_EQ(NO_ERROR, native_window_dequeue_buffer_and_wait(mANW.get(), &anb));
     ASSERT_TRUE(anb != NULL);
 
-    sp<GraphicBuffer> buf(new GraphicBuffer(anb, false));
-    ASSERT_EQ(NO_ERROR, mANW->lockBuffer(mANW.get(), buf->getNativeBuffer()));
 
     // Fill the buffer with the a checkerboard pattern
     uint8_t* img = NULL;
+    sp<GraphicBuffer> buf(new GraphicBuffer(anb, false));
     buf->lock(GRALLOC_USAGE_SW_WRITE_OFTEN, (void**)(&img));
     SurfaceMediaSourceTest::fillYV12Buffer(img, width, height, buf->getStride());
     buf->unlock();
 
-    ASSERT_EQ(NO_ERROR, mANW->queueBuffer(mANW.get(), buf->getNativeBuffer()));
+    ASSERT_EQ(NO_ERROR, mANW->queueBuffer(mANW.get(), buf->getNativeBuffer(),
+            -1));
 }
 
 // Dequeuing and queuing the buffer without really filling it in.
 void SurfaceMediaSourceTest::oneBufferPassNoFill(int width, int height ) {
     ANativeWindowBuffer* anb;
-    ASSERT_EQ(NO_ERROR, mANW->dequeueBuffer(mANW.get(), &anb));
+    ASSERT_EQ(NO_ERROR, native_window_dequeue_buffer_and_wait(mANW.get(), &anb));
     ASSERT_TRUE(anb != NULL);
 
-    sp<GraphicBuffer> buf(new GraphicBuffer(anb, false));
-    // ASSERT_EQ(NO_ERROR, mANW->lockBuffer(mANW.get(), buf->getNativeBuffer()));
     // We do not fill the buffer in. Just queue it back.
-    ASSERT_EQ(NO_ERROR, mANW->queueBuffer(mANW.get(), buf->getNativeBuffer()));
+    sp<GraphicBuffer> buf(new GraphicBuffer(anb, false));
+    ASSERT_EQ(NO_ERROR, mANW->queueBuffer(mANW.get(), buf->getNativeBuffer(),
+            -1));
 }
 
 // Fill a YV12 buffer with a multi-colored checkerboard pattern
@@ -652,7 +652,7 @@
     ANativeWindowBuffer* anb;
 
     // Note: make sure we get an ERROR back when dequeuing!
-    ASSERT_NE(NO_ERROR, mANW->dequeueBuffer(mANW.get(), &anb));
+    ASSERT_NE(NO_ERROR, native_window_dequeue_buffer_and_wait(mANW.get(), &anb));
 }
 
 // pass multiple buffers from the native_window the SurfaceMediaSource
diff --git a/services/audioflinger/AudioPolicyService.cpp b/services/audioflinger/AudioPolicyService.cpp
index 0d13970..c32fc6b 100644
--- a/services/audioflinger/AudioPolicyService.cpp
+++ b/services/audioflinger/AudioPolicyService.cpp
@@ -373,6 +373,7 @@
     if (uint32_t(stream) >= AUDIO_STREAM_CNT) {
         return BAD_VALUE;
     }
+    Mutex::Autolock _l(mLock);
     mpAudioPolicy->init_stream_volume(mpAudioPolicy, stream, indexMin, indexMax);
     return NO_ERROR;
 }
@@ -390,7 +391,7 @@
     if (uint32_t(stream) >= AUDIO_STREAM_CNT) {
         return BAD_VALUE;
     }
-
+    Mutex::Autolock _l(mLock);
     if (mpAudioPolicy->set_stream_volume_index_for_device) {
         return mpAudioPolicy->set_stream_volume_index_for_device(mpAudioPolicy,
                                                                 stream,
@@ -411,6 +412,7 @@
     if (uint32_t(stream) >= AUDIO_STREAM_CNT) {
         return BAD_VALUE;
     }
+    Mutex::Autolock _l(mLock);
     if (mpAudioPolicy->get_stream_volume_index_for_device) {
         return mpAudioPolicy->get_stream_volume_index_for_device(mpAudioPolicy,
                                                                 stream,
diff --git a/services/camera/libcameraservice/Android.mk b/services/camera/libcameraservice/Android.mk
index 3cae1f5..8cccf49 100644
--- a/services/camera/libcameraservice/Android.mk
+++ b/services/camera/libcameraservice/Android.mk
@@ -7,7 +7,10 @@
 include $(CLEAR_VARS)
 
 LOCAL_SRC_FILES:=               \
-    CameraService.cpp
+    CameraService.cpp \
+    CameraClient.cpp \
+    Camera2Client.cpp \
+    Camera2Device.cpp
 
 LOCAL_SHARED_LIBRARIES:= \
     libui \
@@ -18,7 +21,12 @@
     libmedia_native \
     libcamera_client \
     libgui \
-    libhardware
+    libhardware \
+    libsync \
+    libcamera_metadata
+
+LOCAL_C_INCLUDES += \
+    system/media/camera/include
 
 LOCAL_MODULE:= libcameraservice
 
diff --git a/services/camera/libcameraservice/Camera2Client.cpp b/services/camera/libcameraservice/Camera2Client.cpp
new file mode 100644
index 0000000..c90f81a
--- /dev/null
+++ b/services/camera/libcameraservice/Camera2Client.cpp
@@ -0,0 +1,2730 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "Camera2Client"
+#define ATRACE_TAG ATRACE_TAG_CAMERA
+//#define LOG_NDEBUG 0
+
+#include <utils/Log.h>
+#include <utils/Trace.h>
+
+#include <cutils/properties.h>
+#include <gui/SurfaceTextureClient.h>
+#include <gui/Surface.h>
+
+#include <math.h>
+
+#include "Camera2Client.h"
+
+namespace android {
+
+#define ALOG1(...) ALOGD_IF(gLogLevel >= 1, __VA_ARGS__);
+#define ALOG2(...) ALOGD_IF(gLogLevel >= 2, __VA_ARGS__);
+
+static int getCallingPid() {
+    return IPCThreadState::self()->getCallingPid();
+}
+
+static int getCallingUid() {
+    return IPCThreadState::self()->getCallingUid();
+}
+
+// Interface used by CameraService
+
+Camera2Client::Camera2Client(const sp<CameraService>& cameraService,
+        const sp<ICameraClient>& cameraClient,
+        int cameraId,
+        int cameraFacing,
+        int clientPid):
+        Client(cameraService, cameraClient,
+                cameraId, cameraFacing, clientPid),
+        mState(NOT_INITIALIZED),
+        mPreviewStreamId(NO_STREAM),
+        mPreviewRequest(NULL),
+        mCaptureStreamId(NO_STREAM),
+        mCaptureRequest(NULL)
+{
+    ATRACE_CALL();
+
+    mDevice = new Camera2Device(cameraId);
+}
+
+status_t Camera2Client::initialize(camera_module_t *module)
+{
+    ATRACE_CALL();
+    status_t res;
+
+    res = mDevice->initialize(module);
+    if (res != OK) {
+        ALOGE("%s: Camera %d: unable to initialize device: %s (%d)",
+                __FUNCTION__, mCameraId, strerror(-res), res);
+        return NO_INIT;
+    }
+
+    res = buildDefaultParameters();
+    if (res != OK) {
+        ALOGE("%s: Camera %d: unable to build defaults: %s (%d)",
+                __FUNCTION__, mCameraId, strerror(-res), res);
+        return NO_INIT;
+    }
+
+    if (gLogLevel >= 1) {
+        ALOGD("%s: Default parameters converted from camera %d:", __FUNCTION__,
+              mCameraId);
+        ALOGD("%s", mParamsFlattened.string());
+    }
+
+    mState = STOPPED;
+
+    return OK;
+}
+
+Camera2Client::~Camera2Client() {
+    ATRACE_CALL();
+    ALOGV("%s: Camera %d: Shutting down", __FUNCTION__, mCameraId);
+
+    mDestructionStarted = true;
+
+    disconnect();
+
+}
+
+status_t Camera2Client::dump(int fd, const Vector<String16>& args) {
+    String8 result;
+    result.appendFormat("Client2[%d] (%p) PID: %d, dump:\n",
+            mCameraId,
+            getCameraClient()->asBinder().get(),
+            mClientPid);
+    result.append("  State: ");
+#define CASE_APPEND_ENUM(x) case x: result.append(#x "\n"); break;
+
+    result.append(getStateName(mState));
+
+    result.append("\n  Current parameters:\n");
+    result.appendFormat("    Preview size: %d x %d\n",
+            mParameters.previewWidth, mParameters.previewHeight);
+    result.appendFormat("    Preview FPS range: %d - %d\n",
+            mParameters.previewFpsRange[0], mParameters.previewFpsRange[1]);
+    result.appendFormat("    Preview HAL pixel format: 0x%x\n",
+            mParameters.previewFormat);
+    result.appendFormat("    Preview transform: %x\n",
+            mParameters.previewTransform);
+    result.appendFormat("    Picture size: %d x %d\n",
+            mParameters.pictureWidth, mParameters.pictureHeight);
+    result.appendFormat("    Jpeg thumbnail size: %d x %d\n",
+            mParameters.jpegThumbSize[0], mParameters.jpegThumbSize[1]);
+    result.appendFormat("    Jpeg quality: %d, thumbnail quality: %d\n",
+            mParameters.jpegQuality, mParameters.jpegThumbQuality);
+    result.appendFormat("    Jpeg rotation: %d\n", mParameters.jpegRotation);
+    result.appendFormat("    GPS tags %s\n",
+            mParameters.gpsEnabled ? "enabled" : "disabled");
+    if (mParameters.gpsEnabled) {
+        result.appendFormat("    GPS lat x long x alt: %f x %f x %f\n",
+                mParameters.gpsCoordinates[0], mParameters.gpsCoordinates[1],
+                mParameters.gpsCoordinates[2]);
+        result.appendFormat("    GPS timestamp: %lld\n",
+                mParameters.gpsTimestamp);
+        result.appendFormat("    GPS processing method: %s\n",
+                mParameters.gpsProcessingMethod.string());
+    }
+
+    result.append("    White balance mode: ");
+    switch (mParameters.wbMode) {
+        CASE_APPEND_ENUM(ANDROID_CONTROL_AWB_AUTO)
+        CASE_APPEND_ENUM(ANDROID_CONTROL_AWB_INCANDESCENT)
+        CASE_APPEND_ENUM(ANDROID_CONTROL_AWB_FLUORESCENT)
+        CASE_APPEND_ENUM(ANDROID_CONTROL_AWB_WARM_FLUORESCENT)
+        CASE_APPEND_ENUM(ANDROID_CONTROL_AWB_DAYLIGHT)
+        CASE_APPEND_ENUM(ANDROID_CONTROL_AWB_CLOUDY_DAYLIGHT)
+        CASE_APPEND_ENUM(ANDROID_CONTROL_AWB_TWILIGHT)
+        CASE_APPEND_ENUM(ANDROID_CONTROL_AWB_SHADE)
+        default: result.append("UNKNOWN\n");
+    }
+
+    result.append("    Effect mode: ");
+    switch (mParameters.effectMode) {
+        CASE_APPEND_ENUM(ANDROID_CONTROL_EFFECT_OFF)
+        CASE_APPEND_ENUM(ANDROID_CONTROL_EFFECT_MONO)
+        CASE_APPEND_ENUM(ANDROID_CONTROL_EFFECT_NEGATIVE)
+        CASE_APPEND_ENUM(ANDROID_CONTROL_EFFECT_SOLARIZE)
+        CASE_APPEND_ENUM(ANDROID_CONTROL_EFFECT_SEPIA)
+        CASE_APPEND_ENUM(ANDROID_CONTROL_EFFECT_POSTERIZE)
+        CASE_APPEND_ENUM(ANDROID_CONTROL_EFFECT_WHITEBOARD)
+        CASE_APPEND_ENUM(ANDROID_CONTROL_EFFECT_BLACKBOARD)
+        CASE_APPEND_ENUM(ANDROID_CONTROL_EFFECT_AQUA)
+        default: result.append("UNKNOWN\n");
+    }
+
+    result.append("    Antibanding mode: ");
+    switch (mParameters.antibandingMode) {
+        CASE_APPEND_ENUM(ANDROID_CONTROL_AE_ANTIBANDING_AUTO)
+        CASE_APPEND_ENUM(ANDROID_CONTROL_AE_ANTIBANDING_OFF)
+        CASE_APPEND_ENUM(ANDROID_CONTROL_AE_ANTIBANDING_50HZ)
+        CASE_APPEND_ENUM(ANDROID_CONTROL_AE_ANTIBANDING_60HZ)
+        default: result.append("UNKNOWN\n");
+    }
+
+    result.append("    Scene mode: ");
+    switch (mParameters.sceneMode) {
+        case ANDROID_CONTROL_SCENE_MODE_UNSUPPORTED:
+            result.append("AUTO\n"); break;
+        CASE_APPEND_ENUM(ANDROID_CONTROL_SCENE_MODE_ACTION)
+        CASE_APPEND_ENUM(ANDROID_CONTROL_SCENE_MODE_PORTRAIT)
+        CASE_APPEND_ENUM(ANDROID_CONTROL_SCENE_MODE_LANDSCAPE)
+        CASE_APPEND_ENUM(ANDROID_CONTROL_SCENE_MODE_NIGHT)
+        CASE_APPEND_ENUM(ANDROID_CONTROL_SCENE_MODE_NIGHT_PORTRAIT)
+        CASE_APPEND_ENUM(ANDROID_CONTROL_SCENE_MODE_THEATRE)
+        CASE_APPEND_ENUM(ANDROID_CONTROL_SCENE_MODE_BEACH)
+        CASE_APPEND_ENUM(ANDROID_CONTROL_SCENE_MODE_SNOW)
+        CASE_APPEND_ENUM(ANDROID_CONTROL_SCENE_MODE_SUNSET)
+        CASE_APPEND_ENUM(ANDROID_CONTROL_SCENE_MODE_STEADYPHOTO)
+        CASE_APPEND_ENUM(ANDROID_CONTROL_SCENE_MODE_FIREWORKS)
+        CASE_APPEND_ENUM(ANDROID_CONTROL_SCENE_MODE_SPORTS)
+        CASE_APPEND_ENUM(ANDROID_CONTROL_SCENE_MODE_PARTY)
+        CASE_APPEND_ENUM(ANDROID_CONTROL_SCENE_MODE_CANDLELIGHT)
+        CASE_APPEND_ENUM(ANDROID_CONTROL_SCENE_MODE_BARCODE)
+        default: result.append("UNKNOWN\n");
+    }
+
+    result.append("    Flash mode: ");
+    switch (mParameters.flashMode) {
+        CASE_APPEND_ENUM(Parameters::FLASH_MODE_OFF)
+        CASE_APPEND_ENUM(Parameters::FLASH_MODE_AUTO)
+        CASE_APPEND_ENUM(Parameters::FLASH_MODE_ON)
+        CASE_APPEND_ENUM(Parameters::FLASH_MODE_TORCH)
+        CASE_APPEND_ENUM(Parameters::FLASH_MODE_RED_EYE)
+        CASE_APPEND_ENUM(Parameters::FLASH_MODE_INVALID)
+        default: result.append("UNKNOWN\n");
+    }
+
+    result.append("    Focus mode: ");
+    switch (mParameters.focusMode) {
+        CASE_APPEND_ENUM(Parameters::FOCUS_MODE_AUTO)
+        CASE_APPEND_ENUM(Parameters::FOCUS_MODE_MACRO)
+        CASE_APPEND_ENUM(Parameters::FOCUS_MODE_CONTINUOUS_VIDEO)
+        CASE_APPEND_ENUM(Parameters::FOCUS_MODE_CONTINUOUS_PICTURE)
+        CASE_APPEND_ENUM(Parameters::FOCUS_MODE_EDOF)
+        CASE_APPEND_ENUM(Parameters::FOCUS_MODE_INFINITY)
+        CASE_APPEND_ENUM(Parameters::FOCUS_MODE_FIXED)
+        CASE_APPEND_ENUM(Parameters::FOCUS_MODE_INVALID)
+        default: result.append("UNKNOWN\n");
+    }
+
+    result.append("    Focusing areas:\n");
+    for (size_t i = 0; i < mParameters.focusingAreas.size(); i++) {
+        result.appendFormat("      [ (%d, %d, %d, %d), weight %d ]\n",
+                mParameters.focusingAreas[i].left,
+                mParameters.focusingAreas[i].top,
+                mParameters.focusingAreas[i].right,
+                mParameters.focusingAreas[i].bottom,
+                mParameters.focusingAreas[i].weight);
+    }
+
+    result.appendFormat("    Exposure compensation index: %d\n",
+            mParameters.exposureCompensation);
+
+    result.appendFormat("    AE lock %s, AWB lock %s\n",
+            mParameters.autoExposureLock ? "enabled" : "disabled",
+            mParameters.autoWhiteBalanceLock ? "enabled" : "disabled" );
+
+    result.appendFormat("    Metering areas:\n");
+    for (size_t i = 0; i < mParameters.meteringAreas.size(); i++) {
+        result.appendFormat("      [ (%d, %d, %d, %d), weight %d ]\n",
+                mParameters.meteringAreas[i].left,
+                mParameters.meteringAreas[i].top,
+                mParameters.meteringAreas[i].right,
+                mParameters.meteringAreas[i].bottom,
+                mParameters.meteringAreas[i].weight);
+    }
+
+    result.appendFormat("    Zoom index: %d\n", mParameters.zoom);
+    result.appendFormat("    Video size: %d x %d\n", mParameters.videoWidth,
+            mParameters.videoHeight);
+
+    result.appendFormat("    Recording hint is %s\n",
+            mParameters.recordingHint ? "set" : "not set");
+
+    result.appendFormat("    Video stabilization is %s\n",
+            mParameters.videoStabilization ? "enabled" : "disabled");
+
+    result.append("  Current streams:\n");
+    result.appendFormat("    Preview stream ID: %d\n", mPreviewStreamId);
+    result.appendFormat("    Capture stream ID: %d\n", mCaptureStreamId);
+
+    result.append("  Current requests:\n");
+    if (mPreviewRequest != NULL) {
+        result.append("    Preview request:\n");
+        write(fd, result.string(), result.size());
+        dump_camera_metadata(mPreviewRequest, fd, 2);
+    } else {
+        result.append("    Preview request: undefined\n");
+        write(fd, result.string(), result.size());
+    }
+
+    if (mCaptureRequest != NULL) {
+        result = "    Capture request:\n";
+        write(fd, result.string(), result.size());
+        dump_camera_metadata(mCaptureRequest, fd, 2);
+    } else {
+        result = "    Capture request: undefined\n";
+        write(fd, result.string(), result.size());
+    }
+
+    result = "  Device dump:\n";
+    write(fd, result.string(), result.size());
+
+    status_t res = mDevice->dump(fd, args);
+    if (res != OK) {
+        result = String8::format("   Error dumping device: %s (%d)",
+                strerror(-res), res);
+        write(fd, result.string(), result.size());
+    }
+
+#undef CASE_APPEND_ENUM
+    return NO_ERROR;
+}
+
+const char* Camera2Client::getStateName(State state) {
+#define CASE_ENUM_TO_CHAR(x) case x: return(#x); break;
+    switch(state) {
+        CASE_ENUM_TO_CHAR(NOT_INITIALIZED)
+        CASE_ENUM_TO_CHAR(STOPPED)
+        CASE_ENUM_TO_CHAR(WAITING_FOR_PREVIEW_WINDOW)
+        CASE_ENUM_TO_CHAR(PREVIEW)
+        CASE_ENUM_TO_CHAR(RECORD)
+        CASE_ENUM_TO_CHAR(STILL_CAPTURE)
+        CASE_ENUM_TO_CHAR(VIDEO_SNAPSHOT)
+        default:
+            return "Unknown state!";
+            break;
+    }
+#undef CASE_ENUM_TO_CHAR
+}
+
+// ICamera interface
+
+void Camera2Client::disconnect() {
+    ATRACE_CALL();
+    Mutex::Autolock icl(mICameraLock);
+
+    if (mDevice == 0) return;
+
+    stopPreviewLocked();
+
+    mDevice->waitUntilDrained();
+
+    if (mPreviewStreamId != NO_STREAM) {
+        mDevice->deleteStream(mPreviewStreamId);
+        mPreviewStreamId = NO_STREAM;
+    }
+
+    if (mCaptureStreamId != NO_STREAM) {
+        mDevice->deleteStream(mCaptureStreamId);
+        mCaptureStreamId = NO_STREAM;
+    }
+
+    CameraService::Client::disconnect();
+}
+
+status_t Camera2Client::connect(const sp<ICameraClient>& client) {
+    ATRACE_CALL();
+    Mutex::Autolock icl(mICameraLock);
+
+    return BAD_VALUE;
+}
+
+status_t Camera2Client::lock() {
+    ATRACE_CALL();
+    Mutex::Autolock icl(mICameraLock);
+
+    return BAD_VALUE;
+}
+
+status_t Camera2Client::unlock() {
+    ATRACE_CALL();
+    Mutex::Autolock icl(mICameraLock);
+
+    return BAD_VALUE;
+}
+
+status_t Camera2Client::setPreviewDisplay(
+        const sp<Surface>& surface) {
+    ATRACE_CALL();
+    Mutex::Autolock icl(mICameraLock);
+
+    if (mState >= PREVIEW) return INVALID_OPERATION;
+
+    sp<IBinder> binder;
+    sp<ANativeWindow> window;
+    if (surface != 0) {
+        binder = surface->asBinder();
+        window = surface;
+    }
+
+    return setPreviewWindowLocked(binder,window);
+}
+
+status_t Camera2Client::setPreviewTexture(
+        const sp<ISurfaceTexture>& surfaceTexture) {
+    ATRACE_CALL();
+    Mutex::Autolock icl(mICameraLock);
+
+    if (mState >= PREVIEW) return INVALID_OPERATION;
+
+    sp<IBinder> binder;
+    sp<ANativeWindow> window;
+    if (surfaceTexture != 0) {
+        binder = surfaceTexture->asBinder();
+        window = new SurfaceTextureClient(surfaceTexture);
+    }
+    return setPreviewWindowLocked(binder, window);
+}
+
+status_t Camera2Client::setPreviewWindowLocked(const sp<IBinder>& binder,
+        sp<ANativeWindow> window) {
+    ATRACE_CALL();
+    status_t res;
+
+    if (binder == mPreviewSurface) {
+        return NO_ERROR;
+    }
+
+    if (mPreviewStreamId != NO_STREAM) {
+        res = mDevice->waitUntilDrained();
+        if (res != OK) {
+            ALOGE("%s: Error waiting for preview to drain: %s (%d)",
+                    __FUNCTION__, strerror(-res), res);
+            return res;
+        }
+        res = mDevice->deleteStream(mPreviewStreamId);
+        if (res != OK) {
+            ALOGE("%s: Unable to delete old preview stream: %s (%d)",
+                    __FUNCTION__, strerror(-res), res);
+            return res;
+        }
+        mPreviewStreamId = NO_STREAM;
+    }
+
+    mPreviewSurface = binder;
+    mPreviewWindow = window;
+
+    if (mState == WAITING_FOR_PREVIEW_WINDOW) {
+        return startPreviewLocked();
+    }
+
+    return OK;
+}
+
+void Camera2Client::setPreviewCallbackFlag(int flag) {
+    ATRACE_CALL();
+    Mutex::Autolock icl(mICameraLock);
+}
+
+status_t Camera2Client::startPreview() {
+    ATRACE_CALL();
+    Mutex::Autolock icl(mICameraLock);
+    return startPreviewLocked();
+}
+
+status_t Camera2Client::startPreviewLocked() {
+    ATRACE_CALL();
+    status_t res;
+    if (mState >= PREVIEW) {
+        ALOGE("%s: Can't start preview in state %s",
+                __FUNCTION__, getStateName(mState));
+        return INVALID_OPERATION;
+    }
+
+    if (mPreviewWindow == 0) {
+        mState = WAITING_FOR_PREVIEW_WINDOW;
+        return OK;
+    }
+    mState = STOPPED;
+
+    res = updatePreviewStream();
+    if (res != OK) {
+        ALOGE("%s: Camera %d: Unable to update preview stream: %s (%d)",
+                __FUNCTION__, mCameraId, strerror(-res), res);
+        return res;
+    }
+
+    if (mPreviewRequest == NULL) {
+        res = updatePreviewRequest();
+        if (res != OK) {
+            ALOGE("%s: Camera %d: Unable to create preview request: %s (%d)",
+                    __FUNCTION__, mCameraId, strerror(-res), res);
+            return res;
+        }
+    }
+
+    res = updateEntry(mPreviewRequest,
+            ANDROID_REQUEST_OUTPUT_STREAMS,
+            &mPreviewStreamId, 1);
+    if (res != OK) {
+        ALOGE("%s: Camera %d: Unable to set up preview request: %s (%d)",
+                __FUNCTION__, mCameraId, strerror(-res), res);
+        return res;
+    }
+    res = sort_camera_metadata(mPreviewRequest);
+    if (res != OK) {
+        ALOGE("%s: Camera %d: Error sorting preview request: %s (%d)",
+                __FUNCTION__, mCameraId, strerror(-res), res);
+        return res;
+    }
+
+    res = mDevice->setStreamingRequest(mPreviewRequest);
+    if (res != OK) {
+        ALOGE("%s: Camera %d: Unable to set preview request to start preview: "
+                "%s (%d)",
+                __FUNCTION__, mCameraId, strerror(-res), res);
+        return res;
+    }
+    mState = PREVIEW;
+
+    return OK;
+}
+
+void Camera2Client::stopPreview() {
+    ATRACE_CALL();
+    Mutex::Autolock icl(mICameraLock);
+    stopPreviewLocked();
+}
+
+void Camera2Client::stopPreviewLocked() {
+    ATRACE_CALL();
+    switch (mState) {
+        case NOT_INITIALIZED:
+            ALOGE("%s: Camera %d: Call before initialized",
+                    __FUNCTION__, mCameraId);
+            break;
+        case STOPPED:
+            break;
+        case STILL_CAPTURE:
+            ALOGE("%s: Camera %d: Cannot stop preview during still capture.",
+                    __FUNCTION__, mCameraId);
+            break;
+        case RECORD:
+            // TODO: Handle record stop here
+        case PREVIEW:
+            mDevice->setStreamingRequest(NULL);
+        case WAITING_FOR_PREVIEW_WINDOW:
+            mState = STOPPED;
+            break;
+        default:
+            ALOGE("%s: Camera %d: Unknown state %d", __FUNCTION__, mCameraId,
+                    mState);
+    }
+}
+
+bool Camera2Client::previewEnabled() {
+    ATRACE_CALL();
+    Mutex::Autolock icl(mICameraLock);
+    return mState == PREVIEW;
+}
+
+status_t Camera2Client::storeMetaDataInBuffers(bool enabled) {
+    ATRACE_CALL();
+    Mutex::Autolock icl(mICameraLock);
+    return BAD_VALUE;
+}
+
+status_t Camera2Client::startRecording() {
+    ATRACE_CALL();
+    Mutex::Autolock icl(mICameraLock);
+    return BAD_VALUE;
+}
+
+void Camera2Client::stopRecording() {
+    ATRACE_CALL();
+    Mutex::Autolock icl(mICameraLock);
+}
+
+bool Camera2Client::recordingEnabled() {
+    ATRACE_CALL();
+    Mutex::Autolock icl(mICameraLock);
+    return BAD_VALUE;
+}
+
+void Camera2Client::releaseRecordingFrame(const sp<IMemory>& mem) {
+    ATRACE_CALL();
+    Mutex::Autolock icl(mICameraLock);
+}
+
+status_t Camera2Client::autoFocus() {
+    ATRACE_CALL();
+    Mutex::Autolock icl(mICameraLock);
+    return OK;
+}
+
+status_t Camera2Client::cancelAutoFocus() {
+    ATRACE_CALL();
+    Mutex::Autolock icl(mICameraLock);
+    return OK;
+}
+
+status_t Camera2Client::takePicture(int msgType) {
+    ATRACE_CALL();
+    Mutex::Autolock icl(mICameraLock);
+    status_t res;
+
+    switch (mState) {
+        case NOT_INITIALIZED:
+        case STOPPED:
+        case WAITING_FOR_PREVIEW_WINDOW:
+            ALOGE("%s: Camera %d: Cannot take picture without preview enabled",
+                    __FUNCTION__, mCameraId);
+            return INVALID_OPERATION;
+        case PREVIEW:
+        case RECORD:
+            // Good to go for takePicture
+            break;
+        case STILL_CAPTURE:
+        case VIDEO_SNAPSHOT:
+            ALOGE("%s: Camera %d: Already taking a picture",
+                    __FUNCTION__, mCameraId);
+            return INVALID_OPERATION;
+    }
+
+    Mutex::Autolock pl(mParamsLock);
+
+    res = updateCaptureStream();
+    if (res != OK) {
+        ALOGE("%s: Camera %d: Can't set up still image stream: %s (%d)",
+                __FUNCTION__, mCameraId, strerror(-res), res);
+        return res;
+    }
+
+    if (mCaptureRequest == NULL) {
+        res = updateCaptureRequest();
+        if (res != OK) {
+            ALOGE("%s: Camera %d: Can't create still image capture request: "
+                    "%s (%d)", __FUNCTION__, mCameraId, strerror(-res), res);
+            return res;
+        }
+    }
+
+    // TODO: For video snapshot, will need 3 streams here
+    camera_metadata_entry_t outputStreams;
+    uint8_t streamIds[2] = { mPreviewStreamId, mCaptureStreamId };
+    res = updateEntry(mCaptureRequest, ANDROID_REQUEST_OUTPUT_STREAMS,
+            &streamIds, 2);
+    if (res != OK) {
+        ALOGE("%s: Camera %d: Unable to set up still image capture request: "
+                "%s (%d)",
+                __FUNCTION__, mCameraId, strerror(-res), res);
+        return res;
+    }
+    res = sort_camera_metadata(mCaptureRequest);
+    if (res != OK) {
+        ALOGE("%s: Camera %d: Unable to sort capture request: %s (%d)",
+                __FUNCTION__, mCameraId, strerror(-res), res);
+        return res;
+    }
+
+    camera_metadata_t *captureCopy = clone_camera_metadata(mCaptureRequest);
+    if (captureCopy == NULL) {
+        ALOGE("%s: Camera %d: Unable to copy capture request for HAL device",
+                __FUNCTION__, mCameraId);
+        return NO_MEMORY;
+    }
+
+    if (mState == PREVIEW) {
+        res = mDevice->setStreamingRequest(NULL);
+        if (res != OK) {
+            ALOGE("%s: Camera %d: Unable to stop preview for still capture: "
+                    "%s (%d)",
+                    __FUNCTION__, mCameraId, strerror(-res), res);
+            return res;
+        }
+    }
+
+    res = mDevice->capture(captureCopy);
+    if (res != OK) {
+        ALOGE("%s: Camera %d: Unable to submit still image capture request: "
+                "%s (%d)",
+                __FUNCTION__, mCameraId, strerror(-res), res);
+        return res;
+    }
+
+    switch (mState) {
+        case PREVIEW:
+            mState = STILL_CAPTURE;
+            break;
+        case RECORD:
+            mState = VIDEO_SNAPSHOT;
+            break;
+        default:
+            ALOGE("%s: Camera %d: Unknown state for still capture!",
+                    __FUNCTION__, mCameraId);
+            return INVALID_OPERATION;
+    }
+
+    return OK;
+}
+
+status_t Camera2Client::setParameters(const String8& params) {
+    ATRACE_CALL();
+    Mutex::Autolock icl(mICameraLock);
+    Mutex::Autolock pl(mParamsLock);
+    status_t res;
+
+    CameraParameters newParams(params);
+
+    // TODO: Currently ignoring any changes to supposedly read-only
+    // parameters such as supported preview sizes, etc. Should probably
+    // produce an error if they're changed.
+
+    /** Extract and verify new parameters */
+
+    size_t i;
+
+    // PREVIEW_SIZE
+    int previewWidth, previewHeight;
+    newParams.getPreviewSize(&previewWidth, &previewHeight);
+
+    if (previewWidth != mParameters.previewWidth ||
+            previewHeight != mParameters.previewHeight) {
+        if (mState >= PREVIEW) {
+            ALOGE("%s: Preview size cannot be updated when preview "
+                    "is active!", __FUNCTION__);
+            return BAD_VALUE;
+        }
+        camera_metadata_entry_t availablePreviewSizes =
+            staticInfo(ANDROID_SCALER_AVAILABLE_PROCESSED_SIZES);
+        for (i = 0; i < availablePreviewSizes.count; i += 2 ) {
+            if (availablePreviewSizes.data.i32[i] == previewWidth &&
+                    availablePreviewSizes.data.i32[i+1] == previewHeight) break;
+        }
+        if (i == availablePreviewSizes.count) {
+            ALOGE("%s: Requested preview size %d x %d is not supported",
+                    __FUNCTION__, previewWidth, previewHeight);
+            return BAD_VALUE;
+        }
+    }
+
+    // PREVIEW_FPS_RANGE
+    int previewFpsRange[2];
+    int previewFps = 0;
+    bool fpsRangeChanged = false;
+    newParams.getPreviewFpsRange(&previewFpsRange[0], &previewFpsRange[1]);
+    if (previewFpsRange[0] != mParameters.previewFpsRange[0] ||
+            previewFpsRange[1] != mParameters.previewFpsRange[1]) {
+        fpsRangeChanged = true;
+        camera_metadata_entry_t availablePreviewFpsRanges =
+            staticInfo(ANDROID_CONTROL_AE_AVAILABLE_TARGET_FPS_RANGES, 2);
+        for (i = 0; i < availablePreviewFpsRanges.count; i += 2) {
+            if ((availablePreviewFpsRanges.data.i32[i] ==
+                    previewFpsRange[0]) &&
+                (availablePreviewFpsRanges.data.i32[i+1] ==
+                    previewFpsRange[1]) ) {
+                break;
+            }
+        }
+        if (i == availablePreviewFpsRanges.count) {
+            ALOGE("%s: Requested preview FPS range %d - %d is not supported",
+                __FUNCTION__, previewFpsRange[0], previewFpsRange[1]);
+            return BAD_VALUE;
+        }
+        previewFps = previewFpsRange[0];
+    }
+
+    // PREVIEW_FORMAT
+    int previewFormat = formatStringToEnum(newParams.getPreviewFormat());
+    if (previewFormat != mParameters.previewFormat) {
+        if (mState >= PREVIEW) {
+            ALOGE("%s: Preview format cannot be updated when preview "
+                    "is active!", __FUNCTION__);
+            return BAD_VALUE;
+        }
+        camera_metadata_entry_t availableFormats =
+            staticInfo(ANDROID_SCALER_AVAILABLE_FORMATS);
+        for (i = 0; i < availableFormats.count; i++) {
+            if (availableFormats.data.i32[i] == previewFormat) break;
+        }
+        if (i == availableFormats.count) {
+            ALOGE("%s: Requested preview format %s (0x%x) is not supported",
+                    __FUNCTION__, newParams.getPreviewFormat(), previewFormat);
+            return BAD_VALUE;
+        }
+    }
+
+    // PREVIEW_FRAME_RATE
+    // Deprecated, only use if the preview fps range is unchanged this time.
+    // The single-value FPS is the same as the minimum of the range.
+    if (!fpsRangeChanged) {
+        previewFps = newParams.getPreviewFrameRate();
+        if (previewFps != mParameters.previewFps) {
+            camera_metadata_entry_t availableFrameRates =
+                staticInfo(ANDROID_CONTROL_AE_AVAILABLE_TARGET_FPS_RANGES);
+            for (i = 0; i < availableFrameRates.count; i+=2) {
+                if (availableFrameRates.data.i32[i] == previewFps) break;
+            }
+            if (i == availableFrameRates.count) {
+                ALOGE("%s: Requested preview frame rate %d is not supported",
+                        __FUNCTION__, previewFps);
+                return BAD_VALUE;
+            }
+            previewFpsRange[0] = availableFrameRates.data.i32[i];
+            previewFpsRange[1] = availableFrameRates.data.i32[i+1];
+        }
+    }
+
+    // PICTURE_SIZE
+    int pictureWidth, pictureHeight;
+    newParams.getPictureSize(&pictureWidth, &pictureHeight);
+    if (pictureWidth == mParameters.pictureWidth ||
+            pictureHeight == mParameters.pictureHeight) {
+        camera_metadata_entry_t availablePictureSizes =
+            staticInfo(ANDROID_SCALER_AVAILABLE_JPEG_SIZES);
+        for (i = 0; i < availablePictureSizes.count; i+=2) {
+            if (availablePictureSizes.data.i32[i] == pictureWidth &&
+                    availablePictureSizes.data.i32[i+1] == pictureHeight) break;
+        }
+        if (i == availablePictureSizes.count) {
+            ALOGE("%s: Requested picture size %d x %d is not supported",
+                    __FUNCTION__, pictureWidth, pictureHeight);
+            return BAD_VALUE;
+        }
+    }
+
+    // JPEG_THUMBNAIL_WIDTH/HEIGHT
+    int jpegThumbSize[2];
+    jpegThumbSize[0] =
+            newParams.getInt(CameraParameters::KEY_JPEG_THUMBNAIL_WIDTH);
+    jpegThumbSize[1] =
+            newParams.getInt(CameraParameters::KEY_JPEG_THUMBNAIL_HEIGHT);
+    if (jpegThumbSize[0] != mParameters.jpegThumbSize[0] ||
+            jpegThumbSize[1] != mParameters.jpegThumbSize[1]) {
+        camera_metadata_entry_t availableJpegThumbSizes =
+            staticInfo(ANDROID_JPEG_AVAILABLE_THUMBNAIL_SIZES);
+        for (i = 0; i < availableJpegThumbSizes.count; i+=2) {
+            if (availableJpegThumbSizes.data.i32[i] == jpegThumbSize[0] &&
+                    availableJpegThumbSizes.data.i32[i+1] == jpegThumbSize[1]) {
+                break;
+            }
+        }
+        if (i == availableJpegThumbSizes.count) {
+            ALOGE("%s: Requested JPEG thumbnail size %d x %d is not supported",
+                    __FUNCTION__, jpegThumbSize[0], jpegThumbSize[1]);
+            return BAD_VALUE;
+        }
+    }
+
+    // JPEG_THUMBNAIL_QUALITY
+    int jpegThumbQuality =
+            newParams.getInt(CameraParameters::KEY_JPEG_THUMBNAIL_QUALITY);
+    if (jpegThumbQuality < 0 || jpegThumbQuality > 100) {
+        ALOGE("%s: Requested JPEG thumbnail quality %d is not supported",
+                __FUNCTION__, jpegThumbQuality);
+        return BAD_VALUE;
+    }
+
+    // JPEG_QUALITY
+    int jpegQuality =
+            newParams.getInt(CameraParameters::KEY_JPEG_QUALITY);
+    if (jpegQuality < 0 || jpegQuality > 100) {
+        ALOGE("%s: Requested JPEG quality %d is not supported",
+                __FUNCTION__, jpegQuality);
+        return BAD_VALUE;
+    }
+
+    // ROTATION
+    int jpegRotation =
+            newParams.getInt(CameraParameters::KEY_ROTATION);
+    if (jpegRotation != 0 &&
+            jpegRotation != 90 &&
+            jpegRotation != 180 &&
+            jpegRotation != 270) {
+        ALOGE("%s: Requested picture rotation angle %d is not supported",
+                __FUNCTION__, jpegRotation);
+        return BAD_VALUE;
+    }
+
+    // GPS
+    bool gpsEnabled = false;
+    double gpsCoordinates[3] = {0,0,0};
+    int64_t gpsTimestamp = 0;
+    String8 gpsProcessingMethod;
+    const char *gpsLatStr =
+            newParams.get(CameraParameters::KEY_GPS_LATITUDE);
+    if (gpsLatStr != NULL) {
+        const char *gpsLongStr =
+                newParams.get(CameraParameters::KEY_GPS_LONGITUDE);
+        const char *gpsAltitudeStr =
+                newParams.get(CameraParameters::KEY_GPS_ALTITUDE);
+        const char *gpsTimeStr =
+                newParams.get(CameraParameters::KEY_GPS_TIMESTAMP);
+        const char *gpsProcMethodStr =
+                newParams.get(CameraParameters::KEY_GPS_PROCESSING_METHOD);
+        if (gpsLongStr == NULL ||
+                gpsAltitudeStr == NULL ||
+                gpsTimeStr == NULL ||
+                gpsProcMethodStr == NULL) {
+            ALOGE("%s: Incomplete set of GPS parameters provided",
+                    __FUNCTION__);
+            return BAD_VALUE;
+        }
+        char *endPtr;
+        errno = 0;
+        gpsCoordinates[0] = strtod(gpsLatStr, &endPtr);
+        if (errno || endPtr == gpsLatStr) {
+            ALOGE("%s: Malformed GPS latitude: %s", __FUNCTION__, gpsLatStr);
+            return BAD_VALUE;
+        }
+        errno = 0;
+        gpsCoordinates[1] = strtod(gpsLongStr, &endPtr);
+        if (errno || endPtr == gpsLongStr) {
+            ALOGE("%s: Malformed GPS longitude: %s", __FUNCTION__, gpsLongStr);
+            return BAD_VALUE;
+        }
+        errno = 0;
+        gpsCoordinates[2] = strtod(gpsAltitudeStr, &endPtr);
+        if (errno || endPtr == gpsAltitudeStr) {
+            ALOGE("%s: Malformed GPS altitude: %s", __FUNCTION__,
+                    gpsAltitudeStr);
+            return BAD_VALUE;
+        }
+        errno = 0;
+        gpsTimestamp = strtoll(gpsTimeStr, &endPtr, 10);
+        if (errno || endPtr == gpsTimeStr) {
+            ALOGE("%s: Malformed GPS timestamp: %s", __FUNCTION__, gpsTimeStr);
+            return BAD_VALUE;
+        }
+        gpsProcessingMethod = gpsProcMethodStr;
+
+        gpsEnabled = true;
+    }
+
+    // WHITE_BALANCE
+    int wbMode = wbModeStringToEnum(
+        newParams.get(CameraParameters::KEY_WHITE_BALANCE) );
+    if (wbMode != mParameters.wbMode) {
+        camera_metadata_entry_t availableWbModes =
+            staticInfo(ANDROID_CONTROL_AWB_AVAILABLE_MODES);
+        for (i = 0; i < availableWbModes.count; i++) {
+            if (wbMode == availableWbModes.data.u8[i]) break;
+        }
+        if (i == availableWbModes.count) {
+            ALOGE("%s: Requested white balance mode %s is not supported",
+                    __FUNCTION__,
+                    newParams.get(CameraParameters::KEY_WHITE_BALANCE));
+            return BAD_VALUE;
+        }
+    }
+
+    // EFFECT
+    int effectMode = effectModeStringToEnum(
+        newParams.get(CameraParameters::KEY_EFFECT) );
+    if (effectMode != mParameters.effectMode) {
+        camera_metadata_entry_t availableEffectModes =
+            staticInfo(ANDROID_CONTROL_AVAILABLE_EFFECTS);
+        for (i = 0; i < availableEffectModes.count; i++) {
+            if (effectMode == availableEffectModes.data.u8[i]) break;
+        }
+        if (i == availableEffectModes.count) {
+            ALOGE("%s: Requested effect mode \"%s\" is not supported",
+                    __FUNCTION__,
+                    newParams.get(CameraParameters::KEY_EFFECT) );
+            return BAD_VALUE;
+        }
+    }
+
+    // ANTIBANDING
+    int antibandingMode = abModeStringToEnum(
+        newParams.get(CameraParameters::KEY_ANTIBANDING) );
+    if (antibandingMode != mParameters.antibandingMode) {
+        camera_metadata_entry_t availableAbModes =
+            staticInfo(ANDROID_CONTROL_AE_AVAILABLE_ANTIBANDING_MODES);
+        for (i = 0; i < availableAbModes.count; i++) {
+            if (antibandingMode == availableAbModes.data.u8[i]) break;
+        }
+        if (i == availableAbModes.count) {
+            ALOGE("%s: Requested antibanding mode \"%s\" is not supported",
+                    __FUNCTION__,
+                    newParams.get(CameraParameters::KEY_ANTIBANDING));
+            return BAD_VALUE;
+        }
+    }
+
+    // SCENE_MODE
+    int sceneMode = sceneModeStringToEnum(
+        newParams.get(CameraParameters::KEY_SCENE_MODE) );
+    if (sceneMode != mParameters.sceneMode) {
+        camera_metadata_entry_t availableSceneModes =
+            staticInfo(ANDROID_CONTROL_AVAILABLE_SCENE_MODES);
+        for (i = 0; i < availableSceneModes.count; i++) {
+            if (sceneMode == availableSceneModes.data.u8[i]) break;
+        }
+        if (i == availableSceneModes.count) {
+            ALOGE("%s: Requested scene mode \"%s\" is not supported",
+                    __FUNCTION__,
+                    newParams.get(CameraParameters::KEY_SCENE_MODE));
+            return BAD_VALUE;
+        }
+    }
+
+    // FLASH_MODE
+    Parameters::flashMode_t flashMode = flashModeStringToEnum(
+        newParams.get(CameraParameters::KEY_FLASH_MODE) );
+    if (flashMode != mParameters.flashMode) {
+        camera_metadata_entry_t flashAvailable =
+            staticInfo(ANDROID_FLASH_AVAILABLE, 1, 1);
+        if (!flashAvailable.data.u8[0] &&
+                flashMode != Parameters::FLASH_MODE_OFF) {
+            ALOGE("%s: Requested flash mode \"%s\" is not supported: "
+                    "No flash on device", __FUNCTION__,
+                    newParams.get(CameraParameters::KEY_FLASH_MODE));
+            return BAD_VALUE;
+        } else if (flashMode == Parameters::FLASH_MODE_RED_EYE) {
+            camera_metadata_entry_t availableAeModes =
+                staticInfo(ANDROID_CONTROL_AE_AVAILABLE_MODES);
+            for (i = 0; i < availableAeModes.count; i++) {
+                if (flashMode == availableAeModes.data.u8[i]) break;
+            }
+            if (i == availableAeModes.count) {
+                ALOGE("%s: Requested flash mode \"%s\" is not supported",
+                        __FUNCTION__,
+                        newParams.get(CameraParameters::KEY_FLASH_MODE));
+                return BAD_VALUE;
+            }
+        } else if (flashMode == -1) {
+            ALOGE("%s: Requested flash mode \"%s\" is unknown",
+                    __FUNCTION__,
+                    newParams.get(CameraParameters::KEY_FLASH_MODE));
+            return BAD_VALUE;
+        }
+    }
+
+    // FOCUS_MODE
+    Parameters::focusMode_t focusMode = focusModeStringToEnum(
+        newParams.get(CameraParameters::KEY_FOCUS_MODE));
+    if (focusMode != mParameters.focusMode) {
+        if (focusMode != Parameters::FOCUS_MODE_FIXED) {
+            camera_metadata_entry_t minFocusDistance =
+                staticInfo(ANDROID_LENS_MINIMUM_FOCUS_DISTANCE);
+            if (minFocusDistance.data.f[0] == 0) {
+                ALOGE("%s: Requested focus mode \"%s\" is not available: "
+                        "fixed focus lens",
+                        __FUNCTION__,
+                        newParams.get(CameraParameters::KEY_FOCUS_MODE));
+                return BAD_VALUE;
+            } else if (focusMode != Parameters::FOCUS_MODE_INFINITY) {
+                camera_metadata_entry_t availableFocusModes =
+                    staticInfo(ANDROID_CONTROL_AF_AVAILABLE_MODES);
+                for (i = 0; i < availableFocusModes.count; i++) {
+                    if (focusMode == availableFocusModes.data.u8[i]) break;
+                }
+                if (i == availableFocusModes.count) {
+                    ALOGE("%s: Requested focus mode \"%s\" is not supported",
+                            __FUNCTION__,
+                            newParams.get(CameraParameters::KEY_FOCUS_MODE));
+                    return BAD_VALUE;
+                }
+            }
+        }
+    }
+
+    // FOCUS_AREAS
+    Vector<Parameters::Area> focusingAreas;
+    res = parseAreas(newParams.get(CameraParameters::KEY_FOCUS_AREAS),
+            &focusingAreas);
+    size_t max3aRegions =
+        (size_t)staticInfo(ANDROID_CONTROL_MAX_REGIONS, 1, 1).data.i32[0];
+    if (res == OK) res = validateAreas(focusingAreas, max3aRegions);
+    if (res != OK) {
+        ALOGE("%s: Requested focus areas are malformed: %s",
+                __FUNCTION__, newParams.get(CameraParameters::KEY_FOCUS_AREAS));
+        return BAD_VALUE;
+    }
+
+    // EXPOSURE_COMPENSATION
+    int exposureCompensation =
+        newParams.getInt(CameraParameters::KEY_EXPOSURE_COMPENSATION);
+    camera_metadata_entry_t exposureCompensationRange =
+        staticInfo(ANDROID_CONTROL_AE_EXP_COMPENSATION_RANGE);
+    if (exposureCompensation < exposureCompensationRange.data.i32[0] ||
+            exposureCompensation > exposureCompensationRange.data.i32[1]) {
+        ALOGE("%s: Requested exposure compensation index is out of bounds: %d",
+                __FUNCTION__, exposureCompensation);
+        return BAD_VALUE;
+    }
+
+    // AUTO_EXPOSURE_LOCK (always supported)
+    bool autoExposureLock = boolFromString(
+        newParams.get(CameraParameters::KEY_AUTO_EXPOSURE_LOCK));
+
+    // AUTO_WHITEBALANCE_LOCK (always supported)
+    bool autoWhiteBalanceLock = boolFromString(
+        newParams.get(CameraParameters::KEY_AUTO_WHITEBALANCE_LOCK));
+
+    // METERING_AREAS
+    Vector<Parameters::Area> meteringAreas;
+    res = parseAreas(newParams.get(CameraParameters::KEY_METERING_AREAS),
+            &meteringAreas);
+    if (res == OK) res = validateAreas(focusingAreas, max3aRegions);
+    if (res != OK) {
+        ALOGE("%s: Requested metering areas are malformed: %s",
+                __FUNCTION__,
+                newParams.get(CameraParameters::KEY_METERING_AREAS));
+        return BAD_VALUE;
+    }
+
+    // ZOOM
+    int zoom = newParams.getInt(CameraParameters::KEY_ZOOM);
+    if (zoom < 0 || zoom > (int)NUM_ZOOM_STEPS) {
+        ALOGE("%s: Requested zoom level %d is not supported",
+                __FUNCTION__, zoom);
+        return BAD_VALUE;
+    }
+
+    // VIDEO_SIZE
+    int videoWidth, videoHeight;
+    newParams.getVideoSize(&videoWidth, &videoHeight);
+    if (videoWidth != mParameters.videoWidth ||
+            videoHeight != mParameters.videoHeight) {
+        if (mState == RECORD) {
+            ALOGE("%s: Video size cannot be updated when recording is active!",
+                    __FUNCTION__);
+            return BAD_VALUE;
+        }
+        camera_metadata_entry_t availableVideoSizes =
+            staticInfo(ANDROID_SCALER_AVAILABLE_PROCESSED_SIZES);
+        for (i = 0; i < availableVideoSizes.count; i += 2 ) {
+            if (availableVideoSizes.data.i32[i] == videoWidth &&
+                    availableVideoSizes.data.i32[i+1] == videoHeight)  break;
+        }
+        if (i == availableVideoSizes.count) {
+            ALOGE("%s: Requested video size %d x %d is not supported",
+                    __FUNCTION__, videoWidth, videoHeight);
+            return BAD_VALUE;
+        }
+    }
+
+    // RECORDING_HINT (always supported)
+    bool recordingHint = boolFromString(
+        newParams.get(CameraParameters::KEY_RECORDING_HINT) );
+
+    // VIDEO_STABILIZATION
+    bool videoStabilization = boolFromString(
+        newParams.get(CameraParameters::KEY_VIDEO_STABILIZATION) );
+    camera_metadata_entry_t availableVideoStabilizationModes =
+        staticInfo(ANDROID_CONTROL_AVAILABLE_VIDEO_STABILIZATION_MODES);
+    if (videoStabilization && availableVideoStabilizationModes.count == 1) {
+        ALOGE("%s: Video stabilization not supported", __FUNCTION__);
+    }
+
+    /** Update internal parameters */
+    mParameters.previewWidth = previewWidth;
+    mParameters.previewHeight = previewHeight;
+    mParameters.previewFpsRange[0] = previewFpsRange[0];
+    mParameters.previewFpsRange[1] = previewFpsRange[1];
+    mParameters.previewFps = previewFps;
+    mParameters.previewFormat = previewFormat;
+
+    mParameters.pictureWidth = pictureWidth;
+    mParameters.pictureHeight = pictureHeight;
+
+    mParameters.jpegThumbSize[0] = jpegThumbSize[0];
+    mParameters.jpegThumbSize[1] = jpegThumbSize[1];
+    mParameters.jpegQuality = jpegQuality;
+    mParameters.jpegThumbQuality = jpegThumbQuality;
+
+    mParameters.gpsEnabled = gpsEnabled;
+    mParameters.gpsCoordinates[0] = gpsCoordinates[0];
+    mParameters.gpsCoordinates[1] = gpsCoordinates[1];
+    mParameters.gpsCoordinates[2] = gpsCoordinates[2];
+    mParameters.gpsTimestamp = gpsTimestamp;
+    mParameters.gpsProcessingMethod = gpsProcessingMethod;
+
+    mParameters.wbMode = wbMode;
+    mParameters.effectMode = effectMode;
+    mParameters.antibandingMode = antibandingMode;
+    mParameters.sceneMode = sceneMode;
+
+    mParameters.flashMode = flashMode;
+    mParameters.focusMode = focusMode;
+
+    mParameters.focusingAreas = focusingAreas;
+    mParameters.exposureCompensation = exposureCompensation;
+    mParameters.autoExposureLock = autoExposureLock;
+    mParameters.autoWhiteBalanceLock = autoWhiteBalanceLock;
+    mParameters.meteringAreas = meteringAreas;
+    mParameters.zoom = zoom;
+
+    mParameters.videoWidth = videoWidth;
+    mParameters.videoHeight = videoHeight;
+
+    mParameters.recordingHint = recordingHint;
+    mParameters.videoStabilization = videoStabilization;
+
+    res = updatePreviewRequest();
+    if (res != OK) {
+        ALOGE("%s: Camera %d: Unable to update preview request: %s (%d)",
+                __FUNCTION__, mCameraId, strerror(-res), res);
+        return res;
+    }
+    res = updateCaptureRequest();
+    if (res != OK) {
+        ALOGE("%s: Camera %d: Unable to update capture request: %s (%d)",
+                __FUNCTION__, mCameraId, strerror(-res), res);
+        return res;
+    }
+
+    if (mState == PREVIEW) {
+        res = mDevice->setStreamingRequest(mPreviewRequest);
+        if (res != OK) {
+            ALOGE("%s: Camera %d: Error streaming new preview request: %s (%d)",
+                    __FUNCTION__, mCameraId, strerror(-res), res);
+            return res;
+        }
+    }
+
+    return OK;
+}
+
+String8 Camera2Client::getParameters() const {
+    ATRACE_CALL();
+    Mutex::Autolock icl(mICameraLock);
+
+    Mutex::Autolock pl(mParamsLock);
+
+    // TODO: Deal with focus distances
+    return mParamsFlattened;
+}
+
+status_t Camera2Client::sendCommand(int32_t cmd, int32_t arg1, int32_t arg2) {
+    ATRACE_CALL();
+    Mutex::Autolock icl(mICameraLock);
+
+    ALOGV("%s: Camera %d: Command %d (%d, %d)", __FUNCTION__, mCameraId,
+            cmd, arg1, arg2);
+
+    if (cmd == CAMERA_CMD_SET_DISPLAY_ORIENTATION) {
+        int transform = degToTransform(arg1,
+                mCameraFacing == CAMERA_FACING_FRONT);
+        if (transform == -1) {
+            ALOGE("%s: Camera %d: Error setting %d as display orientation value",
+                    __FUNCTION__, mCameraId, arg1);
+            return BAD_VALUE;
+        }
+        if (transform != mParameters.previewTransform &&
+                mPreviewStreamId != NO_STREAM) {
+            mDevice->setStreamTransform(mPreviewStreamId, transform);
+        }
+        mParameters.previewTransform = transform;
+        return OK;
+    }
+
+    ALOGE("%s: Camera %d: Unimplemented command %d (%d, %d)", __FUNCTION__,
+            mCameraId, cmd, arg1, arg2);
+
+    return OK;
+}
+
+/** Device-related methods */
+
+void Camera2Client::onCaptureAvailable() {
+    ATRACE_CALL();
+    status_t res;
+    sp<ICameraClient> currentClient;
+    CpuConsumer::LockedBuffer imgBuffer;
+    {
+        Mutex::Autolock icl(mICameraLock);
+
+        // TODO: Signal errors here upstream
+        if (mState != STILL_CAPTURE && mState != VIDEO_SNAPSHOT) {
+            ALOGE("%s: Camera %d: Still image produced unexpectedly!",
+                    __FUNCTION__, mCameraId);
+            return;
+        }
+
+        res = mCaptureConsumer->lockNextBuffer(&imgBuffer);
+        if (res != OK) {
+            ALOGE("%s: Camera %d: Error receiving still image buffer: %s (%d)",
+                    __FUNCTION__, mCameraId, strerror(-res), res);
+            return;
+        }
+
+        if (imgBuffer.format != HAL_PIXEL_FORMAT_BLOB) {
+            ALOGE("%s: Camera %d: Unexpected format for still image: "
+                    "%x, expected %x", __FUNCTION__, mCameraId,
+                    imgBuffer.format,
+                    HAL_PIXEL_FORMAT_BLOB);
+            mCaptureConsumer->unlockBuffer(imgBuffer);
+            return;
+        }
+
+        // TODO: Optimize this to avoid memcopy
+        void* captureMemory = mCaptureHeap->getBase();
+        size_t size = mCaptureHeap->getSize();
+        memcpy(captureMemory, imgBuffer.data, size);
+
+        mCaptureConsumer->unlockBuffer(imgBuffer);
+
+        currentClient = mCameraClient;
+        switch (mState) {
+            case STILL_CAPTURE:
+                mState = STOPPED;
+                break;
+            case VIDEO_SNAPSHOT:
+                mState = RECORD;
+                break;
+            default:
+                ALOGE("%s: Camera %d: Unexpected state %d", __FUNCTION__,
+                        mCameraId, mState);
+                break;
+        }
+    }
+    // Call outside mICameraLock to allow re-entrancy from notification
+    if (currentClient != 0) {
+        currentClient->dataCallback(CAMERA_MSG_COMPRESSED_IMAGE,
+                mCaptureMemory, NULL);
+    }
+}
+
+camera_metadata_entry_t Camera2Client::staticInfo(uint32_t tag,
+        size_t minCount, size_t maxCount) {
+    status_t res;
+    camera_metadata_entry_t entry;
+    res = find_camera_metadata_entry(mDevice->info(),
+            tag,
+            &entry);
+    if (CC_UNLIKELY( res != OK )) {
+        const char* tagSection = get_camera_metadata_section_name(tag);
+        if (tagSection == NULL) tagSection = "<unknown>";
+        const char* tagName = get_camera_metadata_tag_name(tag);
+        if (tagName == NULL) tagName = "<unknown>";
+
+        ALOGE("Error finding static metadata entry '%s.%s' (%x): %s (%d)",
+                tagSection, tagName, tag, strerror(-res), res);
+        entry.count = 0;
+        entry.data.u8 = NULL;
+    } else if (CC_UNLIKELY(
+            (minCount != 0 && entry.count < minCount) ||
+            (maxCount != 0 && entry.count > maxCount) ) ) {
+        const char* tagSection = get_camera_metadata_section_name(tag);
+        if (tagSection == NULL) tagSection = "<unknown>";
+        const char* tagName = get_camera_metadata_tag_name(tag);
+        if (tagName == NULL) tagName = "<unknown>";
+        ALOGE("Malformed static metadata entry '%s.%s' (%x):"
+                "Expected between %d and %d values, but got %d values",
+                tagSection, tagName, tag, minCount, maxCount, entry.count);
+        entry.count = 0;
+        entry.data.u8 = NULL;
+    }
+
+    return entry;
+}
+
+/** Utility methods */
+
+
+status_t Camera2Client::buildDefaultParameters() {
+    ATRACE_CALL();
+    Mutex::Autolock pl(mParamsLock);
+
+    status_t res;
+    CameraParameters params;
+
+    camera_metadata_entry_t availableProcessedSizes =
+        staticInfo(ANDROID_SCALER_AVAILABLE_PROCESSED_SIZES, 2);
+    if (!availableProcessedSizes.count) return NO_INIT;
+
+    // TODO: Pick more intelligently
+    mParameters.previewWidth = availableProcessedSizes.data.i32[0];
+    mParameters.previewHeight = availableProcessedSizes.data.i32[1];
+    mParameters.videoWidth = mParameters.previewWidth;
+    mParameters.videoHeight = mParameters.previewHeight;
+
+    params.setPreviewSize(mParameters.previewWidth, mParameters.previewHeight);
+    params.setVideoSize(mParameters.videoWidth, mParameters.videoHeight);
+    params.set(CameraParameters::KEY_PREFERRED_PREVIEW_SIZE_FOR_VIDEO,
+            String8::format("%dx%d",
+                    mParameters.previewWidth, mParameters.previewHeight));
+    {
+        String8 supportedPreviewSizes;
+        for (size_t i=0; i < availableProcessedSizes.count; i += 2) {
+            if (i != 0) supportedPreviewSizes += ",";
+            supportedPreviewSizes += String8::format("%dx%d",
+                    availableProcessedSizes.data.i32[i],
+                    availableProcessedSizes.data.i32[i+1]);
+        }
+        params.set(CameraParameters::KEY_SUPPORTED_PREVIEW_SIZES,
+                supportedPreviewSizes);
+        params.set(CameraParameters::KEY_SUPPORTED_VIDEO_SIZES,
+                supportedPreviewSizes);
+    }
+
+    camera_metadata_entry_t availableFpsRanges =
+        staticInfo(ANDROID_CONTROL_AE_AVAILABLE_TARGET_FPS_RANGES, 2);
+    if (!availableFpsRanges.count) return NO_INIT;
+
+    mParameters.previewFpsRange[0] = availableFpsRanges.data.i32[0];
+    mParameters.previewFpsRange[1] = availableFpsRanges.data.i32[1];
+
+    params.set(CameraParameters::KEY_PREVIEW_FPS_RANGE,
+            String8::format("%d,%d",
+                    mParameters.previewFpsRange[0],
+                    mParameters.previewFpsRange[1]));
+
+    {
+        String8 supportedPreviewFpsRange;
+        for (size_t i=0; i < availableFpsRanges.count; i += 2) {
+            if (i != 0) supportedPreviewFpsRange += ",";
+            supportedPreviewFpsRange += String8::format("(%d,%d)",
+                    availableFpsRanges.data.i32[i],
+                    availableFpsRanges.data.i32[i+1]);
+        }
+        params.set(CameraParameters::KEY_SUPPORTED_PREVIEW_FPS_RANGE,
+                supportedPreviewFpsRange);
+    }
+
+    mParameters.previewFormat = HAL_PIXEL_FORMAT_YCrCb_420_SP;
+    params.set(CameraParameters::KEY_PREVIEW_FORMAT,
+            formatEnumToString(mParameters.previewFormat)); // NV21
+
+    mParameters.previewTransform = degToTransform(0,
+            mCameraFacing == CAMERA_FACING_FRONT);
+
+    camera_metadata_entry_t availableFormats =
+        staticInfo(ANDROID_SCALER_AVAILABLE_FORMATS);
+
+    {
+        String8 supportedPreviewFormats;
+        bool addComma = false;
+        for (size_t i=0; i < availableFormats.count; i++) {
+            if (addComma) supportedPreviewFormats += ",";
+            addComma = true;
+            switch (availableFormats.data.i32[i]) {
+            case HAL_PIXEL_FORMAT_YCbCr_422_SP:
+                supportedPreviewFormats +=
+                    CameraParameters::PIXEL_FORMAT_YUV422SP;
+                break;
+            case HAL_PIXEL_FORMAT_YCrCb_420_SP:
+                supportedPreviewFormats +=
+                    CameraParameters::PIXEL_FORMAT_YUV420SP;
+                break;
+            case HAL_PIXEL_FORMAT_YCbCr_422_I:
+                supportedPreviewFormats +=
+                    CameraParameters::PIXEL_FORMAT_YUV422I;
+                break;
+            case HAL_PIXEL_FORMAT_YV12:
+                supportedPreviewFormats +=
+                    CameraParameters::PIXEL_FORMAT_YUV420P;
+                break;
+            case HAL_PIXEL_FORMAT_RGB_565:
+                supportedPreviewFormats +=
+                    CameraParameters::PIXEL_FORMAT_RGB565;
+                break;
+            case HAL_PIXEL_FORMAT_RGBA_8888:
+                supportedPreviewFormats +=
+                    CameraParameters::PIXEL_FORMAT_RGBA8888;
+                break;
+            // Not advertizing JPEG, RAW_SENSOR, etc, for preview formats
+            case HAL_PIXEL_FORMAT_RAW_SENSOR:
+            case HAL_PIXEL_FORMAT_BLOB:
+                addComma = false;
+                break;
+
+            default:
+                ALOGW("%s: Camera %d: Unknown preview format: %x",
+                        __FUNCTION__, mCameraId, availableFormats.data.i32[i]);
+                addComma = false;
+                break;
+            }
+        }
+        params.set(CameraParameters::KEY_SUPPORTED_PREVIEW_FORMATS,
+                supportedPreviewFormats);
+    }
+
+    // PREVIEW_FRAME_RATE / SUPPORTED_PREVIEW_FRAME_RATES are deprecated, but
+    // still have to do something sane for them
+
+    params.set(CameraParameters::KEY_PREVIEW_FRAME_RATE,
+            mParameters.previewFpsRange[0]);
+
+    {
+        String8 supportedPreviewFrameRates;
+        for (size_t i=0; i < availableFpsRanges.count; i += 2) {
+            if (i != 0) supportedPreviewFrameRates += ",";
+            supportedPreviewFrameRates += String8::format("%d",
+                    availableFpsRanges.data.i32[i]);
+        }
+        params.set(CameraParameters::KEY_SUPPORTED_PREVIEW_FRAME_RATES,
+                supportedPreviewFrameRates);
+    }
+
+    camera_metadata_entry_t availableJpegSizes =
+        staticInfo(ANDROID_SCALER_AVAILABLE_JPEG_SIZES, 2);
+    if (!availableJpegSizes.count) return NO_INIT;
+
+    // TODO: Pick maximum
+    mParameters.pictureWidth = availableJpegSizes.data.i32[0];
+    mParameters.pictureHeight = availableJpegSizes.data.i32[1];
+
+    params.setPictureSize(mParameters.pictureWidth,
+            mParameters.pictureHeight);
+
+    {
+        String8 supportedPictureSizes;
+        for (size_t i=0; i < availableJpegSizes.count; i += 2) {
+            if (i != 0) supportedPictureSizes += ",";
+            supportedPictureSizes += String8::format("%dx%d",
+                    availableJpegSizes.data.i32[i],
+                    availableJpegSizes.data.i32[i+1]);
+        }
+        params.set(CameraParameters::KEY_SUPPORTED_PICTURE_SIZES,
+                supportedPictureSizes);
+    }
+
+    params.setPictureFormat(CameraParameters::PIXEL_FORMAT_JPEG);
+    params.set(CameraParameters::KEY_SUPPORTED_PICTURE_FORMATS,
+            CameraParameters::PIXEL_FORMAT_JPEG);
+
+    camera_metadata_entry_t availableJpegThumbnailSizes =
+        staticInfo(ANDROID_JPEG_AVAILABLE_THUMBNAIL_SIZES, 2);
+    if (!availableJpegThumbnailSizes.count) return NO_INIT;
+
+    // TODO: Pick default thumbnail size sensibly
+    mParameters.jpegThumbSize[0] = availableJpegThumbnailSizes.data.i32[0];
+    mParameters.jpegThumbSize[1] = availableJpegThumbnailSizes.data.i32[1];
+
+    params.set(CameraParameters::KEY_JPEG_THUMBNAIL_WIDTH,
+            mParameters.jpegThumbSize[0]);
+    params.set(CameraParameters::KEY_JPEG_THUMBNAIL_HEIGHT,
+            mParameters.jpegThumbSize[1]);
+
+    {
+        String8 supportedJpegThumbSizes;
+        for (size_t i=0; i < availableJpegThumbnailSizes.count; i += 2) {
+            if (i != 0) supportedJpegThumbSizes += ",";
+            supportedJpegThumbSizes += String8::format("%dx%d",
+                    availableJpegThumbnailSizes.data.i32[i],
+                    availableJpegThumbnailSizes.data.i32[i+1]);
+        }
+        params.set(CameraParameters::KEY_SUPPORTED_JPEG_THUMBNAIL_SIZES,
+                supportedJpegThumbSizes);
+    }
+
+    mParameters.jpegThumbQuality = 90;
+    params.set(CameraParameters::KEY_JPEG_THUMBNAIL_QUALITY,
+            mParameters.jpegThumbQuality);
+    mParameters.jpegQuality = 90;
+    params.set(CameraParameters::KEY_JPEG_QUALITY,
+            mParameters.jpegQuality);
+    mParameters.jpegRotation = 0;
+    params.set(CameraParameters::KEY_ROTATION,
+            mParameters.jpegRotation);
+
+    mParameters.gpsEnabled = false;
+    mParameters.gpsProcessingMethod = "unknown";
+    // GPS fields in CameraParameters are not set by implementation
+
+    mParameters.wbMode = ANDROID_CONTROL_AWB_AUTO;
+    params.set(CameraParameters::KEY_WHITE_BALANCE,
+            CameraParameters::WHITE_BALANCE_AUTO);
+
+    camera_metadata_entry_t availableWhiteBalanceModes =
+        staticInfo(ANDROID_CONTROL_AWB_AVAILABLE_MODES);
+    {
+        String8 supportedWhiteBalance;
+        bool addComma = false;
+        for (size_t i=0; i < availableWhiteBalanceModes.count; i++) {
+            if (addComma) supportedWhiteBalance += ",";
+            addComma = true;
+            switch (availableWhiteBalanceModes.data.u8[i]) {
+            case ANDROID_CONTROL_AWB_AUTO:
+                supportedWhiteBalance +=
+                    CameraParameters::WHITE_BALANCE_AUTO;
+                break;
+            case ANDROID_CONTROL_AWB_INCANDESCENT:
+                supportedWhiteBalance +=
+                    CameraParameters::WHITE_BALANCE_INCANDESCENT;
+                break;
+            case ANDROID_CONTROL_AWB_FLUORESCENT:
+                supportedWhiteBalance +=
+                    CameraParameters::WHITE_BALANCE_FLUORESCENT;
+                break;
+            case ANDROID_CONTROL_AWB_WARM_FLUORESCENT:
+                supportedWhiteBalance +=
+                    CameraParameters::WHITE_BALANCE_WARM_FLUORESCENT;
+                break;
+            case ANDROID_CONTROL_AWB_DAYLIGHT:
+                supportedWhiteBalance +=
+                    CameraParameters::WHITE_BALANCE_DAYLIGHT;
+                break;
+            case ANDROID_CONTROL_AWB_CLOUDY_DAYLIGHT:
+                supportedWhiteBalance +=
+                    CameraParameters::WHITE_BALANCE_CLOUDY_DAYLIGHT;
+                break;
+            case ANDROID_CONTROL_AWB_TWILIGHT:
+                supportedWhiteBalance +=
+                    CameraParameters::WHITE_BALANCE_TWILIGHT;
+                break;
+            case ANDROID_CONTROL_AWB_SHADE:
+                supportedWhiteBalance +=
+                    CameraParameters::WHITE_BALANCE_SHADE;
+                break;
+            // Skipping values not mappable to v1 API
+            case ANDROID_CONTROL_AWB_OFF:
+                addComma = false;
+                break;
+            default:
+                ALOGW("%s: Camera %d: Unknown white balance value: %d",
+                        __FUNCTION__, mCameraId,
+                        availableWhiteBalanceModes.data.u8[i]);
+                addComma = false;
+                break;
+            }
+        }
+        params.set(CameraParameters::KEY_SUPPORTED_WHITE_BALANCE,
+                supportedWhiteBalance);
+    }
+
+    mParameters.effectMode = ANDROID_CONTROL_EFFECT_OFF;
+    params.set(CameraParameters::KEY_EFFECT,
+            CameraParameters::EFFECT_NONE);
+
+    camera_metadata_entry_t availableEffects =
+        staticInfo(ANDROID_CONTROL_AVAILABLE_EFFECTS);
+    if (!availableEffects.count) return NO_INIT;
+    {
+        String8 supportedEffects;
+        bool addComma = false;
+        for (size_t i=0; i < availableEffects.count; i++) {
+            if (addComma) supportedEffects += ",";
+            addComma = true;
+            switch (availableEffects.data.u8[i]) {
+                case ANDROID_CONTROL_EFFECT_OFF:
+                    supportedEffects +=
+                        CameraParameters::EFFECT_NONE;
+                    break;
+                case ANDROID_CONTROL_EFFECT_MONO:
+                    supportedEffects +=
+                        CameraParameters::EFFECT_MONO;
+                    break;
+                case ANDROID_CONTROL_EFFECT_NEGATIVE:
+                    supportedEffects +=
+                        CameraParameters::EFFECT_NEGATIVE;
+                    break;
+                case ANDROID_CONTROL_EFFECT_SOLARIZE:
+                    supportedEffects +=
+                        CameraParameters::EFFECT_SOLARIZE;
+                    break;
+                case ANDROID_CONTROL_EFFECT_SEPIA:
+                    supportedEffects +=
+                        CameraParameters::EFFECT_SEPIA;
+                    break;
+                case ANDROID_CONTROL_EFFECT_POSTERIZE:
+                    supportedEffects +=
+                        CameraParameters::EFFECT_POSTERIZE;
+                    break;
+                case ANDROID_CONTROL_EFFECT_WHITEBOARD:
+                    supportedEffects +=
+                        CameraParameters::EFFECT_WHITEBOARD;
+                    break;
+                case ANDROID_CONTROL_EFFECT_BLACKBOARD:
+                    supportedEffects +=
+                        CameraParameters::EFFECT_BLACKBOARD;
+                    break;
+                case ANDROID_CONTROL_EFFECT_AQUA:
+                    supportedEffects +=
+                        CameraParameters::EFFECT_AQUA;
+                    break;
+                default:
+                    ALOGW("%s: Camera %d: Unknown effect value: %d",
+                        __FUNCTION__, mCameraId, availableEffects.data.u8[i]);
+                    addComma = false;
+                    break;
+            }
+        }
+        params.set(CameraParameters::KEY_SUPPORTED_EFFECTS, supportedEffects);
+    }
+
+    mParameters.antibandingMode = ANDROID_CONTROL_AE_ANTIBANDING_AUTO;
+    params.set(CameraParameters::KEY_ANTIBANDING,
+            CameraParameters::ANTIBANDING_AUTO);
+
+    camera_metadata_entry_t availableAntibandingModes =
+        staticInfo(ANDROID_CONTROL_AE_AVAILABLE_ANTIBANDING_MODES);
+    if (!availableAntibandingModes.count) return NO_INIT;
+    {
+        String8 supportedAntibanding;
+        bool addComma = false;
+        for (size_t i=0; i < availableAntibandingModes.count; i++) {
+            if (addComma) supportedAntibanding += ",";
+            addComma = true;
+            switch (availableAntibandingModes.data.u8[i]) {
+                case ANDROID_CONTROL_AE_ANTIBANDING_OFF:
+                    supportedAntibanding +=
+                        CameraParameters::ANTIBANDING_OFF;
+                    break;
+                case ANDROID_CONTROL_AE_ANTIBANDING_50HZ:
+                    supportedAntibanding +=
+                        CameraParameters::ANTIBANDING_50HZ;
+                    break;
+                case ANDROID_CONTROL_AE_ANTIBANDING_60HZ:
+                    supportedAntibanding +=
+                        CameraParameters::ANTIBANDING_60HZ;
+                    break;
+                case ANDROID_CONTROL_AE_ANTIBANDING_AUTO:
+                    supportedAntibanding +=
+                        CameraParameters::ANTIBANDING_AUTO;
+                    break;
+                default:
+                    ALOGW("%s: Camera %d: Unknown antibanding value: %d",
+                        __FUNCTION__, mCameraId,
+                            availableAntibandingModes.data.u8[i]);
+                    addComma = false;
+                    break;
+            }
+        }
+        params.set(CameraParameters::KEY_SUPPORTED_ANTIBANDING,
+                supportedAntibanding);
+    }
+
+    mParameters.sceneMode = ANDROID_CONTROL_OFF;
+    params.set(CameraParameters::KEY_SCENE_MODE,
+            CameraParameters::SCENE_MODE_AUTO);
+
+    camera_metadata_entry_t availableSceneModes =
+        staticInfo(ANDROID_CONTROL_AVAILABLE_SCENE_MODES);
+    if (!availableSceneModes.count) return NO_INIT;
+    {
+        String8 supportedSceneModes(CameraParameters::SCENE_MODE_AUTO);
+        bool addComma = true;
+        bool noSceneModes = false;
+        for (size_t i=0; i < availableSceneModes.count; i++) {
+            if (addComma) supportedSceneModes += ",";
+            addComma = true;
+            switch (availableSceneModes.data.u8[i]) {
+                case ANDROID_CONTROL_SCENE_MODE_UNSUPPORTED:
+                    noSceneModes = true;
+                    break;
+                case ANDROID_CONTROL_SCENE_MODE_FACE_PRIORITY:
+                    // Not in old API
+                    addComma = false;
+                    break;
+                case ANDROID_CONTROL_SCENE_MODE_ACTION:
+                    supportedSceneModes +=
+                        CameraParameters::SCENE_MODE_ACTION;
+                    break;
+                case ANDROID_CONTROL_SCENE_MODE_PORTRAIT:
+                    supportedSceneModes +=
+                        CameraParameters::SCENE_MODE_PORTRAIT;
+                    break;
+                case ANDROID_CONTROL_SCENE_MODE_LANDSCAPE:
+                    supportedSceneModes +=
+                        CameraParameters::SCENE_MODE_LANDSCAPE;
+                    break;
+                case ANDROID_CONTROL_SCENE_MODE_NIGHT:
+                    supportedSceneModes +=
+                        CameraParameters::SCENE_MODE_NIGHT;
+                    break;
+                case ANDROID_CONTROL_SCENE_MODE_NIGHT_PORTRAIT:
+                    supportedSceneModes +=
+                        CameraParameters::SCENE_MODE_NIGHT_PORTRAIT;
+                    break;
+                case ANDROID_CONTROL_SCENE_MODE_THEATRE:
+                    supportedSceneModes +=
+                        CameraParameters::SCENE_MODE_THEATRE;
+                    break;
+                case ANDROID_CONTROL_SCENE_MODE_BEACH:
+                    supportedSceneModes +=
+                        CameraParameters::SCENE_MODE_BEACH;
+                    break;
+                case ANDROID_CONTROL_SCENE_MODE_SNOW:
+                    supportedSceneModes +=
+                        CameraParameters::SCENE_MODE_SNOW;
+                    break;
+                case ANDROID_CONTROL_SCENE_MODE_SUNSET:
+                    supportedSceneModes +=
+                        CameraParameters::SCENE_MODE_SUNSET;
+                    break;
+                case ANDROID_CONTROL_SCENE_MODE_STEADYPHOTO:
+                    supportedSceneModes +=
+                        CameraParameters::SCENE_MODE_STEADYPHOTO;
+                    break;
+                case ANDROID_CONTROL_SCENE_MODE_FIREWORKS:
+                    supportedSceneModes +=
+                        CameraParameters::SCENE_MODE_FIREWORKS;
+                    break;
+                case ANDROID_CONTROL_SCENE_MODE_SPORTS:
+                    supportedSceneModes +=
+                        CameraParameters::SCENE_MODE_SPORTS;
+                    break;
+                case ANDROID_CONTROL_SCENE_MODE_PARTY:
+                    supportedSceneModes +=
+                        CameraParameters::SCENE_MODE_PARTY;
+                    break;
+                case ANDROID_CONTROL_SCENE_MODE_CANDLELIGHT:
+                    supportedSceneModes +=
+                        CameraParameters::SCENE_MODE_CANDLELIGHT;
+                    break;
+                case ANDROID_CONTROL_SCENE_MODE_BARCODE:
+                    supportedSceneModes +=
+                        CameraParameters::SCENE_MODE_BARCODE;
+                    break;
+                default:
+                    ALOGW("%s: Camera %d: Unknown scene mode value: %d",
+                        __FUNCTION__, mCameraId,
+                            availableSceneModes.data.u8[i]);
+                    addComma = false;
+                    break;
+            }
+        }
+        if (!noSceneModes) {
+            params.set(CameraParameters::KEY_SUPPORTED_SCENE_MODES,
+                    supportedSceneModes);
+        }
+    }
+
+    camera_metadata_entry_t flashAvailable =
+        staticInfo(ANDROID_FLASH_AVAILABLE, 1, 1);
+    if (!flashAvailable.count) return NO_INIT;
+
+    camera_metadata_entry_t availableAeModes =
+        staticInfo(ANDROID_CONTROL_AE_AVAILABLE_MODES);
+    if (!availableAeModes.count) return NO_INIT;
+
+    if (flashAvailable.data.u8[0]) {
+        mParameters.flashMode = Parameters::FLASH_MODE_AUTO;
+        params.set(CameraParameters::KEY_FLASH_MODE,
+                CameraParameters::FLASH_MODE_AUTO);
+
+        String8 supportedFlashModes(CameraParameters::FLASH_MODE_OFF);
+        supportedFlashModes = supportedFlashModes +
+            "," + CameraParameters::FLASH_MODE_AUTO +
+            "," + CameraParameters::FLASH_MODE_ON +
+            "," + CameraParameters::FLASH_MODE_TORCH;
+        for (size_t i=0; i < availableAeModes.count; i++) {
+            if (availableAeModes.data.u8[i] ==
+                    ANDROID_CONTROL_AE_ON_AUTO_FLASH_REDEYE) {
+                supportedFlashModes = supportedFlashModes + "," +
+                    CameraParameters::FLASH_MODE_RED_EYE;
+                break;
+            }
+        }
+        params.set(CameraParameters::KEY_SUPPORTED_FLASH_MODES,
+                supportedFlashModes);
+    } else {
+        mParameters.flashMode = Parameters::FLASH_MODE_OFF;
+        params.set(CameraParameters::KEY_FLASH_MODE,
+                CameraParameters::FLASH_MODE_OFF);
+        params.set(CameraParameters::KEY_SUPPORTED_FLASH_MODES,
+                CameraParameters::FLASH_MODE_OFF);
+    }
+
+    camera_metadata_entry_t minFocusDistance =
+        staticInfo(ANDROID_LENS_MINIMUM_FOCUS_DISTANCE, 1, 1);
+    if (!minFocusDistance.count) return NO_INIT;
+
+    camera_metadata_entry_t availableAfModes =
+        staticInfo(ANDROID_CONTROL_AF_AVAILABLE_MODES);
+    if (!availableAfModes.count) return NO_INIT;
+
+    if (minFocusDistance.data.f[0] == 0) {
+        // Fixed-focus lens
+        mParameters.focusMode = Parameters::FOCUS_MODE_FIXED;
+        params.set(CameraParameters::KEY_FOCUS_MODE,
+                CameraParameters::FOCUS_MODE_FIXED);
+        params.set(CameraParameters::KEY_SUPPORTED_FOCUS_MODES,
+                CameraParameters::FOCUS_MODE_FIXED);
+    } else {
+        mParameters.focusMode = Parameters::FOCUS_MODE_AUTO;
+        params.set(CameraParameters::KEY_FOCUS_MODE,
+                CameraParameters::FOCUS_MODE_AUTO);
+        String8 supportedFocusModes(CameraParameters::FOCUS_MODE_FIXED);
+        supportedFocusModes = supportedFocusModes + "," +
+            CameraParameters::FOCUS_MODE_INFINITY;
+        bool addComma = true;
+
+        for (size_t i=0; i < availableAfModes.count; i++) {
+            if (addComma) supportedFocusModes += ",";
+            addComma = true;
+            switch (availableAfModes.data.u8[i]) {
+                case ANDROID_CONTROL_AF_AUTO:
+                    supportedFocusModes +=
+                        CameraParameters::FOCUS_MODE_AUTO;
+                    break;
+                case ANDROID_CONTROL_AF_MACRO:
+                    supportedFocusModes +=
+                        CameraParameters::FOCUS_MODE_MACRO;
+                    break;
+                case ANDROID_CONTROL_AF_CONTINUOUS_VIDEO:
+                    supportedFocusModes +=
+                        CameraParameters::FOCUS_MODE_CONTINUOUS_VIDEO;
+                    break;
+                case ANDROID_CONTROL_AF_CONTINUOUS_PICTURE:
+                    supportedFocusModes +=
+                        CameraParameters::FOCUS_MODE_CONTINUOUS_PICTURE;
+                    break;
+                case ANDROID_CONTROL_AF_EDOF:
+                    supportedFocusModes +=
+                        CameraParameters::FOCUS_MODE_EDOF;
+                    break;
+                // Not supported in old API
+                case ANDROID_CONTROL_AF_OFF:
+                    addComma = false;
+                    break;
+                default:
+                    ALOGW("%s: Camera %d: Unknown AF mode value: %d",
+                        __FUNCTION__, mCameraId, availableAfModes.data.u8[i]);
+                    addComma = false;
+                    break;
+            }
+        }
+        params.set(CameraParameters::KEY_SUPPORTED_FOCUS_MODES,
+                supportedFocusModes);
+    }
+
+    camera_metadata_entry_t max3aRegions =
+        staticInfo(ANDROID_CONTROL_MAX_REGIONS, 1, 1);
+    if (!max3aRegions.count) return NO_INIT;
+
+    params.set(CameraParameters::KEY_MAX_NUM_FOCUS_AREAS,
+            max3aRegions.data.i32[0]);
+    params.set(CameraParameters::KEY_FOCUS_AREAS,
+            "(0,0,0,0,0)");
+    mParameters.focusingAreas.clear();
+    mParameters.focusingAreas.add(Parameters::Area(0,0,0,0,0));
+
+    camera_metadata_entry_t availableFocalLengths =
+        staticInfo(ANDROID_LENS_AVAILABLE_FOCAL_LENGTHS);
+    if (!availableFocalLengths.count) return NO_INIT;
+
+    float minFocalLength = availableFocalLengths.data.f[0];
+    params.setFloat(CameraParameters::KEY_FOCAL_LENGTH, minFocalLength);
+
+    camera_metadata_entry_t sensorSize =
+        staticInfo(ANDROID_SENSOR_PHYSICAL_SIZE, 2, 2);
+    if (!sensorSize.count) return NO_INIT;
+
+    // The fields of view here assume infinity focus, maximum wide angle
+    float horizFov = 180 / M_PI *
+            2 * atanf(sensorSize.data.f[0] / (2 * minFocalLength));
+    float vertFov  = 180 / M_PI *
+            2 * atanf(sensorSize.data.f[1] / (2 * minFocalLength));
+    params.setFloat(CameraParameters::KEY_HORIZONTAL_VIEW_ANGLE, horizFov);
+    params.setFloat(CameraParameters::KEY_VERTICAL_VIEW_ANGLE, vertFov);
+
+    mParameters.exposureCompensation = 0;
+    params.set(CameraParameters::KEY_EXPOSURE_COMPENSATION,
+                mParameters.exposureCompensation);
+
+    camera_metadata_entry_t exposureCompensationRange =
+        staticInfo(ANDROID_CONTROL_AE_EXP_COMPENSATION_RANGE, 2, 2);
+    if (!exposureCompensationRange.count) return NO_INIT;
+
+    params.set(CameraParameters::KEY_MAX_EXPOSURE_COMPENSATION,
+            exposureCompensationRange.data.i32[1]);
+    params.set(CameraParameters::KEY_MIN_EXPOSURE_COMPENSATION,
+            exposureCompensationRange.data.i32[0]);
+
+    camera_metadata_entry_t exposureCompensationStep =
+        staticInfo(ANDROID_CONTROL_AE_EXP_COMPENSATION_STEP, 1, 1);
+    if (!exposureCompensationStep.count) return NO_INIT;
+
+    params.setFloat(CameraParameters::KEY_EXPOSURE_COMPENSATION_STEP,
+            exposureCompensationStep.data.r[0].numerator /
+            exposureCompensationStep.data.r[0].denominator);
+
+    mParameters.autoExposureLock = false;
+    params.set(CameraParameters::KEY_AUTO_EXPOSURE_LOCK,
+            CameraParameters::FALSE);
+    params.set(CameraParameters::KEY_AUTO_EXPOSURE_LOCK_SUPPORTED,
+            CameraParameters::TRUE);
+
+    mParameters.autoWhiteBalanceLock = false;
+    params.set(CameraParameters::KEY_AUTO_WHITEBALANCE_LOCK,
+            CameraParameters::FALSE);
+    params.set(CameraParameters::KEY_AUTO_WHITEBALANCE_LOCK_SUPPORTED,
+            CameraParameters::TRUE);
+
+    mParameters.meteringAreas.add(Parameters::Area(0, 0, 0, 0, 0));
+    params.set(CameraParameters::KEY_MAX_NUM_METERING_AREAS,
+            max3aRegions.data.i32[0]);
+    params.set(CameraParameters::KEY_METERING_AREAS,
+            "(0,0,0,0,0)");
+
+    mParameters.zoom = 0;
+    params.set(CameraParameters::KEY_ZOOM, mParameters.zoom);
+    params.set(CameraParameters::KEY_MAX_ZOOM, NUM_ZOOM_STEPS - 1);
+
+    camera_metadata_entry_t maxDigitalZoom =
+        staticInfo(ANDROID_SCALER_AVAILABLE_MAX_ZOOM, 1, 1);
+    if (!maxDigitalZoom.count) return NO_INIT;
+
+    {
+        String8 zoomRatios;
+        float zoom = 1.f;
+        float zoomIncrement = (maxDigitalZoom.data.f[0] - zoom) /
+                (NUM_ZOOM_STEPS-1);
+        bool addComma = false;
+        for (size_t i=0; i < NUM_ZOOM_STEPS; i++) {
+            if (addComma) zoomRatios += ",";
+            addComma = true;
+            zoomRatios += String8::format("%d", static_cast<int>(zoom * 100));
+            zoom += zoomIncrement;
+        }
+        params.set(CameraParameters::KEY_ZOOM_RATIOS, zoomRatios);
+    }
+
+    params.set(CameraParameters::KEY_ZOOM_SUPPORTED,
+            CameraParameters::TRUE);
+    params.set(CameraParameters::KEY_SMOOTH_ZOOM_SUPPORTED,
+            CameraParameters::TRUE);
+
+    params.set(CameraParameters::KEY_FOCUS_DISTANCES,
+            "Infinity,Infinity,Infinity");
+
+    camera_metadata_entry_t maxFacesDetected =
+        staticInfo(ANDROID_STATS_MAX_FACE_COUNT, 1, 1);
+    params.set(CameraParameters::KEY_MAX_NUM_DETECTED_FACES_HW,
+            maxFacesDetected.data.i32[0]);
+    params.set(CameraParameters::KEY_MAX_NUM_DETECTED_FACES_SW,
+            0);
+
+    params.set(CameraParameters::KEY_VIDEO_FRAME_FORMAT,
+            formatEnumToString(HAL_PIXEL_FORMAT_YCrCb_420_SP));
+
+    params.set(CameraParameters::KEY_RECORDING_HINT,
+            CameraParameters::FALSE);
+
+    params.set(CameraParameters::KEY_VIDEO_SNAPSHOT_SUPPORTED,
+            CameraParameters::TRUE);
+
+    params.set(CameraParameters::KEY_VIDEO_STABILIZATION,
+            CameraParameters::FALSE);
+
+    camera_metadata_entry_t availableVideoStabilizationModes =
+        staticInfo(ANDROID_CONTROL_AVAILABLE_VIDEO_STABILIZATION_MODES);
+    if (!availableVideoStabilizationModes.count) return NO_INIT;
+
+    if (availableVideoStabilizationModes.count > 1) {
+        params.set(CameraParameters::KEY_VIDEO_STABILIZATION_SUPPORTED,
+                CameraParameters::TRUE);
+    } else {
+        params.set(CameraParameters::KEY_VIDEO_STABILIZATION_SUPPORTED,
+                CameraParameters::FALSE);
+    }
+
+    mParamsFlattened = params.flatten();
+
+    return OK;
+}
+
+status_t Camera2Client::updatePreviewStream() {
+    ATRACE_CALL();
+    status_t res;
+    if (mPreviewStreamId != NO_STREAM) {
+        // Check if stream parameters have to change
+        uint32_t currentWidth, currentHeight;
+        res = mDevice->getStreamInfo(mPreviewStreamId,
+                &currentWidth, &currentHeight, 0);
+        if (res != OK) {
+            ALOGE("%s: Camera %d: Error querying preview stream info: "
+                    "%s (%d)", __FUNCTION__, mCameraId, strerror(-res), res);
+            return res;
+        }
+        if (currentWidth != (uint32_t)mParameters.previewWidth ||
+                currentHeight != (uint32_t)mParameters.previewHeight) {
+            res = mDevice->waitUntilDrained();
+            if (res != OK) {
+                ALOGE("%s: Camera %d: Error waiting for preview to drain: "
+                        "%s (%d)", __FUNCTION__, mCameraId, strerror(-res), res);
+                return res;
+            }
+            res = mDevice->deleteStream(mPreviewStreamId);
+            if (res != OK) {
+                ALOGE("%s: Camera %d: Unable to delete old output stream "
+                        "for preview: %s (%d)", __FUNCTION__, mCameraId,
+                        strerror(-res), res);
+                return res;
+            }
+            mPreviewStreamId = NO_STREAM;
+        }
+    }
+
+    if (mPreviewStreamId == NO_STREAM) {
+        res = mDevice->createStream(mPreviewWindow,
+                mParameters.previewWidth, mParameters.previewHeight,
+                CAMERA2_HAL_PIXEL_FORMAT_OPAQUE, 0,
+                &mPreviewStreamId);
+        if (res != OK) {
+            ALOGE("%s: Camera %d: Unable to create preview stream: %s (%d)",
+                    __FUNCTION__, mCameraId, strerror(-res), res);
+            return res;
+        }
+    }
+
+    res = mDevice->setStreamTransform(mPreviewStreamId,
+            mParameters.previewTransform);
+    if (res != OK) {
+        ALOGE("%s: Camera %d: Unable to set preview stream transform: "
+                "%s (%d)", __FUNCTION__, mCameraId, strerror(-res), res);
+        return res;
+    }
+
+    return OK;
+}
+
+status_t Camera2Client::updatePreviewRequest() {
+    ATRACE_CALL();
+    status_t res;
+    if (mPreviewRequest == NULL) {
+        res = mDevice->createDefaultRequest(CAMERA2_TEMPLATE_PREVIEW,
+                &mPreviewRequest);
+        if (res != OK) {
+            ALOGE("%s: Camera %d: Unable to create default preview request: "
+                    "%s (%d)", __FUNCTION__, mCameraId, strerror(-res), res);
+            return res;
+        }
+    }
+
+    res = updateRequestCommon(mPreviewRequest);
+    if (res != OK) {
+        ALOGE("%s: Camera %d: Unable to update common entries of preview "
+                "request: %s (%d)", __FUNCTION__, mCameraId,
+                strerror(-res), res);
+        return res;
+    }
+
+    return OK;
+}
+
+status_t Camera2Client::updateCaptureStream() {
+    ATRACE_CALL();
+    status_t res;
+    // Find out buffer size for JPEG
+    camera_metadata_entry_t maxJpegSize =
+            staticInfo(ANDROID_JPEG_MAX_SIZE);
+    if (maxJpegSize.count == 0) {
+        ALOGE("%s: Camera %d: Can't find ANDROID_JPEG_MAX_SIZE!",
+                __FUNCTION__, mCameraId);
+        return INVALID_OPERATION;
+    }
+
+    if (mCaptureConsumer == 0) {
+        // Create CPU buffer queue endpoint
+        mCaptureConsumer = new CpuConsumer(1);
+        mCaptureConsumer->setFrameAvailableListener(new CaptureWaiter(this));
+        mCaptureConsumer->setName(String8("Camera2Client::CaptureConsumer"));
+        mCaptureWindow = new SurfaceTextureClient(
+            mCaptureConsumer->getProducerInterface());
+        // Create memory for API consumption
+        mCaptureHeap = new MemoryHeapBase(maxJpegSize.data.i32[0], 0,
+                "Camera2Client::CaptureHeap");
+        if (mCaptureHeap->getSize() == 0) {
+            ALOGE("%s: Camera %d: Unable to allocate memory for capture",
+                    __FUNCTION__, mCameraId);
+            return NO_MEMORY;
+        }
+        mCaptureMemory = new MemoryBase(mCaptureHeap,
+                0, maxJpegSize.data.i32[0]);
+    }
+
+    if (mCaptureStreamId != NO_STREAM) {
+        // Check if stream parameters have to change
+        uint32_t currentWidth, currentHeight;
+        res = mDevice->getStreamInfo(mCaptureStreamId,
+                &currentWidth, &currentHeight, 0);
+        if (res != OK) {
+            ALOGE("%s: Camera %d: Error querying capture output stream info: "
+                    "%s (%d)", __FUNCTION__, mCameraId, strerror(-res), res);
+            return res;
+        }
+        if (currentWidth != (uint32_t)mParameters.pictureWidth ||
+                currentHeight != (uint32_t)mParameters.pictureHeight) {
+            res = mDevice->deleteStream(mCaptureStreamId);
+            if (res != OK) {
+                ALOGE("%s: Camera %d: Unable to delete old output stream "
+                        "for capture: %s (%d)", __FUNCTION__, mCameraId,
+                        strerror(-res), res);
+                return res;
+            }
+            mCaptureStreamId = NO_STREAM;
+        }
+    }
+
+    if (mCaptureStreamId == NO_STREAM) {
+        // Create stream for HAL production
+        res = mDevice->createStream(mCaptureWindow,
+                mParameters.pictureWidth, mParameters.pictureHeight,
+                HAL_PIXEL_FORMAT_BLOB, maxJpegSize.data.i32[0],
+                &mCaptureStreamId);
+        if (res != OK) {
+            ALOGE("%s: Camera %d: Can't create output stream for capture: "
+                    "%s (%d)", __FUNCTION__, mCameraId, strerror(-res), res);
+            return res;
+        }
+
+    }
+    return OK;
+}
+
+status_t Camera2Client::updateCaptureRequest() {
+    ATRACE_CALL();
+    status_t res;
+    if (mCaptureRequest == NULL) {
+        res = mDevice->createDefaultRequest(CAMERA2_TEMPLATE_STILL_CAPTURE,
+                &mCaptureRequest);
+        if (res != OK) {
+            ALOGE("%s: Camera %d: Unable to create default still image request:"
+                    " %s (%d)", __FUNCTION__, mCameraId, strerror(-res), res);
+            return res;
+        }
+    }
+
+    res = updateRequestCommon(mCaptureRequest);
+    if (res != OK) {
+        ALOGE("%s: Camera %d: Unable to update common entries of capture "
+                "request: %s (%d)", __FUNCTION__, mCameraId,
+                strerror(-res), res);
+        return res;
+    }
+
+    res = updateEntry(mCaptureRequest,
+            ANDROID_JPEG_THUMBNAIL_SIZE,
+            mParameters.jpegThumbSize, 2);
+    if (res != OK) return res;
+    res = updateEntry(mCaptureRequest,
+            ANDROID_JPEG_THUMBNAIL_QUALITY,
+            &mParameters.jpegThumbQuality, 1);
+    if (res != OK) return res;
+    res = updateEntry(mCaptureRequest,
+            ANDROID_JPEG_QUALITY,
+            &mParameters.jpegQuality, 1);
+    if (res != OK) return res;
+    res = updateEntry(mCaptureRequest,
+            ANDROID_JPEG_ORIENTATION,
+            &mParameters.jpegRotation, 1);
+    if (res != OK) return res;
+
+    if (mParameters.gpsEnabled) {
+        res = updateEntry(mCaptureRequest,
+                ANDROID_JPEG_GPS_COORDINATES,
+                mParameters.gpsCoordinates, 3);
+        if (res != OK) return res;
+        res = updateEntry(mCaptureRequest,
+                ANDROID_JPEG_GPS_TIMESTAMP,
+                &mParameters.gpsTimestamp, 1);
+        if (res != OK) return res;
+        res = updateEntry(mCaptureRequest,
+                ANDROID_JPEG_GPS_PROCESSING_METHOD,
+                mParameters.gpsProcessingMethod.string(),
+                mParameters.gpsProcessingMethod.size());
+        if (res != OK) return res;
+    } else {
+        res = deleteEntry(mCaptureRequest,
+                ANDROID_JPEG_GPS_COORDINATES);
+        if (res != OK) return res;
+        res = deleteEntry(mCaptureRequest,
+                ANDROID_JPEG_GPS_TIMESTAMP);
+        if (res != OK) return res;
+        res = deleteEntry(mCaptureRequest,
+                ANDROID_JPEG_GPS_PROCESSING_METHOD);
+        if (res != OK) return res;
+    }
+
+    return OK;
+}
+
+status_t Camera2Client::updateRequestCommon(camera_metadata_t *request) {
+    ATRACE_CALL();
+    status_t res;
+    res = updateEntry(request,
+            ANDROID_CONTROL_AE_TARGET_FPS_RANGE, mParameters.previewFpsRange, 2);
+    if (res != OK) return res;
+
+    uint8_t wbMode = mParameters.autoWhiteBalanceLock ?
+            ANDROID_CONTROL_AWB_LOCKED : mParameters.wbMode;
+    res = updateEntry(request,
+            ANDROID_CONTROL_AWB_MODE, &wbMode, 1);
+    if (res != OK) return res;
+    res = updateEntry(request,
+            ANDROID_CONTROL_EFFECT_MODE, &mParameters.effectMode, 1);
+    if (res != OK) return res;
+    res = updateEntry(request,
+            ANDROID_CONTROL_AE_ANTIBANDING_MODE,
+            &mParameters.antibandingMode, 1);
+    if (res != OK) return res;
+
+    uint8_t controlMode =
+            (mParameters.sceneMode == ANDROID_CONTROL_SCENE_MODE_UNSUPPORTED) ?
+            ANDROID_CONTROL_AUTO : ANDROID_CONTROL_USE_SCENE_MODE;
+    res = updateEntry(request,
+            ANDROID_CONTROL_MODE, &controlMode, 1);
+    if (res != OK) return res;
+    if (controlMode == ANDROID_CONTROL_USE_SCENE_MODE) {
+        res = updateEntry(request,
+                ANDROID_CONTROL_SCENE_MODE,
+                &mParameters.sceneMode, 1);
+        if (res != OK) return res;
+    }
+
+    uint8_t flashMode = ANDROID_FLASH_OFF;
+    uint8_t aeMode;
+    switch (mParameters.flashMode) {
+        case Parameters::FLASH_MODE_OFF:
+            aeMode = ANDROID_CONTROL_AE_ON; break;
+        case Parameters::FLASH_MODE_AUTO:
+            aeMode = ANDROID_CONTROL_AE_ON_AUTO_FLASH; break;
+        case Parameters::FLASH_MODE_ON:
+            aeMode = ANDROID_CONTROL_AE_ON_ALWAYS_FLASH; break;
+        case Parameters::FLASH_MODE_TORCH:
+            aeMode = ANDROID_CONTROL_AE_ON;
+            flashMode = ANDROID_FLASH_TORCH;
+            break;
+        case Parameters::FLASH_MODE_RED_EYE:
+            aeMode = ANDROID_CONTROL_AE_ON_AUTO_FLASH_REDEYE; break;
+        default:
+            ALOGE("%s: Camera %d: Unknown flash mode %d", __FUNCTION__,
+                    mCameraId, mParameters.flashMode);
+            return BAD_VALUE;
+    }
+    if (mParameters.autoExposureLock) aeMode = ANDROID_CONTROL_AE_LOCKED;
+
+    res = updateEntry(request,
+            ANDROID_FLASH_MODE, &flashMode, 1);
+    if (res != OK) return res;
+    res = updateEntry(request,
+            ANDROID_CONTROL_AE_MODE, &aeMode, 1);
+    if (res != OK) return res;
+
+    float focusDistance = 0; // infinity focus in diopters
+    uint8_t focusMode;
+    switch (mParameters.focusMode) {
+        case Parameters::FOCUS_MODE_AUTO:
+        case Parameters::FOCUS_MODE_MACRO:
+        case Parameters::FOCUS_MODE_CONTINUOUS_VIDEO:
+        case Parameters::FOCUS_MODE_CONTINUOUS_PICTURE:
+        case Parameters::FOCUS_MODE_EDOF:
+            focusMode = mParameters.focusMode;
+            break;
+        case Parameters::FOCUS_MODE_INFINITY:
+        case Parameters::FOCUS_MODE_FIXED:
+            focusMode = ANDROID_CONTROL_AF_OFF;
+            break;
+        default:
+            ALOGE("%s: Camera %d: Unknown focus mode %d", __FUNCTION__,
+                    mCameraId, mParameters.focusMode);
+            return BAD_VALUE;
+    }
+    res = updateEntry(request,
+            ANDROID_LENS_FOCUS_DISTANCE, &focusDistance, 1);
+    if (res != OK) return res;
+    res = updateEntry(request,
+            ANDROID_CONTROL_AF_MODE, &focusMode, 1);
+    if (res != OK) return res;
+
+    size_t focusingAreasSize = mParameters.focusingAreas.size() * 5;
+    int32_t *focusingAreas = new int32_t[focusingAreasSize];
+    for (size_t i = 0; i < focusingAreasSize; i += 5) {
+        focusingAreas[i + 0] = mParameters.focusingAreas[i].left;
+        focusingAreas[i + 1] = mParameters.focusingAreas[i].top;
+        focusingAreas[i + 2] = mParameters.focusingAreas[i].right;
+        focusingAreas[i + 3] = mParameters.focusingAreas[i].bottom;
+        focusingAreas[i + 4] = mParameters.focusingAreas[i].weight;
+    }
+    res = updateEntry(request,
+            ANDROID_CONTROL_AF_REGIONS, focusingAreas,focusingAreasSize);
+    if (res != OK) return res;
+    delete[] focusingAreas;
+
+    res = updateEntry(request,
+            ANDROID_CONTROL_AE_EXP_COMPENSATION,
+            &mParameters.exposureCompensation, 1);
+    if (res != OK) return res;
+
+    size_t meteringAreasSize = mParameters.meteringAreas.size() * 5;
+    int32_t *meteringAreas = new int32_t[meteringAreasSize];
+    for (size_t i = 0; i < meteringAreasSize; i += 5) {
+        meteringAreas[i + 0] = mParameters.meteringAreas[i].left;
+        meteringAreas[i + 1] = mParameters.meteringAreas[i].top;
+        meteringAreas[i + 2] = mParameters.meteringAreas[i].right;
+        meteringAreas[i + 3] = mParameters.meteringAreas[i].bottom;
+        meteringAreas[i + 4] = mParameters.meteringAreas[i].weight;
+    }
+    res = updateEntry(request,
+            ANDROID_CONTROL_AE_REGIONS, meteringAreas, meteringAreasSize);
+    if (res != OK) return res;
+
+    res = updateEntry(request,
+            ANDROID_CONTROL_AWB_REGIONS, meteringAreas, meteringAreasSize);
+    if (res != OK) return res;
+    delete[] meteringAreas;
+
+    // Need to convert zoom index into a crop rectangle. The rectangle is
+    // chosen to maximize its area on the sensor
+
+    camera_metadata_entry_t maxDigitalZoom =
+            staticInfo(ANDROID_SCALER_AVAILABLE_MAX_ZOOM);
+    float zoomIncrement = (maxDigitalZoom.data.f[0] - 1) /
+            (NUM_ZOOM_STEPS-1);
+    float zoomRatio = 1 + zoomIncrement * mParameters.zoom;
+
+    camera_metadata_entry_t activePixelArraySize =
+            staticInfo(ANDROID_SENSOR_ACTIVE_ARRAY_SIZE, 2, 2);
+    int32_t arrayWidth = activePixelArraySize.data.i32[0];
+    int32_t arrayHeight = activePixelArraySize.data.i32[1];
+    float zoomLeft, zoomTop, zoomWidth, zoomHeight;
+    if (mParameters.previewWidth >= mParameters.previewHeight) {
+        zoomWidth =  arrayWidth / zoomRatio;
+        zoomHeight = zoomWidth *
+                mParameters.previewHeight / mParameters.previewWidth;
+    } else {
+        zoomHeight = arrayHeight / zoomRatio;
+        zoomWidth = zoomHeight *
+                mParameters.previewWidth / mParameters.previewHeight;
+    }
+    zoomLeft = (arrayWidth - zoomWidth) / 2;
+    zoomTop = (arrayHeight - zoomHeight) / 2;
+
+    int32_t cropRegion[3] = { zoomLeft, zoomTop, zoomWidth };
+    res = updateEntry(request,
+            ANDROID_SCALER_CROP_REGION, cropRegion, 3);
+    if (res != OK) return res;
+
+    // TODO: Decide how to map recordingHint, or whether just to ignore it
+
+    uint8_t vstabMode = mParameters.videoStabilization ?
+            ANDROID_CONTROL_VIDEO_STABILIZATION_ON :
+            ANDROID_CONTROL_VIDEO_STABILIZATION_OFF;
+    res = updateEntry(request,
+            ANDROID_CONTROL_VIDEO_STABILIZATION_MODE,
+            &vstabMode, 1);
+    if (res != OK) return res;
+
+    return OK;
+}
+
+status_t Camera2Client::updateEntry(camera_metadata_t *buffer,
+        uint32_t tag, const void *data, size_t data_count) {
+    camera_metadata_entry_t entry;
+    status_t res;
+    res = find_camera_metadata_entry(buffer, tag, &entry);
+    if (res == NAME_NOT_FOUND) {
+        res = add_camera_metadata_entry(buffer,
+                tag, data, data_count);
+    } else if (res == OK) {
+        res = update_camera_metadata_entry(buffer,
+                entry.index, data, data_count, NULL);
+    }
+
+    if (res != OK) {
+        ALOGE("%s: Unable to update metadata entry %s.%s (%x): %s (%d)",
+                __FUNCTION__, get_camera_metadata_section_name(tag),
+                get_camera_metadata_tag_name(tag), tag, strerror(-res), res);
+    }
+    return res;
+}
+
+status_t Camera2Client::deleteEntry(camera_metadata_t *buffer, uint32_t tag) {
+    camera_metadata_entry_t entry;
+    status_t res;
+    res = find_camera_metadata_entry(buffer, tag, &entry);
+    if (res == NAME_NOT_FOUND) {
+        return OK;
+    } else if (res != OK) {
+        ALOGE("%s: Error looking for entry %s.%s (%x): %s %d",
+                __FUNCTION__,
+                get_camera_metadata_section_name(tag),
+                get_camera_metadata_tag_name(tag), tag, strerror(-res), res);
+        return res;
+    }
+    res = delete_camera_metadata_entry(buffer, entry.index);
+    if (res != OK) {
+        ALOGE("%s: Error deleting entry %s.%s (%x): %s %d",
+                __FUNCTION__,
+                get_camera_metadata_section_name(tag),
+                get_camera_metadata_tag_name(tag), tag, strerror(-res), res);
+    }
+    return res;
+}
+int Camera2Client::formatStringToEnum(const char *format) {
+    return
+        !strcmp(format, CameraParameters::PIXEL_FORMAT_YUV422SP) ?
+            HAL_PIXEL_FORMAT_YCbCr_422_SP : // NV16
+        !strcmp(format, CameraParameters::PIXEL_FORMAT_YUV420SP) ?
+            HAL_PIXEL_FORMAT_YCrCb_420_SP : // NV21
+        !strcmp(format, CameraParameters::PIXEL_FORMAT_YUV422I) ?
+            HAL_PIXEL_FORMAT_YCbCr_422_I :  // YUY2
+        !strcmp(format, CameraParameters::PIXEL_FORMAT_YUV420P) ?
+            HAL_PIXEL_FORMAT_YV12 :         // YV12
+        !strcmp(format, CameraParameters::PIXEL_FORMAT_RGB565) ?
+            HAL_PIXEL_FORMAT_RGB_565 :      // RGB565
+        !strcmp(format, CameraParameters::PIXEL_FORMAT_RGBA8888) ?
+            HAL_PIXEL_FORMAT_RGBA_8888 :    // RGB8888
+        !strcmp(format, CameraParameters::PIXEL_FORMAT_BAYER_RGGB) ?
+            HAL_PIXEL_FORMAT_RAW_SENSOR :   // Raw sensor data
+        -1;
+}
+
+const char* Camera2Client::formatEnumToString(int format) {
+    const char *fmt;
+    switch(format) {
+        case HAL_PIXEL_FORMAT_YCbCr_422_SP: // NV16
+            fmt = CameraParameters::PIXEL_FORMAT_YUV422SP;
+            break;
+        case HAL_PIXEL_FORMAT_YCrCb_420_SP: // NV21
+            fmt = CameraParameters::PIXEL_FORMAT_YUV420SP;
+            break;
+        case HAL_PIXEL_FORMAT_YCbCr_422_I: // YUY2
+            fmt = CameraParameters::PIXEL_FORMAT_YUV422I;
+            break;
+        case HAL_PIXEL_FORMAT_YV12:        // YV12
+            fmt = CameraParameters::PIXEL_FORMAT_YUV420P;
+            break;
+        case HAL_PIXEL_FORMAT_RGB_565:     // RGB565
+            fmt = CameraParameters::PIXEL_FORMAT_RGB565;
+            break;
+        case HAL_PIXEL_FORMAT_RGBA_8888:   // RGBA8888
+            fmt = CameraParameters::PIXEL_FORMAT_RGBA8888;
+            break;
+        case HAL_PIXEL_FORMAT_RAW_SENSOR:
+            ALOGW("Raw sensor preview format requested.");
+            fmt = CameraParameters::PIXEL_FORMAT_BAYER_RGGB;
+            break;
+        default:
+            ALOGE("%s: Unknown preview format: %x",
+                    __FUNCTION__,  format);
+            fmt = NULL;
+            break;
+    }
+    return fmt;
+}
+
+int Camera2Client::wbModeStringToEnum(const char *wbMode) {
+    return
+        !strcmp(wbMode, CameraParameters::WHITE_BALANCE_AUTO) ?
+            ANDROID_CONTROL_AWB_AUTO :
+        !strcmp(wbMode, CameraParameters::WHITE_BALANCE_INCANDESCENT) ?
+            ANDROID_CONTROL_AWB_INCANDESCENT :
+        !strcmp(wbMode, CameraParameters::WHITE_BALANCE_FLUORESCENT) ?
+            ANDROID_CONTROL_AWB_FLUORESCENT :
+        !strcmp(wbMode, CameraParameters::WHITE_BALANCE_WARM_FLUORESCENT) ?
+            ANDROID_CONTROL_AWB_WARM_FLUORESCENT :
+        !strcmp(wbMode, CameraParameters::WHITE_BALANCE_DAYLIGHT) ?
+            ANDROID_CONTROL_AWB_DAYLIGHT :
+        !strcmp(wbMode, CameraParameters::WHITE_BALANCE_CLOUDY_DAYLIGHT) ?
+            ANDROID_CONTROL_AWB_CLOUDY_DAYLIGHT :
+        !strcmp(wbMode, CameraParameters::WHITE_BALANCE_TWILIGHT) ?
+            ANDROID_CONTROL_AWB_TWILIGHT :
+        !strcmp(wbMode, CameraParameters::WHITE_BALANCE_SHADE) ?
+            ANDROID_CONTROL_AWB_SHADE :
+        -1;
+}
+
+int Camera2Client::effectModeStringToEnum(const char *effectMode) {
+    return
+        !strcmp(effectMode, CameraParameters::EFFECT_NONE) ?
+            ANDROID_CONTROL_EFFECT_OFF :
+        !strcmp(effectMode, CameraParameters::EFFECT_MONO) ?
+            ANDROID_CONTROL_EFFECT_MONO :
+        !strcmp(effectMode, CameraParameters::EFFECT_NEGATIVE) ?
+            ANDROID_CONTROL_EFFECT_NEGATIVE :
+        !strcmp(effectMode, CameraParameters::EFFECT_SOLARIZE) ?
+            ANDROID_CONTROL_EFFECT_SOLARIZE :
+        !strcmp(effectMode, CameraParameters::EFFECT_SEPIA) ?
+            ANDROID_CONTROL_EFFECT_SEPIA :
+        !strcmp(effectMode, CameraParameters::EFFECT_POSTERIZE) ?
+            ANDROID_CONTROL_EFFECT_POSTERIZE :
+        !strcmp(effectMode, CameraParameters::EFFECT_WHITEBOARD) ?
+            ANDROID_CONTROL_EFFECT_WHITEBOARD :
+        !strcmp(effectMode, CameraParameters::EFFECT_BLACKBOARD) ?
+            ANDROID_CONTROL_EFFECT_BLACKBOARD :
+        !strcmp(effectMode, CameraParameters::EFFECT_AQUA) ?
+            ANDROID_CONTROL_EFFECT_AQUA :
+        -1;
+}
+
+int Camera2Client::abModeStringToEnum(const char *abMode) {
+    return
+        !strcmp(abMode, CameraParameters::ANTIBANDING_AUTO) ?
+            ANDROID_CONTROL_AE_ANTIBANDING_AUTO :
+        !strcmp(abMode, CameraParameters::ANTIBANDING_OFF) ?
+            ANDROID_CONTROL_AE_ANTIBANDING_OFF :
+        !strcmp(abMode, CameraParameters::ANTIBANDING_50HZ) ?
+            ANDROID_CONTROL_AE_ANTIBANDING_50HZ :
+        !strcmp(abMode, CameraParameters::ANTIBANDING_60HZ) ?
+            ANDROID_CONTROL_AE_ANTIBANDING_60HZ :
+        -1;
+}
+
+int Camera2Client::sceneModeStringToEnum(const char *sceneMode) {
+    return
+        !strcmp(sceneMode, CameraParameters::SCENE_MODE_AUTO) ?
+            ANDROID_CONTROL_SCENE_MODE_UNSUPPORTED :
+        !strcmp(sceneMode, CameraParameters::SCENE_MODE_ACTION) ?
+            ANDROID_CONTROL_SCENE_MODE_ACTION :
+        !strcmp(sceneMode, CameraParameters::SCENE_MODE_PORTRAIT) ?
+            ANDROID_CONTROL_SCENE_MODE_PORTRAIT :
+        !strcmp(sceneMode, CameraParameters::SCENE_MODE_LANDSCAPE) ?
+            ANDROID_CONTROL_SCENE_MODE_LANDSCAPE :
+        !strcmp(sceneMode, CameraParameters::SCENE_MODE_NIGHT) ?
+            ANDROID_CONTROL_SCENE_MODE_NIGHT :
+        !strcmp(sceneMode, CameraParameters::SCENE_MODE_NIGHT_PORTRAIT) ?
+            ANDROID_CONTROL_SCENE_MODE_NIGHT_PORTRAIT :
+        !strcmp(sceneMode, CameraParameters::SCENE_MODE_THEATRE) ?
+            ANDROID_CONTROL_SCENE_MODE_THEATRE :
+        !strcmp(sceneMode, CameraParameters::SCENE_MODE_BEACH) ?
+            ANDROID_CONTROL_SCENE_MODE_BEACH :
+        !strcmp(sceneMode, CameraParameters::SCENE_MODE_SNOW) ?
+            ANDROID_CONTROL_SCENE_MODE_SNOW :
+        !strcmp(sceneMode, CameraParameters::SCENE_MODE_SUNSET) ?
+            ANDROID_CONTROL_SCENE_MODE_SUNSET :
+        !strcmp(sceneMode, CameraParameters::SCENE_MODE_STEADYPHOTO) ?
+            ANDROID_CONTROL_SCENE_MODE_STEADYPHOTO :
+        !strcmp(sceneMode, CameraParameters::SCENE_MODE_FIREWORKS) ?
+            ANDROID_CONTROL_SCENE_MODE_FIREWORKS :
+        !strcmp(sceneMode, CameraParameters::SCENE_MODE_SPORTS) ?
+            ANDROID_CONTROL_SCENE_MODE_SPORTS :
+        !strcmp(sceneMode, CameraParameters::SCENE_MODE_PARTY) ?
+            ANDROID_CONTROL_SCENE_MODE_PARTY :
+        !strcmp(sceneMode, CameraParameters::SCENE_MODE_CANDLELIGHT) ?
+            ANDROID_CONTROL_SCENE_MODE_CANDLELIGHT :
+        !strcmp(sceneMode, CameraParameters::SCENE_MODE_BARCODE) ?
+            ANDROID_CONTROL_SCENE_MODE_BARCODE:
+        -1;
+}
+
+Camera2Client::Parameters::flashMode_t Camera2Client::flashModeStringToEnum(
+        const char *flashMode) {
+    return
+        !strcmp(flashMode, CameraParameters::FLASH_MODE_OFF) ?
+            Parameters::FLASH_MODE_OFF :
+        !strcmp(flashMode, CameraParameters::FLASH_MODE_AUTO) ?
+            Parameters::FLASH_MODE_AUTO :
+        !strcmp(flashMode, CameraParameters::FLASH_MODE_ON) ?
+            Parameters::FLASH_MODE_ON :
+        !strcmp(flashMode, CameraParameters::FLASH_MODE_RED_EYE) ?
+            Parameters::FLASH_MODE_RED_EYE :
+        !strcmp(flashMode, CameraParameters::FLASH_MODE_TORCH) ?
+            Parameters::FLASH_MODE_TORCH :
+        Parameters::FLASH_MODE_INVALID;
+}
+
+Camera2Client::Parameters::focusMode_t Camera2Client::focusModeStringToEnum(
+        const char *focusMode) {
+    return
+        !strcmp(focusMode, CameraParameters::FOCUS_MODE_AUTO) ?
+            Parameters::FOCUS_MODE_AUTO :
+        !strcmp(focusMode, CameraParameters::FOCUS_MODE_INFINITY) ?
+            Parameters::FOCUS_MODE_INFINITY :
+        !strcmp(focusMode, CameraParameters::FOCUS_MODE_MACRO) ?
+            Parameters::FOCUS_MODE_MACRO :
+        !strcmp(focusMode, CameraParameters::FOCUS_MODE_FIXED) ?
+            Parameters::FOCUS_MODE_FIXED :
+        !strcmp(focusMode, CameraParameters::FOCUS_MODE_EDOF) ?
+            Parameters::FOCUS_MODE_EDOF :
+        !strcmp(focusMode, CameraParameters::FOCUS_MODE_CONTINUOUS_VIDEO) ?
+            Parameters::FOCUS_MODE_CONTINUOUS_VIDEO :
+        !strcmp(focusMode, CameraParameters::FOCUS_MODE_CONTINUOUS_PICTURE) ?
+            Parameters::FOCUS_MODE_CONTINUOUS_PICTURE :
+        Parameters::FOCUS_MODE_INVALID;
+}
+
+status_t Camera2Client::parseAreas(const char *areasCStr,
+        Vector<Parameters::Area> *areas) {
+    static const size_t NUM_FIELDS = 5;
+    areas->clear();
+    if (areasCStr == NULL) {
+        // If no key exists, use default (0,0,0,0,0)
+        areas->push();
+        return OK;
+    }
+    String8 areasStr(areasCStr);
+    ssize_t areaStart = areasStr.find("(", 0) + 1;
+    while (areaStart != 0) {
+        const char* area = areasStr.string() + areaStart;
+        char *numEnd;
+        int vals[NUM_FIELDS];
+        for (size_t i = 0; i < NUM_FIELDS; i++) {
+            errno = 0;
+            vals[i] = strtol(area, &numEnd, 10);
+            if (errno || numEnd == area) return BAD_VALUE;
+            area = numEnd + 1;
+        }
+        areas->push(Parameters::Area(
+            vals[0], vals[1], vals[2], vals[3], vals[4]) );
+        areaStart = areasStr.find("(", areaStart) + 1;
+    }
+    return OK;
+}
+
+status_t Camera2Client::validateAreas(const Vector<Parameters::Area> &areas,
+                                      size_t maxRegions) {
+    // Definition of valid area can be found in
+    // include/camera/CameraParameters.h
+    if (areas.size() == 0) return BAD_VALUE;
+    if (areas.size() == 1) {
+        if (areas[0].left == 0 &&
+                areas[0].top == 0 &&
+                areas[0].right == 0 &&
+                areas[0].bottom == 0 &&
+                areas[0].weight == 0) {
+            // Single (0,0,0,0,0) entry is always valid (== driver decides)
+            return OK;
+        }
+    }
+    if (areas.size() > maxRegions) {
+        ALOGE("%s: Too many areas requested: %d",
+                __FUNCTION__, areas.size());
+        return BAD_VALUE;
+    }
+
+    for (Vector<Parameters::Area>::const_iterator a = areas.begin();
+         a != areas.end(); a++) {
+        if (a->weight < 1 || a->weight > 1000) return BAD_VALUE;
+        if (a->left < -1000 || a->left > 1000) return BAD_VALUE;
+        if (a->top < -1000 || a->top > 1000) return BAD_VALUE;
+        if (a->right < -1000 || a->right > 1000) return BAD_VALUE;
+        if (a->bottom < -1000 || a->bottom > 1000) return BAD_VALUE;
+        if (a->left >= a->right) return BAD_VALUE;
+        if (a->top >= a->bottom) return BAD_VALUE;
+    }
+    return OK;
+}
+
+bool Camera2Client::boolFromString(const char *boolStr) {
+    return !boolStr ? false :
+        !strcmp(boolStr, CameraParameters::TRUE) ? true :
+        false;
+}
+
+int Camera2Client::degToTransform(int degrees, bool mirror) {
+    if (!mirror) {
+        if (degrees == 0) return 0;
+        else if (degrees == 90) return HAL_TRANSFORM_ROT_90;
+        else if (degrees == 180) return HAL_TRANSFORM_ROT_180;
+        else if (degrees == 270) return HAL_TRANSFORM_ROT_270;
+    } else {  // Do mirror (horizontal flip)
+        if (degrees == 0) {           // FLIP_H and ROT_0
+            return HAL_TRANSFORM_FLIP_H;
+        } else if (degrees == 90) {   // FLIP_H and ROT_90
+            return HAL_TRANSFORM_FLIP_H | HAL_TRANSFORM_ROT_90;
+        } else if (degrees == 180) {  // FLIP_H and ROT_180
+            return HAL_TRANSFORM_FLIP_V;
+        } else if (degrees == 270) {  // FLIP_H and ROT_270
+            return HAL_TRANSFORM_FLIP_V | HAL_TRANSFORM_ROT_90;
+        }
+    }
+    ALOGE("%s: Bad input: %d", __FUNCTION__, degrees);
+    return -1;
+}
+
+} // namespace android
diff --git a/services/camera/libcameraservice/Camera2Client.h b/services/camera/libcameraservice/Camera2Client.h
new file mode 100644
index 0000000..2dc02bc
--- /dev/null
+++ b/services/camera/libcameraservice/Camera2Client.h
@@ -0,0 +1,269 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_SERVERS_CAMERA_CAMERA2CLIENT_H
+#define ANDROID_SERVERS_CAMERA_CAMERA2CLIENT_H
+
+#include "Camera2Device.h"
+#include "CameraService.h"
+#include "camera/CameraParameters.h"
+#include <binder/MemoryBase.h>
+#include <binder/MemoryHeapBase.h>
+#include <gui/CpuConsumer.h>
+
+namespace android {
+
+/**
+ * Implements the android.hardware.camera API on top of
+ * camera device HAL version 2.
+ */
+class Camera2Client : public CameraService::Client
+{
+public:
+    // ICamera interface (see ICamera for details)
+    virtual void            disconnect();
+    virtual status_t        connect(const sp<ICameraClient>& client);
+    virtual status_t        lock();
+    virtual status_t        unlock();
+    virtual status_t        setPreviewDisplay(const sp<Surface>& surface);
+    virtual status_t        setPreviewTexture(
+        const sp<ISurfaceTexture>& surfaceTexture);
+    virtual void            setPreviewCallbackFlag(int flag);
+    virtual status_t        startPreview();
+    virtual void            stopPreview();
+    virtual bool            previewEnabled();
+    virtual status_t        storeMetaDataInBuffers(bool enabled);
+    virtual status_t        startRecording();
+    virtual void            stopRecording();
+    virtual bool            recordingEnabled();
+    virtual void            releaseRecordingFrame(const sp<IMemory>& mem);
+    virtual status_t        autoFocus();
+    virtual status_t        cancelAutoFocus();
+    virtual status_t        takePicture(int msgType);
+    virtual status_t        setParameters(const String8& params);
+    virtual String8         getParameters() const;
+    virtual status_t        sendCommand(int32_t cmd, int32_t arg1, int32_t arg2);
+
+    // Interface used by CameraService
+    Camera2Client(const sp<CameraService>& cameraService,
+            const sp<ICameraClient>& cameraClient,
+            int cameraId,
+            int cameraFacing,
+            int clientPid);
+    ~Camera2Client();
+
+    status_t initialize(camera_module_t *module);
+
+    virtual status_t dump(int fd, const Vector<String16>& args);
+
+private:
+    enum State {
+        NOT_INITIALIZED,
+        STOPPED,
+        WAITING_FOR_PREVIEW_WINDOW,
+        PREVIEW,
+        RECORD,
+        STILL_CAPTURE,
+        VIDEO_SNAPSHOT
+    } mState;
+
+    static const char *getStateName(State state);
+
+    /** ICamera interface-related private members */
+
+    // Mutex that must be locked by methods implementing the ICamera interface.
+    // Ensures serialization between incoming ICamera calls
+    mutable Mutex mICameraLock;
+
+    // The following must be called with mICamaeraLock already locked
+
+    status_t setPreviewWindowLocked(const sp<IBinder>& binder,
+            sp<ANativeWindow> window);
+
+    void stopPreviewLocked();
+    status_t startPreviewLocked();
+
+    // Mutex that must be locked before accessing mParameters, mParamsFlattened
+    mutable Mutex mParamsLock;
+    String8 mParamsFlattened;
+    // Current camera state; this is the contents of the CameraParameters object
+    // in a more-efficient format. The enum values are mostly based off the
+    // corresponding camera2 enums, not the camera1 strings. A few are defined
+    // here if they don't cleanly map to camera2 values.
+    struct Parameters {
+        int previewWidth, previewHeight;
+        int32_t previewFpsRange[2];
+        int previewFps; // deprecated, here only for tracking changes
+        int previewFormat;
+
+        int previewTransform; // set by CAMERA_CMD_SET_DISPLAY_ORIENTATION
+
+        int pictureWidth, pictureHeight;
+
+        int32_t jpegThumbSize[2];
+        int32_t jpegQuality, jpegThumbQuality;
+        int32_t jpegRotation;
+
+        bool gpsEnabled;
+        double gpsCoordinates[3];
+        int64_t gpsTimestamp;
+        String8 gpsProcessingMethod;
+
+        int wbMode;
+        int effectMode;
+        int antibandingMode;
+        int sceneMode;
+
+        enum flashMode_t {
+            FLASH_MODE_OFF = 0,
+            FLASH_MODE_AUTO,
+            FLASH_MODE_ON,
+            FLASH_MODE_TORCH,
+            FLASH_MODE_RED_EYE = ANDROID_CONTROL_AE_ON_AUTO_FLASH_REDEYE,
+            FLASH_MODE_INVALID = -1
+        } flashMode;
+
+        enum focusMode_t {
+            FOCUS_MODE_AUTO = ANDROID_CONTROL_AF_AUTO,
+            FOCUS_MODE_MACRO = ANDROID_CONTROL_AF_MACRO,
+            FOCUS_MODE_CONTINUOUS_VIDEO = ANDROID_CONTROL_AF_CONTINUOUS_VIDEO,
+            FOCUS_MODE_CONTINUOUS_PICTURE =
+                ANDROID_CONTROL_AF_CONTINUOUS_PICTURE,
+            FOCUS_MODE_EDOF = ANDROID_CONTROL_AF_EDOF,
+            FOCUS_MODE_INFINITY,
+            FOCUS_MODE_FIXED,
+            FOCUS_MODE_INVALID = -1
+        } focusMode;
+
+        struct Area {
+            int left, top, right, bottom;
+            int weight;
+            Area() {}
+            Area(int left, int top, int right, int bottom, int weight):
+                    left(left), top(top), right(right), bottom(bottom),
+                    weight(weight) {}
+        };
+        Vector<Area> focusingAreas;
+
+        int32_t exposureCompensation;
+        bool autoExposureLock;
+        bool autoWhiteBalanceLock;
+
+        Vector<Area> meteringAreas;
+
+        int zoom;
+
+        int videoWidth, videoHeight;
+
+        bool recordingHint;
+        bool videoStabilization;
+    } mParameters;
+
+    /** Camera device-related private members */
+
+    // Simple listener that forwards frame available notifications from
+    // a CPU consumer to the capture notification
+    class CaptureWaiter: public CpuConsumer::FrameAvailableListener {
+      public:
+        CaptureWaiter(Camera2Client *parent) : mParent(parent) {}
+        void onFrameAvailable() { mParent->onCaptureAvailable(); }
+      private:
+        Camera2Client *mParent;
+    };
+
+    void onCaptureAvailable();
+
+    // Number of zoom steps to simulate
+    static const unsigned int NUM_ZOOM_STEPS = 10;
+    // Used with mPreviewStreamId, mCaptureStreamId
+    static const int NO_STREAM = -1;
+
+    sp<IBinder> mPreviewSurface;
+    sp<ANativeWindow> mPreviewWindow;
+
+    int mPreviewStreamId;
+    camera_metadata_t *mPreviewRequest;
+
+    int mCaptureStreamId;
+    sp<CpuConsumer>    mCaptureConsumer;
+    sp<ANativeWindow>  mCaptureWindow;
+    sp<CaptureWaiter>  mCaptureWaiter;
+    camera_metadata_t *mCaptureRequest;
+    sp<MemoryHeapBase> mCaptureHeap;
+    sp<MemoryBase>     mCaptureMemory;
+
+    sp<Camera2Device> mDevice;
+
+
+    // Get values for static camera info entry. min/maxCount are used for error
+    // checking the number of values in the entry. 0 for max/minCount means to
+    // do no bounds check in that direction. In case of error, the entry data
+    // pointer is null and the count is 0.
+    camera_metadata_entry_t staticInfo(uint32_t tag,
+            size_t minCount=0, size_t maxCount=0);
+
+    /** Utility methods */
+
+    // Convert static camera info from a camera2 device to the
+    // old API parameter map.
+    status_t buildDefaultParameters();
+
+    // Update preview request based on mParameters
+    status_t updatePreviewRequest();
+    // Update preview stream based on mParameters
+    status_t updatePreviewStream();
+
+    // Update capture request based on mParameters
+    status_t updateCaptureRequest();
+    // Update capture stream based on mParameters
+    status_t updateCaptureStream();
+
+    // Update parameters all requests use, based on mParameters
+    status_t updateRequestCommon(camera_metadata_t *request);
+
+    // Update specific metadata entry with new values. Adds entry if it does not
+    // exist, which will invalidate sorting
+    static status_t updateEntry(camera_metadata_t *buffer,
+            uint32_t tag, const void *data, size_t data_count);
+
+    // Remove metadata entry. Will invalidate sorting. If entry does not exist,
+    // does nothing.
+    static status_t deleteEntry(camera_metadata_t *buffer,
+            uint32_t tag);
+
+    // Convert camera1 preview format string to camera2 enum
+    static int formatStringToEnum(const char *format);
+    static const char *formatEnumToString(int format);
+
+    static int wbModeStringToEnum(const char *wbMode);
+    static int effectModeStringToEnum(const char *effectMode);
+    static int abModeStringToEnum(const char *abMode);
+    static int sceneModeStringToEnum(const char *sceneMode);
+    static Parameters::flashMode_t flashModeStringToEnum(const char *flashMode);
+    static Parameters::focusMode_t focusModeStringToEnum(const char *focusMode);
+    static status_t parseAreas(const char *areasCStr,
+            Vector<Parameters::Area> *areas);
+    static status_t validateAreas(const Vector<Parameters::Area> &areas,
+                                  size_t maxRegions);
+    static bool boolFromString(const char *boolStr);
+
+    // Map from camera orientation + facing to gralloc transform enum
+    static int degToTransform(int degrees, bool mirror);
+};
+
+}; // namespace android
+
+#endif
diff --git a/services/camera/libcameraservice/Camera2Device.cpp b/services/camera/libcameraservice/Camera2Device.cpp
new file mode 100644
index 0000000..8d07eee
--- /dev/null
+++ b/services/camera/libcameraservice/Camera2Device.cpp
@@ -0,0 +1,941 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "Camera2Device"
+//#define LOG_NDEBUG 0
+//#define LOG_NNDEBUG 0  // Per-frame verbose logging
+
+#ifdef LOG_NNDEBUG
+#define ALOGVV(...) ALOGV(__VA_ARGS__)
+#else
+#define ALOGVV(...) ((void)0)
+#endif
+
+#include <utils/Log.h>
+#include "Camera2Device.h"
+
+namespace android {
+
+Camera2Device::Camera2Device(int id):
+        mId(id),
+        mDevice(NULL)
+{
+    ALOGV("%s: E", __FUNCTION__);
+}
+
+Camera2Device::~Camera2Device()
+{
+    ALOGV("%s: E", __FUNCTION__);
+    if (mDevice) {
+        status_t res;
+        res = mDevice->common.close(&mDevice->common);
+        if (res != OK) {
+            ALOGE("%s: Could not close camera %d: %s (%d)",
+                    __FUNCTION__,
+                    mId, strerror(-res), res);
+        }
+        mDevice = NULL;
+    }
+}
+
+status_t Camera2Device::initialize(camera_module_t *module)
+{
+    ALOGV("%s: E", __FUNCTION__);
+
+    status_t res;
+    char name[10];
+    snprintf(name, sizeof(name), "%d", mId);
+
+    res = module->common.methods->open(&module->common, name,
+            reinterpret_cast<hw_device_t**>(&mDevice));
+
+    if (res != OK) {
+        ALOGE("%s: Could not open camera %d: %s (%d)", __FUNCTION__,
+                mId, strerror(-res), res);
+        return res;
+    }
+
+    if (mDevice->common.version != CAMERA_DEVICE_API_VERSION_2_0) {
+        ALOGE("%s: Could not open camera %d: "
+                "Camera device is not version %x, reports %x instead",
+                __FUNCTION__, mId, CAMERA_DEVICE_API_VERSION_2_0,
+                mDevice->common.version);
+        return BAD_VALUE;
+    }
+
+    camera_info info;
+    res = module->get_camera_info(mId, &info);
+    if (res != OK ) return res;
+
+    if (info.device_version != mDevice->common.version) {
+        ALOGE("%s: HAL reporting mismatched camera_info version (%x)"
+                " and device version (%x).", __FUNCTION__,
+                mDevice->common.version, info.device_version);
+        return BAD_VALUE;
+    }
+
+    mDeviceInfo = info.static_camera_characteristics;
+
+    res = mRequestQueue.setConsumerDevice(mDevice);
+    if (res != OK) {
+        ALOGE("%s: Camera %d: Unable to connect request queue to device: %s (%d)",
+                __FUNCTION__, mId, strerror(-res), res);
+        return res;
+    }
+    res = mFrameQueue.setProducerDevice(mDevice);
+    if (res != OK) {
+        ALOGE("%s: Camera %d: Unable to connect frame queue to device: %s (%d)",
+                __FUNCTION__, mId, strerror(-res), res);
+        return res;
+    }
+
+    res = mDevice->ops->get_metadata_vendor_tag_ops(mDevice, &mVendorTagOps);
+    if (res != OK ) {
+        ALOGE("%s: Camera %d: Unable to retrieve tag ops from device: %s (%d)",
+                __FUNCTION__, mId, strerror(-res), res);
+        return res;
+    }
+
+    return OK;
+}
+
+status_t Camera2Device::dump(int fd, const Vector<String16>& args) {
+
+    String8 result;
+
+    result.appendFormat("  Camera2Device[%d] dump:\n", mId);
+
+    result.appendFormat("    Static camera information metadata:\n");
+    write(fd, result.string(), result.size());
+    dump_camera_metadata(mDeviceInfo, fd, 2);
+
+    result = "    Request queue contents:\n";
+    write(fd, result.string(), result.size());
+    mRequestQueue.dump(fd, args);
+
+    result = "    Frame queue contents:\n";
+    write(fd, result.string(), result.size());
+    mFrameQueue.dump(fd, args);
+
+    result = "    Active streams:\n";
+    write(fd, result.string(), result.size());
+    for (StreamList::iterator s = mStreams.begin(); s != mStreams.end(); s++) {
+        (*s)->dump(fd, args);
+    }
+
+    result = "    HAL device dump:\n";
+    write(fd, result.string(), result.size());
+
+    status_t res;
+    res = mDevice->ops->dump(mDevice, fd);
+
+    return res;
+}
+
+camera_metadata_t *Camera2Device::info() {
+    ALOGV("%s: E", __FUNCTION__);
+
+    return mDeviceInfo;
+}
+
+status_t Camera2Device::capture(camera_metadata_t* request) {
+    ALOGV("%s: E", __FUNCTION__);
+
+    mRequestQueue.enqueue(request);
+    return OK;
+}
+
+
+status_t Camera2Device::setStreamingRequest(camera_metadata_t* request) {
+    ALOGV("%s: E", __FUNCTION__);
+
+    mRequestQueue.setStreamSlot(request);
+    return OK;
+}
+
+status_t Camera2Device::createStream(sp<ANativeWindow> consumer,
+        uint32_t width, uint32_t height, int format, size_t size, int *id) {
+    status_t res;
+    ALOGV("%s: E", __FUNCTION__);
+
+    sp<StreamAdapter> stream = new StreamAdapter(mDevice);
+
+    res = stream->connectToDevice(consumer, width, height, format, size);
+    if (res != OK) {
+        ALOGE("%s: Camera %d: Unable to create stream (%d x %d, format %x):"
+                "%s (%d)",
+                __FUNCTION__, mId, width, height, format, strerror(-res), res);
+        return res;
+    }
+
+    *id = stream->getId();
+
+    mStreams.push_back(stream);
+    return OK;
+}
+
+status_t Camera2Device::getStreamInfo(int id,
+        uint32_t *width, uint32_t *height, uint32_t *format) {
+    ALOGV("%s: E", __FUNCTION__);
+    bool found = false;
+    StreamList::iterator streamI;
+    for (streamI = mStreams.begin();
+         streamI != mStreams.end(); streamI++) {
+        if ((*streamI)->getId() == id) {
+            found = true;
+            break;
+        }
+    }
+    if (!found) {
+        ALOGE("%s: Camera %d: Stream %d does not exist",
+                __FUNCTION__, mId, id);
+        return BAD_VALUE;
+    }
+
+    if (width) *width = (*streamI)->getWidth();
+    if (height) *height = (*streamI)->getHeight();
+    if (format) *format = (*streamI)->getFormat();
+
+    return OK;
+}
+
+status_t Camera2Device::setStreamTransform(int id,
+        int transform) {
+    ALOGV("%s: E", __FUNCTION__);
+    bool found = false;
+    StreamList::iterator streamI;
+    for (streamI = mStreams.begin();
+         streamI != mStreams.end(); streamI++) {
+        if ((*streamI)->getId() == id) {
+            found = true;
+            break;
+        }
+    }
+    if (!found) {
+        ALOGE("%s: Camera %d: Stream %d does not exist",
+                __FUNCTION__, mId, id);
+        return BAD_VALUE;
+    }
+
+    return (*streamI)->setTransform(transform);
+}
+
+status_t Camera2Device::deleteStream(int id) {
+    ALOGV("%s: E", __FUNCTION__);
+    bool found = false;
+    for (StreamList::iterator streamI = mStreams.begin();
+         streamI != mStreams.end(); streamI++) {
+        if ((*streamI)->getId() == id) {
+            status_t res = (*streamI)->disconnect();
+            if (res != OK) {
+                ALOGE("%s: Unable to disconnect stream %d from HAL device: "
+                        "%s (%d)", __FUNCTION__, id, strerror(-res), res);
+                return res;
+            }
+            mStreams.erase(streamI);
+            found = true;
+            break;
+        }
+    }
+    if (!found) {
+        ALOGE("%s: Camera %d: Unable to find stream %d to delete",
+                __FUNCTION__, mId, id);
+        return BAD_VALUE;
+    }
+    return OK;
+}
+
+status_t Camera2Device::createDefaultRequest(int templateId,
+        camera_metadata_t **request) {
+    ALOGV("%s: E", __FUNCTION__);
+    return mDevice->ops->construct_default_request(
+        mDevice, templateId, request);
+}
+
+status_t Camera2Device::waitUntilDrained() {
+    static const uint32_t kSleepTime = 50000; // 50 ms
+    static const uint32_t kMaxSleepTime = 10000000; // 10 s
+
+    if (mRequestQueue.getBufferCount() ==
+            CAMERA2_REQUEST_QUEUE_IS_BOTTOMLESS) return INVALID_OPERATION;
+
+    // TODO: Set up notifications from HAL, instead of sleeping here
+    uint32_t totalTime = 0;
+    while (mDevice->ops->get_in_progress_count(mDevice) > 0) {
+        usleep(kSleepTime);
+        totalTime += kSleepTime;
+        if (totalTime > kMaxSleepTime) {
+            ALOGE("%s: Waited %d us, requests still in flight", __FUNCTION__,
+                    totalTime);
+            return TIMED_OUT;
+        }
+    }
+    return OK;
+}
+
+/**
+ * Camera2Device::MetadataQueue
+ */
+
+Camera2Device::MetadataQueue::MetadataQueue():
+            mDevice(NULL),
+            mFrameCount(0),
+            mCount(0),
+            mStreamSlotCount(0),
+            mSignalConsumer(true)
+{
+    camera2_request_queue_src_ops::dequeue_request = consumer_dequeue;
+    camera2_request_queue_src_ops::request_count = consumer_buffer_count;
+    camera2_request_queue_src_ops::free_request = consumer_free;
+
+    camera2_frame_queue_dst_ops::dequeue_frame = producer_dequeue;
+    camera2_frame_queue_dst_ops::cancel_frame = producer_cancel;
+    camera2_frame_queue_dst_ops::enqueue_frame = producer_enqueue;
+}
+
+Camera2Device::MetadataQueue::~MetadataQueue() {
+    Mutex::Autolock l(mMutex);
+    freeBuffers(mEntries.begin(), mEntries.end());
+    freeBuffers(mStreamSlot.begin(), mStreamSlot.end());
+}
+
+// Connect to camera2 HAL as consumer (input requests/reprocessing)
+status_t Camera2Device::MetadataQueue::setConsumerDevice(camera2_device_t *d) {
+    status_t res;
+    res = d->ops->set_request_queue_src_ops(d,
+            this);
+    if (res != OK) return res;
+    mDevice = d;
+    return OK;
+}
+
+status_t Camera2Device::MetadataQueue::setProducerDevice(camera2_device_t *d) {
+    status_t res;
+    res = d->ops->set_frame_queue_dst_ops(d,
+            this);
+    return res;
+}
+
+// Real interfaces
+status_t Camera2Device::MetadataQueue::enqueue(camera_metadata_t *buf) {
+    ALOGVV("%s: E", __FUNCTION__);
+    Mutex::Autolock l(mMutex);
+
+    mCount++;
+    mEntries.push_back(buf);
+
+    return signalConsumerLocked();
+}
+
+int Camera2Device::MetadataQueue::getBufferCount() {
+    Mutex::Autolock l(mMutex);
+    if (mStreamSlotCount > 0) {
+        return CAMERA2_REQUEST_QUEUE_IS_BOTTOMLESS;
+    }
+    return mCount;
+}
+
+status_t Camera2Device::MetadataQueue::dequeue(camera_metadata_t **buf,
+        bool incrementCount)
+{
+    ALOGVV("%s: E", __FUNCTION__);
+    status_t res;
+    Mutex::Autolock l(mMutex);
+
+    if (mCount == 0) {
+        if (mStreamSlotCount == 0) {
+            ALOGVV("%s: Empty", __FUNCTION__);
+            *buf = NULL;
+            mSignalConsumer = true;
+            return OK;
+        }
+        ALOGVV("%s: Streaming %d frames to queue", __FUNCTION__,
+              mStreamSlotCount);
+
+        for (List<camera_metadata_t*>::iterator slotEntry = mStreamSlot.begin();
+                slotEntry != mStreamSlot.end();
+                slotEntry++ ) {
+            size_t entries = get_camera_metadata_entry_count(*slotEntry);
+            size_t dataBytes = get_camera_metadata_data_count(*slotEntry);
+
+            camera_metadata_t *copy =
+                    allocate_camera_metadata(entries, dataBytes);
+            append_camera_metadata(copy, *slotEntry);
+            mEntries.push_back(copy);
+        }
+        mCount = mStreamSlotCount;
+    }
+    ALOGVV("MetadataQueue: deque (%d buffers)", mCount);
+    camera_metadata_t *b = *(mEntries.begin());
+    mEntries.erase(mEntries.begin());
+
+    if (incrementCount) {
+        camera_metadata_entry_t frameCount;
+        res = find_camera_metadata_entry(b,
+                ANDROID_REQUEST_FRAME_COUNT,
+                &frameCount);
+        if (res != OK) {
+            ALOGE("%s: Unable to add frame count: %s (%d)",
+                    __FUNCTION__, strerror(-res), res);
+        } else {
+            *frameCount.data.i32 = mFrameCount;
+        }
+        mFrameCount++;
+    }
+
+    *buf = b;
+    mCount--;
+
+    return OK;
+}
+
+status_t Camera2Device::MetadataQueue::waitForBuffer(nsecs_t timeout)
+{
+    Mutex::Autolock l(mMutex);
+    status_t res;
+    while (mCount == 0) {
+        res = notEmpty.waitRelative(mMutex,timeout);
+        if (res != OK) return res;
+    }
+    return OK;
+}
+
+status_t Camera2Device::MetadataQueue::setStreamSlot(camera_metadata_t *buf)
+{
+    ALOGV("%s: E", __FUNCTION__);
+    Mutex::Autolock l(mMutex);
+    if (buf == NULL) {
+        freeBuffers(mStreamSlot.begin(), mStreamSlot.end());
+        mStreamSlotCount = 0;
+        return OK;
+    }
+    camera_metadata_t *buf2 = clone_camera_metadata(buf);
+    if (!buf2) {
+        ALOGE("%s: Unable to clone metadata buffer!", __FUNCTION__);
+        return NO_MEMORY;
+    }
+
+    if (mStreamSlotCount > 1) {
+        List<camera_metadata_t*>::iterator deleter = ++mStreamSlot.begin();
+        freeBuffers(++mStreamSlot.begin(), mStreamSlot.end());
+        mStreamSlotCount = 1;
+    }
+    if (mStreamSlotCount == 1) {
+        free_camera_metadata( *(mStreamSlot.begin()) );
+        *(mStreamSlot.begin()) = buf2;
+    } else {
+        mStreamSlot.push_front(buf2);
+        mStreamSlotCount = 1;
+    }
+    return signalConsumerLocked();
+}
+
+status_t Camera2Device::MetadataQueue::setStreamSlot(
+        const List<camera_metadata_t*> &bufs)
+{
+    ALOGV("%s: E", __FUNCTION__);
+    Mutex::Autolock l(mMutex);
+    status_t res;
+
+    if (mStreamSlotCount > 0) {
+        freeBuffers(mStreamSlot.begin(), mStreamSlot.end());
+    }
+    mStreamSlotCount = 0;
+    for (List<camera_metadata_t*>::const_iterator r = bufs.begin();
+         r != bufs.end(); r++) {
+        camera_metadata_t *r2 = clone_camera_metadata(*r);
+        if (!r2) {
+            ALOGE("%s: Unable to clone metadata buffer!", __FUNCTION__);
+            return NO_MEMORY;
+        }
+        mStreamSlot.push_back(r2);
+        mStreamSlotCount++;
+    }
+    return signalConsumerLocked();
+}
+
+status_t Camera2Device::MetadataQueue::dump(int fd,
+        const Vector<String16>& args) {
+    String8 result;
+    status_t notLocked;
+    notLocked = mMutex.tryLock();
+    if (notLocked) {
+        result.append("    (Unable to lock queue mutex)\n");
+    }
+    result.appendFormat("      Current frame number: %d\n", mFrameCount);
+    if (mStreamSlotCount == 0) {
+        result.append("      Stream slot: Empty\n");
+        write(fd, result.string(), result.size());
+    } else {
+        result.appendFormat("      Stream slot: %d entries\n",
+                mStreamSlot.size());
+        int i = 0;
+        for (List<camera_metadata_t*>::iterator r = mStreamSlot.begin();
+             r != mStreamSlot.end(); r++) {
+            result = String8::format("       Stream slot buffer %d:\n", i);
+            write(fd, result.string(), result.size());
+            dump_camera_metadata(*r, fd, 2);
+            i++;
+        }
+    }
+    if (mEntries.size() == 0) {
+        result = "      Main queue is empty\n";
+        write(fd, result.string(), result.size());
+    } else {
+        result = String8::format("      Main queue has %d entries:\n",
+                mEntries.size());
+        int i = 0;
+        for (List<camera_metadata_t*>::iterator r = mEntries.begin();
+             r != mEntries.end(); r++) {
+            result = String8::format("       Queue entry %d:\n", i);
+            write(fd, result.string(), result.size());
+            dump_camera_metadata(*r, fd, 2);
+            i++;
+        }
+    }
+
+    if (notLocked == 0) {
+        mMutex.unlock();
+    }
+
+    return OK;
+}
+
+status_t Camera2Device::MetadataQueue::signalConsumerLocked() {
+    status_t res = OK;
+    notEmpty.signal();
+    if (mSignalConsumer && mDevice != NULL) {
+        mSignalConsumer = false;
+
+        mMutex.unlock();
+        ALOGV("%s: Signaling consumer", __FUNCTION__);
+        res = mDevice->ops->notify_request_queue_not_empty(mDevice);
+        mMutex.lock();
+    }
+    return res;
+}
+
+status_t Camera2Device::MetadataQueue::freeBuffers(
+        List<camera_metadata_t*>::iterator start,
+        List<camera_metadata_t*>::iterator end)
+{
+    while (start != end) {
+        free_camera_metadata(*start);
+        start = mStreamSlot.erase(start);
+    }
+    return OK;
+}
+
+Camera2Device::MetadataQueue* Camera2Device::MetadataQueue::getInstance(
+        const camera2_request_queue_src_ops_t *q)
+{
+    const MetadataQueue* cmq = static_cast<const MetadataQueue*>(q);
+    return const_cast<MetadataQueue*>(cmq);
+}
+
+Camera2Device::MetadataQueue* Camera2Device::MetadataQueue::getInstance(
+        const camera2_frame_queue_dst_ops_t *q)
+{
+    const MetadataQueue* cmq = static_cast<const MetadataQueue*>(q);
+    return const_cast<MetadataQueue*>(cmq);
+}
+
+int Camera2Device::MetadataQueue::consumer_buffer_count(
+        const camera2_request_queue_src_ops_t *q)
+{
+    MetadataQueue *queue = getInstance(q);
+    return queue->getBufferCount();
+}
+
+int Camera2Device::MetadataQueue::consumer_dequeue(
+        const camera2_request_queue_src_ops_t *q,
+        camera_metadata_t **buffer)
+{
+    MetadataQueue *queue = getInstance(q);
+    return queue->dequeue(buffer, true);
+}
+
+int Camera2Device::MetadataQueue::consumer_free(
+        const camera2_request_queue_src_ops_t *q,
+        camera_metadata_t *old_buffer)
+{
+    MetadataQueue *queue = getInstance(q);
+    free_camera_metadata(old_buffer);
+    return OK;
+}
+
+int Camera2Device::MetadataQueue::producer_dequeue(
+        const camera2_frame_queue_dst_ops_t *q,
+        size_t entries, size_t bytes,
+        camera_metadata_t **buffer)
+{
+    camera_metadata_t *new_buffer =
+            allocate_camera_metadata(entries, bytes);
+    if (new_buffer == NULL) return NO_MEMORY;
+    *buffer = new_buffer;
+        return OK;
+}
+
+int Camera2Device::MetadataQueue::producer_cancel(
+        const camera2_frame_queue_dst_ops_t *q,
+        camera_metadata_t *old_buffer)
+{
+    free_camera_metadata(old_buffer);
+    return OK;
+}
+
+int Camera2Device::MetadataQueue::producer_enqueue(
+        const camera2_frame_queue_dst_ops_t *q,
+        camera_metadata_t *filled_buffer)
+{
+    MetadataQueue *queue = getInstance(q);
+    return queue->enqueue(filled_buffer);
+}
+
+/**
+ * Camera2Device::StreamAdapter
+ */
+
+#ifndef container_of
+#define container_of(ptr, type, member) \
+    (type *)((char*)(ptr) - offsetof(type, member))
+#endif
+
+Camera2Device::StreamAdapter::StreamAdapter(camera2_device_t *d):
+        mState(DISCONNECTED),
+        mDevice(d),
+        mId(-1),
+        mWidth(0), mHeight(0), mFormat(0), mSize(0), mUsage(0),
+        mMaxProducerBuffers(0), mMaxConsumerBuffers(0),
+        mTotalBuffers(0),
+        mFormatRequested(0),
+        mActiveBuffers(0),
+        mFrameCount(0),
+        mLastTimestamp(0)
+{
+    camera2_stream_ops::dequeue_buffer = dequeue_buffer;
+    camera2_stream_ops::enqueue_buffer = enqueue_buffer;
+    camera2_stream_ops::cancel_buffer = cancel_buffer;
+    camera2_stream_ops::set_crop = set_crop;
+}
+
+Camera2Device::StreamAdapter::~StreamAdapter() {
+    disconnect();
+}
+
+status_t Camera2Device::StreamAdapter::connectToDevice(
+        sp<ANativeWindow> consumer,
+        uint32_t width, uint32_t height, int format, size_t size) {
+    status_t res;
+
+    if (mState != DISCONNECTED) return INVALID_OPERATION;
+    if (consumer == NULL) {
+        ALOGE("%s: Null consumer passed to stream adapter", __FUNCTION__);
+        return BAD_VALUE;
+    }
+
+    mConsumerInterface = consumer;
+    mWidth = width;
+    mHeight = height;
+    mSize = (format == HAL_PIXEL_FORMAT_BLOB) ? size : 0;
+    mFormatRequested = format;
+
+    // Allocate device-side stream interface
+
+    uint32_t id;
+    uint32_t formatActual;
+    uint32_t usage;
+    uint32_t maxBuffers = 2;
+    res = mDevice->ops->allocate_stream(mDevice,
+            mWidth, mHeight, mFormatRequested, getStreamOps(),
+            &id, &formatActual, &usage, &maxBuffers);
+    if (res != OK) {
+        ALOGE("%s: Device stream allocation failed: %s (%d)",
+                __FUNCTION__, strerror(-res), res);
+        return res;
+    }
+
+    mId = id;
+    mFormat = formatActual;
+    mUsage = usage;
+    mMaxProducerBuffers = maxBuffers;
+
+    mState = ALLOCATED;
+
+    // Configure consumer-side ANativeWindow interface
+    res = native_window_api_connect(mConsumerInterface.get(),
+            NATIVE_WINDOW_API_CAMERA);
+    if (res != OK) {
+        ALOGE("%s: Unable to connect to native window for stream %d",
+                __FUNCTION__, mId);
+
+        return res;
+    }
+
+    mState = CONNECTED;
+
+    res = native_window_set_usage(mConsumerInterface.get(), mUsage);
+    if (res != OK) {
+        ALOGE("%s: Unable to configure usage %08x for stream %d",
+                __FUNCTION__, mUsage, mId);
+        return res;
+    }
+
+    res = native_window_set_scaling_mode(mConsumerInterface.get(),
+            NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW);
+    if (res != OK) {
+        ALOGE("%s: Unable to configure stream scaling: %s (%d)",
+                __FUNCTION__, strerror(-res), res);
+        return res;
+    }
+
+    res = setTransform(0);
+    if (res != OK) {
+        return res;
+    }
+
+    if (mFormat == HAL_PIXEL_FORMAT_BLOB) {
+        res = native_window_set_buffers_geometry(mConsumerInterface.get(),
+                mSize, 1, mFormat);
+        if (res != OK) {
+            ALOGE("%s: Unable to configure compressed stream buffer geometry"
+                    " %d x %d, size %d for stream %d",
+                    __FUNCTION__, mWidth, mHeight, mSize, mId);
+            return res;
+        }
+    } else {
+        res = native_window_set_buffers_geometry(mConsumerInterface.get(),
+                mWidth, mHeight, mFormat);
+        if (res != OK) {
+            ALOGE("%s: Unable to configure stream buffer geometry"
+                    " %d x %d, format 0x%x for stream %d",
+                    __FUNCTION__, mWidth, mHeight, mFormat, mId);
+            return res;
+        }
+    }
+
+    int maxConsumerBuffers;
+    res = mConsumerInterface->query(mConsumerInterface.get(),
+            NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS, &maxConsumerBuffers);
+    if (res != OK) {
+        ALOGE("%s: Unable to query consumer undequeued"
+                " buffer count for stream %d", __FUNCTION__, mId);
+        return res;
+    }
+    mMaxConsumerBuffers = maxConsumerBuffers;
+
+    ALOGV("%s: Producer wants %d buffers, consumer wants %d", __FUNCTION__,
+            mMaxProducerBuffers, mMaxConsumerBuffers);
+
+    mTotalBuffers = mMaxConsumerBuffers + mMaxProducerBuffers;
+    mActiveBuffers = 0;
+    mFrameCount = 0;
+    mLastTimestamp = 0;
+
+    res = native_window_set_buffer_count(mConsumerInterface.get(),
+            mTotalBuffers);
+    if (res != OK) {
+        ALOGE("%s: Unable to set buffer count for stream %d",
+                __FUNCTION__, mId);
+        return res;
+    }
+
+    // Register allocated buffers with HAL device
+    buffer_handle_t *buffers = new buffer_handle_t[mTotalBuffers];
+    ANativeWindowBuffer **anwBuffers = new ANativeWindowBuffer*[mTotalBuffers];
+    uint32_t bufferIdx = 0;
+    for (; bufferIdx < mTotalBuffers; bufferIdx++) {
+        res = native_window_dequeue_buffer_and_wait(mConsumerInterface.get(),
+                &anwBuffers[bufferIdx]);
+        if (res != OK) {
+            ALOGE("%s: Unable to dequeue buffer %d for initial registration for"
+                    "stream %d", __FUNCTION__, bufferIdx, mId);
+            goto cleanUpBuffers;
+        }
+
+        buffers[bufferIdx] = anwBuffers[bufferIdx]->handle;
+    }
+
+    res = mDevice->ops->register_stream_buffers(mDevice,
+            mId,
+            mTotalBuffers,
+            buffers);
+    if (res != OK) {
+        ALOGE("%s: Unable to register buffers with HAL device for stream %d",
+                __FUNCTION__, mId);
+    } else {
+        mState = ACTIVE;
+    }
+
+cleanUpBuffers:
+    for (uint32_t i = 0; i < bufferIdx; i++) {
+        res = mConsumerInterface->cancelBuffer(mConsumerInterface.get(),
+                anwBuffers[i], -1);
+        if (res != OK) {
+            ALOGE("%s: Unable to cancel buffer %d after registration",
+                    __FUNCTION__, i);
+        }
+    }
+    delete[] anwBuffers;
+    delete[] buffers;
+
+    return res;
+}
+
+status_t Camera2Device::StreamAdapter::disconnect() {
+    status_t res;
+    if (mState >= ALLOCATED) {
+        res = mDevice->ops->release_stream(mDevice, mId);
+        if (res != OK) {
+            ALOGE("%s: Unable to release stream %d",
+                    __FUNCTION__, mId);
+            return res;
+        }
+    }
+    if (mState >= CONNECTED) {
+        res = native_window_api_disconnect(mConsumerInterface.get(),
+                NATIVE_WINDOW_API_CAMERA);
+        if (res != OK) {
+            ALOGE("%s: Unable to disconnect stream %d from native window",
+                    __FUNCTION__, mId);
+            return res;
+        }
+    }
+    mId = -1;
+    mState = DISCONNECTED;
+    return OK;
+}
+
+status_t Camera2Device::StreamAdapter::setTransform(int transform) {
+    status_t res;
+    if (mState < CONNECTED) {
+        ALOGE("%s: Cannot set transform on unconnected stream", __FUNCTION__);
+        return INVALID_OPERATION;
+    }
+    res = native_window_set_buffers_transform(mConsumerInterface.get(),
+                                              transform);
+    if (res != OK) {
+        ALOGE("%s: Unable to configure stream transform to %x: %s (%d)",
+                __FUNCTION__, transform, strerror(-res), res);
+    }
+    return res;
+}
+
+status_t Camera2Device::StreamAdapter::dump(int fd,
+        const Vector<String16>& args) {
+    String8 result = String8::format("      Stream %d: %d x %d, format 0x%x\n",
+            mId, mWidth, mHeight, mFormat);
+    result.appendFormat("        size %d, usage 0x%x, requested format 0x%x\n",
+            mSize, mUsage, mFormatRequested);
+    result.appendFormat("        total buffers: %d, dequeued buffers: %d\n",
+            mTotalBuffers, mActiveBuffers);
+    result.appendFormat("        frame count: %d, last timestamp %lld\n",
+            mFrameCount, mLastTimestamp);
+    write(fd, result.string(), result.size());
+    return OK;
+}
+
+const camera2_stream_ops *Camera2Device::StreamAdapter::getStreamOps() {
+    return static_cast<camera2_stream_ops *>(this);
+}
+
+ANativeWindow* Camera2Device::StreamAdapter::toANW(
+        const camera2_stream_ops_t *w) {
+    return static_cast<const StreamAdapter*>(w)->mConsumerInterface.get();
+}
+
+int Camera2Device::StreamAdapter::dequeue_buffer(const camera2_stream_ops_t *w,
+        buffer_handle_t** buffer) {
+    int res;
+    StreamAdapter* stream =
+            const_cast<StreamAdapter*>(static_cast<const StreamAdapter*>(w));
+    if (stream->mState != ACTIVE) {
+        ALOGE("%s: Called when in bad state: %d", __FUNCTION__, stream->mState);
+        return INVALID_OPERATION;
+    }
+
+    ANativeWindow *a = toANW(w);
+    ANativeWindowBuffer* anb;
+    res = native_window_dequeue_buffer_and_wait(a, &anb);
+    if (res != OK) return res;
+
+    *buffer = &(anb->handle);
+    stream->mActiveBuffers++;
+
+    ALOGVV("%s: Buffer %p", __FUNCTION__, *buffer);
+    return res;
+}
+
+int Camera2Device::StreamAdapter::enqueue_buffer(const camera2_stream_ops_t* w,
+        int64_t timestamp,
+        buffer_handle_t* buffer) {
+    StreamAdapter *stream =
+            const_cast<StreamAdapter*>(static_cast<const StreamAdapter*>(w));
+    ALOGVV("%s: Stream %d: Buffer %p captured at %lld ns",
+            __FUNCTION__, stream->mId, buffer, timestamp);
+    int state = stream->mState;
+    if (state != ACTIVE) {
+        ALOGE("%s: Called when in bad state: %d", __FUNCTION__, state);
+        return INVALID_OPERATION;
+    }
+    ANativeWindow *a = toANW(w);
+    status_t err;
+    err = native_window_set_buffers_timestamp(a, timestamp);
+    if (err != OK) {
+        ALOGE("%s: Error setting timestamp on native window: %s (%d)",
+                __FUNCTION__, strerror(-err), err);
+        return err;
+    }
+    err = a->queueBuffer(a,
+            container_of(buffer, ANativeWindowBuffer, handle), -1);
+    if (err != OK) {
+        ALOGE("%s: Error queueing buffer to native window: %s (%d)",
+                __FUNCTION__, strerror(-err), err);
+    }
+    stream->mActiveBuffers--;
+    stream->mFrameCount++;
+    stream->mLastTimestamp = timestamp;
+    return err;
+}
+
+int Camera2Device::StreamAdapter::cancel_buffer(const camera2_stream_ops_t* w,
+        buffer_handle_t* buffer) {
+    StreamAdapter *stream =
+            const_cast<StreamAdapter*>(static_cast<const StreamAdapter*>(w));
+    if (stream->mState != ACTIVE) {
+        ALOGE("%s: Called when in bad state: %d", __FUNCTION__, stream->mState);
+        return INVALID_OPERATION;
+    }
+    stream->mActiveBuffers--;
+    ANativeWindow *a = toANW(w);
+    return a->cancelBuffer(a,
+            container_of(buffer, ANativeWindowBuffer, handle), -1);
+}
+
+int Camera2Device::StreamAdapter::set_crop(const camera2_stream_ops_t* w,
+        int left, int top, int right, int bottom) {
+    int state = static_cast<const StreamAdapter*>(w)->mState;
+    if (state != ACTIVE) {
+        ALOGE("%s: Called when in bad state: %d", __FUNCTION__, state);
+        return INVALID_OPERATION;
+    }
+    ANativeWindow *a = toANW(w);
+    android_native_rect_t crop = { left, top, right, bottom };
+    return native_window_set_crop(a, &crop);
+}
+
+
+}; // namespace android
diff --git a/services/camera/libcameraservice/Camera2Device.h b/services/camera/libcameraservice/Camera2Device.h
new file mode 100644
index 0000000..1116be0
--- /dev/null
+++ b/services/camera/libcameraservice/Camera2Device.h
@@ -0,0 +1,289 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_SERVERS_CAMERA_CAMERA2DEVICE_H
+#define ANDROID_SERVERS_CAMERA_CAMERA2DEVICE_H
+
+#include <utils/Condition.h>
+#include <utils/Errors.h>
+#include <utils/List.h>
+#include <utils/Mutex.h>
+#include <utils/RefBase.h>
+#include <utils/String8.h>
+#include <utils/String16.h>
+#include <utils/Vector.h>
+
+#include "hardware/camera2.h"
+
+namespace android {
+
+class Camera2Device : public virtual RefBase {
+  public:
+    Camera2Device(int id);
+
+    ~Camera2Device();
+
+    status_t initialize(camera_module_t *module);
+
+    status_t dump(int fd, const Vector<String16>& args);
+
+    /**
+     * Get a pointer to the device's static characteristics metadata buffer
+     */
+    camera_metadata_t* info();
+
+    /**
+     * Submit request for capture. The Camera2Device takes ownership of the
+     * passed-in buffer.
+     */
+    status_t capture(camera_metadata_t *request);
+
+    /**
+     * Submit request for streaming. The Camera2Device makes a copy of the
+     * passed-in buffer and the caller retains ownership.
+     */
+    status_t setStreamingRequest(camera_metadata_t *request);
+
+    /**
+     * Create an output stream of the requested size and format.
+     *
+     * If format is CAMERA2_HAL_PIXEL_FORMAT_OPAQUE, then the HAL device selects
+     * an appropriate format; it can be queried with getStreamInfo.
+     *
+     * If format is HAL_PIXEL_FORMAT_COMPRESSED, the size parameter must be
+     * equal to the size in bytes of the buffers to allocate for the stream. For
+     * other formats, the size parameter is ignored.
+     */
+    status_t createStream(sp<ANativeWindow> consumer,
+            uint32_t width, uint32_t height, int format, size_t size,
+            int *id);
+
+    /**
+     * Get information about a given stream.
+     */
+    status_t getStreamInfo(int id,
+            uint32_t *width, uint32_t *height, uint32_t *format);
+
+    /**
+     * Set stream gralloc buffer transform
+     */
+    status_t setStreamTransform(int id, int transform);
+
+    /**
+     * Delete stream. Must not be called if there are requests in flight which
+     * reference that stream.
+     */
+    status_t deleteStream(int id);
+
+    /**
+     * Create a metadata buffer with fields that the HAL device believes are
+     * best for the given use case
+     */
+    status_t createDefaultRequest(int templateId,
+            camera_metadata_t **request);
+
+    /**
+     * Wait until all requests have been processed. Returns INVALID_OPERATION if
+     * the streaming slot is not empty, or TIMED_OUT if the requests haven't
+     * finished processing in 10 seconds.
+     */
+    status_t waitUntilDrained();
+
+  private:
+
+    const int mId;
+    camera2_device_t *mDevice;
+
+    camera_metadata_t *mDeviceInfo;
+    vendor_tag_query_ops_t *mVendorTagOps;
+
+    /**
+     * Queue class for both sending requests to a camera2 device, and for
+     * receiving frames from a camera2 device.
+     */
+    class MetadataQueue: public camera2_request_queue_src_ops_t,
+                         public camera2_frame_queue_dst_ops_t {
+      public:
+        MetadataQueue();
+        ~MetadataQueue();
+
+        // Interface to camera2 HAL device, either for requests (device is
+        // consumer) or for frames (device is producer)
+        const camera2_request_queue_src_ops_t*   getToConsumerInterface();
+        void setFromConsumerInterface(camera2_device_t *d);
+
+        // Connect queue consumer endpoint to a camera2 device
+        status_t setConsumerDevice(camera2_device_t *d);
+        // Connect queue producer endpoint to a camera2 device
+        status_t setProducerDevice(camera2_device_t *d);
+
+        const camera2_frame_queue_dst_ops_t* getToProducerInterface();
+
+        // Real interfaces. On enqueue, queue takes ownership of buffer pointer
+        // On dequeue, user takes ownership of buffer pointer.
+        status_t enqueue(camera_metadata_t *buf);
+        status_t dequeue(camera_metadata_t **buf, bool incrementCount = true);
+        int      getBufferCount();
+        status_t waitForBuffer(nsecs_t timeout);
+
+        // Set repeating buffer(s); if the queue is empty on a dequeue call, the
+        // queue copies the contents of the stream slot into the queue, and then
+        // dequeues the first new entry. The metadata buffers passed in are
+        // copied.
+        status_t setStreamSlot(camera_metadata_t *buf);
+        status_t setStreamSlot(const List<camera_metadata_t*> &bufs);
+
+        status_t dump(int fd, const Vector<String16>& args);
+
+      private:
+        status_t signalConsumerLocked();
+        status_t freeBuffers(List<camera_metadata_t*>::iterator start,
+                List<camera_metadata_t*>::iterator end);
+
+        camera2_device_t *mDevice;
+
+        Mutex mMutex;
+        Condition notEmpty;
+
+        int mFrameCount;
+
+        int mCount;
+        List<camera_metadata_t*> mEntries;
+        int mStreamSlotCount;
+        List<camera_metadata_t*> mStreamSlot;
+
+        bool mSignalConsumer;
+
+        static MetadataQueue* getInstance(
+            const camera2_frame_queue_dst_ops_t *q);
+        static MetadataQueue* getInstance(
+            const camera2_request_queue_src_ops_t *q);
+
+        static int consumer_buffer_count(
+            const camera2_request_queue_src_ops_t *q);
+
+        static int consumer_dequeue(const camera2_request_queue_src_ops_t *q,
+            camera_metadata_t **buffer);
+
+        static int consumer_free(const camera2_request_queue_src_ops_t *q,
+                camera_metadata_t *old_buffer);
+
+        static int producer_dequeue(const camera2_frame_queue_dst_ops_t *q,
+                size_t entries, size_t bytes,
+                camera_metadata_t **buffer);
+
+        static int producer_cancel(const camera2_frame_queue_dst_ops_t *q,
+            camera_metadata_t *old_buffer);
+
+        static int producer_enqueue(const camera2_frame_queue_dst_ops_t *q,
+                camera_metadata_t *filled_buffer);
+
+    }; // class MetadataQueue
+
+    MetadataQueue mRequestQueue;
+    MetadataQueue mFrameQueue;
+
+    /**
+     * Adapter from an ANativeWindow interface to camera2 device stream ops.
+     * Also takes care of allocating/deallocating stream in device interface
+     */
+    class StreamAdapter: public camera2_stream_ops, public virtual RefBase {
+      public:
+        StreamAdapter(camera2_device_t *d);
+
+        ~StreamAdapter();
+
+        /**
+         * Create a HAL device stream of the requested size and format.
+         *
+         * If format is CAMERA2_HAL_PIXEL_FORMAT_OPAQUE, then the HAL device
+         * selects an appropriate format; it can be queried with getFormat.
+         *
+         * If format is HAL_PIXEL_FORMAT_COMPRESSED, the size parameter must
+         * be equal to the size in bytes of the buffers to allocate for the
+         * stream. For other formats, the size parameter is ignored.
+         */
+        status_t connectToDevice(sp<ANativeWindow> consumer,
+                uint32_t width, uint32_t height, int format, size_t size);
+
+        status_t disconnect();
+
+        status_t setTransform(int transform);
+
+        // Get stream parameters.
+        // Only valid after a successful connectToDevice call.
+        int      getId() const     { return mId; }
+        uint32_t getWidth() const  { return mWidth; }
+        uint32_t getHeight() const { return mHeight; }
+        uint32_t getFormat() const { return mFormat; }
+
+        // Dump stream information
+        status_t dump(int fd, const Vector<String16>& args);
+
+      private:
+        enum {
+            ERROR = -1,
+            DISCONNECTED = 0,
+            ALLOCATED,
+            CONNECTED,
+            ACTIVE
+        } mState;
+
+        sp<ANativeWindow> mConsumerInterface;
+        camera2_device_t *mDevice;
+
+        uint32_t mId;
+        uint32_t mWidth;
+        uint32_t mHeight;
+        uint32_t mFormat;
+        size_t   mSize;
+        uint32_t mUsage;
+        uint32_t mMaxProducerBuffers;
+        uint32_t mMaxConsumerBuffers;
+        uint32_t mTotalBuffers;
+        int mFormatRequested;
+
+        /** Debugging information */
+        uint32_t mActiveBuffers;
+        uint32_t mFrameCount;
+        int64_t  mLastTimestamp;
+
+        const camera2_stream_ops *getStreamOps();
+
+        static ANativeWindow* toANW(const camera2_stream_ops_t *w);
+
+        static int dequeue_buffer(const camera2_stream_ops_t *w,
+                buffer_handle_t** buffer);
+
+        static int enqueue_buffer(const camera2_stream_ops_t* w,
+                int64_t timestamp,
+                buffer_handle_t* buffer);
+
+        static int cancel_buffer(const camera2_stream_ops_t* w,
+                buffer_handle_t* buffer);
+
+        static int set_crop(const camera2_stream_ops_t* w,
+                int left, int top, int right, int bottom);
+    }; // class StreamAdapter
+
+    typedef List<sp<StreamAdapter> > StreamList;
+    StreamList mStreams;
+
+}; // class Camera2Device
+
+}; // namespace android
+
+#endif
diff --git a/services/camera/libcameraservice/CameraClient.cpp b/services/camera/libcameraservice/CameraClient.cpp
new file mode 100644
index 0000000..80ccb43
--- /dev/null
+++ b/services/camera/libcameraservice/CameraClient.cpp
@@ -0,0 +1,958 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "CameraClient"
+//#define LOG_NDEBUG 0
+
+#include <cutils/properties.h>
+#include <gui/SurfaceTextureClient.h>
+#include <gui/Surface.h>
+
+#include "CameraClient.h"
+#include "CameraHardwareInterface.h"
+#include "CameraService.h"
+
+namespace android {
+
+#define LOG1(...) ALOGD_IF(gLogLevel >= 1, __VA_ARGS__);
+#define LOG2(...) ALOGD_IF(gLogLevel >= 2, __VA_ARGS__);
+
+static int getCallingPid() {
+    return IPCThreadState::self()->getCallingPid();
+}
+
+static int getCallingUid() {
+    return IPCThreadState::self()->getCallingUid();
+}
+
+CameraClient::CameraClient(const sp<CameraService>& cameraService,
+        const sp<ICameraClient>& cameraClient,
+        int cameraId, int cameraFacing, int clientPid):
+        Client(cameraService, cameraClient,
+                cameraId, cameraFacing, clientPid)
+{
+    int callingPid = getCallingPid();
+    LOG1("CameraClient::CameraClient E (pid %d, id %d)", callingPid, cameraId);
+
+    mHardware = NULL;
+    mMsgEnabled = 0;
+    mSurface = 0;
+    mPreviewWindow = 0;
+    mDestructionStarted = false;
+
+    // Callback is disabled by default
+    mPreviewCallbackFlag = CAMERA_FRAME_CALLBACK_FLAG_NOOP;
+    mOrientation = getOrientation(0, mCameraFacing == CAMERA_FACING_FRONT);
+    mPlayShutterSound = true;
+    LOG1("CameraClient::CameraClient X (pid %d, id %d)", callingPid, cameraId);
+}
+
+status_t CameraClient::initialize(camera_module_t *module) {
+    int callingPid = getCallingPid();
+    LOG1("CameraClient::initialize E (pid %d, id %d)", callingPid, mCameraId);
+
+    char camera_device_name[10];
+    status_t res;
+    snprintf(camera_device_name, sizeof(camera_device_name), "%d", mCameraId);
+
+    mHardware = new CameraHardwareInterface(camera_device_name);
+    res = mHardware->initialize(&module->common);
+    if (res != OK) {
+        ALOGE("%s: Camera %d: unable to initialize device: %s (%d)",
+                __FUNCTION__, mCameraId, strerror(-res), res);
+        return NO_INIT;
+    }
+
+    mHardware->setCallbacks(notifyCallback,
+            dataCallback,
+            dataCallbackTimestamp,
+            (void *)mCameraId);
+
+    // Enable zoom, error, focus, and metadata messages by default
+    enableMsgType(CAMERA_MSG_ERROR | CAMERA_MSG_ZOOM | CAMERA_MSG_FOCUS |
+                  CAMERA_MSG_PREVIEW_METADATA | CAMERA_MSG_FOCUS_MOVE);
+
+    LOG1("CameraClient::initialize X (pid %d, id %d)", callingPid, mCameraId);
+    return OK;
+}
+
+
+// tear down the client
+CameraClient::~CameraClient() {
+    // this lock should never be NULL
+    Mutex* lock = mCameraService->getClientLockById(mCameraId);
+    lock->lock();
+    mDestructionStarted = true;
+    // client will not be accessed from callback. should unlock to prevent dead-lock in disconnect
+    lock->unlock();
+    int callingPid = getCallingPid();
+    LOG1("CameraClient::~CameraClient E (pid %d, this %p)", callingPid, this);
+
+    // set mClientPid to let disconnet() tear down the hardware
+    mClientPid = callingPid;
+    disconnect();
+    LOG1("CameraClient::~CameraClient X (pid %d, this %p)", callingPid, this);
+}
+
+status_t CameraClient::dump(int fd, const Vector<String16>& args) {
+    const size_t SIZE = 256;
+    char buffer[SIZE];
+
+    size_t len = snprintf(buffer, SIZE, "Client[%d] (%p) PID: %d\n",
+            mCameraId,
+            getCameraClient()->asBinder().get(),
+            mClientPid);
+    len = (len > SIZE - 1) ? SIZE - 1 : len;
+    write(fd, buffer, len);
+    return mHardware->dump(fd, args);
+}
+
+// ----------------------------------------------------------------------------
+
+status_t CameraClient::checkPid() const {
+    int callingPid = getCallingPid();
+    if (callingPid == mClientPid) return NO_ERROR;
+
+    ALOGW("attempt to use a locked camera from a different process"
+         " (old pid %d, new pid %d)", mClientPid, callingPid);
+    return EBUSY;
+}
+
+status_t CameraClient::checkPidAndHardware() const {
+    status_t result = checkPid();
+    if (result != NO_ERROR) return result;
+    if (mHardware == 0) {
+        ALOGE("attempt to use a camera after disconnect() (pid %d)", getCallingPid());
+        return INVALID_OPERATION;
+    }
+    return NO_ERROR;
+}
+
+status_t CameraClient::lock() {
+    int callingPid = getCallingPid();
+    LOG1("lock (pid %d)", callingPid);
+    Mutex::Autolock lock(mLock);
+
+    // lock camera to this client if the the camera is unlocked
+    if (mClientPid == 0) {
+        mClientPid = callingPid;
+        return NO_ERROR;
+    }
+
+    // returns NO_ERROR if the client already owns the camera, EBUSY otherwise
+    return checkPid();
+}
+
+status_t CameraClient::unlock() {
+    int callingPid = getCallingPid();
+    LOG1("unlock (pid %d)", callingPid);
+    Mutex::Autolock lock(mLock);
+
+    // allow anyone to use camera (after they lock the camera)
+    status_t result = checkPid();
+    if (result == NO_ERROR) {
+        if (mHardware->recordingEnabled()) {
+            ALOGE("Not allowed to unlock camera during recording.");
+            return INVALID_OPERATION;
+        }
+        mClientPid = 0;
+        LOG1("clear mCameraClient (pid %d)", callingPid);
+        // we need to remove the reference to ICameraClient so that when the app
+        // goes away, the reference count goes to 0.
+        mCameraClient.clear();
+    }
+    return result;
+}
+
+// connect a new client to the camera
+status_t CameraClient::connect(const sp<ICameraClient>& client) {
+    int callingPid = getCallingPid();
+    LOG1("connect E (pid %d)", callingPid);
+    Mutex::Autolock lock(mLock);
+
+    if (mClientPid != 0 && checkPid() != NO_ERROR) {
+        ALOGW("Tried to connect to a locked camera (old pid %d, new pid %d)",
+                mClientPid, callingPid);
+        return EBUSY;
+    }
+
+    if (mCameraClient != 0 && (client->asBinder() == mCameraClient->asBinder())) {
+        LOG1("Connect to the same client");
+        return NO_ERROR;
+    }
+
+    mPreviewCallbackFlag = CAMERA_FRAME_CALLBACK_FLAG_NOOP;
+    mClientPid = callingPid;
+    mCameraClient = client;
+
+    LOG1("connect X (pid %d)", callingPid);
+    return NO_ERROR;
+}
+
+static void disconnectWindow(const sp<ANativeWindow>& window) {
+    if (window != 0) {
+        status_t result = native_window_api_disconnect(window.get(),
+                NATIVE_WINDOW_API_CAMERA);
+        if (result != NO_ERROR) {
+            ALOGW("native_window_api_disconnect failed: %s (%d)", strerror(-result),
+                    result);
+        }
+    }
+}
+
+void CameraClient::disconnect() {
+    int callingPid = getCallingPid();
+    LOG1("disconnect E (pid %d)", callingPid);
+    Mutex::Autolock lock(mLock);
+
+    if (checkPid() != NO_ERROR) {
+        ALOGW("different client - don't disconnect");
+        return;
+    }
+
+    if (mClientPid <= 0) {
+        LOG1("camera is unlocked (mClientPid = %d), don't tear down hardware", mClientPid);
+        return;
+    }
+
+    // Make sure disconnect() is done once and once only, whether it is called
+    // from the user directly, or called by the destructor.
+    if (mHardware == 0) return;
+
+    LOG1("hardware teardown");
+    // Before destroying mHardware, we must make sure it's in the
+    // idle state.
+    // Turn off all messages.
+    disableMsgType(CAMERA_MSG_ALL_MSGS);
+    mHardware->stopPreview();
+    mHardware->cancelPicture();
+    // Release the hardware resources.
+    mHardware->release();
+
+    // Release the held ANativeWindow resources.
+    if (mPreviewWindow != 0) {
+        disconnectWindow(mPreviewWindow);
+        mPreviewWindow = 0;
+        mHardware->setPreviewWindow(mPreviewWindow);
+    }
+    mHardware.clear();
+
+    CameraService::Client::disconnect();
+
+    LOG1("disconnect X (pid %d)", callingPid);
+}
+
+// ----------------------------------------------------------------------------
+
+status_t CameraClient::setPreviewWindow(const sp<IBinder>& binder,
+        const sp<ANativeWindow>& window) {
+    Mutex::Autolock lock(mLock);
+    status_t result = checkPidAndHardware();
+    if (result != NO_ERROR) return result;
+
+    // return if no change in surface.
+    if (binder == mSurface) {
+        return NO_ERROR;
+    }
+
+    if (window != 0) {
+        result = native_window_api_connect(window.get(), NATIVE_WINDOW_API_CAMERA);
+        if (result != NO_ERROR) {
+            ALOGE("native_window_api_connect failed: %s (%d)", strerror(-result),
+                    result);
+            return result;
+        }
+    }
+
+    // If preview has been already started, register preview buffers now.
+    if (mHardware->previewEnabled()) {
+        if (window != 0) {
+            native_window_set_scaling_mode(window.get(),
+                    NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW);
+            native_window_set_buffers_transform(window.get(), mOrientation);
+            result = mHardware->setPreviewWindow(window);
+        }
+    }
+
+    if (result == NO_ERROR) {
+        // Everything has succeeded.  Disconnect the old window and remember the
+        // new window.
+        disconnectWindow(mPreviewWindow);
+        mSurface = binder;
+        mPreviewWindow = window;
+    } else {
+        // Something went wrong after we connected to the new window, so
+        // disconnect here.
+        disconnectWindow(window);
+    }
+
+    return result;
+}
+
+// set the Surface that the preview will use
+status_t CameraClient::setPreviewDisplay(const sp<Surface>& surface) {
+    LOG1("setPreviewDisplay(%p) (pid %d)", surface.get(), getCallingPid());
+
+    sp<IBinder> binder(surface != 0 ? surface->asBinder() : 0);
+    sp<ANativeWindow> window(surface);
+    return setPreviewWindow(binder, window);
+}
+
+// set the SurfaceTexture that the preview will use
+status_t CameraClient::setPreviewTexture(
+        const sp<ISurfaceTexture>& surfaceTexture) {
+    LOG1("setPreviewTexture(%p) (pid %d)", surfaceTexture.get(),
+            getCallingPid());
+
+    sp<IBinder> binder;
+    sp<ANativeWindow> window;
+    if (surfaceTexture != 0) {
+        binder = surfaceTexture->asBinder();
+        window = new SurfaceTextureClient(surfaceTexture);
+    }
+    return setPreviewWindow(binder, window);
+}
+
+// set the preview callback flag to affect how the received frames from
+// preview are handled.
+void CameraClient::setPreviewCallbackFlag(int callback_flag) {
+    LOG1("setPreviewCallbackFlag(%d) (pid %d)", callback_flag, getCallingPid());
+    Mutex::Autolock lock(mLock);
+    if (checkPidAndHardware() != NO_ERROR) return;
+
+    mPreviewCallbackFlag = callback_flag;
+    if (mPreviewCallbackFlag & CAMERA_FRAME_CALLBACK_FLAG_ENABLE_MASK) {
+        enableMsgType(CAMERA_MSG_PREVIEW_FRAME);
+    } else {
+        disableMsgType(CAMERA_MSG_PREVIEW_FRAME);
+    }
+}
+
+// start preview mode
+status_t CameraClient::startPreview() {
+    LOG1("startPreview (pid %d)", getCallingPid());
+    return startCameraMode(CAMERA_PREVIEW_MODE);
+}
+
+// start recording mode
+status_t CameraClient::startRecording() {
+    LOG1("startRecording (pid %d)", getCallingPid());
+    return startCameraMode(CAMERA_RECORDING_MODE);
+}
+
+// start preview or recording
+status_t CameraClient::startCameraMode(camera_mode mode) {
+    LOG1("startCameraMode(%d)", mode);
+    Mutex::Autolock lock(mLock);
+    status_t result = checkPidAndHardware();
+    if (result != NO_ERROR) return result;
+
+    switch(mode) {
+        case CAMERA_PREVIEW_MODE:
+            if (mSurface == 0 && mPreviewWindow == 0) {
+                LOG1("mSurface is not set yet.");
+                // still able to start preview in this case.
+            }
+            return startPreviewMode();
+        case CAMERA_RECORDING_MODE:
+            if (mSurface == 0 && mPreviewWindow == 0) {
+                ALOGE("mSurface or mPreviewWindow must be set before startRecordingMode.");
+                return INVALID_OPERATION;
+            }
+            return startRecordingMode();
+        default:
+            return UNKNOWN_ERROR;
+    }
+}
+
+status_t CameraClient::startPreviewMode() {
+    LOG1("startPreviewMode");
+    status_t result = NO_ERROR;
+
+    // if preview has been enabled, nothing needs to be done
+    if (mHardware->previewEnabled()) {
+        return NO_ERROR;
+    }
+
+    if (mPreviewWindow != 0) {
+        native_window_set_scaling_mode(mPreviewWindow.get(),
+                NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW);
+        native_window_set_buffers_transform(mPreviewWindow.get(),
+                mOrientation);
+    }
+    mHardware->setPreviewWindow(mPreviewWindow);
+    result = mHardware->startPreview();
+
+    return result;
+}
+
+status_t CameraClient::startRecordingMode() {
+    LOG1("startRecordingMode");
+    status_t result = NO_ERROR;
+
+    // if recording has been enabled, nothing needs to be done
+    if (mHardware->recordingEnabled()) {
+        return NO_ERROR;
+    }
+
+    // if preview has not been started, start preview first
+    if (!mHardware->previewEnabled()) {
+        result = startPreviewMode();
+        if (result != NO_ERROR) {
+            return result;
+        }
+    }
+
+    // start recording mode
+    enableMsgType(CAMERA_MSG_VIDEO_FRAME);
+    mCameraService->playSound(CameraService::SOUND_RECORDING);
+    result = mHardware->startRecording();
+    if (result != NO_ERROR) {
+        ALOGE("mHardware->startRecording() failed with status %d", result);
+    }
+    return result;
+}
+
+// stop preview mode
+void CameraClient::stopPreview() {
+    LOG1("stopPreview (pid %d)", getCallingPid());
+    Mutex::Autolock lock(mLock);
+    if (checkPidAndHardware() != NO_ERROR) return;
+
+
+    disableMsgType(CAMERA_MSG_PREVIEW_FRAME);
+    mHardware->stopPreview();
+
+    mPreviewBuffer.clear();
+}
+
+// stop recording mode
+void CameraClient::stopRecording() {
+    LOG1("stopRecording (pid %d)", getCallingPid());
+    Mutex::Autolock lock(mLock);
+    if (checkPidAndHardware() != NO_ERROR) return;
+
+    mCameraService->playSound(CameraService::SOUND_RECORDING);
+    disableMsgType(CAMERA_MSG_VIDEO_FRAME);
+    mHardware->stopRecording();
+
+    mPreviewBuffer.clear();
+}
+
+// release a recording frame
+void CameraClient::releaseRecordingFrame(const sp<IMemory>& mem) {
+    Mutex::Autolock lock(mLock);
+    if (checkPidAndHardware() != NO_ERROR) return;
+    mHardware->releaseRecordingFrame(mem);
+}
+
+status_t CameraClient::storeMetaDataInBuffers(bool enabled)
+{
+    LOG1("storeMetaDataInBuffers: %s", enabled? "true": "false");
+    Mutex::Autolock lock(mLock);
+    if (checkPidAndHardware() != NO_ERROR) {
+        return UNKNOWN_ERROR;
+    }
+    return mHardware->storeMetaDataInBuffers(enabled);
+}
+
+bool CameraClient::previewEnabled() {
+    LOG1("previewEnabled (pid %d)", getCallingPid());
+
+    Mutex::Autolock lock(mLock);
+    if (checkPidAndHardware() != NO_ERROR) return false;
+    return mHardware->previewEnabled();
+}
+
+bool CameraClient::recordingEnabled() {
+    LOG1("recordingEnabled (pid %d)", getCallingPid());
+
+    Mutex::Autolock lock(mLock);
+    if (checkPidAndHardware() != NO_ERROR) return false;
+    return mHardware->recordingEnabled();
+}
+
+status_t CameraClient::autoFocus() {
+    LOG1("autoFocus (pid %d)", getCallingPid());
+
+    Mutex::Autolock lock(mLock);
+    status_t result = checkPidAndHardware();
+    if (result != NO_ERROR) return result;
+
+    return mHardware->autoFocus();
+}
+
+status_t CameraClient::cancelAutoFocus() {
+    LOG1("cancelAutoFocus (pid %d)", getCallingPid());
+
+    Mutex::Autolock lock(mLock);
+    status_t result = checkPidAndHardware();
+    if (result != NO_ERROR) return result;
+
+    return mHardware->cancelAutoFocus();
+}
+
+// take a picture - image is returned in callback
+status_t CameraClient::takePicture(int msgType) {
+    LOG1("takePicture (pid %d): 0x%x", getCallingPid(), msgType);
+
+    Mutex::Autolock lock(mLock);
+    status_t result = checkPidAndHardware();
+    if (result != NO_ERROR) return result;
+
+    if ((msgType & CAMERA_MSG_RAW_IMAGE) &&
+        (msgType & CAMERA_MSG_RAW_IMAGE_NOTIFY)) {
+        ALOGE("CAMERA_MSG_RAW_IMAGE and CAMERA_MSG_RAW_IMAGE_NOTIFY"
+                " cannot be both enabled");
+        return BAD_VALUE;
+    }
+
+    // We only accept picture related message types
+    // and ignore other types of messages for takePicture().
+    int picMsgType = msgType
+                        & (CAMERA_MSG_SHUTTER |
+                           CAMERA_MSG_POSTVIEW_FRAME |
+                           CAMERA_MSG_RAW_IMAGE |
+                           CAMERA_MSG_RAW_IMAGE_NOTIFY |
+                           CAMERA_MSG_COMPRESSED_IMAGE);
+
+    enableMsgType(picMsgType);
+
+    return mHardware->takePicture();
+}
+
+// set preview/capture parameters - key/value pairs
+status_t CameraClient::setParameters(const String8& params) {
+    LOG1("setParameters (pid %d) (%s)", getCallingPid(), params.string());
+
+    Mutex::Autolock lock(mLock);
+    status_t result = checkPidAndHardware();
+    if (result != NO_ERROR) return result;
+
+    CameraParameters p(params);
+    return mHardware->setParameters(p);
+}
+
+// get preview/capture parameters - key/value pairs
+String8 CameraClient::getParameters() const {
+    Mutex::Autolock lock(mLock);
+    if (checkPidAndHardware() != NO_ERROR) return String8();
+
+    String8 params(mHardware->getParameters().flatten());
+    LOG1("getParameters (pid %d) (%s)", getCallingPid(), params.string());
+    return params;
+}
+
+// enable shutter sound
+status_t CameraClient::enableShutterSound(bool enable) {
+    LOG1("enableShutterSound (pid %d)", getCallingPid());
+
+    status_t result = checkPidAndHardware();
+    if (result != NO_ERROR) return result;
+
+    if (enable) {
+        mPlayShutterSound = true;
+        return OK;
+    }
+
+    // Disabling shutter sound may not be allowed. In that case only
+    // allow the mediaserver process to disable the sound.
+    char value[PROPERTY_VALUE_MAX];
+    property_get("ro.camera.sound.forced", value, "0");
+    if (strcmp(value, "0") != 0) {
+        // Disabling shutter sound is not allowed. Deny if the current
+        // process is not mediaserver.
+        if (getCallingPid() != getpid()) {
+            ALOGE("Failed to disable shutter sound. Permission denied (pid %d)", getCallingPid());
+            return PERMISSION_DENIED;
+        }
+    }
+
+    mPlayShutterSound = false;
+    return OK;
+}
+
+status_t CameraClient::sendCommand(int32_t cmd, int32_t arg1, int32_t arg2) {
+    LOG1("sendCommand (pid %d)", getCallingPid());
+    int orientation;
+    Mutex::Autolock lock(mLock);
+    status_t result = checkPidAndHardware();
+    if (result != NO_ERROR) return result;
+
+    if (cmd == CAMERA_CMD_SET_DISPLAY_ORIENTATION) {
+        // Mirror the preview if the camera is front-facing.
+        orientation = getOrientation(arg1, mCameraFacing == CAMERA_FACING_FRONT);
+        if (orientation == -1) return BAD_VALUE;
+
+        if (mOrientation != orientation) {
+            mOrientation = orientation;
+            if (mPreviewWindow != 0) {
+                native_window_set_buffers_transform(mPreviewWindow.get(),
+                        mOrientation);
+            }
+        }
+        return OK;
+    } else if (cmd == CAMERA_CMD_ENABLE_SHUTTER_SOUND) {
+        switch (arg1) {
+            case 0:
+                enableShutterSound(false);
+                break;
+            case 1:
+                enableShutterSound(true);
+                break;
+            default:
+                return BAD_VALUE;
+        }
+        return OK;
+    } else if (cmd == CAMERA_CMD_PLAY_RECORDING_SOUND) {
+        mCameraService->playSound(CameraService::SOUND_RECORDING);
+    } else if (cmd == CAMERA_CMD_PING) {
+        // If mHardware is 0, checkPidAndHardware will return error.
+        return OK;
+    }
+
+    return mHardware->sendCommand(cmd, arg1, arg2);
+}
+
+// ----------------------------------------------------------------------------
+
+void CameraClient::enableMsgType(int32_t msgType) {
+    android_atomic_or(msgType, &mMsgEnabled);
+    mHardware->enableMsgType(msgType);
+}
+
+void CameraClient::disableMsgType(int32_t msgType) {
+    android_atomic_and(~msgType, &mMsgEnabled);
+    mHardware->disableMsgType(msgType);
+}
+
+#define CHECK_MESSAGE_INTERVAL 10 // 10ms
+bool CameraClient::lockIfMessageWanted(int32_t msgType) {
+    int sleepCount = 0;
+    while (mMsgEnabled & msgType) {
+        if (mLock.tryLock() == NO_ERROR) {
+            if (sleepCount > 0) {
+                LOG1("lockIfMessageWanted(%d): waited for %d ms",
+                    msgType, sleepCount * CHECK_MESSAGE_INTERVAL);
+            }
+            return true;
+        }
+        if (sleepCount++ == 0) {
+            LOG1("lockIfMessageWanted(%d): enter sleep", msgType);
+        }
+        usleep(CHECK_MESSAGE_INTERVAL * 1000);
+    }
+    ALOGW("lockIfMessageWanted(%d): dropped unwanted message", msgType);
+    return false;
+}
+
+// Callback messages can be dispatched to internal handlers or pass to our
+// client's callback functions, depending on the message type.
+//
+// notifyCallback:
+//      CAMERA_MSG_SHUTTER              handleShutter
+//      (others)                        c->notifyCallback
+// dataCallback:
+//      CAMERA_MSG_PREVIEW_FRAME        handlePreviewData
+//      CAMERA_MSG_POSTVIEW_FRAME       handlePostview
+//      CAMERA_MSG_RAW_IMAGE            handleRawPicture
+//      CAMERA_MSG_COMPRESSED_IMAGE     handleCompressedPicture
+//      (others)                        c->dataCallback
+// dataCallbackTimestamp
+//      (others)                        c->dataCallbackTimestamp
+//
+// NOTE: the *Callback functions grab mLock of the client before passing
+// control to handle* functions. So the handle* functions must release the
+// lock before calling the ICameraClient's callbacks, so those callbacks can
+// invoke methods in the Client class again (For example, the preview frame
+// callback may want to releaseRecordingFrame). The handle* functions must
+// release the lock after all accesses to member variables, so it must be
+// handled very carefully.
+
+void CameraClient::notifyCallback(int32_t msgType, int32_t ext1,
+        int32_t ext2, void* user) {
+    LOG2("notifyCallback(%d)", msgType);
+
+    Mutex* lock = getClientLockFromCookie(user);
+    if (lock == NULL) return;
+    Mutex::Autolock alock(*lock);
+
+    CameraClient* client =
+            static_cast<CameraClient*>(getClientFromCookie(user));
+    if (client == NULL) return;
+
+    if (!client->lockIfMessageWanted(msgType)) return;
+
+    switch (msgType) {
+        case CAMERA_MSG_SHUTTER:
+            // ext1 is the dimension of the yuv picture.
+            client->handleShutter();
+            break;
+        default:
+            client->handleGenericNotify(msgType, ext1, ext2);
+            break;
+    }
+}
+
+void CameraClient::dataCallback(int32_t msgType,
+        const sp<IMemory>& dataPtr, camera_frame_metadata_t *metadata, void* user) {
+    LOG2("dataCallback(%d)", msgType);
+
+    Mutex* lock = getClientLockFromCookie(user);
+    if (lock == NULL) return;
+    Mutex::Autolock alock(*lock);
+
+    CameraClient* client =
+            static_cast<CameraClient*>(getClientFromCookie(user));
+    if (client == NULL) return;
+
+    if (!client->lockIfMessageWanted(msgType)) return;
+    if (dataPtr == 0 && metadata == NULL) {
+        ALOGE("Null data returned in data callback");
+        client->handleGenericNotify(CAMERA_MSG_ERROR, UNKNOWN_ERROR, 0);
+        return;
+    }
+
+    switch (msgType & ~CAMERA_MSG_PREVIEW_METADATA) {
+        case CAMERA_MSG_PREVIEW_FRAME:
+            client->handlePreviewData(msgType, dataPtr, metadata);
+            break;
+        case CAMERA_MSG_POSTVIEW_FRAME:
+            client->handlePostview(dataPtr);
+            break;
+        case CAMERA_MSG_RAW_IMAGE:
+            client->handleRawPicture(dataPtr);
+            break;
+        case CAMERA_MSG_COMPRESSED_IMAGE:
+            client->handleCompressedPicture(dataPtr);
+            break;
+        default:
+            client->handleGenericData(msgType, dataPtr, metadata);
+            break;
+    }
+}
+
+void CameraClient::dataCallbackTimestamp(nsecs_t timestamp,
+        int32_t msgType, const sp<IMemory>& dataPtr, void* user) {
+    LOG2("dataCallbackTimestamp(%d)", msgType);
+
+    Mutex* lock = getClientLockFromCookie(user);
+    if (lock == NULL) return;
+    Mutex::Autolock alock(*lock);
+
+    CameraClient* client =
+            static_cast<CameraClient*>(getClientFromCookie(user));
+    if (client == NULL) return;
+
+    if (!client->lockIfMessageWanted(msgType)) return;
+
+    if (dataPtr == 0) {
+        ALOGE("Null data returned in data with timestamp callback");
+        client->handleGenericNotify(CAMERA_MSG_ERROR, UNKNOWN_ERROR, 0);
+        return;
+    }
+
+    client->handleGenericDataTimestamp(timestamp, msgType, dataPtr);
+}
+
+// snapshot taken callback
+void CameraClient::handleShutter(void) {
+    if (mPlayShutterSound) {
+        mCameraService->playSound(CameraService::SOUND_SHUTTER);
+    }
+
+    sp<ICameraClient> c = mCameraClient;
+    if (c != 0) {
+        mLock.unlock();
+        c->notifyCallback(CAMERA_MSG_SHUTTER, 0, 0);
+        if (!lockIfMessageWanted(CAMERA_MSG_SHUTTER)) return;
+    }
+    disableMsgType(CAMERA_MSG_SHUTTER);
+
+    mLock.unlock();
+}
+
+// preview callback - frame buffer update
+void CameraClient::handlePreviewData(int32_t msgType,
+                                              const sp<IMemory>& mem,
+                                              camera_frame_metadata_t *metadata) {
+    ssize_t offset;
+    size_t size;
+    sp<IMemoryHeap> heap = mem->getMemory(&offset, &size);
+
+    // local copy of the callback flags
+    int flags = mPreviewCallbackFlag;
+
+    // is callback enabled?
+    if (!(flags & CAMERA_FRAME_CALLBACK_FLAG_ENABLE_MASK)) {
+        // If the enable bit is off, the copy-out and one-shot bits are ignored
+        LOG2("frame callback is disabled");
+        mLock.unlock();
+        return;
+    }
+
+    // hold a strong pointer to the client
+    sp<ICameraClient> c = mCameraClient;
+
+    // clear callback flags if no client or one-shot mode
+    if (c == 0 || (mPreviewCallbackFlag & CAMERA_FRAME_CALLBACK_FLAG_ONE_SHOT_MASK)) {
+        LOG2("Disable preview callback");
+        mPreviewCallbackFlag &= ~(CAMERA_FRAME_CALLBACK_FLAG_ONE_SHOT_MASK |
+                                  CAMERA_FRAME_CALLBACK_FLAG_COPY_OUT_MASK |
+                                  CAMERA_FRAME_CALLBACK_FLAG_ENABLE_MASK);
+        disableMsgType(CAMERA_MSG_PREVIEW_FRAME);
+    }
+
+    if (c != 0) {
+        // Is the received frame copied out or not?
+        if (flags & CAMERA_FRAME_CALLBACK_FLAG_COPY_OUT_MASK) {
+            LOG2("frame is copied");
+            copyFrameAndPostCopiedFrame(msgType, c, heap, offset, size, metadata);
+        } else {
+            LOG2("frame is forwarded");
+            mLock.unlock();
+            c->dataCallback(msgType, mem, metadata);
+        }
+    } else {
+        mLock.unlock();
+    }
+}
+
+// picture callback - postview image ready
+void CameraClient::handlePostview(const sp<IMemory>& mem) {
+    disableMsgType(CAMERA_MSG_POSTVIEW_FRAME);
+
+    sp<ICameraClient> c = mCameraClient;
+    mLock.unlock();
+    if (c != 0) {
+        c->dataCallback(CAMERA_MSG_POSTVIEW_FRAME, mem, NULL);
+    }
+}
+
+// picture callback - raw image ready
+void CameraClient::handleRawPicture(const sp<IMemory>& mem) {
+    disableMsgType(CAMERA_MSG_RAW_IMAGE);
+
+    ssize_t offset;
+    size_t size;
+    sp<IMemoryHeap> heap = mem->getMemory(&offset, &size);
+
+    sp<ICameraClient> c = mCameraClient;
+    mLock.unlock();
+    if (c != 0) {
+        c->dataCallback(CAMERA_MSG_RAW_IMAGE, mem, NULL);
+    }
+}
+
+// picture callback - compressed picture ready
+void CameraClient::handleCompressedPicture(const sp<IMemory>& mem) {
+    disableMsgType(CAMERA_MSG_COMPRESSED_IMAGE);
+
+    sp<ICameraClient> c = mCameraClient;
+    mLock.unlock();
+    if (c != 0) {
+        c->dataCallback(CAMERA_MSG_COMPRESSED_IMAGE, mem, NULL);
+    }
+}
+
+
+void CameraClient::handleGenericNotify(int32_t msgType,
+    int32_t ext1, int32_t ext2) {
+    sp<ICameraClient> c = mCameraClient;
+    mLock.unlock();
+    if (c != 0) {
+        c->notifyCallback(msgType, ext1, ext2);
+    }
+}
+
+void CameraClient::handleGenericData(int32_t msgType,
+    const sp<IMemory>& dataPtr, camera_frame_metadata_t *metadata) {
+    sp<ICameraClient> c = mCameraClient;
+    mLock.unlock();
+    if (c != 0) {
+        c->dataCallback(msgType, dataPtr, metadata);
+    }
+}
+
+void CameraClient::handleGenericDataTimestamp(nsecs_t timestamp,
+    int32_t msgType, const sp<IMemory>& dataPtr) {
+    sp<ICameraClient> c = mCameraClient;
+    mLock.unlock();
+    if (c != 0) {
+        c->dataCallbackTimestamp(timestamp, msgType, dataPtr);
+    }
+}
+
+void CameraClient::copyFrameAndPostCopiedFrame(
+        int32_t msgType, const sp<ICameraClient>& client,
+        const sp<IMemoryHeap>& heap, size_t offset, size_t size,
+        camera_frame_metadata_t *metadata) {
+    LOG2("copyFrameAndPostCopiedFrame");
+    // It is necessary to copy out of pmem before sending this to
+    // the callback. For efficiency, reuse the same MemoryHeapBase
+    // provided it's big enough. Don't allocate the memory or
+    // perform the copy if there's no callback.
+    // hold the preview lock while we grab a reference to the preview buffer
+    sp<MemoryHeapBase> previewBuffer;
+
+    if (mPreviewBuffer == 0) {
+        mPreviewBuffer = new MemoryHeapBase(size, 0, NULL);
+    } else if (size > mPreviewBuffer->virtualSize()) {
+        mPreviewBuffer.clear();
+        mPreviewBuffer = new MemoryHeapBase(size, 0, NULL);
+    }
+    if (mPreviewBuffer == 0) {
+        ALOGE("failed to allocate space for preview buffer");
+        mLock.unlock();
+        return;
+    }
+    previewBuffer = mPreviewBuffer;
+
+    memcpy(previewBuffer->base(), (uint8_t *)heap->base() + offset, size);
+
+    sp<MemoryBase> frame = new MemoryBase(previewBuffer, 0, size);
+    if (frame == 0) {
+        ALOGE("failed to allocate space for frame callback");
+        mLock.unlock();
+        return;
+    }
+
+    mLock.unlock();
+    client->dataCallback(msgType, frame, metadata);
+}
+
+int CameraClient::getOrientation(int degrees, bool mirror) {
+    if (!mirror) {
+        if (degrees == 0) return 0;
+        else if (degrees == 90) return HAL_TRANSFORM_ROT_90;
+        else if (degrees == 180) return HAL_TRANSFORM_ROT_180;
+        else if (degrees == 270) return HAL_TRANSFORM_ROT_270;
+    } else {  // Do mirror (horizontal flip)
+        if (degrees == 0) {           // FLIP_H and ROT_0
+            return HAL_TRANSFORM_FLIP_H;
+        } else if (degrees == 90) {   // FLIP_H and ROT_90
+            return HAL_TRANSFORM_FLIP_H | HAL_TRANSFORM_ROT_90;
+        } else if (degrees == 180) {  // FLIP_H and ROT_180
+            return HAL_TRANSFORM_FLIP_V;
+        } else if (degrees == 270) {  // FLIP_H and ROT_270
+            return HAL_TRANSFORM_FLIP_V | HAL_TRANSFORM_ROT_90;
+        }
+    }
+    ALOGE("Invalid setDisplayOrientation degrees=%d", degrees);
+    return -1;
+}
+
+}; // namespace android
diff --git a/services/camera/libcameraservice/CameraClient.h b/services/camera/libcameraservice/CameraClient.h
new file mode 100644
index 0000000..256298d
--- /dev/null
+++ b/services/camera/libcameraservice/CameraClient.h
@@ -0,0 +1,155 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_SERVERS_CAMERA_CAMERACLIENT_H
+#define ANDROID_SERVERS_CAMERA_CAMERACLIENT_H
+
+#include "CameraService.h"
+
+namespace android {
+
+class MemoryHeapBase;
+class CameraHardwareInterface;
+
+class CameraClient : public CameraService::Client
+{
+public:
+    // ICamera interface (see ICamera for details)
+    virtual void            disconnect();
+    virtual status_t        connect(const sp<ICameraClient>& client);
+    virtual status_t        lock();
+    virtual status_t        unlock();
+    virtual status_t        setPreviewDisplay(const sp<Surface>& surface);
+    virtual status_t        setPreviewTexture(const sp<ISurfaceTexture>& surfaceTexture);
+    virtual void            setPreviewCallbackFlag(int flag);
+    virtual status_t        startPreview();
+    virtual void            stopPreview();
+    virtual bool            previewEnabled();
+    virtual status_t        storeMetaDataInBuffers(bool enabled);
+    virtual status_t        startRecording();
+    virtual void            stopRecording();
+    virtual bool            recordingEnabled();
+    virtual void            releaseRecordingFrame(const sp<IMemory>& mem);
+    virtual status_t        autoFocus();
+    virtual status_t        cancelAutoFocus();
+    virtual status_t        takePicture(int msgType);
+    virtual status_t        setParameters(const String8& params);
+    virtual String8         getParameters() const;
+    virtual status_t        sendCommand(int32_t cmd, int32_t arg1, int32_t arg2);
+
+    // Interface used by CameraService
+    CameraClient(const sp<CameraService>& cameraService,
+            const sp<ICameraClient>& cameraClient,
+            int cameraId,
+            int cameraFacing,
+            int clientPid);
+    ~CameraClient();
+
+    status_t initialize(camera_module_t *module);
+
+    status_t dump(int fd, const Vector<String16>& args);
+
+private:
+
+    // check whether the calling process matches mClientPid.
+    status_t                checkPid() const;
+    status_t                checkPidAndHardware() const;  // also check mHardware != 0
+
+    // these are internal functions used to set up preview buffers
+    status_t                registerPreviewBuffers();
+
+    // camera operation mode
+    enum camera_mode {
+        CAMERA_PREVIEW_MODE   = 0,  // frame automatically released
+        CAMERA_RECORDING_MODE = 1,  // frame has to be explicitly released by releaseRecordingFrame()
+    };
+    // these are internal functions used for preview/recording
+    status_t                startCameraMode(camera_mode mode);
+    status_t                startPreviewMode();
+    status_t                startRecordingMode();
+
+    // internal function used by sendCommand to enable/disable shutter sound.
+    status_t                enableShutterSound(bool enable);
+
+    // these are static callback functions
+    static void             notifyCallback(int32_t msgType, int32_t ext1, int32_t ext2, void* user);
+    static void             dataCallback(int32_t msgType, const sp<IMemory>& dataPtr,
+            camera_frame_metadata_t *metadata, void* user);
+    static void             dataCallbackTimestamp(nsecs_t timestamp, int32_t msgType, const sp<IMemory>& dataPtr, void* user);
+    // handlers for messages
+    void                    handleShutter(void);
+    void                    handlePreviewData(int32_t msgType, const sp<IMemory>& mem,
+            camera_frame_metadata_t *metadata);
+    void                    handlePostview(const sp<IMemory>& mem);
+    void                    handleRawPicture(const sp<IMemory>& mem);
+    void                    handleCompressedPicture(const sp<IMemory>& mem);
+    void                    handleGenericNotify(int32_t msgType, int32_t ext1, int32_t ext2);
+    void                    handleGenericData(int32_t msgType, const sp<IMemory>& dataPtr,
+            camera_frame_metadata_t *metadata);
+    void                    handleGenericDataTimestamp(nsecs_t timestamp, int32_t msgType, const sp<IMemory>& dataPtr);
+
+    void                    copyFrameAndPostCopiedFrame(
+        int32_t msgType,
+        const sp<ICameraClient>& client,
+        const sp<IMemoryHeap>& heap,
+        size_t offset, size_t size,
+        camera_frame_metadata_t *metadata);
+
+    int                     getOrientation(int orientation, bool mirror);
+
+    status_t                setPreviewWindow(
+        const sp<IBinder>& binder,
+        const sp<ANativeWindow>& window);
+
+
+    // these are initialized in the constructor.
+    sp<CameraHardwareInterface>     mHardware;       // cleared after disconnect()
+    int                             mPreviewCallbackFlag;
+    int                             mOrientation;     // Current display orientation
+    bool                            mPlayShutterSound;
+
+    // Ensures atomicity among the public methods
+    mutable Mutex                   mLock;
+    // This is a binder of Surface or SurfaceTexture.
+    sp<IBinder>                     mSurface;
+    sp<ANativeWindow>               mPreviewWindow;
+
+    // If the user want us to return a copy of the preview frame (instead
+    // of the original one), we allocate mPreviewBuffer and reuse it if possible.
+    sp<MemoryHeapBase>              mPreviewBuffer;
+
+    // We need to avoid the deadlock when the incoming command thread and
+    // the CameraHardwareInterface callback thread both want to grab mLock.
+    // An extra flag is used to tell the callback thread that it should stop
+    // trying to deliver the callback messages if the client is not
+    // interested in it anymore. For example, if the client is calling
+    // stopPreview(), the preview frame messages do not need to be delivered
+    // anymore.
+
+    // This function takes the same parameter as the enableMsgType() and
+    // disableMsgType() functions in CameraHardwareInterface.
+    void                    enableMsgType(int32_t msgType);
+    void                    disableMsgType(int32_t msgType);
+    volatile int32_t        mMsgEnabled;
+
+    // This function keeps trying to grab mLock, or give up if the message
+    // is found to be disabled. It returns true if mLock is grabbed.
+    bool                    lockIfMessageWanted(int32_t msgType);
+};
+
+}
+
+#endif
diff --git a/services/camera/libcameraservice/CameraHardwareInterface.h b/services/camera/libcameraservice/CameraHardwareInterface.h
index 87a0802..05ac9fa 100644
--- a/services/camera/libcameraservice/CameraHardwareInterface.h
+++ b/services/camera/libcameraservice/CameraHardwareInterface.h
@@ -569,7 +569,7 @@
         int rc;
         ANativeWindow *a = anw(w);
         ANativeWindowBuffer* anb;
-        rc = a->dequeueBuffer(a, &anb);
+        rc = native_window_dequeue_buffer_and_wait(a, &anb);
         if (!rc) {
             *buffer = &anb->handle;
             *stride = anb->stride;
@@ -587,8 +587,7 @@
                       buffer_handle_t* buffer)
     {
         ANativeWindow *a = anw(w);
-        return a->lockBuffer(a,
-                  container_of(buffer, ANativeWindowBuffer, handle));
+        return 0;
     }
 
     static int __enqueue_buffer(struct preview_stream_ops* w,
@@ -596,7 +595,7 @@
     {
         ANativeWindow *a = anw(w);
         return a->queueBuffer(a,
-                  container_of(buffer, ANativeWindowBuffer, handle));
+                  container_of(buffer, ANativeWindowBuffer, handle), -1);
     }
 
     static int __cancel_buffer(struct preview_stream_ops* w,
@@ -604,7 +603,7 @@
     {
         ANativeWindow *a = anw(w);
         return a->cancelBuffer(a,
-                  container_of(buffer, ANativeWindowBuffer, handle));
+                  container_of(buffer, ANativeWindowBuffer, handle), -1);
     }
 
     static int __set_buffer_count(struct preview_stream_ops* w, int count)
diff --git a/services/camera/libcameraservice/CameraHardwareStub.cpp b/services/camera/libcameraservice/CameraHardwareStub.cpp
deleted file mode 100644
index cdfb2f5..0000000
--- a/services/camera/libcameraservice/CameraHardwareStub.cpp
+++ /dev/null
@@ -1,410 +0,0 @@
-/*
-**
-** Copyright 2008, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-**     http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
-
-#define LOG_TAG "CameraHardwareStub"
-#include <utils/Log.h>
-
-#include "CameraHardwareStub.h"
-#include <utils/threads.h>
-#include <fcntl.h>
-#include <sys/mman.h>
-
-#include "CannedJpeg.h"
-
-namespace android {
-
-CameraHardwareStub::CameraHardwareStub()
-                  : mParameters(),
-                    mPreviewHeap(0),
-                    mRawHeap(0),
-                    mFakeCamera(0),
-                    mPreviewFrameSize(0),
-                    mNotifyCb(0),
-                    mDataCb(0),
-                    mDataCbTimestamp(0),
-                    mCallbackCookie(0),
-                    mMsgEnabled(0),
-                    mCurrentPreviewFrame(0)
-{
-    initDefaultParameters();
-}
-
-void CameraHardwareStub::initDefaultParameters()
-{
-    CameraParameters p;
-
-    p.set(CameraParameters::KEY_SUPPORTED_PREVIEW_SIZES, "320x240");
-    p.setPreviewSize(320, 240);
-    p.setPreviewFrameRate(15);
-    p.setPreviewFormat(CameraParameters::PIXEL_FORMAT_YUV420SP);
-
-    p.set(CameraParameters::KEY_SUPPORTED_PICTURE_SIZES, "320x240");
-    p.setPictureSize(320, 240);
-    p.setPictureFormat(CameraParameters::PIXEL_FORMAT_JPEG);
-
-    if (setParameters(p) != NO_ERROR) {
-        ALOGE("Failed to set default parameters?!");
-    }
-}
-
-void CameraHardwareStub::initHeapLocked()
-{
-    // Create raw heap.
-    int picture_width, picture_height;
-    mParameters.getPictureSize(&picture_width, &picture_height);
-    mRawHeap = new MemoryHeapBase(picture_width * picture_height * 3 / 2);
-
-    int preview_width, preview_height;
-    mParameters.getPreviewSize(&preview_width, &preview_height);
-    ALOGD("initHeapLocked: preview size=%dx%d", preview_width, preview_height);
-
-    // Note that we enforce yuv420sp in setParameters().
-    int how_big = preview_width * preview_height * 3 / 2;
-
-    // If we are being reinitialized to the same size as before, no
-    // work needs to be done.
-    if (how_big == mPreviewFrameSize)
-        return;
-
-    mPreviewFrameSize = how_big;
-
-    // Make a new mmap'ed heap that can be shared across processes.
-    // use code below to test with pmem
-    mPreviewHeap = new MemoryHeapBase(mPreviewFrameSize * kBufferCount);
-    // Make an IMemory for each frame so that we can reuse them in callbacks.
-    for (int i = 0; i < kBufferCount; i++) {
-        mBuffers[i] = new MemoryBase(mPreviewHeap, i * mPreviewFrameSize, mPreviewFrameSize);
-    }
-
-    // Recreate the fake camera to reflect the current size.
-    delete mFakeCamera;
-    mFakeCamera = new FakeCamera(preview_width, preview_height);
-}
-
-CameraHardwareStub::~CameraHardwareStub()
-{
-    delete mFakeCamera;
-    mFakeCamera = 0; // paranoia
-}
-
-status_t CameraHardwareStub::setPreviewWindow(const sp<ANativeWindow>& buf)
-{
-    return NO_ERROR;
-}
-
-sp<IMemoryHeap> CameraHardwareStub::getRawHeap() const
-{
-    return mRawHeap;
-}
-
-void CameraHardwareStub::setCallbacks(notify_callback notify_cb,
-                                      data_callback data_cb,
-                                      data_callback_timestamp data_cb_timestamp,
-                                      void* user)
-{
-    Mutex::Autolock lock(mLock);
-    mNotifyCb = notify_cb;
-    mDataCb = data_cb;
-    mDataCbTimestamp = data_cb_timestamp;
-    mCallbackCookie = user;
-}
-
-void CameraHardwareStub::enableMsgType(int32_t msgType)
-{
-    Mutex::Autolock lock(mLock);
-    mMsgEnabled |= msgType;
-}
-
-void CameraHardwareStub::disableMsgType(int32_t msgType)
-{
-    Mutex::Autolock lock(mLock);
-    mMsgEnabled &= ~msgType;
-}
-
-bool CameraHardwareStub::msgTypeEnabled(int32_t msgType)
-{
-    Mutex::Autolock lock(mLock);
-    return (mMsgEnabled & msgType);
-}
-
-// ---------------------------------------------------------------------------
-
-int CameraHardwareStub::previewThread()
-{
-    mLock.lock();
-        // the attributes below can change under our feet...
-
-        int previewFrameRate = mParameters.getPreviewFrameRate();
-
-        // Find the offset within the heap of the current buffer.
-        ssize_t offset = mCurrentPreviewFrame * mPreviewFrameSize;
-
-        sp<MemoryHeapBase> heap = mPreviewHeap;
-
-        // this assumes the internal state of fake camera doesn't change
-        // (or is thread safe)
-        FakeCamera* fakeCamera = mFakeCamera;
-
-        sp<MemoryBase> buffer = mBuffers[mCurrentPreviewFrame];
-
-    mLock.unlock();
-
-    // TODO: here check all the conditions that could go wrong
-    if (buffer != 0) {
-        // Calculate how long to wait between frames.
-        int delay = (int)(1000000.0f / float(previewFrameRate));
-
-        // This is always valid, even if the client died -- the memory
-        // is still mapped in our process.
-        void *base = heap->base();
-
-        // Fill the current frame with the fake camera.
-        uint8_t *frame = ((uint8_t *)base) + offset;
-        fakeCamera->getNextFrameAsYuv420(frame);
-
-        //ALOGV("previewThread: generated frame to buffer %d", mCurrentPreviewFrame);
-
-        // Notify the client of a new frame.
-        if (mMsgEnabled & CAMERA_MSG_PREVIEW_FRAME)
-            mDataCb(CAMERA_MSG_PREVIEW_FRAME, buffer, NULL, mCallbackCookie);
-
-        // Advance the buffer pointer.
-        mCurrentPreviewFrame = (mCurrentPreviewFrame + 1) % kBufferCount;
-
-        // Wait for it...
-        usleep(delay);
-    }
-
-    return NO_ERROR;
-}
-
-status_t CameraHardwareStub::startPreview()
-{
-    Mutex::Autolock lock(mLock);
-    if (mPreviewThread != 0) {
-        // already running
-        return INVALID_OPERATION;
-    }
-    mPreviewThread = new PreviewThread(this);
-    return NO_ERROR;
-}
-
-void CameraHardwareStub::stopPreview()
-{
-    sp<PreviewThread> previewThread;
-
-    { // scope for the lock
-        Mutex::Autolock lock(mLock);
-        previewThread = mPreviewThread;
-    }
-
-    // don't hold the lock while waiting for the thread to quit
-    if (previewThread != 0) {
-        previewThread->requestExitAndWait();
-    }
-
-    Mutex::Autolock lock(mLock);
-    mPreviewThread.clear();
-}
-
-bool CameraHardwareStub::previewEnabled() {
-    return mPreviewThread != 0;
-}
-
-status_t CameraHardwareStub::startRecording()
-{
-    return UNKNOWN_ERROR;
-}
-
-void CameraHardwareStub::stopRecording()
-{
-}
-
-bool CameraHardwareStub::recordingEnabled()
-{
-    return false;
-}
-
-void CameraHardwareStub::releaseRecordingFrame(const sp<IMemory>& mem)
-{
-}
-
-// ---------------------------------------------------------------------------
-
-int CameraHardwareStub::beginAutoFocusThread(void *cookie)
-{
-    CameraHardwareStub *c = (CameraHardwareStub *)cookie;
-    return c->autoFocusThread();
-}
-
-int CameraHardwareStub::autoFocusThread()
-{
-    if (mMsgEnabled & CAMERA_MSG_FOCUS)
-        mNotifyCb(CAMERA_MSG_FOCUS, true, 0, mCallbackCookie);
-    return NO_ERROR;
-}
-
-status_t CameraHardwareStub::autoFocus()
-{
-    Mutex::Autolock lock(mLock);
-    if (createThread(beginAutoFocusThread, this) == false)
-        return UNKNOWN_ERROR;
-    return NO_ERROR;
-}
-
-status_t CameraHardwareStub::cancelAutoFocus()
-{
-    return NO_ERROR;
-}
-
-/*static*/ int CameraHardwareStub::beginPictureThread(void *cookie)
-{
-    CameraHardwareStub *c = (CameraHardwareStub *)cookie;
-    return c->pictureThread();
-}
-
-int CameraHardwareStub::pictureThread()
-{
-    if (mMsgEnabled & CAMERA_MSG_SHUTTER)
-        mNotifyCb(CAMERA_MSG_SHUTTER, 0, 0, mCallbackCookie);
-
-    if (mMsgEnabled & CAMERA_MSG_RAW_IMAGE) {
-        //FIXME: use a canned YUV image!
-        // In the meantime just make another fake camera picture.
-        int w, h;
-        mParameters.getPictureSize(&w, &h);
-        sp<MemoryBase> mem = new MemoryBase(mRawHeap, 0, w * h * 3 / 2);
-        FakeCamera cam(w, h);
-        cam.getNextFrameAsYuv420((uint8_t *)mRawHeap->base());
-        mDataCb(CAMERA_MSG_RAW_IMAGE, mem, NULL, mCallbackCookie);
-    }
-
-    if (mMsgEnabled & CAMERA_MSG_COMPRESSED_IMAGE) {
-        sp<MemoryHeapBase> heap = new MemoryHeapBase(kCannedJpegSize);
-        sp<MemoryBase> mem = new MemoryBase(heap, 0, kCannedJpegSize);
-        memcpy(heap->base(), kCannedJpeg, kCannedJpegSize);
-        mDataCb(CAMERA_MSG_COMPRESSED_IMAGE, mem, NULL, mCallbackCookie);
-    }
-    return NO_ERROR;
-}
-
-status_t CameraHardwareStub::takePicture()
-{
-    stopPreview();
-    if (createThread(beginPictureThread, this) == false)
-        return UNKNOWN_ERROR;
-    return NO_ERROR;
-}
-
-status_t CameraHardwareStub::cancelPicture()
-{
-    return NO_ERROR;
-}
-
-status_t CameraHardwareStub::dump(int fd, const Vector<String16>& args) const
-{
-    const size_t SIZE = 256;
-    char buffer[SIZE];
-    String8 result;
-    AutoMutex lock(&mLock);
-    if (mFakeCamera != 0) {
-        mFakeCamera->dump(fd);
-        mParameters.dump(fd, args);
-        snprintf(buffer, 255, " preview frame(%d), size (%d), running(%s)\n", mCurrentPreviewFrame, mPreviewFrameSize, mPreviewRunning?"true": "false");
-        result.append(buffer);
-    } else {
-        result.append("No camera client yet.\n");
-    }
-    write(fd, result.string(), result.size());
-    return NO_ERROR;
-}
-
-status_t CameraHardwareStub::setParameters(const CameraParameters& params)
-{
-    Mutex::Autolock lock(mLock);
-    // XXX verify params
-
-    if (strcmp(params.getPreviewFormat(),
-        CameraParameters::PIXEL_FORMAT_YUV420SP) != 0) {
-        ALOGE("Only yuv420sp preview is supported");
-        return -1;
-    }
-
-    if (strcmp(params.getPictureFormat(),
-        CameraParameters::PIXEL_FORMAT_JPEG) != 0) {
-        ALOGE("Only jpeg still pictures are supported");
-        return -1;
-    }
-
-    int w, h;
-    params.getPictureSize(&w, &h);
-    if (w != kCannedJpegWidth && h != kCannedJpegHeight) {
-        ALOGE("Still picture size must be size of canned JPEG (%dx%d)",
-             kCannedJpegWidth, kCannedJpegHeight);
-        return -1;
-    }
-
-    mParameters = params;
-    initHeapLocked();
-
-    return NO_ERROR;
-}
-
-CameraParameters CameraHardwareStub::getParameters() const
-{
-    Mutex::Autolock lock(mLock);
-    return mParameters;
-}
-
-status_t CameraHardwareStub::sendCommand(int32_t command, int32_t arg1,
-                                         int32_t arg2)
-{
-    return BAD_VALUE;
-}
-
-void CameraHardwareStub::release()
-{
-}
-
-sp<CameraHardwareInterface> CameraHardwareStub::createInstance()
-{
-    return new CameraHardwareStub();
-}
-
-static CameraInfo sCameraInfo[] = {
-    {
-        CAMERA_FACING_BACK,
-        90,  /* orientation */
-    }
-};
-
-extern "C" int HAL_getNumberOfCameras()
-{
-    return sizeof(sCameraInfo) / sizeof(sCameraInfo[0]);
-}
-
-extern "C" void HAL_getCameraInfo(int cameraId, struct CameraInfo* cameraInfo)
-{
-    memcpy(cameraInfo, &sCameraInfo[cameraId], sizeof(CameraInfo));
-}
-
-extern "C" sp<CameraHardwareInterface> HAL_openCameraHardware(int cameraId)
-{
-    return CameraHardwareStub::createInstance();
-}
-
-}; // namespace android
diff --git a/services/camera/libcameraservice/CameraHardwareStub.h b/services/camera/libcameraservice/CameraHardwareStub.h
deleted file mode 100644
index c6d8756..0000000
--- a/services/camera/libcameraservice/CameraHardwareStub.h
+++ /dev/null
@@ -1,126 +0,0 @@
-/*
-**
-** Copyright 2008, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-**     http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
-
-#ifndef ANDROID_HARDWARE_CAMERA_HARDWARE_STUB_H
-#define ANDROID_HARDWARE_CAMERA_HARDWARE_STUB_H
-
-#include "FakeCamera.h"
-#include <utils/threads.h>
-#include <camera/CameraHardwareInterface.h>
-#include <binder/MemoryBase.h>
-#include <binder/MemoryHeapBase.h>
-#include <utils/threads.h>
-
-namespace android {
-
-class CameraHardwareStub : public CameraHardwareInterface {
-public:
-    virtual status_t setPreviewWindow(const sp<ANativeWindow>& buf);
-    virtual sp<IMemoryHeap> getRawHeap() const;
-
-    virtual void        setCallbacks(notify_callback notify_cb,
-                                     data_callback data_cb,
-                                     data_callback_timestamp data_cb_timestamp,
-                                     void* user);
-
-    virtual void        enableMsgType(int32_t msgType);
-    virtual void        disableMsgType(int32_t msgType);
-    virtual bool        msgTypeEnabled(int32_t msgType);
-
-    virtual status_t    startPreview();
-    virtual void        stopPreview();
-    virtual bool        previewEnabled();
-
-    virtual status_t    startRecording();
-    virtual void        stopRecording();
-    virtual bool        recordingEnabled();
-    virtual void        releaseRecordingFrame(const sp<IMemory>& mem);
-
-    virtual status_t    autoFocus();
-    virtual status_t    cancelAutoFocus();
-    virtual status_t    takePicture();
-    virtual status_t    cancelPicture();
-    virtual status_t    dump(int fd, const Vector<String16>& args) const;
-    virtual status_t    setParameters(const CameraParameters& params);
-    virtual CameraParameters  getParameters() const;
-    virtual status_t    sendCommand(int32_t command, int32_t arg1,
-                                    int32_t arg2);
-    virtual void release();
-
-    static sp<CameraHardwareInterface> createInstance();
-
-private:
-                        CameraHardwareStub();
-    virtual             ~CameraHardwareStub();
-
-    static const int kBufferCount = 4;
-
-    class PreviewThread : public Thread {
-        CameraHardwareStub* mHardware;
-    public:
-        PreviewThread(CameraHardwareStub* hw) :
-                Thread(false), mHardware(hw) { }
-        virtual void onFirstRef() {
-            run("CameraPreviewThread", PRIORITY_URGENT_DISPLAY);
-        }
-        virtual bool threadLoop() {
-            mHardware->previewThread();
-            // loop until we need to quit
-            return true;
-        }
-    };
-
-    void initDefaultParameters();
-    void initHeapLocked();
-
-    int previewThread();
-
-    static int beginAutoFocusThread(void *cookie);
-    int autoFocusThread();
-
-    static int beginPictureThread(void *cookie);
-    int pictureThread();
-
-    mutable Mutex       mLock;
-
-    CameraParameters    mParameters;
-
-    sp<MemoryHeapBase>  mPreviewHeap;
-    sp<MemoryHeapBase>  mRawHeap;
-    sp<MemoryBase>      mBuffers[kBufferCount];
-
-    FakeCamera          *mFakeCamera;
-    bool                mPreviewRunning;
-    int                 mPreviewFrameSize;
-
-    // protected by mLock
-    sp<PreviewThread>   mPreviewThread;
-
-    notify_callback    mNotifyCb;
-    data_callback      mDataCb;
-    data_callback_timestamp mDataCbTimestamp;
-    void               *mCallbackCookie;
-
-    int32_t             mMsgEnabled;
-
-    // only used from PreviewThread
-    int                 mCurrentPreviewFrame;
-};
-
-}; // namespace android
-
-#endif
diff --git a/services/camera/libcameraservice/CameraService.cpp b/services/camera/libcameraservice/CameraService.cpp
index bf07f8b..912ee4a 100644
--- a/services/camera/libcameraservice/CameraService.cpp
+++ b/services/camera/libcameraservice/CameraService.cpp
@@ -38,14 +38,15 @@
 #include <utils/String16.h>
 
 #include "CameraService.h"
-#include "CameraHardwareInterface.h"
+#include "CameraClient.h"
+#include "Camera2Client.h"
 
 namespace android {
 
 // ----------------------------------------------------------------------------
 // Logging support -- this is for debugging only
 // Use "adb shell dumpsys media.camera -v 1" to change it.
-static volatile int32_t gLogLevel = 0;
+volatile int32_t gLogLevel = 0;
 
 #define LOG1(...) ALOGD_IF(gLogLevel >= 1, __VA_ARGS__);
 #define LOG2(...) ALOGD_IF(gLogLevel >= 2, __VA_ARGS__);
@@ -133,7 +134,6 @@
 sp<ICamera> CameraService::connect(
         const sp<ICameraClient>& cameraClient, int cameraId) {
     int callingPid = getCallingPid();
-    sp<CameraHardwareInterface> hardware = NULL;
 
     LOG1("CameraService::connect E (pid %d, id %d)", callingPid, cameraId);
 
@@ -186,16 +186,31 @@
         return NULL;
     }
 
-    char camera_device_name[10];
-    snprintf(camera_device_name, sizeof(camera_device_name), "%d", cameraId);
+    int deviceVersion;
+    if (mModule->common.module_api_version == CAMERA_MODULE_API_VERSION_2_0) {
+        deviceVersion = info.device_version;
+    } else {
+        deviceVersion = CAMERA_DEVICE_API_VERSION_1_0;
+    }
 
-    hardware = new CameraHardwareInterface(camera_device_name);
-    if (hardware->initialize(&mModule->common) != OK) {
-        hardware.clear();
+    switch(deviceVersion) {
+      case CAMERA_DEVICE_API_VERSION_1_0:
+        client = new CameraClient(this, cameraClient, cameraId,
+                info.facing, callingPid);
+        break;
+      case CAMERA_DEVICE_API_VERSION_2_0:
+        client = new Camera2Client(this, cameraClient, cameraId,
+                info.facing, callingPid);
+        break;
+      default:
+        ALOGE("Unknown camera device HAL version: %d", deviceVersion);
         return NULL;
     }
 
-    client = new Client(this, cameraClient, hardware, cameraId, info.facing, callingPid);
+    if (client->initialize(mModule) != OK) {
+        return NULL;
+    }
+
     mClient[cameraId] = client;
     LOG1("CameraService::connect X (id %d)", cameraId);
     return client;
@@ -335,34 +350,17 @@
 
 CameraService::Client::Client(const sp<CameraService>& cameraService,
         const sp<ICameraClient>& cameraClient,
-        const sp<CameraHardwareInterface>& hardware,
         int cameraId, int cameraFacing, int clientPid) {
     int callingPid = getCallingPid();
     LOG1("Client::Client E (pid %d, id %d)", callingPid, cameraId);
 
     mCameraService = cameraService;
     mCameraClient = cameraClient;
-    mHardware = hardware;
     mCameraId = cameraId;
     mCameraFacing = cameraFacing;
     mClientPid = clientPid;
-    mMsgEnabled = 0;
-    mSurface = 0;
-    mPreviewWindow = 0;
     mDestructionStarted = false;
-    mHardware->setCallbacks(notifyCallback,
-                            dataCallback,
-                            dataCallbackTimestamp,
-                            (void *)cameraId);
 
-    // Enable zoom, error, focus, and metadata messages by default
-    enableMsgType(CAMERA_MSG_ERROR | CAMERA_MSG_ZOOM | CAMERA_MSG_FOCUS |
-                  CAMERA_MSG_PREVIEW_METADATA | CAMERA_MSG_FOCUS_MOVE);
-
-    // Callback is disabled by default
-    mPreviewCallbackFlag = CAMERA_FRAME_CALLBACK_FLAG_NOOP;
-    mOrientation = getOrientation(0, mCameraFacing == CAMERA_FACING_FRONT);
-    mPlayShutterSound = true;
     cameraService->setCameraBusy(cameraId);
     cameraService->loadSound();
     LOG1("Client::Client X (pid %d, id %d)", callingPid, cameraId);
@@ -370,582 +368,7 @@
 
 // tear down the client
 CameraService::Client::~Client() {
-    // this lock should never be NULL
-    Mutex* lock = mCameraService->getClientLockById(mCameraId);
-    lock->lock();
-    mDestructionStarted = true;
-    // client will not be accessed from callback. should unlock to prevent dead-lock in disconnect
-    lock->unlock();
-    int callingPid = getCallingPid();
-    LOG1("Client::~Client E (pid %d, this %p)", callingPid, this);
-
-    // set mClientPid to let disconnet() tear down the hardware
-    mClientPid = callingPid;
-    disconnect();
     mCameraService->releaseSound();
-    LOG1("Client::~Client X (pid %d, this %p)", callingPid, this);
-}
-
-// ----------------------------------------------------------------------------
-
-status_t CameraService::Client::checkPid() const {
-    int callingPid = getCallingPid();
-    if (callingPid == mClientPid) return NO_ERROR;
-
-    ALOGW("attempt to use a locked camera from a different process"
-         " (old pid %d, new pid %d)", mClientPid, callingPid);
-    return EBUSY;
-}
-
-status_t CameraService::Client::checkPidAndHardware() const {
-    status_t result = checkPid();
-    if (result != NO_ERROR) return result;
-    if (mHardware == 0) {
-        ALOGE("attempt to use a camera after disconnect() (pid %d)", getCallingPid());
-        return INVALID_OPERATION;
-    }
-    return NO_ERROR;
-}
-
-status_t CameraService::Client::lock() {
-    int callingPid = getCallingPid();
-    LOG1("lock (pid %d)", callingPid);
-    Mutex::Autolock ilock(mICameraLock);
-    Mutex::Autolock lock(mLock);
-
-    // lock camera to this client if the the camera is unlocked
-    if (mClientPid == 0) {
-        mClientPid = callingPid;
-        return NO_ERROR;
-    }
-
-    // returns NO_ERROR if the client already owns the camera, EBUSY otherwise
-    return checkPid();
-}
-
-status_t CameraService::Client::unlock() {
-    int callingPid = getCallingPid();
-    LOG1("unlock (pid %d)", callingPid);
-    Mutex::Autolock iLock(mICameraLock);
-    Mutex::Autolock lock(mLock);
-
-    // allow anyone to use camera (after they lock the camera)
-    status_t result = checkPid();
-    if (result == NO_ERROR) {
-        if (mHardware->recordingEnabled()) {
-            ALOGE("Not allowed to unlock camera during recording.");
-            return INVALID_OPERATION;
-        }
-        mClientPid = 0;
-        LOG1("clear mCameraClient (pid %d)", callingPid);
-        // we need to remove the reference to ICameraClient so that when the app
-        // goes away, the reference count goes to 0.
-        mCameraClient.clear();
-    }
-    return result;
-}
-
-// connect a new client to the camera
-status_t CameraService::Client::connect(const sp<ICameraClient>& client) {
-    int callingPid = getCallingPid();
-    LOG1("connect E (pid %d)", callingPid);
-    Mutex::Autolock iLock(mICameraLock);
-    Mutex::Autolock lock(mLock);
-
-    if (mClientPid != 0 && checkPid() != NO_ERROR) {
-        ALOGW("Tried to connect to a locked camera (old pid %d, new pid %d)",
-                mClientPid, callingPid);
-        return EBUSY;
-    }
-
-    if (mCameraClient != 0 && (client->asBinder() == mCameraClient->asBinder())) {
-        LOG1("Connect to the same client");
-        return NO_ERROR;
-    }
-
-    mPreviewCallbackFlag = CAMERA_FRAME_CALLBACK_FLAG_NOOP;
-    mClientPid = callingPid;
-    mCameraClient = client;
-
-    LOG1("connect X (pid %d)", callingPid);
-    return NO_ERROR;
-}
-
-static void disconnectWindow(const sp<ANativeWindow>& window) {
-    if (window != 0) {
-        status_t result = native_window_api_disconnect(window.get(),
-                NATIVE_WINDOW_API_CAMERA);
-        if (result != NO_ERROR) {
-            ALOGW("native_window_api_disconnect failed: %s (%d)", strerror(-result),
-                    result);
-        }
-    }
-}
-
-void CameraService::Client::disconnect() {
-    int callingPid = getCallingPid();
-    LOG1("disconnect E (pid %d)", callingPid);
-    Mutex::Autolock iLock(mICameraLock);
-    Mutex::Autolock lock(mLock);
-
-    if (checkPid() != NO_ERROR) {
-        ALOGW("different client - don't disconnect");
-        return;
-    }
-
-    if (mClientPid <= 0) {
-        LOG1("camera is unlocked (mClientPid = %d), don't tear down hardware", mClientPid);
-        return;
-    }
-
-    // Make sure disconnect() is done once and once only, whether it is called
-    // from the user directly, or called by the destructor.
-    if (mHardware == 0) return;
-
-    LOG1("hardware teardown");
-    // Before destroying mHardware, we must make sure it's in the
-    // idle state.
-    // Turn off all messages.
-    disableMsgType(CAMERA_MSG_ALL_MSGS);
-    mHardware->stopPreview();
-    mHardware->cancelPicture();
-    // Release the hardware resources.
-    mHardware->release();
-
-    // Release the held ANativeWindow resources.
-    if (mPreviewWindow != 0) {
-        disconnectWindow(mPreviewWindow);
-        mPreviewWindow = 0;
-        mHardware->setPreviewWindow(mPreviewWindow);
-    }
-    mHardware.clear();
-
-    mCameraService->removeClient(mCameraClient);
-    mCameraService->setCameraFree(mCameraId);
-
-    LOG1("disconnect X (pid %d)", callingPid);
-}
-
-// ----------------------------------------------------------------------------
-
-status_t CameraService::Client::setPreviewWindow(const sp<IBinder>& binder,
-        const sp<ANativeWindow>& window) {
-    Mutex::Autolock iLock(mICameraLock);
-    Mutex::Autolock lock(mLock);
-    status_t result = checkPidAndHardware();
-    if (result != NO_ERROR) return result;
-
-    // return if no change in surface.
-    if (binder == mSurface) {
-        return NO_ERROR;
-    }
-
-    if (window != 0) {
-        result = native_window_api_connect(window.get(), NATIVE_WINDOW_API_CAMERA);
-        if (result != NO_ERROR) {
-            ALOGE("native_window_api_connect failed: %s (%d)", strerror(-result),
-                    result);
-            return result;
-        }
-    }
-
-    // If preview has been already started, register preview buffers now.
-    if (mHardware->previewEnabled()) {
-        if (window != 0) {
-            native_window_set_scaling_mode(window.get(),
-                    NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW);
-            native_window_set_buffers_transform(window.get(), mOrientation);
-            result = mHardware->setPreviewWindow(window);
-        }
-    }
-
-    if (result == NO_ERROR) {
-        // Everything has succeeded.  Disconnect the old window and remember the
-        // new window.
-        disconnectWindow(mPreviewWindow);
-        mSurface = binder;
-        mPreviewWindow = window;
-    } else {
-        // Something went wrong after we connected to the new window, so
-        // disconnect here.
-        disconnectWindow(window);
-    }
-
-    return result;
-}
-
-// set the Surface that the preview will use
-status_t CameraService::Client::setPreviewDisplay(const sp<Surface>& surface) {
-    LOG1("setPreviewDisplay(%p) (pid %d)", surface.get(), getCallingPid());
-
-    sp<IBinder> binder(surface != 0 ? surface->asBinder() : 0);
-    sp<ANativeWindow> window(surface);
-    return setPreviewWindow(binder, window);
-}
-
-// set the SurfaceTexture that the preview will use
-status_t CameraService::Client::setPreviewTexture(
-        const sp<ISurfaceTexture>& surfaceTexture) {
-    LOG1("setPreviewTexture(%p) (pid %d)", surfaceTexture.get(),
-            getCallingPid());
-
-    sp<IBinder> binder;
-    sp<ANativeWindow> window;
-    if (surfaceTexture != 0) {
-        binder = surfaceTexture->asBinder();
-        window = new SurfaceTextureClient(surfaceTexture);
-    }
-    return setPreviewWindow(binder, window);
-}
-
-// set the preview callback flag to affect how the received frames from
-// preview are handled.
-void CameraService::Client::setPreviewCallbackFlag(int callback_flag) {
-    LOG1("setPreviewCallbackFlag(%d) (pid %d)", callback_flag, getCallingPid());
-    Mutex::Autolock iLock(mICameraLock);
-    Mutex::Autolock lock(mLock);
-    if (checkPidAndHardware() != NO_ERROR) return;
-
-    mPreviewCallbackFlag = callback_flag;
-    if (mPreviewCallbackFlag & CAMERA_FRAME_CALLBACK_FLAG_ENABLE_MASK) {
-        enableMsgType(CAMERA_MSG_PREVIEW_FRAME);
-    } else {
-        disableMsgType(CAMERA_MSG_PREVIEW_FRAME);
-    }
-}
-
-// start preview mode
-status_t CameraService::Client::startPreview() {
-    LOG1("startPreview (pid %d)", getCallingPid());
-    return startCameraMode(CAMERA_PREVIEW_MODE);
-}
-
-// start recording mode
-status_t CameraService::Client::startRecording() {
-    LOG1("startRecording (pid %d)", getCallingPid());
-    return startCameraMode(CAMERA_RECORDING_MODE);
-}
-
-// start preview or recording
-status_t CameraService::Client::startCameraMode(camera_mode mode) {
-    LOG1("startCameraMode(%d)", mode);
-    Mutex::Autolock iLock(mICameraLock);
-    Mutex::Autolock lock(mLock);
-    status_t result = checkPidAndHardware();
-    if (result != NO_ERROR) return result;
-
-    switch(mode) {
-        case CAMERA_PREVIEW_MODE:
-            if (mSurface == 0 && mPreviewWindow == 0) {
-                LOG1("mSurface is not set yet.");
-                // still able to start preview in this case.
-            }
-            return startPreviewMode();
-        case CAMERA_RECORDING_MODE:
-            if (mSurface == 0 && mPreviewWindow == 0) {
-                ALOGE("mSurface or mPreviewWindow must be set before startRecordingMode.");
-                return INVALID_OPERATION;
-            }
-            return startRecordingMode();
-        default:
-            return UNKNOWN_ERROR;
-    }
-}
-
-status_t CameraService::Client::startPreviewMode() {
-    LOG1("startPreviewMode");
-    status_t result = NO_ERROR;
-
-    // if preview has been enabled, nothing needs to be done
-    if (mHardware->previewEnabled()) {
-        return NO_ERROR;
-    }
-
-    if (mPreviewWindow != 0) {
-        native_window_set_scaling_mode(mPreviewWindow.get(),
-                NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW);
-        native_window_set_buffers_transform(mPreviewWindow.get(),
-                mOrientation);
-    }
-    mHardware->setPreviewWindow(mPreviewWindow);
-    result = mHardware->startPreview();
-
-    return result;
-}
-
-status_t CameraService::Client::startRecordingMode() {
-    LOG1("startRecordingMode");
-    status_t result = NO_ERROR;
-
-    // if recording has been enabled, nothing needs to be done
-    if (mHardware->recordingEnabled()) {
-        return NO_ERROR;
-    }
-
-    // if preview has not been started, start preview first
-    if (!mHardware->previewEnabled()) {
-        result = startPreviewMode();
-        if (result != NO_ERROR) {
-            return result;
-        }
-    }
-
-    // start recording mode
-    enableMsgType(CAMERA_MSG_VIDEO_FRAME);
-    mCameraService->playSound(SOUND_RECORDING);
-    result = mHardware->startRecording();
-    if (result != NO_ERROR) {
-        ALOGE("mHardware->startRecording() failed with status %d", result);
-    }
-    return result;
-}
-
-// stop preview mode
-void CameraService::Client::stopPreview() {
-    LOG1("stopPreview (pid %d)", getCallingPid());
-    Mutex::Autolock iLock(mICameraLock);
-    Mutex::Autolock lock(mLock);
-    if (checkPidAndHardware() != NO_ERROR) return;
-
-
-    disableMsgType(CAMERA_MSG_PREVIEW_FRAME);
-    mHardware->stopPreview();
-
-    mPreviewBuffer.clear();
-}
-
-// stop recording mode
-void CameraService::Client::stopRecording() {
-    LOG1("stopRecording (pid %d)", getCallingPid());
-    Mutex::Autolock iLock(mICameraLock);
-    Mutex::Autolock lock(mLock);
-    if (checkPidAndHardware() != NO_ERROR) return;
-
-    mCameraService->playSound(SOUND_RECORDING);
-    disableMsgType(CAMERA_MSG_VIDEO_FRAME);
-    mHardware->stopRecording();
-
-    mPreviewBuffer.clear();
-}
-
-// release a recording frame
-void CameraService::Client::releaseRecordingFrame(const sp<IMemory>& mem) {
-    Mutex::Autolock iLock(mICameraLock);
-    Mutex::Autolock lock(mLock);
-    if (checkPidAndHardware() != NO_ERROR) return;
-    mHardware->releaseRecordingFrame(mem);
-}
-
-status_t CameraService::Client::storeMetaDataInBuffers(bool enabled)
-{
-    LOG1("storeMetaDataInBuffers: %s", enabled? "true": "false");
-    Mutex::Autolock iLock(mICameraLock);
-    Mutex::Autolock lock(mLock);
-    if (checkPidAndHardware() != NO_ERROR) {
-        return UNKNOWN_ERROR;
-    }
-    return mHardware->storeMetaDataInBuffers(enabled);
-}
-
-bool CameraService::Client::previewEnabled() {
-    LOG1("previewEnabled (pid %d)", getCallingPid());
-
-    Mutex::Autolock iLock(mICameraLock);
-    Mutex::Autolock lock(mLock);
-    if (checkPidAndHardware() != NO_ERROR) return false;
-    return mHardware->previewEnabled();
-}
-
-bool CameraService::Client::recordingEnabled() {
-    LOG1("recordingEnabled (pid %d)", getCallingPid());
-
-    Mutex::Autolock iLock(mICameraLock);
-    Mutex::Autolock lock(mLock);
-    if (checkPidAndHardware() != NO_ERROR) return false;
-    return mHardware->recordingEnabled();
-}
-
-status_t CameraService::Client::autoFocus() {
-    LOG1("autoFocus (pid %d)", getCallingPid());
-
-    Mutex::Autolock iLock(mICameraLock);
-    Mutex::Autolock lock(mLock);
-    status_t result = checkPidAndHardware();
-    if (result != NO_ERROR) return result;
-
-    return mHardware->autoFocus();
-}
-
-status_t CameraService::Client::cancelAutoFocus() {
-    LOG1("cancelAutoFocus (pid %d)", getCallingPid());
-
-    Mutex::Autolock iLock(mICameraLock);
-    Mutex::Autolock lock(mLock);
-    status_t result = checkPidAndHardware();
-    if (result != NO_ERROR) return result;
-
-    return mHardware->cancelAutoFocus();
-}
-
-// take a picture - image is returned in callback
-status_t CameraService::Client::takePicture(int msgType) {
-    LOG1("takePicture (pid %d): 0x%x", getCallingPid(), msgType);
-
-    Mutex::Autolock iLock(mICameraLock);
-    int picMsgType = 0;
-    { // scope for lock
-        Mutex::Autolock lock(mLock);
-        status_t result = checkPidAndHardware();
-        if (result != NO_ERROR) return result;
-
-        if ((msgType & CAMERA_MSG_RAW_IMAGE) &&
-                (msgType & CAMERA_MSG_RAW_IMAGE_NOTIFY)) {
-            ALOGE("CAMERA_MSG_RAW_IMAGE and CAMERA_MSG_RAW_IMAGE_NOTIFY"
-                    " cannot be both enabled");
-            return BAD_VALUE;
-        }
-
-        // We only accept picture related message types
-        // and ignore other types of messages for takePicture().
-        picMsgType = msgType
-                & (CAMERA_MSG_SHUTTER |
-                        CAMERA_MSG_POSTVIEW_FRAME |
-                        CAMERA_MSG_RAW_IMAGE |
-                        CAMERA_MSG_RAW_IMAGE_NOTIFY |
-                        CAMERA_MSG_COMPRESSED_IMAGE);
-
-    }
-    enableMsgType(picMsgType);
-
-    return mHardware->takePicture();
-}
-
-// set preview/capture parameters - key/value pairs
-status_t CameraService::Client::setParameters(const String8& params) {
-    LOG1("setParameters (pid %d) (%s)", getCallingPid(), params.string());
-
-    Mutex::Autolock iLock(mICameraLock);
-    Mutex::Autolock lock(mLock);
-    status_t result = checkPidAndHardware();
-    if (result != NO_ERROR) return result;
-
-    CameraParameters p(params);
-    return mHardware->setParameters(p);
-}
-
-// get preview/capture parameters - key/value pairs
-String8 CameraService::Client::getParameters() const {
-    Mutex::Autolock iLock(mICameraLock);
-    Mutex::Autolock lock(mLock);
-    if (checkPidAndHardware() != NO_ERROR) return String8();
-
-    String8 params(mHardware->getParameters().flatten());
-    LOG1("getParameters (pid %d) (%s)", getCallingPid(), params.string());
-    return params;
-}
-
-// enable shutter sound
-status_t CameraService::Client::enableShutterSound(bool enable) {
-    LOG1("enableShutterSound (pid %d)", getCallingPid());
-
-    status_t result = checkPidAndHardware();
-    if (result != NO_ERROR) return result;
-
-    if (enable) {
-        mPlayShutterSound = true;
-        return OK;
-    }
-
-    // Disabling shutter sound may not be allowed. In that case only
-    // allow the mediaserver process to disable the sound.
-    char value[PROPERTY_VALUE_MAX];
-    property_get("ro.camera.sound.forced", value, "0");
-    if (strcmp(value, "0") != 0) {
-        // Disabling shutter sound is not allowed. Deny if the current
-        // process is not mediaserver.
-        if (getCallingPid() != getpid()) {
-            ALOGE("Failed to disable shutter sound. Permission denied (pid %d)", getCallingPid());
-            return PERMISSION_DENIED;
-        }
-    }
-
-    mPlayShutterSound = false;
-    return OK;
-}
-
-status_t CameraService::Client::sendCommand(int32_t cmd, int32_t arg1, int32_t arg2) {
-    LOG1("sendCommand (pid %d)", getCallingPid());
-    int orientation;
-    Mutex::Autolock iLock(mICameraLock);
-    Mutex::Autolock lock(mLock);
-    status_t result = checkPidAndHardware();
-    if (result != NO_ERROR) return result;
-
-    if (cmd == CAMERA_CMD_SET_DISPLAY_ORIENTATION) {
-        // Mirror the preview if the camera is front-facing.
-        orientation = getOrientation(arg1, mCameraFacing == CAMERA_FACING_FRONT);
-        if (orientation == -1) return BAD_VALUE;
-
-        if (mOrientation != orientation) {
-            mOrientation = orientation;
-            if (mPreviewWindow != 0) {
-                native_window_set_buffers_transform(mPreviewWindow.get(),
-                        mOrientation);
-            }
-        }
-        return OK;
-    } else if (cmd == CAMERA_CMD_ENABLE_SHUTTER_SOUND) {
-        switch (arg1) {
-            case 0:
-                enableShutterSound(false);
-                break;
-            case 1:
-                enableShutterSound(true);
-                break;
-            default:
-                return BAD_VALUE;
-        }
-        return OK;
-    } else if (cmd == CAMERA_CMD_PLAY_RECORDING_SOUND) {
-        mCameraService->playSound(SOUND_RECORDING);
-    } else if (cmd == CAMERA_CMD_PING) {
-        // If mHardware is 0, checkPidAndHardware will return error.
-        return OK;
-    }
-
-    return mHardware->sendCommand(cmd, arg1, arg2);
-}
-
-// ----------------------------------------------------------------------------
-
-void CameraService::Client::enableMsgType(int32_t msgType) {
-    android_atomic_or(msgType, &mMsgEnabled);
-    mHardware->enableMsgType(msgType);
-}
-
-void CameraService::Client::disableMsgType(int32_t msgType) {
-    android_atomic_and(~msgType, &mMsgEnabled);
-    mHardware->disableMsgType(msgType);
-}
-
-#define CHECK_MESSAGE_INTERVAL 10 // 10ms
-bool CameraService::Client::lockIfMessageWanted(int32_t msgType) {
-    int sleepCount = 0;
-    while (mMsgEnabled & msgType) {
-        if (mLock.tryLock() == NO_ERROR) {
-            if (sleepCount > 0) {
-                LOG1("lockIfMessageWanted(%d): waited for %d ms",
-                    msgType, sleepCount * CHECK_MESSAGE_INTERVAL);
-            }
-            return true;
-        }
-        if (sleepCount++ == 0) {
-            LOG1("lockIfMessageWanted(%d): enter sleep", msgType);
-        }
-        usleep(CHECK_MESSAGE_INTERVAL * 1000);
-    }
-    ALOGW("lockIfMessageWanted(%d): dropped unwanted message", msgType);
-    return false;
 }
 
 // ----------------------------------------------------------------------------
@@ -967,311 +390,12 @@
     // destruction already started, so should not be accessed
     if (client->mDestructionStarted) return NULL;
 
-    // The checks below are not necessary and are for debugging only.
-    if (client->mCameraService.get() != gCameraService) {
-        ALOGE("mismatch service!");
-        return NULL;
-    }
-
-    if (client->mHardware == 0) {
-        ALOGE("mHardware == 0: callback after disconnect()?");
-        return NULL;
-    }
-
     return client;
 }
 
-// Callback messages can be dispatched to internal handlers or pass to our
-// client's callback functions, depending on the message type.
-//
-// notifyCallback:
-//      CAMERA_MSG_SHUTTER              handleShutter
-//      (others)                        c->notifyCallback
-// dataCallback:
-//      CAMERA_MSG_PREVIEW_FRAME        handlePreviewData
-//      CAMERA_MSG_POSTVIEW_FRAME       handlePostview
-//      CAMERA_MSG_RAW_IMAGE            handleRawPicture
-//      CAMERA_MSG_COMPRESSED_IMAGE     handleCompressedPicture
-//      (others)                        c->dataCallback
-// dataCallbackTimestamp
-//      (others)                        c->dataCallbackTimestamp
-//
-// NOTE: the *Callback functions grab mLock of the client before passing
-// control to handle* functions. So the handle* functions must release the
-// lock before calling the ICameraClient's callbacks, so those callbacks can
-// invoke methods in the Client class again (For example, the preview frame
-// callback may want to releaseRecordingFrame). The handle* functions must
-// release the lock after all accesses to member variables, so it must be
-// handled very carefully.
-
-void CameraService::Client::notifyCallback(int32_t msgType, int32_t ext1,
-        int32_t ext2, void* user) {
-    LOG2("notifyCallback(%d)", msgType);
-
-    Mutex* lock = getClientLockFromCookie(user);
-    if (lock == NULL) return;
-    Mutex::Autolock alock(*lock);
-
-    Client* client = getClientFromCookie(user);
-    if (client == NULL) return;
-
-    if (!client->lockIfMessageWanted(msgType)) return;
-
-    switch (msgType) {
-        case CAMERA_MSG_SHUTTER:
-            // ext1 is the dimension of the yuv picture.
-            client->handleShutter();
-            break;
-        default:
-            client->handleGenericNotify(msgType, ext1, ext2);
-            break;
-    }
-}
-
-void CameraService::Client::dataCallback(int32_t msgType,
-        const sp<IMemory>& dataPtr, camera_frame_metadata_t *metadata, void* user) {
-    LOG2("dataCallback(%d)", msgType);
-
-    Mutex* lock = getClientLockFromCookie(user);
-    if (lock == NULL) return;
-    Mutex::Autolock alock(*lock);
-
-    Client* client = getClientFromCookie(user);
-    if (client == NULL) return;
-
-    if (!client->lockIfMessageWanted(msgType)) return;
-    if (dataPtr == 0 && metadata == NULL) {
-        ALOGE("Null data returned in data callback");
-        client->handleGenericNotify(CAMERA_MSG_ERROR, UNKNOWN_ERROR, 0);
-        return;
-    }
-
-    switch (msgType & ~CAMERA_MSG_PREVIEW_METADATA) {
-        case CAMERA_MSG_PREVIEW_FRAME:
-            client->handlePreviewData(msgType, dataPtr, metadata);
-            break;
-        case CAMERA_MSG_POSTVIEW_FRAME:
-            client->handlePostview(dataPtr);
-            break;
-        case CAMERA_MSG_RAW_IMAGE:
-            client->handleRawPicture(dataPtr);
-            break;
-        case CAMERA_MSG_COMPRESSED_IMAGE:
-            client->handleCompressedPicture(dataPtr);
-            break;
-        default:
-            client->handleGenericData(msgType, dataPtr, metadata);
-            break;
-    }
-}
-
-void CameraService::Client::dataCallbackTimestamp(nsecs_t timestamp,
-        int32_t msgType, const sp<IMemory>& dataPtr, void* user) {
-    LOG2("dataCallbackTimestamp(%d)", msgType);
-
-    Mutex* lock = getClientLockFromCookie(user);
-    if (lock == NULL) return;
-    Mutex::Autolock alock(*lock);
-
-    Client* client = getClientFromCookie(user);
-    if (client == NULL) return;
-
-    if (!client->lockIfMessageWanted(msgType)) return;
-
-    if (dataPtr == 0) {
-        ALOGE("Null data returned in data with timestamp callback");
-        client->handleGenericNotify(CAMERA_MSG_ERROR, UNKNOWN_ERROR, 0);
-        return;
-    }
-
-    client->handleGenericDataTimestamp(timestamp, msgType, dataPtr);
-}
-
-// snapshot taken callback
-void CameraService::Client::handleShutter(void) {
-    if (mPlayShutterSound) {
-        mCameraService->playSound(SOUND_SHUTTER);
-    }
-
-    sp<ICameraClient> c = mCameraClient;
-    if (c != 0) {
-        mLock.unlock();
-        c->notifyCallback(CAMERA_MSG_SHUTTER, 0, 0);
-        if (!lockIfMessageWanted(CAMERA_MSG_SHUTTER)) return;
-    }
-    disableMsgType(CAMERA_MSG_SHUTTER);
-
-    mLock.unlock();
-}
-
-// preview callback - frame buffer update
-void CameraService::Client::handlePreviewData(int32_t msgType,
-                                              const sp<IMemory>& mem,
-                                              camera_frame_metadata_t *metadata) {
-    ssize_t offset;
-    size_t size;
-    sp<IMemoryHeap> heap = mem->getMemory(&offset, &size);
-
-    // local copy of the callback flags
-    int flags = mPreviewCallbackFlag;
-
-    // is callback enabled?
-    if (!(flags & CAMERA_FRAME_CALLBACK_FLAG_ENABLE_MASK)) {
-        // If the enable bit is off, the copy-out and one-shot bits are ignored
-        LOG2("frame callback is disabled");
-        mLock.unlock();
-        return;
-    }
-
-    // hold a strong pointer to the client
-    sp<ICameraClient> c = mCameraClient;
-
-    // clear callback flags if no client or one-shot mode
-    if (c == 0 || (mPreviewCallbackFlag & CAMERA_FRAME_CALLBACK_FLAG_ONE_SHOT_MASK)) {
-        LOG2("Disable preview callback");
-        mPreviewCallbackFlag &= ~(CAMERA_FRAME_CALLBACK_FLAG_ONE_SHOT_MASK |
-                                  CAMERA_FRAME_CALLBACK_FLAG_COPY_OUT_MASK |
-                                  CAMERA_FRAME_CALLBACK_FLAG_ENABLE_MASK);
-        disableMsgType(CAMERA_MSG_PREVIEW_FRAME);
-    }
-
-    if (c != 0) {
-        // Is the received frame copied out or not?
-        if (flags & CAMERA_FRAME_CALLBACK_FLAG_COPY_OUT_MASK) {
-            LOG2("frame is copied");
-            copyFrameAndPostCopiedFrame(msgType, c, heap, offset, size, metadata);
-        } else {
-            LOG2("frame is forwarded");
-            mLock.unlock();
-            c->dataCallback(msgType, mem, metadata);
-        }
-    } else {
-        mLock.unlock();
-    }
-}
-
-// picture callback - postview image ready
-void CameraService::Client::handlePostview(const sp<IMemory>& mem) {
-    disableMsgType(CAMERA_MSG_POSTVIEW_FRAME);
-
-    sp<ICameraClient> c = mCameraClient;
-    mLock.unlock();
-    if (c != 0) {
-        c->dataCallback(CAMERA_MSG_POSTVIEW_FRAME, mem, NULL);
-    }
-}
-
-// picture callback - raw image ready
-void CameraService::Client::handleRawPicture(const sp<IMemory>& mem) {
-    disableMsgType(CAMERA_MSG_RAW_IMAGE);
-
-    ssize_t offset;
-    size_t size;
-    sp<IMemoryHeap> heap = mem->getMemory(&offset, &size);
-
-    sp<ICameraClient> c = mCameraClient;
-    mLock.unlock();
-    if (c != 0) {
-        c->dataCallback(CAMERA_MSG_RAW_IMAGE, mem, NULL);
-    }
-}
-
-// picture callback - compressed picture ready
-void CameraService::Client::handleCompressedPicture(const sp<IMemory>& mem) {
-    disableMsgType(CAMERA_MSG_COMPRESSED_IMAGE);
-
-    sp<ICameraClient> c = mCameraClient;
-    mLock.unlock();
-    if (c != 0) {
-        c->dataCallback(CAMERA_MSG_COMPRESSED_IMAGE, mem, NULL);
-    }
-}
-
-
-void CameraService::Client::handleGenericNotify(int32_t msgType,
-    int32_t ext1, int32_t ext2) {
-    sp<ICameraClient> c = mCameraClient;
-    mLock.unlock();
-    if (c != 0) {
-        c->notifyCallback(msgType, ext1, ext2);
-    }
-}
-
-void CameraService::Client::handleGenericData(int32_t msgType,
-    const sp<IMemory>& dataPtr, camera_frame_metadata_t *metadata) {
-    sp<ICameraClient> c = mCameraClient;
-    mLock.unlock();
-    if (c != 0) {
-        c->dataCallback(msgType, dataPtr, metadata);
-    }
-}
-
-void CameraService::Client::handleGenericDataTimestamp(nsecs_t timestamp,
-    int32_t msgType, const sp<IMemory>& dataPtr) {
-    sp<ICameraClient> c = mCameraClient;
-    mLock.unlock();
-    if (c != 0) {
-        c->dataCallbackTimestamp(timestamp, msgType, dataPtr);
-    }
-}
-
-void CameraService::Client::copyFrameAndPostCopiedFrame(
-        int32_t msgType, const sp<ICameraClient>& client,
-        const sp<IMemoryHeap>& heap, size_t offset, size_t size,
-        camera_frame_metadata_t *metadata) {
-    LOG2("copyFrameAndPostCopiedFrame");
-    // It is necessary to copy out of pmem before sending this to
-    // the callback. For efficiency, reuse the same MemoryHeapBase
-    // provided it's big enough. Don't allocate the memory or
-    // perform the copy if there's no callback.
-    // hold the preview lock while we grab a reference to the preview buffer
-    sp<MemoryHeapBase> previewBuffer;
-
-    if (mPreviewBuffer == 0) {
-        mPreviewBuffer = new MemoryHeapBase(size, 0, NULL);
-    } else if (size > mPreviewBuffer->virtualSize()) {
-        mPreviewBuffer.clear();
-        mPreviewBuffer = new MemoryHeapBase(size, 0, NULL);
-    }
-    if (mPreviewBuffer == 0) {
-        ALOGE("failed to allocate space for preview buffer");
-        mLock.unlock();
-        return;
-    }
-    previewBuffer = mPreviewBuffer;
-
-    memcpy(previewBuffer->base(), (uint8_t *)heap->base() + offset, size);
-
-    sp<MemoryBase> frame = new MemoryBase(previewBuffer, 0, size);
-    if (frame == 0) {
-        ALOGE("failed to allocate space for frame callback");
-        mLock.unlock();
-        return;
-    }
-
-    mLock.unlock();
-    client->dataCallback(msgType, frame, metadata);
-}
-
-int CameraService::Client::getOrientation(int degrees, bool mirror) {
-    if (!mirror) {
-        if (degrees == 0) return 0;
-        else if (degrees == 90) return HAL_TRANSFORM_ROT_90;
-        else if (degrees == 180) return HAL_TRANSFORM_ROT_180;
-        else if (degrees == 270) return HAL_TRANSFORM_ROT_270;
-    } else {  // Do mirror (horizontal flip)
-        if (degrees == 0) {           // FLIP_H and ROT_0
-            return HAL_TRANSFORM_FLIP_H;
-        } else if (degrees == 90) {   // FLIP_H and ROT_90
-            return HAL_TRANSFORM_FLIP_H | HAL_TRANSFORM_ROT_90;
-        } else if (degrees == 180) {  // FLIP_H and ROT_180
-            return HAL_TRANSFORM_FLIP_V;
-        } else if (degrees == 270) {  // FLIP_H and ROT_270
-            return HAL_TRANSFORM_FLIP_V | HAL_TRANSFORM_ROT_90;
-        }
-    }
-    ALOGE("Invalid setDisplayOrientation degrees=%d", degrees);
-    return -1;
+void CameraService::Client::disconnect() {
+    mCameraService->removeClient(mCameraClient);
+    mCameraService->setCameraFree(mCameraId);
 }
 
 // ----------------------------------------------------------------------------
@@ -1293,24 +417,18 @@
 }
 
 status_t CameraService::dump(int fd, const Vector<String16>& args) {
-    static const char* kDeadlockedString = "CameraService may be deadlocked\n";
-
-    const size_t SIZE = 256;
-    char buffer[SIZE];
     String8 result;
     if (checkCallingPermission(String16("android.permission.DUMP")) == false) {
-        snprintf(buffer, SIZE, "Permission Denial: "
+        result.appendFormat("Permission Denial: "
                 "can't dump CameraService from pid=%d, uid=%d\n",
                 getCallingPid(),
                 getCallingUid());
-        result.append(buffer);
         write(fd, result.string(), result.size());
     } else {
         bool locked = tryLock(mServiceLock);
         // failed to lock - CameraService is probably deadlocked
         if (!locked) {
-            String8 result(kDeadlockedString);
-            write(fd, result.string(), result.size());
+            result.append("CameraService may be deadlocked\n");
         }
 
         bool hasClient = false;
@@ -1318,17 +436,10 @@
             sp<Client> client = mClient[i].promote();
             if (client == 0) continue;
             hasClient = true;
-            sprintf(buffer, "Client[%d] (%p) PID: %d\n",
-                    i,
-                    client->getCameraClient()->asBinder().get(),
-                    client->mClientPid);
-            result.append(buffer);
-            write(fd, result.string(), result.size());
-            client->mHardware->dump(fd, args);
+            client->dump(fd, args);
         }
         if (!hasClient) {
-            result.append("No camera client yet.\n");
-            write(fd, result.string(), result.size());
+            result.append("No camera clients yet.\n");
         }
 
         if (locked) mServiceLock.unlock();
@@ -1336,14 +447,15 @@
         // change logging level
         int n = args.size();
         for (int i = 0; i + 1 < n; i++) {
-            if (args[i] == String16("-v")) {
+            String16 verboseOption("-v");
+            if (args[i] == verboseOption) {
                 String8 levelStr(args[i+1]);
                 int level = atoi(levelStr.string());
-                sprintf(buffer, "Set Log Level to %d", level);
-                result.append(buffer);
+                result.appendFormat("Setting log level to %d.\n", level);
                 setLogLevel(level);
             }
         }
+        write(fd, result.string(), result.size());
     }
     return NO_ERROR;
 }
diff --git a/services/camera/libcameraservice/CameraService.h b/services/camera/libcameraservice/CameraService.h
index 95ac197..630fca7 100644
--- a/services/camera/libcameraservice/CameraService.h
+++ b/services/camera/libcameraservice/CameraService.h
@@ -27,17 +27,18 @@
 
 namespace android {
 
+extern volatile int32_t gLogLevel;
+
 class MemoryHeapBase;
 class MediaPlayer;
-class CameraHardwareInterface;
 
 class CameraService :
     public BinderService<CameraService>,
     public BnCameraService
 {
-    class Client;
     friend class BinderService<CameraService>;
 public:
+    class Client;
     static char const* getServiceName() { return "media.camera"; }
 
                         CameraService();
@@ -68,6 +69,68 @@
     void                playSound(sound_kind kind);
     void                releaseSound();
 
+    class Client : public BnCamera
+    {
+    public:
+        // ICamera interface (see ICamera for details)
+        virtual void          disconnect();
+        virtual status_t      connect(const sp<ICameraClient>& client) = 0;
+        virtual status_t      lock() = 0;
+        virtual status_t      unlock() = 0;
+        virtual status_t      setPreviewDisplay(const sp<Surface>& surface) = 0;
+        virtual status_t      setPreviewTexture(const sp<ISurfaceTexture>& surfaceTexture) = 0;
+        virtual void          setPreviewCallbackFlag(int flag) = 0;
+        virtual status_t      startPreview() = 0;
+        virtual void          stopPreview() = 0;
+        virtual bool          previewEnabled() = 0;
+        virtual status_t      storeMetaDataInBuffers(bool enabled) = 0;
+        virtual status_t      startRecording() = 0;
+        virtual void          stopRecording() = 0;
+        virtual bool          recordingEnabled() = 0;
+        virtual void          releaseRecordingFrame(const sp<IMemory>& mem) = 0;
+        virtual status_t      autoFocus() = 0;
+        virtual status_t      cancelAutoFocus() = 0;
+        virtual status_t      takePicture(int msgType) = 0;
+        virtual status_t      setParameters(const String8& params) = 0;
+        virtual String8       getParameters() const = 0;
+        virtual status_t      sendCommand(int32_t cmd, int32_t arg1, int32_t arg2) = 0;
+
+        // Interface used by CameraService
+        Client(const sp<CameraService>& cameraService,
+                const sp<ICameraClient>& cameraClient,
+                int cameraId,
+                int cameraFacing,
+                int clientPid);
+        ~Client();
+
+        // return our camera client
+        const sp<ICameraClient>&    getCameraClient() {
+            return mCameraClient;
+        }
+
+        virtual status_t initialize(camera_module_t *module) = 0;
+
+        virtual status_t dump(int fd, const Vector<String16>& args) = 0;
+
+    protected:
+        static Mutex*        getClientLockFromCookie(void* user);
+        // convert client from cookie. Client lock should be acquired before getting Client.
+        static Client*       getClientFromCookie(void* user);
+
+        // the instance is in the middle of destruction. When this is set,
+        // the instance should not be accessed from callback.
+        // CameraService's mClientLock should be acquired to access this.
+        bool                            mDestructionStarted;
+
+        // these are initialized in the constructor.
+        sp<CameraService>               mCameraService;  // immutable after constructor
+        sp<ICameraClient>               mCameraClient;
+        int                             mCameraId;       // immutable after constructor
+        int                             mCameraFacing;   // immutable after constructor
+        pid_t                           mClientPid;
+
+    };
+
 private:
     Mutex               mServiceLock;
     wp<Client>          mClient[MAX_CAMERAS];  // protected by mServiceLock
@@ -86,147 +149,6 @@
     sp<MediaPlayer>     mSoundPlayer[NUM_SOUNDS];
     int                 mSoundRef;  // reference count (release all MediaPlayer when 0)
 
-    class Client : public BnCamera
-    {
-    public:
-        // ICamera interface (see ICamera for details)
-        virtual void            disconnect();
-        virtual status_t        connect(const sp<ICameraClient>& client);
-        virtual status_t        lock();
-        virtual status_t        unlock();
-        virtual status_t        setPreviewDisplay(const sp<Surface>& surface);
-        virtual status_t        setPreviewTexture(const sp<ISurfaceTexture>& surfaceTexture);
-        virtual void            setPreviewCallbackFlag(int flag);
-        virtual status_t        startPreview();
-        virtual void            stopPreview();
-        virtual bool            previewEnabled();
-        virtual status_t        storeMetaDataInBuffers(bool enabled);
-        virtual status_t        startRecording();
-        virtual void            stopRecording();
-        virtual bool            recordingEnabled();
-        virtual void            releaseRecordingFrame(const sp<IMemory>& mem);
-        virtual status_t        autoFocus();
-        virtual status_t        cancelAutoFocus();
-        virtual status_t        takePicture(int msgType);
-        virtual status_t        setParameters(const String8& params);
-        virtual String8         getParameters() const;
-        virtual status_t        sendCommand(int32_t cmd, int32_t arg1, int32_t arg2);
-    private:
-        friend class CameraService;
-                                Client(const sp<CameraService>& cameraService,
-                                       const sp<ICameraClient>& cameraClient,
-                                       const sp<CameraHardwareInterface>& hardware,
-                                       int cameraId,
-                                       int cameraFacing,
-                                       int clientPid);
-                                ~Client();
-
-        // return our camera client
-        const sp<ICameraClient>&    getCameraClient() { return mCameraClient; }
-
-        // check whether the calling process matches mClientPid.
-        status_t                checkPid() const;
-        status_t                checkPidAndHardware() const;  // also check mHardware != 0
-
-        // these are internal functions used to set up preview buffers
-        status_t                registerPreviewBuffers();
-
-        // camera operation mode
-        enum camera_mode {
-            CAMERA_PREVIEW_MODE   = 0,  // frame automatically released
-            CAMERA_RECORDING_MODE = 1,  // frame has to be explicitly released by releaseRecordingFrame()
-        };
-        // these are internal functions used for preview/recording
-        status_t                startCameraMode(camera_mode mode);
-        status_t                startPreviewMode();
-        status_t                startRecordingMode();
-
-        // internal function used by sendCommand to enable/disable shutter sound.
-        status_t                enableShutterSound(bool enable);
-
-        // these are static callback functions
-        static void             notifyCallback(int32_t msgType, int32_t ext1, int32_t ext2, void* user);
-        static void             dataCallback(int32_t msgType, const sp<IMemory>& dataPtr,
-                                             camera_frame_metadata_t *metadata, void* user);
-        static void             dataCallbackTimestamp(nsecs_t timestamp, int32_t msgType, const sp<IMemory>& dataPtr, void* user);
-        static Mutex*        getClientLockFromCookie(void* user);
-        // convert client from cookie. Client lock should be acquired before getting Client.
-        static Client*       getClientFromCookie(void* user);
-        // handlers for messages
-        void                    handleShutter(void);
-        void                    handlePreviewData(int32_t msgType, const sp<IMemory>& mem,
-                                                  camera_frame_metadata_t *metadata);
-        void                    handlePostview(const sp<IMemory>& mem);
-        void                    handleRawPicture(const sp<IMemory>& mem);
-        void                    handleCompressedPicture(const sp<IMemory>& mem);
-        void                    handleGenericNotify(int32_t msgType, int32_t ext1, int32_t ext2);
-        void                    handleGenericData(int32_t msgType, const sp<IMemory>& dataPtr,
-                                                  camera_frame_metadata_t *metadata);
-        void                    handleGenericDataTimestamp(nsecs_t timestamp, int32_t msgType, const sp<IMemory>& dataPtr);
-
-        void                    copyFrameAndPostCopiedFrame(
-                                    int32_t msgType,
-                                    const sp<ICameraClient>& client,
-                                    const sp<IMemoryHeap>& heap,
-                                    size_t offset, size_t size,
-                                    camera_frame_metadata_t *metadata);
-
-        int                     getOrientation(int orientation, bool mirror);
-
-        status_t                setPreviewWindow(
-                                    const sp<IBinder>& binder,
-                                    const sp<ANativeWindow>& window);
-
-        // these are initialized in the constructor.
-        sp<CameraService>               mCameraService;  // immutable after constructor
-        sp<ICameraClient>               mCameraClient;
-        int                             mCameraId;       // immutable after constructor
-        int                             mCameraFacing;   // immutable after constructor
-        pid_t                           mClientPid;
-        sp<CameraHardwareInterface>     mHardware;       // cleared after disconnect()
-        int                             mPreviewCallbackFlag;
-        int                             mOrientation;     // Current display orientation
-        bool                            mPlayShutterSound;
-
-        // Ensures atomicity among the public methods
-        mutable Mutex                   mLock;
-        // A lock to synchronize access through the ICamera binder
-        // interface. The entire binder call should be done with mICameraLock
-        // locked, to serialize ICamera access, even when mLock is disabled for
-        // calls to the HAL.
-        mutable Mutex                   mICameraLock;
-        // This is a binder of Surface or SurfaceTexture.
-        sp<IBinder>                     mSurface;
-        sp<ANativeWindow>               mPreviewWindow;
-
-        // If the user want us to return a copy of the preview frame (instead
-        // of the original one), we allocate mPreviewBuffer and reuse it if possible.
-        sp<MemoryHeapBase>              mPreviewBuffer;
-
-        // the instance is in the middle of destruction. When this is set,
-        // the instance should not be accessed from callback.
-        // CameraService's mClientLock should be acquired to access this.
-        bool                            mDestructionStarted;
-
-        // We need to avoid the deadlock when the incoming command thread and
-        // the CameraHardwareInterface callback thread both want to grab mLock.
-        // An extra flag is used to tell the callback thread that it should stop
-        // trying to deliver the callback messages if the client is not
-        // interested in it anymore. For example, if the client is calling
-        // stopPreview(), the preview frame messages do not need to be delivered
-        // anymore.
-
-        // This function takes the same parameter as the enableMsgType() and
-        // disableMsgType() functions in CameraHardwareInterface.
-        void                    enableMsgType(int32_t msgType);
-        void                    disableMsgType(int32_t msgType);
-        volatile int32_t        mMsgEnabled;
-
-        // This function keeps trying to grab mLock, or give up if the message
-        // is found to be disabled. It returns true if mLock is grabbed.
-        bool                    lockIfMessageWanted(int32_t msgType);
-    };
-
     camera_module_t *mModule;
 };
 
diff --git a/services/camera/libcameraservice/CannedJpeg.h b/services/camera/libcameraservice/CannedJpeg.h
deleted file mode 100644
index 6dd99c1..0000000
--- a/services/camera/libcameraservice/CannedJpeg.h
+++ /dev/null
@@ -1,750 +0,0 @@
-/*
- * Copyright (C) 2010 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.
- */
-
-const int kCannedJpegWidth = 320;
-const int kCannedJpegHeight = 240;
-const int kCannedJpegSize = 8733;
-
-const char kCannedJpeg[] = {
-  0xff,  0xd8,  0xff,  0xe0,  0x00,  0x10,  0x4a,  0x46,  0x49,  0x46,  0x00,  0x01,
-  0x01,  0x01,  0x00,  0x60,  0x00,  0x60,  0x00,  0x00,  0xff,  0xe1,  0x00,  0x66,
-  0x45,  0x78,  0x69,  0x66,  0x00,  0x00,  0x49,  0x49,  0x2a,  0x00,  0x08,  0x00,
-  0x00,  0x00,  0x04,  0x00,  0x1a,  0x01,  0x05,  0x00,  0x01,  0x00,  0x00,  0x00,
-  0x3e,  0x00,  0x00,  0x00,  0x1b,  0x01,  0x05,  0x00,  0x01,  0x00,  0x00,  0x00,
-  0x46,  0x00,  0x00,  0x00,  0x28,  0x01,  0x03,  0x00,  0x01,  0x00,  0x00,  0x00,
-  0x02,  0x00,  0x00,  0x00,  0x31,  0x01,  0x02,  0x00,  0x10,  0x00,  0x00,  0x00,
-  0x4e,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x60,  0x00,  0x00,  0x00,
-  0x01,  0x00,  0x00,  0x00,  0x60,  0x00,  0x00,  0x00,  0x01,  0x00,  0x00,  0x00,
-  0x50,  0x61,  0x69,  0x6e,  0x74,  0x2e,  0x4e,  0x45,  0x54,  0x20,  0x76,  0x33,
-  0x2e,  0x33,  0x36,  0x00,  0xff,  0xdb,  0x00,  0x43,  0x00,  0x03,  0x02,  0x02,
-  0x03,  0x02,  0x02,  0x03,  0x03,  0x03,  0x03,  0x04,  0x03,  0x03,  0x04,  0x05,
-  0x08,  0x05,  0x05,  0x04,  0x04,  0x05,  0x0a,  0x07,  0x07,  0x06,  0x08,  0x0c,
-  0x0a,  0x0c,  0x0c,  0x0b,  0x0a,  0x0b,  0x0b,  0x0d,  0x0e,  0x12,  0x10,  0x0d,
-  0x0e,  0x11,  0x0e,  0x0b,  0x0b,  0x10,  0x16,  0x10,  0x11,  0x13,  0x14,  0x15,
-  0x15,  0x15,  0x0c,  0x0f,  0x17,  0x18,  0x16,  0x14,  0x18,  0x12,  0x14,  0x15,
-  0x14,  0xff,  0xdb,  0x00,  0x43,  0x01,  0x03,  0x04,  0x04,  0x05,  0x04,  0x05,
-  0x09,  0x05,  0x05,  0x09,  0x14,  0x0d,  0x0b,  0x0d,  0x14,  0x14,  0x14,  0x14,
-  0x14,  0x14,  0x14,  0x14,  0x14,  0x14,  0x14,  0x14,  0x14,  0x14,  0x14,  0x14,
-  0x14,  0x14,  0x14,  0x14,  0x14,  0x14,  0x14,  0x14,  0x14,  0x14,  0x14,  0x14,
-  0x14,  0x14,  0x14,  0x14,  0x14,  0x14,  0x14,  0x14,  0x14,  0x14,  0x14,  0x14,
-  0x14,  0x14,  0x14,  0x14,  0x14,  0x14,  0x14,  0x14,  0x14,  0x14,  0xff,  0xc0,
-  0x00,  0x11,  0x08,  0x00,  0xf0,  0x01,  0x40,  0x03,  0x01,  0x22,  0x00,  0x02,
-  0x11,  0x01,  0x03,  0x11,  0x01,  0xff,  0xc4,  0x00,  0x1f,  0x00,  0x00,  0x01,
-  0x05,  0x01,  0x01,  0x01,  0x01,  0x01,  0x01,  0x00,  0x00,  0x00,  0x00,  0x00,
-  0x00,  0x00,  0x00,  0x01,  0x02,  0x03,  0x04,  0x05,  0x06,  0x07,  0x08,  0x09,
-  0x0a,  0x0b,  0xff,  0xc4,  0x00,  0xb5,  0x10,  0x00,  0x02,  0x01,  0x03,  0x03,
-  0x02,  0x04,  0x03,  0x05,  0x05,  0x04,  0x04,  0x00,  0x00,  0x01,  0x7d,  0x01,
-  0x02,  0x03,  0x00,  0x04,  0x11,  0x05,  0x12,  0x21,  0x31,  0x41,  0x06,  0x13,
-  0x51,  0x61,  0x07,  0x22,  0x71,  0x14,  0x32,  0x81,  0x91,  0xa1,  0x08,  0x23,
-  0x42,  0xb1,  0xc1,  0x15,  0x52,  0xd1,  0xf0,  0x24,  0x33,  0x62,  0x72,  0x82,
-  0x09,  0x0a,  0x16,  0x17,  0x18,  0x19,  0x1a,  0x25,  0x26,  0x27,  0x28,  0x29,
-  0x2a,  0x34,  0x35,  0x36,  0x37,  0x38,  0x39,  0x3a,  0x43,  0x44,  0x45,  0x46,
-  0x47,  0x48,  0x49,  0x4a,  0x53,  0x54,  0x55,  0x56,  0x57,  0x58,  0x59,  0x5a,
-  0x63,  0x64,  0x65,  0x66,  0x67,  0x68,  0x69,  0x6a,  0x73,  0x74,  0x75,  0x76,
-  0x77,  0x78,  0x79,  0x7a,  0x83,  0x84,  0x85,  0x86,  0x87,  0x88,  0x89,  0x8a,
-  0x92,  0x93,  0x94,  0x95,  0x96,  0x97,  0x98,  0x99,  0x9a,  0xa2,  0xa3,  0xa4,
-  0xa5,  0xa6,  0xa7,  0xa8,  0xa9,  0xaa,  0xb2,  0xb3,  0xb4,  0xb5,  0xb6,  0xb7,
-  0xb8,  0xb9,  0xba,  0xc2,  0xc3,  0xc4,  0xc5,  0xc6,  0xc7,  0xc8,  0xc9,  0xca,
-  0xd2,  0xd3,  0xd4,  0xd5,  0xd6,  0xd7,  0xd8,  0xd9,  0xda,  0xe1,  0xe2,  0xe3,
-  0xe4,  0xe5,  0xe6,  0xe7,  0xe8,  0xe9,  0xea,  0xf1,  0xf2,  0xf3,  0xf4,  0xf5,
-  0xf6,  0xf7,  0xf8,  0xf9,  0xfa,  0xff,  0xc4,  0x00,  0x1f,  0x01,  0x00,  0x03,
-  0x01,  0x01,  0x01,  0x01,  0x01,  0x01,  0x01,  0x01,  0x01,  0x00,  0x00,  0x00,
-  0x00,  0x00,  0x00,  0x01,  0x02,  0x03,  0x04,  0x05,  0x06,  0x07,  0x08,  0x09,
-  0x0a,  0x0b,  0xff,  0xc4,  0x00,  0xb5,  0x11,  0x00,  0x02,  0x01,  0x02,  0x04,
-  0x04,  0x03,  0x04,  0x07,  0x05,  0x04,  0x04,  0x00,  0x01,  0x02,  0x77,  0x00,
-  0x01,  0x02,  0x03,  0x11,  0x04,  0x05,  0x21,  0x31,  0x06,  0x12,  0x41,  0x51,
-  0x07,  0x61,  0x71,  0x13,  0x22,  0x32,  0x81,  0x08,  0x14,  0x42,  0x91,  0xa1,
-  0xb1,  0xc1,  0x09,  0x23,  0x33,  0x52,  0xf0,  0x15,  0x62,  0x72,  0xd1,  0x0a,
-  0x16,  0x24,  0x34,  0xe1,  0x25,  0xf1,  0x17,  0x18,  0x19,  0x1a,  0x26,  0x27,
-  0x28,  0x29,  0x2a,  0x35,  0x36,  0x37,  0x38,  0x39,  0x3a,  0x43,  0x44,  0x45,
-  0x46,  0x47,  0x48,  0x49,  0x4a,  0x53,  0x54,  0x55,  0x56,  0x57,  0x58,  0x59,
-  0x5a,  0x63,  0x64,  0x65,  0x66,  0x67,  0x68,  0x69,  0x6a,  0x73,  0x74,  0x75,
-  0x76,  0x77,  0x78,  0x79,  0x7a,  0x82,  0x83,  0x84,  0x85,  0x86,  0x87,  0x88,
-  0x89,  0x8a,  0x92,  0x93,  0x94,  0x95,  0x96,  0x97,  0x98,  0x99,  0x9a,  0xa2,
-  0xa3,  0xa4,  0xa5,  0xa6,  0xa7,  0xa8,  0xa9,  0xaa,  0xb2,  0xb3,  0xb4,  0xb5,
-  0xb6,  0xb7,  0xb8,  0xb9,  0xba,  0xc2,  0xc3,  0xc4,  0xc5,  0xc6,  0xc7,  0xc8,
-  0xc9,  0xca,  0xd2,  0xd3,  0xd4,  0xd5,  0xd6,  0xd7,  0xd8,  0xd9,  0xda,  0xe2,
-  0xe3,  0xe4,  0xe5,  0xe6,  0xe7,  0xe8,  0xe9,  0xea,  0xf2,  0xf3,  0xf4,  0xf5,
-  0xf6,  0xf7,  0xf8,  0xf9,  0xfa,  0xff,  0xda,  0x00,  0x0c,  0x03,  0x01,  0x00,
-  0x02,  0x11,  0x03,  0x11,  0x00,  0x3f,  0x00,  0xf9,  0xd2,  0xa3,  0x95,  0xbb,
-  0x54,  0x84,  0xe0,  0x66,  0xa0,  0x27,  0x27,  0x35,  0xed,  0x9e,  0x50,  0x95,
-  0x2c,  0x4b,  0xc6,  0x6a,  0x35,  0x1b,  0x8e,  0x2a,  0x70,  0x30,  0x28,  0x00,
-  0xa8,  0xe5,  0x6e,  0x71,  0x52,  0x31,  0xda,  0x33,  0x50,  0x13,  0x93,  0x40,
-  0x09,  0x52,  0xc6,  0xb8,  0x19,  0xf5,  0xa6,  0x2a,  0xee,  0x6c,  0x54,  0xd4,
-  0x00,  0x54,  0x52,  0x36,  0x5b,  0x1e,  0x95,  0x23,  0xb6,  0xd5,  0xcd,  0x41,
-  0x40,  0x05,  0x4c,  0x8b,  0xb5,  0x7d,  0xea,  0x34,  0x5d,  0xcd,  0xed,  0x53,
-  0x50,  0x01,  0x50,  0xbb,  0x6e,  0x6f,  0x6a,  0x91,  0xdb,  0x6a,  0xfb,  0xd4,
-  0x34,  0x00,  0x54,  0xe8,  0xbb,  0x57,  0x15,  0x1c,  0x6b,  0x96,  0xcf,  0xa5,
-  0x4b,  0x40,  0x05,  0x42,  0xcd,  0xb9,  0xb3,  0x4f,  0x91,  0xb0,  0x31,  0xeb,
-  0x51,  0x50,  0x02,  0x81,  0x93,  0x53,  0xa8,  0xda,  0x31,  0x51,  0xc4,  0xbc,
-  0xe6,  0xa4,  0xa0,  0x00,  0x9c,  0x0a,  0x81,  0x8e,  0xe3,  0x9a,  0x92,  0x56,
-  0xe3,  0x15,  0x15,  0x00,  0x28,  0x19,  0x38,  0xa9,  0xc0,  0xc0,  0xc5,  0x47,
-  0x12,  0xf7,  0xa9,  0x28,  0x00,  0x27,  0x00,  0x9a,  0x80,  0x9c,  0x9c,  0xd3,
-  0xe5,  0x6e,  0xd5,  0x1d,  0x00,  0x2a,  0x8d,  0xc7,  0x15,  0x3d,  0x32,  0x35,
-  0xc0,  0xcf,  0xad,  0x3e,  0x80,  0x11,  0x8e,  0xd1,  0x9a,  0x82,  0x9f,  0x23,
-  0x64,  0xe3,  0xd2,  0x99,  0x40,  0x0e,  0x45,  0xdc,  0xde,  0xd5,  0x35,  0x36,
-  0x35,  0xc2,  0xfb,  0x9a,  0x75,  0x00,  0x35,  0xdb,  0x6a,  0xfb,  0xd4,  0x34,
-  0xe9,  0x1b,  0x73,  0x7b,  0x0a,  0x6d,  0x00,  0x3e,  0x35,  0xcb,  0x7b,  0x0a,
-  0x96,  0x91,  0x17,  0x6a,  0xd2,  0xd0,  0x03,  0x64,  0x6c,  0x2f,  0xb9,  0xa8,
-  0x69,  0xce,  0xdb,  0x9a,  0x9b,  0xd6,  0x80,  0x1f,  0x12,  0xe4,  0xe7,  0xd2,
-  0xa5,  0xa4,  0x51,  0xb4,  0x62,  0x97,  0xa5,  0x00,  0x67,  0xc9,  0xad,  0xd8,
-  0x91,  0x81,  0x72,  0x9f,  0x9d,  0x47,  0xfd,  0xb3,  0x65,  0xff,  0x00,  0x3f,
-  0x29,  0x5f,  0xa0,  0x1f,  0xf0,  0xe9,  0x6f,  0x09,  0x7f,  0xd0,  0xfb,  0xad,
-  0x7f,  0xe0,  0x24,  0x34,  0x7f,  0xc3,  0xa5,  0xbc,  0x25,  0xff,  0x00,  0x43,
-  0xee,  0xb5,  0xff,  0x00,  0x80,  0x90,  0xd7,  0x3f,  0xb7,  0x87,  0x73,  0x6f,
-  0x63,  0x33,  0xe0,  0x28,  0xf5,  0x9b,  0x11,  0xc9,  0xb9,  0x4c,  0xfd,  0x69,
-  0xff,  0x00,  0xdb,  0x96,  0x1f,  0xf3,  0xf5,  0x1f,  0xe7,  0x5f,  0x7d,  0x7f,
-  0xc3,  0xa5,  0xbc,  0x25,  0xff,  0x00,  0x43,  0xee,  0xb5,  0xff,  0x00,  0x80,
-  0x90,  0xd1,  0xff,  0x00,  0x0e,  0x96,  0xf0,  0x97,  0xfd,  0x0f,  0xba,  0xd7,
-  0xfe,  0x02,  0x43,  0x47,  0xb7,  0x87,  0x70,  0xf6,  0x33,  0x3e,  0x02,  0x93,
-  0x5b,  0xb1,  0x3c,  0x0b,  0x94,  0xc7,  0xd6,  0x99,  0xfd,  0xb3,  0x65,  0xff,
-  0x00,  0x3f,  0x29,  0xf9,  0xd7,  0xe8,  0x07,  0xfc,  0x3a,  0x5b,  0xc2,  0x5f,
-  0xf4,  0x3e,  0xeb,  0x5f,  0xf8,  0x09,  0x0d,  0x1f,  0xf0,  0xe9,  0x6f,  0x09,
-  0x7f,  0xd0,  0xfb,  0xad,  0x7f,  0xe0,  0x24,  0x34,  0xbd,  0xbc,  0x03,  0xd8,
-  0xcc,  0xf8,  0x0e,  0x3d,  0x6a,  0xc1,  0x47,  0x37,  0x29,  0x9f,  0xad,  0x3b,
-  0xfb,  0x72,  0xc3,  0xfe,  0x7e,  0xa3,  0xfc,  0xeb,  0xef,  0xaf,  0xf8,  0x74,
-  0xb7,  0x84,  0xbf,  0xe8,  0x7d,  0xd6,  0xbf,  0xf0,  0x12,  0x1a,  0x3f,  0xe1,
-  0xd2,  0xde,  0x12,  0xff,  0x00,  0xa1,  0xf7,  0x5a,  0xff,  0x00,  0xc0,  0x48,
-  0x69,  0xfb,  0x78,  0x77,  0x0f,  0x63,  0x33,  0xe0,  0x19,  0x35,  0xbb,  0x26,
-  0x3c,  0x5c,  0xa6,  0x3e,  0xb4,  0xdf,  0xed,  0x9b,  0x2f,  0xf9,  0xf9,  0x4a,
-  0xfd,  0x00,  0xff,  0x00,  0x87,  0x4b,  0x78,  0x4b,  0xfe,  0x87,  0xdd,  0x6b,
-  0xff,  0x00,  0x01,  0x21,  0xa3,  0xfe,  0x1d,  0x2d,  0xe1,  0x2f,  0xfa,  0x1f,
-  0x75,  0xaf,  0xfc,  0x04,  0x86,  0x97,  0xb7,  0x80,  0x7b,  0x19,  0x9f,  0x01,
-  0xa6,  0xb5,  0x60,  0xab,  0xff,  0x00,  0x1f,  0x51,  0xe7,  0xeb,  0x4e,  0xfe,
-  0xdc,  0xb0,  0xff,  0x00,  0x9f,  0xa8,  0xff,  0x00,  0x3a,  0xfb,  0xeb,  0xfe,
-  0x1d,  0x2d,  0xe1,  0x2f,  0xfa,  0x1f,  0x75,  0xaf,  0xfc,  0x04,  0x86,  0x8f,
-  0xf8,  0x74,  0xb7,  0x84,  0xbf,  0xe8,  0x7d,  0xd6,  0xbf,  0xf0,  0x12,  0x1a,
-  0x3d,  0xbc,  0x03,  0xd8,  0xcc,  0xf8,  0x05,  0xf5,  0xab,  0x26,  0x6f,  0xf8,
-  0xf9,  0x4c,  0x7d,  0x69,  0xbf,  0xdb,  0x36,  0x5f,  0xf3,  0xf2,  0x9f,  0x9d,
-  0x7e,  0x80,  0x7f,  0xc3,  0xa5,  0xbc,  0x25,  0xff,  0x00,  0x43,  0xee,  0xb5,
-  0xff,  0x00,  0x80,  0x90,  0xd1,  0xff,  0x00,  0x0e,  0x96,  0xf0,  0x97,  0xfd,
-  0x0f,  0xba,  0xd7,  0xfe,  0x02,  0x43,  0x47,  0xb7,  0x80,  0x7b,  0x19,  0x9f,
-  0x02,  0x26,  0xb5,  0x60,  0xab,  0x8f,  0xb5,  0x47,  0xf9,  0xd2,  0xff,  0x00,
-  0x6e,  0x58,  0x7f,  0xcf,  0xd4,  0x7f,  0x9d,  0x7d,  0xf5,  0xff,  0x00,  0x0e,
-  0x96,  0xf0,  0x97,  0xfd,  0x0f,  0xba,  0xd7,  0xfe,  0x02,  0x43,  0x47,  0xfc,
-  0x3a,  0x5b,  0xc2,  0x5f,  0xf4,  0x3e,  0xeb,  0x5f,  0xf8,  0x09,  0x0d,  0x1e,
-  0xde,  0x01,  0xec,  0x66,  0x7c,  0x00,  0xda,  0xd5,  0x93,  0x1c,  0xfd,  0xa5,
-  0x3f,  0x3a,  0x4f,  0xed,  0x8b,  0x2f,  0xf9,  0xf9,  0x4f,  0xce,  0xbf,  0x40,
-  0x3f,  0xe1,  0xd2,  0xde,  0x12,  0xff,  0x00,  0xa1,  0xf7,  0x5a,  0xff,  0x00,
-  0xc0,  0x48,  0x68,  0xff,  0x00,  0x87,  0x4b,  0x78,  0x4b,  0xfe,  0x87,  0xdd,
-  0x6b,  0xff,  0x00,  0x01,  0x21,  0xa7,  0xed,  0xe1,  0xdc,  0x3d,  0x8c,  0xcf,
-  0x81,  0x57,  0x5a,  0xb0,  0x51,  0x8f,  0xb5,  0x47,  0xf9,  0xd1,  0xfd,  0xb9,
-  0x61,  0xff,  0x00,  0x3f,  0x49,  0xf9,  0xd7,  0xdf,  0x5f,  0xf0,  0xe9,  0x6f,
-  0x09,  0x7f,  0xd0,  0xfb,  0xad,  0x7f,  0xe0,  0x24,  0x34,  0x7f,  0xc3,  0xa5,
-  0xbc,  0x25,  0xff,  0x00,  0x43,  0xee,  0xb5,  0xff,  0x00,  0x80,  0x90,  0xd2,
-  0xf6,  0xf0,  0x0f,  0x63,  0x33,  0xe0,  0x06,  0xd6,  0xac,  0x98,  0xe7,  0xed,
-  0x29,  0xf9,  0xd2,  0x0d,  0x62,  0xcb,  0xfe,  0x7e,  0x53,  0xf3,  0xaf,  0xd0,
-  0x0f,  0xf8,  0x74,  0xb7,  0x84,  0xbf,  0xe8,  0x7d,  0xd6,  0xbf,  0xf0,  0x12,
-  0x1a,  0x3f,  0xe1,  0xd2,  0xde,  0x12,  0xff,  0x00,  0xa1,  0xf7,  0x5a,  0xff,
-  0x00,  0xc0,  0x48,  0x69,  0xfb,  0x78,  0x77,  0x0f,  0x63,  0x33,  0xe0,  0x51,
-  0xad,  0xd8,  0x01,  0x8f,  0xb5,  0x47,  0xf9,  0xd0,  0x75,  0xcb,  0x0c,  0x7f,
-  0xc7,  0xca,  0x7e,  0x75,  0xf7,  0xd7,  0xfc,  0x3a,  0x5b,  0xc2,  0x5f,  0xf4,
-  0x3e,  0xeb,  0x5f,  0xf8,  0x09,  0x0d,  0x1f,  0xf0,  0xe9,  0x6f,  0x09,  0x7f,
-  0xd0,  0xfb,  0xad,  0x7f,  0xe0,  0x24,  0x34,  0x7b,  0x78,  0x77,  0x0f,  0x63,
-  0x33,  0xf3,  0xfc,  0xeb,  0x36,  0x44,  0xff,  0x00,  0xc7,  0xca,  0x7e,  0x74,
-  0xa3,  0x58,  0xb1,  0x24,  0x66,  0xe5,  0x31,  0xf5,  0xaf,  0xbf,  0xff,  0x00,
-  0xe1,  0xd2,  0xde,  0x12,  0xff,  0x00,  0xa1,  0xf7,  0x5a,  0xff,  0x00,  0xc0,
-  0x48,  0x68,  0xff,  0x00,  0x87,  0x4b,  0x78,  0x4b,  0xfe,  0x87,  0xdd,  0x6b,
-  0xff,  0x00,  0x01,  0x21,  0xa3,  0xdb,  0xc3,  0xb8,  0x7b,  0x19,  0x9f,  0x02,
-  0xff,  0x00,  0x6d,  0xd8,  0x7f,  0xcf,  0xd4,  0x7f,  0x9d,  0x07,  0x5c,  0xb1,
-  0x03,  0x8b,  0x94,  0xcf,  0xd6,  0xbe,  0xfa,  0xff,  0x00,  0x87,  0x4b,  0x78,
-  0x4b,  0xfe,  0x87,  0xdd,  0x6b,  0xff,  0x00,  0x01,  0x21,  0xa3,  0xfe,  0x1d,
-  0x2d,  0xe1,  0x2f,  0xfa,  0x1f,  0x75,  0xaf,  0xfc,  0x04,  0x86,  0x8f,  0x6f,
-  0x0e,  0xe1,  0xec,  0x66,  0x7e,  0x7f,  0xff,  0x00,  0x6c,  0xd9,  0x7f,  0xcf,
-  0xca,  0x7e,  0x74,  0xab,  0xac,  0x58,  0xe7,  0x9b,  0x94,  0xc7,  0xd6,  0xbe,
-  0xff,  0x00,  0xff,  0x00,  0x87,  0x4b,  0x78,  0x4b,  0xfe,  0x87,  0xdd,  0x6b,
-  0xff,  0x00,  0x01,  0x21,  0xa3,  0xfe,  0x1d,  0x2d,  0xe1,  0x2f,  0xfa,  0x1f,
-  0x75,  0xaf,  0xfc,  0x04,  0x86,  0x8f,  0x6f,  0x0e,  0xe1,  0xec,  0x66,  0x7c,
-  0x0b,  0xfd,  0xb9,  0x61,  0xff,  0x00,  0x3f,  0x51,  0xfe,  0x74,  0x8d,  0xae,
-  0x58,  0xed,  0x38,  0xb9,  0x4c,  0xfd,  0x6b,  0xef,  0xbf,  0xf8,  0x74,  0xb7,
-  0x84,  0xbf,  0xe8,  0x7d,  0xd6,  0xbf,  0xf0,  0x12,  0x1a,  0x3f,  0xe1,  0xd2,
-  0xde,  0x12,  0xff,  0x00,  0xa1,  0xf7,  0x5a,  0xff,  0x00,  0xc0,  0x48,  0x68,
-  0xf6,  0xf0,  0xee,  0x1e,  0xc6,  0x67,  0xe7,  0xff,  0x00,  0xf6,  0xc5,  0x97,
-  0xfc,  0xfc,  0xa7,  0xe7,  0x4e,  0x4d,  0x62,  0xc7,  0x77,  0x37,  0x29,  0xf9,
-  0xd7,  0xdf,  0xdf,  0xf0,  0xe9,  0x6f,  0x09,  0x7f,  0xd0,  0xfb,  0xad,  0x7f,
-  0xe0,  0x24,  0x34,  0x7f,  0xc3,  0xa5,  0xbc,  0x25,  0xff,  0x00,  0x43,  0xee,
-  0xb5,  0xff,  0x00,  0x80,  0x90,  0xd1,  0xed,  0xe1,  0xdc,  0x3d,  0x8c,  0xcf,
-  0x81,  0x7f,  0xb7,  0x2c,  0x3f,  0xe7,  0xea,  0x3f,  0xce,  0x91,  0xf5,  0xcb,
-  0x1c,  0x71,  0x72,  0x9f,  0x9d,  0x7d,  0xf7,  0xff,  0x00,  0x0e,  0x96,  0xf0,
-  0x97,  0xfd,  0x0f,  0xba,  0xd7,  0xfe,  0x02,  0x43,  0x47,  0xfc,  0x3a,  0x5b,
-  0xc2,  0x5f,  0xf4,  0x3e,  0xeb,  0x5f,  0xf8,  0x09,  0x0d,  0x1e,  0xde,  0x1d,
-  0xc3,  0xd8,  0xcc,  0xfc,  0xff,  0x00,  0xfe,  0xd9,  0xb2,  0xff,  0x00,  0x9f,
-  0x94,  0xfc,  0xe9,  0xd1,  0xeb,  0x36,  0x20,  0xe4,  0xdc,  0xa7,  0xe7,  0x5f,
-  0x7f,  0x7f,  0xc3,  0xa5,  0xbc,  0x25,  0xff,  0x00,  0x43,  0xee,  0xb5,  0xff,
-  0x00,  0x80,  0x90,  0xd1,  0xff,  0x00,  0x0e,  0x96,  0xf0,  0x97,  0xfd,  0x0f,
-  0xba,  0xd7,  0xfe,  0x02,  0x43,  0x47,  0xb7,  0x87,  0x70,  0xf6,  0x33,  0x3e,
-  0x05,  0xfe,  0xdc,  0xb0,  0xff,  0x00,  0x9f,  0xa8,  0xff,  0x00,  0x3a,  0x6c,
-  0x9a,  0xdd,  0x89,  0x18,  0x17,  0x29,  0xf9,  0xd7,  0xdf,  0x9f,  0xf0,  0xe9,
-  0x6f,  0x09,  0x7f,  0xd0,  0xfb,  0xad,  0x7f,  0xe0,  0x24,  0x34,  0x7f,  0xc3,
-  0xa5,  0xbc,  0x25,  0xff,  0x00,  0x43,  0xee,  0xb5,  0xff,  0x00,  0x80,  0x90,
-  0xd1,  0xed,  0xe1,  0xdc,  0x3d,  0x8c,  0xcf,  0xbc,  0xa8,  0xa2,  0x8a,  0xf3,
-  0x0e,  0xf0,  0xa2,  0x8a,  0x28,  0x00,  0xa2,  0x8a,  0x28,  0x00,  0xa2,  0x8a,
-  0x28,  0x00,  0xa2,  0x8a,  0x28,  0x00,  0xa2,  0x8a,  0x28,  0x00,  0xa2,  0x8a,
-  0x28,  0x00,  0xa2,  0x8a,  0x28,  0x00,  0xa2,  0xa0,  0xbb,  0xbd,  0xb7,  0xb0,
-  0x88,  0x49,  0x73,  0x3c,  0x56,  0xf1,  0x96,  0x0a,  0x1e,  0x57,  0x0a,  0x09,
-  0x3d,  0x06,  0x4f,  0x7a,  0x9e,  0x95,  0xd3,  0x76,  0xea,  0x01,  0x45,  0x14,
-  0x53,  0x00,  0xa2,  0x8a,  0x28,  0x00,  0xa2,  0x8a,  0x82,  0xda,  0xf6,  0xde,
-  0xf0,  0xca,  0x2d,  0xe7,  0x8a,  0x73,  0x13,  0x98,  0xe4,  0xf2,  0xdc,  0x36,
-  0xc6,  0x1d,  0x54,  0xe3,  0xa1,  0xf6,  0xa4,  0xda,  0x4e,  0xcc,  0x09,  0xe8,
-  0xa2,  0x8a,  0x60,  0x14,  0x51,  0x45,  0x00,  0x14,  0x51,  0x45,  0x00,  0x14,
-  0x51,  0x45,  0x00,  0x14,  0x51,  0x45,  0x00,  0x14,  0x51,  0x45,  0x00,  0x14,
-  0x51,  0x45,  0x00,  0x14,  0x51,  0x45,  0x00,  0x14,  0x51,  0x45,  0x02,  0xb8,
-  0x51,  0x45,  0x14,  0x05,  0xc2,  0x8a,  0x28,  0xa0,  0x2e,  0x14,  0x51,  0x45,
-  0x01,  0x70,  0xa2,  0x8a,  0x28,  0x18,  0x51,  0x45,  0x14,  0x0a,  0xe1,  0x45,
-  0x14,  0x50,  0x17,  0x0a,  0x28,  0xa2,  0x80,  0xb9,  0xca,  0xfc,  0x4a,  0xf0,
-  0x52,  0x78,  0xef,  0xc2,  0xb7,  0x1a,  0x76,  0xef,  0x2e,  0xe5,  0x4f,  0x9d,
-  0x6c,  0xe4,  0xe0,  0x09,  0x00,  0x38,  0xcf,  0xb1,  0xc9,  0x1f,  0x8e,  0x7b,
-  0x57,  0x3d,  0xf0,  0x5b,  0xc7,  0x53,  0x6b,  0xba,  0x6c,  0xda,  0x16,  0xaa,
-  0x5a,  0x3d,  0x73,  0x4a,  0xfd,  0xd4,  0x8b,  0x2f,  0xdf,  0x91,  0x01,  0xc0,
-  0x27,  0xdc,  0x1e,  0x0f,  0xe0,  0x7b,  0xd7,  0xa3,  0x5c,  0xdc,  0xc5,  0x67,
-  0x04,  0x93,  0xcf,  0x2a,  0x43,  0x0c,  0x60,  0xb3,  0xc9,  0x23,  0x05,  0x55,
-  0x1e,  0xa4,  0x9e,  0x95,  0xf3,  0x47,  0xc4,  0x8f,  0x1f,  0xe9,  0x36,  0xdf,
-  0x10,  0xed,  0x3c,  0x41,  0xe1,  0x39,  0x99,  0xaf,  0xa1,  0xe2,  0xea,  0x42,
-  0x98,  0x82,  0x72,  0x38,  0xe3,  0x90,  0x4e,  0x46,  0x41,  0xe9,  0x9c,  0x0c,
-  0x7a,  0xd7,  0xc4,  0x67,  0x98,  0x9a,  0x59,  0x3e,  0x26,  0x9e,  0x64,  0xa6,
-  0x93,  0x7e,  0xec,  0xe3,  0x7d,  0x65,  0x1e,  0xe9,  0x77,  0x8b,  0xd7,  0xd3,
-  0x4b,  0x99,  0x4d,  0xa8,  0xbe,  0x63,  0xe9,  0xca,  0x2b,  0xe4,  0x3d,  0x73,
-  0xe3,  0x3f,  0x8b,  0xb5,  0xc6,  0x6d,  0xfa,  0xb4,  0x96,  0x71,  0x9e,  0x91,
-  0x59,  0x0f,  0x28,  0x0f,  0xc4,  0x7c,  0xdf,  0x99,  0xae,  0x56,  0xe7,  0x5a,
-  0xd4,  0x6f,  0x18,  0xb5,  0xc5,  0xfd,  0xd4,  0xec,  0x7b,  0xc9,  0x33,  0x31,
-  0xfd,  0x4d,  0x78,  0x75,  0xf8,  0xfb,  0x0b,  0x07,  0x6a,  0x14,  0x65,  0x25,
-  0xe6,  0xd2,  0xff,  0x00,  0x32,  0x1d,  0x75,  0xd1,  0x1f,  0x73,  0x51,  0x5f,
-  0x0b,  0xdb,  0xea,  0xf7,  0xf6,  0xad,  0xba,  0x0b,  0xdb,  0x88,  0x58,  0x77,
-  0x8e,  0x56,  0x53,  0xfa,  0x1a,  0xe9,  0xf4,  0x5f,  0x8b,  0xfe,  0x2e,  0xd0,
-  0xd9,  0x7c,  0xad,  0x66,  0x7b,  0x84,  0x1f,  0xf2,  0xce,  0xec,  0xf9,  0xc0,
-  0xff,  0x00,  0xdf,  0x59,  0x23,  0xf0,  0x34,  0xa8,  0x71,  0xf6,  0x1a,  0x4e,
-  0xd5,  0xa8,  0x4a,  0x2b,  0xc9,  0xa7,  0xfe,  0x40,  0xab,  0xae,  0xa8,  0xfa,
-  0x13,  0xe2,  0xff,  0x00,  0x8f,  0xcf,  0x82,  0xfc,  0x3e,  0x21,  0xb3,  0x6d,
-  0xda,  0xcd,  0xfe,  0x62,  0xb5,  0x45,  0xe5,  0x97,  0xb1,  0x7c,  0x7b,  0x67,
-  0x8f,  0x72,  0x3d,  0xea,  0x5f,  0x84,  0x7e,  0x05,  0x6f,  0x04,  0x78,  0x60,
-  0x2d,  0xd1,  0x2d,  0xa9,  0xde,  0xb0,  0x9e,  0xe8,  0x93,  0x9d,  0xad,  0x8e,
-  0x17,  0xf0,  0x1d,  0x4f,  0xa9,  0x35,  0xe2,  0x5e,  0x13,  0xf8,  0x89,  0x61,
-  0xac,  0xfc,  0x49,  0x8f,  0xc4,  0x3e,  0x30,  0x76,  0xcc,  0x68,  0x16,  0xd8,
-  0x43,  0x19,  0x68,  0x61,  0x61,  0xd0,  0x91,  0x92,  0x40,  0x1c,  0x9e,  0x33,
-  0xc9,  0xcd,  0x7d,  0x3b,  0x63,  0x7f,  0x6d,  0xaa,  0x5a,  0x45,  0x75,  0x69,
-  0x3c,  0x77,  0x36,  0xd2,  0x8d,  0xc9,  0x2c,  0x4c,  0x19,  0x58,  0x7b,  0x11,
-  0x5e,  0xde,  0x4d,  0x8b,  0xa3,  0x9d,  0xe3,  0x2a,  0x66,  0x1c,  0xe9,  0xf2,
-  0x5e,  0x30,  0x8f,  0x58,  0xae,  0xb2,  0x6b,  0xbc,  0xbf,  0x05,  0xa1,  0x50,
-  0x6a,  0x6f,  0x98,  0xb1,  0x45,  0x14,  0x57,  0xdc,  0x9b,  0x5c,  0x28,  0xa2,
-  0x8a,  0x02,  0xe1,  0x45,  0x14,  0x50,  0x17,  0x0a,  0x28,  0xa2,  0x80,  0xb8,
-  0x51,  0x45,  0x14,  0x05,  0xc2,  0x8a,  0x28,  0xa0,  0x2e,  0x14,  0x51,  0x45,
-  0x01,  0x70,  0xa2,  0x8a,  0x28,  0x0b,  0x8d,  0xcd,  0x19,  0xa6,  0xe4,  0x51,
-  0x91,  0x55,  0x62,  0x47,  0x66,  0x8c,  0xd3,  0x72,  0x28,  0xc8,  0xa2,  0xc0,
-  0x3b,  0x34,  0x66,  0x9b,  0x91,  0x46,  0x45,  0x16,  0x01,  0xd9,  0xa3,  0x34,
-  0xdc,  0x8a,  0x32,  0x28,  0xb0,  0x0e,  0xcd,  0x19,  0xa6,  0xe4,  0x52,  0xe4,
-  0x51,  0x60,  0xb8,  0xb9,  0xa3,  0x34,  0xdc,  0x8a,  0x32,  0x28,  0xb0,  0x0e,
-  0xdd,  0x46,  0x69,  0xb9,  0x14,  0x64,  0x51,  0x60,  0x1d,  0x9a,  0xa7,  0xac,
-  0x6b,  0x16,  0x9a,  0x0e,  0x9b,  0x71,  0xa8,  0x5f,  0x4c,  0x20,  0xb5,  0x81,
-  0x37,  0xbb,  0x9e,  0xc3,  0xd0,  0x7a,  0x93,  0xd0,  0x0a,  0xb5,  0x91,  0x5f,
-  0x39,  0xfe,  0xd1,  0x1e,  0x37,  0x7d,  0x4b,  0x5a,  0x4f,  0x0f,  0x5b,  0x48,
-  0x45,  0xa5,  0x96,  0x1e,  0x70,  0xa7,  0xef,  0xca,  0x46,  0x40,  0x3f,  0xee,
-  0x83,  0xf9,  0x93,  0xe9,  0x5e,  0x06,  0x79,  0x9a,  0xc3,  0x27,  0xc1,  0x4b,
-  0x12,  0xd5,  0xe5,  0xb4,  0x57,  0x76,  0xff,  0x00,  0xab,  0xbf,  0x24,  0x44,
-  0xe5,  0xca,  0xae,  0x72,  0xbf,  0x12,  0xbe,  0x2a,  0xea,  0x3e,  0x3e,  0xbd,
-  0x78,  0xd5,  0x9e,  0xd3,  0x48,  0x46,  0xfd,  0xd5,  0xa2,  0x9f,  0xbd,  0xe8,
-  0xcf,  0xea,  0x7f,  0x41,  0xdb,  0xd4,  0xc3,  0xe0,  0x5f,  0x85,  0x1a,  0xd7,
-  0x8f,  0xed,  0xe6,  0xb9,  0xb1,  0xf2,  0x2d,  0xed,  0x22,  0x6d,  0x86,  0x7b,
-  0x96,  0x21,  0x59,  0xb1,  0x9c,  0x0c,  0x02,  0x4f,  0x51,  0xf9,  0xd7,  0x19,
-  0x5e,  0xcd,  0xf0,  0x73,  0xe3,  0x16,  0x97,  0xe1,  0x0d,  0x06,  0x4d,  0x23,
-  0x57,  0x49,  0x63,  0x44,  0x95,  0xa5,  0x86,  0x78,  0x53,  0x78,  0x21,  0xba,
-  0xab,  0x0e,  0xb9,  0xcf,  0x7f,  0x7f,  0x6a,  0xfc,  0x1b,  0x2e,  0xa9,  0x87,
-  0xcd,  0xb3,  0x2f,  0x69,  0x9c,  0xd5,  0x6a,  0x2e,  0xfa,  0xde,  0xda,  0xf4,
-  0x57,  0xe8,  0xbf,  0xe1,  0x8e,  0x48,  0xda,  0x52,  0xf7,  0x8f,  0x30,  0xf1,
-  0x57,  0x85,  0x75,  0x0f,  0x06,  0xeb,  0x12,  0x69,  0xba,  0x94,  0x42,  0x3b,
-  0x84,  0x01,  0x83,  0x21,  0xca,  0xba,  0x9e,  0x8c,  0xa7,  0xb8,  0xac,  0x8a,
-  0xed,  0x3e,  0x2c,  0xf8,  0xee,  0x1f,  0x1f,  0xf8,  0x9c,  0x5e,  0xda,  0xc2,
-  0xf0,  0xda,  0x41,  0x08,  0x82,  0x2f,  0x33,  0x01,  0xd8,  0x02,  0x49,  0x63,
-  0xe9,  0xc9,  0x3c,  0x57,  0x17,  0x5e,  0x26,  0x3e,  0x9e,  0x1e,  0x96,  0x2a,
-  0xa4,  0x30,  0xb2,  0xe6,  0xa6,  0x9b,  0xb3,  0xee,  0x88,  0x76,  0xbe,  0x81,
-  0x5a,  0x1a,  0x06,  0x83,  0x7b,  0xe2,  0x7d,  0x5e,  0xdf,  0x4d,  0xd3,  0xe2,
-  0xf3,  0xae,  0xa7,  0x38,  0x55,  0xce,  0x00,  0x00,  0x64,  0x92,  0x7b,  0x00,
-  0x39,  0xac,  0xfa,  0xea,  0x3e,  0x1b,  0x78,  0xc1,  0x7c,  0x0d,  0xe2,  0xcb,
-  0x5d,  0x52,  0x58,  0x4c,  0xf6,  0xe1,  0x5a,  0x39,  0x51,  0x3e,  0xf6,  0xd6,
-  0x18,  0x24,  0x7b,  0x8e,  0x0d,  0x67,  0x83,  0x85,  0x1a,  0x98,  0x8a,  0x70,
-  0xc4,  0x4b,  0x96,  0x0d,  0xae,  0x67,  0xd9,  0x5f,  0x50,  0x56,  0xbe,  0xa6,
-  0x97,  0x8d,  0x7e,  0x0e,  0xeb,  0xde,  0x06,  0xd3,  0x17,  0x50,  0xbb,  0x36,
-  0xf7,  0x56,  0x99,  0x0b,  0x24,  0x96,  0xae,  0x4f,  0x96,  0x4f,  0x4d,  0xc0,
-  0x81,  0xc1,  0x3c,  0x66,  0xa9,  0xfc,  0x3e,  0xf8,  0x93,  0xaa,  0x78,  0x03,
-  0x50,  0x0f,  0x6c,  0xe6,  0x7b,  0x07,  0x6f,  0xdf,  0xd9,  0x3b,  0x7c,  0x8e,
-  0x3d,  0x47,  0xa3,  0x7b,  0xfe,  0x79,  0xaf,  0x45,  0xf8,  0xad,  0xf1,  0xb3,
-  0x47,  0xf1,  0x27,  0x85,  0x26,  0xd2,  0x34,  0x84,  0x9a,  0x67,  0xbb,  0x2b,
-  0xe6,  0xcb,  0x34,  0x7b,  0x04,  0x6a,  0x18,  0x36,  0x07,  0xa9,  0xc8,  0x1e,
-  0xd5,  0xe1,  0x95,  0xf4,  0x39,  0xab,  0xc2,  0x65,  0x79,  0x84,  0x67,  0x93,
-  0x55,  0x6d,  0x24,  0x9d,  0xd3,  0xbd,  0x9f,  0x55,  0x7e,  0xaa,  0xd6,  0xbe,
-  0xfb,  0xd8,  0xb9,  0x5a,  0x32,  0xf7,  0x59,  0xf6,  0xef,  0x86,  0xbc,  0x49,
-  0x63,  0xe2,  0xbd,  0x1a,  0xdf,  0x53,  0xd3,  0xe5,  0xf3,  0x2d,  0xe6,  0x1d,
-  0xfe,  0xf2,  0x1e,  0xea,  0xc3,  0xb1,  0x15,  0xa9,  0x9a,  0xf9,  0x7b,  0xe0,
-  0x27,  0x8d,  0xe4,  0xf0,  0xef,  0x8a,  0x53,  0x4a,  0x9e,  0x43,  0xfd,  0x9f,
-  0xa9,  0x30,  0x8f,  0x69,  0x3c,  0x24,  0xdf,  0xc0,  0xc3,  0xeb,  0xf7,  0x7f,
-  0x11,  0xe9,  0x5f,  0x4f,  0xe4,  0x57,  0xee,  0x3c,  0x3f,  0x9b,  0xc7,  0x39,
-  0xc1,  0x2a,  0xed,  0x5a,  0x6b,  0x49,  0x2f,  0x3f,  0xf2,  0x7b,  0xfe,  0x1d,
-  0x0e,  0xb8,  0x4f,  0x99,  0x5c,  0x76,  0x4d,  0x19,  0xa6,  0xe4,  0x51,  0x91,
-  0x5f,  0x4b,  0x62,  0xc7,  0x64,  0xd1,  0x9a,  0x6e,  0x45,  0x19,  0x14,  0x58,
-  0x2e,  0x3b,  0x34,  0x66,  0x9b,  0x91,  0x46,  0x45,  0x16,  0x0b,  0x8e,  0xcd,
-  0x19,  0xa6,  0xe4,  0x51,  0x91,  0x45,  0x80,  0x76,  0x68,  0xcd,  0x37,  0x34,
-  0x64,  0x51,  0x60,  0xb8,  0xec,  0xd1,  0x9a,  0x6e,  0x45,  0x19,  0x14,  0x58,
-  0x07,  0x64,  0xd1,  0x9a,  0x6e,  0x45,  0x19,  0x14,  0x58,  0x06,  0x6e,  0xa3,
-  0x75,  0x37,  0x34,  0x66,  0xae,  0xc4,  0x5c,  0x76,  0xea,  0x37,  0x53,  0x73,
-  0x46,  0x68,  0xb0,  0x5c,  0x76,  0xea,  0x37,  0x53,  0x73,  0x46,  0x68,  0xb0,
-  0x5c,  0x76,  0xea,  0x37,  0x53,  0x72,  0x28,  0xcd,  0x16,  0x0b,  0x8e,  0xdd,
-  0x46,  0xea,  0x6e,  0x68,  0xcd,  0x16,  0x0b,  0x8e,  0xdd,  0x46,  0xea,  0x6e,
-  0x68,  0xcd,  0x16,  0x0b,  0x8e,  0xdd,  0x46,  0xea,  0xc4,  0xf1,  0x57,  0x8c,
-  0x34,  0xaf,  0x06,  0x69,  0xff,  0x00,  0x6b,  0xd5,  0x2e,  0x44,  0x28,  0xc7,
-  0x08,  0x8a,  0x37,  0x3c,  0x87,  0xd1,  0x47,  0x7f,  0xe5,  0x5c,  0x0d,  0x9f,
-  0xed,  0x1f,  0xe1,  0xcb,  0x8b,  0xc1,  0x14,  0xd6,  0x97,  0xf6,  0xb0,  0x93,
-  0x81,  0x3b,  0xa2,  0xb0,  0x1e,  0xe4,  0x06,  0x27,  0xf2,  0xcd,  0x78,  0xf8,
-  0xac,  0xdf,  0x2f,  0xc0,  0xd4,  0x54,  0x71,  0x35,  0xa3,  0x19,  0x3e,  0x8d,
-  0xfe,  0x7d,  0xbe,  0x64,  0xb9,  0x25,  0xb9,  0xeb,  0x05,  0xf6,  0x82,  0x4f,
-  0x41,  0x5f,  0x10,  0xeb,  0x7a,  0x93,  0xeb,  0x3a,  0xcd,  0xf5,  0xfc,  0x84,
-  0x97,  0xb9,  0x9d,  0xe6,  0x39,  0xff,  0x00,  0x69,  0x89,  0xfe,  0xb5,  0xf6,
-  0xad,  0x8e,  0xa1,  0x6b,  0xab,  0x58,  0xc5,  0x75,  0x69,  0x34,  0x77,  0x36,
-  0xb3,  0x2e,  0xe4,  0x91,  0x0e,  0x55,  0x85,  0x78,  0x5f,  0xfc,  0x2d,  0x5f,
-  0x87,  0x3f,  0xf4,  0x25,  0x27,  0xfe,  0x00,  0xdb,  0xff,  0x00,  0x8d,  0x7c,
-  0x67,  0x18,  0xe1,  0xa8,  0x63,  0x61,  0x87,  0x55,  0x31,  0x31,  0xa7,  0x1f,
-  0x79,  0xab,  0xdd,  0xf3,  0x7c,  0x3a,  0xab,  0x76,  0xfd,  0x4c,  0xea,  0x59,
-  0xdb,  0x53,  0xc4,  0x68,  0xaf,  0x6e,  0xff,  0x00,  0x85,  0xab,  0xf0,  0xe7,
-  0xfe,  0x84,  0xa4,  0xff,  0x00,  0xc0,  0x1b,  0x7f,  0xf1,  0xa3,  0xfe,  0x16,
-  0xaf,  0xc3,  0x9f,  0xfa,  0x12,  0x93,  0xff,  0x00,  0x00,  0x6d,  0xff,  0x00,
-  0xc6,  0xbf,  0x33,  0xfe,  0xc5,  0xc0,  0xff,  0x00,  0xd0,  0x7c,  0x3e,  0xe9,
-  0x7f,  0x91,  0x8f,  0x2a,  0xee,  0x78,  0x8d,  0x15,  0xed,  0xdf,  0xf0,  0xb5,
-  0x7e,  0x1c,  0xff,  0x00,  0xd0,  0x94,  0x9f,  0xf8,  0x03,  0x6f,  0xfe,  0x34,
-  0x7f,  0xc2,  0xd5,  0xf8,  0x73,  0xff,  0x00,  0x42,  0x52,  0x7f,  0xe0,  0x0d,
-  0xbf,  0xf8,  0xd1,  0xfd,  0x8b,  0x81,  0xff,  0x00,  0xa0,  0xf8,  0x7d,  0xd2,
-  0xff,  0x00,  0x20,  0xe5,  0x5d,  0xcf,  0x11,  0xa2,  0xbd,  0xbb,  0xfe,  0x16,
-  0xaf,  0xc3,  0x9f,  0xfa,  0x12,  0x93,  0xff,  0x00,  0x00,  0x6d,  0xff,  0x00,
-  0xc6,  0x8f,  0xf8,  0x5a,  0xbf,  0x0e,  0x7f,  0xe8,  0x4a,  0x4f,  0xfc,  0x01,
-  0xb7,  0xff,  0x00,  0x1a,  0x3f,  0xb1,  0x70,  0x3f,  0xf4,  0x1f,  0x0f,  0xba,
-  0x5f,  0xe4,  0x1c,  0xab,  0xb9,  0xe2,  0x34,  0x57,  0xb7,  0x7f,  0xc2,  0xd5,
-  0xf8,  0x73,  0xff,  0x00,  0x42,  0x52,  0x7f,  0xe0,  0x0d,  0xbf,  0xf8,  0xd1,
-  0xff,  0x00,  0x0b,  0x57,  0xe1,  0xcf,  0xfd,  0x09,  0x49,  0xff,  0x00,  0x80,
-  0x36,  0xff,  0x00,  0xe3,  0x47,  0xf6,  0x2e,  0x07,  0xfe,  0x83,  0xe1,  0xf7,
-  0x4b,  0xfc,  0x83,  0x95,  0x77,  0x3c,  0x52,  0x09,  0xde,  0xda,  0x78,  0xe6,
-  0x89,  0x8a,  0x49,  0x1b,  0x07,  0x56,  0x1d,  0x41,  0x07,  0x20,  0xd7,  0xdb,
-  0xfa,  0x5d,  0xf0,  0xd4,  0x74,  0xdb,  0x4b,  0xb0,  0x30,  0x27,  0x85,  0x25,
-  0x03,  0xfd,  0xe5,  0x07,  0xfa,  0xd7,  0x85,  0xff,  0x00,  0xc2,  0xd5,  0xf8,
-  0x73,  0xff,  0x00,  0x42,  0x52,  0x7f,  0xe0,  0x0d,  0xbf,  0xf8,  0xd7,  0xb6,
-  0x69,  0x1a,  0x95,  0xa5,  0xc7,  0x87,  0xec,  0xaf,  0xe1,  0x55,  0xb3,  0xb1,
-  0x7b,  0x54,  0x99,  0x11,  0xf0,  0x82,  0x28,  0xca,  0x02,  0x01,  0xec,  0x30,
-  0x3f,  0x0e,  0x2b,  0xf4,  0x7e,  0x0e,  0xc2,  0xd0,  0xc1,  0xce,  0xbc,  0x69,
-  0x62,  0x63,  0x51,  0x34,  0x9b,  0x4a,  0xfa,  0x5a,  0xfa,  0xeb,  0xea,  0x6d,
-  0x4e,  0xca,  0xfa,  0x9a,  0x5b,  0xa8,  0xdd,  0x5e,  0x57,  0xab,  0xfe,  0xd1,
-  0x3e,  0x1b,  0xd3,  0xaf,  0x1a,  0x0b,  0x68,  0x6e,  0xf5,  0x15,  0x53,  0x83,
-  0x34,  0x28,  0xaa,  0x87,  0xe9,  0xb8,  0x82,  0x7f,  0x2a,  0xeb,  0xbc,  0x1b,
-  0xf1,  0x07,  0x45,  0xf1,  0xcd,  0xbb,  0xbe,  0x99,  0x70,  0x7c,  0xe8,  0xc6,
-  0x64,  0xb6,  0x98,  0x6d,  0x91,  0x07,  0xa9,  0x1d,  0xc7,  0xb8,  0xc8,  0xaf,
-  0xb7,  0xc3,  0xe7,  0x19,  0x76,  0x2a,  0xb7,  0xd5,  0xe8,  0x56,  0x8c,  0xa7,
-  0xd9,  0x3f,  0xcb,  0xbf,  0xc8,  0xd1,  0x49,  0x3d,  0x2e,  0x74,  0xdb,  0xa8,
-  0xcd,  0x37,  0x34,  0x64,  0x57,  0xb2,  0x55,  0xc7,  0x6e,  0xa3,  0x75,  0x37,
-  0x34,  0x66,  0x8b,  0x05,  0xc7,  0x6e,  0xa3,  0x75,  0x37,  0x34,  0x66,  0x8b,
-  0x05,  0xc7,  0x6e,  0xa3,  0x75,  0x37,  0x34,  0x66,  0x8b,  0x05,  0xc7,  0x6e,
-  0xa3,  0x75,  0x37,  0x34,  0x64,  0x51,  0x60,  0xb8,  0xed,  0xd4,  0x6e,  0xa6,
-  0xe4,  0x51,  0x9a,  0x2c,  0x17,  0x1b,  0x9a,  0x33,  0x51,  0xee,  0xa3,  0x75,
-  0x55,  0x88,  0xb9,  0x26,  0x68,  0xcd,  0x47,  0xba,  0x8d,  0xd4,  0x58,  0x2e,
-  0x49,  0x9a,  0x33,  0x51,  0xee,  0xa3,  0x75,  0x16,  0x15,  0xc9,  0x32,  0x28,
-  0xa8,  0xf7,  0x51,  0xba,  0x8b,  0x0e,  0xe4,  0x99,  0xa3,  0x35,  0x1e,  0xea,
-  0x37,  0x51,  0x60,  0xb9,  0x26,  0x68,  0xcd,  0x47,  0xba,  0x8c,  0xd3,  0xb0,
-  0x5c,  0xf9,  0x7b,  0xe3,  0xb6,  0xaf,  0x3e,  0xa5,  0xf1,  0x0e,  0xf2,  0xde,
-  0x47,  0x26,  0x1b,  0x24,  0x48,  0x62,  0x4e,  0xc0,  0x15,  0x0c,  0x4f,  0xe2,
-  0x58,  0xfe,  0x95,  0xe7,  0x95,  0xda,  0x7c,  0x64,  0xff,  0x00,  0x92,  0x97,
-  0xad,  0xff,  0x00,  0xbf,  0x1f,  0xfe,  0x8a,  0x4a,  0xe2,  0xeb,  0xf9,  0x47,
-  0x3a,  0x9c,  0xaa,  0x66,  0x78,  0x99,  0x49,  0xdd,  0xf3,  0xcb,  0xf0,  0x6d,
-  0x23,  0x92,  0x5b,  0x9e,  0xf7,  0xfb,  0x34,  0xeb,  0x13,  0xcd,  0x67,  0xac,
-  0xe9,  0xb2,  0x39,  0x6b,  0x78,  0x1a,  0x39,  0xa2,  0x04,  0xfd,  0xd2,  0xdb,
-  0x83,  0x0f,  0xc7,  0x68,  0xfd,  0x6b,  0xc1,  0x2b,  0xda,  0xff,  0x00,  0x66,
-  0x73,  0x8b,  0xed,  0x7f,  0xfe,  0xb9,  0xc3,  0xfc,  0xde,  0xbc,  0x52,  0xbd,
-  0x8c,  0xd2,  0x72,  0x9e,  0x4b,  0x97,  0x39,  0x3b,  0xdb,  0xda,  0xaf,  0x92,
-  0x92,  0xb1,  0x4f,  0xe1,  0x41,  0x45,  0x14,  0x57,  0xc6,  0x90,  0x14,  0x51,
-  0x45,  0x00,  0x14,  0x51,  0x45,  0x00,  0x14,  0x51,  0x45,  0x00,  0x15,  0xef,
-  0x7f,  0x13,  0xf5,  0x89,  0xf4,  0xef,  0x82,  0xbe,  0x19,  0xb6,  0x81,  0xca,
-  0x0b,  0xc8,  0x2d,  0x62,  0x94,  0x83,  0xd5,  0x04,  0x3b,  0x88,  0xfc,  0x48,
-  0x15,  0xe0,  0x95,  0xed,  0x7f,  0x17,  0x0f,  0xfc,  0x5a,  0x5f,  0x05,  0xff,
-  0x00,  0xd7,  0x38,  0x3f,  0xf4,  0x45,  0x7d,  0x96,  0x47,  0x39,  0x43,  0x03,
-  0x98,  0x4a,  0x2e,  0xcf,  0x91,  0x7e,  0x32,  0xb3,  0xfc,  0x0a,  0x8e,  0xcc,
-  0xf1,  0x4a,  0xe9,  0xbe,  0x1a,  0x6a,  0xf3,  0xe8,  0xbe,  0x3a,  0xd1,  0x67,
-  0x81,  0xca,  0x99,  0x2e,  0x52,  0x07,  0x00,  0xfd,  0xe4,  0x76,  0x0a,  0xc0,
-  0xfe,  0x07,  0xf4,  0xae,  0x66,  0xb6,  0x3c,  0x1b,  0xff,  0x00,  0x23,  0x7e,
-  0x87,  0xff,  0x00,  0x5f,  0xd0,  0x7f,  0xe8,  0xc5,  0xaf,  0x9b,  0xc0,  0xce,
-  0x54,  0xf1,  0x54,  0xa7,  0x07,  0x66,  0xa4,  0xbf,  0x31,  0x2d,  0xcf,  0xb4,
-  0x33,  0x46,  0x6a,  0x3d,  0xd4,  0x6e,  0xaf,  0xeb,  0x9b,  0x1d,  0x57,  0x24,
-  0xcd,  0x19,  0xa8,  0xf7,  0x51,  0xba,  0x8b,  0x0e,  0xe4,  0x99,  0xa3,  0x35,
-  0x1e,  0xea,  0x37,  0x51,  0x60,  0xb9,  0x26,  0x68,  0xcd,  0x47,  0xba,  0x8d,
-  0xd4,  0x58,  0x2e,  0x49,  0x9a,  0x33,  0x51,  0xee,  0xa3,  0x75,  0x16,  0x15,
-  0xc9,  0x33,  0x46,  0x6a,  0x3d,  0xd4,  0x6e,  0xa2,  0xc3,  0xb8,  0xdd,  0xd4,
-  0x9b,  0xa9,  0xbb,  0xa8,  0xdd,  0x5a,  0x19,  0xdc,  0x7e,  0xea,  0x4d,  0xd4,
-  0xdd,  0xd4,  0x6e,  0xa0,  0x57,  0x1f,  0xba,  0x8d,  0xd4,  0xcd,  0xd4,  0x6e,
-  0xa0,  0x77,  0x1f,  0xba,  0x8d,  0xd4,  0xcd,  0xd4,  0x6e,  0xa4,  0x2b,  0x8f,
-  0xdd,  0x49,  0xba,  0x9b,  0xba,  0x8d,  0xd4,  0xc2,  0xe3,  0xb7,  0x52,  0xee,
-  0xa6,  0x6e,  0xa3,  0x75,  0x20,  0xb9,  0xf2,  0x9f,  0xc6,  0x3f,  0xf9,  0x29,
-  0x5a,  0xdf,  0xfb,  0xf1,  0xff,  0x00,  0xe8,  0xb4,  0xae,  0x32,  0xbb,  0x2f,
-  0x8c,  0x5c,  0xfc,  0x49,  0xd6,  0xff,  0x00,  0xdf,  0x8f,  0xff,  0x00,  0x45,
-  0xa5,  0x71,  0xb5,  0xfc,  0x99,  0x9c,  0x7f,  0xc8,  0xcb,  0x13,  0xfe,  0x39,
-  0xff,  0x00,  0xe9,  0x4c,  0xc1,  0xee,  0x7b,  0x57,  0xec,  0xd2,  0x71,  0x7d,
-  0xaf,  0x7f,  0xd7,  0x38,  0x7f,  0x9b,  0xd7,  0x8a,  0xd7,  0xb4,  0x7e,  0xcd,
-  0x67,  0x17,  0xda,  0xf7,  0xfd,  0x73,  0x87,  0xf9,  0xbd,  0x78,  0xbd,  0x7b,
-  0x19,  0x97,  0xfc,  0x89,  0x32,  0xef,  0xfb,  0x8b,  0xff,  0x00,  0xa5,  0x21,
-  0xbd,  0x90,  0x51,  0x45,  0x15,  0xf2,  0x02,  0x0a,  0x28,  0xa2,  0x80,  0x0a,
-  0x28,  0xa2,  0x80,  0x0a,  0x28,  0xa2,  0x80,  0x0a,  0xf6,  0xaf,  0x8b,  0x47,
-  0x3f,  0x09,  0x7c,  0x17,  0xff,  0x00,  0x5c,  0xe0,  0xff,  0x00,  0xd1,  0x15,
-  0xe2,  0xb5,  0xed,  0x1f,  0x16,  0x4f,  0xfc,  0x5a,  0x6f,  0x06,  0x7f,  0xd7,
-  0x38,  0x3f,  0xf4,  0x45,  0x7d,  0x7e,  0x4d,  0xff,  0x00,  0x22,  0xfc,  0xc3,
-  0xfc,  0x11,  0xff,  0x00,  0xd2,  0x90,  0xd6,  0xcc,  0xf1,  0x7a,  0xd8,  0xf0,
-  0x67,  0xfc,  0x8e,  0x1a,  0x17,  0xfd,  0x7f,  0xc1,  0xff,  0x00,  0xa3,  0x16,
-  0xb1,  0xeb,  0x63,  0xc1,  0xdf,  0xf2,  0x37,  0x68,  0x7f,  0xf5,  0xfd,  0x07,
-  0xfe,  0x8c,  0x5a,  0xf9,  0xbc,  0x27,  0xfb,  0xcd,  0x3f,  0xf1,  0x2f,  0xcc,
-  0x48,  0xfb,  0x2b,  0x75,  0x1b,  0xa9,  0x9b,  0xa8,  0xdd,  0x5f,  0xd8,  0x16,
-  0x37,  0xb8,  0xfd,  0xd4,  0x6e,  0xa6,  0x6e,  0xa3,  0x75,  0x20,  0xb8,  0xed,
-  0xd4,  0xbb,  0xa9,  0x9b,  0xa8,  0xdd,  0x4c,  0x2e,  0x3f,  0x75,  0x26,  0xea,
-  0x6e,  0xea,  0x37,  0x52,  0x0b,  0x8f,  0xdd,  0x49,  0xba,  0x9b,  0xba,  0x8d,
-  0xd4,  0xec,  0x3b,  0x8f,  0xdd,  0x49,  0xba,  0x9b,  0xba,  0x8d,  0xd4,  0x0a,
-  0xe4,  0x74,  0x53,  0x33,  0x4b,  0x93,  0x57,  0x63,  0x3b,  0x8e,  0xa2,  0x9b,
-  0x9a,  0x4c,  0xd1,  0x60,  0xb8,  0xfa,  0x29,  0x99,  0xa3,  0x34,  0x58,  0x2e,
-  0x3f,  0x34,  0x53,  0x33,  0x4b,  0x93,  0x45,  0x82,  0xe3,  0xa8,  0xcd,  0x33,
-  0x34,  0x66,  0x8b,  0x05,  0xc7,  0xd1,  0x4d,  0xc9,  0xa3,  0x26,  0x8b,  0x05,
-  0xcf,  0x96,  0x3e,  0x30,  0x7f,  0xc9,  0x48,  0xd6,  0xbf,  0xdf,  0x8f,  0xff,
-  0x00,  0x45,  0xa5,  0x71,  0xb5,  0xdd,  0xfc,  0x6c,  0xd3,  0xa6,  0xb1,  0xf8,
-  0x85,  0x7f,  0x2c,  0x8a,  0x44,  0x77,  0x4b,  0x1c,  0xd1,  0xb7,  0x66,  0x1b,
-  0x02,  0x9f,  0xd5,  0x4d,  0x70,  0x95,  0xfc,  0x97,  0x9d,  0x42,  0x50,  0xcc,
-  0xf1,  0x31,  0x92,  0xb7,  0xbf,  0x2f,  0xfd,  0x29,  0x90,  0x7b,  0x3f,  0xec,
-  0xdb,  0xff,  0x00,  0x1f,  0xba,  0xef,  0xfd,  0x73,  0x87,  0xf9,  0xbd,  0x78,
-  0xc5,  0x7b,  0x87,  0xec,  0xe3,  0xa7,  0x4d,  0x1c,  0x3a,  0xd5,  0xf3,  0x29,
-  0x58,  0x24,  0x31,  0xc2,  0x8d,  0xfd,  0xe2,  0x37,  0x16,  0xfc,  0xb2,  0x3f,
-  0x3a,  0xf0,  0xfa,  0xf6,  0x73,  0x58,  0x4a,  0x19,  0x26,  0x5b,  0xcc,  0xad,
-  0x7f,  0x6a,  0xff,  0x00,  0xf2,  0x64,  0x01,  0x45,  0x14,  0x57,  0xc6,  0x00,
-  0x51,  0x45,  0x14,  0x00,  0x51,  0x45,  0x14,  0x00,  0x51,  0x45,  0x14,  0x00,
-  0x57,  0xb3,  0xfc,  0x57,  0xff,  0x00,  0x92,  0x51,  0xe0,  0xdf,  0xfa,  0xe7,
-  0x07,  0xfe,  0x88,  0xaf,  0x18,  0xaf,  0x70,  0xf8,  0x9b,  0xa7,  0x4d,  0x79,
-  0xf0,  0x77,  0xc3,  0x37,  0x11,  0x29,  0x74,  0xb5,  0x8a,  0xd9,  0xe4,  0xc7,
-  0x65,  0x30,  0xed,  0xcf,  0xe6,  0x40,  0xfc,  0x6b,  0xec,  0xf2,  0x38,  0x4a,
-  0x78,  0x0c,  0xc1,  0x45,  0x5f,  0xdc,  0x5f,  0x84,  0xae,  0xc0,  0xf0,  0xfa,
-  0xd8,  0xf0,  0x6f,  0xfc,  0x8d,  0xfa,  0x1f,  0xfd,  0x7f,  0x41,  0xff,  0x00,
-  0xa3,  0x16,  0xb1,  0xeb,  0xa2,  0xf8,  0x79,  0xa7,  0x4d,  0xaa,  0x78,  0xdf,
-  0x45,  0x86,  0x15,  0x2c,  0xcb,  0x75,  0x1c,  0xad,  0x8e,  0xca,  0x8c,  0x18,
-  0x9f,  0xc8,  0x57,  0xcd,  0x60,  0x61,  0x29,  0xe2,  0xe9,  0x46,  0x2a,  0xed,
-  0xca,  0x3f,  0x9a,  0x03,  0xeb,  0x9c,  0xd1,  0x4c,  0xcd,  0x2e,  0x4d,  0x7f,
-  0x60,  0x58,  0xbb,  0x8e,  0xa2,  0x99,  0x9a,  0x33,  0x45,  0x82,  0xe3,  0xe8,
-  0xa6,  0x66,  0x8c,  0xd1,  0x60,  0xb8,  0xfa,  0x29,  0x99,  0xa5,  0xc9,  0xa2,
-  0xc1,  0x71,  0xd9,  0xa2,  0x9b,  0x93,  0x49,  0x9a,  0x2c,  0x17,  0x1f,  0x45,
-  0x33,  0x34,  0x66,  0x8b,  0x05,  0xc6,  0x6e,  0xa3,  0x75,  0x30,  0x90,  0x3a,
-  0x9c,  0x51,  0x9a,  0xd2,  0xc6,  0x57,  0x1f,  0xba,  0x8d,  0xd4,  0xda,  0x4c,
-  0xd1,  0x60,  0xb8,  0xfd,  0xd4,  0x6e,  0xa6,  0x02,  0x0f,  0x43,  0x9a,  0x37,
-  0x01,  0xdf,  0x14,  0x58,  0x2e,  0x3f,  0x75,  0x1b,  0xa9,  0xb4,  0x94,  0x58,
-  0x2e,  0x3f,  0x75,  0x1b,  0xa9,  0xb4,  0x80,  0x83,  0xd0,  0xe6,  0x8b,  0x05,
-  0xc7,  0xee,  0xa3,  0x75,  0x30,  0x90,  0x3a,  0x9c,  0x51,  0x9a,  0x2c,  0x17,
-  0x31,  0x3c,  0x5d,  0xe0,  0xcd,  0x2f,  0xc6,  0xb6,  0x2b,  0x6f,  0xa8,  0xc4,
-  0x4b,  0x26,  0x4c,  0x53,  0xc6,  0x71,  0x24,  0x64,  0xf5,  0xc1,  0xfe,  0x87,
-  0x8a,  0xe0,  0x6d,  0x3f,  0x67,  0x7d,  0x32,  0x2b,  0xb0,  0xf7,  0x1a,  0xad,
-  0xcc,  0xf6,  0xe0,  0xe7,  0xca,  0x58,  0xd5,  0x09,  0x1e,  0x85,  0xb2,  0x7f,
-  0x95,  0x7a,  0xd5,  0x25,  0x78,  0x38,  0xcc,  0x87,  0x2c,  0xcc,  0x2b,  0x2a,
-  0xf8,  0x9a,  0x2a,  0x52,  0xef,  0xaa,  0xfb,  0xec,  0xd5,  0xfe,  0x77,  0x0b,
-  0x95,  0xf4,  0xad,  0x32,  0xd3,  0x44,  0xb0,  0x86,  0xca,  0xc6,  0x05,  0xb7,
-  0xb6,  0x88,  0x61,  0x23,  0x4e,  0x83,  0xfc,  0x4f,  0xbd,  0x7c,  0x6b,  0x5f,
-  0x69,  0x57,  0xc5,  0xb5,  0xf9,  0x8f,  0x88,  0xb0,  0x8d,  0x38,  0xe0,  0xe1,
-  0x05,  0x64,  0xb9,  0xec,  0x97,  0xfd,  0xb8,  0x34,  0x14,  0x51,  0x45,  0x7e,
-  0x32,  0x30,  0xa2,  0x8a,  0x28,  0x00,  0xa2,  0x8a,  0x28,  0x00,  0xa2,  0x8a,
-  0x28,  0x00,  0xaf,  0xad,  0xfc,  0x2b,  0x04,  0x57,  0x9e,  0x06,  0xd1,  0xad,
-  0xe7,  0x8d,  0x66,  0x86,  0x4d,  0x3a,  0x04,  0x78,  0xdc,  0x65,  0x58,  0x18,
-  0xd7,  0x20,  0x8a,  0xf9,  0x22,  0xbe,  0xba,  0xf0,  0x67,  0xfc,  0x89,  0xfa,
-  0x17,  0xfd,  0x78,  0x41,  0xff,  0x00,  0xa2,  0xd6,  0xbf,  0x5c,  0xf0,  0xee,
-  0x2a,  0x58,  0x9c,  0x42,  0x7b,  0x72,  0xaf,  0xcc,  0x47,  0x05,  0xab,  0x7e,
-  0xcf,  0x7a,  0x4d,  0xdd,  0xdb,  0x4b,  0x65,  0xa8,  0x4f,  0x63,  0x13,  0x1c,
-  0xf9,  0x25,  0x04,  0x80,  0x7b,  0x02,  0x48,  0x3f,  0x9e,  0x6b,  0xaf,  0xf0,
-  0x57,  0xc3,  0xcd,  0x27,  0xc0,  0xd1,  0xb9,  0xb3,  0x47,  0x9a,  0xee,  0x41,
-  0xb6,  0x4b,  0xa9,  0xb0,  0x5c,  0x8f,  0x41,  0xe8,  0x3d,  0x87,  0xe3,  0x5d,
-  0x36,  0x69,  0x6b,  0xf5,  0x7c,  0x37,  0x0f,  0xe5,  0x78,  0x3a,  0xff,  0x00,
-  0x59,  0xa1,  0x41,  0x46,  0x7d,  0xf5,  0xd3,  0xd1,  0x6c,  0xbe,  0x49,  0x0a,
-  0xe3,  0xb7,  0x51,  0xba,  0x99,  0x9a,  0x03,  0x03,  0xde,  0xbd,  0xfb,  0x05,
-  0xc7,  0xee,  0xa3,  0x75,  0x30,  0x90,  0x06,  0x4f,  0x14,  0x51,  0x60,  0xb8,
-  0xfd,  0xd4,  0x6e,  0xa6,  0xd1,  0x45,  0x82,  0xe3,  0xb7,  0x51,  0xba,  0x98,
-  0x08,  0x3d,  0x0e,  0x68,  0x24,  0x0e,  0xf4,  0x58,  0x2e,  0x3f,  0x75,  0x1b,
-  0xa9,  0x94,  0xb4,  0x58,  0x2e,  0x3b,  0x75,  0x1b,  0xa9,  0x99,  0xa0,  0x10,
-  0x7a,  0x1a,  0x2c,  0x17,  0x31,  0x62,  0xbd,  0x91,  0x46,  0xf7,  0x90,  0x3e,
-  0xd3,  0xf7,  0x1b,  0xa9,  0xad,  0x58,  0xa5,  0x13,  0x46,  0xae,  0xbd,  0x08,
-  0xac,  0x3f,  0x38,  0xff,  0x00,  0x71,  0x3f,  0xef,  0x91,  0x56,  0x52,  0xf1,
-  0xe3,  0x48,  0x55,  0x42,  0x80,  0x7a,  0x80,  0x3d,  0xeb,  0xb2,  0x70,  0xbe,
-  0xc7,  0x9d,  0x4e,  0xaf,  0x2e,  0xec,  0xd6,  0xcd,  0x36,  0x59,  0x44,  0x31,
-  0xb3,  0xb7,  0x41,  0x49,  0xba,  0xb3,  0x1e,  0xf2,  0x49,  0x12,  0x65,  0x60,
-  0x08,  0x1d,  0x01,  0x1e,  0xf5,  0x84,  0x61,  0xcc,  0x75,  0x4e,  0xa7,  0x22,
-  0x1b,  0x2d,  0xec,  0x8c,  0x0b,  0xa4,  0x81,  0x37,  0x1f,  0xb8,  0xbd,  0x7e,
-  0xb4,  0xb1,  0x5e,  0xc8,  0xa0,  0x3b,  0xb8,  0x7d,  0xa7,  0xee,  0x37,  0x5f,
-  0xad,  0x57,  0xf3,  0x8f,  0xf7,  0x13,  0xfe,  0xf9,  0x14,  0x79,  0xc7,  0xfb,
-  0x89,  0xff,  0x00,  0x7c,  0x8a,  0xeb,  0xe5,  0x56,  0xb5,  0x8e,  0x0e,  0x77,
-  0x7b,  0xdc,  0xdd,  0x8e,  0x41,  0x2a,  0x2b,  0xaf,  0x42,  0x33,  0x4e,  0xac,
-  0xa8,  0xef,  0x1d,  0x3c,  0x85,  0x00,  0x05,  0x3d,  0x40,  0x1e,  0xe6,  0xb4,
-  0x77,  0x57,  0x24,  0xa3,  0xca,  0x77,  0xc2,  0x7c,  0xe8,  0x74,  0x92,  0x08,
-  0xd1,  0x99,  0x8f,  0x00,  0x66,  0xb2,  0xa5,  0xbd,  0x91,  0x81,  0x74,  0x70,
-  0x99,  0x38,  0xd8,  0x3a,  0xfd,  0x69,  0xd2,  0x5e,  0x3b,  0xf9,  0xea,  0x40,
-  0x2a,  0x3a,  0x02,  0x3d,  0xc5,  0x55,  0xf3,  0x8f,  0xf7,  0x13,  0xfe,  0xf9,
-  0x15,  0xbc,  0x21,  0x6d,  0xce,  0x6a,  0x95,  0x6f,  0xa2,  0x64,  0xf1,  0x5e,
-  0x48,  0xa3,  0x7b,  0x48,  0x1f,  0x69,  0xfb,  0x8d,  0xd4,  0xd6,  0xac,  0x52,
-  0x89,  0xa3,  0x57,  0x5e,  0x86,  0xb0,  0xfc,  0xe3,  0xfd,  0xc4,  0xff,  0x00,
-  0xbe,  0x45,  0x59,  0x4b,  0xc7,  0x8d,  0x61,  0x0a,  0x14,  0x03,  0xd4,  0x01,
-  0xef,  0x44,  0xe1,  0x7d,  0x85,  0x4e,  0xaf,  0x2e,  0xec,  0xd6,  0xcd,  0x15,
-  0x1e,  0xea,  0x5d,  0xd5,  0xcd,  0x63,  0xba,  0xe3,  0xeb,  0xc0,  0xbc,  0x71,
-  0xf0,  0x57,  0x55,  0x83,  0x57,  0x9e,  0xe7,  0x44,  0x85,  0x6f,  0x6c,  0xa6,
-  0x72,  0xe2,  0x25,  0x70,  0xaf,  0x16,  0x4e,  0x76,  0xe0,  0x91,  0x91,  0xe9,
-  0x8a,  0xf7,  0xad,  0xd4,  0x66,  0xbe,  0x7f,  0x39,  0xc8,  0xf0,  0x99,  0xe5,
-  0x18,  0xd2,  0xc4,  0xdd,  0x72,  0xbb,  0xa6,  0xb7,  0x5d,  0xfb,  0xef,  0xe8,
-  0x17,  0xb1,  0xf2,  0xc5,  0xff,  0x00,  0xc3,  0x5f,  0x12,  0xe9,  0x96,  0x53,
-  0x5d,  0xdd,  0x69,  0x52,  0x43,  0x6f,  0x0a,  0x97,  0x92,  0x42,  0xe8,  0x42,
-  0x81,  0xd4,  0xf0,  0x6b,  0x99,  0xaf,  0xaa,  0xfe,  0x21,  0x9c,  0xf8,  0x1f,
-  0x5c,  0xff,  0x00,  0xaf,  0x47,  0xfe,  0x55,  0xf2,  0xa5,  0x7e,  0x01,  0xc5,
-  0x59,  0x1e,  0x1f,  0x22,  0xc4,  0x53,  0xa3,  0x87,  0x93,  0x92,  0x94,  0x6f,
-  0xef,  0x5b,  0xbd,  0xba,  0x24,  0x5a,  0x77,  0x0a,  0xe9,  0xec,  0xbe,  0x19,
-  0xf8,  0x9b,  0x51,  0xb3,  0x86,  0xea,  0xdb,  0x49,  0x92,  0x5b,  0x79,  0x90,
-  0x49,  0x1b,  0x87,  0x40,  0x19,  0x48,  0xc8,  0x3d,  0x6b,  0x98,  0xaf,  0xac,
-  0x3c,  0x08,  0x71,  0xe0,  0xad,  0x0b,  0xfe,  0xbc,  0xa1,  0xff,  0x00,  0xd0,
-  0x05,  0x57,  0x0a,  0xe4,  0x58,  0x7c,  0xf6,  0xbd,  0x5a,  0x58,  0x89,  0x4a,
-  0x2a,  0x2a,  0xfe,  0xed,  0xbb,  0xdb,  0xaa,  0x60,  0xdd,  0x8f,  0x9e,  0xdb,
-  0xe1,  0x4f,  0x8a,  0xd1,  0x4b,  0x1d,  0x1a,  0x50,  0x00,  0xc9,  0x3e,  0x62,
-  0x7f,  0xf1,  0x55,  0xc9,  0xd7,  0xd9,  0x17,  0x4d,  0xfe,  0x8d,  0x37,  0xfb,
-  0x87,  0xf9,  0x57,  0xc6,  0xf5,  0xd1,  0xc5,  0x9c,  0x3d,  0x86,  0xc8,  0x5d,
-  0x05,  0x87,  0x9c,  0xa5,  0xcf,  0xcd,  0x7e,  0x6b,  0x74,  0xb6,  0xd6,  0x4b,
-  0xb8,  0x27,  0x70,  0xae,  0x87,  0x47,  0xf0,  0x07,  0x88,  0x35,  0xfb,  0x04,
-  0xbd,  0xb0,  0xd3,  0x64,  0xb9,  0xb5,  0x72,  0x42,  0xc8,  0xae,  0xa0,  0x12,
-  0x0e,  0x0f,  0x53,  0xeb,  0x5c,  0xf5,  0x7d,  0x27,  0xf0,  0x54,  0xe3,  0xe1,
-  0xed,  0x8f,  0xfd,  0x74,  0x97,  0xff,  0x00,  0x43,  0x35,  0xe7,  0x70,  0xbe,
-  0x4f,  0x43,  0x3c,  0xc6,  0xcb,  0x0d,  0x5e,  0x4d,  0x25,  0x16,  0xf4,  0xb5,
-  0xee,  0x9a,  0x5d,  0x53,  0xee,  0x0d,  0xd8,  0xf3,  0x1f,  0x0d,  0x7c,  0x12,
-  0xd7,  0xb5,  0x3d,  0x42,  0x31,  0xa9,  0x40,  0x34,  0xdb,  0x20,  0xc0,  0xc8,
-  0xee,  0xea,  0xce,  0x47,  0x70,  0xa0,  0x13,  0xcf,  0xb9,  0xe2,  0xbe,  0x87,
-  0xb7,  0x82,  0x3b,  0x4b,  0x78,  0xa0,  0x89,  0x42,  0x45,  0x12,  0x84,  0x45,
-  0x1d,  0x80,  0x18,  0x02,  0x97,  0x34,  0x9b,  0xab,  0xfa,  0x07,  0x25,  0xe1,
-  0xfc,  0x1e,  0x45,  0x09,  0x47,  0x0d,  0x76,  0xe5,  0xbb,  0x7a,  0xbd,  0x36,
-  0x5a,  0x24,  0xad,  0xf2,  0x22,  0xf7,  0x24,  0xcd,  0x19,  0xa8,  0xf7,  0x51,
-  0xba,  0xbe,  0x96,  0xc1,  0x71,  0xd2,  0x48,  0x22,  0x46,  0x76,  0xe0,  0x0e,
-  0x6b,  0x2a,  0x5b,  0xd9,  0x18,  0x17,  0x47,  0x11,  0xe4,  0xe3,  0x60,  0xeb,
-  0xf5,  0xa7,  0x49,  0x78,  0xef,  0xe7,  0xa9,  0x00,  0xa8,  0xe8,  0x08,  0xf7,
-  0x02,  0xaa,  0xf9,  0xc7,  0xfb,  0x89,  0xff,  0x00,  0x7c,  0x8a,  0xe9,  0x84,
-  0x2d,  0xb9,  0xc5,  0x56,  0xaf,  0x36,  0x89,  0x93,  0xc5,  0x7b,  0x22,  0x8d,
-  0xef,  0x20,  0x7d,  0xa7,  0xee,  0x37,  0x53,  0x5a,  0xd1,  0x4a,  0x26,  0x8d,
-  0x5d,  0x7a,  0x1a,  0xc2,  0xf3,  0x8f,  0xf7,  0x13,  0xfe,  0xf9,  0x15,  0x65,
-  0x2f,  0x1e,  0x34,  0x84,  0x28,  0x50,  0x09,  0xe4,  0x01,  0xef,  0x44,  0xe1,
-  0x7d,  0x85,  0x4e,  0xaf,  0x2e,  0xec,  0xd6,  0xa6,  0xcb,  0x28,  0x86,  0x36,
-  0x76,  0xe8,  0x29,  0x37,  0x56,  0x63,  0xde,  0x3c,  0x89,  0x30,  0x60,  0xa4,
-  0x0e,  0x80,  0x8f,  0x7a,  0xc2,  0x30,  0xe6,  0x3a,  0xa7,  0x53,  0x91,  0x0d,
-  0x96,  0xf6,  0x46,  0x05,  0xd2,  0x40,  0x9b,  0x8f,  0xdc,  0x5e,  0xa3,  0xde,
-  0x96,  0x2b,  0xd9,  0x14,  0x07,  0x77,  0x0f,  0xb4,  0xfd,  0xc6,  0xeb,  0xf5,
-  0xaa,  0xfe,  0x71,  0xfe,  0xe2,  0x7f,  0xdf,  0x22,  0x8f,  0x38,  0xff,  0x00,
-  0x71,  0x3f,  0xef,  0x91,  0x5d,  0x7c,  0xaa,  0xd6,  0xb1,  0xc1,  0xce,  0xef,
-  0x7b,  0x9b,  0xb1,  0xc8,  0x25,  0x45,  0x75,  0xe8,  0x46,  0x69,  0xd5,  0x95,
-  0x1d,  0xe3,  0xa0,  0x81,  0x46,  0x02,  0x9e,  0xa0,  0x0f,  0x72,  0x2b,  0x4b,
-  0x35,  0xc9,  0x28,  0xf2,  0x9d,  0xf0,  0xa9,  0xce,  0x85,  0x92,  0x41,  0x1a,
-  0x33,  0xb7,  0x40,  0x32,  0x6b,  0x2a,  0x5b,  0xd9,  0x1c,  0x17,  0x47,  0x09,
-  0x93,  0x8d,  0x83,  0xaf,  0xd6,  0x9d,  0x25,  0xe3,  0xbf,  0x9e,  0xa4,  0x02,
-  0xa3,  0xa0,  0x23,  0xdc,  0x55,  0x5f,  0x38,  0xff,  0x00,  0x71,  0x3f,  0xef,
-  0x91,  0x5b,  0xc2,  0x16,  0xdc,  0xe6,  0xa9,  0x57,  0x9b,  0x44,  0xc8,  0xea,
-  0x70,  0xa4,  0x88,  0x30,  0x09,  0xff,  0x00,  0xf5,  0xd3,  0x4d,  0xbb,  0x09,
-  0x84,  0x59,  0x1b,  0xbd,  0x7b,  0x56,  0x95,  0xb4,  0x66,  0x18,  0x42,  0x13,
-  0x92,  0x3d,  0x2a,  0xe5,  0x2b,  0x23,  0x2a,  0x70,  0x72,  0x6d,  0x32,  0x7a,
-  0xc8,  0x2a,  0x40,  0x9f,  0x20,  0x8f,  0xff,  0x00,  0x5d,  0x6a,  0xe6,  0xa3,
-  0xb9,  0x8c,  0xcf,  0x09,  0x40,  0x40,  0x27,  0xd6,  0xb1,  0x83,  0xe5,  0x3a,
-  0x6a,  0x47,  0x99,  0x5c,  0xc7,  0xa2,  0xa5,  0x5b,  0x76,  0x69,  0x8c,  0x59,
-  0x1b,  0xbf,  0x4a,  0x3e,  0xce,  0xde,  0x7f,  0x95,  0x91,  0xbb,  0xd7,  0xb5,
-  0x74,  0xdd,  0x1c,  0x3c,  0xac,  0x7a,  0xa9,  0x2d,  0x6f,  0x80,  0x7f,  0xcb,
-  0x1a,  0xd6,  0xa8,  0x6d,  0xe3,  0x30,  0xc2,  0xa8,  0x48,  0x24,  0x77,  0x15,
-  0x26,  0x6b,  0x9a,  0x6f,  0x99,  0x9d,  0xf4,  0xe3,  0xca,  0x8c,  0xb6,  0x52,
-  0x1a,  0xe3,  0x20,  0xff,  0x00,  0x96,  0x15,  0x5e,  0xb6,  0x2e,  0x23,  0x33,
-  0x44,  0xc8,  0x08,  0x04,  0xd6,  0x67,  0xd9,  0xdb,  0xcf,  0xf2,  0xb2,  0x37,
-  0x7a,  0xf6,  0xad,  0xa1,  0x24,  0xd1,  0xcb,  0x52,  0x0e,  0x2d,  0x58,  0x8a,
-  0xa7,  0x0a,  0x48,  0x83,  0x00,  0x9f,  0xff,  0x00,  0x5d,  0x34,  0xdb,  0xb2,
-  0xcc,  0x22,  0xc8,  0xdd,  0xeb,  0xda,  0xb4,  0xad,  0xa3,  0x30,  0xc2,  0xaa,
-  0x4e,  0x48,  0xf4,  0xa2,  0x52,  0xb2,  0x0a,  0x70,  0x72,  0x6d,  0x32,  0x7a,
-  0x29,  0xa4,  0xd1,  0x9a,  0xe5,  0xb1,  0xde,  0x3a,  0x8a,  0x6e,  0x73,  0x41,
-  0x34,  0x58,  0x0e,  0x7f,  0xe2,  0x1f,  0xfc,  0x88,  0xfa,  0xe7,  0xfd,  0x7a,
-  0xbf,  0xf2,  0xaf,  0x95,  0xab,  0xeb,  0x2f,  0x18,  0x58,  0x4b,  0xaa,  0xf8,
-  0x57,  0x56,  0xb4,  0x80,  0x6e,  0x9a,  0x6b,  0x69,  0x15,  0x17,  0xd5,  0xb6,
-  0x9c,  0x0f,  0xce,  0xbe,  0x4e,  0x65,  0x2a,  0x48,  0x20,  0x82,  0x38,  0x20,
-  0xf6,  0xaf,  0xc1,  0x7c,  0x46,  0x84,  0x96,  0x32,  0x84,  0xed,  0xa3,  0x8b,
-  0x5f,  0x73,  0xff,  0x00,  0x82,  0x8d,  0x20,  0x25,  0x7d,  0x5d,  0xe0,  0x5f,
-  0xf9,  0x12,  0xf4,  0x2f,  0xfa,  0xf2,  0x87,  0xff,  0x00,  0x40,  0x15,  0xf2,
-  0x9a,  0x23,  0x48,  0xea,  0x88,  0xa5,  0x9d,  0x8e,  0x02,  0x81,  0x92,  0x4d,
-  0x7d,  0x69,  0xe1,  0x8b,  0x19,  0x34,  0xbf,  0x0d,  0xe9,  0x76,  0x73,  0x71,
-  0x2c,  0x16,  0xd1,  0xc6,  0xe3,  0xd0,  0x85,  0x00,  0xd5,  0x78,  0x73,  0x09,
-  0x3c,  0x56,  0x22,  0x76,  0xd1,  0x45,  0x2f,  0xc7,  0xfe,  0x00,  0x4c,  0xd0,
-  0xba,  0xff,  0x00,  0x8f,  0x69,  0xbf,  0xdc,  0x3f,  0xca,  0xbe,  0x39,  0xaf,
-  0xb1,  0xe5,  0x5f,  0x32,  0x27,  0x4c,  0xe3,  0x72,  0x91,  0x9a,  0xf9,  0x03,
-  0x50,  0xb1,  0x9b,  0x4c,  0xbe,  0xb8,  0xb4,  0x9d,  0x0a,  0x4d,  0x04,  0x86,
-  0x37,  0x53,  0xd8,  0x83,  0x8a,  0xed,  0xf1,  0x22,  0x12,  0xff,  0x00,  0x65,
-  0x9d,  0xb4,  0xf7,  0xd7,  0xfe,  0x92,  0x10,  0x2b,  0xd7,  0xd2,  0x5f,  0x05,
-  0xbf,  0xe4,  0x9f,  0x58,  0xff,  0x00,  0xd7,  0x49,  0x7f,  0xf4,  0x33,  0x5f,
-  0x36,  0xd7,  0xd3,  0x9f,  0x0a,  0x74,  0xe9,  0xb4,  0xbf,  0x01,  0xe9,  0x91,
-  0x4e,  0xa5,  0x24,  0x75,  0x69,  0x76,  0x9e,  0xa0,  0x33,  0x12,  0x3f,  0x42,
-  0x2b,  0xc3,  0xf0,  0xf6,  0x12,  0x96,  0x69,  0x52,  0x49,  0x68,  0xa0,  0xff,
-  0x00,  0x19,  0x44,  0x72,  0xd8,  0xeb,  0xe8,  0xa6,  0xe6,  0x8c,  0xd7,  0xf4,
-  0x3d,  0x8c,  0x87,  0x51,  0x4d,  0xcd,  0x19,  0xa2,  0xc0,  0x65,  0xb2,  0x90,
-  0xd7,  0x19,  0x04,  0x7f,  0xfb,  0x42,  0xab,  0xd6,  0xc5,  0xc4,  0x66,  0x68,
-  0x59,  0x07,  0x04,  0xfa,  0xd6,  0x67,  0xd9,  0xdb,  0xcf,  0xf2,  0xb2,  0x37,
-  0x7a,  0xf6,  0xae,  0xa8,  0x4a,  0xe8,  0xe0,  0xa9,  0x07,  0x16,  0xac,  0x45,
-  0x53,  0x85,  0x24,  0x41,  0x80,  0x4f,  0xff,  0x00,  0xae,  0x9a,  0x6d,  0xd9,
-  0x66,  0x11,  0x64,  0x6e,  0xf5,  0xed,  0x5a,  0x76,  0xd1,  0x98,  0x21,  0x0a,
-  0x48,  0x27,  0xda,  0x89,  0x4a,  0xc8,  0x29,  0xc1,  0xc9,  0xb4,  0xc9,  0xab,
-  0x20,  0xa9,  0x02,  0x7c,  0x82,  0x3f,  0xfd,  0x75,  0xab,  0x9a,  0x8a,  0xe6,
-  0x33,  0x34,  0x45,  0x41,  0xc1,  0xf7,  0xac,  0x60,  0xf9,  0x4e,  0x9a,  0x91,
-  0xe6,  0x46,  0x45,  0x15,  0x28,  0xb7,  0x66,  0x98,  0xc5,  0x91,  0xb8,  0x77,
-  0xed,  0x47,  0xd9,  0xdb,  0xcf,  0xf2,  0xb2,  0x37,  0x7a,  0xf6,  0xae,  0x9b,
-  0xa3,  0x87,  0x95,  0x8f,  0x55,  0x25,  0xad,  0xf0,  0x0f,  0xf9,  0x63,  0x5a,
-  0xd5,  0x0d,  0xba,  0x18,  0x61,  0x54,  0x24,  0x12,  0x3d,  0x2a,  0x4c,  0xd7,
-  0x34,  0xdf,  0x33,  0x3b,  0xe9,  0xc7,  0x95,  0x19,  0x6c,  0xa4,  0x35,  0xc6,
-  0x41,  0xff,  0x00,  0x2c,  0x2a,  0xbd,  0x6c,  0x5c,  0x46,  0x66,  0x85,  0x90,
-  0x1c,  0x13,  0xeb,  0x59,  0x9f,  0x67,  0x6f,  0x3f,  0xca,  0xc8,  0xdd,  0xfa,
-  0x56,  0xd0,  0x92,  0x68,  0xe5,  0xa9,  0x06,  0x9a,  0xb1,  0xa0,  0xd6,  0xc1,
-  0xae,  0x04,  0xb9,  0x39,  0x1d,  0xaa,  0x6a,  0x28,  0xae,  0x76,  0xdb,  0x3a,
-  0xd2,  0xb6,  0xc1,  0x45,  0x14,  0x52,  0x19,  0x0a,  0xdb,  0x05,  0xb8,  0x32,
-  0xe4,  0xe4,  0xf6,  0xa3,  0xec,  0xc3,  0xed,  0x1e,  0x6e,  0x4e,  0x7d,  0x2a,
-  0x6a,  0x2a,  0xb9,  0x99,  0x3c,  0xa8,  0x28,  0xa2,  0x8a,  0x92,  0x82,  0xa1,
-  0xfb,  0x30,  0xfb,  0x47,  0x9b,  0x93,  0x9f,  0x4a,  0x9a,  0x8a,  0x69,  0xd8,
-  0x4d,  0x5f,  0x72,  0x16,  0xb6,  0x0d,  0x70,  0x25,  0xc9,  0xc8,  0xed,  0x53,
-  0x51,  0x45,  0x0d,  0xb6,  0x09,  0x5b,  0x60,  0xa2,  0x8a,  0x29,  0x0c,  0x28,
-  0xa2,  0x8a,  0x00,  0x2b,  0x83,  0xf1,  0x57,  0xc1,  0xdd,  0x1b,  0xc4,  0xb7,
-  0xaf,  0x79,  0x1b,  0xcb,  0xa7,  0x5d,  0x48,  0x73,  0x21,  0x80,  0x02,  0x8e,
-  0x7d,  0x4a,  0x9e,  0xff,  0x00,  0x42,  0x2b,  0xbc,  0xa2,  0xbc,  0xfc,  0x76,
-  0x5f,  0x85,  0xcc,  0xa9,  0xfb,  0x1c,  0x5d,  0x35,  0x38,  0xf9,  0xfe,  0x8f,
-  0x75,  0xf2,  0x1a,  0x6d,  0x1c,  0x3f,  0x84,  0xbe,  0x11,  0xe8,  0xde,  0x16,
-  0xbb,  0x4b,  0xc2,  0xd2,  0x5f,  0xde,  0x27,  0x29,  0x24,  0xf8,  0xda,  0x87,
-  0xd5,  0x54,  0x77,  0xf7,  0x39,  0xae,  0xe2,  0x8a,  0x29,  0xe0,  0xb0,  0x18,
-  0x5c,  0xba,  0x97,  0xb1,  0xc2,  0x53,  0x50,  0x8f,  0x97,  0xeb,  0xd5,  0xfc,
-  0xc2,  0xed,  0x85,  0x71,  0xfe,  0x31,  0xf8,  0x5f,  0xa4,  0x78,  0xc6,  0x6f,
-  0xb4,  0xcd,  0xe6,  0x5a,  0x5e,  0xe3,  0x06,  0xe2,  0x0c,  0x65,  0xc7,  0x6d,
-  0xc0,  0xf5,  0xfe,  0x7e,  0xf5,  0xd8,  0x51,  0x55,  0x8c,  0xc1,  0x61,  0xf1,
-  0xf4,  0x9d,  0x0c,  0x54,  0x14,  0xe2,  0xfa,  0x3f,  0xeb,  0x46,  0x17,  0x68,
-  0xf3,  0xbf,  0x0f,  0x7c,  0x11,  0xd1,  0x74,  0x6b,  0xc4,  0xb9,  0xb9,  0x96,
-  0x5d,  0x49,  0xd0,  0xe5,  0x63,  0x94,  0x05,  0x8f,  0x3e,  0xa5,  0x47,  0x5f,
-  0xc4,  0xe3,  0xda,  0xbd,  0x13,  0xa5,  0x14,  0x56,  0x38,  0x1c,  0xb7,  0x07,
-  0x96,  0x41,  0xd3,  0xc1,  0xd3,  0x50,  0x4f,  0x7b,  0x75,  0xf5,  0x7b,  0xb0,
-  0x6d,  0xb0,  0xa2,  0x8a,  0x2b,  0xd3,  0x10,  0x51,  0x45,  0x14,  0x00,  0x54,
-  0x3f,  0x66,  0x1f,  0x68,  0xf3,  0x72,  0x73,  0xe9,  0x53,  0x51,  0x4d,  0x3b,
-  0x09,  0xab,  0xee,  0x42,  0xd6,  0xc1,  0xae,  0x04,  0xb9,  0x39,  0x1d,  0xaa,
-  0x6a,  0x28,  0xa1,  0xb6,  0xc1,  0x2b,  0x6c,  0x14,  0x51,  0x45,  0x21,  0x90,
-  0xad,  0xb0,  0x5b,  0x83,  0x2e,  0x4e,  0x4f,  0x6a,  0x3e,  0xcc,  0x3e,  0xd1,
-  0xe6,  0xe4,  0xe7,  0xd2,  0xa6,  0xa2,  0xab,  0x99,  0x93,  0xca,  0x82,  0x8a,
-  0x28,  0xa9,  0x28,  0x2a,  0x1f,  0xb3,  0x0f,  0xb4,  0x79,  0xb9,  0x39,  0xf4,
-  0xa9,  0xa8,  0xa6,  0x9d,  0x84,  0xd5,  0xf7,  0x3e,  0x20,  0xff,  0x00,  0x87,
-  0xa6,  0xf8,  0x5b,  0xfe,  0x84,  0x7d,  0x63,  0xff,  0x00,  0x02,  0xa2,  0xa3,
-  0xfe,  0x1e,  0x9b,  0xe1,  0x6f,  0xfa,  0x11,  0xf5,  0x8f,  0xfc,  0x0a,  0x8a,
-  0xbe,  0x17,  0xfe,  0xc6,  0xb2,  0xff,  0x00,  0x9f,  0x64,  0xa7,  0x47,  0xa2,
-  0x59,  0x31,  0xe6,  0xd9,  0x31,  0x45,  0x8e,  0x9e,  0x44,  0x7d,  0xcd,  0xff,
-  0x00,  0x0f,  0x4d,  0xf0,  0xb7,  0xfd,  0x08,  0xfa,  0xc7,  0xfe,  0x05,  0x45,
-  0x47,  0xfc,  0x3d,  0x37,  0xc2,  0xdf,  0xf4,  0x23,  0xeb,  0x1f,  0xf8,  0x15,
-  0x15,  0x7c,  0x3b,  0xfd,  0x87,  0x61,  0xff,  0x00,  0x3e,  0xb1,  0xfe,  0x54,
-  0xd9,  0x34,  0x6b,  0x05,  0x1c,  0x5b,  0x47,  0x9f,  0xa5,  0x16,  0x0e,  0x44,
-  0x7d,  0xc9,  0xff,  0x00,  0x0f,  0x4d,  0xf0,  0xb7,  0xfd,  0x08,  0xfa,  0xc7,
-  0xfe,  0x05,  0x45,  0x47,  0xfc,  0x3d,  0x37,  0xc2,  0xdf,  0xf4,  0x23,  0xeb,
-  0x1f,  0xf8,  0x15,  0x15,  0x7c,  0x2f,  0xfd,  0x8d,  0x65,  0xff,  0x00,  0x3e,
-  0xc9,  0xf9,  0x53,  0xe3,  0xd1,  0x2c,  0x4f,  0x26,  0xd9,  0x31,  0xf4,  0xa2,
-  0xc1,  0xc8,  0x8f,  0xb9,  0x7f,  0xe1,  0xe9,  0xbe,  0x16,  0xff,  0x00,  0xa1,
-  0x1f,  0x58,  0xff,  0x00,  0xc0,  0xa8,  0xa8,  0xff,  0x00,  0x87,  0xa6,  0xf8,
-  0x5b,  0xfe,  0x84,  0x7d,  0x63,  0xff,  0x00,  0x02,  0xa2,  0xaf,  0x87,  0x7f,
-  0xb0,  0xec,  0x3f,  0xe7,  0xd6,  0x3f,  0xca,  0x99,  0x26,  0x8d,  0x62,  0x38,
-  0x16,  0xc9,  0x9a,  0x2c,  0x1c,  0x88,  0xfb,  0x97,  0xfe,  0x1e,  0x9b,  0xe1,
-  0x6f,  0xfa,  0x11,  0xf5,  0x8f,  0xfc,  0x0a,  0x8a,  0x8f,  0xf8,  0x7a,  0x6f,
-  0x85,  0xbf,  0xe8,  0x47,  0xd6,  0x3f,  0xf0,  0x2a,  0x2a,  0xf8,  0x5f,  0xfb,
-  0x1a,  0xcb,  0xfe,  0x7d,  0x93,  0xf2,  0xa9,  0x23,  0xd1,  0x2c,  0x48,  0xc9,
-  0xb6,  0x4f,  0xca,  0x8b,  0x07,  0x22,  0x3e,  0xe4,  0xff,  0x00,  0x87,  0xa6,
-  0xf8,  0x5b,  0xfe,  0x84,  0x7d,  0x63,  0xff,  0x00,  0x02,  0xa2,  0xa3,  0xfe,
-  0x1e,  0x9b,  0xe1,  0x6f,  0xfa,  0x11,  0xf5,  0x8f,  0xfc,  0x0a,  0x8a,  0xbe,
-  0x1d,  0xfe,  0xc3,  0xb0,  0xff,  0x00,  0x9f,  0x58,  0xff,  0x00,  0x2a,  0x64,
-  0x9a,  0x35,  0x88,  0x38,  0x16,  0xc9,  0xf9,  0x51,  0x60,  0xe4,  0x47,  0xdc,
-  0xbf,  0xf0,  0xf4,  0xdf,  0x0b,  0x7f,  0xd0,  0x8f,  0xac,  0x7f,  0xe0,  0x54,
-  0x54,  0x7f,  0xc3,  0xd3,  0x7c,  0x2d,  0xff,  0x00,  0x42,  0x3e,  0xb1,  0xff,
-  0x00,  0x81,  0x51,  0x57,  0xc2,  0xff,  0x00,  0xd8,  0xd6,  0x5f,  0xf3,  0xec,
-  0x9f,  0x95,  0x48,  0x9a,  0x1d,  0x89,  0x19,  0x36,  0xc9,  0xf9,  0x51,  0x60,
-  0xe4,  0x47,  0xdc,  0x9f,  0xf0,  0xf4,  0xdf,  0x0b,  0x7f,  0xd0,  0x8f,  0xac,
-  0x7f,  0xe0,  0x54,  0x54,  0x7f,  0xc3,  0xd3,  0x7c,  0x2d,  0xff,  0x00,  0x42,
-  0x3e,  0xb1,  0xff,  0x00,  0x81,  0x51,  0x57,  0xc3,  0xbf,  0xd8,  0x76,  0x1f,
-  0xf3,  0xeb,  0x1f,  0xe5,  0x51,  0xbe,  0x8d,  0x63,  0x9c,  0x0b,  0x64,  0xfc,
-  0xa8,  0xb0,  0x72,  0x23,  0xee,  0x6f,  0xf8,  0x7a,  0x6f,  0x85,  0xbf,  0xe8,
-  0x47,  0xd6,  0x3f,  0xf0,  0x2a,  0x2a,  0x3f,  0xe1,  0xe9,  0xbe,  0x16,  0xff,
-  0x00,  0xa1,  0x1f,  0x58,  0xff,  0x00,  0xc0,  0xa8,  0xab,  0xe1,  0x7f,  0xec,
-  0x7b,  0x2f,  0xf9,  0xf6,  0x4f,  0xca,  0x9b,  0x2e,  0x9d,  0xa7,  0xdb,  0xed,
-  0x53,  0x67,  0xe6,  0xc8,  0xc0,  0x90,  0xb1,  0xae,  0x4e,  0x3d,  0x68,  0xb0,
-  0x72,  0x23,  0xee,  0xaf,  0xf8,  0x7a,  0x6f,  0x85,  0xbf,  0xe8,  0x47,  0xd6,
-  0x3f,  0xf0,  0x2a,  0x2a,  0x3f,  0xe1,  0xe9,  0xbe,  0x16,  0xff,  0x00,  0xa1,
-  0x1f,  0x58,  0xff,  0x00,  0xc0,  0xa8,  0xab,  0xe1,  0x1f,  0x23,  0x4b,  0xd8,
-  0x1b,  0xec,  0x44,  0x8d,  0xbb,  0x9b,  0x09,  0xf7,  0x06,  0x48,  0xc9,  0xe7,
-  0xd8,  0xfe,  0x54,  0x3d,  0x9e,  0x9e,  0x2e,  0x04,  0x66,  0xcb,  0x60,  0x27,
-  0x68,  0x72,  0xbf,  0x29,  0x3f,  0x5c,  0xd1,  0x60,  0xe4,  0x47,  0xdd,  0xdf,
-  0xf0,  0xf4,  0xdf,  0x0b,  0x7f,  0xd0,  0x8f,  0xac,  0x7f,  0xe0,  0x54,  0x54,
-  0x7f,  0xc3,  0xd3,  0x7c,  0x2d,  0xff,  0x00,  0x42,  0x3e,  0xb1,  0xff,  0x00,
-  0x81,  0x51,  0x57,  0xc1,  0x82,  0xdf,  0x4e,  0x1b,  0xb7,  0xd9,  0x98,  0x88,
-  0x19,  0xda,  0xeb,  0xc9,  0xe7,  0x1c,  0x73,  0xea,  0x45,  0x4d,  0x1d,  0x9e,
-  0x9a,  0x46,  0x0d,  0x91,  0x12,  0x02,  0x41,  0x8c,  0xaf,  0xcd,  0x9c,  0x67,
-  0xd7,  0xd2,  0x8b,  0x07,  0x22,  0x3e,  0xed,  0xff,  0x00,  0x87,  0xa6,  0xf8,
-  0x5b,  0xfe,  0x84,  0x7d,  0x63,  0xff,  0x00,  0x02,  0xa2,  0xa3,  0xfe,  0x1e,
-  0x9b,  0xe1,  0x6f,  0xfa,  0x11,  0xf5,  0x8f,  0xfc,  0x0a,  0x8a,  0xbe,  0x16,
-  0xb7,  0xd3,  0xf4,  0xeb,  0x86,  0x65,  0xfb,  0x1f,  0x96,  0xea,  0x01,  0x2b,
-  0x22,  0xe0,  0xe0,  0xf7,  0xa7,  0x36,  0x8f,  0x62,  0x49,  0xc5,  0xb2,  0x62,
-  0x8b,  0x07,  0x22,  0x3e,  0xe7,  0xff,  0x00,  0x87,  0xa6,  0xf8,  0x5b,  0xfe,
-  0x84,  0x7d,  0x63,  0xff,  0x00,  0x02,  0xa2,  0xa3,  0xfe,  0x1e,  0x9b,  0xe1,
-  0x6f,  0xfa,  0x11,  0xf5,  0x8f,  0xfc,  0x0a,  0x8a,  0xbe,  0x17,  0xfe,  0xc6,
-  0xb2,  0x3f,  0xf2,  0xec,  0x95,  0x30,  0xd0,  0xec,  0x40,  0xff,  0x00,  0x8f,
-  0x64,  0xa2,  0xc1,  0xc8,  0x8f,  0xb8,  0xbf,  0xe1,  0xe9,  0xbe,  0x16,  0xff,
-  0x00,  0xa1,  0x1f,  0x58,  0xff,  0x00,  0xc0,  0xa8,  0xa8,  0xff,  0x00,  0x87,
-  0xa6,  0xf8,  0x5b,  0xfe,  0x84,  0x7d,  0x63,  0xff,  0x00,  0x02,  0xa2,  0xaf,
-  0x87,  0x7f,  0xb1,  0x2c,  0x07,  0xfc,  0xba,  0xc7,  0xf9,  0x54,  0x27,  0x47,
-  0xb2,  0x27,  0xfe,  0x3d,  0x92,  0x8b,  0x07,  0x22,  0x3e,  0xe8,  0xff,  0x00,
-  0x87,  0xa6,  0xf8,  0x5b,  0xfe,  0x84,  0x7d,  0x63,  0xff,  0x00,  0x02,  0xa2,
-  0xa3,  0xfe,  0x1e,  0x9b,  0xe1,  0x6f,  0xfa,  0x11,  0xf5,  0x8f,  0xfc,  0x0a,
-  0x8a,  0xbe,  0x17,  0x1a,  0x2d,  0x91,  0x38,  0xfb,  0x32,  0x54,  0xdf,  0xd8,
-  0x76,  0x1f,  0xf3,  0xea,  0x9f,  0x95,  0x16,  0x0e,  0x44,  0x7d,  0xc5,  0xff,
-  0x00,  0x0f,  0x4d,  0xf0,  0xb7,  0xfd,  0x08,  0xfa,  0xc7,  0xfe,  0x05,  0x45,
-  0x47,  0xfc,  0x3d,  0x37,  0xc2,  0xdf,  0xf4,  0x23,  0xeb,  0x1f,  0xf8,  0x15,
-  0x15,  0x7c,  0x3a,  0x74,  0x4b,  0x00,  0x33,  0xf6,  0x58,  0xff,  0x00,  0x2a,
-  0x84,  0xe8,  0xd6,  0x5f,  0xf3,  0xec,  0x94,  0x58,  0x39,  0x11,  0xf7,  0x47,
-  0xfc,  0x3d,  0x37,  0xc2,  0xdf,  0xf4,  0x23,  0xeb,  0x1f,  0xf8,  0x15,  0x15,
-  0x1f,  0xf0,  0xf4,  0xdf,  0x0b,  0x7f,  0xd0,  0x8f,  0xac,  0x7f,  0xe0,  0x54,
-  0x55,  0xf0,  0xc2,  0xe8,  0xb6,  0x4c,  0x40,  0xfb,  0x32,  0x54,  0xbf,  0xd8,
-  0x76,  0x1f,  0xf3,  0xea,  0x94,  0x58,  0x39,  0x11,  0xf7,  0x17,  0xfc,  0x3d,
-  0x37,  0xc2,  0xdf,  0xf4,  0x23,  0xeb,  0x1f,  0xf8,  0x15,  0x15,  0x1f,  0xf0,
-  0xf4,  0xdf,  0x0b,  0x7f,  0xd0,  0x8f,  0xac,  0x7f,  0xe0,  0x54,  0x55,  0xf0,
-  0xe3,  0x68,  0xb6,  0x0a,  0x09,  0xfb,  0x2c,  0x7f,  0x95,  0x45,  0xfd,  0x8d,
-  0x65,  0xff,  0x00,  0x3e,  0xc9,  0x45,  0x83,  0x91,  0x1f,  0x74,  0x7f,  0xc3,
-  0xd3,  0x7c,  0x2d,  0xff,  0x00,  0x42,  0x3e,  0xb1,  0xff,  0x00,  0x81,  0x51,
-  0x51,  0xff,  0x00,  0x0f,  0x4d,  0xf0,  0xb7,  0xfd,  0x08,  0xfa,  0xc7,  0xfe,
-  0x05,  0x45,  0x5f,  0x0c,  0x26,  0x89,  0x64,  0xcd,  0xff,  0x00,  0x1e,  0xc9,
-  0x52,  0xff,  0x00,  0x61,  0xd8,  0x7f,  0xcf,  0xac,  0x7f,  0x95,  0x16,  0x0e,
-  0x44,  0x7d,  0xc5,  0xff,  0x00,  0x0f,  0x4d,  0xf0,  0xb7,  0xfd,  0x08,  0xfa,
-  0xc7,  0xfe,  0x05,  0x45,  0x47,  0xfc,  0x3d,  0x37,  0xc2,  0xdf,  0xf4,  0x23,
-  0xeb,  0x1f,  0xf8,  0x15,  0x15,  0x7c,  0x38,  0xfa,  0x2d,  0x82,  0xaf,  0xfc,
-  0x7a,  0xc7,  0xf9,  0x54,  0x5f,  0xd8,  0xd6,  0x5f,  0xf3,  0xec,  0x94,  0x58,
-  0x39,  0x11,  0x72,  0xa7,  0x45,  0xda,  0xb8,  0xa8,  0xe3,  0x5c,  0xb6,  0x7d,
-  0x2a,  0x5a,  0xa2,  0xc2,  0xa1,  0x66,  0xdc,  0xd9,  0xa7,  0xc8,  0xd8,  0x18,
-  0xf5,  0xa8,  0xa8,  0x01,  0x40,  0xc9,  0xa9,  0xd4,  0x6d,  0x18,  0xa8,  0xe2,
-  0x5e,  0x73,  0x52,  0x50,  0x00,  0x4e,  0x05,  0x40,  0xc7,  0x71,  0xcd,  0x49,
-  0x2b,  0x71,  0x8a,  0x8a,  0x80,  0x14,  0x0c,  0x9c,  0x54,  0xe0,  0x60,  0x62,
-  0xa3,  0x89,  0x7b,  0xd4,  0x94,  0x00,  0x13,  0x80,  0x4d,  0x40,  0x4e,  0x4e,
-  0x69,  0xf2,  0xb7,  0x6a,  0x8e,  0x80,  0x15,  0x46,  0xe3,  0x8a,  0x9e,  0x99,
-  0x1a,  0xe0,  0x67,  0xd6,  0x9f,  0x40,  0x08,  0xc7,  0x68,  0xcd,  0x41,  0x4f,
-  0x91,  0xb2,  0x71,  0xe9,  0x4c,  0xa0,  0x07,  0x22,  0xee,  0x6f,  0x6a,  0x27,
-  0xb5,  0x59,  0xa4,  0x49,  0x37,  0xbc,  0x6e,  0xbc,  0x06,  0x43,  0x8c,  0x8f,
-  0x43,  0xed,  0x52,  0x46,  0xb8,  0x5f,  0x73,  0x4e,  0xa0,  0x0a,  0xa6,  0xca,
-  0x38,  0xa2,  0x95,  0x41,  0x6f,  0xde,  0x2e,  0xc3,  0xcf,  0x6c,  0x93,  0xff,
-  0x00,  0xb3,  0x1a,  0x87,  0xec,  0x60,  0xca,  0xae,  0xd2,  0x48,  0xe1,  0x4e,
-  0x42,  0x12,  0x36,  0x83,  0xf9,  0x55,  0xa9,  0x1b,  0x73,  0x7b,  0x0a,  0x6d,
-  0x00,  0x57,  0x8b,  0x49,  0xb7,  0x0c,  0xfb,  0x53,  0xcb,  0x0c,  0x00,  0x21,
-  0x38,  0xe8,  0x72,  0x0f,  0xd6,  0xa6,  0x5d,  0x39,  0x17,  0x90,  0xf2,  0x79,
-  0x99,  0x2c,  0x64,  0x27,  0x2c,  0x4e,  0xdc,  0x7e,  0x82,  0xac,  0xa2,  0xed,
-  0x5a,  0x5a,  0x00,  0xad,  0x1d,  0xaa,  0xdb,  0x16,  0x6f,  0x31,  0xe5,  0x91,
-  0xc0,  0x05,  0xe4,  0x39,  0x38,  0x1d,  0xbf,  0x5a,  0x5a,  0x73,  0xb6,  0xe6,
-  0xa6,  0xf5,  0xa0,  0x07,  0xc4,  0xb9,  0x39,  0xf4,  0xa9,  0x69,  0x14,  0x6d,
-  0x18,  0xa5,  0xe9,  0x40,  0x0c,  0x95,  0xb0,  0x31,  0x51,  0x52,  0xb1,  0xdc,
-  0x49,  0xa0,  0x0c,  0x9c,  0x50,  0x03,  0xe2,  0x5e,  0xf5,  0x25,  0x00,  0x60,
-  0x62,  0x82,  0x70,  0x33,  0x40,  0x11,  0xca,  0xdd,  0xaa,  0x3a,  0x52,  0x72,
-  0x73,  0x42,  0x8d,  0xc4,  0x0a,  0x00,  0x92,  0x25,  0xc0,  0xcd,  0x3e,  0x8e,
-  0x94,  0x8c,  0x76,  0x82,  0x68,  0x02,  0x39,  0x5b,  0x27,  0x1e,  0x94,  0xca,
-  0x3a,  0xd3,  0x91,  0x77,  0x35,  0x00,  0x49,  0x1a,  0xe1,  0x7d,  0xcd,  0x3a,
-  0x8a,  0x47,  0x6d,  0xab,  0x40,  0x11,  0xc8,  0xd9,  0x6f,  0x61,  0x4c,  0xa2,
-  0x9d,  0x1a,  0xee,  0x6f,  0x61,  0x40,  0x1f,  0xff,  0xd9
-};
diff --git a/services/camera/libcameraservice/FakeCamera.cpp b/services/camera/libcameraservice/FakeCamera.cpp
deleted file mode 100644
index f3a6a67..0000000
--- a/services/camera/libcameraservice/FakeCamera.cpp
+++ /dev/null
@@ -1,433 +0,0 @@
-/*
-**
-** Copyright 2008, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License"); 
-** you may not use this file except in compliance with the License. 
-** You may obtain a copy of the License at 
-**
-**     http://www.apache.org/licenses/LICENSE-2.0 
-**
-** Unless required by applicable law or agreed to in writing, software 
-** distributed under the License is distributed on an "AS IS" BASIS, 
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
-** See the License for the specific language governing permissions and 
-** limitations under the License.
-*/
-
-#define LOG_TAG "FakeCamera"
-#include <utils/Log.h>
-
-#include <string.h>
-#include <stdlib.h>
-#include <utils/String8.h>
-
-#include "FakeCamera.h"
-
-
-namespace android {
-
-// TODO: All this rgb to yuv should probably be in a util class.
-
-// TODO: I think something is wrong in this class because the shadow is kBlue
-// and the square color should alternate between kRed and kGreen. However on the
-// emulator screen these are all shades of gray. Y seems ok but the U and V are
-// probably not.
-
-static int tables_initialized = 0;
-uint8_t *gYTable, *gCbTable, *gCrTable;
-
-static int
-clamp(int  x)
-{
-    if (x > 255) return 255;
-    if (x < 0)   return 0;
-    return x;
-}
-
-/* the equation used by the video code to translate YUV to RGB looks like this
- *
- *    Y  = (Y0 - 16)*k0
- *    Cb = Cb0 - 128
- *    Cr = Cr0 - 128
- *
- *    G = ( Y - k1*Cr - k2*Cb )
- *    R = ( Y + k3*Cr )
- *    B = ( Y + k4*Cb )
- *
- */
-
-static const double  k0 = 1.164;
-static const double  k1 = 0.813;
-static const double  k2 = 0.391;
-static const double  k3 = 1.596;
-static const double  k4 = 2.018;
-
-/* let's try to extract the value of Y
- *
- *   G + k1/k3*R + k2/k4*B = Y*( 1 + k1/k3 + k2/k4 )
- *
- *   Y  = ( G + k1/k3*R + k2/k4*B ) / (1 + k1/k3 + k2/k4)
- *   Y0 = ( G0 + k1/k3*R0 + k2/k4*B0 ) / ((1 + k1/k3 + k2/k4)*k0) + 16
- *
- * let define:
- *   kYr = k1/k3
- *   kYb = k2/k4
- *   kYy = k0 * ( 1 + kYr + kYb )
- *
- * we have:
- *    Y  = ( G + kYr*R + kYb*B )
- *    Y0 = clamp[ Y/kYy + 16 ]
- */
-
-static const double kYr = k1/k3;
-static const double kYb = k2/k4;
-static const double kYy = k0*( 1. + kYr + kYb );
-
-static void
-initYtab( void )
-{
-    const  int imax = (int)( (kYr + kYb)*(31 << 2) + (61 << 3) + 0.1 );
-    int    i;
-
-    gYTable = (uint8_t *)malloc(imax);
-
-    for(i=0; i<imax; i++) {
-        int  x = (int)(i/kYy + 16.5);
-        if (x < 16) x = 16;
-        else if (x > 235) x = 235;
-        gYTable[i] = (uint8_t) x;
-    }
-}
-
-/*
- *   the source is RGB565, so adjust for 8-bit range of input values:
- *
- *   G = (pixels >> 3) & 0xFC;
- *   R = (pixels >> 8) & 0xF8;
- *   B = (pixels & 0x1f) << 3;
- *
- *   R2 = (pixels >> 11)      R = R2*8
- *   B2 = (pixels & 0x1f)     B = B2*8
- *
- *   kYr*R = kYr2*R2 =>  kYr2 = kYr*8
- *   kYb*B = kYb2*B2 =>  kYb2 = kYb*8
- *
- *   we want to use integer multiplications:
- *
- *   SHIFT1 = 9
- *
- *   (ALPHA*R2) >> SHIFT1 == R*kYr  =>  ALPHA = kYr*8*(1 << SHIFT1)
- *
- *   ALPHA = kYr*(1 << (SHIFT1+3))
- *   BETA  = kYb*(1 << (SHIFT1+3))
- */
-
-static const int  SHIFT1  = 9;
-static const int  ALPHA   = (int)( kYr*(1 << (SHIFT1+3)) + 0.5 );
-static const int  BETA    = (int)( kYb*(1 << (SHIFT1+3)) + 0.5 );
-
-/*
- *  now let's try to get the values of Cb and Cr
- *
- *  R-B = (k3*Cr - k4*Cb)
- *
- *    k3*Cr = k4*Cb + (R-B)
- *    k4*Cb = k3*Cr - (R-B)
- *
- *  R-G = (k1+k3)*Cr + k2*Cb
- *      = (k1+k3)*Cr + k2/k4*(k3*Cr - (R-B)/k0)
- *      = (k1 + k3 + k2*k3/k4)*Cr - k2/k4*(R-B)
- *
- *  kRr*Cr = (R-G) + kYb*(R-B)
- *
- *  Cr  = ((R-G) + kYb*(R-B))/kRr
- *  Cr0 = clamp(Cr + 128)
- */
-
-static const double  kRr = (k1 + k3 + k2*k3/k4);
-
-static void
-initCrtab( void )
-{
-    uint8_t *pTable;
-    int i;
-
-    gCrTable = (uint8_t *)malloc(768*2);
-
-    pTable = gCrTable + 384;
-    for(i=-384; i<384; i++)
-        pTable[i] = (uint8_t) clamp( i/kRr + 128.5 );
-}
-
-/*
- *  B-G = (k2 + k4)*Cb + k1*Cr
- *      = (k2 + k4)*Cb + k1/k3*(k4*Cb + (R-B))
- *      = (k2 + k4 + k1*k4/k3)*Cb + k1/k3*(R-B)
- *
- *  kBb*Cb = (B-G) - kYr*(R-B)
- *
- *  Cb   = ((B-G) - kYr*(R-B))/kBb
- *  Cb0  = clamp(Cb + 128)
- *
- */
-
-static const double  kBb = (k2 + k4 + k1*k4/k3);
-
-static void
-initCbtab( void )
-{
-    uint8_t *pTable;
-    int i;
-
-    gCbTable = (uint8_t *)malloc(768*2);
-
-    pTable = gCbTable + 384;
-    for(i=-384; i<384; i++)
-        pTable[i] = (uint8_t) clamp( i/kBb + 128.5 );
-}
-
-/*
- *   SHIFT2 = 16
- *
- *   DELTA = kYb*(1 << SHIFT2)
- *   GAMMA = kYr*(1 << SHIFT2)
- */
-
-static const int  SHIFT2 = 16;
-static const int  DELTA  = kYb*(1 << SHIFT2);
-static const int  GAMMA  = kYr*(1 << SHIFT2);
-
-int32_t ccrgb16toyuv_wo_colorkey(uint8_t *rgb16, uint8_t *yuv420,
-        uint32_t *param, uint8_t *table[])
-{
-    uint16_t *inputRGB = (uint16_t*)rgb16;
-    uint8_t *outYUV = yuv420;
-    int32_t width_dst = param[0];
-    int32_t height_dst = param[1];
-    int32_t pitch_dst = param[2];
-    int32_t mheight_dst = param[3];
-    int32_t pitch_src = param[4];
-    uint8_t *y_tab = table[0];
-    uint8_t *cb_tab = table[1];
-    uint8_t *cr_tab = table[2];
-
-    int32_t size16 = pitch_dst*mheight_dst;
-    int32_t i,j,count;
-    int32_t ilimit,jlimit;
-    uint8_t *tempY,*tempU,*tempV;
-    uint16_t pixels;
-    int   tmp;
-uint32_t temp;
-
-    tempY = outYUV;
-    tempU = outYUV + (height_dst * pitch_dst);
-    tempV = tempU + 1;
-
-    jlimit = height_dst;
-    ilimit = width_dst;
-
-    for(j=0; j<jlimit; j+=1)
-    {
-        for (i=0; i<ilimit; i+=2)
-        {
-            int32_t   G_ds = 0, B_ds = 0, R_ds = 0;
-            uint8_t   y0, y1, u, v;
-
-            pixels =  inputRGB[i];
-            temp = (BETA*(pixels & 0x001F) + ALPHA*(pixels>>11) );
-            y0   = y_tab[(temp>>SHIFT1) + ((pixels>>3) & 0x00FC)];
-
-            G_ds    += (pixels>>1) & 0x03E0;
-            B_ds    += (pixels<<5) & 0x03E0;
-            R_ds    += (pixels>>6) & 0x03E0;
-
-            pixels =  inputRGB[i+1];
-            temp = (BETA*(pixels & 0x001F) + ALPHA*(pixels>>11) );
-            y1   = y_tab[(temp>>SHIFT1) + ((pixels>>3) & 0x00FC)];
-
-            G_ds    += (pixels>>1) & 0x03E0;
-            B_ds    += (pixels<<5) & 0x03E0;
-            R_ds    += (pixels>>6) & 0x03E0;
-
-            R_ds >>= 1;
-            B_ds >>= 1;
-            G_ds >>= 1;
-
-            tmp = R_ds - B_ds;
-
-            u = cb_tab[(((B_ds-G_ds)<<SHIFT2) - GAMMA*tmp)>>(SHIFT2+2)];
-            v = cr_tab[(((R_ds-G_ds)<<SHIFT2) + DELTA*tmp)>>(SHIFT2+2)];
-
-            tempY[0] = y0;
-            tempY[1] = y1;
-            tempY += 2;
-
-            if ((j&1) == 0) {
-                tempU[0] = u;
-                tempV[0] = v;
-                tempU += 2;
-                tempV += 2;
-            }
-        }
-
-        inputRGB += pitch_src;
-    }
-
-    return 1;
-}
-
-#define min(a,b) ((a)<(b)?(a):(b))
-#define max(a,b) ((a)>(b)?(a):(b))
-
-static void convert_rgb16_to_yuv420(uint8_t *rgb, uint8_t *yuv, int width, int height)
-{
-    if (!tables_initialized) {
-        initYtab();
-        initCrtab();
-        initCbtab();
-        tables_initialized = 1;
-    }
-
-    uint32_t param[6];
-    param[0] = (uint32_t) width;
-    param[1] = (uint32_t) height;
-    param[2] = (uint32_t) width;
-    param[3] = (uint32_t) height;
-    param[4] = (uint32_t) width;
-    param[5] = (uint32_t) 0;
-
-    uint8_t *table[3];
-    table[0] = gYTable;
-    table[1] = gCbTable + 384;
-    table[2] = gCrTable + 384;
-
-    ccrgb16toyuv_wo_colorkey(rgb, yuv, param, table);
-}
-
-const int FakeCamera::kRed;
-const int FakeCamera::kGreen;
-const int FakeCamera::kBlue;
-
-FakeCamera::FakeCamera(int width, int height)
-          : mTmpRgb16Buffer(0)
-{
-    setSize(width, height);
-}
-
-FakeCamera::~FakeCamera()
-{
-    delete[] mTmpRgb16Buffer;
-}
-
-void FakeCamera::setSize(int width, int height)
-{
-    mWidth = width;
-    mHeight = height;
-    mCounter = 0;
-    mCheckX = 0;
-    mCheckY = 0;
-
-    // This will cause it to be reallocated on the next call
-    // to getNextFrameAsYuv420().
-    delete[] mTmpRgb16Buffer;
-    mTmpRgb16Buffer = 0;
-}
-
-void FakeCamera::getNextFrameAsRgb565(uint16_t *buffer)
-{
-    int size = mWidth / 10;
-
-    drawCheckerboard(buffer, size);
-
-    int x = ((mCounter*3)&255);
-    if(x>128) x = 255 - x;
-    int y = ((mCounter*5)&255);
-    if(y>128) y = 255 - y;
-
-    drawSquare(buffer, x*size/32, y*size/32, (size*5)>>1, (mCounter&0x100)?kRed:kGreen, kBlue);
-
-    mCounter++;
-}
-
-void FakeCamera::getNextFrameAsYuv420(uint8_t *buffer)
-{
-    if (mTmpRgb16Buffer == 0)
-        mTmpRgb16Buffer = new uint16_t[mWidth * mHeight];
-
-    getNextFrameAsRgb565(mTmpRgb16Buffer);
-    convert_rgb16_to_yuv420((uint8_t*)mTmpRgb16Buffer, buffer, mWidth, mHeight);
-}
-
-void FakeCamera::drawSquare(uint16_t *dst, int x, int y, int size, int color, int shadow)
-{
-    int square_xstop, square_ystop, shadow_xstop, shadow_ystop;
-
-    square_xstop = min(mWidth, x+size);
-    square_ystop = min(mHeight, y+size);
-    shadow_xstop = min(mWidth, x+size+(size/4));
-    shadow_ystop = min(mHeight, y+size+(size/4));
-
-    // Do the shadow.
-    uint16_t *sh = &dst[(y+(size/4))*mWidth];
-    for (int j = y + (size/4); j < shadow_ystop; j++) {
-        for (int i = x + (size/4); i < shadow_xstop; i++) {
-            sh[i] &= shadow;
-        }
-        sh += mWidth;
-    }
-
-    // Draw the square.
-    uint16_t *sq = &dst[y*mWidth];
-    for (int j = y; j < square_ystop; j++) {
-        for (int i = x; i < square_xstop; i++) {
-            sq[i] = color;
-        }
-        sq += mWidth;
-    }
-}
-
-void FakeCamera::drawCheckerboard(uint16_t *dst, int size)
-{
-    bool black = true;
-
-    if((mCheckX/size)&1)
-        black = false;
-    if((mCheckY/size)&1)
-        black = !black;
-
-    int county = mCheckY%size;
-    int checkxremainder = mCheckX%size;
-
-    for(int y=0;y<mHeight;y++) {
-        int countx = checkxremainder;
-        bool current = black;
-        for(int x=0;x<mWidth;x++) {
-            dst[y*mWidth+x] = current?0:0xffff;
-            if(countx++ >= size) {
-                countx=0;
-                current = !current;
-            }
-        }
-        if(county++ >= size) {
-            county=0;
-            black = !black;
-        }
-    }
-    mCheckX += 3;
-    mCheckY++;
-}
-
-
-void FakeCamera::dump(int fd) const
-{
-    const size_t SIZE = 256;
-    char buffer[SIZE];
-    String8 result;
-    snprintf(buffer, 255, " width x height (%d x %d), counter (%d), check x-y coordinate(%d, %d)\n", mWidth, mHeight, mCounter, mCheckX, mCheckY);
-    result.append(buffer);
-    ::write(fd, result.string(), result.size());
-}
-
-
-}; // namespace android
diff --git a/services/camera/libcameraservice/FakeCamera.h b/services/camera/libcameraservice/FakeCamera.h
deleted file mode 100644
index 724de20..0000000
--- a/services/camera/libcameraservice/FakeCamera.h
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
-**
-** Copyright 2008, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License"); 
-** you may not use this file except in compliance with the License. 
-** You may obtain a copy of the License at 
-**
-**     http://www.apache.org/licenses/LICENSE-2.0 
-**
-** Unless required by applicable law or agreed to in writing, software 
-** distributed under the License is distributed on an "AS IS" BASIS, 
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
-** See the License for the specific language governing permissions and 
-** limitations under the License.
-*/
-
-#ifndef ANDROID_HARDWARE_FAKECAMERA_H
-#define ANDROID_HARDWARE_FAKECAMERA_H
-
-#include <sys/types.h>
-#include <stdint.h>
-
-namespace android {
-
-/*
- * FakeCamera is used in the CameraHardwareStub to provide a fake video feed
- * when the system does not have a camera in hardware.
- * The fake video is a moving black and white checkerboard background with a
- * bouncing gray square in the foreground.
- * This class is not thread-safe.
- *
- * TODO: Since the major methods provides a raw/uncompressed video feed, rename
- * this class to RawVideoSource.
- */
-
-class FakeCamera {
-public:
-    FakeCamera(int width, int height);
-    ~FakeCamera();
-
-    void setSize(int width, int height);
-    void getNextFrameAsYuv420(uint8_t *buffer);
-    // Write to the fd a string representing the current state.
-    void dump(int fd) const;
-
-private:
-    // TODO: remove the uint16_t buffer param everywhere since it is a field of
-    // this class.
-    void getNextFrameAsRgb565(uint16_t *buffer);
-
-    void drawSquare(uint16_t *buffer, int x, int y, int size, int color, int shadow);
-    void drawCheckerboard(uint16_t *buffer, int size);
-
-    static const int kRed = 0xf800;
-    static const int kGreen = 0x07c0;
-    static const int kBlue = 0x003e;
-
-    int         mWidth, mHeight;
-    int         mCounter;
-    int         mCheckX, mCheckY;
-    uint16_t    *mTmpRgb16Buffer;
-};
-
-}; // namespace android
-
-#endif // ANDROID_HARDWARE_FAKECAMERA_H