1 /*
2  * Copyright (C) 2023 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package android.bluetooth;
18 
19 import static com.google.common.truth.Truth.assertThat;
20 
21 import android.content.BroadcastReceiver;
22 import android.content.Context;
23 import android.content.Intent;
24 import android.content.IntentFilter;
25 import android.util.Log;
26 
27 import androidx.test.core.app.ApplicationProvider;
28 import androidx.test.ext.junit.runners.AndroidJUnit4;
29 
30 import com.android.compatibility.common.util.AdoptShellPermissionsRule;
31 
32 import com.google.common.util.concurrent.SettableFuture;
33 
34 import org.junit.Rule;
35 import org.junit.Test;
36 import org.junit.runner.RunWith;
37 
38 import pandora.HostProto.DiscoverabilityMode;
39 import pandora.HostProto.SetDiscoverabilityModeRequest;
40 
41 import java.util.ArrayList;
42 
43 /** Test cases for {@link DeviceDiscoveryManager}. */
44 @RunWith(AndroidJUnit4.class)
45 public class DeviceDiscoveryTest {
46     private static final String TAG = "DeviceDiscoveryTest";
47 
48     private final Context mContext = ApplicationProvider.getApplicationContext();
49     private final BluetoothManager mManager = mContext.getSystemService(BluetoothManager.class);
50     private final BluetoothAdapter mAdapter = mManager.getAdapter();
51 
52     private SettableFuture<String> mFutureDiscoveryStartedIntent;
53     private SettableFuture<String> mFutureDiscoveryFinishedIntent;
54 
55     @Rule public final AdoptShellPermissionsRule mPermissionRule = new AdoptShellPermissionsRule();
56 
57     @Rule public final PandoraDevice mBumble = new PandoraDevice();
58 
59     private ArrayList<Intent> mDeviceFoundData;
60 
61     private BroadcastReceiver mConnectionStateReceiver =
62             new BroadcastReceiver() {
63                 @Override
64                 public void onReceive(Context context, Intent intent) {
65                     if (BluetoothAdapter.ACTION_DISCOVERY_STARTED.equals(intent.getAction())) {
66                         mFutureDiscoveryStartedIntent.set(
67                                 BluetoothAdapter.ACTION_DISCOVERY_STARTED);
68                     } else if (BluetoothAdapter.ACTION_DISCOVERY_FINISHED.equals(
69                             intent.getAction())) {
70                         mFutureDiscoveryFinishedIntent.set(
71                                 BluetoothAdapter.ACTION_DISCOVERY_FINISHED);
72                     } else if (BluetoothDevice.ACTION_FOUND.equals(intent.getAction())) {
73                         mDeviceFoundData.add(intent);
74                     }
75                 }
76             };
77 
78     @Test
startDeviceDiscoveryTest()79     public void startDeviceDiscoveryTest() throws Exception {
80         mFutureDiscoveryStartedIntent = SettableFuture.create();
81         mFutureDiscoveryFinishedIntent = SettableFuture.create();
82 
83         IntentFilter filter = new IntentFilter(BluetoothAdapter.ACTION_DISCOVERY_STARTED);
84         filter.addAction(BluetoothAdapter.ACTION_DISCOVERY_FINISHED);
85         mContext.registerReceiver(mConnectionStateReceiver, filter);
86 
87         assertThat(mAdapter.startDiscovery()).isTrue();
88         assertThat(mFutureDiscoveryStartedIntent.get())
89                 .isEqualTo(BluetoothAdapter.ACTION_DISCOVERY_STARTED);
90 
91         // Wait for device discovery to complete
92         assertThat(mFutureDiscoveryFinishedIntent.get())
93                 .isEqualTo(BluetoothAdapter.ACTION_DISCOVERY_FINISHED);
94 
95         mContext.unregisterReceiver(mConnectionStateReceiver);
96     }
97 
98     @Test
cancelDeviceDiscoveryTest()99     public void cancelDeviceDiscoveryTest() throws Exception {
100         mFutureDiscoveryStartedIntent = SettableFuture.create();
101         mFutureDiscoveryFinishedIntent = SettableFuture.create();
102 
103         IntentFilter filter = new IntentFilter(BluetoothAdapter.ACTION_DISCOVERY_STARTED);
104         filter.addAction(BluetoothAdapter.ACTION_DISCOVERY_FINISHED);
105         mContext.registerReceiver(mConnectionStateReceiver, filter);
106 
107         assertThat(mAdapter.startDiscovery()).isTrue();
108         assertThat(mFutureDiscoveryStartedIntent.get())
109                 .isEqualTo(BluetoothAdapter.ACTION_DISCOVERY_STARTED);
110 
111         // Issue a cancel discovery and wait for device discovery finished
112         assertThat(mAdapter.cancelDiscovery()).isTrue();
113         assertThat(mFutureDiscoveryFinishedIntent.get())
114                 .isEqualTo(BluetoothAdapter.ACTION_DISCOVERY_FINISHED);
115 
116         mContext.unregisterReceiver(mConnectionStateReceiver);
117     }
118 
119     @Test
checkDeviceIsDiscoveredTest()120     public void checkDeviceIsDiscoveredTest() throws Exception {
121         mFutureDiscoveryStartedIntent = SettableFuture.create();
122         mFutureDiscoveryFinishedIntent = SettableFuture.create();
123         mDeviceFoundData = new ArrayList<Intent>();
124 
125         // Ensure remote device is discoverable
126         mBumble.hostBlocking()
127                 .setDiscoverabilityMode(
128                         SetDiscoverabilityModeRequest.newBuilder()
129                                 .setMode(DiscoverabilityMode.DISCOVERABLE_GENERAL)
130                                 .build());
131 
132         IntentFilter filter = new IntentFilter(BluetoothAdapter.ACTION_DISCOVERY_STARTED);
133         filter.addAction(BluetoothAdapter.ACTION_DISCOVERY_FINISHED);
134         filter.addAction(BluetoothDevice.ACTION_FOUND);
135         mContext.registerReceiver(mConnectionStateReceiver, filter);
136 
137         assertThat(mAdapter.startDiscovery()).isTrue();
138         assertThat(mFutureDiscoveryStartedIntent.get())
139                 .isEqualTo(BluetoothAdapter.ACTION_DISCOVERY_STARTED);
140 
141         // Wait for device discovery to complete
142         assertThat(mFutureDiscoveryFinishedIntent.get())
143                 .isEqualTo(BluetoothAdapter.ACTION_DISCOVERY_FINISHED);
144 
145         mContext.unregisterReceiver(mConnectionStateReceiver);
146 
147         // Ensure we received at least one inquiry response
148         assertThat(!mDeviceFoundData.isEmpty()).isTrue();
149         Log.i(TAG, "Found inquiry results count:" + mDeviceFoundData.size());
150     }
151 }
152