Merge "Fix vht_oper_centr_freq_seg0_idx in VapeInteropTest"
diff --git a/acts/framework/acts/base_test.py b/acts/framework/acts/base_test.py
index 3a5a808..3b2a467 100755
--- a/acts/framework/acts/base_test.py
+++ b/acts/framework/acts/base_test.py
@@ -317,35 +317,20 @@
         if not controllers:
             return None
 
-        # Collect controller information and write to test result.
+        # Log controller information
         # Implementation of "get_info" is optional for a controller module.
         if hasattr(controller_module, "get_info"):
             controller_info = controller_module.get_info(controllers)
             self.log.info("Controller %s: %s", module_config_name,
                           controller_info)
-            self.results.add_controller_info(module_config_name,
-                                             controller_info)
         else:
             self.log.warning("No controller info obtained for %s",
                              module_config_name)
-        self._record_controller_info()
 
         if builtin:
             setattr(self, module_ref_name, controllers)
         return controllers
 
-    def _record_controller_info(self):
-        """Collect controller information and write to summary file."""
-        try:
-            manager = self._controller_manager
-            for record in manager.get_controller_info_records():
-                self.summary_writer.dump(
-                    record.to_dict(),
-                    records.TestSummaryEntryType.CONTROLLER_INFO)
-        except Exception:
-            self.log.exception('Unable to write controller info records to'
-                               ' summary file')
-
     def _setup_class(self):
         """Proxy function to guarantee the base implementation of setup_class
         is called.
@@ -820,7 +805,7 @@
                                      records.TestSummaryEntryType.RECORD)
             self._on_skip(record)
 
-    def run(self, test_names=None, test_case_iterations=1):
+    def run(self, test_names=None):
         """Runs test cases within a test class by the order they appear in the
         execution list.
 
@@ -884,6 +869,11 @@
             return self.results
 
         # Run tests in order.
+        test_case_iterations = self.user_params.get(
+            keys.Config.key_test_case_iterations.value, 1)
+        if any([substr in self.__class__.__name__ for substr in
+                ['Preflight', 'Postflight']]):
+            test_case_iterations = 1
         try:
             for test_name, test_func in tests:
                 for _ in range(test_case_iterations):
diff --git a/acts/framework/acts/bin/act.py b/acts/framework/acts/bin/act.py
index 8ea2bdd..72cb0c3 100755
--- a/acts/framework/acts/bin/act.py
+++ b/acts/framework/acts/bin/act.py
@@ -14,18 +14,22 @@
 #   See the License for the specific language governing permissions and
 #   limitations under the License.
 
-from builtins import str
-
 import argparse
-import multiprocessing
+import os
+import re
 import signal
 import sys
 import traceback
+from builtins import str
+
+from mobly import config_parser as mobly_config_parser
 
 from acts import config_parser
 from acts import keys
 from acts import signals
 from acts import test_runner
+from acts import utils
+from acts.config_parser import ActsConfigError
 
 
 def _run_test(parsed_config, test_identifiers, repeat=1):
@@ -34,8 +38,8 @@
     This is the function to start separate processes with.
 
     Args:
-        parsed_config: A dict that is a set of configs for one
-                       test_runner.TestRunner.
+        parsed_config: A mobly.config_parser.TestRunConfig that is a set of
+                       configs for one test_runner.TestRunner.
         test_identifiers: A list of tuples, each identifies what test case to
                           run on what test class.
         repeat: Number of times to iterate the specified tests.
@@ -63,8 +67,8 @@
     signal handlers that properly shut down the test_runner.TestRunner run.
 
     Args:
-        parsed_config: A dict that is a set of configs for one
-                       test_runner.TestRunner.
+        parsed_config: A mobly.config_parser.TestRunConfig that is a set of
+                       configs for one test_runner.TestRunner.
         test_identifiers: A list of tuples, each identifies what test case to
                           run on what test class.
 
@@ -91,8 +95,8 @@
     of their corresponding configs.
 
     Args:
-        parsed_configs: A list of dicts, each is a set of configs for one
-                        test_runner.TestRunner.
+        parsed_configs: A list of mobly.config_parser.TestRunConfig, each is a
+                        set of configs for one test_runner.TestRunner.
         test_identifiers: A list of tuples, each identifies what test case to
                           run on what test class.
         repeat: Number of times to iterate the specified tests.
@@ -107,7 +111,7 @@
             ok = ok and ret
         except Exception as e:
             print("Exception occurred when executing test bed %s. %s" %
-                  (c[keys.Config.key_testbed.value], e))
+                  (c.testbed_name, e))
     return ok
 
 
@@ -123,7 +127,6 @@
                      "run all test cases found."))
     parser.add_argument('-c',
                         '--config',
-                        nargs=1,
                         type=str,
                         required=True,
                         metavar="<PATH>",
@@ -184,9 +187,45 @@
         test_list = config_parser.parse_test_file(args.testfile[0])
     elif args.testclass:
         test_list = args.testclass
-    parsed_configs = config_parser.load_test_config_file(
-        args.config[0], args.testbed, args.testpaths, args.logpath,
-        args.test_case_iterations)
+    if re.search(r'\.ya?ml$', args.config):
+        parsed_configs = mobly_config_parser.load_test_config_file(
+            args.config, args.testbed)
+    else:
+        parsed_configs = config_parser.load_test_config_file(
+            args.config, args.testbed)
+
+    for test_run_config in parsed_configs:
+        # TODO(markdr): Remove this statement after the next Mobly release.
+        test_run_config.testbed_name = getattr(test_run_config, 'testbed_name',
+                                               test_run_config.test_bed_name)
+
+        if args.testpaths:
+            tp_key = keys.Config.key_test_paths.value
+            test_run_config.controller_configs[tp_key] = args.testpaths
+        if args.logpath:
+            test_run_config.log_path = args.logpath
+        if args.test_case_iterations:
+            # TODO(markdr): Remove this check after the next Mobly release.
+            if test_run_config.user_params is None:
+                test_run_config.user_params = {}
+
+            ti_key = keys.Config.key_test_case_iterations.value
+            test_run_config.user_params[ti_key] = args.test_case_iterations
+
+        # Sets the --testpaths flag to the default test directory if left unset.
+        testpath_key = keys.Config.key_test_paths.value
+        if (testpath_key not in test_run_config.controller_configs
+                or test_run_config.controller_configs[testpath_key] is None):
+            test_run_config.controller_configs[testpath_key] = utils.abs_path(
+                utils.os.path.join(os.path.dirname(__file__),
+                                   '../../../tests/'))
+
+        # TODO(markdr): Find a way to merge this with the validation done in
+        # Mobly's load_test_config_file.
+        if not test_run_config.log_path:
+            raise ActsConfigError("Required key %s missing in test config." %
+                                  keys.Config.key_log_path.value)
+        test_run_config.log_path = utils.abs_path(test_run_config.log_path)
 
     # Prepare args for test runs
     test_identifiers = config_parser.parse_test_list(test_list)
diff --git a/acts/framework/acts/config_parser.py b/acts/framework/acts/config_parser.py
index bdab874..549ebed 100755
--- a/acts/framework/acts/config_parser.py
+++ b/acts/framework/acts/config_parser.py
@@ -43,6 +43,12 @@
     Making sure all the required fields exist.
     """
     for k in keys.Config.reserved_keys.value:
+        # TODO(markdr): Remove this continue after merging this with the
+        # validation done in Mobly's load_test_config_file.
+        if (k == keys.Config.key_test_paths.value
+                or k == keys.Config.key_log_path.value):
+            continue
+
         if k not in test_config:
             raise ActsConfigError("Required key %s missing in test config." %
                                   k)
@@ -164,41 +170,24 @@
     return result
 
 
-def load_test_config_file(test_config_path,
-                          tb_filters=None,
-                          override_test_path=None,
-                          override_log_path=None,
-                          override_test_case_iterations=None):
+def load_test_config_file(test_config_path, tb_filters=None):
     """Processes the test configuration file provided by the user.
 
     Loads the configuration file into a json object, unpacks each testbed
-    config into its own json object, and validate the configuration in the
-    process.
+    config into its own TestRunConfig object, and validate the configuration in
+    the process.
 
     Args:
         test_config_path: Path to the test configuration file.
         tb_filters: A subset of test bed names to be pulled from the config
                     file. If None, then all test beds will be selected.
-        override_test_path: If not none the test path to use instead.
-        override_log_path: If not none the log path to use instead.
-        override_test_case_iterations: If not None, override the config file
-                                       value.
 
     Returns:
-        A list of test configuration json objects to be passed to
+        A list of mobly.config_parser.TestRunConfig objects to be passed to
         test_runner.TestRunner.
     """
     configs = utils.load_config(test_config_path)
 
-    test_paths_key = keys.Config.key_test_paths.value
-    if override_test_path:
-        configs[test_paths_key] = override_test_path
-    if override_log_path:
-        configs[keys.Config.key_log_path.value] = override_log_path
-    if override_test_case_iterations:
-        configs[keys.Config.key_test_case_iterations.value] = (
-            override_test_case_iterations)
-
     testbeds = configs[keys.Config.key_testbed.value]
     if type(testbeds) is list:
         tb_dict = dict()
@@ -238,10 +227,6 @@
         configs[keys.Config.key_test_failure_tracebacks.
                 value] = os.environ[_ENV_TEST_FAILURE_TRACEBACKS]
 
-    # Add the global paths to the global config.
-    k_log_path = keys.Config.key_log_path.value
-    configs[k_log_path] = utils.abs_path(configs[k_log_path])
-
     # TODO: See if there is a better way to do this: b/29836695
     config_path, _ = os.path.split(utils.abs_path(test_config_path))
     configs[keys.Config.key_config_path.value] = config_path
@@ -255,10 +240,15 @@
         test_run_config = mobly_config_parser.TestRunConfig()
         test_run_config.testbed_name = testbed[
             keys.Config.key_testbed_name.value]
-        test_run_config.log_path = configs[k_log_path]
         test_run_config.controller_configs = testbed
-        test_run_config.controller_configs[test_paths_key] = (
-            configs[test_paths_key])
+        test_run_config.controller_configs[
+            keys.Config.key_test_paths.value] = configs.get(
+                keys.Config.key_test_paths.value, None)
+        test_run_config.log_path = configs.get(keys.Config.key_log_path.value,
+                                               None)
+        if test_run_config.log_path is not None:
+            test_run_config.log_path = utils.abs_path(test_run_config.log_path)
+
         user_param_pairs = []
         for item in itertools.chain(configs.items(), testbed.items()):
             if item[0] not in keys.Config.reserved_keys.value:
diff --git a/acts/framework/acts/controllers/access_point.py b/acts/framework/acts/controllers/access_point.py
index 4b89de6..38db6a7 100755
--- a/acts/framework/acts/controllers/access_point.py
+++ b/acts/framework/acts/controllers/access_point.py
@@ -150,6 +150,7 @@
         self.lan = self.interfaces.get_lan_interface()
         self.__initial_ap()
         self.scapy_install_path = None
+        self.setup_bridge = False
 
     def __initial_ap(self):
         """Initial AP interfaces.
@@ -179,7 +180,10 @@
                 self.ssh.run(BRIDGE_DOWN)
                 self.ssh.run(BRIDGE_DEL)
 
-    def start_ap(self, hostapd_config, additional_parameters=None):
+    def start_ap(self,
+                 hostapd_config,
+                 setup_bridge=False,
+                 additional_parameters=None):
         """Starts as an ap using a set of configurations.
 
         This will start an ap on this host. To start an ap the controller
@@ -190,11 +194,13 @@
 
         Args:
             hostapd_config: hostapd_config.HostapdConfig, The configurations
-                            to use when starting up the ap.
+                to use when starting up the ap.
+            setup_bridge: Whether to bridge the LAN interface WLAN interface.
+                Only one WLAN interface can be bridged with the LAN interface
+                and none of the guest networks can be bridged.
             additional_parameters: A dictionary of parameters that can sent
-                                   directly into the hostapd config file.  This
-                                   can be used for debugging and or adding one
-                                   off parameters into the config.
+                directly into the hostapd config file.  This can be used for
+                debugging and or adding one off parameters into the config.
 
         Returns:
             An identifier for each ssid being started. These identifiers can be
@@ -203,7 +209,6 @@
         Raises:
             Error: When the ap can't be brought up.
         """
-
         if hostapd_config.frequency < 5000:
             interface = self.wlan_2g
             subnet = self._AP_2G_SUBNET
@@ -275,7 +280,12 @@
         # the server will come up.
         interface_ip = ipaddress.ip_interface(
             '%s/%s' % (subnet.router, subnet.network.netmask))
-        self._ip_cmd.set_ipv4_address(interface, interface_ip)
+        if setup_bridge is True:
+            bridge_interface_name = 'br_lan'
+            self.create_bridge(bridge_interface_name, [interface, self.lan])
+            self._ip_cmd.set_ipv4_address(bridge_interface_name, interface_ip)
+        else:
+            self._ip_cmd.set_ipv4_address(interface, interface_ip)
         if hostapd_config.bss_lookup:
             # This loop goes through each interface that was setup for
             # hostapd and assigns the DHCP scopes that were defined but
@@ -442,6 +452,13 @@
         del self._aps[identifier]
         if configured_subnets:
             self.start_dhcp(subnets=configured_subnets)
+        bridge_interfaces = self.interfaces.get_bridge_interface()
+        if bridge_interfaces:
+            for iface in bridge_interfaces:
+                BRIDGE_DOWN = 'ifconfig {} down'.format(iface)
+                BRIDGE_DEL = 'brctl delbr {}'.format(iface)
+                self.ssh.run(BRIDGE_DOWN)
+                self.ssh.run(BRIDGE_DEL)
 
     def stop_all_aps(self):
         """Stops all running aps on this device."""
diff --git a/acts/framework/acts/controllers/android_device.py b/acts/framework/acts/controllers/android_device.py
index f66d6ce..1f8bbce 100755
--- a/acts/framework/acts/controllers/android_device.py
+++ b/acts/framework/acts/controllers/android_device.py
@@ -473,7 +473,8 @@
             'serial': self.serial,
             'model': self.model,
             'build_info': self.build_info,
-            'user_added_info': self._user_added_device_info
+            'user_added_info': self._user_added_device_info,
+            'flavor': self.flavor
         }
         return info
 
@@ -526,6 +527,11 @@
             return self.adb.getprop("ro.product.name").lower()
 
     @property
+    def flavor(self):
+        """Returns the specific flavor of Android build the device is using."""
+        return self.adb.getprop("ro.build.flavor").lower()
+
+    @property
     def droid(self):
         """Returns the RPC Service of the first Sl4aSession created."""
         if len(self._sl4a_manager.sessions) > 0:
diff --git a/acts/framework/acts/controllers/anritsu_lib/_anritsu_utils.py b/acts/framework/acts/controllers/anritsu_lib/_anritsu_utils.py
index 14a3a38..64f24b7 100644
--- a/acts/framework/acts/controllers/anritsu_lib/_anritsu_utils.py
+++ b/acts/framework/acts/controllers/anritsu_lib/_anritsu_utils.py
@@ -93,6 +93,7 @@
     536870953: 'The specified IP address is the same as that of Default Gateway'
                'specified by Simulation parameter.',
     536870954: 'TFT IE conversion failed.',
+    536870955: 'Saving settings to the SmartStudio scenario failed.',
     536875008: 'An error exists in the parameter configuration.'
                '(This error applies only to the current version.)',
     536936448: 'License verification failed.',
diff --git a/acts/framework/acts/controllers/anritsu_lib/md8475_cellular_simulator.py b/acts/framework/acts/controllers/anritsu_lib/md8475_cellular_simulator.py
index b3eeee7..b76c2d8 100644
--- a/acts/framework/acts/controllers/anritsu_lib/md8475_cellular_simulator.py
+++ b/acts/framework/acts/controllers/anritsu_lib/md8475_cellular_simulator.py
@@ -516,7 +516,7 @@
     def stop(self):
         """ Stops current simulation. After calling this method, the simulator
         will need to be set up again. """
-        self.simulator.stop()
+        self.anritsu.stop_simulation()
 
     def start_data_traffic(self):
         """ Starts transmitting data from the instrument to the DUT. """
diff --git a/acts/framework/acts/controllers/attenuator.py b/acts/framework/acts/controllers/attenuator.py
index aa84801..9d99c2d 100644
--- a/acts/framework/acts/controllers/attenuator.py
+++ b/acts/framework/acts/controllers/attenuator.py
@@ -48,17 +48,16 @@
                 logging.error('Attempt %s to open connection to attenuator '
                               'failed: %s' % (attempt_number, e))
                 if attempt_number == _ATTENUATOR_OPEN_RETRIES:
-                    ping_output = job.run(
-                        'ping %s -c 1 -w 1' % ip_address, ignore_status=True)
+                    ping_output = job.run('ping %s -c 1 -w 1' % ip_address,
+                                          ignore_status=True)
                     if ping_output.exit_status == 1:
-                        logging.error(
-                            'Unable to ping attenuator at %s' % ip_address)
+                        logging.error('Unable to ping attenuator at %s' %
+                                      ip_address)
                     else:
-                        logging.error(
-                            'Able to ping attenuator at %s' % ip_address)
-                        job.run(
-                            'echo "q" | telnet %s %s' % (ip_address, port),
-                            ignore_status=True)
+                        logging.error('Able to ping attenuator at %s' %
+                                      ip_address)
+                        job.run('echo "q" | telnet %s %s' % (ip_address, port),
+                                ignore_status=True)
                     raise
         for i in range(inst_cnt):
             attn = Attenuator(attn_inst, idx=i)
@@ -72,13 +71,31 @@
     return objs
 
 
+def get_info(attenuators):
+    """Get information on a list of Attenuator objects.
+
+    Args:
+        attenuators: A list of Attenuator objects.
+
+    Returns:
+        A list of dict, each representing info for Attenuator objects.
+    """
+    device_info = []
+    for attenuator in attenuators:
+        info = {
+            "Address": attenuator.instrument.address,
+            "Attenuator_Port": attenuator.idx
+        }
+        device_info.append(info)
+    return device_info
+
+
 def destroy(objs):
     for attn in objs:
         attn.instrument.close()
 
 
-def get_attenuators_for_device(device_attenuator_configs,
-                               attenuators,
+def get_attenuators_for_device(device_attenuator_configs, attenuators,
                                attenuator_key):
     """Gets the list of attenuators associated to a specified device and builds
     a list of the attenuator objects associated to the ip address in the
@@ -139,11 +156,12 @@
         for attenuator_port in device_attenuator_config[attenuator_key]:
             for attenuator in attenuators:
                 if (attenuator.instrument.address ==
-                        device_attenuator_config['Address'] and
-                        attenuator.idx is attenuator_port):
+                        device_attenuator_config['Address']
+                        and attenuator.idx is attenuator_port):
                     attenuator_list.append(attenuator)
     return attenuator_list
 
+
 """Classes for accessing, managing, and manipulating attenuators.
 
 Users will instantiate a specific child class, but almost all operation should
@@ -244,7 +262,6 @@
     the physical implementation and allows the user to think only of attenuators
     regardless of their location.
     """
-
     def __init__(self, instrument, idx=0, offset=0):
         """This is the constructor for Attenuator
 
@@ -313,7 +330,6 @@
     convenience to the user and avoid re-implementation of helper functions and
     small loops scattered throughout user code.
     """
-
     def __init__(self, name=''):
         """This constructor for AttenuatorGroup
 
diff --git a/acts/framework/acts/controllers/fuchsia_device.py b/acts/framework/acts/controllers/fuchsia_device.py
index fd4aecd..998927d 100644
--- a/acts/framework/acts/controllers/fuchsia_device.py
+++ b/acts/framework/acts/controllers/fuchsia_device.py
@@ -14,6 +14,7 @@
 #   See the License for the specific language governing permissions and
 #   limitations under the License.
 
+import backoff
 import json
 import logging
 import platform
@@ -22,6 +23,7 @@
 import re
 import requests
 import subprocess
+import socket
 import time
 
 from acts import context
@@ -146,7 +148,6 @@
         log: A logger object.
         port: The TCP port number of the Fuchsia device.
     """
-
     def __init__(self, fd_conf_data):
         """
         Args:
@@ -230,13 +231,13 @@
         # Init server
         self.init_server_connection()
 
-    def init_server_connection(self, retry_count=3):
-        """Initializes HTTP connection with SL4F server.
-
-        Args:
-            retry_count: How many time to retry connecting assuming a
-                known error.
-        """
+    @backoff.on_exception(
+        backoff.constant,
+        (ConnectionRefusedError, requests.exceptions.ConnectionError),
+        interval=1.5,
+        max_tries=4)
+    def init_server_connection(self):
+        """Initializes HTTP connection with SL4F server."""
         self.log.debug("Initialziing server connection")
         init_data = json.dumps({
             "jsonrpc": "2.0",
@@ -246,28 +247,8 @@
                 "client_id": self.client_id
             }
         })
-        retry_counter = 0
-        while retry_counter < retry_count:
-            try:
-                requests.get(url=self.init_address, data=init_data)
-                retry_counter = retry_count + 1
-            except ConnectionRefusedError:
-                self.log.info('Connection Refused Error.  '
-                              'Retrying in 1 second.')
-                e = ConnectionRefusedError('Connection Refused Error.')
-                retry_counter += 1
-                time.sleep(1)
-            except requests.exceptions.ConnectionError:
-                self.log.info('Requests ConnectionError.  '
-                              'Retrying in 1 second.')
-                e = requests.exceptions.ConnectionError('Requests '
-                                                        'ConnectionError')
-                retry_counter += 1
-                time.sleep(1)
-            except Exception as e:
-                raise e
-        if retry_counter is retry_count:
-            raise e
+
+        requests.get(url=self.init_address, data=init_data)
         self.test_counter += 1
 
     def build_id(self, test_id):
@@ -315,7 +296,8 @@
         elif os_type == 'Linux':
             timeout_flag = '-W'
         else:
-            raise ValueError('Invalid OS.  Only Linux and MacOS are supported.')
+            raise ValueError(
+                'Invalid OS.  Only Linux and MacOS are supported.')
         ping_command = ['ping', '%s' % timeout_flag, '1', '-c', '1', self.ip]
         self.clean_up()
         self.log.info('Rebooting FuchsiaDevice %s' % self.ip)
@@ -331,7 +313,7 @@
         self.log.info('Waiting for FuchsiaDevice %s to come back up.' %
                       self.ip)
         self.log.debug('Waiting for FuchsiaDevice %s to stop responding'
-                      ' to pings.' % self.ip)
+                       ' to pings.' % self.ip)
         while True:
             initial_ping_status_code = subprocess.call(
                 ping_command,
@@ -340,28 +322,26 @@
             if initial_ping_status_code != 1:
                 break
             else:
-                initial_ping_elapsed_time = (
-                        time.time() - initial_ping_start_time)
+                initial_ping_elapsed_time = (time.time() -
+                                             initial_ping_start_time)
                 if initial_ping_elapsed_time > timeout:
                     try:
                         uptime = (int(
                             self.send_command_ssh(
                                 'clock --monotonic',
-                                timeout=
-                                FUCHSIA_RECONNECT_AFTER_REBOOT_TIME).stdout)
-                                / FUCHSIA_TIME_IN_NANOSECONDS)
+                                timeout=FUCHSIA_RECONNECT_AFTER_REBOOT_TIME).
+                            stdout) / FUCHSIA_TIME_IN_NANOSECONDS)
                     except Exception as e:
-                        self.log.debug('Unable to retrieve uptime from device.')
+                        self.log.info('Unable to retrieve uptime from device.')
                     # Device failed to restart within the specified period.
                     # Restart the services so other tests can continue.
                     self.start_services()
                     self.init_server_connection()
-                    raise TimeoutError('Waited %s seconds, and FuchsiaDevice %s'
-                                       ' never stopped responding to pings.'
-                                       ' Uptime reported as %s' %
-                                       (initial_ping_elapsed_time,
-                                        self.ip,
-                                        str(uptime)))
+                    raise TimeoutError(
+                        'Waited %s seconds, and FuchsiaDevice %s'
+                        ' never stopped responding to pings.'
+                        ' Uptime reported as %s' %
+                        (initial_ping_elapsed_time, self.ip, str(uptime)))
 
         start_time = time.time()
         self.log.debug('Waiting for FuchsiaDevice %s to start responding '
@@ -377,8 +357,8 @@
                 raise TimeoutError('Waited %s seconds, and FuchsiaDevice %s'
                                    'did not repond to a ping.' %
                                    (elapsed_time, self.ip))
-        self.log.debug('Received a ping back in %s seconds.'
-                       % str(time.time() - start_time))
+        self.log.debug('Received a ping back in %s seconds.' %
+                       str(time.time() - start_time))
         # Wait 5 seconds after receiving a ping packet to just to let
         # the OS get everything up and running.
         time.sleep(10)
@@ -656,15 +636,17 @@
                            disconnect_response.get("error"))
             return False
 
-    def start_services(self, skip_sl4f=False, retry_count=3):
+    @backoff.on_exception(backoff.constant,
+                          (FuchsiaSyslogError, socket.timeout),
+                          interval=1.5,
+                          max_tries=4)
+    def start_services(self, skip_sl4f=False):
         """Starts long running services on the Fuchsia device.
 
         1. Start SL4F if not skipped.
 
         Args:
             skip_sl4f: Does not attempt to start SL4F if True.
-            retry_count: How many time to retry connecting assuming a
-                known error.
         """
         self.log.debug("Attempting to start Fuchsia device services on %s." %
                        self.ip)
@@ -672,24 +654,9 @@
             self.log_process = start_syslog(self.serial, self.log_path,
                                             self.ip, self.ssh_username,
                                             self.ssh_config)
-            retry_counter = 0
-            while retry_counter < retry_count:
-                if ENABLE_LOG_LISTENER:
-                    try:
-                        self.log_process.start()
-                        retry_counter = retry_count + 1
-                    except FuchsiaSyslogError:
-                        self.log.info('Fuchsia Syslog Error.  '
-                                      'Retrying in 1 second.')
-                        e = FuchsiaSyslogError('Fuchsia Syslog Error')
-                        retry_counter += 1
-                        time.sleep(1)
-                    except Exception as e:
-                        raise e
-                else:
-                    retry_counter = retry_count + 1
-            if retry_counter is retry_count:
-                raise e
+
+            if ENABLE_LOG_LISTENER:
+                self.log_process.start()
 
             if not skip_sl4f:
                 self.control_daemon("sl4f.cmx", "start")
diff --git a/acts/framework/acts/controllers/fuchsia_lib/utils_lib.py b/acts/framework/acts/controllers/fuchsia_lib/utils_lib.py
index 6456a08..56fd4c2 100644
--- a/acts/framework/acts/controllers/fuchsia_lib/utils_lib.py
+++ b/acts/framework/acts/controllers/fuchsia_lib/utils_lib.py
@@ -14,9 +14,11 @@
 #   See the License for the specific language governing permissions and
 #   limitations under the License.
 
+import backoff
 import os
 import logging
 import paramiko
+import socket
 import time
 
 logging.getLogger("paramiko").setLevel(logging.WARNING)
@@ -51,11 +53,17 @@
     raise Exception('No valid ssh key type found', exceptions)
 
 
+@backoff.on_exception(
+    backoff.constant,
+    (paramiko.ssh_exception.SSHException,
+     paramiko.ssh_exception.AuthenticationException, socket.timeout,
+     socket.error, ConnectionRefusedError, ConnectionResetError),
+    interval=1.5,
+    max_tries=4)
 def create_ssh_connection(ip_address,
                           ssh_username,
                           ssh_config,
-                          connect_timeout=30,
-                          retry_count=3):
+                          connect_timeout=30):
     """Creates and ssh connection to a Fuchsia device
 
     Args:
@@ -63,8 +71,6 @@
         ssh_username: Username for ssh server.
         ssh_config: ssh_config location for the ssh server.
         connect_timeout: Timeout value for connecting to ssh_server.
-        retry_count: How many time to retry connecting assuming a
-            known error.
 
     Returns:
         A paramiko ssh object
@@ -72,31 +78,12 @@
     ssh_key = get_private_key(ip_address=ip_address, ssh_config=ssh_config)
     ssh_client = paramiko.SSHClient()
     ssh_client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
-    retry_counter = 0
-    while retry_counter < retry_count:
-        try:
-            ssh_client.connect(hostname=ip_address,
-                               username=ssh_username,
-                               allow_agent=False,
-                               pkey=ssh_key,
-                               timeout=connect_timeout,
-                               banner_timeout=200)
-            retry_counter = retry_count + 1
-        except paramiko.ssh_exception.SSHException:
-            logging.info('Paramiko SSHException.  Retrying in 1 second.')
-            e = paramiko.ssh_exception.SSHException('Paramiko SSHException')
-            time.sleep(1)
-            retry_counter =+ 1
-        except ConnectionRefusedError:
-            logging.info('Connection Refused Error.  Retrying in 1 second.')
-            e = ConnectionRefusedError('Connection Refused Error')
-            time.sleep(1)
-            retry_counter =+ 1
-        except Exception as e:
-            raise e
-    if retry_counter is retry_count:
-        raise e
-
+    ssh_client.connect(hostname=ip_address,
+                       username=ssh_username,
+                       allow_agent=False,
+                       pkey=ssh_key,
+                       timeout=connect_timeout,
+                       banner_timeout=200)
     return ssh_client
 
 
diff --git a/acts/framework/acts/controllers/fuchsia_lib/wlan_lib.py b/acts/framework/acts/controllers/fuchsia_lib/wlan_lib.py
index ac20854..e980815 100644
--- a/acts/framework/acts/controllers/fuchsia_lib/wlan_lib.py
+++ b/acts/framework/acts/controllers/fuchsia_lib/wlan_lib.py
@@ -20,6 +20,9 @@
 COMMAND_CONNECT = "wlan.connect"
 COMMAND_DISCONNECT = "wlan.disconnect"
 COMMAND_STATUS = "wlan.status"
+COMMAND_GET_IFACE_ID_LIST = "wlan.get_iface_id_list"
+COMMAND_DESTROY_IFACE = "wlan.destroy_iface"
+
 
 class FuchsiaWlanLib(BaseLib):
     def __init__(self, addr, tc, client_id):
@@ -31,8 +34,8 @@
     def wlanStartScan(self):
         """ Starts a wlan scan
 
-                Returns:
-                    scan results
+        Returns:
+            scan results
         """
         test_cmd = COMMAND_SCAN
         test_id = self.build_id(self.test_counter)
@@ -42,12 +45,12 @@
 
     def wlanConnectToNetwork(self, target_ssid, target_pwd=None):
         """ Triggers a network connection
-                Args:
-                    target_ssid: the network to attempt a connection to
-                    target_pwd: (optional) password for the target network
+        Args:
+            target_ssid: the network to attempt a connection to
+            target_pwd: (optional) password for the target network
 
-                Returns:
-                    boolean indicating if the connection was successful
+        Returns:
+            boolean indicating if the connection was successful
         """
         test_cmd = COMMAND_CONNECT
         test_args = {"target_ssid": target_ssid, "target_pwd": target_pwd}
@@ -64,12 +67,39 @@
 
         return self.send_command(test_id, test_cmd, {})
 
+    def wlanDestroyIface(self, iface_id):
+        """ Destroy WLAN interface by ID.
+        Args:
+            iface_id: the interface id.
+
+        Returns:
+            Dictionary, service id if success, error if error.
+        """
+        test_cmd = COMMAND_DESTROY_IFACE
+        test_args = {"identifier": iface_id}
+        test_id = self.build_id(self.test_counter)
+        self.test_counter += 1
+
+        return self.send_command(test_id, test_cmd, test_args)
+
+    def wlanGetIfaceIdList(self):
+        """ Get a list if wlan interface IDs.
+
+        Returns:
+            Dictionary, service id if success, error if error.
+        """
+        test_cmd = COMMAND_GET_IFACE_ID_LIST
+        test_id = self.build_id(self.test_counter)
+        self.test_counter += 1
+
+        return self.send_command(test_id, test_cmd, {})
+
     def wlanStatus(self):
         """ Request connection status
 
