Merge "Revert "Introduce BLE advertiser wrapper for unit tests."" into main

This commit is contained in:
Chen Wang 2025-08-01 10:54:55 -07:00 • committed by Android (Google) Code Review
commit 672392609b
6 changed files with 79 additions and 218 deletions

View file

@ -41,7 +41,6 @@ import android.nearby.aidl.IOffloadCallback;
import android.util.Log;
import com.android.internal.annotations.VisibleForTesting;
import com.android.server.nearby.injector.BluetoothLeAdvertiserWrapper;
import com.android.server.nearby.injector.Injector;
import com.android.server.nearby.managers.BluetoothFinderManager;
import com.android.server.nearby.managers.BroadcastProviderManager;
@ -196,7 +195,6 @@ public class NearbyService extends INearbyManager.Stub {
if (mInjector instanceof SystemInjector) {
// The nearby service must be functioning after this boot phase.
((SystemInjector) mInjector).initializeBluetoothAdapter();
((SystemInjector) mInjector).initializeBluetoothLeAdvertiserWrapper();
// Initialize ContextManager for CHRE scan.
((SystemInjector) mInjector).initializeContextHubManager();
}
@ -229,8 +227,6 @@ public class NearbyService extends INearbyManager.Stub {
private static final class SystemInjector implements Injector {
private final Context mContext;
@Nullable private BluetoothAdapter mBluetoothAdapter;
@Nullable private BluetoothLeAdvertiserWrapper mBluetoothLeAdvertiserWrapper;
@Nullable private ContextHubManager mContextHubManager;
@Nullable private AppOpsManager mAppOpsManager;
@ -244,12 +240,6 @@ public class NearbyService extends INearbyManager.Stub {
return mBluetoothAdapter;
}
@Override
@Nullable
public BluetoothLeAdvertiserWrapper getBluetoothLeAdvertiserWrapper() {
return mBluetoothLeAdvertiserWrapper;
};
@Override
@Nullable
public ContextHubManager getContextHubManager() {
@ -273,13 +263,6 @@ public class NearbyService extends INearbyManager.Stub {
mBluetoothAdapter = manager.getAdapter();
}
synchronized void initializeBluetoothLeAdvertiserWrapper() {
if (mBluetoothLeAdvertiserWrapper != null) {
return;
}
mBluetoothLeAdvertiserWrapper = new BluetoothLeAdvertiserWrapper(mContext);
}
synchronized void initializeContextHubManager() {
if (mContextHubManager != null) {
return;

View file

@ -1,136 +0,0 @@
/*
* Copyright (C) 2025 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.server.nearby.injector;
import static com.android.server.nearby.NearbyService.TAG;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothManager;
import android.bluetooth.le.AdvertiseCallback;
import android.bluetooth.le.AdvertiseData;
import android.bluetooth.le.AdvertiseSettings;
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.util.Log;
/**
* Wrapper for BluetoothLeAdvertiser.
*
* This class proxies all functions to BluetoothLeAdvertiser.
* It will be mocked for unit tests.
*
* @see BluetoothLeAdvertiser for the details of each public function APIs.
*/
public class BluetoothLeAdvertiserWrapper {
private final BluetoothAdapter mAdapter;
private final BluetoothLeAdvertiser mLeAdvertiser;
/**
* Returns a wrapper of BluetoothLeAdvertiser.
*
* @return an object of BluetoothLeAdvertiserWrapper
* @see BluetoothLeAdvertiser
*/
public BluetoothLeAdvertiserWrapper(Context context) {
BluetoothManager manager = context.getSystemService(BluetoothManager.class);
if (manager == null) {
mAdapter = null;
mLeAdvertiser = null;
return;
}
mAdapter = manager.getAdapter();
mLeAdvertiser = mAdapter == null ? null : mAdapter.getBluetoothLeAdvertiser();
}
/**
* Starts BLE advertising.
*
* @see BluetoothLeAdvertiser
*/
public void startAdvertising(
AdvertiseSettings settings,
AdvertiseData advertiseData,
final AdvertiseCallback callback) {
if (mLeAdvertiser == null) {
Log.e(TAG, "Call startAdvertising from null advertiser.");
}
mLeAdvertiser.startAdvertising(settings, advertiseData, callback);
}
/**
* Starts BLE advertisingSet.
*
* @see BluetoothLeAdvertiser
*/
public void startAdvertisingSet(
AdvertisingSetParameters parameters,
AdvertiseData advertiseData,
AdvertiseData scanResponse,
PeriodicAdvertisingParameters periodicParameters,
AdvertiseData periodicData,
AdvertisingSetCallback callback) {
if (mLeAdvertiser == null) {
Log.e(TAG, "Call startAdvertisingSet from null advertiser.");
}
mLeAdvertiser.startAdvertisingSet(
parameters,
advertiseData,
scanResponse,
periodicParameters,
periodicData,
callback);
}
/**
* Stops BLE advertising.
*
* @see BluetoothLeAdvertiser
*/
public void stopAdvertising(final AdvertiseCallback callback) {
if (mLeAdvertiser == null) {
Log.e(TAG, "Call startAdvertising from null advertiser.");
}
mLeAdvertiser.stopAdvertising(callback);
}
/**
* Stops BLE advertisingSet.
*
* @see BluetoothLeAdvertiser
*/
public void stopAdvertisingSet(AdvertisingSetCallback callback) {
if (mLeAdvertiser == null) {
Log.e(TAG, "Call startAdvertisingSet from null advertiser.");
}
mLeAdvertiser.stopAdvertisingSet(callback);
}
/**
* Checks if BLE supports extended advertising.
*
* @return true if extended advertisng is supported.
*/
public Boolean isLeExtendedAdvertisingSupported() {
if (mAdapter == null) {
Log.e(TAG, "Checks extended BLE support from null BLE adapter.");
}
return mAdapter.isLeExtendedAdvertisingSupported();
}
}

View file

@ -29,9 +29,6 @@ public interface Injector {
/** Get the BluetoothAdapter for BleDiscoveryProvider to scan. */
BluetoothAdapter getBluetoothAdapter();
/** Get the BluetoothLeAdvertiserWrapper to start BLE broadcast. */
BluetoothLeAdvertiserWrapper getBluetoothLeAdvertiserWrapper();
/** Get the ContextHubManagerAdapter for ChreDiscoveryProvider to scan. */
ContextHubManager getContextHubManager();

View file

@ -19,18 +19,19 @@ package com.android.server.nearby.provider;
import static com.android.server.nearby.NearbyService.TAG;
import static com.android.server.nearby.presence.PresenceConstants.PRESENCE_UUID;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.le.AdvertiseCallback;
import android.bluetooth.le.AdvertiseData;
import android.bluetooth.le.AdvertiseSettings;
import android.bluetooth.le.AdvertisingSet;
import android.bluetooth.le.AdvertisingSetCallback;
import android.bluetooth.le.AdvertisingSetParameters;
import android.bluetooth.le.BluetoothLeAdvertiser;
import android.nearby.BroadcastCallback;
import android.nearby.BroadcastRequest;
import android.util.Log;
import com.android.internal.annotations.VisibleForTesting;
import com.android.server.nearby.injector.BluetoothLeAdvertiserWrapper;
import com.android.server.nearby.injector.Injector;
import java.util.concurrent.Executor;
@ -54,7 +55,6 @@ public class BleBroadcastProvider extends AdvertiseCallback {
private boolean mIsAdvertising;
@VisibleForTesting
AdvertisingSetCallback mAdvertisingSetCallback;
public BleBroadcastProvider(Injector injector, Executor executor) {
mInjector = injector;
mExecutor = executor;
@ -70,45 +70,49 @@ public class BleBroadcastProvider extends AdvertiseCallback {
stop();
}
boolean advertiseStarted = false;
BluetoothLeAdvertiserWrapper advertiser = mInjector.getBluetoothLeAdvertiserWrapper();
if (advertiser != null) {
advertiseStarted = true;
AdvertiseData advertiseData =
new AdvertiseData.Builder()
.addServiceData(PRESENCE_UUID, advertisementPackets).build();
try {
mBroadcastListener = listener;
switch (version) {
case BroadcastRequest.PRESENCE_VERSION_V0:
advertiser.startAdvertising(getAdvertiseSettings(),
advertiseData, this);
Log.v(TAG, "Start to broadcast V0 advertisement.");
break;
case BroadcastRequest.PRESENCE_VERSION_V1:
if (advertiser.isLeExtendedAdvertisingSupported()) {
if (mAdvertisingSetCallback == null) {
mAdvertisingSetCallback = getAdvertisingSetCallback();
BluetoothAdapter adapter = mInjector.getBluetoothAdapter();
if (adapter != null) {
BluetoothLeAdvertiser bluetoothLeAdvertiser =
mInjector.getBluetoothAdapter().getBluetoothLeAdvertiser();
if (bluetoothLeAdvertiser != null) {
advertiseStarted = true;
AdvertiseData advertiseData =
new AdvertiseData.Builder()
.addServiceData(PRESENCE_UUID, advertisementPackets).build();
try {
mBroadcastListener = listener;
switch (version) {
case BroadcastRequest.PRESENCE_VERSION_V0:
bluetoothLeAdvertiser.startAdvertising(getAdvertiseSettings(),
advertiseData, this);
Log.v(TAG, "Start to broadcast V0 advertisement.");
break;
case BroadcastRequest.PRESENCE_VERSION_V1:
if (adapter.isLeExtendedAdvertisingSupported()) {
if (mAdvertisingSetCallback == null) {
mAdvertisingSetCallback = getAdvertisingSetCallback();
}
bluetoothLeAdvertiser.startAdvertisingSet(
getAdvertisingSetParameters(),
advertiseData,
null, null, null, mAdvertisingSetCallback);
Log.v(TAG, "Start to broadcast V1 advertisement.");
} else {
Log.w(TAG, "Failed to start advertising set because the chipset"
+ " does not supports LE Extended Advertising feature.");
advertiseStarted = false;
}
advertiser.startAdvertisingSet(
getAdvertisingSetParameters(),
advertiseData,
null, null, null, mAdvertisingSetCallback);
Log.v(TAG, "Start to broadcast V1 advertisement.");
} else {
Log.w(TAG, "Failed to start advertising set because the chipset"
+ " does not supports LE Extended Advertising feature.");
break;
default:
Log.w(TAG, "Failed to start advertising set because the advertisement"
+ " is wrong.");
advertiseStarted = false;
}
break;
default:
Log.w(TAG, "Failed to start advertising set because the advertisement"
+ " is wrong.");
advertiseStarted = false;
}
} catch (NullPointerException | IllegalStateException | SecurityException
| IllegalArgumentException e) {
Log.w(TAG, "Failed to start advertising.", e);
advertiseStarted = false;
}
} catch (NullPointerException | IllegalStateException | SecurityException
| IllegalArgumentException e) {
Log.w(TAG, "Failed to start advertising.", e);
advertiseStarted = false;
}
}
if (!advertiseStarted) {
@ -121,10 +125,14 @@ public class BleBroadcastProvider extends AdvertiseCallback {
*/
public void stop() {
if (mIsAdvertising) {
BluetoothLeAdvertiserWrapper advertiser = mInjector.getBluetoothLeAdvertiserWrapper();
if (advertiser != null) {
advertiser.stopAdvertising(this);
advertiser.stopAdvertisingSet(mAdvertisingSetCallback);
BluetoothAdapter adapter = mInjector.getBluetoothAdapter();
if (adapter != null) {
BluetoothLeAdvertiser bluetoothLeAdvertiser =
mInjector.getBluetoothAdapter().getBluetoothLeAdvertiser();
if (bluetoothLeAdvertiser != null) {
bluetoothLeAdvertiser.stopAdvertising(this);
bluetoothLeAdvertiser.stopAdvertisingSet(mAdvertisingSetCallback);
}
}
mBroadcastListener = null;
mIsAdvertising = false;

View file

@ -21,14 +21,19 @@ import static org.mockito.Mockito.atLeastOnce;
import static org.mockito.Mockito.eq;
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.bluetooth.BluetoothManager;
import android.bluetooth.le.AdvertiseSettings;
import android.bluetooth.le.AdvertisingSetCallback;
import android.content.Context;
import android.hardware.location.ContextHubManager;
import android.nearby.BroadcastCallback;
import android.nearby.BroadcastRequest;
import com.android.server.nearby.injector.BluetoothLeAdvertiserWrapper;
import androidx.test.core.app.ApplicationProvider;
import com.android.server.nearby.injector.Injector;
import com.google.common.util.concurrent.MoreExecutors;
@ -37,7 +42,6 @@ import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.mockito.junit.MockitoJUnit;
import org.mockito.junit.MockitoRule;
@ -48,22 +52,14 @@ public class BleBroadcastProviderTest {
@Rule
public final MockitoRule mocks = MockitoJUnit.rule();
@Mock
private Injector mInjector;
@Mock
private BluetoothLeAdvertiserWrapper mBluetoothLeAdvertiserWrapper;
@Mock
private BleBroadcastProvider.BroadcastListener mBroadcastListener;
private BleBroadcastProvider mBleBroadcastProvider;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
when(mInjector.getBluetoothLeAdvertiserWrapper()).thenReturn(mBluetoothLeAdvertiserWrapper);
when(mBluetoothLeAdvertiserWrapper.isLeExtendedAdvertisingSupported()).thenReturn(true);
mBleBroadcastProvider = new BleBroadcastProvider(mInjector, MoreExecutors.directExecutor());
mBleBroadcastProvider = new BleBroadcastProvider(new TestInjector(),
MoreExecutors.directExecutor());
}
@Test
@ -118,5 +114,24 @@ public class BleBroadcastProviderTest {
public void testStop() {
mBleBroadcastProvider.stop();
}
}
private static class TestInjector implements Injector {
@Override
public BluetoothAdapter getBluetoothAdapter() {
Context context = ApplicationProvider.getApplicationContext();
BluetoothManager bluetoothManager = context.getSystemService(BluetoothManager.class);
return bluetoothManager.getAdapter();
}
@Override
public ContextHubManager getContextHubManager() {
return null;
}
@Override
public AppOpsManager getAppOpsManager() {
return null;
}
}
}

View file

@ -40,7 +40,6 @@ import android.nearby.ScanFilter;
import androidx.test.platform.app.InstrumentationRegistry;
import com.android.server.nearby.injector.BluetoothLeAdvertiserWrapper;
import com.android.server.nearby.injector.Injector;
import org.junit.Before;
@ -123,11 +122,6 @@ public final class BleDiscoveryProviderTest {
return mBluetoothAdapter;
}
@Override
public BluetoothLeAdvertiserWrapper getBluetoothLeAdvertiserWrapper() {
return null;
};
@Override
public ContextHubManager getContextHubManager() {
return null;