Home | History | Annotate | Download | only in tools
      1 #!/usr/bin/env python
      2 # Copyright (C) 2017 The Android Open Source Project
      3 #
      4 # Licensed under the Apache License, Version 2.0 (the "License");
      5 # you may not use this file except in compliance with the License.
      6 # You may obtain a copy of the License at
      7 #
      8 #      http://www.apache.org/licenses/LICENSE-2.0
      9 #
     10 # Unless required by applicable law or agreed to in writing, software
     11 # distributed under the License is distributed on an "AS IS" BASIS,
     12 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13 # See the License for the specific language governing permissions and
     14 # limitations under the License.
     15 
     16 from __future__ import print_function
     17 import argparse
     18 import datetime
     19 import os
     20 import subprocess
     21 import sys
     22 
     23 """Pulls all format files from an Android device.
     24 
     25 Usage: ./tools/pull_ftrace_format_files.py [-s serial] [-p directory_prefix]
     26 """
     27 
     28 ROOT_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
     29 ADB_PATH = os.path.join(ROOT_DIR, 'buildtools/android_sdk/platform-tools/adb')
     30 
     31 def adb(*cmd, **kwargs):
     32   serial = kwargs.get('serial', None)
     33   prefix = [ADB_PATH]
     34   if serial:
     35     prefix += ['-s', serial]
     36   cmd = prefix + list(cmd)
     37   output = subprocess.check_output(cmd).replace('\r', '')
     38   return output
     39 
     40 
     41 def get_devices():
     42   #  adb devices output looks like:
     43   #    List of devices attached
     44   #    557dccd8\tdevice
     45   #  With a trailing newline.
     46   serials = [s.split('\t')[0] for s in adb('devices').split('\n')[1:] if s]
     47   return serials
     48 
     49 
     50 def ensure_output_directory_empty(path):
     51   if os.path.isfile(path):
     52     print('The output directory {} exists as a file.'.format(path))
     53     sys.exit(1)
     54 
     55   if os.path.isdir(path) and os.listdir(path):
     56     print('The output directory {} exists but is not empty.'.format(path))
     57     sys.exit(1)
     58 
     59   if not os.path.isdir(path):
     60     os.makedirs(path)
     61 
     62 
     63 def ensure_dir(path):
     64   try:
     65     os.makedirs(path)
     66   except OSError:
     67     if not os.path.isdir(path):
     68       raise
     69 
     70 
     71 def ensure_single_device(serial):
     72   serials = get_devices()
     73   if serial is None and len(serials) == 1:
     74     return serials[0]
     75 
     76   if serial in serials:
     77     return serial
     78 
     79   if not serials:
     80     print('No devices connected.')
     81   elif serial is None:
     82     print('More than one device connected, use -s.')
     83   else:
     84     print('No device with serial {} found.'.format(serial))
     85   sys.exit(1)
     86 
     87 
     88 def pull_format_files(serial, output_directory):
     89   # Pulling each file individually is 100x slower so we pipe all together then
     90   # split them on the host.
     91   cmd = "find /sys/kernel/debug/tracing/ " \
     92       "-name available_events -o " \
     93       "-name format -o " \
     94       "-name header_event -o " \
     95       "-name header_page | " \
     96       "grep -v '/instances/' | " \
     97       "while read f; do echo 'path:' $f; cat $f; done"
     98 
     99   output = adb('shell', cmd, serial=serial)
    100   sections = output.split('path: /sys/kernel/debug/tracing/')
    101   for section in sections:
    102     if not section:
    103       continue
    104     path, rest = section.split('\n', 1)
    105     path = os.path.join(output_directory, path)
    106     ensure_dir(os.path.dirname(path))
    107     with open(path, 'wb') as f:
    108       f.write(rest)
    109 
    110 
    111 # Produces output of the form: prefix_android_seed_N2F62_3.10.49
    112 def get_output_directory(prefix=None, serial=None):
    113   build_id = adb('shell', 'getprop', 'ro.build.id', serial=serial).strip()
    114   product = adb('shell', 'getprop', 'ro.build.product', serial=serial).strip()
    115   kernel = adb('shell', 'uname', '-r', serial=serial).split('-')[0].strip()
    116   parts = ['android', product, build_id, kernel]
    117   if prefix:
    118     parts = [prefix] + parts
    119   return '_'.join(parts)
    120 
    121 
    122 def main():
    123   parser = argparse.ArgumentParser(description='Pull format files.')
    124   parser.add_argument('-p', dest='prefix', default=None,
    125                       help='the output directory prefix')
    126   parser.add_argument('-s', dest='serial', default=None,
    127                       help='use device with the given serial')
    128   args = parser.parse_args()
    129 
    130   prefix = args.prefix
    131   serial = args.serial
    132 
    133   serial = ensure_single_device(serial)
    134   output_directory = get_output_directory(prefix, serial)
    135 
    136   ensure_output_directory_empty(output_directory)
    137   pull_format_files(serial, output_directory)
    138 
    139   return 0
    140 
    141 
    142 if __name__ == '__main__':
    143     sys.exit(main())
    144 
    145