resolve merge conflicts of 9bce15d9087a80c2bf565717e9b61c1a2fcd02e3 to stage-aosp-master

BUG: None
Test: I solemnly swear I tested this conflict resolution.
Change-Id: I41cfea9d74d5f044866ade338d187b469acb4c4d
diff --git a/acts/framework/acts/test_utils/bt/BluetoothBaseTest.py b/acts/framework/acts/test_utils/bt/BluetoothBaseTest.py
index a311857..197da27 100644
--- a/acts/framework/acts/test_utils/bt/BluetoothBaseTest.py
+++ b/acts/framework/acts/test_utils/bt/BluetoothBaseTest.py
@@ -31,6 +31,7 @@
 from acts.libs.proto.proto_utils import compile_import_proto
 from acts.libs.proto.proto_utils import parse_proto_to_ascii
 from acts.test_utils.bt.bt_metrics_utils import get_bluetooth_metrics
+from acts.test_utils.bt.bt_test_utils import get_device_selector_dictionary
 from acts.test_utils.bt.bt_test_utils import reset_bluetooth
 from acts.test_utils.bt.bt_test_utils import setup_multiple_devices_for_bt_test
 from acts.test_utils.bt.bt_test_utils import take_btsnoop_logs
@@ -52,6 +53,13 @@
         BaseTestClass.__init__(self, controllers)
         for ad in self.android_devices:
             self._setup_bt_libs(ad)
+        if 'preferred_device_order' in self.user_params:
+            prefered_device_order = self.user_params['preferred_device_order']
+            for i, ad in enumerate(self.android_devices):
+                if ad.serial in prefered_device_order:
+                    index = prefered_device_order.index(ad.serial)
+                    self.android_devices[i], self.android_devices[index] = \
+                        self.android_devices[index], self.android_devices[i]
 
     def collect_bluetooth_manager_metrics_logs(self, ads, test_name):
         """
@@ -123,6 +131,8 @@
         return _safe_wrap_test_case
 
     def setup_class(self):
+        self.device_selector = get_device_selector_dictionary(
+            self.android_devices)
         if "reboot_between_test_class" in self.user_params:
             threads = []
             for a in self.android_devices:
@@ -235,3 +245,6 @@
         # Shell command library
         setattr(android_device, "shell",
                 ShellCommands(log=self.log, dut=android_device))
+        # Setup Android Device feature list
+        setattr(android_device, "features",
+                android_device.adb.shell("pm list features").split("\n"))
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 534adf1..e35e2f1 100644
--- a/acts/framework/acts/test_utils/bt/bt_test_utils.py
+++ b/acts/framework/acts/test_utils/bt/bt_test_utils.py
@@ -223,7 +223,8 @@
     threads = []
     try:
         for a in android_devices:
-            thread = threading.Thread(target=factory_reset_bluetooth, args=([[a]]))
+            thread = threading.Thread(
+                target=factory_reset_bluetooth, args=([[a]]))
             threads.append(thread)
             thread.start()
         for t in threads:
@@ -282,7 +283,11 @@
             return False
     return True
 
-def wait_for_bluetooth_manager_state(droid, state=None, timeout=10, threshold=5):
+
+def wait_for_bluetooth_manager_state(droid,
+                                     state=None,
+                                     timeout=10,
+                                     threshold=5):
     """ Waits for BlueTooth normalized state or normalized explicit state
     args:
         droid: droid device object
@@ -301,7 +306,8 @@
             # for any normalized state
             if state is None:
                 if len(set(all_states[-threshold:])) == 1:
-                    log.info("State normalized {}".format(set(all_states[-threshold:])))
+                    log.info("State normalized {}".format(
+                        set(all_states[-threshold:])))
                     return True
             else:
                 # explicit check against normalized state
@@ -310,9 +316,11 @@
         time.sleep(0.5)
     log.error(
         "Bluetooth state fails to normalize" if state is None else
-        "Failed to match bluetooth state, current state {} expected state {}".format(get_state(), state))
+        "Failed to match bluetooth state, current state {} expected state {}".
+        format(get_state(), state))
     return False
 