-                Returns:
-                    Client state summary containing WlanClientState and
-                    status of various networks connections
+        Returns:
+            Client state summary containing WlanClientState and
+            status of various networks connections
         """
         test_cmd = COMMAND_STATUS
         test_id = self.build_id(self.test_counter)
diff --git a/acts/framework/acts/controllers/iperf_client.py b/acts/framework/acts/controllers/iperf_client.py
index 40c6993..80a8410 100644
--- a/acts/framework/acts/controllers/iperf_client.py
+++ b/acts/framework/acts/controllers/iperf_client.py
@@ -23,6 +23,8 @@
 from acts import utils
 from acts.controllers.android_device import AndroidDevice
 from acts.controllers.iperf_server import _AndroidDeviceBridge
+from acts.controllers.fuchsia_lib.utils_lib import create_ssh_connection
+from acts.controllers.fuchsia_lib.utils_lib import SshResults
 from acts.controllers.utils_lib.ssh import connection
 from acts.controllers.utils_lib.ssh import settings
 from acts.event import event_bus
@@ -51,12 +53,24 @@
         if type(c) is dict and 'AndroidDevice' in c:
             results.append(IPerfClientOverAdb(c['AndroidDevice']))
         elif type(c) is dict and 'ssh_config' in c:
-            results.append(IPerfClientOverSsh(c['ssh_config']))
+            results.append(
+                IPerfClientOverSsh(c['ssh_config'],
+                                   use_paramiko=c.get('use_paramiko'),
+                                   test_interface=c.get('test_interface')))
         else:
             results.append(IPerfClient())
     return results
 
 
+def get_info(iperf_clients):
+    """Placeholder for info about iperf clients
+
+    Returns:
+        None
+    """
+    return None
+
+
 def destroy(_):
     # No cleanup needed.
     pass
@@ -98,7 +112,7 @@
 
         return os.path.join(full_out_dir, out_file_name)
 
-    def start(self, ip, iperf_args, tag, timeout=3600):
+    def start(self, ip, iperf_args, tag, timeout=3600, iperf_binary=None):
         """Starts iperf client, and waits for completion.
 
         Args:
@@ -107,6 +121,8 @@
                 client. Eg: iperf_args = "-t 10 -p 5001 -w 512k/-u -b 200M -J".
             tag: A string to further identify iperf results file
             timeout: the maximum amount of time the iperf client can run.
+            iperf_binary: Location of iperf3 binary. If none, it is assumed the
+                the binary is in the path.
 
         Returns:
             full_out_path: iperf result path.
@@ -116,8 +132,7 @@
 
 class IPerfClient(IPerfClientBase):
     """Class that handles iperf3 client operations."""
-
-    def start(self, ip, iperf_args, tag, timeout=3600):
+    def start(self, ip, iperf_args, tag, timeout=3600, iperf_binary=None):
         """Starts iperf client, and waits for completion.
 
         Args:
@@ -126,11 +141,19 @@
             client. Eg: iperf_args = "-t 10 -p 5001 -w 512k/-u -b 200M -J".
             tag: tag to further identify iperf results file
             timeout: unused.
+            iperf_binary: Location of iperf3 binary. If none, it is assumed the
+                the binary is in the path.
 
         Returns:
             full_out_path: iperf result path.
         """
-        iperf_cmd = ['iperf3', '-c', ip] + iperf_args.split(' ')
+        if not iperf_binary:
+            logging.debug('No iperf3 binary specified.  '
+                          'Assuming iperf3 is in the path.')
+            iperf_binary = 'iperf3'
+        else:
+            logging.debug('Using iperf3 binary located at %s' % iperf_binary)
+        iperf_cmd = [str(iperf_binary), '-c', ip] + iperf_args.split(' ')
         full_out_path = self._get_full_file_path(tag)
 
         with open(full_out_path, 'w') as out_file:
@@ -141,12 +164,21 @@
 
 class IPerfClientOverSsh(IPerfClientBase):
     """Class that handles iperf3 client operations on remote machines."""
-
-    def __init__(self, ssh_config):
+    def __init__(self, ssh_config, use_paramiko=False, test_interface=None):
         self._ssh_settings = settings.from_config(ssh_config)
-        self._ssh_session = connection.SshConnection(self._ssh_settings)
+        self._use_paramiko = use_paramiko
+        if str(self._use_paramiko) == 'True':
+            self._ssh_session = create_ssh_connection(
+                ip_address=ssh_config['host'],
+                ssh_username=ssh_config['user'],
+                ssh_config=ssh_config['ssh_config'])
+        else:
+            self._ssh_session = connection.SshConnection(self._ssh_settings)
 
-    def start(self, ip, iperf_args, tag, timeout=3600):
+        self.hostname = self._ssh_settings.hostname
+        self.test_interface = test_interface
+
+    def start(self, ip, iperf_args, tag, timeout=3600, iperf_binary=None):
         """Starts iperf client, and waits for completion.
 
         Args:
@@ -155,15 +187,33 @@
             client. Eg: iperf_args = "-t 10 -p 5001 -w 512k/-u -b 200M -J".
             tag: tag to further identify iperf results file
             timeout: the maximum amount of time to allow the iperf client to run
+            iperf_binary: Location of iperf3 binary. If none, it is assumed the
+                the binary is in the path.
 
         Returns:
             full_out_path: iperf result path.
         """
-        iperf_cmd = 'iperf3 -c {} {}'.format(ip, iperf_args)
+        if not iperf_binary:
+            logging.debug('No iperf3 binary specified.  '
+                          'Assuming iperf3 is in the path.')
+            iperf_binary = 'iperf3'
+        else:
+            logging.debug('Using iperf3 binary located at %s' % iperf_binary)
+        iperf_cmd = '{} -c {} {}'.format(iperf_binary, ip, iperf_args)
         full_out_path = self._get_full_file_path(tag)
 
         try:
-            iperf_process = self._ssh_session.run(iperf_cmd, timeout=timeout)
+            if self._use_paramiko:
+                cmd_result_stdin, cmd_result_stdout, cmd_result_stderr = (
+                    self._ssh_session.exec_command(iperf_cmd, timeout=timeout))
+                cmd_result_exit_status = (
+                    cmd_result_stdout.channel.recv_exit_status())
+                iperf_process = SshResults(cmd_result_stdin, cmd_result_stdout,
+                                           cmd_result_stderr,
+                                           cmd_result_exit_status)
+            else:
+                iperf_process = self._ssh_session.run(iperf_cmd,
+                                                      timeout=timeout)
             iperf_output = iperf_process.stdout
             with open(full_out_path, 'w') as out_file:
                 out_file.write(iperf_output)
@@ -175,7 +225,6 @@
 
 class IPerfClientOverAdb(IPerfClientBase):
     """Class that handles iperf3 operations over ADB devices."""
-
     def __init__(self, android_device_or_serial):
         """Creates a new IPerfClientOverAdb object.
 
@@ -195,7 +244,7 @@
             return _AndroidDeviceBridge.android_devices()[
                 self._android_device_or_serial]
 
-    def start(self, ip, iperf_args, tag, timeout=3600):
+    def start(self, ip, iperf_args, tag, timeout=3600, iperf_binary=None):
         """Starts iperf client, and waits for completion.
 
         Args:
@@ -204,14 +253,27 @@
             client. Eg: iperf_args = "-t 10 -p 5001 -w 512k/-u -b 200M -J".
             tag: tag to further identify iperf results file
             timeout: the maximum amount of time to allow the iperf client to run
+            iperf_binary: Location of iperf3 binary. If none, it is assumed the
+                the binary is in the path.
 
         Returns:
             The iperf result file path.
         """
         iperf_output = ''
         try:
-            iperf_status, iperf_output = self._android_device.run_iperf_client(
-                ip, iperf_args, timeout=timeout)
+            if not iperf_binary:
+                logging.debug('No iperf3 binary specified.  '
+                              'Assuming iperf3 is in the path.')
+                iperf_binary = 'iperf3'
+            else:
+                logging.debug('Using iperf3 binary located at %s' %
+                              iperf_binary)
+            iperf_cmd = '{} -c {} {}'.format(iperf_binary, ip, iperf_args)
+            out = self._android_device.adb.shell(str(iperf_cmd),
+                                                 timeout=timeout)
+            clean_out = out.split('\n')
+            if "error" in clean_out[0].lower():
+                raise Exception('clean_out')
         except job.TimeoutError:
             logging.warning('TimeoutError: Iperf measurement timed out.')
 
diff --git a/acts/framework/acts/controllers/iperf_server.py b/acts/framework/acts/controllers/iperf_server.py
index 039f143..f8048b9 100755
--- a/acts/framework/acts/controllers/iperf_server.py
+++ b/acts/framework/acts/controllers/iperf_server.py
@@ -17,6 +17,7 @@
 import json
 import logging
 import math
+import IPy
 import os
 import shlex
 import subprocess
@@ -36,6 +37,10 @@
 
 ACTS_CONTROLLER_CONFIG_NAME = 'IPerfServer'
 ACTS_CONTROLLER_REFERENCE_NAME = 'iperf_servers'
+KILOBITS = 1024
+MEGABITS = KILOBITS * 1024
+GIGABITS = MEGABITS * 1024
+BITS_IN_BYTE = 8
 
 
 def create(configs):
@@ -56,7 +61,10 @@
         elif type(c) is dict and 'AndroidDevice' in c and 'port' in c:
             results.append(IPerfServerOverAdb(c['AndroidDevice'], c['port']))
         elif type(c) is dict and 'ssh_config' in c and 'port' in c:
-            results.append(IPerfServerOverSsh(c['ssh_config'], c['port']))
+            results.append(
+                IPerfServerOverSsh(c['ssh_config'],
+                                   c['port'],
+                                   test_interface=c.get('test_interface')))
         else:
             raise ValueError(
                 'Config entry %s in %s is not a valid IPerfServer '
@@ -64,6 +72,15 @@
     return results
 
 
+def get_info(iperf_servers):
+    """Placeholder for info about iperf servers
+
+    Returns:
+        None
+    """
+    return None
+
+
 def destroy(iperf_server_list):
     for iperf_server in iperf_server_list:
         try:
@@ -73,7 +90,7 @@
 
 
 class IPerfResult(object):
-    def __init__(self, result_path):
+    def __init__(self, result_path, reporting_speed_units='Mbytes'):
         """Loads iperf result from file.
 
         Loads iperf result from JSON formatted server log. File can be accessed
@@ -82,6 +99,7 @@
         containing multiple iperf client runs.
         """
         # if result_path isn't a path, treat it as JSON
+        self.reporting_speed_units = reporting_speed_units
         if not os.path.exists(result_path):
             self.result = json.loads(result_path)
         else:
@@ -89,8 +107,8 @@
                 with open(result_path, 'r') as f:
                     iperf_output = f.readlines()
                     if '}\n' in iperf_output:
-                        iperf_output = iperf_output[:iperf_output.index('}\n')
-                                                    + 1]
+                        iperf_output = iperf_output[:iperf_output.index('}\n'
+                                                                        ) + 1]
                     iperf_string = ''.join(iperf_output)
                     iperf_string = iperf_string.replace('nan', '0')
                     self.result = json.loads(iperf_string)
@@ -110,6 +128,33 @@
         return ('end' in self.result) and ('sum_received' in self.result['end']
                                            or 'sum' in self.result['end'])
 
+    def _get_reporting_speed(self, network_speed_in_bits_per_second):
+        """Sets the units for the network speed reporting based on how the
+        object was initiated.  Defaults to Megabytes per second.  Currently
+        supported, bits per second (bits), kilobits per second (kbits), megabits
+        per second (mbits), gigabits per second (gbits), bytes per second
+        (bytes), kilobits per second (kbytes), megabits per second (mbytes),
+        gigabytes per second (gbytes).
+
+        Args:
+            network_speed_in_bits_per_second: The network speed from iperf in
+                bits per second.
+
+        Returns:
+            The value of the throughput in the appropriate units.
+        """
+        speed_divisor = 1
+        print(self.reporting_speed_units)
+        if self.reporting_speed_units[1:].lower() == 'bytes':
+            speed_divisor = speed_divisor * BITS_IN_BYTE
+        if self.reporting_speed_units[0:1].lower() == 'k':
+            speed_divisor = speed_divisor * KILOBITS
+        if self.reporting_speed_units[0:1].lower() == 'm':
+            speed_divisor = speed_divisor * MEGABITS
+        if self.reporting_speed_units[0:1].lower() == 'g':
+            speed_divisor = speed_divisor * GIGABITS
+        return network_speed_in_bits_per_second / speed_divisor
+
     def get_json(self):
         """Returns the raw json output from iPerf."""
         return self.result
@@ -131,7 +176,7 @@
         if not self._has_data() or 'sum' not in self.result['end']:
             return None
         bps = self.result['end']['sum']['bits_per_second']
-        return bps / 8 / 1024 / 1024
+        return self._get_reporting_speed(bps)
 
     @property
     def avg_receive_rate(self):
@@ -143,7 +188,7 @@
         if not self._has_data() or 'sum_received' not in self.result['end']:
             return None
         bps = self.result['end']['sum_received']['bits_per_second']
-        return bps / 8 / 1024 / 1024
+        return self._get_reporting_speed(bps)
 
     @property
     def avg_send_rate(self):
@@ -155,7 +200,7 @@
         if not self._has_data() or 'sum_sent' not in self.result['end']:
             return None
         bps = self.result['end']['sum_sent']['bits_per_second']
-        return bps / 8 / 1024 / 1024
+        return self._get_reporting_speed(bps)
 
     @property
     def instantaneous_rates(self):
@@ -167,7 +212,7 @@
         if not self._has_data():
             return None
         intervals = [
-            interval['sum']['bits_per_second'] / 8 / 1024 / 1024
+            self._get_reporting_speed(interval['sum']['bits_per_second'])
             for interval in self.result['intervals']
         ]
         return intervals
@@ -199,10 +244,11 @@
         """
         if not self._has_data():
             return None
-        instantaneous_rates = self.instantaneous_rates[iperf_ignored_interval:
-                                                       -1]
+        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
@@ -256,7 +302,7 @@
         Note: If the directory for the file path does not exist, it will be
         created.
 
-        Args:
+        Args:s
             tag: The tag passed in to the server run.
         """
         out_dir = self.log_path
@@ -297,7 +343,6 @@
 
 class IPerfServer(IPerfServerBase):
     """Class that handles iperf server commands on localhost."""
-
     def __init__(self, port=5201):
         super().__init__(port)
         self._hinted_port = port
@@ -335,8 +380,9 @@
         if self._last_opened_file:
             self._last_opened_file.close()
         self._last_opened_file = open(self._current_log_file, 'w')
-        self._iperf_process = subprocess.Popen(
-            command, stdout=self._last_opened_file, stderr=subprocess.DEVNULL)
+        self._iperf_process = subprocess.Popen(command,
+                                               stdout=self._last_opened_file,
+                                               stderr=subprocess.DEVNULL)
         for attempts_left in reversed(range(3)):
             try:
                 self._port = int(
@@ -374,15 +420,22 @@
 
 class IPerfServerOverSsh(IPerfServerBase):
     """Class that handles iperf3 operations on remote machines."""
-
-    def __init__(self, ssh_config, port):
+    def __init__(self, ssh_config, port, test_interface=None):
         super().__init__(port)
         ssh_settings = settings.from_config(ssh_config)
         self._ssh_session = connection.SshConnection(ssh_settings)
 
-        self._iperf_command = 'iperf3 -s -J -p {}'.format(self.port)
         self._iperf_pid = None
         self._current_tag = None
+        self.hostname = ssh_settings.hostname
+        try:
+            # A test interface can only be found if an ip address is specified.
+            # A fully qualified hostname will return None for the
+            # test_interface.
+            self.test_interface = self._get_test_interface_based_on_ip(
+                test_interface)
+        except Exception:
+            self.test_interface = None
 
     @property
     def port(self):
@@ -395,7 +448,46 @@
     def _get_remote_log_path(self):
         return 'iperf_server_port%s.log' % self.port
 
-    def start(self, extra_args='', tag=''):
+    def _get_test_interface_based_on_ip(self, test_interface):
+        """Gets the test interface for a particular IP if the test interface
+            passed in test_interface is None
+
+        Args:
+            test_interface: Either a interface name, ie eth0, or None
+
+        Returns:
+            The name of the test interface.
+        """
+        if test_interface:
+            return test_interface
+        return utils.get_interface_based_on_ip(self._ssh_session,
+                                               self.hostname)
+
+    def get_interface_ip_addresses(self, interface):
+        """Gets all of the ip addresses, ipv4 and ipv6, associated with a
+           particular interface name.
+
+        Args:
+            interface: The interface name on the device, ie eth0
+
+    Returns:
+        A list of dictionaries of the the various IP addresses:
+            ipv4_private_local_addresses: Any 192.168, 172.16, or 10
+                addresses
+            ipv4_public_addresses: Any IPv4 public addresses
+            ipv6_link_local_addresses: Any fe80:: addresses
+            ipv6_private_local_addresses: Any fd00:: addresses
+            ipv6_public_addresses: Any publicly routable addresses
+    """
+        return utils.get_interface_ip_addresses(self._ssh_session, interface)
+
+    def renew_test_interface_ip_address(self):
+        """Renews the test interface's IP address.  Necessary for changing
+           DHCP scopes during a test.
+        """
+        utils.renew_linux_ip_address(self._ssh_session, self.test_interface)
+
+    def start(self, extra_args='', tag='', iperf_binary=None):
         """Starts iperf server on specified machine and port.
 
         Args:
@@ -403,12 +495,22 @@
                 server with.
             tag: Appended to log file name to identify logs from different
                 iperf runs.
+            iperf_binary: Location of iperf3 binary. If none, it is assumed the
+                the binary is in the path.
         """
         if self.started:
             return
 
+        if not iperf_binary:
+            logging.debug('No iperf3 binary specified.  '
+                          'Assuming iperf3 is in the path.')
+            iperf_binary = 'iperf3'
+        else:
+            logging.debug('Using iperf3 binary located at %s' % iperf_binary)
+        iperf_command = '{} -s -J -p {}'.format(iperf_binary, self.port)
+
         cmd = '{cmd} {extra_flags} > {log_file}'.format(
-            cmd=self._iperf_command,
+            cmd=iperf_command,
             extra_flags=extra_args,
             log_file=self._get_remote_log_path())
 
@@ -463,8 +565,10 @@
         """
         if not _AndroidDeviceBridge._test_class:
             return {}
-        return {device.serial: device
-                for device in _AndroidDeviceBridge._test_class.android_devices}
+        return {
+            device.serial: device
+            for device in _AndroidDeviceBridge._test_class.android_devices
+        }
 
 
 event_bus.register_subscription(
@@ -474,7 +578,6 @@
 
 class IPerfServerOverAdb(IPerfServerBase):
     """Class that handles iperf3 operations over ADB devices."""
-
     def __init__(self, android_device_or_serial, port):
         """Creates a new IPerfServerOverAdb object.
 
@@ -488,7 +591,6 @@
         super().__init__(port)
         self._android_device_or_serial = android_device_or_serial
 
-        self._iperf_command = 'iperf3 -s -J -p {}'.format(self.port)
         self._iperf_process = None
         self._current_tag = ''
 
@@ -511,7 +613,7 @@
     def _get_device_log_path(self):
         return '~/data/iperf_server_port%s.log' % self.port
 
-    def start(self, extra_args='', tag=''):
+    def start(self, extra_args='', tag='', iperf_binary=None):
         """Starts iperf server on an ADB device.
 
         Args:
@@ -519,13 +621,23 @@
                 server with.
             tag: Appended to log file name to identify logs from different
                 iperf runs.
+            iperf_binary: Location of iperf3 binary. If none, it is assumed the
+                the binary is in the path.
         """
         if self._iperf_process is not None:
             return
 
+        if not iperf_binary:
+            logging.debug('No iperf3 binary specified.  '
+                          'Assuming iperf3 is in the path.')
+            iperf_binary = 'iperf3'
+        else:
+            logging.debug('Using iperf3 binary located at %s' % iperf_binary)
+        iperf_command = '{} -s -J -p {}'.format(iperf_binary, self.port)
+
         self._iperf_process = self._android_device.adb.shell_nb(
             '{cmd} {extra_flags} > {log_file}'.format(
-                cmd=self._iperf_command,
+                cmd=iperf_command,
                 extra_flags=extra_args,
                 log_file=self._get_device_log_path()))
         self._iperf_process_adb_pid = ''
diff --git a/acts/framework/acts/controllers/monsoon_lib/api/hvpm/monsoon.py b/acts/framework/acts/controllers/monsoon_lib/api/hvpm/monsoon.py
index 97e4ce7..1353677 100644
--- a/acts/framework/acts/controllers/monsoon_lib/api/hvpm/monsoon.py
+++ b/acts/framework/acts/controllers/monsoon_lib/api/hvpm/monsoon.py
@@ -122,7 +122,8 @@
 
         assembly_line_builder = AssemblyLineBuilder(manager.Queue,
                                                     ThreadAssemblyLine)
-        assembly_line_builder.source(HvpmTransformer(self.serial, duration))
+        assembly_line_builder.source(
+            HvpmTransformer(self.serial, duration + measure_after_seconds))
         if hz != 5000:
             assembly_line_builder.into(DownSampler(int(5000 / hz)))
         if output_path:
diff --git a/acts/framework/acts/controllers/sl4a_lib/rpc_client.py b/acts/framework/acts/controllers/sl4a_lib/rpc_client.py
index e08ffb0..2f40bee 100644
--- a/acts/framework/acts/controllers/sl4a_lib/rpc_client.py
+++ b/acts/framework/acts/controllers/sl4a_lib/rpc_client.py
@@ -276,8 +276,9 @@
                     break
         except BrokenPipeError as e:
             if self.is_alive:
-                self._log.exception('Exception %s happened for sl4a call %s',
-                                    e, method)
+                self._log.exception('The device disconnected during RPC call '
+                                    '%s. Please check the logcat for a crash '
+                                    'or disconnect.', method)
                 self.on_error(connection)
             else:
                 self._log.warning('The connection was killed during cleanup:')
diff --git a/acts/framework/acts/records.py b/acts/framework/acts/records.py
index a847ccb..e7738e4 100644
--- a/acts/framework/acts/records.py
+++ b/acts/framework/acts/records.py
@@ -20,7 +20,6 @@
 import copy
 import io
 import json
-import logging
 
 from acts import logger
 from acts.libs import yaml_writer
@@ -169,11 +168,6 @@
         self.skipped: A list of records for tests skipped.
     """
 
-    def __init__(self):
-        super().__init__()
-        self.controller_info = {}
-        self.extras = {}
-
     def __add__(self, r):
         """Overrides '+' operator for TestResult class.
 
@@ -186,7 +180,7 @@
         Returns:
             A TestResult instance that's the sum of two TestResult instances.
         """
-        if not isinstance(r, TestResult):
+        if not isinstance(r, MoblyTestResult):
             raise TypeError("Operand %s of type %s is not a TestResult." %
                             (r, type(r)))
         sum_result = TestResult()
@@ -195,31 +189,8 @@
             l_value = getattr(self, name)
             if isinstance(r_value, list):
                 setattr(sum_result, name, l_value + r_value)
-            elif isinstance(r_value, dict):
-                sum_dict = copy.deepcopy(l_value)
-                sum_dict.update(copy.deepcopy(r_value))
-                setattr(sum_result, name, sum_dict)
         return sum_result
 
-    def add_controller_info(self, name, info):
-        try:
-            json.dumps(info)
-        except TypeError:
-            logging.warning(("Controller info for %s is not JSON serializable!"
-                             " Coercing it to string.") % name)
-            self.controller_info[name] = str(info)
-            return
-        self.controller_info[name] = info
-
-    def set_extra_data(self, name, info):
-        try:
-            json.dumps(info)
-        except TypeError:
-            logging.warning("Controller info for %s is not JSON serializable! "
-                            "Coercing it to string." % name)
-            info = str(info)
-        self.extras[name] = info
-
     def json_str(self):
         """Converts this test result to a string in json format.
 
@@ -237,10 +208,10 @@
             A json-format string representing the test results.
         """
         d = collections.OrderedDict()
-        d["ControllerInfo"] = self.controller_info
+        d["ControllerInfo"] = {record.controller_name: record.controller_info
+                               for record in self.controller_info}
         d["Results"] = [record.to_dict() for record in self.executed]
         d["Summary"] = self.summary_dict()
-        d["Extras"] = self.extras
         d["Error"] = self.errors_list()
         json_str = json.dumps(d, indent=4)
         return json_str
diff --git a/acts/framework/acts/test_runner.py b/acts/framework/acts/test_runner.py
index 0d2142b..6420706 100644
--- a/acts/framework/acts/test_runner.py
+++ b/acts/framework/acts/test_runner.py
@@ -14,6 +14,7 @@
 #   See the License for the specific language governing permissions and
 #   limitations under the License.
 import itertools
+
 from future import standard_library
 
 standard_library.install_aliases()
@@ -240,19 +241,10 @@
 
         for test_cls_name_match in matches:
             test_cls = self.test_classes[test_cls_name_match]
-            if 'Preflight' in test_cls_name_match or (
-                    'Postflight' in test_cls_name_match):
-                test_case_iterations = 1
-            else:
-                test_case_iterations = self.test_run_config.user_params.get(
-                    keys.Config.key_test_case_iterations.value, 1)
-
             test_cls_instance = test_cls(self.test_run_config)
             try:
-                cls_result = test_cls_instance.run(test_cases,
-                                                   test_case_iterations)
+                cls_result = test_cls_instance.run(test_cases)
                 self.results += cls_result
-                self._write_results_to_file()
             except signals.TestAbortAll as e:
                 self.results += e.results
                 raise e
diff --git a/acts/framework/acts/test_utils/abstract_devices/bluetooth_device.py b/acts/framework/acts/test_utils/abstract_devices/bluetooth_device.py
index 8ffd19b..53890f8 100644
--- a/acts/framework/acts/test_utils/abstract_devices/bluetooth_device.py
+++ b/acts/framework/acts/test_utils/abstract_devices/bluetooth_device.py
@@ -148,7 +148,7 @@
             inspect.currentframe().f_code.co_name))
 
     def gatt_client_write_characteristic_without_response_by_handle(
-        self, peer_identifier, handle, value):
+            self, peer_identifier, handle, value):
         """Base generic Bluetooth interface. Only called if not overridden by
         another supported device.
         """
@@ -181,7 +181,7 @@
             inspect.currentframe().f_code.co_name))
 
     def gatt_client_enable_notifiy_characteristic_by_handle(
-        self, peer_identifier, handle):
+            self, peer_identifier, handle):
         """Base generic Bluetooth interface. Only called if not overridden by
         another supported device.
         """
@@ -189,7 +189,7 @@
             inspect.currentframe().f_code.co_name))
 
     def gatt_client_disable_notifiy_characteristic_by_handle(
-        self, peer_identifier, handle):
+            self, peer_identifier, handle):
         """Base generic Bluetooth interface. Only called if not overridden by
         another supported device.
         """
@@ -416,7 +416,7 @@
         self.device.droid.bluetoothStartPairingHelper(True)
 
     def gatt_client_write_characteristic_without_response_by_handle(
-        self, peer_identifier, handle, value):
+            self, peer_identifier, handle, value):
         """ Perform a GATT Client write Characteristic without response to
         remote peer GATT server database.
 
@@ -536,7 +536,7 @@
         return event['data']['CharacteristicValue']
 
     def gatt_client_enable_notifiy_characteristic_by_handle(
-        self, peer_identifier, handle):
+            self, peer_identifier, handle):
         """ Perform a GATT Client enable Characteristic notification to remote
         peer GATT server database.
 
@@ -550,7 +550,7 @@
             inspect.currentframe().f_code.co_name))
 
     def gatt_client_disable_notifiy_characteristic_by_handle(
-        self, peer_identifier, handle):
+            self, peer_identifier, handle):
         """ Perform a GATT Client disable Characteristic notification to remote
         peer GATT server database.
 
@@ -862,7 +862,7 @@
         self.device.btc_lib.setName(name)
 
     def gatt_client_write_characteristic_without_response_by_handle(
-        self, peer_identifier, handle, value):
+            self, peer_identifier, handle, value):
         """ Perform a GATT Client write Characteristic without response to
         remote peer GATT server database.
 
@@ -883,7 +883,7 @@
         if result.get("error") is not None:
             self.log.error(
                 "Failed to write characteristic handle {} with err: {}".format(
-                    peer_identifier, result.get("error")))
+                    handle, result.get("error")))
             return False
         return True
 
@@ -909,7 +909,7 @@
         if result.get("error") is not None:
             self.log.error(
                 "Failed to write characteristic handle {} with err: {}".format(
-                    peer_identifier, result.get("error")))
+                    handle, result.get("error")))
             return False
         return True
 
@@ -933,7 +933,7 @@
         if result.get("error") is not None:
             self.log.error(
                 "Failed to read characteristic handle {} with err: {}".format(
-                    peer_identifier, result.get("error")))
+                    handle, result.get("error")))
             return None
         return result.get("result")
 
@@ -961,12 +961,12 @@
         if result.get("error") is not None:
             self.log.error(
                 "Failed to read characteristic handle {} with err: {}".format(
-                    peer_identifier, result.get("error")))
+                    handle, result.get("error")))
             return None
         return result.get("result")
 
     def gatt_client_enable_notifiy_characteristic_by_handle(
-        self, peer_identifier, handle):
+            self, peer_identifier, handle):
         """ Perform a GATT Client enable Characteristic notification to remote
         peer GATT server database.
 
@@ -985,12 +985,12 @@
         if result.get("error") is not None:
             self.log.error(
                 "Failed to enable characteristic notifications for handle {} "
-                "with err: {}".format(peer_identifier, result.get("error")))
+                "with err: {}".format(handle, result.get("error")))
             return None
         return result.get("result")
 
     def gatt_client_disable_notifiy_characteristic_by_handle(
-        self, peer_identifier, handle):
+            self, peer_identifier, handle):
         """ Perform a GATT Client disable Characteristic notification to remote
         peer GATT server database.
 
@@ -1231,7 +1231,7 @@
         self.device.btc_lib.forgetDevice(peer_identifier)
 
     def _find_service_id_and_connect_to_service_for_handle(
-        self, peer_identifier, handle):
+            self, peer_identifier, handle):
         fail_err = "Failed to find handle {} in Peer database."
         try:
             services = self.device.gattc_lib.listServices(peer_identifier)
diff --git a/acts/framework/acts/test_utils/abstract_devices/utils_lib/wlan_utils.py b/acts/framework/acts/test_utils/abstract_devices/utils_lib/wlan_utils.py
index 745d35f..d4af3c3 100644
--- a/acts/framework/acts/test_utils/abstract_devices/utils_lib/wlan_utils.py
+++ b/acts/framework/acts/test_utils/abstract_devices/utils_lib/wlan_utils.py
@@ -25,8 +25,8 @@
 
        Args: Args match setup_ap_and_associate
     """
-    asserts.assert_true(
-        setup_ap_and_associate(*args, **kwargs), 'Failed to associate.')
+    asserts.assert_true(setup_ap_and_associate(*args, **kwargs),
+                        'Failed to associate.')
     asserts.explicit_pass('Successfully associated.')
 
 
@@ -49,7 +49,8 @@
                            check_connectivity=False,
                            n_capabilities=None,
                            ac_capabilities=None,
-                           vht_bandwidth=None):
+                           vht_bandwidth=None,
+                           setup_bridge=False):
     """Sets up the AP and associates a client.
 
     Args:
@@ -73,14 +74,13 @@
              beacon_interval, dtim_period, frag_threshold, rts_threshold,
              force_wmm, hidden, security, additional_ap_parameters, password,
              check_connectivity, n_capabilities, ac_capabilities,
-             vht_bandwidth)
+             vht_bandwidth, setup_bridge)
 
-    return associate(
-        client,
-        ssid,
-        password,
-        check_connectivity=check_connectivity,
-        hidden=hidden)
+    return associate(client,
+                     ssid,
+                     password,
+                     check_connectivity=check_connectivity,
+                     hidden=hidden)
 
 
 def setup_ap(access_point,
@@ -101,7 +101,8 @@
              check_connectivity=False,
              n_capabilities=None,
              ac_capabilities=None,
-             vht_bandwidth=None):
+             vht_bandwidth=None,
+             setup_bridge=False):
     """Sets up the AP.
 
     Args:
@@ -120,27 +121,27 @@
         password: Password to connect to WLAN if necessary.
         check_connectivity: Whether to check for internet connectivity.
     """
