Merge "Address API review feedback" into tm-dev
diff --git a/nearby/framework/java/android/nearby/INearbyManager.aidl b/nearby/framework/java/android/nearby/INearbyManager.aidl
index e5c4102..62e109e 100644
--- a/nearby/framework/java/android/nearby/INearbyManager.aidl
+++ b/nearby/framework/java/android/nearby/INearbyManager.aidl
@@ -28,7 +28,7 @@
*/
interface INearbyManager {
- void registerScanListener(in ScanRequest scanRequest, in IScanListener listener);
+ int registerScanListener(in ScanRequest scanRequest, in IScanListener listener);
void unregisterScanListener(in IScanListener listener);
diff --git a/nearby/framework/java/android/nearby/NearbyManager.java b/nearby/framework/java/android/nearby/NearbyManager.java
index 1f6edd3..2654046 100644
--- a/nearby/framework/java/android/nearby/NearbyManager.java
+++ b/nearby/framework/java/android/nearby/NearbyManager.java
@@ -16,9 +16,12 @@
package android.nearby;
+import android.Manifest;
import android.annotation.CallbackExecutor;
+import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.annotation.RequiresPermission;
import android.annotation.SuppressLint;
import android.annotation.SystemApi;
import android.annotation.SystemService;
@@ -48,6 +51,25 @@
public class NearbyManager {
/**
+ * Represents the scanning state.
+ *
+ * @hide
+ */
+ @IntDef({
+ ScanStatus.UNKNOWN,
+ ScanStatus.SUCCESS,
+ ScanStatus.ERROR,
+ })
+ public @interface ScanStatus {
+ // Default, invalid state.
+ int UNKNOWN = 0;
+ // The successful state.
+ int SUCCESS = 1;
+ // Failed state.
+ int ERROR = 2;
+ }
+
+ /**
* Whether allows Fast Pair to scan.
*
* (0 = disabled, 1 = enabled)
@@ -68,7 +90,7 @@
/**
* Creates a new NearbyManager.
*
- * @param service The service object.
+ * @param service the service object
*/
NearbyManager(@NonNull INearbyManager service) {
mService = service;
@@ -93,11 +115,16 @@
* Start scan for nearby devices with given parameters. Devices matching {@link ScanRequest}
* will be delivered through the given callback.
*
- * @param scanRequest Various parameters clients send when requesting scanning.
- * @param executor Executor where the listener method is called.
- * @param scanCallback The callback to notify clients when there is a scan result.
+ * @param scanRequest various parameters clients send when requesting scanning
+ * @param executor executor where the listener method is called
+ * @param scanCallback the callback to notify clients when there is a scan result
+ *
+ * @return whether scanning was successfully started
*/
- public void startScan(@NonNull ScanRequest scanRequest,
+ @RequiresPermission(allOf = {android.Manifest.permission.BLUETOOTH_SCAN,
+ android.Manifest.permission.BLUETOOTH_PRIVILEGED})
+ @ScanStatus
+ public int startScan(@NonNull ScanRequest scanRequest,
@CallbackExecutor @NonNull Executor executor,
@NonNull ScanCallback scanCallback) {
Objects.requireNonNull(scanRequest, "scanRequest must not be null");
@@ -115,8 +142,12 @@
Preconditions.checkState(transport.isRegistered());
transport.setExecutor(executor);
}
- mService.registerScanListener(scanRequest, transport);
+ @ScanStatus int status = mService.registerScanListener(scanRequest, transport);
+ if (status != ScanStatus.SUCCESS) {
+ return status;
+ }
sScanListeners.put(scanCallback, new WeakReference<>(transport));
+ return ScanStatus.SUCCESS;
}
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
@@ -131,9 +162,11 @@
* Suppressed lint: Registration methods should have overload that accepts delivery Executor.
* Already have executor in startScan() method.
*
- * @param scanCallback The callback that was used to start the scan.
+ * @param scanCallback the callback that was used to start the scan
*/
@SuppressLint("ExecutorRegistration")
+ @RequiresPermission(allOf = {android.Manifest.permission.BLUETOOTH_SCAN,
+ android.Manifest.permission.BLUETOOTH_PRIVILEGED})
public void stopScan(@NonNull ScanCallback scanCallback) {
Preconditions.checkArgument(scanCallback != null,
"invalid null scanCallback");
@@ -155,10 +188,12 @@
/**
* Start broadcasting the request using nearby specification.
*
- * @param broadcastRequest Request for the nearby broadcast.
- * @param executor Executor for running the callback.
- * @param callback Callback for notifying the client.
+ * @param broadcastRequest request for the nearby broadcast
+ * @param executor executor for running the callback
+ * @param callback callback for notifying the client
*/
+ @RequiresPermission(allOf = {Manifest.permission.BLUETOOTH_ADVERTISE,
+ android.Manifest.permission.BLUETOOTH_PRIVILEGED})
public void startBroadcast(@NonNull BroadcastRequest broadcastRequest,
@CallbackExecutor @NonNull Executor executor, @NonNull BroadcastCallback callback) {
try {
@@ -184,9 +219,11 @@
/**
* Stop the broadcast associated with the given callback.
*
- * @param callback The callback that was used for starting the broadcast.
+ * @param callback the callback that was used for starting the broadcast
*/
@SuppressLint("ExecutorRegistration")
+ @RequiresPermission(allOf = {Manifest.permission.BLUETOOTH_ADVERTISE,
+ android.Manifest.permission.BLUETOOTH_PRIVILEGED})
public void stopBroadcast(@NonNull BroadcastCallback callback) {
try {
synchronized (sBroadcastListeners) {
@@ -206,9 +243,9 @@
/**
* Read from {@link Settings} whether Fast Pair scan is enabled.
*
- * @param context the {@link Context} to query the setting.
- * @param def the default value if no setting value.
- * @return whether the Fast Pair is enabled.
+ * @param context the {@link Context} to query the setting
+ * @param def the default value if no setting value
+ * @return whether the Fast Pair is enabled
*/
public static boolean getFastPairScanEnabled(@NonNull Context context, boolean def) {
final int enabled = Settings.Secure.getInt(
@@ -219,8 +256,8 @@
/**
* Write into {@link Settings} whether Fast Pair scan is enabled
*
- * @param context the {@link Context} to set the setting.
- * @param enable whether the Fast Pair scan should be enabled.
+ * @param context the {@link Context} to set the setting
+ * @param enable whether the Fast Pair scan should be enabled
*/
public static void setFastPairScanEnabled(@NonNull Context context, boolean enable) {
Settings.Secure.putInt(
diff --git a/nearby/service/java/com/android/server/nearby/NearbyService.java b/nearby/service/java/com/android/server/nearby/NearbyService.java
index ca9bca3..d721575 100644
--- a/nearby/service/java/com/android/server/nearby/NearbyService.java
+++ b/nearby/service/java/com/android/server/nearby/NearbyService.java
@@ -31,6 +31,7 @@
import android.nearby.IBroadcastListener;
import android.nearby.INearbyManager;
import android.nearby.IScanListener;
+import android.nearby.NearbyManager;
import android.nearby.ScanRequest;
import android.util.Log;
@@ -99,8 +100,12 @@
}
@Override
- public void registerScanListener(ScanRequest scanRequest, IScanListener listener) {
- mProviderManager.registerScanListener(scanRequest, listener);
+ @NearbyManager.ScanStatus
+ public int registerScanListener(ScanRequest scanRequest, IScanListener listener) {
+ if (mProviderManager.registerScanListener(scanRequest, listener)) {
+ return NearbyManager.ScanStatus.SUCCESS;
+ }
+ return NearbyManager.ScanStatus.ERROR;
}
@Override
diff --git a/nearby/service/java/com/android/server/nearby/provider/DiscoveryProviderManager.java b/nearby/service/java/com/android/server/nearby/provider/DiscoveryProviderManager.java
index fbbfae1..7ff3110 100644
--- a/nearby/service/java/com/android/server/nearby/provider/DiscoveryProviderManager.java
+++ b/nearby/service/java/com/android/server/nearby/provider/DiscoveryProviderManager.java
@@ -95,7 +95,7 @@
/**
* Registers the listener in the manager and starts scan according to the requested scan mode.
*/
- public void registerScanListener(ScanRequest scanRequest, IScanListener listener) {
+ public boolean registerScanListener(ScanRequest scanRequest, IScanListener listener) {
synchronized (mLock) {
IBinder listenerBinder = listener.asBinder();
if (mScanTypeScanListenerRecordMap.containsKey(listener.asBinder())) {
@@ -103,11 +103,13 @@
.get(listenerBinder).getScanRequest();
if (scanRequest.equals(savedScanRequest)) {
Log.d(TAG, "Already registered the scanRequest: " + scanRequest);
- return;
+ return true;
}
}
- startProviders(scanRequest);
+ if (!startProviders(scanRequest)) {
+ return false;
+ }
ScanListenerRecord scanListenerRecord = new ScanListenerRecord(scanRequest, listener);
mScanTypeScanListenerRecordMap.put(listenerBinder, scanListenerRecord);
@@ -116,6 +118,7 @@
mScanMode = scanRequest.getScanMode();
invalidateProviderScanMode();
}
+ return true;
}
}
@@ -159,10 +162,14 @@
}
}
- private void startProviders(ScanRequest scanRequest) {
+ // Returns false when fail to start all the providers. Returns true if any one of the provider
+ // starts successfully.
+ private boolean startProviders(ScanRequest scanRequest) {
if (scanRequest.isBleEnabled()) {
startBleProvider(scanRequest);
+ return true;
}
+ return false;
}
private void startBleProvider(ScanRequest scanRequest) {
diff --git a/nearby/tests/multidevices/host/Android.bp b/nearby/tests/multidevices/host/Android.bp
index bad8a26..533153a 100644
--- a/nearby/tests/multidevices/host/Android.bp
+++ b/nearby/tests/multidevices/host/Android.bp
@@ -16,11 +16,11 @@
default_applicable_licenses: ["Android-Apache-2.0"],
}
-// Run the tests: atest -v CtsSeekerDiscoverProviderTest
+// Run the tests: atest -v CtsNearbyMultiDevicesTestSuite
python_test_host {
- name: "CtsSeekerDiscoverProviderTest",
- main: "seeker_discover_provider_test.py",
- srcs: ["seeker_discover_provider_test.py"],
+ name: "CtsNearbyMultiDevicesTestSuite",
+ main: "suite_main.py",
+ srcs: ["*.py"],
libs: ["NearbyMultiDevicesHostHelper"],
test_suites: [
"cts",
diff --git a/nearby/tests/multidevices/host/AndroidTest.xml b/nearby/tests/multidevices/host/AndroidTest.xml
index cca0826..f8294f4 100644
--- a/nearby/tests/multidevices/host/AndroidTest.xml
+++ b/nearby/tests/multidevices/host/AndroidTest.xml
@@ -10,7 +10,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
-<configuration description="Config for CTS seeker scan provider test">
+<configuration description="Config for CTS Nearby Mainline multi devices end-to-end test suite">
<option name="test-suite-tag" value="cts" />
<option name="config-descriptor:metadata" key="component" value="wifi" />
<option name="config-descriptor:metadata" key="parameter" value="not_instant_app" />
@@ -34,6 +34,10 @@
<option name="dep-module" value="mobly" />
<option name="dep-module" value="retry" />
</target_preparer>
+ <target_preparer class="com.android.tradefed.targetprep.DeviceSetup">
+ <option name="force-skip-system-props" value="true" /> <!-- avoid restarting device -->
+ <option name="screen-always-on" value="on" />
+ </target_preparer>
</device>
<device name="device2">
<target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
@@ -44,11 +48,15 @@
<option name="run-command" value="input keyevent KEYCODE_WAKEUP" />
<option name="run-command" value="wm dismiss-keyguard" />
</target_preparer>
+ <target_preparer class="com.android.tradefed.targetprep.DeviceSetup">
+ <option name="force-skip-system-props" value="true" /> <!-- avoid restarting device -->
+ <option name="screen-always-on" value="on" />
+ </target_preparer>
</device>
<test class="com.android.tradefed.testtype.mobly.MoblyBinaryHostTest">
<!-- The mobly-par-file-name should match the module name -->
- <option name="mobly-par-file-name" value="CtsSeekerDiscoverProviderTest" />
+ <option name="mobly-par-file-name" value="CtsNearbyMultiDevicesTestSuite" />
<!-- Timeout limit in milliseconds for all test cases of the python binary -->
<option name="mobly-test-timeout" value="60000" />
</test>
diff --git a/nearby/tests/multidevices/host/seeker_discover_provider_test.py b/nearby/tests/multidevices/host/seeker_discover_provider_test.py
index 03f3661..c82812a 100644
--- a/nearby/tests/multidevices/host/seeker_discover_provider_test.py
+++ b/nearby/tests/multidevices/host/seeker_discover_provider_test.py
@@ -14,25 +14,25 @@
"""CTS-V Nearby Mainline Fast Pair end-to-end test case: seeker can discover the provider."""
-import logging
-import sys
+from typing import List
from mobly import base_test
-from mobly import test_runner
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
-# Default model ID to simulate on provider side.
-DEFAULT_MODEL_ID = '00000C'
-# Default public key to simulate as registered headsets.
-DEFAULT_ANTI_SPOOFING_KEY = 'Cbj9eCJrTdDgSYxLkqtfADQi86vIaMvxJsQ298sZYWE='
+# 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
+
# Time in seconds for events waiting.
-SETUP_TIMEOUT_SEC = 5
-BECOME_DISCOVERABLE_TIMEOUT_SEC = 10
-START_ADVERTISING_TIMEOUT_SEC = 5
-SCAN_TIMEOUT_SEC = 30
+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
@@ -42,17 +42,16 @@
class SeekerDiscoverProviderTest(base_test.BaseTestClass):
"""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)
+ self._duts = self.register_controller(android_device)
# Assume the 1st phone is provider, the 2nd is seeker.
- provider_ad, seeker_ad = self.duts
- provider_ad.debug_tag = 'FastPairProviderSimulator'
- seeker_ad.debug_tag = 'MainlineFastPairSeeker'
+ provider_ad, seeker_ad = self._duts
self._provider = FastPairProviderSimulator(provider_ad)
self._seeker = FastPairSeeker(seeker_ad)
self._provider.load_snippet()
@@ -61,7 +60,8 @@
def setup_test(self) -> None:
super().setup_test()
self._provider.setup_provider_simulator(SETUP_TIMEOUT_SEC)
- self._provider.start_model_id_advertising(DEFAULT_MODEL_ID, DEFAULT_ANTI_SPOOFING_KEY)
+ 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.start_scan()
@@ -71,21 +71,12 @@
self._seeker.stop_scan()
self._provider.teardown_provider_simulator()
# Create per-test excepts of logcat.
- for dut in self.duts:
+ for dut in self._duts:
dut.services.create_output_excerpts_all(self.current_test_info)
def test_seeker_start_scanning_find_provider(self) -> None:
provider_ble_mac_address = self._provider.get_ble_mac_address()
self._seeker.wait_and_assert_provider_found(
timeout_seconds=SCAN_TIMEOUT_SEC,
- expected_model_id=DEFAULT_MODEL_ID,
+ expected_model_id=PROVIDER_SIMULATOR_MODEL_ID,
expected_ble_mac_address=provider_ble_mac_address)
-
-
-if __name__ == '__main__':
- # Take test args
- index = sys.argv.index('--')
- sys.argv = sys.argv[:1] + sys.argv[index + 1:]
-
- logging.basicConfig(filename="/tmp/seeker_scan_provider_test_log.txt", level=logging.INFO)
- test_runner.main()
diff --git a/nearby/tests/multidevices/host/suite_main.py b/nearby/tests/multidevices/host/suite_main.py
new file mode 100644
index 0000000..788fbd5
--- /dev/null
+++ b/nearby/tests/multidevices/host/suite_main.py
@@ -0,0 +1,37 @@
+# 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.
+
+"""The entry point for Nearby Mainline multi devices end-to-end test suite."""
+
+import logging
+import sys
+
+from mobly import suite_runner
+
+import seeker_discover_provider_test
+
+_BOOTSTRAP_LOGGING_FILENAME = '/tmp/nearby_multi_devices_test_suite_log.txt'
+_TEST_CLASSES_LIST = [
+ seeker_discover_provider_test.SeekerDiscoverProviderTest,
+]
+
+
+def _valid_argument(arg: str) -> bool:
+ return arg.startswith(('--config', '-c', '--tests', '--test_case'))
+
+
+if __name__ == '__main__':
+ logging.basicConfig(filename=_BOOTSTRAP_LOGGING_FILENAME, level=logging.INFO)
+ suite_runner.run_suite(argv=[arg for arg in sys.argv if _valid_argument(arg)],
+ test_classes=_TEST_CLASSES_LIST)
diff --git a/nearby/tests/multidevices/host/test_helper/constants.py b/nearby/tests/multidevices/host/test_helper/constants.py
new file mode 100644
index 0000000..6b5185f
--- /dev/null
+++ b/nearby/tests/multidevices/host/test_helper/constants.py
@@ -0,0 +1,25 @@
+# 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.
+
+# Default model ID to simulate on provider side.
+DEFAULT_MODEL_ID = '00000c'
+
+# Default public key to simulate as registered headsets.
+DEFAULT_ANTI_SPOOFING_KEY = 'Cbj9eCJrTdDgSYxLkqtfADQi86vIaMvxJsQ298sZYWE='
+
+# Time in seconds for events waiting.
+SETUP_TIMEOUT_SEC = 5
+BECOME_DISCOVERABLE_TIMEOUT_SEC = 10
+START_ADVERTISING_TIMEOUT_SEC = 5
+SCAN_TIMEOUT_SEC = 30
diff --git a/nearby/tests/multidevices/host/test_helper/fast_pair_provider_simulator.py b/nearby/tests/multidevices/host/test_helper/fast_pair_provider_simulator.py
index 8563e8e..8a98112 100644
--- a/nearby/tests/multidevices/host/test_helper/fast_pair_provider_simulator.py
+++ b/nearby/tests/multidevices/host/test_helper/fast_pair_provider_simulator.py
@@ -43,6 +43,7 @@
def __init__(self, ad: AndroidDevice) -> None:
self._ad = ad
+ self._ad.debug_tag = 'FastPairProviderSimulator'
self._provider_status_callback = None
def load_snippet(self) -> None:
@@ -92,6 +93,9 @@
0x00000C).
anti_spoofing_key: A public key for registered headsets.
"""
+ self._ad.log.info(
+ 'Provider simulator starts advertising as model id "%s" with anti-spoofing key "%s".',
+ model_id, anti_spoofing_key)
self._provider_status_callback = (
self._ad.fp.startModelIdAdvertising(model_id, anti_spoofing_key))
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 85c37df..9bb2689 100644
--- a/nearby/tests/multidevices/host/test_helper/fast_pair_seeker.py
+++ b/nearby/tests/multidevices/host/test_helper/fast_pair_seeker.py
@@ -37,6 +37,7 @@
def __init__(self, ad: AndroidDevice) -> None:
self._ad = ad
+ self._ad.debug_tag = 'MainlineFastPairSeeker'
self._scan_result_callback = None
def load_snippet(self) -> None: