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

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: 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 class DragAction:
21 """Action describing a touch drag."""
22 def __init__(self, start, end, duration, points):
23 self.start = start
24 self.end = end
25 self.duration = duration
26 self.points = points
27
28 def run(self, device):
29 """Perform the action."""
30 return device.drag(self.start, self.end, self.duration, self.points)
31
32
33 class PressAction:
34 """Action describing a button press."""
35 def __init__(self, button, press_type):
36 self.button = button
37 self.press_type = press_type
38
39 def run(self, device):
40 """Perform the action."""
41 return device.press(self.button, self.press_type)
42
43
44 def parse_action(action_dict):
45 """Parse a dict describing an action and return an Action object."""
46 if action_dict['type'] == 'drag':
47 return DragAction(tuple(action_dict['start']),
48 tuple(action_dict['end']),
rmistry 2015/12/02 20:49:18 What does it return if you do not specify tuple he
borenet 2015/12/03 18:14:48 A list. I'm not sure if monkeyrunner really cares
49 action_dict['duration'],
50 action_dict['points'])
51 elif action_dict['type'] == 'press':
52 return PressAction(action_dict['button'], action_dict['press_type'])
53 else:
54 raise TypeError('Unsupported action type: %s' % action_dict['type'])
55
56
57 class App:
58 """Class which describes an app to launch and actions to run."""
59 def __init__(self, name, package, activity, actions):
60 self.name = name
61 self.package = package
62 self.activity = activity
63 self.run_component = '/'.join((self.package, self.activity))
rmistry 2015/12/02 20:49:18 [optional] I believe '%s/%s' % (self.package, self
borenet 2015/12/03 18:14:48 Done.
64 self.actions = [parse_action(a) for a in actions]
65
66 def launch(self, device):
67 """Launch the app on the device."""
68 device.startActivity(component=self.run_component)
69 time.sleep(3)
rmistry 2015/12/02 20:49:18 Make time to wait a parameter in the constructor.
borenet 2015/12/03 18:14:48 Done.
70
71 def kill(self):
72 """Kill the app."""
73 adb_shell('am force-stop %s' % self.package)
74
75
76 def check_output(cmd):
77 """Convenience implementation of subprocess.check_output."""
78 proc = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
79 if proc.wait() != 0:
80 raise Exception('Command failed: %s' % ' '.join(cmd))
81 return proc.communicate()[0]
82
83
84 def adb_shell(cmd):
85 """Run the given ADB shell command and emulate the exit code."""
86 output = check_output(['adb', 'shell', cmd + '; echo $?']).strip()
87 split = output.splitlines()
rmistry 2015/12/02 20:49:18 Call these lines or tokens or output_tokens instea
borenet 2015/12/03 18:14:48 Done.
88 if split[-1] != '0':
89 raise Exception('ADB command failed: %s\n\nOutput:\n%s' % (cmd, output))
90 return '\n'.join(split[:-1])
91
92
93 def remote_file_exists(filename):
94 """Return True if the given file exists on the device and False otherwise."""
95 try:
96 adb_shell('test -f %s' % filename)
97 return True
98 except Exception:
99 return False
100
101
102 def capture_skp(filename, package, device):
rmistry 2015/12/02 20:49:18 call this skp_file instead? that is the argument y
borenet 2015/12/03 18:14:48 Done.
103 """Capture an SKP."""
104 remote_path = '/data/data/%s/cache/%s' % (package, os.path.basename(filename))
105 if remote_file_exists(remote_path):
106 adb_shell('rm %s' % remote_path)
rmistry 2015/12/02 20:49:18 I am assuming that trying to remove a file that do
borenet 2015/12/03 18:14:47 Yeah, so the problem with that is I'd want to actu
rmistry 2015/12/04 13:47:51 You would be saving an exists call in a few places
borenet 2015/12/04 14:41:44 Done.
107
108 adb_shell('setprop debug.hwui.capture_frame_as_skp %s' % remote_path)
109 try:
110 # Spin, wait for the SKP to be written.
111 timeout = 10 # Seconds
112 start = time.time()
113 device.drag((300, 300), (300, 350), 1, 10) # Dummy action to force a draw.
114 while not remote_file_exists(remote_path):
115 if time.time() - start > timeout:
116 raise Exception('Timed out waiting for SKP capture.')
117 time.sleep(1)
118
119 # Pull the SKP from the device.
120 cmd = ['adb', 'pull', remote_path, filename]
121 check_output(cmd)
122
123 finally:
124 adb_shell('setprop debug.hwui.capture_frame_as_skp ""')
125
126
127 def load_app(filename):
128 """Load the JSON file describing an app and return an App instance."""
129 with open(filename) as f:
130 app_dict = ast.literal_eval(f.read())
131 return App(app_dict['name'],
132 app_dict['package'],
133 app_dict['activity'],
134 app_dict['actions'])
135
136
137 def main():
138 """Capture SKPs for all apps."""
139 device = MonkeyRunner.waitForConnection()
140
141 # TODO(borenet): Kill all apps.
142 device.wake()
143 device.drag((600, 600), (10, 10), 0.2, 10)
144
145 apps_dir = os.path.join(os.path.dirname(os.path.realpath(__file__)), 'apps')
146 app_files = [os.path.join(apps_dir, app) for app in os.listdir(apps_dir)]
147
148 for app_file in app_files:
149 app = load_app(app_file)
150 print app.name
151 print ' Package %s' % app.package
152 app.launch(device)
153 print ' Launched activity %s' % app.activity
154
155 for action in app.actions:
156 print ' %s' % action.__class__.__name__
157 action.run(device)
158
159 time.sleep(1)
rmistry 2015/12/02 20:49:18 Could also either put this in the JSON or make it
borenet 2015/12/03 18:14:48 Done.
160 print ' Capturing SKP.'
161 skp_file = '%s.skp' % app.name
162 capture_skp(skp_file, app.package, device)
163 print ' Wrote SKP to %s' % skp_file
164 print ''
rmistry 2015/12/02 20:49:18 [optional] print with no arguments should also wor
borenet 2015/12/03 18:14:48 Done.
165 app.kill()
166
167
168 if __name__ == '__main__':
169 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