-    ap = hostapd_ap_preset.create_ap_preset(
-        profile_name=profile_name,
-        iface_wlan_2g=access_point.wlan_2g,
-        iface_wlan_5g=access_point.wlan_5g,
-        channel=channel,
-        ssid=ssid,
-        mode=mode,
-        short_preamble=preamble,
-        beacon_interval=beacon_interval,
-        dtim_period=dtim_period,
-        frag_threshold=frag_threshold,
-        rts_threshold=rts_threshold,
-        force_wmm=force_wmm,
-        hidden=hidden,
-        bss_settings=[],
-        security=security,
-        n_capabilities=n_capabilities,
-        ac_capabilities=ac_capabilities,
-        vht_bandwidth=vht_bandwidth)
-    access_point.start_ap(
-        hostapd_config=ap, additional_parameters=additional_ap_parameters)
+    ap = hostapd_ap_preset.create_ap_preset(profile_name=profile_name,
+                                            iface_wlan_2g=access_point.wlan_2g,
+                                            iface_wlan_5g=access_point.wlan_5g,
+                                            channel=channel,
+                                            ssid=ssid,
+                                            mode=mode,
+                                            short_preamble=preamble,
+                                            beacon_interval=beacon_interval,
+                                            dtim_period=dtim_period,
+                                            frag_threshold=frag_threshold,
+                                            rts_threshold=rts_threshold,
+                                            force_wmm=force_wmm,
+                                            hidden=hidden,
+                                            bss_settings=[],
+                                            security=security,
+                                            n_capabilities=n_capabilities,
+                                            ac_capabilities=ac_capabilities,
+                                            vht_bandwidth=vht_bandwidth)
+    access_point.start_ap(hostapd_config=ap,
+                          setup_bridge=setup_bridge,
+                          additional_parameters=additional_ap_parameters)
 
 
 def associate(client,
@@ -157,8 +158,10 @@
         check_connectivity: Whether to check internet connectivity.
         hidden: If the WLAN is hidden or not.
     """
-    return client.associate(
-        ssid, password, check_connectivity=check_connectivity, hidden=hidden)
+    return client.associate(ssid,
+                            password,
+                            check_connectivity=check_connectivity,
+                            hidden=hidden)
 
 
 def status(client):
diff --git a/acts/framework/acts/test_utils/abstract_devices/wlan_device.py b/acts/framework/acts/test_utils/abstract_devices/wlan_device.py
index 3ec32bc..dc3544a 100644
--- a/acts/framework/acts/test_utils/abstract_devices/wlan_device.py
+++ b/acts/framework/acts/test_utils/abstract_devices/wlan_device.py
@@ -14,6 +14,9 @@
 #   See the License for the specific language governing permissions and
 #   limitations under the License.
 
+import inspect
+import logging
+
 import acts.test_utils.wifi.wifi_test_utils as wutils
 
 from acts import asserts
@@ -33,8 +36,8 @@
     elif isinstance(hardware_device, AndroidDevice):
         return AndroidWlanDevice(hardware_device)
     else:
-        raise ValueError(
-            'Unable to create WlanDevice for type %s' % type(hardware_device))
+        raise ValueError('Unable to create WlanDevice for type %s' %
+                         type(hardware_device))
 
 
 class WlanDevice(object):
@@ -49,37 +52,42 @@
 
     def __init__(self, device):
         self.device = device
+        self.log = logging
 
     def wifi_toggle_state(self, state):
         """Base generic WLAN interface.  Only called if not overridden by
         another supported device.
         """
-        raise NotImplementedError('wifi_toggle_state must be defined.')
+        raise NotImplementedError("{} must be defined.".format(
+            inspect.currentframe().f_code.co_name))
 
     def reset_wifi(self):
         """Base generic WLAN interface.  Only called if not overridden by
         another supported device.
         """
-        raise NotImplementedError('reset_wifi must be defined.')
+        raise NotImplementedError("{} must be defined.".format(
+            inspect.currentframe().f_code.co_name))
 
     def take_bug_report(self, test_name, begin_time):
         """Base generic WLAN interface.  Only called if not overridden by
         another supported device.
         """
-        raise NotImplementedError('take_bug_report must be defined.')
+        raise NotImplementedError("{} must be defined.".format(
+            inspect.currentframe().f_code.co_name))
 
     def get_log(self, test_name, begin_time):
         """Base generic WLAN interface.  Only called if not overridden by
         another supported device.
         """
-        raise NotImplementedError('get_log( must be defined.')
+        raise NotImplementedError("{} must be defined.".format(
+            inspect.currentframe().f_code.co_name))
 
     def turn_location_off_and_scan_toggle_off(self):
         """Base generic WLAN interface.  Only called if not overridden by
         another supported device.
         """
-        raise NotImplementedError('turn_location_off_and_scan_toggle_off'
-                                  ' must be defined.')
+        raise NotImplementedError("{} must be defined.".format(
+            inspect.currentframe().f_code.co_name))
 
     def associate(self,
                   target_ssid,
@@ -89,13 +97,29 @@
         """Base generic WLAN interface.  Only called if not overriden by
         another supported device.
         """
-        raise NotImplementedError('associate must be defined.')
+        raise NotImplementedError("{} must be defined.".format(
+            inspect.currentframe().f_code.co_name))
 
     def disconnect(self):
         """Base generic WLAN interface.  Only called if not overridden by
         another supported device.
         """
-        raise NotImplementedError('disconnect must be defined.')
+        raise NotImplementedError("{} must be defined.".format(
+            inspect.currentframe().f_code.co_name))
+
+    def get_wlan_interface_id_list(self):
+        """Base generic WLAN interface.  Only called if not overridden by
+        another supported device.
+        """
+        raise NotImplementedError("{} must be defined.".format(
+            inspect.currentframe().f_code.co_name))
+
+    def destroy_wlan_interface(self, iface_id):
+        """Base generic WLAN interface.  Only called if not overridden by
+        another supported device.
+        """
+        raise NotImplementedError("{} must be defined.".format(
+            inspect.currentframe().f_code.co_name))
 
 
 class AndroidWlanDevice(WlanDevice):
@@ -163,6 +187,12 @@
     def disconnect(self):
         wutils.turn_location_off_and_scan_toggle_off(self.device)
 
+    def get_wlan_interface_id_list(self):
+        pass
+
+    def destroy_wlan_interface(self, iface_id):
+        pass
+
 
 class FuchsiaWlanDevice(WlanDevice):
     """Class wrapper for an Fuchsia WLAN device.
@@ -215,24 +245,50 @@
         connection_response = self.device.wlan_lib.wlanConnectToNetwork(
             target_ssid, target_pwd=target_pwd)
 
-        return self.device.check_connect_response(
-            connection_response)
+        return self.device.check_connect_response(connection_response)
 
     def disconnect(self):
         """Function to disconnect from a Fuchsia WLAN device.
            Asserts if disconnect was not successful.
         """
         disconnect_response = self.device.wlan_lib.wlanDisconnect()
-        asserts.assert_true(self.device.check_disconnect_response(
-            disconnect_response), 'Failed to disconnect.')
+        asserts.assert_true(
+            self.device.check_disconnect_response(disconnect_response),
+            'Failed to disconnect.')
 
     def status(self):
         return self.device.wlan_lib.wlanStatus()
 
     def ping(self, dest_ip, count=3, interval=1000, timeout=1000, size=25):
-        return self.device.ping(
-            dest_ip,
-            count=count,
-            interval=interval,
-            timeout=timeout,
-            size=size)
+        return self.device.ping(dest_ip,
+                                count=count,
+                                interval=interval,
+                                timeout=timeout,
+                                size=size)
+
+    def get_wlan_interface_id_list(self):
+        """Function to list available WLAN interfaces.
+
+        Returns:
+            A list of wlan interface IDs.
+        """
+        return self.device.wlan_lib.wlanGetIfaceIdList().get('result')
+
+    def destroy_wlan_interface(self, iface_id):
+        """Function to associate a Fuchsia WLAN device.
+
+        Args:
+            target_ssid: SSID to associate to.
+            target_pwd: Password for the SSID, if necessary.
+            check_connectivity: Whether to check for internet connectivity.
+            hidden: Whether the network is hidden.
+        Returns:
+            True if successfully destroyed wlan interface, False if not.
+        """
+        result = self.device.wlan_lib.wlanDestroyIface(iface_id)
+        if result.get('error') is None:
+            return True
+        else:
+            self.log.error("Failed to destroy interface with: {}".format(
+                result.get('error')))
+            return False
diff --git a/acts/framework/acts/test_utils/bt/bt_test_utils.py b/acts/framework/acts/test_utils/bt/bt_test_utils.py
index aea9fb2..83b74e1 100644
--- a/acts/framework/acts/test_utils/bt/bt_test_utils.py
+++ b/acts/framework/acts/test_utils/bt/bt_test_utils.py
@@ -24,6 +24,7 @@
 from queue import Empty
 from subprocess import call
 
+from acts import asserts
 from acts.test_utils.bt.bt_constants import adv_fail
 from acts.test_utils.bt.bt_constants import adv_succ
 from acts.test_utils.bt.bt_constants import batch_scan_not_supported_list
@@ -58,7 +59,6 @@
 from acts.test_utils.tel.tel_test_utils import verify_http_connection
 from acts.utils import exe_cmd
 
-from acts import context
 from acts import utils
 
 log = logging
@@ -1745,3 +1745,55 @@
         log.error("Mismatch! Read: {}, Expected: {}".format(read_msg, msg))
         return False
     return True
+
+
+class MediaControlOverSl4a(object):
+    """Media control using sl4a facade for general purpose.
+
+    """
+    def __init__(self, android_device, music_file):
+        """Initialize the media_control class.
+
+        Args:
+            android_dut: android_device object
+            music_file: location of the music file
+        """
+        self.android_device = android_device
+        self.music_file = music_file
+
+    def play(self):
+        """Play media.
+
+        """
+        self.android_device.droid.mediaPlayOpen('file://%s' % self.music_file,
+                                                'default', True)
+        playing = self.android_device.droid.mediaIsPlaying()
+        asserts.assert_true(playing,
+                            'Failed to play music %s' % self.music_file)
+
+    def pause(self):
+        """Pause media.
+
+        """
+        self.android_device.droid.mediaPlayPause('default')
+        paused = not self.android_device.droid.mediaIsPlaying()
+        asserts.assert_true(paused,
+                            'Failed to pause music %s' % self.music_file)
+
+    def resume(self):
+        """Resume media.
+
+        """
+        self.android_device.droid.mediaPlayStart('default')
+        playing = self.android_device.droid.mediaIsPlaying()
+        asserts.assert_true(playing,
+                            'Failed to play music %s' % self.music_file)
+
+    def stop(self):
+        """Stop media.
+
+        """
+        self.android_device.droid.mediaPlayStop('default')
+        stopped = not self.android_device.droid.mediaIsPlaying()
+        asserts.assert_true(stopped,
+                            'Failed to stop music %s' % self.music_file)
diff --git a/acts/framework/acts/test_utils/coex/audio_capture.py b/acts/framework/acts/test_utils/coex/audio_capture.py
deleted file mode 100644
index bb29dcc..0000000
--- a/acts/framework/acts/test_utils/coex/audio_capture.py
+++ /dev/null
@@ -1,159 +0,0 @@
-#!/usr/bin/env python3
-#
-# Copyright (C) 2018 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License"); you may not
-# use this file except in compliance with the License. You may obtain a copy of
-# the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-# License for the specific language governing permissions and limitations under
-# the License.
-
-import argparse
-import json
-import logging
-import os
-import pyaudio
-import wave
-
-RECORD_FILE_TEMPLATE = 'recorded_audio_%s.wav'
-
-
-class DeviceNotFound(Exception):
-    """Raises exception if audio capture device is not found."""
-
-# TODO: (@sairamganesh) This class will be deprecated for
-# ../acts/test_utils/coex/audio_capture_device.py
-
-
-class AudioCapture:
-
-    def __init__(self, test_params, path):
-        """Creates object to pyaudio and defines audio parameters.
-
-        Args:
-            test_params: Audio parameters fetched from config.
-            path: Result path.
-        """
-        self.audio = pyaudio.PyAudio()
-        self.audio_format = pyaudio.paInt16
-        self.audio_params = test_params
-        self.channels = self.audio_params["channel"]
-        self.chunk = self.audio_params["chunk"]
-        self.sample_rate = self.audio_params["sample_rate"]
-        self.file_counter = 0
-        self.__input_device = None
-        self.record_file_template = os.path.join(path, RECORD_FILE_TEMPLATE)
-        if not self.audio_params["ssh_config"]:
-            self.__input_device = self.__get_input_device()
-
-    @property
-    def name(self):
-        try:
-            return self.audio_params["ssh_config"]["host"]
-        except KeyError:
-            return self.__input_device["name"]
-
-    def __get_input_device(self):
-        """Checks for the audio capture device."""
-        if self.__input_device is None:
-            for i in range(self.audio.get_device_count()):
-                device_info = self.audio.get_device_info_by_index(i)
-                logging.info("Device Information {}".format(device_info))
-                if self.audio_params['input_device'] in device_info['name']:
-                    self.__input_device = device_info
-                    break
-            else:
-                logging.error("Audio Capture device {} not found.".format(
-                    self.audio_params["input_device"]))
-                raise DeviceNotFound("Audio Capture Input device not found")
-        return self.__input_device
-
-    def capture_and_store_audio(self, trim_beginning=0, trim_end=0):
-        """Records the A2DP streaming.
-
-        Args:
-            trim_beginning: how many seconds to trim from the beginning
-            trim_end: how many seconds to trim from the end
-        """
-        if self.audio_params['ssh_config']:
-            self.__input_device = self.__get_input_device()
-        stream = self.audio.open(
-            format=self.audio_format,
-            channels=self.channels,
-            rate=self.sample_rate,
-            input=True,
-            frames_per_buffer=self.chunk,
-            input_device_index=self.__input_device['index'])
-        frames = []
-        b_chunks = trim_beginning * (self.sample_rate // self.chunk)
-        e_chunks = trim_end * (self.sample_rate // self.chunk)
-        total_chunks = self.sample_rate // self.chunk * self.audio_params[
-            'record_duration']
-        for i in range(total_chunks):
-            try:
-                data = stream.read(self.chunk, exception_on_overflow=False)
-            except IOError as ex:
-                logging.error("Cannot record audio :{}".format(ex))
-                return False
-            if b_chunks <= i < total_chunks - e_chunks:
-                frames.append(data)
-
-        stream.stop_stream()
-        stream.close()
-        status = self.write_record_file(frames)
-        return status
-
-    def last_fileno(self):
-        return self.next_fileno() - 1
-
-    def next_fileno(self):
-        counter = 0
-        while os.path.exists(self.record_file_template % counter):
-            counter += 1
-        return counter
-
-    def write_record_file(self, frames):
-        """Writes the recorded audio into the file.
-
-        Args:
-            frames: Recorded audio frames.
-        """
-        file_name = self.record_file_template % self.next_fileno()
-        logging.info('writing to %s' % file_name)
-        wf = wave.open(file_name, 'wb')
-        wf.setnchannels(self.channels)
-        wf.setsampwidth(self.audio.get_sample_size(self.audio_format))
-        wf.setframerate(self.sample_rate)
-        wf.writeframes(b''.join(frames))
-        wf.close()
-        return True
-
-    def terminate_audio(self):
-        """Terminates the pulse audio instance."""
-        self.audio.terminate()
-
-
-if __name__ == '__main__':
-    parser = argparse.ArgumentParser()
-    parser.add_argument(
-        '-p',
-        '--path',
-        type=str,
-        help="Contains path where the recorded files to be stored")
-    parser.add_argument(
-        '-t',
-        '--test_params',
-        type=json.loads,
-        help="Contains sample rate, channels,"
-             " chunk and device index for recording.")
-    args = parser.parse_args()
-    audio = AudioCapture(args.test_params, args.path)
-    audio.capture_and_store_audio(args.test_params['trim_beginning'],
-                                  args.test_params['trim_end'])
-    audio.terminate_audio()
diff --git a/acts/framework/acts/test_utils/coex/audio_capture_device.py b/acts/framework/acts/test_utils/coex/audio_capture_device.py
index 924bf4a..f99f6a8 100644
--- a/acts/framework/acts/test_utils/coex/audio_capture_device.py
+++ b/acts/framework/acts/test_utils/coex/audio_capture_device.py
@@ -57,6 +57,21 @@
     def last_fileno(self):
         return self.next_fileno - 1
 
+    @property
+    def get_last_record_duration_millis(self):
+        """Get duration of most recently recorded file.
+
+        Returns:
+            duration (float): duration of recorded file in milliseconds.
+        """
+        latest_file_path = self.wave_file % self.last_fileno
+        print (latest_file_path)
+        with wave.open(latest_file_path, 'r') as f:
+            frames = f.getnframes()
+            rate = f.getframerate()
+            duration = (frames / float(rate)) * 1000
+        return duration
+
     def write_record_file(self, audio_params, frames):
         """Writes the recorded audio into the file.
 
diff --git a/acts/framework/acts/test_utils/coex/audio_test_utils.py b/acts/framework/acts/test_utils/coex/audio_test_utils.py
index b514712..f4dc403 100644
--- a/acts/framework/acts/test_utils/coex/audio_test_utils.py
+++ b/acts/framework/acts/test_utils/coex/audio_test_utils.py
@@ -15,17 +15,15 @@
 # the License.
 
 import logging
+import numpy
 import os
-import wave
+import scipy.io.wavfile as sciwav
 
+from acts.test_utils.coex.audio_capture_device import AudioCaptureBase
 from acts.test_utils.coex.audio_capture_device import CaptureAudioOverAdb
 from acts.test_utils.coex.audio_capture_device import CaptureAudioOverLocal
-from acts.controllers.utils_lib.ssh import connection
-from acts.controllers.utils_lib.ssh import settings
 from acts.test_utils.audio_analysis_lib import audio_analysis
 from acts.test_utils.audio_analysis_lib.check_quality import quality_analysis
-from acts.test_utils.coex.audio_capture import AudioCapture
-from acts.test_utils.coex.audio_capture import RECORD_FILE_TEMPLATE
 
 ANOMALY_DETECTION_BLOCK_SIZE = audio_analysis.ANOMALY_DETECTION_BLOCK_SIZE
 ANOMALY_GROUPING_TOLERANCE = audio_analysis.ANOMALY_GROUPING_TOLERANCE
@@ -67,58 +65,21 @@
 class FileNotFound(Exception):
     """Raises Exception if file is not present"""
 
-# TODO @sairamganesh Rename this class to AudioCaptureResult and
-# remove duplicates which are in ../test_utils/coex/audio_capture_device.py.
 
-
-class SshAudioCapture(AudioCapture):
-
-    def __init__(self, test_params, path):
-        super(SshAudioCapture, self).__init__(test_params, path)
-        self.remote_path = path
-        self.ssh_session = None
-
-    def capture_audio(self, trim_beginning=0, trim_end=0):
-        """Captures audio and store results.
+class AudioCaptureResult(AudioCaptureBase):
+    def __init__(self, path, audio_params=None):
+        """Initializes Audio Capture Result class.
 
         Args:
-            trim_beginning: To trim audio at the start in seconds.
-            trim_end: To trim audio at the end in seconds.
-
-        Returns:
-            Returns exit status of ssh connection.
+            path: Path of audio capture result.
         """
-        if not trim_beginning:
-            trim_beginning = self.audio_params.get('trim_beginning', 0)
-        if not trim_end:
-            trim_end = self.audio_params.get('trim_end', 0)
-        if self.audio_params["ssh_config"]:
-            ssh_settings = settings.from_config(
-                self.audio_params["ssh_config"])
-            self.ssh_session = connection.SshConnection(ssh_settings)
-            cur_path = os.path.dirname(os.path.realpath(__file__))
-            local_path = os.path.join(cur_path, "audio_capture.py")
-            self.ssh_session.send_file(local_path,
-                                       self.audio_params["dest_path"])
-            path = self.audio_params["dest_path"]
-            test_params = str(self.audio_params).replace("\'", "\"")
-            self.cmd = "python3 audio_capture.py -p '{}' -t '{}'".format(
-                path, test_params)
-            job_result = self.ssh_session.run(self.cmd)
-            logging.debug("Job Result {}".format(job_result.stdout))
-            self.ssh_session.pull_file(
-                self.remote_path, os.path.join(
-                    self.audio_params["dest_path"], "*.wav"))
-            return bool(not job_result.exit_status)
-        else:
-            return self.capture_and_store_audio(trim_beginning, trim_end)
-
-    def terminate_and_store_audio_results(self):
-        """Terminates audio and stores audio files."""
-        if self.audio_params["ssh_config"]:
-            self.ssh_session.run('rm *.wav', ignore_status=True)
-        else:
-            self.terminate_audio()
+        super().__init__()
+        self.path = path
+        self.audio_params = audio_params
+        self.analysis_path = os.path.join(self.log_path,
+                                          ANALYSIS_FILE_TEMPLATE)
+        if self.audio_params:
+            self._trim_wave_file()
 
     def THDN(self, win_size=None, step_size=None, q=1, freq=None):
         """Calculate THD+N value for most recently recorded file.
@@ -137,19 +98,19 @@
             channel_results (list): THD+N value for each channel's signal.
                 List index corresponds to channel index.
         """
-        latest_file_path = self.record_file_template % self.last_fileno()
         if not (win_size and step_size):
-            return audio_analysis.get_file_THDN(filename=latest_file_path,
+            return audio_analysis.get_file_THDN(filename=self.path,
                                                 q=q,
                                                 freq=freq)
         else:
-            return audio_analysis.get_file_max_THDN(filename=latest_file_path,
+            return audio_analysis.get_file_max_THDN(filename=self.path,
                                                     step_size=step_size,
                                                     window_size=win_size,
                                                     q=q,
                                                     freq=freq)
 
-    def detect_anomalies(self, freq=None,
+    def detect_anomalies(self,
+                         freq=None,
                          block_size=ANOMALY_DETECTION_BLOCK_SIZE,
                          threshold=PATTERN_MATCHING_THRESHOLD,
                          tolerance=ANOMALY_GROUPING_TOLERANCE):
@@ -172,51 +133,59 @@
             channel_results (list): anomaly durations for each channel's signal.
                 List index corresponds to channel index.
         """
-        latest_file_path = self.record_file_template % self.last_fileno()
-        return audio_analysis.get_file_anomaly_durations(
-            filename=latest_file_path,
-            freq=freq,
-            block_size=block_size,
-            threshold=threshold,
-            tolerance=tolerance)
+        return audio_analysis.get_file_anomaly_durations(filename=self.path,
+                                                         freq=freq,
+                                                         block_size=block_size,
+                                                         threshold=threshold,
+                                                         tolerance=tolerance)
 
-    def get_last_record_duration_millis(self):
-        """Get duration of most recently recorded file.
+    @property
+    def analysis_fileno(self):
+        """Returns the file number to dump audio analysis results."""
+        counter = 0
+        while os.path.exists(self.analysis_path % counter):
+            counter += 1
+        return counter
 
-        Returns:
-            duration (float): duration of recorded file in milliseconds.
-        """
-        latest_file_path = self.record_file_template % self.last_fileno()
-        with wave.open(latest_file_path, 'r') as f:
-            frames = f.getnframes()
-            rate = f.getframerate()
-            duration = (frames / float(rate)) * 1000
-        return duration
-
-    def audio_quality_analysis(self, path):
+    def audio_quality_analysis(self):
         """Measures audio quality based on the audio file given as input.
 
-        Args:
-            path: Log path
-
         Returns:
             analysis_path on success.
         """
-        dest_file_path = os.path.join(path,
-                RECORD_FILE_TEMPLATE % self.last_fileno())
-        analysis_path = os.path.join(path,
-                ANALYSIS_FILE_TEMPLATE % self.last_fileno())
-        if not os.path.exists(dest_file_path):
+        analysis_path = self.analysis_path % self.analysis_fileno
+        if not os.path.exists(self.path):
             raise FileNotFound("Recorded file not found")
         try:
-            quality_analysis(
-                filename=dest_file_path,
-                output_file=analysis_path,
-                bit_width=bits_per_sample,
-                rate=self.audio_params["sample_rate"],
-                channel=self.audio_params["channel"],
-                spectral_only=False)
+            quality_analysis(filename=self.path,
+                             output_file=analysis_path,
+                             bit_width=bits_per_sample,
+                             rate=self.audio_params["sample_rate"],
+                             channel=self.audio_params["channel"],
+                             spectral_only=False)
         except Exception as err:
             logging.exception("Failed to analyze raw audio: %s" % err)
         return analysis_path
 
+    def _trim_wave_file(self):
+        """Trim wave files.
+
+        """
+        original_record_file_name = 'original_' + os.path.basename(self.path)
+        original_record_file_path = os.path.join(os.path.dirname(self.path),
+                                                 original_record_file_name)
+        os.rename(self.path, original_record_file_path)
+        fs, data = sciwav.read(original_record_file_path)
+        trim_start = self.audio_params['trim_start']
+        trim_end = self.audio_params['trim_end']
+        trim = numpy.array([[trim_start, trim_end]])
+        trim = trim * fs
+        new_wave_file_list = []
+        for elem in trim:
+            # To check start and end doesn't exceed raw data dimension
+            start_read = min(elem[0], data.shape[0] - 1)
+            end_read = min(elem[1], data.shape[0] - 1)
+            new_wave_file_list.extend(data[start_read:end_read])
+        new_wave_file = numpy.array(new_wave_file_list)
+
+        sciwav.write(self.path, fs, new_wave_file)
diff --git a/acts/framework/acts/test_utils/gnss/gnss_test_utils.py b/acts/framework/acts/test_utils/gnss/gnss_test_utils.py
index bbd78a5..443cbfd 100644
--- a/acts/framework/acts/test_utils/gnss/gnss_test_utils.py
+++ b/acts/framework/acts/test_utils/gnss/gnss_test_utils.py
@@ -228,7 +228,9 @@
         network: Dictionary with network info.
     """
     SSID = network[WifiEnums.SSID_KEY]
-    wutils.start_wifi_connection_scan_and_return_status(ad)
+    ad.ed.clear_all_events()
+    wutils.reset_wifi(ad)
+    wutils.start_wifi_connection_scan_and_ensure_network_found(ad, SSID)
     wutils.wifi_connect(ad, network, num_of_tries=5)
 
 
@@ -655,17 +657,17 @@
     raise signals.TestFailure("Fail to get %s location fixed within %d "
                               "attempts." % (type.upper(), retries))
 
-
-def start_ttff_by_gtw_gpstool(ad, ttff_mode, iteration):
+def start_ttff_by_gtw_gpstool(ad, ttff_mode, iteration, aid_data=False):
     """Identify which TTFF mode for different test items.
 
     Args:
         ad: An AndroidDevice object.
         ttff_mode: TTFF Test mode for current test item.
         iteration: Iteration of TTFF cycles.
+        aid_data: Boolean for identify aid_data existed or not
     """
     begin_time = get_current_epoch_time()
-    if ttff_mode == "hs" or ttff_mode == "ws":
+    if (ttff_mode == "hs" or ttff_mode == "ws") and not aid_data:
         ad.log.info("Wait 5 minutes to start TTFF %s..." % ttff_mode.upper())
         time.sleep(300)
     if ttff_mode == "cs":
@@ -1011,26 +1013,27 @@
     ad.log.error("GnssLocationProvider is unable to report location.")
     return False
 
-
-def check_network_location(ad, retries, location_type):
+def check_network_location(ad, retries, location_type, criteria=30):
     """Verify if NLP reports location after requesting via GPSTool.
 
     Args:
         ad: An AndroidDevice object.
         retries: Retry time.
         location_type: neworkLocationType of cell or wifi.
+        criteria: expected nlp return time, default 30 seconds
 
     Returns:
         True: NLP reports location.
         otherwise return False.
     """
+    criteria = criteria * 1000
     for i in range(retries):
         time.sleep(1)
         begin_time = get_current_epoch_time()
         ad.log.info("Try to get NLP status - attempt %d" % (i+1))
         ad.adb.shell(
             "am start -S -n com.android.gpstool/.GPSTool --es mode nlp")
-        while get_current_epoch_time() - begin_time <= 30000:
+        while get_current_epoch_time() - begin_time <= criteria:
             logcat_results = ad.search_logcat("LocationManagerService: "
                                               "incoming location: Location",
                                               begin_time)
diff --git a/acts/framework/acts/test_utils/power/PowerBTBaseTest.py b/acts/framework/acts/test_utils/power/PowerBTBaseTest.py
index bd7dcfb..8979822 100644
--- a/acts/framework/acts/test_utils/power/PowerBTBaseTest.py
+++ b/acts/framework/acts/test_utils/power/PowerBTBaseTest.py
@@ -37,14 +37,14 @@
         obj_atten: attenuator object, a single port attenuator
         attenuation_target: target attenuation level to reach to.
     """
-    attenuation_step_max = 5
+    attenuation_step_max = 20
     sign = lambda x: copysign(1, x)
     attenuation_delta = obj_atten.get_atten() - attenuation_target
     while abs(attenuation_delta) > attenuation_step_max:
         attenuation_intermediate = obj_atten.get_atten(
         ) - sign(attenuation_delta) * attenuation_step_max
         obj_atten.set_atten(attenuation_intermediate)
-        time.sleep(2)
+        time.sleep(5)
         attenuation_delta = obj_atten.get_atten() - attenuation_target
     obj_atten.set_atten(attenuation_target)
 
diff --git a/acts/framework/acts/test_utils/power/PowerBaseTest.py b/acts/framework/acts/test_utils/power/PowerBaseTest.py
index df669ae..53fbc7a 100644
--- a/acts/framework/acts/test_utils/power/PowerBaseTest.py
+++ b/acts/framework/acts/test_utils/power/PowerBaseTest.py
@@ -52,7 +52,6 @@
     """Create a random obj with unknown attributes and value.
 
     """
-
     def __init__(self, **kwargs):
         self.__dict__.update(kwargs)
 
@@ -71,7 +70,6 @@
     """Base class for all wireless power related tests.
 
     """
-
     def __init__(self, controllers):
 
         base_test.BaseTestClass.__init__(self, controllers)
@@ -80,8 +78,13 @@
         self.start_meas_time = 0
         self.rockbottom_script = None
         self.img_name = ''
+        self.dut = None
         self.power_logger = PowerMetricLogger.for_test_case()
 
+    @property
+    def final_test(self):
+        return self.current_test_name == self.results.requested[-1]
+
     def setup_class(self):
 
         self.log = logging.getLogger()
@@ -150,7 +153,7 @@
         self.mon_info = self.create_monsoon_info()
 
         # Sync device time, timezone and country code
-        utils.require_sl4a((self.dut,))
+        utils.require_sl4a((self.dut, ))
         utils.sync_device_time(self.dut)
         self.dut.droid.wifiSetCountryCode('US')
 
@@ -186,15 +189,22 @@
         self.power_logger.set_avg_power(self.power_result.metric_value)
         self.power_logger.set_testbed(self.testbed_name)
 
+        build_id = self.dut.build_info.get('incremental_build_id')
+        branch = self.user_params.get('branch')
+        target = self.dut.device_info.get('flavor')
+
+        self.power_logger.set_branch(branch)
+        self.power_logger.set_build_id(build_id)
+        self.power_logger.set_target(target)
+
         # Take Bugreport
         if self.bug_report:
             begin_time = utils.get_current_epoch_time()
             self.dut.take_bug_report(self.test_name, begin_time)
 
         # Allow the device to cooldown before executing the next test
-        last_test = self.current_test_name == self.results.requested[-1]
         cooldown = self.test_params.get('cooldown', None)
-        if cooldown and not last_test:
+        if cooldown and not self.final_test:
             time.sleep(cooldown)
 
     def teardown_class(self):
@@ -391,14 +401,13 @@
                                      '%s_%s.txt' % (tag, highest_value + 1))
 
         total_expected_samples = self.mon_info.freq * self.mon_info.duration
-        min_required_samples = (total_expected_samples
-                                * MIN_PERCENT_SAMPLE / 100)
+        min_required_samples = (total_expected_samples * MIN_PERCENT_SAMPLE /
+                                100)
         for retry_measure in range(1, MEASUREMENT_RETRY_COUNT + 1):
             # Resets the battery status right before the test starts.
             self.dut.adb.shell(RESET_BATTERY_STATS)
-            self.log.info(
-                'Starting power measurement, attempt #{}.'.format(
-                    retry_measure))
+            self.log.info('Starting power measurement, attempt #{}.'.format(
+                retry_measure))
             # Start the power measurement using monsoon.
             self.mon_info.dut.usb(PassthroughStates.AUTO)
             result = self.mon_info.dut.measure_power(
@@ -431,7 +440,8 @@
             except AttributeError:
                 # This attribute does not exist for HVPMs.
                 pass
-            self.log.error('Unable to gather enough samples to run validation.')
+            self.log.error(
+                'Unable to gather enough samples to run validation.')
 
     def process_iperf_results(self):
         """Get the iperf results and process.
@@ -456,7 +466,7 @@
             throughput = (math.fsum(
                 iperf_result.instantaneous_rates[self.start_meas_time:-1]
             ) / len(iperf_result.instantaneous_rates[self.start_meas_time:-1])
-                          ) * 8 * (1.024 ** 2)
+                          ) * 8 * (1.024**2)
 
             self.log.info('The average throughput is {}'.format(throughput))
         except ValueError:
diff --git a/acts/framework/acts/test_utils/power/cellular/__init__.py b/acts/framework/acts/test_utils/power/cellular/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/acts/framework/acts/test_utils/power/cellular/__init__.py
diff --git a/acts/framework/acts/test_utils/power/cellular/cellular_power_base_test.py b/acts/framework/acts/test_utils/power/cellular/cellular_power_base_test.py
index 23cc5fe..4b2b342 100644
--- a/acts/framework/acts/test_utils/power/cellular/cellular_power_base_test.py
+++ b/acts/framework/acts/test_utils/power/cellular/cellular_power_base_test.py
@@ -360,8 +360,7 @@
 
         # Instantiate a new simulation
         self.simulation = simulation_class(self.cellular_simulator, self.log,
-                                           self.dut,
-                                           self.test_params,
+                                           self.dut, self.test_params,
                                            self.calibration_table[sim_type])
 
     def ensure_valid_calibration_table(self, calibration_table):
diff --git a/acts/framework/acts/test_utils/power/loggers/power_metric_logger.py b/acts/framework/acts/test_utils/power/loggers/power_metric_logger.py
index 6738e09..09cf399 100644
--- a/acts/framework/acts/test_utils/power/loggers/power_metric_logger.py
+++ b/acts/framework/acts/test_utils/power/loggers/power_metric_logger.py
@@ -48,6 +48,15 @@
     def set_testbed(self, testbed):
         self.proto.testbed = testbed
 
+    def set_branch(self, branch):
+        self.proto.branch = branch
+
+    def set_build_id(self, build_id):
+        self.proto.build_id = build_id
+
+    def set_target(self, target):
+        self.proto.target = target
+
     def end(self, event):
         metric = ProtoMetric(name='spanner_power_metric', data=self.proto)
         return self.publisher.publish(metric)
diff --git a/acts/framework/acts/test_utils/power/loggers/protos/power_metric.proto b/acts/framework/acts/test_utils/power/loggers/protos/power_metric.proto
index a3c81ba..5cd9bf9 100644
--- a/acts/framework/acts/test_utils/power/loggers/protos/power_metric.proto
+++ b/acts/framework/acts/test_utils/power/loggers/protos/power_metric.proto
@@ -19,6 +19,9 @@
   optional float avg_power = 1; // Required
   optional string testbed = 2; // Required
   optional PowerCellularMetric cellular_metric = 3;
+  optional string branch = 4;
+  optional string build_id = 5;
+  optional string target = 6;
 }
 
 message PowerCellularMetric {
diff --git a/acts/framework/acts/test_utils/power/loggers/protos/power_metric_pb2.py b/acts/framework/acts/test_utils/power/loggers/protos/power_metric_pb2.py
index 0d205dd..6f29e20 100644
--- a/acts/framework/acts/test_utils/power/loggers/protos/power_metric_pb2.py
+++ b/acts/framework/acts/test_utils/power/loggers/protos/power_metric_pb2.py
@@ -19,7 +19,7 @@
   name='power_metric.proto',
   package='wireless.android.platform.testing.power.metrics',
   syntax='proto2',
-  serialized_pb=_b('\n\x12power_metric.proto\x12/wireless.android.platform.testing.power.metrics\"\x90\x01\n\x0bPowerMetric\x12\x11\n\tavg_power\x18\x01 \x01(\x02\x12\x0f\n\x07testbed\x18\x02 \x01(\t\x12]\n\x0f\x63\x65llular_metric\x18\x03 \x01(\x0b\x32\x44.wireless.android.platform.testing.power.metrics.PowerCellularMetric\"?\n\x13PowerCellularMetric\x12\x13\n\x0b\x61vg_dl_tput\x18\x01 \x01(\x02\x12\x13\n\x0b\x61vg_ul_tput\x18\x02 \x01(\x02')
+  serialized_pb=_b('\n\x12power_metric.proto\x12/wireless.android.platform.testing.power.metrics\"\xc2\x01\n\x0bPowerMetric\x12\x11\n\tavg_power\x18\x01 \x01(\x02\x12\x0f\n\x07testbed\x18\x02 \x01(\t\x12]\n\x0f\x63\x65llular_metric\x18\x03 \x01(\x0b\x32\x44.wireless.android.platform.testing.power.metrics.PowerCellularMetric\x12\x0e\n\x06\x62ranch\x18\x04 \x01(\t\x12\x10\n\x08\x62uild_id\x18\x05 \x01(\t\x12\x0e\n\x06target\x18\x06 \x01(\t\"?\n\x13PowerCellularMetric\x12\x13\n\x0b\x61vg_dl_tput\x18\x01 \x01(\x02\x12\x13\n\x0b\x61vg_ul_tput\x18\x02 \x01(\x02')
 )
 
 
@@ -53,6 +53,27 @@
       message_type=None, enum_type=None, containing_type=None,
       is_extension=False, extension_scope=None,
       options=None),
+    _descriptor.FieldDescriptor(
+      name='branch', full_name='wireless.android.platform.testing.power.metrics.PowerMetric.branch', index=3,
+      number=4, type=9, cpp_type=9, label=1,
+      has_default_value=False, default_value=_b("").decode('utf-8'),
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      options=None),
+    _descriptor.FieldDescriptor(
+      name='build_id', full_name='wireless.android.platform.testing.power.metrics.PowerMetric.build_id', index=4,
+      number=5, type=9, cpp_type=9, label=1,
+      has_default_value=False, default_value=_b("").decode('utf-8'),
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      options=None),
+    _descriptor.FieldDescriptor(
+      name='target', full_name='wireless.android.platform.testing.power.metrics.PowerMetric.target', index=5,
+      number=6, type=9, cpp_type=9, label=1,
+      has_default_value=False, default_value=_b("").decode('utf-8'),
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      options=None),
   ],
   extensions=[
   ],
@@ -66,7 +87,7 @@
   oneofs=[
   ],
   serialized_start=72,
-  serialized_end=216,
+  serialized_end=266,
 )
 
 
