[nearby] Enable BLE when init

Fix: 294906731
Test: -m
Ignore-AOSP-First: nearby_not_in_aosp_yet
(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:2a9323b184edda09184d5d94c32ca5dfaedf2690)
Merged-In: Ie380efbc452af51691daa1e96e04dd575801c3a9
Change-Id: Ie380efbc452af51691daa1e96e04dd575801c3a9
diff --git a/nearby/service/java/com/android/server/nearby/managers/DiscoveryProviderManager.java b/nearby/service/java/com/android/server/nearby/managers/DiscoveryProviderManager.java
index 0c41426..5797d3d 100644
--- a/nearby/service/java/com/android/server/nearby/managers/DiscoveryProviderManager.java
+++ b/nearby/service/java/com/android/server/nearby/managers/DiscoveryProviderManager.java
@@ -21,6 +21,7 @@
 import static com.android.server.nearby.NearbyService.TAG;
 
 import android.annotation.Nullable;
+import android.bluetooth.BluetoothAdapter;
 import android.content.Context;
 import android.nearby.DataElement;
 import android.nearby.IScanListener;
@@ -141,6 +142,8 @@
 
     /** Called after boot completed. */
     public void init() {
+        // Register BLE only scan when Bluetooth is turned off
+        setBleScanEnabled();
         if (mInjector.getContextHubManager() != null) {
             mChreDiscoveryProvider.init();
         }
@@ -313,4 +316,29 @@
     public void onMergedRegistrationsUpdated() {
         invalidateProviderScanMode();
     }
+
+    /**
+     * Registers Nearby service to Ble scan if Bluetooth is off. (Even when Bluetooth is off)
+     * @return {@code true} when Nearby currently can scan through Bluetooth or Ble or successfully
+     * registers Nearby service to Ble scan when Blutooth is off.
+     */
+    public boolean setBleScanEnabled() {
+        BluetoothAdapter adapter = mInjector.getBluetoothAdapter();
+        if (adapter == null) {
+            Log.e(TAG, "BluetoothAdapter is null.");
+            return false;
+        }
+        if (adapter.isEnabled() || adapter.isLeEnabled()) {
+            return true;
+        }
+        if (!adapter.isBleScanAlwaysAvailable()) {
+            Log.v(TAG, "Ble always on scan is disabled.");
+            return false;
+        }
+        if (!adapter.enableBLE()) {
+            Log.e(TAG, "Failed to register Ble scan.");
+            return false;
+        }
+        return true;
+    }
 }
diff --git a/nearby/service/java/com/android/server/nearby/managers/DiscoveryProviderManagerLegacy.java b/nearby/service/java/com/android/server/nearby/managers/DiscoveryProviderManagerLegacy.java
index 4b76eba..df33773 100644
--- a/nearby/service/java/com/android/server/nearby/managers/DiscoveryProviderManagerLegacy.java
+++ b/nearby/service/java/com/android/server/nearby/managers/DiscoveryProviderManagerLegacy.java
@@ -22,6 +22,7 @@
 
 import android.annotation.Nullable;
 import android.app.AppOpsManager;
+import android.bluetooth.BluetoothAdapter;
 import android.content.Context;
 import android.nearby.DataElement;
 import android.nearby.IScanListener;
@@ -220,6 +221,8 @@
 
     /** Called after boot completed. */
     public void init() {
+        // Register BLE only scan when Bluetooth is turned off
+        setBleScanEnabled();
         if (mInjector.getContextHubManager() != null) {
             mChreDiscoveryProvider.init();
         }
@@ -503,4 +506,29 @@
             unregisterScanListener(listener);
         }
     }
