Merge "audio policy: deprecate ro.camera.sound.forced" into jb-mr1-dev
diff --git a/services/camera/libcameraservice/Camera2Client.cpp b/services/camera/libcameraservice/Camera2Client.cpp
index 3239483..e073e39 100644
--- a/services/camera/libcameraservice/Camera2Client.cpp
+++ b/services/camera/libcameraservice/Camera2Client.cpp
@@ -378,16 +378,7 @@
 
     ALOGV("Camera %d: Shutting down", mCameraId);
 
-    res = mStreamingProcessor->stopStream();
-    if (res != OK) {
-        ALOGE("%s: Problem stopping streaming: %s (%d)",
-                __FUNCTION__, strerror(-res), res);
-    }
-    res = mDevice->waitUntilDrained();
-    if (res != OK) {
-        ALOGE("%s: Problem waiting for HAL: %s (%d)",
-                __FUNCTION__, strerror(-res), res);
-    }
+    stopPreviewL();
 
     {
         SharedParameters::Lock l(mParameters);
@@ -733,6 +724,7 @@
 void Camera2Client::stopPreviewL() {
     ATRACE_CALL();
     status_t res;
+    const nsecs_t kStopCaptureTimeout = 3000000000LL; // 3 seconds
     Parameters::State state;
     {
         SharedParameters::Lock l(mParameters);
@@ -745,13 +737,11 @@
                     __FUNCTION__, mCameraId);
             break;
         case Parameters::STOPPED:
-            break;
+        case Parameters::VIDEO_SNAPSHOT:
         case Parameters::STILL_CAPTURE:
-            ALOGE("%s: Camera %d: Cannot stop preview during still capture.",
-                    __FUNCTION__, mCameraId);
-            break;
+            mCaptureSequencer->waitUntilIdle(kStopCaptureTimeout);
+            // no break
         case Parameters::RECORD:
-            // no break - identical to preview
         case Parameters::PREVIEW:
             mStreamingProcessor->stopStream();
             res = mDevice->waitUntilDrained();
diff --git a/services/camera/libcameraservice/CameraService.cpp b/services/camera/libcameraservice/CameraService.cpp
index 6fbd6ed..124d24d 100644
--- a/services/camera/libcameraservice/CameraService.cpp
+++ b/services/camera/libcameraservice/CameraService.cpp
@@ -409,6 +409,9 @@
 // tear down the client
 CameraService::Client::~Client() {
     mCameraService->releaseSound();
+
+    // unconditionally disconnect. function is idempotent
+    Client::disconnect();
 }
 
 // ----------------------------------------------------------------------------
@@ -433,6 +436,7 @@
     return client;
 }
 
+// NOTE: function is idempotent
 void CameraService::Client::disconnect() {
     mCameraService->removeClient(mCameraClient);
     mCameraService->setCameraFree(mCameraId);
diff --git a/services/camera/libcameraservice/camera2/CaptureSequencer.cpp b/services/camera/libcameraservice/camera2/CaptureSequencer.cpp
index a849246..5156539 100644
--- a/services/camera/libcameraservice/camera2/CaptureSequencer.cpp
+++ b/services/camera/libcameraservice/camera2/CaptureSequencer.cpp
@@ -72,6 +72,23 @@
     return OK;
 }
 
+status_t CaptureSequencer::waitUntilIdle(nsecs_t timeout) {
+    ATRACE_CALL();
+    ALOGV("%s: Waiting for idle", __FUNCTION__);
+    Mutex::Autolock l(mStateMutex);
+    status_t res = -1;
+    while (mCaptureState != IDLE) {
+        nsecs_t startTime = systemTime();
+
+        res = mStateChanged.waitRelative(mStateMutex, timeout);
+        if (res != OK) return res;
+
+        timeout -= (systemTime() - startTime);
+    }
+    ALOGV("%s: Now idle", __FUNCTION__);
+    return OK;
+}
+
 void CaptureSequencer::notifyAutoExposure(uint8_t newState, int triggerId) {
     ATRACE_CALL();
     Mutex::Autolock l(mInputMutex);
@@ -137,8 +154,9 @@
     "ZSL_WAITING",
     "ZSL_REPROCESSING",
     "STANDARD_START",
-    "STANDARD_PRECAPTURE",
-    "STANDARD_CAPTURING",
+    "STANDARD_PRECAPTURE_WAIT",
+    "STANDARD_CAPTURE",
+    "STANDARD_CAPTURE_WAIT",
     "BURST_CAPTURE_START",
     "BURST_CAPTURE_WAIT",
     "DONE",
@@ -168,15 +186,26 @@
     sp<Camera2Client> client = mClient.promote();
     if (client == 0) return false;
 
-    if (mCaptureState < ERROR) {
-        CaptureState oldState = mCaptureState;
-        mCaptureState = (this->*kStateManagers[mCaptureState])(client);
-        if (ATRACE_ENABLED() && oldState != mCaptureState) {
-            ATRACE_INT("cam2_capt_state", mCaptureState);
-        }
-    } else {
-        ALOGE("%s: Bad capture state: %s",
-                __FUNCTION__, kStateNames[mCaptureState]);
+    CaptureState currentState;
+    {
+        Mutex::Autolock l(mStateMutex);
+        currentState = mCaptureState;
+    }
+
+    currentState = (this->*kStateManagers[currentState])(client);
+
+    Mutex::Autolock l(mStateMutex);
+    if (currentState != mCaptureState) {
+        mCaptureState = currentState;
+        ATRACE_INT("cam2_capt_state", mCaptureState);
+        ALOGV("Camera %d: New capture state %s",
+                client->getCameraId(), kStateNames[mCaptureState]);
+        mStateChanged.signal();
+    }
+
+    if (mCaptureState == ERROR) {
+        ALOGE("Camera %d: Stopping capture sequencer due to error",
+                client->getCameraId());
         return false;
     }
 
@@ -214,6 +243,11 @@
     {
         SharedParameters::Lock l(client->getParameters());
         switch (l.mParameters.state) {
+            case Parameters::DISCONNECTED:
+                ALOGW("%s: Camera %d: Discarding image data during shutdown ",
+                        __FUNCTION__, client->getCameraId());
+                res = INVALID_OPERATION;
+                break;
             case Parameters::STILL_CAPTURE:
                 l.mParameters.state = Parameters::STOPPED;
                 break;
diff --git a/services/camera/libcameraservice/camera2/CaptureSequencer.h b/services/camera/libcameraservice/camera2/CaptureSequencer.h
index 07e4c01..8df6d95 100644
--- a/services/camera/libcameraservice/camera2/CaptureSequencer.h
+++ b/services/camera/libcameraservice/camera2/CaptureSequencer.h
@@ -53,6 +53,11 @@
     // Begin still image capture
     status_t startCapture();
 
+    // Wait until current image capture completes; returns immediately if no
+    // capture is active. Returns TIMED_OUT if capture does not complete during
+    // the specified duration.
+    status_t waitUntilIdle(nsecs_t timeout);
+
     // Notifications about AE state changes
     void notifyAutoExposure(uint8_t newState, int triggerId);
 
@@ -118,6 +123,8 @@
         NUM_CAPTURE_STATES
     } mCaptureState;
     static const char* kStateNames[];
+    Mutex mStateMutex; // Guards mCaptureState
+    Condition mStateChanged;
 
     typedef CaptureState (CaptureSequencer::*StateManager)(sp<Camera2Client> &client);
     static const StateManager kStateManagers[];
diff --git a/services/camera/libcameraservice/camera2/JpegProcessor.cpp b/services/camera/libcameraservice/camera2/JpegProcessor.cpp
index a353679..ffc072b 100644
--- a/services/camera/libcameraservice/camera2/JpegProcessor.cpp
+++ b/services/camera/libcameraservice/camera2/JpegProcessor.cpp
@@ -209,24 +209,6 @@
     ALOGV("%s: Camera %d: Still capture available", __FUNCTION__,
             client->getCameraId());
 
-    // TODO: Signal errors here upstream
-    {
-        SharedParameters::Lock l(client->getParameters());
-
-        switch (l.mParameters.state) {
-            case Parameters::STILL_CAPTURE:
-            case Parameters::VIDEO_SNAPSHOT:
-                break;
-            default:
-                ALOGE("%s: Camera %d: Still image produced unexpectedly "
-                        "in state %s!",
-                        __FUNCTION__, client->getCameraId(),
-                        Parameters::getStateName(l.mParameters.state));
-                mCaptureConsumer->unlockBuffer(imgBuffer);
-                return BAD_VALUE;
-        }
-    }
-
     if (imgBuffer.format != HAL_PIXEL_FORMAT_BLOB) {
         ALOGE("%s: Camera %d: Unexpected format for still image: "
                 "%x, expected %x", __FUNCTION__, client->getCameraId(),
diff --git a/services/camera/libcameraservice/camera2/Parameters.cpp b/services/camera/libcameraservice/camera2/Parameters.cpp
index 1b15a1c..199e525 100644
--- a/services/camera/libcameraservice/camera2/Parameters.cpp
+++ b/services/camera/libcameraservice/camera2/Parameters.cpp
@@ -542,9 +542,9 @@
     if (!availableAeModes.count) return NO_INIT;
 
     if (flashAvailable.data.u8[0]) {
-        flashMode = Parameters::FLASH_MODE_AUTO;
+        flashMode = Parameters::FLASH_MODE_OFF;
         params.set(CameraParameters::KEY_FLASH_MODE,
-                CameraParameters::FLASH_MODE_AUTO);
+                CameraParameters::FLASH_MODE_OFF);
 
         String8 supportedFlashModes(CameraParameters::FLASH_MODE_OFF);
         supportedFlashModes = supportedFlashModes +
@@ -635,8 +635,11 @@
         staticInfo(ANDROID_CONTROL_MAX_REGIONS, 1, 1);
     if (!max3aRegions.count) return NO_INIT;
 
-    params.set(CameraParameters::KEY_MAX_NUM_FOCUS_AREAS,
-            max3aRegions.data.i32[0]);
+    int32_t maxNumFocusAreas = 0;
+    if (focusMode != Parameters::FOCUS_MODE_FIXED) {
+        maxNumFocusAreas = max3aRegions.data.i32[0];
+    }
+    params.set(CameraParameters::KEY_MAX_NUM_FOCUS_AREAS, maxNumFocusAreas);
     params.set(CameraParameters::KEY_FOCUS_AREAS,
             "(0,0,0,0,0)");
     focusingAreas.clear();
@@ -726,7 +729,7 @@
     params.set(CameraParameters::KEY_ZOOM_SUPPORTED,
             CameraParameters::TRUE);
     params.set(CameraParameters::KEY_SMOOTH_ZOOM_SUPPORTED,
-            CameraParameters::TRUE);
+            CameraParameters::FALSE);
 
     params.set(CameraParameters::KEY_FOCUS_DISTANCES,
             "Infinity,Infinity,Infinity");
@@ -1466,7 +1469,7 @@
     size_t max3aRegions =
         (size_t)staticInfo(ANDROID_CONTROL_MAX_REGIONS, 1, 1).data.i32[0];
     if (res == OK) res = validateAreas(validatedParams.focusingAreas,
-            max3aRegions);
+            max3aRegions, AREA_KIND_FOCUS);
     if (res != OK) {
         ALOGE("%s: Requested focus areas are malformed: %s",
                 __FUNCTION__, newParams.get(CameraParameters::KEY_FOCUS_AREAS));
@@ -1499,7 +1502,8 @@
     res = parseAreas(newParams.get(CameraParameters::KEY_METERING_AREAS),
             &validatedParams.meteringAreas);
     if (res == OK) {
-        res = validateAreas(validatedParams.meteringAreas, max3aRegions);
+        res = validateAreas(validatedParams.meteringAreas, max3aRegions,
+                            AREA_KIND_METERING);
     }
     if (res != OK) {
         ALOGE("%s: Requested metering areas are malformed: %s",
@@ -1510,7 +1514,8 @@
 
     // ZOOM
     validatedParams.zoom = newParams.getInt(CameraParameters::KEY_ZOOM);
-    if (validatedParams.zoom < 0 || validatedParams.zoom > (int)NUM_ZOOM_STEPS) {
+    if (validatedParams.zoom < 0
+                || validatedParams.zoom >= (int)NUM_ZOOM_STEPS) {
         ALOGE("%s: Requested zoom level %d is not supported",
                 __FUNCTION__, validatedParams.zoom);
         return BAD_VALUE;
@@ -2111,7 +2116,8 @@
 }
 
 status_t Parameters::validateAreas(const Vector<Parameters::Area> &areas,
-                                      size_t maxRegions) {
+                                      size_t maxRegions,
+                                      AreaKind areaKind) const {
     // Definition of valid area can be found in
     // include/camera/CameraParameters.h
     if (areas.size() == 0) return BAD_VALUE;
@@ -2125,6 +2131,12 @@
             return OK;
         }
     }
+
+    // fixed focus can only set (0,0,0,0,0) focus area
+    if (areaKind == AREA_KIND_FOCUS && focusMode == FOCUS_MODE_FIXED) {
+        return BAD_VALUE;
+    }
+
     if (areas.size() > maxRegions) {
         ALOGE("%s: Too many areas requested: %d",
                 __FUNCTION__, areas.size());
diff --git a/services/camera/libcameraservice/camera2/Parameters.h b/services/camera/libcameraservice/camera2/Parameters.h
index daae7c4..fd02744 100644
--- a/services/camera/libcameraservice/camera2/Parameters.h
+++ b/services/camera/libcameraservice/camera2/Parameters.h
@@ -258,8 +258,15 @@
     static const char* focusModeEnumToString(focusMode_t focusMode);
     static status_t parseAreas(const char *areasCStr,
             Vector<Area> *areas);
-    static status_t validateAreas(const Vector<Area> &areas,
-                                  size_t maxRegions);
+
+    enum AreaKind
+    {
+        AREA_KIND_FOCUS,
+        AREA_KIND_METERING
+    };
+    status_t validateAreas(const Vector<Area> &areas,
+                                  size_t maxRegions,
+                                  AreaKind areaKind) const;
     static bool boolFromString(const char *boolStr);
 
     // Map from camera orientation + facing to gralloc transform enum