@@ -103,8 +124,8 @@
   extension_ranges=[],
   oneofs=[
   ],
-  serialized_start=218,
-  serialized_end=281,
+  serialized_start=268,
+  serialized_end=331,
 )
 
 _POWERMETRIC.fields_by_name['cellular_metric'].message_type = _POWERCELLULARMETRIC
diff --git a/acts/framework/acts/utils.py b/acts/framework/acts/utils.py
index 99c961a..b42ea21 100755
--- a/acts/framework/acts/utils.py
+++ b/acts/framework/acts/utils.py
@@ -19,6 +19,7 @@
 import copy
 import datetime
 import functools
+import IPy
 import json
 import logging
 import os
@@ -1381,3 +1382,97 @@
 def ascii_string(uc_string):
     """Converts unicode string to ascii"""
     return str(uc_string).encode('ASCII')
+
+
+def get_interface_ip_addresses(comm_channel, interface):
+    """Gets all of the ip addresses, ipv4 and ipv6, associated with a
+       particular interface name.
+
+    Args:
+        comm_channel: How to send commands to a device.  Can be ssh, adb serial,
+            etc.  Must have the run function implemented.
+        interface: The interface name on the device, ie eth0
+
+    Returns:
+        A list of dictionaries of the the various IP addresses:
+            ipv4_private_local_addresses: Any 192.168, 172.16, or 10
+                addresses
+            ipv4_public_addresses: Any IPv4 public addresses
+            ipv6_link_local_addresses: Any fe80:: addresses
+            ipv6_private_local_addresses: Any fd00:: addresses
+            ipv6_public_addresses: Any publicly routable addresses
+    """
+    ipv4_private_local_addresses = []
+    ipv4_public_addresses = []
+    ipv6_link_local_addresses = []
+    ipv6_private_local_addresses = []
+    ipv6_public_addresses = []
+    all_interfaces_and_addresses = comm_channel.run(
+        'ip -o addr | awk \'!/^[0-9]*: ?lo|link\/ether/ {gsub("/", " "); '
+        'print $2" "$4}\'').stdout
+    ifconfig_output = comm_channel.run('ifconfig %s' % interface).stdout
+    for interface_line in all_interfaces_and_addresses.split('\n'):
+        if interface != interface_line.split()[0]:
+            continue
+        on_device_ip = IPy.IP(interface_line.split()[1])
+        if on_device_ip.version() is 4:
+            if on_device_ip.iptype() == 'PRIVATE':
+                if str(on_device_ip) in ifconfig_output:
+                    ipv4_private_local_addresses.append(
+                        on_device_ip.strNormal())
+            elif on_device_ip.iptype() == 'PUBLIC':
+                if str(on_device_ip) in ifconfig_output:
+                    ipv4_public_addresses.append(on_device_ip.strNormal())
+        elif on_device_ip.version() is 6:
+            if on_device_ip.iptype() == 'LINKLOCAL':
+                if str(on_device_ip) in ifconfig_output:
+                    ipv6_link_local_addresses.append(on_device_ip.strNormal())
+            elif on_device_ip.iptype() == 'ULA':
+                if str(on_device_ip) in ifconfig_output:
+                    ipv6_private_local_addresses.append(
+                        on_device_ip.strNormal())
+            elif 'ALLOCATED' in on_device_ip.iptype():
+                if str(on_device_ip) in ifconfig_output:
+                    ipv6_public_addresses.append(on_device_ip.strNormal())
+    return {
+        'ipv4_private': ipv4_private_local_addresses,
+        'ipv4_public': ipv4_public_addresses,
+        'ipv6_link_local': ipv6_link_local_addresses,
+        'ipv6_private_local': ipv6_private_local_addresses,
+        'ipv6_public': ipv6_public_addresses
+    }
+
+
+def get_interface_based_on_ip(comm_channel, desired_ip_address):
+    """Gets the interface for a particular IP
+
+    Args:
+        comm_channel: How to send commands to a device.  Can be ssh, adb serial,
+            etc.  Must have the run function implemented.
+        desired_ip_address: The IP address that is being looked for on a device.
+
+    Returns:
+        The name of the test interface.
+    """
+
+    desired_ip_address = desired_ip_address.split('%', 1)[0]
+    all_ips_and_interfaces = comm_channel.run(
+        '(ip -o -4 addr show; ip -o -6 addr show) | '
+        'awk \'{print $2" "$4}\'').stdout
+    #ipv4_addresses = comm_channel.run(
+    #    'ip -o -4 addr show| awk \'{print $2": "$4}\'').stdout
+    #ipv6_addresses = comm_channel._ssh_session.run(
+    #    'ip -o -6 addr show| awk \'{print $2": "$4}\'').stdout
+    #if desired_ip_address in ipv4_addresses:
+    #    ip_addresses_to_search = ipv4_addresses
+    #elif desired_ip_address in ipv6_addresses:
+    #    ip_addresses_to_search = ipv6_addresses
+    for ip_address_and_interface in all_ips_and_interfaces.split('\n'):
+        if desired_ip_address in ip_address_and_interface:
+            return ip_address_and_interface.split()[1][:-1]
+    return None
+
+
+def renew_linux_ip_address(comm_channel, interface):
+    comm_channel.run('sudo dhclient -r %s' % interface)
+    comm_channel.run('sudo dhclient %s' % interface)
diff --git a/acts/framework/setup.py b/acts/framework/setup.py
index 32b8a93..59210f9 100755
--- a/acts/framework/setup.py
+++ b/acts/framework/setup.py
@@ -23,6 +23,7 @@
 import sys
 
 install_requires = [
+    'backoff',
     # Future needs to have a newer version that contains urllib.
     'future>=0.16.0',
     'mock',
@@ -39,6 +40,7 @@
     'xlsxwriter',
     'mobly',
     'grpcio',
+    'IPy',
     'Monsoon',
     # paramiko-ng is needed vs paramiko as currently paramiko does not support
     # ed25519 ssh keys, which is what Fuchsia uses.
@@ -58,7 +60,6 @@
     """Class used to execute unit tests using PyTest. This allows us to execute
     unit tests without having to install the package.
     """
-
     def finalize_options(self):
         test.test.finalize_options(self)
         self.test_args = ['-x', "tests"]
@@ -143,9 +144,8 @@
         try:
             import acts as acts_module
         except ImportError:
-            self.announce(
-                'Acts is not installed, nothing to uninstall.',
-                level=log.ERROR)
+            self.announce('Acts is not installed, nothing to uninstall.',
+                          level=log.ERROR)
             return
 
         while acts_module:
@@ -166,22 +166,21 @@
         os.path.join(framework_dir, 'acts', 'bin', 'monsoon.py')
     ]
 
-    setuptools.setup(
-        name='acts',
-        version='0.9',
-        description='Android Comms Test Suite',
-        license='Apache2.0',
-        packages=setuptools.find_packages(),
-        include_package_data=False,
-        tests_require=['pytest'],
-        install_requires=install_requires,
-        scripts=scripts,
-        cmdclass={
-            'test': PyTest,
-            'install_deps': ActsInstallDependencies,
-            'uninstall': ActsUninstall
-        },
-        url="http://www.android.com/")
+    setuptools.setup(name='acts',
+                     version='0.9',
+                     description='Android Comms Test Suite',
+                     license='Apache2.0',
+                     packages=setuptools.find_packages(),
+                     include_package_data=False,
+                     tests_require=['pytest'],
+                     install_requires=install_requires,
+                     scripts=scripts,
+                     cmdclass={
+                         'test': PyTest,
+                         'install_deps': ActsInstallDependencies,
+                         'uninstall': ActsUninstall
+                     },
+                     url="http://www.android.com/")
 
     if {'-u', '--uninstall', 'uninstall'}.intersection(sys.argv):
         installed_scripts = [
diff --git a/acts/framework/tests/acts_base_class_test.py b/acts/framework/tests/acts_base_class_test.py
index 9189a77..90fff56 100755
--- a/acts/framework/tests/acts_base_class_test.py
+++ b/acts/framework/tests/acts_base_class_test.py
@@ -1131,7 +1131,7 @@
             ]
             base_cls = base_test.BaseTestClass(mock_test_config)
             base_cls.register_controller(mock_controller)
-            self.assertEqual(base_cls.results.controller_info, {})
+            self.assertEqual(base_cls.results.controller_info, [])
         finally:
             setattr(mock_controller, 'get_info', get_info)
 
diff --git a/acts/framework/tests/acts_records_test.py b/acts/framework/tests/acts_records_test.py
index a744e1a..4224cff 100755
--- a/acts/framework/tests/acts_records_test.py
+++ b/acts/framework/tests/acts_records_test.py
@@ -16,6 +16,8 @@
 
 import unittest
 
+from mobly.records import ControllerInfoRecord
+
 from acts import records
 from acts import signals
 
@@ -169,17 +171,19 @@
         record1.test_pass(s)
         tr1 = records.TestResult()
         tr1.add_record(record1)
-        tr1.add_controller_info("MockDevice", ["magicA", "magicB"])
+        device1 = ControllerInfoRecord('TestClass', 'MockDevice', 'device1')
+        tr1.add_controller_info_record(device1)
         record2 = records.TestResultRecord(self.tn)
         record2.test_begin()
         s = signals.TestPass(self.details, self.json_extra)
         record2.test_pass(s)
         tr2 = records.TestResult()
         tr2.add_record(record2)
-        tr2.add_controller_info("MockDevice", ["magicC"])
+        device2 = ControllerInfoRecord('TestClass', 'MockDevice', 'device2')
+        tr2.add_controller_info_record(device2)
         tr2 += tr1
         self.assertTrue(tr2.passed, [tr1, tr2])
-        self.assertTrue(tr2.controller_info, {"MockDevice": ["magicC"]})
+        self.assertTrue(tr2.controller_info, [device1, device2])
 
     def test_result_add_operator_type_mismatch(self):
         record1 = records.TestResultRecord(self.tn)
diff --git a/acts/framework/tests/libs/version_selector_test.py b/acts/framework/tests/libs/version_selector_test.py
index ec23c73..6c3393e 100755
--- a/acts/framework/tests/libs/version_selector_test.py
+++ b/acts/framework/tests/libs/version_selector_test.py
@@ -110,7 +110,7 @@
         test_run_config.controller_configs = {}
 
         test_class = VersionedTestClass(test_run_config)
-        test_class.run(['test_1', 'test_2'], 1)
+        test_class.run(['test_1', 'test_2'])
 
         self.assertIn('Executed 2', test_class.results.summary_str(),
                       'One or more of the test cases did not execute.')
diff --git a/acts/framework/tests/test_utils/power/tel/lab/__init__.py b/acts/framework/tests/test_utils/power/tel/lab/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/acts/framework/tests/test_utils/power/tel/lab/__init__.py
diff --git a/acts/framework/tests/test_utils/power/tel/lab/consume_parameter_test.py b/acts/framework/tests/test_utils/power/tel/lab/consume_parameter_test.py
new file mode 100644
index 0000000..ad63848
--- /dev/null
+++ b/acts/framework/tests/test_utils/power/tel/lab/consume_parameter_test.py
@@ -0,0 +1,88 @@
+#!/usr/bin/env python3
+#
+#   Copyright 2019 - The Android Open Source Project
+#
+#   Licensed under the Apache License, Version 2.0 (the "License");
+#   you may not use this file except in compliance with the License.
+#   You may obtain a copy of the License at
+#
+#       http://www.apache.org/licenses/LICENSE-2.0
+#
+#   Unless required by applicable law or agreed to in writing, software
+#   distributed under the License is distributed on an "AS IS" BASIS,
+#   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+#   See the License for the specific language governing permissions and
+#   limitations under the License.
+
+import unittest
+import mobly.config_parser as mobly_config_parser
+import tests.test_utils.power.tel.lab.mock_bokeh
+from unittest import mock
+
+
+class ConsumeParameterTest(unittest.TestCase):
+    """ Unit tests for testing the consumption of test name parameters
+      for instances of PowerCellularLabBaseTest
+    """
+    @classmethod
+    def setUpClass(self):
+        from acts.test_utils.power.cellular.cellular_power_base_test import PowerCellularLabBaseTest as PCBT
+        self.PCBT = PCBT
+        PCBT.log = mock.Mock()
+        PCBT.log_path = ''
+
+    def setUp(self):
+        self.tb_key = 'testbed_configs'
+        test_run_config = mobly_config_parser.TestRunConfig()
+        test_run_config.testbed_name = 'MockTestBed'
+        test_run_config.controller_configs = {}
+        test_run_config.log_path = '/tmp'
+        test_run_config.user_params = {}
+        test_run_config.summary_writer = mock.MagicMock()
+        test = self.PCBT(test_run_config)
+        self.test = test
+
+    def test_consume_parameter_typical_case(self):
+        """ Tests the typical case: The parameter is available
+            for consumption and it has enough values
+        """
+        parameters = ['param1', 1, 2, 'param2', 3, 'param3', 'value']
+        expected = ['param2', 3]
+        self.test.unpack_userparams(parameters=parameters)
+        try:
+            result = self.test.consume_parameter('param2', 1)
+            self.assertTrue(
+                result == expected,
+                'Consume parameter did not return the expected result')
+        except ValueError as e:
+            self.fail('Error thrown: {}'.format(e))
+
+    def test_consume_parameter_returns_empty_when_parameter_unavailabe(self):
+        """ Tests the case where the requested parameter is unavailable
+            for consumption. In this case, a ValueError should be raised
+        """
+        parameters = ['param1', 1, 2]
+        expected = []
+        self.test.unpack_userparams(parameters=parameters)
+        try:
+            result = self.test.consume_parameter('param2', 1)
+            self.assertTrue(
+                result == expected,
+                'Consume parameter should return empty list for an invalid key'
+            )
+        except ValueError as e:
+            self.fail('Error thrown: {}'.format(e))
+
+    def test_consume_parameter_throws_when_requesting_too_many_parameters(
+            self):
+        """ Tests the case where the requested parameter is available
+            for consumption, but too many values are requested
+        """
+        parameters = ['param1', 1, 2]
+        self.test.unpack_userparams(parameters=parameters)
+        with self.assertRaises(ValueError):
+            self.test.consume_parameter('param1', 3)
+
+
+if __name__ == '__main__':
+    unittest.main()
diff --git a/acts/framework/tests/test_utils/power/tel/lab/ensure_valid_calibration_table_test.py b/acts/framework/tests/test_utils/power/tel/lab/ensure_valid_calibration_table_test.py
new file mode 100644
index 0000000..60909db
--- /dev/null
+++ b/acts/framework/tests/test_utils/power/tel/lab/ensure_valid_calibration_table_test.py
@@ -0,0 +1,87 @@
+#!/usr/bin/env python3
+#
+#   Copyright 2019 - The Android Open Source Project
+#
+#   Licensed under the Apache License, Version 2.0 (the "License");
+#   you may not use this file except in compliance with the License.
+#   You may obtain a copy of the License at
+#
+#       http://www.apache.org/licenses/LICENSE-2.0
+#
+#   Unless required by applicable law or agreed to in writing, software
+#   distributed under the License is distributed on an "AS IS" BASIS,
+#   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+#   See the License for the specific language governing permissions and
+#   limitations under the License.
+
+import unittest
+import mobly.config_parser as mobly_config_parser
+import tests.test_utils.power.tel.lab.mock_bokeh
+from unittest import mock
+
+
+class EnsureValidCalibrationTableTest(unittest.TestCase):
+    """ Unit tests for exercising the logic of ensure_valid_calibration_table
+        for instances of PowerCellularLabBaseTest
+    """
+
+    VALID_CALIBRATION_TABLE = {'1': {'2': {'3': 123, '4': 3.14}}, '2': 45.67}
+
+    INVALID_CALIBRATION_TABLE = invalid = {'1': {'a': 'invalid'}, '2': 1234}
+
+    @classmethod
+    def setUpClass(self):
+        from acts.test_utils.power.cellular.cellular_power_base_test import PowerCellularLabBaseTest as PCBT
+        self.PCBT = PCBT
+        PCBT.log = mock.Mock()
+        PCBT.log_path = ''
+
+
+    def setUp(self):
+        self.tb_key = 'testbed_configs'
+        test_run_config = mobly_config_parser.TestRunConfig()
+        test_run_config.testbed_name = 'MockTestBed'
+        test_run_config.controller_configs = {}
+        test_run_config.log_path = '/tmp'
+        test_run_config.user_params = {}
+        test_run_config.summary_writer = mock.MagicMock()
+        test = self.PCBT(test_run_config)
+        self.test = test
+
+
+    def _assert_no_exception(self, func, *args, **kwargs):
+        try:
+            func(*args, **kwargs)
+        except Exception as e:
+            self.fail('Error thrown: {}'.format(e))
+
+    def _assert_calibration_table_passes(self, table):
+        self._assert_no_exception(self.test.ensure_valid_calibration_table, table)
+
+    def _assert_calibration_table_fails(self, table):
+        with self.assertRaises(TypeError):
+            self.test.ensure_valid_calibration_table(table)
+
+    def test_ensure_valid_calibration_table_passes_with_empty_table(self):
+        """ Ensure that empty calibration tables are invalid """
+        self._assert_calibration_table_passes({})
+
+    def test_ensure_valid_calibration_table_passes_with_valid_table(self):
+        """ Ensure that valid calibration tables throw no error """
+        self._assert_calibration_table_passes(self.VALID_CALIBRATION_TABLE)
+
+    def test_ensure_valid_calibration_table_fails_with_invalid_data(self):
+        """ Ensure that calibration tables with invalid entries throw an error """
+        self._assert_calibration_table_fails(self.INVALID_CALIBRATION_TABLE)
+
+    def test_ensure_valid_calibration_table_fails_with_none(self):
+        """ Ensure an exception is thrown if no calibration table is given """
+        self._assert_calibration_table_fails(None)
+
+    def test_ensure_valid_calibration_table_fails_with_invalid_type(self):
+        """ Ensure an exception is thrown if no calibration table is given """
+        self._assert_calibration_table_fails([])
+
+
+if __name__ == '__main__':
+    unittest.main()
diff --git a/acts/framework/tests/test_utils/power/tel/lab/init_simulation_test.py b/acts/framework/tests/test_utils/power/tel/lab/init_simulation_test.py
new file mode 100644
index 0000000..45ab3f9
--- /dev/null
+++ b/acts/framework/tests/test_utils/power/tel/lab/init_simulation_test.py
@@ -0,0 +1,86 @@
+#!/usr/bin/env python3
+#
+#   Copyright 2019 - The Android Open Source Project
+#
+#   Licensed under the Apache License, Version 2.0 (the "License");
+#   you may not use this file except in compliance with the License.
+#   You may obtain a copy of the License at
+#
+#       http://www.apache.org/licenses/LICENSE-2.0
+#
+#   Unless required by applicable law or agreed to in writing, software
+#   distributed under the License is distributed on an "AS IS" BASIS,
+#   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+#   See the License for the specific language governing permissions and
+#   limitations under the License.
+
+import unittest
+import mobly.config_parser as mobly_config_parser
+import tests.test_utils.power.tel.lab.mock_bokeh
+from acts.test_utils.power.tel_simulations.LteSimulation import LteSimulation
+from acts.test_utils.power.tel_simulations.UmtsSimulation import UmtsSimulation
+from unittest import mock
+
+
+class InitSimulationTest(unittest.TestCase):
+    """ Unit tests for ensuring the simulation is correctly
+        initialized for instances of PowerCellularLabBaseTest
+    """
+    @classmethod
+    def setUpClass(self):
+        from acts.test_utils.power.cellular.cellular_power_base_test import PowerCellularLabBaseTest as PCBT
+        self.PCBT = PCBT
+        PCBT.log = mock.Mock()
+        PCBT.log_path = ''
+
+    def setUp(self):
+        self.tb_key = 'testbed_configs'
+        test_run_config = mobly_config_parser.TestRunConfig()
+        test_run_config.testbed_name = 'MockTestBed'
+        test_run_config.controller_configs = {}
+        test_run_config.log_path = '/tmp'
+        test_run_config.user_params = {}
+        test_run_config.summary_writer = mock.MagicMock()
+        test = self.PCBT(test_run_config)
+        self.test = test
+
+    def test_init_simulation_reuses_simulation_if_same_type(self):
+        """ Ensure that a new simulation is not instantiated if
+            the type is the same as the last simulation
+        """
+        mock_lte_sim = mock.Mock(spec=LteSimulation)
+        self.test.unpack_userparams(simulation=mock_lte_sim)
+        try:
+            self.test.init_simulation(self.PCBT.PARAM_SIM_TYPE_LTE)
+        except ValueError as e:
+            self.fail('Error thrown: {}'.format(e))
+        self.assertTrue(self.test.simulation is mock_lte_sim,
+                        'A new simulation was instantiated')
+
+    def test_init_simulation_does_not_reuse_simulation_if_different_type(self):
+        """ Ensure that a new simulation is instantiated if
+            the type is different from the last simulation
+        """
+        self.test.unpack_userparams(simulation=mock.Mock(spec=LteSimulation),
+                               test_params=mock.Mock())
+        try:
+            with mock.patch.object(UmtsSimulation,
+                                   '__init__',
+                                   return_value=None) as mock_init:
+                self.test.init_simulation(self.PCBT.PARAM_SIM_TYPE_UMTS)
+        except Exception as e:
+            self.fail('Error thrown: {}'.format(e))
+        self.assertTrue(mock_init.called,
+                        'A new simulation was not instantiated')
+
+    def test_init_simulation_throws_error_with_invalid_simulation_type(self):
+        """ Ensure that a new simulation is not instantiated if
+            the type is invalid
+        """
+        self.test.unpack_userparams(simulation=mock.Mock(spec=LteSimulation))
+        with self.assertRaises(ValueError):
+            self.test.init_simulation('Invalid simulation type')
+
+
+if __name__ == '__main__':
+    unittest.main()
diff --git a/acts/framework/tests/test_utils/power/tel/lab/initialize_simulator_test.py b/acts/framework/tests/test_utils/power/tel/lab/initialize_simulator_test.py
new file mode 100644
index 0000000..bf3ab52
--- /dev/null
+++ b/acts/framework/tests/test_utils/power/tel/lab/initialize_simulator_test.py
@@ -0,0 +1,111 @@
+#!/usr/bin/env python3
+#
+#   Copyright 2019 - The Android Open Source Project
+#
+#   Licensed under the Apache License, Version 2.0 (the "License");
+#   you may not use this file except in compliance with the License.
+#   You may obtain a copy of the License at
+#
+#       http://www.apache.org/licenses/LICENSE-2.0
+#
+#   Unless required by applicable law or agreed to in writing, software
+#   distributed under the License is distributed on an "AS IS" BASIS,
+#   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+#   See the License for the specific language governing permissions and
+#   limitations under the License.
+
+import unittest
+import mobly.config_parser as mobly_config_parser
+import tests.test_utils.power.tel.lab.mock_bokeh
+from acts.controllers.anritsu_lib import md8475_cellular_simulator as anritsu
+from acts.controllers.rohdeschwarz_lib import cmw500_cellular_simulator as cmw
+from unittest import mock
+
+
+class InitializeSimulatorTest(unittest.TestCase):
+    """ Unit tests for ensuring the simulator is correctly
+        initialized for instances of PowerCellularLabBaseTest
+    """
+    @classmethod
+    def setUpClass(self):
+        from acts.test_utils.power.cellular.cellular_power_base_test import PowerCellularLabBaseTest as PCBT
+        self.PCBT = PCBT
+        PCBT.log = mock.Mock()
+        PCBT.log_path = ''
+
+    def setUp(self):
+        self.tb_key = 'testbed_configs'
+        test_run_config = mobly_config_parser.TestRunConfig()
+        test_run_config.testbed_name = 'MockTestBed'
+        test_run_config.controller_configs = {}
+        test_run_config.log_path = '/tmp'
+        test_run_config.user_params = {}
+        test_run_config.summary_writer = mock.MagicMock()
+        test = self.PCBT(test_run_config)
+        self.test = test
+
+    def test_initialize_simulator_md8475_A(self):
+        """ Ensure that an instance of MD8475CellularSimulator
+            is returned when requesting md8475_version A
+        """
+        self.test.unpack_userparams(md8475_version='A', md8475a_ip_address='12345')
+        try:
+            with mock.patch.object(anritsu.MD8475CellularSimulator,
+                                   '__init__',
+                                   return_value=None):
+                result = self.test.initialize_simulator()
+                self.assertTrue(
+                    isinstance(result, anritsu.MD8475CellularSimulator),
+                    'Incorrect simulator type returned for md8475_version A')
+        except ValueError as e:
+            self.fail('Error thrown: {}'.format(e))
+
+    def test_initialize_simulator_md8475_B(self):
+        """ Ensure that an instance of MD8475BCellularSimulator
+            is returned when requesting md8475_version B
+        """
+        self.test.unpack_userparams(md8475_version='B', md8475a_ip_address='12345')
+        try:
+            with mock.patch.object(anritsu.MD8475BCellularSimulator,
+                                   '__init__',
+                                   return_value=None):
+                result = self.test.initialize_simulator()
+                self.assertTrue(
+                    isinstance(result, anritsu.MD8475BCellularSimulator),
+                    'Incorrect simulator type returned for md8475_version B')
+        except ValueError as e:
+            self.fail('Error thrown: {}'.format(e))
+
+    def test_initialize_simulator_cmw500(self):
+        """ Ensure that an instance of CMW500CellularSimulator
+            is returned when requesting cmw500
+        """
+        self.test.unpack_userparams(md8475_version=None,
+                               md8475a_ip_address=None,
+                               cmw500_ip='12345',
+                               cmw500_port='12345')
+        try:
+            with mock.patch.object(cmw.CMW500CellularSimulator,
+                                   '__init__',
+                                   return_value=None):
+                result = self.test.initialize_simulator()
+                self.assertTrue(
+                    isinstance(result, cmw.CMW500CellularSimulator),
+                    'Incorrect simulator type returned for cmw500')
+        except ValueError as e:
+            self.fail('Error thrown: {}'.format(e))
+
+    def test_initialize_simulator_throws_with_missing_configs(self):
+        """ Ensure that an error is raised when initialize_simulator
+            is called with missing configs
+        """
+        self.test.unpack_userparams(md8475_version=None,
+                               md8475a_ip_address=None,
+                               cmw500_ip='12345')
+        with self.assertRaises(RuntimeError), mock.patch.object(
+                cmw.CMW500CellularSimulator, '__init__', return_value=None):
+            self.test.initialize_simulator()
+
+
+if __name__ == '__main__':
+    unittest.main()
diff --git a/acts/framework/tests/test_utils/power/tel/lab/mock_bokeh.py b/acts/framework/tests/test_utils/power/tel/lab/mock_bokeh.py
new file mode 100644
index 0000000..7364386
--- /dev/null
+++ b/acts/framework/tests/test_utils/power/tel/lab/mock_bokeh.py
@@ -0,0 +1,8 @@
+import sys
+from mock import Mock
+
+sys.modules['bokeh'] = Mock()
+sys.modules['bokeh.layouts'] = Mock()
+sys.modules['bokeh.models'] = Mock()
+sys.modules['bokeh.models.widgets'] = Mock()
+sys.modules['bokeh.plotting'] = Mock()
\ No newline at end of file
diff --git a/acts/framework/tests/test_utils/power/tel/lab/power_tel_traffic_e2e_test.py b/acts/framework/tests/test_utils/power/tel/lab/power_tel_traffic_e2e_test.py
new file mode 100644
index 0000000..4f2a06a
--- /dev/null
+++ b/acts/framework/tests/test_utils/power/tel/lab/power_tel_traffic_e2e_test.py
@@ -0,0 +1,110 @@
+#!/usr/bin/env python3
+#
+#   Copyright 2019 - The Android Open Source Project
+#
+#   Licensed under the Apache License, Version 2.0 (the "License");
+#   you may not use this file except in compliance with the License.
+#   You may obtain a copy of the License at
+#
+#       http://www.apache.org/licenses/LICENSE-2.0
+#
+#   Unless required by applicable law or agreed to in writing, software
+#   distributed under the License is distributed on an "AS IS" BASIS,
+#   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+#   See the License for the specific language governing permissions and
+#   limitations under the License.
+
+import unittest
+import tests.test_utils.power.tel.lab.mock_bokeh
+import acts.test_utils.power.cellular.cellular_traffic_power_test as ctpt
+import mobly.config_parser as mobly_config_parser
+from acts.test_utils.power.tel_simulations.LteSimulation import LteSimulation
+from acts.controllers.rohdeschwarz_lib import cmw500_cellular_simulator as cmw
+from unittest import mock
+
+
+class PowerTelTrafficE2eTest(unittest.TestCase):
+    """ E2E sanity test for the power cellular traffic tests """
+    @classmethod
+    def setUpClass(cls):
+        cls.PTTT = ctpt.PowerTelTrafficTest
+        cls.PTTT.log = mock.Mock()
+        cls.PTTT.log_path = ''
+
+    @mock.patch('json.load')
+    @mock.patch('builtins.open')
+    @mock.patch('os.chmod')
+    @mock.patch('os.system')
+    @mock.patch('time.sleep')
+    @mock.patch(
+        'acts.test_utils.tel.tel_test_utils.toggle_airplane_mode_by_adb')
+    @mock.patch('acts.test_utils.wifi.wifi_test_utils.reset_wifi')
+    @mock.patch('acts.test_utils.wifi.wifi_test_utils.wifi_toggle_state')
+    @mock.patch(
+        'acts.metrics.loggers.blackbox.BlackboxMetricLogger.for_test_case')
+    @mock.patch(
+        'acts.test_utils.power.loggers.power_metric_logger.PowerMetricLogger.for_test_case'
+    )
+    def test_e2e(self, *args):
+
+        # Configure the test
+        test_to_mock = 'test_lte_traffic_direction_dlul_blimit_0_0'
+        self.tb_key = 'testbed_configs'
+        test_run_config = mobly_config_parser.TestRunConfig()
+        test_run_config.testbed_name = 'MockTestBed'
+        test_run_config.controller_configs = {}
+        test_run_config.log_path = '/tmp'
+        test_run_config.user_params = {}
+        test_run_config.summary_writer = mock.MagicMock()
+        test = self.PTTT(test_run_config)
+        mock_android = mock.Mock()
+        mock_android.model = 'coral'
+        test.unpack_userparams(
+            android_devices=[mock_android],
+            monsoons=[mock.Mock()],
+            iperf_servers=[mock.Mock(), mock.Mock()],
+            packet_senders=[mock.Mock(), mock.Mock()],
+            custom_files=['pass_fail_threshold_coral.json', 'rockbottom_coral.sh'],
+            simulation=mock.Mock(spec=LteSimulation),
+            mon_freq=5000,
+            mon_duration=0,
+            mon_offset=0,
+            current_test_name=test_to_mock,
+            test_name=test_to_mock,
+            test_result=mock.Mock(),
+            bug_report={},
+            dut_rockbottom=mock.Mock(),
+            start_tel_traffic=mock.Mock(),
+            init_simulation=mock.Mock(),
+            initialize_simulator=mock.Mock(return_value=mock.Mock(
+                spec=cmw.CMW500CellularSimulator)),
+            collect_power_data=mock.Mock(),
+            get_iperf_results=mock.Mock(return_value={
+                'ul': 0,
+                'dl': 0
+            }),
+            pass_fail_check=mock.Mock())
+
+        # Emulate lifecycle
+        test.setup_class()
+        test.setup_test()
+        test.power_tel_traffic_test()
+        test.teardown_test()
+        test.teardown_class()
+
+        self.assertTrue(test.start_tel_traffic.called,
+                        'Start traffic was not called')
+        self.assertTrue(test.init_simulation.called,
+                        'Simulation was not initialized')
+        self.assertTrue(test.initialize_simulator.called,
+                        'Simulator was not initialized')
+        self.assertTrue(test.collect_power_data.called,
+                        'Power data was not collected')
+        self.assertTrue(test.get_iperf_results.called,
+                        'Did not get iperf results')
+        self.assertTrue(test.pass_fail_check.called,
+                        'Pass/Fail check was not performed')
+
+
+if __name__ == '__main__':
+    unittest.main()
diff --git a/acts/framework/tests/test_utils/power/tel/lab/save_summary_to_file_test.py b/acts/framework/tests/test_utils/power/tel/lab/save_summary_to_file_test.py
new file mode 100644
index 0000000..ebc34ed
--- /dev/null
+++ b/acts/framework/tests/test_utils/power/tel/lab/save_summary_to_file_test.py
@@ -0,0 +1,60 @@
+#!/usr/bin/env python3
+#
+#   Copyright 2019 - The Android Open Source Project
+#
+#   Licensed under the Apache License, Version 2.0 (the "License");
+#   you may not use this file except in compliance with the License.
+#   You may obtain a copy of the License at
+#
+#       http://www.apache.org/licenses/LICENSE-2.0
+#
+#   Unless required by applicable law or agreed to in writing, software
+#   distributed under the License is distributed on an "AS IS" BASIS,
+#   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+#   See the License for the specific language governing permissions and
+#   limitations under the License.
+
+import unittest
+import mobly.config_parser as mobly_config_parser
+import tests.test_utils.power.tel.lab.mock_bokeh
+from acts.test_utils.power.tel_simulations.LteSimulation import LteSimulation
+from unittest import mock
+from unittest.mock import mock_open
+
+
+class SaveSummaryToFileTest(unittest.TestCase):
+    """ Unit tests for testing the save summary functionality for
+        instances of PowerCellularLabBaseTest
+    """
+
+    @classmethod
+    def setUpClass(self):
+        from acts.test_utils.power.cellular.cellular_power_base_test import PowerCellularLabBaseTest as PCBT
+        self.PCBT = PCBT
+        PCBT.log = mock.Mock()
+        PCBT.log_path = ''
+
+    def setUp(self):
+        self.tb_key = 'testbed_configs'
+        test_run_config = mobly_config_parser.TestRunConfig()
+        test_run_config.testbed_name = 'MockTestBed'
+        test_run_config.controller_configs = {}
+        test_run_config.log_path = '/tmp'
+        test_run_config.user_params = {}
+        test_run_config.summary_writer = mock.MagicMock()
+        test = self.PCBT(test_run_config)
+        self.test = test
+
+    def test_save_summary_to_file(self):
+        """ Ensure that a new file is written when saving
+            the test summary
+        """
+        self.test.unpack_userparams(simulation=mock.Mock(spec=LteSimulation))
+        m = mock_open()
+        with mock.patch('builtins.open', m, create=False):
+            self.test.save_summary_to_file()
+        self.assertTrue(m.called, 'Test summary was not written to output')
+
+
+if __name__ == '__main__':
+    unittest.main()
diff --git a/acts/tests/google/coex/performance_tests/CoexBasicPerformanceTest.py b/acts/tests/google/coex/performance_tests/CoexBasicPerformanceTest.py
index 00cb735..c5c1879 100644
--- a/acts/tests/google/coex/performance_tests/CoexBasicPerformanceTest.py
+++ b/acts/tests/google/coex/performance_tests/CoexBasicPerformanceTest.py
@@ -14,153 +14,60 @@
 # License for the specific language governing permissions and limitations under
 # the License.
 
