auto import from //branches/cupcake/...@125939
diff --git a/camera/libcameraservice/CameraHardwareStub.cpp b/camera/libcameraservice/CameraHardwareStub.cpp
index ea21af8..3d6b0b1 100644
--- a/camera/libcameraservice/CameraHardwareStub.cpp
+++ b/camera/libcameraservice/CameraHardwareStub.cpp
@@ -183,6 +183,10 @@
     mPreviewThread.clear();
 }
 
+bool CameraHardwareStub::previewEnabled() {
+    return mPreviewThread != 0;
+}
+
 // ---------------------------------------------------------------------------
 
 int CameraHardwareStub::beginAutoFocusThread(void *cookie)
diff --git a/camera/libcameraservice/CameraHardwareStub.h b/camera/libcameraservice/CameraHardwareStub.h
index 5b445d3..9f5ddf1 100644
--- a/camera/libcameraservice/CameraHardwareStub.h
+++ b/camera/libcameraservice/CameraHardwareStub.h
@@ -33,6 +33,7 @@
 
     virtual status_t    startPreview(preview_callback cb, void* user);
     virtual void        stopPreview();
+    virtual bool        previewEnabled();
     virtual status_t    autoFocus(autofocus_callback, void *user);
     virtual status_t    takePicture(shutter_callback,
                                     raw_callback,
diff --git a/camera/libcameraservice/CameraService.cpp b/camera/libcameraservice/CameraService.cpp
index 800ffa4..33987c3 100644
--- a/camera/libcameraservice/CameraService.cpp
+++ b/camera/libcameraservice/CameraService.cpp
@@ -107,7 +107,7 @@
     }
 
     // create a new Client object
-    sp<Client> client = new Client(this, cameraClient);
+    sp<Client> client = new Client(this, cameraClient, IPCThreadState::self()->getCallingPid());
     mClient = client;
 #if DEBUG_CLIENT_REFERENCES
     // Enable tracking for this object, and track increments and decrements of
@@ -151,10 +151,12 @@
 }
 
 CameraService::Client::Client(const sp<CameraService>& cameraService,
-        const sp<ICameraClient>& cameraClient) :
-    mCameraService(cameraService), mCameraClient(cameraClient), mHardware(0)
+        const sp<ICameraClient>& cameraClient, pid_t clientPid) 
 {
     LOGD("Client E constructor");
+    mCameraService = cameraService;
+    mCameraClient = cameraClient;
+    mClientPid = clientPid;
     mHardware = openCameraHardware();
 
     // Callback is disabled by default
@@ -162,12 +164,36 @@
     LOGD("Client X constructor");
 }
 
+status_t CameraService::Client::checkPid()
+{
+    // zero means the interface is not locked down
+    if (mClientPid == 0) return NO_ERROR;
+    return (int) mClientPid == IPCThreadState::self()->getCallingPid() ? NO_ERROR : -EBUSY;
+}
+
+status_t CameraService::Client::lock()
+{
+    // lock camera to this client
+    status_t result = checkPid();
+    if (result == NO_ERROR) mClientPid = IPCThreadState::self()->getCallingPid();
+    return result;
+}
+
+status_t CameraService::Client::unlock()
+{
+    // allow anyone to use camera
+    status_t result = checkPid();
+    if (result == NO_ERROR) mClientPid = 0;
+    return result;
+}
+
 status_t CameraService::Client::connect(const sp<ICameraClient>& client)
 {
-    // remvoe old client
-    LOGD("connect (new client)");
+    // remove old client
+    LOGV("connect new client to existing camera");
     Mutex::Autolock _l(mLock);
     mCameraClient = client;
+    mClientPid = IPCThreadState::self()->getCallingPid();
     mFrameCallbackFlag = FRAME_CALLBACK_FLAG_NOOP;
     return NO_ERROR;
 }
