Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / tools / telemetry / telemetry / core / forwarders / android_forwarder.py
index f2f09d3..589d2ec 100644 (file)
@@ -13,8 +13,7 @@ from telemetry.core import forwarders
 from telemetry.core import platform
 from telemetry.core import util
 from telemetry.core.backends import adb_commands
-from telemetry.util import cloud_storage
-from telemetry.util import path
+from telemetry.util import support_binaries
 
 util.AddDirToPythonPath(util.GetChromiumSrcDir(), 'build', 'android')
 try:
@@ -34,8 +33,7 @@ class AndroidForwarderFactory(forwarders.ForwarderFactory):
 
   def Create(self, port_pairs):
     if self._rndis_configurator:
-      return AndroidRndisForwarder(self._adb, self.host_ip,
-                                   self._rndis_configurator.device_iface,
+      return AndroidRndisForwarder(self._adb, self._rndis_configurator,
                                    port_pairs)
     return AndroidForwarder(self._adb, port_pairs)
 
@@ -55,29 +53,40 @@ class AndroidForwarder(forwarders.Forwarder):
   def __init__(self, adb, port_pairs):
     super(AndroidForwarder, self).__init__(port_pairs)
     self._device = adb.device()
-    forwarder.Forwarder.Map([p for p in port_pairs if p], self._device)
+    forwarder.Forwarder.Map([(p.remote_port, p.local_port)
+                             for p in port_pairs if p], self._device)
+    self._port_pairs = forwarders.PortPairs(*[
+        forwarders.PortPair(
+            p.local_port,
+            forwarder.Forwarder.DevicePortForHostPort(p.local_port))
+        if p else None for p in port_pairs])
     # TODO(tonyg): Verify that each port can connect to host.
 
   def Close(self):
     for port_pair in self._port_pairs:
       if port_pair:
-        forwarder.Forwarder.UnmapDevicePort(port_pair.local_port, self._device)
+        forwarder.Forwarder.UnmapDevicePort(port_pair.remote_port, self._device)
     super(AndroidForwarder, self).Close()
 
 
 class AndroidRndisForwarder(forwarders.Forwarder):
   """Forwards traffic using RNDIS. Assumes the device has root access."""
 
-  def __init__(self, adb, host_ip, device_iface, port_pairs):
+  def __init__(self, adb, rndis_configurator, port_pairs):
     super(AndroidRndisForwarder, self).__init__(port_pairs)
 
     self._adb = adb
-    self._device_iface = device_iface
-    self._host_ip = host_ip
+    self._rndis_configurator = rndis_configurator
+    self._device_iface = rndis_configurator.device_iface
+    self._host_ip = rndis_configurator.host_ip
     self._original_dns = None, None, None
     self._RedirectPorts(port_pairs)
     if port_pairs.dns:
       self._OverrideDns()
+      self._OverrideDefaultGateway()
+      # Need to override routing policy again since call to setifdns
+      # sometimes resets policy table
+      self._rndis_configurator.OverrideRoutingPolicy()
     # TODO(tonyg): Verify that each port can connect to host.
 
   @property
@@ -85,7 +94,9 @@ class AndroidRndisForwarder(forwarders.Forwarder):
     return self._host_ip
 
   def Close(self):
+    self._rndis_configurator.RestoreRoutingPolicy()
     self._SetDns(*self._original_dns)
+    self._RestoreDefaultGateway()
     super(AndroidRndisForwarder, self).Close()
 
   def _RedirectPorts(self, port_pairs):
@@ -103,11 +114,6 @@ class AndroidRndisForwarder(forwarders.Forwarder):
   def _OverrideDns(self):
     """Overrides DNS on device to point at the host."""
     self._original_dns = self._GetCurrentDns()
-    if not self._original_dns[0]:
-      # No default route. Install one via the host. This is needed because
-      # getaddrinfo in bionic uses routes to determine AI_ADDRCONFIG.
-      self._adb.RunShellCommand('route add default gw %s dev %s' %
-                                (self.host_ip, self._device_iface))
     self._SetDns(self._device_iface, self.host_ip, self.host_ip)
 
   def _SetDns(self, iface, dns1, dns2):
@@ -128,10 +134,10 @@ class AndroidRndisForwarder(forwarders.Forwarder):
       self._adb.device().SetProp('net.dnschange', int(dnschange) + 1)
     # Since commit 8b47b3601f82f299bb8c135af0639b72b67230e6 to frameworks/base
     # the net.dns1 properties have been replaced with explicit commands for netd
-    self._adb.RunShellCommand('ndc netd resolver setifdns %s %s %s' %
+    self._adb.RunShellCommand('netd resolver setifdns %s %s %s' %
                               (iface, dns1, dns2))
     # TODO(szym): if we know the package UID, we could setifaceforuidrange
-    self._adb.RunShellCommand('ndc netd resolver setdefaultif %s' % iface)
+    self._adb.RunShellCommand('netd resolver setdefaultif %s' % iface)
 
   def _GetCurrentDns(self):
     """Returns current gateway, dns1, and dns2."""
@@ -144,6 +150,22 @@ class AndroidRndisForwarder(forwarders.Forwarder):
       self._adb.device().GetProp('net.dns2'),
     )
 
+  def _OverrideDefaultGateway(self):
+    """Force traffic to go through RNDIS interface.
+
+    Override any default gateway route. Without this traffic may go through
+    the wrong interface.
+
+    This introduces the risk that _RestoreDefaultGateway() is not called
+    (e.g. Telemetry crashes). A power cycle or "adb reboot" is a simple
+    workaround around in that case.
+    """
+    self._adb.RunShellCommand('route add default gw %s dev %s' %
+                              (self.host_ip, self._device_iface))
+
+  def _RestoreDefaultGateway(self):
+    self._adb.RunShellCommand('netcfg %s down' % self._device_iface)
+
 
 class AndroidRndisConfigurator(object):
   """Configures a linux host to connect to an android device via RNDIS.
@@ -170,7 +192,7 @@ class AndroidRndisConfigurator(object):
     self.device_iface = None
 
     if platform.GetHostPlatform().GetOSName() == 'mac':
-      self._InstallHorndis()
+      self._InstallHorndis(platform.GetHostPlatform().GetArchName())
 
     assert self._IsRndisSupported(), 'Device does not support RNDIS.'
     self._CheckConfigureNetwork()
@@ -217,17 +239,16 @@ class AndroidRndisConfigurator(object):
 
   def _WriteProtectedFile(self, file_path, contents):
     subprocess.check_call(
-        ['sudo', 'bash', '-c', 'echo -e "%s" > %s' % (contents, file_path)])
+        ['/usr/bin/sudo', 'bash', '-c',
+         'echo -e "%s" > %s' % (contents, file_path)])
 
-  def _InstallHorndis(self):
+  def _InstallHorndis(self, arch_name):
     if 'HoRNDIS' in subprocess.check_output(['kextstat']):
       return
     logging.info('Installing HoRNDIS...')
-    pkg_path = os.path.join(
-        path.GetTelemetryDir(), 'bin', 'mac', 'HoRNDIS-rel5.pkg')
-    cloud_storage.GetIfChanged(pkg_path, bucket=cloud_storage.PUBLIC_BUCKET)
+    pkg_path = support_binaries.FindPath('HoRNDIS-rel5.pkg', arch_name, 'mac')
     subprocess.check_call(
-        ['sudo', 'installer', '-pkg', pkg_path, '-target', '/'])
+        ['/usr/bin/sudo', 'installer', '-pkg', pkg_path, '-target', '/'])
 
   def _DisableRndis(self):
     self._device.SetProp('sys.usb.config', 'adb')
@@ -374,10 +395,10 @@ doit &
         if 'Telemetry' not in subprocess.check_output(
             ['networksetup', '-listallnetworkservices']):
           subprocess.check_call(
-              ['sudo', 'networksetup',
+              ['/usr/bin/sudo', 'networksetup',
                '-createnetworkservice', 'Telemetry', host_iface])
           subprocess.check_call(
-              ['sudo', 'networksetup',
+              ['/usr/bin/sudo', 'networksetup',
                '-setmanual', 'Telemetry', '192.168.123.1', '255.255.255.0'])
       elif platform.GetHostPlatform().GetOSName() == 'linux':
         with open(self._NETWORK_INTERFACES) as f:
@@ -393,22 +414,18 @@ doit &
         if not os.path.exists(interface_conf_file):
           interface_conf_dir = os.path.dirname(interface_conf_file)
           if not interface_conf_dir:
-            subprocess.call(['sudo', '/bin/mkdir', interface_conf_dir])
-            subprocess.call(['sudo', '/bin/chmod', '755', interface_conf_dir])
+            subprocess.call(['/usr/bin/sudo', '/bin/mkdir', interface_conf_dir])
+            subprocess.call(
+                ['/usr/bin/sudo', '/bin/chmod', '755', interface_conf_dir])
           interface_conf = '\n'.join([
               '# Added by Telemetry for RNDIS forwarding.',
-              'auto %s' % host_iface,
+              'allow-hotplug %s' % host_iface,
               'iface %s inet static' % host_iface,
               '  address 192.168.123.1',
               '  netmask 255.255.255.0',
               ])
           self._WriteProtectedFile(interface_conf_file, interface_conf)
-          subprocess.check_call(['sudo', '/etc/init.d/networking', 'restart'])
-        if 'stop/waiting' not in subprocess.check_output(
-            ['status', 'network-manager']):
-          logging.info('Stopping network-manager...')
-          subprocess.call(['sudo', 'stop', 'network-manager'])
-
+          subprocess.check_call(['/usr/bin/sudo', 'ifup', host_iface])
       logging.info('Waiting for RNDIS connectivity...')
       util.WaitFor(HasHostAddress, 10)
 
@@ -456,13 +473,30 @@ doit &
       return subprocess.call(['ping', '-q', '-c1', '-W1', self._device_ip],
                              stdout=devnull) == 0
 
+  def OverrideRoutingPolicy(self):
+    """Override any routing policy that could prevent
+    packets from reaching the rndis interface
+    """
+    policies = self._device.RunShellCommand('ip rule')
+    if len(policies) > 1 and not ('lookup main' in policies[1]):
+      self._device.RunShellCommand('ip rule add prio 1 from all table main')
+      self._device.RunShellCommand('ip route flush cache')
+
+  def RestoreRoutingPolicy(self):
+    policies = self._device.RunShellCommand('ip rule')
+    if len(policies) > 1 and re.match("^1:.*lookup main", policies[1]):
+      self._device.RunShellCommand('ip rule del prio 1')
+      self._device.RunShellCommand('ip route flush cache')
+
   def _CheckConfigureNetwork(self):
     """Enables RNDIS and configures it, retrying until we have connectivity."""
     force = False
     for _ in range(3):
       device_iface, host_iface = self._CheckEnableRndis(force)
       self._ConfigureNetwork(device_iface, host_iface)
+      self.OverrideRoutingPolicy()
       if self._TestConnectivity():
         return
       force = True
+    self.RestoreRoutingPolicy()
     raise Exception('No connectivity, giving up.')