+
 def factory_reset_bluetooth(android_devices):
     """Clears Bluetooth stack of input Android device list.
 
@@ -340,6 +348,7 @@
             return False
     return True
 
+
 def reset_bluetooth(android_devices):
     """Resets Bluetooth state of input Android device list.
 
@@ -576,6 +585,7 @@
     mac_address = event['data']['Result']['deviceInfo']['address']
     return mac_address, advertise_callback, scan_callback
 
+
 def enable_bluetooth(droid, ed):
     if droid.bluetoothCheckState() is True:
         return True
@@ -594,6 +604,7 @@
 
     return True
 
+
 def disable_bluetooth(droid):
     """Disable Bluetooth on input Droid object.
 
@@ -1000,7 +1011,8 @@
                 bluetooth_profile_connection_state_changed, bt_default_timeout)
             pri_ad.log.info("Got event {}".format(profile_event))
         except Exception as e:
-            pri_ad.log.error("Did not disconnect from Profiles. Reason {}".format(e))
+            pri_ad.log.error(
+                "Did not disconnect from Profiles. Reason {}".format(e))
             return False
 
         profile = profile_event['data']['profile']
@@ -1398,3 +1410,78 @@
         if (device["address"] == source.droid.bluetoothGetLocalAddress()):
             return True
     return False
+
+
+def get_device_selector_dictionary(android_device_list):
+    """Create a dictionary of Bluetooth features vs Android devices.
+
+    Args:
+        android_device_list: The list of Android devices.
+    Returns:
+        A dictionary of profiles/features to Android devices.
+    """
+    selector_dict = {}
+    for ad in android_device_list:
+        uuids = ad.droid.bluetoothGetLocalUuids()
+
+        for profile, uuid_const in sig_uuid_constants.items():
+            uuid_check = sig_uuid_constants['BASE_UUID'].format(
+                uuid_const).lower()
+            if uuid_check in uuids:
+                if profile in selector_dict:
+                    selector_dict[profile].append(ad)
+                else:
+                    selector_dict[profile] = [ad]
+
+        # Various services may not be active during BT startup.
+        # If the device can be identified through adb shell pm list features
+        # then try to add them to the appropriate profiles / features.
+
+        # Android TV.
+        if "feature:com.google.android.tv.installed" in ad.features:
+            ad.log.info("Android TV device found.")
+            supported_profiles = ['AudioSink']
+            _add_android_device_to_dictionary(ad, supported_profiles,
+                                              selector_dict)
+
+        # Android Auto
+        elif "feature:android.hardware.type.automotive" in ad.features:
+            ad.log.info("Android Auto device found.")
+            # Add: AudioSink , A/V_RemoteControl,
+            supported_profiles = [
+                'AudioSink', 'A/V_RemoteControl', 'Message Notification Server'
+            ]
+            _add_android_device_to_dictionary(ad, supported_profiles,
+                                              selector_dict)
+        # Android Wear
+        elif "feature:android.hardware.type.watch" in ad.features:
+            ad.log.info("Android Wear device found.")
+            supported_profiles = []
+            _add_android_device_to_dictionary(ad, supported_profiles,
+                                              selector_dict)
+        # Android Phone
+        elif "feature:android.hardware.telephony" in ad.features:
+            ad.log.info("Android Phone device found.")
+            # Add: AudioSink
+            supported_profiles = [
+                'AudioSource', 'A/V_RemoteControlTarget',
+                'Message Access Server'
+            ]
+            _add_android_device_to_dictionary(ad, supported_profiles,
+                                              selector_dict)
+    return selector_dict
+
+
+def _add_android_device_to_dictionary(android_device, profile_list,
+                                      selector_dict):
+    """Adds the AndroidDevice and supported features to the selector dictionary
+
+    Args:
+        android_device: The Android device.
+        profile_list: The list of profiles the Android device supports.
+    """
+    for profile in profile_list:
+        if profile in selector_dict and android_device not in selector_dict[profile]:
+            selector_dict[profile].append(android_device)
+        else:
+            selector_dict[profile] = [android_device]