@@ -209,6 +235,7 @@
 {
     LOGD("Client E disconnect");
     Mutex::Autolock lock(mLock);
+    if (checkPid() != NO_ERROR) return;
     mCameraService->removeClient(mCameraClient);
     if (mHardware != 0) {
         // Before destroying mHardware, we must make sure it's in the
@@ -228,6 +255,8 @@
 {
     LOGD("setPreviewDisplay(%p)", surface.get());
     Mutex::Autolock lock(mLock);
+    status_t result = checkPid();
+    if (result != NO_ERROR) return result;
     Mutex::Autolock surfaceLock(mSurfaceLock);
     // asBinder() is safe on NULL (returns NULL)
     if (surface->asBinder() != mSurface->asBinder()) {
@@ -245,6 +274,7 @@
 void CameraService::Client::setFrameCallbackFlag(int frame_callback_flag)
 {
     Mutex::Autolock lock(mLock);
+    if (checkPid() != NO_ERROR) return;
     mFrameCallbackFlag = frame_callback_flag;
 }
 
@@ -258,6 +288,8 @@
      */
 
     Mutex::Autolock lock(mLock);
+    status_t result = checkPid();
+    if (result != NO_ERROR) return result;
 
     if (mHardware == 0) {
         LOGE("mHardware is NULL, returning.");
@@ -269,14 +301,15 @@
         return INVALID_OPERATION;
     }
 
+    // do nothing if preview is already started
+    if (mHardware->previewEnabled()) return NO_ERROR;
+
     // 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
@@ -284,6 +317,7 @@
     status_t ret = mHardware->startPreview(previewCallback,
                                            mCameraService.get());
     if (ret == NO_ERROR) {
+        mSurface->unregisterBuffers();
         mSurface->registerBuffers(w,h,w,h,
                                   PIXEL_FORMAT_YCbCr_420_SP,
                                   mHardware->getPreviewHeap());
@@ -300,6 +334,7 @@
     LOGD("stopPreview()");
 
     Mutex::Autolock lock(mLock);
+    if (checkPid() != NO_ERROR) return;
 
     if (mHardware == 0) {
         LOGE("mHardware is NULL, returning.");
@@ -315,6 +350,13 @@
     mPreviewBuffer.clear();
 }
 
+bool CameraService::Client::previewEnabled()
+{
+    Mutex::Autolock lock(mLock);
+    if (mHardware == 0) return false;
+    return mHardware->previewEnabled();
+}
+
 // Safely retrieves a strong pointer to the client during a hardware callback.
 sp<CameraService::Client> CameraService::Client::getClientFromCookie(void* user)
 {
@@ -424,6 +466,8 @@
     LOGV("autoFocus");
 
     Mutex::Autolock lock(mLock);
+    status_t result = checkPid();
+    if (result != NO_ERROR) return result;
 
     if (mHardware == 0) {
         LOGE("mHardware is NULL, returning.");
@@ -440,6 +484,8 @@
     LOGD("takePicture");
 
     Mutex::Autolock lock(mLock);
+    status_t result = checkPid();
+    if (result != NO_ERROR) return result;
 
     if (mHardware == 0) {
         LOGE("mHardware is NULL, returning.");
@@ -580,6 +626,8 @@
     LOGD("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.");
diff --git a/camera/libcameraservice/CameraService.h b/camera/libcameraservice/CameraService.h
index b225aa9..cd8c1e9 100644
--- a/camera/libcameraservice/CameraService.h
+++ b/camera/libcameraservice/CameraService.h
@@ -73,6 +73,12 @@
         // 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);
 
@@ -86,6 +92,9 @@
         // stop preview mode
         virtual void            stopPreview();
 
+        // get preview state
+        virtual bool            previewEnabled();
+
         // auto focus
         virtual status_t        autoFocus();
 
@@ -103,11 +112,14 @@
 
     private:
         friend class CameraService;
-                                Client( const sp<CameraService>& cameraService,
-                                        const sp<ICameraClient>& cameraClient);
+                                Client(const sp<CameraService>& cameraService,
+                                        const sp<ICameraClient>& cameraClient,
+                                        pid_t clientPid);
                                 Client();
         virtual                 ~Client();
 
+                    status_t    checkPid();
+
         static      void        previewCallback(const sp<IMemory>& mem, void* user);
         static      void        shutterCallback(void *user);
         static      void        yuvPictureCallback(const sp<IMemory>& mem, void* user);
@@ -132,7 +144,7 @@
         // 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
+        // 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;
@@ -146,6 +158,7 @@
                     // they don't need to be protected by a lock
                     sp<ICameraClient>           mCameraClient;
                     sp<CameraHardwareInterface> mHardware;
+                    pid_t                       mClientPid;
     };
 
 // ----------------------------------------------------------------------------