+
+    /**
+     * Registers Nearby service to Ble scan if Bluetooth is off. (Even when Bluetooth is off)
+     * @return {@code true} when Nearby currently can scan through Bluetooth or Ble or successfully
+     * registers Nearby service to Ble scan when Blutooth is off.
+     */
+    public boolean setBleScanEnabled() {
+        BluetoothAdapter adapter = mInjector.getBluetoothAdapter();
+        if (adapter == null) {
+            Log.e(TAG, "BluetoothAdapter is null.");
+            return false;
+        }
+        if (adapter.isEnabled() || adapter.isLeEnabled()) {
+            return true;
+        }
+        if (!adapter.isBleScanAlwaysAvailable()) {
+            Log.v(TAG, "Ble always on scan is disabled.");
+            return false;
+        }
+        if (!adapter.enableBLE()) {
+            Log.e(TAG, "Failed to register Ble scan.");
+            return false;
+        }
+        return true;
+    }
 }
diff --git a/nearby/tests/unit/src/com/android/server/nearby/managers/DiscoveryProviderManagerLegacyTest.java b/nearby/tests/unit/src/com/android/server/nearby/managers/DiscoveryProviderManagerLegacyTest.java
index aa0dad3..a8c30a8 100644
--- a/nearby/tests/unit/src/com/android/server/nearby/managers/DiscoveryProviderManagerLegacyTest.java
+++ b/nearby/tests/unit/src/com/android/server/nearby/managers/DiscoveryProviderManagerLegacyTest.java
@@ -23,10 +23,12 @@
 
 import static org.mockito.Mockito.atLeastOnce;
 import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.times;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
 import android.app.AppOpsManager;
+import android.bluetooth.BluetoothAdapter;
 import android.content.Context;
 import android.nearby.DataElement;
 import android.nearby.IScanListener;
@@ -86,6 +88,8 @@
     DiscoveryProviderManagerLegacy.ScanListenerDeathRecipient mScanListenerDeathRecipient;
     @Mock
     IBinder mIBinder;
+    @Mock
+    BluetoothAdapter mBluetoothAdapter;
     private DiscoveryProviderManagerLegacy mDiscoveryProviderManager;
     private Map<IBinder, DiscoveryProviderManagerLegacy.ScanListenerRecord>
             mScanTypeScanListenerRecordMap;
@@ -137,8 +141,11 @@
     public void setup() {
         MockitoAnnotations.initMocks(this);
         when(mInjector.getAppOpsManager()).thenReturn(mAppOpsManager);
+        when(mInjector.getBluetoothAdapter()).thenReturn(mBluetoothAdapter);
         when(mBleDiscoveryProvider.getController()).thenReturn(mBluetoothController);
         when(mChreDiscoveryProvider.getController()).thenReturn(mChreController);
+        when(mBluetoothAdapter.isBleScanAlwaysAvailable()).thenReturn(true);
+        when(mBluetoothAdapter.isEnabled()).thenReturn(true);
 
         mScanTypeScanListenerRecordMap = new HashMap<>();
         mDiscoveryProviderManager =
@@ -164,6 +171,13 @@
     }
 
     @Test
+    public void test_enableBleWhenBleOff() throws Exception {
+        when(mBluetoothAdapter.isEnabled()).thenReturn(false);
+        mDiscoveryProviderManager.init();
+        verify(mBluetoothAdapter, times(1)).enableBLE();
+    }
+
+    @Test
     public void testStartProviders_chreOnlyChreAvailable_bleProviderNotStarted() {
         when(mChreDiscoveryProvider.available()).thenReturn(true);
 
@@ -375,4 +389,62 @@
                 .isTrue();
         assertThat(manager.mChreDiscoveryProvider.getFiltersLocked()).isNotNull();
     }
