Home | History | Annotate | Download | only in pylib
      1 # Copyright 2013 The Chromium Authors. All rights reserved.
      2 # Use of this source code is governed by a BSD-style license that can be
      3 # found in the LICENSE file.
      4 
      5 import os
      6 import tempfile
      7 import time
      8 
      9 import android_commands
     10 import cmd_helper
     11 
     12 
     13 def _GetTimestamp():
     14  return time.strftime('%Y-%m-%d-%H%M%S', time.localtime())
     15 
     16 
     17 def _EnsureHostDirectory(host_file):
     18   host_dir = os.path.dirname(os.path.abspath(host_file))
     19   if not os.path.exists(host_dir):
     20     os.makedirs(host_dir)
     21 
     22 
     23 def TakeScreenshot(adb, host_file):
     24   """Saves a screenshot image to |host_file| on the host.
     25 
     26   Args:
     27     adb: AndroidCommands instance.
     28     host_file: Path to the image file to store on the host.
     29   """
     30   host_file = os.path.abspath(host_file or
     31                               'screenshot-%s.png' % _GetTimestamp())
     32   _EnsureHostDirectory(host_file)
     33   device_file = '%s/screenshot.png' % adb.GetExternalStorage()
     34   adb.RunShellCommand('/system/bin/screencap -p %s' % device_file)
     35   adb.PullFileFromDevice(device_file, host_file)
     36   adb.RunShellCommand('rm -f "%s"' % device_file)
     37   return host_file
     38 
     39 
     40 class VideoRecorder(object):
     41   """Records a screen capture video from an Android Device (KitKat or newer).
     42 
     43   Args:
     44     adb: AndroidCommands instance.
     45     host_file: Path to the video file to store on the host.
     46     megabits_per_second: Video bitrate in megabits per second. Allowed range
     47                          from 0.1 to 100 mbps.
     48     size: Video frame size tuple (width, height) or None to use the device
     49           default.
     50     rotate: If True, the video will be rotated 90 degrees.
     51   """
     52   def __init__(self, adb, host_file, megabits_per_second=4, size=None,
     53                rotate=False):
     54     self._adb = adb
     55     self._device_file = '%s/screen-recording.mp4' % adb.GetExternalStorage()
     56     self._host_file = host_file or 'screen-recording-%s.mp4' % _GetTimestamp()
     57     self._host_file = os.path.abspath(self._host_file)
     58     self._recorder = None
     59     self._recorder_pids = None
     60     self._recorder_stdout = None
     61     self._is_started = False
     62 
     63     self._args = ['adb']
     64     if self._adb.GetDevice():
     65       self._args += ['-s', self._adb.GetDevice()]
     66     self._args += ['shell', 'screenrecord', '--verbose']
     67     self._args += ['--bit-rate', str(megabits_per_second * 1000 * 1000)]
     68     if size:
     69       self._args += ['--size', '%dx%d' % size]
     70     if rotate:
     71       self._args += ['--rotate']
     72     self._args += [self._device_file]
     73 
     74   def Start(self):
     75     """Start recording video."""
     76     _EnsureHostDirectory(self._host_file)
     77     self._recorder_stdout = tempfile.mkstemp()[1]
     78     self._recorder = cmd_helper.Popen(
     79         self._args, stdout=open(self._recorder_stdout, 'w'))
     80     self._recorder_pids = self._adb.ExtractPid('screenrecord')
     81     if not self._recorder_pids:
     82       raise RuntimeError('Recording failed. Is your device running Android '
     83                          'KitKat or later?')
     84 
     85   def IsStarted(self):
     86     if not self._is_started:
     87       for line in open(self._recorder_stdout):
     88         self._is_started = line.startswith('Content area is ')
     89         if self._is_started:
     90           break
     91     return self._is_started
     92 
     93   def Stop(self):
     94     """Stop recording video."""
     95     os.remove(self._recorder_stdout)
     96     self._is_started = False
     97     if not self._recorder or not self._recorder_pids:
     98       return
     99     self._adb.RunShellCommand('kill -SIGINT ' + ' '.join(self._recorder_pids))
    100     self._recorder.wait()
    101 
    102   def Pull(self):
    103     """Pull resulting video file from the device.
    104 
    105     Returns:
    106       Output video file name on the host.
    107     """
    108     self._adb.PullFileFromDevice(self._device_file, self._host_file)
    109     self._adb.RunShellCommand('rm -f "%s"' % self._device_file)
    110     return self._host_file
    111