Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1115)

Side by Side Diff: platform_tools/android/skp_gen/android_skp_capture.py

Issue 1483063006: Add android_skp_capture.py, JSON file for geniewidget (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: more Created 5 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | platform_tools/android/skp_gen/apps/geniewidget.json » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 #!/usr/bin/env python
2
3 # Copyright 2015 Google Inc.
4 #
5 # Use of this source code is governed by a BSD-style license that can be
6 # found in the LICENSE file.
7
8
9 from __future__ import with_statement
10
11 # Imports the monkeyrunner modules used by this program
12 from com.android.monkeyrunner import MonkeyRunner, MonkeyDevice
13
14 import ast
15 import os
16 import subprocess
17 import time
18
19
20 # Time to wait between performing UI actions and capturing the SKP.
21 WAIT_FOR_SKP_CAPTURE = 1
22
23
24 class DragAction:
25 """Action describing a touch drag."""
26 def __init__(self, start, end, duration, points):
27 self.start = start
28 self.end = end
29 self.duration = duration
30 self.points = points
31
32 def run(self, device):
33 """Perform the action."""
34 return device.drag(self.start, self.end, self.duration, self.points)
35
36
37 class PressAction:
38 """Action describing a button press."""
39 def __init__(self, button, press_type):
40 self.button = button
41 self.press_type = press_type
42
43 def run(self, device):
44 """Perform the action."""
45 return device.press(self.button, self.press_type)
46
47
48 def parse_action(action_dict):
49 """Parse a dict describing an action and return an Action object."""
50 if action_dict['type'] == 'drag':
51 return DragAction(tuple(action_dict['start']),
52 tuple(action_dict['end']),
53 action_dict['duration'],
54 action_dict['points'])
55 elif action_dict['type'] == 'press':
56 return PressAction(action_dict['button'], action_dict['press_type'])
57 else:
58 raise TypeError('Unsupported action type: %s' % action_dict['type'])
59
60
61 class App:
62 """Class which describes an app to launch and actions to run."""
63 def __init__(self, name, package, activity, app_launch_delay, actions):
64 self.name = name
65 self.package = package
66 self.activity = activity
67 self.app_launch_delay = app_launch_delay
68 self.run_component = '%s/%s' % (self.package, self.activity)
69 self.actions = [parse_action(a) for a in actions]
70
71 def launch(self, device):
72 """Launch the app on the device."""
73 device.startActivity(component=self.run_component)
74 time.sleep(self.app_launch_delay)
75
76 def kill(self):
77 """Kill the app."""
78 adb_shell('am force-stop %s' % self.package)
79
80
81 def check_output(cmd):
82 """Convenience implementation of subprocess.check_output."""
83 proc = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
84 if proc.wait() != 0:
85 raise Exception('Command failed: %s' % ' '.join(cmd))
86 return proc.communicate()[0]
87
88
89 def adb_shell(cmd):
90 """Run the given ADB shell command and emulate the exit code."""
91 output = check_output(['adb', 'shell', cmd + '; echo $?']).strip()
92 lines = output.splitlines()
93 if lines[-1] != '0':
94 raise Exception('ADB command failed: %s\n\nOutput:\n%s' % (cmd, output))
95 return '\n'.join(lines[:-1])
96
97
98 def remote_file_exists(filename):
99 """Return True if the given file exists on the device and False otherwise."""
100 try:
101 adb_shell('test -f %s' % filename)
102 return True
103 except Exception:
104 return False
105
106
107 def capture_skp(skp_file, package, device):
108 """Capture an SKP."""
109 remote_path = '/data/data/%s/cache/%s' % (package, os.path.basename(skp_file))
110 try:
111 adb_shell('rm %s' % remote_path)
112 except Exception:
113 if remote_file_exists(remote_path):
114 raise
115
116 adb_shell('setprop debug.hwui.capture_frame_as_skp %s' % remote_path)
117 try:
118 # Spin, wait for the SKP to be written.
119 timeout = 10 # Seconds
120 start = time.time()
121 device.drag((300, 300), (300, 350), 1, 10) # Dummy action to force a draw.
122 while not remote_file_exists(remote_path):
123 if time.time() - start > timeout:
124 raise Exception('Timed out waiting for SKP capture.')
125 time.sleep(1)
126
127 # Pull the SKP from the device.
128 cmd = ['adb', 'pull', remote_path, skp_file]
129 check_output(cmd)
130
131 finally:
132 adb_shell('setprop debug.hwui.capture_frame_as_skp ""')
133
134
135 def load_app(filename):
136 """Load the JSON file describing an app and return an App instance."""
137 with open(filename) as f:
138 app_dict = ast.literal_eval(f.read())
139 return App(app_dict['name'],
140 app_dict['package'],
141 app_dict['activity'],
142 app_dict['app_launch_delay'],
143 app_dict['actions'])
144
145
146 def main():
147 """Capture SKPs for all apps."""
148 device = MonkeyRunner.waitForConnection()
149
150 # TODO(borenet): Kill all apps.
151 device.wake()
152 device.drag((600, 600), (10, 10), 0.2, 10)
153
154 apps_dir = os.path.join(os.path.dirname(os.path.realpath(__file__)), 'apps')
155 app_files = [os.path.join(apps_dir, app) for app in os.listdir(apps_dir)]
156
157 for app_file in app_files:
158 app = load_app(app_file)
159 print app.name
160 print ' Package %s' % app.package
161 app.launch(device)
162 print ' Launched activity %s' % app.activity
163
164 for action in app.actions:
165 print ' %s' % action.__class__.__name__
166 action.run(device)
167
168 time.sleep(WAIT_FOR_SKP_CAPTURE)
169 print ' Capturing SKP.'
170 skp_file = '%s.skp' % app.name
171 capture_skp(skp_file, app.package, device)
172 print ' Wrote SKP to %s' % skp_file
173 print
174 app.kill()
175
176
177 if __name__ == '__main__':
178 main()
OLDNEW
« no previous file with comments | « no previous file | platform_tools/android/skp_gen/apps/geniewidget.json » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698