+
+    @Test
+    public void isBluetoothEnabledTest_bluetoothEnabled() {
+        when(mBluetoothAdapter.isEnabled()).thenReturn(true);
+        when(mBluetoothAdapter.isLeEnabled()).thenReturn(false);
+        when(mBluetoothAdapter.isBleScanAlwaysAvailable()).thenReturn(true);
+        when(mBluetoothAdapter.enableBLE()).thenReturn(true);
+
+        assertThat(mDiscoveryProviderManager.setBleScanEnabled()).isTrue();
+    }
+
+    @Test
+    public void isBluetoothEnabledTest_bleEnabled() {
+        when(mBluetoothAdapter.isEnabled()).thenReturn(false);
+        when(mBluetoothAdapter.isLeEnabled()).thenReturn(true);
+        when(mBluetoothAdapter.isBleScanAlwaysAvailable()).thenReturn(true);
+        when(mBluetoothAdapter.enableBLE()).thenReturn(true);
+
+        assertThat(mDiscoveryProviderManager.setBleScanEnabled()).isTrue();
+    }
+
+    @Test
+    public void enabledTest_enabled() {
+        when(mBluetoothAdapter.isEnabled()).thenReturn(false);
+        when(mBluetoothAdapter.isLeEnabled()).thenReturn(false);
+        when(mBluetoothAdapter.isBleScanAlwaysAvailable()).thenReturn(true);
+        when(mBluetoothAdapter.enableBLE()).thenReturn(true);
+
+        assertThat(mDiscoveryProviderManager.setBleScanEnabled()).isTrue();
+    }
+
+    @Test
+    public void enabledTest_enableFailed() {
+        when(mBluetoothAdapter.isEnabled()).thenReturn(false);
+        when(mBluetoothAdapter.isLeEnabled()).thenReturn(false);
+        when(mBluetoothAdapter.isBleScanAlwaysAvailable()).thenReturn(true);
+        when(mBluetoothAdapter.enableBLE()).thenReturn(false);
+
+        assertThat(mDiscoveryProviderManager.setBleScanEnabled()).isFalse();
+    }
+
+    @Test
+    public void enabledTest_scanIsOn() {
+        when(mBluetoothAdapter.isEnabled()).thenReturn(true);
+        when(mBluetoothAdapter.isLeEnabled()).thenReturn(false);
+        when(mBluetoothAdapter.isBleScanAlwaysAvailable()).thenReturn(false);
+
+        assertThat(mDiscoveryProviderManager.setBleScanEnabled()).isTrue();
+    }
+
+    @Test
+    public void enabledTest_failed() {
+        when(mBluetoothAdapter.isEnabled()).thenReturn(false);
+        when(mBluetoothAdapter.isLeEnabled()).thenReturn(false);
+        when(mBluetoothAdapter.isBleScanAlwaysAvailable()).thenReturn(false);
+
+        assertThat(mDiscoveryProviderManager.setBleScanEnabled()).isFalse();
+    }
 }
diff --git a/nearby/tests/unit/src/com/android/server/nearby/managers/DiscoveryProviderManagerTest.java b/nearby/tests/unit/src/com/android/server/nearby/managers/DiscoveryProviderManagerTest.java
index 7ecf631..b05893f 100644
--- a/nearby/tests/unit/src/com/android/server/nearby/managers/DiscoveryProviderManagerTest.java
+++ b/nearby/tests/unit/src/com/android/server/nearby/managers/DiscoveryProviderManagerTest.java
@@ -24,10 +24,12 @@
 import static org.mockito.Mockito.atLeastOnce;
 import static org.mockito.Mockito.never;
 import static org.mockito.Mockito.reset;
+import static org.mockito.Mockito.times;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
 import android.app.AppOpsManager;
+import android.bluetooth.BluetoothAdapter;
 import android.content.Context;
 import android.nearby.DataElement;
 import android.nearby.IScanListener;
@@ -80,6 +82,8 @@
     CallerIdentity mCallerIdentity;
     @Mock
     IBinder mIBinder;
+    @Mock
+    BluetoothAdapter mBluetoothAdapter;
     private Executor mExecutor;
     private DiscoveryProviderManager mDiscoveryProviderManager;
 
@@ -134,6 +138,9 @@
         when(mBleDiscoveryProvider.getController()).thenReturn(mBluetoothController);
         when(mChreDiscoveryProvider.getController()).thenReturn(mChreController);
         when(mScanListener.asBinder()).thenReturn(mIBinder);
