• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.bluetooth.le.AdvertiseData;
22 import android.bluetooth.le.AdvertisingSet;
23 import android.bluetooth.le.AdvertisingSetCallback;
24 import android.bluetooth.le.AdvertisingSetParameters;
25 import android.bluetooth.le.BluetoothLeAdvertiser;
26 import android.util.Log;
27 
28 import androidx.core.util.Pair;
29 import androidx.test.core.app.ApplicationProvider;
30 import androidx.test.ext.junit.runners.AndroidJUnit4;
31 
32 import com.android.compatibility.common.util.AdoptShellPermissionsRule;
33 
34 import io.grpc.Deadline;
35 
36 import org.junit.Ignore;
37 import org.junit.Rule;
38 import org.junit.Test;
39 import org.junit.runner.RunWith;
40 
41 import pandora.HostProto.ScanRequest;
42 import pandora.HostProto.ScanningResponse;
43 
44 import java.util.Iterator;
45 import java.util.concurrent.CompletableFuture;
46 import java.util.concurrent.TimeUnit;
47 
48 /** Test cases for {@link AdvertiseManager}. */
49 @RunWith(AndroidJUnit4.class)
50 public class LeAdvertisingTest {
51     private static final String TAG = LeAdvertisingTest.class.getSimpleName();
52 
53     private static final int TIMEOUT_ADVERTISING_MS = 1000;
54 
55     @Rule public final AdoptShellPermissionsRule mPermissionRule = new AdoptShellPermissionsRule();
56 
57     @Rule public final PandoraDevice mBumble = new PandoraDevice();
58 
59     @Test
60     @Ignore("b/343525982: Remove hidden api's dependencies to enable the test.")
advertisingSet()61     public void advertisingSet() throws Exception {
62         Pair<String, Integer> addressPair = startAdvertising().join();
63         ScanningResponse response = scanWithBumble(addressPair);
64 
65         Log.i(TAG, "scan response: " + response);
66         assertThat(response).isNotNull();
67     }
68 
scanWithBumble(Pair<String, Integer> addressPair)69     private ScanningResponse scanWithBumble(Pair<String, Integer> addressPair) {
70         Log.d(TAG, "scanWithBumble");
71         String address = addressPair.first;
72         int addressType = addressPair.second;
73 
74         StreamObserverSpliterator<ScanningResponse> responseObserver =
75                 new StreamObserverSpliterator<>();
76         Deadline deadline = Deadline.after(TIMEOUT_ADVERTISING_MS, TimeUnit.MILLISECONDS);
77         mBumble.host()
78                 .withDeadline(deadline)
79                 .scan(ScanRequest.newBuilder().build(), responseObserver);
80         Iterator<ScanningResponse> responseObserverIterator = responseObserver.iterator();
81         while (true) {
82             ScanningResponse scanningResponse = responseObserverIterator.next();
83             String addr =
84                     Utils.addressStringFromByteString(
85                             addressType == AdvertisingSetParameters.ADDRESS_TYPE_PUBLIC
86                                     ? scanningResponse.getPublic()
87                                     : scanningResponse.getRandom());
88 
89             if (addr.equals(address)) {
90                 return scanningResponse;
91             }
92         }
93     }
94 
startAdvertising()95     private CompletableFuture<Pair<String, Integer>> startAdvertising() {
96         CompletableFuture<Pair<String, Integer>> future =
97                 new CompletableFuture<Pair<String, Integer>>();
98 
99         android.content.Context context = ApplicationProvider.getApplicationContext();
100         BluetoothManager bluetoothManager = context.getSystemService(BluetoothManager.class);
101         BluetoothAdapter bluetoothAdapter = bluetoothManager.getAdapter();
102 
103         // Start advertising
104         BluetoothLeAdvertiser leAdvertiser = bluetoothAdapter.getBluetoothLeAdvertiser();
105         AdvertisingSetParameters parameters =
106                 new AdvertisingSetParameters.Builder()
107                         .setOwnAddressType(AdvertisingSetParameters.ADDRESS_TYPE_RANDOM)
108                         .build();
109         AdvertiseData advertiseData = new AdvertiseData.Builder().build();
110         AdvertiseData scanResponse = new AdvertiseData.Builder().build();
111         AdvertisingSetCallback advertisingSetCallback =
112                 new AdvertisingSetCallback() {
113                     @Override
114                     public void onAdvertisingSetStarted(
115                             AdvertisingSet advertisingSet, int txPower, int status) {
116                         Log.i(
117                                 TAG,
118                                 "onAdvertisingSetStarted "
119                                         + " txPower:"
120                                         + txPower
121                                         + " status:"
122                                         + status);
123                         advertisingSet.enableAdvertising(true, TIMEOUT_ADVERTISING_MS, 0);
124                     }
125 
126                     @Override
127                     public void onOwnAddressRead(
128                             AdvertisingSet advertisingSet, int addressType, String address) {
129                         Log.i(
130                                 TAG,
131                                 "onOwnAddressRead "
132                                         + " addressType:"
133                                         + addressType
134                                         + " address:"
135                                         + address);
136                         future.complete(new Pair<String, Integer>(address, addressType));
137                     }
138 
139                     @Override
140                     public void onAdvertisingEnabled(
141                             AdvertisingSet advertisingSet, boolean enabled, int status) {
142                         Log.i(
143                                 TAG,
144                                 "onAdvertisingEnabled "
145                                         + " enabled:"
146                                         + enabled
147                                         + " status:"
148                                         + status);
149                         advertisingSet.getOwnAddress();
150                     }
151                 };
152         leAdvertiser.startAdvertisingSet(
153                 parameters, advertiseData, scanResponse, null, null, 0, 0, advertisingSetCallback);
154 
155         return future;
156     }
157 }
158