Merge "Add device check and extract a base class for Fast Pair test cases." into tm-dev
diff --git a/nearby/tests/multidevices/host/seeker_discover_provider_test.py b/nearby/tests/multidevices/host/seeker_discover_provider_test.py
index c82812a..6356595 100644
--- a/nearby/tests/multidevices/host/seeker_discover_provider_test.py
+++ b/nearby/tests/multidevices/host/seeker_discover_provider_test.py
@@ -14,14 +14,8 @@
 
 """CTS-V Nearby Mainline Fast Pair end-to-end test case: seeker can discover the provider."""
 
-from typing import List
-
-from mobly import base_test
-from mobly.controllers import android_device
-
 from test_helper import constants
-from test_helper import fast_pair_provider_simulator
-from test_helper import fast_pair_seeker
+from test_helper import fast_pair_base_test
 
 # The model ID to simulate on provider side.
 PROVIDER_SIMULATOR_MODEL_ID = constants.DEFAULT_MODEL_ID
@@ -29,37 +23,16 @@
 PROVIDER_SIMULATOR_ANTI_SPOOFING_KEY = constants.DEFAULT_ANTI_SPOOFING_KEY
 
 # Time in seconds for events waiting.
-SETUP_TIMEOUT_SEC = constants.SETUP_TIMEOUT_SEC
 BECOME_DISCOVERABLE_TIMEOUT_SEC = constants.BECOME_DISCOVERABLE_TIMEOUT_SEC
 START_ADVERTISING_TIMEOUT_SEC = constants.START_ADVERTISING_TIMEOUT_SEC
 SCAN_TIMEOUT_SEC = constants.SCAN_TIMEOUT_SEC
 
-# Abbreviations for common use type.
-FastPairProviderSimulator = fast_pair_provider_simulator.FastPairProviderSimulator
-FastPairSeeker = fast_pair_seeker.FastPairSeeker
 
-
-class SeekerDiscoverProviderTest(base_test.BaseTestClass):
+class SeekerDiscoverProviderTest(fast_pair_base_test.FastPairBaseTest):
     """Fast Pair seeker discover provider test."""
 
-    _duts: List[android_device.AndroidDevice]
-    _provider: FastPairProviderSimulator
-    _seeker: FastPairSeeker
-
-    def setup_class(self) -> None:
-        super().setup_class()
-        self._duts = self.register_controller(android_device)
-
-        # Assume the 1st phone is provider, the 2nd is seeker.
-        provider_ad, seeker_ad = self._duts
-        self._provider = FastPairProviderSimulator(provider_ad)
-        self._seeker = FastPairSeeker(seeker_ad)
-        self._provider.load_snippet()
-        self._seeker.load_snippet()
-
     def setup_test(self) -> None:
         super().setup_test()
-        self._provider.setup_provider_simulator(SETUP_TIMEOUT_SEC)
         self._provider.start_model_id_advertising(
             PROVIDER_SIMULATOR_MODEL_ID, PROVIDER_SIMULATOR_ANTI_SPOOFING_KEY)
         self._provider.wait_for_discoverable_mode(BECOME_DISCOVERABLE_TIMEOUT_SEC)
@@ -67,12 +40,9 @@
         self._seeker.start_scan()
 
     def teardown_test(self) -> None:
-        super().teardown_test()
         self._seeker.stop_scan()
         self._provider.teardown_provider_simulator()
-        # Create per-test excepts of logcat.
-        for dut in self._duts:
-            dut.services.create_output_excerpts_all(self.current_test_info)
+        super().teardown_test()
 
     def test_seeker_start_scanning_find_provider(self) -> None:
         provider_ble_mac_address = self._provider.get_ble_mac_address()
diff --git a/nearby/tests/multidevices/host/seeker_show_halfsheet_test.py b/nearby/tests/multidevices/host/seeker_show_halfsheet_test.py
index 07079ae..f6561e5 100644
--- a/nearby/tests/multidevices/host/seeker_show_halfsheet_test.py
+++ b/nearby/tests/multidevices/host/seeker_show_halfsheet_test.py
@@ -14,14 +14,8 @@
 
 """CTS-V Nearby Mainline Fast Pair end-to-end test case: seeker show half sheet UI."""
 
-from typing import List
-
-from mobly import base_test
-from mobly.controllers import android_device
-
 from test_helper import constants
-from test_helper import fast_pair_provider_simulator
-from test_helper import fast_pair_seeker
+from test_helper import fast_pair_base_test
 
 # The model ID to simulate on provider side.
 PROVIDER_SIMULATOR_MODEL_ID = constants.DEFAULT_MODEL_ID
@@ -36,32 +30,12 @@
 START_ADVERTISING_TIMEOUT_SEC = constants.START_ADVERTISING_TIMEOUT_SEC
 HALF_SHEET_POPUP_TIMEOUT_SEC = constants.HALF_SHEET_POPUP_TIMEOUT_SEC
 
-# Abbreviations for common use type.
-FastPairProviderSimulator = fast_pair_provider_simulator.FastPairProviderSimulator
-FastPairSeeker = fast_pair_seeker.FastPairSeeker
 
-
-class SeekerShowHalfSheetTest(base_test.BaseTestClass):
+class SeekerShowHalfSheetTest(fast_pair_base_test.FastPairBaseTest):
     """Fast Pair seeker show half sheet UI test."""
 
