class HttpDownloadLoop(DeviceTestStepBase): def run(self, context): """ Runs the test step @type context: TestStepContext @param context: test case context """ DeviceTestStepBase.run(self, context) self._logger.info("HttpDownloadStress: Run") self._device_manager = DeviceManager() runtime_minutes = self._pars.duration sleep_time_seconds = self._pars.sleep_time serve_from_host = self._pars.serve_from_host file_download_url = self._pars.file_download_url expected_file_checksum = self._pars.expected_file_checksum allowed_retries = self._pars.allowed_retries host_file_name = self._pars.host_file_name device_directory = self._pars.scripts_path self._device.remove_device_files(device_directory, "*.log") self._device.remove_device_files(device_directory, "*.bin") download_file_extension = os.path.splitext( os.path.basename(file_download_url))[1] self._device.remove_device_files( device_directory, '*.{0}'.format(download_file_extension)) # If we aren't serving from the host and the file download URL is not provided, # we don't have anything for the device to download if serve_from_host == False and file_download_url == None: msg = "No file to download. SERVE_FROM_HOST==False and FILE_DOWNLOAD_URL was not specified." self._ts_verdict_msg = msg raise DeviceException(DeviceException.OPERATION_FAILED, msg) if serve_from_host: # Rewrite our URL to point to this host # This is a really ugly URL. But to serve from the non-current-working-directory # is a lot more work so we'll save that for another time. # Get our port number report_path = self._device_manager.get_global_config( ).campaignConfig.get("campaignReportTree").get_report_path() tc_name = self._tc_parameters.get_name() http_running_file_path = os.path.join(report_path, tc_name, 'http_download_loop', '.http_running') run_file = open(http_running_file_path) port = run_file.read() run_file.close() file_download_url = "http://%s:%s/%s" % (socket.gethostbyname( socket.getfqdn()), port, host_file_name) # If we are serving from the host, lets calculate the checksum from the file on the host http_serve_file = open( os.path.join(report_path, tc_name, 'http_download_loop', 'http_serve', host_file_name), 'rb') md5_hash = hashlib.md5() read_data = http_serve_file.read(1024 * 1024) while read_data: md5_hash.update(read_data) read_data = http_serve_file.read(1024 * 1024) expected_file_checksum = md5_hash.hexdigest() http_serve_file.close() # Run test with all parameters # Give it a 10 minute (600 second) extra timeout because the script will finish the main # loop on time, but then it removes a bunch of files. On a 30 minute run, # it took 2 minutes and 20 seconds to delete the files. cmd = 'adb shell "cd %s; ./file_download.sh --duration_minutes=%d --sleep_seconds=%d --url=%s --file_checksum=%s --allowed_retries=%d"' % ( device_directory, runtime_minutes, sleep_time_seconds, file_download_url, expected_file_checksum, allowed_retries) verdict, output = self._device.run_cmd(cmd, (runtime_minutes + 1) * 60) if verdict == Global.FAILURE: msg = "Http_Download_Stress: run_cmd failed\n" self._ts_verdict_msg = msg raise DeviceException(DeviceException.OPERATION_FAILED, msg) else: self._logger.info("Http_Download_Stress: PASSED")
class PlayVideoLoop(DeviceTestStepBase): def __init__(self, tc_conf, global_conf, ts_conf, factory): """ Constructor """ DeviceTestStepBase.__init__(self, tc_conf, global_conf, ts_conf, factory) # Load Multimedia ue command. self._multimedia_api = self._device.get_uecmd("Multimedia") self._video_api = self._device.get_uecmd("Video") self._phonesystem_api = self._device.get_uecmd("PhoneSystem") self._system_api = self._device.get_uecmd("System") self._device_manager = DeviceManager() self._device_logger = self._device.get_device_logger() def run(self, context): """ Runs the test step :type context: TestStepContext :param context: test case context """ DeviceTestStepBase.run(self, context) self._logger.debug("START PLAY_VIDEO_LOOP Run Phase") #Get Video Playback parameters videoFile = self._pars.video_file runtime_seconds = self._pars.duration * 60 vsp_enabled = self._pars.intel_smart_video_enabled hwc_enabled = self._pars.hwc_enabled monitor_dropped_frames = self._pars.monitor_dropped_frames report_path = self._device_manager.get_global_config( ).campaignConfig.get("campaignReportTree").get_report_path() tc_name = self._tc_parameters.get_name() test_files_root = os.path.join(report_path, tc_name, 'play_video_loop') vlist = videoFile.replace(', ', ',') num_of_videos = len(videoFile.split(',')) # Start to monitor video decoder error conditions video_decoder_error_messages = self._device.get_video_decoder_error_messages( ) self._system_api.start_log_monitoring( device_logger=self._device_logger, target_messages=video_decoder_error_messages) # Start to monitor VSP error conditions if vsp_enabled == True: video_enhancer_error_messages = self._device.get_video_decoder_error_messages( ) self._system_api.start_log_monitoring( device_logger=self._device_logger, target_messages=video_enhancer_error_messages) #Disable hardware composer if the HWC_ENABLED parameter is false if hwc_enabled == False: self._multimedia_api.set_hardware_composer(enable=False) #Enabled Intel Smart Video if the INTEL_SMART_VIDEO_ENABLED parameter is true if vsp_enabled == True: self._multimedia_api.set_intel_smart_video(enable=True) start_time = time.time() if (num_of_videos == 1): self._video_api.play(filename=videoFile, loop=True, screen_orientation='landscape') else: Package = "com.example.gdc_cv_videoloop" triglogAppmsg = [[ "PackageActivity " + Package, "CV Video Loop: Video execution path: file:" ]] # Add triglogs for applications and drivers for triglog in triglogAppmsg: self._device_logger.add_trigger_message(triglog[1]) self._multimedia_api.play_video_list( vlist, self._pars.duration, screen_orientation='landscape') #Check logs for messages that indicate successful start of the activity for triglog in triglogAppmsg: time.sleep(1) messages = self._device_logger.get_message_triggered_status( triglog[1]) if len(messages) == 0: msg = triglog[ 0] + " failed to start properly. Could not find this message in the log: " + triglog[ 1] raise DeviceException(DeviceException.OPERATION_FAILED, msg) #Remove trigger messages for errors for triglog in triglogAppmsg: self._device_logger.remove_trigger_message(triglog[1]) #Wait for 10 seconds to check play back status time.sleep(10) while time.time() - start_time < runtime_seconds: if (num_of_videos == 1): (is_playing, played_duration) = self._video_api.is_playing() else: #Check whether the application is running. is_playing = self._phonesystem_api.check_process(Package) if not is_playing: msg = "Video playback is not working.\n" self.ts_verdict_msg = msg raise DeviceException(DeviceException.OPERATION_FAILED, msg) # If set to true, we'll not be able to rely on this thread because USB connection for ADB will be disconnected periodically and therefore won't start it. if not monitor_dropped_frames: self._logger.debug("Starting to check for dropped frames.\n") (cmd_output, no_total_frames, no_dropped_frames ) = self._multimedia_api.get_number_of_dropped_frames() percentage_frames_dropped = float(no_dropped_frames) / float( no_total_frames) if percentage_frames_dropped > 0.1: self._logger.error( "Exceeded dropped frame rate of 10%. Dropped rate is %.1f%%. Failing test" % percentage_frames_dropped) frames_dropped_log_file = open( os.path.join(test_files_root, "frames_dropped.log"), 'a') frames_dropped_log_file.write(cmd_output) frames_dropped_log_file.close() self._logger.debug("Videoplayback: Passed {0} seconds".format( round(time.time() - start_time, 0))) time.sleep(30) # Check for system UI systemui_ok = self._phonesystem_api.check_process("systemui") if systemui_ok == False: self._logger.error("Systemui is not active.") raise DeviceException(DeviceException.OPERATION_FAILED, "Systemui is not active.") else: self._logger.info("Systemui is active") if (num_of_videos == 1): self._video_api.stop() else: self._system_api.stop_app(Package) #Verify if frame drop occurred if os.path.exists(os.path.join(test_files_root, 'frame_dropped.log')): msg = "Too many frames were dropped. Failing test." self.ts_verdict_msg = msg raise DeviceException(DeviceException.OPERATION_FAILED, msg) #Verify if logs for error messages were triggered self._system_api.check_logged_errors( device_logger=self._device_logger, target_messages=video_decoder_error_messages) #Stop to monitor video decoder error conditions self._system_api.stop_log_monitoring( device_logger=self._device_logger, target_messages=video_decoder_error_messages) if vsp_enabled == True: # verify VSP error messages are triggered self._system_api.check_logged_errors( device_logger=self._device_logger, target_messages=video_enhancer_error_messages) # Stop to monitor VSP error conditions self._system_api.stop_log_monitoring( device_logger=self._device_logger, target_messages=video_enhancer_error_messages) # Turn off VSP features by writing to the Intel Smart Video shared preferences file. self._multimedia_api.set_intel_smart_video(enable=False) # Turn on HWC features if hwc_enabled == False: self._multimedia_api.set_hardware_composer(enable=True) self._logger.info("Video playback PASSED") self._logger.debug("FINISHED PLAY_VIDEO_LOOP Run Phase")
class InstallFileHost(TestStepBase): """ Install a file on a host """ def run(self, context): """ Runs the test step :type context: TestStepContext :param context: test case context """ TestStepBase.run(self, context) # Check whether source file exist or not if not os.path.isfile(self._pars.src_file_path): error_msg = "{0}: File {1} does not exist!".format( self._pars.id, self._pars.src_file_path) raise AcsConfigException(AcsConfigException.INVALID_PARAMETER, error_msg) basename_file = os.path.basename( self._pars.src_file_path) # File name of the source file zipped = self._pars.type == "zipped_tarball" or self._pars.type == "tarball" or self._pars.type == "zipped" (dest_parentdir, sep, dest_subdir) = self._pars.dest_dir.partition('/') if dest_parentdir == '[REPORT]': #Destination directory will be located under _Report directory self._device_manager = DeviceManager() report_path = self._device_manager.get_global_config( ).campaignConfig.get("campaignReportTree").get_report_path() host_destination = os.path.join(report_path, self._tc_parameters.get_name(), dest_subdir) # Destination path #Create the destination directory if not os.path.exists(host_destination): self._logger.debug("{0}: make {1} folder".format( self._pars.id, host_destination)) os.makedirs(host_destination) elif self._pars.src_file_path == self._pars.dest_dir and zipped: # We will unzip in the same directory as the src_file path. host_destination = os.path.dirname(self._pars.dest_dir) basename_file = "" else: #Destination directory is given as an absolute path host_destination = self._pars.dest_dir #Create the destination directory if not os.path.exists(host_destination): self._logger.debug("{0}: make {1} folder".format( self._pars.id, host_destination)) os.mkdir(host_destination) if self._pars.type == 'media' or self._pars.type == "bin": shutil.copy(self._pars.src_file_path, host_destination) elif zipped: tfile = tarfile.open(self._pars.src_file_path) try: tfile.extractall(host_destination) except IOError as e: try: # Have seen it fail the first time before due to "Text file busy" error of one member. tfile.extractall(host_destination) except IOError as e: # Two times should have been enough tries. self._logger.error( "{0}: IOError happened two times trying to extract {1} to {2}! Raising exception!\nI/o error({3}): {4}" .format(self._pars.id, basename_file, host_destination, e.errno, e.strerror)) raise except: self._logger.error( "{0}: Unexpected error occured while trying to extract {1} to {2}\n" .format(self._pars.id, basename_file, host_destination) + traceback.format_exc()) raise except: self._logger.error( "Unexpected error occured while trying to extract {0} to {1}\n" .format(basename_file, host_destination) + traceback.formate_exc()) raise tfile.close() if os.path.exists(host_destination): msg = "{0}: Installed {1} to {2}".format(self._pars.id, basename_file, host_destination) self._logger.info(msg) context.set_info(self._pars.destination_stored_path, os.path.join(host_destination, basename_file)) else: msg = "{0}: Failed to install {1} to {2}".format( self._pars.id, basename_file, host_destination) self._logger.info(msg) raise AcsConfigException(AcsConfigException.OPERATION_FAILED, msg)
class RecordVideoLoop(DeviceTestStepBase): def run(self, context): """ Runs the test step @type context: TestStepContext @param context: test case context """ DeviceTestStepBase.run(self, context) self._logger.info(self._pars.id + ": Test step starting.") # App signature to use with gui focus lock file appSignature = 'record_video_loop' try: # Delete any focus-lock file that may not have been released during the previous test run. osbv_utils.cleanup_focus_lock(appSignature) except: raise DeviceException(DeviceException.OPERATION_FAILED, self._pars.id + ": Issue trying to remove previous focus lock file.") loop_count = 1 # variable for the different resolution video recording. loop_cnt =0 self.videos_saved = 0 self.total_videos_saved = 0 error_counts = {} self.video_file_type = "mp4" # Timeout value to use that determines amount of time to wait on gui focus lock file to be removed. self.gui_lock_wait_time = self._pars.gui_lock_wait_time self._dut_os = self._device.get_device_os_path() # Set report path self._device_manager = DeviceManager() # Create folder under report path to put files into when there is an issue. self.report_path = self._device_manager.get_global_config().campaignConfig.get("campaignReportTree").create_subfolder('record_video_loop') # Following call creates directory to store files created from TS that will generally not be needed unless an error is hit. self.temp_dir = osbv_utils.test_step_temp_dir(self) # Create folder under temp_dir to put videos from device into. self.host_save_folder = os.path.join(self.temp_dir, 'saved_videos') if not os.path.exists(self.host_save_folder): os.makedirs(self.host_save_folder) # Get UECmdLayer self._camera_api = self._device.get_uecmd("Camera") self._keyevent_api = self._device.get_uecmd("KeyEvent") self._file_api = self._device.get_uecmd("File") self._phone_system_api = self._device.get_uecmd("PhoneSystem") self._camera_app = self._camera_api.get_camera_version(self._pars.camera_app) if self._camera_app == "Android_Intel_Camera_v2.2" or self._camera_app == "Android_Google_Camera_v2.0": self._camera_api.camera_app_setup(self._camera_app, 'video') else: error_msg = self._pars.id + ": Selected camera app: {0} is not supported".format(self._camera_app) self._logger.error(error_msg) raise AcsConfigException(AcsConfigException.INVALID_PARAMETER, error_msg) start_time = float(time.time()) end_time = start_time + (float(self._pars.duration)) * 60 try: # Following calls will remove all files in the save directory(ies). for directory in self._camera_api.device_save_directory: try: self._phone_system_api.delete(directory + self._dut_os.sep + '*.*') except DeviceException: self._logger.info(self._pars.id + ": Directory {0} was already empty.".format(directory)) while (time.time() < end_time): # Primary Test Loop # The following actions are executed in every loop: # 1. Open the camera app # 2. Start video capture # 3. Wait a random time period defined by user params # 4. Stop video capture # 5. Verify video file was created # 6. Move the video to our save directory. # 7. If loop%self._pars.video_upload_modulus==0, pull save directory to the PC and delete them from the device return_code = 0 video_duration = random.randint(self._pars.video_interval_min, self._pars.video_interval_max) self._logger.info(self._pars.id + ": Loop %d."%(loop_count)) loop_start_time = datetime.datetime.now() # Lock the GUI focus before starting video_capture so that video capture doesn't conflict with other apps. if not osbv_utils.set_focus_lock(appSignature, timeout_sec=self._pars.gui_lock_wait_time): # Could not set the focus-lock raise DeviceException(DeviceException.OPERATION_FAILED, self._pars.id + ": Video Capture failed to set the focus-lock!") self._logger.debug(self._pars.id + ": Starting camera application") # Prepare video capture by making sure it is correctly launched and in gui focus. (return_code, reset_loop) = self._camera_api.prepare_video_capture(error_counts = error_counts, restart_app = self._pars.restart_app, checkTriglogMsg = True) if return_code == -1: # Test has failed #[12/19/14: Jong ] After failure, there does not exist a directory to clean out #self.cleanup_test(error_counts) self.ts_verdict_msg = self._pars.id + ": Test has failed after trying to capture video!" raise DeviceException(DeviceException.OPERATION_FAILED, self._pars.id + ": Test has failed after trying to capture video!") if reset_loop: # Check if focus lock still exists with video capture's appSignature and remove if so. if appSignature == osbv_utils.get_lock_signature(): if not osbv_utils.release_focus_lock(appSignature): # Unable to release the focus-lock raise DeviceException(DeviceException.OPERATION_FAILED, self._pars.id + ": Video_Capture failed to release the focus-lock!") continue # Recording videos of different resolution. if self._pars.record_type == 'DIFFRES': device_orient=self._camera_api.device_orientation() # Check camera in use. We want "BACK" (world facing) camera. stat = self._camera_api.get_camera_in_use() if stat == "FRONT": # Change from "FRONT" to "BACK". self._camera_api.change_camera("back") # Verify whether the camera is changed or not. check_f = self._camera_api.get_camera_in_use() if check_f == "BACK": self._logger.debug("{0}: 'BACK' camera is now selected.".format(self._pars.id)) else: self._logger.error("{0}: Camera is not changed to 'BACK'".format(self._pars.id)) raise DeviceException(DeviceException.INVALID_DEVICE_STATE, "{0}: Camera in use should be 'BACK' but is still {1}.".format(self._pars.id, check_f)) elif stat == "BACK": self._logger.debug("{0}: Back camera is selected.".format(self._pars.id)) else: self._logger.error("{0}: Camera is not properly selected.".format(self._pars.id)) raise DeviceException(DeviceException.INVALID_DEVICE_STATE, self._pars.id + ": Camera is not properly selected.") self._camera_api.select_camera_settings() # Switch between different resolution options: SD, HD, HD(HS), Full HD, Full HD(HS) if device_orient== 'portrait' : keyevent_list= ["DPAD_RIGHT","DPAD_RIGHT","DPAD_RIGHT","ENTER"] for i in range(0,loop_cnt%5) : keyevent_list.append("DPAD_RIGHT") elif device_orient== 'landscape' : keyevent_list= ["DPAD_DOWN","DPAD_DOWN","DPAD_DOWN","ENTER"] for i in range(0,loop_cnt%5) : keyevent_list.append("DPAD_DOWN") else: self._logger.error(self._pars.id + ": " + device_orient + " is not a proper orientation. ") raise DeviceException(DeviceException.OPERATION_FAILED, self._pars.id + ": " + device_orient + " is not a proper orientation.") keyevent_list.append("ENTER") self._keyevent_api.scenario(keyevent_list,1) time.sleep(2) loop_cnt+=1 self._logger.debug(self._pars.id + ": Recording started. Waiting %d seconds until stopping."%video_duration) self._camera_api.camera_application_start_stop_recording(video_duration) self._logger.info(self._pars.id + ": Video recording done.") # Release the GUI focus lock so that other apps can take focus if not osbv_utils.release_focus_lock(appSignature): # Unable to release the focus-lock raise DeviceException(DeviceException.OPERATION_FAILED, self._pars.id + ": Video Capture failed to release the focus-lock!") # Verify that the video was captured in SD card or eMMC. self._logger.info(self._pars.id + ': Checking for video files in save directory(ies).') (video_found, reset_loop, self.videos_saved) = self._camera_api.verify_video_creation(error_counts = error_counts, videos_saved = self.videos_saved) if reset_loop: # We must have hit a known issue. Try to stop app to see if it helps and retry this iteration of the loop. self._camera_api.stop_system_camera_application() continue if not video_found: # No video file was found and no known issues were hit. Video capture failed and now exiting thread. self.cleanup_test(error_counts) self.ts_verdict_msg = self._pars.id + ": No video file was found and no known issues were hit, test has failed." raise DeviceException(DeviceException.OPERATION_FAILED, self._pars.id + ": Failed to execute correctly.") if loop_count%self._pars.video_upload_modulus == 0: # Pull the video files to the PC self._logger.info(self._pars.id + ': Pulling video files from device to the PC log directory') self._camera_api.upload_output_files(False, self.host_save_folder) self.total_videos_saved += self.videos_saved self.videos_saved = 0 loop_time_delta = datetime.datetime.now() - loop_start_time loop_time_delta_hours = loop_time_delta.seconds/(60*60) loop_time_delta_minutes = (loop_time_delta.seconds-(loop_time_delta_hours*(60*60)))/60 loop_time_delta_seconds = loop_time_delta.seconds-(loop_time_delta_hours*(60*60))-(loop_time_delta_minutes*60) self._logger.info(self._pars.id + ": Loop %d duration: %02d:%02d:%02d"%(loop_count, loop_time_delta_hours, loop_time_delta_minutes, loop_time_delta_seconds)) loop_count += 1 self._logger.info(self._pars.id + ': Test complete successfully. {0} videos recorded'.format(self.total_videos_saved)) self.cleanup_test(error_counts) # Kill the camera app self._camera_api.stop_system_camera_application() except OSError as e: self._logger.error(self._pars.id + ": OS Error({0}): {1}".format(e.errno, e.strerror)) raise except: import traceback self._logger.error(self._pars.id + ": Unexpected exception -> " + str(sys.exc_info()[0])) self._logger.error(traceback.format_exc()) self.ts_verdict_msg = self._pars.id + ": Unexpected exception being raised" raise finally: # Check if focus lock still exists with video capture's appSignature and remove if so. if appSignature == osbv_utils.get_lock_signature(): if not osbv_utils.release_focus_lock(appSignature): # Unable to release the focus-lock raise DeviceException(DeviceException.OPERATION_FAILED, self._pars.id + ": Video_Capture failed to release the focus-lock!") self._logger.info(self._pars.id + ": Test step finished.") def cleanup_test(self, error_counts): (result, output) = self._file_api.exist(self._camera_api.backup_dir + self._dut_os.sep + "*." + self.video_file_type) if result: self._camera_api.upload_output_files(False, self.host_save_folder) if len(error_counts) != 0: self._logger.info(self._pars.id + ": Issues encountered:") for error in error_counts: self._logger.info(" %s: %d"%(error, error_counts[error])) self._logger.error(self._pars.id + ": Pulling error screenshots and logcat files from DUT...") imageDir = os.path.join(self.report_path,'error_images_%s'%datetimestamp.fromtimestamp(time.time()).strftime('%Y-%m-%d_%H-%M-%S')) if not os.path.exists(imageDir): os.makedirs(imageDir) self._camera_api.upload_output_files(True, imageDir)
class RunUMGAudioDockToolkit(EquipmentTestStepBase): """ Start audio docking toolkit on UNIX host PC """ def __init__(self, tc_conf, global_conf, ts_conf, factory): EquipmentTestStepBase.__init__(self, tc_conf, global_conf, ts_conf, factory) self.local_computer = None def run(self, context): """ Run MCG audio docking toolkit :type context: TestStepContext :param context: test case context """ EquipmentTestStepBase.run(self, context) self.local_computer = self._equipment_manager.get_computer("COMPUTER1") self._logger.info(self._pars.id + ": Test step starting.") # Set report path self._device_manager = DeviceManager() report_path = self._device_manager.get_global_config( ).campaignConfig.get("campaignReportTree").create_subfolder( 'run_umg_audio_dock_toolkit') # Use these to log stdout and stderr under the report directory created for this test step in <root>\acs\src\_Reports. self._logger.info( "{0}: stdout and stderr logs will be stored in this directory - {1}" .format(self._pars.id, report_path)) stdout_log = open(os.path.join(report_path, "dock_toolkit_stdout.log"), 'w') stderr_log = open(os.path.join(report_path, "dock_toolkit_stderr.log"), 'w') # We use os.name b/c there's a good chance the audio docking files will work on all *ix operating systems if os.name != 'posix': # We raise an exception so that the rest of this script is not executed raise AcsConfigException( self._pars.id + ": The USB audio docking test is only executable in a Linux-like OS." ) self._logger.debug(self._pars.id + ": Report path is {0} folder".format(report_path)) # Since this is only meant to run on ubuntu host, not worrying about OS type with regards to the cmd being run on host PC. try: # Make sure we have permission to create log files in report directory. os.chmod(report_path, 0o777) cur_dir = os.getcwd() os.chdir(self._pars.scripts_path) self.local_computer.run_cmd("./run", timeout=-1, stdout=stdout_log, stderr=stderr_log) os.chdir(cur_dir) # We want this test step to last at least as long as we are playing audio on device or longer. Adding a couple minutes to duration. time.sleep((self._pars.duration + 2) * 60) except: import traceback self._logger.error(self._pars.id + ": Unexpected exception -> " + str(sys.exc_info()[0])) self._logger.error(traceback.format_exc()) self.ts_verdict_msg = self._pars.id + ": Unexpected exception being raised" raise finally: # Using -1 timeout with run_cmd when launching the dock toolkit let us launch as async process which is stored in self.local_computer._async_process. # Since the toolkit will run indefinitely, we must force it to end with terminate() method. self.local_computer._async_process.terminate() self._logger.info(self._pars.id + ": Test step finished.")
class TakePicturesLoop(DeviceTestStepBase): def run(self, context): """ Runs the test step @type context: TestStepContext @param context: test case context """ DeviceTestStepBase.run(self, context) self._logger.info(self._pars.id + ": Test step starting.") # App signature to use with gui focus lock file appSignature = 'take_pictures_loop' try: # Delete any focus-lock file that may not have been released during the previous test run. osbv_utils.cleanup_focus_lock(appSignature) except: raise DeviceException(DeviceException.OPERATION_FAILED, self._pars.id + ": Issue trying to remove previous focus lock file.") loop = 1 numPicsTaken = 0 num_pics_to_take = 2 # Number of consecutive retries in loop before it would fail due to too many. max_retries = 50 retry = max_retries self.pic_file_type = "jpg" self._dut_os = self._device.get_device_os_path() # Set report path self._device_manager = DeviceManager() self.report_path = self._device_manager.get_global_config().campaignConfig.get("campaignReportTree").create_subfolder('take_pictures_loop') # Following call creates directory to store files created from TS that will generally not be needed unless an error is hit. self.temp_dir = osbv_utils.test_step_temp_dir(self) # Create folder under temp_dir to put pictures from device into. self.host_save_folder = os.path.join(self.temp_dir, 'saved_pics') # Timeout value to use that determines amount of time to wait on gui focus lock file to be removed. self.gui_lock_wait_time = self._pars.gui_lock_wait_time if not os.path.exists(self.host_save_folder): os.makedirs(self.host_save_folder) # Get UECmdLayer self._camera_api = self._device.get_uecmd("Camera") self._file_api = self._device.get_uecmd("File") self._camera_app = self._camera_api.get_camera_version(self._pars.camera_app) # Set camera application to image capture mode self._camera_api.camera_app_setup(self._camera_app, 'camera') start_time = float(time.time()) end_time = start_time + (float(self._pars.duration)) * 60 errorCount = { 'camConnectionErr':0, 'camStopped' :0, 'camNotResponding':0, 'unclassifiedFail':0 } try: # Following calls will remove all files in the save directory(ies). for directory in self._camera_api.device_save_directory: try: self._device.get_uecmd("PhoneSystem").delete(directory + self._dut_os.sep + '*.*') except DeviceException: self._logger.info(self._pars.id + ": Directory {0} was already empty.".format(directory)) # Verify which camera app is used and run the below commands only if Intel camera is used. if self._camera_app in ("Android_Intel_Camera_v2.2", "Android_Intel_Refcam2_v0.9", "Android_Google_Camera_v2.4", "Android_Intel_RefCam_v1.0"): #Open the camera app to check the initial camera used(Front or Back) self._camera_api.launch_system_camera_application(checkTriglogMsg = True, reset = True) # Wait for 4 second to load the camera app. the first launch takes longer due to driver initialization time.sleep(4) # Check camera in use and if it is not what user has chosen to be used, change it. stat = self._camera_api.get_camera_in_use() if stat != self._pars.camera_to_use: # We need to switch the camera in use. if stat == "BACK": self._camera_api.change_camera("front") elif stat == "FRONT": self._camera_api.change_camera("back") else: raise DeviceException(DeviceException.INVALID_DEVICE_STATE, self._pars.id + ": Camera used is " + stat + ", failing test.") # Wait for 2 second to switch camera time.sleep(2) # Verify whether the camera is changed or not. check_f = self._camera_api.get_camera_in_use() if self._pars.camera_to_use == check_f: self._logger.info("{0}: {1} camera is now selected.".format(self._pars.id, self._pars.camera_to_use)) else: self._logger.error("{0}: Camera is not changed".format(self._pars.id)) raise DeviceException(DeviceException.INVALID_DEVICE_STATE, "{0}: Camera in use should be {1} but is still {2}.".format(self._pars.id, self._pars.camera_to_use, check_f)) while (time.time() < end_time): self._logger.info(self._pars.id + ": Starting loop {0}".format(loop)) time_start1 = float(time.time()) self._logger.info(self._pars.id + ": Start image capturing:") if not osbv_utils.set_focus_lock(appSignature, timeout_sec=self.gui_lock_wait_time): # Could not set the focus-lock raise DeviceException(DeviceException.OPERATION_FAILED, self._pars.id + ": Failed to set focus lock.") if self._pars.restart_app: # Stops and starts app. self._camera_api.launch_system_camera_application(checkTriglogMsg = True, reset = True) else: # Displays app if not started. self._camera_api.launch_system_camera_application(checkTriglogMsg = True) # Wait for 1 second to re-load the camera app time.sleep(1) if self._camera_app in ("Android_Intel_Refcam2_v0.9", "Android_Intel_RefCam_v1.0"): # take picture if self._pars.camera_mode == "BURST": #Settings for selecting burst mode self._camera_api.toggle_burst_mode() self._camera_api.camera_refcam_take_picture(1) else: self._camera_api.camera_refcam_take_picture(num_pics_to_take) else : # Sleeps default of 5 seconds between each picture for a non-burst mode. self._camera_api.camera_application_take_picture(num_pics_to_take) if not osbv_utils.release_focus_lock(appSignature): # Could not release the focus-lock raise DeviceException(DeviceException.OPERATION_FAILED, self._pars.id + ": Failed to release focus lock.") retVal = int(self._camera_api.move_files_to_backup_dir(self._camera_api.device_save_directory)) if (retVal - numPicsTaken) == 0: # Check the error type and increment errorCount appropriately errorCode = self._camera_api.check_for_camera_issues(errorCount) # Reset the retry counter if this is a known issue if errorCode != 'unclassifiedFail': retry = max_retries if retry < 1: # The test failed self.fail_test_cleanup(numPicsTaken, errorCount) self.ts_verdict_msg = self._pars.id + ": Too many loop retries, test has failed." raise DeviceException(DeviceException.OPERATION_FAILED, self._pars.id + ": Failed to execute correctly.") self._logger.info(self._pars.id + ": This iteration of image capture failed. Allowing %d more attempts..."%(retry-1)) retry -= 1 continue elif retry < max_retries: # image_capture recovered, so reset the retry counter retry = max_retries numPicsTaken = retVal # Count iteration time self.delta(time_start1,1, loop) loop += 1 if ((loop % 20) == 0): self._logger.info(self._pars.id + ': Copy newly captured images to host dir: {0}'.format(self.host_save_folder)) time_start2 = float(time.time()) #Pull pics to host every 20 iterations of loop. self._camera_api.upload_output_files(False, self.host_save_folder) self.delta(time_start2, 2, loop) # Sleep at random interval between min and max before moving towards next loop iteration. time.sleep(random.randint(self._pars.picture_interval_min, self._pars.picture_interval_max)) self._logger.info(self._pars.id + ": Number of pictures taken = %d"%numPicsTaken) # Times up! The test passed if it made it this far without encountering a failure and we've taken pictures. time_start2= float(time.time()) self.delta(time_start2,2, loop) # The test passed unless 0 pictures were taken. if numPicsTaken < 1: self._logger.info(self._pars.id + ' is at the end of the test but has {0} pictures were taken... faling test.'.format(numPicsTaken)) self.fail_test_cleanup(numPicsTaken, errorCount) self.ts_verdict_msg = self._pars.id + ": Finished loop without any pictures taken!" raise DeviceException(DeviceException.OPERATION_FAILED, self._pars.id + ": Failed to execute correctly.") else: self.pass_test_cleanup(numPicsTaken, errorCount) except OSError as e: self._logger.error(self._pars.id + ": OS Error({0}): {1}".format(e.errno, e.strerror)) raise except: import traceback self._logger.error(self._pars.id + ": Unexpected exception -> " + str(sys.exc_info()[0])) self._logger.error(traceback.format_exc()) self.ts_verdict_msg = self._pars.id + ": Unexpected exception being raised" raise finally: # Check if focus lock still exists with video capture's appSignature and remove if so. if appSignature == osbv_utils.get_lock_signature(): if not osbv_utils.release_focus_lock(appSignature): # Unable to release the focus-lock raise DeviceException(DeviceException.OPERATION_FAILED, self._pars.id + ": Failed to release focus lock.") self._logger.info(self._pars.id + ": Test step finished.") #Close the camera after the test is completed. self._camera_api.stop_system_camera_application() def delta(self, time_start, flag, loop): time_stop = float(time.time()) sr = round((time_stop - time_start),0) s = int("%d"%sr) hours = s // 3600 s = s - (hours*3600) minutes = s//60 seconds = s - (minutes * 60) run_duration = '%sh:%sm:%ss'%(hours,minutes,seconds) if flag==1: self._logger.info(self._pars.id + ": Test duration for Loop " + str(loop) + ": " + str(run_duration)) if flag==2: self._logger.info(self._pars.id + ": duration of pulling pics to host: " + str(run_duration)) def fail_test_cleanup(self, numPicsTaken, errorCount): ''' Perform any needed cleanup and summary logging ''' (result, output) = self._file_api.exist(self._camera_api.backup_dir + self._dut_os.sep + "*." + self.pic_file_type) if result: self._logger.info(self._pars.id + ': Copy the remaining captured images to save directory') self._camera_api.upload_output_files(False, self.host_save_folder) pull_screenshots = False self._logger.error(self._pars.id + ": The test FAILED due to unresolvable camera failures!") self._logger.error(self._pars.id + ": Summary:") self._logger.error(self._pars.id + ": Images captured successfully before failure: %d"%numPicsTaken) self._logger.error(self._pars.id + ": Errors encountered by type:") for camErr in errorCount: self._logger.error(self._pars.id + ": %s: %d"%(camErr,errorCount[camErr])) if errorCount[camErr] > 0: pull_screenshots = True if pull_screenshots == True: self._logger.error(self._pars.id + ": Pulling error screenshots and logcat files from DUT...") imageDir = os.path.join(self.report_path,'error_images_%s'%datetime.fromtimestamp(time.time()).strftime('%Y-%m-%d_%H-%M-%S')) if not os.path.exists(imageDir): os.makedirs(imageDir) self._camera_api.move_files_to_backup_dir(self._camera_api.device_save_directory) self._camera_api.upload_output_files(True, imageDir) def pass_test_cleanup(self, numPicsTaken, errorCount): ''' Perform any needed cleanup and summary logging ''' (result, output) = self._file_api.exist(self._camera_api.backup_dir + self._dut_os.sep + "*." + self.pic_file_type) if result: self._logger.info(self._pars.id + ': Copy the remaining captured images to save directory') self._camera_api.upload_output_files(False, self.host_save_folder) pull_screenshots = False self._logger.info(self._pars.id + ': Test complete successfully') self._logger.info(self._pars.id + ": Summary:") self._logger.info(self._pars.id + ": Images captured successfully: %d"%numPicsTaken) self._logger.error(self._pars.id + ": Errors encountered by type:") for camErr in errorCount: self._logger.error(self._pars.id + ": %s: %d"%(camErr,errorCount[camErr])) if errorCount[camErr] > 0: pull_screenshots = True if pull_screenshots == True: self._logger.error(self._pars.id + ": Pulling error screenshots and logcat files from DUT...") imageDir = os.path.join(self.report_path,'error_images_%s'%datetime.fromtimestamp(time.time()).strftime('%Y-%m-%d_%H-%M-%S')) if not os.path.exists(imageDir): os.makedirs(imageDir) self._camera_api.move_files_to_backup_dir(self._camera_api.device_save_directory) self._camera_api.upload_output_files(True, imageDir)