196 lines
6.6 KiB
Python
196 lines
6.6 KiB
Python
# Copyright 2023 The Android Open Source Project
|
|
#
|
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
# you may not use this file except in compliance with the License.
|
|
# You may obtain a copy of the License at
|
|
#
|
|
# http://www.apache.org/licenses/LICENSE-2.0
|
|
#
|
|
# Unless required by applicable law or agreed to in writing, software
|
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
# See the License for the specific language governing permissions and
|
|
# limitations under the License.
|
|
|
|
import ast
|
|
import logging
|
|
import os
|
|
import platform
|
|
import subprocess
|
|
import time
|
|
|
|
from mobly import asserts
|
|
from mobly import base_test
|
|
from mobly import test_runner
|
|
from mobly.controllers import android_device
|
|
|
|
|
|
class DeviceAsWebcamTest(base_test.BaseTestClass):
|
|
# Tests device as webcam functionality with Mobly base test class to run.
|
|
|
|
_ACTION_WEBCAM_RESULT = 'com.android.cts.verifier.camera.webcam.ACTION_WEBCAM_RESULT'
|
|
_WEBCAM_RESULTS = 'camera.webcam.extra.RESULTS'
|
|
_WEBCAM_TEST_ACTIVITY = 'com.android.cts.verifier/.camera.webcam.WebcamTestActivity'
|
|
_DAC_PREVIEW_ACTIVITY = 'com.android.DeviceAsWebcam/.DeviceAsWebcamPreview'
|
|
_ACTIVITY_START_WAIT = 1.5 # seconds
|
|
_ADB_RESTART_WAIT = 9 # seconds
|
|
_FPS_TOLERANCE = 0.15 # 15 percent
|
|
_RESULT_PASS = 'PASS'
|
|
_RESULT_FAIL = 'FAIL'
|
|
_RESULT_NOT_EXECUTED = 'NOT_EXECUTED'
|
|
_MANUAL_FRAME_CHECK_DURATION = 8 # seconds
|
|
_WINDOWS_OS = 'Windows'
|
|
_MAC_OS = 'Darwin'
|
|
_LINUX_OS = 'Linux'
|
|
|
|
def run_os_specific_test(self):
|
|
"""Runs the os specific webcam test script.
|
|
|
|
Returns:
|
|
A result list of tuples (tested_fps, actual_fps)
|
|
"""
|
|
results = []
|
|
current_os = platform.system()
|
|
|
|
if current_os == self._WINDOWS_OS:
|
|
import windows_webcam_test
|
|
logging.info('Starting test on Windows')
|
|
# Due to compatibility issues directly running the windows
|
|
# main function, the results from the windows_webcam_test script
|
|
# are printed to the stdout and retrieved
|
|
output = subprocess.check_output(['python', 'windows_webcam_test.py'])
|
|
output_str = output.decode('utf-8')
|
|
results = ast.literal_eval(output_str.strip())
|
|
elif current_os == self._LINUX_OS:
|
|
import linux_webcam_test
|
|
logging.info('Starting test on Linux')
|
|
results = linux_webcam_test.main()
|
|
elif current_os == self._MAC_OS:
|
|
import mac_webcam_test
|
|
logging.info('Starting test on Mac')
|
|
results = mac_webcam_test.main()
|
|
else:
|
|
logging.info('Running on an unknown OS')
|
|
|
|
return results
|
|
|
|
def validate_fps(self, results):
|
|
"""Verifies the webcam FPS falls within the acceptable range of the tested FPS.
|
|
|
|
Args:
|
|
results: A result list of tuples (tested_fps, actual_fps)
|
|
|
|
Returns:
|
|
True if all FPS are within tolerance range, False otherwise
|
|
"""
|
|
result = True
|
|
|
|
for elem in results:
|
|
tested_fps = elem[0]
|
|
actual_fps = elem[1]
|
|
|
|
max_diff = tested_fps * self._FPS_TOLERANCE
|
|
|
|
if abs(tested_fps - actual_fps) > max_diff:
|
|
logging.error('FPS is out of tolerance range! '
|
|
' Tested: %d Actual FPS: %d', tested_fps, actual_fps)
|
|
result = False
|
|
|
|
return result
|
|
|
|
def run_cmd(self, cmd):
|
|
"""Replaces os.system call, while hiding stdout+stderr messages."""
|
|
with open(os.devnull, 'wb') as devnull:
|
|
subprocess.check_call(cmd.split(), stdout=devnull,
|
|
stderr=subprocess.STDOUT)
|
|
|
|
def setup_class(self):
|
|
# Registering android_device controller module declares the test
|
|
# dependencies on Android device hardware. By default, we expect at least
|
|
# one object is created from this.
|
|
devices = self.register_controller(android_device, min_number=1)
|
|
self.dut = devices[0]
|
|
self.dut.adb.root()
|
|
|
|
def test_webcam(self):
|
|
|
|
adb = f'adb -s {self.dut.serial}'
|
|
|
|
# Keep device on while testing since it requires a manual check on the
|
|
# webcam frames
|
|
# '7' is a combination of flags ORed together to keep the device on
|
|
# in all cases
|
|
self.dut.adb.shell(['settings', 'put', 'global',
|
|
'stay_on_while_plugged_in', '7'])
|
|
|
|
cmd = f"""{adb} shell am start {self._WEBCAM_TEST_ACTIVITY}
|
|
--activity-brought-to-front"""
|
|
self.run_cmd(cmd)
|
|
|
|
# Check if webcam feature is enabled
|
|
dut_webcam_enabled = self.dut.adb.shell(['getprop', 'ro.usb.uvc.enabled'])
|
|
if 'true' in dut_webcam_enabled.decode('utf-8'):
|
|
logging.info('Webcam enabled, testing webcam')
|
|
else:
|
|
logging.info('Webcam not enabled, skipping webcam test')
|
|
|
|
# Notify CTSVerifier test that the webcam test was skipped,
|
|
# the test will be marked as PASSED for this case
|
|
cmd = (f"""{adb} shell am broadcast -a
|
|
{self._ACTION_WEBCAM_RESULT} --es {self._WEBCAM_RESULTS}
|
|
{self._RESULT_NOT_EXECUTED}""")
|
|
self.run_cmd(cmd)
|
|
|
|
return
|
|
|
|
# Set USB preference option to webcam
|
|
set_uvc = self.dut.adb.shell(['svc', 'usb', 'setFunctions', 'uvc'])
|
|
if not set_uvc:
|
|
logging.error('USB preference option to set webcam unsuccessful')
|
|
|
|
# Notify CTSVerifier test that setting webcam option was unsuccessful
|
|
cmd = (f"""{adb} shell am broadcast -a
|
|
{self._ACTION_WEBCAM_RESULT} --es {self._WEBCAM_RESULTS}
|
|
{self._RESULT_FAIL}""")
|
|
self.run_cmd(cmd)
|
|
return
|
|
|
|
# After resetting the USB preference, adb disconnects
|
|
# and reconnects so wait for device
|
|
time.sleep(self._ADB_RESTART_WAIT)
|
|
|
|
fps_results = self.run_os_specific_test()
|
|
logging.info('FPS test results (Expected, Actual): %s', fps_results)
|
|
result = self.validate_fps(fps_results)
|
|
|
|
test_status = self._RESULT_PASS
|
|
if not result or not fps_results:
|
|
logging.info('FPS testing failed')
|
|
test_status = self._RESULT_FAIL
|
|
|
|
# Send result to CTSVerifier test
|
|
time.sleep(self._ACTIVITY_START_WAIT)
|
|
cmd = (f"""{adb} shell am broadcast -a
|
|
{self._ACTION_WEBCAM_RESULT} --es {self._WEBCAM_RESULTS}
|
|
{test_status}""")
|
|
self.run_cmd(cmd)
|
|
|
|
# Enable the webcam service preview activity for a manual
|
|
# check on webcam frames
|
|
cmd = f"""{adb} shell am start {self._DAC_PREVIEW_ACTIVITY}
|
|
--activity-no-history"""
|
|
self.run_cmd(cmd)
|
|
time.sleep(self._MANUAL_FRAME_CHECK_DURATION)
|
|
|
|
cmd = f"""{adb} shell am start {self._WEBCAM_TEST_ACTIVITY}
|
|
--activity-brought-to-front"""
|
|
self.run_cmd(cmd)
|
|
|
|
asserts.assert_true(test_status == self._RESULT_PASS, 'Results: Failed')
|
|
|
|
self.dut.adb.shell(['settings', 'put',
|
|
'global', 'stay_on_while_plugged_in', '0'])
|
|
|
|
if __name__ == '__main__':
|
|
test_runner.main()
|