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""" A simple device interface for build steps. 6 7""" 8 9import logging 10import os 11import re 12import sys 13 14from util import build_utils 15 16from devil.android import device_errors 17from devil.android import device_utils 18from devil.android.sdk import adb_wrapper 19 20 21def GetAttachedDevices(): 22 return [a.GetDeviceSerial() 23 for a in adb_wrapper.AdbWrapper.Devices()] 24 25 26class BuildDevice(object): 27 def __init__(self, configuration): 28 self.id = configuration['id'] 29 self.description = configuration['description'] 30 self.install_metadata = configuration['install_metadata'] 31 self.device = device_utils.DeviceUtils(self.id) 32 33 def RunShellCommand(self, *args, **kwargs): 34 return self.device.RunShellCommand(*args, **kwargs) 35 36 def PushChangedFiles(self, *args, **kwargs): 37 return self.device.PushChangedFiles(*args, **kwargs) 38 39 def GetSerialNumber(self): 40 return self.id 41 42 def Install(self, *args, **kwargs): 43 return self.device.Install(*args, **kwargs) 44 45 def InstallSplitApk(self, *args, **kwargs): 46 return self.device.InstallSplitApk(*args, **kwargs) 47 48 def GetInstallMetadata(self, apk_package): 49 """Gets the metadata on the device for the apk_package apk.""" 50 # Matches lines like: 51 # -rw-r--r-- system system 7376582 2013-04-19 16:34 \ 52 # org.chromium.chrome.apk 53 # -rw-r--r-- system system 7376582 2013-04-19 16:34 \ 54 # org.chromium.chrome-1.apk 55 apk_matcher = lambda s: re.match('.*%s(-[0-9]*)?.apk$' % apk_package, s) 56 matches = filter(apk_matcher, self.install_metadata) 57 return matches[0] if matches else None 58 59 60def GetConfigurationForDevice(device_id): 61 device = device_utils.DeviceUtils(device_id) 62 configuration = None 63 has_root = False 64 is_online = device.IsOnline() 65 if is_online: 66 cmd = 'ls -l /data/app; getprop ro.build.description' 67 cmd_output = device.RunShellCommand(cmd) 68 has_root = not 'Permission denied' in cmd_output[0] 69 if not has_root: 70 # Disable warning log messages from EnableRoot() 71 logging.getLogger().disabled = True 72 try: 73 device.EnableRoot() 74 has_root = True 75 except device_errors.CommandFailedError: 76 has_root = False 77 finally: 78 logging.getLogger().disabled = False 79 cmd_output = device.RunShellCommand(cmd) 80 81 configuration = { 82 'id': device_id, 83 'description': cmd_output[-1], 84 'install_metadata': cmd_output[:-1], 85 } 86 return configuration, is_online, has_root 87 88 89def WriteConfigurations(configurations, path): 90 # Currently we only support installing to the first device. 91 build_utils.WriteJson(configurations[:1], path, only_if_changed=True) 92 93 94def ReadConfigurations(path): 95 return build_utils.ReadJson(path) 96 97 98def GetBuildDevice(configurations): 99 assert len(configurations) == 1 100 return BuildDevice(configurations[0]) 101 102 103def GetBuildDeviceFromPath(path): 104 configurations = ReadConfigurations(path) 105 if len(configurations) > 0: 106 return GetBuildDevice(ReadConfigurations(path)) 107 return None 108 109