def create_ssh_tunnel(self, port, local_port=None): """Create an ssh tunnel from local_port to port. This securely forwards traffic from local_port on this machine to the remote SSH host at port. Args: port: remote port on the host. local_port: local forwarding port, or None to pick an available port. Returns: the created tunnel process. """ if local_port is None: local_port = host_utils.get_available_host_port() else: for tunnel in self._tunnels: if tunnel.remote_port == port: return tunnel.local_port extra_flags = { '-n': None, # Read from /dev/null for stdin '-N': None, # Do not execute a remote command '-q': None, # Suppress warnings and diagnostic commands '-L': '%d:localhost:%d' % (local_port, port), } extra_options = dict() if self._master_ssh_proc: extra_options['ControlPath'] = self.socket_path tunnel_cmd = self._formatter.format_ssh_local_command( self._settings, extra_flags=extra_flags, extra_options=extra_options) self.log.debug('Full tunnel command: %s', tunnel_cmd) # Exec the ssh process directly so that when we deliver signals, we # deliver them straight to the child process. tunnel_proc = job.run_async(tunnel_cmd) self.log.debug( 'Started ssh tunnel, local = %d' ' remote = %d, pid = %d', local_port, port, tunnel_proc.pid) self._tunnels.append(_Tunnel(local_port, port, tunnel_proc)) return local_port
def get_droid(self, handle_event=True): """Create an sl4n connection to the device. Return the connection handler 'droid'. By default, another connection on the same session is made for EventDispatcher, and the dispatcher is returned to the caller as well. If sl4n server is not started on the device, try to start it. Args: handle_event: True if this droid session will need to handle events. Returns: droid: Android object useds to communicate with sl4n on the android device. ed: An optional EventDispatcher to organize events for this droid. Examples: Don't need event handling: >>> ad = NativeAndroidDevice() >>> droid = ad.get_droid(False) Need event handling: >>> ad = NativeAndroidDevice() >>> droid, ed = ad.get_droid() """ if not self.h_port or not host_utils.is_port_available(self.h_port): self.h_port = host_utils.get_available_host_port() self.adb.tcp_forward(self.h_port, self.d_port) pid = self.adb.shell("pidof -s sl4n", ignore_status=True) while (pid): self.adb.shell("kill {}".format(pid)) pid = self.adb.shell("pidof -s sl4n", ignore_status=True) call( ["adb -s " + self.serial + " shell sh -c \"/system/bin/sl4n\" &"], shell=True) try: time.sleep(3) droid = self.start_new_session() except: droid = self.start_new_session() return droid
def get_droid(self, handle_event=True): """Create an sl4a connection to the device. Return the connection handler 'droid'. By default, another connection on the same session is made for EventDispatcher, and the dispatcher is returned to the caller as well. If sl4a server is not started on the device, try to start it. Args: handle_event: True if this droid session will need to handle events. Returns: droid: Android object used to communicate with sl4a on the android device. ed: An optional EventDispatcher to organize events for this droid. Examples: Don't need event handling: >>> ad = AndroidDevice() >>> droid = ad.get_droid(False) Need event handling: >>> ad = AndroidDevice() >>> droid, ed = ad.get_droid() """ forward_success = False last_error = None for _ in range(PORT_RETRY_COUNT): if not self.h_port or not host_utils.is_port_available( self.h_port): self.h_port = host_utils.get_available_host_port() try: self.adb.tcp_forward(self.h_port, self.d_port) forward_success = True break except adb.AdbError as e: last_error = e pass if not forward_success: self.log.error(last_error) raise last_error for i in range(PORT_RETRY_COUNT): try: if self.is_sl4a_running(): self.log.info("Stop sl4a apk") self.stop_sl4a() time.sleep(15) self.log.info("Start sl4a apk") self.start_sl4a() time.sleep(5) droid = self.start_new_session() if handle_event: ed = self.get_dispatcher(droid) return droid, ed return droid except Exception as e: self.log.warning("get_droid with exception: %s", e) if i == PORT_RETRY_COUNT - 1: raise