def connect(self): # NOQA pylint: disable=R0912 iteration_number = 0 max_iterations = self.ready_timeout / self.delay available = False self.logger.debug('Polling for device {}...'.format(self.adb_name)) while iteration_number < max_iterations: devices = adb_list_devices() if self.adb_name: for device in devices: if device.name == self.adb_name and device.status != 'offline': available = True else: # adb_name not set if len(devices) == 1: available = True elif len(devices) > 1: raise DeviceError( 'More than one device is connected and adb_name is not set.' ) if available: break else: time.sleep(self.delay) iteration_number += 1 else: raise DeviceError('Could not boot {} ({}).'.format( self.name, self.adb_name)) while iteration_number < max_iterations: available = (1 == int('0' + adb_shell(self.adb_name, 'getprop sys.boot_completed', timeout=self.default_timeout))) if available: break else: time.sleep(self.delay) iteration_number += 1 else: raise DeviceError('Could not boot {} ({}).'.format( self.name, self.adb_name)) if self._just_rebooted: self.logger.debug('Waiting for boot to complete...') # On some devices, adb connection gets reset some time after booting. # This causes errors during execution. To prevent this, open a shell # session and wait for it to be killed. Once its killed, give adb # enough time to restart, and then the device should be ready. # TODO: This is more of a work-around rather than an actual solution. # Need to figure out what is going on the "proper" way of handling it. try: adb_shell(self.adb_name, '', timeout=20) time.sleep(5) # give adb time to re-initialize except TimeoutError: pass # timed out waiting for the session to be killed -- assume not going to be. self.logger.debug('Boot completed.') self._just_rebooted = False self._is_ready = True
def connect(self): # NOQA pylint: disable=R0912 iteration_number = 0 max_iterations = self.ready_timeout / self.delay available = False self.logger.debug("Polling for device {}...".format(self.adb_name)) while iteration_number < max_iterations: devices = adb_list_devices() if self.adb_name: for device in devices: if device.name == self.adb_name and device.status != "offline": available = True else: # adb_name not set if len(devices) == 1: available = True elif len(devices) > 1: raise DeviceError("More than one device is connected and adb_name is not set.") if available: break else: time.sleep(self.delay) iteration_number += 1 else: raise DeviceError("Could not boot {} ({}).".format(self.name, self.adb_name)) while iteration_number < max_iterations: available = ( int("0" + (adb_shell(self.adb_name, "getprop sys.boot_completed", timeout=self.default_timeout))) == 1 ) if available: break else: time.sleep(self.delay) iteration_number += 1 else: raise DeviceError("Could not boot {} ({}).".format(self.name, self.adb_name)) if self._just_rebooted: self.logger.debug("Waiting for boot to complete...") # On some devices, adb connection gets reset some time after booting. # This causes errors during execution. To prevent this, open a shell # session and wait for it to be killed. Once its killed, give adb # enough time to restart, and then the device should be ready. # TODO: This is more of a work-around rather than an actual solution. # Need to figure out what is going on the "proper" way of handling it. try: adb_shell(self.adb_name, "", timeout=20) time.sleep(5) # give adb time to re-initialize except TimeoutError: pass # timed out waiting for the session to be killed -- assume not going to be. self.logger.debug("Boot completed.") self._just_rebooted = False self._is_ready = True
def file_exists(self, filepath): self._check_ready() output = adb_shell( self.adb_name, 'if [ -e \'{}\' ]; then echo 1; else echo 0; fi'.format(filepath), timeout=self.default_timeout) return bool(int(output))
def execute(self, command, timeout=default_timeout, check_exit_code=True, background=False, as_root=False, busybox=False, **kwargs): """ Execute the specified command on the device using adb. Parameters: :param command: The command to be executed. It should appear exactly as if you were typing it into a shell. :param timeout: Time, in seconds, to wait for adb to return before aborting and raising an error. Defaults to ``AndroidDevice.default_timeout``. :param check_exit_code: If ``True``, the return code of the command on the Device will be check and exception will be raised if it is not 0. Defaults to ``True``. :param background: If ``True``, will execute adb in a subprocess, and will return immediately, not waiting for adb to return. Defaults to ``False`` :param busybox: If ``True``, will use busybox to execute the command. Defaults to ``False``. Added in version 2.1.3 .. note:: The device must be rooted to be able to use busybox. :param as_root: If ``True``, will attempt to execute command in privileged mode. The device must be rooted, otherwise an error will be raised. Defaults to ``False``. Added in version 2.1.3 :returns: If ``background`` parameter is set to ``True``, the subprocess object will be returned; otherwise, the contents of STDOUT from the device will be returned. :raises: DeviceError if adb timed out or if the command returned non-zero exit code on the device, or if attempting to execute a command in privileged mode on an unrooted device. """ self._check_ready() if as_root and not self.is_rooted: raise DeviceError( 'Attempting to execute "{}" as root on unrooted device.'. format(command)) if busybox: if not self.is_rooted: DeviceError('Attempting to execute "{}" with busybox. '.format( command) + 'Busybox can only be deployed to rooted devices.') command = ' '.join([self.busybox, command]) if background: return adb_background_shell(self.adb_name, command, as_root=as_root) else: return adb_shell(self.adb_name, command, timeout, check_exit_code, as_root)
def clear_logcat(self): """Clear (flush) logcat log.""" if self._logcat_poller: return self._logcat_poller.clear_buffer() else: return adb_shell(self.adb_name, 'logcat -c', timeout=self.default_timeout)
def file_exists(self, filepath): self._check_ready() output = adb_shell(self.adb_name, 'if [ -e \'{}\' ]; then echo 1; else echo 0; fi'.format(filepath), timeout=self.default_timeout) if int(output): return True else: return False
def execute( self, command, timeout=default_timeout, check_exit_code=True, background=False, as_root=False, busybox=False, **kwargs ): """ Execute the specified command on the device using adb. Parameters: :param command: The command to be executed. It should appear exactly as if you were typing it into a shell. :param timeout: Time, in seconds, to wait for adb to return before aborting and raising an error. Defaults to ``AndroidDevice.default_timeout``. :param check_exit_code: If ``True``, the return code of the command on the Device will be check and exception will be raised if it is not 0. Defaults to ``True``. :param background: If ``True``, will execute adb in a subprocess, and will return immediately, not waiting for adb to return. Defaults to ``False`` :param busybox: If ``True``, will use busybox to execute the command. Defaults to ``False``. Added in version 2.1.3 .. note:: The device must be rooted to be able to use busybox. :param as_root: If ``True``, will attempt to execute command in privileged mode. The device must be rooted, otherwise an error will be raised. Defaults to ``False``. Added in version 2.1.3 :returns: If ``background`` parameter is set to ``True``, the subprocess object will be returned; otherwise, the contents of STDOUT from the device will be returned. :raises: DeviceError if adb timed out or if the command returned non-zero exit code on the device, or if attempting to execute a command in privileged mode on an unrooted device. """ self._check_ready() if as_root and not self.is_rooted: raise DeviceError('Attempting to execute "{}" as root on unrooted device.'.format(command)) if busybox: if not self.is_rooted: DeviceError( 'Attempting to execute "{}" with busybox. '.format(command) + "Busybox can only be deployed to rooted devices." ) command = " ".join([self.busybox, command]) if background: return adb_background_shell(self.adb_name, command, as_root=as_root) else: return adb_shell(self.adb_name, command, timeout, check_exit_code, as_root)
def connect(self): # NOQA pylint: disable=R0912 super(Note3Device, self).connect() if self._just_rebooted: self.logger.debug('Waiting for boot to complete...') # On the Note 3, adb connection gets reset some time after booting. # This causes errors during execution. To prevent this, open a shell # session and wait for it to be killed. Once its killed, give adb # enough time to restart, and then the device should be ready. try: adb_shell(self.adb_name, '', timeout=20) # pylint: disable=no-member time.sleep(5) # give adb time to re-initialize except TimeoutError: pass # timed out waiting for the session to be killed -- assume not going to be. self.logger.debug('Boot completed.') self._just_rebooted = False # Swipe upwards to unlock the screen. time.sleep(self.long_delay) self.execute('input touchscreen swipe 540 1600 560 800 ')
def disable_selinux(self): # This may be invoked from intialize() so we can't use execute() or the # standard API for doing this. api_level = int(adb_shell(self.adb_name, "getprop ro.build.version.sdk", timeout=self.default_timeout).strip()) # SELinux was added in Android 4.3 (API level 18). Trying to # 'getenforce' in earlier versions will produce an error. if api_level >= 18: se_status = self.execute("getenforce", as_root=True).strip() if se_status == "Enforcing": self.execute("setenforce 0", as_root=True)
def is_network_connected(self): network_host = 'www.google.com' self.logger.debug('Checking for internet connectivity.') output = adb_shell(self.adb_name, 'ping -q -w 1 -c 1 {}'.format(network_host), timeout=self.default_timeout) if not 'unknown host' in output: self.logger.debug('Found network host {}'.format(network_host)) return True else: self.logger.debug('Cannot find network host {}'.format(network_host)) return False
def is_rooted(self): if self._is_rooted is None: try: result = adb_shell(self.adb_name, 'su', timeout=1) if 'not found' in result: self._is_rooted = False else: self._is_rooted = True except TimeoutError: self._is_rooted = True except DeviceError: self._is_rooted = False return self._is_rooted
def disable_selinux(self): # This may be invoked from intialize() so we can't use execute() or the # standard API for doing this. api_level = int( adb_shell(self.adb_name, 'getprop ro.build.version.sdk', timeout=self.default_timeout).strip()) # SELinux was added in Android 4.3 (API level 18). Trying to # 'getenforce' in earlier versions will produce an error. if api_level >= 18: se_status = self.execute('getenforce', as_root=True).strip() if se_status == 'Enforcing': self.execute('setenforce 0', as_root=True)
def ping(self): try: # May be triggered inside initialize() adb_shell(self.adb_name, 'ls /', timeout=10) except (TimeoutError, CalledProcessError): raise DeviceNotRespondingError(self.adb_name or self.name)
def clear_buffer(self): self.logger.debug('Clearing logcat buffer.') with self.lock: adb_shell(self.adb_device, 'logcat -c', timeout=self.timeout) with open(self.buffer_file, 'w') as _: # NOQA pass
def file_exists(self, filepath): self._check_ready() output = adb_shell( self.adb_name, "if [ -e '{}' ]; then echo 1; else echo 0; fi".format(filepath), timeout=self.default_timeout ) return bool(int(output))
def delete_file(self, filepath, as_root=False): # pylint: disable=W0221 self._check_ready() adb_shell(self.adb_name, "rm '{}'".format(filepath), as_root=as_root, timeout=self.default_timeout)
def clear_buffer(self): self.logger.debug("Clearing logcat buffer.") with self.lock: adb_shell(self.adb_device, "logcat -c", timeout=self.timeout) with open(self.buffer_file, "w") as _: # NOQA pass