+import itertools
+
+from acts.test_utils.bt.bt_test_utils import enable_bluetooth
 from acts.test_utils.coex.CoexPerformanceBaseTest import CoexPerformanceBaseTest
 from acts.test_utils.coex.coex_test_utils import perform_classic_discovery
 
 
 class CoexBasicPerformanceTest(CoexPerformanceBaseTest):
 
-    def setup_class(self):
-        super().setup_class()
+    def __init__(self, controllers):
+        super().__init__(controllers)
+        req_params = [
+            # A dict containing:
+            #     protocol: A list containing TCP/UDP. Ex: protocol: ['tcp'].
+            #     stream: A list containing ul/dl. Ex: stream: ['ul']
+            'standalone_params'
+        ]
+        self.unpack_userparams(req_params)
+        self.tests = self.generated_test_cases(['bt_on', 'perform_discovery'])
 
-    def run_iperf_and_perform_discovery(self):
-        """Starts iperf client on host machine and bluetooth discovery
+    def perform_discovery(self):
+        """ Starts iperf client on host machine and bluetooth discovery
         simultaneously.
 
         Returns:
             True if successful, False otherwise.
         """
         tasks = [(perform_classic_discovery,
-                  (self.pri_ad, self.iperf["duration"], self.json_file,
-                   self.dev_list)), (self.run_iperf_and_get_result, ())]
-        if not self.set_attenuation_and_run_iperf(tasks):
-            return False
-        return self.teardown_result()
+                  (self.pri_ad, self.iperf['duration'], self.json_file,
+                   self.dev_list)),
+                 (self.run_iperf_and_get_result, ())]
+        return self.set_attenuation_and_run_iperf(tasks)
 
-    def test_performance_with_bt_on_tcp_ul(self):
-        """Check throughput when bluetooth on.
-
-        This test is to start TCP-Uplink traffic between host machine and
-        android device and check the throughput when bluetooth is on.
-
-        Steps:
-        1. Start TCP-uplink traffic when bluetooth is on.
-
-        Test Id: Bt_CoEx_kpi_005
-        """
-        self.set_attenuation_and_run_iperf()
-        return self.teardown_result()
-
-    def test_performance_with_bt_on_tcp_dl(self):
-        """Check throughput when bluetooth on.
-
-        This test is to start TCP-downlink traffic between host machine and
-        android device and check the throughput when bluetooth is on.
-
-        Steps:
-        1. Start TCP-downlink traffic when bluetooth is on.
-
-        Test Id: Bt_CoEx_kpi_006
-        """
-        self.set_attenuation_and_run_iperf()
-        return self.teardown_result()
-
-    def test_performance_with_bt_on_udp_ul(self):
-        """Check throughput when bluetooth on.
-
-        This test is to start UDP-uplink traffic between host machine and
-        android device and check the throughput when bluetooth is on.
-
-        Steps:
-        1. Start UDP-uplink traffic when bluetooth is on.
-
-        Test Id: Bt_CoEx_kpi_007
-        """
-        self.set_attenuation_and_run_iperf()
-        return self.teardown_result()
-
-    def test_performance_with_bt_on_udp_dl(self):
-        """Check throughput when bluetooth on.
-
-        This test is to start UDP-downlink traffic between host machine and
-        android device and check the throughput when bluetooth is on.
-
-        Steps:
-        1. Start UDP-downlink traffic when bluetooth is on.
-
-        Test Id: Bt_CoEx_kpi_008
-        """
-        self.set_attenuation_and_run_iperf()
-        return self.teardown_result()
-
-    def test_performance_with_bluetooth_discovery_tcp_ul(self):
-        """Check throughput when bluetooth discovery is ongoing.
-
-        This test is to start TCP-uplink traffic between host machine and
-        android device and bluetooth discovery and checks throughput.
-
-        Steps:
-        1. Start TCP-uplink traffic and bluetooth discovery parallelly.
+    def bt_on(self):
+        """ Turns on bluetooth and runs iperf.
 
         Returns:
-            True if successful, False otherwise.
-
-        Test Id: Bt_CoEx_kpi_009
+            True on success, False otherwise.
         """
-        if not self.run_iperf_and_perform_discovery():
+        if not enable_bluetooth(self.pri_ad.droid, self.pri_ad.ed):
             return False
-        return True
+        return self.set_attenuation_and_run_iperf()
 
-    def test_performance_with_bluetooth_discovery_tcp_dl(self):
-        """Check throughput when bluetooth discovery is ongoing.
+    def generated_test_cases(self, test_types):
+        """ Auto generates tests for basic coex tests. """
+        test_cases = []
+        for protocol, stream, test_type in itertools.product(
+                self.standalone_params['protocol'],
+                self.standalone_params['stream'], test_types):
 
-        This test is to start TCP-downlink traffic between host machine and
-        android device and bluetooth discovery and checks throughput.
+            test_name = 'test_performance_with_{}_{}_{}'.format(
+                test_type, protocol, stream)
 
-        Steps:
-        1. Start TCP-downlink traffic and bluetooth discovery parallelly.
-
-        Returns:
-            True if successful, False otherwise.
-
-        Test Id: Bt_CoEx_kpi_010
-        """
-        if not self.run_iperf_and_perform_discovery():
-            return False
-        return True
-
-    def test_performance_with_bluetooth_discovery_udp_ul(self):
-        """Check throughput when bluetooth discovery is ongoing.
-
-        This test is to start UDP-uplink traffic between host machine and
-        android device and bluetooth discovery and checks throughput.
-
-        Steps:
-        1. Start UDP-uplink traffic and bluetooth discovery parallelly.
-
-        Returns:
-            True if successful, False otherwise.
-
-        Test Id: Bt_CoEx_kpi_011
-        """
-        if not self.run_iperf_and_perform_discovery():
-            return False
-        return True
-
-    def test_performance_with_bluetooth_discovery_udp_dl(self):
-        """Check throughput when bluetooth discovery is ongoing.
-
-        This test is to start UDP-downlink traffic between host machine and
-        android device and bluetooth discovery and checks throughput.
-
-        Steps:
-        1. Start UDP-downlink traffic and bluetooth discovery parallelly.
-
-        Returns:
-            True if successful, False otherwise.
-
-        Test Id: Bt_CoEx_kpi_012
-        """
-        if not self.run_iperf_and_perform_discovery():
-            return False
-        return True
+            test_function = getattr(self, test_type)
+            setattr(self, test_name, test_function)
+            test_cases.append(test_name)
+        return test_cases
diff --git a/acts/tests/google/fuchsia/wlan/WlanInterfaceTest.py b/acts/tests/google/fuchsia/wlan/WlanInterfaceTest.py
new file mode 100644
index 0000000..b8395f1
--- /dev/null
+++ b/acts/tests/google/fuchsia/wlan/WlanInterfaceTest.py
@@ -0,0 +1,59 @@
+#!/usr/bin/env python3
+#
+#   Copyright 2019 - The Android secure Source Project
+#
+#   Licensed under the Apache License, Version 2.0 (the "License");
+#   you may not use this file except in compliance with the License.
+#   You may obtain a copy of the License at
+#
+#       http://www.apache.org/licenses/LICENSE-2.0
+#
+#   Unless required by applicable law or agreed to in writing, software
+#   distributed under the License is distributed on an "AS IS" BASIS,
+#   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+#   See the License for the specific language governing permissions and
+#   limitations under the License.
+
+from acts import signals
+
+from acts.base_test import BaseTestClass
+from acts.test_utils.abstract_devices.wlan_device import create_wlan_device
+
+
+class WlanInterfaceTest(BaseTestClass):
+    def setup_class(self):
+        dut = self.user_params.get('dut', None)
+        if dut:
+          if dut == 'fuchsia_devices':
+             self.dut = create_wlan_device(self.fuchsia_devices[0])
+          elif dut == 'android_devices':
+             self.dut = create_wlan_device(self.android_devices[0])
+          else:
+             raise ValueError('Invalid DUT specified in config. (%s)' % self.user_params['dut'])
+        else:
+            # Default is an Fuchsia device
+            self.dut = create_wlan_device(self.fuchsia_devices[0])
+
+    def test_destroy_iface(self):
+        """Test that we don't error out when destroying the WLAN interface.
+
+        Steps:
+        1. Find a wlan interface
+        2. Destroy it
+
+        Expected Result:
+        Verify there are no errors in destroying the wlan interface.
+
+        Returns:
+          signals.TestPass if no errors
+          signals.TestFailure if there are any errors during the test.
+
+        TAGS: WLAN
+        Priority: 1
+        """
+        wlan_interfaces = self.dut.get_wlan_interface_id_list()
+        if len(wlan_interfaces) < 1:
+            raise signals.TestFailure("Not enough wlan interfaces for test")
+        if not self.dut.destroy_wlan_interface(wlan_interfaces[0]):
+            raise signals.TestFailure("Failed to destroy WLAN interface")
+        raise signals.TestPass("Success")
diff --git a/acts/tests/google/gnss/LocationPlatinumTest.py b/acts/tests/google/gnss/LocationPlatinumTest.py
new file mode 100644
index 0000000..c1debf5
--- /dev/null
+++ b/acts/tests/google/gnss/LocationPlatinumTest.py
@@ -0,0 +1,262 @@
+#!/usr/bin/env python3.5
+#
+#   Copyright 2019 - The Android Open Source Project
+#
+#   Licensed under the Apache License, Version 2.0 (the "License");
+#   you may not use this file except in compliance with the License.
+#   You may obtain a copy of the License at
+#
+#       http://www.apache.org/licenses/LICENSE-2.0
+#
+#   Unless required by applicable law or agreed to in writing, software
+#   distributed under the License is distributed on an "AS IS" BASIS,
+#   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+#   See the License for the specific language governing permissions and
+#   limitations under the License.
+import time
+from collections import namedtuple
+
+from acts import asserts
+from acts import signals
+from acts import utils
+from acts.base_test import BaseTestClass
+from acts.test_utils.gnss import gnss_test_utils as gutils
+from acts.test_utils.wifi import wifi_test_utils as wutils
+from acts.test_utils.tel import tel_test_utils as tutils
+
+TEST_PACKAGE_NAME = 'com.google.android.apps.maps'
+LOCATION_PERMISSIONS = [
+    'android.permission.ACCESS_FINE_LOCATION',
+    'android.permission.ACCESS_COARSE_LOCATION'
+]
+BACKGROUND_LOCATION_PERMISSION = 'android.permission.ACCESS_BACKGROUND_LOCATION'
+
+
+class LocationPlatinumTest(BaseTestClass):
+    """Location Platinum Tests"""
+
+    def setup_class(self):
+        super().setup_class()
+        self.ad = self.android_devices[0]
+        req_params = [
+            # A { SSID, password } dictionary. Password is optional.
+            'pixel_lab_network',
+            # A [latitude, longitude] list to identify test location.
+            'pixel_lab_location',
+            # Cold Start Criteria, a int to define the criteria.
+            'cs_criteria',
+            # Warm Start Criteria, a int to define the criteria.
+            'ws_criteria',
+            # Hot Start Criteria, a int to define the criteria.
+            'hs_criteria',
+            # NetworkLocationProvide Criteria, a int to define the criteria.
+            'nlp_criteria',
+            # A list to identify QXDM log path.
+            'qdsp6m_path'
+        ]
+        self.unpack_userparams(req_param_names=req_params)
+
+        # Init test types Cold Start, Warm Start and Hot Start.
+        test_type = namedtuple('Type', ['command', 'criteria'])
+        self.test_types = {
+            'cs': test_type('Cold Start', self.cs_criteria),
+            'ws': test_type('Warm Start', self.ws_criteria),
+            'hs': test_type('Hot Start', self.hs_criteria)
+        }
+        gutils._init_device(self.ad)
+        self.begin_time = utils.get_current_epoch_time()
+        gutils.clear_logd_gnss_qxdm_log(self.ad)
+        tutils.start_qxdm_logger(self.ad, self.begin_time)
+        tutils.start_adb_tcpdump(self.ad)
+
+    def setup_test(self):
+        """Prepare device with mobile data, wifi and gps ready for test """
+        if int(self.ad.adb.shell('settings get secure location_mode')) != 3:
+            self.ad.adb.shell('settings put secure location_mode 3')
+        if not self.ad.droid.wifiCheckState():
+            wutils.wifi_toggle_state(self.ad, True)
+            gutils.connect_to_wifi_network(self.ad, self.pixel_lab_network)
+        if int(self.ad.adb.shell('settings get global mobile_data')) != 1:
+            gutils.set_mobile_data(self.ad, True)
+        self.grant_location_permission(True)
+        self.ad.adb.shell('pm grant com.android.gpstool %s' %
+                          BACKGROUND_LOCATION_PERMISSION)
+
+    def teardown_class(self):
+        tutils.stop_qxdm_logger(self.ad)
+        gutils.get_gnss_qxdm_log(self.ad, self.qdsp6m_path)
+        tutils.stop_adb_tcpdump(self.ad)
+        tutils.get_tcpdump_log(self.ad, 'location_platinum', self.begin_time)
+        self.ad.take_bug_report('location_platinum', self.begin_time)
+
+    def grant_location_permission(self, option):
+        """Grant or revoke location related permission.
+
+        Args:
+            option: Boolean to grant or revoke location related permissions.
+        """
+        action = 'grant' if option else 'revoke'
+        for permission in LOCATION_PERMISSIONS:
+            self.ad.log.info('%s permission:%s' % (action, permission))
+            self.ad.adb.shell('pm %s %s %s' %
+                              (action, TEST_PACKAGE_NAME, permission))
+
+    def confirm_permission_usage_window(self):
+        """ allow the script to confirm permission keep in use"""
+        time.sleep(1)
+        for _ in range(3):
+            # Press Tab for 3 times
+            self.ad.adb.shell('input keyevent 61')
+        # Press Enter to confirm using current permission set.
+        self.ad.adb.shell('input keyevent 66')
+        time.sleep(1)
+
+    def get_and_verify_ttff(self, mode):
+        """Retrieve ttff with designate mode.
+
+        Args:
+            mode: A string for identify gnss test mode.
+        """
+        if mode in self.test_types:
+            test_type = self.test_types.get(mode)
+        else:
+            raise signals.TestFailure('Unrecognized mode %s' % mode)
+
+        gutils.process_gnss_by_gtw_gpstool(self.ad,
+                                           self.test_types['cs'].criteria)
+        begin_time = gutils.get_current_epoch_time()
+        gutils.start_ttff_by_gtw_gpstool(
+            self.ad, ttff_mode=mode, iteration=1, aid_data=True)
+        ttff_data = gutils.process_ttff_by_gtw_gpstool(self.ad, begin_time,
+                                                       self.pixel_lab_location)
+        result = gutils.check_ttff_data(
+            self.ad,
+            ttff_data,
+            ttff_mode=test_type.command,
+            criteria=test_type.criteria)
+        asserts.assert_true(
+            result,
+            '%s TTFF fails to reach designated criteria' % test_type.command)
+
+    # Test cases
+    def test_gnss_cold_ttff(self):
+        """
+            1. Send intent to GPSTool for cold start test.
+            2. Retrieve ttff and validate with target criteria.
+        """
+        self.get_and_verify_ttff('cs')
+
+    def test_gnss_warm_ttff(self):
+        """
+            1. Send intent to GPSTool for warm start test.
+            2. Retrieve ttff and validate with target criteria.
+        """
+        self.get_and_verify_ttff('ws')
+
+    def test_gnss_hot_ttff(self):
+        """
+            1. Send intent to GPSTool for hot start test.
+            2. Retrieve ttff and validate with target criteria.
+        """
+        self.get_and_verify_ttff('hs')
+
+    def test_nlp_available_by_wifi(self):
+        """
+            1. Disable mobile data.
+            2. Send intent to GPSTool for NLP.
+            3. Retrieve response time and validate with criteria.
+        """
+        gutils.set_mobile_data(self.ad, False)
+        asserts.assert_true(
+            gutils.check_network_location(
+                self.ad, 1, 'networkLocationType=wifi', self.nlp_criteria),
+            'Fail to get NLP from wifi')
+
+    def test_nlp_available_by_cell(self):
+        """
+            1. Disable wifi.
+            2. Send intent to GPSTool for NLP.
+            3. Retrieve response time and validate with criteria.
+        """
+        wutils.wifi_toggle_state(self.ad, False)
+        asserts.assert_true(
+            gutils.check_network_location(
+                self.ad, 1, 'networkLocationType=cell', self.nlp_criteria),
+            'Fail to get NLP from cell')
+
+    def test_toggle_location_setting_off_on_report_location(self):
+        """
+            1. Toggle location setting off on.
+            2. Open Google Map and ask for location.
+            3. Validate there are location fix in logcat.
+        """
+        self.ad.adb.shell('settings put secure location_mode 0')
+        self.ad.adb.shell('settings put secure location_mode 3')
+        gutils.launch_google_map(self.ad)
+        asserts.assert_true(
+            gutils.check_location_api(self.ad, retries=1),
+            'DUT failed to receive location fix')
+
+    def test_toggle_location_setting_off_not_report_location(self):
+        """
+            1. Toggle location setting off.
+            2. Open Google Map and ask for location.
+            3. Validate there is no location fix in logcat.
+        """
+        self.ad.adb.shell('settings put secure location_mode 0')
+        gutils.launch_google_map(self.ad)
+        asserts.assert_false(
+            gutils.check_location_api(self.ad, retries=1),
+            'DUT Still receive location fix')
+
+    def test_toggle_location_permission_off_on(self):
+        """
+            1. Toggle Google Map location permission off on.
+            2. Open Google Map and ask for location.
+            3. Validate there are location fix in logcat.
+        """
+        self.grant_location_permission(False)
+        self.grant_location_permission(True)
+        gutils.launch_google_map(self.ad)
+        asserts.assert_true(
+            gutils.check_location_api(self.ad, retries=1),
+            'DUT fail to receive location fix')
+
+    def test_toggle_location_permission_off(self):
+        """
+            1. Toggle Google Map location permission off.
+            2. Open Google Map and ask for location.
+            3. Validate there is no location fix in logcat.
+        """
+        self.grant_location_permission(False)
+        gutils.launch_google_map(self.ad)
+        asserts.assert_false(
+            gutils.check_location_api(self.ad, retries=1),
+            'DUT still receive location fix')
+
+    def test_location_only_in_use_state(self):
+        """
+            1. Revoke ACCESS_BACKGROUBND_LOCATION permission on GPSTool.
+            2. Open GPSTool for tracking.
+            3. Validate there are location fix in logcat.
+            4. Turn GPSTool from foreground to background by press home.
+            5. Wait 60 seconds for app clean up.
+            6. Validate GPSTool is skipping for location update in logcat.
+        """
+        self.ad.log.info('Revoke background permission')
+        self.ad.adb.shell('pm revoke com.android.gpstool %s' %
+                          BACKGROUND_LOCATION_PERMISSION)
+        gutils.start_gnss_by_gtw_gpstool(self.ad, True)
+        self.confirm_permission_usage_window()
+        asserts.assert_true(
+            gutils.check_location_api(self.ad, retries=1),
+            'APP failed to receive location fix in foreground')
+        # Press HOME and let GPStool go background
+        self.ad.adb.shell('input keyevent 3')
+        begin_time = utils.get_current_epoch_time()
+        time.sleep(60)
+        result = self.ad.search_logcat(
+            'skipping loc update for no op app: com.android.gpstool',
+            begin_time)
+        asserts.assert_true(
+            result, 'APP still receive location fix in background')
diff --git a/acts/tests/google/net/DataCostTest.py b/acts/tests/google/net/DataCostTest.py
index 2b7bd50..617626f 100644
--- a/acts/tests/google/net/DataCostTest.py
+++ b/acts/tests/google/net/DataCostTest.py
@@ -65,6 +65,34 @@
 
     """ Helper functions """
 
+    def _clear_netstats(self, ad):
+        """ Clear netstats stored on device
+
+        Args:
+            ad: Android device object
+        """
+        ad.log.info("Clear netstats record.")
+        ad.adb.shell("rm /data/system/netstats/*")
+        asserts.assert_equal("", ad.adb.shell("ls /data/system/netstats/"),
+                             "Fail to clear netstats.")
+        ad.reboot()
+        time.sleep(10)
+        self._check_multipath_preference_from_dumpsys(ad)
+
+    def _check_multipath_preference_from_dumpsys(self, ad):
+        """ Check cell multipath_preference from dumpsys
+
+        Args:
+            ad: Android device object
+        """
+        out = ad.adb.shell("dumpsys connectivity | grep budget")
+        asserts.assert_true(out, "Fail to get status from dumpsys.")
+        ad.log.info("MultipathPolicyTracker: %s" % out)
+        asserts.assert_true(
+            "HANDOVER|RELIABILITY" in out,
+            "Cell multipath preference should be HANDOVER|RELIABILITY."
+        )
+
     def _get_total_data_usage_for_device(self, ad, conn_type, sub_id):
         """ Get total data usage in MB for device
 
@@ -138,6 +166,8 @@
         """
         # set vars
         ad = self.android_devices[0]
+        self._clear_netstats(ad)
+
         sub_id = str(ad.droid.telephonyGetSubscriberId())
         cell_network = ad.droid.connectivityGetActiveNetwork()
         self.log.info("cell network %s" % cell_network)
