oprofile_android revision 87866d93bd7de46ffe9333437e5230c6eda58448
1#!/usr/bin/env python2.6
2#
3# Copyright (C) 2011 The Android Open Source Project
4#
5# Licensed under the Apache License, Version 2.0 (the "License");
6# you may not use this file except in compliance with the License.
7# You may obtain a copy of the License at
8#
9#      http://www.apache.org/licenses/LICENSE-2.0
10#
11# Unless required by applicable law or agreed to in writing, software
12# distributed under the License is distributed on an "AS IS" BASIS,
13# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14# See the License for the specific language governing permissions and
15# limitations under the License.
16#
17
18#
19# Remotely controls an OProfile session on an Android device.
20#
21
22import os
23import sys
24import subprocess
25import getopt
26import re
27
28
29class Adb:
30  def __init__(self, serial_number):
31    self._base_args = ['adb']
32    if serial_number != None:
33      self._base_args.append('-s')
34      self._base_args.append(serial_number)
35
36  def shell(self, command_args, echo=True):
37    print 'adb: %s' % (' '.join(command_args))
38    popen = subprocess.Popen(self._base_args + ['shell'] + command_args,
39      stdout=subprocess.PIPE, stderr=subprocess.PIPE)
40    output = ''
41    while True:
42      stdout, stderr = popen.communicate()
43      if echo:
44        print stdout
45        print stderr
46      output += stdout
47      output += stderr
48      rc = popen.poll()
49      if rc is not None:
50        break
51    print 'exit code: %d' % rc
52    return rc, output
53
54
55class Tool:
56  def __init__(self, argv):
57    self.argv = argv
58    self.verbose = False
59
60  def usage(self):
61    print "Usage:" + self.argv[0]
62    print "    -h, --help          : show this help text"
63    print "    -s, --serial=number : the serial number of the device being profiled"
64    print "    -v, --verbose       : show verbose output"
65    print "    --setup             : setup profiler"
66    print "    --shutdown          : shutdown profiler"
67    print "    --start             : start profiling"
68    print "    --stop              : stop profiling"
69    print "    --status            : show profiler status"
70    print
71
72  def main(self):
73    try:
74      opts, args = getopt.getopt(self.argv[1:],
75        "hs:v",
76        ["help", "serial=", "setup", "start", "stop", "status", "shutdown", "verbose"])
77    except getopt.GetoptError, e:
78      self.usage()
79      print str(e)
80      return 1
81
82    serial_number = None
83    command = None
84    for o, a in opts:
85      if o in ('-h', '--help'):
86        self.usage()
87        return 0
88      elif o in ('-s', '--serial'):
89        serial_number = a
90      elif o in ('-v', '--verbose'):
91        self.verbose = True
92      elif o in ('--setup', '--start', '--stop', '--status', '--shutdown'):
93        command = o[2:]
94      else:
95        assert False, 'unhandled option' + o
96
97    self.adb = Adb(serial_number)
98
99    if command == 'setup':
100      rc = self.setup()
101    elif command == 'shutdown':
102      rc = self.shutdown()
103    elif command == 'start':
104      rc = self.start()
105    elif command == 'stop':
106      rc = self.stop()
107    elif command == 'status':
108      rc = self.status()
109    else:
110      self.usage()
111      print 'A command must be specified.'
112      rc = 1
113    return rc
114
115  def setup(self):
116    rc, output = self.adb.shell(['cat', '/proc/kallsyms'], echo=False)
117    if rc != 0:
118      print 'Failed to determine kernel VMA range.'
119      return rc
120    vma_start = re.search('([0-9a-fA-F]{8}) T _text', output).group(1)
121    vma_end = re.search('([0-9a-fA-F]{8}) A _etext', output).group(1)
122
123    rc, output = self.adb.shell(['/system/xbin/opcontrol'] + self.opcontrol_verbose() + [
124      '--reset',
125      '--kernel-range=' + vma_start + '-' + vma_end,
126      '--event=CPU_CYCLES:100000',
127      '--setup',
128      '--status', '--verbose-log=all'])
129
130  def shutdown(self):
131    rc, output = self.adb.shell(['/system/xbin/opcontrol'] + self.opcontrol_verbose() + [
132      '--shutdown'])
133    if rc != 0:
134      print 'Failed to shutdown.'
135      return rc
136    return rc
137
138  def start(self):
139    rc, output = self.adb.shell(['/system/xbin/opcontrol'] + self.opcontrol_verbose() + [
140      '--start', '--status'])
141    return rc
142
143  def stop(self):
144    rc, output = self.adb.shell(['/system/xbin/opcontrol'] + self.opcontrol_verbose() + [
145      '--stop', '--status'])
146    return rc
147
148  def status(self):
149    rc, output = self.adb.shell(['/system/xbin/opcontrol'] + self.opcontrol_verbose() + [
150      '--status'])
151    return rc
152
153  def opcontrol_verbose(self):
154    if self.verbose:
155      return ['--verbose']
156    else:
157      return []
158
159# Main entry point
160tool = Tool(sys.argv)
161rc = tool.main()
162sys.exit(rc)