mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-24 21:31:04 +00:00
Bug 1145680 - [mozdevice] Add reboot, move, copy, and info methods to adb.py. r=bc
This commit is contained in:
parent
4cd1bc150b
commit
cf61aea229
@ -170,30 +170,38 @@ Device Shell methods
|
||||
Informational methods
|
||||
+++++++++++++++++++++
|
||||
.. automethod:: ADBDevice.clear_logcat
|
||||
.. automethod:: ADBDevice.get_battery_percentage
|
||||
.. automethod:: ADBDevice.get_info
|
||||
.. automethod:: ADBDevice.get_logcat
|
||||
.. automethod:: ADBDevice.get_prop(self, prop, timeout=None)
|
||||
.. automethod:: ADBDevice.get_state(self, timeout=None)
|
||||
.. automethod:: ADBDevice.get_prop
|
||||
.. automethod:: ADBDevice.get_state
|
||||
|
||||
System control methods
|
||||
++++++++++++++++++++++
|
||||
.. automethod:: ADBDevice.is_device_ready
|
||||
.. automethod:: ADBDevice.reboot
|
||||
|
||||
File management methods
|
||||
+++++++++++++++++++++++
|
||||
.. automethod:: ADBDevice.chmod(self, path, recursive=False, mask="777", timeout=None, root=False)
|
||||
.. automethod:: ADBDevice.exists(self, path, timeout=None, root=False)
|
||||
.. automethod:: ADBDevice.is_dir(self, path, timeout=None, root=False)
|
||||
.. automethod:: ADBDevice.is_file(self, path, timeout=None, root=False)
|
||||
.. automethod:: ADBDevice.list_files(self, path, timeout=None, root=False)
|
||||
.. automethod:: ADBDevice.mkdir(self, path, parents=False, timeout=None, root=False)
|
||||
.. automethod:: ADBDevice.push(self, local, remote, timeout=None)
|
||||
.. automethod:: ADBDevice.rm(self, path, recursive=False, force=False, timeout=None, root=False)
|
||||
.. automethod:: ADBDevice.rmdir(self, path, timeout=None, root=False)
|
||||
.. automethod:: ADBDevice.chmod
|
||||
.. automethod:: ADBDevice.cp
|
||||
.. automethod:: ADBDevice.exists
|
||||
.. automethod:: ADBDevice.is_dir
|
||||
.. automethod:: ADBDevice.is_file
|
||||
.. automethod:: ADBDevice.list_files
|
||||
.. automethod:: ADBDevice.mkdir
|
||||
.. automethod:: ADBDevice.mv
|
||||
.. automethod:: ADBDevice.push
|
||||
.. automethod:: ADBDevice.rm
|
||||
.. automethod:: ADBDevice.rmdir
|
||||
.. autoattribute:: ADBDevice.test_root
|
||||
|
||||
Process management methods
|
||||
++++++++++++++++++++++++++
|
||||
.. automethod:: ADBDevice.get_process_list(self, timeout=None)
|
||||
.. automethod:: ADBDevice.kill(self, pids, sig=None, attempts=3, wait=5, timeout=None, root=False)
|
||||
.. automethod:: ADBDevice.pkill(self, appname, sig=None, attempts=3, wait=5, timeout=None, root=False)
|
||||
.. automethod:: ADBDevice.process_exist(self, process_name, timeout=None)
|
||||
|
||||
.. automethod:: ADBDevice.get_process_list
|
||||
.. automethod:: ADBDevice.kill
|
||||
.. automethod:: ADBDevice.pkill
|
||||
.. automethod:: ADBDevice.process_exist
|
||||
|
||||
ADBAndroid
|
||||
``````````
|
||||
@ -201,24 +209,32 @@ ADBAndroid
|
||||
|
||||
Informational methods
|
||||
+++++++++++++++++++++
|
||||
.. automethod:: ADBAndroid.get_battery_percentage(self, timeout=None)
|
||||
.. automethod:: ADBAndroid.get_battery_percentage
|
||||
|
||||
System control methods
|
||||
++++++++++++++++++++++
|
||||
.. automethod:: ADBAndroid.is_device_ready(self, timeout=None)
|
||||
.. automethod:: ADBAndroid.power_on(self, timeout=None)
|
||||
.. automethod:: ADBAndroid.reboot(self, timeout=None)
|
||||
.. automethod:: ADBAndroid.is_device_ready
|
||||
.. automethod:: ADBAndroid.power_on
|
||||
|
||||
Application management methods
|
||||
++++++++++++++++++++++++++++++
|
||||
.. automethod:: ADBAndroid.install_app(self, apk_path, timeout=None)
|
||||
.. automethod:: ADBAndroid.is_app_installed(self, app_name, timeout=None)
|
||||
.. automethod:: ADBAndroid.launch_application(self, app_name, activity_name, intent, url=None, extras=None, wait=True, fail_if_running=True, timeout=None)
|
||||
.. automethod:: ADBAndroid.launch_fennec(self, app_name, intent="android.intent.action.VIEW", moz_env=None, extra_args=None, url=None, wait=True, fail_if_running=True, timeout=None)
|
||||
.. automethod:: ADBAndroid.stop_application(self, app_name, timeout=None, root=False)
|
||||
.. automethod:: ADBAndroid.uninstall_app(self, app_name, reboot=False, timeout=None)
|
||||
.. automethod:: ADBAndroid.update_app(self, apk_path, timeout=None)
|
||||
.. automethod:: ADBAndroid.install_app
|
||||
.. automethod:: ADBAndroid.is_app_installed
|
||||
.. automethod:: ADBAndroid.launch_application
|
||||
.. automethod:: ADBAndroid.launch_fennec
|
||||
.. automethod:: ADBAndroid.stop_application
|
||||
.. automethod:: ADBAndroid.uninstall_app
|
||||
.. automethod:: ADBAndroid.update_app
|
||||
|
||||
ADBB2G
|
||||
``````
|
||||
.. autoclass:: ADBB2G
|
||||
|
||||
Informational methods
|
||||
+++++++++++++++++++++
|
||||
.. automethod:: ADBB2G.get_battery_percentage
|
||||
.. automethod:: ADBB2G.get_info
|
||||
.. automethod:: ADBB2G.get_memory_total
|
||||
|
||||
ADBProcess
|
||||
``````````
|
||||
|
@ -4,6 +4,7 @@
|
||||
|
||||
from adb import ADBError, ADBRootError, ADBTimeoutError, ADBProcess, ADBCommand, ADBHost, ADBDevice
|
||||
from adb_android import ADBAndroid
|
||||
from adb_b2g import ADBB2G
|
||||
from devicemanager import DeviceManager, DMError, ZeroconfListener
|
||||
from devicemanagerADB import DeviceManagerADB
|
||||
from devicemanagerSUT import DeviceManagerSUT
|
||||
|
@ -2,6 +2,7 @@
|
||||
# License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
# You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
from abc import ABCMeta, abstractmethod
|
||||
import os
|
||||
import posixpath
|
||||
import re
|
||||
@ -12,9 +13,7 @@ import traceback
|
||||
|
||||
|
||||
class ADBProcess(object):
|
||||
"""ADBProcess encapsulates the data related to executing the adb process.
|
||||
|
||||
"""
|
||||
"""ADBProcess encapsulates the data related to executing the adb process."""
|
||||
def __init__(self, args):
|
||||
#: command argument argument list.
|
||||
self.args = args
|
||||
@ -64,7 +63,6 @@ class ADBError(Exception):
|
||||
device either exited with a non-zero exitcode or when an
|
||||
unexpected error condition has occurred. Generally, ADBErrors can
|
||||
be handled and the device can continue to be used.
|
||||
|
||||
"""
|
||||
pass
|
||||
|
||||
@ -73,7 +71,6 @@ class ADBRootError(Exception):
|
||||
root but the device does not support it. This error is fatal since
|
||||
there is no recovery possible by the script. You must either root
|
||||
your device or change your scripts to not require running as root.
|
||||
|
||||
"""
|
||||
pass
|
||||
|
||||
@ -94,7 +91,6 @@ class ADBTimeoutError(Exception):
|
||||
|
||||
* Rebooting the device manually.
|
||||
* Rebooting the host.
|
||||
|
||||
"""
|
||||
pass
|
||||
|
||||
@ -117,7 +113,6 @@ class ADBCommand(object):
|
||||
adbcommand = ADBCommand()
|
||||
except NotImplementedError:
|
||||
print "ADBCommand can not be instantiated."
|
||||
|
||||
"""
|
||||
|
||||
def __init__(self,
|
||||
@ -138,7 +133,6 @@ class ADBCommand(object):
|
||||
|
||||
:raises: * ADBError
|
||||
* ADBTimeoutError
|
||||
|
||||
"""
|
||||
if self.__class__ == ADBCommand:
|
||||
raise NotImplementedError
|
||||
@ -211,7 +205,6 @@ class ADBCommand(object):
|
||||
|
||||
It is the caller's responsibilty to clean up by closing
|
||||
the stdout and stderr temporary files.
|
||||
|
||||
"""
|
||||
args = [self._adb_path]
|
||||
if self._adb_host:
|
||||
@ -263,7 +256,6 @@ class ADBCommand(object):
|
||||
|
||||
:raises: * ADBTimeoutError
|
||||
* ADBError
|
||||
|
||||
"""
|
||||
adb_process = None
|
||||
try:
|
||||
@ -306,7 +298,6 @@ class ADBHost(ADBCommand):
|
||||
|
||||
adbhost = ADBHost()
|
||||
adbhost.start_server()
|
||||
|
||||
"""
|
||||
def __init__(self,
|
||||
adb='adb',
|
||||
@ -326,7 +317,6 @@ class ADBHost(ADBCommand):
|
||||
|
||||
:raises: * ADBError
|
||||
* ADBTimeoutError
|
||||
|
||||
"""
|
||||
ADBCommand.__init__(self, adb=adb, adb_host=adb_host,
|
||||
adb_port=adb_port, logger_name=logger_name,
|
||||
@ -362,7 +352,6 @@ class ADBHost(ADBCommand):
|
||||
|
||||
It is the caller's responsibilty to clean up by closing
|
||||
the stdout and stderr temporary files.
|
||||
|
||||
"""
|
||||
return ADBCommand.command(self, cmds, timeout=timeout)
|
||||
|
||||
@ -382,7 +371,6 @@ class ADBHost(ADBCommand):
|
||||
|
||||
:raises: * ADBTimeoutError
|
||||
* ADBError
|
||||
|
||||
"""
|
||||
return ADBCommand.command_output(self, cmds, timeout=timeout)
|
||||
|
||||
@ -415,7 +403,6 @@ class ADBHost(ADBCommand):
|
||||
while true; do
|
||||
adb -a fork-server server
|
||||
done
|
||||
|
||||
"""
|
||||
self.command_output(["start-server"], timeout=timeout)
|
||||
|
||||
@ -430,7 +417,6 @@ class ADBHost(ADBCommand):
|
||||
:type timeout: integer or None
|
||||
:raises: * ADBTimeoutError
|
||||
* ADBError
|
||||
|
||||
"""
|
||||
self.command_output(["kill-server"], timeout=timeout)
|
||||
|
||||
@ -457,7 +443,6 @@ class ADBHost(ADBCommand):
|
||||
|
||||
[{'device_serial': 'b313b945', 'state': 'device', 'product': 'd2vzw',
|
||||
'usb': '1-7', 'device': 'd2vzw', 'model': 'SCH_I535' }]
|
||||
|
||||
"""
|
||||
# b313b945 device usb:1-7 product:d2vzw model:SCH_I535 device:d2vzw
|
||||
# from Android system/core/adb/transport.c statename()
|
||||
@ -486,22 +471,12 @@ class ADBHost(ADBCommand):
|
||||
|
||||
|
||||
class ADBDevice(ADBCommand):
|
||||
"""ADBDevice provides methods which can be used to interact with
|
||||
the associated Android-based device.
|
||||
|
||||
Android specific features such as Application management are not
|
||||
included but are provided via the ADBAndroid interface.
|
||||
|
||||
::
|
||||
|
||||
from mozdevice import ADBDevice
|
||||
|
||||
adbdevice = ADBDevice()
|
||||
print adbdevice.list_files("/mnt/sdcard")
|
||||
if adbdevice.process_exist("org.mozilla.fennec"):
|
||||
print "Fennec is running"
|
||||
|
||||
"""ADBDevice is an abstract base class which provides methods which
|
||||
can be used to interact with the associated Android or B2G based
|
||||
device. It must be used via one of the concrete implementations in
|
||||
:class:`ADBAndroid` or :class:`ADBB2G`.
|
||||
"""
|
||||
__metaclass__ = ABCMeta
|
||||
|
||||
def __init__(self,
|
||||
device=None,
|
||||
@ -547,8 +522,6 @@ class ADBDevice(ADBCommand):
|
||||
:raises: * ADBError
|
||||
* ADBTimeoutError
|
||||
* ValueError
|
||||
|
||||
|
||||
"""
|
||||
ADBCommand.__init__(self, adb=adb, adb_host=adb_host,
|
||||
adb_port=adb_port, logger_name=logger_name,
|
||||
@ -604,6 +577,9 @@ class ADBDevice(ADBCommand):
|
||||
except ADBError:
|
||||
self._ls += " -a"
|
||||
|
||||
# Do we have cp?
|
||||
self._have_cp = self.shell_bool("type cp")
|
||||
|
||||
self._logger.debug("ADBDevice: %s" % self.__dict__)
|
||||
|
||||
def _get_device_serial(self, device):
|
||||
@ -644,7 +620,6 @@ class ADBDevice(ADBCommand):
|
||||
def _escape_command_line(cmd):
|
||||
"""Utility function to return escaped and quoted version of command
|
||||
line.
|
||||
|
||||
"""
|
||||
quoted_cmd = []
|
||||
|
||||
@ -667,7 +642,6 @@ class ADBDevice(ADBCommand):
|
||||
def _get_exitcode(file_obj):
|
||||
"""Get the exitcode from the last line of the file_obj for shell
|
||||
commands.
|
||||
|
||||
"""
|
||||
file_obj.seek(0, os.SEEK_END)
|
||||
|
||||
@ -806,7 +780,6 @@ class ADBDevice(ADBCommand):
|
||||
|
||||
It is the caller's responsibilty to clean up by closing
|
||||
the stdout and stderr temporary files.
|
||||
|
||||
"""
|
||||
|
||||
return ADBCommand.command(self, cmds,
|
||||
@ -829,7 +802,6 @@ class ADBDevice(ADBCommand):
|
||||
|
||||
:raises: * ADBTimeoutError
|
||||
* ADBError
|
||||
|
||||
"""
|
||||
return ADBCommand.command_output(self, cmds,
|
||||
device_serial=self._device_serial,
|
||||
@ -980,7 +952,6 @@ class ADBDevice(ADBCommand):
|
||||
|
||||
It is the caller's responsibilty to clean up by closing
|
||||
the stdout and stderr temporary files.
|
||||
|
||||
"""
|
||||
if root:
|
||||
ld_library_path='LD_LIBRARY_PATH=/vendor/lib:/system/lib'
|
||||
@ -1058,7 +1029,6 @@ class ADBDevice(ADBCommand):
|
||||
|
||||
:raises: * ADBTimeoutError
|
||||
* ADBRootError
|
||||
|
||||
"""
|
||||
adb_process = None
|
||||
try:
|
||||
@ -1093,7 +1063,6 @@ class ADBDevice(ADBCommand):
|
||||
:raises: * ADBTimeoutError
|
||||
* ADBRootError
|
||||
* ADBError
|
||||
|
||||
"""
|
||||
adb_process = None
|
||||
try:
|
||||
@ -1151,7 +1120,6 @@ class ADBDevice(ADBCommand):
|
||||
"radio", "events", and "main". Defaults to "main".
|
||||
:raises: * ADBTimeoutError
|
||||
* ADBError
|
||||
|
||||
"""
|
||||
buffers = self._get_logcat_buffer_args(buffers)
|
||||
cmds = ["logcat", "-c"] + buffers
|
||||
@ -1188,7 +1156,6 @@ class ADBDevice(ADBCommand):
|
||||
:returns: list of lines logcat output.
|
||||
:raises: * ADBTimeoutError
|
||||
* ADBError
|
||||
|
||||
"""
|
||||
buffers = self._get_logcat_buffer_args(buffers)
|
||||
cmds = ["logcat", "-v", format, "-d"] + buffers + filter_specs
|
||||
@ -1213,7 +1180,6 @@ class ADBDevice(ADBCommand):
|
||||
:returns: string value of property.
|
||||
:raises: * ADBTimeoutError
|
||||
* ADBError
|
||||
|
||||
"""
|
||||
output = self.shell_output('getprop %s' % prop, timeout=timeout)
|
||||
return output
|
||||
@ -1231,7 +1197,6 @@ class ADBDevice(ADBCommand):
|
||||
:returns: string value of adb get-state.
|
||||
:raises: * ADBTimeoutError
|
||||
* ADBError
|
||||
|
||||
"""
|
||||
output = self.command_output(["get-state"], timeout=timeout).strip()
|
||||
return output
|
||||
@ -1253,7 +1218,6 @@ class ADBDevice(ADBCommand):
|
||||
be found.
|
||||
:raises: * ADBTimeoutError
|
||||
* ADBError
|
||||
|
||||
"""
|
||||
ip_regexp = re.compile(r'(\w+)\s+UP\s+([1-9]\d{0,2}\.\d{1,3}\.\d{1,3}\.\d{1,3})')
|
||||
data = self.shell_output('netcfg')
|
||||
@ -1309,7 +1273,6 @@ class ADBDevice(ADBCommand):
|
||||
:raises: * ADBTimeoutError
|
||||
* ADBRootError
|
||||
* ADBError
|
||||
|
||||
"""
|
||||
path = posixpath.normpath(path.strip())
|
||||
self._logger.debug('chmod: path=%s, recursive=%s, mask=%s, root=%s' %
|
||||
@ -1356,7 +1319,6 @@ class ADBDevice(ADBCommand):
|
||||
:returns: boolean - True if path exists.
|
||||
:raises: * ADBTimeoutError
|
||||
* ADBRootError
|
||||
|
||||
"""
|
||||
path = posixpath.normpath(path)
|
||||
return self.shell_bool('ls -a %s' % path, timeout=timeout, root=root)
|
||||
@ -1378,7 +1340,6 @@ class ADBDevice(ADBCommand):
|
||||
directory.
|
||||
:raises: * ADBTimeoutError
|
||||
* ADBRootError
|
||||
|
||||
"""
|
||||
path = posixpath.normpath(path)
|
||||
return self.shell_bool('ls -a %s/' % path, timeout=timeout, root=root)
|
||||
@ -1400,7 +1361,6 @@ class ADBDevice(ADBCommand):
|
||||
file.
|
||||
:raises: * ADBTimeoutError
|
||||
* ADBRootError
|
||||
|
||||
"""
|
||||
path = posixpath.normpath(path)
|
||||
return (
|
||||
@ -1424,7 +1384,6 @@ class ADBDevice(ADBCommand):
|
||||
:returns: list of files/directories contained in the directory.
|
||||
:raises: * ADBTimeoutError
|
||||
* ADBRootError
|
||||
|
||||
"""
|
||||
path = posixpath.normpath(path.strip())
|
||||
data = []
|
||||
@ -1461,7 +1420,6 @@ class ADBDevice(ADBCommand):
|
||||
:raises: * ADBTimeoutError
|
||||
* ADBRootError
|
||||
* ADBError
|
||||
|
||||
"""
|
||||
path = posixpath.normpath(path)
|
||||
if parents:
|
||||
@ -1504,7 +1462,6 @@ class ADBDevice(ADBCommand):
|
||||
:type timeout: integer or None
|
||||
:raises: * ADBTimeoutError
|
||||
* ADBError
|
||||
|
||||
"""
|
||||
self.command_output(["push", os.path.realpath(local), remote],
|
||||
timeout=timeout)
|
||||
@ -1525,7 +1482,6 @@ class ADBDevice(ADBCommand):
|
||||
:type timeout: integer or None
|
||||
:raises: * ADBTimeoutError
|
||||
* ADBError
|
||||
|
||||
"""
|
||||
self.command_output(["pull", remote, os.path.realpath(local)],
|
||||
timeout=timeout)
|
||||
@ -1551,7 +1507,6 @@ class ADBDevice(ADBCommand):
|
||||
:raises: * ADBTimeoutError
|
||||
* ADBRootError
|
||||
* ADBError
|
||||
|
||||
"""
|
||||
cmd = "rm"
|
||||
if recursive:
|
||||
@ -1580,7 +1535,6 @@ class ADBDevice(ADBCommand):
|
||||
:raises: * ADBTimeoutError
|
||||
* ADBRootError
|
||||
* ADBError
|
||||
|
||||
"""
|
||||
self.shell_output("rmdir %s" % path, timeout=timeout, root=root)
|
||||
if self.is_dir(path, timeout=timeout, root=root):
|
||||
@ -1603,7 +1557,6 @@ class ADBDevice(ADBCommand):
|
||||
on the device.
|
||||
:raises: * ADBTimeoutError
|
||||
* ADBError
|
||||
|
||||
"""
|
||||
adb_process = None
|
||||
try:
|
||||
@ -1668,7 +1621,6 @@ class ADBDevice(ADBCommand):
|
||||
:raises: * ADBTimeoutError
|
||||
* ADBRootError
|
||||
* ADBError
|
||||
|
||||
"""
|
||||
pid_list = [str(pid) for pid in pids]
|
||||
for attempt in range(attempts):
|
||||
@ -1719,7 +1671,6 @@ class ADBDevice(ADBCommand):
|
||||
:raises: * ADBTimeoutError
|
||||
* ADBRootError
|
||||
* ADBError
|
||||
|
||||
"""
|
||||
procs = self.get_process_list(timeout=timeout)
|
||||
# limit the comparion to the first 75 characters due to a
|
||||
@ -1753,7 +1704,6 @@ class ADBDevice(ADBCommand):
|
||||
|
||||
:raises: * ADBTimeoutError
|
||||
* ADBError
|
||||
|
||||
"""
|
||||
if not isinstance(process_name, basestring):
|
||||
raise ADBError("Process name %s is not a string" % process_name)
|
||||
@ -1783,3 +1733,204 @@ class ADBDevice(ADBCommand):
|
||||
if proc_name == app[:75]:
|
||||
return True
|
||||
return False
|
||||
|
||||
def cp(self, source, destination, recursive=False, timeout=None,
|
||||
root=False):
|
||||
"""Copies a file or directory on the device.
|
||||
|
||||
:param source: string containing the path of the source file or
|
||||
directory.
|
||||
:param destination: string containing the path of the destination file
|
||||
or directory.
|
||||
:param recursive: optional boolean indicating if a recursive copy is to
|
||||
be performed. Required if the source is a directory. Defaults to
|
||||
False. Think cp -R source destination.
|
||||
:param timeout: optional integer specifying the maximum time in
|
||||
seconds for any spawned adb process to complete before
|
||||
throwing an ADBTimeoutError.
|
||||
This timeout is per adb call. The total time spent
|
||||
may exceed this value. If it is not specified, the value
|
||||
set in the ADBDevice constructor is used.
|
||||
:raises: * ADBTimeoutError
|
||||
* ADBRootError
|
||||
* ADBError
|
||||
"""
|
||||
source = posixpath.normpath(source)
|
||||
destination = posixpath.normpath(destination)
|
||||
if self._have_cp:
|
||||
r = '-R' if recursive else ''
|
||||
self.shell_output('cp %s %s %s' % (r, source, destination),
|
||||
timeout=timeout, root=root)
|
||||
return
|
||||
|
||||
# Emulate cp behavior depending on if source and destination
|
||||
# already exists and whether they are a directory or file.
|
||||
if not self.exists(source, timeout=timeout, root=root):
|
||||
raise ADBError("cp: can't stat '%s': No such file or directory" %
|
||||
source)
|
||||
|
||||
if self.is_file(source, timeout=timeout, root=root):
|
||||
if self.is_dir(destination, timeout=timeout, root=root):
|
||||
# Copy the source file into the destination directory
|
||||
destination = posixpath.join(destination,
|
||||
posixpath.basename(source))
|
||||
self.shell_output('dd if=%s of=%s' % (source, destination),
|
||||
timeout=timeout, root=root)
|
||||
return
|
||||
|
||||
if self.is_file(destination, timeout=timeout, root=root):
|
||||
raise ADBError('cp: %s: Not a directory' % destination)
|
||||
|
||||
if not recursive:
|
||||
raise ADBError("cp: omitting directory '%s'" % source)
|
||||
|
||||
if self.is_dir(destination, timeout=timeout, root=root):
|
||||
# Copy the source directory into the destination directory.
|
||||
destination_dir = posixpath.join(destination,
|
||||
posixpath.basename(source))
|
||||
else:
|
||||
# Copy the contents of the source directory into the
|
||||
# destination directory.
|
||||
destination_dir = destination
|
||||
|
||||
try:
|
||||
# Do not create parent directories since cp does not.
|
||||
self.mkdir(destination_dir, timeout=timeout, root=root)
|
||||
except ADBError as e:
|
||||
if 'File exists' not in e.message:
|
||||
raise
|
||||
|
||||
for i in self.list_files(source, timeout=timeout, root=root):
|
||||
self.cp(posixpath.join(source, i),
|
||||
posixpath.join(destination_dir, i),
|
||||
recursive=recursive,
|
||||
timeout=timeout, root=root)
|
||||
|
||||
def mv(self, source, destination, timeout=None, root=False):
|
||||
"""Moves a file or directory on the device.
|
||||
|
||||
:param source: string containing the path of the source file or
|
||||
directory.
|
||||
:param destination: string containing the path of the destination file
|
||||
or directory.
|
||||
:param timeout: optional integer specifying the maximum time in
|
||||
seconds for any spawned adb process to complete before
|
||||
throwing an ADBTimeoutError.
|
||||
This timeout is per adb call. The total time spent
|
||||
may exceed this value. If it is not specified, the value
|
||||
set in the ADBDevice constructor is used.
|
||||
:raises: * ADBTimeoutError
|
||||
* ADBRootError
|
||||
* ADBError
|
||||
"""
|
||||
source = posixpath.normpath(source)
|
||||
destination = posixpath.normpath(destination)
|
||||
self.shell_output('mv %s %s' % (source, destination), timeout=timeout,
|
||||
root=root)
|
||||
|
||||
def reboot(self, timeout=None):
|
||||
"""Reboots the device.
|
||||
|
||||
:param timeout: optional integer specifying the maximum time in
|
||||
seconds for any spawned adb process to complete before
|
||||
throwing an ADBTimeoutError.
|
||||
This timeout is per adb call. The total time spent
|
||||
may exceed this value. If it is not specified, the value
|
||||
set in the ADB constructor is used.
|
||||
:raises: * ADBTimeoutError
|
||||
* ADBError
|
||||
|
||||
reboot() reboots the device, issues an adb wait-for-device in order to
|
||||
wait for the device to complete rebooting, then calls is_device_ready()
|
||||
to determine if the device has completed booting.
|
||||
"""
|
||||
self.command_output(["reboot"], timeout=timeout)
|
||||
self.command_output(["wait-for-device"], timeout=timeout)
|
||||
return self.is_device_ready(timeout=timeout)
|
||||
|
||||
@abstractmethod
|
||||
def is_device_ready(self, timeout=None):
|
||||
"""Abstract class that returns True if the device is ready.
|
||||
|
||||
:param timeout: optional integer specifying the maximum time in
|
||||
seconds for any spawned adb process to complete before
|
||||
throwing an ADBTimeoutError.
|
||||
This timeout is per adb call. The total time spent
|
||||
may exceed this value. If it is not specified, the value
|
||||
set in the ADB constructor is used.
|
||||
:raises: * ADBTimeoutError
|
||||
* ADBError
|
||||
"""
|
||||
return
|
||||
|
||||
@abstractmethod
|
||||
def get_battery_percentage(self, timeout=None):
|
||||
"""Abstract class that returns the battery charge as a percentage.
|
||||
|
||||
:param timeout: optional integer specifying the maximum time in
|
||||
seconds for any spawned adb process to complete before
|
||||
throwing an ADBTimeoutError.
|
||||
This timeout is per adb call. The total time spent
|
||||
may exceed this value. If it is not specified, the value
|
||||
set in the ADBDevice constructor is used.
|
||||
:returns: battery charge as a percentage.
|
||||
:raises: * ADBTimeoutError
|
||||
* ADBError
|
||||
"""
|
||||
return
|
||||
|
||||
def get_info(self, directive=None, timeout=None):
|
||||
"""
|
||||
Returns a dictionary of information strings about the device.
|
||||
|
||||
:param directive: information you want to get. Options are:
|
||||
- `battery` - battery charge as a percentage
|
||||
- `disk` - total, free, available bytes on disk
|
||||
- `id` - unique id of the device
|
||||
- `os` - name of the os
|
||||
- `process` - list of running processes (same as ps)
|
||||
- `systime` - system time of the device
|
||||
- `uptime` - uptime of the device
|
||||
|
||||
If `directive` is `None`, will return all available information
|
||||
:param timeout: optional integer specifying the maximum time in
|
||||
seconds for any spawned adb process to complete before
|
||||
throwing an ADBTimeoutError.
|
||||
This timeout is per adb call. The total time spent
|
||||
may exceed this value. If it is not specified, the value
|
||||
set in the ADB constructor is used.
|
||||
:raises: * ADBTimeoutError
|
||||
* ADBError
|
||||
"""
|
||||
directives = ['battery', 'disk', 'id', 'os', 'process', 'systime',
|
||||
'uptime']
|
||||
|
||||
if (directive in directives):
|
||||
directives = [directive]
|
||||
|
||||
info = {}
|
||||
if 'battery' in directives:
|
||||
info['battery'] = self.get_battery_percentage(timeout=timeout)
|
||||
if 'disk' in directives:
|
||||
info['disk'] = self.shell_output('df /data /system /sdcard',
|
||||
timeout=timeout).splitlines()
|
||||
if 'id' in directives:
|
||||
info['id'] = self.command_output(['get-serialno'], timeout=timeout)
|
||||
if 'os' in directives:
|
||||
info['os'] = self.shell_output('getprop ro.build.display.id',
|
||||
timeout=timeout)
|
||||
if 'process' in directives:
|
||||
ps = self.shell_output('ps', timeout=timeout)
|
||||
info['process'] = ps.splitlines()
|
||||
if 'systime' in directives:
|
||||
info['systime'] = self.shell_output('date', timeout=timeout)
|
||||
if 'uptime' in directives:
|
||||
uptime = self.shell_output('uptime', timeout=timeout)
|
||||
if uptime:
|
||||
m = re.match('up time: ((\d+) days, )*(\d{2}):(\d{2}):(\d{2})',
|
||||
uptime)
|
||||
if m:
|
||||
uptime = '%d days %d hours %d minutes %d seconds' % tuple(
|
||||
[int(g or 0) for g in m.groups()[1:]])
|
||||
info['uptime'] = uptime
|
||||
return info
|
||||
|
@ -10,8 +10,19 @@ from adb import ADBDevice, ADBError
|
||||
from distutils.version import StrictVersion
|
||||
|
||||
|
||||
class ADBAndroidMixin(object):
|
||||
"""Mixin to extend ADB with Android-specific functionality"""
|
||||
class ADBAndroid(ADBDevice):
|
||||
"""ADBAndroid implements :class:`ADBDevice` providing Android-specific
|
||||
functionality.
|
||||
|
||||
::
|
||||
|
||||
from mozdevice import ADBAndroid
|
||||
|
||||
adbdevice = ADBAndroid()
|
||||
print adbdevice.list_files("/mnt/sdcard")
|
||||
if adbdevice.process_exist("org.mozilla.fennec"):
|
||||
print "Fennec is running"
|
||||
"""
|
||||
|
||||
# Informational methods
|
||||
|
||||
@ -28,7 +39,6 @@ class ADBAndroidMixin(object):
|
||||
:returns: battery charge as a percentage.
|
||||
:raises: * ADBTimeoutError
|
||||
* ADBError
|
||||
|
||||
"""
|
||||
level = None
|
||||
scale = None
|
||||
@ -67,7 +77,6 @@ class ADBAndroidMixin(object):
|
||||
:type timeout: integer or None
|
||||
:raises: * ADBTimeoutError
|
||||
* ADBError
|
||||
|
||||
"""
|
||||
self.command_output(["wait-for-device"], timeout=timeout)
|
||||
pm_error_string = "Error: Could not access the Package Manager"
|
||||
@ -120,7 +129,6 @@ class ADBAndroidMixin(object):
|
||||
:type timeout: integer or None
|
||||
:raises: * ADBTimeoutError
|
||||
* ADBError
|
||||
|
||||
"""
|
||||
try:
|
||||
self.shell_output('svc power stayon true', timeout=timeout)
|
||||
@ -131,31 +139,6 @@ class ADBAndroidMixin(object):
|
||||
raise
|
||||
self._logger.warning('Unable to set power stayon true: %s' % e)
|
||||
|
||||
def reboot(self, timeout=None):
|
||||
"""Reboots the device.
|
||||
|
||||
This method uses the Android only package manager to determine
|
||||
if the device is ready after the reboot.
|
||||
|
||||
:param timeout: The maximum time in
|
||||
seconds for any spawned adb process to complete before
|
||||
throwing an ADBTimeoutError.
|
||||
This timeout is per adb call. The total time spent
|
||||
may exceed this value. If it is not specified, the value
|
||||
set in the ADB constructor is used.
|
||||
:type timeout: integer or None
|
||||
:raises: * ADBTimeoutError
|
||||
* ADBError
|
||||
|
||||
reboot() reboots the device, issues an adb wait-for-device in order to
|
||||
wait for the device to complete rebooting, then calls is_device_ready()
|
||||
to determine if the device has completed booting.
|
||||
|
||||
"""
|
||||
self.command_output(["reboot"], timeout=timeout)
|
||||
self.command_output(["wait-for-device"], timeout=timeout)
|
||||
return self.is_device_ready(timeout=timeout)
|
||||
|
||||
# Application management methods
|
||||
|
||||
def install_app(self, apk_path, timeout=None):
|
||||
@ -171,7 +154,6 @@ class ADBAndroidMixin(object):
|
||||
:type timeout: integer or None
|
||||
:raises: * ADBTimeoutError
|
||||
* ADBError
|
||||
|
||||
"""
|
||||
data = self.command_output(["install", apk_path], timeout=timeout)
|
||||
if data.find('Success') == -1:
|
||||
@ -191,7 +173,6 @@ class ADBAndroidMixin(object):
|
||||
:type timeout: integer or None
|
||||
:raises: * ADBTimeoutError
|
||||
* ADBError
|
||||
|
||||
"""
|
||||
pm_error_string = 'Error: Could not access the Package Manager'
|
||||
data = self.shell_output("pm list package %s" % app_name, timeout=timeout)
|
||||
@ -226,7 +207,6 @@ class ADBAndroidMixin(object):
|
||||
:type timeout: integer or None
|
||||
:raises: * ADBTimeoutError
|
||||
* ADBError
|
||||
|
||||
"""
|
||||
# If fail_if_running is True, we throw an exception here. Only one
|
||||
# instance of an application can be running at once on Android,
|
||||
@ -287,7 +267,6 @@ class ADBAndroidMixin(object):
|
||||
:type timeout: integer or None
|
||||
:raises: * ADBTimeoutError
|
||||
* ADBError
|
||||
|
||||
"""
|
||||
extras = {}
|
||||
|
||||
@ -327,7 +306,6 @@ class ADBAndroidMixin(object):
|
||||
executed as root.
|
||||
:raises: * ADBTimeoutError
|
||||
* ADBError
|
||||
|
||||
"""
|
||||
version = self.shell_output("getprop ro.build.version.release",
|
||||
timeout=timeout, root=root)
|
||||
@ -367,7 +345,6 @@ class ADBAndroidMixin(object):
|
||||
:type timeout: integer or None
|
||||
:raises: * ADBTimeoutError
|
||||
* ADBError
|
||||
|
||||
"""
|
||||
if self.is_app_installed(app_name, timeout=timeout):
|
||||
data = self.command_output(["uninstall", app_name], timeout=timeout)
|
||||
@ -391,27 +368,8 @@ class ADBAndroidMixin(object):
|
||||
:type timeout: integer or None
|
||||
:raises: * ADBTimeoutError
|
||||
* ADBError
|
||||
|
||||
"""
|
||||
output = self.command_output(["install", "-r", apk_path],
|
||||
timeout=timeout)
|
||||
self.reboot(timeout=timeout)
|
||||
return output
|
||||
|
||||
|
||||
class ADBAndroid(ADBDevice, ADBAndroidMixin):
|
||||
"""ADBAndroid provides all of the methods of :class:`mozdevice.ADB` with
|
||||
Android specific extensions useful for that platform.
|
||||
|
||||
::
|
||||
|
||||
from mozdevice import ADBAndroid as ADBDevice
|
||||
|
||||
adb = ADBDevice(...)
|
||||
|
||||
if adb.is_device_ready():
|
||||
adb.install_app("/tmp/build.apk")
|
||||
adb.launch_fennec("org.mozilla.fennec")
|
||||
|
||||
"""
|
||||
pass
|
||||
|
122
testing/mozbase/mozdevice/mozdevice/adb_b2g.py
Normal file
122
testing/mozbase/mozdevice/mozdevice/adb_b2g.py
Normal file
@ -0,0 +1,122 @@
|
||||
# This Source Code Form is subject to the terms of the Mozilla Public
|
||||
# License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
# You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
import traceback
|
||||
|
||||
import mozfile
|
||||
|
||||
from adb import ADBDevice, ADBError
|
||||
|
||||
|
||||
class ADBB2G(ADBDevice):
|
||||
"""ADBB2G implements :class:`ADBDevice` providing B2G-specific
|
||||
functionality.
|
||||
|
||||
::
|
||||
|
||||
from mozdevice import ADBB2G
|
||||
|
||||
adbdevice = ADBB2G()
|
||||
print adbdevice.list_files("/mnt/sdcard")
|
||||
if adbdevice.process_exist("b2g"):
|
||||
print "B2G is running"
|
||||
"""
|
||||
|
||||
def get_battery_percentage(self, timeout=None):
|
||||
"""Returns the battery charge as a percentage.
|
||||
|
||||
:param timeout: optional integer specifying the maximum time in
|
||||
seconds for any spawned adb process to complete before
|
||||
throwing an ADBTimeoutError.
|
||||
This timeout is per adb call. The total time spent
|
||||
may exceed this value. If it is not specified, the value
|
||||
set in the ADBDevice constructor is used.
|
||||
:returns: battery charge as a percentage.
|
||||
:raises: * ADBTimeoutError
|
||||
* ADBError
|
||||
"""
|
||||
with mozfile.NamedTemporaryFile() as tf:
|
||||
self.pull('/sys/class/power_supply/battery/capacity', tf.name,
|
||||
timeout=timeout)
|
||||
try:
|
||||
with open(tf.name) as tf2:
|
||||
return tf2.read().splitlines()[0]
|
||||
except Exception as e:
|
||||
raise ADBError(traceback.format_exception_only(
|
||||
type(e), e)[0].strip())
|
||||
|
||||
def get_memory_total(self, timeout=None):
|
||||
"""Returns the total memory available with units.
|
||||
|
||||
:param timeout: optional integer specifying the maximum time in
|
||||
seconds for any spawned adb process to complete before
|
||||
throwing an ADBTimeoutError.
|
||||
This timeout is per adb call. The total time spent
|
||||
may exceed this value. If it is not specified, the value
|
||||
set in the ADBDevice constructor is used.
|
||||
:returns: memory total with units.
|
||||
:raises: * ADBTimeoutError
|
||||
* ADBError
|
||||
"""
|
||||
meminfo = {}
|
||||
with mozfile.NamedTemporaryFile() as tf:
|
||||
self.pull('/proc/meminfo', tf.name, timeout=timeout)
|
||||
try:
|
||||
with open(tf.name) as tf2:
|
||||
for line in tf2.read().splitlines():
|
||||
key, value = line.split(':')
|
||||
meminfo[key] = value.strip()
|
||||
except Exception as e:
|
||||
raise ADBError(traceback.format_exception_only(
|
||||
type(e), e)[0].strip())
|
||||
return meminfo['MemTotal']
|
||||
|
||||
def get_info(self, directive=None, timeout=None):
|
||||
"""
|
||||
Returns a dictionary of information strings about the device.
|
||||
|
||||
:param directive: information you want to get. Options are:
|
||||
- `battery` - battery charge as a percentage
|
||||
- `disk` - total, free, available bytes on disk
|
||||
- `id` - unique id of the device
|
||||
- `memtotal` - total memory available on the device
|
||||
- `os` - name of the os
|
||||
- `process` - list of running processes (same as ps)
|
||||
- `systime` - system time of the device
|
||||
- `uptime` - uptime of the device
|
||||
|
||||
If `directive` is `None`, will return all available information
|
||||
:param timeout: optional integer specifying the maximum time in
|
||||
seconds for any spawned adb process to complete before
|
||||
throwing an ADBTimeoutError.
|
||||
This timeout is per adb call. The total time spent
|
||||
may exceed this value. If it is not specified, the value
|
||||
set in the ADB constructor is used.
|
||||
:raises: * ADBTimeoutError
|
||||
* ADBError
|
||||
"""
|
||||
info = super(ADBB2G, self).get_info(directive=directive,
|
||||
timeout=timeout)
|
||||
|
||||
directives = ['memtotal']
|
||||
if (directive in directives):
|
||||
directives = [directive]
|
||||
|
||||
if 'memtotal' in directives:
|
||||
info['memtotal'] = self.get_memory_total(timeout=timeout)
|
||||
return info
|
||||
|
||||
def is_device_ready(self, timeout=None):
|
||||
"""Returns True if the device is ready.
|
||||
|
||||
:param timeout: optional integer specifying the maximum time in
|
||||
seconds for any spawned adb process to complete before
|
||||
throwing an ADBTimeoutError.
|
||||
This timeout is per adb call. The total time spent
|
||||
may exceed this value. If it is not specified, the value
|
||||
set in the ADB constructor is used.
|
||||
:raises: * ADBTimeoutError
|
||||
* ADBError
|
||||
"""
|
||||
return self.shell_bool('ls /sbin', timeout=timeout)
|
@ -192,7 +192,7 @@ class B2GExecutorBrowser(ExecutorBrowser):
|
||||
|
||||
import sys, subprocess
|
||||
|
||||
self.device = mozdevice.ADBDevice()
|
||||
self.device = mozdevice.ADBB2G()
|
||||
self.device.forward("tcp:%s" % self.marionette_port,
|
||||
"tcp:2828")
|
||||
self.executor = None
|
||||
|
Loading…
Reference in New Issue
Block a user