@@ -182,6 +212,8 @@
         """
         # set vars
         ad = self.android_devices[1]
+        self._clear_netstats(ad)
+
         cell_network = ad.droid.connectivityGetActiveNetwork()
         self.log.info("cell network %s" % cell_network)
         wutils.wifi_connect(ad, self.wifi_network)
diff --git a/acts/tests/google/tel/live/TelLiveStressTest.py b/acts/tests/google/tel/live/TelLiveStressTest.py
index ec364ce..5d55883 100644
--- a/acts/tests/google/tel/live/TelLiveStressTest.py
+++ b/acts/tests/google/tel/live/TelLiveStressTest.py
@@ -96,6 +96,7 @@
 from acts.test_utils.tel.tel_subscription_utils import set_subid_for_data
 from acts.test_utils.tel.tel_subscription_utils import set_subid_for_message
 from acts.test_utils.tel.tel_subscription_utils import set_subid_for_outgoing_call
+from acts.test_utils.tel.tel_subscription_utils import set_slways_allow_mms_data
 from acts.utils import get_current_epoch_time
 from acts.utils import rand_ascii_str
 
@@ -960,6 +961,7 @@
         if not call_verification_func:
             call_verification_func = is_phone_in_call
         self.finishing_time = time.time() + self.max_run_time
+        # CBRS setup
         if self.cbrs_esim:
             cbrs_sub_count = 0
             for ad in self.android_devices:
@@ -976,6 +978,15 @@
             if cbrs_sub_count != 2:
                 self.log.error("Expecting - 2 CBRS subs, found - %d", cbrs_sub_count)
                 raise signals.TestAbortClass("Cannot find all expected CBRS subs")
+        # DSDS setup
+        if self.dsds_esim:
+            for ad in self.android_devices:
+                for i in range(0, 2):
+                    sub_id = get_subid_from_slot_index(ad.log, ad, i)
+                    set_slways_allow_mms_data(ad, sub_id)
+                    operator = get_operatorname_from_slot_index(ad, i)
+                    ad.log.info("Slot %d - Sub %s - %s", i, sub_id, operator)
+        # Actual test trigger
         if not self.dsds_esim and self.check_incall_data():
             self.log.info(
                 "==== Start parallel voice/message/data stress test ====")
diff --git a/acts/tests/google/tel/live/TelLiveVoiceConfTest.py b/acts/tests/google/tel/live/TelLiveVoiceConfTest.py
index 8488b9c..a719aa1 100644
--- a/acts/tests/google/tel/live/TelLiveVoiceConfTest.py
+++ b/acts/tests/google/tel/live/TelLiveVoiceConfTest.py
@@ -1341,85 +1341,12 @@
 
         return call_ab_id, call_ac_id
 
-    def _test_ims_conference_merge_drop_second_call_no_cep(
-            self, call_ab_id, call_ac_id):
-        """Test conference merge and drop in VoLTE call.
+    def _merge_ims_conference_call(self, call_ab_id, call_ac_id):
+        """Merge IMS conference call for both cases of CEP enabled and disabled.
 
         PhoneA in IMS (VoLTE or WiFi Calling) call with PhoneB.
         PhoneA in IMS (VoLTE or WiFi Calling) call with PhoneC.
         Merge calls to conference on PhoneA.
-        Hangup on PhoneC, check call continues between AB.
-        Hangup on PhoneB, check A ends.
-
-        Args:
-            call_ab_id: call id for call_AB on PhoneA.
-            call_ac_id: call id for call_AC on PhoneA.
-
-        Returns:
-            True if succeed;
-            False if failed.
-        """
-        ads = self.android_devices
-
-        self.log.info("Step4: Merge to Conf Call and verify Conf Call.")
-        ads[0].droid.telecomCallJoinCallsInConf(call_ab_id, call_ac_id)
-        time.sleep(WAIT_TIME_IN_CALL)
-        calls = ads[0].droid.telecomCallGetCallIds()
-        ads[0].log.info("Calls in PhoneA %s", calls)
-        if num_active_calls(self.log, ads[0]) != 1:
-            ads[0].log.error("Total number of call lists is not 1.")
-            if get_cep_conference_call_id(ads[0]) is not None:
-                self.log.error("CEP enabled.")
-            else:
-                self.log.error("Merge failed.")
-            return False
-        call_conf_id = None
-        for call_id in calls:
-            if call_id != call_ab_id and call_id != call_ac_id:
-                call_conf_id = call_id
-        if not call_conf_id:
-            self.log.error("Merge call fail, no new conference call id.")
-            return False
-        if not verify_incall_state(self.log, [ads[0], ads[1], ads[2]], True):
-            return False
-
-        # Check if Conf Call is currently active
-        if ads[0].droid.telecomCallGetCallState(
-                call_conf_id) != CALL_STATE_ACTIVE:
-            ads[0].log.error(
-                "Call_id:%s, state:%s, expected: STATE_ACTIVE", call_conf_id,
-                ads[0].droid.telecomCallGetCallState(call_conf_id))
-            return False
-
-        self.log.info("Step5: End call on PhoneC and verify call continues.")
-        if not self._hangup_call(ads[2], "PhoneC"):
-            return False
-        time.sleep(WAIT_TIME_IN_CALL)
-        calls = ads[0].droid.telecomCallGetCallIds()
-        ads[0].log.info("Calls in PhoneA %s", calls)
-        if not verify_incall_state(self.log, [ads[0], ads[1]], True):
-            return False
-        if not verify_incall_state(self.log, [ads[2]], False):
-            return False
-
-        # Because of b/18413009, VZW VoLTE conference host will not drop call
-        # even if all participants drop. The reason is VZW network is not
-        # providing such information to DUT.
-        # So this test probably will fail on the last step for VZW.
-        self.log.info("Step6: End call on PhoneB and verify PhoneA end.")
-        if not self._hangup_call(ads[1], "PhoneB"):
-            return False
-        time.sleep(WAIT_TIME_IN_CALL)
-        if not verify_incall_state(self.log, [ads[0], ads[1], ads[2]], False):
-            return False
-        return True
-
-    def _merge_cep_conference_call(self, call_ab_id, call_ac_id):
-        """Merge CEP conference call.
-
-        PhoneA in IMS (VoLTE or WiFi Calling) call with PhoneB.
-        PhoneA in IMS (VoLTE or WiFi Calling) call with PhoneC.
-        Merge calls to conference on PhoneA (CEP enabled IMS conference).
 
         Args:
             call_ab_id: call id for call_AB on PhoneA.
@@ -1429,48 +1356,58 @@
             call_id for conference
         """
         ads = self.android_devices
-
         self.log.info("Step4: Merge to Conf Call and verify Conf Call.")
         ads[0].droid.telecomCallJoinCallsInConf(call_ab_id, call_ac_id)
         time.sleep(WAIT_TIME_IN_CALL)
         calls = ads[0].droid.telecomCallGetCallIds()
         ads[0].log.info("Calls in PhoneA %s", calls)
 
-        call_conf_id = get_cep_conference_call_id(ads[0])
-        if call_conf_id is None:
-            self.log.error(
-                "No call with children. Probably CEP not enabled or merge failed."
-            )
-            return None
-        calls.remove(call_conf_id)
-        if (set(ads[0].droid.telecomCallGetCallChildren(call_conf_id)) !=
-                set(calls)):
-            ads[0].log.error(
-                "Children list %s for conference call is not correct.",
-                ads[0].droid.telecomCallGetCallChildren(call_conf_id))
-            return None
+        call_conf_id = None
+        if num_active_calls(self.log, ads[0]) != 1:
+            ads[0].log.info("Total number of call ids is not 1.")
+            call_conf_id = get_cep_conference_call_id(ads[0])
+            if call_conf_id is not None:
+                self.log.info("New conference call id is found. CEP enabled.")
+                calls.remove(call_conf_id)
+                if (set(ads[0].droid.telecomCallGetCallChildren(
+                    call_conf_id)) != set(calls)):
+                    ads[0].log.error(
+                        "Children list %s for conference call is not correct.",
+                        ads[0].droid.telecomCallGetCallChildren(call_conf_id))
+                    return None
 
-        if (CALL_PROPERTY_CONFERENCE not in ads[0]
-                .droid.telecomCallGetProperties(call_conf_id)):
-            ads[0].log.error(
-                "Conf call id % properties wrong: %s", call_conf_id,
-                ads[0].droid.telecomCallGetProperties(call_conf_id))
-            return None
+                if (CALL_PROPERTY_CONFERENCE not in ads[0]
+                        .droid.telecomCallGetProperties(call_conf_id)):
+                    ads[0].log.error(
+                        "Conf call id % properties wrong: %s", call_conf_id,
+                        ads[0].droid.telecomCallGetProperties(call_conf_id))
+                    return None
 
-        if (CALL_CAPABILITY_MANAGE_CONFERENCE not in ads[0]
-                .droid.telecomCallGetCapabilities(call_conf_id)):
-            ads[0].log.error(
-                "Conf call id %s capabilities wrong: %s", call_conf_id,
-                ads[0].droid.telecomCallGetCapabilities(call_conf_id))
-            return None
+                if (CALL_CAPABILITY_MANAGE_CONFERENCE not in ads[0]
+                        .droid.telecomCallGetCapabilities(call_conf_id)):
+                    ads[0].log.error(
+                        "Conf call id %s capabilities wrong: %s", call_conf_id,
+                        ads[0].droid.telecomCallGetCapabilities(call_conf_id))
+                    return None
 
-        if (call_ab_id in calls) or (call_ac_id in calls):
-            self.log.error(
-                "Previous call ids should not in new call list after merge.")
-            return None
+                if (call_ab_id in calls) or (call_ac_id in calls):
+                    self.log.error("Previous call ids should not in new call"
+                    " list after merge.")
+                    return None
+        else:
+            for call_id in calls:
+                if call_id != call_ab_id and call_id != call_ac_id:
+                    call_conf_id = call_id
+                    self.log.info("CEP not enabled.")
 
+        if not call_conf_id:
+            self.log.error("Merge call fail, no new conference call id.")
+            raise signals.TestFailure(
+                "Calls were not merged. Failed to merge calls.",
+                extras={"fail_reason": "Calls were not merged."
+                    " Failed to merge calls."})
         if not verify_incall_state(self.log, [ads[0], ads[1], ads[2]], True):
