diff options
Diffstat (limited to 'services')
7 files changed, 91 insertions, 55 deletions
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 @@ void Camera2Client::disconnect() { 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::stopPreview() { 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 @@ void Camera2Client::stopPreviewL() { __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 @@ CameraService::Client::Client(const sp<CameraService>& cameraService, // tear down the client CameraService::Client::~Client() { mCameraService->releaseSound(); + + // unconditionally disconnect. function is idempotent + Client::disconnect(); } // ---------------------------------------------------------------------------- @@ -433,6 +436,7 @@ CameraService::Client* CameraService::Client::getClientFromCookie(void* user) { 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 @@ status_t CaptureSequencer::startCapture() { 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 @@ const char* CaptureSequencer::kStateNames[CaptureSequencer::NUM_CAPTURE_STATES+1 "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 @@ bool CaptureSequencer::threadLoop() { 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 @@ CaptureSequencer::CaptureState CaptureSequencer::manageDone(sp<Camera2Client> &c { 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 @@ class CaptureSequencer: // 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 @@ class CaptureSequencer: 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 @@ status_t JpegProcessor::processNewCapture(sp<Camera2Client> &client) { 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 @@ status_t Parameters::initialize(const CameraMetadata *info) { 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 @@ status_t Parameters::initialize(const CameraMetadata *info) { 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 @@ status_t Parameters::initialize(const CameraMetadata *info) { 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 @@ status_t Parameters::set(const String8& paramString) { 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 @@ status_t Parameters::set(const String8& paramString) { 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 @@ status_t Parameters::set(const String8& paramString) { // 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::parseAreas(const char *areasCStr, } 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 @@ status_t Parameters::validateAreas(const Vector<Parameters::Area> &areas, 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 @@ struct Parameters { 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 |