Merge "[Tests]Integrate UI interaction for R2 provisioning."
diff --git a/acts/framework/acts/controllers/iperf_server.py b/acts/framework/acts/controllers/iperf_server.py
index 07eb459..7576d86 100755
--- a/acts/framework/acts/controllers/iperf_server.py
+++ b/acts/framework/acts/controllers/iperf_server.py
@@ -55,8 +55,9 @@
         elif type(c) is dict and 'ssh_config' in c and 'port' in c:
             results.append(IPerfServerOverSsh(c['ssh_config'], c['port']))
         else:
-            raise ValueError('Config entry %s in %s is not a valid IPerfServer '
-                             'config.' % (repr(c), configs))
+            raise ValueError(
+                'Config entry %s in %s is not a valid IPerfServer '
+                'config.' % (repr(c), configs))
     return results
 
 
@@ -193,8 +194,7 @@
         instantaneous_rates = self.instantaneous_rates[iperf_ignored_interval:
                                                        -1]
         avg_rate = math.fsum(instantaneous_rates) / len(instantaneous_rates)
-        sqd_deviations = [(rate - avg_rate) ** 2 for rate in
-                          instantaneous_rates]
+        sqd_deviations = [(rate - avg_rate)**2 for rate in instantaneous_rates]
         std_dev = math.sqrt(
             math.fsum(sqd_deviations) / (len(sqd_deviations) - 1))
         return std_dev
@@ -252,8 +252,8 @@
 
         with IPerfServerBase.__log_file_lock:
             tags = [tag, IPerfServerBase.__log_file_counter]
-            out_file_name = 'IPerfServer,%s.log' % (','.join(
-                [str(x) for x in tags if x != '' and x is not None]))
+            out_file_name = 'IPerfServer,%s.log' % (
+                ','.join([str(x) for x in tags if x != '' and x is not None]))
             IPerfServerBase.__log_file_counter += 1
 
         file_path = os.path.join(out_dir, out_file_name)
@@ -379,14 +379,15 @@
             return
 
         self._ssh_session.run_async('kill -9 {}'.format(str(self._iperf_pid)))
-        iperf_result = self._ssh_session.run(
-            'cat {}'.format(self._get_remote_log_path()))
+        iperf_result = self._ssh_session.run('cat {}'.format(
+            self._get_remote_log_path()))
 
         log_file = self._get_full_file_path(self._current_tag)
         with open(log_file, 'w') as f:
             f.write(iperf_result.stdout)
 
-        self._ssh_session.run_async('rm {}'.format(self._get_remote_log_path()))
+        self._ssh_session.run_async('rm {}'.format(
+            self._get_remote_log_path()))
         self._iperf_pid = None
         return log_file
 
@@ -412,7 +413,8 @@
         _AndroidDeviceBridge.android_devices = {}
 
 
-event_bus.register_subscription(_AndroidDeviceBridge.on_test_begin.subscription)
+event_bus.register_subscription(
+    _AndroidDeviceBridge.on_test_begin.subscription)
 event_bus.register_subscription(_AndroidDeviceBridge.on_test_end.subscription)
 
 
@@ -472,6 +474,8 @@
                 cmd=self._iperf_command,
                 extra_flags=extra_args,
                 log_file=self._get_device_log_path()))
+        self._iperf_process_adb_pid = self._android_device.adb.shell(
+            'pgrep iperf3 -n')
 
         self._current_tag = tag
 
@@ -486,15 +490,24 @@
 
         job.run('kill -9 {}'.format(self._iperf_process.pid))
 
-        iperf_result = self._android_device.adb.shell(
-            'cat {}'.format(self._get_device_log_path()))
+        #TODO(markdr): update with definitive kill method
+        while True:
+            iperf_process_list = self._android_device.adb.shell('pgrep iperf3')
+            if iperf_process_list.find(self._iperf_process_adb_pid) == -1:
+                break
+            else:
+                self._android_device.adb.shell("kill -9 {}".format(
+                    self._iperf_process_adb_pid))
+
+        iperf_result = self._android_device.adb.shell('cat {}'.format(
+            self._get_device_log_path()))
 
         log_file = self._get_full_file_path(self._current_tag)
         with open(log_file, 'w') as f:
             f.write(iperf_result)
 
-        self._android_device.adb.shell(
-            'rm {}'.format(self._get_device_log_path()))
+        self._android_device.adb.shell('rm {}'.format(
+            self._get_device_log_path()))
 
         self._iperf_process = None
         return log_file
diff --git a/acts/framework/acts/controllers/utils_lib/ssh/connection.py b/acts/framework/acts/controllers/utils_lib/ssh/connection.py
index 6405b52..891a07e 100644
--- a/acts/framework/acts/controllers/utils_lib/ssh/connection.py
+++ b/acts/framework/acts/controllers/utils_lib/ssh/connection.py
@@ -214,7 +214,7 @@
                 line_index = output.find('\n') + 1
                 if line_index == 0:
                     line_index = len(output)
