| Index: build/android/pylib/forwarder.py | 
| diff --git a/build/android/pylib/forwarder.py b/build/android/pylib/forwarder.py | 
| index e15de872543a081012dc017e04dba1f2ef195dbc..40a5d36fae3305753d68b6bffc46cfb97bc2b355 100644 | 
| --- a/build/android/pylib/forwarder.py | 
| +++ b/build/android/pylib/forwarder.py | 
| @@ -12,6 +12,7 @@ import time | 
| import android_commands | 
| import cmd_helper | 
| import constants | 
| +import ports | 
|  | 
| from pylib import pexpect | 
|  | 
| @@ -23,6 +24,10 @@ def _MakeBinaryPath(build_type, binary_name): | 
| class Forwarder(object): | 
| """Thread-safe class to manage port forwards from the device to the host.""" | 
|  | 
| +  # Unix Abstract socket path: | 
| +  _DEVICE_ADB_CONTROL_PORT = 'chrome_device_forwarder' | 
| +  _TIMEOUT_SECS = 30 | 
| + | 
| _DEVICE_FORWARDER_FOLDER = (constants.TEST_EXECUTABLE_DIR + | 
| '/forwarder/') | 
| _DEVICE_FORWARDER_PATH = (constants.TEST_EXECUTABLE_DIR + | 
| @@ -65,16 +70,19 @@ class Forwarder(object): | 
| """ | 
| with self._lock: | 
| self._InitDeviceLocked(tool) | 
| +      self._InitHostLocked() | 
| host_name = '127.0.0.1' | 
| redirection_commands = [ | 
| -          ['--serial-id=' + self._adb.Adb().GetSerialNumber(), '--map', | 
| -           str(device), str(host)] for device, host in port_pairs] | 
| +          '%d:%d:%d:%s' % (self._host_adb_control_port, device, host, | 
| +                           host_name) for device, host in port_pairs] | 
| +      logging.info('Command format: <ADB port>:<Device port>' + | 
| +                   '[:<Forward to port>:<Forward to address>]') | 
| logging.info('Forwarding using commands: %s', redirection_commands) | 
|  | 
| for redirection_command in redirection_commands: | 
| try: | 
| (exit_code, output) = cmd_helper.GetCmdStatusAndOutput( | 
| -              [self._host_forwarder_path] + redirection_command) | 
| +              [self._host_forwarder_path, redirection_command]) | 
| except OSError as e: | 
| if e.errno == 2: | 
| raise Exception('Unable to start host forwarder. Make sure you have' | 
| @@ -93,6 +101,19 @@ class Forwarder(object): | 
| logging.info('Forwarding device port: %d to host port: %d.', | 
| device_port, host_port) | 
|  | 
| +  def _InitHostLocked(self): | 
| +    """Initializes the host forwarder process (only once).""" | 
| +    if self._host_adb_control_port: | 
| +      return | 
| +    self._host_adb_control_port = ports.AllocateTestServerPort() | 
| +    if not self._host_adb_control_port: | 
| +      raise Exception('Failed to allocate a TCP port in the host machine.') | 
| +    if cmd_helper.RunCmd( | 
| +        ['adb', '-s', self._adb._adb.GetSerialNumber(), 'forward', | 
| +         'tcp:%s' % self._host_adb_control_port, | 
| +         'localabstract:%s' % Forwarder._DEVICE_ADB_CONTROL_PORT]) != 0: | 
| +      raise Exception('Error while running adb forward.') | 
| + | 
| def _InitDeviceLocked(self, tool): | 
| """Initializes the device forwarder process (only once).""" | 
| if self._device_initialized: | 
| @@ -101,8 +122,9 @@ class Forwarder(object): | 
| self._device_forwarder_path_on_host, | 
| Forwarder._DEVICE_FORWARDER_FOLDER) | 
| (exit_code, output) = self._adb.GetShellCommandStatusAndOutput( | 
| -        '%s %s %s' % (Forwarder._LD_LIBRARY_PATH, tool.GetUtilWrapper(), | 
| -                      Forwarder._DEVICE_FORWARDER_PATH)) | 
| +        '%s %s %s %s' % (Forwarder._LD_LIBRARY_PATH, tool.GetUtilWrapper(), | 
| +                         Forwarder._DEVICE_FORWARDER_PATH, | 
| +                         Forwarder._DEVICE_ADB_CONTROL_PORT)) | 
| if exit_code != 0: | 
| raise Exception( | 
| 'Failed to start device forwarder:\n%s' % '\n'.join(output)) | 
| @@ -115,11 +137,11 @@ class Forwarder(object): | 
| device_port: A previously forwarded port (through Run()). | 
| """ | 
| with self._lock: | 
| -      redirection_command = [ | 
| -          '--serial-id=' + self._adb.Adb().GetSerialNumber(), '--unmap', | 
| -          str(device_port)] | 
| +      # Please note the minus sign below. | 
| +      redirection_command = '%d:-%d' % ( | 
| +          self._host_adb_control_port, device_port) | 
| (exit_code, output) = cmd_helper.GetCmdStatusAndOutput( | 
| -          [self._host_forwarder_path] + redirection_command) | 
| +          [self._host_forwarder_path, redirection_command]) | 
| if exit_code != 0: | 
| raise Exception('%s exited with %d:\n%s' % ( | 
| self._host_forwarder_path, exit_code, '\n'.join(output))) | 
| @@ -135,7 +157,7 @@ class Forwarder(object): | 
| host_forwarder_path = _MakeBinaryPath(build_type, 'host_forwarder') | 
| assert os.path.exists(host_forwarder_path), 'Please build forwarder2' | 
| (exit_code, output) = cmd_helper.GetCmdStatusAndOutput( | 
| -        [host_forwarder_path, '--kill-server']) | 
| +        [host_forwarder_path, 'kill-server']) | 
| if exit_code != 0: | 
| (exit_code, output) = cmd_helper.GetCmdStatusAndOutput( | 
| ['pkill', 'host_forwarder']) | 
| @@ -156,8 +178,8 @@ class Forwarder(object): | 
| if not adb.FileExistsOnDevice(Forwarder._DEVICE_FORWARDER_PATH): | 
| return | 
| (exit_code, output) = adb.GetShellCommandStatusAndOutput( | 
| -        '%s %s --kill-server' % (tool.GetUtilWrapper(), | 
| -                                 Forwarder._DEVICE_FORWARDER_PATH)) | 
| +        '%s %s kill-server' % (tool.GetUtilWrapper(), | 
| +                               Forwarder._DEVICE_FORWARDER_PATH)) | 
| # TODO(pliard): Remove the following call to KillAllBlocking() when we are | 
| # sure that the old version of device_forwarder (not supporting | 
| # 'kill-server') is not running on the bots anymore. | 
|  |