summaryrefslogtreecommitdiffstats
path: root/services
diff options
context:
space:
mode:
Diffstat (limited to 'services')
-rw-r--r--services/camera/libcameraservice/Camera2Client.cpp20
-rw-r--r--services/camera/libcameraservice/CameraService.cpp4
-rw-r--r--services/camera/libcameraservice/camera2/CaptureSequencer.cpp56
-rw-r--r--services/camera/libcameraservice/camera2/CaptureSequencer.h7
-rw-r--r--services/camera/libcameraservice/camera2/JpegProcessor.cpp18
-rw-r--r--services/camera/libcameraservice/camera2/Parameters.cpp30
-rw-r--r--services/camera/libcameraservice/camera2/Parameters.h11
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