-            return None
+            return False
 
         # Check if Conf Call is currently active
         if ads[0].droid.telecomCallGetCallState(
@@ -1482,7 +1419,7 @@
 
         return call_conf_id
 
-    def _test_ims_conference_merge_drop_second_call_from_participant_cep(
+    def _test_ims_conference_merge_drop_second_call_from_participant(
             self, call_ab_id, call_ac_id):
         """Test conference merge and drop in IMS (VoLTE or WiFi Calling) call.
         (CEP enabled).
@@ -1503,7 +1440,7 @@
         """
         ads = self.android_devices
 
-        call_conf_id = self._merge_cep_conference_call(call_ab_id, call_ac_id)
+        call_conf_id = self._merge_ims_conference_call(call_ab_id, call_ac_id)
         if call_conf_id is None:
             return False
 
@@ -1526,7 +1463,7 @@
             return False
         return True
 
-    def _test_ims_conference_merge_drop_first_call_from_participant_cep(
+    def _test_ims_conference_merge_drop_first_call_from_participant(
             self, call_ab_id, call_ac_id):
         """Test conference merge and drop in IMS (VoLTE or WiFi Calling) call.
         (CEP enabled).
@@ -1547,7 +1484,7 @@
         """
         ads = self.android_devices
 
-        call_conf_id = self._merge_cep_conference_call(call_ab_id, call_ac_id)
+        call_conf_id = self._merge_ims_conference_call(call_ab_id, call_ac_id)
         if call_conf_id is None:
             return False
 
@@ -1568,7 +1505,7 @@
             return False
         return True
 
-    def _test_ims_conference_merge_drop_second_call_from_host_cep(
+    def _test_ims_conference_merge_drop_second_call_from_host(
             self, call_ab_id, call_ac_id):
         """Test conference merge and drop in IMS (VoLTE or WiFi Calling) call.
         (CEP enabled).
@@ -1592,7 +1529,7 @@
         call_ab_uri = get_call_uri(ads[0], call_ab_id)
         call_ac_uri = get_call_uri(ads[0], call_ac_id)
 
-        call_conf_id = self._merge_cep_conference_call(call_ab_id, call_ac_id)
+        call_conf_id = self._merge_ims_conference_call(call_ab_id, call_ac_id)
         if call_conf_id is None:
             return False
 
@@ -1636,7 +1573,7 @@
             return False
         return True
 
-    def _test_ims_conference_merge_drop_first_call_from_host_cep(
+    def _test_ims_conference_merge_drop_first_call_from_host(
             self, call_ab_id, call_ac_id):
         """Test conference merge and drop in IMS (VoLTE or WiFi Calling) call.
         (CEP enabled).
@@ -1660,7 +1597,7 @@
         call_ab_uri = get_call_uri(ads[0], call_ab_id)
         call_ac_uri = get_call_uri(ads[0], call_ac_id)
 
-        call_conf_id = self._merge_cep_conference_call(call_ab_id, call_ac_id)
+        call_conf_id = self._merge_ims_conference_call(call_ab_id, call_ac_id)
         if call_conf_id is None:
             return False
 
@@ -2409,103 +2346,6 @@
 
         return call_ab_id, call_ac_id
 
-    def _test_epdg_conference_merge_drop(self, call_ab_id, call_ac_id):
-        """Test conference merge and drop in epdg call.
-
-        PhoneA in epdg call with PhoneB.
-        PhoneA in epdg call with PhoneC.
-        Merge calls to conference on PhoneA.
-        Hangup on PhoneC, check call continues between AB.
-        Hangup on PhoneB, check A ends.
-
-        Args:
-            call_ab_id: call id for call_AB on PhoneA.
-            call_ac_id: call id for call_AC on PhoneA.
-
-        Returns:
-            True if succeed;
-            False if failed.
-        """
-        ads = self.android_devices
-        self.log.info("Step4: Merge to Conf Call and verify Conf Call.")
-        ads[0].droid.telecomCallJoinCallsInConf(call_ab_id, call_ac_id)
-        time.sleep(WAIT_TIME_IN_CALL)
-        calls = ads[0].droid.telecomCallGetCallIds()
-        ads[0].log.info("Calls in PhoneA %s", calls)
-
-        call_conf_id = None
-        if num_active_calls(self.log, ads[0]) != 1:
-            ads[0].log.info("Total number of call ids is not 1.")
-            call_conf_id = get_cep_conference_call_id(ads[0])
-            if call_conf_id is not None:
-                self.log.info("New conference call id is found. CEP enabled.")
-
-                calls.remove(call_conf_id)
-                if (set(ads[0].droid.telecomCallGetCallChildren(
-                    call_conf_id)) != set(calls)):
-                    ads[0].log.error(
-                        "Children list %s for conference call is not correct.",
-                        ads[0].droid.telecomCallGetCallChildren(call_conf_id))
-                    return False
-
-                if (CALL_PROPERTY_CONFERENCE not in ads[0]
-                        .droid.telecomCallGetProperties(call_conf_id)):
-                    ads[0].log.error(
-                        "Conf call id % properties wrong: %s", call_conf_id,
-                        ads[0].droid.telecomCallGetProperties(call_conf_id))
-                    return False
-
-                if (CALL_CAPABILITY_MANAGE_CONFERENCE not in ads[0]
-                        .droid.telecomCallGetCapabilities(call_conf_id)):
-                    ads[0].log.error(
-                        "Conf call id %s capabilities wrong: %s", call_conf_id,
-                        ads[0].droid.telecomCallGetCapabilities(call_conf_id))
-                    return False
-
-                if (call_ab_id in calls) or (call_ac_id in calls):
-                    self.log.error(
-                        "Previous call ids should not in new call list after "
-                        "merge.")
-                    return False
-        else:
-            for call_id in calls:
-                if call_id != call_ab_id and call_id != call_ac_id:
-                    call_conf_id = call_id
-                    self.log.info("CEP not enabled.")
-
-        if not call_conf_id:
-            self.log.error("Merge call fail, no new conference call id.")
-            return False
-        if not verify_incall_state(self.log, [ads[0], ads[1], ads[2]], True):
-            return False
-
-        # Check if Conf Call is currently active
-        if ads[0].droid.telecomCallGetCallState(
-                call_conf_id) != CALL_STATE_ACTIVE:
-            ads[0].log.error(
-                "Call_id: %s, state: %s, expected: STATE_ACTIVE", call_conf_id,
-                ads[0].droid.telecomCallGetCallState(call_conf_id))
-            return False
-
-        self.log.info("Step5: End call on PhoneC and verify call continues.")
-        if not self._hangup_call(ads[2], "PhoneC"):
-            return False
-        time.sleep(WAIT_TIME_IN_CALL)
-        calls = ads[0].droid.telecomCallGetCallIds()
-        ads[0].log.info("Calls in PhoneA %s", calls)
-        if not verify_incall_state(self.log, [ads[0], ads[1]], True):
-            return False
-        if not verify_incall_state(self.log, [ads[2]], False):
-            return False
-
-        self.log.info("Step6: End call on PhoneB and verify PhoneA end.")
-        if not self._hangup_call(ads[1], "PhoneB"):
-            return False
-        time.sleep(WAIT_TIME_IN_CALL)
-        if not verify_incall_state(self.log, [ads[0], ads[1], ads[2]], False):
-            return False
-        return True
-
     """ Tests Begin """
 
     @TelephonyBaseTest.tel_test_wrap
@@ -3338,7 +3178,7 @@
         if call_ab_id is None or call_ac_id is None:
             return False
 
-        return self._test_ims_conference_merge_drop_second_call_no_cep(
+        return self._test_ims_conference_merge_drop_second_call_from_participant(
             call_ab_id, call_ac_id)
 
     @TelephonyBaseTest.tel_test_wrap
@@ -3360,7 +3200,7 @@
         if call_ab_id is None or call_ac_id is None:
             return False
 
-        return self._test_ims_conference_merge_drop_second_call_from_participant_cep(
+        return self._test_ims_conference_merge_drop_second_call_from_participant(
             call_ab_id, call_ac_id)
 
     @TelephonyBaseTest.tel_test_wrap
@@ -3381,7 +3221,7 @@
         if call_ab_id is None or call_ac_id is None:
             return False
 
-        return self._test_ims_conference_merge_drop_second_call_from_host_cep(
+        return self._test_ims_conference_merge_drop_second_call_from_host(
             call_ab_id, call_ac_id)
 
     @TelephonyBaseTest.tel_test_wrap
@@ -3403,7 +3243,7 @@
         if call_ab_id is None or call_ac_id is None:
             return False
 
-        return self._test_ims_conference_merge_drop_first_call_from_participant_cep(
+        return self._test_ims_conference_merge_drop_first_call_from_participant(
             call_ab_id, call_ac_id)
 
     @TelephonyBaseTest.tel_test_wrap
@@ -3424,7 +3264,7 @@
         if call_ab_id is None or call_ac_id is None:
             return False
 
-        return self._test_ims_conference_merge_drop_first_call_from_host_cep(
+        return self._test_ims_conference_merge_drop_first_call_from_host(
             call_ab_id, call_ac_id)
 
     @TelephonyBaseTest.tel_test_wrap
@@ -3446,7 +3286,7 @@
         if call_ab_id is None or call_ac_id is None:
             return False
 
-        return self._test_ims_conference_merge_drop_second_call_no_cep(
+        return self._test_ims_conference_merge_drop_second_call_from_participant(
             call_ab_id, call_ac_id)
 
     @TelephonyBaseTest.tel_test_wrap
@@ -3468,7 +3308,7 @@
         if call_ab_id is None or call_ac_id is None:
             return False
 
-        return self._test_ims_conference_merge_drop_second_call_from_participant_cep(
+        return self._test_ims_conference_merge_drop_second_call_from_participant(
             call_ab_id, call_ac_id)
 
     @TelephonyBaseTest.tel_test_wrap
@@ -3489,7 +3329,7 @@
         if call_ab_id is None or call_ac_id is None:
             return False
 
-        return self._test_ims_conference_merge_drop_second_call_from_host_cep(
+        return self._test_ims_conference_merge_drop_second_call_from_host(
             call_ab_id, call_ac_id)
 
     @TelephonyBaseTest.tel_test_wrap
@@ -3511,7 +3351,7 @@
         if call_ab_id is None or call_ac_id is None:
             return False
 
-        return self._test_ims_conference_merge_drop_first_call_from_participant_cep(
+        return self._test_ims_conference_merge_drop_first_call_from_participant(
             call_ab_id, call_ac_id)
 
     @TelephonyBaseTest.tel_test_wrap
@@ -3532,7 +3372,7 @@
         if call_ab_id is None or call_ac_id is None:
             return False
 
-        return self._test_ims_conference_merge_drop_first_call_from_host_cep(
+        return self._test_ims_conference_merge_drop_first_call_from_host(
             call_ab_id, call_ac_id)
 
     @TelephonyBaseTest.tel_test_wrap
@@ -3554,7 +3394,7 @@
         if call_ab_id is None or call_ac_id is None:
             return False
 
-        return self._test_ims_conference_merge_drop_second_call_no_cep(
+        return self._test_ims_conference_merge_drop_second_call_from_participant(
             call_ab_id, call_ac_id)
 
     @TelephonyBaseTest.tel_test_wrap
@@ -3576,7 +3416,7 @@
         if call_ab_id is None or call_ac_id is None:
             return False
 
-        return self._test_ims_conference_merge_drop_second_call_from_participant_cep(
+        return self._test_ims_conference_merge_drop_second_call_from_participant(
             call_ab_id, call_ac_id)
 
     @TelephonyBaseTest.tel_test_wrap
@@ -3597,7 +3437,7 @@
         if call_ab_id is None or call_ac_id is None:
             return False
 
-        return self._test_ims_conference_merge_drop_second_call_from_host_cep(
+        return self._test_ims_conference_merge_drop_second_call_from_host(
             call_ab_id, call_ac_id)
 
     @TelephonyBaseTest.tel_test_wrap
@@ -3619,7 +3459,7 @@
         if call_ab_id is None or call_ac_id is None:
             return False
 
-        return self._test_ims_conference_merge_drop_first_call_from_participant_cep(
+        return self._test_ims_conference_merge_drop_first_call_from_participant(
             call_ab_id, call_ac_id)
 
     @TelephonyBaseTest.tel_test_wrap
@@ -3640,7 +3480,7 @@
         if call_ab_id is None or call_ac_id is None:
             return False
 
-        return self._test_ims_conference_merge_drop_first_call_from_host_cep(
+        return self._test_ims_conference_merge_drop_first_call_from_host(
             call_ab_id, call_ac_id)
 
     @TelephonyBaseTest.tel_test_wrap
@@ -3662,7 +3502,7 @@
         if call_ab_id is None or call_ac_id is None:
             return False
 
-        return self._test_ims_conference_merge_drop_second_call_no_cep(
+        return self._test_ims_conference_merge_drop_second_call_from_participant(
             call_ab_id, call_ac_id)
 
     @TelephonyBaseTest.tel_test_wrap
@@ -3684,7 +3524,7 @@
         if call_ab_id is None or call_ac_id is None:
             return False
 
-        return self._test_ims_conference_merge_drop_second_call_from_participant_cep(
+        return self._test_ims_conference_merge_drop_second_call_from_participant(
             call_ab_id, call_ac_id)
 
     @TelephonyBaseTest.tel_test_wrap
@@ -3705,7 +3545,7 @@
         if call_ab_id is None or call_ac_id is None:
             return False
 
-        return self._test_ims_conference_merge_drop_second_call_from_host_cep(
+        return self._test_ims_conference_merge_drop_second_call_from_host(
             call_ab_id, call_ac_id)
 
     @TelephonyBaseTest.tel_test_wrap
@@ -3727,7 +3567,7 @@
         if call_ab_id is None or call_ac_id is None:
             return False
 
-        return self._test_ims_conference_merge_drop_first_call_from_participant_cep(
+        return self._test_ims_conference_merge_drop_first_call_from_participant(
             call_ab_id, call_ac_id)
 
     @TelephonyBaseTest.tel_test_wrap
@@ -3748,7 +3588,7 @@
         if call_ab_id is None or call_ac_id is None:
             return False
 
-        return self._test_ims_conference_merge_drop_first_call_from_host_cep(
+        return self._test_ims_conference_merge_drop_first_call_from_host(
             call_ab_id, call_ac_id)
 
     @TelephonyBaseTest.tel_test_wrap
@@ -3770,7 +3610,7 @@
         if call_ab_id is None or call_ac_id is None:
             return False
 
-        return self._test_ims_conference_merge_drop_second_call_no_cep(
+        return self._test_ims_conference_merge_drop_second_call_from_participant(
             call_ab_id, call_ac_id)
 
     @TelephonyBaseTest.tel_test_wrap
@@ -3792,7 +3632,7 @@
         if call_ab_id is None or call_ac_id is None:
             return False
 
-        return self._test_ims_conference_merge_drop_second_call_from_participant_cep(
+        return self._test_ims_conference_merge_drop_second_call_from_participant(
             call_ab_id, call_ac_id)
 
     @TelephonyBaseTest.tel_test_wrap
@@ -3813,7 +3653,7 @@
         if call_ab_id is None or call_ac_id is None:
             return False
 
-        return self._test_ims_conference_merge_drop_second_call_from_host_cep(
+        return self._test_ims_conference_merge_drop_second_call_from_host(
             call_ab_id, call_ac_id)
 
     @TelephonyBaseTest.tel_test_wrap
@@ -3835,7 +3675,7 @@
         if call_ab_id is None or call_ac_id is None:
             return False
 
-        return self._test_ims_conference_merge_drop_first_call_from_participant_cep(
+        return self._test_ims_conference_merge_drop_first_call_from_participant(
             call_ab_id, call_ac_id)
 
     @TelephonyBaseTest.tel_test_wrap
@@ -3856,7 +3696,7 @@
         if call_ab_id is None or call_ac_id is None:
             return False
 
-        return self._test_ims_conference_merge_drop_first_call_from_host_cep(
+        return self._test_ims_conference_merge_drop_first_call_from_host(
             call_ab_id, call_ac_id)
 
     @TelephonyBaseTest.tel_test_wrap
@@ -3878,7 +3718,7 @@
         if call_ab_id is None or call_ac_id is None:
             return False
 
-        return self._test_ims_conference_merge_drop_second_call_no_cep(
+        return self._test_ims_conference_merge_drop_second_call_from_participant(
             call_ab_id, call_ac_id)
 
     @TelephonyBaseTest.tel_test_wrap
@@ -3900,7 +3740,7 @@
         if call_ab_id is None or call_ac_id is None:
             return False
 
-        return self._test_ims_conference_merge_drop_second_call_from_participant_cep(
+        return self._test_ims_conference_merge_drop_second_call_from_participant(
             call_ab_id, call_ac_id)
 
     @TelephonyBaseTest.tel_test_wrap
@@ -3921,7 +3761,7 @@
         if call_ab_id is None or call_ac_id is None:
             return False
 
-        return self._test_ims_conference_merge_drop_second_call_from_host_cep(
+        return self._test_ims_conference_merge_drop_second_call_from_host(
             call_ab_id, call_ac_id)
 
     @TelephonyBaseTest.tel_test_wrap
@@ -3943,7 +3783,7 @@
         if call_ab_id is None or call_ac_id is None:
             return False
 
-        return self._test_ims_conference_merge_drop_first_call_from_participant_cep(
+        return self._test_ims_conference_merge_drop_first_call_from_participant(
             call_ab_id, call_ac_id)
 
     @TelephonyBaseTest.tel_test_wrap
@@ -3964,7 +3804,7 @@
         if call_ab_id is None or call_ac_id is None:
             return False
 
-        return self._test_ims_conference_merge_drop_first_call_from_host_cep(
+        return self._test_ims_conference_merge_drop_first_call_from_host(
             call_ab_id, call_ac_id)
 
     @TelephonyBaseTest.tel_test_wrap
@@ -3986,7 +3826,7 @@
         if call_ab_id is None or call_ac_id is None:
             return False
 
-        return self._test_ims_conference_merge_drop_second_call_no_cep(
+        return self._test_ims_conference_merge_drop_second_call_from_participant(
             call_ab_id, call_ac_id)
 
     @TelephonyBaseTest.tel_test_wrap
@@ -4008,7 +3848,7 @@
         if call_ab_id is None or call_ac_id is None:
             return False
 
-        return self._test_ims_conference_merge_drop_second_call_from_participant_cep(
+        return self._test_ims_conference_merge_drop_second_call_from_participant(
             call_ab_id, call_ac_id)
 
     @TelephonyBaseTest.tel_test_wrap
@@ -4029,7 +3869,7 @@
         if call_ab_id is None or call_ac_id is None:
             return False
 
-        return self._test_ims_conference_merge_drop_second_call_from_host_cep(
+        return self._test_ims_conference_merge_drop_second_call_from_host(
             call_ab_id, call_ac_id)
 
     @TelephonyBaseTest.tel_test_wrap
@@ -4051,7 +3891,7 @@
         if call_ab_id is None or call_ac_id is None:
             return False
 
-        return self._test_ims_conference_merge_drop_first_call_from_participant_cep(
+        return self._test_ims_conference_merge_drop_first_call_from_participant(
             call_ab_id, call_ac_id)
 
     @TelephonyBaseTest.tel_test_wrap
@@ -4072,7 +3912,7 @@
         if call_ab_id is None or call_ac_id is None:
             return False
 
-        return self._test_ims_conference_merge_drop_first_call_from_host_cep(
+        return self._test_ims_conference_merge_drop_first_call_from_host(
             call_ab_id, call_ac_id)
 
     @TelephonyBaseTest.tel_test_wrap
@@ -4094,7 +3934,7 @@
         if call_ab_id is None or call_ac_id is None:
             return False
 
-        return self._test_ims_conference_merge_drop_second_call_no_cep(
+        return self._test_ims_conference_merge_drop_second_call_from_participant(
             call_ab_id, call_ac_id)
 
     @TelephonyBaseTest.tel_test_wrap
@@ -4116,7 +3956,7 @@
         if call_ab_id is None or call_ac_id is None:
             return False
 
-        return self._test_ims_conference_merge_drop_second_call_from_participant_cep(
+        return self._test_ims_conference_merge_drop_second_call_from_participant(
             call_ab_id, call_ac_id)
 
     @TelephonyBaseTest.tel_test_wrap
@@ -4137,7 +3977,7 @@
         if call_ab_id is None or call_ac_id is None:
             return False
 
-        return self._test_ims_conference_merge_drop_second_call_from_host_cep(
+        return self._test_ims_conference_merge_drop_second_call_from_host(
             call_ab_id, call_ac_id)
 
     @TelephonyBaseTest.tel_test_wrap
@@ -4159,7 +3999,7 @@
         if call_ab_id is None or call_ac_id is None:
             return False
 
-        return self._test_ims_conference_merge_drop_first_call_from_participant_cep(
+        return self._test_ims_conference_merge_drop_first_call_from_participant(
             call_ab_id, call_ac_id)
 
     @TelephonyBaseTest.tel_test_wrap
@@ -4180,7 +4020,7 @@
         if call_ab_id is None or call_ac_id is None:
             return False
 
-        return self._test_ims_conference_merge_drop_first_call_from_host_cep(
+        return self._test_ims_conference_merge_drop_first_call_from_host(
             call_ab_id, call_ac_id)
 
     @TelephonyBaseTest.tel_test_wrap
@@ -4202,7 +4042,7 @@
         if call_ab_id is None or call_ac_id is None:
             return False
 
-        return self._test_ims_conference_merge_drop_second_call_no_cep(
+        return self._test_ims_conference_merge_drop_second_call_from_participant(
             call_ab_id, call_ac_id)
 
     @TelephonyBaseTest.tel_test_wrap
@@ -4224,7 +4064,7 @@
         if call_ab_id is None or call_ac_id is None:
             return False
 
-        return self._test_ims_conference_merge_drop_second_call_from_participant_cep(
+        return self._test_ims_conference_merge_drop_second_call_from_participant(
             call_ab_id, call_ac_id)
 
     @TelephonyBaseTest.tel_test_wrap
@@ -4245,7 +4085,7 @@
         if call_ab_id is None or call_ac_id is None:
             return False
 
-        return self._test_ims_conference_merge_drop_second_call_from_host_cep(
+        return self._test_ims_conference_merge_drop_second_call_from_host(
             call_ab_id, call_ac_id)
 
     @TelephonyBaseTest.tel_test_wrap
@@ -4267,7 +4107,7 @@
         if call_ab_id is None or call_ac_id is None:
             return False
 
-        return self._test_ims_conference_merge_drop_first_call_from_participant_cep(
+        return self._test_ims_conference_merge_drop_first_call_from_participant(
             call_ab_id, call_ac_id)
 
     @TelephonyBaseTest.tel_test_wrap
@@ -4288,7 +4128,7 @@
         if call_ab_id is None or call_ac_id is None:
             return False
 
-        return self._test_ims_conference_merge_drop_first_call_from_host_cep(
+        return self._test_ims_conference_merge_drop_first_call_from_host(
             call_ab_id, call_ac_id)
 
     @TelephonyBaseTest.tel_test_wrap
@@ -4899,7 +4739,7 @@
         if call_ab_id is None or call_ac_id is None:
             return False
 
-        return self._test_ims_conference_merge_drop_second_call_no_cep(
+        return self._test_ims_conference_merge_drop_second_call_from_participant(
             call_ab_id, call_ac_id)
 
     @TelephonyBaseTest.tel_test_wrap
@@ -4922,7 +4762,7 @@
         if call_ab_id is None or call_ac_id is None:
             return False
 
-        return self._test_ims_conference_merge_drop_second_call_from_participant_cep(
+        return self._test_ims_conference_merge_drop_second_call_from_participant(
             call_ab_id, call_ac_id)
 
     @TelephonyBaseTest.tel_test_wrap
@@ -4945,7 +4785,7 @@
         if call_ab_id is None or call_ac_id is None:
             return False
 
-        return self._test_ims_conference_merge_drop_second_call_from_host_cep(
+        return self._test_ims_conference_merge_drop_second_call_from_host(
             call_ab_id, call_ac_id)
 
     @TelephonyBaseTest.tel_test_wrap
@@ -4968,7 +4808,7 @@
         if call_ab_id is None or call_ac_id is None:
             return False
 
-        return self._test_ims_conference_merge_drop_first_call_from_participant_cep(
+        return self._test_ims_conference_merge_drop_first_call_from_participant(
             call_ab_id, call_ac_id)
 
     @TelephonyBaseTest.tel_test_wrap
@@ -4991,7 +4831,7 @@
         if call_ab_id is None or call_ac_id is None:
             return False
 
-        return self._test_ims_conference_merge_drop_first_call_from_host_cep(
+        return self._test_ims_conference_merge_drop_first_call_from_host(
             call_ab_id, call_ac_id)
 
     @TelephonyBaseTest.tel_test_wrap
@@ -5015,7 +4855,7 @@
         if call_ab_id is None or call_ac_id is None:
             return False
 
-        return self._test_ims_conference_merge_drop_second_call_no_cep(
+        return self._test_ims_conference_merge_drop_second_call_from_participant(
             call_ab_id, call_ac_id)
 
     @TelephonyBaseTest.tel_test_wrap
@@ -5039,7 +4879,7 @@
         if call_ab_id is None or call_ac_id is None:
             return False
 
-        return self._test_ims_conference_merge_drop_second_call_from_participant_cep(
+        return self._test_ims_conference_merge_drop_second_call_from_participant(
             call_ab_id, call_ac_id)
 
     @TelephonyBaseTest.tel_test_wrap
@@ -5063,7 +4903,7 @@
         if call_ab_id is None or call_ac_id is None:
             return False
 
-        return self._test_ims_conference_merge_drop_second_call_from_host_cep(
+        return self._test_ims_conference_merge_drop_second_call_from_host(
             call_ab_id, call_ac_id)
 
     @TelephonyBaseTest.tel_test_wrap
@@ -5087,7 +4927,7 @@
         if call_ab_id is None or call_ac_id is None:
             return False
 
-        return self._test_ims_conference_merge_drop_first_call_from_participant_cep(
+        return self._test_ims_conference_merge_drop_first_call_from_participant(
             call_ab_id, call_ac_id)
 
     @TelephonyBaseTest.tel_test_wrap
@@ -5111,7 +4951,7 @@
         if call_ab_id is None or call_ac_id is None:
             return False
 
-        return self._test_ims_conference_merge_drop_first_call_from_host_cep(
+        return self._test_ims_conference_merge_drop_first_call_from_host(
             call_ab_id, call_ac_id)
 
     @TelephonyBaseTest.tel_test_wrap
@@ -5134,7 +4974,7 @@
         if call_ab_id is None or call_ac_id is None:
             return False
 
-        return self._test_ims_conference_merge_drop_second_call_no_cep(
+        return self._test_ims_conference_merge_drop_second_call_from_participant(
             call_ab_id, call_ac_id)
 
     @TelephonyBaseTest.tel_test_wrap
@@ -5157,7 +4997,7 @@
         if call_ab_id is None or call_ac_id is None:
             return False
 
-        return self._test_ims_conference_merge_drop_second_call_from_participant_cep(
+        return self._test_ims_conference_merge_drop_second_call_from_participant(
             call_ab_id, call_ac_id)
 
     @TelephonyBaseTest.tel_test_wrap
@@ -5180,7 +5020,7 @@
         if call_ab_id is None or call_ac_id is None:
             return False
 
-        return self._test_ims_conference_merge_drop_second_call_from_host_cep(
+        return self._test_ims_conference_merge_drop_second_call_from_host(
             call_ab_id, call_ac_id)
 
     @TelephonyBaseTest.tel_test_wrap
@@ -5203,7 +5043,7 @@
         if call_ab_id is None or call_ac_id is None:
             return False
 
-        return self._test_ims_conference_merge_drop_first_call_from_participant_cep(
+        return self._test_ims_conference_merge_drop_first_call_from_participant(
             call_ab_id, call_ac_id)
 
     @TelephonyBaseTest.tel_test_wrap
@@ -5226,7 +5066,7 @@
         if call_ab_id is None or call_ac_id is None:
             return False
 
-        return self._test_ims_conference_merge_drop_first_call_from_host_cep(
+        return self._test_ims_conference_merge_drop_first_call_from_host(
             call_ab_id, call_ac_id)
 
     @TelephonyBaseTest.tel_test_wrap
@@ -5250,7 +5090,7 @@
         if call_ab_id is None or call_ac_id is None:
             return False
 
-        return self._test_ims_conference_merge_drop_second_call_no_cep(
+        return self._test_ims_conference_merge_drop_second_call_from_participant(
             call_ab_id, call_ac_id)
 
     @TelephonyBaseTest.tel_test_wrap
@@ -5274,7 +5114,7 @@
         if call_ab_id is None or call_ac_id is None:
             return False
 
-        return self._test_ims_conference_merge_drop_second_call_from_participant_cep(
+        return self._test_ims_conference_merge_drop_second_call_from_participant(
             call_ab_id, call_ac_id)
 
     @TelephonyBaseTest.tel_test_wrap
@@ -5298,7 +5138,7 @@
         if call_ab_id is None or call_ac_id is None:
             return False
 
-        return self._test_ims_conference_merge_drop_second_call_from_host_cep(
+        return self._test_ims_conference_merge_drop_second_call_from_host(
             call_ab_id, call_ac_id)
 
     @TelephonyBaseTest.tel_test_wrap
@@ -5322,7 +5162,7 @@
         if call_ab_id is None or call_ac_id is None:
             return False
 
-        return self._test_ims_conference_merge_drop_first_call_from_participant_cep(
+        return self._test_ims_conference_merge_drop_first_call_from_participant(
             call_ab_id, call_ac_id)
 
     @TelephonyBaseTest.tel_test_wrap
@@ -5346,7 +5186,7 @@
         if call_ab_id is None or call_ac_id is None:
             return False
 
-        return self._test_ims_conference_merge_drop_first_call_from_host_cep(
+        return self._test_ims_conference_merge_drop_first_call_from_host(
             call_ab_id, call_ac_id)
 
     @TelephonyBaseTest.tel_test_wrap
@@ -5369,7 +5209,7 @@
         if call_ab_id is None or call_ac_id is None:
             return False
 
-        return self._test_ims_conference_merge_drop_second_call_no_cep(
+        return self._test_ims_conference_merge_drop_second_call_from_participant(
             call_ab_id, call_ac_id)
 
     @TelephonyBaseTest.tel_test_wrap
@@ -5392,7 +5232,7 @@
         if call_ab_id is None or call_ac_id is None:
             return False
 
-        return self._test_ims_conference_merge_drop_second_call_from_participant_cep(
+        return self._test_ims_conference_merge_drop_second_call_from_participant(
             call_ab_id, call_ac_id)
 
     @TelephonyBaseTest.tel_test_wrap
@@ -5415,7 +5255,7 @@
         if call_ab_id is None or call_ac_id is None:
             return False
 
-        return self._test_ims_conference_merge_drop_second_call_from_host_cep(
+        return self._test_ims_conference_merge_drop_second_call_from_host(
             call_ab_id, call_ac_id)
 
     @TelephonyBaseTest.tel_test_wrap
@@ -5438,7 +5278,7 @@
         if call_ab_id is None or call_ac_id is None:
             return False
 
-        return self._test_ims_conference_merge_drop_first_call_from_participant_cep(
+        return self._test_ims_conference_merge_drop_first_call_from_participant(
             call_ab_id, call_ac_id)
 
     @TelephonyBaseTest.tel_test_wrap
@@ -5461,7 +5301,7 @@
         if call_ab_id is None or call_ac_id is None:
             return False
 
-        return self._test_ims_conference_merge_drop_first_call_from_host_cep(
+        return self._test_ims_conference_merge_drop_first_call_from_host(
             call_ab_id, call_ac_id)
 
     @TelephonyBaseTest.tel_test_wrap
@@ -5485,7 +5325,7 @@
         if call_ab_id is None or call_ac_id is None:
             return False
 
-        return self._test_ims_conference_merge_drop_second_call_no_cep(
+        return self._test_ims_conference_merge_drop_second_call_from_participant(
             call_ab_id, call_ac_id)
 
     @TelephonyBaseTest.tel_test_wrap
@@ -5509,7 +5349,7 @@
         if call_ab_id is None or call_ac_id is None:
             return False
 
-        return self._test_ims_conference_merge_drop_second_call_from_participant_cep(
+        return self._test_ims_conference_merge_drop_second_call_from_participant(
             call_ab_id, call_ac_id)
 
     @TelephonyBaseTest.tel_test_wrap
@@ -5533,7 +5373,7 @@
         if call_ab_id is None or call_ac_id is None:
             return False
 
-        return self._test_ims_conference_merge_drop_second_call_from_host_cep(
+        return self._test_ims_conference_merge_drop_second_call_from_host(
             call_ab_id, call_ac_id)
 
     @TelephonyBaseTest.tel_test_wrap
@@ -5557,7 +5397,7 @@
         if call_ab_id is None or call_ac_id is None:
             return False
 
-        return self._test_ims_conference_merge_drop_first_call_from_participant_cep(
+        return self._test_ims_conference_merge_drop_first_call_from_participant(
             call_ab_id, call_ac_id)
 
     @TelephonyBaseTest.tel_test_wrap
@@ -5581,7 +5421,7 @@
         if call_ab_id is None or call_ac_id is None:
             return False
 
-        return self._test_ims_conference_merge_drop_first_call_from_host_cep(
+        return self._test_ims_conference_merge_drop_first_call_from_host(
             call_ab_id, call_ac_id)
 
     @TelephonyBaseTest.tel_test_wrap
@@ -5604,7 +5444,7 @@
         if call_ab_id is None or call_ac_id is None:
             return False
 
-        return self._test_ims_conference_merge_drop_second_call_no_cep(
+        return self._test_ims_conference_merge_drop_second_call_from_participant(
             call_ab_id, call_ac_id)
 
     @TelephonyBaseTest.tel_test_wrap
@@ -5627,7 +5467,7 @@
         if call_ab_id is None or call_ac_id is None:
             return False
 
-        return self._test_ims_conference_merge_drop_second_call_from_participant_cep(
+        return self._test_ims_conference_merge_drop_second_call_from_participant(
             call_ab_id, call_ac_id)
 
     @TelephonyBaseTest.tel_test_wrap
@@ -5650,7 +5490,7 @@
         if call_ab_id is None or call_ac_id is None:
             return False
 
-        return self._test_ims_conference_merge_drop_second_call_from_host_cep(
+        return self._test_ims_conference_merge_drop_second_call_from_host(
             call_ab_id, call_ac_id)
 
     @TelephonyBaseTest.tel_test_wrap
@@ -5673,7 +5513,7 @@
         if call_ab_id is None or call_ac_id is None:
             return False
 
-        return self._test_ims_conference_merge_drop_first_call_from_participant_cep(
+        return self._test_ims_conference_merge_drop_first_call_from_participant(
             call_ab_id, call_ac_id)
 
     @TelephonyBaseTest.tel_test_wrap
@@ -5696,7 +5536,7 @@
         if call_ab_id is None or call_ac_id is None:
             return False
 
-        return self._test_ims_conference_merge_drop_first_call_from_host_cep(
+        return self._test_ims_conference_merge_drop_first_call_from_host(
             call_ab_id, call_ac_id)
 
     @TelephonyBaseTest.tel_test_wrap
@@ -5720,7 +5560,7 @@
         if call_ab_id is None or call_ac_id is None:
             return False
 
-        return self._test_ims_conference_merge_drop_second_call_no_cep(
+        return self._test_ims_conference_merge_drop_second_call_from_participant(
             call_ab_id, call_ac_id)
 
     @TelephonyBaseTest.tel_test_wrap
@@ -5744,7 +5584,7 @@
         if call_ab_id is None or call_ac_id is None:
             return False
 
-        return self._test_ims_conference_merge_drop_second_call_from_participant_cep(
+        return self._test_ims_conference_merge_drop_second_call_from_participant(
             call_ab_id, call_ac_id)
 
     @TelephonyBaseTest.tel_test_wrap
@@ -5768,7 +5608,7 @@
         if call_ab_id is None or call_ac_id is None:
             return False
 
-        return self._test_ims_conference_merge_drop_second_call_from_host_cep(
+        return self._test_ims_conference_merge_drop_second_call_from_host(
             call_ab_id, call_ac_id)
 
     @TelephonyBaseTest.tel_test_wrap
@@ -5792,7 +5632,7 @@
         if call_ab_id is None or call_ac_id is None:
             return False
 
-        return self._test_ims_conference_merge_drop_first_call_from_participant_cep(
+        return self._test_ims_conference_merge_drop_first_call_from_participant(
             call_ab_id, call_ac_id)
 
     @TelephonyBaseTest.tel_test_wrap
@@ -5816,7 +5656,7 @@
         if call_ab_id is None or call_ac_id is None:
             return False
 
-        return self._test_ims_conference_merge_drop_first_call_from_host_cep(
+        return self._test_ims_conference_merge_drop_first_call_from_host(
             call_ab_id, call_ac_id)
 
     @TelephonyBaseTest.tel_test_wrap
@@ -5839,7 +5679,7 @@
         if call_ab_id is None or call_ac_id is None:
             return False
 
-        return self._test_ims_conference_merge_drop_second_call_no_cep(
+        return self._test_ims_conference_merge_drop_second_call_from_participant(
             call_ab_id, call_ac_id)
 
     @TelephonyBaseTest.tel_test_wrap
@@ -5862,7 +5702,7 @@
         if call_ab_id is None or call_ac_id is None:
             return False
 
-        return self._test_ims_conference_merge_drop_second_call_from_participant_cep(
+        return self._test_ims_conference_merge_drop_second_call_from_participant(
             call_ab_id, call_ac_id)
 
     @TelephonyBaseTest.tel_test_wrap
@@ -5885,7 +5725,7 @@
         if call_ab_id is None or call_ac_id is None:
             return False
 
-        return self._test_ims_conference_merge_drop_second_call_from_host_cep(
+        return self._test_ims_conference_merge_drop_second_call_from_host(
             call_ab_id, call_ac_id)
 
     @TelephonyBaseTest.tel_test_wrap
@@ -5908,7 +5748,7 @@
         if call_ab_id is None or call_ac_id is None:
             return False
 
-        return self._test_ims_conference_merge_drop_first_call_from_participant_cep(
+        return self._test_ims_conference_merge_drop_first_call_from_participant(
             call_ab_id, call_ac_id)
 
     @TelephonyBaseTest.tel_test_wrap
@@ -5931,7 +5771,7 @@
         if call_ab_id is None or call_ac_id is None:
             return False
 
-        return self._test_ims_conference_merge_drop_first_call_from_host_cep(
+        return self._test_ims_conference_merge_drop_first_call_from_host(
             call_ab_id, call_ac_id)
 
     @TelephonyBaseTest.tel_test_wrap
@@ -5955,7 +5795,7 @@
         if call_ab_id is None or call_ac_id is None:
             return False
 
-        return self._test_ims_conference_merge_drop_second_call_no_cep(
+        return self._test_ims_conference_merge_drop_second_call_from_participant(
             call_ab_id, call_ac_id)
 
     @TelephonyBaseTest.tel_test_wrap
@@ -5979,7 +5819,7 @@
         if call_ab_id is None or call_ac_id is None:
             return False
 
-        return self._test_ims_conference_merge_drop_second_call_from_participant_cep(
+        return self._test_ims_conference_merge_drop_second_call_from_participant(
             call_ab_id, call_ac_id)
 
     @TelephonyBaseTest.tel_test_wrap
@@ -6003,7 +5843,7 @@
         if call_ab_id is None or call_ac_id is None:
             return False
 
-        return self._test_ims_conference_merge_drop_second_call_from_host_cep(
+        return self._test_ims_conference_merge_drop_second_call_from_host(
             call_ab_id, call_ac_id)
 
     @TelephonyBaseTest.tel_test_wrap
@@ -6027,7 +5867,7 @@
         if call_ab_id is None or call_ac_id is None:
             return False
 
-        return self._test_ims_conference_merge_drop_first_call_from_participant_cep(
+        return self._test_ims_conference_merge_drop_first_call_from_participant(
             call_ab_id, call_ac_id)
 
     @TelephonyBaseTest.tel_test_wrap
@@ -6051,7 +5891,7 @@
         if call_ab_id is None or call_ac_id is None:
             return False
 
-        return self._test_ims_conference_merge_drop_first_call_from_host_cep(
+        return self._test_ims_conference_merge_drop_first_call_from_host(
             call_ab_id, call_ac_id)
 
     @TelephonyBaseTest.tel_test_wrap
@@ -6074,7 +5914,7 @@
         if call_ab_id is None or call_ac_id is None:
             return False
 
-        return self._test_ims_conference_merge_drop_second_call_no_cep(
+        return self._test_ims_conference_merge_drop_second_call_from_participant(
             call_ab_id, call_ac_id)
 
     @TelephonyBaseTest.tel_test_wrap
@@ -6097,7 +5937,7 @@
         if call_ab_id is None or call_ac_id is None:
             return False
 
-        return self._test_ims_conference_merge_drop_second_call_from_participant_cep(
+        return self._test_ims_conference_merge_drop_second_call_from_participant(
             call_ab_id, call_ac_id)
 
     @TelephonyBaseTest.tel_test_wrap
@@ -6120,7 +5960,7 @@
         if call_ab_id is None or call_ac_id is None:
             return False
 
-        return self._test_ims_conference_merge_drop_second_call_from_host_cep(
+        return self._test_ims_conference_merge_drop_second_call_from_host(
             call_ab_id, call_ac_id)
 
     @TelephonyBaseTest.tel_test_wrap
@@ -6143,7 +5983,7 @@
         if call_ab_id is None or call_ac_id is None:
             return False
 
-        return self._test_ims_conference_merge_drop_first_call_from_participant_cep(
+        return self._test_ims_conference_merge_drop_first_call_from_participant(
             call_ab_id, call_ac_id)
 
     @TelephonyBaseTest.tel_test_wrap
@@ -6166,7 +6006,7 @@
         if call_ab_id is None or call_ac_id is None:
             return False
 
-        return self._test_ims_conference_merge_drop_first_call_from_host_cep(
+        return self._test_ims_conference_merge_drop_first_call_from_host(
             call_ab_id, call_ac_id)
 
     @TelephonyBaseTest.tel_test_wrap
@@ -6190,7 +6030,7 @@
         if call_ab_id is None or call_ac_id is None:
             return False
 
-        return self._test_ims_conference_merge_drop_second_call_no_cep(
+        return self._test_ims_conference_merge_drop_second_call_from_participant(
             call_ab_id, call_ac_id)
 
     @TelephonyBaseTest.tel_test_wrap
@@ -6214,7 +6054,7 @@
         if call_ab_id is None or call_ac_id is None:
             return False
 
-        return self._test_ims_conference_merge_drop_second_call_from_participant_cep(
+        return self._test_ims_conference_merge_drop_second_call_from_participant(
             call_ab_id, call_ac_id)
 
     @TelephonyBaseTest.tel_test_wrap
@@ -6238,7 +6078,7 @@
         if call_ab_id is None or call_ac_id is None:
             return False
 
-        return self._test_ims_conference_merge_drop_second_call_from_host_cep(
+        return self._test_ims_conference_merge_drop_second_call_from_host(
             call_ab_id, call_ac_id)
 
     @TelephonyBaseTest.tel_test_wrap
@@ -6262,7 +6102,7 @@
         if call_ab_id is None or call_ac_id is None:
             return False
 
-        return self._test_ims_conference_merge_drop_first_call_from_participant_cep(
+        return self._test_ims_conference_merge_drop_first_call_from_participant(
             call_ab_id, call_ac_id)
 
     @TelephonyBaseTest.tel_test_wrap
@@ -6286,7 +6126,7 @@
         if call_ab_id is None or call_ac_id is None:
             return False
 
-        return self._test_ims_conference_merge_drop_first_call_from_host_cep(
+        return self._test_ims_conference_merge_drop_first_call_from_host(
             call_ab_id, call_ac_id)
 
     @TelephonyBaseTest.tel_test_wrap
@@ -6309,7 +6149,7 @@
         if call_ab_id is None or call_ac_id is None:
             return False
 
-        return self._test_ims_conference_merge_drop_second_call_no_cep(
+        return self._test_ims_conference_merge_drop_second_call_from_participant(
             call_ab_id, call_ac_id)
 
     @TelephonyBaseTest.tel_test_wrap
@@ -6332,7 +6172,7 @@
         if call_ab_id is None or call_ac_id is None:
             return False
 
-        return self._test_ims_conference_merge_drop_second_call_from_participant_cep(
+        return self._test_ims_conference_merge_drop_second_call_from_participant(
             call_ab_id, call_ac_id)
 
     @TelephonyBaseTest.tel_test_wrap
@@ -6355,7 +6195,7 @@
         if call_ab_id is None or call_ac_id is None:
             return False
 
-        return self._test_ims_conference_merge_drop_second_call_from_host_cep(
+        return self._test_ims_conference_merge_drop_second_call_from_host(
             call_ab_id, call_ac_id)
 
     @TelephonyBaseTest.tel_test_wrap
@@ -6378,7 +6218,7 @@
         if call_ab_id is None or call_ac_id is None:
             return False
 
-        return self._test_ims_conference_merge_drop_first_call_from_participant_cep(
+        return self._test_ims_conference_merge_drop_first_call_from_participant(
             call_ab_id, call_ac_id)
 
     @TelephonyBaseTest.tel_test_wrap
@@ -6401,7 +6241,7 @@
         if call_ab_id is None or call_ac_id is None:
             return False
 
-        return self._test_ims_conference_merge_drop_first_call_from_host_cep(
+        return self._test_ims_conference_merge_drop_first_call_from_host(
             call_ab_id, call_ac_id)
 
     @TelephonyBaseTest.tel_test_wrap
@@ -6425,7 +6265,7 @@
         if call_ab_id is None or call_ac_id is None:
             return False
 
-        return self._test_ims_conference_merge_drop_second_call_no_cep(
+        return self._test_ims_conference_merge_drop_second_call_from_participant(
             call_ab_id, call_ac_id)
 
     @TelephonyBaseTest.tel_test_wrap
@@ -6449,7 +6289,7 @@
         if call_ab_id is None or call_ac_id is None:
             return False
 
-        return self._test_ims_conference_merge_drop_second_call_from_participant_cep(
+        return self._test_ims_conference_merge_drop_second_call_from_participant(
             call_ab_id, call_ac_id)
 
     @TelephonyBaseTest.tel_test_wrap
@@ -6473,7 +6313,7 @@
         if call_ab_id is None or call_ac_id is None:
             return False
 
-        return self._test_ims_conference_merge_drop_second_call_from_host_cep(
+        return self._test_ims_conference_merge_drop_second_call_from_host(
             call_ab_id, call_ac_id)
 
     @TelephonyBaseTest.tel_test_wrap
@@ -6497,7 +6337,7 @@
         if call_ab_id is None or call_ac_id is None:
             return False
 
-        return self._test_ims_conference_merge_drop_first_call_from_participant_cep(
+        return self._test_ims_conference_merge_drop_first_call_from_participant(
             call_ab_id, call_ac_id)
 
     @TelephonyBaseTest.tel_test_wrap
@@ -6521,7 +6361,7 @@
         if call_ab_id is None or call_ac_id is None:
             return False
 
-        return self._test_ims_conference_merge_drop_first_call_from_host_cep(
+        return self._test_ims_conference_merge_drop_first_call_from_host(
             call_ab_id, call_ac_id)
 
     @TelephonyBaseTest.tel_test_wrap
@@ -6544,7 +6384,7 @@
         if call_ab_id is None or call_ac_id is None:
             return False
 
-        return self._test_ims_conference_merge_drop_second_call_no_cep(
+        return self._test_ims_conference_merge_drop_second_call_from_participant(
             call_ab_id, call_ac_id)
 
     @TelephonyBaseTest.tel_test_wrap
@@ -6567,7 +6407,7 @@
         if call_ab_id is None or call_ac_id is None:
             return False
 
-        return self._test_ims_conference_merge_drop_second_call_from_participant_cep(
+        return self._test_ims_conference_merge_drop_second_call_from_participant(
             call_ab_id, call_ac_id)
 
     @TelephonyBaseTest.tel_test_wrap
@@ -6590,7 +6430,7 @@
         if call_ab_id is None or call_ac_id is None:
             return False
 
-        return self._test_ims_conference_merge_drop_second_call_from_host_cep(
+        return self._test_ims_conference_merge_drop_second_call_from_host(
             call_ab_id, call_ac_id)
 
     @TelephonyBaseTest.tel_test_wrap
@@ -6613,7 +6453,7 @@
         if call_ab_id is None or call_ac_id is None:
             return False
 
-        return self._test_ims_conference_merge_drop_first_call_from_participant_cep(
+        return self._test_ims_conference_merge_drop_first_call_from_participant(
             call_ab_id, call_ac_id)
 
     @TelephonyBaseTest.tel_test_wrap
@@ -6636,7 +6476,7 @@
         if call_ab_id is None or call_ac_id is None:
             return False
 
-        return self._test_ims_conference_merge_drop_first_call_from_host_cep(
+        return self._test_ims_conference_merge_drop_first_call_from_host(
             call_ab_id, call_ac_id)
 
     @TelephonyBaseTest.tel_test_wrap
@@ -6660,7 +6500,7 @@
         if call_ab_id is None or call_ac_id is None:
             return False
 
-        return self._test_ims_conference_merge_drop_second_call_no_cep(
+        return self._test_ims_conference_merge_drop_second_call_from_participant(
             call_ab_id, call_ac_id)
 
     @TelephonyBaseTest.tel_test_wrap
@@ -6684,7 +6524,7 @@
         if call_ab_id is None or call_ac_id is None:
             return False
 
-        return self._test_ims_conference_merge_drop_second_call_from_participant_cep(
+        return self._test_ims_conference_merge_drop_second_call_from_participant(
             call_ab_id, call_ac_id)
 
     @TelephonyBaseTest.tel_test_wrap
@@ -6708,7 +6548,7 @@
         if call_ab_id is None or call_ac_id is None:
             return False
 
-        return self._test_ims_conference_merge_drop_second_call_from_host_cep(
+        return self._test_ims_conference_merge_drop_second_call_from_host(
             call_ab_id, call_ac_id)
 
     @TelephonyBaseTest.tel_test_wrap
@@ -6732,7 +6572,7 @@
         if call_ab_id is None or call_ac_id is None:
             return False
 
-        return self._test_ims_conference_merge_drop_first_call_from_participant_cep(
+        return self._test_ims_conference_merge_drop_first_call_from_participant(
             call_ab_id, call_ac_id)
 
     @TelephonyBaseTest.tel_test_wrap
@@ -6756,7 +6596,7 @@
         if call_ab_id is None or call_ac_id is None:
             return False
 
-        return self._test_ims_conference_merge_drop_first_call_from_host_cep(
+        return self._test_ims_conference_merge_drop_first_call_from_host(
             call_ab_id, call_ac_id)
 
     @TelephonyBaseTest.tel_test_wrap
@@ -6779,7 +6619,7 @@
         if call_ab_id is None or call_ac_id is None:
             return False
 
-        return self._test_ims_conference_merge_drop_second_call_no_cep(
+        return self._test_ims_conference_merge_drop_second_call_from_participant(
             call_ab_id, call_ac_id)
 
     @TelephonyBaseTest.tel_test_wrap
@@ -6802,7 +6642,7 @@
         if call_ab_id is None or call_ac_id is None:
             return False
 
-        return self._test_ims_conference_merge_drop_second_call_from_participant_cep(
+        return self._test_ims_conference_merge_drop_second_call_from_participant(
             call_ab_id, call_ac_id)
 
     @TelephonyBaseTest.tel_test_wrap
@@ -6825,7 +6665,7 @@
         if call_ab_id is None or call_ac_id is None:
             return False
 
-        return self._test_ims_conference_merge_drop_second_call_from_host_cep(
+        return self._test_ims_conference_merge_drop_second_call_from_host(
             call_ab_id, call_ac_id)
 
     @TelephonyBaseTest.tel_test_wrap
@@ -6848,7 +6688,7 @@
         if call_ab_id is None or call_ac_id is None:
             return False
 
-        return self._test_ims_conference_merge_drop_first_call_from_participant_cep(
+        return self._test_ims_conference_merge_drop_first_call_from_participant(
             call_ab_id, call_ac_id)
 
     @TelephonyBaseTest.tel_test_wrap
@@ -6871,7 +6711,7 @@
         if call_ab_id is None or call_ac_id is None:
             return False
 
-        return self._test_ims_conference_merge_drop_first_call_from_host_cep(
+        return self._test_ims_conference_merge_drop_first_call_from_host(
             call_ab_id, call_ac_id)
 
     @TelephonyBaseTest.tel_test_wrap
@@ -6895,7 +6735,7 @@
         if call_ab_id is None or call_ac_id is None:
             return False
 
-        return self._test_ims_conference_merge_drop_second_call_no_cep(
+        return self._test_ims_conference_merge_drop_second_call_from_participant(
             call_ab_id, call_ac_id)
 
     @TelephonyBaseTest.tel_test_wrap
@@ -6919,7 +6759,7 @@
         if call_ab_id is None or call_ac_id is None:
             return False
 
-        return self._test_ims_conference_merge_drop_second_call_from_participant_cep(
+        return self._test_ims_conference_merge_drop_second_call_from_participant(
             call_ab_id, call_ac_id)
 
     @TelephonyBaseTest.tel_test_wrap
@@ -6943,7 +6783,7 @@
         if call_ab_id is None or call_ac_id is None:
             return False
 
-        return self._test_ims_conference_merge_drop_second_call_from_host_cep(
+        return self._test_ims_conference_merge_drop_second_call_from_host(
             call_ab_id, call_ac_id)
 
     @TelephonyBaseTest.tel_test_wrap
@@ -6967,7 +6807,7 @@
         if call_ab_id is None or call_ac_id is None:
             return False
 
-        return self._test_ims_conference_merge_drop_first_call_from_participant_cep(
+        return self._test_ims_conference_merge_drop_first_call_from_participant(
             call_ab_id, call_ac_id)
 
     @TelephonyBaseTest.tel_test_wrap
@@ -6991,7 +6831,7 @@
         if call_ab_id is None or call_ac_id is None:
             return False
 
-        return self._test_ims_conference_merge_drop_first_call_from_host_cep(
+        return self._test_ims_conference_merge_drop_first_call_from_host(
             call_ab_id, call_ac_id)
 
     @TelephonyBaseTest.tel_test_wrap
@@ -7318,7 +7158,7 @@
         if call_ab_id is None or call_ac_id is None:
             return False
 
-        return self._test_epdg_conference_merge_drop(call_ab_id, call_ac_id)
+        return self._test_ims_conference_merge_drop_second_call_from_participant(call_ab_id, call_ac_id)
 
     @TelephonyBaseTest.tel_test_wrap
     @test_tracker_info(uuid="89b9f228-97a6-4e5c-96b9-a7f87d847c22")
@@ -7353,7 +7193,8 @@
         if call_ab_id is None or call_ac_id is None:
             return False
 
-        return self._test_epdg_conference_merge_drop(call_ab_id, call_ac_id)
+        return self._test_ims_conference_merge_drop_second_call_from_participant(
+            call_ab_id, call_ac_id)
 
     @TelephonyBaseTest.tel_test_wrap
     @test_tracker_info(uuid="2c6dc281-59b0-4ea4-b811-e4c3a4d654ab")
@@ -7388,7 +7229,8 @@
         if call_ab_id is None or call_ac_id is None:
             return False
 
-        return self._test_epdg_conference_merge_drop(call_ab_id, call_ac_id)
+        return self._test_ims_conference_merge_drop_second_call_from_participant(
+            call_ab_id, call_ac_id)
 
     @TelephonyBaseTest.tel_test_wrap
     @test_tracker_info(uuid="f6727241-b727-4eb8-8c0d-f61d3a14a635")
@@ -7423,7 +7265,8 @@
         if call_ab_id is None or call_ac_id is None:
             return False
 
-        return self._test_epdg_conference_merge_drop(call_ab_id, call_ac_id)
+        return self._test_ims_conference_merge_drop_second_call_from_participant(
+            call_ab_id, call_ac_id)
 
     @TelephonyBaseTest.tel_test_wrap
     @test_tracker_info(uuid="c9e54db0-2b0b-428b-ba63-619ad0b8637b")
@@ -7458,7 +7301,8 @@
         if call_ab_id is None or call_ac_id is None:
             return False
 
-        return self._test_epdg_conference_merge_drop(call_ab_id, call_ac_id)
+        return self._test_ims_conference_merge_drop_second_call_from_participant(
+            call_ab_id, call_ac_id)
 
     @TelephonyBaseTest.tel_test_wrap
     @test_tracker_info(uuid="a478cc82-d95c-43fc-9735-d8333b8937e2")
@@ -7493,7 +7337,8 @@
         if call_ab_id is None or call_ac_id is None:
             return False
 
-        return self._test_epdg_conference_merge_drop(call_ab_id, call_ac_id)
+        return self._test_ims_conference_merge_drop_second_call_from_participant(
+            call_ab_id, call_ac_id)
 
     @TelephonyBaseTest.tel_test_wrap
     @test_tracker_info(uuid="b1acb263-1481-44a5-b18e-58bdeff7bc1e")
@@ -7524,7 +7369,8 @@
         if call_ab_id is None or call_ac_id is None:
             return False
 
-        return self._test_epdg_conference_merge_drop(call_ab_id, call_ac_id)
+        return self._test_ims_conference_merge_drop_second_call_from_participant(
+            call_ab_id, call_ac_id)
 
     @TelephonyBaseTest.tel_test_wrap
     @test_tracker_info(uuid="03b8a0d2-80dd-465a-ad14-5db94cdbcc53")
@@ -7555,7 +7401,8 @@
         if call_ab_id is None or call_ac_id is None:
             return False
 
-        return self._test_epdg_conference_merge_drop(call_ab_id, call_ac_id)
+        return self._test_ims_conference_merge_drop_second_call_from_participant(
+            call_ab_id, call_ac_id)
 
     @TelephonyBaseTest.tel_test_wrap
     @test_tracker_info(uuid="9eb1a816-1e2c-41da-b083-2026163a3893")
@@ -7586,7 +7433,8 @@
         if call_ab_id is None or call_ac_id is None:
             return False
 
-        return self._test_epdg_conference_merge_drop(call_ab_id, call_ac_id)
+        return self._test_ims_conference_merge_drop_second_call_from_participant(
+            call_ab_id, call_ac_id)
 
     @TelephonyBaseTest.tel_test_wrap
     @test_tracker_info(uuid="3d66a1b6-916f-4221-bd99-21ff4d40ebb8")
@@ -7617,7 +7465,8 @@
         if call_ab_id is None or call_ac_id is None:
             return False
 
-        return self._test_epdg_conference_merge_drop(call_ab_id, call_ac_id)
+        return self._test_ims_conference_merge_drop_second_call_from_participant(
+            call_ab_id, call_ac_id)
 
     @TelephonyBaseTest.tel_test_wrap
     @test_tracker_info(uuid="9d8e8b2f-e2b9-4607-8c54-6233b3096123")
@@ -7648,7 +7497,8 @@
         if call_ab_id is None or call_ac_id is None:
             return False
 
-        return self._test_epdg_conference_merge_drop(call_ab_id, call_ac_id)
+        return self._test_ims_conference_merge_drop_second_call_from_participant(
+            call_ab_id, call_ac_id)
 
     @TelephonyBaseTest.tel_test_wrap
     @test_tracker_info(uuid="0884206b-2471-4a7e-95aa-228379416ff8")
@@ -7679,7 +7529,8 @@
         if call_ab_id is None or call_ac_id is None:
             return False
 
-        return self._test_epdg_conference_merge_drop(call_ab_id, call_ac_id)
+        return self._test_ims_conference_merge_drop_second_call_from_participant(
+            call_ab_id, call_ac_id)
 
     @TelephonyBaseTest.tel_test_wrap
     @test_tracker_info(uuid="c7706af6-dc77-4002-b295-66c60aeace6b")
@@ -7710,7 +7561,8 @@
         if call_ab_id is None or call_ac_id is None:
             return False
 
-        return self._test_epdg_conference_merge_drop(call_ab_id, call_ac_id)
+        return self._test_ims_conference_merge_drop_second_call_from_participant(
+            call_ab_id, call_ac_id)
 
     @TelephonyBaseTest.tel_test_wrap
     @test_tracker_info(uuid="b079618f-e32b-4ba0-9009-06e013805c39")
@@ -7741,7 +7593,8 @@
         if call_ab_id is None or call_ac_id is None:
             return False
 
-        return self._test_epdg_conference_merge_drop(call_ab_id, call_ac_id)
+        return self._test_ims_conference_merge_drop_second_call_from_participant(
+            call_ab_id, call_ac_id)
 
     @TelephonyBaseTest.tel_test_wrap
     @test_tracker_info(uuid="571fe98b-354f-4038-8441-0e4b1840eb7a")
@@ -7772,7 +7625,8 @@
         if call_ab_id is None or call_ac_id is None:
             return False
 
-        return self._test_epdg_conference_merge_drop(call_ab_id, call_ac_id)
+        return self._test_ims_conference_merge_drop_second_call_from_participant(
+            call_ab_id, call_ac_id)
 
     @TelephonyBaseTest.tel_test_wrap
     @test_tracker_info(uuid="8f531f3c-493e-43d6-9d6d-f4990b5feba4")
@@ -7803,7 +7657,8 @@
         if call_ab_id is None or call_ac_id is None:
             return False
 
-        return self._test_epdg_conference_merge_drop(call_ab_id, call_ac_id)
+        return self._test_ims_conference_merge_drop_second_call_from_participant(
+            call_ab_id, call_ac_id)
 
     @TelephonyBaseTest.tel_test_wrap
     @test_tracker_info(uuid="00e1194b-3c06-46c4-8764-0339c0aa9f9e")
@@ -7834,7 +7689,8 @@
         if call_ab_id is None or call_ac_id is None:
             return False
 
-        return self._test_epdg_conference_merge_drop(call_ab_id, call_ac_id)
+        return self._test_ims_conference_merge_drop_second_call_from_participant(
+            call_ab_id, call_ac_id)
 
     @TelephonyBaseTest.tel_test_wrap
     @test_tracker_info(uuid="c94f6444-d265-4277-9555-57041e3c4ff4")
@@ -7865,7 +7721,8 @@
         if call_ab_id is None or call_ac_id is None:
             return False
 
-        return self._test_epdg_conference_merge_drop(call_ab_id, call_ac_id)
+        return self._test_ims_conference_merge_drop_second_call_from_participant(
+            call_ab_id, call_ac_id)
 
     @TelephonyBaseTest.tel_test_wrap
     @test_tracker_info(uuid="0980745e-dcdc-4c56-84e3-e2ee076059ee")
@@ -7899,7 +7756,8 @@
         if call_ab_id is None or call_ac_id is None:
             return False
 
-        return self._test_epdg_conference_merge_drop(call_ab_id, call_ac_id)
+        return self._test_ims_conference_merge_drop_second_call_from_participant(
+            call_ab_id, call_ac_id)
 
     @TelephonyBaseTest.tel_test_wrap
     @test_tracker_info(uuid="6bf0b152-fb1c-4edc-9525-b39e8640b967")
@@ -7933,7 +7791,8 @@
         if call_ab_id is None or call_ac_id is None:
             return False
 
-        return self._test_epdg_conference_merge_drop(call_ab_id, call_ac_id)
+        return self._test_ims_conference_merge_drop_second_call_from_participant(
+            call_ab_id, call_ac_id)
 
     @TelephonyBaseTest.tel_test_wrap
     @test_tracker_info(uuid="e3013df6-98ca-4318-85ba-04011ba0a24f")
@@ -7968,7 +7827,8 @@
         if call_ab_id is None or call_ac_id is None:
             return False
 
-        return self._test_epdg_conference_merge_drop(call_ab_id, call_ac_id)
+        return self._test_ims_conference_merge_drop_second_call_from_participant(
+            call_ab_id, call_ac_id)
 
     @TelephonyBaseTest.tel_test_wrap
     @test_tracker_info(uuid="e88bf042-8799-44c7-bc50-66ac1e1fb2ac")
@@ -8004,7 +7864,8 @@
         if call_ab_id is None or call_ac_id is None:
             return False
 
-        return self._test_epdg_conference_merge_drop(call_ab_id, call_ac_id)
+        return self._test_ims_conference_merge_drop_second_call_from_participant(
+            call_ab_id, call_ac_id)
 
     @TelephonyBaseTest.tel_test_wrap
     @test_tracker_info(uuid="a8302e73-82a4-4409-b038-5c604fb4c66c")
@@ -8038,7 +7899,8 @@
         if call_ab_id is None or call_ac_id is None:
             return False
 
-        return self._test_epdg_conference_merge_drop(call_ab_id, call_ac_id)
+        return self._test_ims_conference_merge_drop_second_call_from_participant(
+            call_ab_id, call_ac_id)
 
     @TelephonyBaseTest.tel_test_wrap
     @test_tracker_info(uuid="80f69baf-1649-4858-b35c-b25baf79b42c")
@@ -8072,7 +7934,8 @@
         if call_ab_id is None or call_ac_id is None:
             return False
 
-        return self._test_epdg_conference_merge_drop(call_ab_id, call_ac_id)
+        return self._test_ims_conference_merge_drop_second_call_from_participant(
+            call_ab_id, call_ac_id)
 
     @TelephonyBaseTest.tel_test_wrap
     @test_tracker_info(uuid="1ac0c067-49fb-41d9-8649-cc709bdd8926")
@@ -8107,7 +7970,8 @@
         if call_ab_id is None or call_ac_id is None:
             return False
 
-        return self._test_epdg_conference_merge_drop(call_ab_id, call_ac_id)
+        return self._test_ims_conference_merge_drop_second_call_from_participant(
+            call_ab_id, call_ac_id)
 
     @TelephonyBaseTest.tel_test_wrap
     @test_tracker_info(uuid="b20b1a94-048c-4f10-9261-dde79e1edb00")
@@ -8143,7 +8007,8 @@
         if call_ab_id is None or call_ac_id is None:
             return False
 
-        return self._test_epdg_conference_merge_drop(call_ab_id, call_ac_id)
+        return self._test_ims_conference_merge_drop_second_call_from_participant(
+            call_ab_id, call_ac_id)
 
     @TelephonyBaseTest.tel_test_wrap
     @test_tracker_info(uuid="402b175f-1510-4e2a-97c2-7c9ea5ce40f6")
@@ -8173,7 +8038,8 @@
         if call_ab_id is None or call_ac_id is None:
             return False
 
-        return self._test_epdg_conference_merge_drop(call_ab_id, call_ac_id)
+        return self._test_ims_conference_merge_drop_second_call_from_participant(
+            call_ab_id, call_ac_id)
 
     @TelephonyBaseTest.tel_test_wrap
     @test_tracker_info(uuid="7c710fbf-4b77-4b46-9719-e17b3d047cfc")
@@ -8204,7 +8070,8 @@
         if call_ab_id is None or call_ac_id is None:
             return False
 
-        return self._test_epdg_conference_merge_drop(call_ab_id, call_ac_id)
+        return self._test_ims_conference_merge_drop_second_call_from_participant(
+            call_ab_id, call_ac_id)
 
     @TelephonyBaseTest.tel_test_wrap
     @test_tracker_info(uuid="642afbac-30c1-4dbf-bf3e-758ab6c3a306")
@@ -8235,7 +8102,8 @@
         if call_ab_id is None or call_ac_id is None:
             return False
 
-        return self._test_epdg_conference_merge_drop(call_ab_id, call_ac_id)
+        return self._test_ims_conference_merge_drop_second_call_from_participant(
+            call_ab_id, call_ac_id)
 
     @TelephonyBaseTest.tel_test_wrap
     @test_tracker_info(uuid="a4ae1e39-ed6d-412e-b821-321c715a5d47")
@@ -8267,7 +8135,8 @@
         if call_ab_id is None or call_ac_id is None:
             return False
 
-        return self._test_epdg_conference_merge_drop(call_ab_id, call_ac_id)
+        return self._test_ims_conference_merge_drop_second_call_from_participant(
+            call_ab_id, call_ac_id)
 
     @TelephonyBaseTest.tel_test_wrap
     @test_tracker_info(uuid="7b8431f2-8a49-4aa9-b84d-77f16a6a2c30")
@@ -8297,7 +8166,8 @@
         if call_ab_id is None or call_ac_id is None:
             return False
 
-        return self._test_epdg_conference_merge_drop(call_ab_id, call_ac_id)
+        return self._test_ims_conference_merge_drop_second_call_from_participant(
+            call_ab_id, call_ac_id)
 
     @TelephonyBaseTest.tel_test_wrap
     @test_tracker_info(uuid="5b4d7444-32a1-4e82-8847-1c4ae002edca")
@@ -8328,7 +8198,8 @@
         if call_ab_id is None or call_ac_id is None:
             return False
 
-        return self._test_epdg_conference_merge_drop(call_ab_id, call_ac_id)
+        return self._test_ims_conference_merge_drop_second_call_from_participant(
+            call_ab_id, call_ac_id)
 
     @TelephonyBaseTest.tel_test_wrap
     @test_tracker_info(uuid="88c6c179-0b56-4d03-b5e4-76a147a40995")
@@ -8359,7 +8230,8 @@
         if call_ab_id is None or call_ac_id is None:
             return False
 
-        return self._test_epdg_conference_merge_drop(call_ab_id, call_ac_id)
+        return self._test_ims_conference_merge_drop_second_call_from_participant(
+            call_ab_id, call_ac_id)
 
     @TelephonyBaseTest.tel_test_wrap
     @test_tracker_info(uuid="7f744ab3-f919-4a7a-83ce-e38487d619cc")
@@ -8391,7 +8263,8 @@
         if call_ab_id is None or call_ac_id is None:
             return False
 
-        return self._test_epdg_conference_merge_drop(call_ab_id, call_ac_id)
+        return self._test_ims_conference_merge_drop_second_call_from_participant(
+            call_ab_id, call_ac_id)
 
     @TelephonyBaseTest.tel_test_wrap
     @test_tracker_info(uuid="5c861a99-a1b8-45fc-ba67-f8fde4575efc")
@@ -8421,7 +8294,8 @@
         if call_ab_id is None or call_ac_id is None:
             return False
 
-        return self._test_epdg_conference_merge_drop(call_ab_id, call_ac_id)
+        return self._test_ims_conference_merge_drop_second_call_from_participant(
+            call_ab_id, call_ac_id)
 
     @TelephonyBaseTest.tel_test_wrap
     @test_tracker_info(uuid="fdb32a13-302c-4c1c-a77e-f78ed7e90911")
@@ -8452,7 +8326,8 @@
         if call_ab_id is None or call_ac_id is None:
             return False
 
-        return self._test_epdg_conference_merge_drop(call_ab_id, call_ac_id)
+        return self._test_ims_conference_merge_drop_second_call_from_participant(
+            call_ab_id, call_ac_id)
 
     @TelephonyBaseTest.tel_test_wrap
     @test_tracker_info(uuid="a2cf3366-ae66-4e8f-a682-df506173f282")
@@ -8483,7 +8358,8 @@
         if call_ab_id is None or call_ac_id is None:
             return False
 
-        return self._test_epdg_conference_merge_drop(call_ab_id, call_ac_id)
+        return self._test_ims_conference_merge_drop_second_call_from_participant(
+            call_ab_id, call_ac_id)
 
     @TelephonyBaseTest.tel_test_wrap
     @test_tracker_info(uuid="fc5f0f1c-9610-4d0f-adce-9c8db351e7da")
@@ -8515,7 +8391,8 @@
         if call_ab_id is None or call_ac_id is None:
             return False
 
-        return self._test_epdg_conference_merge_drop(call_ab_id, call_ac_id)
+        return self._test_ims_conference_merge_drop_second_call_from_participant(
+            call_ab_id, call_ac_id)
 
     @TelephonyBaseTest.tel_test_wrap
     @test_tracker_info(uuid="05332b1e-c36b-4874-b13b-f8e49d0d9bca")
@@ -8545,7 +8422,8 @@
         if call_ab_id is None or call_ac_id is None:
             return False
 
-        return self._test_epdg_conference_merge_drop(call_ab_id, call_ac_id)
+        return self._test_ims_conference_merge_drop_second_call_from_participant(
+            call_ab_id, call_ac_id)
 
     @TelephonyBaseTest.tel_test_wrap
     @test_tracker_info(uuid="2421d340-f9cb-47e7-ac3e-8581e141a6d0")
@@ -8576,7 +8454,8 @@
         if call_ab_id is None or call_ac_id is None:
             return False
 
-        return self._test_epdg_conference_merge_drop(call_ab_id, call_ac_id)
+        return self._test_ims_conference_merge_drop_second_call_from_participant(
+            call_ab_id, call_ac_id)
 
     @TelephonyBaseTest.tel_test_wrap
     @test_tracker_info(uuid="7c1f6008-cf59-4e63-9285-3cf1c26bc0aa")
@@ -8607,7 +8486,8 @@
         if call_ab_id is None or call_ac_id is None:
             return False
 
-        return self._test_epdg_conference_merge_drop(call_ab_id, call_ac_id)
+        return self._test_ims_conference_merge_drop_second_call_from_participant(
+            call_ab_id, call_ac_id)
 
     @TelephonyBaseTest.tel_test_wrap
     @test_tracker_info(uuid="be153f3d-0707-45d0-9ddd-4aa696e0e536")
@@ -8639,7 +8519,8 @@
         if call_ab_id is None or call_ac_id is None:
             return False
 
-        return self._test_epdg_conference_merge_drop(call_ab_id, call_ac_id)
+        return self._test_ims_conference_merge_drop_second_call_from_participant(
+            call_ab_id, call_ac_id)
 
     @TelephonyBaseTest.tel_test_wrap
     @test_tracker_info(uuid="7235c917-a2d4-4561-bda5-630171053f8f")
@@ -8669,7 +8550,8 @@
         if call_ab_id is None or call_ac_id is None:
             return False
 
-        return self._test_epdg_conference_merge_drop(call_ab_id, call_ac_id)
+        return self._test_ims_conference_merge_drop_second_call_from_participant(
+            call_ab_id, call_ac_id)
 
     @TelephonyBaseTest.tel_test_wrap
     @test_tracker_info(uuid="8e52b9a4-c0d1-4dcd-9359-746354124763")
@@ -8699,7 +8581,8 @@
         if call_ab_id is None or call_ac_id is None:
             return False
 
-        return self._test_epdg_conference_merge_drop(call_ab_id, call_ac_id)
+        return self._test_ims_conference_merge_drop_second_call_from_participant(
+            call_ab_id, call_ac_id)
 
     @TelephonyBaseTest.tel_test_wrap
     @test_tracker_info(uuid="49a4440f-40a1-4518-810a-6ba9f1fbc243")
@@ -8730,7 +8613,8 @@
         if call_ab_id is None or call_ac_id is None:
             return False
 
-        return self._test_epdg_conference_merge_drop(call_ab_id, call_ac_id)
+        return self._test_ims_conference_merge_drop_second_call_from_participant(
+            call_ab_id, call_ac_id)
 
     @TelephonyBaseTest.tel_test_wrap
     @test_tracker_info(uuid="9d05bde3-50ac-4a49-a0db-2181c9b5a10f")
@@ -8761,7 +8645,8 @@
         if call_ab_id is None or call_ac_id is None:
             return False
 
-        return self._test_epdg_conference_merge_drop(call_ab_id, call_ac_id)
+        return self._test_ims_conference_merge_drop_second_call_from_participant(
+            call_ab_id, call_ac_id)
 
     @TelephonyBaseTest.tel_test_wrap
     @test_tracker_info(uuid="5c44eb64-b184-417a-97c9-8c22c48fb731")
@@ -8791,7 +8676,8 @@
         if call_ab_id is None or call_ac_id is None:
             return False
 
-        return self._test_epdg_conference_merge_drop(call_ab_id, call_ac_id)
+        return self._test_ims_conference_merge_drop_second_call_from_participant(
+            call_ab_id, call_ac_id)
 
     @TelephonyBaseTest.tel_test_wrap
     @test_tracker_info(uuid="e16e2e81-1b59-4b02-b601-bb27b62d6468")
@@ -8821,7 +8707,8 @@
         if call_ab_id is None or call_ac_id is None:
             return False
 
-        return self._test_epdg_conference_merge_drop(call_ab_id, call_ac_id)
+        return self._test_ims_conference_merge_drop_second_call_from_participant(
+            call_ab_id, call_ac_id)
 
     @TelephonyBaseTest.tel_test_wrap
     @test_tracker_info(uuid="fd4c3b72-ea2d-4cd4-af79-b93635eda8b8")
@@ -8852,7 +8739,8 @@
         if call_ab_id is None or call_ac_id is None:
             return False
 
-        return self._test_epdg_conference_merge_drop(call_ab_id, call_ac_id)
+        return self._test_ims_conference_merge_drop_second_call_from_participant(
+            call_ab_id, call_ac_id)
 
     @TelephonyBaseTest.tel_test_wrap
     @test_tracker_info(uuid="a33d7b2b-cc22-40c3-9689-a2a14642396d")
@@ -8883,7 +8771,8 @@
         if call_ab_id is None or call_ac_id is None:
             return False
 
-        return self._test_epdg_conference_merge_drop(call_ab_id, call_ac_id)
+        return self._test_ims_conference_merge_drop_second_call_from_participant(
+            call_ab_id, call_ac_id)
 
     @TelephonyBaseTest.tel_test_wrap
     @test_tracker_info(uuid="7839c6a3-6797-4cd0-a918-c7d317881e3d")
@@ -9900,7 +9789,7 @@
         if call_ab_id is None or call_ac_id is None:
             return False
 
-        return self._test_ims_conference_merge_drop_second_call_no_cep(
+        return self._test_ims_conference_merge_drop_second_call_from_participant(
             call_ab_id, call_ac_id)
 
     @TelephonyBaseTest.tel_test_wrap
@@ -9946,7 +9835,7 @@
         if call_ab_id is None or call_ac_id is None:
             return False
 
-        return self._test_ims_conference_merge_drop_second_call_from_participant_cep(
+        return self._test_ims_conference_merge_drop_second_call_from_participant(
             call_ab_id, call_ac_id)
 
     @TelephonyBaseTest.tel_test_wrap
@@ -9992,7 +9881,7 @@
         if call_ab_id is None or call_ac_id is None:
             return False
 
-        return self._test_ims_conference_merge_drop_second_call_from_host_cep(
+        return self._test_ims_conference_merge_drop_second_call_from_host(
             call_ab_id, call_ac_id)
 
     @TelephonyBaseTest.tel_test_wrap
@@ -10038,7 +9927,7 @@
         if call_ab_id is None or call_ac_id is None:
             return False
 
-        return self._test_ims_conference_merge_drop_first_call_from_participant_cep(
+        return self._test_ims_conference_merge_drop_first_call_from_participant(
             call_ab_id, call_ac_id)
 
     @TelephonyBaseTest.tel_test_wrap
@@ -10084,7 +9973,7 @@
         if call_ab_id is None or call_ac_id is None:
             return False
 
-        return self._test_ims_conference_merge_drop_first_call_from_host_cep(
+        return self._test_ims_conference_merge_drop_first_call_from_host(
             call_ab_id, call_ac_id)
 
     @TelephonyBaseTest.tel_test_wrap
@@ -10130,7 +10019,7 @@
         if call_ab_id is None or call_ac_id is None:
             return False
 
-        return self._test_ims_conference_merge_drop_second_call_no_cep(
+        return self._test_ims_conference_merge_drop_second_call_from_participant(
             call_ab_id, call_ac_id)
 
     @TelephonyBaseTest.tel_test_wrap
@@ -10176,7 +10065,7 @@
         if call_ab_id is None or call_ac_id is None:
             return False
 
-        return self._test_ims_conference_merge_drop_second_call_from_participant_cep(
+        return self._test_ims_conference_merge_drop_second_call_from_participant(
             call_ab_id, call_ac_id)
 
     @TelephonyBaseTest.tel_test_wrap
@@ -10222,7 +10111,7 @@
         if call_ab_id is None or call_ac_id is None:
             return False
 
-        return self._test_ims_conference_merge_drop_second_call_from_host_cep(
+        return self._test_ims_conference_merge_drop_second_call_from_host(
             call_ab_id, call_ac_id)
 
     @TelephonyBaseTest.tel_test_wrap
@@ -10268,7 +10157,7 @@
         if call_ab_id is None or call_ac_id is None:
             return False
 
-        return self._test_ims_conference_merge_drop_first_call_from_participant_cep(
+        return self._test_ims_conference_merge_drop_first_call_from_participant(
             call_ab_id, call_ac_id)
 
     @TelephonyBaseTest.tel_test_wrap
@@ -10314,7 +10203,7 @@
         if call_ab_id is None or call_ac_id is None:
             return False
 
-        return self._test_ims_conference_merge_drop_first_call_from_host_cep(
+        return self._test_ims_conference_merge_drop_first_call_from_host(
             call_ab_id, call_ac_id)
 
     @TelephonyBaseTest.tel_test_wrap
@@ -10360,7 +10249,7 @@
         if call_ab_id is None or call_ac_id is None:
             return False
 
-        return self._test_ims_conference_merge_drop_second_call_no_cep(
+        return self._test_ims_conference_merge_drop_second_call_from_participant(
             call_ab_id, call_ac_id)
 
     @TelephonyBaseTest.tel_test_wrap
@@ -10406,7 +10295,7 @@
         if call_ab_id is None or call_ac_id is None:
             return False
 
-        return self._test_ims_conference_merge_drop_second_call_from_participant_cep(
+        return self._test_ims_conference_merge_drop_second_call_from_participant(
             call_ab_id, call_ac_id)
 
     @TelephonyBaseTest.tel_test_wrap
@@ -10452,7 +10341,7 @@
         if call_ab_id is None or call_ac_id is None:
             return False
 
-        return self._test_ims_conference_merge_drop_second_call_from_host_cep(
+        return self._test_ims_conference_merge_drop_second_call_from_host(
             call_ab_id, call_ac_id)
 
     @TelephonyBaseTest.tel_test_wrap
@@ -10498,7 +10387,7 @@
         if call_ab_id is None or call_ac_id is None:
             return False
 
-        return self._test_ims_conference_merge_drop_first_call_from_participant_cep(
+        return self._test_ims_conference_merge_drop_first_call_from_participant(
             call_ab_id, call_ac_id)
 
     @TelephonyBaseTest.tel_test_wrap
@@ -10544,7 +10433,7 @@
         if call_ab_id is None or call_ac_id is None:
             return False
 
-        return self._test_ims_conference_merge_drop_first_call_from_host_cep(
+        return self._test_ims_conference_merge_drop_first_call_from_host(
             call_ab_id, call_ac_id)
 
     @TelephonyBaseTest.tel_test_wrap
@@ -10592,7 +10481,7 @@
         if call_ab_id is None or call_ac_id is None:
             return False
 
-        return self._test_ims_conference_merge_drop_second_call_no_cep(
+        return self._test_ims_conference_merge_drop_second_call_from_participant(
             call_ab_id, call_ac_id)
 
     @TelephonyBaseTest.tel_test_wrap
@@ -10640,7 +10529,7 @@
         if call_ab_id is None or call_ac_id is None:
             return False
 
-        return self._test_ims_conference_merge_drop_second_call_from_host_cep(
+        return self._test_ims_conference_merge_drop_second_call_from_host(
             call_ab_id, call_ac_id)
 
     @TelephonyBaseTest.tel_test_wrap
@@ -10688,7 +10577,7 @@
         if call_ab_id is None or call_ac_id is None:
             return False
 
-        return self._test_ims_conference_merge_drop_second_call_from_participant_cep(
+        return self._test_ims_conference_merge_drop_second_call_from_participant(
             call_ab_id, call_ac_id)
 
     @TelephonyBaseTest.tel_test_wrap
diff --git a/acts/tests/google/tel/live/TelLiveVoiceTest.py b/acts/tests/google/tel/live/TelLiveVoiceTest.py
index 2f3f177..6b15845 100644
--- a/acts/tests/google/tel/live/TelLiveVoiceTest.py
+++ b/acts/tests/google/tel/live/TelLiveVoiceTest.py
@@ -38,6 +38,7 @@
 from acts.test_utils.tel.tel_defines import PHONE_TYPE_GSM
 from acts.test_utils.tel.tel_defines import WAIT_TIME_IN_CALL
 from acts.test_utils.tel.tel_defines import WAIT_TIME_IN_CALL_FOR_IMS
+from acts.test_utils.tel.tel_defines import WAIT_TIME_ANDROID_STATE_SETTLING
 from acts.test_utils.tel.tel_defines import WFC_MODE_CELLULAR_PREFERRED
 from acts.test_utils.tel.tel_defines import WFC_MODE_WIFI_ONLY
 from acts.test_utils.tel.tel_defines import WFC_MODE_WIFI_PREFERRED
@@ -136,10 +137,13 @@
         for iteration in range(3):
             result = True
             ad.log.info("Attempt %d", iteration + 1)
-            if not initiate_call(ad.log, ad, STORY_LINE) and \
-                                 wait_for_in_call_active(ad, 60, 3):
+            if not initiate_call(ad.log, ad, STORY_LINE):
                 ad.log.error("Call Failed to Initiate")
                 result = False
+                continue
+            if not wait_for_in_call_active(ad, 60, 3):
+                ad.log.error("Waiting for Call in Active Failed")
+                result = False
             time.sleep(WAIT_TIME_IN_CALL)
             if not is_phone_in_call(ad.log, ad):
                 ad.log.error("Call Dropped")
@@ -150,6 +154,7 @@
             if result:
                 ad.log.info("Call test PASS in iteration %d", iteration + 1)
                 return True
+            time.sleep(WAIT_TIME_ANDROID_STATE_SETTLING)
         ad.log.info("Call test FAIL in all 3 iterations")
         return False
 
diff --git a/acts/tests/google/wifi/WifiPingTest.py b/acts/tests/google/wifi/WifiPingTest.py
index 0cd1618..42aee02 100644
--- a/acts/tests/google/wifi/WifiPingTest.py
+++ b/acts/tests/google/wifi/WifiPingTest.py
@@ -427,7 +427,7 @@
             wutils.wifi_connect(self.dut,
                                 testcase_params['test_network'],
                                 num_of_tries=5,
-                                check_connectivity=False)
+                                check_connectivity=True)
         self.dut_ip = self.dut.droid.connectivityGetIPv4Addresses('wlan0')[0]
         if testcase_params['channel'] not in self.atten_dut_chain_map.keys():
             self.atten_dut_chain_map[testcase_params[
diff --git a/acts/tests/meta/ActsUnitTest.py b/acts/tests/meta/ActsUnitTest.py
index ec4e98e..89db2c4 100755
--- a/acts/tests/meta/ActsUnitTest.py
+++ b/acts/tests/meta/ActsUnitTest.py
@@ -52,6 +52,12 @@
     'tests/controllers/sl4a_lib/test_suite.py',
     'tests/test_runner_test.py',
     'tests/libs/version_selector_test.py',
+    'tests/test_utils/power/tel/lab/consume_parameter_test.py',
+    'tests/test_utils/power/tel/lab/ensure_valid_calibration_table_test.py',
+    'tests/test_utils/power/tel/lab/init_simulation_test.py',
+    'tests/test_utils/power/tel/lab/initialize_simulator_test.py',
+    'tests/test_utils/power/tel/lab/save_summary_to_file_test.py',
+    'tests/test_utils/power/tel/lab/power_tel_traffic_e2e_test.py'
 ]
 
 # The number of seconds to wait before considering the unit test to have timed