blob: c2ab1524c63bfdadcfcaedf092f3293cfcf64050 [file] [log] [blame]
# Copyright 2022 The ChromiumOS Authors
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
"""Test that sets privacy screen to specific state.
Description
-----------
This test measures the functionality of the privacy screen. It sets privacy
screen to a specific state then checks if privacy screen is refreshed to that
state.
Test Procedure
--------------
This is an automatic test that doesn't need any user interaction.
Dependency
----------
- Need a built-in privacy screen.
- Command ``cros-health-tool``.
Examples
--------
Turn privacy screen on and then validate state:
.. test_list::
generic_display_panel_examples:PrivacyScreen
Argument ``target_state`` is required and must be either ``on`` or ``off``.
"""
import enum
import json
import logging
from typing import Any, Dict
from cros.factory.device.device_types import CalledProcessError
from cros.factory.device.device_types import DeviceBoard
from cros.factory.device import device_utils
from cros.factory.test.i18n import _
from cros.factory.test import test_case
from cros.factory.utils.arg_utils import Arg
from cros.factory.utils import process_utils
from cros.factory.utils.type_utils import Error
class PrivacyScreenNotSupportedException(Error):
"""Privacy screen is not supported."""
class PrivacyScreenTest(test_case.TestCase):
"""Pytest to measure functionality of built-in privacy screen."""
related_components = (test_case.TestCategory.LCD, )
ARGS = [
Arg('target_state', enum.Enum('_StateType', ['on', 'off']),
'Privacy screen target state.'),
]
dut: DeviceBoard
def setUp(self):
self.AddTask(self._RunDiagnosticsRoutine)
self.dut = device_utils.CreateDUTInterface()
def _RunDiagnosticsRoutine(self):
# yapf: disable
self.ui.SetState(_('Running diagnostics privacy screen routine...')) # type: ignore #TODO(b/338318729) Fixit! # pylint: disable=line-too-long
# yapf: enable
# yapf: disable
arg_state = f'--set_privacy_screen={self.args.target_state}' # type: ignore #TODO(b/338318729) Fixit! # pylint: disable=line-too-long
# yapf: enable
try:
process_utils.Spawn(
['cros-health-tool', 'diag', 'privacy_screen', arg_state],
check_call=True)
except CalledProcessError as e:
current_state = 'on' if self._IsPrivacyScreenOn() else 'off'
logging.error('Privacy screen routine failed with exit code %d.',
e.returncode)
logging.error('Privacy screen expected state: %s, current state: %s',
# yapf: disable
self.args.target_state, current_state) # type: ignore #TODO(b/338318729) Fixit! # pylint: disable=line-too-long
# yapf: enable
logging.error('Privacy screen routine stderr: %s', e.stderr)
ui_msg = _(
'Diagnostics privacy screen routine failed. '
'Expected state: {expected_state}, current state: {current_state}',
# yapf: disable
expected_state=self.args.target_state, current_state=current_state) # type: ignore #TODO(b/338318729) Fixit! # pylint: disable=line-too-long
# yapf: enable
# yapf: disable
self.ui.SetState(ui_msg) # type: ignore #TODO(b/338318729) Fixit! # pylint: disable=line-too-long
# yapf: enable
raise
ui_msg = _('Privacy screen state "{state}" verified.',
# yapf: disable
state=self.args.target_state) # type: ignore #TODO(b/338318729) Fixit! # pylint: disable=line-too-long
# yapf: enable
# yapf: disable
self.ui.SetState(ui_msg) # type: ignore #TODO(b/338318729) Fixit! # pylint: disable=line-too-long
# yapf: enable
def _IsPrivacyScreenOn(self) -> bool:
try:
stdout: str = self.dut.CheckOutput(
['cros-health-tool', 'telem', '--category=display'])
except CalledProcessError:
logging.error('Failed to execute cros-health-tool.')
raise
try:
stdout_obj: dict = json.loads(stdout)
except json.decoder.JSONDecodeError:
logging.error('Unexpected stdout format from cros-health-tool: %r',
stdout)
raise
# The stdout_obj is like this:
#
# {
# "edp": {
# "display_height": "170",
# "display_width": "310",
# "edid_version": "1.4",
# "input_type": "Digital",
# "manufacture_year": 2021,
# "manufacturer": "IVO",
# "model_id": 35962,
# "privacy_screen_enabled": false,
# "privacy_screen_supported": true,
# "refresh_rate": 60.00968456004427,
# "resolution_horizontal": "1920",
# "resolution_vertical": "1080",
# "serial_number": "4"
# }
# }
display_info: Dict[str, Any] = stdout_obj.get('edp', None)
self.assertIsInstance(
display_info, dict,
msg=f'Unexpected stdout format from cros-health-tool:\n{stdout}')
privacy_screen_supported = display_info.get('privacy_screen_supported',
False)
self.assertIsInstance(
privacy_screen_supported, bool,
msg=f'Unexpected stdout format from cros-health-tool:\n{stdout}')
if not privacy_screen_supported:
raise PrivacyScreenNotSupportedException()
privacy_screen_enabled = display_info.get('privacy_screen_enabled', False)
self.assertIsInstance(
privacy_screen_enabled, bool,
msg=f'Unexpected stdout format from cros-health-tool:\n{stdout}')
return privacy_screen_enabled