aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGoogler <noreply@google.com>2024-04-23 11:13:29 -0700
committerCopybara-Service <copybara-worker@google.com>2024-04-23 11:14:04 -0700
commit811b0ff8c67bdd29997126bf7a09916e26ab5303 (patch)
treef54b7d631a46fa3f64fba0e2ef4af4094dbadf17
parent6131a9b624eb61aba41896dbf3b26f67c182ab31 (diff)
downloadrobolectric-811b0ff8c67bdd29997126bf7a09916e26ab5303.tar.gz
Add #startAdvertisingSet API support in ShadowBluetoothLeAdvertiser.
Extends ShadowBluetoothLeAdvertiser minSdk from O to L. PiperOrigin-RevId: 627447267
-rw-r--r--robolectric/src/test/java/org/robolectric/shadows/ShadowBluetoothLeAdvertiserTest.java349
-rw-r--r--shadows/framework/src/main/java/org/robolectric/shadows/ShadowBluetoothLeAdvertiser.java171
2 files changed, 324 insertions, 196 deletions
diff --git a/robolectric/src/test/java/org/robolectric/shadows/ShadowBluetoothLeAdvertiserTest.java b/robolectric/src/test/java/org/robolectric/shadows/ShadowBluetoothLeAdvertiserTest.java
index 7dc4fe798..9b2ffb50b 100644
--- a/robolectric/src/test/java/org/robolectric/shadows/ShadowBluetoothLeAdvertiserTest.java
+++ b/robolectric/src/test/java/org/robolectric/shadows/ShadowBluetoothLeAdvertiserTest.java
@@ -1,15 +1,13 @@
package org.robolectric.shadows;
+import static android.os.Build.VERSION_CODES.LOLLIPOP;
import static android.os.Build.VERSION_CODES.O;
-import static android.os.Build.VERSION_CODES.UPSIDE_DOWN_CAKE;
import static com.google.common.truth.Truth.assertThat;
import static org.junit.Assert.assertThrows;
import static org.robolectric.Shadows.shadowOf;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
-import android.bluetooth.BluetoothGattServer;
-import android.bluetooth.BluetoothManager;
import android.bluetooth.le.AdvertiseCallback;
import android.bluetooth.le.AdvertiseData;
import android.bluetooth.le.AdvertiseSettings;
@@ -18,11 +16,9 @@ import android.bluetooth.le.AdvertisingSetCallback;
import android.bluetooth.le.AdvertisingSetParameters;
import android.bluetooth.le.BluetoothLeAdvertiser;
import android.bluetooth.le.PeriodicAdvertisingParameters;
-import android.content.Context;
import android.os.Handler;
import android.os.Looper;
import android.os.ParcelUuid;
-import androidx.test.core.app.ApplicationProvider;
import java.util.Optional;
import org.junit.Before;
import org.junit.Test;
@@ -32,7 +28,7 @@ import org.robolectric.annotation.Config;
/** Unit tests for {@link ShadowBluetoothLeAdvertiser}. */
@RunWith(RobolectricTestRunner.class)
-@Config(minSdk = O)
+@Config(minSdk = LOLLIPOP)
public class ShadowBluetoothLeAdvertiserTest {
private static final String ADVERTISE_DATA_UUID1 = "00000000-0000-0000-0000-0000000000A1";
@@ -43,13 +39,6 @@ public class ShadowBluetoothLeAdvertiserTest {
private static final String CALLBACK1_FAILURE_RESULT = "c1f";
private static final String CALLBACK2_SUCCESS_RESULT = "c2s";
private static final String CALLBACK2_FAILURE_RESULT = "c2f";
-
- private final Context context = ApplicationProvider.getApplicationContext();
- private final BluetoothManager bluetoothManager =
- context.getSystemService(BluetoothManager.class);
- private final BluetoothAdapter bluetoothAdapter = bluetoothManager.getAdapter();
- private final ShadowBluetoothAdapter shadowBluetoothAdapter = shadowOf(bluetoothAdapter);
- private final BluetoothGattServer gattServer = bluetoothManager.openGattServer(context, null);
private final Handler mainLooperHandler = new Handler(Looper.getMainLooper());
private BluetoothLeAdvertiser bluetoothLeAdvertiser;
@@ -62,33 +51,6 @@ public class ShadowBluetoothLeAdvertiserTest {
private AdvertiseData scanResponse2;
private AdvertiseCallback advertiseCallback1;
private AdvertiseCallback advertiseCallback2;
-
- private Optional<Integer> advertisingSetStartStatusOptional;
- private boolean advertisingSetStopped;
- private AdvertisingSetCallback advertisingSetCallback =
- new AdvertisingSetCallback() {
- @Override
- public void onAdvertisingSetStarted(
- AdvertisingSet advertisingSet, int txPower, int status) {
- advertisingSetStartStatusOptional = Optional.of(status);
- /* switch (status) {
- case AdvertisingSetCallback.ADVERTISE_SUCCESS:
- advertisingSetStartStatusOptional.
- break;
- case AdvertisingSetCallback.ADVERTISE_FAILED_DATA_TOO_LARGE:
- break;
- case AdvertisingSetCallback.ADVERTISE_FAILED_ALREADY_STARTED:
- break;
- default:
- break; */
- }
-
- @Override
- public void onAdvertisingSetStopped(AdvertisingSet advertisingSet) {
- advertisingSetStopped = true;
- }
- };
-
private String result;
private int error;
private AdvertiseSettings settings;
@@ -170,9 +132,6 @@ public class ShadowBluetoothLeAdvertiserTest {
.setTxPowerLevel(AdvertiseSettings.ADVERTISE_TX_POWER_LOW)
.setConnectable(false)
.build();
-
- advertisingSetStartStatusOptional = Optional.empty();
- advertisingSetStopped = false;
}
@Test
@@ -246,10 +205,10 @@ public class ShadowBluetoothLeAdvertiserTest {
.addServiceUuid(ParcelUuid.fromString("EEEEEEEE-FFFF-FFFF-FFFF-FFFFFFFFFFFF"))
.build();
bluetoothLeAdvertiser.startAdvertising(
- advertiseSettings1, null, oversizedData, advertiseCallback1);
+ advertiseSettings1, /* advertiseData= */ null, oversizedData, advertiseCallback1);
assertThat(error).isEqualTo(AdvertiseCallback.ADVERTISE_FAILED_DATA_TOO_LARGE);
bluetoothLeAdvertiser.startAdvertising(
- advertiseSettings1, oversizedData, null, advertiseCallback1);
+ advertiseSettings1, oversizedData, /* scanResponse= */ null, advertiseCallback1);
assertThat(error).isEqualTo(AdvertiseCallback.ADVERTISE_FAILED_DATA_TOO_LARGE);
}
@@ -502,84 +461,86 @@ public class ShadowBluetoothLeAdvertiserTest {
}
@Test
- @Config(minSdk = UPSIDE_DOWN_CAKE)
+ @Config(minSdk = O)
public void startAdvertisingSet() {
+ AdvertisingStatus status = new AdvertisingStatus();
bluetoothLeAdvertiser.startAdvertisingSet(
buildAdvertisingSetParams(
- true, true, true, BluetoothDevice.PHY_LE_CODED, BluetoothDevice.PHY_LE_CODED),
+ /* isLegacy= */ true,
+ /* isConnectable= */ true,
+ /* isScannable= */ true,
+ BluetoothDevice.PHY_LE_CODED,
+ BluetoothDevice.PHY_LE_CODED),
advertiseData1,
- null,
- null,
- null,
- 0,
- 0,
- gattServer,
- advertisingSetCallback,
- mainLooperHandler);
-
- assertThat(advertisingSetStartStatusOptional.get())
- .isEqualTo(AdvertisingSetCallback.ADVERTISE_SUCCESS);
+ /* scanResponse= */ null,
+ /* periodicParameters= */ null,
+ /* periodicData= */ null,
+ createAdvertisingSetCallback(status));
+
+ assertThat(status.isStarted).isTrue();
assertThat(shadowOf(bluetoothLeAdvertiser).getAdvertisingSetRequestCount()).isEqualTo(1);
}
@Test
- @Config(minSdk = UPSIDE_DOWN_CAKE)
+ @Config(minSdk = O)
public void
startAdvertisingSet_advertisingAlreadyStarted_invokeOnAdvertisingSetStartedWithAlreadyStartedStatusCode() {
+ AdvertisingStatus status = new AdvertisingStatus();
+ AdvertisingSetCallback callback = createAdvertisingSetCallback(status);
bluetoothLeAdvertiser.startAdvertisingSet(
buildAdvertisingSetParams(
- true, true, true, BluetoothDevice.PHY_LE_CODED, BluetoothDevice.PHY_LE_CODED),
+ /* isLegacy= */ true,
+ /* isConnectable= */ true,
+ /* isScannable= */ true,
+ BluetoothDevice.PHY_LE_CODED,
+ BluetoothDevice.PHY_LE_CODED),
advertiseData1,
- null,
- null,
- null,
- 0,
- 0,
- gattServer,
- advertisingSetCallback,
- mainLooperHandler);
+ /* scanResponse= */ null,
+ /* periodicParameters= */ null,
+ /* periodicData= */ null,
+ callback);
bluetoothLeAdvertiser.startAdvertisingSet(
buildAdvertisingSetParams(
- true, true, true, BluetoothDevice.PHY_LE_CODED, BluetoothDevice.PHY_LE_CODED),
+ /* isLegacy= */ true,
+ /* isConnectable= */ true,
+ /* isScannable= */ true,
+ BluetoothDevice.PHY_LE_CODED,
+ BluetoothDevice.PHY_LE_CODED),
advertiseData1,
- null,
- null,
- null,
- 0,
- 0,
- gattServer,
- advertisingSetCallback,
- mainLooperHandler);
-
- assertThat(advertisingSetStartStatusOptional.get())
+ /* scanResponse= */ null,
+ /* periodicParameters= */ null,
+ /* periodicData= */ null,
+ callback);
+
+ assertThat(status.getStatusCode())
.isEqualTo(AdvertisingSetCallback.ADVERTISE_FAILED_ALREADY_STARTED);
assertThat(shadowOf(bluetoothLeAdvertiser).getAdvertisingSetRequestCount()).isEqualTo(1);
}
@Test
- @Config(minSdk = UPSIDE_DOWN_CAKE)
+ @Config(minSdk = O)
public void startAdvertisingSet_nullCallback_throwsIllegalArgumentException() {
assertThrows(
IllegalArgumentException.class,
() ->
bluetoothLeAdvertiser.startAdvertisingSet(
buildAdvertisingSetParams(
- true, true, true, BluetoothDevice.PHY_LE_CODED, BluetoothDevice.PHY_LE_CODED),
+ /* isLegacy= */ true,
+ /* isConnectable= */ true,
+ /* isScannable= */ true,
+ BluetoothDevice.PHY_LE_CODED,
+ BluetoothDevice.PHY_LE_CODED),
advertiseData1,
- null,
- null,
- null,
- 0,
- 0,
- gattServer,
- null,
- mainLooperHandler));
+ /* scanResponse= */ null,
+ /* periodicParameters= */ null,
+ /* periodicData= */ null,
+ /* callback= */ null));
assertThat(shadowOf(bluetoothLeAdvertiser).getAdvertisingSetRequestCount()).isEqualTo(0);
}
@Test
- @Config(minSdk = UPSIDE_DOWN_CAKE)
+ @Config(minSdk = O)
public void
startAdvertisingSet_legacyModeWithTooBigAdvertiseData_throwsIllegalArgumentException() {
AdvertiseData oversizedData =
@@ -593,21 +554,22 @@ public class ShadowBluetoothLeAdvertiserTest {
() ->
bluetoothLeAdvertiser.startAdvertisingSet(
buildAdvertisingSetParams(
- true, true, true, BluetoothDevice.PHY_LE_CODED, BluetoothDevice.PHY_LE_CODED),
+ /* isLegacy= */ true,
+ /* isConnectable= */ true,
+ /* isScannable= */ true,
+ BluetoothDevice.PHY_LE_CODED,
+ BluetoothDevice.PHY_LE_CODED),
oversizedData,
/* scanResponse= */ null,
/* periodicParameters= */ null,
/* periodicData= */ null,
- /* duration= */ 0,
- /* maxExtendedAdvertisingEvents= */ 0,
- gattServer,
- advertisingSetCallback,
+ createAdvertisingSetCallback(),
mainLooperHandler));
assertThat(shadowOf(bluetoothLeAdvertiser).getAdvertisingSetRequestCount()).isEqualTo(0);
}
@Test
- @Config(minSdk = UPSIDE_DOWN_CAKE)
+ @Config(minSdk = O)
public void
startAdvertisingSet_legacyModeWithTooBigScanResponse_throwsIllegalArgumentException() {
AdvertiseData oversizedData =
@@ -621,72 +583,72 @@ public class ShadowBluetoothLeAdvertiserTest {
() ->
bluetoothLeAdvertiser.startAdvertisingSet(
buildAdvertisingSetParams(
- true, true, true, BluetoothDevice.PHY_LE_CODED, BluetoothDevice.PHY_LE_CODED),
+ /* isLegacy= */ true,
+ /* isConnectable= */ true,
+ /* isScannable= */ true,
+ BluetoothDevice.PHY_LE_CODED,
+ BluetoothDevice.PHY_LE_CODED),
advertiseData1,
oversizedData,
/* periodicParameters= */ null,
/* periodicData= */ null,
- /* duration= */ 0,
- /* maxExtendedAdvertisingEvents= */ 0,
- gattServer,
- advertisingSetCallback,
- mainLooperHandler));
+ createAdvertisingSetCallback()));
assertThat(shadowOf(bluetoothLeAdvertiser).getAdvertisingSetRequestCount()).isEqualTo(0);
}
@Test
- @Config(minSdk = UPSIDE_DOWN_CAKE)
+ @Config(minSdk = O)
public void
startAdvertisingSet_nonLegacyModePrimaryPhySetButNotSupported_throwsIllegalArgumentException() {
- shadowBluetoothAdapter.setIsLeCodedPhySupported(false);
+ shadowOf(BluetoothAdapter.getDefaultAdapter()).setIsLeCodedPhySupported(false);
assertThrows(
IllegalArgumentException.class,
() ->
bluetoothLeAdvertiser.startAdvertisingSet(
buildAdvertisingSetParams(
- false, true, false, BluetoothDevice.PHY_LE_CODED, BluetoothDevice.PHY_LE_1M),
+ /* isLegacy= */ false,
+ /* isConnectable= */ true,
+ /* isScannable= */ false,
+ BluetoothDevice.PHY_LE_CODED,
+ BluetoothDevice.PHY_LE_1M),
advertiseData1,
/* scanResponse= */ null,
/* periodicParameters= */ null,
/* periodicData= */ null,
- /* duration= */ 0,
- /* maxExtendedAdvertisingEvents= */ 0,
- gattServer,
- advertisingSetCallback,
- mainLooperHandler));
+ createAdvertisingSetCallback()));
assertThat(shadowOf(bluetoothLeAdvertiser).getAdvertisingSetRequestCount()).isEqualTo(0);
}
@Test
- @Config(minSdk = UPSIDE_DOWN_CAKE)
+ @Config(minSdk = O)
public void
startAdvertisingSet_nonLegacyModeSecondaryPhySetButNotSupported_throwsIllegalArgumentException() {
- shadowBluetoothAdapter.setIsLeCodedPhySupported(false);
+ shadowOf(BluetoothAdapter.getDefaultAdapter()).setIsLeCodedPhySupported(false);
assertThrows(
IllegalArgumentException.class,
() ->
bluetoothLeAdvertiser.startAdvertisingSet(
buildAdvertisingSetParams(
- false, true, false, BluetoothDevice.PHY_LE_1M, BluetoothDevice.PHY_LE_CODED),
+ /* isLegacy= */ false,
+ /* isConnectable= */ true,
+ /* isScannable= */ false,
+ BluetoothDevice.PHY_LE_1M,
+ BluetoothDevice.PHY_LE_CODED),
advertiseData1,
/* scanResponse= */ null,
/* periodicParameters= */ null,
/* periodicData= */ null,
- /* duration= */ 0,
- /* maxExtendedAdvertisingEvents= */ 0,
- gattServer,
- advertisingSetCallback,
- mainLooperHandler));
+ createAdvertisingSetCallback()));
assertThat(shadowOf(bluetoothLeAdvertiser).getAdvertisingSetRequestCount()).isEqualTo(0);
}
@Test
- @Config(minSdk = UPSIDE_DOWN_CAKE)
+ @Config(minSdk = O)
public void
startAdvertisingSet_nonLegacyModeWithTooBigAdvertiseData_throwsIllegalArgumentException() {
- shadowBluetoothAdapter.setIsLeExtendedAdvertisingSupported(false);
+ shadowOf(BluetoothAdapter.getDefaultAdapter()).setIsLeExtendedAdvertisingSupported(false);
AdvertiseData oversizedData =
new AdvertiseData.Builder()
.addServiceUuid(ParcelUuid.fromString("FFFFFFFF-FFFF-FFFF-FFFF-FFFFFFFFFFFF"))
@@ -698,24 +660,24 @@ public class ShadowBluetoothLeAdvertiserTest {
() ->
bluetoothLeAdvertiser.startAdvertisingSet(
buildAdvertisingSetParams(
- false, true, false, BluetoothDevice.PHY_LE_CODED, BluetoothDevice.PHY_LE_CODED),
+ /* isLegacy= */ false,
+ /* isConnectable= */ true,
+ /* isScannable= */ false,
+ BluetoothDevice.PHY_LE_CODED,
+ BluetoothDevice.PHY_LE_CODED),
oversizedData,
/* scanResponse= */ null,
/* periodicParameters= */ null,
/* periodicData= */ null,
- /* duration= */ 0,
- /* maxExtendedAdvertisingEvents= */ 0,
- gattServer,
- advertisingSetCallback,
- mainLooperHandler));
+ createAdvertisingSetCallback()));
assertThat(shadowOf(bluetoothLeAdvertiser).getAdvertisingSetRequestCount()).isEqualTo(0);
}
@Test
- @Config(minSdk = UPSIDE_DOWN_CAKE)
+ @Config(minSdk = O)
public void
startAdvertisingSet_nonLegacyModeWithTooBigScanResponse_throwsIllegalArgumentException() {
- shadowBluetoothAdapter.setIsLeExtendedAdvertisingSupported(false);
+ shadowOf(BluetoothAdapter.getDefaultAdapter()).setIsLeExtendedAdvertisingSupported(false);
AdvertiseData oversizedData =
new AdvertiseData.Builder()
.addServiceUuid(ParcelUuid.fromString("FFFFFFFF-FFFF-FFFF-FFFF-FFFFFFFFFFFF"))
@@ -727,24 +689,24 @@ public class ShadowBluetoothLeAdvertiserTest {
() ->
bluetoothLeAdvertiser.startAdvertisingSet(
buildAdvertisingSetParams(
- false, true, false, BluetoothDevice.PHY_LE_CODED, BluetoothDevice.PHY_LE_CODED),
+ /* isLegacy= */ false,
+ /* isConnectable= */ true,
+ /* isScannable= */ false,
+ BluetoothDevice.PHY_LE_CODED,
+ BluetoothDevice.PHY_LE_CODED),
advertiseData1,
oversizedData,
/* periodicParameters= */ null,
/* periodicData= */ null,
- /* duration= */ 0,
- /* maxExtendedAdvertisingEvents= */ 0,
- gattServer,
- advertisingSetCallback,
- mainLooperHandler));
+ createAdvertisingSetCallback()));
assertThat(shadowOf(bluetoothLeAdvertiser).getAdvertisingSetRequestCount()).isEqualTo(0);
}
@Test
- @Config(minSdk = UPSIDE_DOWN_CAKE)
+ @Config(minSdk = O)
public void
startAdvertisingSet_nonLegacyModeWithTooBigPeriodicData_throwsIllegalArgumentException() {
- shadowBluetoothAdapter.setIsLeExtendedAdvertisingSupported(false);
+ shadowOf(BluetoothAdapter.getDefaultAdapter()).setIsLeExtendedAdvertisingSupported(false);
AdvertiseData oversizedData =
new AdvertiseData.Builder()
.addServiceUuid(ParcelUuid.fromString("FFFFFFFF-FFFF-FFFF-FFFF-FFFFFFFFFFFF"))
@@ -756,21 +718,21 @@ public class ShadowBluetoothLeAdvertiserTest {
() ->
bluetoothLeAdvertiser.startAdvertisingSet(
buildAdvertisingSetParams(
- false, true, false, BluetoothDevice.PHY_LE_CODED, BluetoothDevice.PHY_LE_CODED),
+ /* isLegacy= */ false,
+ /* isConnectable= */ true,
+ /* isScannable= */ false,
+ BluetoothDevice.PHY_LE_CODED,
+ BluetoothDevice.PHY_LE_CODED),
advertiseData1,
/* scanResponse= */ null,
new PeriodicAdvertisingParameters.Builder().setInterval(1).build(),
oversizedData,
- /* duration= */ 0,
- /* maxExtendedAdvertisingEvents= */ 0,
- gattServer,
- advertisingSetCallback,
- mainLooperHandler));
+ createAdvertisingSetCallback()));
assertThat(shadowOf(bluetoothLeAdvertiser).getAdvertisingSetRequestCount()).isEqualTo(0);
}
@Test
- @Config(minSdk = UPSIDE_DOWN_CAKE)
+ @Config(minSdk = O)
public void
startAdvertisingSet_maxExtendedAdvertisingEventsOutOfRange_throwsIllegalArgumentException() {
assertThrows(
@@ -778,65 +740,73 @@ public class ShadowBluetoothLeAdvertiserTest {
() ->
bluetoothLeAdvertiser.startAdvertisingSet(
buildAdvertisingSetParams(
- false, true, false, BluetoothDevice.PHY_LE_CODED, BluetoothDevice.PHY_LE_CODED),
+ /* isLegacy= */ false,
+ /* isConnectable= */ true,
+ /* isScannable= */ false,
+ BluetoothDevice.PHY_LE_CODED,
+ BluetoothDevice.PHY_LE_CODED),
advertiseData1,
/* scanResponse= */ null,
/* periodicParameters= */ null,
/* periodicData= */ null,
/* duration= */ 0,
- -1,
- gattServer,
- advertisingSetCallback,
+ /* maxExtendedAdvertisingEvents= */ -1,
+ createAdvertisingSetCallback(),
mainLooperHandler));
assertThat(shadowOf(bluetoothLeAdvertiser).getAdvertisingSetRequestCount()).isEqualTo(0);
}
@Test
- @Config(minSdk = UPSIDE_DOWN_CAKE)
+ @Config(minSdk = O)
public void startAdvertisingSet_durationOutOfRange_throwsIllegalArgumentException() {
assertThrows(
IllegalArgumentException.class,
() ->
bluetoothLeAdvertiser.startAdvertisingSet(
buildAdvertisingSetParams(
- false, true, false, BluetoothDevice.PHY_LE_CODED, BluetoothDevice.PHY_LE_CODED),
+ /* isLegacy= */ false,
+ /* isConnectable= */ true,
+ /* isScannable= */ false,
+ BluetoothDevice.PHY_LE_CODED,
+ BluetoothDevice.PHY_LE_CODED),
advertiseData1,
/* scanResponse= */ null,
/* periodicParameters= */ null,
/* periodicData= */ null,
- -1,
+ /* duration= */ -1,
/* maxExtendedAdvertisingEvents= */ 0,
- gattServer,
- advertisingSetCallback,
- mainLooperHandler));
+ createAdvertisingSetCallback()));
assertThat(shadowOf(bluetoothLeAdvertiser).getAdvertisingSetRequestCount()).isEqualTo(0);
}
@Test
- @Config(minSdk = UPSIDE_DOWN_CAKE)
+ @Config(minSdk = O)
public void stopAdvertisingSet() {
+ AdvertisingStatus status = new AdvertisingStatus();
+ AdvertisingSetCallback callback = createAdvertisingSetCallback(status);
bluetoothLeAdvertiser.startAdvertisingSet(
buildAdvertisingSetParams(
- true, true, true, BluetoothDevice.PHY_LE_CODED, BluetoothDevice.PHY_LE_CODED),
+ /* isLegacy= */ true,
+ /* isConnectable= */ true,
+ /* isScannable= */ true,
+ BluetoothDevice.PHY_LE_CODED,
+ BluetoothDevice.PHY_LE_CODED),
advertiseData1,
- null,
- null,
- null,
- 0,
- 0,
- gattServer,
- advertisingSetCallback,
- mainLooperHandler);
+ /* scanResponse= */ null,
+ /* periodicParameters= */ null,
+ /* periodicData= */ null,
+ callback);
assertThat(shadowOf(bluetoothLeAdvertiser).getAdvertisingSetRequestCount()).isEqualTo(1);
+ assertThat(status.isStarted).isTrue();
- bluetoothLeAdvertiser.stopAdvertisingSet(advertisingSetCallback);
+ bluetoothLeAdvertiser.stopAdvertisingSet(callback);
- assertThat(advertisingSetStopped).isTrue();
+ assertThat(status.isStarted).isFalse();
assertThat(shadowOf(bluetoothLeAdvertiser).getAdvertisingSetRequestCount()).isEqualTo(0);
}
@Test
- @Config(minSdk = UPSIDE_DOWN_CAKE)
+ @Config(minSdk = O)
public void stopAdvertisingSet_nullCallback_throwsIllegalArgumentException() {
assertThrows(
IllegalArgumentException.class, () -> bluetoothLeAdvertiser.stopAdvertisingSet(null));
@@ -856,4 +826,51 @@ public class ShadowBluetoothLeAdvertiserTest {
.setSecondaryPhy(secondaryPhy)
.build();
}
+
+ private AdvertisingSetCallback createAdvertisingSetCallback() {
+ return createAdvertisingSetCallback(new AdvertisingStatus());
+ }
+
+ private AdvertisingSetCallback createAdvertisingSetCallback(AdvertisingStatus advertisingStatus) {
+ return new AdvertisingSetCallback() {
+ @Override
+ public void onAdvertisingSetStarted(AdvertisingSet advertisingSet, int txPower, int status) {
+ advertisingStatus.setStatusCode(status);
+ if (status == AdvertisingSetCallback.ADVERTISE_SUCCESS) {
+ advertisingStatus.setStarted(true);
+ }
+ }
+
+ @Override
+ public void onAdvertisingSetStopped(AdvertisingSet advertisingSet) {
+ advertisingStatus.setStarted(false);
+ }
+ };
+ }
+
+ static class AdvertisingStatus {
+ private Optional<Integer> statusCode;
+ private boolean isStarted;
+
+ AdvertisingStatus() {
+ isStarted = false;
+ statusCode = Optional.empty();
+ }
+
+ public void setStatusCode(int statusCode) {
+ this.statusCode = Optional.of(statusCode);
+ }
+
+ public void setStarted(boolean started) {
+ this.isStarted = started;
+ }
+
+ public int getStatusCode() {
+ return statusCode.get();
+ }
+
+ public boolean isStarted() {
+ return isStarted;
+ }
+ }
}
diff --git a/shadows/framework/src/main/java/org/robolectric/shadows/ShadowBluetoothLeAdvertiser.java b/shadows/framework/src/main/java/org/robolectric/shadows/ShadowBluetoothLeAdvertiser.java
index c4e614dd5..ae8d16d46 100644
--- a/shadows/framework/src/main/java/org/robolectric/shadows/ShadowBluetoothLeAdvertiser.java
+++ b/shadows/framework/src/main/java/org/robolectric/shadows/ShadowBluetoothLeAdvertiser.java
@@ -1,5 +1,6 @@
package org.robolectric.shadows;
+import static android.os.Build.VERSION_CODES.LOLLIPOP;
import static android.os.Build.VERSION_CODES.O;
import static android.os.Build.VERSION_CODES.R;
import static android.os.Build.VERSION_CODES.S;
@@ -19,7 +20,10 @@ import android.bluetooth.le.AdvertisingSetParameters;
import android.bluetooth.le.BluetoothLeAdvertiser;
import android.bluetooth.le.PeriodicAdvertisingParameters;
import android.content.AttributionSource;
+import android.os.Build;
+import android.os.Build.VERSION_CODES;
import android.os.Handler;
+import android.os.Looper;
import android.os.ParcelUuid;
import java.util.HashMap;
import java.util.HashSet;
@@ -36,7 +40,7 @@ import org.robolectric.util.reflector.Direct;
import org.robolectric.util.reflector.ForType;
/** Shadow implementation of {@link BluetoothLeAdvertiser}. */
-@Implements(value = BluetoothLeAdvertiser.class, minSdk = O)
+@Implements(value = BluetoothLeAdvertiser.class, minSdk = LOLLIPOP)
public class ShadowBluetoothLeAdvertiser {
private static final String CALLBACK_NULL_MESSAGE = "callback cannot be null.";
@@ -135,23 +139,116 @@ public class ShadowBluetoothLeAdvertiser {
}
/**
- * Start Bluetooth LE Advertising Set. This method returns immediately, the operation status is
- * delivered through {@code callback}.
- *
- * @param parameters Advertising set parameters.
- * @param advertiseData Advertisement data to be broadcasted.
- * @param scanResponse Scan response associated with the advertisement data.
- * @param periodicParameters Periodic advertisng parameters.
- * @param periodicData Periodic advertising data.
- * @param duration Advertising duration, in 10ms unit.
- * @param maxExtendedAdvertisingEvents Maximum number of extended advertising events the
- * controller shall attempt to send prior to terminating the extended advertising, even if the
- * duration has not expired.
- * @param gattServer GattServer the GATT server that will "own" connections derived from this
- * advertising.
- * @param callback Callback for advertising set.
- * @param handler Thread upon which the callbacks will be invoked.
- * @throws IllegalArgumentException When {@code callback} is not present.
+ * Creates a new advertising set. If operation succeed, device will start advertising. This method
+ * returns immediately, the operation status is delivered through {@code
+ * callback.onAdvertisingSetStarted()} on the caller thread.
+ */
+ @Implementation(minSdk = O)
+ protected void startAdvertisingSet(
+ AdvertisingSetParameters parameters,
+ AdvertiseData advertiseData,
+ AdvertiseData scanResponse,
+ PeriodicAdvertisingParameters periodicParameters,
+ AdvertiseData periodicData,
+ AdvertisingSetCallback callback) {
+ startAdvertisingSet(
+ parameters,
+ advertiseData,
+ scanResponse,
+ periodicParameters,
+ periodicData,
+ /* duration= */ 0,
+ /* maxExtendedAdvertisingEvents= */ 0,
+ callback,
+ new Handler(Looper.getMainLooper()));
+ }
+
+ /**
+ * Creates a new advertising set. If operation succeed, device will start advertising. This method
+ * returns immediately, the operation status is delivered through {@code
+ * callback.onAdvertisingSetStarted()} on the caller thread instead of the {@code handler}.
+ */
+ @Implementation(minSdk = O)
+ protected void startAdvertisingSet(
+ AdvertisingSetParameters parameters,
+ AdvertiseData advertiseData,
+ AdvertiseData scanResponse,
+ PeriodicAdvertisingParameters periodicParameters,
+ AdvertiseData periodicData,
+ AdvertisingSetCallback callback,
+ Handler handler) {
+ startAdvertisingSet(
+ parameters,
+ advertiseData,
+ scanResponse,
+ periodicParameters,
+ periodicData,
+ /* duration= */ 0,
+ /* maxExtendedAdvertisingEvents= */ 0,
+ callback,
+ handler);
+ }
+
+ /**
+ * Creates a new advertising set. If operation succeed, device will start advertising. This method
+ * returns immediately, the operation status is delivered through {@code
+ * callback.onAdvertisingSetStarted()} on the caller thread.
+ */
+ @Implementation(minSdk = O)
+ protected void startAdvertisingSet(
+ AdvertisingSetParameters parameters,
+ AdvertiseData advertiseData,
+ AdvertiseData scanResponse,
+ PeriodicAdvertisingParameters periodicParameters,
+ AdvertiseData periodicData,
+ int duration,
+ int maxExtendedAdvertisingEvents,
+ AdvertisingSetCallback callback) {
+ startAdvertisingSet(
+ parameters,
+ advertiseData,
+ scanResponse,
+ periodicParameters,
+ periodicData,
+ duration,
+ maxExtendedAdvertisingEvents,
+ callback,
+ new Handler(Looper.getMainLooper()));
+ }
+
+ /**
+ * Creates a new advertising set. If operation succeed, device will start advertising. This method
+ * returns immediately, the operation status is delivered through {@code
+ * callback.onAdvertisingSetStarted()} on the caller thread instead of the {@code handler}.
+ */
+ @Implementation(minSdk = O)
+ protected void startAdvertisingSet(
+ AdvertisingSetParameters parameters,
+ AdvertiseData advertiseData,
+ AdvertiseData scanResponse,
+ PeriodicAdvertisingParameters periodicParameters,
+ AdvertiseData periodicData,
+ int duration,
+ int maxExtendedAdvertisingEvents,
+ AdvertisingSetCallback callback,
+ Handler handler) {
+ startAdvertisingSet(
+ parameters,
+ advertiseData,
+ scanResponse,
+ periodicParameters,
+ periodicData,
+ duration,
+ maxExtendedAdvertisingEvents,
+ /* gattServer= */ null,
+ callback,
+ handler);
+ }
+
+ /**
+ * Creates a new advertising set. If operation succeed, device will start advertising. This method
+ * returns immediately, the operation status is delivered through {@code
+ * callback.onAdvertisingSetStarted()} on the caller thread instead of the {@code handler}.
*/
@Implementation(minSdk = UPSIDE_DOWN_CAKE)
protected void startAdvertisingSet(
@@ -170,7 +267,10 @@ public class ShadowBluetoothLeAdvertiser {
}
boolean isConnectable = parameters.isConnectable();
- boolean isDiscoverable = parameters.isDiscoverable();
+ boolean isDiscoverable = true;
+ if (Build.VERSION.SDK_INT >= UPSIDE_DOWN_CAKE) {
+ isDiscoverable = parameters.isDiscoverable();
+ }
boolean hasFlags = isConnectable && isDiscoverable;
if (parameters.isLegacy()) {
if (getTotalBytes(advertiseData, hasFlags) > MAX_LEGACY_ADVERTISING_DATA_BYTES) {
@@ -231,16 +331,27 @@ public class ShadowBluetoothLeAdvertiser {
return;
}
- AdvertisingSet advertisingSet =
- ReflectionHelpers.callConstructor(
- AdvertisingSet.class,
- ClassParameter.from(int.class, advertiserId.getAndAdd(1)),
- ClassParameter.from(
- IBluetoothManager.class,
- ReflectionHelpers.createNullProxy(IBluetoothManager.class)),
- ClassParameter.from(
- AttributionSource.class,
- ReflectionHelpers.callInstanceMethod(bluetoothAdapter, "getAttributionSource")));
+ AdvertisingSet advertisingSet;
+ if (Build.VERSION.SDK_INT >= VERSION_CODES.S) {
+ advertisingSet =
+ ReflectionHelpers.callConstructor(
+ AdvertisingSet.class,
+ ClassParameter.from(int.class, advertiserId.getAndAdd(1)),
+ ClassParameter.from(
+ IBluetoothManager.class,
+ ReflectionHelpers.createNullProxy(IBluetoothManager.class)),
+ ClassParameter.from(
+ AttributionSource.class,
+ ReflectionHelpers.callInstanceMethod(bluetoothAdapter, "getAttributionSource")));
+ } else {
+ advertisingSet =
+ ReflectionHelpers.callConstructor(
+ AdvertisingSet.class,
+ ClassParameter.from(int.class, advertiserId.getAndAdd(1)),
+ ClassParameter.from(
+ IBluetoothManager.class,
+ ReflectionHelpers.createNullProxy(IBluetoothManager.class)));
+ }
callback.onAdvertisingSetStarted(
advertisingSet, parameters.getTxPowerLevel(), AdvertisingSetCallback.ADVERTISE_SUCCESS);
@@ -255,7 +366,7 @@ public class ShadowBluetoothLeAdvertiser {
* @param callback Callback for advertising set.
* @throws IllegalArgumentException When {@code callback} is not present.
*/
- @Implementation(minSdk = UPSIDE_DOWN_CAKE)
+ @Implementation(minSdk = O)
protected void stopAdvertisingSet(AdvertisingSetCallback callback) {
if (callback == null) {
throw new IllegalArgumentException("callback cannot be null");