merge in jb-mr1-release history after reset to jb-mr1-dev
diff --git a/media/libstagefright/wifi-display/source/WifiDisplaySource.h b/media/libstagefright/wifi-display/source/WifiDisplaySource.h
index 8c043cd..c30e3cb 100644
--- a/media/libstagefright/wifi-display/source/WifiDisplaySource.h
+++ b/media/libstagefright/wifi-display/source/WifiDisplaySource.h
@@ -26,7 +26,7 @@
 
 namespace android {
 
-#define REQUIRE_HDCP    0
+#define REQUIRE_HDCP    1
 
 struct IHDCP;
 struct IRemoteDisplayClient;
diff --git a/services/camera/libcameraservice/Camera2Client.cpp b/services/camera/libcameraservice/Camera2Client.cpp
index 1c650f6..948b59f 100644
--- a/services/camera/libcameraservice/Camera2Client.cpp
+++ b/services/camera/libcameraservice/Camera2Client.cpp
@@ -47,9 +47,10 @@
         const sp<ICameraClient>& cameraClient,
         int cameraId,
         int cameraFacing,
-        int clientPid):
+        int clientPid,
+        int servicePid):
         Client(cameraService, cameraClient,
-                cameraId, cameraFacing, clientPid),
+                cameraId, cameraFacing, clientPid, servicePid),
         mSharedCameraClient(cameraClient),
         mParameters(cameraId, cameraFacing)
 {
@@ -64,10 +65,10 @@
 
 status_t Camera2Client::checkPid(const char* checkLocation) const {
     int callingPid = getCallingPid();
-    if (callingPid == mClientPid) return NO_ERROR;
+    if (callingPid == mClientPid || callingPid == mServicePid) return NO_ERROR;
 
     ALOGE("%s: attempt to use a locked camera from a different process"
-            " (old pid %d, new pid %d)", checkLocation, mClientPid, callingPid);
+            " (old pid %d, new pid %d, servicePid %d)", checkLocation, mClientPid, callingPid, mServicePid);
     return PERMISSION_DENIED;
 }
 
@@ -138,8 +139,15 @@
 
     mDestructionStarted = true;
 
-    SharedParameters::Lock l(mParameters);
-    if (l.mParameters.state != Parameters::DISCONNECTED) {
+    Parameters::State state;
+    // warning:
+    //   holding on to locks more than necessary may be hazardous to your health
+    {
+        SharedParameters::Lock l(mParameters);
+        state = l.mParameters.state;
+    }
+
+    if (state != Parameters::DISCONNECTED) {
         // Rewrite mClientPid to allow shutdown by CameraService
         mClientPid = getCallingPid();
         disconnect();
@@ -315,6 +323,21 @@
             getCaptureStreamId());
     result.appendFormat("    Recording stream ID: %d\n",
             getRecordingStreamId());
+
+    result.append("  Quirks for this camera:\n");
+    bool haveQuirk = false;
+    if (p.quirks.triggerAfWithAuto) {
+        result.appendFormat("    triggerAfWithAuto\n");
+        haveQuirk = true;
+    }
+    if (p.quirks.useZslFormat) {
+        result.appendFormat("    useZslFormat\n");
+        haveQuirk = true;
+    }
+    if (!haveQuirk) {
+        result.appendFormat("    none\n");
+    }
+
     write(fd, result.string(), result.size());
 
     mStreamingProcessor->dump(fd, args);
@@ -404,9 +427,6 @@
     mCameraClient = client;
     mSharedCameraClient = client;
 
-    SharedParameters::Lock l(mParameters);
-    l.mParameters.state = Parameters::STOPPED;
-
     return OK;
 }
 
