• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2024 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.os.ParcelUuid;
27 import android.platform.test.annotations.RequiresFlagsEnabled;
28 import android.platform.test.flag.junit.CheckFlagsRule;
29 import android.platform.test.flag.junit.DeviceFlagsValueProvider;
30 
31 import androidx.test.ext.junit.runners.AndroidJUnit4;
32 
33 import com.android.bluetooth.flags.Flags;
34 import com.android.compatibility.common.util.AdoptShellPermissionsRule;
35 
36 import org.junit.Rule;
37 import org.junit.Test;
38 import org.junit.runner.RunWith;
39 
40 import java.util.UUID;
41 import java.util.concurrent.CompletableFuture;
42 import java.util.concurrent.TimeUnit;
43 
44 @RunWith(AndroidJUnit4.class)
45 public class LeLegacyAdvertisingTest {
46     private static final int TIMEOUT_MS = 1_000;
47 
48     @Rule public final AdoptShellPermissionsRule mPermissionRule = new AdoptShellPermissionsRule();
49 
50     @Rule
51     public final CheckFlagsRule mCheckFlagsRule = DeviceFlagsValueProvider.createCheckFlagsRule();
52 
53     @RequiresFlagsEnabled(Flags.FLAG_BLE_CHECK_DATA_LENGTH_ON_LEGACY_ADVERTISING)
54     @Test
setAdvertisingDataOver31Bytes()55     public void setAdvertisingDataOver31Bytes() throws Exception {
56         final BluetoothLeAdvertiser advertiser =
57                 BluetoothAdapter.getDefaultAdapter().getBluetoothLeAdvertiser();
58 
59         // Set legacy scan mode
60         AdvertisingSetParameters params =
61                 new AdvertisingSetParameters.Builder()
62                         .setLegacyMode(true)
63                         .setScannable(true)
64                         .setInterval(AdvertisingSetParameters.INTERVAL_HIGH)
65                         .setTxPowerLevel(AdvertisingSetParameters.TX_POWER_MEDIUM)
66                         .build();
67 
68         AdvertiseData advertiseData =
69                 new AdvertiseData.Builder()
70                         .addServiceUuid(new ParcelUuid(UUID.randomUUID()))
71                         .build();
72 
73         final CompletableFuture<Integer> future = new CompletableFuture<>();
74 
75         AdvertisingSetCallback callback =
76                 new AdvertisingSetCallback() {
77                     @Override
78                     public void onAdvertisingSetStarted(
79                             AdvertisingSet advertisingSet, int txPower, int status) {
80                         // Should be greater than 31
81                         int advertisingDataLengthWhichExceedsLimit = 50;
82                         advertisingSet.setAdvertisingData(
83                                 createAdvertiseData(advertisingDataLengthWhichExceedsLimit));
84                     }
85 
86                     @Override
87                     public void onAdvertisingDataSet(AdvertisingSet advertisingSet, int status) {
88                         future.complete(status);
89                     }
90                 };
91 
92         try {
93             advertiser.startAdvertisingSet(params, advertiseData, null, null, null, callback);
94             future.completeOnTimeout(null, TIMEOUT_MS, TimeUnit.MILLISECONDS).join();
95 
96             Integer setAdvertingDataResult = future.get();
97             assertThat(setAdvertingDataResult).isNotNull();
98             assertThat(setAdvertingDataResult)
99                     .isEqualTo(AdvertisingSetCallback.ADVERTISE_FAILED_DATA_TOO_LARGE);
100         } finally {
101             advertiser.stopAdvertisingSet(callback);
102         }
103     }
104 
105     @RequiresFlagsEnabled(Flags.FLAG_BLE_CHECK_DATA_LENGTH_ON_LEGACY_ADVERTISING)
106     @Test
setScanResponseDataOver31Bytes()107     public void setScanResponseDataOver31Bytes() throws Exception {
108         final BluetoothLeAdvertiser advertiser =
109                 BluetoothAdapter.getDefaultAdapter().getBluetoothLeAdvertiser();
110 
111         // Set legacy scan mode
112         AdvertisingSetParameters params =
113                 new AdvertisingSetParameters.Builder()
114                         .setLegacyMode(true)
115                         .setScannable(true)
116                         .setInterval(AdvertisingSetParameters.INTERVAL_HIGH)
117                         .setTxPowerLevel(AdvertisingSetParameters.TX_POWER_MEDIUM)
118                         .build();
119 
120         AdvertiseData advertiseData =
121                 new AdvertiseData.Builder()
122                         .addServiceUuid(new ParcelUuid(UUID.randomUUID()))
123                         .build();
124 
125         final CompletableFuture<Integer> future = new CompletableFuture<>();
126 
127         AdvertisingSetCallback callback =
128                 new AdvertisingSetCallback() {
129                     @Override
130                     public void onAdvertisingSetStarted(
131                             AdvertisingSet advertisingSet, int txPower, int status) {
132                         // Should be greater than 31
133                         int scanResponseDataLengthWhichExceedsLimit = 50;
134                         advertisingSet.setScanResponseData(
135                                 createAdvertiseData(scanResponseDataLengthWhichExceedsLimit));
136                     }
137 
138                     @Override
139                     public void onScanResponseDataSet(AdvertisingSet advertisingSet, int status) {
140                         future.complete(status);
141                     }
142                 };
143 
144         try {
145             advertiser.startAdvertisingSet(params, advertiseData, null, null, null, callback);
146             future.completeOnTimeout(null, TIMEOUT_MS, TimeUnit.MILLISECONDS).join();
147 
148             Integer setScanResponseResult = future.get();
149             assertThat(setScanResponseResult).isNotNull();
150             assertThat(setScanResponseResult)
151                     .isEqualTo(AdvertisingSetCallback.ADVERTISE_FAILED_DATA_TOO_LARGE);
152         } finally {
153             advertiser.stopAdvertisingSet(callback);
154         }
155     }
156 
createAdvertiseData(int length)157     private AdvertiseData createAdvertiseData(int length) {
158         if (length <= 4) {
159             return null;
160         }
161 
162         // Create an arbitrary manufacturer specific data
163         int manufacturerId = BluetoothAssignedNumbers.GOOGLE;
164         byte[] manufacturerSpecificData = new byte[length - 4];
165         for (int i = 0; i < manufacturerSpecificData.length; i++) {
166             manufacturerSpecificData[i] = (byte) i;
167         }
168 
169         return new AdvertiseData.Builder()
170                 .addManufacturerData(manufacturerId, manufacturerSpecificData)
171                 .build();
172     }
173 }
174