blob: 4fc362973c5723a3cda9d39c2a1bae079f40bd37 [file] [log] [blame]
/*
* Copyright (C) 2012 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#define LOG_TAG "Camera2Client"
#define ATRACE_TAG ATRACE_TAG_CAMERA
//#define LOG_NDEBUG 0
#include <utils/Log.h>
#include <utils/Trace.h>
#include <cutils/properties.h>
#include <gui/SurfaceTextureClient.h>
#include <gui/Surface.h>
#include <math.h>
#include "Camera2Client.h"
namespace android {
#define ALOG1(...) ALOGD_IF(gLogLevel >= 1, __VA_ARGS__);
#define ALOG2(...) ALOGD_IF(gLogLevel >= 2, __VA_ARGS__);
static int getCallingPid() {
return IPCThreadState::self()->getCallingPid();
}
static int getCallingUid() {
return IPCThreadState::self()->getCallingUid();
}
// Interface used by CameraService
Camera2Client::Camera2Client(const sp<CameraService>& cameraService,
const sp<ICameraClient>& cameraClient,
int cameraId,
int cameraFacing,
int clientPid):
Client(cameraService, cameraClient,
cameraId, cameraFacing, clientPid),
mState(NOT_INITIALIZED),
mParams(NULL),
mPreviewStreamId(NO_PREVIEW_STREAM),
mPreviewRequest(NULL)
{
ATRACE_CALL();
mDevice = new Camera2Device(cameraId);
}
status_t Camera2Client::initialize(camera_module_t *module)
{
ATRACE_CALL();
status_t res;
res = mDevice->initialize(module);
if (res != OK) {
ALOGE("%s: Camera %d: unable to initialize device: %s (%d)",
__FUNCTION__, mCameraId, strerror(-res), res);
return NO_INIT;
}
res = buildDefaultParameters();
if (res != OK) {
ALOGE("%s: Camera %d: unable to build defaults: %s (%d)",
__FUNCTION__, mCameraId, strerror(-res), res);
return NO_INIT;
}
if (gLogLevel >= 1) {
ALOGD("%s: Default parameters converted from camera %d:", __FUNCTION__,
mCameraId);
mParams->dump();
}
mState = STOPPED;
return OK;
}
Camera2Client::~Camera2Client() {
ATRACE_CALL();
mDestructionStarted = true;
if (mParams) delete mParams;
disconnect();
}
status_t Camera2Client::dump(int fd, const Vector<String16>& args) {
String8 result;
result.appendFormat("Client2[%d] (%p) PID: %d:\n",
mCameraId,
getCameraClient()->asBinder().get(),
mClientPid);
write(fd, result.string(), result.size());
return NO_ERROR;
}
// ICamera interface
void Camera2Client::disconnect() {
ATRACE_CALL();
if (mDevice == 0) return;
stopPreview();
if (mPreviewStreamId != NO_PREVIEW_STREAM) {
mDevice->deleteStream(mPreviewStreamId);
mPreviewStreamId = NO_PREVIEW_STREAM;
}
CameraService::Client::disconnect();
}
status_t Camera2Client::connect(const sp<ICameraClient>& client) {
ATRACE_CALL();
return BAD_VALUE;
}
status_t Camera2Client::lock() {
ATRACE_CALL();
return BAD_VALUE;
}
status_t Camera2Client::unlock() {
ATRACE_CALL();
return BAD_VALUE;
}
status_t Camera2Client::setPreviewDisplay(
const sp<Surface>& surface) {
ATRACE_CALL();
if (mState == PREVIEW) return INVALID_OPERATION;
sp<IBinder> binder;
sp<ANativeWindow> window;
if (surface != 0) {
binder = surface->asBinder();
window = surface;
}
return setPreviewWindow(binder,window);
}
status_t Camera2Client::setPreviewTexture(
const sp<ISurfaceTexture>& surfaceTexture) {
ATRACE_CALL();
if (mState == PREVIEW) return INVALID_OPERATION;
sp<IBinder> binder;
sp<ANativeWindow> window;
if (surfaceTexture != 0) {
binder = surfaceTexture->asBinder();
window = new SurfaceTextureClient(surfaceTexture);
}
return setPreviewWindow(binder, window);
}
status_t Camera2Client::setPreviewWindow(const sp<IBinder>& binder,
const sp<ANativeWindow>& window) {
ATRACE_CALL();
status_t res;
if (binder == mPreviewSurface) {
return NO_ERROR;
}
if (mPreviewStreamId != NO_PREVIEW_STREAM) {
res = mDevice->deleteStream(mPreviewStreamId);
if (res != OK) {
return res;
}
}
int previewWidth, previewHeight;
mParams->getPreviewSize(&previewWidth, &previewHeight);
res = mDevice->createStream(window,
previewWidth, previewHeight, CAMERA2_HAL_PIXEL_FORMAT_OPAQUE,
&mPreviewStreamId);
if (res != OK) {
return res;
}
if (mState == WAITING_FOR_PREVIEW_WINDOW) {
return startPreview();
}
return OK;
}
void Camera2Client::setPreviewCallbackFlag(int flag) {
ATRACE_CALL();
}
status_t Camera2Client::startPreview() {
ATRACE_CALL();
status_t res;
if (mState == PREVIEW) return INVALID_OPERATION;
if (mPreviewStreamId == NO_PREVIEW_STREAM) {
mState = WAITING_FOR_PREVIEW_WINDOW;
return OK;
}
if (mPreviewRequest == NULL) {
updatePreviewRequest();
}
uint8_t outputStream = mPreviewStreamId;
camera_metadata_entry_t outputStreams;
res = find_camera_metadata_entry(mPreviewRequest,
ANDROID_REQUEST_OUTPUT_STREAMS,
&outputStreams);
if (res == NAME_NOT_FOUND) {
res = add_camera_metadata_entry(mPreviewRequest,
ANDROID_REQUEST_OUTPUT_STREAMS,
&outputStream, 1);
} else if (res == OK) {
res = update_camera_metadata_entry(mPreviewRequest,
outputStreams.index, &outputStream, 1, NULL);
}
if (res != OK) {
ALOGE("%s: Camera %d: Unable to set up preview request: %s (%d)",
__FUNCTION__, mCameraId, strerror(-res), res);
mState = STOPPED;
return res;
}
res = mDevice->setStreamingRequest(mPreviewRequest);
if (res != OK) {
ALOGE("%s: Camera %d: Unable to set preview request to start preview: %s (%d)",
__FUNCTION__, mCameraId, strerror(-res), res);
mState = STOPPED;
return res;
}
mState = PREVIEW;
return OK;
}
void Camera2Client::stopPreview() {
ATRACE_CALL();
if (mState != PREVIEW) return;
mDevice->setStreamingRequest(NULL);
mState = STOPPED;
}
bool Camera2Client::previewEnabled() {
ATRACE_CALL();
return mState == PREVIEW;
}
status_t Camera2Client::storeMetaDataInBuffers(bool enabled) {
ATRACE_CALL();
return BAD_VALUE;
}
status_t Camera2Client::startRecording() {
ATRACE_CALL();
return BAD_VALUE;
}
void Camera2Client::stopRecording() {
ATRACE_CALL();
}
bool Camera2Client::recordingEnabled() {
ATRACE_CALL();
return BAD_VALUE;
}
void Camera2Client::releaseRecordingFrame(const sp<IMemory>& mem) {
ATRACE_CALL();
}
status_t Camera2Client::autoFocus() {
ATRACE_CALL();
return OK;
}
status_t Camera2Client::cancelAutoFocus() {
ATRACE_CALL();
return OK;
}
status_t Camera2Client::takePicture(int msgType) {
ATRACE_CALL();
return BAD_VALUE;
}
status_t Camera2Client::setParameters(const String8& params) {
ATRACE_CALL();
return OK;
}
String8 Camera2Client::getParameters() const {
ATRACE_CALL();
return mParams->flatten();
}
status_t Camera2Client::sendCommand(int32_t cmd, int32_t arg1, int32_t arg2) {
ATRACE_CALL();
return OK;
}
// private methods
status_t Camera2Client::buildDefaultParameters() {
ATRACE_CALL();
status_t res;
if (mParams) {
delete mParams;
}
mParams = new CameraParameters;
camera_metadata_entry_t availableProcessedSizes;
res = find_camera_metadata_entry(mDevice->info(),
ANDROID_SCALER_AVAILABLE_PROCESSED_SIZES,
&availableProcessedSizes);
if (res != OK) return res;
if (availableProcessedSizes.count < 2) {
ALOGE("%s: Camera %d: "
"Malformed %s entry",
__FUNCTION__, mCameraId,
get_camera_metadata_tag_name(
ANDROID_SCALER_AVAILABLE_PROCESSED_SIZES));
return NO_INIT;
}
// TODO: Pick more intelligently
int previewWidth = availableProcessedSizes.data.i32[0];
int previewHeight = availableProcessedSizes.data.i32[1];
mParams->setPreviewSize(previewWidth, previewHeight);
mParams->setVideoSize(previewWidth, previewHeight);
mParams->set(CameraParameters::KEY_PREFERRED_PREVIEW_SIZE_FOR_VIDEO,
String8::format("%dx%d",previewWidth,previewHeight));
{
String8 supportedPreviewSizes;
for (size_t i=0; i < availableProcessedSizes.count; i += 2) {
if (i != 0) supportedPreviewSizes += ",";
supportedPreviewSizes += String8::format("%dx%d",
availableProcessedSizes.data.i32[i],
availableProcessedSizes.data.i32[i+1]);
}
mParams->set(CameraParameters::KEY_SUPPORTED_PREVIEW_SIZES,
supportedPreviewSizes);
mParams->set(CameraParameters::KEY_SUPPORTED_VIDEO_SIZES,
supportedPreviewSizes);
}
camera_metadata_entry_t availableFpsRanges;
res = find_camera_metadata_entry(mDevice->info(),
ANDROID_CONTROL_AE_AVAILABLE_TARGET_FPS_RANGES,
&availableFpsRanges);
if (res != OK) return res;
if (availableFpsRanges.count < 2) {
ALOGE("%s: Camera %d: "
"Malformed %s entry",
__FUNCTION__, mCameraId,
get_camera_metadata_tag_name(
ANDROID_CONTROL_AE_AVAILABLE_TARGET_FPS_RANGES));
return NO_INIT;
}
int previewFpsRangeMin = availableFpsRanges.data.i32[0];
int previewFpsRangeMax = availableFpsRanges.data.i32[1];
mParams->set(CameraParameters::KEY_PREVIEW_FPS_RANGE,
String8::format("%d,%d", previewFpsRangeMin, previewFpsRangeMax));
{
String8 supportedPreviewFpsRange;
for (size_t i=0; i < availableFpsRanges.count; i += 2) {
if (i != 0) supportedPreviewFpsRange += ",";
supportedPreviewFpsRange += String8::format("(%d,%d)",
availableFpsRanges.data.i32[i],
availableFpsRanges.data.i32[i+1]);
}
mParams->set(CameraParameters::KEY_SUPPORTED_PREVIEW_FPS_RANGE,
supportedPreviewFpsRange);
}
mParams->set(CameraParameters::KEY_PREVIEW_FORMAT,
"yuv420sp"); // NV21
camera_metadata_entry_t availableFormats;
res = find_camera_metadata_entry(mDevice->info(),
ANDROID_SCALER_AVAILABLE_FORMATS,
&availableFormats);
{
String8 supportedPreviewFormats;
bool addComma = false;
for (size_t i=0; i < availableFormats.count; i++) {
if (addComma) supportedPreviewFormats += ",";
addComma = true;
switch (availableFormats.data.i32[i]) {
case HAL_PIXEL_FORMAT_YCbCr_422_SP:
supportedPreviewFormats += "yuv422sp";
break;
case HAL_PIXEL_FORMAT_YCrCb_420_SP:
supportedPreviewFormats += "yuv420sp";
break;
case HAL_PIXEL_FORMAT_YCbCr_422_I:
supportedPreviewFormats += "yuv422i-yuyv";
break;
case HAL_PIXEL_FORMAT_YV12:
supportedPreviewFormats += "yuv420p";
break;
case HAL_PIXEL_FORMAT_RGB_565:
supportedPreviewFormats += "rgb565";
break;
// Not advertizing JPEG, RAW_SENSOR, etc, for preview formats
case HAL_PIXEL_FORMAT_RAW_SENSOR:
addComma = false;
break;
default:
ALOGW("%s: Camera %d: Unknown preview format: %x",
__FUNCTION__, mCameraId, availableFormats.data.i32[i]);
addComma = false;
break;
}
}
mParams->set(CameraParameters::KEY_SUPPORTED_PREVIEW_FORMATS,
supportedPreviewFormats);
}
// PREVIEW_FRAME_RATE / SUPPORTED_PREVIEW_FRAME_RATES are deprecated, but
// still have to do something sane for them
mParams->set(CameraParameters::KEY_PREVIEW_FRAME_RATE,
previewFpsRangeMin);
{
String8 supportedPreviewFrameRates;
for (size_t i=0; i < availableFpsRanges.count; i += 2) {
if (i != 0) supportedPreviewFrameRates += ",";
supportedPreviewFrameRates += String8::format("%d",
availableFpsRanges.data.i32[i]);
}
mParams->set(CameraParameters::KEY_SUPPORTED_PREVIEW_FRAME_RATES,
supportedPreviewFrameRates);
}
camera_metadata_entry_t availableJpegSizes;
res = find_camera_metadata_entry(mDevice->info(),
ANDROID_SCALER_AVAILABLE_JPEG_SIZES,
&availableJpegSizes);
if (res != OK) return res;
if (availableJpegSizes.count < 2) {
ALOGE("%s: Camera %d: "
"Malformed %s entry",
__FUNCTION__, mCameraId,
get_camera_metadata_tag_name(
ANDROID_SCALER_AVAILABLE_JPEG_SIZES));
return NO_INIT;
}
// TODO: Pick maximum
int32_t pictureWidth = availableJpegSizes.data.i32[0];
int32_t pictureHeight = availableJpegSizes.data.i32[1];
mParams->setPictureSize(pictureWidth, pictureHeight);
{
String8 supportedPictureSizes;
for (size_t i=0; i < availableJpegSizes.count; i += 2) {
if (i != 0) supportedPictureSizes += ",";
supportedPictureSizes += String8::format("%dx%d",
availableJpegSizes.data.i32[i],
availableJpegSizes.data.i32[i+1]);
}
mParams->set(CameraParameters::KEY_SUPPORTED_PICTURE_SIZES,
supportedPictureSizes);
}
mParams->setPictureFormat("jpeg");
mParams->set(CameraParameters::KEY_SUPPORTED_PICTURE_FORMATS,
"jpeg");
camera_metadata_entry_t availableJpegThumbnailSizes;
res = find_camera_metadata_entry(mDevice->info(),
ANDROID_JPEG_AVAILABLE_THUMBNAIL_SIZES,
&availableJpegThumbnailSizes);
if (res != OK) return res;
if (availableJpegThumbnailSizes.count < 2) {
ALOGE("%s: Camera %d: "
"Malformed %s entry",
__FUNCTION__, mCameraId,
get_camera_metadata_tag_name(
ANDROID_JPEG_AVAILABLE_THUMBNAIL_SIZES));
return NO_INIT;
}
// TODO: Pick default thumbnail size sensibly
int32_t jpegThumbWidth = availableJpegThumbnailSizes.data.i32[0];
int32_t jpegThumbHeight = availableJpegThumbnailSizes.data.i32[1];
mParams->set(CameraParameters::KEY_JPEG_THUMBNAIL_WIDTH,
jpegThumbWidth);
mParams->set(CameraParameters::KEY_JPEG_THUMBNAIL_HEIGHT,
jpegThumbHeight);
{
String8 supportedJpegThumbSizes;
for (size_t i=0; i < availableJpegThumbnailSizes.count; i += 2) {
if (i != 0) supportedJpegThumbSizes += ",";
supportedJpegThumbSizes += String8::format("%dx%d",
availableJpegThumbnailSizes.data.i32[i],
availableJpegThumbnailSizes.data.i32[i+1]);
}
mParams->set(CameraParameters::KEY_SUPPORTED_JPEG_THUMBNAIL_SIZES,
supportedJpegThumbSizes);
}
mParams->set(CameraParameters::KEY_JPEG_THUMBNAIL_QUALITY,
"90");
mParams->set(CameraParameters::KEY_JPEG_QUALITY,
"90");
mParams->set(CameraParameters::KEY_ROTATION,
"0");
// Not settting GPS fields
mParams->set(CameraParameters::KEY_WHITE_BALANCE,
"auto");
camera_metadata_entry_t availableWhiteBalanceModes;
res = find_camera_metadata_entry(mDevice->info(),
ANDROID_CONTROL_AWB_AVAILABLE_MODES,
&availableWhiteBalanceModes);
{
String8 supportedWhiteBalance;
bool addComma = false;
for (size_t i=0; i < availableWhiteBalanceModes.count; i++) {
if (addComma) supportedWhiteBalance += ",";
addComma = true;
switch (availableWhiteBalanceModes.data.u8[i]) {
case ANDROID_CONTROL_AWB_AUTO:
supportedWhiteBalance += "auto";
break;
case ANDROID_CONTROL_AWB_INCANDESCENT:
supportedWhiteBalance += "incandescent";
break;
case ANDROID_CONTROL_AWB_FLUORESCENT:
supportedWhiteBalance += "fluorescent";
break;
case ANDROID_CONTROL_AWB_WARM_FLUORESCENT:
supportedWhiteBalance += "warm-fluorescent";
break;
case ANDROID_CONTROL_AWB_DAYLIGHT:
supportedWhiteBalance += "daylight";
break;
case ANDROID_CONTROL_AWB_CLOUDY_DAYLIGHT:
supportedWhiteBalance += "cloudy-daylight";
break;
case ANDROID_CONTROL_AWB_TWILIGHT:
supportedWhiteBalance += "twilight";
break;
case ANDROID_CONTROL_AWB_SHADE:
supportedWhiteBalance += "shade";
break;
// Skipping values not mappable to v1 API
case ANDROID_CONTROL_AWB_OFF:
addComma = false;
break;
default:
ALOGW("%s: Camera %d: Unknown white balance value: %d",
__FUNCTION__, mCameraId,
availableWhiteBalanceModes.data.u8[i]);
addComma = false;
break;
}
}
mParams->set(CameraParameters::KEY_SUPPORTED_WHITE_BALANCE,
supportedWhiteBalance);
}
mParams->set(CameraParameters::KEY_EFFECT, "none");
camera_metadata_entry_t availableEffects;
res = find_camera_metadata_entry(mDevice->info(),
ANDROID_CONTROL_AVAILABLE_EFFECTS,
&availableEffects);
if (res != OK) return res;
{
String8 supportedEffects;
bool addComma = false;
for (size_t i=0; i < availableEffects.count; i++) {
if (addComma) supportedEffects += ",";
addComma = true;
switch (availableEffects.data.u8[i]) {
case ANDROID_CONTROL_EFFECT_OFF:
supportedEffects += "none";
break;
case ANDROID_CONTROL_EFFECT_MONO:
supportedEffects += "mono";
case ANDROID_CONTROL_EFFECT_NEGATIVE:
supportedEffects += "negative";
break;
case ANDROID_CONTROL_EFFECT_SOLARIZE:
supportedEffects += "solarize";
break;
case ANDROID_CONTROL_EFFECT_SEPIA:
supportedEffects += "sepia";
break;
case ANDROID_CONTROL_EFFECT_POSTERIZE:
supportedEffects += "posterize";
break;
case ANDROID_CONTROL_EFFECT_WHITEBOARD:
supportedEffects += "whiteboard";
break;
case ANDROID_CONTROL_EFFECT_BLACKBOARD:
supportedEffects += "blackboard";
break;
case ANDROID_CONTROL_EFFECT_AQUA:
supportedEffects += "aqua";
break;
default:
ALOGW("%s: Camera %d: Unknown effect value: %d",
__FUNCTION__, mCameraId, availableEffects.data.u8[i]);
addComma = false;
break;
}
}
mParams->set(CameraParameters::KEY_SUPPORTED_EFFECTS, supportedEffects);
}
mParams->set(CameraParameters::KEY_ANTIBANDING, "auto");
camera_metadata_entry_t availableAntibandingModes;
res = find_camera_metadata_entry(mDevice->info(),
ANDROID_CONTROL_AE_AVAILABLE_ANTIBANDING_MODES,
&availableAntibandingModes);
if (res != OK) return res;
{
String8 supportedAntibanding;
bool addComma = false;
for (size_t i=0; i < availableAntibandingModes.count; i++) {
if (addComma) supportedAntibanding += ",";
addComma = true;
switch (availableAntibandingModes.data.u8[i]) {
case ANDROID_CONTROL_AE_ANTIBANDING_OFF:
supportedAntibanding += "off";
break;
case ANDROID_CONTROL_AE_ANTIBANDING_50HZ:
supportedAntibanding += "50hz";
break;
case ANDROID_CONTROL_AE_ANTIBANDING_60HZ:
supportedAntibanding += "60hz";
break;
case ANDROID_CONTROL_AE_ANTIBANDING_AUTO:
supportedAntibanding += "auto";
break;
default:
ALOGW("%s: Camera %d: Unknown antibanding value: %d",
__FUNCTION__, mCameraId,
availableAntibandingModes.data.u8[i]);
addComma = false;
break;
}
}
mParams->set(CameraParameters::KEY_SUPPORTED_ANTIBANDING,
supportedAntibanding);
}
mParams->set(CameraParameters::KEY_SCENE_MODE, "auto");
camera_metadata_entry_t availableSceneModes;
res = find_camera_metadata_entry(mDevice->info(),
ANDROID_CONTROL_AVAILABLE_SCENE_MODES,
&availableSceneModes);
if (res != OK) return res;
{
String8 supportedSceneModes("auto");
bool addComma = true;
bool noSceneModes = false;
for (size_t i=0; i < availableSceneModes.count; i++) {
if (addComma) supportedSceneModes += ",";
addComma = true;
switch (availableSceneModes.data.u8[i]) {
case ANDROID_CONTROL_SCENE_MODE_UNSUPPORTED:
noSceneModes = true;
break;
case ANDROID_CONTROL_SCENE_MODE_FACE_PRIORITY:
// Not in old API
addComma = false;
break;
case ANDROID_CONTROL_SCENE_MODE_ACTION:
supportedSceneModes += "action";
break;
case ANDROID_CONTROL_SCENE_MODE_PORTRAIT:
supportedSceneModes += "portrait";
break;
case ANDROID_CONTROL_SCENE_MODE_LANDSCAPE:
supportedSceneModes += "landscape";
break;
case ANDROID_CONTROL_SCENE_MODE_NIGHT:
supportedSceneModes += "night";
break;
case ANDROID_CONTROL_SCENE_MODE_NIGHT_PORTRAIT:
supportedSceneModes += "night-portrait";
break;
case ANDROID_CONTROL_SCENE_MODE_THEATRE:
supportedSceneModes += "theatre";
break;
case ANDROID_CONTROL_SCENE_MODE_BEACH:
supportedSceneModes += "beach";
break;
case ANDROID_CONTROL_SCENE_MODE_SNOW:
supportedSceneModes += "snow";
break;
case ANDROID_CONTROL_SCENE_MODE_SUNSET:
supportedSceneModes += "sunset";
break;
case ANDROID_CONTROL_SCENE_MODE_STEADYPHOTO:
supportedSceneModes += "steadyphoto";
break;
case ANDROID_CONTROL_SCENE_MODE_FIREWORKS:
supportedSceneModes += "fireworks";
break;
case ANDROID_CONTROL_SCENE_MODE_SPORTS:
supportedSceneModes += "sports";
break;
case ANDROID_CONTROL_SCENE_MODE_PARTY:
supportedSceneModes += "party";
break;
case ANDROID_CONTROL_SCENE_MODE_CANDLELIGHT:
supportedSceneModes += "candlelight";
break;
case ANDROID_CONTROL_SCENE_MODE_BARCODE:
supportedSceneModes += "barcode";
break;
default:
ALOGW("%s: Camera %d: Unknown scene mode value: %d",
__FUNCTION__, mCameraId, availableSceneModes.data.u8[i]);
addComma = false;
break;
}
}
if (!noSceneModes) {
mParams->set(CameraParameters::KEY_SUPPORTED_SCENE_MODES,
supportedSceneModes);
}
}
camera_metadata_entry_t flashAvailable;
res = find_camera_metadata_entry(mDevice->info(),
ANDROID_FLASH_AVAILABLE, &flashAvailable);
if (res != OK) return res;
camera_metadata_entry_t availableAeModes;
res = find_camera_metadata_entry(mDevice->info(),
ANDROID_CONTROL_AE_AVAILABLE_MODES,
&availableAeModes);
if (res != OK) return res;
if (flashAvailable.data.u8[0]) {
mParams->set(CameraParameters::KEY_FLASH_MODE, "auto");
String8 supportedFlashModes("off,auto,on,torch");
for (size_t i=0; i < availableAeModes.count; i++) {
if (availableAeModes.data.u8[i] ==
ANDROID_CONTROL_AE_ON_AUTO_FLASH_REDEYE) {
supportedFlashModes += ",red-eye";
break;
}
}
mParams->set(CameraParameters::KEY_SUPPORTED_FLASH_MODES,
supportedFlashModes);
}
camera_metadata_entry_t minFocusDistance;
res = find_camera_metadata_entry(mDevice->info(),
ANDROID_LENS_MINIMUM_FOCUS_DISTANCE,
&minFocusDistance);
if (res != OK) return res;
camera_metadata_entry_t availableAfModes;
res = find_camera_metadata_entry(mDevice->info(),
ANDROID_CONTROL_AF_AVAILABLE_MODES,
&availableAfModes);
if (res != OK) return res;
if (minFocusDistance.data.f[0] == 0) {
// Fixed-focus lens
mParams->set(CameraParameters::KEY_FOCUS_MODE, "fixed");
mParams->set(CameraParameters::KEY_SUPPORTED_FOCUS_MODES, "fixed");
} else {
mParams->set(CameraParameters::KEY_FOCUS_MODE, "auto");
String8 supportedFocusModes("fixed,infinity");
bool addComma = true;
for (size_t i=0; i < availableAfModes.count; i++) {
if (addComma) supportedFocusModes += ",";
addComma = true;
switch (availableAfModes.data.u8[i]) {
case ANDROID_CONTROL_AF_AUTO:
supportedFocusModes += "auto";
break;
case ANDROID_CONTROL_AF_MACRO:
supportedFocusModes += "macro";
break;
case ANDROID_CONTROL_AF_CONTINUOUS_VIDEO:
supportedFocusModes += "continuous-video";
break;
case ANDROID_CONTROL_AF_CONTINUOUS_PICTURE:
supportedFocusModes += "continuous-picture";
break;
case ANDROID_CONTROL_AF_EDOF:
supportedFocusModes += "edof";
break;
// Not supported in v1 API
case ANDROID_CONTROL_AF_OFF:
addComma = false;
break;
default:
ALOGW("%s: Camera %d: Unknown AF mode value: %d",
__FUNCTION__, mCameraId, availableAfModes.data.u8[i]);
addComma = false;
break;
}
}
mParams->set(CameraParameters::KEY_SUPPORTED_FOCUS_MODES,
supportedFocusModes);
}
camera_metadata_entry_t max3aRegions;
res = find_camera_metadata_entry(mDevice->info(),
ANDROID_CONTROL_MAX_REGIONS, &max3aRegions);
if (res != OK) return res;
mParams->set(CameraParameters::KEY_MAX_NUM_FOCUS_AREAS,
max3aRegions.data.i32[0]);
mParams->set(CameraParameters::KEY_FOCUS_AREAS,
"(0,0,0,0,0)");
camera_metadata_entry_t availableFocalLengths;
res = find_camera_metadata_entry(mDevice->info(),
ANDROID_LENS_AVAILABLE_FOCAL_LENGTHS,
&availableFocalLengths);
if (res != OK) return res;
float minFocalLength = availableFocalLengths.data.f[0];
mParams->setFloat(CameraParameters::KEY_FOCAL_LENGTH, minFocalLength);
camera_metadata_entry_t sensorSize;
res = find_camera_metadata_entry(mDevice->info(),
ANDROID_SENSOR_PHYSICAL_SIZE,
&sensorSize);
if (res != OK) return res;
// The fields of view here assume infinity focus, maximum wide angle
float horizFov = 180 / M_PI *
2 * atanf(sensorSize.data.f[0] / (2 * minFocalLength));
float vertFov = 180 / M_PI *
2 * atanf(sensorSize.data.f[1] / (2 * minFocalLength));
mParams->setFloat(CameraParameters::KEY_HORIZONTAL_VIEW_ANGLE, horizFov);
mParams->setFloat(CameraParameters::KEY_VERTICAL_VIEW_ANGLE, vertFov);
mParams->set(CameraParameters::KEY_EXPOSURE_COMPENSATION, 0);
camera_metadata_entry_t exposureCompensationRange;
res = find_camera_metadata_entry(mDevice->info(),
ANDROID_CONTROL_AE_EXP_COMPENSATION_RANGE,
&exposureCompensationRange);
if (res != OK) return res;
mParams->set(CameraParameters::KEY_MAX_EXPOSURE_COMPENSATION,
exposureCompensationRange.data.i32[1]);
mParams->set(CameraParameters::KEY_MIN_EXPOSURE_COMPENSATION,
exposureCompensationRange.data.i32[0]);
camera_metadata_entry_t exposureCompensationStep;
res = find_camera_metadata_entry(mDevice->info(),
ANDROID_CONTROL_AE_EXP_COMPENSATION_STEP,
&exposureCompensationStep);
if (res != OK) return res;
mParams->setFloat(CameraParameters::KEY_EXPOSURE_COMPENSATION_STEP,
exposureCompensationStep.data.r[0].numerator /
exposureCompensationStep.data.r[0].denominator);
mParams->set(CameraParameters::KEY_AUTO_EXPOSURE_LOCK, "false");
mParams->set(CameraParameters::KEY_AUTO_EXPOSURE_LOCK_SUPPORTED, "true");
mParams->set(CameraParameters::KEY_AUTO_WHITEBALANCE_LOCK, "false");
mParams->set(CameraParameters::KEY_AUTO_WHITEBALANCE_LOCK_SUPPORTED, "true");
mParams->set(CameraParameters::KEY_MAX_NUM_METERING_AREAS,
max3aRegions.data.i32[0]);
mParams->set(CameraParameters::KEY_METERING_AREAS,
"(0,0,0,0,0)");
mParams->set(CameraParameters::KEY_ZOOM, 0);
mParams->set(CameraParameters::KEY_MAX_ZOOM, NUM_ZOOM_STEPS - 1);
camera_metadata_entry_t maxDigitalZoom;
res = find_camera_metadata_entry(mDevice->info(),
ANDROID_SCALER_AVAILABLE_MAX_ZOOM, &maxDigitalZoom);
if (res != OK) return res;
{
String8 zoomRatios;
float zoom = 1.f;
float zoomIncrement = (maxDigitalZoom.data.f[0] - zoom) /
(NUM_ZOOM_STEPS-1);
bool addComma = false;
for (size_t i=0; i < NUM_ZOOM_STEPS; i++) {
if (addComma) zoomRatios += ",";
addComma = true;
zoomRatios += String8::format("%d", static_cast<int>(zoom * 100));
zoom += zoomIncrement;
}
mParams->set(CameraParameters::KEY_ZOOM_RATIOS, zoomRatios);
}
mParams->set(CameraParameters::KEY_ZOOM_SUPPORTED, "true");
mParams->set(CameraParameters::KEY_SMOOTH_ZOOM_SUPPORTED, "true");
mParams->set(CameraParameters::KEY_FOCUS_DISTANCES,
"Infinity,Infinity,Infinity");
camera_metadata_entry_t maxFacesDetected;
res = find_camera_metadata_entry(mDevice->info(),
ANDROID_STATS_MAX_FACE_COUNT,
&maxFacesDetected);
mParams->set(CameraParameters::KEY_MAX_NUM_DETECTED_FACES_HW,
maxFacesDetected.data.i32[0]);
mParams->set(CameraParameters::KEY_MAX_NUM_DETECTED_FACES_SW,
0);
mParams->set(CameraParameters::KEY_VIDEO_FRAME_FORMAT,
"yuv420sp");
mParams->set(CameraParameters::KEY_RECORDING_HINT,
"false");
mParams->set(CameraParameters::KEY_VIDEO_SNAPSHOT_SUPPORTED,
"true");
mParams->set(CameraParameters::KEY_VIDEO_STABILIZATION,
"false");
camera_metadata_entry_t availableVideoStabilizationModes;
res = find_camera_metadata_entry(mDevice->info(),
ANDROID_CONTROL_AVAILABLE_VIDEO_STABILIZATION_MODES,
&availableVideoStabilizationModes);
if (res != OK) return res;
if (availableVideoStabilizationModes.count > 1) {
mParams->set(CameraParameters::KEY_VIDEO_STABILIZATION_SUPPORTED,
"true");
} else {
mParams->set(CameraParameters::KEY_VIDEO_STABILIZATION_SUPPORTED,
"false");
}
return OK;
}
status_t Camera2Client::updatePreviewRequest() {
ATRACE_CALL();
status_t res;
if (mPreviewRequest == NULL) {
res = mDevice->createDefaultRequest(CAMERA2_TEMPLATE_PREVIEW,
&mPreviewRequest);
if (res != OK) {
ALOGE("%s: Camera %d: Unable to create default preview request: "
"%s (%d)", __FUNCTION__, mCameraId, strerror(-res), res);
return res;
}
}
// TODO: Adjust for mParams changes
return OK;
}
} // namespace android