aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--apps/CameraITS/pymodules/its/device.py21
-rw-r--r--apps/CameraITS/pymodules/its/objects.py42
-rw-r--r--apps/CameraITS/service/Android.mk2
-rw-r--r--apps/CameraITS/service/src/com/android/camera2/its/ItsService.java76
-rw-r--r--apps/CameraITS/service/src/com/android/camera2/its/ItsUtils.java6
-rwxr-xr-xapps/CameraITS/tests/regress.sh27
-rw-r--r--apps/CameraITS/tests/test_3a.py10
-rw-r--r--apps/CameraITS/tests/test_3a_remote.py24
-rw-r--r--apps/CameraITS/tests/test_black_level.py20
-rw-r--r--apps/CameraITS/tests/test_black_white.py15
-rw-r--r--apps/CameraITS/tests/test_capture_result.py61
-rw-r--r--apps/CameraITS/tests/test_exposure.py11
-rw-r--r--apps/CameraITS/tests/test_formats.py4
-rw-r--r--apps/CameraITS/tests/test_jpeg.py12
-rw-r--r--apps/CameraITS/tests/test_latching.py52
-rw-r--r--apps/CameraITS/tests/test_param_exposure_time.py2
-rw-r--r--apps/CameraITS/tests/test_param_exposure_time_burst.py43
-rw-r--r--apps/CameraITS/tests/test_param_flash_mode.py25
-rw-r--r--apps/CameraITS/tests/test_param_noise_reduction.py10
-rw-r--r--apps/CameraITS/tests/test_param_sensitivity.py2
-rw-r--r--apps/CameraITS/tests/test_param_sensitivity_burst.py43
-rw-r--r--apps/CameraITS/tests/test_param_tonemap_mode.py15
-rw-r--r--apps/CameraITS/tests/test_predicted_wb.py107
-rw-r--r--apps/TestingCamera/src/com/android/testingcamera/TestingCamera.java8
-rw-r--r--apps/TestingCamera2/Android.mk2
-rw-r--r--apps/TestingCamera2/AndroidManifest.xml4
-rw-r--r--apps/TestingCamera2/src/com/android/testingcamera2/CameraOps.java112
-rw-r--r--apps/TestingCamera2/src/com/android/testingcamera2/TestingCamera2.java117
28 files changed, 596 insertions, 277 deletions
diff --git a/apps/CameraITS/pymodules/its/device.py b/apps/CameraITS/pymodules/its/device.py
index c15f302..f773451 100644
--- a/apps/CameraITS/pymodules/its/device.py
+++ b/apps/CameraITS/pymodules/its/device.py
@@ -48,6 +48,10 @@ class ItsSession(object):
# to adb, which causes it to fail if there is more than one device.
ADB = "adb -d"
+ # Set to True to take a pre-shot before capture and throw it away (for
+ # debug purposes).
+ CAPTURE_THROWAWAY_SHOTS = False
+
DEVICE_FOLDER_ROOT = '/sdcard/its'
DEVICE_FOLDER_CAPTURE = 'captures'
INTENT_CAPTURE = 'com.android.camera2.its.CAPTURE'
@@ -344,7 +348,7 @@ class ItsSession(object):
local_fname = os.path.basename(remote_fname)
return self.__parse_captured_json([local_fname])[0]['cameraProperties']
- def do_3a(self, region_ae, region_af, region_awb,
+ def do_3a(self, region_ae, region_awb, region_af,
do_ae=True, do_awb=True, do_af=True):
"""Perform a 3A operation on the device.
@@ -355,8 +359,8 @@ class ItsSession(object):
Args:
region_ae: Normalized rect. (x,y,w,h) specifying the AE region.
- region_af: Normalized rect. (x,y,w,h) specifying the AF region.
region_awb: Normalized rect. (x,y,w,h) specifying the AWB region.
+ region_af: Normalized rect. (x,y,w,h) specifying the AF region.
Returns:
Five values:
@@ -456,14 +460,11 @@ class ItsSession(object):
burst capture) containing the metadata of the captured image(s).
"""
if request.has_key("captureRequest"):
-
- print "Capturing image (including a pre-shot for settings synch)"
-
- # HACK: Take a pre-shot, to make sure the settings stick.
- # TODO: Remove this code once it is no longer needed.
- self.__start_capture(request)
- self.__wait_for_capture_done_single()
-
+ if self.CAPTURE_THROWAWAY_SHOTS:
+ print "Capturing throw-away image"
+ self.__start_capture(request)
+ self.__wait_for_capture_done_single()
+ print "Capturing image"
self.__start_capture(request)
remote_fname, w, h = self.__wait_for_capture_done_single()
local_fname = self.__copy_captured_files([remote_fname])[0]
diff --git a/apps/CameraITS/pymodules/its/objects.py b/apps/CameraITS/pymodules/its/objects.py
index f50b9d2..9183bc8 100644
--- a/apps/CameraITS/pymodules/its/objects.py
+++ b/apps/CameraITS/pymodules/its/objects.py
@@ -59,6 +59,48 @@ def capture_request_list(obj_list):
"""
return {"captureRequestList": obj_list}
+def manual_capture_request(sensitivity, exp_time_ms):
+ """Return a capture request with everything set to manual.
+
+ Uses identity/unit color correction, and the default tonemap curve.
+
+ Args:
+ sensitivity: The sensitivity value to populate the request with.
+ exp_time_ms: The exposure time, in milliseconds, to populate the
+ request with.
+
+ Returns:
+ The default manual capture request, ready to be passed to the
+ its.device.do_capture function.
+ """
+ return capture_request( {
+ "android.control.mode": 0,
+ "android.control.aeMode": 0,
+ "android.control.awbMode": 0,
+ "android.control.afMode": 0,
+ "android.control.effectMode": 0,
+ "android.sensor.frameDuration": 0,
+ "android.sensor.sensitivity": sensitivity,
+ "android.sensor.exposureTime": exp_time_ms*1000*1000,
+ "android.colorCorrection.mode": 0,
+ "android.colorCorrection.transform":
+ int_to_rational([1,0,0, 0,1,0, 0,0,1]),
+ "android.colorCorrection.gains": [1,1,1,1],
+ "android.tonemap.mode": 1,
+ })
+
+def auto_capture_request():
+ """Return a capture request with everything set to auto.
+ """
+ return capture_request( {
+ "android.control.mode": 1,
+ "android.control.aeMode": 1,
+ "android.control.awbMode": 1,
+ "android.control.afMode": 1,
+ "android.colorCorrection.mode": 1,
+ "android.tonemap.mode": 1,
+ })
+
class __UnitTest(unittest.TestCase):
"""Run a suite of unit tests on this module.
"""
diff --git a/apps/CameraITS/service/Android.mk b/apps/CameraITS/service/Android.mk
index 56b0233..5bb67a1 100644
--- a/apps/CameraITS/service/Android.mk
+++ b/apps/CameraITS/service/Android.mk
@@ -22,6 +22,8 @@ LOCAL_MODULE_TAGS := optional
LOCAL_SDK_VERSION := current
+LOCAL_STATIC_JAVA_LIBRARIES := android-ex-camera2
+
LOCAL_SRC_FILES := \
$(call all-java-files-under, src)
diff --git a/apps/CameraITS/service/src/com/android/camera2/its/ItsService.java b/apps/CameraITS/service/src/com/android/camera2/its/ItsService.java
index e522202..f3a7ac5 100644
--- a/apps/CameraITS/service/src/com/android/camera2/its/ItsService.java
+++ b/apps/CameraITS/service/src/com/android/camera2/its/ItsService.java
@@ -21,9 +21,10 @@ import android.content.Context;
import android.content.Intent;
import android.graphics.ImageFormat;
import android.hardware.camera2.CameraAccessException;
+import android.hardware.camera2.CameraCharacteristics;
import android.hardware.camera2.CameraDevice;
import android.hardware.camera2.CameraManager;
-import android.hardware.camera2.CameraProperties;
+import android.hardware.camera2.CaptureFailure;
import android.hardware.camera2.CaptureRequest;
import android.hardware.camera2.CaptureResult;
import android.hardware.camera2.Rational;
@@ -38,6 +39,10 @@ import android.os.Message;
import android.util.Log;
import android.view.Surface;
+import com.android.ex.camera2.blocking.BlockingCameraManager;
+import com.android.ex.camera2.blocking.BlockingCameraManager.BlockingOpenException;
+import com.android.ex.camera2.blocking.BlockingStateListener;
+
import org.json.JSONObject;
import java.io.File;
@@ -64,6 +69,10 @@ public class ItsService extends Service {
public static final int TIMEOUT_CAPTURE = 10;
public static final int TIMEOUT_3A = 10;
+ // State transition timeouts, in ms.
+ private static final long TIMEOUT_IDLE_MS = 2000;
+ private static final long TIMEOUT_STATE_MS = 500;
+
private static final int MAX_CONCURRENT_READER_BUFFERS = 8;
public static final String REGION_KEY = "regions";
@@ -75,9 +84,12 @@ public class ItsService extends Service {
public static final String TRIGGER_AF_KEY = "af";
private CameraManager mCameraManager = null;
+ private HandlerThread mCameraThread = null;
+ private BlockingCameraManager mBlockingCameraManager = null;
+ private BlockingStateListener mCameraListener = null;
private CameraDevice mCamera = null;
private ImageReader mCaptureReader = null;
- private CameraProperties mCameraProperties = null;
+ private CameraCharacteristics mCameraCharacteristics = null;
private HandlerThread mCommandThread;
private Handler mCommandHandler;
@@ -114,6 +126,8 @@ public class ItsService extends Service {
if (mCameraManager == null) {
throw new ItsException("Failed to connect to camera manager");
}
+ mBlockingCameraManager = new BlockingCameraManager(mCameraManager);
+ mCameraListener = new BlockingStateListener();
// Open the camera device, and get its properties.
String[] devices;
@@ -122,12 +136,23 @@ public class ItsService extends Service {
if (devices == null || devices.length == 0) {
throw new ItsException("No camera devices");
}
+ } catch (CameraAccessException e) {
+ throw new ItsException("Failed to get device ID list", e);
+ }
+
+ mCameraThread = new HandlerThread("ItsCameraThread");
+ try {
+ mCameraThread.start();
+ Handler cameraHandler = new Handler(mCameraThread.getLooper());
// TODO: Add support for specifying which device to open.
- mCamera = mCameraManager.openCamera(devices[0]);
- mCameraProperties = mCamera.getProperties();
+ mCamera = mBlockingCameraManager.openCamera(devices[0], mCameraListener,
+ cameraHandler);
+ mCameraCharacteristics = mCameraManager.getCameraCharacteristics(devices[0]);
} catch (CameraAccessException e) {
- throw new ItsException("Failed to get device ID list");
+ throw new ItsException("Failed to open camera", e);
+ } catch (BlockingOpenException e) {
+ throw new ItsException("Failed to open camera (after blocking)", e);
}
// Create a thread to receive images and save them.
@@ -187,7 +212,10 @@ public class ItsService extends Service {
mSaveThread.quit();
mSaveThread = null;
}
-
+ if (mCameraThread != null) {
+ mCameraThread.quitSafely();
+ mCameraThread = null;
+ }
try {
mCamera.close();
} catch (Exception e) {
@@ -226,15 +254,6 @@ public class ItsService extends Service {
return START_STICKY;
}
- public void idleCamera() throws ItsException {
- try {
- mCamera.stopRepeating();
- mCamera.waitUntilIdle();
- } catch (CameraAccessException e) {
- throw new ItsException("Error waiting for camera idle", e);
- }
- }
-
private ImageReader.OnImageAvailableListener
createAvailableListener(final CaptureListener listener) {
return new ImageReader.OnImageAvailableListener() {
@@ -267,7 +286,7 @@ public class ItsService extends Service {
private void doGetProps() throws ItsException {
String fileName = ItsUtils.getMetadataFileName(0);
File mdFile = ItsUtils.getOutputFile(ItsService.this, fileName);
- ItsUtils.storeCameraProperties(mCameraProperties, mdFile);
+ ItsUtils.storeCameraCharacteristics(mCameraCharacteristics, mdFile);
Log.i(PYTAG,
String.format("### FILE %s",
ItsUtils.getExternallyVisiblePath(ItsService.this, mdFile.toString())));
@@ -292,14 +311,12 @@ public class ItsService extends Service {
throw new ItsException("Invalid URI: " + uri);
}
- idleCamera();
-
// Start a 3A action, and wait for it to converge.
// Get the converged values for each "A", and package into JSON result for caller.
// 3A happens on full-res frames.
- android.hardware.camera2.Size sizes[] = mCameraProperties.get(
- CameraProperties.SCALER_AVAILABLE_JPEG_SIZES);
+ android.hardware.camera2.Size sizes[] = mCameraCharacteristics.get(
+ CameraCharacteristics.SCALER_AVAILABLE_JPEG_SIZES);
int width = sizes[0].getWidth();
int height = sizes[0].getHeight();
int format = ImageFormat.YUV_420_888;
@@ -308,6 +325,10 @@ public class ItsService extends Service {
List<Surface> outputSurfaces = new ArrayList<Surface>(1);
outputSurfaces.add(mCaptureReader.getSurface());
mCamera.configureOutputs(outputSurfaces);
+ mCameraListener.waitForState(BlockingStateListener.STATE_BUSY,
+ TIMEOUT_STATE_MS);
+ mCameraListener.waitForState(BlockingStateListener.STATE_IDLE,
+ TIMEOUT_IDLE_MS);
// Add a listener that just recycles buffers; they aren't saved anywhere.
ImageReader.OnImageAvailableListener readerListener =
@@ -439,8 +460,6 @@ public class ItsService extends Service {
throw new ItsException("Invalid URI: " + uri);
}
- idleCamera();
-
// Parse the JSON to get the list of capture requests.
List<CaptureRequest.Builder> requests = ItsUtils.loadRequestList(mCamera, uri);
@@ -450,8 +469,8 @@ public class ItsService extends Service {
// Capture full-frame images. Use the reported JPEG size rather than the sensor
// size since this is more likely to be the unscaled size; the crop from sensor
// size is probably for the ISP (e.g. demosaicking) rather than the encoder.
- android.hardware.camera2.Size sizes[] = mCameraProperties.get(
- CameraProperties.SCALER_AVAILABLE_JPEG_SIZES);
+ android.hardware.camera2.Size sizes[] = mCameraCharacteristics.get(
+ CameraCharacteristics.SCALER_AVAILABLE_JPEG_SIZES);
int width = sizes[0].getWidth();
int height = sizes[0].getHeight();
int format = ImageFormat.YUV_420_888;
@@ -485,6 +504,10 @@ public class ItsService extends Service {
List<Surface> outputSurfaces = new ArrayList<Surface>(1);
outputSurfaces.add(mCaptureReader.getSurface());
mCamera.configureOutputs(outputSurfaces);
+ mCameraListener.waitForState(BlockingStateListener.STATE_BUSY,
+ TIMEOUT_STATE_MS);
+ mCameraListener.waitForState(BlockingStateListener.STATE_IDLE,
+ TIMEOUT_IDLE_MS);
ImageReader.OnImageAvailableListener readerListener =
createAvailableListener(mCaptureListener);
@@ -656,7 +679,7 @@ public class ItsService extends Service {
String fileName = ItsUtils.getMetadataFileName(
result.get(CaptureResult.SENSOR_TIMESTAMP));
File mdFile = ItsUtils.getOutputFile(ItsService.this, fileName);
- ItsUtils.storeResults(mCameraProperties, request, result, mdFile);
+ ItsUtils.storeResults(mCameraCharacteristics, request, result, mdFile);
mCaptureCallbackLatch.countDown();
}
} catch (ItsException e) {
@@ -669,7 +692,8 @@ public class ItsService extends Service {
}
@Override
- public void onCaptureFailed(CameraDevice camera, CaptureRequest request) {
+ public void onCaptureFailed(CameraDevice camera, CaptureRequest request,
+ CaptureFailure failure) {
mCaptureCallbackLatch.countDown();
Log.e(TAG, "Script error: capture failed");
Log.e(PYTAG, "### FAIL");
diff --git a/apps/CameraITS/service/src/com/android/camera2/its/ItsUtils.java b/apps/CameraITS/service/src/com/android/camera2/its/ItsUtils.java
index 2160590..861f4ae 100644
--- a/apps/CameraITS/service/src/com/android/camera2/its/ItsUtils.java
+++ b/apps/CameraITS/service/src/com/android/camera2/its/ItsUtils.java
@@ -19,7 +19,7 @@ package com.android.camera2.its;
import android.content.Context;
import android.graphics.ImageFormat;
import android.hardware.camera2.CameraDevice;
-import android.hardware.camera2.CameraProperties;
+import android.hardware.camera2.CameraCharacteristics;
import android.hardware.camera2.CaptureRequest;
import android.hardware.camera2.CaptureResult;
import android.media.Image;
@@ -61,7 +61,7 @@ public class ItsUtils {
// The indent amount to use when printing the JSON objects out as strings.
private static final int PPRINT_JSON_INDENT = 2;
- public static void storeCameraProperties(CameraProperties props,
+ public static void storeCameraCharacteristics(CameraCharacteristics props,
File file)
throws ItsException {
try {
@@ -73,7 +73,7 @@ public class ItsUtils {
}
}
- public static void storeResults(CameraProperties props,
+ public static void storeResults(CameraCharacteristics props,
CaptureRequest request,
CaptureResult result,
File file)
diff --git a/apps/CameraITS/tests/regress.sh b/apps/CameraITS/tests/regress.sh
index 73529cb..7d434d6 100755
--- a/apps/CameraITS/tests/regress.sh
+++ b/apps/CameraITS/tests/regress.sh
@@ -16,15 +16,15 @@
# The tests exercised in this file all assert/exit on failure, and terminate
# cleanly on success. The device is rebooted for each test, to ensure that
-# a problem in one test doesn't propagate into subsequent tests. If any tests
-# assert/exit (i.e. fail), this script will exit.
-
-set -e
+# a problem in one test doesn't propagate into subsequent tests.
rm -rf out
mkdir -p out
cd out
+testcount=0
+failcount=0
+
for T in \
test_3a.py \
test_black_white.py \
@@ -42,21 +42,30 @@ for T in \
test_latching.py \
test_linearity.py \
test_param_edge_mode.py \
+ test_param_flash_mode.py \
+ test_predicted_wb.py \
do
+ let testcount=testcount+1
echo ""
echo "--------------------------------------------------------------------"
echo "Running test: $T"
echo "--------------------------------------------------------------------"
python ../"$T" reboot
+ code=$?
+ if [ $code -ne 0 ]; then
+ let failcount=failcount+1
+ echo ""
+ echo "###############"
+ echo "# Test failed #"
+ echo "###############"
+ fi
echo ""
done
-cd ..
-
echo ""
-echo "####################"
-echo "# All tests passed #"
-echo "####################"
+echo "$failcount out of $testcount tests failed"
echo ""
+cd ..
+
diff --git a/apps/CameraITS/tests/test_3a.py b/apps/CameraITS/tests/test_3a.py
index 2ec28b1..72ede98 100644
--- a/apps/CameraITS/tests/test_3a.py
+++ b/apps/CameraITS/tests/test_3a.py
@@ -17,13 +17,9 @@ import its.device
def main():
"""Basic test for bring-up of 3A.
- Will be updated or removed once 3A is working. Simply calls the function to
- initiate the 3A intent, and exits. Watch logcat (once the script exits) to
- see how the 3A operation fared.
+ To pass, 3A must converge. Check that the returned 3A values are legal.
"""
- # TODO: Finish this test
-
with its.device.ItsSession() as cam:
rect = [0,0,1,1]
sens, exp, gains, xform, focus = cam.do_3a(rect, rect, rect)
@@ -34,9 +30,7 @@ def main():
assert(exp > 0)
assert(len(gains) == 4)
assert(len(xform) == 9)
-
- # TODO: Uncomment assertion once AF returns the focus distance.
- #assert(focus > 0)
+ assert(focus > 0)
if __name__ == '__main__':
main()
diff --git a/apps/CameraITS/tests/test_3a_remote.py b/apps/CameraITS/tests/test_3a_remote.py
index 216f525..6d424aa 100644
--- a/apps/CameraITS/tests/test_3a_remote.py
+++ b/apps/CameraITS/tests/test_3a_remote.py
@@ -27,16 +27,6 @@ def main():
"""
NAME = os.path.basename(__file__).split(".")[0]
- auto_req = its.objects.capture_request( {
- "android.control.mode": 1,
- "android.control.aeMode": 1,
- "android.control.awbMode": 1,
- "android.control.afMode": 1,
- "android.colorCorrection.mode": 1,
- "android.tonemap.mode": 1,
- "android.statistics.lensShadingMapMode":1
- })
-
def r2f(r):
return float(r["numerator"]) / float(r["denominator"])
@@ -47,8 +37,17 @@ def main():
# TODO: Test for 3A convergence, and exit this test once converged.
+ triggered = False
while True:
- fname, w, h, md_obj = cam.do_capture(auto_req)
+ req = its.objects.auto_capture_request()
+ req["captureRequest"]["android.statistics.lensShadingMapMode"] = 1
+ req['captureRequest']['android.control.aePrecaptureTrigger'] = (
+ 0 if triggered else 1)
+ req['captureRequest']['android.control.afTrigger'] = (
+ 0 if triggered else 1)
+ triggered = True
+
+ fname, w, h, md_obj = cam.do_capture(req)
cap_res = md_obj["captureResult"]
ae_state = cap_res["android.control.aeState"]
@@ -58,6 +57,8 @@ def main():
transform = cap_res["android.colorCorrection.transform"]
exp_time = cap_res['android.sensor.exposureTime']
lsc_map = cap_res["android.statistics.lensShadingMap"]
+ foc_dist = cap_res['android.lens.focusDistance']
+ foc_range = cap_res['android.lens.focusRange']
print "States (AE,AWB,AF):", ae_state, awb_state, af_state
print "Gains:", gains
@@ -66,6 +67,7 @@ def main():
print "AF region:", cap_res['android.control.afRegions']
print "AWB region:", cap_res['android.control.awbRegions']
print "LSC map:", w_map, h_map, lsc_map[:8]
+ print "Focus (dist,range):", foc_dist, foc_range
print ""
if __name__ == '__main__':
diff --git a/apps/CameraITS/tests/test_black_level.py b/apps/CameraITS/tests/test_black_level.py
index 440b080..cb208d7 100644
--- a/apps/CameraITS/tests/test_black_level.py
+++ b/apps/CameraITS/tests/test_black_level.py
@@ -40,16 +40,6 @@ def main():
# Only check the center part where LSC has little effects.
R = 200
- req = its.objects.capture_request( {
- "android.blackLevel.lock": True,
- "android.control.mode": 0,
- "android.control.aeMode": 0,
- "android.control.awbMode": 0,
- "android.control.afMode": 0,
- "android.sensor.frameDuration": 0,
- "android.sensor.exposureTime": 1*1000*1000
- })
-
# The most frequent pixel value in each image; assume this is the black
# level, since the images are all dark (shot with the lens covered).
ymodes = []
@@ -66,10 +56,18 @@ def main():
print "Sensitivities:", sensitivities
for si, s in enumerate(sensitivities):
for rep in xrange(NUM_REPEAT):
+ req = its.objects.manual_capture_request(100, 1)
+ req["captureRequest"]["android.blackLevel.lock"] = True
req["captureRequest"]["android.sensor.sensitivity"] = s
fname, w, h, cap_md = cam.do_capture(req)
yimg,uimg,vimg = its.image.load_yuv420_to_yuv_planes(fname,w,h)
+ # Magnify the noise in saved images to help visualize.
+ its.image.write_image(yimg * 2,
+ "%s_s=%05d_y.jpg" % (NAME, s), True)
+ its.image.write_image(numpy.absolute(uimg - 0.5) * 2,
+ "%s_s=%05d_u.jpg" % (NAME, s), True)
+
yimg = yimg[w/2-R:w/2+R, h/2-R:h/2+R]
uimg = uimg[w/4-R/2:w/4+R/2, w/4-R/2:w/4+R/2]
vimg = vimg[w/4-R/2:w/4+R/2, w/4-R/2:w/4+R/2]
@@ -95,8 +93,6 @@ def main():
print "U black levels:", umodes
print "V black levels:", vmodes
- assert(all([ymodes[i] == ymodes[0] for i in range(len(ymodes))]))
-
if __name__ == '__main__':
main()
diff --git a/apps/CameraITS/tests/test_black_white.py b/apps/CameraITS/tests/test_black_white.py
index 2b7b2d0..7886d75 100644
--- a/apps/CameraITS/tests/test_black_white.py
+++ b/apps/CameraITS/tests/test_black_white.py
@@ -30,17 +30,6 @@ def main():
"""
NAME = os.path.basename(__file__).split(".")[0]
- req = its.objects.capture_request( {
- "android.sensor.exposureTime": 10*1000, # 0.01ms
- "android.sensor.sensitivity": 100,
- "android.sensor.frameDuration": 0,
- "android.control.mode": 0,
- "android.control.aeMode": 0,
- "android.control.awbMode": 0,
- "android.control.afMode": 0,
- "android.control.effectMode": 0,
- })
-
r_means = []
g_means = []
b_means = []
@@ -48,6 +37,7 @@ def main():
with its.device.ItsSession() as cam:
# Take a shot with very low ISO and exposure time. Expect it to
# be black.
+ req = its.objects.manual_capture_request(100, 0.1)
fname, w, h, cap_md = cam.do_capture(req)
img = its.image.load_yuv420_to_rgb_image(fname, w, h)
its.image.write_image(img, "%s_black.jpg" % (NAME))
@@ -60,8 +50,7 @@ def main():
# Take a shot with very high ISO and exposure time. Expect it to
# be black.
- req["captureRequest"]["android.sensor.sensitivity"] = 10000
- req["captureRequest"]["android.sensor.exposureTime"] = 1000*1000*1000
+ req = its.objects.manual_capture_request(10000, 1000)
fname, w, h, cap_md = cam.do_capture(req)
img = its.image.load_yuv420_to_rgb_image(fname, w, h)
its.image.write_image(img, "%s_white.jpg" % (NAME))
diff --git a/apps/CameraITS/tests/test_capture_result.py b/apps/CameraITS/tests/test_capture_result.py
index fbc1bfc..d0ff74e 100644
--- a/apps/CameraITS/tests/test_capture_result.py
+++ b/apps/CameraITS/tests/test_capture_result.py
@@ -27,28 +27,15 @@ def main():
"""
NAME = os.path.basename(__file__).split(".")[0]
- # TODO: Query the allowable tonemap curve sizes; here, it's hardcoded to
- # a length=64 list of tuples. The max allowed length should be inside the
- # camera properties object.
- L = 32
- LM1 = float(L-1)
-
- manual_tonemap = sum([[i/LM1, i/LM1] for i in range(L)], [])
+ manual_tonemap = [0,0, 1,1] # Linear
manual_transform = its.objects.int_to_rational([1,2,3, 4,5,6, 7,8,9])
manual_gains = [1,2,3,4]
manual_region = [8,8,128,128]
manual_exp_time = 100*1000*1000
manual_sensitivity = 100
- auto_req = its.objects.capture_request( {
- "android.control.mode": 1,
- "android.control.aeMode": 1,
- "android.control.awbMode": 1,
- "android.control.afMode": 1,
- "android.colorCorrection.mode": 1,
- "android.tonemap.mode": 1,
- "android.statistics.lensShadingMapMode":1
- })
+ auto_req = its.objects.auto_capture_request()
+ auto_req["captureRequest"]["android.statistics.lensShadingMapMode"] = 1
manual_req = its.objects.capture_request( {
"android.control.mode": 0,
@@ -97,13 +84,20 @@ def main():
matplotlib.pyplot.savefig("%s_plot_lsc_%s.png" % (NAME, name))
def test_auto(cam, w_map, h_map):
+ # Get 3A lock first, so the auto values in the capture result are
+ # populated properly.
+ rect = [0,0,1,1]
+ cam.do_3a(rect, rect, rect, True, True, False)
+
fname, w, h, md_obj = cam.do_capture(auto_req)
cap_res = md_obj["captureResult"]
gains = cap_res["android.colorCorrection.gains"]
transform = cap_res["android.colorCorrection.transform"]
exp_time = cap_res['android.sensor.exposureTime']
lsc_map = cap_res["android.statistics.lensShadingMap"]
+ ctrl_mode = cap_res["android.control.mode"]
+ print "Control mode:", ctrl_mode
print "Gains:", gains
print "Transform:", [r2f(t) for t in transform]
print "AE region:", cap_res['android.control.aeRegions']
@@ -111,6 +105,8 @@ def main():
print "AWB region:", cap_res['android.control.awbRegions']
print "LSC map:", w_map, h_map, lsc_map[:8]
+ assert(ctrl_mode == 1)
+
# Color correction gain and transform must be valid.
assert(len(gains) == 4)
assert(len(transform) == 9)
@@ -149,15 +145,23 @@ def main():
cap_res["android.tonemap.curveBlue"]]
exp_time = cap_res['android.sensor.exposureTime']
lsc_map = cap_res["android.statistics.lensShadingMap"]
+ pred_gains = cap_res["android.statistics.predictedColorGains"]
+ pred_transform = cap_res["android.statistics.predictedColorTransform"]
+ ctrl_mode = cap_res["android.control.mode"]
+ print "Control mode:", ctrl_mode
print "Gains:", gains
print "Transform:", [r2f(t) for t in transform]
+ print "Predicted gains:", pred_gains
+ print "Predicted transform:", [r2f(t) for t in pred_transform]
print "Tonemap:", curves[0][1::16]
print "AE region:", cap_res['android.control.aeRegions']
print "AF region:", cap_res['android.control.afRegions']
print "AWB region:", cap_res['android.control.awbRegions']
print "LSC map:", w_map, h_map, lsc_map[:8]
+ assert(ctrl_mode == 0)
+
# Color correction gain and transform must be valid.
# Color correction gains and transform should be the same size and
# values as the manually set values.
@@ -168,23 +172,25 @@ def main():
assert(all([is_close_rational(transform[i], manual_transform[i])
for i in xrange(9)]))
+ # The predicted gains and transform must also be valid.
+ assert(len(pred_gains) == 4)
+ assert(len(pred_transform) == 9)
+
# Tonemap must be valid.
- # The returned tonemap can be interpolated from the provided values.
+ # The returned tonemap must be linear.
for c in curves:
assert(len(c) > 0)
- for i, val in enumerate(c):
- ii = int(math.floor(
- ((i+0.5) / float(len(c))*float(len(manual_tonemap)))))
- assert(is_close_float(c[i], manual_tonemap[ii]))
+ assert(all([is_close_float(c[i], c[i+1])
+ for i in xrange(0,len(c),2)]))
# Exposure time must be close to the requested exposure time.
assert(is_close_float(exp_time/1000000.0, manual_exp_time/1000000.0))
- # 3A regions must be valid, and must match the manual regions.
- # TODO: Uncomment these assertions once the bug is fixed.
- #assert(cap_res['android.control.aeRegions'][:4] == manual_region)
- #assert(cap_res['android.control.afRegions'][:4] == manual_region)
- #assert(cap_res['android.control.awbRegions'][:4] == manual_region)
+ # 3A regions must be valid. They don't need to actually match what was
+ # requesed, since the SOC may not support those regions exactly.
+ assert(len(cap_res['android.control.aeRegions']) == 5)
+ assert(len(cap_res['android.control.afRegions']) == 5)
+ assert(len(cap_res['android.control.awbRegions']) == 5)
# Lens shading map must be valid.
assert(w_map > 0 and h_map > 0 and w_map * h_map * 4 == len(lsc_map))
@@ -193,8 +199,7 @@ def main():
# Lens shading map must take into account the manual color correction
# settings. Test this by ensuring that the map is different between
# the auto and manual test cases.
- # TODO: Uncomment these assertions once the bug is fixed.
- #assert(lsc_map != lsc_map_auto)
+ assert(lsc_map != lsc_map_auto)
draw_lsc_plot(w_map, h_map, lsc_map, "manual")
diff --git a/apps/CameraITS/tests/test_exposure.py b/apps/CameraITS/tests/test_exposure.py
index 40861ed..c01ce47 100644
--- a/apps/CameraITS/tests/test_exposure.py
+++ b/apps/CameraITS/tests/test_exposure.py
@@ -35,14 +35,6 @@ def main():
THRESHOLD_MAX_LEVEL = 0.9
THRESHOLD_MAX_ABS_GRAD = 0.001
- req = its.objects.capture_request( {
- "android.control.mode": 0,
- "android.control.aeMode": 0,
- "android.control.awbMode": 0,
- "android.control.afMode": 0,
- "android.sensor.frameDuration": 0
- })
-
mults = range(1, 100, 9)
r_means = []
g_means = []
@@ -50,8 +42,7 @@ def main():
with its.device.ItsSession() as cam:
for m in mults:
- req["captureRequest"]["android.sensor.sensitivity"] = 100*m
- req["captureRequest"]["android.sensor.exposureTime"] = 40*1000*1000/m
+ req = its.objects.manual_capture_request(100*m, 40.0/m)
fname, w, h, md_obj = cam.do_capture(req)
img = its.image.load_yuv420_to_rgb_image(fname, w, h)
its.image.write_image(img, "%s_mult=%02d.jpg" % (NAME, m))
diff --git a/apps/CameraITS/tests/test_formats.py b/apps/CameraITS/tests/test_formats.py
index d05443b..b9b8ae1 100644
--- a/apps/CameraITS/tests/test_formats.py
+++ b/apps/CameraITS/tests/test_formats.py
@@ -26,7 +26,7 @@ def main():
with its.device.ItsSession() as cam:
props = cam.get_camera_properties()
for size in props['android.scaler.availableProcessedSizes']:
- req = its.objects.capture_request({"android.control.aeMode": 0})
+ req = its.objects.manual_capture_request(100,10)
req["outputSurface"] = size
req["outputSurface"]["format"] = "yuv"
fname, w, h, cap_md = cam.do_capture(req)
@@ -35,7 +35,7 @@ def main():
assert(os.path.getsize(fname) == w*h*3/2)
print "Successfully captured YUV %dx%d" % (w, h)
for size in props['android.scaler.availableJpegSizes']:
- req = its.objects.capture_request({"android.control.aeMode": 0})
+ req = its.objects.manual_capture_request(100,10)
req["outputSurface"] = size
req["outputSurface"]["format"] = "jpg"
fname, w, h, cap_md = cam.do_capture(req)
diff --git a/apps/CameraITS/tests/test_jpeg.py b/apps/CameraITS/tests/test_jpeg.py
index 0e2db08..870fda4 100644
--- a/apps/CameraITS/tests/test_jpeg.py
+++ b/apps/CameraITS/tests/test_jpeg.py
@@ -28,20 +28,11 @@ def main():
THRESHOLD_MAX_RMS_DIFF = 0.1
- req = its.objects.capture_request( {
- "android.control.mode": 0,
- "android.control.aeMode": 0,
- "android.control.awbMode": 0,
- "android.control.afMode": 0,
- "android.sensor.frameDuration": 0,
- "android.sensor.sensitivity": 100,
- "android.sensor.exposureTime": 10*1000*1000
- })
-
with its.device.ItsSession() as cam:
props = cam.get_camera_properties()
# YUV
+ req = its.objects.manual_capture_request(100,100)
size = props['android.scaler.availableProcessedSizes'][0]
req["outputSurface"] = size
req["outputSurface"]["format"] = "yuv"
@@ -52,6 +43,7 @@ def main():
rgb0 = its.image.compute_image_means(tile)
# JPEG
+ req = its.objects.manual_capture_request(100,100)
size = props['android.scaler.availableJpegSizes'][0]
req["outputSurface"] = size
req["outputSurface"]["format"] = "jpg"
diff --git a/apps/CameraITS/tests/test_latching.py b/apps/CameraITS/tests/test_latching.py
index d985b2b..14dbed8 100644
--- a/apps/CameraITS/tests/test_latching.py
+++ b/apps/CameraITS/tests/test_latching.py
@@ -30,41 +30,23 @@ def main():
"""
NAME = os.path.basename(__file__).split(".")[0]
- req = {
- "android.control.mode": 0,
- "android.control.aeMode": 0,
- "android.control.awbMode": 0,
- "android.control.afMode": 0,
- "android.sensor.frameDuration": 0,
- "android.sensor.sensitivity": 150,
- "android.sensor.exposureTime": 10*1000*1000
- }
-
- reqs = its.objects.capture_request_list([copy.deepcopy(req)]*2)
-
- req["android.sensor.sensitivity"] *= 10
- reqs["captureRequestList"] += [copy.deepcopy(req)]*2
-
- req["android.sensor.exposureTime"] /= 10
- reqs["captureRequestList"] += [copy.deepcopy(req)]*2
-
- req["android.sensor.exposureTime"] *= 10
- reqs["captureRequestList"] += [copy.deepcopy(req)]*2
-
- req["android.sensor.sensitivity"] /= 10
- reqs["captureRequestList"] += [copy.deepcopy(req)]*2
-
- req["android.sensor.sensitivity"] *= 10
- reqs["captureRequestList"] += [copy.deepcopy(req)]*2
-
- req["android.sensor.exposureTime"] /= 10
- reqs["captureRequestList"] += [copy.deepcopy(req)]*2
-
- req["android.sensor.exposureTime"] *= 10
- reqs["captureRequestList"] += [copy.deepcopy(req)]*2
-
- req["android.sensor.sensitivity"] /= 10
- reqs["captureRequestList"] += [copy.deepcopy(req)]*2
+ S = 150 # Sensitivity
+ E = 10 # Exposure time, ms
+
+ reqs = its.objects.capture_request_list([
+ its.objects.manual_capture_request(S, E )["captureRequest"],
+ its.objects.manual_capture_request(S, E )["captureRequest"],
+ its.objects.manual_capture_request(S*8,E )["captureRequest"],
+ its.objects.manual_capture_request(S*8,E )["captureRequest"],
+ its.objects.manual_capture_request(S, E )["captureRequest"],
+ its.objects.manual_capture_request(S, E )["captureRequest"],
+ its.objects.manual_capture_request(S, E*8)["captureRequest"],
+ its.objects.manual_capture_request(S, E )["captureRequest"],
+ its.objects.manual_capture_request(S*8,E )["captureRequest"],
+ its.objects.manual_capture_request(S, E )["captureRequest"],
+ its.objects.manual_capture_request(S, E*8)["captureRequest"],
+ its.objects.manual_capture_request(S, E )["captureRequest"],
+ ])
r_means = []
g_means = []
diff --git a/apps/CameraITS/tests/test_param_exposure_time.py b/apps/CameraITS/tests/test_param_exposure_time.py
index ddeb304..6b91206 100644
--- a/apps/CameraITS/tests/test_param_exposure_time.py
+++ b/apps/CameraITS/tests/test_param_exposure_time.py
@@ -35,7 +35,7 @@ def main():
"android.control.awbMode": 0,
"android.control.afMode": 0,
"android.sensor.frameDuration": 0,
- "android.sensor.sensitivity": 100
+ "android.sensor.sensitivity": 200
})
exposures = range(1,101,20) # ms
diff --git a/apps/CameraITS/tests/test_param_exposure_time_burst.py b/apps/CameraITS/tests/test_param_exposure_time_burst.py
new file mode 100644
index 0000000..fda31bf
--- /dev/null
+++ b/apps/CameraITS/tests/test_param_exposure_time_burst.py
@@ -0,0 +1,43 @@
+# Copyright 2013 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.
+
+import its.image
+import its.device
+import its.objects
+import pylab
+import os.path
+import matplotlib
+import matplotlib.pyplot
+
+def main():
+ """Test that the android.sensor.exposureTime parameter is applied properly
+ within a burst. Inspects the output metadata.
+ """
+ NAME = os.path.basename(__file__).split(".")[0]
+
+ exp_times = range(1, 100, 9)
+ reqs = its.objects.capture_request_list([
+ its.objects.manual_capture_request(100,e)["captureRequest"]
+ for e in exp_times])
+
+ with its.device.ItsSession() as cam:
+ fnames, w, h, cap_mds = cam.do_capture(reqs)
+ for i,md in enumerate(cap_mds):
+ e_req = exp_times[i]*1000*1000
+ e_res = md["captureResult"]["android.sensor.exposureTime"]
+ print e_req, e_res
+
+if __name__ == '__main__':
+ main()
+
diff --git a/apps/CameraITS/tests/test_param_flash_mode.py b/apps/CameraITS/tests/test_param_flash_mode.py
index cfc1a0d..091a896 100644
--- a/apps/CameraITS/tests/test_param_flash_mode.py
+++ b/apps/CameraITS/tests/test_param_flash_mode.py
@@ -25,23 +25,30 @@ def main():
"""
NAME = os.path.basename(__file__).split(".")[0]
- req = its.objects.capture_request( {
- "android.control.mode": 0,
- "android.control.aeMode": 0,
- "android.control.awbMode": 0,
- "android.control.afMode": 0,
- "android.sensor.frameDuration": 0,
- "android.sensor.exposureTime": 100*1000*1000,
- "android.sensor.sensitivity": 100
- })
+ req = its.objects.auto_capture_request()
+
+ flash_modes_reported = []
+ flash_states_reported = []
with its.device.ItsSession() as cam:
for f in [0,1,2]:
req["captureRequest"]["android.flash.mode"] = f
fname, w, h, cap_md = cam.do_capture(req)
+ flash_modes_reported.append(
+ cap_md["captureResult"]["android.flash.mode"])
+ flash_states_reported.append(
+ cap_md["captureResult"]["android.flash.state"])
img = its.image.load_yuv420_to_rgb_image(fname, w, h)
its.image.write_image(img, "%s_mode=%d.jpg" % (NAME, f))
+ assert(flash_modes_reported == [0,1,2])
+
+ # TODO: Add check on flash_states_reported values.
+
+ # TODO: Add an image check on the brightness of the captured shots, as well
+ # as the exposure values in the capture result, to test that flash was
+ # fired as expected (i.e.) on the shots it was expected to be fired for.
+
if __name__ == '__main__':
main()
diff --git a/apps/CameraITS/tests/test_param_noise_reduction.py b/apps/CameraITS/tests/test_param_noise_reduction.py
index d43d4ed..63d663a 100644
--- a/apps/CameraITS/tests/test_param_noise_reduction.py
+++ b/apps/CameraITS/tests/test_param_noise_reduction.py
@@ -32,7 +32,7 @@ def main():
"""
NAME = os.path.basename(__file__).split(".")[0]
- THRESHOLD_MIN_VARIANCE_RATIO = 0.5
+ THRESHOLD_MIN_VARIANCE_RATIO = 0.7
req = its.objects.capture_request( {
"android.control.mode": 0,
@@ -48,6 +48,8 @@ def main():
# Reference (baseline) variance for each of Y,U,V.
ref_variance = []
+ nr_modes_reported = []
+
with its.device.ItsSession() as cam:
# NR mode 0 with low gain
req["captureRequest"]["android.noiseReduction.mode"] = 0
@@ -66,10 +68,12 @@ def main():
for i in range(3):
# NR modes 0, 1, 2 with high gain
req["captureRequest"]["android.noiseReduction.mode"] = i
- req["captureRequest"]["android.sensor.sensitivity"] = 1600
+ req["captureRequest"]["android.sensor.sensitivity"] = 100*16
req["captureRequest"]["android.sensor.exposureTime"] = (
20*1000*1000/16)
fname, w, h, md_obj = cam.do_capture(req)
+ nr_modes_reported.append(
+ md_obj["captureResult"]["android.noiseReduction.mode"])
its.image.write_image(
its.image.load_yuv420_to_rgb_image(fname, w, h),
"%s_high_gain_nr=%d.jpg" % (NAME, i))
@@ -85,6 +89,8 @@ def main():
pylab.plot(range(3), variances[j], "rgb"[j])
matplotlib.pyplot.savefig("%s_plot_variances.png" % (NAME))
+ assert(nr_modes_reported == [0,1,2])
+
# Check that the variance of the NR=0 image is much higher than for the
# NR=1 and NR=2 images.
for j in range(3):
diff --git a/apps/CameraITS/tests/test_param_sensitivity.py b/apps/CameraITS/tests/test_param_sensitivity.py
index 88be747..bff0c88 100644
--- a/apps/CameraITS/tests/test_param_sensitivity.py
+++ b/apps/CameraITS/tests/test_param_sensitivity.py
@@ -37,7 +37,7 @@ def main():
"android.control.awbMode": 0,
"android.control.afMode": 0,
"android.sensor.frameDuration": 0,
- "android.sensor.exposureTime": 1*1000*1000
+ "android.sensor.exposureTime": 2*1000*1000
})
sensitivities = None
diff --git a/apps/CameraITS/tests/test_param_sensitivity_burst.py b/apps/CameraITS/tests/test_param_sensitivity_burst.py
new file mode 100644
index 0000000..de1119e
--- /dev/null
+++ b/apps/CameraITS/tests/test_param_sensitivity_burst.py
@@ -0,0 +1,43 @@
+# Copyright 2013 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.
+
+import its.image
+import its.device
+import its.objects
+import pylab
+import os.path
+import matplotlib
+import matplotlib.pyplot
+
+def main():
+ """Test that the android.sensor.sensitivity parameter is applied properly
+ within a burst. Inspects the output metadata.
+ """
+ NAME = os.path.basename(__file__).split(".")[0]
+
+ sensitivities = range(350, 400, 7)
+ reqs = its.objects.capture_request_list([
+ its.objects.manual_capture_request(s,10)["captureRequest"]
+ for s in sensitivities])
+
+ with its.device.ItsSession() as cam:
+ fnames, w, h, cap_mds = cam.do_capture(reqs)
+ for i,md in enumerate(cap_mds):
+ s_req = sensitivities[i]
+ s_res = md["captureResult"]["android.sensor.sensitivity"]
+ print s_req, s_res
+
+if __name__ == '__main__':
+ main()
+
diff --git a/apps/CameraITS/tests/test_param_tonemap_mode.py b/apps/CameraITS/tests/test_param_tonemap_mode.py
index fc7186e..4000292 100644
--- a/apps/CameraITS/tests/test_param_tonemap_mode.py
+++ b/apps/CameraITS/tests/test_param_tonemap_mode.py
@@ -40,17 +40,6 @@ def main():
L = 32
LM1 = float(L-1)
- req = its.objects.capture_request( {
- "android.tonemap.mode": 0,
- "android.control.mode": 0,
- "android.control.aeMode": 0,
- "android.control.awbMode": 0,
- "android.control.afMode": 0,
- "android.sensor.sensitivity": 100,
- "android.sensor.exposureTime": 50*1000*1000,
- "android.sensor.frameDuration": 0
- })
-
with its.device.ItsSession() as cam:
# Test 1: that the tonemap curves have the expected effect. Take two
@@ -61,6 +50,8 @@ def main():
rgb_means = []
for n in [0,1]:
+ req = its.objects.manual_capture_request(100,50)
+ req["captureRequest"]["android.tonemap.mode"] = 0
req["captureRequest"]["android.tonemap.curveRed"] = (
sum([[i/LM1, (1+0.5*n)*i/LM1] for i in range(L)], []))
req["captureRequest"]["android.tonemap.curveGreen"] = (
@@ -87,6 +78,8 @@ def main():
for size in [32,64]:
m = float(size-1)
curve = sum([[i/m, i/m] for i in range(size)], [])
+ req = its.objects.manual_capture_request(100,50)
+ req["captureRequest"]["android.tonemap.mode"] = 0
req["captureRequest"]["android.tonemap.curveRed"] = curve
req["captureRequest"]["android.tonemap.curveGreen"] = curve
req["captureRequest"]["android.tonemap.curveBlue"] = curve
diff --git a/apps/CameraITS/tests/test_predicted_wb.py b/apps/CameraITS/tests/test_predicted_wb.py
new file mode 100644
index 0000000..3aade2b
--- /dev/null
+++ b/apps/CameraITS/tests/test_predicted_wb.py
@@ -0,0 +1,107 @@
+# Copyright 2013 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.
+
+import its.image
+import its.device
+import its.objects
+import os.path
+import pprint
+import math
+import numpy
+import matplotlib.pyplot
+import mpl_toolkits.mplot3d
+
+def main():
+ """Test that valid data comes back in CaptureResult objects.
+ """
+ NAME = os.path.basename(__file__).split(".")[0]
+
+ def r2f(r):
+ return float(r["numerator"]) / float(r["denominator"])
+
+ if not its.device.reboot_device_on_argv():
+ its.device.reboot_device()
+
+ # Run a first pass, which starts with a 3A convergence step.
+ with its.device.ItsSession() as cam:
+ # Get 3A lock first, so the auto values in the capture result are
+ # populated properly.
+ r = [0,0,1,1]
+ sens,exp,awb_gains,awb_transform,_ = cam.do_3a(r,r,r,True,True,False)
+
+ # Capture an auto shot using the converged 3A.
+ req = its.objects.auto_capture_request()
+ fname, w, h, md_obj = cam.do_capture(req)
+ img = its.image.load_yuv420_to_rgb_image(fname, w, h)
+ its.image.write_image(img, "%s_n=1_pass=1_auto.jpg" % (NAME))
+ cap_res = md_obj["captureResult"]
+ auto_gains = cap_res["android.colorCorrection.gains"]
+ auto_transform = cap_res["android.colorCorrection.transform"]
+
+ # Capture a request using default (unit/identify) gains, and get the
+ # predicted gains and transform.
+ req = its.objects.manual_capture_request(sens, exp/(1000.0*1000.0))
+ fname, w, h, md_obj = cam.do_capture(req)
+ img = its.image.load_yuv420_to_rgb_image(fname, w, h)
+ its.image.write_image(img, "%s_n=2_pass=1_identity.jpg" % (NAME))
+ cap_res = md_obj["captureResult"]
+ pred_gains_1 = cap_res["android.statistics.predictedColorGains"]
+ pred_transform_1 = cap_res["android.statistics.predictedColorTransform"]
+
+ # Capture a request using the predicted gains/transform.
+ req = its.objects.manual_capture_request(sens, exp/(1000.0*1000.0))
+ req["captureRequest"]["android.colorCorrection.transform"] = \
+ pred_transform_1
+ req["captureRequest"]["android.colorCorrection.gains"] = pred_gains_1
+ fname, w, h, md_obj = cam.do_capture(req)
+ img = its.image.load_yuv420_to_rgb_image(fname, w, h)
+ its.image.write_image(img, "%s_n=3_pass=1_predicted.jpg" % (NAME))
+
+ print "Pass 1 metering gains:", awb_gains
+ print "Pass 1 metering transform:", awb_transform
+ print "Pass 1 auto shot gains:", auto_gains
+ print "Pass 1 auto shot transform:", [r2f(t) for t in auto_transform]
+ print "Pass 1 predicted gains:", pred_gains_1
+ print "Pass 1 predicted transform:", [r2f(t) for t in pred_transform_1]
+
+ if not its.device.reboot_device_on_argv():
+ its.device.reboot_device()
+
+ # Run a second pass after rebooting that doesn't start with 3A convergence.
+ with its.device.ItsSession() as cam:
+ # Capture a request using default (unit/identify) gains, and get the
+ # predicted gains and transform.
+ req = its.objects.manual_capture_request(sens, exp/(1000.0*1000.0))
+ fname, w, h, md_obj = cam.do_capture(req)
+ img = its.image.load_yuv420_to_rgb_image(fname, w, h)
+ its.image.write_image(img, "%s_n=4_pass=2_identity.jpg" % (NAME))
+ cap_res = md_obj["captureResult"]
+ pred_gains_2 = cap_res["android.statistics.predictedColorGains"]
+ pred_transform_2 = cap_res["android.statistics.predictedColorTransform"]
+
+ # Capture a request using the predicted gains/transform.
+ req = its.objects.manual_capture_request(sens, exp/(1000.0*1000.0))
+ req["captureRequest"]["android.colorCorrection.transform"] = \
+ pred_transform_2
+ req["captureRequest"]["android.colorCorrection.gains"] = pred_gains_2
+ fname, w, h, md_obj = cam.do_capture(req)
+ img = its.image.load_yuv420_to_rgb_image(fname, w, h)
+ its.image.write_image(img, "%s_n=5_pass=2_predicted.jpg" % (NAME))
+
+ print "Pass 2 predicted gains:", pred_gains_2
+ print "Pass 2 predicted transform:", [r2f(t) for t in pred_transform_2]
+
+if __name__ == '__main__':
+ main()
+
diff --git a/apps/TestingCamera/src/com/android/testingcamera/TestingCamera.java b/apps/TestingCamera/src/com/android/testingcamera/TestingCamera.java
index 6500823..1c2d5c7 100644
--- a/apps/TestingCamera/src/com/android/testingcamera/TestingCamera.java
+++ b/apps/TestingCamera/src/com/android/testingcamera/TestingCamera.java
@@ -1458,7 +1458,13 @@ public class TestingCamera extends Activity
mRecordHandoffCheckBox.setEnabled(true);
mRecordToggle.setChecked(false);
if (mRecorder != null) {
- mRecorder.stop();
+ try {
+ mRecorder.stop();
+ } catch (RuntimeException e) {
+ // this can happen if there were no frames received by recorder
+ logE("Could not create output file");
+ error = true;
+ }
if (mRecordHandoffCheckBox.isChecked()) {
mState = CAMERA_UNINITIALIZED;
diff --git a/apps/TestingCamera2/Android.mk b/apps/TestingCamera2/Android.mk
index cdc27ff..868de25 100644
--- a/apps/TestingCamera2/Android.mk
+++ b/apps/TestingCamera2/Android.mk
@@ -22,6 +22,8 @@ LOCAL_MODULE_TAGS := optional
LOCAL_SDK_VERSION := current
+LOCAL_STATIC_JAVA_LIBRARIES := android-ex-camera2
+
LOCAL_SRC_FILES := \
$(call all-java-files-under, src) \
$(call all-renderscript-files-under, src)
diff --git a/apps/TestingCamera2/AndroidManifest.xml b/apps/TestingCamera2/AndroidManifest.xml
index 3da7d2a..0bc7f4e 100644
--- a/apps/TestingCamera2/AndroidManifest.xml
+++ b/apps/TestingCamera2/AndroidManifest.xml
@@ -34,8 +34,8 @@
>
<activity
android:name=".TestingCamera2"
- android:label="@string/app_name"
- android:screenOrientation="landscape">
+ android:configChanges="orientation|keyboardHidden|screenSize"
+ android:label="@string/app_name">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
diff --git a/apps/TestingCamera2/src/com/android/testingcamera2/CameraOps.java b/apps/TestingCamera2/src/com/android/testingcamera2/CameraOps.java
index 855f6c8..0b0470d 100644
--- a/apps/TestingCamera2/src/com/android/testingcamera2/CameraOps.java
+++ b/apps/TestingCamera2/src/com/android/testingcamera2/CameraOps.java
@@ -22,18 +22,23 @@ import android.hardware.camera2.CameraAccessException;
import android.hardware.camera2.CameraDevice;
import android.hardware.camera2.CameraManager;
import android.hardware.camera2.CameraMetadata;
-import android.hardware.camera2.CameraProperties;
+import android.hardware.camera2.CameraCharacteristics;
import android.hardware.camera2.CaptureRequest;
import android.hardware.camera2.Size;
import android.media.Image;
import android.media.ImageReader;
import android.os.Handler;
+import android.os.HandlerThread;
import android.os.Looper;
import android.os.Message;
import android.util.Log;
import android.view.Surface;
import android.view.SurfaceHolder;
+import com.android.ex.camera2.blocking.BlockingCameraManager;
+import com.android.ex.camera2.blocking.BlockingCameraManager.BlockingOpenException;
+import com.android.ex.camera2.blocking.BlockingStateListener;
+
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
@@ -46,14 +51,18 @@ public class CameraOps {
private static final String TAG = "CameraOps";
- private final Thread mOpsThread;
- private Handler mOpsHandler;
+ private final HandlerThread mOpsThread;
+ private final Handler mOpsHandler;
private final CameraManager mCameraManager;
+ private final BlockingCameraManager mBlockingCameraManager;
+ private final BlockingStateListener mDeviceListener =
+ new BlockingStateListener();
+
private CameraDevice mCamera;
private ImageReader mCaptureReader;
- private CameraProperties mCameraProperties;
+ private CameraCharacteristics mCameraCharacteristics;
private int mEncodingBitRate;
@@ -74,6 +83,10 @@ public class CameraOps {
private static final Size DEFAULT_SIZE = new Size(640, 480);
private static final Size HIGH_RESOLUTION_SIZE = new Size(1920, 1080);
+ private static final long IDLE_WAIT_MS = 2000;
+ // General short wait timeout for most state transitions
+ private static final long STATE_WAIT_MS = 500;
+
private int mStatus = STATUS_UNINITIALIZED;
CameraRecordingStream mRecordingStream;
@@ -84,28 +97,16 @@ public class CameraOps {
}
}
- private class OpsHandler extends Handler {
- @Override
- public void handleMessage(Message msg) {
-
- }
- }
-
private CameraOps(Context ctx) throws ApiFailureException {
mCameraManager = (CameraManager) ctx.getSystemService(Context.CAMERA_SERVICE);
if (mCameraManager == null) {
throw new ApiFailureException("Can't connect to camera manager!");
}
+ mBlockingCameraManager = new BlockingCameraManager(mCameraManager);
- mOpsThread = new Thread(new Runnable() {
- @Override
- public void run() {
- Looper.prepare();
- mOpsHandler = new OpsHandler();
- Looper.loop();
- }
- }, "CameraOpsThread");
+ mOpsThread = new HandlerThread("CameraOpsThread");
mOpsThread.start();
+ mOpsHandler = new Handler(mOpsThread.getLooper());
mRecordingStream = new CameraRecordingStream();
mStatus = STATUS_OK;
@@ -130,29 +131,18 @@ public class CameraOps {
mCameraManager.addAvailabilityListener(listener, mOpsHandler);
}
- public CameraProperties getCameraProperties() {
- checkOk();
- if (mCameraProperties == null) {
- throw new IllegalStateException("CameraProperties is not available");
- }
- return mCameraProperties;
- }
-
- public void openDevice(String cameraId)
- throws CameraAccessException, ApiFailureException {
+ public CameraCharacteristics getCameraCharacteristics() {
checkOk();
-
- if (mCamera != null) {
- throw new IllegalStateException("Already have open camera device");
+ if (mCameraCharacteristics == null) {
+ throw new IllegalStateException("CameraCharacteristics is not available");
}
-
- mCamera = mCameraManager.openCamera(cameraId);
+ return mCameraCharacteristics;
}
public void closeDevice()
throws ApiFailureException {
checkOk();
- mCameraProperties = null;
+ mCameraCharacteristics = null;
if (mCamera == null) return;
@@ -172,16 +162,27 @@ public class CameraOps {
if (devices == null || devices.length == 0) {
throw new ApiFailureException("no devices");
}
- mCamera = mCameraManager.openCamera(devices[0]);
- mCameraProperties = mCamera.getProperties();
+ mCamera = mBlockingCameraManager.openCamera(devices[0],
+ mDeviceListener, mOpsHandler);
+ mCameraCharacteristics = mCameraManager.getCameraCharacteristics(mCamera.getId());
} catch (CameraAccessException e) {
throw new ApiFailureException("open failure", e);
+ } catch (BlockingOpenException e) {
+ throw new ApiFailureException("open async failure", e);
}
}
mStatus = STATUS_OK;
}
+ private void configureOutputs(List<Surface> outputs) throws CameraAccessException {
+ mCamera.configureOutputs(outputs);
+ mDeviceListener.waitForState(BlockingStateListener.STATE_BUSY,
+ STATE_WAIT_MS);
+ mDeviceListener.waitForState(BlockingStateListener.STATE_IDLE,
+ IDLE_WAIT_MS);
+ }
+
/**
* Set up SurfaceView dimensions for camera preview
*/
@@ -189,13 +190,14 @@ public class CameraOps {
minimalOpenCamera();
try {
- CameraProperties properties = mCamera.getProperties();
+ CameraCharacteristics properties =
+ mCameraManager.getCameraCharacteristics(mCamera.getId());
Size[] previewSizes = null;
Size sz = DEFAULT_SIZE;
if (properties != null) {
previewSizes = properties.get(
- CameraProperties.SCALER_AVAILABLE_PROCESSED_SIZES);
+ CameraCharacteristics.SCALER_AVAILABLE_PROCESSED_SIZES);
}
if (previewSizes != null && previewSizes.length != 0 &&
@@ -231,17 +233,15 @@ public class CameraOps {
public void minimalPreview(SurfaceHolder previewHolder) throws ApiFailureException {
minimalOpenCamera();
+
if (mPreviewSurface == null) {
throw new ApiFailureException("Preview surface is not created");
}
try {
- mCamera.stopRepeating();
- mCamera.waitUntilIdle();
-
List<Surface> outputSurfaces = new ArrayList<Surface>(/*capacity*/1);
outputSurfaces.add(mPreviewSurface);
- mCamera.configureOutputs(outputSurfaces);
+ configureOutputs(outputSurfaces);
CaptureRequest.Builder previewBuilder;
mPreviewRequestBuilder = mCamera.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
@@ -259,14 +259,12 @@ public class CameraOps {
minimalOpenCamera();
try {
- mCamera.stopRepeating();
- mCamera.waitUntilIdle();
-
- CameraProperties properties = mCamera.getProperties();
+ CameraCharacteristics properties =
+ mCameraManager.getCameraCharacteristics(mCamera.getId());
Size[] jpegSizes = null;
if (properties != null) {
jpegSizes = properties.get(
- CameraProperties.SCALER_AVAILABLE_JPEG_SIZES);
+ CameraCharacteristics.SCALER_AVAILABLE_JPEG_SIZES);
}
int width = 640;
int height = 480;
@@ -288,7 +286,7 @@ public class CameraOps {
List<Surface> outputSurfaces = new ArrayList<Surface>(/*capacity*/1);
outputSurfaces.add(mCaptureReader.getSurface());
- mCamera.configureOutputs(outputSurfaces);
+ configureOutputs(outputSurfaces);
CaptureRequest.Builder captureBuilder =
mCamera.createCaptureRequest(CameraDevice.TEMPLATE_STILL_CAPTURE);
@@ -315,7 +313,6 @@ public class CameraOps {
mCaptureReader.setOnImageAvailableListener(readerListener, h);
mCamera.capture(captureBuilder.build(), l, mOpsHandler);
-
} catch (CameraAccessException e) {
throw new ApiFailureException("Error in minimal JPEG capture", e);
}
@@ -339,7 +336,7 @@ public class CameraOps {
mRecordingRequestBuilder.addTarget(mPreviewSurface);
// Start camera streaming and recording.
- mCamera.configureOutputs(mOutputSurfaces);
+ configureOutputs(mOutputSurfaces);
mCamera.setRepeatingRequest(mRecordingRequestBuilder.build(), null, null);
mRecordingStream.start();
} catch (CameraAccessException e) {
@@ -362,11 +359,13 @@ public class CameraOps {
*/
mRecordingStream.onConfiguringRequest(mRecordingRequestBuilder, /* detach */true);
mRecordingStream.onConfiguringOutputs(mOutputSurfaces, /* detach */true);
- mCamera.stopRepeating();
- mCamera.waitUntilIdle();
+
+ // Remove recording surface before calling RecordingStream.stop,
+ // since that invalidates the surface.
+ configureOutputs(mOutputSurfaces);
+
mRecordingStream.stop();
- mCamera.configureOutputs(mOutputSurfaces);
mCamera.setRepeatingRequest(mRecordingRequestBuilder.build(), null, null);
} catch (CameraAccessException e) {
throw new ApiFailureException("Error stop recording", e);
@@ -375,12 +374,13 @@ public class CameraOps {
private Size getRecordingSize() throws ApiFailureException {
try {
- CameraProperties properties = mCamera.getProperties();
+ CameraCharacteristics properties =
+ mCameraManager.getCameraCharacteristics(mCamera.getId());
Size[] recordingSizes = null;
if (properties != null) {
recordingSizes = properties.get(
- CameraProperties.SCALER_AVAILABLE_PROCESSED_SIZES);
+ CameraCharacteristics.SCALER_AVAILABLE_PROCESSED_SIZES);
}
mEncodingBitRate = ENC_BIT_RATE_LOW;
diff --git a/apps/TestingCamera2/src/com/android/testingcamera2/TestingCamera2.java b/apps/TestingCamera2/src/com/android/testingcamera2/TestingCamera2.java
index 596dd28..a3882df 100644
--- a/apps/TestingCamera2/src/com/android/testingcamera2/TestingCamera2.java
+++ b/apps/TestingCamera2/src/com/android/testingcamera2/TestingCamera2.java
@@ -17,11 +17,13 @@
package com.android.testingcamera2;
import android.app.Activity;
+import android.content.res.Configuration;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.ImageFormat;
+import android.hardware.camera2.CameraCharacteristics;
import android.hardware.camera2.CameraDevice;
-import android.hardware.camera2.CameraProperties;
+import android.hardware.camera2.CaptureFailure;
import android.hardware.camera2.CaptureRequest;
import android.hardware.camera2.CaptureResult;
import android.media.Image;
@@ -32,6 +34,7 @@ import android.util.Log;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
+import android.view.ViewGroup.LayoutParams;
import android.view.WindowManager;
import android.widget.Button;
import android.widget.ImageView;
@@ -58,7 +61,9 @@ public class TestingCamera2 extends Activity implements SurfaceHolder.Callback {
// Min and max sensitivity ISO values
private static final int MIN_SENSITIVITY = 100;
private static final int MAX_SENSITIVITY = 1600;
+ private static final int ORIENTATION_UNINITIALIZED = -1;
+ private int mLastOrientation = ORIENTATION_UNINITIALIZED;
private SurfaceView mPreviewView;
private ImageView mStillView;
@@ -78,7 +83,7 @@ public class TestingCamera2 extends Activity implements SurfaceHolder.Callback {
private ToggleButton mManualCtrlToggle;
private CameraControls mCameraControl = null;
- private Set<View> mManualControls = new HashSet<View>();
+ private final Set<View> mManualControls = new HashSet<View>();
Handler mMainHandler;
@@ -135,12 +140,18 @@ public class TestingCamera2 extends Activity implements SurfaceHolder.Callback {
} catch(ApiFailureException e) {
logException("Cannot create camera ops!",e);
}
+
+ // Process the initial configuration (for i.e. initial orientation)
+ // We need this because #onConfigurationChanged doesn't get called when the app launches
+ maybeUpdateConfiguration(getResources().getConfiguration());
}
@Override
public void onResume() {
super.onResume();
try {
+ if (VERBOSE) Log.v(TAG, String.format("onResume"));
+
mCameraOps.minimalPreviewConfig(mPreviewView.getHolder());
mCurrentPreviewHolder = mPreviewView.getHolder();
} catch (ApiFailureException e) {
@@ -152,6 +163,8 @@ public class TestingCamera2 extends Activity implements SurfaceHolder.Callback {
public void onPause() {
super.onPause();
try {
+ if (VERBOSE) Log.v(TAG, String.format("onPause"));
+
mCameraOps.closeDevice();
} catch (ApiFailureException e) {
logException("Can't close device: ",e);
@@ -159,12 +172,81 @@ public class TestingCamera2 extends Activity implements SurfaceHolder.Callback {
mCurrentPreviewHolder = null;
}
+ @Override
+ public void onConfigurationChanged(Configuration newConfig) {
+ super.onConfigurationChanged(newConfig);
+
+ if (VERBOSE) {
+ Log.v(TAG, String.format("onConfiguredChanged: orientation %x",
+ newConfig.orientation));
+ }
+
+ maybeUpdateConfiguration(newConfig);
+ }
+
+ private void maybeUpdateConfiguration(Configuration newConfig) {
+ if (VERBOSE) {
+ Log.v(TAG, String.format("handleConfiguration: orientation %x",
+ newConfig.orientation));
+ }
+
+ if (mLastOrientation != newConfig.orientation) {
+ mLastOrientation = newConfig.orientation;
+ updatePreviewOrientation();
+ }
+ }
+
+ private void updatePreviewOrientation() {
+ LayoutParams params = mPreviewView.getLayoutParams();
+ int width = params.width;
+ int height = params.height;
+
+ if (VERBOSE) {
+ Log.v(TAG, String.format(
+ "onConfiguredChanged: current layout is %dx%d", width,
+ height));
+ }
+ /**
+ * Force wide aspect ratios for landscape
+ * Force narrow aspect ratios for portrait
+ */
+ if (mLastOrientation == Configuration.ORIENTATION_LANDSCAPE) {
+ if (height > width) {
+ int tmp = width;
+ width = height;
+ height = tmp;
+ }
+ } else if (mLastOrientation == Configuration.ORIENTATION_PORTRAIT) {
+ if (width > height) {
+ int tmp = width;
+ width = height;
+ height = tmp;
+ }
+ }
+
+ if (width != params.width && height != params.height) {
+ if (VERBOSE) {
+ Log.v(TAG, String.format(
+ "onConfiguredChanged: updating preview size to %dx%d", width,
+ height));
+ }
+ params.width = width;
+ params.height = height;
+
+ mPreviewView.setLayoutParams(params);
+ }
+ }
+
/** SurfaceHolder.Callback methods */
@Override
public void surfaceChanged(SurfaceHolder holder,
int format,
int width,
int height) {
+ if (VERBOSE) {
+ Log.v(TAG, String.format("surfaceChanged: format %x, width %d, height %d", format,
+ width, height));
+ }
if (mCurrentPreviewHolder != null && holder == mCurrentPreviewHolder) {
try {
mCameraOps.minimalPreview(holder);
@@ -183,7 +265,7 @@ public class TestingCamera2 extends Activity implements SurfaceHolder.Callback {
public void surfaceDestroyed(SurfaceHolder holder) {
}
- private Button.OnClickListener mInfoButtonListener = new Button.OnClickListener() {
+ private final Button.OnClickListener mInfoButtonListener = new Button.OnClickListener() {
@Override
public void onClick(View v) {
final Handler uiHandler = new Handler();
@@ -213,7 +295,7 @@ public class TestingCamera2 extends Activity implements SurfaceHolder.Callback {
}
}
- private CameraOps.CaptureListener mCaptureListener = new CameraOps.CaptureListener() {
+ private final CameraOps.CaptureListener mCaptureListener = new CameraOps.CaptureListener() {
@Override
public void onCaptureAvailable(Image capture) {
if (capture.getFormat() != ImageFormat.JPEG) {
@@ -230,7 +312,7 @@ public class TestingCamera2 extends Activity implements SurfaceHolder.Callback {
};
// TODO: this callback is not called for each capture, need figure out why.
- private CameraOps.CaptureResultListener mCaptureResultListener =
+ private final CameraOps.CaptureResultListener mCaptureResultListener =
new CameraOps.CaptureResultListener() {
@Override
@@ -283,7 +365,8 @@ public class TestingCamera2 extends Activity implements SurfaceHolder.Callback {
}
@Override
- public void onCaptureFailed(CameraDevice camera, CaptureRequest request) {
+ public void onCaptureFailed(CameraDevice camera, CaptureRequest request,
+ CaptureFailure failure) {
Log.e(TAG, "Capture failed");
}
};
@@ -292,15 +375,15 @@ public class TestingCamera2 extends Activity implements SurfaceHolder.Callback {
Log.e(TAG, msg + Log.getStackTraceString(e));
}
- private OnSeekBarChangeListener mSensitivitySeekBarListener =
+ private final OnSeekBarChangeListener mSensitivitySeekBarListener =
new OnSeekBarChangeListener() {
@Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
int[] defaultRange = {MIN_SENSITIVITY, MAX_SENSITIVITY};
- CameraProperties properties = mCameraOps.getCameraProperties();
+ CameraCharacteristics properties = mCameraOps.getCameraCharacteristics();
int[] sensitivityRange = properties.get(
- CameraProperties.SENSOR_INFO_SENSITIVITY_RANGE);
+ CameraCharacteristics.SENSOR_INFO_SENSITIVITY_RANGE);
if (sensitivityRange == null || sensitivityRange.length < 2 ||
sensitivityRange[0] > MIN_SENSITIVITY || sensitivityRange[1] < MAX_SENSITIVITY) {
Log.e(TAG, "unable to get sensitivity range, use default range");
@@ -328,15 +411,15 @@ public class TestingCamera2 extends Activity implements SurfaceHolder.Callback {
}
};
- private OnSeekBarChangeListener mExposureSeekBarListener =
+ private final OnSeekBarChangeListener mExposureSeekBarListener =
new OnSeekBarChangeListener() {
@Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
long[] defaultRange = {MIN_EXPOSURE, MAX_EXPOSURE};
- CameraProperties properties = mCameraOps.getCameraProperties();
+ CameraCharacteristics properties = mCameraOps.getCameraCharacteristics();
long[] exposureRange = properties.get(
- CameraProperties.SENSOR_INFO_EXPOSURE_TIME_RANGE);
+ CameraCharacteristics.SENSOR_INFO_EXPOSURE_TIME_RANGE);
// Not enforce the max value check here, most of the devices don't support
// larger than 30s exposure time
if (exposureRange == null || exposureRange.length < 2 ||
@@ -365,14 +448,14 @@ public class TestingCamera2 extends Activity implements SurfaceHolder.Callback {
}
};
- private OnSeekBarChangeListener mFrameDurationSeekBarListener =
+ private final OnSeekBarChangeListener mFrameDurationSeekBarListener =
new OnSeekBarChangeListener() {
@Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
- CameraProperties properties = mCameraOps.getCameraProperties();
+ CameraCharacteristics properties = mCameraOps.getCameraCharacteristics();
Long frameDurationMax = properties.get(
- CameraProperties.SENSOR_INFO_MAX_FRAME_DURATION);
+ CameraCharacteristics.SENSOR_INFO_MAX_FRAME_DURATION);
if (frameDurationMax == null || frameDurationMax <= 0) {
frameDurationMax = MAX_FRAME_DURATION;
Log.e(TAG, "max frame duration is invalid, set to " + frameDurationMax);
@@ -399,7 +482,7 @@ public class TestingCamera2 extends Activity implements SurfaceHolder.Callback {
}
};
- private View.OnClickListener mControlToggleListener =
+ private final View.OnClickListener mControlToggleListener =
new View.OnClickListener() {
@Override
public void onClick(View v) {
@@ -415,7 +498,7 @@ public class TestingCamera2 extends Activity implements SurfaceHolder.Callback {
}
};
- private View.OnClickListener mRecordingToggleListener =
+ private final View.OnClickListener mRecordingToggleListener =
new View.OnClickListener() {
@Override
public void onClick(View v) {