+        when(mInjector.getBluetoothAdapter()).thenReturn(mBluetoothAdapter);
+        when(mBluetoothAdapter.isBleScanAlwaysAvailable()).thenReturn(true);
+        when(mBluetoothAdapter.isEnabled()).thenReturn(true);
 
         mDiscoveryProviderManager =
                 new DiscoveryProviderManager(mContext, mExecutor, mInjector,
@@ -157,6 +164,13 @@
     }
 
     @Test
+    public void test_enableBleWhenBleOff() throws Exception {
+        when(mBluetoothAdapter.isEnabled()).thenReturn(false);
+        mDiscoveryProviderManager.init();
+        verify(mBluetoothAdapter, times(1)).enableBLE();
+    }
+
+    @Test
     public void testStartProviders_chreOnlyChreAvailable_bleProviderNotStarted() {
         reset(mBluetoothController);
         when(mChreDiscoveryProvider.available()).thenReturn(true);
@@ -336,4 +350,62 @@
                 .isTrue();
         assertThat(manager.mChreDiscoveryProvider.getFiltersLocked()).isNotNull();
     }
+
+    @Test
+    public void isBluetoothEnabledTest_bluetoothEnabled() {
+        when(mBluetoothAdapter.isEnabled()).thenReturn(true);
+        when(mBluetoothAdapter.isLeEnabled()).thenReturn(false);
+        when(mBluetoothAdapter.isBleScanAlwaysAvailable()).thenReturn(true);
+        when(mBluetoothAdapter.enableBLE()).thenReturn(true);
+
+        assertThat(mDiscoveryProviderManager.setBleScanEnabled()).isTrue();
+    }
+
+    @Test
+    public void isBluetoothEnabledTest_bleEnabled() {
+        when(mBluetoothAdapter.isEnabled()).thenReturn(false);
+        when(mBluetoothAdapter.isLeEnabled()).thenReturn(true);
+        when(mBluetoothAdapter.isBleScanAlwaysAvailable()).thenReturn(true);
+        when(mBluetoothAdapter.enableBLE()).thenReturn(true);
+
+        assertThat(mDiscoveryProviderManager.setBleScanEnabled()).isTrue();
+    }
+
+    @Test
+    public void enabledTest_enabled() {
+        when(mBluetoothAdapter.isEnabled()).thenReturn(false);
+        when(mBluetoothAdapter.isLeEnabled()).thenReturn(false);
+        when(mBluetoothAdapter.isBleScanAlwaysAvailable()).thenReturn(true);
+        when(mBluetoothAdapter.enableBLE()).thenReturn(true);
+
+        assertThat(mDiscoveryProviderManager.setBleScanEnabled()).isTrue();
+    }
+
+    @Test
+    public void enabledTest_enableFailed() {
+        when(mBluetoothAdapter.isEnabled()).thenReturn(false);
+        when(mBluetoothAdapter.isLeEnabled()).thenReturn(false);
+        when(mBluetoothAdapter.isBleScanAlwaysAvailable()).thenReturn(true);
+        when(mBluetoothAdapter.enableBLE()).thenReturn(false);
+
+        assertThat(mDiscoveryProviderManager.setBleScanEnabled()).isFalse();
+    }
+
+    @Test
+    public void enabledTest_scanIsOn() {
+        when(mBluetoothAdapter.isEnabled()).thenReturn(true);
+        when(mBluetoothAdapter.isLeEnabled()).thenReturn(false);
+        when(mBluetoothAdapter.isBleScanAlwaysAvailable()).thenReturn(false);
+
+        assertThat(mDiscoveryProviderManager.setBleScanEnabled()).isTrue();
+    }
+
+    @Test
+    public void enabledTest_failed() {
+        when(mBluetoothAdapter.isEnabled()).thenReturn(false);
+        when(mBluetoothAdapter.isLeEnabled()).thenReturn(false);
+        when(mBluetoothAdapter.isBleScanAlwaysAvailable()).thenReturn(false);
+
+        assertThat(mDiscoveryProviderManager.setBleScanEnabled()).isFalse();
+    }
 }