move native services under services/

moved surfaceflinger, audioflinger, cameraservice

all native services should now reside in this location.

Change-Id: Icd7336f7289db35df9c8c1857a5122bb8a6f1c86
diff --git a/services/camera/libcameraservice/Android.mk b/services/camera/libcameraservice/Android.mk
new file mode 100644
index 0000000..df5c166
--- /dev/null
+++ b/services/camera/libcameraservice/Android.mk
@@ -0,0 +1,71 @@
+LOCAL_PATH:= $(call my-dir)
+
+#
+# Set USE_CAMERA_STUB for non-emulator and non-simulator builds, if you want
+# the camera service to use the fake camera.  For emulator or simulator builds,
+# we always use the fake camera.
+
+ifeq ($(USE_CAMERA_STUB),)
+USE_CAMERA_STUB:=false
+ifneq ($(filter sooner generic sim,$(TARGET_DEVICE)),)
+USE_CAMERA_STUB:=true
+endif #libcamerastub
+endif
+
+ifeq ($(USE_CAMERA_STUB),true)
+#
+# libcamerastub
+#
+
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES:=               \
+    CameraHardwareStub.cpp      \
+    FakeCamera.cpp
+
+LOCAL_MODULE:= libcamerastub
+
+ifeq ($(TARGET_SIMULATOR),true)
+LOCAL_CFLAGS += -DSINGLE_PROCESS
+endif
+
+LOCAL_SHARED_LIBRARIES:= libui
+
+include $(BUILD_STATIC_LIBRARY)
+endif # USE_CAMERA_STUB
+
+#
+# libcameraservice
+#
+
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES:=               \
+    CameraService.cpp
+
+LOCAL_SHARED_LIBRARIES:= \
+    libui \
+    libutils \
+    libbinder \
+    libcutils \
+    libmedia \
+    libcamera_client \
+    libsurfaceflinger_client
+
+LOCAL_MODULE:= libcameraservice
+
+LOCAL_CFLAGS += -DLOG_TAG=\"CameraService\"
+
+ifeq ($(TARGET_SIMULATOR),true)
+LOCAL_CFLAGS += -DSINGLE_PROCESS
+endif
+
+ifeq ($(USE_CAMERA_STUB), true)
+LOCAL_STATIC_LIBRARIES += libcamerastub
+LOCAL_CFLAGS += -include CameraHardwareStub.h
+else
+LOCAL_SHARED_LIBRARIES += libcamera 
+endif
+
+include $(BUILD_SHARED_LIBRARY)
+
diff --git a/services/camera/libcameraservice/CameraHardwareStub.cpp b/services/camera/libcameraservice/CameraHardwareStub.cpp
new file mode 100644
index 0000000..8b66389
--- /dev/null
+++ b/services/camera/libcameraservice/CameraHardwareStub.cpp
@@ -0,0 +1,402 @@
+/*
+**
+** 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("preview-size-values","320x240");
+    p.setPreviewSize(320, 240);
+    p.setPreviewFrameRate(15);
+    p.setPreviewFormat("yuv422sp");
+
+    p.set("picture-size-values", "320x240");
+    p.setPictureSize(320, 240);
+    p.setPictureFormat("jpeg");
+
+    if (setParameters(p) != NO_ERROR) {
+        LOGE("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 * 2 * picture_height);
+
+    int preview_width, preview_height;
+    mParameters.getPreviewSize(&preview_width, &preview_height);
+    LOGD("initHeapLocked: preview size=%dx%d", preview_width, preview_height);
+
+    // Note that we enforce yuv422 in setParameters().
+    int how_big = preview_width * preview_height * 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
+    singleton.clear();
+}
+
+sp<IMemoryHeap> CameraHardwareStub::getPreviewHeap() const
+{
+    return mPreviewHeap;
+}
+
+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->getNextFrameAsYuv422(frame);
+
+        //LOGV("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, 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 * 2 * h);
+        FakeCamera cam(w, h);
+        cam.getNextFrameAsYuv422((uint8_t *)mRawHeap->base());
+        mDataCb(CAMERA_MSG_RAW_IMAGE, mem, 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, mCallbackCookie);
+    }
+    return NO_ERROR;
+}
+
+status_t CameraHardwareStub::takePicture()
+{
+    stopPreview();
+    if (createThread(beginPictureThread, this) == false)
+        return -1;
+    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(), "yuv422sp") != 0) {
+        LOGE("Only yuv422sp preview is supported");
+        return -1;
+    }
+
+    if (strcmp(params.getPictureFormat(), "jpeg") != 0) {
+        LOGE("Only jpeg still pictures are supported");
+        return -1;
+    }
+
+    int w, h;
+    params.getPictureSize(&w, &h);
+    if (w != kCannedJpegWidth && h != kCannedJpegHeight) {
+        LOGE("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()
+{
+}
+
+wp<CameraHardwareInterface> CameraHardwareStub::singleton;
+
+sp<CameraHardwareInterface> CameraHardwareStub::createInstance()
+{
+    if (singleton != 0) {
+        sp<CameraHardwareInterface> hardware = singleton.promote();
+        if (hardware != 0) {
+            return hardware;
+        }
+    }
+    sp<CameraHardwareInterface> hardware(new CameraHardwareStub());
+    singleton = hardware;
+    return hardware;
+}
+
+extern "C" sp<CameraHardwareInterface> openCameraHardware()
+{
+    return CameraHardwareStub::createInstance();
+}
+
+}; // namespace android
diff --git a/services/camera/libcameraservice/CameraHardwareStub.h b/services/camera/libcameraservice/CameraHardwareStub.h
new file mode 100644
index 0000000..957813a
--- /dev/null
+++ b/services/camera/libcameraservice/CameraHardwareStub.h
@@ -0,0 +1,135 @@
+/*
+**
+** 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 sp<IMemoryHeap> getPreviewHeap() const;
+    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 wp<CameraHardwareInterface> singleton;
+
+    static const int kBufferCount = 4;
+
+    class PreviewThread : public Thread {
+        CameraHardwareStub* mHardware;
+    public:
+        PreviewThread(CameraHardwareStub* hw) :
+#ifdef SINGLE_PROCESS
+            // In single process mode this thread needs to be a java thread,
+            // since we won't be calling through the binder.
+            Thread(true),
+#else
+            Thread(false),
+#endif
+              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
new file mode 100644
index 0000000..00bd54e
--- /dev/null
+++ b/services/camera/libcameraservice/CameraService.cpp
@@ -0,0 +1,1417 @@
+/*
+**
+** Copyright (C) 2008, The Android Open Source Project
+** Copyright (C) 2008 HTC Inc.
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+
+#define LOG_TAG "CameraService"
+#include <utils/Log.h>
+
+#include <binder/IServiceManager.h>
+#include <binder/IPCThreadState.h>
+#include <utils/String16.h>
+#include <utils/Errors.h>
+#include <binder/MemoryBase.h>
+#include <binder/MemoryHeapBase.h>
+#include <camera/ICameraService.h>
+#include <surfaceflinger/ISurface.h>
+#include <ui/Overlay.h>
+
+#include <hardware/hardware.h>
+
+#include <media/mediaplayer.h>
+#include <media/AudioSystem.h>
+#include "CameraService.h"
+
+#include <cutils/atomic.h>
+
+namespace android {
+
+extern "C" {
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <pthread.h>
+#include <signal.h>
+}
+
+// When you enable this, as well as DEBUG_REFS=1 and
+// DEBUG_REFS_ENABLED_BY_DEFAULT=0 in libutils/RefBase.cpp, this will track all
+// references to the CameraService::Client in order to catch the case where the
+// client is being destroyed while a callback from the CameraHardwareInterface
+// is outstanding.  This is a serious bug because if we make another call into
+// CameraHardwreInterface that itself triggers a callback, we will deadlock.
+
+#define DEBUG_CLIENT_REFERENCES 0
+
+#define PICTURE_TIMEOUT seconds(5)
+
+#define DEBUG_DUMP_PREVIEW_FRAME_TO_FILE 0 /* n-th frame to write */
+#define DEBUG_DUMP_JPEG_SNAPSHOT_TO_FILE 0
+#define DEBUG_DUMP_YUV_SNAPSHOT_TO_FILE 0
+#define DEBUG_DUMP_POSTVIEW_SNAPSHOT_TO_FILE 0
+
+#if DEBUG_DUMP_PREVIEW_FRAME_TO_FILE
+static int debug_frame_cnt;
+#endif
+
+static int getCallingPid() {
+    return IPCThreadState::self()->getCallingPid();
+}
+
+// ----------------------------------------------------------------------------
+
+void CameraService::instantiate() {
+    defaultServiceManager()->addService(
+            String16("media.camera"), new CameraService());
+}
+
+// ----------------------------------------------------------------------------
+
+CameraService::CameraService() :
+    BnCameraService()
+{
+    LOGI("CameraService started: pid=%d", getpid());
+    mUsers = 0;
+}
+
+CameraService::~CameraService()
+{
+    if (mClient != 0) {
+        LOGE("mClient was still connected in destructor!");
+    }
+}
+
+sp<ICamera> CameraService::connect(const sp<ICameraClient>& cameraClient)
+{
+    int callingPid = getCallingPid();
+    LOGV("CameraService::connect E (pid %d, client %p)", callingPid,
+            cameraClient->asBinder().get());
+
+    Mutex::Autolock lock(mServiceLock);
+    sp<Client> client;
+    if (mClient != 0) {
+        sp<Client> currentClient = mClient.promote();
+        if (currentClient != 0) {
+            sp<ICameraClient> currentCameraClient(currentClient->getCameraClient());
+            if (cameraClient->asBinder() == currentCameraClient->asBinder()) {
+                // This is the same client reconnecting...
+                LOGV("CameraService::connect X (pid %d, same client %p) is reconnecting...",
+                    callingPid, cameraClient->asBinder().get());
+                return currentClient;
+            } else {
+                // It's another client... reject it
+                LOGV("CameraService::connect X (pid %d, new client %p) rejected. "
+                    "(old pid %d, old client %p)",
+                    callingPid, cameraClient->asBinder().get(),
+                    currentClient->mClientPid, currentCameraClient->asBinder().get());
+                if (kill(currentClient->mClientPid, 0) == -1 && errno == ESRCH) {
+                    LOGV("The old client is dead!");
+                }
+                return client;
+            }
+        } else {
+            // can't promote, the previous client has died...
+            LOGV("New client (pid %d) connecting, old reference was dangling...",
+                    callingPid);
+            mClient.clear();
+        }
+    }
+
+    if (mUsers > 0) {
+        LOGV("Still have client, rejected");
+        return client;
+    }
+
+    // create a new Client object
+    client = new Client(this, cameraClient, callingPid);
+    mClient = client;
+#if DEBUG_CLIENT_REFERENCES
+    // Enable tracking for this object, and track increments and decrements of
+    // the refcount.
+    client->trackMe(true, true);
+#endif
+    LOGV("CameraService::connect X");
+    return client;
+}
+
+void CameraService::removeClient(const sp<ICameraClient>& cameraClient)
+{
+    int callingPid = getCallingPid();
+
+    // Declare this outside the lock to make absolutely sure the
+    // destructor won't be called with the lock held.
+    sp<Client> client;
+
+    Mutex::Autolock lock(mServiceLock);
+
+    if (mClient == 0) {
+        // This happens when we have already disconnected.
+        LOGV("removeClient (pid %d): already disconnected", callingPid);
+        return;
+    }
+
+    // Promote mClient. It can fail if we are called from this path:
+    // Client::~Client() -> disconnect() -> removeClient().
+    client = mClient.promote();
+    if (client == 0) {
+        LOGV("removeClient (pid %d): no more strong reference", callingPid);
+        mClient.clear();
+        return;
+    }
+
+    if (cameraClient->asBinder() != client->getCameraClient()->asBinder()) {
+        // ugh! that's not our client!!
+        LOGW("removeClient (pid %d): mClient doesn't match!", callingPid);
+    } else {
+        // okay, good, forget about mClient
+        mClient.clear();
+    }
+
+    LOGV("removeClient (pid %d) done", callingPid);
+}
+
+// The reason we need this count is a new CameraService::connect() request may
+// come in while the previous Client's destructor has not been run or is still
+// running. If the last strong reference of the previous Client is gone but
+// destructor has not been run, we should not allow the new Client to be created
+// because we need to wait for the previous Client to tear down the hardware
+// first.
+void CameraService::incUsers() {
+    android_atomic_inc(&mUsers);
+}
+
+void CameraService::decUsers() {
+    android_atomic_dec(&mUsers);
+}
+
+static sp<MediaPlayer> newMediaPlayer(const char *file)
+{
+    sp<MediaPlayer> mp = new MediaPlayer();
+    if (mp->setDataSource(file, NULL /* headers */) == NO_ERROR) {
+        mp->setAudioStreamType(AudioSystem::ENFORCED_AUDIBLE);
+        mp->prepare();
+    } else {
+        mp.clear();
+        LOGE("Failed to load CameraService sounds.");
+    }
+    return mp;
+}
+
+CameraService::Client::Client(const sp<CameraService>& cameraService,
+        const sp<ICameraClient>& cameraClient, pid_t clientPid)
+{
+    int callingPid = getCallingPid();
+    LOGV("Client::Client E (pid %d)", callingPid);
+    mCameraService = cameraService;
+    mCameraClient = cameraClient;
+    mClientPid = clientPid;
+    mHardware = openCameraHardware();
+    mUseOverlay = mHardware->useOverlay();
+
+    mHardware->setCallbacks(notifyCallback,
+                            dataCallback,
+                            dataCallbackTimestamp,
+                            mCameraService.get());
+
+    // Enable zoom, error, and focus messages by default
+    mHardware->enableMsgType(CAMERA_MSG_ERROR |
+                             CAMERA_MSG_ZOOM |
+                             CAMERA_MSG_FOCUS);
+
+    mMediaPlayerClick = newMediaPlayer("/system/media/audio/ui/camera_click.ogg");
+    mMediaPlayerBeep = newMediaPlayer("/system/media/audio/ui/VideoRecord.ogg");
+    mOverlayW = 0;
+    mOverlayH = 0;
+
+    // Callback is disabled by default
+    mPreviewCallbackFlag = FRAME_CALLBACK_FLAG_NOOP;
+    mOrientation = 0;
+    cameraService->incUsers();
+    LOGV("Client::Client X (pid %d)", callingPid);
+}
+
+status_t CameraService::Client::checkPid()
+{
+    int callingPid = getCallingPid();
+    if (mClientPid == callingPid) return NO_ERROR;
+    LOGW("Attempt to use locked camera (client %p) from different process "
+        " (old pid %d, new pid %d)",
+        getCameraClient()->asBinder().get(), mClientPid, callingPid);
+    return -EBUSY;
+}
+
+status_t CameraService::Client::lock()
+{
+    int callingPid = getCallingPid();
+    LOGV("lock from pid %d (mClientPid %d)", callingPid, mClientPid);
+    Mutex::Autolock _l(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();
+    LOGV("unlock from pid %d (mClientPid %d)", callingPid, mClientPid);
+    Mutex::Autolock _l(mLock);
+    // allow anyone to use camera
+    status_t result = checkPid();
+    if (result == NO_ERROR) {
+        mClientPid = 0;
+        LOGV("clear mCameraClient (pid %d)", callingPid);
+        // we need to remove the reference so that when app goes
+        // away, the reference count goes to 0.
+        mCameraClient.clear();
+    }
+    return result;
+}
+
+status_t CameraService::Client::connect(const sp<ICameraClient>& client)
+{
+    int callingPid = getCallingPid();
+
+    // connect a new process to the camera
+    LOGV("Client::connect E (pid %d, client %p)", callingPid, client->asBinder().get());
+
+    // I hate this hack, but things get really ugly when the media recorder
+    // service is handing back the camera to the app. The ICameraClient
+    // destructor will be called during the same IPC, making it look like
+    // the remote client is trying to disconnect. This hack temporarily
+    // sets the mClientPid to an invalid pid to prevent the hardware from
+    // being torn down.
+    {
+
+        // hold a reference to the old client or we will deadlock if the client is
+        // in the same process and we hold the lock when we remove the reference
+        sp<ICameraClient> oldClient;
+        {
+            Mutex::Autolock _l(mLock);
+            if (mClientPid != 0 && checkPid() != NO_ERROR) {
+                LOGW("Tried to connect to locked camera (old pid %d, new pid %d)",
+                        mClientPid, callingPid);
+                return -EBUSY;
+            }
+            oldClient = mCameraClient;
+
+            // did the client actually change?
+            if ((mCameraClient != NULL) && (client->asBinder() == mCameraClient->asBinder())) {
+                LOGV("Connect to the same client");
+                return NO_ERROR;
+            }
+
+            mCameraClient = client;
+            mClientPid = -1;
+            mPreviewCallbackFlag = FRAME_CALLBACK_FLAG_NOOP;
+            LOGV("Connect to the new client (pid %d, client %p)",
+                callingPid, mCameraClient->asBinder().get());
+        }
+
+    }
+    // the old client destructor is called when oldClient goes out of scope
+    // now we set the new PID to lock the interface again
+    mClientPid = callingPid;
+
+    return NO_ERROR;
+}
+
+#if HAVE_ANDROID_OS
+static void *unregister_surface(void *arg)
+{
+    ISurface *surface = (ISurface *)arg;
+    surface->unregisterBuffers();
+    IPCThreadState::self()->flushCommands();
+    return NULL;
+}
+#endif
+
+CameraService::Client::~Client()
+{
+    int callingPid = getCallingPid();
+
+    // tear down client
+    LOGV("Client::~Client E (pid %d, client %p)",
+            callingPid, getCameraClient()->asBinder().get());
+    if (mSurface != 0 && !mUseOverlay) {
+#if HAVE_ANDROID_OS
+        pthread_t thr;
+        // We unregister the buffers in a different thread because binder does
+        // not let us make sychronous transactions in a binder destructor (that
+        // is, upon our reaching a refcount of zero.)
+        pthread_create(&thr, NULL,
+                       unregister_surface,
+                       mSurface.get());
+        pthread_join(thr, NULL);
+#else
+        mSurface->unregisterBuffers();
+#endif
+    }
+
+    if (mMediaPlayerBeep.get() != NULL) {
+        mMediaPlayerBeep->disconnect();
+        mMediaPlayerBeep.clear();
+    }
+    if (mMediaPlayerClick.get() != NULL) {
+        mMediaPlayerClick->disconnect();
+        mMediaPlayerClick.clear();
+    }
+
+    // make sure we tear down the hardware
+    mClientPid = callingPid;
+    disconnect();
+    LOGV("Client::~Client X (pid %d)", mClientPid);
+}
+
+void CameraService::Client::disconnect()
+{
+    int callingPid = getCallingPid();
+
+    LOGV("Client::disconnect() E (pid %d client %p)",
+            callingPid, getCameraClient()->asBinder().get());
+
+    Mutex::Autolock lock(mLock);
+    if (mClientPid <= 0) {
+        LOGV("camera is unlocked (mClientPid = %d), don't tear down hardware", mClientPid);
+        return;
+    }
+    if (checkPid() != NO_ERROR) {
+        LOGV("Different client - don't disconnect");
+        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;
+
+    LOGV("hardware teardown");
+    // Before destroying mHardware, we must make sure it's in the
+    // idle state.
+    mHardware->stopPreview();
+    // Cancel all picture callbacks.
+    mHardware->disableMsgType(CAMERA_MSG_SHUTTER |
+                              CAMERA_MSG_POSTVIEW_FRAME |
+                              CAMERA_MSG_RAW_IMAGE |
+                              CAMERA_MSG_COMPRESSED_IMAGE);
+    mHardware->cancelPicture();
+    // Turn off remaining messages.
+    mHardware->disableMsgType(CAMERA_MSG_ALL_MSGS);
+    // Release the hardware resources.
+    mHardware->release();
+    // Release the held overlay resources.
+    if (mUseOverlay)
+    {
+        mOverlayRef = 0;
+    }
+    mHardware.clear();
+
+    mCameraService->removeClient(mCameraClient);
+    mCameraService->decUsers();
+
+    LOGV("Client::disconnect() X (pid %d)", callingPid);
+}
+
+// pass the buffered ISurface to the camera service
+status_t CameraService::Client::setPreviewDisplay(const sp<ISurface>& surface)
+{
+    LOGV("setPreviewDisplay(%p) (pid %d)",
+         ((surface == NULL) ? NULL : surface.get()), getCallingPid());
+    Mutex::Autolock lock(mLock);
+    status_t result = checkPid();
+    if (result != NO_ERROR) return result;
+
+    Mutex::Autolock surfaceLock(mSurfaceLock);
+    result = NO_ERROR;
+    // asBinder() is safe on NULL (returns NULL)
+    if (surface->asBinder() != mSurface->asBinder()) {
+        if (mSurface != 0) {
+            LOGV("clearing old preview surface %p", mSurface.get());
+            if ( !mUseOverlay)
+            {
+                mSurface->unregisterBuffers();
+            }
+            else
+            {
+                // Force the destruction of any previous overlay
+                sp<Overlay> dummy;
+                mHardware->setOverlay( dummy );
+            }
+        }
+        mSurface = surface;
+        mOverlayRef = 0;
+        // If preview has been already started, set overlay or register preview
+        // buffers now.
+        if (mHardware->previewEnabled()) {
+            if (mUseOverlay) {
+                result = setOverlay();
+            } else if (mSurface != 0) {
+                result = registerPreviewBuffers();
+            }
+        }
+    }
+    return result;
+}
+
+// set the preview callback flag to affect how the received frames from
+// preview are handled.
+void CameraService::Client::setPreviewCallbackFlag(int callback_flag)
+{
+    LOGV("setPreviewCallbackFlag (pid %d)", getCallingPid());
+    Mutex::Autolock lock(mLock);
+    if (checkPid() != NO_ERROR) return;
+    mPreviewCallbackFlag = callback_flag;
+
+    if(mUseOverlay) {
+        if(mPreviewCallbackFlag & FRAME_CALLBACK_FLAG_ENABLE_MASK)
+            mHardware->enableMsgType(CAMERA_MSG_PREVIEW_FRAME);
+        else
+            mHardware->disableMsgType(CAMERA_MSG_PREVIEW_FRAME);
+    }
+}
+
+// start preview mode
+status_t CameraService::Client::startCameraMode(camera_mode mode)
+{
+    int callingPid = getCallingPid();
+
+    LOGV("startCameraMode(%d) (pid %d)", mode, callingPid);
+
+    /* we cannot call into mHardware with mLock held because
+     * mHardware has callbacks onto us which acquire this lock
+     */
+
+    Mutex::Autolock lock(mLock);
+    status_t result = checkPid();
+    if (result != NO_ERROR) return result;
+
+    if (mHardware == 0) {
+        LOGE("mHardware is NULL, returning.");
+        return INVALID_OPERATION;
+    }
+
+    switch(mode) {
+    case CAMERA_RECORDING_MODE:
+        if (mSurface == 0) {
+            LOGE("setPreviewDisplay must be called before startRecordingMode.");
+            return INVALID_OPERATION;
+        }
+        return startRecordingMode();
+
+    default: // CAMERA_PREVIEW_MODE
+        if (mSurface == 0) {
+            LOGV("mSurface is not set yet.");
+        }
+        return startPreviewMode();
+    }
+}
+
+status_t CameraService::Client::startRecordingMode()
+{
+    LOGV("startRecordingMode (pid %d)", getCallingPid());
+
+    status_t ret = UNKNOWN_ERROR;
+
+    // if preview has not been started, start preview first
+    if (!mHardware->previewEnabled()) {
+        ret = startPreviewMode();
+        if (ret != NO_ERROR) {
+            return ret;
+        }
+    }
+
+    // if recording has been enabled, nothing needs to be done
+    if (mHardware->recordingEnabled()) {
+        return NO_ERROR;
+    }
+
+    // start recording mode
+    ret = mHardware->startRecording();
+    if (ret != NO_ERROR) {
+        LOGE("mHardware->startRecording() failed with status %d", ret);
+    }
+    return ret;
+}
+
+status_t CameraService::Client::setOverlay()
+{
+    LOGV("setOverlay");
+    int w, h;
+    CameraParameters params(mHardware->getParameters());
+    params.getPreviewSize(&w, &h);
+
+    if ( w != mOverlayW || h != mOverlayH )
+    {
+        // Force the destruction of any previous overlay
+        sp<Overlay> dummy;
+        mHardware->setOverlay( dummy );
+        mOverlayRef = 0;
+    }
+
+    status_t ret = NO_ERROR;
+    if (mSurface != 0) {
+        if (mOverlayRef.get() == NULL) {
+
+            // FIXME:
+            // Surfaceflinger may hold onto the previous overlay reference for some
+            // time after we try to destroy it. retry a few times. In the future, we
+            // should make the destroy call block, or possibly specify that we can
+            // wait in the createOverlay call if the previous overlay is in the 
+            // process of being destroyed.
+            for (int retry = 0; retry < 50; ++retry) {
+                mOverlayRef = mSurface->createOverlay(w, h, OVERLAY_FORMAT_DEFAULT,
+                                                      mOrientation);
+                if (mOverlayRef != NULL) break;
+                LOGW("Overlay create failed - retrying");
+                usleep(20000);
+            }
+            if ( mOverlayRef.get() == NULL )
+            {
+                LOGE("Overlay Creation Failed!");
+                return -EINVAL;
+            }
+            ret = mHardware->setOverlay(new Overlay(mOverlayRef));
+        }
+    } else {
+        ret = mHardware->setOverlay(NULL);
+    }
+    if (ret != NO_ERROR) {
+        LOGE("mHardware->setOverlay() failed with status %d\n", ret);
+    }
+
+    mOverlayW = w;
+    mOverlayH = h;
+
+    return ret;
+}
+
+status_t CameraService::Client::registerPreviewBuffers()
+{
+    int w, h;
+    CameraParameters params(mHardware->getParameters());
+    params.getPreviewSize(&w, &h);
+
+    // don't use a hardcoded format here
+    ISurface::BufferHeap buffers(w, h, w, h,
+                                 HAL_PIXEL_FORMAT_YCrCb_420_SP,
+                                 mOrientation,
+                                 0,
+                                 mHardware->getPreviewHeap());
+
+    status_t ret = mSurface->registerBuffers(buffers);
+    if (ret != NO_ERROR) {
+        LOGE("registerBuffers failed with status %d", ret);
+    }
+    return ret;
+}
+
+status_t CameraService::Client::startPreviewMode()
+{
+    LOGV("startPreviewMode (pid %d)", getCallingPid());
+
+    // if preview has been enabled, nothing needs to be done
+    if (mHardware->previewEnabled()) {
+        return NO_ERROR;
+    }
+
+    // start preview mode
+#if DEBUG_DUMP_PREVIEW_FRAME_TO_FILE
+    debug_frame_cnt = 0;
+#endif
+    status_t ret = NO_ERROR;
+
+    if (mUseOverlay) {
+        // If preview display has been set, set overlay now.
+        if (mSurface != 0) {
+            ret = setOverlay();
+        }
+        if (ret != NO_ERROR) return ret;
+        ret = mHardware->startPreview();
+    } else {
+        mHardware->enableMsgType(CAMERA_MSG_PREVIEW_FRAME);
+        ret = mHardware->startPreview();
+        if (ret != NO_ERROR) return ret;
+        // If preview display has been set, register preview buffers now.
+        if (mSurface != 0) {
+           // Unregister here because the surface registered with raw heap.
+           mSurface->unregisterBuffers();
+           ret = registerPreviewBuffers();
+        }
+    }
+    return ret;
+}
+
+status_t CameraService::Client::startPreview()
+{
+    LOGV("startPreview (pid %d)", getCallingPid());
+
+    return startCameraMode(CAMERA_PREVIEW_MODE);
+}
+
+status_t CameraService::Client::startRecording()
+{
+    LOGV("startRecording (pid %d)", getCallingPid());
+
+    if (mMediaPlayerBeep.get() != NULL) {
+        // do not play record jingle if stream volume is 0
+        // (typically because ringer mode is silent).
+        int index;
+        AudioSystem::getStreamVolumeIndex(AudioSystem::ENFORCED_AUDIBLE, &index);
+        if (index != 0) {
+            mMediaPlayerBeep->seekTo(0);
+            mMediaPlayerBeep->start();
+        }
+    }
+
+    mHardware->enableMsgType(CAMERA_MSG_VIDEO_FRAME);
+
+    return startCameraMode(CAMERA_RECORDING_MODE);
+}
+
+// stop preview mode
+void CameraService::Client::stopPreview()
+{
+    LOGV("stopPreview (pid %d)", getCallingPid());
+
+    // hold main lock during state transition
+    {
+        Mutex::Autolock lock(mLock);
+        if (checkPid() != NO_ERROR) return;
+
+        if (mHardware == 0) {
+            LOGE("mHardware is NULL, returning.");
+            return;
+        }
+
+        mHardware->stopPreview();
+        mHardware->disableMsgType(CAMERA_MSG_PREVIEW_FRAME);
+        LOGV("stopPreview(), hardware stopped OK");
+
+        if (mSurface != 0 && !mUseOverlay) {
+            mSurface->unregisterBuffers();
+        }
+    }
+
+    // hold preview buffer lock
+    {
+        Mutex::Autolock lock(mPreviewLock);
+        mPreviewBuffer.clear();
+    }
+}
+
+// stop recording mode
+void CameraService::Client::stopRecording()
+{
+    LOGV("stopRecording (pid %d)", getCallingPid());
+
+    // hold main lock during state transition
+    {
+        Mutex::Autolock lock(mLock);
+        if (checkPid() != NO_ERROR) return;
+
+        if (mHardware == 0) {
+            LOGE("mHardware is NULL, returning.");
+            return;
+        }
+
+        if (mMediaPlayerBeep.get() != NULL) {
+            mMediaPlayerBeep->seekTo(0);
+            mMediaPlayerBeep->start();
+        }
+
+        mHardware->stopRecording();
+        mHardware->disableMsgType(CAMERA_MSG_VIDEO_FRAME);
+        LOGV("stopRecording(), hardware stopped OK");
+    }
+
+    // hold preview buffer lock
+    {
+        Mutex::Autolock lock(mPreviewLock);
+        mPreviewBuffer.clear();
+    }
+}
+
+// release a recording frame
+void CameraService::Client::releaseRecordingFrame(const sp<IMemory>& mem)
+{
+    Mutex::Autolock lock(mLock);
+    if (checkPid() != NO_ERROR) return;
+
+    if (mHardware == 0) {
+        LOGE("mHardware is NULL, returning.");
+        return;
+    }
+
+    mHardware->releaseRecordingFrame(mem);
+}
+
+bool CameraService::Client::previewEnabled()
+{
+    Mutex::Autolock lock(mLock);
+    if (mHardware == 0) return false;
+    return mHardware->previewEnabled();
+}
+
+bool CameraService::Client::recordingEnabled()
+{
+    Mutex::Autolock lock(mLock);
+    if (mHardware == 0) return false;
+    return mHardware->recordingEnabled();
+}
+
+// Safely retrieves a strong pointer to the client during a hardware callback.
+sp<CameraService::Client> CameraService::Client::getClientFromCookie(void* user)
+{
+    sp<Client> client = 0;
+    CameraService *service = static_cast<CameraService*>(user);
+    if (service != NULL) {
+        Mutex::Autolock ourLock(service->mServiceLock);
+        if (service->mClient != 0) {
+            client = service->mClient.promote();
+            if (client == 0) {
+                LOGE("getClientFromCookie: client appears to have died");
+                service->mClient.clear();
+            }
+        } else {
+            LOGE("getClientFromCookie: got callback but client was NULL");
+        }
+    }
+    return client;
+}
+
+
+#if DEBUG_DUMP_JPEG_SNAPSHOT_TO_FILE || \
+    DEBUG_DUMP_YUV_SNAPSHOT_TO_FILE || \
+    DEBUG_DUMP_PREVIEW_FRAME_TO_FILE
+static void dump_to_file(const char *fname,
+                         uint8_t *buf, uint32_t size)
+{
+    int nw, cnt = 0;
+    uint32_t written = 0;
+
+    LOGV("opening file [%s]\n", fname);
+    int fd = open(fname, O_RDWR | O_CREAT);
+    if (fd < 0) {
+        LOGE("failed to create file [%s]: %s", fname, strerror(errno));
+        return;
+    }
+
+    LOGV("writing %d bytes to file [%s]\n", size, fname);
+    while (written < size) {
+        nw = ::write(fd,
+                     buf + written,
+                     size - written);
+        if (nw < 0) {
+            LOGE("failed to write to file [%s]: %s",
+                 fname, strerror(errno));
+            break;
+        }
+        written += nw;
+        cnt++;
+    }
+    LOGV("done writing %d bytes to file [%s] in %d passes\n",
+         size, fname, cnt);
+    ::close(fd);
+}
+#endif
+
+status_t CameraService::Client::autoFocus()
+{
+    LOGV("autoFocus (pid %d)", getCallingPid());
+
+    Mutex::Autolock lock(mLock);
+    status_t result = checkPid();
+    if (result != NO_ERROR) return result;
+
+    if (mHardware == 0) {
+        LOGE("mHardware is NULL, returning.");
+        return INVALID_OPERATION;
+    }
+
+    return mHardware->autoFocus();
+}
+
+status_t CameraService::Client::cancelAutoFocus()
+{
+    LOGV("cancelAutoFocus (pid %d)", getCallingPid());
+
+    Mutex::Autolock lock(mLock);
+    status_t result = checkPid();
+    if (result != NO_ERROR) return result;
+
+    if (mHardware == 0) {
+        LOGE("mHardware is NULL, returning.");
+        return INVALID_OPERATION;
+    }
+
+    return mHardware->cancelAutoFocus();
+}
+
+// take a picture - image is returned in callback
+status_t CameraService::Client::takePicture()
+{
+    LOGV("takePicture (pid %d)", getCallingPid());
+
+    Mutex::Autolock lock(mLock);
+    status_t result = checkPid();
+    if (result != NO_ERROR) return result;
+
+    if (mHardware == 0) {
+        LOGE("mHardware is NULL, returning.");
+        return INVALID_OPERATION;
+    }
+
+    mHardware->enableMsgType(CAMERA_MSG_SHUTTER |
+                             CAMERA_MSG_POSTVIEW_FRAME |
+                             CAMERA_MSG_RAW_IMAGE |
+                             CAMERA_MSG_COMPRESSED_IMAGE);
+
+    return mHardware->takePicture();
+}
+
+// snapshot taken
+void CameraService::Client::handleShutter(
+    image_rect_type *size // The width and height of yuv picture for
+                          // registerBuffer. If this is NULL, use the picture
+                          // size from parameters.
+)
+{
+    // Play shutter sound.
+    if (mMediaPlayerClick.get() != NULL) {
+        // do not play shutter sound if stream volume is 0
+        // (typically because ringer mode is silent).
+        int index;
+        AudioSystem::getStreamVolumeIndex(AudioSystem::ENFORCED_AUDIBLE, &index);
+        if (index != 0) {
+            mMediaPlayerClick->seekTo(0);
+            mMediaPlayerClick->start();
+        }
+    }
+
+    // Screen goes black after the buffer is unregistered.
+    if (mSurface != 0 && !mUseOverlay) {
+        mSurface->unregisterBuffers();
+    }
+
+    sp<ICameraClient> c = mCameraClient;
+    if (c != NULL) {
+        c->notifyCallback(CAMERA_MSG_SHUTTER, 0, 0);
+    }
+    mHardware->disableMsgType(CAMERA_MSG_SHUTTER);
+
+    // It takes some time before yuvPicture callback to be called.
+    // Register the buffer for raw image here to reduce latency.
+    if (mSurface != 0 && !mUseOverlay) {
+        int w, h;
+        CameraParameters params(mHardware->getParameters());
+        if (size == NULL) {
+            params.getPictureSize(&w, &h);
+        } else {
+            w = size->width;
+            h = size->height;
+            w &= ~1;
+            h &= ~1;
+            LOGV("Snapshot image width=%d, height=%d", w, h);
+        }
+        // FIXME: don't use hardcoded format constants here
+        ISurface::BufferHeap buffers(w, h, w, h,
+            HAL_PIXEL_FORMAT_YCrCb_420_SP, mOrientation, 0,
+            mHardware->getRawHeap());
+
+        mSurface->registerBuffers(buffers);
+    }
+}
+
+// preview callback - frame buffer update
+void CameraService::Client::handlePreviewData(const sp<IMemory>& mem)
+{
+    ssize_t offset;
+    size_t size;
+    sp<IMemoryHeap> heap = mem->getMemory(&offset, &size);
+
+#if DEBUG_HEAP_LEAKS && 0 // debugging
+    if (gWeakHeap == NULL) {
+        if (gWeakHeap != heap) {
+            LOGV("SETTING PREVIEW HEAP");
+            heap->trackMe(true, true);
+            gWeakHeap = heap;
+        }
+    }
+#endif
+#if DEBUG_DUMP_PREVIEW_FRAME_TO_FILE
+    {
+        if (debug_frame_cnt++ == DEBUG_DUMP_PREVIEW_FRAME_TO_FILE) {
+            dump_to_file("/data/preview.yuv",
+                         (uint8_t *)heap->base() + offset, size);
+        }
+    }
+#endif
+
+    if (!mUseOverlay)
+    {
+        Mutex::Autolock surfaceLock(mSurfaceLock);
+        if (mSurface != NULL) {
+            mSurface->postBuffer(offset);
+        }
+    }
+
+    // local copy of the callback flags
+    int flags = mPreviewCallbackFlag;
+
+    // is callback enabled?
+    if (!(flags & FRAME_CALLBACK_FLAG_ENABLE_MASK)) {
+        // If the enable bit is off, the copy-out and one-shot bits are ignored
+        LOGV("frame callback is diabled");
+        return;
+    }
+
+    // hold a strong pointer to the client
+    sp<ICameraClient> c = mCameraClient;
+
+    // clear callback flags if no client or one-shot mode
+    if ((c == NULL) || (mPreviewCallbackFlag & FRAME_CALLBACK_FLAG_ONE_SHOT_MASK)) {
+        LOGV("Disable preview callback");
+        mPreviewCallbackFlag &= ~(FRAME_CALLBACK_FLAG_ONE_SHOT_MASK |
+                                FRAME_CALLBACK_FLAG_COPY_OUT_MASK |
+                                FRAME_CALLBACK_FLAG_ENABLE_MASK);
+        // TODO: Shouldn't we use this API for non-overlay hardware as well?
+        if (mUseOverlay)
+            mHardware->disableMsgType(CAMERA_MSG_PREVIEW_FRAME);
+    }
+
+    // Is the received frame copied out or not?
+    if (flags & FRAME_CALLBACK_FLAG_COPY_OUT_MASK) {
+        LOGV("frame is copied");
+        copyFrameAndPostCopiedFrame(c, heap, offset, size);
+    } else {
+        LOGV("frame is forwarded");
+        c->dataCallback(CAMERA_MSG_PREVIEW_FRAME, mem);
+    }
+}
+
+// picture callback - postview image ready
+void CameraService::Client::handlePostview(const sp<IMemory>& mem)
+{
+#if DEBUG_DUMP_POSTVIEW_SNAPSHOT_TO_FILE // for testing pursposes only
+    {
+        ssize_t offset;
+        size_t size;
+        sp<IMemoryHeap> heap = mem->getMemory(&offset, &size);
+        dump_to_file("/data/postview.yuv",
+                     (uint8_t *)heap->base() + offset, size);
+    }
+#endif
+
+    sp<ICameraClient> c = mCameraClient;
+    if (c != NULL) {
+        c->dataCallback(CAMERA_MSG_POSTVIEW_FRAME, mem);
+    }
+    mHardware->disableMsgType(CAMERA_MSG_POSTVIEW_FRAME);
+}
+
+// picture callback - raw image ready
+void CameraService::Client::handleRawPicture(const sp<IMemory>& mem)
+{
+    ssize_t offset;
+    size_t size;
+    sp<IMemoryHeap> heap = mem->getMemory(&offset, &size);
+#if DEBUG_HEAP_LEAKS && 0 // debugging
+    gWeakHeap = heap; // debugging
+#endif
+
+    //LOGV("handleRawPicture(%d, %d)", offset, size);
+#if DEBUG_DUMP_YUV_SNAPSHOT_TO_FILE // for testing pursposes only
+    dump_to_file("/data/photo.yuv",
+                 (uint8_t *)heap->base() + offset, size);
+#endif
+
+    // Put the YUV version of the snapshot in the preview display.
+    if (mSurface != 0 && !mUseOverlay) {
+        mSurface->postBuffer(offset);
+    }
+
+    sp<ICameraClient> c = mCameraClient;
+    if (c != NULL) {
+        c->dataCallback(CAMERA_MSG_RAW_IMAGE, mem);
+    }
+    mHardware->disableMsgType(CAMERA_MSG_RAW_IMAGE);
+}
+
+// picture callback - compressed picture ready
+void CameraService::Client::handleCompressedPicture(const sp<IMemory>& mem)
+{
+#if DEBUG_DUMP_JPEG_SNAPSHOT_TO_FILE // for testing pursposes only
+    {
+        ssize_t offset;
+        size_t size;
+        sp<IMemoryHeap> heap = mem->getMemory(&offset, &size);
+        dump_to_file("/data/photo.jpg",
+                     (uint8_t *)heap->base() + offset, size);
+    }
+#endif
+
+    sp<ICameraClient> c = mCameraClient;
+    if (c != NULL) {
+        c->dataCallback(CAMERA_MSG_COMPRESSED_IMAGE, mem);
+    }
+    mHardware->disableMsgType(CAMERA_MSG_COMPRESSED_IMAGE);
+}
+
+void CameraService::Client::notifyCallback(int32_t msgType, int32_t ext1, int32_t ext2, void* user)
+{
+    LOGV("notifyCallback(%d)", msgType);
+
+    sp<Client> client = getClientFromCookie(user);
+    if (client == 0) {
+        return;
+    }
+
+    switch (msgType) {
+        case CAMERA_MSG_SHUTTER:
+            // ext1 is the dimension of the yuv picture.
+            client->handleShutter((image_rect_type *)ext1);
+            break;
+        default:
+            sp<ICameraClient> c = client->mCameraClient;
+            if (c != NULL) {
+                c->notifyCallback(msgType, ext1, ext2);
+            }
+            break;
+    }
+
+#if DEBUG_CLIENT_REFERENCES
+    if (client->getStrongCount() == 1) {
+        LOGE("++++++++++++++++ (NOTIFY CALLBACK) THIS WILL CAUSE A LOCKUP!");
+        client->printRefs();
+    }
+#endif
+}
+
+void CameraService::Client::dataCallback(int32_t msgType, const sp<IMemory>& dataPtr, void* user)
+{
+    LOGV("dataCallback(%d)", msgType);
+
+    sp<Client> client = getClientFromCookie(user);
+    if (client == 0) {
+        return;
+    }
+
+    sp<ICameraClient> c = client->mCameraClient;
+    if (dataPtr == NULL) {
+        LOGE("Null data returned in data callback");
+        if (c != NULL) {
+            c->notifyCallback(CAMERA_MSG_ERROR, UNKNOWN_ERROR, 0);
+            c->dataCallback(msgType, NULL);
+        }
+        return;
+    }
+
+    switch (msgType) {
+        case CAMERA_MSG_PREVIEW_FRAME:
+            client->handlePreviewData(dataPtr);
+            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:
+            if (c != NULL) {
+                c->dataCallback(msgType, dataPtr);
+            }
+            break;
+    }
+
+#if DEBUG_CLIENT_REFERENCES
+    if (client->getStrongCount() == 1) {
+        LOGE("++++++++++++++++ (DATA CALLBACK) THIS WILL CAUSE A LOCKUP!");
+        client->printRefs();
+    }
+#endif
+}
+
+void CameraService::Client::dataCallbackTimestamp(nsecs_t timestamp, int32_t msgType,
+                                                  const sp<IMemory>& dataPtr, void* user)
+{
+    LOGV("dataCallbackTimestamp(%d)", msgType);
+
+    sp<Client> client = getClientFromCookie(user);
+    if (client == 0) {
+        return;
+    }
+    sp<ICameraClient> c = client->mCameraClient;
+
+    if (dataPtr == NULL) {
+        LOGE("Null data returned in data with timestamp callback");
+        if (c != NULL) {
+            c->notifyCallback(CAMERA_MSG_ERROR, UNKNOWN_ERROR, 0);
+            c->dataCallbackTimestamp(0, msgType, NULL);
+        }
+        return;
+    }
+
+    if (c != NULL) {
+        c->dataCallbackTimestamp(timestamp, msgType, dataPtr);
+    }
+
+#if DEBUG_CLIENT_REFERENCES
+    if (client->getStrongCount() == 1) {
+        LOGE("++++++++++++++++ (DATA CALLBACK TIMESTAMP) THIS WILL CAUSE A LOCKUP!");
+        client->printRefs();
+    }
+#endif
+}
+
+// set preview/capture parameters - key/value pairs
+status_t CameraService::Client::setParameters(const String8& params)
+{
+    LOGV("setParameters(%s)", params.string());
+
+    Mutex::Autolock lock(mLock);
+    status_t result = checkPid();
+    if (result != NO_ERROR) return result;
+
+    if (mHardware == 0) {
+        LOGE("mHardware is NULL, returning.");
+        return INVALID_OPERATION;
+    }
+
+    CameraParameters p(params);
+
+    return mHardware->setParameters(p);
+}
+
+// get preview/capture parameters - key/value pairs
+String8 CameraService::Client::getParameters() const
+{
+    Mutex::Autolock lock(mLock);
+
+    if (mHardware == 0) {
+        LOGE("mHardware is NULL, returning.");
+        return String8();
+    }
+
+    String8 params(mHardware->getParameters().flatten());
+    LOGV("getParameters(%s)", params.string());
+    return params;
+}
+
+status_t CameraService::Client::sendCommand(int32_t cmd, int32_t arg1, int32_t arg2)
+{
+    LOGV("sendCommand (pid %d)", getCallingPid());
+    Mutex::Autolock lock(mLock);
+    status_t result = checkPid();
+    if (result != NO_ERROR) return result;
+
+    if (cmd == CAMERA_CMD_SET_DISPLAY_ORIENTATION) {
+        // The orientation cannot be set during preview.
+        if (mHardware->previewEnabled()) {
+            return INVALID_OPERATION;
+        }
+        switch (arg1) {
+            case 0:
+                mOrientation = ISurface::BufferHeap::ROT_0;
+                break;
+            case 90:
+                mOrientation = ISurface::BufferHeap::ROT_90;
+                break;
+            case 180:
+                mOrientation = ISurface::BufferHeap::ROT_180;
+                break;
+            case 270:
+                mOrientation = ISurface::BufferHeap::ROT_270;
+                break;
+            default:
+                return BAD_VALUE;
+        }
+        return OK;
+    }
+
+    if (mHardware == 0) {
+        LOGE("mHardware is NULL, returning.");
+        return INVALID_OPERATION;
+    }
+
+    return mHardware->sendCommand(cmd, arg1, arg2);
+}
+
+void CameraService::Client::copyFrameAndPostCopiedFrame(const sp<ICameraClient>& client,
+        const sp<IMemoryHeap>& heap, size_t offset, size_t size)
+{
+    LOGV("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;
+    {
+        Mutex::Autolock lock(mPreviewLock);
+        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) {
+            LOGE("failed to allocate space for preview buffer");
+            return;
+        }
+        previewBuffer = mPreviewBuffer;
+    }
+    memcpy(previewBuffer->base(),
+           (uint8_t *)heap->base() + offset, size);
+
+    sp<MemoryBase> frame = new MemoryBase(previewBuffer, 0, size);
+    if (frame == 0) {
+        LOGE("failed to allocate space for frame callback");
+        return;
+    }
+    client->dataCallback(CAMERA_MSG_PREVIEW_FRAME, frame);
+}
+
+static const int kDumpLockRetries = 50;
+static const int kDumpLockSleep = 60000;
+
+static bool tryLock(Mutex& mutex)
+{
+    bool locked = false;
+    for (int i = 0; i < kDumpLockRetries; ++i) {
+        if (mutex.tryLock() == NO_ERROR) {
+            locked = true;
+            break;
+        }
+        usleep(kDumpLockSleep);
+    }
+    return locked;
+}
+
+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: "
+                "can't dump CameraService from pid=%d, uid=%d\n",
+                getCallingPid(),
+                IPCThreadState::self()->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());
+        }
+
+        if (mClient != 0) {
+            sp<Client> currentClient = mClient.promote();
+            sprintf(buffer, "Client (%p) PID: %d\n",
+                    currentClient->getCameraClient()->asBinder().get(),
+                    currentClient->mClientPid);
+            result.append(buffer);
+            write(fd, result.string(), result.size());
+            currentClient->mHardware->dump(fd, args);
+        } else {
+            result.append("No camera client yet.\n");
+            write(fd, result.string(), result.size());
+        }
+
+        if (locked) mServiceLock.unlock();
+    }
+    return NO_ERROR;
+}
+
+
+status_t CameraService::onTransact(
+    uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
+{
+    // permission checks...
+    switch (code) {
+        case BnCameraService::CONNECT:
+            IPCThreadState* ipc = IPCThreadState::self();
+            const int pid = ipc->getCallingPid();
+            const int self_pid = getpid();
+            if (pid != self_pid) {
+                // we're called from a different process, do the real check
+                if (!checkCallingPermission(
+                        String16("android.permission.CAMERA")))
+                {
+                    const int uid = ipc->getCallingUid();
+                    LOGE("Permission Denial: "
+                            "can't use the camera pid=%d, uid=%d", pid, uid);
+                    return PERMISSION_DENIED;
+                }
+            }
+            break;
+    }
+
+    status_t err = BnCameraService::onTransact(code, data, reply, flags);
+
+#if DEBUG_HEAP_LEAKS
+    LOGV("+++ onTransact err %d code %d", err, code);
+
+    if (err == UNKNOWN_TRANSACTION || err == PERMISSION_DENIED) {
+        // the 'service' command interrogates this binder for its name, and then supplies it
+        // even for the debugging commands.  that means we need to check for it here, using
+        // ISurfaceComposer (since we delegated the INTERFACE_TRANSACTION handling to
+        // BnSurfaceComposer before falling through to this code).
+
+        LOGV("+++ onTransact code %d", code);
+
+        CHECK_INTERFACE(ICameraService, data, reply);
+
+        switch(code) {
+        case 1000:
+        {
+            if (gWeakHeap != 0) {
+                sp<IMemoryHeap> h = gWeakHeap.promote();
+                IMemoryHeap *p = gWeakHeap.unsafe_get();
+                LOGV("CHECKING WEAK REFERENCE %p (%p)", h.get(), p);
+                if (h != 0)
+                    h->printRefs();
+                bool attempt_to_delete = data.readInt32() == 1;
+                if (attempt_to_delete) {
+                    // NOT SAFE!
+                    LOGV("DELETING WEAK REFERENCE %p (%p)", h.get(), p);
+                    if (p) delete p;
+                }
+                return NO_ERROR;
+            }
+        }
+        break;
+        default:
+            break;
+        }
+    }
+#endif // DEBUG_HEAP_LEAKS
+
+    return err;
+}
+
+}; // namespace android
diff --git a/services/camera/libcameraservice/CameraService.h b/services/camera/libcameraservice/CameraService.h
new file mode 100644
index 0000000..bc49b1d
--- /dev/null
+++ b/services/camera/libcameraservice/CameraService.h
@@ -0,0 +1,227 @@
+/*
+**
+** Copyright (C) 2008, The Android Open Source Project
+** Copyright (C) 2008 HTC Inc.
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+
+#ifndef ANDROID_SERVERS_CAMERA_CAMERASERVICE_H
+#define ANDROID_SERVERS_CAMERA_CAMERASERVICE_H
+
+#include <camera/ICameraService.h>
+#include <camera/CameraHardwareInterface.h>
+#include <camera/Camera.h>
+
+namespace android {
+
+class MemoryHeapBase;
+class MediaPlayer;
+
+// ----------------------------------------------------------------------------
+
+#define LIKELY( exp )       (__builtin_expect( (exp) != 0, true  ))
+#define UNLIKELY( exp )     (__builtin_expect( (exp) != 0, false ))
+
+// When enabled, this feature allows you to send an event to the CameraService
+// so that you can cause all references to the heap object gWeakHeap, defined
+// below, to be printed. You will also need to set DEBUG_REFS=1 and
+// DEBUG_REFS_ENABLED_BY_DEFAULT=0 in libutils/RefBase.cpp. You just have to
+// set gWeakHeap to the appropriate heap you want to track.
+
+#define DEBUG_HEAP_LEAKS 0
+
+// ----------------------------------------------------------------------------
+
+class CameraService : public BnCameraService
+{
+    class Client;
+
+public:
+    static void instantiate();
+
+    // ICameraService interface
+    virtual sp<ICamera>     connect(const sp<ICameraClient>& cameraClient);
+
+    virtual status_t        dump(int fd, const Vector<String16>& args);
+
+            void            removeClient(const sp<ICameraClient>& cameraClient);
+
+    virtual status_t onTransact(
+        uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags);
+
+private:
+
+// ----------------------------------------------------------------------------
+
+    class Client : public BnCamera {
+
+    public:
+        virtual void            disconnect();
+
+        // connect new client with existing camera remote
+        virtual status_t        connect(const sp<ICameraClient>& client);
+
+        // prevent other processes from using this ICamera interface
+        virtual status_t        lock();
+
+        // allow other processes to use this ICamera interface
+        virtual status_t        unlock();
+
+        // pass the buffered ISurface to the camera service
+        virtual status_t        setPreviewDisplay(const sp<ISurface>& surface);
+
+        // set the preview callback flag to affect how the received frames from
+        // preview are handled.
+        virtual void            setPreviewCallbackFlag(int callback_flag);
+
+        // start preview mode, must call setPreviewDisplay first
+        virtual status_t        startPreview();
+
+        // stop preview mode
+        virtual void            stopPreview();
+
+        // get preview state
+        virtual bool            previewEnabled();
+
+        // start recording mode
+        virtual status_t        startRecording();
+
+        // stop recording mode
+        virtual void            stopRecording();
+
+        // get recording state
+        virtual bool            recordingEnabled();
+
+        // release a recording frame
+        virtual void            releaseRecordingFrame(const sp<IMemory>& mem);
+
+        // auto focus
+        virtual status_t        autoFocus();
+
+        // cancel auto focus
+        virtual status_t        cancelAutoFocus();
+
+        // take a picture - returns an IMemory (ref-counted mmap)
+        virtual status_t        takePicture();
+
+        // set preview/capture parameters - key/value pairs
+        virtual status_t        setParameters(const String8& params);
+
+        // get preview/capture parameters - key/value pairs
+        virtual String8         getParameters() const;
+
+        // send command to camera driver
+        virtual status_t        sendCommand(int32_t cmd, int32_t arg1, int32_t arg2);
+
+        // our client...
+        const sp<ICameraClient>&    getCameraClient() const { return mCameraClient; }
+
+    private:
+        friend class CameraService;
+                                Client(const sp<CameraService>& cameraService,
+                                        const sp<ICameraClient>& cameraClient,
+                                        pid_t clientPid);
+                                Client();
+        virtual                 ~Client();
+
+                    status_t    checkPid();
+
+        static      void        notifyCallback(int32_t msgType, int32_t ext1, int32_t ext2, void* user);
+        static      void        dataCallback(int32_t msgType, const sp<IMemory>& dataPtr, void* user);
+        static      void        dataCallbackTimestamp(nsecs_t timestamp, int32_t msgType,
+                                                      const sp<IMemory>& dataPtr, void* user);
+
+        static      sp<Client>  getClientFromCookie(void* user);
+
+                    void        handlePreviewData(const sp<IMemory>&);
+                    void        handleShutter(image_rect_type *image);
+                    void        handlePostview(const sp<IMemory>&);
+                    void        handleRawPicture(const sp<IMemory>&);
+                    void        handleCompressedPicture(const sp<IMemory>&);
+
+                    void        copyFrameAndPostCopiedFrame(const sp<ICameraClient>& client,
+                                    const sp<IMemoryHeap>& heap, size_t offset, size_t size);
+
+        // 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()
+        };
+        status_t                startCameraMode(camera_mode mode);
+        status_t                startPreviewMode();
+        status_t                startRecordingMode();
+        status_t                setOverlay();
+        status_t                registerPreviewBuffers();
+
+        // Ensures atomicity among the public methods
+        mutable     Mutex                       mLock;
+
+        // mSurfaceLock synchronizes access to mSurface between
+        // setPreviewSurface() and postPreviewFrame().  Note that among
+        // the public methods, all accesses to mSurface are
+        // syncrhonized by mLock.  However, postPreviewFrame() is called
+        // by the CameraHardwareInterface callback, and needs to
+        // access mSurface.  It cannot hold mLock, however, because
+        // stopPreview() may be holding that lock while attempting
+        // to stop preview, and stopPreview itself will block waiting
+        // for a callback from CameraHardwareInterface.  If this
+        // happens, it will cause a deadlock.
+        mutable     Mutex                       mSurfaceLock;
+        mutable     Condition                   mReady;
+                    sp<CameraService>           mCameraService;
+                    sp<ISurface>                mSurface;
+                    int                         mPreviewCallbackFlag;
+                    int                         mOrientation;
+
+                    sp<MediaPlayer>             mMediaPlayerClick;
+                    sp<MediaPlayer>             mMediaPlayerBeep;
+
+                    // these are immutable once the object is created,
+                    // they don't need to be protected by a lock
+                    sp<ICameraClient>           mCameraClient;
+                    sp<CameraHardwareInterface> mHardware;
+                    pid_t                       mClientPid;
+                    bool                        mUseOverlay;
+
+                    sp<OverlayRef>              mOverlayRef;
+                    int                         mOverlayW;
+                    int                         mOverlayH;
+
+        mutable     Mutex                       mPreviewLock;
+                    sp<MemoryHeapBase>          mPreviewBuffer;
+    };
+
+// ----------------------------------------------------------------------------
+
+                            CameraService();
+    virtual                 ~CameraService();
+
+    // We use a count for number of clients (shoule only be 0 or 1).
+    volatile    int32_t                     mUsers;
+    virtual     void                        incUsers();
+    virtual     void                        decUsers();
+
+    mutable     Mutex                       mServiceLock;
+                wp<Client>                  mClient;
+
+#if DEBUG_HEAP_LEAKS
+                wp<IMemoryHeap>             gWeakHeap;
+#endif
+};
+
+// ----------------------------------------------------------------------------
+
+}; // namespace android
+
+#endif
diff --git a/services/camera/libcameraservice/CannedJpeg.h b/services/camera/libcameraservice/CannedJpeg.h
new file mode 100644
index 0000000..b6266fb
--- /dev/null
+++ b/services/camera/libcameraservice/CannedJpeg.h
@@ -0,0 +1,734 @@
+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
new file mode 100644
index 0000000..6749899
--- /dev/null
+++ b/services/camera/libcameraservice/FakeCamera.cpp
@@ -0,0 +1,430 @@
+/*
+**
+** 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 *yuv422,uint32_t *param,uint8_t *table[])
+{
+    uint16_t *inputRGB = (uint16_t*)rgb16;
+    uint8_t *outYUV =  yuv422;
+    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;
+            tempU[0] = u;
+            tempV[0] = v;
+
+            tempY += 2;
+            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_yuv422(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 getNextFrameAsYuv422().
+    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::getNextFrameAsYuv422(uint8_t *buffer)
+{
+    if (mTmpRgb16Buffer == 0)
+        mTmpRgb16Buffer = new uint16_t[mWidth * mHeight];
+
+    getNextFrameAsRgb565(mTmpRgb16Buffer);
+    convert_rgb16_to_yuv422((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
new file mode 100644
index 0000000..f7f8803
--- /dev/null
+++ b/services/camera/libcameraservice/FakeCamera.h
@@ -0,0 +1,67 @@
+/*
+**
+** 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 getNextFrameAsYuv422(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
diff --git a/services/camera/tests/CameraServiceTest/Android.mk b/services/camera/tests/CameraServiceTest/Android.mk
new file mode 100644
index 0000000..9bb190a
--- /dev/null
+++ b/services/camera/tests/CameraServiceTest/Android.mk
@@ -0,0 +1,24 @@
+LOCAL_PATH:= $(call my-dir)
+
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES:= CameraServiceTest.cpp
+
+LOCAL_MODULE:= CameraServiceTest
+
+LOCAL_MODULE_TAGS := tests
+
+LOCAL_C_INCLUDES += \
+                frameworks/base/libs
+
+LOCAL_CFLAGS :=
+
+LOCAL_SHARED_LIBRARIES += \
+		libbinder \
+                libcutils \
+                libutils \
+                libui \
+                libcamera_client \
+                libsurfaceflinger_client
+
+include $(BUILD_EXECUTABLE)
diff --git a/services/camera/tests/CameraServiceTest/CameraServiceTest.cpp b/services/camera/tests/CameraServiceTest/CameraServiceTest.cpp
new file mode 100644
index 0000000..9fc795b
--- /dev/null
+++ b/services/camera/tests/CameraServiceTest/CameraServiceTest.cpp
@@ -0,0 +1,849 @@
+#define LOG_TAG "CameraServiceTest"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <unistd.h>
+#include <surfaceflinger/ISurface.h>
+#include <camera/Camera.h>
+#include <camera/CameraParameters.h>
+#include <ui/GraphicBuffer.h>
+#include <camera/ICamera.h>
+#include <camera/ICameraClient.h>
+#include <camera/ICameraService.h>
+#include <ui/Overlay.h>
+#include <binder/IPCThreadState.h>
+#include <binder/IServiceManager.h>
+#include <binder/ProcessState.h>
+#include <utils/KeyedVector.h>
+#include <utils/Log.h>
+#include <utils/Vector.h>
+#include <utils/threads.h>
+
+using namespace android;
+
+//
+//  Assertion and Logging utilities
+//
+#define INFO(...) \
+    do { \
+        printf(__VA_ARGS__); \
+        printf("\n"); \
+        LOGD(__VA_ARGS__); \
+    } while(0)
+
+void assert_fail(const char *file, int line, const char *func, const char *expr) {
+    INFO("assertion failed at file %s, line %d, function %s:",
+            file, line, func);
+    INFO("%s", expr);
+    exit(1);
+}
+
+void assert_eq_fail(const char *file, int line, const char *func,
+        const char *expr, int actual) {
+    INFO("assertion failed at file %s, line %d, function %s:",
+            file, line, func);
+    INFO("(expected) %s != (actual) %d", expr, actual);
+    exit(1);
+}
+
+#define ASSERT(e) \
+    do { \
+        if (!(e)) \
+            assert_fail(__FILE__, __LINE__, __func__, #e); \
+    } while(0)
+
+#define ASSERT_EQ(expected, actual) \
+    do { \
+        int _x = (actual); \
+        if (_x != (expected)) \
+            assert_eq_fail(__FILE__, __LINE__, __func__, #expected, _x); \
+    } while(0)
+
+//
+//  Holder service for pass objects between processes.
+//
+class IHolder : public IInterface {
+protected:
+    enum {
+        HOLDER_PUT = IBinder::FIRST_CALL_TRANSACTION,
+        HOLDER_GET,
+        HOLDER_CLEAR
+    };
+public:
+    DECLARE_META_INTERFACE(Holder);
+
+    virtual void put(sp<IBinder> obj) = 0;
+    virtual sp<IBinder> get() = 0;
+    virtual void clear() = 0;
+};
+
+class BnHolder : public BnInterface<IHolder> {
+    virtual status_t onTransact(uint32_t code,
+                                const Parcel& data,
+                                Parcel* reply,
+                                uint32_t flags = 0);
+};
+
+class BpHolder : public BpInterface<IHolder> {
+public:
+    BpHolder(const sp<IBinder>& impl)
+        : BpInterface<IHolder>(impl) {
+    }
+
+    virtual void put(sp<IBinder> obj) {
+        Parcel data, reply;
+        data.writeStrongBinder(obj);
+        remote()->transact(HOLDER_PUT, data, &reply, IBinder::FLAG_ONEWAY);
+    }
+
+    virtual sp<IBinder> get() {
+        Parcel data, reply;
+        remote()->transact(HOLDER_GET, data, &reply);
+        return reply.readStrongBinder();
+    }
+
+    virtual void clear() {
+        Parcel data, reply;
+        remote()->transact(HOLDER_CLEAR, data, &reply);
+    }
+};
+
+IMPLEMENT_META_INTERFACE(Holder, "CameraServiceTest.Holder");
+
+status_t BnHolder::onTransact(
+    uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) {
+    switch(code) {
+        case HOLDER_PUT: {
+            put(data.readStrongBinder());
+            return NO_ERROR;
+        } break;
+        case HOLDER_GET: {
+            reply->writeStrongBinder(get());
+            return NO_ERROR;
+        } break;
+        case HOLDER_CLEAR: {
+            clear();
+            return NO_ERROR;
+        } break;
+        default:
+            return BBinder::onTransact(code, data, reply, flags);
+    }
+}
+
+class HolderService : public BnHolder {
+    virtual void put(sp<IBinder> obj) {
+        mObj = obj;
+    }
+    virtual sp<IBinder> get() {
+        return mObj;
+    }
+    virtual void clear() {
+        mObj.clear();
+    }
+private:
+    sp<IBinder> mObj;
+};
+
+//
+//  A mock CameraClient
+//
+class MCameraClient : public BnCameraClient {
+public:
+    virtual void notifyCallback(int32_t msgType, int32_t ext1, int32_t ext2);
+    virtual void dataCallback(int32_t msgType, const sp<IMemory>& data);
+    virtual void dataCallbackTimestamp(nsecs_t timestamp,
+            int32_t msgType, const sp<IMemory>& data) {}
+
+    // new functions
+    void clearStat();
+    enum OP { EQ, GE, LE, GT, LT };
+    void assertNotify(int32_t msgType, OP op, int count);
+    void assertData(int32_t msgType, OP op, int count);
+    void waitNotify(int32_t msgType, OP op, int count);
+    void waitData(int32_t msgType, OP op, int count);
+    void assertDataSize(int32_t msgType, OP op, int dataSize);
+
+    void setReleaser(ICamera *releaser) {
+        mReleaser = releaser;
+    }
+private:
+    Mutex mLock;
+    Condition mCond;
+    DefaultKeyedVector<int32_t, int> mNotifyCount;
+    DefaultKeyedVector<int32_t, int> mDataCount;
+    DefaultKeyedVector<int32_t, int> mDataSize;
+    bool test(OP op, int v1, int v2);
+
+    ICamera *mReleaser;
+};
+
+void MCameraClient::clearStat() {
+    Mutex::Autolock _l(mLock);
+    mNotifyCount.clear();
+    mDataCount.clear();
+    mDataSize.clear();
+}
+
+bool MCameraClient::test(OP op, int v1, int v2) {
+    switch (op) {
+        case EQ: return v1 == v2;
+        case GT: return v1 > v2;
+        case LT: return v1 < v2;
+        case GE: return v1 >= v2;
+        case LE: return v1 <= v2;
+        default: ASSERT(0); break;
+    }
+    return false;
+}
+
+void MCameraClient::assertNotify(int32_t msgType, OP op, int count) {
+    Mutex::Autolock _l(mLock);
+    int v = mNotifyCount.valueFor(msgType);
+    ASSERT(test(op, v, count));
+}
+
+void MCameraClient::assertData(int32_t msgType, OP op, int count) {
+    Mutex::Autolock _l(mLock);
+    int v = mDataCount.valueFor(msgType);
+    ASSERT(test(op, v, count));
+}
+
+void MCameraClient::assertDataSize(int32_t msgType, OP op, int dataSize) {
+    Mutex::Autolock _l(mLock);
+    int v = mDataSize.valueFor(msgType);
+    ASSERT(test(op, v, dataSize));
+}
+
+void MCameraClient::notifyCallback(int32_t msgType, int32_t ext1, int32_t ext2) {
+    INFO(__func__);
+    Mutex::Autolock _l(mLock);
+    ssize_t i = mNotifyCount.indexOfKey(msgType);
+    if (i < 0) {
+        mNotifyCount.add(msgType, 1);
+    } else {
+        ++mNotifyCount.editValueAt(i);
+    }
+    mCond.signal();
+}
+
+void MCameraClient::dataCallback(int32_t msgType, const sp<IMemory>& data) {
+    INFO(__func__);
+    int dataSize = data->size();
+    INFO("data type = %d, size = %d", msgType, dataSize);
+    Mutex::Autolock _l(mLock);
+    ssize_t i = mDataCount.indexOfKey(msgType);
+    if (i < 0) {
+        mDataCount.add(msgType, 1);
+        mDataSize.add(msgType, dataSize);
+    } else {
+        ++mDataCount.editValueAt(i);
+        mDataSize.editValueAt(i) = dataSize;
+    }
+    mCond.signal();
+
+    if (msgType == CAMERA_MSG_VIDEO_FRAME) {
+        ASSERT(mReleaser != NULL);
+        mReleaser->releaseRecordingFrame(data);
+    }
+}
+
+void MCameraClient::waitNotify(int32_t msgType, OP op, int count) {
+    INFO("waitNotify: %d, %d, %d", msgType, op, count);
+    Mutex::Autolock _l(mLock);
+    while (true) {
+        int v = mNotifyCount.valueFor(msgType);
+        if (test(op, v, count)) {
+            break;
+        }
+        mCond.wait(mLock);
+    }
+}
+
+void MCameraClient::waitData(int32_t msgType, OP op, int count) {
+    INFO("waitData: %d, %d, %d", msgType, op, count);
+    Mutex::Autolock _l(mLock);
+    while (true) {
+        int v = mDataCount.valueFor(msgType);
+        if (test(op, v, count)) {
+            break;
+        }
+        mCond.wait(mLock);
+    }
+}
+
+//
+//  A mock Surface
+//
+class MSurface : public BnSurface {
+public:
+    virtual status_t registerBuffers(const BufferHeap& buffers);
+    virtual void postBuffer(ssize_t offset);
+    virtual void unregisterBuffers();
+    virtual sp<OverlayRef> createOverlay(
+            uint32_t w, uint32_t h, int32_t format, int32_t orientation);
+    virtual sp<GraphicBuffer> requestBuffer(int bufferIdx, int usage);
+
+    // new functions
+    void clearStat();
+    void waitUntil(int c0, int c1, int c2);
+
+private:
+    // check callback count
+    Condition mCond;
+    Mutex mLock;
+    int registerBuffersCount;
+    int postBufferCount;
+    int unregisterBuffersCount;
+};
+
+status_t MSurface::registerBuffers(const BufferHeap& buffers) {
+    INFO(__func__);
+    Mutex::Autolock _l(mLock);
+    ++registerBuffersCount;
+    mCond.signal();
+    return NO_ERROR;
+}
+
+void MSurface::postBuffer(ssize_t offset) {
+    // INFO(__func__);
+    Mutex::Autolock _l(mLock);
+    ++postBufferCount;
+    mCond.signal();
+}
+
+void MSurface::unregisterBuffers() {
+    INFO(__func__);
+    Mutex::Autolock _l(mLock);
+    ++unregisterBuffersCount;
+    mCond.signal();
+}
+
+sp<GraphicBuffer> MSurface::requestBuffer(int bufferIdx, int usage) {
+    INFO(__func__);
+    return NULL;
+}
+
+void MSurface::clearStat() {
+    Mutex::Autolock _l(mLock);
+    registerBuffersCount = 0;
+    postBufferCount = 0;
+    unregisterBuffersCount = 0;
+}
+
+void MSurface::waitUntil(int c0, int c1, int c2) {
+    INFO("waitUntil: %d %d %d", c0, c1, c2);
+    Mutex::Autolock _l(mLock);
+    while (true) {
+        if (registerBuffersCount >= c0 &&
+            postBufferCount >= c1 &&
+            unregisterBuffersCount >= c2) {
+            break;
+        }
+        mCond.wait(mLock);
+    }
+}
+
+sp<OverlayRef> MSurface::createOverlay(uint32_t w, uint32_t h, int32_t format,
+        int32_t orientation) {
+    // We don't expect this to be called in current hardware.
+    ASSERT(0);
+    sp<OverlayRef> dummy;
+    return dummy;
+}
+
+//
+//  Utilities to use the Holder service
+//
+sp<IHolder> getHolder() {
+    sp<IServiceManager> sm = defaultServiceManager();
+    ASSERT(sm != 0);
+    sp<IBinder> binder = sm->getService(String16("CameraServiceTest.Holder"));
+    ASSERT(binder != 0);
+    sp<IHolder> holder = interface_cast<IHolder>(binder);
+    ASSERT(holder != 0);
+    return holder;
+}
+
+void putTempObject(sp<IBinder> obj) {
+    INFO(__func__);
+    getHolder()->put(obj);
+}
+
+sp<IBinder> getTempObject() {
+    INFO(__func__);
+    return getHolder()->get();
+}
+
+void clearTempObject() {
+    INFO(__func__);
+    getHolder()->clear();
+}
+
+//
+//  Get a Camera Service
+//
+sp<ICameraService> getCameraService() {
+    sp<IServiceManager> sm = defaultServiceManager();
+    ASSERT(sm != 0);
+    sp<IBinder> binder = sm->getService(String16("media.camera"));
+    ASSERT(binder != 0);
+    sp<ICameraService> cs = interface_cast<ICameraService>(binder);
+    ASSERT(cs != 0);
+    return cs;
+}
+
+//
+// Various Connect Tests
+//
+void testConnect() {
+    INFO(__func__);
+    sp<ICameraService> cs = getCameraService();
+    sp<MCameraClient> cc = new MCameraClient();
+    sp<ICamera> c = cs->connect(cc);
+    ASSERT(c != 0);
+    c->disconnect();
+}
+
+void testAllowConnectOnceOnly() {
+    INFO(__func__);
+    sp<ICameraService> cs = getCameraService();
+    // Connect the first client.
+    sp<MCameraClient> cc = new MCameraClient();
+    sp<ICamera> c = cs->connect(cc);
+    ASSERT(c != 0);
+    // Same client -- ok.
+    ASSERT(cs->connect(cc) != 0);
+    // Different client -- not ok.
+    sp<MCameraClient> cc2 = new MCameraClient();
+    ASSERT(cs->connect(cc2) == 0);
+    c->disconnect();
+}
+
+void testReconnectFailed() {
+    INFO(__func__);
+    sp<ICamera> c = interface_cast<ICamera>(getTempObject());
+    sp<MCameraClient> cc2 = new MCameraClient();
+    ASSERT(c->connect(cc2) != NO_ERROR);
+}
+
+void testReconnectSuccess() {
+    INFO(__func__);
+    sp<ICamera> c = interface_cast<ICamera>(getTempObject());
+    sp<MCameraClient> cc = new MCameraClient();
+    ASSERT(c->connect(cc) == NO_ERROR);
+}
+
+void testLockFailed() {
+    INFO(__func__);
+    sp<ICamera> c = interface_cast<ICamera>(getTempObject());
+    ASSERT(c->lock() != NO_ERROR);
+}
+
+void testLockUnlockSuccess() {
+    INFO(__func__);
+    sp<ICamera> c = interface_cast<ICamera>(getTempObject());
+    ASSERT(c->lock() == NO_ERROR);
+    ASSERT(c->unlock() == NO_ERROR);
+}
+
+void testLockSuccess() {
+    INFO(__func__);
+    sp<ICamera> c = interface_cast<ICamera>(getTempObject());
+    ASSERT(c->lock() == NO_ERROR);
+}
+
+//
+// Run the connect tests in another process.
+//
+const char *gExecutable;
+
+struct FunctionTableEntry {
+    const char *name;
+    void (*func)();
+};
+
+FunctionTableEntry function_table[] = {
+#define ENTRY(x) {#x, &x}
+    ENTRY(testReconnectFailed),
+    ENTRY(testReconnectSuccess),
+    ENTRY(testLockUnlockSuccess),
+    ENTRY(testLockFailed),
+    ENTRY(testLockSuccess),
+#undef ENTRY
+};
+
+void runFunction(const char *tag) {
+    INFO("runFunction: %s", tag);
+    int entries = sizeof(function_table) / sizeof(function_table[0]);
+    for (int i = 0; i < entries; i++) {
+        if (strcmp(function_table[i].name, tag) == 0) {
+            (*function_table[i].func)();
+            return;
+        }
+    }
+    ASSERT(0);
+}
+
+void runInAnotherProcess(const char *tag) {
+    pid_t pid = fork();
+    if (pid == 0) {
+        execlp(gExecutable, gExecutable, tag, NULL);
+        ASSERT(0);
+    } else {
+        int status;
+        ASSERT_EQ(pid, wait(&status));
+        ASSERT_EQ(0, status);
+    }
+}
+
+void testReconnect() {
+    INFO(__func__);
+    sp<ICameraService> cs = getCameraService();
+    sp<MCameraClient> cc = new MCameraClient();
+    sp<ICamera> c = cs->connect(cc);
+    ASSERT(c != 0);
+    // Reconnect to the same client -- ok.
+    ASSERT(c->connect(cc) == NO_ERROR);
+    // Reconnect to a different client (but the same pid) -- ok.
+    sp<MCameraClient> cc2 = new MCameraClient();
+    ASSERT(c->connect(cc2) == NO_ERROR);
+    c->disconnect();
+    cc->assertNotify(CAMERA_MSG_ERROR, MCameraClient::EQ, 0);
+}
+
+void testLockUnlock() {
+    sp<ICameraService> cs = getCameraService();
+    sp<MCameraClient> cc = new MCameraClient();
+    sp<ICamera> c = cs->connect(cc);
+    ASSERT(c != 0);
+    // We can lock as many times as we want.
+    ASSERT(c->lock() == NO_ERROR);
+    ASSERT(c->lock() == NO_ERROR);
+    // Lock from a different process -- not ok.
+    putTempObject(c->asBinder());
+    runInAnotherProcess("testLockFailed");
+    // Unlock then lock from a different process -- ok.
+    ASSERT(c->unlock() == NO_ERROR);
+    runInAnotherProcess("testLockUnlockSuccess");
+    // Unlock then lock from a different process -- ok.
+    runInAnotherProcess("testLockSuccess");
+    c->disconnect();
+    clearTempObject();
+}
+
+void testReconnectFromAnotherProcess() {
+    INFO(__func__);
+
+    sp<ICameraService> cs = getCameraService();
+    sp<MCameraClient> cc = new MCameraClient();
+    sp<ICamera> c = cs->connect(cc);
+    ASSERT(c != 0);
+    // Reconnect from a different process -- not ok.
+    putTempObject(c->asBinder());
+    runInAnotherProcess("testReconnectFailed");
+    // Unlock then reconnect from a different process -- ok.
+    ASSERT(c->unlock() == NO_ERROR);
+    runInAnotherProcess("testReconnectSuccess");
+    c->disconnect();
+    clearTempObject();
+}
+
+// We need to flush the command buffer after the reference
+// to ICamera is gone. The sleep is for the server to run
+// the destructor for it.
+static void flushCommands() {
+    IPCThreadState::self()->flushCommands();
+    usleep(200000);  // 200ms
+}
+
+// Run a test case
+#define RUN(class_name) do { \
+    { \
+        INFO(#class_name); \
+        class_name instance; \
+        instance.run(); \
+    } \
+    flushCommands(); \
+} while(0)
+
+// Base test case after the the camera is connected.
+class AfterConnect {
+protected:
+    sp<ICameraService> cs;
+    sp<MCameraClient> cc;
+    sp<ICamera> c;
+
+    AfterConnect() {
+        cs = getCameraService();
+        cc = new MCameraClient();
+        c = cs->connect(cc);
+        ASSERT(c != 0);
+    }
+
+    ~AfterConnect() {
+        c.clear();
+        cc.clear();
+        cs.clear();
+    }
+};
+
+class TestSetPreviewDisplay : public AfterConnect {
+public:
+    void run() {
+        sp<MSurface> surface = new MSurface();
+        ASSERT(c->setPreviewDisplay(surface) == NO_ERROR);
+        c->disconnect();
+        cc->assertNotify(CAMERA_MSG_ERROR, MCameraClient::EQ, 0);
+    }
+};
+
+class TestStartPreview : public AfterConnect {
+public:
+    void run() {
+        sp<MSurface> surface = new MSurface();
+        ASSERT(c->setPreviewDisplay(surface) == NO_ERROR);
+
+        ASSERT(c->startPreview() == NO_ERROR);
+        ASSERT(c->previewEnabled() == true);
+
+        surface->waitUntil(1, 10, 0); // needs 1 registerBuffers and 10 postBuffer
+        surface->clearStat();
+
+        c->disconnect();
+        // TODO: CameraService crashes for this. Fix it.
+#if 0
+        sp<MSurface> another_surface = new MSurface();
+        c->setPreviewDisplay(another_surface);  // just to make sure unregisterBuffers
+                                                // is called.
+        surface->waitUntil(0, 0, 1);  // needs unregisterBuffers
+#endif
+        cc->assertNotify(CAMERA_MSG_ERROR, MCameraClient::EQ, 0);
+    }
+};
+
+class TestStartPreviewWithoutDisplay : AfterConnect {
+public:
+    void run() {
+        ASSERT(c->startPreview() == NO_ERROR);
+        ASSERT(c->previewEnabled() == true);
+        c->disconnect();
+        cc->assertNotify(CAMERA_MSG_ERROR, MCameraClient::EQ, 0);
+    }
+};
+
+// Base test case after the the camera is connected and the preview is started.
+class AfterStartPreview : public AfterConnect {
+protected:
+    sp<MSurface> surface;
+
+    AfterStartPreview() {
+        surface = new MSurface();
+        ASSERT(c->setPreviewDisplay(surface) == NO_ERROR);
+        ASSERT(c->startPreview() == NO_ERROR);
+    }
+
+    ~AfterStartPreview() {
+        surface.clear();
+    }
+};
+
+class TestAutoFocus : public AfterStartPreview {
+public:
+    void run() {
+        cc->assertNotify(CAMERA_MSG_FOCUS, MCameraClient::EQ, 0);
+        c->autoFocus();
+        cc->waitNotify(CAMERA_MSG_FOCUS, MCameraClient::EQ, 1);
+        c->disconnect();
+        cc->assertNotify(CAMERA_MSG_ERROR, MCameraClient::EQ, 0);
+    }
+};
+
+class TestStopPreview : public AfterStartPreview {
+public:
+    void run() {
+        ASSERT(c->previewEnabled() == true);
+        c->stopPreview();
+        ASSERT(c->previewEnabled() == false);
+        c->disconnect();
+        cc->assertNotify(CAMERA_MSG_ERROR, MCameraClient::EQ, 0);
+    }
+};
+
+class TestTakePicture: public AfterStartPreview {
+public:
+    void run() {
+        ASSERT(c->takePicture() == NO_ERROR);
+        cc->waitNotify(CAMERA_MSG_SHUTTER, MCameraClient::EQ, 1);
+        cc->waitData(CAMERA_MSG_RAW_IMAGE, MCameraClient::EQ, 1);
+        cc->waitData(CAMERA_MSG_COMPRESSED_IMAGE, MCameraClient::EQ, 1);
+        c->stopPreview();
+#if 1  // TODO: It crashes if we don't have this. Fix it.
+        usleep(100000);
+#endif
+        c->disconnect();
+        cc->assertNotify(CAMERA_MSG_ERROR, MCameraClient::EQ, 0);
+    }
+};
+
+class TestTakeMultiplePictures: public AfterStartPreview {
+public:
+    void run() {
+        for (int i = 0; i < 10; i++) {
+            cc->clearStat();
+            ASSERT(c->takePicture() == NO_ERROR);
+            cc->waitNotify(CAMERA_MSG_SHUTTER, MCameraClient::EQ, 1);
+            cc->waitData(CAMERA_MSG_RAW_IMAGE, MCameraClient::EQ, 1);
+            cc->waitData(CAMERA_MSG_COMPRESSED_IMAGE, MCameraClient::EQ, 1);
+            usleep(100000);  // 100ms
+        }
+        c->disconnect();
+        cc->assertNotify(CAMERA_MSG_ERROR, MCameraClient::EQ, 0);
+    }
+};
+
+class TestGetParameters: public AfterStartPreview {
+public:
+    void run() {
+        String8 param_str = c->getParameters();
+        INFO(param_str);
+    }
+};
+
+class TestPictureSize : public AfterStartPreview {
+public:
+    void checkOnePicture(int w, int h) {
+        const float rate = 0.5;  // byte per pixel limit
+        int pixels = w * h;
+
+        CameraParameters param(c->getParameters());
+        param.setPictureSize(w, h);
+        c->setParameters(param.flatten());
+
+        cc->clearStat();
+        ASSERT(c->takePicture() == NO_ERROR);
+        cc->waitData(CAMERA_MSG_RAW_IMAGE, MCameraClient::EQ, 1);
+        cc->assertDataSize(CAMERA_MSG_RAW_IMAGE, MCameraClient::EQ, pixels*3/2);
+        cc->waitData(CAMERA_MSG_COMPRESSED_IMAGE, MCameraClient::EQ, 1);
+        cc->assertDataSize(CAMERA_MSG_COMPRESSED_IMAGE, MCameraClient::LT,
+                int(pixels * rate));
+        cc->assertDataSize(CAMERA_MSG_COMPRESSED_IMAGE, MCameraClient::GT, 0);
+        cc->assertNotify(CAMERA_MSG_ERROR, MCameraClient::EQ, 0);
+        usleep(100000);  // 100ms
+    }
+
+    void run() {
+        checkOnePicture(2048, 1536);
+        checkOnePicture(1600, 1200);
+        checkOnePicture(1024, 768);
+    }
+};
+
+class TestPreviewCallbackFlag : public AfterConnect {
+public:
+    void run() {
+        sp<MSurface> surface = new MSurface();
+        ASSERT(c->setPreviewDisplay(surface) == NO_ERROR);
+
+        // Try all flag combinations.
+        for (int v = 0; v < 8; v++) {
+            cc->clearStat();
+            c->setPreviewCallbackFlag(v);
+            ASSERT(c->previewEnabled() == false);
+            ASSERT(c->startPreview() == NO_ERROR);
+            ASSERT(c->previewEnabled() == true);
+            sleep(2);
+            c->stopPreview();
+            if ((v & FRAME_CALLBACK_FLAG_ENABLE_MASK) == 0) {
+                cc->assertData(CAMERA_MSG_PREVIEW_FRAME, MCameraClient::EQ, 0);
+            } else {
+                if ((v & FRAME_CALLBACK_FLAG_ONE_SHOT_MASK) == 0) {
+                    cc->assertData(CAMERA_MSG_PREVIEW_FRAME, MCameraClient::GE, 10);
+                } else {
+                    cc->assertData(CAMERA_MSG_PREVIEW_FRAME, MCameraClient::EQ, 1);
+                }
+            }
+        }
+    }
+};
+
+class TestRecording : public AfterConnect {
+public:
+    void run() {
+        ASSERT(c->recordingEnabled() == false);
+        sp<MSurface> surface = new MSurface();
+        ASSERT(c->setPreviewDisplay(surface) == NO_ERROR);
+        c->setPreviewCallbackFlag(FRAME_CALLBACK_FLAG_ENABLE_MASK);
+        cc->setReleaser(c.get());
+        c->startRecording();
+        ASSERT(c->recordingEnabled() == true);
+        sleep(2);
+        c->stopRecording();
+        cc->setReleaser(NULL);
+        cc->assertData(CAMERA_MSG_VIDEO_FRAME, MCameraClient::GE, 10);
+    }
+};
+
+class TestPreviewSize : public AfterStartPreview {
+public:
+    void checkOnePicture(int w, int h) {
+        int size = w*h*3/2;  // should read from parameters
+
+        c->stopPreview();
+
+        CameraParameters param(c->getParameters());
+        param.setPreviewSize(w, h);
+        c->setPreviewCallbackFlag(FRAME_CALLBACK_FLAG_ENABLE_MASK);
+        c->setParameters(param.flatten());
+
+        c->startPreview();
+
+        cc->clearStat();
+        cc->waitData(CAMERA_MSG_PREVIEW_FRAME, MCameraClient::GE, 1);
+        cc->assertDataSize(CAMERA_MSG_PREVIEW_FRAME, MCameraClient::EQ, size);
+    }
+
+    void run() {
+        checkOnePicture(480, 320);
+        checkOnePicture(352, 288);
+        checkOnePicture(176, 144);
+    }
+};
+
+void runHolderService() {
+    defaultServiceManager()->addService(
+            String16("CameraServiceTest.Holder"), new HolderService());
+    ProcessState::self()->startThreadPool();
+}
+
+int main(int argc, char **argv)
+{
+    if (argc != 1) {
+        runFunction(argv[1]);
+        return 0;
+    }
+    INFO("CameraServiceTest start");
+    gExecutable = argv[0];
+    runHolderService();
+
+    testConnect();                              flushCommands();
+    testAllowConnectOnceOnly();                 flushCommands();
+    testReconnect();                            flushCommands();
+    testLockUnlock();                           flushCommands();
+    testReconnectFromAnotherProcess();          flushCommands();
+
+    RUN(TestSetPreviewDisplay);
+    RUN(TestStartPreview);
+    RUN(TestStartPreviewWithoutDisplay);
+    RUN(TestAutoFocus);
+    RUN(TestStopPreview);
+    RUN(TestTakePicture);
+    RUN(TestTakeMultiplePictures);
+    RUN(TestGetParameters);
+    RUN(TestPictureSize);
+    RUN(TestPreviewCallbackFlag);
+    RUN(TestRecording);
+    RUN(TestPreviewSize);
+}