Index: build/android/pylib/device/wifi_manager.py |
diff --git a/build/android/pylib/device/wifi_manager.py b/build/android/pylib/device/wifi_manager.py |
new file mode 100644 |
index 0000000000000000000000000000000000000000..4ab4e64db2ebe5db805eff3de7544bb1e0f19b3b |
--- /dev/null |
+++ b/build/android/pylib/device/wifi_manager.py |
@@ -0,0 +1,210 @@ |
+# Copyright (c) 2013 The Chromium Authors. All rights reserved. |
+# Use of this source code is governed by a BSD-style license that can be |
+# found in the LICENSE file. |
+ |
+"""Manages WiFi connection""" |
+ |
+import logging |
+import os |
+import sys |
+import time |
+ |
+sys.path.append(os.path.join(sys.path[0], '..', '..', 'build','android')) |
+from pylib import constants |
+from pylib.device import device_utils |
+from pylib.device import device_errors |
+from pylib.utils import logging_utils |
+from pylib.utils import timeout_retry |
+ |
+_ACTIVITY_RESULT_OK = -1 |
+_STR_TO_BOOL = {'true': True, 'false': False} |
+ |
+ |
+class WiFiManager(object): |
+ """A wrapper around WifiUtil.apk to manage wifi settings. |
+ |
+ WifiUtil is available at build/android/apks/WifiUtil.apk, for more |
navabi
2015/06/18 01:04:57
changed this.
|
+ information, see the README in build/android/apks/ |
+ """ |
+ |
+ def __init__(self, device): |
+ """ |
+ Args: |
+ device: A DeviceUtils object to work with. |
+ """ |
+ self._device = device |
+ self._apk_installed = False |
+ |
+ def IsWifiEnabled(self): |
+ """Checks whether or not wifi is enabled on the device.""" |
+ return self._WifiUtilMethod('isWifiEnabled') |
+ |
+ def IsInternetReachable(self, destination='www.google.com', count=2, |
+ timeout=5): |
+ """Checks whether or not internet is reachable from the device. |
+ |
+ Args: |
+ destination: A string with a destination to check for connectivity. |
+ count: Number of ping packets to send. |
+ timeout: Number of seconds to wait for packets to return. |
+ |
+ Return: |
+ True if pings to the destination succeeded, False otherwise. |
+ """ |
+ try: |
+ self._device.RunShellCommand( |
+ ['ping', '-w', str(timeout), '-c', str(count), destination], |
+ check_return=True) |
+ return True |
+ except device_errors.AdbShellCommandFailedError: |
+ return False |
+ |
+ def EnableWifi(self): |
+ """Enables wifi on the device.""" |
+ if not self._WifiUtilMethod('enableWifi'): |
+ raise device_errors.CommandFailedError( |
+ 'Failed to enable wifi on the device') |
+ |
+ def DisableWifi(self): |
+ """Disables wifi on the device.""" |
+ if not self._WifiUtilMethod('disableWifi'): |
+ raise device_errors.CommandFailedError( |
+ 'Failed to disable wifi on the device') |
+ |
+ def AddOpenNetwork(self, ssid): |
+ """Adds an open wifi network configuarion. |
+ |
+ Args: |
+ ssid: A string with the SSID of a wifi network. |
+ |
+ Return: |
+ The network ID of the new network configuarion as an integer. |
+ """ |
+ return self._WifiUtilMethod('addOpenNetwork', {'ssid': ssid}, type_fn=int) |
+ |
+ def AddSecureNetwork(self, ssid, password_file): |
+ """Adds an wpa/psk wifi network configuarion. |
+ |
+ Args: |
+ ssid: A string with the SSID of a wifi network. |
+ password_file: A file containing the password for the wifi |
+ |
+ Return: |
+ The network ID of the new network configuarion as an integer. |
+ """ |
+ with open(password_file) as f: |
+ password = f.read().rstrip() |
+ with logging_utils.SuppressLogging(): |
+ result = self._WifiUtilMethod('addWpaPskNetwork', |
+ {'ssid': ssid, 'psk': password}, type_fn=int) |
+ return result |
+ |
+ def AssociateNetwork(self, net_id): |
+ """Associates (connects) to a previously configured network. |
+ |
+ Args: |
+ net_id: An integer with the network ID to associate with. |
+ """ |
+ if not self._WifiUtilMethod('associateNetwork', {'id': net_id}): |
+ raise device_errors.CommandFailedError( |
+ 'Failed to connect to network id %d.' % net_id) |
+ |
+ def SaveConfiguration(self): |
+ """Persists the current configured networks. |
+ |
+ Note: It is possible for this method to change the network IDs of existing |
+ networks. |
+ """ |
+ if not self._WifiUtilMethod('saveConfiguration'): |
+ raise device_errors.CommandFailedError( |
+ 'Failed to save the current network configuration.') |
+ |
+ def ConnectToGoogleGuest(self): |
+ self.ConnectToWifi('GoogleGuest') |
+ |
+ def ConnectToWifi(self, ssid, password_file=None): |
+ """Enables wifi on the device and connects to specified ssid.""" |
+ def wifi_enabled(): |
+ return self.IsWifiEnabled() |
+ |
+ def internet_reachable(): |
+ return self.IsInternetReachable() |
+ |
+ logging.info('Enabling wifi') |
+ self.EnableWifi() |
+ if not timeout_retry.WaitFor(wifi_enabled, max_tries=6): |
+ raise device_errors.CommandFailedError( |
+ 'Timed out waiting for wifi to be enabled') |
+ |
+ logging.info('Adding %s', ssid) |
+ if password_file: |
+ net_id = self.AddSecureNetwork(ssid, password_file) |
+ else: |
+ net_id = self.AddOpenNetwork(ssid) |
+ logging.info('Connecting to %s', ssid) |
+ self.AssociateNetwork(net_id) |
+ logging.info('Saving wifi configuration') |
+ self.SaveConfiguration() |
+ |
+ if not timeout_retry.WaitFor(internet_reachable, max_tries=6): |
+ raise device_errors.CommandFailedError( |
+ 'Timed out waiting for Internet connectivity: www.google.com is not' |
+ ' responding.') |
+ |
+ def _WifiUtilMethod(self, method, args=None, type_fn=None): |
navabi
2015/06/18 01:04:57
and I changed the name of the type_fn argument. It
perezju
2015/06/18 09:53:33
nit: maybe call it "return_as"? looks a bit nicer
|
+ """Run a WifiUtil.apk instrumentation and return its result. |
+ |
+ Maps each invocation to an instrumentation command of the form: |
+ |
+ am instrument -e method <METHOD> -e <KEY1> <VAL1> ... \ |
+ -w com.android.tradefed.utils.wifi/.WifiUtil |
+ |
+ Args: |
+ method: A string with the name of the WifiUtil.apk method to invoke. |
+ args: A dictionary with extra arguments for the method, values will be |
+ implicitly casted to strings. |
+ type_fn: A function called to interpret the result of the method. The |
+ default expects and returns a boolean value. |
+ |
+ Return: |
+ The result obtained from INSTRUMENTATION_RESULT: result=[value], as |
+ interpreted by the type_fn function. |
+ |
+ Raises: |
+ AssertionError if the instrumentation call is not successful, or the |
+ instrumentation result is missing. |
+ """ |
+ if not self._apk_installed: |
+ self._InstallWifiUtilApk() |
+ |
+ extras = {'method': method} |
+ if args is not None: |
+ extras.update((k, str(v)) for k, v in args.iteritems()) |
+ if type_fn is None: |
+ type_fn = lambda r: _STR_TO_BOOL[r] |
+ |
+ output = self._device.StartInstrumentation( |
+ 'com.android.tradefed.utils.wifi/.WifiUtil', |
+ extras=extras) |
+ results = {} |
+ code = None |
+ for line in output: |
+ section, content = line.split(': ', 1) |
+ if section == 'INSTRUMENTATION_RESULT': |
+ key, value = content.split('=', 1) |
+ results[key] = value |
+ elif section == 'INSTRUMENTATION_CODE': |
+ code = int(content) |
+ if code != _ACTIVITY_RESULT_OK or 'result' not in results: |
+ raise device_errors.CommandFailedError('WifiUtil method %s failed (%s): ' |
+ '%s' % (method, code, results)) |
+ |
+ return type_fn(results['result']) |
+ |
+ def _InstallWifiUtilApk(self): |
+ """Install or update the WifiUtil.apk on the device.""" |
+ logging.info('Installing WifiUtil APK') |
+ wifi_util_apk_file_path = os.path.join( |
+ constants.DIR_SOURCE_ROOT, 'build', 'android', 'apks', 'WifiUtil.apk') |
+ self._device.Install(wifi_util_apk_file_path) |
+ self._apk_installed = True |