1 /* 2 * Copyright (C) 2014 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.camera.one.v2; 18 19 import android.graphics.PointF; 20 import android.graphics.Rect; 21 import android.hardware.camera2.CameraCharacteristics; 22 import android.hardware.camera2.CaptureResult; 23 import android.hardware.camera2.params.MeteringRectangle; 24 25 import com.android.camera.debug.Log; 26 import com.android.camera.one.OneCamera; 27 import com.android.camera.one.Settings3A; 28 import com.android.camera.util.CameraUtil; 29 30 /** 31 * Helper class to implement auto focus and 3A in camera2-based 32 * {@link com.android.camera.one.OneCamera} implementations. 33 */ 34 @Deprecated 35 public class AutoFocusHelper { 36 private static final Log.Tag TAG = new Log.Tag("OneCameraAFHelp"); 37 38 /** camera2 API metering region weight. */ 39 private static final int CAMERA2_REGION_WEIGHT = (int) 40 (CameraUtil.lerp(MeteringRectangle.METERING_WEIGHT_MIN, MeteringRectangle.METERING_WEIGHT_MAX, 41 Settings3A.getGcamMeteringRegionFraction())); 42 43 /** Zero weight 3A region, to reset regions per API. */ 44 private static final MeteringRectangle[] ZERO_WEIGHT_3A_REGION = new MeteringRectangle[]{ 45 new MeteringRectangle(0, 0, 0, 0, 0) 46 }; 47 getZeroWeightRegion()48 public static MeteringRectangle[] getZeroWeightRegion() { 49 return ZERO_WEIGHT_3A_REGION; 50 } 51 52 /** 53 * Convert reported camera2 AF state to OneCamera AutoFocusState. 54 */ stateFromCamera2State(int state)55 public static OneCamera.AutoFocusState stateFromCamera2State(int state) { 56 switch (state) { 57 case CaptureResult.CONTROL_AF_STATE_ACTIVE_SCAN: 58 return OneCamera.AutoFocusState.ACTIVE_SCAN; 59 case CaptureResult.CONTROL_AF_STATE_PASSIVE_SCAN: 60 return OneCamera.AutoFocusState.PASSIVE_SCAN; 61 case CaptureResult.CONTROL_AF_STATE_PASSIVE_FOCUSED: 62 return OneCamera.AutoFocusState.PASSIVE_FOCUSED; 63 case CaptureResult.CONTROL_AF_STATE_FOCUSED_LOCKED: 64 return OneCamera.AutoFocusState.ACTIVE_FOCUSED; 65 case CaptureResult.CONTROL_AF_STATE_PASSIVE_UNFOCUSED: 66 return OneCamera.AutoFocusState.PASSIVE_UNFOCUSED; 67 case CaptureResult.CONTROL_AF_STATE_NOT_FOCUSED_LOCKED: 68 return OneCamera.AutoFocusState.ACTIVE_UNFOCUSED; 69 default: 70 return OneCamera.AutoFocusState.INACTIVE; 71 } 72 } 73 74 /** 75 * Complain if CONTROL_AF_STATE is not present in result. 76 * Could indicate bug in API implementation. 77 */ checkControlAfState(CaptureResult result)78 public static boolean checkControlAfState(CaptureResult result) { 79 boolean missing = result.get(CaptureResult.CONTROL_AF_STATE) == null; 80 if (missing) { 81 // throw new IllegalStateException("CaptureResult missing CONTROL_AF_STATE."); 82 Log.e(TAG, "\n!!!! TotalCaptureResult missing CONTROL_AF_STATE. !!!!\n "); 83 } 84 return !missing; 85 } 86 87 /** 88 * Complain if LENS_STATE is not present in result. 89 * Could indicate bug in API implementation. 90 */ checkLensState(CaptureResult result)91 public static boolean checkLensState(CaptureResult result) { 92 boolean missing = result.get(CaptureResult.LENS_STATE) == null; 93 if (missing) { 94 // throw new IllegalStateException("CaptureResult missing LENS_STATE."); 95 Log.e(TAG, "\n!!!! TotalCaptureResult missing LENS_STATE. !!!!\n "); 96 } 97 return !missing; 98 } 99 100 logExtraFocusInfo(CaptureResult result)101 public static void logExtraFocusInfo(CaptureResult result) { 102 if(!checkControlAfState(result) || !checkLensState(result)) { 103 return; 104 } 105 106 Object tag = result.getRequest().getTag(); 107 108 Log.v(TAG, String.format("af_state:%-17s lens_foc_dist:%.3f lens_state:%-10s %s", 109 controlAFStateToString(result.get(CaptureResult.CONTROL_AF_STATE)), 110 result.get(CaptureResult.LENS_FOCUS_DISTANCE), 111 lensStateToString(result.get(CaptureResult.LENS_STATE)), 112 (tag == null) ? "" : "[" + tag +"]" 113 )); 114 } 115 116 /** Compute 3A regions for a sensor-referenced touch coordinate. 117 * Returns a MeteringRectangle[] with length 1. 118 * 119 * @param nx x coordinate of the touch point, in normalized portrait coordinates. 120 * @param ny y coordinate of the touch point, in normalized portrait coordinates. 121 * @param fraction Fraction in [0,1]. Multiplied by min(cropRegion.width(), cropRegion.height()) 122 * to determine the side length of the square MeteringRectangle. 123 * @param cropRegion Crop region of the image. 124 * @param sensorOrientation sensor orientation as defined by 125 * CameraCharacteristics.get(CameraCharacteristics.SENSOR_ORIENTATION). 126 */ regionsForNormalizedCoord(float nx, float ny, float fraction, final Rect cropRegion, int sensorOrientation)127 private static MeteringRectangle[] regionsForNormalizedCoord(float nx, float ny, 128 float fraction, final Rect cropRegion, int sensorOrientation) { 129 // Compute half side length in pixels. 130 int minCropEdge = Math.min(cropRegion.width(), cropRegion.height()); 131 int halfSideLength = (int) (0.5f * fraction * minCropEdge); 132 133 // Compute the output MeteringRectangle in sensor space. 134 // nx, ny is normalized to the screen. 135 // Crop region itself is specified in sensor coordinates. 136 137 // Normalized coordinates, now rotated into sensor space. 138 PointF nsc = CameraUtil.normalizedSensorCoordsForNormalizedDisplayCoords( 139 nx, ny, sensorOrientation); 140 141 int xCenterSensor = (int)(cropRegion.left + nsc.x * cropRegion.width()); 142 int yCenterSensor = (int)(cropRegion.top + nsc.y * cropRegion.height()); 143 144 Rect meteringRegion = new Rect(xCenterSensor - halfSideLength, 145 yCenterSensor - halfSideLength, 146 xCenterSensor + halfSideLength, 147 yCenterSensor + halfSideLength); 148 149 // Clamp meteringRegion to cropRegion. 150 meteringRegion.left = CameraUtil.clamp(meteringRegion.left, cropRegion.left, cropRegion.right); 151 meteringRegion.top = CameraUtil.clamp(meteringRegion.top, cropRegion.top, cropRegion.bottom); 152 meteringRegion.right = CameraUtil.clamp(meteringRegion.right, cropRegion.left, cropRegion.right); 153 meteringRegion.bottom = CameraUtil.clamp(meteringRegion.bottom, cropRegion.top, cropRegion.bottom); 154 155 return new MeteringRectangle[]{new MeteringRectangle(meteringRegion, CAMERA2_REGION_WEIGHT)}; 156 } 157 158 /** 159 * Return AF region(s) for a sensor-referenced touch coordinate. 160 * 161 * <p> 162 * Normalized coordinates are referenced to portrait preview window with 163 * (0, 0) top left and (1, 1) bottom right. Rotation has no effect. 164 * </p> 165 * 166 * @return AF region(s). 167 */ afRegionsForNormalizedCoord(float nx, float ny, final Rect cropRegion, int sensorOrientation)168 public static MeteringRectangle[] afRegionsForNormalizedCoord(float nx, 169 float ny, final Rect cropRegion, int sensorOrientation) { 170 return regionsForNormalizedCoord(nx, ny, Settings3A.getAutoFocusRegionWidth(), 171 cropRegion, sensorOrientation); 172 } 173 174 /** 175 * Return AE region(s) for a sensor-referenced touch coordinate. 176 * 177 * <p> 178 * Normalized coordinates are referenced to portrait preview window with 179 * (0, 0) top left and (1, 1) bottom right. Rotation has no effect. 180 * </p> 181 * 182 * @return AE region(s). 183 */ aeRegionsForNormalizedCoord(float nx, float ny, final Rect cropRegion, int sensorOrientation)184 public static MeteringRectangle[] aeRegionsForNormalizedCoord(float nx, 185 float ny, final Rect cropRegion, int sensorOrientation) { 186 return regionsForNormalizedCoord(nx, ny, Settings3A.getMeteringRegionWidth(), 187 cropRegion, sensorOrientation); 188 } 189 190 /** 191 * [Gcam mode only]: Return AE region(s) for a sensor-referenced touch coordinate. 192 * 193 * <p> 194 * Normalized coordinates are referenced to portrait preview window with 195 * (0, 0) top left and (1, 1) bottom right. Rotation has no effect. 196 * </p> 197 * 198 * @return AE region(s). 199 */ gcamAERegionsForNormalizedCoord(float nx, float ny, final Rect cropRegion, int sensorOrientation)200 public static MeteringRectangle[] gcamAERegionsForNormalizedCoord(float nx, 201 float ny, final Rect cropRegion, int sensorOrientation) { 202 return regionsForNormalizedCoord(nx, ny, Settings3A.getGcamMeteringRegionFraction(), 203 cropRegion, sensorOrientation); 204 } 205 206 /** 207 * Calculates sensor crop region for a zoom level (zoom >= 1.0). 208 * 209 * @return Crop region. 210 */ cropRegionForZoom(CameraCharacteristics characteristics, float zoom)211 public static Rect cropRegionForZoom(CameraCharacteristics characteristics, float zoom) { 212 Rect sensor = characteristics.get(CameraCharacteristics.SENSOR_INFO_ACTIVE_ARRAY_SIZE); 213 int xCenter = sensor.width() / 2; 214 int yCenter = sensor.height() / 2; 215 int xDelta = (int) (0.5f * sensor.width() / zoom); 216 int yDelta = (int) (0.5f * sensor.height() / zoom); 217 return new Rect(xCenter - xDelta, yCenter - yDelta, xCenter + xDelta, yCenter + yDelta); 218 } 219 220 /** 221 * Utility function: converts CaptureResult.CONTROL_AF_STATE to String. 222 */ controlAFStateToString(int controlAFState)223 private static String controlAFStateToString(int controlAFState) { 224 switch (controlAFState) { 225 case CaptureResult.CONTROL_AF_STATE_INACTIVE: 226 return "inactive"; 227 case CaptureResult.CONTROL_AF_STATE_PASSIVE_SCAN: 228 return "passive_scan"; 229 case CaptureResult.CONTROL_AF_STATE_PASSIVE_FOCUSED: 230 return "passive_focused"; 231 case CaptureResult.CONTROL_AF_STATE_ACTIVE_SCAN: 232 return "active_scan"; 233 case CaptureResult.CONTROL_AF_STATE_FOCUSED_LOCKED: 234 return "focus_locked"; 235 case CaptureResult.CONTROL_AF_STATE_NOT_FOCUSED_LOCKED: 236 return "not_focus_locked"; 237 case CaptureResult.CONTROL_AF_STATE_PASSIVE_UNFOCUSED: 238 return "passive_unfocused"; 239 default: 240 return "unknown"; 241 } 242 } 243 244 /** 245 * Utility function: converts CaptureResult.LENS_STATE to String. 246 */ lensStateToString(int lensState)247 private static String lensStateToString(int lensState) { 248 switch (lensState) { 249 case CaptureResult.LENS_STATE_MOVING: 250 return "moving"; 251 case CaptureResult.LENS_STATE_STATIONARY: 252 return "stationary"; 253 default: 254 return "unknown"; 255 } 256 } 257 258 } 259