Return status to startScan() API

Bug: 216294721
Test: Build and flash
Change-Id: I19e4e00bf61f2ae8ff1fffb3563b5d85afb95563
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) {