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.
5 """Brings in Chrome Android's android_commands module, which itself is a
6 thin(ish) wrapper around adb."""
14 from telemetry.core import util
15 from telemetry.core.platform.profiler import android_prebuilt_profiler_helper
17 # This is currently a thin wrapper around Chrome Android's
18 # build scripts, located in chrome/build/android. This file exists mainly to
19 # deal with locating the module.
21 util.AddDirToPythonPath(util.GetChromiumSrcDir(), 'build', 'android')
23 from pylib import android_commands # pylint: disable=F0401
24 from pylib import constants # pylint: disable=F0401
25 from pylib import ports # pylint: disable=F0401
26 from pylib.utils import apk_helper # pylint: disable=F0401
27 from pylib.utils import test_environment # pylint: disable=F0401
29 android_commands = None
32 def IsAndroidSupported():
33 return android_commands != None
36 def GetAttachedDevices():
37 """Returns a list of attached, online android devices.
39 If a preferred device has been set with ANDROID_SERIAL, it will be first in
41 return android_commands.GetAttachedDevices()
44 def CleanupLeftoverProcesses():
45 test_environment.CleanupLeftoverProcesses()
48 def AllocateTestServerPort():
49 return ports.AllocateTestServerPort()
52 def ResetTestServerPortAllocation():
53 return ports.ResetTestServerPortAllocation()
56 class AdbCommands(object):
57 """A thin wrapper around ADB"""
59 def __init__(self, device):
60 self._adb = android_commands.AndroidCommands(device, api_strict_mode=True)
67 def system_properties(self):
68 return self._adb.system_properties
73 def Forward(self, local, remote):
74 ret = self._adb.Adb().SendCommand('forward %s %s' % (local, remote))
77 def RunShellCommand(self, command, timeout_time=20, log_result=False):
78 """Send a command to the adb shell and return the result.
81 command: String containing the shell command to send. Must not include
82 the single quotes as we use them to escape the whole command.
83 timeout_time: Number of seconds to wait for command to respond before
84 retrying, used by AdbInterface.SendShellCommand.
85 log_result: Boolean to indicate whether we should log the result of the
89 list containing the lines of output received from running the command
91 return self._adb.RunShellCommand(command, timeout_time, log_result)
93 def RunShellCommandWithSU(self, command, timeout_time=20, log_result=False):
94 return self._adb.RunShellCommandWithSU(command, timeout_time, log_result)
96 def CloseApplication(self, package):
97 """Attempt to close down the application, using increasing violence.
100 package: Name of the process to kill off, e.g.
101 com.google.android.apps.chrome
103 self._adb.CloseApplication(package)
105 def KillAll(self, process):
106 """Android version of killall, connected via adb.
109 process: name of the process to kill off
112 the number of processess killed
114 return self._adb.KillAll(process)
116 def ExtractPid(self, process_name):
117 """Extracts Process Ids for a given process name from Android Shell.
120 process_name: name of the process on the device.
123 List of all the process ids (as strings) that match the given name.
124 If the name of a process exactly matches the given name, the pid of
125 that process will be inserted to the front of the pid list.
127 return self._adb.ExtractPid(process_name)
129 def Install(self, apk_path):
130 """Installs specified package if necessary.
133 apk_path: Path to .apk file to install.
136 if (os.path.exists(os.path.join(
137 constants.GetOutDirectory('Release'), 'md5sum_bin_host'))):
138 constants.SetBuildType('Release')
139 elif (os.path.exists(os.path.join(
140 constants.GetOutDirectory('Debug'), 'md5sum_bin_host'))):
141 constants.SetBuildType('Debug')
143 apk_package_name = apk_helper.GetPackageName(apk_path)
144 return self._adb.ManagedInstall(apk_path, package_name=apk_package_name)
146 def StartActivity(self, package, activity, wait_for_completion=False,
147 action='android.intent.action.VIEW',
148 category=None, data=None,
149 extras=None, trace_file_name=None,
151 """Starts |package|'s activity on the device.
154 package: Name of package to start (e.g. 'com.google.android.apps.chrome').
155 activity: Name of activity (e.g. '.Main' or
156 'com.google.android.apps.chrome.Main').
157 wait_for_completion: wait for the activity to finish launching (-W flag).
158 action: string (e.g. 'android.intent.action.MAIN'). Default is VIEW.
159 category: string (e.g. 'android.intent.category.HOME')
160 data: Data string to pass to activity (e.g. 'http://www.example.com/').
161 extras: Dict of extras to pass to activity. Values are significant.
162 trace_file_name: If used, turns on and saves the trace to this file name.
164 return self._adb.StartActivity(package, activity, wait_for_completion,
167 extras, trace_file_name,
170 def Push(self, local, remote):
171 return self._adb.Adb().Push(local, remote)
173 def Pull(self, remote, local):
174 return self._adb.Adb().Pull(remote, local)
176 def FileExistsOnDevice(self, file_name):
177 return self._adb.FileExistsOnDevice(file_name)
179 def IsRootEnabled(self):
180 return self._adb.IsRootEnabled()
183 return self._adb.GoHome()
185 def RestartAdbdOnDevice(self):
186 return self._adb.RestartAdbdOnDevice()
188 def IsUserBuild(self):
189 return self._adb.GetBuildType() == 'user'
192 def GetBuildTypeOfPath(path):
195 for build_dir, build_type in util.GetBuildDirectories():
196 if os.path.join(build_dir, build_type) in path:
201 def SetupPrebuiltTools(adb):
202 # TODO(bulach): build the host tools for mac, and the targets for x86/mips.
203 # Prebuilt tools from r226197.
204 has_prebuilt = sys.platform.startswith('linux')
206 abi = adb.system_properties['ro.product.cpu.abi']
207 has_prebuilt = abi.startswith('armeabi')
210 'Prebuilt android tools only available for Linux host and ARM device.')
216 'forwarder_dist/device_forwarder',
218 'md5sum_dist/md5sum_bin',
223 for t in prebuilt_tools:
224 src = os.path.basename(t)
225 android_prebuilt_profiler_helper.GetIfChanged(src)
226 bin_path = util.FindSupportBinary(t)
228 build_type = GetBuildTypeOfPath(bin_path) or 'Release'
229 constants.SetBuildType(build_type)
230 dest = os.path.join(constants.GetOutDirectory(), t)
232 logging.warning('Setting up prebuilt %s', dest)
233 if not os.path.exists(os.path.dirname(dest)):
234 os.makedirs(os.path.dirname(dest))
235 prebuilt_path = android_prebuilt_profiler_helper.GetHostPath(src)
236 if not os.path.exists(prebuilt_path):
237 raise NotImplementedError("""
238 %s must be checked into cloud storage.
240 http://www.chromium.org/developers/telemetry/upload_to_cloud_storage
242 shutil.copyfile(prebuilt_path, dest)
243 os.chmod(dest, stat.S_IRUSR | stat.S_IWUSR | stat.S_IXUSR)