Code drop from //branches/cupcake/...@124589
diff --git a/camera/libcameraservice/Android.mk b/camera/libcameraservice/Android.mk
index 4e7d6d2..2dfe659 100644
--- a/camera/libcameraservice/Android.mk
+++ b/camera/libcameraservice/Android.mk
@@ -4,12 +4,13 @@
 # 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 ($(BOARD_CAMERA_LIBRARIES),)
-USE_CAMERA_STUB:=true
-else
+
+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)
 #
@@ -51,7 +52,7 @@
 LOCAL_STATIC_LIBRARIES += libcamerastub
 LOCAL_CFLAGS += -include CameraHardwareStub.h
 else
-LOCAL_SHARED_LIBRARIES += $(BOARD_CAMERA_LIBRARIES)
+LOCAL_SHARED_LIBRARIES += libcamera 
 endif
 
 include $(BUILD_SHARED_LIBRARY)
diff --git a/camera/libcameraservice/CameraService.cpp b/camera/libcameraservice/CameraService.cpp
index 5784c4b..800ffa4 100644
--- a/camera/libcameraservice/CameraService.cpp
+++ b/camera/libcameraservice/CameraService.cpp
@@ -1,6 +1,7 @@
 /*
 **
-** Copyright 2008, The Android Open Source Project
+** 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.
@@ -15,7 +16,7 @@
 ** limitations under the License.
 */
 
-
+//#define LOG_NDEBUG 0
 #define LOG_TAG "CameraService"
 #include <utils/Log.h>
 
@@ -155,10 +156,22 @@
 {
     LOGD("Client E constructor");
     mHardware = openCameraHardware();
-    mHasFrameCallback = false;
+
+    // Callback is disabled by default
+    mFrameCallbackFlag = FRAME_CALLBACK_FLAG_NOOP;
     LOGD("Client X constructor");
 }
 