-                real_output = output[line_index + 1:].encode(io_encoding)
+                real_output = output[line_index:].encode(io_encoding)
 
                 result = job.Result(
                     command=result.command,
diff --git a/acts/framework/acts/test_utils/coex/coex_test_utils.py b/acts/framework/acts/test_utils/coex/coex_test_utils.py
index afc9fac..844510f 100644
--- a/acts/framework/acts/test_utils/coex/coex_test_utils.py
+++ b/acts/framework/acts/test_utils/coex/coex_test_utils.py
@@ -1054,8 +1054,9 @@
             ad.adb.push(item, android_music_path)
         return music_file_to_play
     else:
-        ad.log.error("Music file should be of type list")
-        return False
+        music_file_to_play = audio_params["music_file"]
+        ad.adb.push("{} {}".format(music_file_to_play, android_music_path))
+        return (os.path.basename(music_file_to_play))
 
 
 def bokeh_chart_plot(bt_attenuation_range,
diff --git a/acts/framework/acts/test_utils/wifi/wifi_performance_test_utils.py b/acts/framework/acts/test_utils/wifi/wifi_performance_test_utils.py
index 184cd0a..10cbbbb 100644
--- a/acts/framework/acts/test_utils/wifi/wifi_performance_test_utils.py
+++ b/acts/framework/acts/test_utils/wifi/wifi_performance_test_utils.py
@@ -195,7 +195,10 @@
                                                                    None)])
 
 
-def get_connected_rssi(dut, num_measurements=1, polling_frequency=SHORT_SLEEP):
+def get_connected_rssi(dut,
+                       num_measurements=1,
+                       polling_frequency=SHORT_SLEEP,
+                       first_measurement_delay=0):
     """Gets all RSSI values reported for the connected access point/BSSID.
 
     Args:
@@ -215,6 +218,7 @@
          ('chain_0_rssi', empty_rssi_result()),
          ('chain_1_rssi', empty_rssi_result())])
     # yapf: enable
+    time.sleep(first_measurement_delay)
     for idx in range(num_measurements):
         measurement_start_time = time.time()
         # Get signal poll RSSI
@@ -281,8 +285,10 @@
 @nonblocking
 def get_connected_rssi_nb(dut,
                           num_measurements=1,
-                          polling_frequency=SHORT_SLEEP):
-    return get_connected_rssi(dut, num_measurements, polling_frequency)
+                          polling_frequency=SHORT_SLEEP,
+                          first_measurement_delay=0):
+    return get_connected_rssi(dut, num_measurements, polling_frequency,
+                              first_measurement_delay)
 
 
 def get_scan_rssi(dut, tracked_bssids, num_measurements=1):
diff --git a/acts/framework/acts/test_utils/wifi/wifi_test_utils.py b/acts/framework/acts/test_utils/wifi/wifi_test_utils.py
index 37523e3..665388d 100755
--- a/acts/framework/acts/test_utils/wifi/wifi_test_utils.py
+++ b/acts/framework/acts/test_utils/wifi/wifi_test_utils.py
@@ -41,7 +41,7 @@
 # change.
 SHORT_TIMEOUT = 30
 ROAMING_TIMEOUT = 30
-
+WIFI_CONNECTION_TIMEOUT_DEFAULT = 30
 # Speed of light in m/s.
 SPEED_OF_LIGHT = 299792458
 
@@ -1555,6 +1555,28 @@
             raise signals.TestFailure(msg)
 
 
+def check_autoconnect_to_open_network(ad, conn_timeout=WIFI_CONNECTION_TIMEOUT_DEFAULT):
+    """Connects to any open WiFI AP
+     Args:
+         timeout value in sec to wait for UE to connect to a WiFi AP
+     Returns:
+         True if UE connects to WiFi AP (supplicant_state = completed)
+         False if UE fails to complete connection within WIFI_CONNECTION_TIMEOUT time.
+    """
+    if ad.droid.wifiCheckState():
+        return True
+    ad.droid.wifiToggleState()
+    wifi_connection_state = None
+    timeout = time.time() + conn_timeout
+    while wifi_connection_state != "completed":
+        wifi_connection_state = ad.droid.wifiGetConnectionInfo()[
+            'supplicant_state']
+        if time.time() > timeout:
+            ad.log.warning("Failed to connect to WiFi AP")
+            return False
+    return True
+
+
 def expand_enterprise_config_by_phase2(config):
     """Take an enterprise config and generate a list of configs, each with
     a different phase2 auth type.
