1*b7c941bbSAndroid Build Coastguard Worker# Copyright 2014 The Android Open Source Project 2*b7c941bbSAndroid Build Coastguard Worker# 3*b7c941bbSAndroid Build Coastguard Worker# Licensed under the Apache License, Version 2.0 (the "License"); 4*b7c941bbSAndroid Build Coastguard Worker# you may not use this file except in compliance with the License. 5*b7c941bbSAndroid Build Coastguard Worker# You may obtain a copy of the License at 6*b7c941bbSAndroid Build Coastguard Worker# 7*b7c941bbSAndroid Build Coastguard Worker# http://www.apache.org/licenses/LICENSE-2.0 8*b7c941bbSAndroid Build Coastguard Worker# 9*b7c941bbSAndroid Build Coastguard Worker# Unless required by applicable law or agreed to in writing, software 10*b7c941bbSAndroid Build Coastguard Worker# distributed under the License is distributed on an "AS IS" BASIS, 11*b7c941bbSAndroid Build Coastguard Worker# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12*b7c941bbSAndroid Build Coastguard Worker# See the License for the specific language governing permissions and 13*b7c941bbSAndroid Build Coastguard Worker# limitations under the License. 14*b7c941bbSAndroid Build Coastguard Worker 15*b7c941bbSAndroid Build Coastguard Workerimport glob 16*b7c941bbSAndroid Build Coastguard Workerimport json 17*b7c941bbSAndroid Build Coastguard Workerimport logging 18*b7c941bbSAndroid Build Coastguard Workerimport os 19*b7c941bbSAndroid Build Coastguard Workerimport os.path 20*b7c941bbSAndroid Build Coastguard Workerimport re 21*b7c941bbSAndroid Build Coastguard Workerimport subprocess 22*b7c941bbSAndroid Build Coastguard Workerimport sys 23*b7c941bbSAndroid Build Coastguard Workerimport tempfile 24*b7c941bbSAndroid Build Coastguard Workerimport time 25*b7c941bbSAndroid Build Coastguard Workerimport types 26*b7c941bbSAndroid Build Coastguard Worker 27*b7c941bbSAndroid Build Coastguard Workerimport camera_properties_utils 28*b7c941bbSAndroid Build Coastguard Workerimport capture_request_utils 29*b7c941bbSAndroid Build Coastguard Workerimport image_processing_utils 30*b7c941bbSAndroid Build Coastguard Workerimport its_device_utils 31*b7c941bbSAndroid Build Coastguard Workerimport its_session_utils 32*b7c941bbSAndroid Build Coastguard Workerimport lighting_control_utils 33*b7c941bbSAndroid Build Coastguard Workerimport numpy as np 34*b7c941bbSAndroid Build Coastguard Workerimport yaml 35*b7c941bbSAndroid Build Coastguard Worker 36*b7c941bbSAndroid Build Coastguard Worker 37*b7c941bbSAndroid Build Coastguard WorkerYAML_FILE_DIR = os.environ['CAMERA_ITS_TOP'] 38*b7c941bbSAndroid Build Coastguard WorkerCONFIG_FILE = os.path.join(YAML_FILE_DIR, 'config.yml') 39*b7c941bbSAndroid Build Coastguard WorkerTEST_KEY_TABLET = 'tablet' 40*b7c941bbSAndroid Build Coastguard WorkerTEST_KEY_SENSOR_FUSION = 'sensor_fusion' 41*b7c941bbSAndroid Build Coastguard WorkerACTIVITY_START_WAIT = 1.5 # seconds 42*b7c941bbSAndroid Build Coastguard WorkerMERGE_RESULTS_TIMEOUT = 3600 # seconds 43*b7c941bbSAndroid Build Coastguard Worker 44*b7c941bbSAndroid Build Coastguard WorkerNUM_TRIES = 2 45*b7c941bbSAndroid Build Coastguard WorkerRESULT_PASS = 'PASS' 46*b7c941bbSAndroid Build Coastguard WorkerRESULT_FAIL = 'FAIL' 47*b7c941bbSAndroid Build Coastguard WorkerRESULT_NOT_EXECUTED = 'NOT_EXECUTED' 48*b7c941bbSAndroid Build Coastguard WorkerRESULT_KEY = 'result' 49*b7c941bbSAndroid Build Coastguard WorkerMETRICS_KEY = 'mpc_metrics' 50*b7c941bbSAndroid Build Coastguard WorkerPERFORMANCE_KEY = 'performance_metrics' 51*b7c941bbSAndroid Build Coastguard WorkerFEATURE_QUERY_KEY = 'feature_query_proto' 52*b7c941bbSAndroid Build Coastguard WorkerSUMMARY_KEY = 'summary' 53*b7c941bbSAndroid Build Coastguard WorkerRESULT_VALUES = (RESULT_PASS, RESULT_FAIL, RESULT_NOT_EXECUTED) 54*b7c941bbSAndroid Build Coastguard WorkerCTS_VERIFIER_PACKAGE_NAME = 'com.android.cts.verifier' 55*b7c941bbSAndroid Build Coastguard WorkerACTION_ITS_RESULT = 'com.android.cts.verifier.camera.its.ACTION_ITS_RESULT' 56*b7c941bbSAndroid Build Coastguard WorkerEXTRA_VERSION = 'camera.its.extra.VERSION' 57*b7c941bbSAndroid Build Coastguard WorkerCURRENT_ITS_VERSION = '1.0' # version number to sync with CtsVerifier 58*b7c941bbSAndroid Build Coastguard WorkerEXTRA_CAMERA_ID = 'camera.its.extra.CAMERA_ID' 59*b7c941bbSAndroid Build Coastguard WorkerEXTRA_RESULTS = 'camera.its.extra.RESULTS' 60*b7c941bbSAndroid Build Coastguard WorkerEXTRA_TABLET_NAME = 'camera.its.extra.TABLET_NAME' 61*b7c941bbSAndroid Build Coastguard WorkerTIME_KEY_START = 'start' 62*b7c941bbSAndroid Build Coastguard WorkerTIME_KEY_END = 'end' 63*b7c941bbSAndroid Build Coastguard WorkerVALID_CONTROLLERS = ('arduino', 'canakit') 64*b7c941bbSAndroid Build Coastguard Worker_FRONT_CAMERA_ID = '1' 65*b7c941bbSAndroid Build Coastguard Worker# recover replaced '_' in scene def 66*b7c941bbSAndroid Build Coastguard Worker_INT_STR_DICT = types.MappingProxyType({'11': '1_1', '12': '1_2'}) 67*b7c941bbSAndroid Build Coastguard Worker_MAIN_TESTBED = 0 68*b7c941bbSAndroid Build Coastguard Worker_PROPERTIES_TO_MATCH = ( 69*b7c941bbSAndroid Build Coastguard Worker 'ro.product.model', 'ro.product.name', 'ro.build.display.id', 'ro.revision' 70*b7c941bbSAndroid Build Coastguard Worker) 71*b7c941bbSAndroid Build Coastguard Worker 72*b7c941bbSAndroid Build Coastguard Worker# Scenes that can be automated through tablet display 73*b7c941bbSAndroid Build Coastguard Worker# Notes on scene names: 74*b7c941bbSAndroid Build Coastguard Worker# scene*_1/2/... are same scene split to load balance run times for scenes 75*b7c941bbSAndroid Build Coastguard Worker# scene*_a/b/... are similar scenes that share one or more tests 76*b7c941bbSAndroid Build Coastguard Worker_TABLET_SCENES = ( 77*b7c941bbSAndroid Build Coastguard Worker 'scene0', 'scene1_1', 'scene1_2', 'scene1_3', 'scene2_a', 'scene2_b', 78*b7c941bbSAndroid Build Coastguard Worker 'scene2_c', 'scene2_d', 'scene2_e', 'scene2_f', 'scene2_g', 'scene3', 79*b7c941bbSAndroid Build Coastguard Worker 'scene4', 'scene6', 'scene6_tele', 'scene7', 'scene8', 'scene9', 80*b7c941bbSAndroid Build Coastguard Worker os.path.join('scene_extensions', 'scene_hdr'), 81*b7c941bbSAndroid Build Coastguard Worker os.path.join('scene_extensions', 'scene_low_light'), 82*b7c941bbSAndroid Build Coastguard Worker 'scene_video', 83*b7c941bbSAndroid Build Coastguard Worker) 84*b7c941bbSAndroid Build Coastguard Worker 85*b7c941bbSAndroid Build Coastguard Worker# Scenes that use the 'sensor_fusion' test rig 86*b7c941bbSAndroid Build Coastguard Worker_MOTION_SCENES = ('sensor_fusion', 'feature_combination',) 87*b7c941bbSAndroid Build Coastguard Worker 88*b7c941bbSAndroid Build Coastguard Worker# Scenes that uses lighting control 89*b7c941bbSAndroid Build Coastguard Worker_FLASH_SCENES = ('scene_flash',) 90*b7c941bbSAndroid Build Coastguard Worker 91*b7c941bbSAndroid Build Coastguard Worker# Scenes that uses checkerboard as chart 92*b7c941bbSAndroid Build Coastguard Worker_CHECKERBOARD_SCENES = ('sensor_fusion', 'scene_flash', 'feature_combination',) 93*b7c941bbSAndroid Build Coastguard Worker 94*b7c941bbSAndroid Build Coastguard Worker# Scenes that have to be run manually regardless of configuration 95*b7c941bbSAndroid Build Coastguard Worker_MANUAL_SCENES = ('scene5',) 96*b7c941bbSAndroid Build Coastguard Worker 97*b7c941bbSAndroid Build Coastguard Worker# Scene extensions 98*b7c941bbSAndroid Build Coastguard Worker_EXTENSIONS_SCENES = (os.path.join('scene_extensions', 'scene_hdr'), 99*b7c941bbSAndroid Build Coastguard Worker os.path.join('scene_extensions', 'scene_low_light'), 100*b7c941bbSAndroid Build Coastguard Worker ) 101*b7c941bbSAndroid Build Coastguard Worker 102*b7c941bbSAndroid Build Coastguard Worker# All possible scenes 103*b7c941bbSAndroid Build Coastguard Worker_ALL_SCENES = _TABLET_SCENES + _MANUAL_SCENES + _MOTION_SCENES + _FLASH_SCENES 104*b7c941bbSAndroid Build Coastguard Worker 105*b7c941bbSAndroid Build Coastguard Worker# Scenes that are logically grouped and can be called as group 106*b7c941bbSAndroid Build Coastguard Worker# scene6_tele is not grouped with scene6 because it requires extension rig 107*b7c941bbSAndroid Build Coastguard Worker_GROUPED_SCENES = types.MappingProxyType({ 108*b7c941bbSAndroid Build Coastguard Worker 'scene1': ('scene1_1', 'scene1_2'), 109*b7c941bbSAndroid Build Coastguard Worker 'scene2': ('scene2_a', 'scene2_b', 'scene2_c', 'scene2_d', 'scene2_e', 110*b7c941bbSAndroid Build Coastguard Worker 'scene2_f', 'scene2_g') 111*b7c941bbSAndroid Build Coastguard Worker}) 112*b7c941bbSAndroid Build Coastguard Worker 113*b7c941bbSAndroid Build Coastguard Worker# Scene requirements for manual testing. 114*b7c941bbSAndroid Build Coastguard Worker_SCENE_REQ = types.MappingProxyType({ 115*b7c941bbSAndroid Build Coastguard Worker 'scene0': None, 116*b7c941bbSAndroid Build Coastguard Worker 'scene1_1': 'A grey card covering at least the middle 30% of the scene', 117*b7c941bbSAndroid Build Coastguard Worker 'scene1_2': 'A grey card covering at least the middle 30% of the scene', 118*b7c941bbSAndroid Build Coastguard Worker 'scene1_3': 'A grey card covering at least the middle 30% of the scene, ' 119*b7c941bbSAndroid Build Coastguard Worker 'without a white border like scene1_1 or scene1_2', 120*b7c941bbSAndroid Build Coastguard Worker 'scene2_a': 'The picture with 3 faces in tests/scene2_a/scene2_a.png', 121*b7c941bbSAndroid Build Coastguard Worker 'scene2_b': 'The picture with 3 faces in tests/scene2_b/scene2_b.png', 122*b7c941bbSAndroid Build Coastguard Worker 'scene2_c': 'The picture with 3 faces in tests/scene2_c/scene2_c.png', 123*b7c941bbSAndroid Build Coastguard Worker 'scene2_d': 'The picture with 3 faces in tests/scene2_d/scene2_d.png', 124*b7c941bbSAndroid Build Coastguard Worker 'scene2_e': 'The picture with 3 faces in tests/scene2_e/scene2_e.png', 125*b7c941bbSAndroid Build Coastguard Worker 'scene2_f': 'The picture with 3 faces in tests/scene2_f/scene2_f.png', 126*b7c941bbSAndroid Build Coastguard Worker 'scene2_g': 'The picture with 3 profile faces in tests/scene2_g/scene2_g.png', 127*b7c941bbSAndroid Build Coastguard Worker 'scene3': 'The ISO12233 chart', 128*b7c941bbSAndroid Build Coastguard Worker 'scene4': 'A test chart of a circle covering at least the middle 50% of ' 129*b7c941bbSAndroid Build Coastguard Worker 'the scene. See tests/scene4/scene4.png', 130*b7c941bbSAndroid Build Coastguard Worker 'scene5': 'Capture images with a diffuser attached to the camera. See ' 131*b7c941bbSAndroid Build Coastguard Worker 'source.android.com/docs/compatibility/cts/camera-its-tests#scene5/diffuser ' # pylint: disable line-too-long 132*b7c941bbSAndroid Build Coastguard Worker 'for more details', 133*b7c941bbSAndroid Build Coastguard Worker 'scene6': 'A grid of ArUco markers on a white background. ' 134*b7c941bbSAndroid Build Coastguard Worker 'See tests/scene6/scene6.png', 135*b7c941bbSAndroid Build Coastguard Worker 'scene6_tele': 'A grid of ArUco markers on a white background. Identical ' 136*b7c941bbSAndroid Build Coastguard Worker 'to scene6, but for tele cameras. ' 137*b7c941bbSAndroid Build Coastguard Worker 'See tests/scene6_tele/scene6_tele.png', 138*b7c941bbSAndroid Build Coastguard Worker 'scene7': 'The picture with 4 different colors, slanted edge and' 139*b7c941bbSAndroid Build Coastguard Worker '4 ArUco markers. See tests/scene7/scene7.png', 140*b7c941bbSAndroid Build Coastguard Worker 'scene8': 'The picture with 4 faces in 4 different colors overlay.' 141*b7c941bbSAndroid Build Coastguard Worker 'See tests/scene8/scene8.png', 142*b7c941bbSAndroid Build Coastguard Worker 'scene9': 'A scene with high entropy consisting of random size and colored ' 143*b7c941bbSAndroid Build Coastguard Worker 'circles. See tests/scene9/scene9.png', 144*b7c941bbSAndroid Build Coastguard Worker # Use os.path to avoid confusion on other platforms 145*b7c941bbSAndroid Build Coastguard Worker os.path.join('scene_extensions', 'scene_hdr'): ( 146*b7c941bbSAndroid Build Coastguard Worker 'A tablet displayed scene with a face on the left ' 147*b7c941bbSAndroid Build Coastguard Worker 'and a low-contrast QR code on the right. ' 148*b7c941bbSAndroid Build Coastguard Worker 'See tests/scene_extensions/scene_hdr/scene_hdr.png' 149*b7c941bbSAndroid Build Coastguard Worker ), 150*b7c941bbSAndroid Build Coastguard Worker os.path.join('scene_extensions', 'scene_low_light'): ( 151*b7c941bbSAndroid Build Coastguard Worker 'A tablet displayed scene with a grid of squares of varying ' 152*b7c941bbSAndroid Build Coastguard Worker 'brightness. See ' 153*b7c941bbSAndroid Build Coastguard Worker 'tests/scene_extensions/scene_low_light/scene_low_light.png' 154*b7c941bbSAndroid Build Coastguard Worker ), 155*b7c941bbSAndroid Build Coastguard Worker 'sensor_fusion': 'A checkerboard pattern for phone to rotate in front of ' 156*b7c941bbSAndroid Build Coastguard Worker 'in tests/sensor_fusion/checkerboard.pdf\n' 157*b7c941bbSAndroid Build Coastguard Worker 'See tests/sensor_fusion/SensorFusion.pdf for detailed ' 158*b7c941bbSAndroid Build Coastguard Worker 'instructions.\nNote that this test will be skipped ' 159*b7c941bbSAndroid Build Coastguard Worker 'on devices not supporting REALTIME camera timestamp.', 160*b7c941bbSAndroid Build Coastguard Worker 'feature_combination': 'The same scene as sensor_fusion, ' 161*b7c941bbSAndroid Build Coastguard Worker 'separated for easier testing.', 162*b7c941bbSAndroid Build Coastguard Worker 'scene_flash': 'A checkerboard pattern chart with lights off.', 163*b7c941bbSAndroid Build Coastguard Worker 'scene_video': 'A tablet displayed scene with a series of circles moving ' 164*b7c941bbSAndroid Build Coastguard Worker 'at different simulated frame rates. ' 165*b7c941bbSAndroid Build Coastguard Worker 'See tests/scene_video/scene_video.mp4', 166*b7c941bbSAndroid Build Coastguard Worker}) 167*b7c941bbSAndroid Build Coastguard Worker 168*b7c941bbSAndroid Build Coastguard Worker# Made mutable to allow for test augmentation based on first API level 169*b7c941bbSAndroid Build Coastguard WorkerSUB_CAMERA_TESTS = { 170*b7c941bbSAndroid Build Coastguard Worker 'scene0': ( 171*b7c941bbSAndroid Build Coastguard Worker 'test_jitter', 172*b7c941bbSAndroid Build Coastguard Worker 'test_metadata', 173*b7c941bbSAndroid Build Coastguard Worker 'test_request_capture_match', 174*b7c941bbSAndroid Build Coastguard Worker 'test_sensor_events', 175*b7c941bbSAndroid Build Coastguard Worker 'test_solid_color_test_pattern', 176*b7c941bbSAndroid Build Coastguard Worker 'test_unified_timestamps', 177*b7c941bbSAndroid Build Coastguard Worker ), 178*b7c941bbSAndroid Build Coastguard Worker 'scene1_1': ( 179*b7c941bbSAndroid Build Coastguard Worker 'test_burst_capture', 180*b7c941bbSAndroid Build Coastguard Worker 'test_burst_sameness_manual', 181*b7c941bbSAndroid Build Coastguard Worker 'test_exposure_x_iso', 182*b7c941bbSAndroid Build Coastguard Worker 'test_linearity', 183*b7c941bbSAndroid Build Coastguard Worker ), 184*b7c941bbSAndroid Build Coastguard Worker 'scene1_2': ( 185*b7c941bbSAndroid Build Coastguard Worker 'test_raw_exposure', 186*b7c941bbSAndroid Build Coastguard Worker ), 187*b7c941bbSAndroid Build Coastguard Worker 'scene1_3': ( 188*b7c941bbSAndroid Build Coastguard Worker 'test_dng_noise_model', 189*b7c941bbSAndroid Build Coastguard Worker 'test_raw_sensitivity', 190*b7c941bbSAndroid Build Coastguard Worker 'test_yuv_plus_raw', 191*b7c941bbSAndroid Build Coastguard Worker ), 192*b7c941bbSAndroid Build Coastguard Worker 'scene2_a': ( 193*b7c941bbSAndroid Build Coastguard Worker 'test_num_faces', 194*b7c941bbSAndroid Build Coastguard Worker ), 195*b7c941bbSAndroid Build Coastguard Worker 'scene4': ( 196*b7c941bbSAndroid Build Coastguard Worker 'test_aspect_ratio_and_crop', 197*b7c941bbSAndroid Build Coastguard Worker ), 198*b7c941bbSAndroid Build Coastguard Worker 'scene6_tele': ( 199*b7c941bbSAndroid Build Coastguard Worker 'test_zoom_tele', 200*b7c941bbSAndroid Build Coastguard Worker ), 201*b7c941bbSAndroid Build Coastguard Worker 'scene_video': ( 202*b7c941bbSAndroid Build Coastguard Worker 'test_preview_frame_drop', 203*b7c941bbSAndroid Build Coastguard Worker ), 204*b7c941bbSAndroid Build Coastguard Worker 'sensor_fusion': ( 205*b7c941bbSAndroid Build Coastguard Worker 'test_sensor_fusion', 206*b7c941bbSAndroid Build Coastguard Worker ), 207*b7c941bbSAndroid Build Coastguard Worker} 208*b7c941bbSAndroid Build Coastguard Worker 209*b7c941bbSAndroid Build Coastguard Worker_LIGHTING_CONTROL_TESTS = ( 210*b7c941bbSAndroid Build Coastguard Worker 'test_auto_flash.py', 211*b7c941bbSAndroid Build Coastguard Worker 'test_preview_min_frame_rate.py', 212*b7c941bbSAndroid Build Coastguard Worker 'test_led_snapshot.py', 213*b7c941bbSAndroid Build Coastguard Worker 'test_night_extension.py', 214*b7c941bbSAndroid Build Coastguard Worker 'test_low_light_boost_extension.py', 215*b7c941bbSAndroid Build Coastguard Worker 'test_hdr_extension.py', 216*b7c941bbSAndroid Build Coastguard Worker ) 217*b7c941bbSAndroid Build Coastguard Worker 218*b7c941bbSAndroid Build Coastguard Worker_EXTENSION_NAMES = ( 219*b7c941bbSAndroid Build Coastguard Worker 'hdr', 220*b7c941bbSAndroid Build Coastguard Worker 'low_light', 221*b7c941bbSAndroid Build Coastguard Worker) 222*b7c941bbSAndroid Build Coastguard Worker 223*b7c941bbSAndroid Build Coastguard Worker_DST_SCENE_DIR = '/sdcard/Download/' 224*b7c941bbSAndroid Build Coastguard Worker_SUB_CAMERA_LEVELS = 2 225*b7c941bbSAndroid Build Coastguard WorkerMOBLY_TEST_SUMMARY_TXT_FILE = 'test_mobly_summary.txt' 226*b7c941bbSAndroid Build Coastguard Worker 227*b7c941bbSAndroid Build Coastguard Worker 228*b7c941bbSAndroid Build Coastguard Workerdef report_result(device_id, camera_id, tablet_name, results): 229*b7c941bbSAndroid Build Coastguard Worker """Sends a pass/fail result to the device, via an intent. 230*b7c941bbSAndroid Build Coastguard Worker 231*b7c941bbSAndroid Build Coastguard Worker Args: 232*b7c941bbSAndroid Build Coastguard Worker device_id: The ID string of the device to report the results to. 233*b7c941bbSAndroid Build Coastguard Worker camera_id: The ID string of the camera for which to report pass/fail. 234*b7c941bbSAndroid Build Coastguard Worker tablet_name: The tablet name to identify model and build. 235*b7c941bbSAndroid Build Coastguard Worker results: a dictionary contains all ITS scenes as key and result/summary of 236*b7c941bbSAndroid Build Coastguard Worker current ITS run. See test_report_result unit test for an example. 237*b7c941bbSAndroid Build Coastguard Worker """ 238*b7c941bbSAndroid Build Coastguard Worker adb = f'adb -s {device_id}' 239*b7c941bbSAndroid Build Coastguard Worker its_device_utils.start_its_test_activity(device_id) 240*b7c941bbSAndroid Build Coastguard Worker time.sleep(ACTIVITY_START_WAIT) 241*b7c941bbSAndroid Build Coastguard Worker 242*b7c941bbSAndroid Build Coastguard Worker # Validate/process results argument 243*b7c941bbSAndroid Build Coastguard Worker for scene in results: 244*b7c941bbSAndroid Build Coastguard Worker if RESULT_KEY not in results[scene]: 245*b7c941bbSAndroid Build Coastguard Worker raise ValueError(f'ITS result not found for {scene}') 246*b7c941bbSAndroid Build Coastguard Worker if results[scene][RESULT_KEY] not in RESULT_VALUES: 247*b7c941bbSAndroid Build Coastguard Worker raise ValueError(f'Unknown ITS result for {scene}: {results[RESULT_KEY]}') 248*b7c941bbSAndroid Build Coastguard Worker if SUMMARY_KEY in results[scene]: 249*b7c941bbSAndroid Build Coastguard Worker device_summary_path = f'/sdcard/its_camera{camera_id}_{scene}.txt' 250*b7c941bbSAndroid Build Coastguard Worker its_device_utils.run( 251*b7c941bbSAndroid Build Coastguard Worker f'{adb} push {results[scene][SUMMARY_KEY]} {device_summary_path}') 252*b7c941bbSAndroid Build Coastguard Worker results[scene][SUMMARY_KEY] = device_summary_path 253*b7c941bbSAndroid Build Coastguard Worker 254*b7c941bbSAndroid Build Coastguard Worker json_results = json.dumps(results) 255*b7c941bbSAndroid Build Coastguard Worker cmd = (f"{adb} shell am broadcast -a {ACTION_ITS_RESULT} --es {EXTRA_VERSION}" 256*b7c941bbSAndroid Build Coastguard Worker f" {CURRENT_ITS_VERSION} --es {EXTRA_CAMERA_ID} {camera_id} --es " 257*b7c941bbSAndroid Build Coastguard Worker f"{EXTRA_TABLET_NAME} {tablet_name} --es " 258*b7c941bbSAndroid Build Coastguard Worker f"{EXTRA_RESULTS} \'{json_results}\'") 259*b7c941bbSAndroid Build Coastguard Worker its_device_utils.run(cmd) 260*b7c941bbSAndroid Build Coastguard Worker 261*b7c941bbSAndroid Build Coastguard Worker 262*b7c941bbSAndroid Build Coastguard Workerdef write_result(testbed_index, device_id, camera_id, results): 263*b7c941bbSAndroid Build Coastguard Worker """Writes results to a temporary file for merging. 264*b7c941bbSAndroid Build Coastguard Worker 265*b7c941bbSAndroid Build Coastguard Worker Args: 266*b7c941bbSAndroid Build Coastguard Worker testbed_index: the index of a finished testbed. 267*b7c941bbSAndroid Build Coastguard Worker device_id: the ID string of the device that created results. 268*b7c941bbSAndroid Build Coastguard Worker camera_id: the ID string of the camera of the device. 269*b7c941bbSAndroid Build Coastguard Worker results: a dictionary that contains all ITS scenes as key 270*b7c941bbSAndroid Build Coastguard Worker and result/summary of current ITS run. 271*b7c941bbSAndroid Build Coastguard Worker """ 272*b7c941bbSAndroid Build Coastguard Worker result = {'device_id': device_id, 'results': results} 273*b7c941bbSAndroid Build Coastguard Worker file_name = f'testbed_{testbed_index}_camera_{camera_id}.tmp' 274*b7c941bbSAndroid Build Coastguard Worker with open(file_name, 'w') as f: 275*b7c941bbSAndroid Build Coastguard Worker json.dump(result, f) 276*b7c941bbSAndroid Build Coastguard Worker 277*b7c941bbSAndroid Build Coastguard Worker 278*b7c941bbSAndroid Build Coastguard Workerdef parse_testbeds(completed_testbeds): 279*b7c941bbSAndroid Build Coastguard Worker """Parses completed testbeds and yields device_id, camera_id, and results. 280*b7c941bbSAndroid Build Coastguard Worker 281*b7c941bbSAndroid Build Coastguard Worker Args: 282*b7c941bbSAndroid Build Coastguard Worker completed_testbeds: an iterable of completed testbed indices. 283*b7c941bbSAndroid Build Coastguard Worker Yields: 284*b7c941bbSAndroid Build Coastguard Worker device_id: the device associated with the testbed. 285*b7c941bbSAndroid Build Coastguard Worker camera_id: one of the camera_ids associated with the testbed. 286*b7c941bbSAndroid Build Coastguard Worker results: the dictionary with scenes and result/summary of testbed's run. 287*b7c941bbSAndroid Build Coastguard Worker """ 288*b7c941bbSAndroid Build Coastguard Worker for i in completed_testbeds: 289*b7c941bbSAndroid Build Coastguard Worker for file_name in glob.glob(f'testbed_{i}_camera_*.tmp'): 290*b7c941bbSAndroid Build Coastguard Worker camera_id = file_name.split('camera_')[1].split('.tmp')[0] 291*b7c941bbSAndroid Build Coastguard Worker device_id = '' 292*b7c941bbSAndroid Build Coastguard Worker results = {} 293*b7c941bbSAndroid Build Coastguard Worker with open(file_name, 'r') as f: 294*b7c941bbSAndroid Build Coastguard Worker testbed_data = json.load(f) 295*b7c941bbSAndroid Build Coastguard Worker device_id = testbed_data['device_id'] 296*b7c941bbSAndroid Build Coastguard Worker results = testbed_data['results'] 297*b7c941bbSAndroid Build Coastguard Worker if not device_id or not results: 298*b7c941bbSAndroid Build Coastguard Worker raise ValueError(f'device_id or results for {file_name} not found.') 299*b7c941bbSAndroid Build Coastguard Worker yield device_id, camera_id, results 300*b7c941bbSAndroid Build Coastguard Worker 301*b7c941bbSAndroid Build Coastguard Worker 302*b7c941bbSAndroid Build Coastguard Workerdef get_device_property(device_id, property_name): 303*b7c941bbSAndroid Build Coastguard Worker """Get property of a given device. 304*b7c941bbSAndroid Build Coastguard Worker 305*b7c941bbSAndroid Build Coastguard Worker Args: 306*b7c941bbSAndroid Build Coastguard Worker device_id: the ID string of a device. 307*b7c941bbSAndroid Build Coastguard Worker property_name: the desired property string. 308*b7c941bbSAndroid Build Coastguard Worker Returns: 309*b7c941bbSAndroid Build Coastguard Worker The value of the property. 310*b7c941bbSAndroid Build Coastguard Worker """ 311*b7c941bbSAndroid Build Coastguard Worker property_cmd = f'adb -s {device_id} shell getprop {property_name}' 312*b7c941bbSAndroid Build Coastguard Worker raw_output = subprocess.check_output( 313*b7c941bbSAndroid Build Coastguard Worker property_cmd, stderr=subprocess.STDOUT, shell=True) 314*b7c941bbSAndroid Build Coastguard Worker return str(raw_output.decode('utf-8')).strip() 315*b7c941bbSAndroid Build Coastguard Worker 316*b7c941bbSAndroid Build Coastguard Worker 317*b7c941bbSAndroid Build Coastguard Workerdef are_devices_similar(device_id_1, device_id_2): 318*b7c941bbSAndroid Build Coastguard Worker """Checks if key dimensions are the same between devices. 319*b7c941bbSAndroid Build Coastguard Worker 320*b7c941bbSAndroid Build Coastguard Worker Args: 321*b7c941bbSAndroid Build Coastguard Worker device_id_1: the ID string of the _MAIN_TESTBED device. 322*b7c941bbSAndroid Build Coastguard Worker device_id_2: the ID string of another device. 323*b7c941bbSAndroid Build Coastguard Worker Returns: 324*b7c941bbSAndroid Build Coastguard Worker True if both devices share key dimensions. 325*b7c941bbSAndroid Build Coastguard Worker """ 326*b7c941bbSAndroid Build Coastguard Worker for property_to_match in _PROPERTIES_TO_MATCH: 327*b7c941bbSAndroid Build Coastguard Worker property_value_1 = get_device_property(device_id_1, property_to_match) 328*b7c941bbSAndroid Build Coastguard Worker property_value_2 = get_device_property(device_id_2, property_to_match) 329*b7c941bbSAndroid Build Coastguard Worker if property_value_1 != property_value_2: 330*b7c941bbSAndroid Build Coastguard Worker logging.error('%s does not match %s for %s', 331*b7c941bbSAndroid Build Coastguard Worker property_value_1, property_value_2, property_to_match) 332*b7c941bbSAndroid Build Coastguard Worker return False 333*b7c941bbSAndroid Build Coastguard Worker return True 334*b7c941bbSAndroid Build Coastguard Worker 335*b7c941bbSAndroid Build Coastguard Worker 336*b7c941bbSAndroid Build Coastguard Workerdef check_manual_scenes(device_id, camera_id, scene, out_path): 337*b7c941bbSAndroid Build Coastguard Worker """Halt run to change scenes. 338*b7c941bbSAndroid Build Coastguard Worker 339*b7c941bbSAndroid Build Coastguard Worker Args: 340*b7c941bbSAndroid Build Coastguard Worker device_id: id of device 341*b7c941bbSAndroid Build Coastguard Worker camera_id: id of camera 342*b7c941bbSAndroid Build Coastguard Worker scene: Name of the scene to copy image files. 343*b7c941bbSAndroid Build Coastguard Worker out_path: output file location 344*b7c941bbSAndroid Build Coastguard Worker """ 345*b7c941bbSAndroid Build Coastguard Worker hidden_physical_id = None 346*b7c941bbSAndroid Build Coastguard Worker if its_session_utils.SUB_CAMERA_SEPARATOR in camera_id: 347*b7c941bbSAndroid Build Coastguard Worker split_camera_ids = camera_id.split(its_session_utils.SUB_CAMERA_SEPARATOR) 348*b7c941bbSAndroid Build Coastguard Worker if len(split_camera_ids) == _SUB_CAMERA_LEVELS: 349*b7c941bbSAndroid Build Coastguard Worker camera_id = split_camera_ids[0] 350*b7c941bbSAndroid Build Coastguard Worker hidden_physical_id = split_camera_ids[1] 351*b7c941bbSAndroid Build Coastguard Worker 352*b7c941bbSAndroid Build Coastguard Worker with its_session_utils.ItsSession( 353*b7c941bbSAndroid Build Coastguard Worker device_id=device_id, 354*b7c941bbSAndroid Build Coastguard Worker camera_id=camera_id, 355*b7c941bbSAndroid Build Coastguard Worker hidden_physical_id=hidden_physical_id) as cam: 356*b7c941bbSAndroid Build Coastguard Worker props = cam.get_camera_properties() 357*b7c941bbSAndroid Build Coastguard Worker props = cam.override_with_hidden_physical_camera_props(props) 358*b7c941bbSAndroid Build Coastguard Worker 359*b7c941bbSAndroid Build Coastguard Worker while True: 360*b7c941bbSAndroid Build Coastguard Worker input(f'\n Press <ENTER> after positioning camera {camera_id} with ' 361*b7c941bbSAndroid Build Coastguard Worker f'{scene}.\n The scene setup should be: \n {_SCENE_REQ[scene]}\n') 362*b7c941bbSAndroid Build Coastguard Worker # Converge 3A prior to capture 363*b7c941bbSAndroid Build Coastguard Worker if scene == 'scene5': 364*b7c941bbSAndroid Build Coastguard Worker cam.do_3a(do_af=False, lock_ae=camera_properties_utils.ae_lock(props), 365*b7c941bbSAndroid Build Coastguard Worker lock_awb=camera_properties_utils.awb_lock(props)) 366*b7c941bbSAndroid Build Coastguard Worker else: 367*b7c941bbSAndroid Build Coastguard Worker cam.do_3a() 368*b7c941bbSAndroid Build Coastguard Worker req, fmt = capture_request_utils.get_fastest_auto_capture_settings(props) 369*b7c941bbSAndroid Build Coastguard Worker logging.info('Capturing an image to check the test scene') 370*b7c941bbSAndroid Build Coastguard Worker cap = cam.do_capture(req, fmt) 371*b7c941bbSAndroid Build Coastguard Worker img = image_processing_utils.convert_capture_to_rgb_image(cap) 372*b7c941bbSAndroid Build Coastguard Worker img_name = os.path.join(out_path, f'test_{scene.replace("/", "_")}.jpg') 373*b7c941bbSAndroid Build Coastguard Worker logging.info('Please check scene setup in %s', img_name) 374*b7c941bbSAndroid Build Coastguard Worker image_processing_utils.write_image(img, img_name) 375*b7c941bbSAndroid Build Coastguard Worker choice = input(f'Is the image okay for ITS {scene}? (Y/N)').lower() 376*b7c941bbSAndroid Build Coastguard Worker if choice == 'y': 377*b7c941bbSAndroid Build Coastguard Worker break 378*b7c941bbSAndroid Build Coastguard Worker 379*b7c941bbSAndroid Build Coastguard Worker 380*b7c941bbSAndroid Build Coastguard Workerdef get_config_file_contents(): 381*b7c941bbSAndroid Build Coastguard Worker """Read the config file contents from a YML file. 382*b7c941bbSAndroid Build Coastguard Worker 383*b7c941bbSAndroid Build Coastguard Worker Args: 384*b7c941bbSAndroid Build Coastguard Worker None 385*b7c941bbSAndroid Build Coastguard Worker 386*b7c941bbSAndroid Build Coastguard Worker Returns: 387*b7c941bbSAndroid Build Coastguard Worker config_file_contents: a dict read from config.yml 388*b7c941bbSAndroid Build Coastguard Worker """ 389*b7c941bbSAndroid Build Coastguard Worker with open(CONFIG_FILE) as file: 390*b7c941bbSAndroid Build Coastguard Worker config_file_contents = yaml.safe_load(file) 391*b7c941bbSAndroid Build Coastguard Worker return config_file_contents 392*b7c941bbSAndroid Build Coastguard Worker 393*b7c941bbSAndroid Build Coastguard Worker 394*b7c941bbSAndroid Build Coastguard Workerdef get_test_params(config_file_contents): 395*b7c941bbSAndroid Build Coastguard Worker """Reads the config file parameters. 396*b7c941bbSAndroid Build Coastguard Worker 397*b7c941bbSAndroid Build Coastguard Worker Args: 398*b7c941bbSAndroid Build Coastguard Worker config_file_contents: dict read from config.yml file 399*b7c941bbSAndroid Build Coastguard Worker 400*b7c941bbSAndroid Build Coastguard Worker Returns: 401*b7c941bbSAndroid Build Coastguard Worker dict of test parameters 402*b7c941bbSAndroid Build Coastguard Worker """ 403*b7c941bbSAndroid Build Coastguard Worker test_params = None 404*b7c941bbSAndroid Build Coastguard Worker for _, j in config_file_contents.items(): 405*b7c941bbSAndroid Build Coastguard Worker for datadict in j: 406*b7c941bbSAndroid Build Coastguard Worker test_params = datadict.get('TestParams') 407*b7c941bbSAndroid Build Coastguard Worker return test_params 408*b7c941bbSAndroid Build Coastguard Worker 409*b7c941bbSAndroid Build Coastguard Worker 410*b7c941bbSAndroid Build Coastguard Workerdef get_device_serial_number(device, config_file_contents): 411*b7c941bbSAndroid Build Coastguard Worker """Returns the serial number of the device with label from the config file. 412*b7c941bbSAndroid Build Coastguard Worker 413*b7c941bbSAndroid Build Coastguard Worker The config file contains TestBeds dictionary which contains Controllers and 414*b7c941bbSAndroid Build Coastguard Worker Android Device dicts.The two devices used by the test per box are listed 415*b7c941bbSAndroid Build Coastguard Worker here labels dut and tablet. Parse through the nested TestBeds dict to get 416*b7c941bbSAndroid Build Coastguard Worker the Android device details. 417*b7c941bbSAndroid Build Coastguard Worker 418*b7c941bbSAndroid Build Coastguard Worker Args: 419*b7c941bbSAndroid Build Coastguard Worker device: String device label as specified in config file.dut/tablet 420*b7c941bbSAndroid Build Coastguard Worker config_file_contents: dict read from config.yml file 421*b7c941bbSAndroid Build Coastguard Worker """ 422*b7c941bbSAndroid Build Coastguard Worker 423*b7c941bbSAndroid Build Coastguard Worker for _, j in config_file_contents.items(): 424*b7c941bbSAndroid Build Coastguard Worker for datadict in j: 425*b7c941bbSAndroid Build Coastguard Worker android_device_contents = datadict.get('Controllers') 426*b7c941bbSAndroid Build Coastguard Worker for device_dict in android_device_contents.get('AndroidDevice'): 427*b7c941bbSAndroid Build Coastguard Worker for _, label in device_dict.items(): 428*b7c941bbSAndroid Build Coastguard Worker if label == 'tablet': 429*b7c941bbSAndroid Build Coastguard Worker tablet_device_id = str(device_dict.get('serial')) 430*b7c941bbSAndroid Build Coastguard Worker if label == 'dut': 431*b7c941bbSAndroid Build Coastguard Worker dut_device_id = str(device_dict.get('serial')) 432*b7c941bbSAndroid Build Coastguard Worker if device == 'tablet': 433*b7c941bbSAndroid Build Coastguard Worker return tablet_device_id 434*b7c941bbSAndroid Build Coastguard Worker else: 435*b7c941bbSAndroid Build Coastguard Worker return dut_device_id 436*b7c941bbSAndroid Build Coastguard Worker 437*b7c941bbSAndroid Build Coastguard Worker 438*b7c941bbSAndroid Build Coastguard Workerdef get_updated_yml_file(yml_file_contents): 439*b7c941bbSAndroid Build Coastguard Worker """Create a new yml file and write the testbed contents in it. 440*b7c941bbSAndroid Build Coastguard Worker 441*b7c941bbSAndroid Build Coastguard Worker This testbed file is per box and contains all the parameters and 442*b7c941bbSAndroid Build Coastguard Worker device id used by the mobly tests. 443*b7c941bbSAndroid Build Coastguard Worker 444*b7c941bbSAndroid Build Coastguard Worker Args: 445*b7c941bbSAndroid Build Coastguard Worker yml_file_contents: Data to write in yml file. 446*b7c941bbSAndroid Build Coastguard Worker 447*b7c941bbSAndroid Build Coastguard Worker Returns: 448*b7c941bbSAndroid Build Coastguard Worker Updated yml file contents. 449*b7c941bbSAndroid Build Coastguard Worker """ 450*b7c941bbSAndroid Build Coastguard Worker os.chmod(YAML_FILE_DIR, 0o755) 451*b7c941bbSAndroid Build Coastguard Worker file_descriptor, new_yaml_file = tempfile.mkstemp( 452*b7c941bbSAndroid Build Coastguard Worker suffix='.yml', prefix='config_', dir=YAML_FILE_DIR) 453*b7c941bbSAndroid Build Coastguard Worker os.close(file_descriptor) 454*b7c941bbSAndroid Build Coastguard Worker with open(new_yaml_file, 'w') as f: 455*b7c941bbSAndroid Build Coastguard Worker yaml.dump(yml_file_contents, stream=f, default_flow_style=False) 456*b7c941bbSAndroid Build Coastguard Worker new_yaml_file_name = os.path.basename(new_yaml_file) 457*b7c941bbSAndroid Build Coastguard Worker return new_yaml_file_name 458*b7c941bbSAndroid Build Coastguard Worker 459*b7c941bbSAndroid Build Coastguard Worker 460*b7c941bbSAndroid Build Coastguard Workerdef enable_external_storage(device_id): 461*b7c941bbSAndroid Build Coastguard Worker """Override apk mode to allow write to external storage. 462*b7c941bbSAndroid Build Coastguard Worker 463*b7c941bbSAndroid Build Coastguard Worker Args: 464*b7c941bbSAndroid Build Coastguard Worker device_id: Serial number of the device. 465*b7c941bbSAndroid Build Coastguard Worker 466*b7c941bbSAndroid Build Coastguard Worker """ 467*b7c941bbSAndroid Build Coastguard Worker cmd = (f'adb -s {device_id} shell appops ' 468*b7c941bbSAndroid Build Coastguard Worker 'set com.android.cts.verifier MANAGE_EXTERNAL_STORAGE allow') 469*b7c941bbSAndroid Build Coastguard Worker its_device_utils.run(cmd) 470*b7c941bbSAndroid Build Coastguard Worker 471*b7c941bbSAndroid Build Coastguard Worker 472*b7c941bbSAndroid Build Coastguard Workerdef get_available_cameras(device_id, camera_id): 473*b7c941bbSAndroid Build Coastguard Worker """Get available camera devices in the current state. 474*b7c941bbSAndroid Build Coastguard Worker 475*b7c941bbSAndroid Build Coastguard Worker Args: 476*b7c941bbSAndroid Build Coastguard Worker device_id: Serial number of the device. 477*b7c941bbSAndroid Build Coastguard Worker camera_id: Logical camera_id 478*b7c941bbSAndroid Build Coastguard Worker 479*b7c941bbSAndroid Build Coastguard Worker Returns: 480*b7c941bbSAndroid Build Coastguard Worker List of all the available camera_ids. 481*b7c941bbSAndroid Build Coastguard Worker """ 482*b7c941bbSAndroid Build Coastguard Worker with its_session_utils.ItsSession( 483*b7c941bbSAndroid Build Coastguard Worker device_id=device_id, 484*b7c941bbSAndroid Build Coastguard Worker camera_id=camera_id) as cam: 485*b7c941bbSAndroid Build Coastguard Worker props = cam.get_camera_properties() 486*b7c941bbSAndroid Build Coastguard Worker props = cam.override_with_hidden_physical_camera_props(props) 487*b7c941bbSAndroid Build Coastguard Worker unavailable_physical_cameras = cam.get_unavailable_physical_cameras( 488*b7c941bbSAndroid Build Coastguard Worker camera_id) 489*b7c941bbSAndroid Build Coastguard Worker unavailable_physical_ids = unavailable_physical_cameras[ 490*b7c941bbSAndroid Build Coastguard Worker 'unavailablePhysicalCamerasArray'] 491*b7c941bbSAndroid Build Coastguard Worker output = cam.get_camera_ids() 492*b7c941bbSAndroid Build Coastguard Worker all_camera_ids = output['cameraIdArray'] 493*b7c941bbSAndroid Build Coastguard Worker # Concat camera_id, physical camera_id and sub camera separator 494*b7c941bbSAndroid Build Coastguard Worker unavailable_physical_ids = [f'{camera_id}.{s}' 495*b7c941bbSAndroid Build Coastguard Worker for s in unavailable_physical_ids] 496*b7c941bbSAndroid Build Coastguard Worker for i in unavailable_physical_ids: 497*b7c941bbSAndroid Build Coastguard Worker if i in all_camera_ids: 498*b7c941bbSAndroid Build Coastguard Worker all_camera_ids.remove(i) 499*b7c941bbSAndroid Build Coastguard Worker logging.debug('available camera ids: %s', all_camera_ids) 500*b7c941bbSAndroid Build Coastguard Worker return all_camera_ids 501*b7c941bbSAndroid Build Coastguard Worker 502*b7c941bbSAndroid Build Coastguard Worker 503*b7c941bbSAndroid Build Coastguard Workerdef get_unavailable_physical_cameras(device_id, camera_id): 504*b7c941bbSAndroid Build Coastguard Worker """Get unavailable physical cameras in the current state. 505*b7c941bbSAndroid Build Coastguard Worker 506*b7c941bbSAndroid Build Coastguard Worker Args: 507*b7c941bbSAndroid Build Coastguard Worker device_id: Serial number of the device. 508*b7c941bbSAndroid Build Coastguard Worker camera_id: Logical camera device id 509*b7c941bbSAndroid Build Coastguard Worker 510*b7c941bbSAndroid Build Coastguard Worker Returns: 511*b7c941bbSAndroid Build Coastguard Worker List of all the unavailable camera_ids. 512*b7c941bbSAndroid Build Coastguard Worker """ 513*b7c941bbSAndroid Build Coastguard Worker with its_session_utils.ItsSession( 514*b7c941bbSAndroid Build Coastguard Worker device_id=device_id, 515*b7c941bbSAndroid Build Coastguard Worker camera_id=camera_id) as cam: 516*b7c941bbSAndroid Build Coastguard Worker unavailable_physical_cameras = cam.get_unavailable_physical_cameras( 517*b7c941bbSAndroid Build Coastguard Worker camera_id) 518*b7c941bbSAndroid Build Coastguard Worker unavailable_physical_ids = unavailable_physical_cameras[ 519*b7c941bbSAndroid Build Coastguard Worker 'unavailablePhysicalCamerasArray'] 520*b7c941bbSAndroid Build Coastguard Worker unavailable_physical_ids = [f'{camera_id}.{s}' 521*b7c941bbSAndroid Build Coastguard Worker for s in unavailable_physical_ids] 522*b7c941bbSAndroid Build Coastguard Worker logging.debug('Unavailable physical camera ids: %s', 523*b7c941bbSAndroid Build Coastguard Worker unavailable_physical_ids) 524*b7c941bbSAndroid Build Coastguard Worker return unavailable_physical_ids 525*b7c941bbSAndroid Build Coastguard Worker 526*b7c941bbSAndroid Build Coastguard Worker 527*b7c941bbSAndroid Build Coastguard Workerdef is_device_folded(device_id): 528*b7c941bbSAndroid Build Coastguard Worker """Returns True if the foldable device is in folded state. 529*b7c941bbSAndroid Build Coastguard Worker 530*b7c941bbSAndroid Build Coastguard Worker Args: 531*b7c941bbSAndroid Build Coastguard Worker device_id: Serial number of the foldable device. 532*b7c941bbSAndroid Build Coastguard Worker """ 533*b7c941bbSAndroid Build Coastguard Worker cmd = (f'adb -s {device_id} shell cmd device_state state') 534*b7c941bbSAndroid Build Coastguard Worker result = subprocess.getoutput(cmd) 535*b7c941bbSAndroid Build Coastguard Worker if 'CLOSE' in result: 536*b7c941bbSAndroid Build Coastguard Worker return True 537*b7c941bbSAndroid Build Coastguard Worker return False 538*b7c941bbSAndroid Build Coastguard Worker 539*b7c941bbSAndroid Build Coastguard Worker 540*b7c941bbSAndroid Build Coastguard Workerdef augment_sub_camera_tests(first_api_level): 541*b7c941bbSAndroid Build Coastguard Worker """Adds certain tests to SUB_CAMERA_TESTS depending on first_api_level. 542*b7c941bbSAndroid Build Coastguard Worker 543*b7c941bbSAndroid Build Coastguard Worker Args: 544*b7c941bbSAndroid Build Coastguard Worker first_api_level: First api level of the device. 545*b7c941bbSAndroid Build Coastguard Worker """ 546*b7c941bbSAndroid Build Coastguard Worker if (first_api_level >= its_session_utils.ANDROID15_API_LEVEL): 547*b7c941bbSAndroid Build Coastguard Worker logging.debug('Augmenting sub camera tests') 548*b7c941bbSAndroid Build Coastguard Worker SUB_CAMERA_TESTS['scene6'] = ('test_in_sensor_zoom',) 549*b7c941bbSAndroid Build Coastguard Worker 550*b7c941bbSAndroid Build Coastguard Worker 551*b7c941bbSAndroid Build Coastguard Workerdef main(): 552*b7c941bbSAndroid Build Coastguard Worker """Run all the Camera ITS automated tests. 553*b7c941bbSAndroid Build Coastguard Worker 554*b7c941bbSAndroid Build Coastguard Worker Script should be run from the top-level CameraITS directory. 555*b7c941bbSAndroid Build Coastguard Worker 556*b7c941bbSAndroid Build Coastguard Worker Command line arguments: 557*b7c941bbSAndroid Build Coastguard Worker camera: the camera(s) to be tested. Use comma to separate multiple 558*b7c941bbSAndroid Build Coastguard Worker camera Ids. Ex: "camera=0,1" or "camera=1" 559*b7c941bbSAndroid Build Coastguard Worker scenes: the test scene(s) to be executed. Use comma to separate 560*b7c941bbSAndroid Build Coastguard Worker multiple scenes. Ex: "scenes=scene0,scene1_1" or 561*b7c941bbSAndroid Build Coastguard Worker "scenes=0,1_1,sensor_fusion" (sceneX can be abbreviated by X 562*b7c941bbSAndroid Build Coastguard Worker where X is scene name minus 'scene') 563*b7c941bbSAndroid Build Coastguard Worker """ 564*b7c941bbSAndroid Build Coastguard Worker logging.basicConfig(level=logging.INFO) 565*b7c941bbSAndroid Build Coastguard Worker # Make output directories to hold the generated files. 566*b7c941bbSAndroid Build Coastguard Worker topdir = tempfile.mkdtemp(prefix='CameraITS_') 567*b7c941bbSAndroid Build Coastguard Worker try: 568*b7c941bbSAndroid Build Coastguard Worker subprocess.call(['chmod', 'g+rx', topdir]) 569*b7c941bbSAndroid Build Coastguard Worker except OSError as e: 570*b7c941bbSAndroid Build Coastguard Worker logging.info(repr(e)) 571*b7c941bbSAndroid Build Coastguard Worker 572*b7c941bbSAndroid Build Coastguard Worker scenes = [] 573*b7c941bbSAndroid Build Coastguard Worker camera_id_combos = [] 574*b7c941bbSAndroid Build Coastguard Worker testbed_index = None 575*b7c941bbSAndroid Build Coastguard Worker num_testbeds = None 576*b7c941bbSAndroid Build Coastguard Worker # Override camera, scenes and testbed with cmd line values if available 577*b7c941bbSAndroid Build Coastguard Worker for s in list(sys.argv[1:]): 578*b7c941bbSAndroid Build Coastguard Worker if 'scenes=' in s: 579*b7c941bbSAndroid Build Coastguard Worker scenes = s.split('=')[1].split(',') 580*b7c941bbSAndroid Build Coastguard Worker elif 'camera=' in s: 581*b7c941bbSAndroid Build Coastguard Worker camera_id_combos = s.split('=')[1].split(',') 582*b7c941bbSAndroid Build Coastguard Worker elif 'testbed_index=' in s: 583*b7c941bbSAndroid Build Coastguard Worker testbed_index = int(s.split('=')[1]) 584*b7c941bbSAndroid Build Coastguard Worker elif 'num_testbeds=' in s: 585*b7c941bbSAndroid Build Coastguard Worker num_testbeds = int(s.split('=')[1]) 586*b7c941bbSAndroid Build Coastguard Worker else: 587*b7c941bbSAndroid Build Coastguard Worker raise ValueError(f'Unknown argument {s}') 588*b7c941bbSAndroid Build Coastguard Worker if testbed_index is None and num_testbeds is not None: 589*b7c941bbSAndroid Build Coastguard Worker raise ValueError( 590*b7c941bbSAndroid Build Coastguard Worker 'testbed_index must be specified if num_testbeds is specified.') 591*b7c941bbSAndroid Build Coastguard Worker if (testbed_index is not None and num_testbeds is not None and 592*b7c941bbSAndroid Build Coastguard Worker testbed_index >= num_testbeds): 593*b7c941bbSAndroid Build Coastguard Worker raise ValueError('testbed_index must be less than num_testbeds. ' 594*b7c941bbSAndroid Build Coastguard Worker 'testbed_index starts at 0.') 595*b7c941bbSAndroid Build Coastguard Worker 596*b7c941bbSAndroid Build Coastguard Worker # Prepend 'scene' if not specified at cmd line 597*b7c941bbSAndroid Build Coastguard Worker for i, s in enumerate(scenes): 598*b7c941bbSAndroid Build Coastguard Worker if (not s.startswith('scene') and 599*b7c941bbSAndroid Build Coastguard Worker not s.startswith(('checkerboard', 'sensor_fusion', 600*b7c941bbSAndroid Build Coastguard Worker 'flash', 'feature_combination', '<scene-name>'))): 601*b7c941bbSAndroid Build Coastguard Worker scenes[i] = f'scene{s}' 602*b7c941bbSAndroid Build Coastguard Worker if s.startswith('flash') or s.startswith('extensions'): 603*b7c941bbSAndroid Build Coastguard Worker scenes[i] = f'scene_{s}' 604*b7c941bbSAndroid Build Coastguard Worker # Handle scene_extensions 605*b7c941bbSAndroid Build Coastguard Worker if any(s.startswith(extension) for extension in _EXTENSION_NAMES): 606*b7c941bbSAndroid Build Coastguard Worker scenes[i] = f'scene_extensions/scene_{s}' 607*b7c941bbSAndroid Build Coastguard Worker if (any(s.startswith('scene_' + extension) 608*b7c941bbSAndroid Build Coastguard Worker for extension in _EXTENSION_NAMES)): 609*b7c941bbSAndroid Build Coastguard Worker scenes[i] = f'scene_extensions/{s}' 610*b7c941bbSAndroid Build Coastguard Worker 611*b7c941bbSAndroid Build Coastguard Worker # Read config file and extract relevant TestBed 612*b7c941bbSAndroid Build Coastguard Worker config_file_contents = get_config_file_contents() 613*b7c941bbSAndroid Build Coastguard Worker if testbed_index is None: 614*b7c941bbSAndroid Build Coastguard Worker for i in config_file_contents['TestBeds']: 615*b7c941bbSAndroid Build Coastguard Worker if scenes in ( 616*b7c941bbSAndroid Build Coastguard Worker ['sensor_fusion'], ['checkerboard'], ['scene_flash'], 617*b7c941bbSAndroid Build Coastguard Worker ['feature_combination'] 618*b7c941bbSAndroid Build Coastguard Worker ): 619*b7c941bbSAndroid Build Coastguard Worker if TEST_KEY_SENSOR_FUSION not in i['Name'].lower(): 620*b7c941bbSAndroid Build Coastguard Worker config_file_contents['TestBeds'].remove(i) 621*b7c941bbSAndroid Build Coastguard Worker else: 622*b7c941bbSAndroid Build Coastguard Worker if TEST_KEY_SENSOR_FUSION in i['Name'].lower(): 623*b7c941bbSAndroid Build Coastguard Worker config_file_contents['TestBeds'].remove(i) 624*b7c941bbSAndroid Build Coastguard Worker else: 625*b7c941bbSAndroid Build Coastguard Worker config_file_contents = { 626*b7c941bbSAndroid Build Coastguard Worker 'TestBeds': [config_file_contents['TestBeds'][testbed_index]] 627*b7c941bbSAndroid Build Coastguard Worker } 628*b7c941bbSAndroid Build Coastguard Worker 629*b7c941bbSAndroid Build Coastguard Worker # Get test parameters from config file 630*b7c941bbSAndroid Build Coastguard Worker test_params_content = get_test_params(config_file_contents) 631*b7c941bbSAndroid Build Coastguard Worker if not camera_id_combos: 632*b7c941bbSAndroid Build Coastguard Worker camera_id_combos = str(test_params_content['camera']).split(',') 633*b7c941bbSAndroid Build Coastguard Worker if not scenes: 634*b7c941bbSAndroid Build Coastguard Worker scenes = str(test_params_content['scene']).split(',') 635*b7c941bbSAndroid Build Coastguard Worker scenes = [_INT_STR_DICT.get(n, n) for n in scenes] # recover '1_1' & '1_2' 636*b7c941bbSAndroid Build Coastguard Worker 637*b7c941bbSAndroid Build Coastguard Worker device_id = get_device_serial_number('dut', config_file_contents) 638*b7c941bbSAndroid Build Coastguard Worker # Enable external storage on DUT to send summary report to CtsVerifier.apk 639*b7c941bbSAndroid Build Coastguard Worker enable_external_storage(device_id) 640*b7c941bbSAndroid Build Coastguard Worker 641*b7c941bbSAndroid Build Coastguard Worker # Add to SUB_CAMERA_TESTS depending on first_api_level 642*b7c941bbSAndroid Build Coastguard Worker augment_sub_camera_tests(its_session_utils.get_first_api_level(device_id)) 643*b7c941bbSAndroid Build Coastguard Worker 644*b7c941bbSAndroid Build Coastguard Worker # Verify that CTS Verifier is installed 645*b7c941bbSAndroid Build Coastguard Worker its_session_utils.check_apk_installed(device_id, CTS_VERIFIER_PACKAGE_NAME) 646*b7c941bbSAndroid Build Coastguard Worker # Check whether the dut is foldable or not 647*b7c941bbSAndroid Build Coastguard Worker testing_foldable_device = True if test_params_content[ 648*b7c941bbSAndroid Build Coastguard Worker 'foldable_device'] == 'True' else False 649*b7c941bbSAndroid Build Coastguard Worker available_camera_ids_to_test_foldable = [] 650*b7c941bbSAndroid Build Coastguard Worker if testing_foldable_device: 651*b7c941bbSAndroid Build Coastguard Worker logging.debug('Testing foldable device.') 652*b7c941bbSAndroid Build Coastguard Worker # Check the state of foldable device. True if device is folded, 653*b7c941bbSAndroid Build Coastguard Worker # false if the device is opened. 654*b7c941bbSAndroid Build Coastguard Worker device_folded = is_device_folded(device_id) 655*b7c941bbSAndroid Build Coastguard Worker # list of available camera_ids to be tested in device state 656*b7c941bbSAndroid Build Coastguard Worker available_camera_ids_to_test_foldable = get_available_cameras( 657*b7c941bbSAndroid Build Coastguard Worker device_id, _FRONT_CAMERA_ID) 658*b7c941bbSAndroid Build Coastguard Worker 659*b7c941bbSAndroid Build Coastguard Worker config_file_test_key = config_file_contents['TestBeds'][0]['Name'].lower() 660*b7c941bbSAndroid Build Coastguard Worker logging.info('Saving %s output files to: %s', config_file_test_key, topdir) 661*b7c941bbSAndroid Build Coastguard Worker if TEST_KEY_TABLET in config_file_test_key: 662*b7c941bbSAndroid Build Coastguard Worker tablet_id = get_device_serial_number('tablet', config_file_contents) 663*b7c941bbSAndroid Build Coastguard Worker tablet_name_cmd = f'adb -s {tablet_id} shell getprop ro.product.device' 664*b7c941bbSAndroid Build Coastguard Worker raw_output = subprocess.check_output( 665*b7c941bbSAndroid Build Coastguard Worker tablet_name_cmd, stderr=subprocess.STDOUT, shell=True) 666*b7c941bbSAndroid Build Coastguard Worker tablet_name = str(raw_output.decode('utf-8')).strip() 667*b7c941bbSAndroid Build Coastguard Worker logging.debug('Tablet name: %s', tablet_name) 668*b7c941bbSAndroid Build Coastguard Worker brightness = test_params_content['brightness'] 669*b7c941bbSAndroid Build Coastguard Worker its_session_utils.validate_tablet(tablet_name, brightness, tablet_id) 670*b7c941bbSAndroid Build Coastguard Worker else: 671*b7c941bbSAndroid Build Coastguard Worker tablet_id = None 672*b7c941bbSAndroid Build Coastguard Worker tablet_name = "sensor_fusion" 673*b7c941bbSAndroid Build Coastguard Worker 674*b7c941bbSAndroid Build Coastguard Worker testing_sensor_fusion_with_controller = False 675*b7c941bbSAndroid Build Coastguard Worker if TEST_KEY_SENSOR_FUSION in config_file_test_key: 676*b7c941bbSAndroid Build Coastguard Worker if test_params_content['rotator_cntl'].lower() in VALID_CONTROLLERS: 677*b7c941bbSAndroid Build Coastguard Worker testing_sensor_fusion_with_controller = True 678*b7c941bbSAndroid Build Coastguard Worker 679*b7c941bbSAndroid Build Coastguard Worker testing_flash_with_controller = False 680*b7c941bbSAndroid Build Coastguard Worker if (test_params_content.get('lighting_cntl', 'None').lower() == 'arduino' and 681*b7c941bbSAndroid Build Coastguard Worker 'manual' not in config_file_test_key): 682*b7c941bbSAndroid Build Coastguard Worker testing_flash_with_controller = True 683*b7c941bbSAndroid Build Coastguard Worker 684*b7c941bbSAndroid Build Coastguard Worker # Expand GROUPED_SCENES and remove any duplicates 685*b7c941bbSAndroid Build Coastguard Worker scenes = [_GROUPED_SCENES[s] if s in _GROUPED_SCENES else s for s in scenes] 686*b7c941bbSAndroid Build Coastguard Worker scenes = np.hstack(scenes).tolist() 687*b7c941bbSAndroid Build Coastguard Worker scenes = sorted(set(scenes), key=scenes.index) 688*b7c941bbSAndroid Build Coastguard Worker # List of scenes to be executed in folded state will have '_folded' 689*b7c941bbSAndroid Build Coastguard Worker # prefix. This will help distinguish the test results from folded vs 690*b7c941bbSAndroid Build Coastguard Worker # open device state for front camera_ids. 691*b7c941bbSAndroid Build Coastguard Worker folded_device_scenes = [] 692*b7c941bbSAndroid Build Coastguard Worker for scene in scenes: 693*b7c941bbSAndroid Build Coastguard Worker folded_device_scenes.append(f'{scene}_folded') 694*b7c941bbSAndroid Build Coastguard Worker 695*b7c941bbSAndroid Build Coastguard Worker logging.info('Running ITS on device: %s, camera(s): %s, scene(s): %s', 696*b7c941bbSAndroid Build Coastguard Worker device_id, camera_id_combos, scenes) 697*b7c941bbSAndroid Build Coastguard Worker 698*b7c941bbSAndroid Build Coastguard Worker # Determine if manual run 699*b7c941bbSAndroid Build Coastguard Worker if tablet_id is not None and not set(scenes).intersection(_MANUAL_SCENES): 700*b7c941bbSAndroid Build Coastguard Worker auto_scene_switch = True 701*b7c941bbSAndroid Build Coastguard Worker else: 702*b7c941bbSAndroid Build Coastguard Worker auto_scene_switch = False 703*b7c941bbSAndroid Build Coastguard Worker logging.info('Manual, checkerboard scenes, or scene5 testing.') 704*b7c941bbSAndroid Build Coastguard Worker 705*b7c941bbSAndroid Build Coastguard Worker folded_prompted = False 706*b7c941bbSAndroid Build Coastguard Worker opened_prompted = False 707*b7c941bbSAndroid Build Coastguard Worker for camera_id in camera_id_combos: 708*b7c941bbSAndroid Build Coastguard Worker test_params_content['camera'] = camera_id 709*b7c941bbSAndroid Build Coastguard Worker results = {} 710*b7c941bbSAndroid Build Coastguard Worker unav_cameras = [] 711*b7c941bbSAndroid Build Coastguard Worker # Get the list of unavailable cameras in current device state. 712*b7c941bbSAndroid Build Coastguard Worker # These camera_ids should not be tested in current device state. 713*b7c941bbSAndroid Build Coastguard Worker if testing_foldable_device: 714*b7c941bbSAndroid Build Coastguard Worker unav_cameras = get_unavailable_physical_cameras( 715*b7c941bbSAndroid Build Coastguard Worker device_id, _FRONT_CAMERA_ID) 716*b7c941bbSAndroid Build Coastguard Worker 717*b7c941bbSAndroid Build Coastguard Worker if testing_foldable_device: 718*b7c941bbSAndroid Build Coastguard Worker device_state = 'folded' if device_folded else 'opened' 719*b7c941bbSAndroid Build Coastguard Worker 720*b7c941bbSAndroid Build Coastguard Worker testing_folded_front_camera = (testing_foldable_device and 721*b7c941bbSAndroid Build Coastguard Worker device_folded and 722*b7c941bbSAndroid Build Coastguard Worker _FRONT_CAMERA_ID in camera_id) 723*b7c941bbSAndroid Build Coastguard Worker 724*b7c941bbSAndroid Build Coastguard Worker # Raise an assertion error if there is any camera unavailable in 725*b7c941bbSAndroid Build Coastguard Worker # current device state. Usually scenes with suffix 'folded' will 726*b7c941bbSAndroid Build Coastguard Worker # be executed in folded state. 727*b7c941bbSAndroid Build Coastguard Worker if (testing_foldable_device and 728*b7c941bbSAndroid Build Coastguard Worker _FRONT_CAMERA_ID in camera_id and camera_id in unav_cameras): 729*b7c941bbSAndroid Build Coastguard Worker raise AssertionError( 730*b7c941bbSAndroid Build Coastguard Worker f'Camera {camera_id} is unavailable in device state {device_state}' 731*b7c941bbSAndroid Build Coastguard Worker f' and cannot be tested with device {device_state}!') 732*b7c941bbSAndroid Build Coastguard Worker 733*b7c941bbSAndroid Build Coastguard Worker if (testing_folded_front_camera and camera_id not in unav_cameras 734*b7c941bbSAndroid Build Coastguard Worker and not folded_prompted): 735*b7c941bbSAndroid Build Coastguard Worker folded_prompted = True 736*b7c941bbSAndroid Build Coastguard Worker input('\nYou are testing a foldable device in folded state. ' 737*b7c941bbSAndroid Build Coastguard Worker 'Please make sure the device is folded and press <ENTER> ' 738*b7c941bbSAndroid Build Coastguard Worker 'after positioning properly.\n') 739*b7c941bbSAndroid Build Coastguard Worker 740*b7c941bbSAndroid Build Coastguard Worker if (testing_foldable_device and 741*b7c941bbSAndroid Build Coastguard Worker not device_folded and _FRONT_CAMERA_ID in camera_id and 742*b7c941bbSAndroid Build Coastguard Worker camera_id not in unav_cameras and not opened_prompted): 743*b7c941bbSAndroid Build Coastguard Worker opened_prompted = True 744*b7c941bbSAndroid Build Coastguard Worker input('\nYou are testing a foldable device in opened state. ' 745*b7c941bbSAndroid Build Coastguard Worker 'Please make sure the device is unfolded and press <ENTER> ' 746*b7c941bbSAndroid Build Coastguard Worker 'after positioning properly.\n') 747*b7c941bbSAndroid Build Coastguard Worker 748*b7c941bbSAndroid Build Coastguard Worker # Run through all scenes if user does not supply one and config file doesn't 749*b7c941bbSAndroid Build Coastguard Worker # have specific scene name listed. 750*b7c941bbSAndroid Build Coastguard Worker if its_session_utils.SUB_CAMERA_SEPARATOR in camera_id: 751*b7c941bbSAndroid Build Coastguard Worker possible_scenes = list(SUB_CAMERA_TESTS.keys()) 752*b7c941bbSAndroid Build Coastguard Worker if auto_scene_switch: 753*b7c941bbSAndroid Build Coastguard Worker possible_scenes.remove('sensor_fusion') 754*b7c941bbSAndroid Build Coastguard Worker else: 755*b7c941bbSAndroid Build Coastguard Worker if 'checkerboard' in scenes: 756*b7c941bbSAndroid Build Coastguard Worker possible_scenes = _CHECKERBOARD_SCENES 757*b7c941bbSAndroid Build Coastguard Worker elif 'scene_flash' in scenes: 758*b7c941bbSAndroid Build Coastguard Worker possible_scenes = _FLASH_SCENES 759*b7c941bbSAndroid Build Coastguard Worker elif 'scene_extensions' in scenes: 760*b7c941bbSAndroid Build Coastguard Worker possible_scenes = _EXTENSIONS_SCENES 761*b7c941bbSAndroid Build Coastguard Worker else: 762*b7c941bbSAndroid Build Coastguard Worker possible_scenes = _TABLET_SCENES if auto_scene_switch else _ALL_SCENES 763*b7c941bbSAndroid Build Coastguard Worker 764*b7c941bbSAndroid Build Coastguard Worker if ('<scene-name>' in scenes or 'checkerboard' in scenes or 765*b7c941bbSAndroid Build Coastguard Worker 'scene_extensions' in scenes): 766*b7c941bbSAndroid Build Coastguard Worker per_camera_scenes = possible_scenes 767*b7c941bbSAndroid Build Coastguard Worker else: 768*b7c941bbSAndroid Build Coastguard Worker # Validate user input scene names 769*b7c941bbSAndroid Build Coastguard Worker per_camera_scenes = [] 770*b7c941bbSAndroid Build Coastguard Worker for s in scenes: 771*b7c941bbSAndroid Build Coastguard Worker if s in possible_scenes: 772*b7c941bbSAndroid Build Coastguard Worker per_camera_scenes.append(s) 773*b7c941bbSAndroid Build Coastguard Worker if not per_camera_scenes: 774*b7c941bbSAndroid Build Coastguard Worker raise ValueError('No valid scene specified for this camera.') 775*b7c941bbSAndroid Build Coastguard Worker 776*b7c941bbSAndroid Build Coastguard Worker # Folded state scenes will have 'folded' suffix only for 777*b7c941bbSAndroid Build Coastguard Worker # front cameras since rear cameras are common in both folded 778*b7c941bbSAndroid Build Coastguard Worker # and unfolded state. 779*b7c941bbSAndroid Build Coastguard Worker foldable_per_camera_scenes = [] 780*b7c941bbSAndroid Build Coastguard Worker if testing_folded_front_camera: 781*b7c941bbSAndroid Build Coastguard Worker if camera_id not in available_camera_ids_to_test_foldable: 782*b7c941bbSAndroid Build Coastguard Worker raise AssertionError(f'camera {camera_id} is not available.') 783*b7c941bbSAndroid Build Coastguard Worker for s in per_camera_scenes: 784*b7c941bbSAndroid Build Coastguard Worker foldable_per_camera_scenes.append(f'{s}_folded') 785*b7c941bbSAndroid Build Coastguard Worker 786*b7c941bbSAndroid Build Coastguard Worker if foldable_per_camera_scenes: 787*b7c941bbSAndroid Build Coastguard Worker per_camera_scenes = foldable_per_camera_scenes 788*b7c941bbSAndroid Build Coastguard Worker 789*b7c941bbSAndroid Build Coastguard Worker logging.info('camera: %s, scene(s): %s', camera_id, per_camera_scenes) 790*b7c941bbSAndroid Build Coastguard Worker 791*b7c941bbSAndroid Build Coastguard Worker if testing_folded_front_camera: 792*b7c941bbSAndroid Build Coastguard Worker all_scenes = [f'{s}_folded' for s in _ALL_SCENES] 793*b7c941bbSAndroid Build Coastguard Worker else: 794*b7c941bbSAndroid Build Coastguard Worker all_scenes = _ALL_SCENES 795*b7c941bbSAndroid Build Coastguard Worker 796*b7c941bbSAndroid Build Coastguard Worker for s in all_scenes: 797*b7c941bbSAndroid Build Coastguard Worker results[s] = {RESULT_KEY: RESULT_NOT_EXECUTED} 798*b7c941bbSAndroid Build Coastguard Worker 799*b7c941bbSAndroid Build Coastguard Worker # assert device folded testing scenes with suffix 'folded' 800*b7c941bbSAndroid Build Coastguard Worker if testing_foldable_device and 'folded' in s: 801*b7c941bbSAndroid Build Coastguard Worker if not device_folded: 802*b7c941bbSAndroid Build Coastguard Worker raise AssertionError('Device should be folded during' 803*b7c941bbSAndroid Build Coastguard Worker ' testing scenes with suffix "folded"') 804*b7c941bbSAndroid Build Coastguard Worker 805*b7c941bbSAndroid Build Coastguard Worker # A subdir in topdir will be created for each camera_id. All scene test 806*b7c941bbSAndroid Build Coastguard Worker # output logs for each camera id will be stored in this subdir. 807*b7c941bbSAndroid Build Coastguard Worker # This output log path is a mobly param : LogPath 808*b7c941bbSAndroid Build Coastguard Worker camera_id_str = ( 809*b7c941bbSAndroid Build Coastguard Worker camera_id.replace(its_session_utils.SUB_CAMERA_SEPARATOR, '_') 810*b7c941bbSAndroid Build Coastguard Worker ) 811*b7c941bbSAndroid Build Coastguard Worker mobly_output_logs_path = os.path.join(topdir, f'cam_id_{camera_id_str}') 812*b7c941bbSAndroid Build Coastguard Worker os.mkdir(mobly_output_logs_path) 813*b7c941bbSAndroid Build Coastguard Worker tot_pass = 0 814*b7c941bbSAndroid Build Coastguard Worker for s in per_camera_scenes: 815*b7c941bbSAndroid Build Coastguard Worker results[s]['TEST_STATUS'] = [] 816*b7c941bbSAndroid Build Coastguard Worker results[s][METRICS_KEY] = [] 817*b7c941bbSAndroid Build Coastguard Worker results[s][PERFORMANCE_KEY] = [] 818*b7c941bbSAndroid Build Coastguard Worker results[s][FEATURE_QUERY_KEY] = [] 819*b7c941bbSAndroid Build Coastguard Worker 820*b7c941bbSAndroid Build Coastguard Worker # unit is millisecond for execution time record in CtsVerifier 821*b7c941bbSAndroid Build Coastguard Worker scene_start_time = int(round(time.time() * 1000)) 822*b7c941bbSAndroid Build Coastguard Worker scene_test_summary = f'Cam{camera_id} {s}' + '\n' 823*b7c941bbSAndroid Build Coastguard Worker mobly_scene_output_logs_path = os.path.join(mobly_output_logs_path, s) 824*b7c941bbSAndroid Build Coastguard Worker 825*b7c941bbSAndroid Build Coastguard Worker # Since test directories do not have 'folded' in the name, we need 826*b7c941bbSAndroid Build Coastguard Worker # to remove that suffix for the path of the scenes to be loaded 827*b7c941bbSAndroid Build Coastguard Worker # on the tablets 828*b7c941bbSAndroid Build Coastguard Worker testing_scene = s 829*b7c941bbSAndroid Build Coastguard Worker if 'folded' in s: 830*b7c941bbSAndroid Build Coastguard Worker testing_scene = s.split('_folded')[0] 831*b7c941bbSAndroid Build Coastguard Worker test_params_content['scene'] = testing_scene 832*b7c941bbSAndroid Build Coastguard Worker test_params_content['scene_with_suffix'] = s 833*b7c941bbSAndroid Build Coastguard Worker 834*b7c941bbSAndroid Build Coastguard Worker if auto_scene_switch: 835*b7c941bbSAndroid Build Coastguard Worker # Copy scene images onto the tablet 836*b7c941bbSAndroid Build Coastguard Worker if 'scene0' not in testing_scene: 837*b7c941bbSAndroid Build Coastguard Worker its_session_utils.copy_scenes_to_tablet(testing_scene, tablet_id) 838*b7c941bbSAndroid Build Coastguard Worker else: 839*b7c941bbSAndroid Build Coastguard Worker # Check manual scenes for correctness 840*b7c941bbSAndroid Build Coastguard Worker if ('scene0' not in testing_scene and 841*b7c941bbSAndroid Build Coastguard Worker not testing_sensor_fusion_with_controller): 842*b7c941bbSAndroid Build Coastguard Worker check_manual_scenes(device_id, camera_id, testing_scene, 843*b7c941bbSAndroid Build Coastguard Worker mobly_output_logs_path) 844*b7c941bbSAndroid Build Coastguard Worker 845*b7c941bbSAndroid Build Coastguard Worker scene_test_list = [] 846*b7c941bbSAndroid Build Coastguard Worker config_file_contents['TestBeds'][0]['TestParams'] = test_params_content 847*b7c941bbSAndroid Build Coastguard Worker # Add the MoblyParams to config.yml file with the path to store camera_id 848*b7c941bbSAndroid Build Coastguard Worker # test results. This is a separate dict other than TestBeds. 849*b7c941bbSAndroid Build Coastguard Worker mobly_params_dict = { 850*b7c941bbSAndroid Build Coastguard Worker 'MoblyParams': { 851*b7c941bbSAndroid Build Coastguard Worker 'LogPath': mobly_scene_output_logs_path 852*b7c941bbSAndroid Build Coastguard Worker } 853*b7c941bbSAndroid Build Coastguard Worker } 854*b7c941bbSAndroid Build Coastguard Worker config_file_contents.update(mobly_params_dict) 855*b7c941bbSAndroid Build Coastguard Worker logging.debug('Final config file contents: %s', config_file_contents) 856*b7c941bbSAndroid Build Coastguard Worker new_yml_file_name = get_updated_yml_file(config_file_contents) 857*b7c941bbSAndroid Build Coastguard Worker logging.info('Using %s as temporary config yml file', new_yml_file_name) 858*b7c941bbSAndroid Build Coastguard Worker if camera_id.rfind(its_session_utils.SUB_CAMERA_SEPARATOR) == -1: 859*b7c941bbSAndroid Build Coastguard Worker scene_dir = os.listdir( 860*b7c941bbSAndroid Build Coastguard Worker os.path.join(os.environ['CAMERA_ITS_TOP'], 'tests', testing_scene)) 861*b7c941bbSAndroid Build Coastguard Worker for file_name in scene_dir: 862*b7c941bbSAndroid Build Coastguard Worker if file_name.endswith('.py') and 'test' in file_name: 863*b7c941bbSAndroid Build Coastguard Worker scene_test_list.append(file_name) 864*b7c941bbSAndroid Build Coastguard Worker else: # sub-camera 865*b7c941bbSAndroid Build Coastguard Worker if SUB_CAMERA_TESTS.get(testing_scene): 866*b7c941bbSAndroid Build Coastguard Worker scene_test_list = [f'{test}.py' for test in SUB_CAMERA_TESTS[ 867*b7c941bbSAndroid Build Coastguard Worker testing_scene]] 868*b7c941bbSAndroid Build Coastguard Worker else: 869*b7c941bbSAndroid Build Coastguard Worker scene_test_list = [] 870*b7c941bbSAndroid Build Coastguard Worker scene_test_list.sort() 871*b7c941bbSAndroid Build Coastguard Worker 872*b7c941bbSAndroid Build Coastguard Worker # Run tests for scene 873*b7c941bbSAndroid Build Coastguard Worker logging.info('Running tests for %s with camera %s', 874*b7c941bbSAndroid Build Coastguard Worker testing_scene, camera_id) 875*b7c941bbSAndroid Build Coastguard Worker num_pass = 0 876*b7c941bbSAndroid Build Coastguard Worker num_skip = 0 877*b7c941bbSAndroid Build Coastguard Worker num_not_mandated_fail = 0 878*b7c941bbSAndroid Build Coastguard Worker num_fail = 0 879*b7c941bbSAndroid Build Coastguard Worker for test in scene_test_list: 880*b7c941bbSAndroid Build Coastguard Worker # Handle repeated test 881*b7c941bbSAndroid Build Coastguard Worker if 'tests/' in test: 882*b7c941bbSAndroid Build Coastguard Worker cmd = [ 883*b7c941bbSAndroid Build Coastguard Worker 'python3', 884*b7c941bbSAndroid Build Coastguard Worker os.path.join(os.environ['CAMERA_ITS_TOP'], test), '-c', 885*b7c941bbSAndroid Build Coastguard Worker f'{new_yml_file_name}' 886*b7c941bbSAndroid Build Coastguard Worker ] 887*b7c941bbSAndroid Build Coastguard Worker else: 888*b7c941bbSAndroid Build Coastguard Worker cmd = [ 889*b7c941bbSAndroid Build Coastguard Worker 'python3', 890*b7c941bbSAndroid Build Coastguard Worker os.path.join(os.environ['CAMERA_ITS_TOP'], 'tests', 891*b7c941bbSAndroid Build Coastguard Worker testing_scene, test), 892*b7c941bbSAndroid Build Coastguard Worker '-c', 893*b7c941bbSAndroid Build Coastguard Worker f'{new_yml_file_name}' 894*b7c941bbSAndroid Build Coastguard Worker ] 895*b7c941bbSAndroid Build Coastguard Worker return_string = '' 896*b7c941bbSAndroid Build Coastguard Worker for num_try in range(NUM_TRIES): 897*b7c941bbSAndroid Build Coastguard Worker # Saves to mobly test summary file 898*b7c941bbSAndroid Build Coastguard Worker # print only messages for manual lighting control testing 899*b7c941bbSAndroid Build Coastguard Worker output = subprocess.Popen( 900*b7c941bbSAndroid Build Coastguard Worker cmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT 901*b7c941bbSAndroid Build Coastguard Worker ) 902*b7c941bbSAndroid Build Coastguard Worker with output.stdout, open( 903*b7c941bbSAndroid Build Coastguard Worker os.path.join(topdir, MOBLY_TEST_SUMMARY_TXT_FILE), 'wb' 904*b7c941bbSAndroid Build Coastguard Worker ) as file: 905*b7c941bbSAndroid Build Coastguard Worker for line in iter(output.stdout.readline, b''): 906*b7c941bbSAndroid Build Coastguard Worker out = line.decode('utf-8').strip() 907*b7c941bbSAndroid Build Coastguard Worker if '<ENTER>' in out: print(out) 908*b7c941bbSAndroid Build Coastguard Worker file.write(line) 909*b7c941bbSAndroid Build Coastguard Worker output.wait() 910*b7c941bbSAndroid Build Coastguard Worker 911*b7c941bbSAndroid Build Coastguard Worker # Parse mobly logs to determine PASS/FAIL(*)/SKIP & socket FAILs 912*b7c941bbSAndroid Build Coastguard Worker with open( 913*b7c941bbSAndroid Build Coastguard Worker os.path.join(topdir, MOBLY_TEST_SUMMARY_TXT_FILE), 'r') as file: 914*b7c941bbSAndroid Build Coastguard Worker test_code = output.returncode 915*b7c941bbSAndroid Build Coastguard Worker test_skipped = False 916*b7c941bbSAndroid Build Coastguard Worker test_not_yet_mandated = False 917*b7c941bbSAndroid Build Coastguard Worker test_mpc_req = '' 918*b7c941bbSAndroid Build Coastguard Worker perf_test_metrics = '' 919*b7c941bbSAndroid Build Coastguard Worker hdr_mpc_req = '' 920*b7c941bbSAndroid Build Coastguard Worker feature_query_proto = '' 921*b7c941bbSAndroid Build Coastguard Worker content = file.read() 922*b7c941bbSAndroid Build Coastguard Worker 923*b7c941bbSAndroid Build Coastguard Worker # Find media performance class logging 924*b7c941bbSAndroid Build Coastguard Worker lines = content.splitlines() 925*b7c941bbSAndroid Build Coastguard Worker for one_line in lines: 926*b7c941bbSAndroid Build Coastguard Worker # regular expression pattern must match 927*b7c941bbSAndroid Build Coastguard Worker # MPC12_CAMERA_LAUNCH_PATTERN or MPC12_JPEG_CAPTURE_PATTERN in 928*b7c941bbSAndroid Build Coastguard Worker # ItsTestActivity.java. 929*b7c941bbSAndroid Build Coastguard Worker mpc_string_match = re.search( 930*b7c941bbSAndroid Build Coastguard Worker '^(1080p_jpeg_capture_time_ms:|camera_launch_time_ms:)', 931*b7c941bbSAndroid Build Coastguard Worker one_line) 932*b7c941bbSAndroid Build Coastguard Worker if mpc_string_match: 933*b7c941bbSAndroid Build Coastguard Worker test_mpc_req = one_line 934*b7c941bbSAndroid Build Coastguard Worker break 935*b7c941bbSAndroid Build Coastguard Worker 936*b7c941bbSAndroid Build Coastguard Worker for one_line in lines: 937*b7c941bbSAndroid Build Coastguard Worker # regular expression pattern must match in ItsTestActivity.java. 938*b7c941bbSAndroid Build Coastguard Worker gainmap_string_match = re.search('^has_gainmap:', one_line) 939*b7c941bbSAndroid Build Coastguard Worker if gainmap_string_match: 940*b7c941bbSAndroid Build Coastguard Worker hdr_mpc_req = one_line 941*b7c941bbSAndroid Build Coastguard Worker break 942*b7c941bbSAndroid Build Coastguard Worker 943*b7c941bbSAndroid Build Coastguard Worker # Find feature combination query proto 944*b7c941bbSAndroid Build Coastguard Worker for one_line in lines: 945*b7c941bbSAndroid Build Coastguard Worker # regular expression pattern must match in ItsTestActivity.java. 946*b7c941bbSAndroid Build Coastguard Worker feature_comb_query_string_match = re.search( 947*b7c941bbSAndroid Build Coastguard Worker '^feature_query_proto:(.*)', one_line 948*b7c941bbSAndroid Build Coastguard Worker ) 949*b7c941bbSAndroid Build Coastguard Worker if feature_comb_query_string_match: 950*b7c941bbSAndroid Build Coastguard Worker feature_query_proto = feature_comb_query_string_match.group(1) 951*b7c941bbSAndroid Build Coastguard Worker break 952*b7c941bbSAndroid Build Coastguard Worker 953*b7c941bbSAndroid Build Coastguard Worker # Find performance metrics logging 954*b7c941bbSAndroid Build Coastguard Worker for one_line in lines: 955*b7c941bbSAndroid Build Coastguard Worker # regular expression pattern must match in ItsTestActivity.java. 956*b7c941bbSAndroid Build Coastguard Worker perf_metrics_string_match = re.search( 957*b7c941bbSAndroid Build Coastguard Worker '^test.*:', 958*b7c941bbSAndroid Build Coastguard Worker one_line) 959*b7c941bbSAndroid Build Coastguard Worker if perf_metrics_string_match: 960*b7c941bbSAndroid Build Coastguard Worker perf_test_metrics = one_line 961*b7c941bbSAndroid Build Coastguard Worker # each test can add multiple metrics 962*b7c941bbSAndroid Build Coastguard Worker results[s][PERFORMANCE_KEY].append(perf_test_metrics) 963*b7c941bbSAndroid Build Coastguard Worker 964*b7c941bbSAndroid Build Coastguard Worker if 'Test skipped' in content: 965*b7c941bbSAndroid Build Coastguard Worker return_string = 'SKIP ' 966*b7c941bbSAndroid Build Coastguard Worker num_skip += 1 967*b7c941bbSAndroid Build Coastguard Worker test_skipped = True 968*b7c941bbSAndroid Build Coastguard Worker break 969*b7c941bbSAndroid Build Coastguard Worker 970*b7c941bbSAndroid Build Coastguard Worker if its_session_utils.NOT_YET_MANDATED_MESSAGE in content: 971*b7c941bbSAndroid Build Coastguard Worker return_string = 'FAIL*' 972*b7c941bbSAndroid Build Coastguard Worker num_not_mandated_fail += 1 973*b7c941bbSAndroid Build Coastguard Worker test_not_yet_mandated = True 974*b7c941bbSAndroid Build Coastguard Worker break 975*b7c941bbSAndroid Build Coastguard Worker 976*b7c941bbSAndroid Build Coastguard Worker if test_code == 0 and not test_skipped: 977*b7c941bbSAndroid Build Coastguard Worker return_string = 'PASS ' 978*b7c941bbSAndroid Build Coastguard Worker num_pass += 1 979*b7c941bbSAndroid Build Coastguard Worker break 980*b7c941bbSAndroid Build Coastguard Worker 981*b7c941bbSAndroid Build Coastguard Worker if test_code == 1 and not test_not_yet_mandated: 982*b7c941bbSAndroid Build Coastguard Worker return_string = 'FAIL ' 983*b7c941bbSAndroid Build Coastguard Worker if 'Problem with socket' in content and num_try != NUM_TRIES-1: 984*b7c941bbSAndroid Build Coastguard Worker logging.info('Retry %s/%s', s, test) 985*b7c941bbSAndroid Build Coastguard Worker else: 986*b7c941bbSAndroid Build Coastguard Worker num_fail += 1 987*b7c941bbSAndroid Build Coastguard Worker break 988*b7c941bbSAndroid Build Coastguard Worker os.remove(os.path.join(topdir, MOBLY_TEST_SUMMARY_TXT_FILE)) 989*b7c941bbSAndroid Build Coastguard Worker status_prefix = '' 990*b7c941bbSAndroid Build Coastguard Worker if testbed_index is not None: 991*b7c941bbSAndroid Build Coastguard Worker status_prefix = config_file_test_key + ':' 992*b7c941bbSAndroid Build Coastguard Worker logging.info('%s%s %s/%s', status_prefix, return_string, s, test) 993*b7c941bbSAndroid Build Coastguard Worker test_name = test.split('/')[-1].split('.')[0] 994*b7c941bbSAndroid Build Coastguard Worker results[s]['TEST_STATUS'].append({ 995*b7c941bbSAndroid Build Coastguard Worker 'test': test_name, 996*b7c941bbSAndroid Build Coastguard Worker 'status': return_string.strip()}) 997*b7c941bbSAndroid Build Coastguard Worker if test_mpc_req: 998*b7c941bbSAndroid Build Coastguard Worker results[s][METRICS_KEY].append(test_mpc_req) 999*b7c941bbSAndroid Build Coastguard Worker if hdr_mpc_req: 1000*b7c941bbSAndroid Build Coastguard Worker results[s][METRICS_KEY].append(hdr_mpc_req) 1001*b7c941bbSAndroid Build Coastguard Worker if feature_query_proto: 1002*b7c941bbSAndroid Build Coastguard Worker results[s][FEATURE_QUERY_KEY].append(feature_query_proto) 1003*b7c941bbSAndroid Build Coastguard Worker 1004*b7c941bbSAndroid Build Coastguard Worker msg_short = f'{return_string} {test}' 1005*b7c941bbSAndroid Build Coastguard Worker scene_test_summary += msg_short + '\n' 1006*b7c941bbSAndroid Build Coastguard Worker if (test in _LIGHTING_CONTROL_TESTS and 1007*b7c941bbSAndroid Build Coastguard Worker not testing_flash_with_controller): 1008*b7c941bbSAndroid Build Coastguard Worker print('Turn lights ON in rig and press <ENTER> to continue.') 1009*b7c941bbSAndroid Build Coastguard Worker 1010*b7c941bbSAndroid Build Coastguard Worker # unit is millisecond for execution time record in CtsVerifier 1011*b7c941bbSAndroid Build Coastguard Worker scene_end_time = int(round(time.time() * 1000)) 1012*b7c941bbSAndroid Build Coastguard Worker skip_string = '' 1013*b7c941bbSAndroid Build Coastguard Worker tot_tests = len(scene_test_list) 1014*b7c941bbSAndroid Build Coastguard Worker tot_tests_run = tot_tests - num_skip 1015*b7c941bbSAndroid Build Coastguard Worker if tot_tests_run != 0: 1016*b7c941bbSAndroid Build Coastguard Worker tests_passed_ratio = (num_pass + num_not_mandated_fail) / tot_tests_run 1017*b7c941bbSAndroid Build Coastguard Worker else: 1018*b7c941bbSAndroid Build Coastguard Worker tests_passed_ratio = (num_pass + num_not_mandated_fail) / 100.0 1019*b7c941bbSAndroid Build Coastguard Worker tests_passed_ratio_format = f'{(100 * tests_passed_ratio):.1f}%' 1020*b7c941bbSAndroid Build Coastguard Worker if num_skip > 0: 1021*b7c941bbSAndroid Build Coastguard Worker skip_string = f",{num_skip} test{'s' if num_skip > 1 else ''} skipped" 1022*b7c941bbSAndroid Build Coastguard Worker test_result = (f'{num_pass + num_not_mandated_fail} / {tot_tests_run} ' 1023*b7c941bbSAndroid Build Coastguard Worker f'tests passed ({tests_passed_ratio_format}){skip_string}') 1024*b7c941bbSAndroid Build Coastguard Worker logging.info(test_result) 1025*b7c941bbSAndroid Build Coastguard Worker if num_not_mandated_fail > 0: 1026*b7c941bbSAndroid Build Coastguard Worker logging.info('(*) %s not_yet_mandated tests failed', 1027*b7c941bbSAndroid Build Coastguard Worker num_not_mandated_fail) 1028*b7c941bbSAndroid Build Coastguard Worker 1029*b7c941bbSAndroid Build Coastguard Worker tot_pass += num_pass 1030*b7c941bbSAndroid Build Coastguard Worker logging.info('scene tests: %s, Total tests passed: %s', tot_tests, 1031*b7c941bbSAndroid Build Coastguard Worker tot_pass) 1032*b7c941bbSAndroid Build Coastguard Worker if tot_tests > 0: 1033*b7c941bbSAndroid Build Coastguard Worker logging.info('%s compatibility score: %.f/100\n', 1034*b7c941bbSAndroid Build Coastguard Worker s, 100 * num_pass / tot_tests) 1035*b7c941bbSAndroid Build Coastguard Worker scene_test_summary_path = os.path.join(mobly_scene_output_logs_path, 1036*b7c941bbSAndroid Build Coastguard Worker 'scene_test_summary.txt') 1037*b7c941bbSAndroid Build Coastguard Worker with open(scene_test_summary_path, 'w') as f: 1038*b7c941bbSAndroid Build Coastguard Worker f.write(scene_test_summary) 1039*b7c941bbSAndroid Build Coastguard Worker results[s][RESULT_KEY] = (RESULT_PASS if num_fail == 0 else RESULT_FAIL) 1040*b7c941bbSAndroid Build Coastguard Worker results[s][SUMMARY_KEY] = scene_test_summary_path 1041*b7c941bbSAndroid Build Coastguard Worker results[s][TIME_KEY_START] = scene_start_time 1042*b7c941bbSAndroid Build Coastguard Worker results[s][TIME_KEY_END] = scene_end_time 1043*b7c941bbSAndroid Build Coastguard Worker else: 1044*b7c941bbSAndroid Build Coastguard Worker logging.info('%s compatibility score: 0/100\n') 1045*b7c941bbSAndroid Build Coastguard Worker 1046*b7c941bbSAndroid Build Coastguard Worker # Delete temporary yml file after scene run. 1047*b7c941bbSAndroid Build Coastguard Worker new_yaml_file_path = os.path.join(YAML_FILE_DIR, new_yml_file_name) 1048*b7c941bbSAndroid Build Coastguard Worker os.remove(new_yaml_file_path) 1049*b7c941bbSAndroid Build Coastguard Worker 1050*b7c941bbSAndroid Build Coastguard Worker # Log results per camera 1051*b7c941bbSAndroid Build Coastguard Worker if num_testbeds is None or testbed_index == _MAIN_TESTBED: 1052*b7c941bbSAndroid Build Coastguard Worker logging.info('Reporting camera %s ITS results to CtsVerifier', camera_id) 1053*b7c941bbSAndroid Build Coastguard Worker logging.info('ITS results to CtsVerifier: %s', results) 1054*b7c941bbSAndroid Build Coastguard Worker report_result(device_id, camera_id, tablet_name, results) 1055*b7c941bbSAndroid Build Coastguard Worker else: 1056*b7c941bbSAndroid Build Coastguard Worker write_result(testbed_index, device_id, camera_id, results) 1057*b7c941bbSAndroid Build Coastguard Worker 1058*b7c941bbSAndroid Build Coastguard Worker logging.info('Test execution completed.') 1059*b7c941bbSAndroid Build Coastguard Worker 1060*b7c941bbSAndroid Build Coastguard Worker # Power down tablet 1061*b7c941bbSAndroid Build Coastguard Worker if tablet_id: 1062*b7c941bbSAndroid Build Coastguard Worker cmd = f'adb -s {tablet_id} shell input keyevent KEYCODE_POWER' 1063*b7c941bbSAndroid Build Coastguard Worker subprocess.Popen(cmd.split()) 1064*b7c941bbSAndroid Build Coastguard Worker 1065*b7c941bbSAndroid Build Coastguard Worker # establish connection with lighting controller 1066*b7c941bbSAndroid Build Coastguard Worker lighting_cntl = test_params_content.get('lighting_cntl', 'None') 1067*b7c941bbSAndroid Build Coastguard Worker lighting_ch = test_params_content.get('lighting_ch', 'None') 1068*b7c941bbSAndroid Build Coastguard Worker arduino_serial_port = lighting_control_utils.lighting_control( 1069*b7c941bbSAndroid Build Coastguard Worker lighting_cntl, lighting_ch) 1070*b7c941bbSAndroid Build Coastguard Worker 1071*b7c941bbSAndroid Build Coastguard Worker # turn OFF lights 1072*b7c941bbSAndroid Build Coastguard Worker lighting_control_utils.set_lighting_state( 1073*b7c941bbSAndroid Build Coastguard Worker arduino_serial_port, lighting_ch, 'OFF') 1074*b7c941bbSAndroid Build Coastguard Worker 1075*b7c941bbSAndroid Build Coastguard Worker if num_testbeds is not None: 1076*b7c941bbSAndroid Build Coastguard Worker if testbed_index == _MAIN_TESTBED: 1077*b7c941bbSAndroid Build Coastguard Worker logging.info('Waiting for all testbeds to finish.') 1078*b7c941bbSAndroid Build Coastguard Worker start = time.time() 1079*b7c941bbSAndroid Build Coastguard Worker completed_testbeds = set() 1080*b7c941bbSAndroid Build Coastguard Worker while time.time() < start + MERGE_RESULTS_TIMEOUT: 1081*b7c941bbSAndroid Build Coastguard Worker for i in range(num_testbeds): 1082*b7c941bbSAndroid Build Coastguard Worker if os.path.isfile(f'testbed_{i}_completed.tmp'): 1083*b7c941bbSAndroid Build Coastguard Worker start = time.time() 1084*b7c941bbSAndroid Build Coastguard Worker completed_testbeds.add(i) 1085*b7c941bbSAndroid Build Coastguard Worker # Already reported _MAIN_TESTBED's results. 1086*b7c941bbSAndroid Build Coastguard Worker if len(completed_testbeds) == num_testbeds - 1: 1087*b7c941bbSAndroid Build Coastguard Worker logging.info('All testbeds completed, merging results.') 1088*b7c941bbSAndroid Build Coastguard Worker for parsed_id, parsed_camera, parsed_results in ( 1089*b7c941bbSAndroid Build Coastguard Worker parse_testbeds(completed_testbeds)): 1090*b7c941bbSAndroid Build Coastguard Worker logging.debug('Parsed id: %s, parsed cam: %s, parsed results: %s', 1091*b7c941bbSAndroid Build Coastguard Worker parsed_id, parsed_camera, parsed_results) 1092*b7c941bbSAndroid Build Coastguard Worker if not are_devices_similar(device_id, parsed_id): 1093*b7c941bbSAndroid Build Coastguard Worker logging.error('Device %s and device %s are not the same ' 1094*b7c941bbSAndroid Build Coastguard Worker 'model/type/build/revision.', 1095*b7c941bbSAndroid Build Coastguard Worker device_id, parsed_id) 1096*b7c941bbSAndroid Build Coastguard Worker return 1097*b7c941bbSAndroid Build Coastguard Worker report_result(device_id, parsed_camera, tablet_name, parsed_results) 1098*b7c941bbSAndroid Build Coastguard Worker for temp_file in glob.glob('testbed_*.tmp'): 1099*b7c941bbSAndroid Build Coastguard Worker os.remove(temp_file) 1100*b7c941bbSAndroid Build Coastguard Worker break 1101*b7c941bbSAndroid Build Coastguard Worker else: 1102*b7c941bbSAndroid Build Coastguard Worker logging.error('No testbeds finished in the last %d seconds, ' 1103*b7c941bbSAndroid Build Coastguard Worker 'but still expected data. ' 1104*b7c941bbSAndroid Build Coastguard Worker 'Completed testbed indices: %s, ' 1105*b7c941bbSAndroid Build Coastguard Worker 'expected number of testbeds: %d', 1106*b7c941bbSAndroid Build Coastguard Worker MERGE_RESULTS_TIMEOUT, list(completed_testbeds), 1107*b7c941bbSAndroid Build Coastguard Worker num_testbeds) 1108*b7c941bbSAndroid Build Coastguard Worker else: 1109*b7c941bbSAndroid Build Coastguard Worker with open(f'testbed_{testbed_index}_completed.tmp', 'w') as _: 1110*b7c941bbSAndroid Build Coastguard Worker pass 1111*b7c941bbSAndroid Build Coastguard Worker 1112*b7c941bbSAndroid Build Coastguard Workerif __name__ == '__main__': 1113*b7c941bbSAndroid Build Coastguard Worker main() 1114