Merge branch 'lmp-dev' of sso://googleplex-android.git.corp.google.com/platform/frameworks/base into lmp-dev

This commit is contained in:
Geoff Mendal
2014-08-11 13:31:17 -07:00
5 changed files with 181 additions and 18 deletions

View File

@@ -48,9 +48,16 @@ public class LegacyFaceDetectMapper {
private static final boolean VERBOSE = Log.isLoggable(TAG, Log.VERBOSE);
private final Camera mCamera;
/** Is the camera capable of face detection? */
private final boolean mFaceDetectSupported;
/** Is the camera is running face detection? */
private boolean mFaceDetectEnabled = false;
/** Did the last request say to use SCENE_MODE = FACE_PRIORITY? */
private boolean mFaceDetectScenePriority = false;
/** Did the last request enable the face detect mode to ON? */
private boolean mFaceDetectReporting = false;
/** Synchronize access to all fields */
private final Object mLock = new Object();
private Camera.Face[] mFaces;
private Camera.Face[] mFacesPrev;
@@ -129,6 +136,17 @@ public class LegacyFaceDetectMapper {
return;
}
/*
* control.sceneMode
*/
int sceneMode = ParamsUtils.getOrDefault(captureRequest, CONTROL_SCENE_MODE,
CONTROL_SCENE_MODE_DISABLED);
if (sceneMode == CONTROL_SCENE_MODE_FACE_PRIORITY && !mFaceDetectSupported) {
Log.w(TAG, "processFaceDetectMode - ignoring control.sceneMode == FACE_PRIORITY; " +
"face detection is not available");
return;
}
// Print some warnings out in case the values were wrong
switch (fdMode) {
case STATISTICS_FACE_DETECT_MODE_OFF:
@@ -145,7 +163,8 @@ public class LegacyFaceDetectMapper {
return;
}
boolean enableFaceDetect = fdMode != STATISTICS_FACE_DETECT_MODE_OFF;
boolean enableFaceDetect = (fdMode != STATISTICS_FACE_DETECT_MODE_OFF)
|| (sceneMode == CONTROL_SCENE_MODE_FACE_PRIORITY);
synchronized (mLock) {
// Enable/disable face detection if it's changed since last time
if (enableFaceDetect != mFaceDetectEnabled) {
@@ -166,6 +185,8 @@ public class LegacyFaceDetectMapper {
}
mFaceDetectEnabled = enableFaceDetect;
mFaceDetectScenePriority = sceneMode == CONTROL_SCENE_MODE_FACE_PRIORITY;
mFaceDetectReporting = fdMode != STATISTICS_FACE_DETECT_MODE_OFF;
}
}
}
@@ -177,6 +198,10 @@ public class LegacyFaceDetectMapper {
* <p>Face detect callbacks are processed in the background, and each call to
* {@link #mapResultFaces} will have the latest faces as reflected by the camera1 callbacks.</p>
*
* <p>If the scene mode was set to {@code FACE_PRIORITY} but face detection is disabled,
* the camera will still run face detection in the background, but no faces will be reported
* in the capture result.</p>
*
* @param result a non-{@code null} result
* @param legacyRequest a non-{@code null} request (read-only)
*/
@@ -186,16 +211,19 @@ public class LegacyFaceDetectMapper {
Camera.Face[] faces, previousFaces;
int fdMode;
boolean fdScenePriority;
synchronized (mLock) {
fdMode = mFaceDetectEnabled ?
fdMode = mFaceDetectReporting ?
STATISTICS_FACE_DETECT_MODE_SIMPLE : STATISTICS_FACE_DETECT_MODE_OFF;
if (mFaceDetectEnabled) {
if (mFaceDetectReporting) {
faces = mFaces;
} else {
faces = null;
}
fdScenePriority = mFaceDetectScenePriority;
previousFaces = mFacesPrev;
mFacesPrev = faces;
}
@@ -227,5 +255,10 @@ public class LegacyFaceDetectMapper {
result.set(CaptureResult.STATISTICS_FACES, convertedFaces.toArray(new Face[0]));
result.set(CaptureResult.STATISTICS_FACE_DETECT_MODE, fdMode);
// Override scene mode with FACE_PRIORITY if the request was using FACE_PRIORITY
if (fdScenePriority) {
result.set(CaptureResult.CONTROL_SCENE_MODE, CONTROL_SCENE_MODE_FACE_PRIORITY);
}
}
}

View File

@@ -36,6 +36,7 @@ import android.hardware.camera2.utils.ParamsUtils;
import android.util.Log;
import android.util.Range;
import android.util.Size;
import android.util.SizeF;
import java.util.ArrayList;
import java.util.Arrays;
@@ -187,10 +188,6 @@ public class LegacyMetadataMapper {
*/
mapFlash(m, p);
/*
* request.*
*/
mapRequest(m, p);
// TODO: map other fields
/*
@@ -223,6 +220,13 @@ public class LegacyMetadataMapper {
*/
mapScalerStreamConfigs(m, p);
// Order matters below: Put this last so that we can read the metadata set previously
/*
* request.*
*/
mapRequest(m, p);
}
private static void mapScalerStreamConfigs(CameraMetadataNative m, Camera.Parameters p) {
@@ -535,9 +539,16 @@ public class LegacyMetadataMapper {
* android.control.availableSceneModes
*/
List<String> sceneModes = p.getSupportedSceneModes();
int[] supportedSceneModes = (sceneModes == null) ? new int[0] :
ArrayUtils.convertStringListToIntArray(sceneModes, sLegacySceneModes, sSceneModes);
m.set(CONTROL_AVAILABLE_SCENE_MODES, supportedSceneModes);
List<Integer> supportedSceneModes =
ArrayUtils.convertStringListToIntList(sceneModes, sLegacySceneModes, sSceneModes);
if (supportedSceneModes == null) { // camera1 doesn't support scene mode settings
supportedSceneModes = new ArrayList<Integer>();
supportedSceneModes.add(CONTROL_SCENE_MODE_DISABLED); // disabled is always available
}
if (p.getMaxNumDetectedFaces() > 0) { // always supports FACE_PRIORITY when face detecting
supportedSceneModes.add(CONTROL_SCENE_MODE_FACE_PRIORITY);
}
m.set(CONTROL_AVAILABLE_SCENE_MODES, ArrayUtils.toIntArray(supportedSceneModes));
}
private static void mapLens(CameraMetadataNative m, Camera.Parameters p) {
@@ -545,11 +556,23 @@ public class LegacyMetadataMapper {
* We can tell if the lens is fixed focus;
* but if it's not, we can't tell the minimum focus distance, so leave it null then.
*/
if (p.getFocusMode() == Camera.Parameters.FOCUS_MODE_FIXED) {
if (VERBOSE) {
Log.v(TAG, "mapLens - focus-mode='" + p.getFocusMode() + "'");
}
if (Camera.Parameters.FOCUS_MODE_FIXED.equals(p.getFocusMode())) {
/*
* lens.info.minimumFocusDistance
*/
m.set(LENS_INFO_MINIMUM_FOCUS_DISTANCE, LENS_INFO_MINIMUM_FOCUS_DISTANCE_FIXED_FOCUS);
if (VERBOSE) {
Log.v(TAG, "mapLens - lens.info.minimumFocusDistance = 0");
}
} else {
if (VERBOSE) {
Log.v(TAG, "mapLens - lens.info.minimumFocusDistance is unknown");
}
}
float[] focalLengths = new float[] { p.getFocalLength() };
@@ -620,7 +643,17 @@ public class LegacyMetadataMapper {
CameraCharacteristics.STATISTICS_INFO_MAX_FACE_COUNT ,
CameraCharacteristics.SYNC_MAX_LATENCY ,
};
m.set(REQUEST_AVAILABLE_CHARACTERISTICS_KEYS, getTagsForKeys(availableKeys));
List<Key<?>> characteristicsKeys = new ArrayList<>(Arrays.asList(availableKeys));
/*
* Add the conditional keys
*/
if (m.get(LENS_INFO_MINIMUM_FOCUS_DISTANCE) != null) {
characteristicsKeys.add(LENS_INFO_MINIMUM_FOCUS_DISTANCE);
}
m.set(REQUEST_AVAILABLE_CHARACTERISTICS_KEYS,
getTagsForKeys(characteristicsKeys.toArray(new Key<?>[0])));
}
/*
@@ -757,6 +790,23 @@ public class LegacyMetadataMapper {
* sensor.info.pixelArraySize
*/
m.set(SENSOR_INFO_PIXEL_ARRAY_SIZE, largestJpegSize);
/*
* sensor.info.physicalSize
*/
{
/*
* Assume focal length is at infinity focus and that the lens is rectilinear.
*/
float focalLength = p.getFocalLength(); // in mm
double angleHor = p.getHorizontalViewAngle() * Math.PI / 180; // to radians
double angleVer = p.getVerticalViewAngle() * Math.PI / 180; // to radians
float height = (float)Math.abs(2 * focalLength * Math.tan(angleVer / 2));
float width = (float)Math.abs(2 * focalLength * Math.tan(angleHor / 2));
m.set(SENSOR_INFO_PHYSICAL_SIZE, new SizeF(width, height)); // in mm
}
}
private static void mapStatistics(CameraMetadataNative m, Parameters p) {
@@ -850,6 +900,11 @@ public class LegacyMetadataMapper {
}
static String convertSceneModeToLegacy(int mode) {
if (mode == CONTROL_SCENE_MODE_FACE_PRIORITY) {
// OK: Let LegacyFaceDetectMapper handle turning face detection on/off
return Parameters.SCENE_MODE_AUTO;
}
int index = ArrayUtils.getArrayIndex(sSceneModes, mode);
if (index < 0) {
return null;
@@ -1057,7 +1112,24 @@ public class LegacyMetadataMapper {
}
// control.captureIntent
m.set(CaptureRequest.CONTROL_CAPTURE_INTENT, templateId);
{
int captureIntent;
switch (templateId) {
case CameraDevice.TEMPLATE_PREVIEW:
captureIntent = CONTROL_CAPTURE_INTENT_PREVIEW;
break;
case CameraDevice.TEMPLATE_STILL_CAPTURE:
captureIntent = CONTROL_CAPTURE_INTENT_STILL_CAPTURE;
break;
case CameraDevice.TEMPLATE_RECORD:
captureIntent = CONTROL_CAPTURE_INTENT_VIDEO_RECORD;
break;
default:
// Can't get anything else since it's guarded by the IAE check
throw new AssertionError("Impossible; keep in sync with sAllowedTemplates");
}
m.set(CaptureRequest.CONTROL_CAPTURE_INTENT, captureIntent);
}
// control.aeMode
m.set(CaptureRequest.CONTROL_AE_MODE, CameraMetadata.CONTROL_AE_MODE_ON);
@@ -1094,6 +1166,11 @@ public class LegacyMetadataMapper {
}
}
if (VERBOSE) {
Log.v(TAG, "createRequestTemplate (templateId=" + templateId + ")," +
" afMode=" + afMode + ", minimumFocusDistance=" + minimumFocusDistance);
}
m.set(CaptureRequest.CONTROL_AF_MODE, afMode);
}

View File

@@ -246,6 +246,19 @@ public class LegacyRequestMapper {
// TODO: Don't add control.awbLock to availableRequestKeys if it's not supported
}
// control.captureIntent
{
int captureIntent = ParamsUtils.getOrDefault(request,
CONTROL_CAPTURE_INTENT,
/*defaultValue*/CONTROL_CAPTURE_INTENT_PREVIEW);
captureIntent = filterSupportedCaptureIntent(captureIntent);
params.setRecordingHint(
captureIntent == CONTROL_CAPTURE_INTENT_VIDEO_RECORD ||
captureIntent == CONTROL_CAPTURE_INTENT_VIDEO_SNAPSHOT);
}
// control.videoStabilizationMode
{
Integer stabMode = getIfSupported(request, CONTROL_VIDEO_STABILIZATION_MODE,
@@ -284,7 +297,7 @@ public class LegacyRequestMapper {
switch (controlMode) {
case CONTROL_MODE_USE_SCENE_MODE: {
int sceneMode = ParamsUtils.getOrDefault(request, CONTROL_SCENE_MODE,
/*defaultValue*/CONTROL_SCENE_MODE_DISABLED);
/*defaultValue*/CONTROL_SCENE_MODE_DISABLED);
String legacySceneMode = LegacyMetadataMapper.
convertSceneModeToLegacy(sceneMode);
if (legacySceneMode != null) {
@@ -339,6 +352,28 @@ public class LegacyRequestMapper {
}
}
static int filterSupportedCaptureIntent(int captureIntent) {
switch (captureIntent) {
case CONTROL_CAPTURE_INTENT_CUSTOM:
case CONTROL_CAPTURE_INTENT_PREVIEW:
case CONTROL_CAPTURE_INTENT_STILL_CAPTURE:
case CONTROL_CAPTURE_INTENT_VIDEO_RECORD:
case CONTROL_CAPTURE_INTENT_VIDEO_SNAPSHOT:
break;
case CONTROL_CAPTURE_INTENT_ZERO_SHUTTER_LAG:
case CONTROL_CAPTURE_INTENT_MANUAL:
captureIntent = CONTROL_CAPTURE_INTENT_PREVIEW;
Log.w(TAG, "Unsupported control.captureIntent value " + captureIntent
+ "; default to PREVIEW");
default:
captureIntent = CONTROL_CAPTURE_INTENT_PREVIEW;
Log.w(TAG, "Unknown control.captureIntent value " + captureIntent
+ "; default to PREVIEW");
}
return captureIntent;
}
private static List<Camera.Area> convertMeteringRegionsToLegacy(
Rect activeArray, ParameterUtils.ZoomData zoomData,
MeteringRectangle[] meteringRegions, int maxNumMeteringAreas, String regionName) {

View File

@@ -35,9 +35,6 @@ import java.util.ArrayList;
import java.util.List;
import static com.android.internal.util.Preconditions.*;
import static android.hardware.camera2.CameraMetadata.CONTROL_VIDEO_STABILIZATION_MODE_OFF;
import static android.hardware.camera2.CameraMetadata.CONTROL_VIDEO_STABILIZATION_MODE_ON;
import static android.hardware.camera2.CaptureRequest.CONTROL_VIDEO_STABILIZATION_MODE;
import static android.hardware.camera2.CaptureResult.*;
/**
@@ -145,6 +142,19 @@ public class LegacyResultMapper {
*/
mapAwb(result, /*out*/params);
/*
* control.captureIntent
*/
{
int captureIntent = ParamsUtils.getOrDefault(request,
CaptureRequest.CONTROL_CAPTURE_INTENT,
/*defaultValue*/CaptureRequest.CONTROL_CAPTURE_INTENT_PREVIEW);
captureIntent = LegacyRequestMapper.filterSupportedCaptureIntent(captureIntent);
result.set(CONTROL_CAPTURE_INTENT, captureIntent);
}
/*
* control.mode
*/
@@ -166,6 +176,8 @@ public class LegacyResultMapper {
int mode = LegacyMetadataMapper.convertSceneModeFromLegacy(legacySceneMode);
if (mode != LegacyMetadataMapper.UNKNOWN_MODE) {
result.set(CaptureResult.CONTROL_SCENE_MODE, mode);
// In case of SCENE_MODE == FACE_PRIORITY, LegacyFaceDetectMapper will override
// the result to say SCENE_MODE == FACE_PRIORITY.
} else {
Log.w(TAG, "Unknown scene mode " + legacySceneMode +
" returned by camera HAL, setting to disabled.");

View File

@@ -725,9 +725,15 @@ public class RequestThreadManager {
CameraMetadataNative result = mMapper.cachedConvertResultMetadata(
mLastRequest, timestampMutable.value);
/*
* Order matters: The default result mapper is state-less; the
* other mappers carry state and may override keys set by the default
* mapper with their own values.
*/
// Update AF state
mFocusStateMapper.mapResultTriggers(result);
// Update detected faces list
// Update face-related results
mFaceDetectMapper.mapResultFaces(result, mLastRequest);
mDeviceState.setCaptureResult(holder, result);