203 lines
6.7 KiB
Python
203 lines
6.7 KiB
Python
|
|
# Copyright 2018 The Chromium OS Authors. All rights reserved.
|
||
|
|
# Use of this source code is governed by a BSD-style license that can be
|
||
|
|
# found in the LICENSE file.
|
||
|
|
|
||
|
|
'''Login with test account and display chart file using telemetry.'''
|
||
|
|
|
||
|
|
import argparse
|
||
|
|
import contextlib
|
||
|
|
import json
|
||
|
|
import logging
|
||
|
|
import os
|
||
|
|
import select
|
||
|
|
import signal
|
||
|
|
import sys
|
||
|
|
import tempfile
|
||
|
|
|
||
|
|
# Set chart process preferred logging format before overridden by importing
|
||
|
|
# common package.
|
||
|
|
logging.basicConfig(
|
||
|
|
level=logging.DEBUG,
|
||
|
|
format='%(asctime)s - %(levelname)s - %(message)s')
|
||
|
|
|
||
|
|
# This sets up import paths for autotest.
|
||
|
|
sys.path.append('/usr/local/autotest/bin')
|
||
|
|
import common
|
||
|
|
from autotest_lib.client.bin import utils
|
||
|
|
from autotest_lib.client.cros import constants
|
||
|
|
from autotest_lib.client.cros.multimedia import display_facade as display_facade_lib
|
||
|
|
from autotest_lib.client.cros.multimedia import facade_resource
|
||
|
|
from autotest_lib.client.common_lib.cros import chrome
|
||
|
|
|
||
|
|
DEFAULT_DISPLAY_LEVEL = 96.0
|
||
|
|
|
||
|
|
|
||
|
|
class Fifo:
|
||
|
|
"""Fifo to communicate with chart service."""
|
||
|
|
|
||
|
|
FIFO_POLL_TIMEOUT_MS = 300
|
||
|
|
|
||
|
|
def __init__(self):
|
||
|
|
self._ready = False
|
||
|
|
|
||
|
|
def __enter__(self):
|
||
|
|
# Prepare fifo file.
|
||
|
|
self._tmpdir = tempfile.mkdtemp(prefix='chart_fifo_', dir='/tmp')
|
||
|
|
self._path = os.path.join(self._tmpdir, 'fifo')
|
||
|
|
os.mkfifo(self._path)
|
||
|
|
|
||
|
|
# Hook SIGINT signal to stop fifo.
|
||
|
|
self._original_sig_handler = signal.getsignal(signal.SIGINT)
|
||
|
|
|
||
|
|
def handler(a, b):
|
||
|
|
signal.signal(signal.SIGINT, self._original_sig_handler)
|
||
|
|
self._ready = False
|
||
|
|
|
||
|
|
signal.signal(signal.SIGINT, handler)
|
||
|
|
|
||
|
|
self._ready = True
|
||
|
|
return self
|
||
|
|
|
||
|
|
def __exit__(self, exc_type, exc_value, exc_traceback):
|
||
|
|
signal.signal(signal.SIGINT, self._original_sig_handler)
|
||
|
|
os.unlink(self._path)
|
||
|
|
os.rmdir(self._tmpdir)
|
||
|
|
|
||
|
|
def get_path(self):
|
||
|
|
return self._path
|
||
|
|
|
||
|
|
def read(self):
|
||
|
|
"""Read json format command from fifo."""
|
||
|
|
while self._ready:
|
||
|
|
with os.fdopen(os.open(self._path, os.O_RDONLY | os.O_NONBLOCK),
|
||
|
|
'r') as fd:
|
||
|
|
p = select.poll()
|
||
|
|
p.register(fd, select.POLLIN)
|
||
|
|
if p.poll(self.FIFO_POLL_TIMEOUT_MS):
|
||
|
|
cmd = fd.read()
|
||
|
|
return json.loads(cmd)
|
||
|
|
return None
|
||
|
|
|
||
|
|
|
||
|
|
@contextlib.contextmanager
|
||
|
|
def control_brightness():
|
||
|
|
"""Help to programmatically control the brightness.
|
||
|
|
|
||
|
|
Returns:
|
||
|
|
A function which can set brightness between [0.0, 100.0].
|
||
|
|
"""
|
||
|
|
|
||
|
|
def set_brightness(display_level):
|
||
|
|
utils.system('backlight_tool --set_brightness_percent=%s' %
|
||
|
|
display_level)
|
||
|
|
logging.info('Set display brightness to %r', display_level)
|
||
|
|
|
||
|
|
original_display_level = utils.system_output(
|
||
|
|
'backlight_tool --get_brightness_percent')
|
||
|
|
logging.info('Save original display brightness %r', original_display_level)
|
||
|
|
|
||
|
|
utils.system('stop powerd', ignore_status=True)
|
||
|
|
yield set_brightness
|
||
|
|
logging.info('Restore display brightness %r', original_display_level)
|
||
|
|
utils.system('start powerd', ignore_status=True)
|
||
|
|
set_brightness(original_display_level)
|
||
|
|
|
||
|
|
|
||
|
|
@contextlib.contextmanager
|
||
|
|
def control_display(cr):
|
||
|
|
"""Fix the display orientation instead of using gyro orientation."""
|
||
|
|
board = utils.get_board()
|
||
|
|
logging.info("Board:%s", board)
|
||
|
|
if board == 'scarlet':
|
||
|
|
DISPLAY_ORIENTATION = 90
|
||
|
|
else:
|
||
|
|
DISPLAY_ORIENTATION = 0
|
||
|
|
|
||
|
|
logging.info('Set fullscreen.')
|
||
|
|
facade = facade_resource.FacadeResource(cr)
|
||
|
|
display_facade = display_facade_lib.DisplayFacadeLocal(facade)
|
||
|
|
display_facade.set_fullscreen(True)
|
||
|
|
|
||
|
|
logging.info('Fix screen rotation %d.', DISPLAY_ORIENTATION)
|
||
|
|
internal_display_id = display_facade.get_internal_display_id()
|
||
|
|
original_display_orientation = display_facade.get_display_rotation(
|
||
|
|
internal_display_id)
|
||
|
|
display_facade.set_display_rotation(internal_display_id,
|
||
|
|
rotation=DISPLAY_ORIENTATION)
|
||
|
|
yield
|
||
|
|
display_facade.set_display_rotation(internal_display_id,
|
||
|
|
rotation=original_display_orientation)
|
||
|
|
|
||
|
|
|
||
|
|
def display(chart_path, display_level):
|
||
|
|
"""Display chart on device by using telemetry."""
|
||
|
|
chart_path = os.path.abspath(chart_path)
|
||
|
|
if os.path.isfile(chart_path):
|
||
|
|
first_chart_name = os.path.basename(chart_path)
|
||
|
|
chart_dir_path = os.path.dirname(chart_path)
|
||
|
|
elif os.path.isdir(chart_path):
|
||
|
|
first_chart_name = None
|
||
|
|
chart_dir_path = chart_path
|
||
|
|
else:
|
||
|
|
assert False, 'chart_path %r not found.' % chart_path
|
||
|
|
|
||
|
|
def show_chart(name):
|
||
|
|
"""Show image on chart base on file name"""
|
||
|
|
filepath = os.path.join(chart_dir_path, name)
|
||
|
|
logging.info('Display chart file of path %r.', filepath)
|
||
|
|
tab = cr.browser.tabs[0]
|
||
|
|
tab.Navigate(cr.browser.platform.http_server.UrlOf(filepath))
|
||
|
|
tab.WaitForDocumentReadyStateToBeComplete()
|
||
|
|
|
||
|
|
logging.info('Setup SIGINT listener for stop displaying.')
|
||
|
|
|
||
|
|
with chrome.Chrome(
|
||
|
|
extension_paths=[constants.DISPLAY_TEST_EXTENSION],
|
||
|
|
autotest_ext=True,
|
||
|
|
init_network_controller=True) as cr, \
|
||
|
|
control_brightness() as set_brightness, \
|
||
|
|
control_display(cr), \
|
||
|
|
Fifo() as fifo:
|
||
|
|
set_brightness(display_level)
|
||
|
|
|
||
|
|
cr.browser.platform.SetHTTPServerDirectories(chart_dir_path)
|
||
|
|
if first_chart_name is not None:
|
||
|
|
show_chart(first_chart_name)
|
||
|
|
|
||
|
|
logging.info('Chart is ready. Fifo: %s', fifo.get_path())
|
||
|
|
# Flush the 'is ready' message for server test to sync with ready state.
|
||
|
|
sys.stdout.flush()
|
||
|
|
sys.stderr.flush()
|
||
|
|
|
||
|
|
while True:
|
||
|
|
cmd = fifo.read()
|
||
|
|
if cmd is None:
|
||
|
|
break
|
||
|
|
new_chart_name = cmd.get('chart_name')
|
||
|
|
if new_chart_name is not None:
|
||
|
|
show_chart(new_chart_name)
|
||
|
|
|
||
|
|
new_display_level = cmd.get('display_level')
|
||
|
|
if new_display_level is not None:
|
||
|
|
set_brightness(new_display_level)
|
||
|
|
|
||
|
|
|
||
|
|
if __name__ == '__main__':
|
||
|
|
argparser = argparse.ArgumentParser(
|
||
|
|
description='Display chart file on chrome by using telemetry.'
|
||
|
|
' Send SIGINT or keyboard interrupt to stop displaying.')
|
||
|
|
argparser.add_argument(
|
||
|
|
'chart_path',
|
||
|
|
help='Path of displayed chart file'
|
||
|
|
' or the directory to put chart files for displaying in fifo mode.'
|
||
|
|
)
|
||
|
|
argparser.add_argument(
|
||
|
|
'--display_level',
|
||
|
|
type=float,
|
||
|
|
default=DEFAULT_DISPLAY_LEVEL,
|
||
|
|
help=
|
||
|
|
'Set brightness as linearly-calculated percent in [0.0, 100.0].')
|
||
|
|
|
||
|
|
args = argparser.parse_args()
|
||
|
|
display(args.chart_path, args.display_level)
|