From baa7ad16504a20c4af8d80bba9b172163640ca91 Mon Sep 17 00:00:00 2001 From: Marc Bonnici Date: Thu, 7 Nov 2019 09:59:48 +0000 Subject: [PATCH] devlib/AndroidTarget: Move adb specific commands into the ADB connection The `AndroidTarget` class should not depend on ADB specific commands as is is possible to use this target with other connection types e.g. ssh. Therefore move the adb specific commands into the `AdbConnection`. - `wait_for_device` and `reboot_bootloader` are now exposed in AndroidTarget as generic methods and call through to the connection method. - `adb_kill_server` is now a standalone function of the AdbConnection. --- devlib/host.py | 6 ++++++ devlib/target.py | 24 ++++-------------------- devlib/utils/android.py | 10 +++++++++- devlib/utils/ssh.py | 19 +++++++++++++++++++ doc/target.rst | 8 ++++++++ 5 files changed, 46 insertions(+), 21 deletions(-) diff --git a/devlib/host.py b/devlib/host.py index 052139b..e040b16 100644 --- a/devlib/host.py +++ b/devlib/host.py @@ -109,6 +109,12 @@ class LocalConnection(object): def cancel_running_command(self): pass + def wait_for_device(self, timeout=30): + return + + def reboot_bootloader(self, timeout=30): + raise NotImplementedError() + def _get_password(self): if self.password: return self.password diff --git a/devlib/target.py b/devlib/target.py index b583839..46a89d4 100644 --- a/devlib/target.py +++ b/devlib/target.py @@ -1530,27 +1530,11 @@ class AndroidTarget(Target): def get_logcat_monitor(self, regexps=None): return LogcatMonitor(self, regexps) - def adb_kill_server(self, timeout=30): - if not isinstance(self.conn, AdbConnection): - raise TargetStableError('Cannot issues adb command without adb connection') - adb_command(self.adb_name, 'kill-server', timeout) + def wait_for_device(self, timeout=30): + self.conn.wait_for_device() - def adb_wait_for_device(self, timeout=30): - if not isinstance(self.conn, AdbConnection): - raise TargetStableError('Cannot issues adb command without adb connection') - adb_command(self.adb_name, 'wait-for-device', timeout) - - def adb_reboot_bootloader(self, timeout=30): - if not isinstance(self.conn, AdbConnection): - raise TargetStableError('Cannot issues adb command without adb connection') - adb_command(self.adb_name, 'reboot-bootloader', timeout) - - def adb_root(self, enable=True, force=False): - if not isinstance(self.conn, AdbConnection): - raise TargetStableError('Cannot enable adb root without adb connection') - if enable and self.connected_as_root and not force: - return - self.conn.adb_root(enable=enable) + def reboot_bootloader(self, timeout=30): + self.conn.reboot_bootloader() def is_screen_on(self): output = self.execute('dumpsys power') diff --git a/devlib/utils/android.py b/devlib/utils/android.py index ca36643..70a8df0 100755 --- a/devlib/utils/android.py +++ b/devlib/utils/android.py @@ -318,7 +318,7 @@ class AdbConnection(object): AdbConnection.active_connections[self.device] -= 1 if AdbConnection.active_connections[self.device] <= 0: if self.adb_as_root: - adb_root(self.device, enable=False) + self.adb_root(self.device, enable=False) adb_disconnect(self.device) del AdbConnection.active_connections[self.device] @@ -335,6 +335,12 @@ class AdbConnection(object): raise TargetStableError(output) AdbConnection._connected_as_root[self.device] = enable + def wait_for_device(self, timeout=30): + adb_command(self.device, 'wait-for-device', timeout) + + def reboot_bootloader(self, timeout=30): + adb_command(self.device, 'reboot-bootloader', timeout) + # Again, we need to handle boards where the default output format from ls is # single column *and* boards where the default output is multi-column. # We need to do this purely because the '-1' option causes errors on older @@ -544,6 +550,8 @@ def adb_background_shell(device, command, logger.debug(full_command) return subprocess.Popen(full_command, stdout=stdout, stderr=stderr, shell=True) +def adb_kill_server(self, timeout=30): + adb_command(None, 'kill-server', timeout) def adb_list_devices(adb_server=None): output = adb_command(None, 'devices', adb_server=adb_server) diff --git a/devlib/utils/ssh.py b/devlib/utils/ssh.py index aabb19d..056ee32 100644 --- a/devlib/utils/ssh.py +++ b/devlib/utils/ssh.py @@ -299,6 +299,12 @@ class SshConnection(object): return True return False + def wait_for_device(self, timeout=30): + return + + def reboot_bootloader(self, timeout=30): + raise NotImplementedError() + def _execute_and_wait_for_prompt(self, command, timeout=None, as_root=False, strip_colors=True, log=True): self.conn.prompt(0.1) # clear an existing prompt if there is one. if as_root and self.connected_as_root: @@ -634,6 +640,19 @@ class Gem5Connection(TelnetConnection): # Delete the lock file os.remove(self.lock_file_name) + def wait_for_device(self, timeout=30): + """ + Wait for Gem5 to be ready for interation with a timeout. + """ + for _ in attempts(timeout): + if self.ready: + return + time.sleep(1) + raise TimeoutError('Gem5 is not ready for interaction') + + def reboot_bootloader(self, timeout=30): + raise NotImplementedError() + # Functions only to be called by the Gem5 connection itself def _connect_gem5_platform(self, platform): port = platform.gem5_port diff --git a/doc/target.rst b/doc/target.rst index 1d4ff76..c6dfaa8 100644 --- a/doc/target.rst +++ b/doc/target.rst @@ -647,6 +647,14 @@ Android Target Returns ``True`` if the targets screen is currently on and ``False`` otherwise. +.. method:: AndroidTarget.wait_for_target(timeout=30) + + Returns when the devices becomes available withing the given timeout + otherwise returns a ``TimeoutError``. + +.. method:: AndroidTarget.reboot_bootloader(timeout=30) + Attempts to reboot the target into it's bootloader. + .. method:: AndroidTarget.homescreen() Returns the device to its home screen.