Add new e2e test case: seeker_show_halfsheet_test.
This test verify half sheet UI pop up for the FP simulator.
This is also the first step for initial pairing e2e tests.
Test: atest -v CtsNearbyMultiDevicesTestSuite
Demo: http://recall/-/cycSROwIosTzHgYDSIqPXl/cfN94OCK5mdobvjdxRD2gp
Bug: 214015364
Change-Id: Ife1279ca34ece513080b4a9bfe8dd03d045d4d94
diff --git a/nearby/tests/multidevices/clients/Android.bp b/nearby/tests/multidevices/clients/Android.bp
index 9c1f3f5..579baa5 100644
--- a/nearby/tests/multidevices/clients/Android.bp
+++ b/nearby/tests/multidevices/clients/Android.bp
@@ -25,8 +25,11 @@
"NearbyFastPairProviderLib",
"NearbyFastPairSeekerSharedLib",
"androidx.test.core",
+ "androidx.test.ext.junit",
+ "androidx.test.uiautomator_uiautomator",
"kotlin-stdlib",
"mobly-snippet-lib",
+ "truth-prebuilt",
],
}
diff --git a/nearby/tests/multidevices/clients/AndroidManifest.xml b/nearby/tests/multidevices/clients/AndroidManifest.xml
index 39140af..86c10b2 100644
--- a/nearby/tests/multidevices/clients/AndroidManifest.xml
+++ b/nearby/tests/multidevices/clients/AndroidManifest.xml
@@ -28,6 +28,7 @@
<uses-permission android:name="android.permission.BLUETOOTH_SCAN" />
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.GET_ACCOUNTS"/>
+ <uses-permission android:name="android.permission.WRITE_SECURE_SETTINGS" />
<application>
<meta-data
@@ -40,6 +41,11 @@
</application>
<instrumentation
+ android:name="androidx.test.runner.AndroidJUnitRunner"
+ android:label="Nearby Mainline Module Instrumentation Test"
+ android:targetPackage="android.nearby.multidevices" />
+
+ <instrumentation
android:name="com.google.android.mobly.snippet.SnippetRunner"
android:label="Nearby Mainline Module Mobly Snippet"
android:targetPackage="android.nearby.multidevices" />
diff --git a/nearby/tests/multidevices/clients/src/android/nearby/multidevices/fastpair/seeker/FastPairSeekerSnippet.kt b/nearby/tests/multidevices/clients/src/android/nearby/multidevices/fastpair/seeker/FastPairSeekerSnippet.kt
index 54d4c67..617eac1 100644
--- a/nearby/tests/multidevices/clients/src/android/nearby/multidevices/fastpair/seeker/FastPairSeekerSnippet.kt
+++ b/nearby/tests/multidevices/clients/src/android/nearby/multidevices/fastpair/seeker/FastPairSeekerSnippet.kt
@@ -17,10 +17,14 @@
package android.nearby.multidevices.fastpair.seeker
import android.content.Context
+import android.nearby.FastPairDeviceMetadata
import android.nearby.NearbyManager
import android.nearby.ScanCallback
import android.nearby.ScanRequest
+import android.nearby.fastpair.seeker.FAKE_TEST_ACCOUNT_NAME
import android.nearby.multidevices.fastpair.seeker.data.FastPairTestDataManager
+import android.nearby.multidevices.fastpair.seeker.ui.CheckNearbyHalfSheetUiTest
+import android.nearby.multidevices.fastpair.seeker.ui.DismissNearbyHalfSheetUiTest
import androidx.test.core.app.ApplicationProvider
import com.google.android.mobly.snippet.Snippet
import com.google.android.mobly.snippet.rpc.AsyncRpc
@@ -60,6 +64,34 @@
nearbyManager.stopScan(scanCallback)
}
+ /** Waits and asserts the HalfSheet showed for Fast Pair pairing.
+ *
+ * @param modelId the expected model id to be associated with the HalfSheet.
+ * @param timeout the number of seconds to wait before giving up.
+ */
+ @Rpc(description = "Waits the HalfSheet showed for Fast Pair pairing.")
+ fun waitAndAssertHalfSheetShowed(modelId: String, timeout: Int) {
+ Log.i("Waits and asserts the HalfSheet showed for Fast Pair model $modelId.")
+
+ val deviceMetadata: FastPairDeviceMetadata =
+ fastPairTestDataManager.testDataCache.getFastPairDeviceMetadata(modelId)
+ ?: throw IllegalArgumentException(
+ "Can't find $modelId-FastPairAntispoofKeyDeviceMetadata pair in " +
+ "FastPairTestDataCache."
+ )
+ val deviceName = deviceMetadata.name!!
+ val initialPairingDescriptionTemplateText = deviceMetadata.initialPairingDescription!!
+
+ CheckNearbyHalfSheetUiTest(
+ waitHalfSheetPopupTimeoutSeconds = timeout,
+ halfSheetTitleText = deviceName,
+ halfSheetSubtitleText = initialPairingDescriptionTemplateText.format(
+ deviceName,
+ FAKE_TEST_ACCOUNT_NAME
+ )
+ ).checkNearbyHalfSheetUi()
+ }
+
/** Puts a model id to FastPairAntispoofKeyDeviceMetadata pair into test data cache.
*
* @param modelId a string of model id to be associated with.
@@ -88,6 +120,24 @@
return fastPairTestDataManager.testDataCache.dumpAccountKeyDeviceMetadataListAsJson()
}
+ /** Writes into {@link Settings} whether Fast Pair scan is enabled.
+ *
+ * @param enable whether the Fast Pair scan should be enabled.
+ */
+ @Rpc(description = "Writes into Settings whether Fast Pair scan is enabled.")
+ fun setFastPairScanEnabled(enable: Boolean) {
+ Log.i("Writes into Settings whether Fast Pair scan is enabled.")
+ NearbyManager.setFastPairScanEnabled(appContext, enable)
+ }
+
+ /** Dismisses the half sheet UI if showed. */
+ @Rpc(description = "Dismisses the half sheet UI if showed.")
+ fun dismissHalfSheet() {
+ Log.i("Dismisses the half sheet UI if showed.")
+
+ DismissNearbyHalfSheetUiTest().dismissHalfSheet()
+ }
+
/** Invokes when the snippet runner shutting down. */
override fun shutdown() {
super.shutdown()
diff --git a/nearby/tests/multidevices/clients/src/android/nearby/multidevices/fastpair/seeker/ui/CheckNearbyHalfSheetUiTest.kt b/nearby/tests/multidevices/clients/src/android/nearby/multidevices/fastpair/seeker/ui/CheckNearbyHalfSheetUiTest.kt
new file mode 100644
index 0000000..84b5e89
--- /dev/null
+++ b/nearby/tests/multidevices/clients/src/android/nearby/multidevices/fastpair/seeker/ui/CheckNearbyHalfSheetUiTest.kt
@@ -0,0 +1,101 @@
+/*
+ * 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.
+ */
+
+package android.nearby.multidevices.fastpair.seeker.ui
+
+import android.os.Bundle
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.platform.app.InstrumentationRegistry
+import androidx.test.uiautomator.UiDevice
+import androidx.test.uiautomator.Until
+import com.google.common.truth.Truth.assertThat
+import com.google.common.truth.Truth.assertWithMessage
+import org.junit.Test
+import org.junit.runner.RunWith
+
+/** An instrumented test to check Nearby half sheet UI showed correctly.
+ *
+ * To run this test directly:
+ * am instrument -w -r \
+ * -e class android.nearby.multidevices.fastpair.seeker.ui.CheckNearbyHalfSheetUiTest \
+ * android.nearby.multidevices/androidx.test.runner.AndroidJUnitRunner
+ */
+@RunWith(AndroidJUnit4::class)
+class CheckNearbyHalfSheetUiTest {
+ private val device = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation())
+ private val waitHalfSheetPopupTimeoutMs: Long
+ private val halfSheetTitleText: String
+ private val halfSheetSubtitleText: String
+
+ constructor() {
+ val arguments: Bundle = InstrumentationRegistry.getArguments()
+ waitHalfSheetPopupTimeoutMs = arguments.getLong(
+ WAIT_HALF_SHEET_POPUP_TIMEOUT_KEY,
+ DEFAULT_WAIT_HALF_SHEET_POPUP_TIMEOUT_MS
+ )
+ halfSheetTitleText =
+ arguments.getString(HALF_SHEET_TITLE_KEY, DEFAULT_HALF_SHEET_TITLE_TEXT)
+ halfSheetSubtitleText =
+ arguments.getString(HALF_SHEET_SUBTITLE_KEY, DEFAULT_HALF_SHEET_SUBTITLE_TEXT)
+ }
+
+ constructor(
+ waitHalfSheetPopupTimeoutSeconds: Int,
+ halfSheetTitleText: String,
+ halfSheetSubtitleText: String
+ ) {
+ this.waitHalfSheetPopupTimeoutMs = waitHalfSheetPopupTimeoutSeconds * 1000L
+ this.halfSheetTitleText = halfSheetTitleText
+ this.halfSheetSubtitleText = halfSheetSubtitleText
+ }
+
+ @Test
+ fun checkNearbyHalfSheetUi() {
+ // Check Nearby half sheet showed by checking button "Connect" on the DevicePairingFragment.
+ val isConnectButtonShowed = device.wait(
+ Until.hasObject(NearbyHalfSheetUiMap.DevicePairingFragment.connectButton),
+ waitHalfSheetPopupTimeoutMs
+ )
+ assertWithMessage("Nearby half sheet didn't show within $waitHalfSheetPopupTimeoutMs ms.")
+ .that(isConnectButtonShowed).isTrue()
+
+ val halfSheetTitle =
+ device.findObject(NearbyHalfSheetUiMap.DevicePairingFragment.halfSheetTitle)
+ assertThat(halfSheetTitle).isNotNull()
+ assertThat(halfSheetTitle.text).isEqualTo(halfSheetTitleText)
+
+ val halfSheetSubtitle =
+ device.findObject(NearbyHalfSheetUiMap.DevicePairingFragment.halfSheetSubtitle)
+ assertThat(halfSheetSubtitle).isNotNull()
+ assertThat(halfSheetSubtitle.text).isEqualTo(halfSheetSubtitleText)
+
+ val deviceImage = device.findObject(NearbyHalfSheetUiMap.DevicePairingFragment.deviceImage)
+ assertThat(deviceImage).isNotNull()
+
+ val infoButton = device.findObject(NearbyHalfSheetUiMap.DevicePairingFragment.infoButton)
+ assertThat(infoButton).isNotNull()
+ }
+
+ companion object {
+ private const val DEFAULT_WAIT_HALF_SHEET_POPUP_TIMEOUT_MS = 1000L
+ private const val DEFAULT_HALF_SHEET_TITLE_TEXT = "Fast Pair Provider Simulator"
+ private const val DEFAULT_HALF_SHEET_SUBTITLE_TEXT = "Fast Pair Provider Simulator will " +
+ "appear on devices linked with nearby-mainline-fpseeker@google.com"
+ private const val WAIT_HALF_SHEET_POPUP_TIMEOUT_KEY = "WAIT_HALF_SHEET_POPUP_TIMEOUT_MS"
+ private const val HALF_SHEET_TITLE_KEY = "HALF_SHEET_TITLE"
+ private const val HALF_SHEET_SUBTITLE_KEY = "HALF_SHEET_SUBTITLE"
+ }
+}
\ No newline at end of file
diff --git a/nearby/tests/multidevices/clients/src/android/nearby/multidevices/fastpair/seeker/ui/DismissNearbyHalfSheetUiTest.kt b/nearby/tests/multidevices/clients/src/android/nearby/multidevices/fastpair/seeker/ui/DismissNearbyHalfSheetUiTest.kt
new file mode 100644
index 0000000..1d99d26
--- /dev/null
+++ b/nearby/tests/multidevices/clients/src/android/nearby/multidevices/fastpair/seeker/ui/DismissNearbyHalfSheetUiTest.kt
@@ -0,0 +1,46 @@
+/*
+ * 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.
+ */
+
+package android.nearby.multidevices.fastpair.seeker.ui
+
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.platform.app.InstrumentationRegistry
+import androidx.test.uiautomator.UiDevice
+import com.google.common.truth.Truth.assertWithMessage
+import org.junit.Test
+import org.junit.runner.RunWith
+
+/** An instrumented test to dismiss Nearby half sheet UI.
+ *
+ * To run this test directly:
+ * am instrument -w -r \
+ * -e class android.nearby.multidevices.fastpair.seeker.ui.DismissNearbyHalfSheetUiTest \
+ * android.nearby.multidevices/androidx.test.runner.AndroidJUnitRunner
+ */
+@RunWith(AndroidJUnit4::class)
+class DismissNearbyHalfSheetUiTest {
+ private val device = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation())
+
+ @Test
+ fun dismissHalfSheet() {
+ device.pressHome()
+ device.waitForIdle()
+
+ assertWithMessage("Fail to dismiss Nearby half sheet.").that(
+ device.findObject(NearbyHalfSheetUiMap.DevicePairingFragment.connectButton)
+ ).isNull()
+ }
+}
\ No newline at end of file
diff --git a/nearby/tests/multidevices/clients/src/android/nearby/multidevices/fastpair/seeker/ui/NearbyHalfSheetUiMap.kt b/nearby/tests/multidevices/clients/src/android/nearby/multidevices/fastpair/seeker/ui/NearbyHalfSheetUiMap.kt
new file mode 100644
index 0000000..c94ff01
--- /dev/null
+++ b/nearby/tests/multidevices/clients/src/android/nearby/multidevices/fastpair/seeker/ui/NearbyHalfSheetUiMap.kt
@@ -0,0 +1,41 @@
+/*
+ * 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.
+ */
+
+package android.nearby.multidevices.fastpair.seeker.ui
+
+import androidx.test.uiautomator.By
+import androidx.test.uiautomator.BySelector
+
+/** UiMap for Nearby Mainline Half Sheet. */
+object NearbyHalfSheetUiMap {
+ private const val PACKAGE_NAME = "com.google.android.nearby.halfsheet"
+ private const val ANDROID_WIDGET_BUTTON = "android.widget.Button"
+ private const val ANDROID_WIDGET_IMAGE_VIEW = "android.widget.ImageView"
+ private const val ANDROID_WIDGET_TEXT_VIEW = "android.widget.TextView"
+
+ object DevicePairingFragment {
+ val halfSheetTitle: BySelector =
+ By.res(PACKAGE_NAME, "toolbar_title").clazz(ANDROID_WIDGET_TEXT_VIEW)
+ val halfSheetSubtitle: BySelector =
+ By.res(PACKAGE_NAME, "header_subtitle").clazz(ANDROID_WIDGET_TEXT_VIEW)
+ val deviceImage: BySelector =
+ By.res(PACKAGE_NAME, "pairing_pic").clazz(ANDROID_WIDGET_IMAGE_VIEW)
+ val connectButton: BySelector =
+ By.res(PACKAGE_NAME, "connect_btn").clazz(ANDROID_WIDGET_BUTTON).text("Connect")
+ val infoButton: BySelector =
+ By.res(PACKAGE_NAME, "info_icon").clazz(ANDROID_WIDGET_IMAGE_VIEW)
+ }
+}
\ No newline at end of file
diff --git a/nearby/tests/multidevices/host/Android.bp b/nearby/tests/multidevices/host/Android.bp
index 8075bf2..8c6559f 100644
--- a/nearby/tests/multidevices/host/Android.bp
+++ b/nearby/tests/multidevices/host/Android.bp
@@ -17,6 +17,7 @@
}
// Run the tests: atest -v CtsNearbyMultiDevicesTestSuite
+// TODO(b/223370810): Flash ROM with ag/17109260 reverted to pass Fast Pair scanning related tests.
python_test_host {
name: "CtsNearbyMultiDevicesTestSuite",
main: "suite_main.py",
@@ -34,6 +35,8 @@
":NearbyMultiDevicesClientsSnippets",
// Package the data provider with the Mobly test.
":NearbyFastPairSeekerDataProvider",
+ // Package the JSON metadata with the Mobly test.
+ "test_data/**/*",
],
}
diff --git a/nearby/tests/multidevices/host/seeker_show_halfsheet_test.py b/nearby/tests/multidevices/host/seeker_show_halfsheet_test.py
new file mode 100644
index 0000000..07079ae
--- /dev/null
+++ b/nearby/tests/multidevices/host/seeker_show_halfsheet_test.py
@@ -0,0 +1,85 @@
+# 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.
+
+"""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
+
+# The model ID to simulate on provider side.
+PROVIDER_SIMULATOR_MODEL_ID = constants.DEFAULT_MODEL_ID
+# The public key to simulate as registered headsets.
+PROVIDER_SIMULATOR_ANTI_SPOOFING_KEY = constants.DEFAULT_ANTI_SPOOFING_KEY
+# The anti-spoof key device metadata JSON file for data provider at seeker side.
+PROVIDER_SIMULATOR_KDM_JSON_FILE = constants.DEFAULT_KDM_JSON_FILE
+
+# 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
+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):
+ """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)
+ self._provider.wait_for_advertising_start(START_ADVERTISING_TIMEOUT_SEC)
+ self._seeker.put_anti_spoof_key_device_metadata(PROVIDER_SIMULATOR_MODEL_ID,
+ PROVIDER_SIMULATOR_KDM_JSON_FILE)
+ 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)
+
+ def test_seeker_show_half_sheet(self) -> None:
+ self._seeker.wait_and_assert_halfsheet_showed(
+ timeout_seconds=HALF_SHEET_POPUP_TIMEOUT_SEC,
+ expected_model_id=PROVIDER_SIMULATOR_MODEL_ID)
diff --git a/nearby/tests/multidevices/host/suite_main.py b/nearby/tests/multidevices/host/suite_main.py
index 788fbd5..406a4f0 100644
--- a/nearby/tests/multidevices/host/suite_main.py
+++ b/nearby/tests/multidevices/host/suite_main.py
@@ -20,10 +20,12 @@
from mobly import suite_runner
import seeker_discover_provider_test
+import seeker_show_halfsheet_test
_BOOTSTRAP_LOGGING_FILENAME = '/tmp/nearby_multi_devices_test_suite_log.txt'
_TEST_CLASSES_LIST = [
seeker_discover_provider_test.SeekerDiscoverProviderTest,
+ seeker_show_halfsheet_test.SeekerShowHalfSheetTest,
]
diff --git a/nearby/tests/multidevices/host/test_helper/constants.py b/nearby/tests/multidevices/host/test_helper/constants.py
index 6b5185f..413e70b 100644
--- a/nearby/tests/multidevices/host/test_helper/constants.py
+++ b/nearby/tests/multidevices/host/test_helper/constants.py
@@ -18,8 +18,12 @@
# Default public key to simulate as registered headsets.
DEFAULT_ANTI_SPOOFING_KEY = 'Cbj9eCJrTdDgSYxLkqtfADQi86vIaMvxJsQ298sZYWE='
+# Default anti-spoof Key Device Metadata JSON file for data provider at seeker side.
+DEFAULT_KDM_JSON_FILE = 'simulator_antispoofkey_devicemeta_json.txt'
+
# Time in seconds for events waiting.
SETUP_TIMEOUT_SEC = 5
BECOME_DISCOVERABLE_TIMEOUT_SEC = 10
START_ADVERTISING_TIMEOUT_SEC = 5
SCAN_TIMEOUT_SEC = 30
+HALF_SHEET_POPUP_TIMEOUT_SEC = 30
diff --git a/nearby/tests/multidevices/host/test_helper/fast_pair_seeker.py b/nearby/tests/multidevices/host/test_helper/fast_pair_seeker.py
index 9bb2689..cfdb966 100644
--- a/nearby/tests/multidevices/host/test_helper/fast_pair_seeker.py
+++ b/nearby/tests/multidevices/host/test_helper/fast_pair_seeker.py
@@ -19,6 +19,7 @@
from mobly.controllers.android_device_lib import snippet_event
from test_helper import event_helper
+from test_helper import utils
# The package name of the Nearby Mainline Fast Pair seeker Mobly snippet.
FP_SEEKER_SNIPPETS_PACKAGE = 'android.nearby.multidevices'
@@ -28,6 +29,7 @@
# Abbreviations for common use type.
AndroidDevice = android_device.AndroidDevice
+JsonObject = utils.JsonObject
SnippetEvent = snippet_event.SnippetEvent
wait_for_event = event_helper.wait_callback_event
@@ -104,3 +106,44 @@
on_received=_on_provider_found_event_received,
on_waiting=_on_provider_found_event_waiting,
on_missed=_on_provider_found_event_missed)
+
+ def put_anti_spoof_key_device_metadata(self, model_id: str, kdm_json_file_name: str) -> None:
+ """Puts a model id to FastPairAntispoofKeyDeviceMetadata pair into test data cache.
+
+ Args:
+ model_id: A string of model id to be associated with.
+ kdm_json_file_name: The FastPairAntispoofKeyDeviceMetadata JSON object.
+ """
+ self._ad.log.info('Puts FastPairAntispoofKeyDeviceMetadata into test data cache for '
+ 'model id "%s".', model_id)
+ kdm_json_object = utils.load_json_fast_pair_test_data(kdm_json_file_name)
+ self._ad.fp.putAntispoofKeyDeviceMetadata(
+ model_id,
+ utils.serialize_as_simplified_json_str(kdm_json_object))
+
+ def set_fast_pair_scan_enabled(self, enable: bool) -> None:
+ """Writes into Settings whether Fast Pair scan is enabled.
+
+ Args:
+ enable: whether the Fast Pair scan should be enabled.
+ """
+ self._ad.log.info('%s Fast Pair scan in Android settings.',
+ 'Enables' if enable else 'Disables')
+ self._ad.fp.setFastPairScanEnabled(enable)
+
+ def wait_and_assert_halfsheet_showed(self, timeout_seconds: int,
+ expected_model_id: str) -> None:
+ """Waits and asserts the onHalfSheetShowed event from the seeker.
+
+ Args:
+ timeout_seconds: The number of seconds to wait before giving up.
+ expected_model_id: The expected model ID of the remote Fast Pair provider
+ device.
+ """
+ self._ad.log.info('Waits and asserts the half sheet showed for model id "%s".',
+ expected_model_id)
+ self._ad.fp.waitAndAssertHalfSheetShowed(expected_model_id, timeout_seconds)
+
+ def dismiss_halfsheet(self) -> None:
+ """Dismisses the half sheet UI if showed."""
+ self._ad.fp.dismissHalfSheet()
diff --git a/nearby/tests/multidevices/host/test_helper/utils.py b/nearby/tests/multidevices/host/test_helper/utils.py
new file mode 100644
index 0000000..a0acb57
--- /dev/null
+++ b/nearby/tests/multidevices/host/test_helper/utils.py
@@ -0,0 +1,42 @@
+# 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.
+
+import json
+import pathlib
+import sys
+from typing import Any, Dict
+
+# Type definition
+JsonObject = Dict[str, Any]
+
+
+def load_json_fast_pair_test_data(json_file_name: str) -> JsonObject:
+ """Loads a JSON text file from test data directory into a Json object.
+
+ Args:
+ json_file_name: The name of the JSON file.
+ """
+ return json.loads(
+ pathlib.Path(sys.argv[0]).parent.joinpath(
+ 'test_data', 'fastpair', json_file_name).read_text()
+ )
+
+
+def serialize_as_simplified_json_str(json_data: JsonObject) -> str:
+ """Serializes a JSON object into a string without empty space.
+
+ Args:
+ json_data: The JSON object to be serialized.
+ """
+ return json.dumps(json_data, separators=(',', ':'))