diff --git a/acts/tests/google/ble/scan/BleOpportunisticScanTest.py b/acts/tests/google/ble/scan/BleOpportunisticScanTest.py
index 0a4dea8..6a87e65 100644
--- a/acts/tests/google/ble/scan/BleOpportunisticScanTest.py
+++ b/acts/tests/google/ble/scan/BleOpportunisticScanTest.py
@@ -28,7 +28,7 @@
 from acts.test_utils.bt.BluetoothBaseTest import BluetoothBaseTest
 from acts.test_utils.bt.bt_constants import ble_scan_settings_modes
 from acts.test_utils.bt.bt_constants import ble_scan_settings_modes
-from acts.test_utils.bt.bt_test_utils import batch_scan_result
+from acts.test_utils.bt.bt_constants import batch_scan_result
 from acts.test_utils.bt.bt_test_utils import cleanup_scanners_and_advertisers
 from acts.test_utils.bt.bt_test_utils import generate_ble_advertise_objects
 from acts.test_utils.bt.bt_test_utils import generate_ble_scan_objects
diff --git a/acts/tests/google/wifi/WifiPingTest.py b/acts/tests/google/wifi/WifiPingTest.py
index be94dfd..f6cfdac 100644
--- a/acts/tests/google/wifi/WifiPingTest.py
+++ b/acts/tests/google/wifi/WifiPingTest.py
@@ -25,7 +25,7 @@
 from acts import utils
 from acts.controllers.utils_lib import ssh
 from acts.metrics.loggers.blackbox import BlackboxMetricLogger
-from acts.test_utils.wifi import wifi_power_test_utils as wputils
+from acts.test_utils.wifi import wifi_performance_test_utils as wputils
 from acts.test_utils.wifi import wifi_retail_ap as retail_ap
 from acts.test_utils.wifi import wifi_test_utils as wutils
 
@@ -40,6 +40,7 @@
     """
 
     TEST_TIMEOUT = 10
+    RSSI_POLL_INTERVAL = 0.2
     SHORT_SLEEP = 1
     MED_SLEEP = 5
     MAX_CONSECUTIVE_ZEROS = 5
@@ -262,59 +263,6 @@
             rvr_range = float("nan")
         return rvr_range
 
-    def get_ping_stats(self, ping_from_dut, ping_duration, ping_interval,
-                       ping_size):
-        """Run ping to or from the DUT.
-
-        The function computes either pings the DUT or pings a remote ip from
-        DUT.
-
-        Args:
-            ping_from_dut: boolean set to true if pinging from the DUT
-            ping_duration: timeout to set on the the ping process (in seconds)
-            ping_interval: time between pings (in seconds)
-            ping_size: size of ping packet payload
-        Returns:
-            ping_result: dict containing ping results and other meta data
-        """
-        ping_cmd = "ping -w {} -i {} -s {}".format(
-            ping_duration,
-            ping_interval,
-            ping_size,
-        )
-        if ping_from_dut:
-            ping_cmd = "{} {}".format(
-                ping_cmd, self.testbed_params["outgoing_ping_address"])
-            ping_output = self.client_dut.adb.shell(
-                ping_cmd,
-                timeout=ping_duration + self.TEST_TIMEOUT,
-                ignore_status=True)
-        else:
-            ping_cmd = "sudo {} {}".format(ping_cmd, self.dut_ip)
-            ping_output = self.ping_server.run(ping_cmd, ignore_status=True)
-        ping_output = ping_output.stdout.splitlines()
-
-        if len(ping_output) == 1:
-            ping_result = self.DISCONNECTED_PING_RESULT
-        else:
-            packet_loss_line = [line for line in ping_output if "loss" in line]
-            packet_loss_percentage = int(
-                packet_loss_line[0].split("%")[0].split(" ")[-1])
-            if packet_loss_percentage == 100:
-                rtt = [float("nan")]
-            else:
-                rtt = [
-                    line.split("time=")[1] for line in ping_output
-                    if "time=" in line
-                ]
-                rtt = [float(line.split(" ")[0]) for line in rtt]
-            ping_result = {
-                "connected": 1,
-                "rtt": rtt,
-                "packet_loss_percentage": packet_loss_percentage
-            }
-        return ping_result
-
     def run_ping_test(self, testcase_params):
         """Main function to test ping.
 
@@ -333,6 +281,7 @@
         test_result["attenuation"] = testcase_params["atten_range"]
         test_result["fixed_attenuation"] = self.testbed_params[
             "fixed_attenuation"][str(testcase_params["channel"])]
+        test_result["rssi_results"] = []
         test_result["ping_results"] = []
         # Run ping and sweep attenuation as needed
         zero_counter = 0
@@ -340,14 +289,24 @@
             for attenuator in self.attenuators:
                 attenuator.set_atten(atten, strict=False)
             time.sleep(self.SHORT_SLEEP)
