зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1486004 - Part 1 - [mozdevice 4.0.0] Use run-as to work around rooted device requirement, r=gbrown,jmaher
Differential Revision: https://phabricator.services.mozilla.com/D82744
This commit is contained in:
Родитель
85e7c622aa
Коммит
421a5117f1
|
@ -2,8 +2,8 @@ Device management
|
|||
-----------------
|
||||
|
||||
Mozbase provides a module called `mozdevice` for the purposes of
|
||||
running automated tests or scripts on an Android or B2G device (e.g. a
|
||||
phone, tablet, or emulator) connected to a workstation.
|
||||
running automated tests or scripts on an Android phone, tablet, or
|
||||
emulator connected to a workstation.
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 3
|
||||
|
|
|
@ -1,121 +1,8 @@
|
|||
:mod:`mozdevice` --- Interact with Android devices
|
||||
==================================================
|
||||
|
||||
Mozdevice provides several interfaces to interact with an Android
|
||||
device such as a phone, tablet, or emulator. It allows you to push
|
||||
files to these types of devices, launch processes, and more. There are
|
||||
currently two available interfaces:
|
||||
|
||||
* :ref:`ADB`: Uses the Android Debugger Protocol explicitly
|
||||
|
||||
.. automodule:: mozdevice
|
||||
|
||||
.. _ADB:
|
||||
|
||||
ADB Interface
|
||||
-------------
|
||||
|
||||
The following classes provide a basic interface to interact with the
|
||||
Android Debug Tool (adb) and Android-based devices. It has replaced
|
||||
the now defunct DeviceManager and DeviceManagerADB classes.
|
||||
|
||||
ADBCommand
|
||||
``````````
|
||||
|
||||
.. autoclass:: mozdevice.ADBCommand
|
||||
|
||||
.. automethod:: ADBCommand.command(self, cmds, timeout=None)
|
||||
.. automethod:: ADBCommand.command_output(self, cmds, timeout=None)
|
||||
|
||||
ADBHost
|
||||
```````
|
||||
.. autoclass:: mozdevice.ADBHost
|
||||
|
||||
.. automethod:: ADBHost.command(self, cmds, timeout=None)
|
||||
.. automethod:: ADBHost.command_output(self, cmds, timeout=None)
|
||||
.. automethod:: ADBHost.start_server(self, timeout=None)
|
||||
.. automethod:: ADBHost.kill_server(self, timeout=None)
|
||||
.. automethod:: ADBHost.devices(self, timeout=None)
|
||||
|
||||
ADBDevice
|
||||
`````````
|
||||
.. autoclass:: mozdevice.ADBDevice
|
||||
|
||||
Host Command methods
|
||||
++++++++++++++++++++
|
||||
.. automethod:: ADBDevice.command(self, cmds, timeout=None)
|
||||
.. automethod:: ADBDevice.command_output(self, cmds, timeout=None)
|
||||
|
||||
Device Shell methods
|
||||
++++++++++++++++++++
|
||||
.. automethod:: ADBDevice.shell(self, cmd, env=None, cwd=None, timeout=None, root=False)
|
||||
.. automethod:: ADBDevice.shell_bool(self, cmd, env=None, cwd=None, timeout=None, root=False)
|
||||
.. automethod:: ADBDevice.shell_output(self, cmd, env=None, cwd=None, timeout=None, root=False)
|
||||
|
||||
Informational methods
|
||||
+++++++++++++++++++++
|
||||
.. automethod:: ADBDevice.clear_logcat
|
||||
.. automethod:: ADBDevice.get_battery_percentage
|
||||
.. automethod:: ADBDevice.get_info
|
||||
.. automethod:: ADBDevice.get_logcat
|
||||
.. automethod:: ADBDevice.get_prop
|
||||
.. automethod:: ADBDevice.get_state
|
||||
.. automethod:: ADBDevice.get_top_activity
|
||||
|
||||
System control methods
|
||||
++++++++++++++++++++++
|
||||
.. automethod:: ADBDevice.is_device_ready
|
||||
.. automethod:: ADBDevice.power_on
|
||||
.. automethod:: ADBDevice.reboot
|
||||
|
||||
File management methods
|
||||
+++++++++++++++++++++++
|
||||
.. automethod:: ADBDevice.chmod
|
||||
.. automethod:: ADBDevice.cp
|
||||
.. automethod:: ADBDevice.exists
|
||||
.. automethod:: ADBDevice.get_file
|
||||
.. automethod:: ADBDevice.is_dir
|
||||
.. automethod:: ADBDevice.is_file
|
||||
.. automethod:: ADBDevice.list_files
|
||||
.. automethod:: ADBDevice.mkdir
|
||||
.. automethod:: ADBDevice.mv
|
||||
.. automethod:: ADBDevice.push
|
||||
.. automethod:: ADBDevice.pull
|
||||
.. automethod:: ADBDevice.rm
|
||||
.. automethod:: ADBDevice.rmdir
|
||||
.. autoattribute:: ADBDevice.test_root
|
||||
|
||||
Process management methods
|
||||
++++++++++++++++++++++++++
|
||||
.. automethod:: ADBDevice.get_process_list
|
||||
.. automethod:: ADBDevice.kill
|
||||
.. automethod:: ADBDevice.pkill
|
||||
.. automethod:: ADBDevice.process_exist
|
||||
|
||||
Application management methods
|
||||
++++++++++++++++++++++++++++++
|
||||
.. automethod:: ADBDevice.install_app
|
||||
.. automethod:: ADBDevice.is_app_installed
|
||||
.. automethod:: ADBDevice.launch_application
|
||||
.. automethod:: ADBDevice.launch_fennec
|
||||
.. automethod:: ADBDevice.launch_geckoview_example
|
||||
.. automethod:: ADBDevice.stop_application
|
||||
.. automethod:: ADBDevice.uninstall_app
|
||||
.. automethod:: ADBDevice.update_app
|
||||
|
||||
ADBProcess
|
||||
``````````
|
||||
.. autoclass:: mozdevice.ADBProcess
|
||||
|
||||
ADBError
|
||||
````````
|
||||
.. autoexception:: mozdevice.ADBError
|
||||
|
||||
ADBRootError
|
||||
````````````
|
||||
.. autoexception:: mozdevice.ADBRootError
|
||||
|
||||
ADBTimeoutError
|
||||
```````````````
|
||||
.. autoexception:: mozdevice.ADBTimeoutError
|
||||
|
||||
:members:
|
||||
:undoc-members:
|
||||
:inherited-members:
|
||||
:show-inheritance:
|
||||
|
|
|
@ -2,11 +2,163 @@
|
|||
# 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/.
|
||||
|
||||
"""mozdevice provides a Python interface to the Android Debug Bridge (adb) for Android Devices.
|
||||
|
||||
mozdevice exports the following classes:
|
||||
|
||||
ADBProcess is a class which is used by ADBCommand to execute commands
|
||||
via subprocess.Popen.
|
||||
|
||||
ADBCommand is an internal only class which provides the basics of
|
||||
the interfaces for connecting to a device, and executing commands
|
||||
either on the host or device using ADBProcess.
|
||||
|
||||
ADBHost is a Python class used to execute commands which are not
|
||||
necessarily associated with a specific device. It is intended to be
|
||||
used directly.
|
||||
|
||||
ADBDevice is a Python class used to execute commands which will
|
||||
interact with a specific connected Android device.
|
||||
|
||||
ADBAndroid inherits directly from ADBDevice and is essentially a
|
||||
synonym for ADBDevice. It is included for backwards compatibility only
|
||||
and should not be used in new code.
|
||||
|
||||
ADBDeviceFactory is a Python function used to create instances of
|
||||
ADBDevice. ADBDeviceFactory is preferred over using ADBDevice to
|
||||
create new instances of ADBDevice since it will only create one
|
||||
instance of ADBDevice for each connected device.
|
||||
|
||||
mozdevice exports the following exceptions:
|
||||
|
||||
::
|
||||
|
||||
Exception -
|
||||
|- ADBTimeoutError
|
||||
|- ADBDeviceFactoryError
|
||||
|- ADBError
|
||||
|- ADBProcessError
|
||||
|- ADBListDevicesError
|
||||
|
||||
ADBTimeoutError is a special exception that is not part of the
|
||||
ADBError class hierarchy. It is raised when a command has failed to
|
||||
complete within the specified timeout period. Since this typically is
|
||||
due to a failure in the usb connection to the device and is not
|
||||
recoverable, it is implemented separately from ADBError so that it
|
||||
will not be caught by normal except clause handling of expected error
|
||||
conditions and is considered to be treated as a *fatal* error.
|
||||
|
||||
ADBDeviceFactoryError is also a special exception that is not part
|
||||
of the ADBError class hierarchy. It is raised by ADBDeviceFactory
|
||||
when the state of the internal ADBDevices object is in an
|
||||
inconsistent state and is considered to be a *fatal* error.
|
||||
|
||||
ADBListDevicesError is an instance of ADBError which is
|
||||
raised only by the ADBHost.devices() method to signify that
|
||||
``adb devices`` reports that the device state has no permissions and can
|
||||
not be contacted via adb.
|
||||
|
||||
ADBProcessError is an instance of ADBError which is raised when a
|
||||
process executed via ADBProcess has exited with a non-zero exit
|
||||
code. It is raised by the ADBCommand.command method and the methods
|
||||
that call it.
|
||||
|
||||
ADBError is a generic exception class to signify that some error
|
||||
condition has occured which may be handled depending on the semantics
|
||||
of the executing code.
|
||||
|
||||
Example:
|
||||
|
||||
::
|
||||
|
||||
from mozdevice import ADBHost, ADBDeviceFactory, ADBError
|
||||
|
||||
adbhost = ADBHost()
|
||||
try:
|
||||
adbhost.kill_server()
|
||||
adbhost.start_server()
|
||||
except ADBError as e:
|
||||
print('Unable to restart the adb server: {}'.format(str(e)))
|
||||
|
||||
device = ADBDeviceFactory()
|
||||
try:
|
||||
sdcard_contents = device.ls('/sdcard/') # List the contents of the sdcard on the device.
|
||||
print('sdcard contains {}'.format(' '.join(sdcard_contents))
|
||||
except ADBError as e:
|
||||
print('Unable to list the sdcard: {}'.format(str(e)))
|
||||
|
||||
Android devices use a security model based upon user permissions much
|
||||
like that used in Linux upon which it is based. The adb shell executes
|
||||
commands on the device as the shell user whose access to the files and
|
||||
directories on the device are limited by the directory and file
|
||||
permissions set in the device's file system.
|
||||
|
||||
Android apps run under their own user accounts and are restricted by
|
||||
the app's requested permissions in terms of what commands and files
|
||||
and directories they may access.
|
||||
|
||||
Like Linux, Android supports a root user who has unrestricted access
|
||||
to the command and content stored on the device.
|
||||
|
||||
Most commercially released Android devices do not allow adb to run
|
||||
commands as the root user. Typically, only Android emulators running
|
||||
certain system images, devices which have AOSP debug or engineering
|
||||
Android builds or devices which have been *rooted* can run commands as
|
||||
the root user.
|
||||
|
||||
ADBDevice supports using both unrooted and rooted devices by laddering
|
||||
its capabilities depending on the specific circumstances where it is
|
||||
used.
|
||||
|
||||
ADBDevice uses a special location on the device, called the
|
||||
*test_root*, where it places content to be tested. This can include
|
||||
binary executables and libraries, configuration files and log
|
||||
files. Since the special location /data/local/tmp is usually
|
||||
accessible by the shell user, the test_root is located at
|
||||
/data/local/tmp/test_root by default. /data/local/tmp is used instead
|
||||
of the sdcard due to recent Scoped Storage restrictions on access to
|
||||
the sdcard in Android 10 and later.
|
||||
|
||||
If the device supports running adbd as root, or if the device has been
|
||||
rooted and supports the use of the su command to run commands as root,
|
||||
ADBDevice will default to running all shell commands under the root
|
||||
user and the test_root will remain set to /data/local/tmp/test_root
|
||||
unless changed.
|
||||
|
||||
If the device does not support running shell commands under the root
|
||||
user, and a *debuggable* app is set in ADBDevice property
|
||||
run_as_package, then ADBDevice will set the test_root to
|
||||
/data/data/<app-package-name>/test_root and will run shell commands as
|
||||
the app user when accessing content located in the app's data
|
||||
directory. Content can be pushed to the app's data directory or pulled
|
||||
from the app's data directory by using the command run-as to access
|
||||
the app's data.
|
||||
|
||||
If a device does not support running commands as root and a
|
||||
*debuggable* app is not being used, command line programs can still be
|
||||
executed by pushing them to the /data/local/tmp directory which is
|
||||
accessible to the shell user.
|
||||
|
||||
If for some reason, the device is not rooted and /data/local/tmp is
|
||||
not acccessible to the shell user, then ADBDevice will fail to
|
||||
initialize and will not be useable for that device.
|
||||
|
||||
NOTE: ADBFactory will clear the contents of the test_root when it
|
||||
first creates an instance of ADBDevice.
|
||||
|
||||
When the run_as_package property is set in an ADBDevice instance, it
|
||||
will clear the contents of the current test_root before changing the
|
||||
test_root to point to the new location
|
||||
/data/data/<app-package-name>/test_root which will then be cleared of
|
||||
any existing content.
|
||||
|
||||
"""
|
||||
|
||||
from __future__ import absolute_import
|
||||
|
||||
from .adb import ADBError, ADBProcessError, ADBRootError, ADBTimeoutError
|
||||
from .adb import ADBProcess, ADBCommand, ADBHost, ADBDevice
|
||||
from .adb import ADBError, ADBProcessError, ADBTimeoutError
|
||||
from .adb import ADBProcess, ADBCommand, ADBHost, ADBDevice, ADBDeviceFactory
|
||||
from .adb_android import ADBAndroid
|
||||
|
||||
__all__ = ['ADBError', 'ADBProcessError', 'ADBRootError', 'ADBTimeoutError',
|
||||
'ADBProcess', 'ADBCommand', 'ADBHost', 'ADBDevice', 'ADBAndroid']
|
||||
__all__ = ['ADBError', 'ADBProcessError', 'ADBTimeoutError',
|
||||
'ADBProcess', 'ADBCommand', 'ADBHost', 'ADBDevice', 'ADBAndroid', 'ADBDeviceFactory']
|
||||
|
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -8,7 +8,7 @@ from __future__ import absolute_import
|
|||
from setuptools import setup
|
||||
|
||||
PACKAGE_NAME = 'mozdevice'
|
||||
PACKAGE_VERSION = '3.2.3'
|
||||
PACKAGE_VERSION = '4.0.0'
|
||||
|
||||
deps = ['mozlog >= 6.0']
|
||||
|
||||
|
|
|
@ -57,7 +57,8 @@ def mock_shell_output(monkeypatch):
|
|||
:param object monkeypatch: pytest provided fixture for mocking.
|
||||
"""
|
||||
|
||||
def shell_output_wrapper(object, cmd, env=None, cwd=None, timeout=None, root=False):
|
||||
def shell_output_wrapper(object, cmd, env=None, cwd=None, timeout=None,
|
||||
enable_run_as=False):
|
||||
"""Actual monkeypatch implementation of the shell_output method call.
|
||||
|
||||
:param object object: placeholder object representing ADBDevice
|
||||
|
@ -67,6 +68,7 @@ def mock_shell_output(monkeypatch):
|
|||
:param cwd: The directory from which to execute.
|
||||
:type cwd: str or None
|
||||
:param timeout: unused parameter tp represent timeout threshold
|
||||
:param enable_run_as: bool determining if run_as <app> is to be used
|
||||
:returns: string - string representation of a simulated call to adb
|
||||
"""
|
||||
if 'pm list package error' in cmd:
|
||||
|
@ -115,6 +117,27 @@ def mock_is_path_internal_storage(monkeypatch):
|
|||
'is_path_internal_storage', is_path_internal_storage_wrapper)
|
||||
|
||||
|
||||
@pytest.fixture(autouse=True)
|
||||
def mock_enable_run_as_for_path(monkeypatch):
|
||||
"""Monkeypatches the ADBDevice.enable_run_as_for_path(path) method.
|
||||
|
||||
Always return True
|
||||
|
||||
:param object monkeypatch: pytest provided fixture for mocking.
|
||||
"""
|
||||
|
||||
def enable_run_as_for_path_wrapper(object, path):
|
||||
"""Actual monkeypatch implementation of the enable_run_as_for_path() call.
|
||||
|
||||
:param str path: The path to test.
|
||||
:returns: boolean
|
||||
"""
|
||||
return True
|
||||
|
||||
monkeypatch.setattr(mozdevice.ADBDevice,
|
||||
'enable_run_as_for_path', enable_run_as_for_path_wrapper)
|
||||
|
||||
|
||||
@pytest.fixture(autouse=True)
|
||||
def mock_shell_bool(monkeypatch):
|
||||
"""Monkeypatches the ADBDevice.shell_bool() method call.
|
||||
|
@ -126,7 +149,8 @@ def mock_shell_bool(monkeypatch):
|
|||
:param object monkeypatch: pytest provided fixture for mocking.
|
||||
"""
|
||||
|
||||
def shell_bool_wrapper(object, cmd, env=None, cwd=None, timeout=None, root=False):
|
||||
def shell_bool_wrapper(object, cmd, env=None, cwd=None, timeout=None,
|
||||
enable_run_as=False):
|
||||
"""Actual monkeypatch implementation of the shell_bool method call.
|
||||
|
||||
:param object object: placeholder object representing ADBDevice
|
||||
|
@ -136,6 +160,7 @@ def mock_shell_bool(monkeypatch):
|
|||
:param cwd: The directory from which to execute.
|
||||
:type cwd: str or None
|
||||
:param timeout: unused parameter tp represent timeout threshold
|
||||
:param enable_run_as: bool determining if run_as <app> is to be used
|
||||
:returns: string - string representation of a simulated call to adb
|
||||
"""
|
||||
print(cmd)
|
||||
|
|
Загрузка…
Ссылка в новой задаче