1*9c5db199SXin Li# Copyright (c) 2019 The Chromium OS Authors. All rights reserved. 2*9c5db199SXin Li# Use of this source code is governed by a BSD-style license that can be 3*9c5db199SXin Li# found in the LICENSE file. 4*9c5db199SXin Li""" 5*9c5db199SXin LiThis profiler will take a screenshot at the specified interval. 6*9c5db199SXin Li""" 7*9c5db199SXin Li 8*9c5db199SXin Liimport os, subprocess 9*9c5db199SXin Liimport threading, time 10*9c5db199SXin Liimport logging 11*9c5db199SXin Lifrom autotest_lib.client.bin import profiler 12*9c5db199SXin Li 13*9c5db199SXin Li 14*9c5db199SXin Liclass screenshot(profiler.profiler): 15*9c5db199SXin Li """ Profiler for running screenshot """ 16*9c5db199SXin Li 17*9c5db199SXin Li version = 1 18*9c5db199SXin Li 19*9c5db199SXin Li def initialize(self, interval=300): 20*9c5db199SXin Li """Initializes the screenshot profiler. 21*9c5db199SXin Li 22*9c5db199SXin Li Args: 23*9c5db199SXin Li interval (int): How often to take a screenshot in seconds 24*9c5db199SXin Li """ 25*9c5db199SXin Li self.interval = interval 26*9c5db199SXin Li 27*9c5db199SXin Li def start(self, test): 28*9c5db199SXin Li self.thread = ScreenshotThread(interval=self.interval, test=test) 29*9c5db199SXin Li 30*9c5db199SXin Li self.thread.start() 31*9c5db199SXin Li 32*9c5db199SXin Li def stop(self, test): 33*9c5db199SXin Li self.thread.stop() 34*9c5db199SXin Li 35*9c5db199SXin Li 36*9c5db199SXin Liclass ScreenshotThread(threading.Thread): 37*9c5db199SXin Li """ Thread that runs screenshot at the specified interval """ 38*9c5db199SXin Li 39*9c5db199SXin Li def __init__(self, interval, test): 40*9c5db199SXin Li threading.Thread.__init__(self) 41*9c5db199SXin Li self.stopped = threading.Event() 42*9c5db199SXin Li self.interval = interval 43*9c5db199SXin Li self.test = test 44*9c5db199SXin Li 45*9c5db199SXin Li def run(self): 46*9c5db199SXin Li logging.info("screenshot thread starting") 47*9c5db199SXin Li 48*9c5db199SXin Li sleep_time = 0 49*9c5db199SXin Li 50*9c5db199SXin Li while not self.stopped.wait(sleep_time): 51*9c5db199SXin Li start_time = time.time() 52*9c5db199SXin Li 53*9c5db199SXin Li path = os.path.join(self.test.profdir, 54*9c5db199SXin Li "screenshot-%d.png" % (int(start_time))) 55*9c5db199SXin Li 56*9c5db199SXin Li # Don't use graphics_utils because we can't control the suffix 57*9c5db199SXin Li cmd = ['screenshot', path] 58*9c5db199SXin Li 59*9c5db199SXin Li logging.debug("Taking screenshot") 60*9c5db199SXin Li 61*9c5db199SXin Li process = subprocess.Popen( 62*9c5db199SXin Li cmd, stderr=subprocess.PIPE, close_fds=True) 63*9c5db199SXin Li 64*9c5db199SXin Li _, stderr = process.communicate() 65*9c5db199SXin Li 66*9c5db199SXin Li if process.returncode: 67*9c5db199SXin Li # If the screen is turned off, screenshot will fail 68*9c5db199SXin Li logging.info('screenshot failed. code: %d, error: %s ', 69*9c5db199SXin Li process.returncode, stderr) 70*9c5db199SXin Li 71*9c5db199SXin Li end_time = time.time() 72*9c5db199SXin Li 73*9c5db199SXin Li sleep_time = self.interval - (end_time - start_time) 74*9c5db199SXin Li 75*9c5db199SXin Li if sleep_time < 0: 76*9c5db199SXin Li sleep_time = 0 77*9c5db199SXin Li 78*9c5db199SXin Li def stop(self): 79*9c5db199SXin Li """ Stops the thread """ 80*9c5db199SXin Li logging.info("Stopping screenshot thread") 81*9c5db199SXin Li 82*9c5db199SXin Li self.stopped.set() 83*9c5db199SXin Li 84*9c5db199SXin Li # Only block for five seconds to not hold up the test shutdown. 85*9c5db199SXin Li # It's very unlikely that the screenshot command will take more 86*9c5db199SXin Li # than a second. 87*9c5db199SXin Li self.join(5) 88*9c5db199SXin Li 89*9c5db199SXin Li logging.info("screenshot thread stopped") 90