1# Copyright 2018 The Chromium OS Authors. All rights reserved. 2# Use of this source code is governed by a BSD-style license that can be 3# found in the LISENCE file. 4 5import logging 6import re 7import os 8import time 9 10from autotest_lib.client.common_lib import error 11from autotest_lib.server import test 12 13CEC_COMMAND = "sudo -u chronos dbus-send --system --print-reply \ 14--type=method_call --dest=org.chromium.CecService \ 15/org/chromium/CecService org.chromium.CecService." 16CEC_CMD_STANDBY = "SendStandByToAllDevices" 17CEC_CMD_IMAGEON = "SendWakeUpToAllDevices" 18CEC_CMD_DISP_STATUS = "GetTvsPowerStatus" 19 20CHAMELEON_ROOT = '/home/root/' 21 22STATUS_ERROR = 0 23STATUS_ON = 3 24STATUS_OFF = 4 25STATUS_TO_ON = 5 26STATUS_TO_OFF = 6 27 28class enterprise_CFM_CEC(test.test): 29 """ 30 Test CEC feature for display power control. 31 """ 32 33 version = 1 34 # TODO: how to get whether it connects to chameleon board 35 chameleon_mode = True 36 37 def initialize(self): 38 """ initialize is a stub function.""" 39 pass 40 41 # Simply run a command in machine and return result messages. 42 def _shcmd(self, cmd): 43 """ A simple wrapper for remote shell command execution. 44 @param cmd: shell command for Fizz 45 """ 46 logging.info('CMD: [%s]', cmd) 47 try: 48 result = self._client.run(cmd) 49 if result is None: 50 return result 51 if result.stderr: 52 logging.info('CMD ERR:\n' + result.stderr) 53 logging.info('CMD OUT:\n' + result.stdout) 54 return result 55 except Exception as e: 56 logging.info('run command failed. ' + str(e)) 57 58 def run_once(self, host=None): 59 """ 60 Test scenario: 61 62 If system does not support cec port, we simply throw an exception. 63 64 Generally we are using the build-in cecservice for this test. This 65 service supports multiple features including turning TV(display) 66 power on/off and monitor its power status. 67 68 Following is test plan: 69 0.0 Copy two python files to chameleon 70 0.1 enable chameleon as hdmi mode 71 0.2 run cec service on chameleon 72 73 0.3 Make sure chrome box is running cecservice 74 0.4 Make sure chrome box's /dev/cecX is open 75 0.5 Run TV power status to check configuration correct 76 (end of step 0) 77 78 79 1.0 Send TV turn-off command 80 1.1 Check TV power status to check whether it is off. 81 (end of step 1) 82 83 2.0 Send TV turn-on command 84 2.1 Check TV power status to check whether it is on. 85 (end of step 2) 86 At every end of step, we have to decide whether we stop this test 87 right now or continue next ones. 88 Note that we could turn on TV first and then turn off it, 89 according to its initial power status. 90 91 3.0 Stop cec service on chameleon 92 3.1 Remove python files from chameleon 93 94 @param host: host object machine. 95 """ 96 97 self._client = host 98 self.chameleon = host.chameleon 99 100 ## TODO check same port 101 #Step 0.0 - 0.2 102 self.copy_cecservice() 103 self.cec_service_init() 104 105 106 # Step 0.3 - 0.5 107 if not self.is_cecservice_running(): 108 self.cec_cleanup() 109 raise error.TestFail("CEC service is not running.") 110 if not self.is_cec_available(): 111 self.cec_cleanup() 112 raise error.TestFail("/dev/cecX port is not open.") 113 status = self.check_display_status() 114 if STATUS_ERROR == status: 115 self.cec_cleanup() 116 raise error.TestFail("CEC communication is not good.") 117 118 # Step 1 & 2 119 if STATUS_ON == status: 120 self.test_turn_off() 121 if not self.chameleon_mode: 122 time.sleep(5) 123 self.test_turn_on() 124 else: 125 self.test_turn_on() 126 if not self.chameleon_mode: 127 time.sleep(5) 128 self.test_turn_off() 129 130 # Step 3 131 self.cec_cleanup() 132 133 # Chameleon 134 def copy_cecservice(self): 135 """ copy python files under ./chameleon_cecservice to chameleon. 136 In that folder, we have two files for cecservice. 137 """ 138 current_dir = os.path.dirname(os.path.realpath(__file__)) 139 base_dir = current_dir + '/chameleon_cecservice/' 140 self.chameleon.host.send_file(base_dir + 'cec_service', CHAMELEON_ROOT) 141 self.chameleon.host.send_file(base_dir + 'it6803.py', CHAMELEON_ROOT) 142 143 def cec_service_init(self): 144 """ Setup chameleon board as a hdmi mode. 145 Run cec service on chameleon 146 """ 147 self.chameleon.host.run('/home/root/setup hdmi') 148 self.chameleon.host.run('(/home/root/cec_service start) '\ 149 '</dev/null >/dev/null 2>&1 & echo -n $!') 150 151 def cec_cleanup(self): 152 """ Stop cec service on chameleon. 153 Delete files new coming on chameleon. 154 """ 155 if self.chameleon_mode: 156 stop_cmd = 'kill $(ps | grep \'cec_service\' | awk \'{print $1}\')' 157 self.chameleon.host.run(stop_cmd) 158 cleanup_cmd = 'rm /home/root/cec_service /home/root/it6803*' 159 self.chameleon.host.run(cleanup_cmd) 160 161 # Fizz 162 def is_cecservice_running(self): 163 """ try to confirm that current box is running cecservice. 164 @return: whether cecservice is running in Fizz. 165 """ 166 cmd = 'initctl list | grep cecservice' 167 result = self._shcmd(cmd) 168 if result is None: 169 return False; 170 if "running" not in result.stdout: 171 return False; 172 return True; 173 174 def is_cec_available(self): 175 """ try to get whether the system makes /dev/cecX open. 176 @return: whether /dev/cecX is open in Fizz 177 """ 178 cmd = "ls /dev/cec*" 179 result = self._shcmd(cmd) 180 if result is None: 181 return False; 182 return True; 183 184 def check_display_status(self): 185 """ try to confirm that current box connected to a display 186 which supports cec feature. 187 @return: current display power status 188 """ 189 cmd = CEC_COMMAND + CEC_CMD_DISP_STATUS 190 result = self._shcmd(cmd).stdout 191 status = re.findall('int32 \\d', result) 192 for s in status: 193 code = int(s[-1]); 194 if code == STATUS_ON or code == STATUS_TO_ON: 195 return STATUS_ON 196 if code == STATUS_OFF or code == STATUS_TO_OFF: 197 return STATUS_OFF 198 return STATUS_ERROR 199 200 def display_on(self): 201 """ send a power turn on cec message """ 202 self._shcmd(CEC_COMMAND + CEC_CMD_IMAGEON) 203 204 def display_off(self): 205 """ send a power turn off cec message""" 206 self._shcmd(CEC_COMMAND + CEC_CMD_STANDBY) 207 208 def test_turn_on(self): 209 """ test sending turn_on cec message process. """ 210 self.display_on() 211 if not self.chameleon_mode: 212 time.sleep(10) 213 status = self.check_display_status() 214 if STATUS_ON != status: 215 self.cec_cleanup() 216 raise error.TestFail("CEC display image on does not work.") 217 218 def test_turn_off(self): 219 """ test sending turn_off cec message process. """ 220 self.display_off() 221 if not self.chameleon_mode: 222 time.sleep(1) 223 status = self.check_display_status() 224 if STATUS_OFF != status: 225 self.cec_cleanup() 226 raise error.TestFail("CEC display standby does not work.") 227