-            current_ping_stats = self.get_ping_stats(
-                0, testcase_params["ping_duration"],
+            rssi_future = wputils.get_connected_rssi_nb(
+                self.client_dut,
+                int(testcase_params["ping_duration"] / 2 /
+                    self.RSSI_POLL_INTERVAL), self.RSSI_POLL_INTERVAL,
+                testcase_params["ping_duration"] / 2)
+            current_ping_stats = wputils.get_ping_stats(
+                self.ping_server, self.dut_ip,
+                testcase_params["ping_duration"],
                 testcase_params["ping_interval"], testcase_params["ping_size"])
+            current_rssi = rssi_future.result()["signal_poll_rssi"]["mean"]
+            test_result["rssi_results"].append(current_rssi)
             if current_ping_stats["connected"]:
-                self.log.info(
-                    "Attenuation = {0}dB Packet Loss Rate = {1}%. Avg Ping RTT = {2:.2f}ms".
-                    format(atten, current_ping_stats["packet_loss_percentage"],
-                           statistics.mean(current_ping_stats["rtt"])))
+                self.log.info("Attenuation = {0}dB\tPacket Loss = {1}%\t"
+                              "Avg RTT = {2:.2f}ms\tRSSI = {3}\t".format(
+                                  atten,
+                                  current_ping_stats["packet_loss_percentage"],
+                                  statistics.mean(current_ping_stats["rtt"]),
+                                  current_rssi))
                 if current_ping_stats["packet_loss_percentage"] == 100:
                     zero_counter = zero_counter + 1
                 else:
diff --git a/acts/tests/google/wifi/WifiRvrTest.py b/acts/tests/google/wifi/WifiRvrTest.py
index 362f6fa..cde6344 100644
--- a/acts/tests/google/wifi/WifiRvrTest.py
+++ b/acts/tests/google/wifi/WifiRvrTest.py
@@ -26,7 +26,7 @@
 from acts.controllers import iperf_server as ipf
 from acts.metrics.loggers.blackbox import BlackboxMetricLogger
 from acts.test_decorators import test_tracker_info
-from acts.test_utils.wifi import wifi_power_test_utils as wputils
+from acts.test_utils.wifi import wifi_performance_test_utils as wputils
 from acts.test_utils.wifi import wifi_retail_ap as retail_ap
 from acts.test_utils.wifi import wifi_test_utils as wutils
 
@@ -44,6 +44,7 @@
     TEST_TIMEOUT = 10
     SHORT_SLEEP = 1
     MED_SLEEP = 5
+    RSSI_POLL_INTERVAL = 1
     MAX_CONSECUTIVE_ZEROS = 5
 
     def __init__(self, controllers):
@@ -294,18 +295,22 @@
         self.log.info("Start running RvR")
         zero_counter = 0
         throughput = []
+        rssi = []
         for atten in testcase_params["atten_range"]:
             # Set Attenuation
-            self.log.info("Setting attenuation to {} dB".format(atten))
             for attenuator in self.attenuators:
                 attenuator.set_atten(atten, strict=False)
             # Start iperf session
             self.iperf_server.start(tag=str(atten))
+            rssi_future = wputils.get_connected_rssi_nb(
+                self.client_dut, testcase_params["iperf_duration"] - 1, 1, 1)
             client_output_path = self.iperf_client.start(
                 testcase_params["iperf_server_address"],
                 testcase_params["iperf_args"], str(atten),
                 testcase_params["iperf_duration"] + self.TEST_TIMEOUT)
             server_output_path = self.iperf_server.stop()
+            current_rssi = rssi_future.result()["signal_poll_rssi"]["mean"]
+            rssi.append(current_rssi)
             # Parse and log result
             if testcase_params["use_client_output"]:
                 iperf_file = client_output_path
@@ -322,8 +327,9 @@
                     "ValueError: Cannot get iperf result. Setting to 0")
                 curr_throughput = 0
             throughput.append(curr_throughput)
-            self.log.info("Throughput at {0:.2f} dB is {1:.2f} Mbps".format(
-                atten, curr_throughput))
+            self.log.info(
+                "Throughput at {0:.2f} dB is {1:.2f} Mbps. RSSI = {2:.2f}".
+                format(atten, curr_throughput, current_rssi))
             if curr_throughput == 0:
                 zero_counter = zero_counter + 1
             else:
@@ -344,6 +350,7 @@
         rvr_result["fixed_attenuation"] = self.testbed_params[
             "fixed_attenuation"][str(testcase_params["channel"])]
         rvr_result["attenuation"] = list(testcase_params["atten_range"])
+        rvr_result["rssi"] = rssi
         rvr_result["throughput_receive"] = throughput
         return rvr_result