+status_t CameraService::Client::connect(const sp<ICameraClient>& client)
+{
+    // remvoe old client
+    LOGD("connect (new client)");
+    Mutex::Autolock _l(mLock);
+    mCameraClient = client;
+    mFrameCallbackFlag = FRAME_CALLBACK_FLAG_NOOP;
+    return NO_ERROR;
+}
+
 #if HAVE_ANDROID_OS
 static void *unregister_surface(void *arg)
 {
@@ -170,7 +183,7 @@
 #endif
 
 CameraService::Client::~Client()
-{ 
+{
     // spin down hardware
     LOGD("Client E destructor");
     if (mSurface != 0) {
@@ -179,7 +192,7 @@
         // 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, 
+        pthread_create(&thr, NULL,
                        unregister_surface,
                        mSurface.get());
         pthread_join(thr, NULL);
@@ -227,12 +240,12 @@
     return NO_ERROR;
 }
 
-// tell the service whether to callback with each preview frame
-void CameraService::Client::setHasFrameCallback(bool installed)
+// set the frame callback flag to affect how the received frames from
+// preview are handled.
+void CameraService::Client::setFrameCallbackFlag(int frame_callback_flag)
 {
     Mutex::Autolock lock(mLock);
-    mHasFrameCallback = installed;
-    // If installed is false, mPreviewBuffer will be released in stopPreview().
+    mFrameCallbackFlag = frame_callback_flag;
 }
 
 // start preview mode, must call setPreviewDisplay first
@@ -250,24 +263,24 @@
         LOGE("mHardware is NULL, returning.");
         return INVALID_OPERATION;
     }
-    
+
     if (mSurface == 0) {
         LOGE("setPreviewDisplay must be called before startPreview!");
         return INVALID_OPERATION;
     }
-    
+
     // XXX: This needs to be improved. remove all hardcoded stuff
-    
+
     int w, h;
     CameraParameters params(mHardware->getParameters());
     params.getPreviewSize(&w, &h);
-    
+
     mSurface->unregisterBuffers();
 
 #if DEBUG_DUMP_PREVIEW_FRAME_TO_FILE
     debug_frame_cnt = 0;
 #endif
-    
+
     status_t ret = mHardware->startPreview(previewCallback,
                                            mCameraService.get());
     if (ret == NO_ERROR) {
@@ -277,7 +290,7 @@
     }
     else LOGE("mHardware->startPreview() failed with status %d\n",
               ret);
-    
+
     return ret;
 }
 
@@ -295,7 +308,7 @@
 
     mHardware->stopPreview();
     LOGD("stopPreview(), hardware stopped OK");
-    
+
     if (mSurface != 0) {
         mSurface->unregisterBuffers();
     }
@@ -361,6 +374,7 @@
 // preview callback - frame buffer update
 void CameraService::Client::previewCallback(const sp<IMemory>& mem, void* user)
 {
+    LOGV("previewCallback()");
     sp<Client> client = getClientFromCookie(user);
     if (client == 0) {
         return;
@@ -395,7 +409,7 @@
     client->postFrame(mem);
 
 #if DEBUG_CLIENT_REFERENCES
-    //**** if the client's refcount is 1, then we are about to destroy it here, 
+    //**** if the client's refcount is 1, then we are about to destroy it here,
     // which is bad--print all refcounts.
     if (client->getStrongCount() == 1) {
         LOGE("++++++++++++++++ (PREVIEW) THIS WILL CAUSE A LOCKUP!");
@@ -431,7 +445,7 @@
         LOGE("mHardware is NULL, returning.");
         return INVALID_OPERATION;
     }
-    
+
     if (mSurface != NULL)
         mSurface->unregisterBuffers();
 
@@ -495,7 +509,7 @@
     client->postRaw(mem);
 
 #if DEBUG_CLIENT_REFERENCES
-    //**** if the client's refcount is 1, then we are about to destroy it here, 
+    //**** if the client's refcount is 1, then we are about to destroy it here,
     // which is bad--print all refcounts.
     if (client->getStrongCount() == 1) {
         LOGE("++++++++++++++++ (RAW) THIS WILL CAUSE A LOCKUP!");
@@ -532,7 +546,7 @@
     client->postJpeg(mem);
 
 #if DEBUG_CLIENT_REFERENCES
-    //**** if the client's refcount is 1, then we are about to destroy it here, 
+    //**** if the client's refcount is 1, then we are about to destroy it here,
     // which is bad--print all refcounts.
     if (client->getStrongCount() == 1) {
         LOGE("++++++++++++++++ (JPEG) THIS WILL CAUSE A LOCKUP!");
@@ -615,37 +629,74 @@
     mCameraClient->jpegCallback(mem);
 }
 
+void CameraService::Client::copyFrameAndPostCopiedFrame(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.
+    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;
+        }
+    }
+    memcpy(mPreviewBuffer->base(),
+           (uint8_t *)heap->base() + offset, size);
+
+    sp<MemoryBase> frame = new MemoryBase(mPreviewBuffer, 0, size);
+    if (frame == 0) {
+        LOGE("failed to allocate space for frame callback");
+        return;
+    }
+    mCameraClient->frameCallback(frame);
+}
+
 void CameraService::Client::postFrame(const sp<IMemory>& mem)
 {
+    LOGV("postFrame");
+    if (mem == 0) {
+        LOGW("mem is a null pointer");
+        return;
+    }
+
     ssize_t offset;
     size_t size;
     sp<IMemoryHeap> heap = mem->getMemory(&offset, &size);
-
-    sp<MemoryBase> frame;
-
     {
         Mutex::Autolock surfaceLock(mSurfaceLock);
-        if (mSurface != NULL)
+        if (mSurface != NULL) {
             mSurface->postBuffer(offset);
-    }
-    
-    // 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.
-    if (mHasFrameCallback) {
-        if (mPreviewBuffer == 0) {
-            mPreviewBuffer = new MemoryHeapBase(size, 0, NULL);
-        } else if (size > mPreviewBuffer->virtualSize()) {
-            mPreviewBuffer.clear();
-            mPreviewBuffer = new MemoryHeapBase(size, 0, NULL);
         }
-        memcpy(mPreviewBuffer->base(), (uint8_t *)heap->base() + offset, size);
-        frame = new MemoryBase(mPreviewBuffer, 0, size);
     }
-    
-    // Do not hold the client lock while calling back.
-    if (frame != 0) {
-        mCameraClient->frameCallback(frame);
+
+    // Is the callback enabled or not?
+    if (!(mFrameCallbackFlag & 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;
+    }
+
+    // Is the received frame copied out or not?
+    if (mFrameCallbackFlag & FRAME_CALLBACK_FLAG_COPY_OUT_MASK) {
+        LOGV("frame is copied out");
+        copyFrameAndPostCopiedFrame(heap, offset, size);
+    } else {
+        LOGV("frame is directly sent out without copying");
+        mCameraClient->frameCallback(mem);
+    }
+
+    // Is this is one-shot only?
+    if (mFrameCallbackFlag & FRAME_CALLBACK_FLAG_ONE_SHOT_MASK) {
+        LOGV("One-shot only, thus clear the bits and disable frame callback");
+        mFrameCallbackFlag &= ~(FRAME_CALLBACK_FLAG_ONE_SHOT_MASK |
+                                FRAME_CALLBACK_FLAG_COPY_OUT_MASK |
+                                FRAME_CALLBACK_FLAG_ENABLE_MASK);
     }
 }
 
@@ -711,7 +762,7 @@
     }
 
     status_t err = BnCameraService::onTransact(code, data, reply, flags);
-    
+
     LOGD("+++ onTransact err %d code %d", err, code);
 
     if (err == UNKNOWN_TRANSACTION || err == PERMISSION_DENIED) {
diff --git a/camera/libcameraservice/CameraService.h b/camera/libcameraservice/CameraService.h
index 683c51b..b225aa9 100644
--- a/camera/libcameraservice/CameraService.h
+++ b/camera/libcameraservice/CameraService.h
@@ -1,6 +1,7 @@
 /*
 **
-** Copyright 2008, The Android Open Source Project
+** 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.
@@ -20,6 +21,8 @@
 
 #include <ui/ICameraService.h>
 #include <ui/CameraHardwareInterface.h>
+#include <ui/Camera.h>
+
 class android::MemoryHeapBase;
 
 namespace android {
@@ -32,7 +35,7 @@
 // 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 
+// 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
@@ -67,11 +70,15 @@
     public:
         virtual void            disconnect();
 
+        // connect new client with existing camera remote
+        virtual status_t        connect(const sp<ICameraClient>& client);
+
         // pass the buffered ISurface to the camera service
         virtual status_t        setPreviewDisplay(const sp<ISurface>& surface);
-        
-        // tell the service whether to callback with each preview frame
-        virtual void            setHasFrameCallback(bool installed);
+
+        // set the frame callback flag to affect how the received frames from
+        // preview are handled.
+        virtual void            setFrameCallbackFlag(int frame_callback_flag);
 
         // start preview mode, must call setPreviewDisplay first
         virtual status_t        startPreview();
@@ -112,6 +119,7 @@
                     void        postRaw(const sp<IMemory>& mem);
                     void        postJpeg(const sp<IMemory>& mem);
                     void        postFrame(const sp<IMemory>& mem);
+                    void        copyFrameAndPostCopiedFrame(sp<IMemoryHeap> heap, size_t offset, size_t size);
                     void        postError(status_t error);
                     void        postAutoFocus(bool focused);
 
@@ -119,20 +127,20 @@
         mutable     Mutex                       mLock;
         // mSurfaceLock synchronizes access to mSurface between
         // setPreviewSurface() and postFrame().  Note that among
-        // the public methods, all accesses to mSurface are 
+        // the public methods, all accesses to mSurface are
         // syncrhonized by mLock.  However, postFrame() is called
-        // by the CameraHardwareInterface callback, and needs to 
+        // by the CameraHardwareInterface callback, and needs to
         // access mSurface.  It cannot hold mLock, however, because
         // stopPreview() may be holding that lock while attempting
         // top stop preview, and stopPreview itself will block waiting
-        // for a callback from CameraHardwareInterface.  If this 
+        // 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;
                     sp<MemoryHeapBase>          mPreviewBuffer;
-                    bool                        mHasFrameCallback;
+                    int                         mFrameCallbackFlag;
 
                     // these are immutable once the object is created,
                     // they don't need to be protected by a lock