summaryrefslogtreecommitdiff
path: root/apps/CameraITS/tests/scene2_a/test_auto_flash.py
diff options
context:
space:
mode:
Diffstat (limited to 'apps/CameraITS/tests/scene2_a/test_auto_flash.py')
-rw-r--r--apps/CameraITS/tests/scene2_a/test_auto_flash.py197
1 files changed, 74 insertions, 123 deletions
diff --git a/apps/CameraITS/tests/scene2_a/test_auto_flash.py b/apps/CameraITS/tests/scene2_a/test_auto_flash.py
index c00cd5c358c..f1b879bc1f6 100644
--- a/apps/CameraITS/tests/scene2_a/test_auto_flash.py
+++ b/apps/CameraITS/tests/scene2_a/test_auto_flash.py
@@ -1,4 +1,4 @@
-# Copyright 2022 The Android Open Source Project
+# 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.
@@ -11,30 +11,27 @@
# 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.
-"""Verifies that flash is fired when lighting conditions are dark."""
+"""Verifies android.flash.mode parameters is applied when set."""
import logging
import os.path
+from mobly import test_runner
+import its_base_test
import camera_properties_utils
import capture_request_utils
+import lighting_control_utils
import image_processing_utils
-import its_base_test
import its_session_utils
-import lighting_control_utils
-from mobly import test_runner
AE_MODES = {0: 'OFF', 1: 'ON', 2: 'ON_AUTO_FLASH', 3: 'ON_ALWAYS_FLASH',
4: 'ON_AUTO_FLASH_REDEYE', 5: 'ON_EXTERNAL_FLASH'}
AE_STATES = {0: 'INACTIVE', 1: 'SEARCHING', 2: 'CONVERGED', 3: 'LOCKED',
4: 'FLASH_REQUIRED', 5: 'PRECAPTURE'}
-FLASH_STATES = {0: 'FLASH_STATE_UNAVAILABLE', 1: 'FLASH_STATE_CHARGING',
- 2: 'FLASH_STATE_READY', 3: 'FLASH_STATE_FIRED',
- 4: 'FLASH_STATE_PARTIAL'}
-_GRAD_DELTA_ATOL = 15 # gradiant for tablets as screen aborbs energy
-_MEAN_DELTA_ATOL = 15 # mean used for reflective charts
-
+_GRAD_DELTA_ATOL = 50 # gradiant for tablets as screen aborbs energy
+_MEAN_DELTA_ATOL = 50 # mean used for reflective charts
+_NUM_FRAMES = 8
_PATCH_H = 0.25 # center 25%
_PATCH_W = 0.25
_PATCH_X = 0.5 - _PATCH_W/2
@@ -43,60 +40,27 @@ _TEST_NAME = os.path.splitext(os.path.basename(__file__))[0]
VGA_W, VGA_H = 640, 480
_CAPTURE_INTENT_STILL_CAPTURE = 2
_AE_MODE_ON_AUTO_FLASH = 2
-_CAPTURE_INTENT_PREVIEW = 1
-_CAPTURE_INTENT_STILL_CAPTURE = 2
-_AE_PRECAPTURE_TRIGGER_START = 1
-_AE_PRECAPTURE_TRIGGER_IDLE = 0
-
-
-def turn_off_tablet(tablet_device):
- output = tablet_device.adb.shell('dumpsys display | grep mScreenState')
- output_list = str(output.decode('utf-8')).strip().split(' ')
- for val in output_list:
- if 'ON' in val:
- tablet_device.adb.shell(['input', 'keyevent', 'KEYCODE_POWER'])
-
-
-def take_captures_with_flash(cam, fmt):
- # Run precapture sequence by setting the aePrecapture trigger to
- # START and capture intent set to Preview.
- preview_req_start = capture_request_utils.auto_capture_request()
- preview_req_start[
- 'android.control.aeMode'] = _AE_MODE_ON_AUTO_FLASH
- preview_req_start[
- 'android.control.captureIntent'] = _CAPTURE_INTENT_PREVIEW
- preview_req_start[
- 'android.control.aePrecaptureTrigger'] = _AE_PRECAPTURE_TRIGGER_START
- # Repeat preview requests with aePrecapture set to IDLE
- # until AE is converged.
- preview_req_idle = capture_request_utils.auto_capture_request()
- preview_req_idle[
- 'android.control.aeMode'] = _AE_MODE_ON_AUTO_FLASH
- preview_req_idle[
- 'android.control.captureIntent'] = _CAPTURE_INTENT_PREVIEW
- preview_req_idle[
- 'android.control.aePrecaptureTrigger'] = _AE_PRECAPTURE_TRIGGER_IDLE
- # Single still capture request.
- still_capture_req = capture_request_utils.auto_capture_request()
- still_capture_req[
- 'android.control.aeMode'] = _AE_MODE_ON_AUTO_FLASH
- still_capture_req[
- 'android.control.captureIntent'] = _CAPTURE_INTENT_STILL_CAPTURE
- still_capture_req[
- 'android.control.aePrecaptureTrigger'] = _AE_PRECAPTURE_TRIGGER_IDLE
- cap = cam.do_capture_with_flash(preview_req_start,
- preview_req_idle,
- still_capture_req, fmt)
- return cap
+
+
+def take_captures(cam, auto_flash=False):
+ req = capture_request_utils.auto_capture_request()
+ req['android.control.captureIntent'] = _CAPTURE_INTENT_STILL_CAPTURE
+ if auto_flash:
+ req['android.control.aeMode'] = _AE_MODE_ON_AUTO_FLASH
+ fmt = {'format': 'yuv', 'width': VGA_W, 'height': VGA_H}
+ captures = []
+ for _ in range(_NUM_FRAMES):
+ one_capture = cam.do_capture(req, fmt)
+ captures.append(one_capture)
+ return captures
class AutoFlashTest(its_base_test.ItsBaseTest):
- """Test that flash is fired when lighting conditions are dark."""
+ """Test that the android.flash.mode parameter is applied."""
def test_auto_flash(self):
logging.debug('AE_MODES: %s', str(AE_MODES))
logging.debug('AE_STATES: %s', str(AE_STATES))
- logging.debug('FLASH_STATES: %s', str(FLASH_STATES))
with its_session_utils.ItsSession(
device_id=self.dut.serial,
@@ -107,10 +71,10 @@ class AutoFlashTest(its_base_test.ItsBaseTest):
test_name = os.path.join(self.log_path, _TEST_NAME)
# check SKIP conditions
- vendor_api_level = its_session_utils.get_vendor_api_level(self.dut.serial)
+ first_api_level = its_session_utils.get_first_api_level(self.dut.serial)
camera_properties_utils.skip_unless(
camera_properties_utils.flash(props) and
- vendor_api_level >= its_session_utils.ANDROID13_API_LEVEL)
+ first_api_level >= its_session_utils.ANDROID13_API_LEVEL)
# establish connection with lighting controller
arduino_serial_port = lighting_control_utils.lighting_control(
@@ -122,22 +86,23 @@ class AutoFlashTest(its_base_test.ItsBaseTest):
# turn OFF tablet to darken scene
if self.tablet:
- turn_off_tablet(self.tablet)
- fmt_name = 'jpeg'
- fmt = {'format': fmt_name}
- logging.debug('Testing %s format.', fmt_name)
+ output = self.tablet.adb.shell('dumpsys display | grep mScreenState')
+ output_list = str(output.decode('utf-8')).strip().split(' ')
+ for val in output_list:
+ if 'ON' in val:
+ self.tablet.adb.shell(['input', 'keyevent', 'KEYCODE_POWER'])
+
no_flash_exp_x_iso = 0
no_flash_mean = 0
no_flash_grad = 0
flash_exp_x_iso = []
+ flash_means = []
+ flash_grads = []
- # take capture with no flash as baseline
- logging.debug('Taking reference frame with no flash.')
+ # take captures with no flash as baseline: use last frame
+ logging.debug('Taking reference frame(s) with no flash.')
cam.do_3a(do_af=False)
- no_flash_req = capture_request_utils.auto_capture_request()
- no_flash_req[
- 'android.control.captureIntent'] = _CAPTURE_INTENT_STILL_CAPTURE
- cap = cam.do_capture(no_flash_req, fmt)
+ cap = take_captures(cam)[_NUM_FRAMES-1]
metadata = cap['metadata']
exp = int(metadata['android.sensor.exposureTime'])
iso = int(metadata['android.sensor.sensitivity'])
@@ -155,79 +120,65 @@ class AutoFlashTest(its_base_test.ItsBaseTest):
patch)[0]*255
no_flash_grad = image_processing_utils.compute_image_max_gradients(
patch)[0]*255
- image_processing_utils.write_image(
- y, f'{test_name}_{fmt_name}_no_flash_Y.jpg')
+ image_processing_utils.write_image(y, f'{test_name}_no_flash_Y.jpg')
# log results
logging.debug('No flash exposure X ISO %d', no_flash_exp_x_iso)
logging.debug('No flash Y grad: %.4f', no_flash_grad)
logging.debug('No flash Y mean: %.4f', no_flash_mean)
- # take capture with auto flash enabled
- logging.debug('Taking capture with auto flash enabled.')
- flash_fired = False
-
- cap = take_captures_with_flash(cam, fmt)
- y, _, _ = image_processing_utils.convert_capture_to_planes(
- cap, props)
- # Save captured image
- image_processing_utils.write_image(y,
- f'{test_name}_{fmt_name}_flash_Y.jpg')
- # evaluate captured image
- metadata = cap['metadata']
- exp = int(metadata['android.sensor.exposureTime'])
- iso = int(metadata['android.sensor.sensitivity'])
- logging.debug('cap ISO: %d, exp: %d ns', iso, exp)
- logging.debug('AE_MODE (cap): %s',
- AE_MODES[metadata['android.control.aeMode']])
- ae_state = AE_STATES[metadata['android.control.aeState']]
- logging.debug('AE_STATE (cap): %s', ae_state)
- flash_state = FLASH_STATES[metadata['android.flash.state']]
- logging.debug('FLASH_STATE: %s', flash_state)
- # FLASH_REQUIRED and FLASH_FIRED
- if ae_state == 'FLASH_REQUIRED' and flash_state == 'FLASH_STATE_FIRED':
- logging.debug('Flash fired')
- flash_fired = True
- flash_exp_x_iso = exp*iso
+ # take captures with auto flash enabled
+ logging.debug('Taking frames with auto flash enabled.')
+ cam.do_3a(do_af=False, auto_flash=True)
+ caps = take_captures(cam, auto_flash=True)
+
+ # evaluate captured images
+ for i in range(_NUM_FRAMES):
+ logging.debug('frame # %d', i)
+ metadata = caps[i]['metadata']
+ exp = int(metadata['android.sensor.exposureTime'])
+ iso = int(metadata['android.sensor.sensitivity'])
+ logging.debug('ISO: %d, exp: %d ns', iso, exp)
+ logging.debug('AE_MODE (cap): %s',
+ AE_MODES[metadata['android.control.aeMode']])
+ ae_state = AE_STATES[metadata['android.control.aeState']]
+ logging.debug('AE_STATE (cap): %s', ae_state)
+ flash_exp_x_iso.append(exp*iso)
y, _, _ = image_processing_utils.convert_capture_to_planes(
- cap, props)
+ caps[i], props)
patch = image_processing_utils.get_image_patch(
y, _PATCH_X, _PATCH_Y, _PATCH_W, _PATCH_H)
- flash_mean = image_processing_utils.compute_image_means(
- patch)[0]*255
- flash_grad = image_processing_utils.compute_image_max_gradients(
- patch)[0]*255
+ flash_means.append(
+ image_processing_utils.compute_image_means(patch)[0]*255)
+ flash_grads.append(
+ image_processing_utils.compute_image_max_gradients(patch)[0]*255)
- if not flash_fired:
- raise AssertionError('Flash was not fired.')
+ image_processing_utils.write_image(
+ y, f'{test_name}_auto_flash_Y_{i}.jpg')
+
+ if i == 0:
+ if ae_state != AE_STATES[4]: # FLASH_REQUIRED
+ raise AssertionError('Scene not dark enough to trigger auto-flash. '
+ 'Check scene.')
# log results
- logging.debug('Flash exposure X ISO %d', flash_exp_x_iso)
- logging.debug('Flash frames Y grad: %.4f', flash_grad)
- logging.debug('Flash frames Y mean: %.4f', flash_mean)
+ logging.debug('Flash exposure X ISOs %s', str(flash_exp_x_iso))
+ logging.debug('Flash frames Y grads: %s', str(flash_grads))
+ logging.debug('Flash frames Y means: %s', str(flash_means))
+
+ # turn lights back ON
+ lighting_control_utils.set_lighting_state(
+ arduino_serial_port, self.lighting_ch, 'ON')
# assert correct behavior
- grad_delta = flash_grad - no_flash_grad
- mean_delta = flash_mean - no_flash_mean
+ grad_delta = max(flash_grads) - no_flash_grad
+ mean_delta = max(flash_means) - no_flash_mean
if not (grad_delta > _GRAD_DELTA_ATOL or
mean_delta > _MEAN_DELTA_ATOL):
raise AssertionError(
f'grad FLASH-OFF: {grad_delta:.3f}, ATOL: {_GRAD_DELTA_ATOL}, '
f'mean FLASH-OFF: {mean_delta:.3f}, ATOL: {_MEAN_DELTA_ATOL}')
- # Ensure that the flash is turned OFF after flash was fired.
- req = capture_request_utils.auto_capture_request()
- req['android.control.captureIntent'] = _CAPTURE_INTENT_STILL_CAPTURE
- cap = cam.do_capture(req, fmt)
- flash_state_after = FLASH_STATES[cap['metadata']['android.flash.state']]
- logging.debug('FLASH_STATE after flash fired: %s', flash_state_after)
- if flash_state_after != 'FLASH_STATE_READY':
- raise AssertionError('Flash should turn OFF after it was fired.')
-
- # turn lights back ON
- lighting_control_utils.set_lighting_state(
- arduino_serial_port, self.lighting_ch, 'ON')
-
if __name__ == '__main__':
test_runner.main()