@@ -588,6 +608,9 @@
 status_t Camera2Client::startPreviewL(Parameters &params, bool restart) {
     ATRACE_CALL();
     status_t res;
+
+    ALOGV("%s: state == %d, restart = %d", __FUNCTION__, params.state, restart);
+
     if (params.state == Parameters::PREVIEW && !restart) {
         // Succeed attempt to re-enter preview state
         ALOGI("%s: Not starting preview; already in preview state.",
@@ -777,6 +800,9 @@
 
 status_t Camera2Client::startRecordingL(Parameters &params, bool restart) {
     status_t res;
+
+    ALOGV("%s: state == %d, restart = %d", __FUNCTION__, params.state, restart);
+
     switch (params.state) {
         case Parameters::STOPPED:
             res = startPreviewL(params, false);
@@ -1415,6 +1441,8 @@
 status_t Camera2Client::updateRequests(Parameters &params) {
     status_t res;
 
+    ALOGV("%s: Camera %d: state = %d", __FUNCTION__, getCameraId(), params.state);
+
     res = mStreamingProcessor->updatePreviewRequest(params);
     if (res != OK) {
         ALOGE("%s: Camera %d: Unable to update preview request: %s (%d)",
diff --git a/services/camera/libcameraservice/Camera2Client.h b/services/camera/libcameraservice/Camera2Client.h
index 3a9d307..fb1dcde 100644
--- a/services/camera/libcameraservice/Camera2Client.h
+++ b/services/camera/libcameraservice/Camera2Client.h
@@ -74,7 +74,8 @@
             const sp<ICameraClient>& cameraClient,
             int cameraId,
             int cameraFacing,
-            int clientPid);
+            int clientPid,
+            int servicePid);
     virtual ~Camera2Client();
 
     status_t initialize(camera_module_t *module);
diff --git a/services/camera/libcameraservice/Camera2Device.cpp b/services/camera/libcameraservice/Camera2Device.cpp
index 2e4098e..25b7a58 100644
--- a/services/camera/libcameraservice/Camera2Device.cpp
+++ b/services/camera/libcameraservice/Camera2Device.cpp
@@ -42,6 +42,7 @@
 Camera2Device::~Camera2Device()
 {
     ATRACE_CALL();
+    ALOGV("%s: Tearing down for camera id %d", __FUNCTION__, mId);
     disconnect();
 }
 
@@ -1114,9 +1115,17 @@
     if (mState >= CONNECTED) {
         res = native_window_api_disconnect(mConsumerInterface.get(),
                 NATIVE_WINDOW_API_CAMERA);
-        if (res != OK) {
-            ALOGE("%s: Unable to disconnect stream %d from native window",
-                    __FUNCTION__, mId);
+
+        /* this is not an error. if client calling process dies,
+           the window will also die and all calls to it will return
+           DEAD_OBJECT, thus it's already "disconnected" */
+        if (res == DEAD_OBJECT) {
+            ALOGW("%s: While disconnecting stream %d from native window, the"
+                  " native window died from under us", __FUNCTION__, mId);
+        }
+        else if (res != OK) {
+            ALOGE("%s: Unable to disconnect stream %d from native window (error %d %s)",
+                    __FUNCTION__, mId, res, strerror(-res));
             return res;
         }
     }
diff --git a/services/camera/libcameraservice/CameraClient.cpp b/services/camera/libcameraservice/CameraClient.cpp
index c9c816a..5b59ef9 100644
--- a/services/camera/libcameraservice/CameraClient.cpp
+++ b/services/camera/libcameraservice/CameraClient.cpp
@@ -40,9 +40,9 @@
 
 CameraClient::CameraClient(const sp<CameraService>& cameraService,
         const sp<ICameraClient>& cameraClient,
-        int cameraId, int cameraFacing, int clientPid):
+        int cameraId, int cameraFacing, int clientPid, int servicePid):
         Client(cameraService, cameraClient,
-                cameraId, cameraFacing, clientPid)
+                cameraId, cameraFacing, clientPid, servicePid)
 {
     int callingPid = getCallingPid();
     LOG1("CameraClient::CameraClient E (pid %d, id %d)", callingPid, cameraId);
@@ -124,7 +124,7 @@
 
 status_t CameraClient::checkPid() const {
     int callingPid = getCallingPid();
-    if (callingPid == mClientPid) return NO_ERROR;
+    if (callingPid == mClientPid || callingPid == mServicePid) return NO_ERROR;
 
     ALOGW("attempt to use a locked camera from a different process"
          " (old pid %d, new pid %d)", mClientPid, callingPid);
diff --git a/services/camera/libcameraservice/CameraClient.h b/services/camera/libcameraservice/CameraClient.h
index 256298d..2f31c4e 100644
--- a/services/camera/libcameraservice/CameraClient.h
+++ b/services/camera/libcameraservice/CameraClient.h
@@ -55,7 +55,8 @@
             const sp<ICameraClient>& cameraClient,
             int cameraId,
             int cameraFacing,
-            int clientPid);
+            int clientPid,
+            int servicePid);
     ~CameraClient();
 
     status_t initialize(camera_module_t *module);
diff --git a/services/camera/libcameraservice/CameraService.cpp b/services/camera/libcameraservice/CameraService.cpp
index 878afde..4d48d8d 100644
--- a/services/camera/libcameraservice/CameraService.cpp
+++ b/services/camera/libcameraservice/CameraService.cpp
@@ -196,11 +196,11 @@
     switch(deviceVersion) {
       case CAMERA_DEVICE_API_VERSION_1_0:
         client = new CameraClient(this, cameraClient, cameraId,
-                info.facing, callingPid);
+                info.facing, callingPid, getpid());
         break;
       case CAMERA_DEVICE_API_VERSION_2_0:
         client = new Camera2Client(this, cameraClient, cameraId,
-                info.facing, callingPid);
+                info.facing, callingPid, getpid());
         break;
       default:
         ALOGE("Unknown camera device HAL version: %d", deviceVersion);
@@ -211,8 +211,10 @@
         return NULL;
     }
 
+    cameraClient->asBinder()->linkToDeath(this);
+
     mClient[cameraId] = client;
-    LOG1("CameraService::connect X (id %d)", cameraId);
+    LOG1("CameraService::connect X (id %d, this pid is %d)", cameraId, getpid());
     return client;
 }
 
@@ -220,12 +222,29 @@
     int callingPid = getCallingPid();
     LOG1("CameraService::removeClient E (pid %d)", callingPid);
 
-    for (int i = 0; i < mNumberOfCameras; i++) {
-        // Declare this before the lock to make absolutely sure the
-        // destructor won't be called with the lock held.
-        sp<Client> client;
+    // Declare this before the lock to make absolutely sure the
+    // destructor won't be called with the lock held.
+    Mutex::Autolock lock(mServiceLock);
 
-        Mutex::Autolock lock(mServiceLock);
+    int outIndex;
+    sp<Client> client = findClientUnsafe(cameraClient, outIndex);
+
+    if (client != 0) {
+        // Found our camera, clear and leave.
+        LOG1("removeClient: clear camera %d", outIndex);
+        mClient[outIndex].clear();
+
+        client->unlinkToDeath(this);
+    }
+
+    LOG1("CameraService::removeClient X (pid %d)", callingPid);
+}
+
+sp<CameraService::Client> CameraService::findClientUnsafe(
+                        const sp<ICameraClient>& cameraClient, int& outIndex) {
+    sp<Client> client;
+
+    for (int i = 0; i < mNumberOfCameras; i++) {
 
         // This happens when we have already disconnected (or this is
         // just another unused camera).
@@ -235,20 +254,21 @@
         // Client::~Client() -> disconnect() -> removeClient().
         client = mClient[i].promote();
 
-        if (client == 0) {
+        // Clean up stale client entry
+        if (client == NULL) {
             mClient[i].clear();
             continue;
         }
 
         if (cameraClient->asBinder() == client->getCameraClient()->asBinder()) {
-            // Found our camera, clear and leave.
-            LOG1("removeClient: clear camera %d", i);
-            mClient[i].clear();
-            break;
+            // Found our camera
+            outIndex = i;
+            return client;
         }
     }
 
-    LOG1("CameraService::removeClient X (pid %d)", callingPid);
+    outIndex = -1;
+    return NULL;
 }
 
 CameraService::Client* CameraService::getClientByIdUnsafe(int cameraId) {
@@ -261,6 +281,21 @@
     return &mClientLock[cameraId];
 }
 
+/*virtual*/sp<CameraService::Client> CameraService::getClientByRemote(
+                                const sp<ICameraClient>& cameraClient) {
+
+    // Declare this before the lock to make absolutely sure the
+    // destructor won't be called with the lock held.
+    sp<Client> client;
+
+    Mutex::Autolock lock(mServiceLock);
+
+    int outIndex;
+    client = findClientUnsafe(cameraClient, outIndex);
+
+    return client;
+}
+
 status_t CameraService::onTransact(
     uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) {
     // Permission checks
@@ -292,10 +327,14 @@
 // the hardware first.
 void CameraService::setCameraBusy(int cameraId) {
     android_atomic_write(1, &mBusy[cameraId]);
+
+    ALOGV("setCameraBusy cameraId=%d", cameraId);
 }
 
 void CameraService::setCameraFree(int cameraId) {
     android_atomic_write(0, &mBusy[cameraId]);
+
+    ALOGV("setCameraFree cameraId=%d", cameraId);
 }
 
 // We share the media players for shutter and recording sound for all clients.
@@ -350,7 +389,7 @@
 
 CameraService::Client::Client(const sp<CameraService>& cameraService,
         const sp<ICameraClient>& cameraClient,
-        int cameraId, int cameraFacing, int clientPid) {
+        int cameraId, int cameraFacing, int clientPid, int servicePid) {
     int callingPid = getCallingPid();
     LOG1("Client::Client E (pid %d, id %d)", callingPid, cameraId);
 
@@ -359,6 +398,7 @@
     mCameraId = cameraId;
     mCameraFacing = cameraFacing;
     mClientPid = clientPid;
+    mServicePid = servicePid;
     mDestructionStarted = false;
 
     cameraService->setCameraBusy(cameraId);
@@ -514,4 +554,26 @@
     return NO_ERROR;
 }
 
+/*virtual*/void CameraService::binderDied(
+    const wp<IBinder> &who) {
+
+    ALOGV("java clients' binder died");
+
+    sp<IBinder> whoStrong = who.promote();
+
+    if (whoStrong == 0) {
+        ALOGV("java clients' binder death already cleaned up (normal case)");
+        return;
+    }
+
+    sp<ICameraClient> iCamClient = interface_cast<ICameraClient>(whoStrong);
+
+    sp<Client> cameraClient = getClientByRemote(iCamClient);
+    ALOGW("Disconnecting camera client %p since the binder for it "
+          "died (this pid %d)", cameraClient.get(), getCallingPid());
+
+    cameraClient->disconnect();
+
+}
+
 }; // namespace android
diff --git a/services/camera/libcameraservice/CameraService.h b/services/camera/libcameraservice/CameraService.h
index 630fca7..f1e7df6 100644
--- a/services/camera/libcameraservice/CameraService.h
+++ b/services/camera/libcameraservice/CameraService.h
@@ -34,7 +34,8 @@
 
 class CameraService :
     public BinderService<CameraService>,
-    public BnCameraService
+    public BnCameraService,
+    public IBinder::DeathRecipient
 {
     friend class BinderService<CameraService>;
 public:
@@ -54,6 +55,8 @@
     virtual Client*     getClientByIdUnsafe(int cameraId);
     virtual Mutex*      getClientLockById(int cameraId);
 
+    virtual sp<Client>  getClientByRemote(const sp<ICameraClient>& cameraClient);
+
     virtual status_t    dump(int fd, const Vector<String16>& args);
     virtual status_t    onTransact(uint32_t code, const Parcel& data,
                                    Parcel* reply, uint32_t flags);
@@ -100,7 +103,8 @@
                 const sp<ICameraClient>& cameraClient,
                 int cameraId,
                 int cameraFacing,
-                int clientPid);
+                int clientPid,
+                int servicePid);
         ~Client();
 
         // return our camera client
@@ -128,6 +132,7 @@
         int                             mCameraId;       // immutable after constructor
         int                             mCameraFacing;   // immutable after constructor
         pid_t                           mClientPid;
+        pid_t                           mServicePid;     // immutable after constructor
 
     };
 
@@ -137,6 +142,9 @@
     Mutex               mClientLock[MAX_CAMERAS]; // prevent Client destruction inside callbacks
     int                 mNumberOfCameras;
 
+    // needs to be called with mServiceLock held
+    sp<Client>          findClientUnsafe(const sp<ICameraClient>& cameraClient, int& outIndex);
+
     // atomics to record whether the hardware is allocated to some client.
     volatile int32_t    mBusy[MAX_CAMERAS];
     void                setCameraBusy(int cameraId);
@@ -150,6 +158,9 @@
     int                 mSoundRef;  // reference count (release all MediaPlayer when 0)
 
     camera_module_t *mModule;
+
+    // IBinder::DeathRecipient implementation
+    virtual void binderDied(const wp<IBinder> &who);
 };
 
 } // namespace android