-    _duts: List[android_device.AndroidDevice]
-    _provider: FastPairProviderSimulator
-    _seeker: FastPairSeeker
-
-    def setup_class(self) -> None:
-        super().setup_class()
-        self._duts = self.register_controller(android_device)
-
-        # Assume the 1st phone is provider, the 2nd is seeker.
-        provider_ad, seeker_ad = self._duts
-        self._provider = FastPairProviderSimulator(provider_ad)
-        self._seeker = FastPairSeeker(seeker_ad)
-        self._provider.load_snippet()
-        self._seeker.load_snippet()
-
     def setup_test(self) -> None:
         super().setup_test()
-        self._provider.setup_provider_simulator(SETUP_TIMEOUT_SEC)
         self._provider.start_model_id_advertising(PROVIDER_SIMULATOR_MODEL_ID,
                                                   PROVIDER_SIMULATOR_ANTI_SPOOFING_KEY)
         self._provider.wait_for_discoverable_mode(BECOME_DISCOVERABLE_TIMEOUT_SEC)
@@ -71,13 +45,10 @@
         self._seeker.set_fast_pair_scan_enabled(True)
 
     def teardown_test(self) -> None:
-        super().teardown_test()
         self._seeker.set_fast_pair_scan_enabled(False)
         self._provider.teardown_provider_simulator()
         self._seeker.dismiss_halfsheet()
-        # Create per-test excepts of logcat.
-        for dut in self._duts:
-            dut.services.create_output_excerpts_all(self.current_test_info)
+        super().teardown_test()
 
     def test_seeker_show_half_sheet(self) -> None:
         self._seeker.wait_and_assert_halfsheet_showed(
diff --git a/nearby/tests/multidevices/host/test_helper/constants.py b/nearby/tests/multidevices/host/test_helper/constants.py
index 413e70b..646b428 100644
--- a/nearby/tests/multidevices/host/test_helper/constants.py
+++ b/nearby/tests/multidevices/host/test_helper/constants.py
@@ -27,3 +27,10 @@
 START_ADVERTISING_TIMEOUT_SEC = 5
 SCAN_TIMEOUT_SEC = 30
 HALF_SHEET_POPUP_TIMEOUT_SEC = 30
+
+# The phone to simulate Fast Pair provider (like headphone) needs changes in Android system:
+# 1. System permission check removal
+# 2. Adjusts Bluetooth profile configurations
+# The build fingerprint of the custom ROM for Fast Pair provider simulator.
+FAST_PAIR_PROVIDER_SIMULATOR_BUILD_FINGERPRINT = (
+    'google/bramble/bramble:Tiramisu/MASTER/eng.hylo.20211019.091550:userdebug/dev-keys')
diff --git a/nearby/tests/multidevices/host/test_helper/fast_pair_base_test.py b/nearby/tests/multidevices/host/test_helper/fast_pair_base_test.py
new file mode 100644
index 0000000..8b84839
--- /dev/null
+++ b/nearby/tests/multidevices/host/test_helper/fast_pair_base_test.py
@@ -0,0 +1,75 @@
+#  Copyright (C) 2022 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.
+
+"""Base for all Nearby Mainline Fast Pair end-to-end test cases."""
+
+from typing import List, Tuple
+
+from mobly import base_test
+from mobly import signals
+from mobly.controllers import android_device
+
+from test_helper import constants
+from test_helper import fast_pair_provider_simulator
+from test_helper import fast_pair_seeker
+
+# Abbreviations for common use type.
+AndroidDevice = android_device.AndroidDevice
+FastPairProviderSimulator = fast_pair_provider_simulator.FastPairProviderSimulator
+FastPairSeeker = fast_pair_seeker.FastPairSeeker
+REQUIRED_BUILD_FINGERPRINT = constants.FAST_PAIR_PROVIDER_SIMULATOR_BUILD_FINGERPRINT
+
+
+class FastPairBaseTest(base_test.BaseTestClass):
+    """Base class for all Nearby Mainline Fast Pair end-to-end classes to inherit."""
+
+    _duts: List[AndroidDevice]
+    _provider: FastPairProviderSimulator
+    _seeker: FastPairSeeker
+
+    def setup_class(self) -> None:
+        super().setup_class()
+        self._duts = self.register_controller(android_device, min_number=2)
+
+        provider_ad, seeker_ad = self._check_devices_supported()
+        self._provider = FastPairProviderSimulator(provider_ad)
+        self._seeker = FastPairSeeker(seeker_ad)
+        self._provider.load_snippet()
+        self._seeker.load_snippet()
+
+    def setup_test(self) -> None:
+        super().setup_test()
+        self._provider.setup_provider_simulator(constants.SETUP_TIMEOUT_SEC)
+
+    def teardown_test(self) -> None:
+        super().teardown_test()
+        # Create per-test excepts of logcat.
+        for dut in self._duts:
+            dut.services.create_output_excerpts_all(self.current_test_info)
+
+    def _check_devices_supported(self) -> Tuple[AndroidDevice, AndroidDevice]:
+        # Assume the 1st phone is provider, the 2nd one is seeker.
+        provider_ad, seeker_ad = self._duts[:2]
+
+        for ad in self._duts:
+            if ad.build_info['build_fingerprint'] == REQUIRED_BUILD_FINGERPRINT:
+                if ad != provider_ad:
+                    provider_ad, seeker_ad = seeker_ad, provider_ad
+                break
+        else:
+            raise signals.TestAbortClass(
+                f'None of phones has custom ROM ({REQUIRED_BUILD_FINGERPRINT}) for Fast Pair '
+                f'provider simulator. Skip all the test cases!')
+
+        return provider_ad, seeker_ad