diff --git a/services/camera/libcameraservice/camera2/CallbackProcessor.cpp b/services/camera/libcameraservice/camera2/CallbackProcessor.cpp
index ede97a6..3e9c255 100644
--- a/services/camera/libcameraservice/camera2/CallbackProcessor.cpp
+++ b/services/camera/libcameraservice/camera2/CallbackProcessor.cpp
@@ -86,6 +86,8 @@
             // Since size should only change while preview is not running,
             // assuming that all existing use of old callback stream is
             // completed.
+            ALOGV("%s: Camera %d: Deleting stream %d since the buffer dimensions changed",
+                __FUNCTION__, client->getCameraId(), mCallbackStreamId);
             res = device->deleteStream(mCallbackStreamId);
             if (res != OK) {
                 ALOGE("%s: Camera %d: Unable to delete old output stream "
diff --git a/services/camera/libcameraservice/camera2/CaptureSequencer.cpp b/services/camera/libcameraservice/camera2/CaptureSequencer.cpp
index c9498c2..98aa380 100644
--- a/services/camera/libcameraservice/camera2/CaptureSequencer.cpp
+++ b/services/camera/libcameraservice/camera2/CaptureSequencer.cpp
@@ -289,13 +289,6 @@
     client->registerFrameListener(mCaptureId,
             this);
 
-    res = client->getCameraDevice()->clearStreamingRequest();
-    if (res != OK) {
-        ALOGE("%s: Camera %d: Unable to stop preview for ZSL capture: "
-                "%s (%d)",
-                __FUNCTION__, client->getCameraId(), strerror(-res), res);
-        return DONE;
-    }
     // TODO: Actually select the right thing here.
     res = processor->pushToReprocess(mCaptureId);
     if (res != OK) {
diff --git a/services/camera/libcameraservice/camera2/JpegProcessor.cpp b/services/camera/libcameraservice/camera2/JpegProcessor.cpp
index 7b368fa..a353679 100644
--- a/services/camera/libcameraservice/camera2/JpegProcessor.cpp
+++ b/services/camera/libcameraservice/camera2/JpegProcessor.cpp
@@ -107,6 +107,8 @@
         }
         if (currentWidth != (uint32_t)params.pictureWidth ||
                 currentHeight != (uint32_t)params.pictureHeight) {
+            ALOGV("%s: Camera %d: Deleting stream %d since the buffer dimensions changed",
+                __FUNCTION__, client->getCameraId(), mCaptureStreamId);
             res = device->deleteStream(mCaptureStreamId);
             if (res != OK) {
                 ALOGE("%s: Camera %d: Unable to delete old output stream "
diff --git a/services/camera/libcameraservice/camera2/Parameters.cpp b/services/camera/libcameraservice/camera2/Parameters.cpp
index 5ba564d..74f4a7e 100644
--- a/services/camera/libcameraservice/camera2/Parameters.cpp
+++ b/services/camera/libcameraservice/camera2/Parameters.cpp
@@ -53,6 +53,9 @@
     res = buildFastInfo();
     if (res != OK) return res;
 
+    res = buildQuirks();
+    if (res != OK) return res;
+
     camera_metadata_ro_entry_t availableProcessedSizes =
         staticInfo(ANDROID_SCALER_AVAILABLE_PROCESSED_SIZES, 2);
     if (!availableProcessedSizes.count) return NO_INIT;
@@ -891,6 +894,21 @@
     return OK;
 }
 
+status_t Parameters::buildQuirks() {
+    camera_metadata_ro_entry_t entry;
+    entry = info->find(ANDROID_QUIRKS_TRIGGER_AF_WITH_AUTO);
+    quirks.triggerAfWithAuto = (entry.count != 0 && entry.data.u8[0] == 1);
+    ALOGV_IF(quirks.triggerAfWithAuto, "Camera %d: Quirk triggerAfWithAuto enabled",
+            cameraId);
+
+    entry = info->find(ANDROID_QUIRKS_USE_ZSL_FORMAT);
+    quirks.useZslFormat = (entry.count != 0 && entry.data.u8[0] == 1);
+    ALOGV_IF(quirks.useZslFormat, "Camera %d: Quirk useZslFormat enabled",
+            cameraId);
+
+    return OK;
+}
+
 camera_metadata_ro_entry_t Parameters::staticInfo(uint32_t tag,
         size_t minCount, size_t maxCount) const {
     status_t res;
diff --git a/services/camera/libcameraservice/camera2/Parameters.h b/services/camera/libcameraservice/camera2/Parameters.h
index c587ca5..47eb993 100644
--- a/services/camera/libcameraservice/camera2/Parameters.h
+++ b/services/camera/libcameraservice/camera2/Parameters.h
@@ -195,8 +195,10 @@
     // Sets up default parameters
     status_t initialize(const CameraMetadata *info);
 
-    // Build fast device info
+    // Build fast-access device static info from static info
     status_t buildFastInfo();
+    // Query for quirks from static info
+    status_t buildQuirks();
 
     // Get entry from camera static characteristics information. min/maxCount
     // are used for error checking the number of values in the entry. 0 for
diff --git a/services/camera/libcameraservice/camera2/StreamingProcessor.cpp b/services/camera/libcameraservice/camera2/StreamingProcessor.cpp
index 140138d..744b7ed 100644
--- a/services/camera/libcameraservice/camera2/StreamingProcessor.cpp
+++ b/services/camera/libcameraservice/camera2/StreamingProcessor.cpp
@@ -170,6 +170,9 @@
         if (client == 0) return INVALID_OPERATION;
         sp<Camera2Device> device = client->getCameraDevice();
 
+        ALOGV("%s: for cameraId %d on streamId %d",
+            __FUNCTION__, client->getCameraId(), mPreviewStreamId);
+
         res = device->waitUntilDrained();
         if (res != OK) {
             ALOGE("%s: Error waiting for preview to drain: %s (%d)",
@@ -351,6 +354,8 @@
     sp<Camera2Client> client = mClient.promote();
     if (client == 0) return INVALID_OPERATION;
 
+    ALOGV("%s: Camera %d: type = %d", __FUNCTION__, client->getCameraId(), type);
+
     Mutex::Autolock m(mMutex);
 
     CameraMetadata &request = (type == PREVIEW) ?
diff --git a/services/camera/libcameraservice/camera2/ZslProcessor.cpp b/services/camera/libcameraservice/camera2/ZslProcessor.cpp
index 9516f97..7977f9d 100644
--- a/services/camera/libcameraservice/camera2/ZslProcessor.cpp
+++ b/services/camera/libcameraservice/camera2/ZslProcessor.cpp
@@ -147,6 +147,8 @@
                         client->getCameraId(), strerror(-res), res);
                 return res;
             }
+            ALOGV("%s: Camera %d: Deleting stream %d since the buffer dimensions changed",
+                __FUNCTION__, client->getCameraId(), mZslStreamId);
             res = device->deleteStream(mZslStreamId);
             if (res != OK) {
                 ALOGE("%s: Camera %d: Unable to delete old output stream "
@@ -161,9 +163,12 @@
     if (mZslStreamId == NO_STREAM) {
         // Create stream for HAL production
         // TODO: Sort out better way to select resolution for ZSL
+        int streamType = params.quirks.useZslFormat ?
+                (int)CAMERA2_HAL_PIXEL_FORMAT_ZSL :
+                (int)HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED;
         res = device->createStream(mZslWindow,
                 params.fastInfo.arrayWidth, params.fastInfo.arrayHeight,
-                CAMERA2_HAL_PIXEL_FORMAT_ZSL, 0,
+                streamType, 0,
                 &mZslStreamId);
         if (res != OK) {
             ALOGE("%s: Camera %d: Can't create output stream for ZSL: "
@@ -292,6 +297,14 @@
             return INVALID_OPERATION;
         }
 
+        res = client->getCameraDevice()->clearStreamingRequest();
+        if (res != OK) {
+            ALOGE("%s: Camera %d: Unable to stop preview for ZSL capture: "
+                "%s (%d)",
+                __FUNCTION__, client->getCameraId(), strerror(-res), res);
+            return INVALID_OPERATION;
+        }
+        // TODO: have push-and-clear be atomic
         res = client->getCameraDevice()->pushReprocessBuffer(mZslReprocessStreamId,
                 handle, this);
         if (res != OK) {