summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--android/app/AndroidManifest.xml11
-rw-r--r--android/app/src/com/android/bluetooth/btservice/AdapterService.java95
-rw-r--r--android/app/src/com/android/bluetooth/btservice/ProfileService.java11
-rw-r--r--android/app/src/com/android/bluetooth/gatt/GattService.java45
-rw-r--r--android/app/tests/unit/src/com/android/bluetooth/TestUtils.java19
-rw-r--r--android/app/tests/unit/src/com/android/bluetooth/btservice/AdapterServiceFactoryResetTest.java54
-rw-r--r--android/app/tests/unit/src/com/android/bluetooth/btservice/AdapterServiceRestartTest.java3
-rw-r--r--android/app/tests/unit/src/com/android/bluetooth/btservice/AdapterServiceTest.java101
-rw-r--r--android/app/tests/unit/src/com/android/bluetooth/btservice/ProfileServiceTest.java60
-rw-r--r--android/app/tests/unit/src/com/android/bluetooth/gatt/AppScanStatsTest.java25
-rw-r--r--android/app/tests/unit/src/com/android/bluetooth/gatt/ContextMapTest.java24
-rw-r--r--android/app/tests/unit/src/com/android/bluetooth/gatt/GattServiceBinderTest.java7
-rw-r--r--android/app/tests/unit/src/com/android/bluetooth/gatt/GattServiceTest.java54
-rw-r--r--android/app/tests/unit/src/com/android/bluetooth/gatt/ScanManagerTest.java21
-rw-r--r--system/binder/android/bluetooth/IBluetoothGatt.aidl7
15 files changed, 218 insertions, 319 deletions
diff --git a/android/app/AndroidManifest.xml b/android/app/AndroidManifest.xml
index 929cc0e42b..7a398344c0 100644
--- a/android/app/AndroidManifest.xml
+++ b/android/app/AndroidManifest.xml
@@ -221,17 +221,6 @@
</intent-filter>
</service>
- <!-- Generic Attribute (GATT) Profile Service -->
- <service android:process="@string/process"
- android:name="com.android.bluetooth.gatt.GattService"
- android:enabled="true"
- android:exported="true"
- android:permission="android.permission.ACCESS_BLUETOOTH_SHARE">
- <intent-filter>
- <action android:name="android.bluetooth.IBluetoothGatt"/>
- </intent-filter>
- </service>
-
<!-- Hearing Aid Profile (HAP) client Profile Service -->
<service android:process="@string/process"
android:name="com.android.bluetooth.hap.HapClientService"
diff --git a/android/app/src/com/android/bluetooth/btservice/AdapterService.java b/android/app/src/com/android/bluetooth/btservice/AdapterService.java
index 8d4bf4bd9a..0def33ca1c 100644
--- a/android/app/src/com/android/bluetooth/btservice/AdapterService.java
+++ b/android/app/src/com/android/bluetooth/btservice/AdapterService.java
@@ -79,11 +79,9 @@ import android.bluetooth.UidTraffic;
import android.companion.CompanionDeviceManager;
import android.content.AttributionSource;
import android.content.BroadcastReceiver;
-import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
-import android.content.ServiceConnection;
import android.content.SharedPreferences;
import android.content.pm.PackageManager;
import android.os.AsyncTask;
@@ -371,7 +369,7 @@ public class AdapterService extends Service {
private BassClientService mBassClientService;
private BatteryService mBatteryService;
private BluetoothQualityReportNativeInterface mBluetoothQualityReportNativeInterface;
- private IBluetoothGatt mBluetoothGatt;
+ private GattService mGattService;
private volatile boolean mTestModeEnabled = false;
@@ -425,8 +423,6 @@ public class AdapterService extends Service {
private static final int MESSAGE_PROFILE_SERVICE_REGISTERED = 2;
private static final int MESSAGE_PROFILE_SERVICE_UNREGISTERED = 3;
private static final int MESSAGE_PREFERRED_AUDIO_PROFILES_AUDIO_FRAMEWORK_TIMEOUT = 4;
- private static final int MESSAGE_ON_PROFILE_SERVICE_BIND = 5;
- private static final int MESSAGE_ON_PROFILE_SERVICE_UNBIND = 6;
class AdapterServiceHandler extends Handler {
AdapterServiceHandler(Looper looper) {
@@ -450,14 +446,6 @@ public class AdapterService extends Service {
verboseLog("handleMessage() - MESSAGE_PROFILE_SERVICE_UNREGISTERED");
unregisterProfileService((ProfileService) msg.obj);
break;
- case MESSAGE_ON_PROFILE_SERVICE_BIND:
- verboseLog("handleMessage() - MESSAGE_ON_PROFILE_SERVICE_BIND");
- onGattBind((IBinder) msg.obj);
- break;
- case MESSAGE_ON_PROFILE_SERVICE_UNBIND:
- verboseLog("handleMessage() - MESSAGE_ON_PROFILE_SERVICE_UNBIND");
- onGattUnbind();
- break;
case MESSAGE_PREFERRED_AUDIO_PROFILES_AUDIO_FRAMEWORK_TIMEOUT:
errorLog(
"handleMessage() - "
@@ -497,22 +485,6 @@ public class AdapterService extends Service {
mRegisteredProfiles.remove(profile);
}
- private void onGattBind(IBinder service) {
- mBluetoothGatt = IBluetoothGatt.Stub.asInterface(service);
- try {
- mBluetoothGatt.startService();
- } catch (RemoteException e) {
- Log.e(TAG, "onGattBind: RemoteException", e);
- }
- }
-
- private void onGattUnbind() {
- mBluetoothGatt = null;
- Log.e(
- TAG,
- "onGattUnbind: Gatt service has disconnected from AdapterService unexpectedly");
- }
-
private void processProfileServiceStateChanged(ProfileService profile, int state) {
switch (state) {
case BluetoothAdapter.STATE_ON:
@@ -1005,47 +977,11 @@ public class AdapterService extends Service {
}
}
- class GattServiceConnection implements ServiceConnection {
- public void onServiceConnected(ComponentName componentName, IBinder service) {
- String name = componentName.getClassName();
- if (DBG) {
- Log.d(TAG, "GattServiceConnection.onServiceConnected: " + name);
- }
- if (!name.equals(GattService.class.getName())) {
- Log.e(TAG, "Unknown service connected: " + name);
- return;
- }
- mHandler.obtainMessage(MESSAGE_ON_PROFILE_SERVICE_BIND, service).sendToTarget();
- }
-
- public void onServiceDisconnected(ComponentName componentName) {
- // Called if we unexpectedly disconnect. This should never happen.
- String name = componentName.getClassName();
- Log.e(TAG, "GattServiceConnection.onServiceDisconnected: " + name);
- if (!name.equals(GattService.class.getName())) {
- Log.e(TAG, "Unknown service disconnected: " + name);
- return;
- }
- mHandler.sendEmptyMessage(MESSAGE_ON_PROFILE_SERVICE_UNBIND);
- }
- }
-
- private GattServiceConnection mGattConnection = new GattServiceConnection();
-
private void startGattProfileService() {
mStartedProfiles.add(GattService.class.getSimpleName());
- Intent intent = new Intent(this, GattService.class);
- if (!bindServiceAsUser(
- intent,
- mGattConnection,
- Context.BIND_AUTO_CREATE | Context.BIND_IMPORTANT,
- UserHandle.CURRENT)) {
- // This should never happen
- // unbindService will be called during stopGattProfileService triggered by AdapterState
- Log.e(TAG, "Error while binding to gatt. This Bluetooth session will timeout");
- unbindService(mGattConnection);
- }
+ mGattService = new GattService(this);
+ ((ProfileService) mGattService).doStart();
}
private void stopGattProfileService() {
@@ -1056,15 +992,10 @@ public class AdapterService extends Service {
}
mStartedProfiles.remove(GattService.class.getSimpleName());
-
- try {
- if (mBluetoothGatt != null) {
- mBluetoothGatt.stopService();
- }
- } catch (RemoteException e) {
- Log.e(TAG, "stopGattProfileService: RemoteException", e);
+ if (mGattService != null) {
+ ((ProfileService) mGattService).doStop();
+ mGattService = null;
}
- unbindService(mGattConnection);
}
private void invalidateBluetoothGetStateCache() {
@@ -5244,6 +5175,7 @@ public class AdapterService extends Service {
try {
AdapterService service = getService();
if (service != null) {
+ enforceBluetoothPrivilegedPermission(service);
service.unregAllGattClient(source);
}
receiver.send(null);
@@ -6883,16 +6815,15 @@ public class AdapterService extends Service {
}
IBluetoothGatt getBluetoothGatt() {
- return mBluetoothGatt;
+ if (mGattService == null) {
+ return null;
+ }
+ return IBluetoothGatt.Stub.asInterface(((ProfileService) mGattService).getBinder());
}
void unregAllGattClient(AttributionSource source) {
- if (mBluetoothGatt != null) {
- try {
- mBluetoothGatt.unregAll(source);
- } catch (RemoteException e) {
- Log.e(TAG, "Unable to disconnect all apps.", e);
- }
+ if (mGattService != null) {
+ mGattService.unregAll(source);
}
}
diff --git a/android/app/src/com/android/bluetooth/btservice/ProfileService.java b/android/app/src/com/android/bluetooth/btservice/ProfileService.java
index 5795847d1b..acd72c7c69 100644
--- a/android/app/src/com/android/bluetooth/btservice/ProfileService.java
+++ b/android/app/src/com/android/bluetooth/btservice/ProfileService.java
@@ -18,6 +18,8 @@ package com.android.bluetooth.btservice;
import static android.Manifest.permission.BLUETOOTH_CONNECT;
+import static java.util.Objects.requireNonNull;
+
import android.annotation.RequiresPermission;
import android.annotation.SuppressLint;
import android.app.Service;
@@ -180,6 +182,11 @@ public abstract class ProfileService extends Service {
return mBinder;
}
+ IBinder getBinder() {
+ requireNonNull(mBinder, "Binder is null. onCreate need to be called first");
+ return mBinder;
+ }
+
@Override
// Suppressed since this is called from framework
@SuppressLint("AndroidFrameworkRequiresPermission")
@@ -295,7 +302,7 @@ public abstract class ProfileService extends Service {
android.Manifest.permission.MANAGE_USERS,
android.Manifest.permission.INTERACT_ACROSS_USERS
})
- protected void doStart() {
+ void doStart() {
Log.v(mName, "doStart");
if (mAdapter == null) {
Log.w(mName, "Can't start profile service: device does not have BT");
@@ -321,7 +328,7 @@ public abstract class ProfileService extends Service {
mAdapterService.onProfileServiceStateChanged(this, BluetoothAdapter.STATE_ON);
}
- protected void doStop() {
+ void doStop() {
Log.v(mName, "doStop");
if (mAdapterService == null || mAdapterService.isStartedProfile(mName)) {
Log.w(mName, "Unexpectedly do Stop, don't stop.");
diff --git a/android/app/src/com/android/bluetooth/gatt/GattService.java b/android/app/src/com/android/bluetooth/gatt/GattService.java
index 8e0a2a38dc..0156835787 100644
--- a/android/app/src/com/android/bluetooth/gatt/GattService.java
+++ b/android/app/src/com/android/bluetooth/gatt/GattService.java
@@ -56,6 +56,7 @@ import android.bluetooth.le.ScanSettings;
import android.companion.AssociationInfo;
import android.companion.CompanionDeviceManager;
import android.content.AttributionSource;
+import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager.NameNotFoundException;
import android.content.pm.PackageManager.PackageInfoFlags;
@@ -290,6 +291,11 @@ public class GattService extends ProfileService {
private Handler mTestModeHandler;
private final Object mTestModeLock = new Object();
+ public GattService(Context ctx) {
+ attachBaseContext(ctx);
+ onCreate();
+ }
+
public static boolean isEnabled() {
return BluetoothProperties.isProfileGattEnabled().orElse(true);
}
@@ -612,34 +618,6 @@ public class GattService extends ProfileService {
}
@Override
- public void startService() {
- GattService service = mService;
- if (service == null) {
- Log.e(TAG, "startService: Service is null");
- return;
- }
- if (!Utils.checkConnectPermissionForDataDelivery(
- service, null, "GattService startService")) {
- return;
- }
- service.doStart();
- }
-
- @Override
- public void stopService() {
- GattService service = mService;
- if (service == null) {
- Log.e(TAG, "stopService: Service is null");
- return;
- }
- if (!Utils.checkConnectPermissionForDataDelivery(
- service, null, "GattService stopService")) {
- return;
- }
- service.doStop();
- }
-
- @Override
public void getDevicesMatchingConnectionStates(int[] states,
AttributionSource attributionSource, SynchronousResultReceiver receiver) {
try {
@@ -1778,15 +1756,6 @@ public class GattService extends ProfileService {
}
@Override
- public void unregAll(AttributionSource attributionSource) {
- GattService service = getService();
- if (service == null) {
- return;
- }
- service.unregAll(attributionSource);
- }
-
- @Override
public void numHwTrackFiltersAvailable(AttributionSource attributionSource,
SynchronousResultReceiver receiver) {
try {
@@ -3435,7 +3404,7 @@ public class GattService extends ProfileService {
}
@RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
- void unregAll(AttributionSource attributionSource) {
+ public void unregAll(AttributionSource attributionSource) {
for (Integer appId : mClientMap.getAllAppsIds()) {
if (DBG) {
Log.d(TAG, "unreg:" + appId);
diff --git a/android/app/tests/unit/src/com/android/bluetooth/TestUtils.java b/android/app/tests/unit/src/com/android/bluetooth/TestUtils.java
index 4104391c2e..913444f682 100644
--- a/android/app/tests/unit/src/com/android/bluetooth/TestUtils.java
+++ b/android/app/tests/unit/src/com/android/bluetooth/TestUtils.java
@@ -39,6 +39,7 @@ import androidx.test.uiautomator.UiDevice;
import com.android.bluetooth.avrcpcontroller.BluetoothMediaBrowserService;
import com.android.bluetooth.btservice.AdapterService;
import com.android.bluetooth.btservice.ProfileService;
+import com.android.bluetooth.gatt.GattService;
import org.junit.Assert;
import org.junit.rules.TestRule;
@@ -138,6 +139,21 @@ public class TestUtils {
method.invoke(null, adapterService);
}
+ /** Helper function to mock getSystemService calls */
+ public static <T> void mockGetSystemService(
+ Context ctx, String serviceName, Class<T> serviceClass, T mockService) {
+ when(ctx.getSystemService(eq(serviceName))).thenReturn(mockService);
+ when(ctx.getSystemServiceName(eq(serviceClass))).thenReturn(serviceName);
+ }
+
+ /** Helper function to mock getSystemService calls */
+ public static <T> T mockGetSystemService(
+ Context ctx, String serviceName, Class<T> serviceClass) {
+ T mockedService = mock(serviceClass);
+ mockGetSystemService(ctx, serviceName, serviceClass, mockedService);
+ return mockedService;
+ }
+
/**
* Start a profile service using the given {@link ServiceTestRule} and verify through
* {@link AdapterService#getAdapterService()} that the service is actually started within
@@ -156,6 +172,9 @@ public class TestUtils {
*/
public static <T extends ProfileService> void startService(ServiceTestRule serviceTestRule,
Class<T> profileServiceClass) throws TimeoutException {
+ if (profileServiceClass == GattService.class) {
+ Assert.assertFalse("GattService cannot be started as a service", true);
+ }
AdapterService adapterService = AdapterService.getAdapterService();
Assert.assertNotNull("Adapter service should not be null", adapterService);
Assert.assertTrue("AdapterService.getAdapterService() must return a mocked or spied object"
diff --git a/android/app/tests/unit/src/com/android/bluetooth/btservice/AdapterServiceFactoryResetTest.java b/android/app/tests/unit/src/com/android/bluetooth/btservice/AdapterServiceFactoryResetTest.java
index 9d81e88e5f..beb4a4554c 100644
--- a/android/app/tests/unit/src/com/android/bluetooth/btservice/AdapterServiceFactoryResetTest.java
+++ b/android/app/tests/unit/src/com/android/bluetooth/btservice/AdapterServiceFactoryResetTest.java
@@ -36,6 +36,7 @@ import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.content.pm.PermissionInfo;
import android.content.res.Resources;
+import android.hardware.display.DisplayManager;
import android.media.AudioManager;
import android.os.BatteryStatsManager;
import android.os.Binder;
@@ -91,16 +92,10 @@ public class AdapterServiceFactoryResetTest {
private @Mock android.app.Application mApplication;
private @Mock MetricsLogger mMockMetricsLogger;
- // Mocked SystemService
- private @Mock AlarmManager mMockAlarmManager;
- private @Mock AppOpsManager mMockAppOpsManager;
- private @Mock AudioManager mMockAudioManager;
- private @Mock DevicePolicyManager mMockDevicePolicyManager;
- private @Mock UserManager mMockUserManager;
-
// SystemService that are not mocked
private BluetoothManager mBluetoothManager;
private CompanionDeviceManager mCompanionDeviceManager;
+ private DisplayManager mDisplayManager;
private PowerManager mPowerManager;
private PermissionCheckerManager mPermissionCheckerManager;
private PermissionManager mPermissionManager;
@@ -131,6 +126,12 @@ public class AdapterServiceFactoryResetTest {
when(mMockContext.getSystemServiceName(eq(serviceClass))).thenReturn(serviceName);
}
+ <T> T mockGetSystemService(String serviceName, Class<T> serviceClass) {
+ T mockedService = mock(serviceClass);
+ mockGetSystemService(serviceName, serviceClass, mockedService);
+ return mockedService;
+ }
+
@Before
public void setUp() throws PackageManager.NameNotFoundException {
Log.e(TAG, "setUp()");
@@ -156,23 +157,20 @@ public class AdapterServiceFactoryResetTest {
}
});
- mPowerManager = InstrumentationRegistry.getTargetContext()
- .getSystemService(PowerManager.class);
- mPermissionCheckerManager = InstrumentationRegistry.getTargetContext()
- .getSystemService(PermissionCheckerManager.class);
-
- mPermissionManager = InstrumentationRegistry.getTargetContext()
- .getSystemService(PermissionManager.class);
+ Context targetContext = InstrumentationRegistry.getTargetContext();
- mBluetoothManager = InstrumentationRegistry.getTargetContext()
- .getSystemService(BluetoothManager.class);
-
- mCompanionDeviceManager =
- InstrumentationRegistry.getTargetContext()
- .getSystemService(CompanionDeviceManager.class);
+ mBluetoothManager = targetContext.getSystemService(BluetoothManager.class);
+ mCompanionDeviceManager = targetContext.getSystemService(CompanionDeviceManager.class);
+ mDisplayManager = targetContext.getSystemService(DisplayManager.class);
+ mPermissionCheckerManager = targetContext.getSystemService(PermissionCheckerManager.class);
+ mPermissionManager = targetContext.getSystemService(PermissionManager.class);
+ mPowerManager = targetContext.getSystemService(PowerManager.class);
when(mMockContext.getCacheDir())
.thenReturn(InstrumentationRegistry.getTargetContext().getCacheDir());
+ when(mMockContext.getUser())
+ .thenReturn(InstrumentationRegistry.getTargetContext().getUser());
+ when(mMockContext.getPackageName()).thenReturn("com.android.bluetooth");
when(mMockContext.getApplicationInfo()).thenReturn(mMockApplicationInfo);
when(mMockContext.getContentResolver()).thenReturn(mMockContentResolver);
when(mMockContext.getApplicationContext()).thenReturn(mMockContext);
@@ -182,12 +180,13 @@ public class AdapterServiceFactoryResetTest {
when(mMockContext.getUserId()).thenReturn(Process.BLUETOOTH_UID);
when(mMockContext.getPackageManager()).thenReturn(mMockPackageManager);
- mockGetSystemService(Context.ALARM_SERVICE, AlarmManager.class, mMockAlarmManager);
- mockGetSystemService(Context.APP_OPS_SERVICE, AppOpsManager.class, mMockAppOpsManager);
- mockGetSystemService(Context.AUDIO_SERVICE, AudioManager.class, mMockAudioManager);
- mockGetSystemService(
- Context.DEVICE_POLICY_SERVICE, DevicePolicyManager.class, mMockDevicePolicyManager);
- mockGetSystemService(Context.USER_SERVICE, UserManager.class, mMockUserManager);
+ mockGetSystemService(Context.ALARM_SERVICE, AlarmManager.class);
+ mockGetSystemService(Context.APP_OPS_SERVICE, AppOpsManager.class);
+ mockGetSystemService(Context.AUDIO_SERVICE, AudioManager.class);
+ DevicePolicyManager dpm =
+ mockGetSystemService(Context.DEVICE_POLICY_SERVICE, DevicePolicyManager.class);
+ doReturn(false).when(dpm).isCommonCriteriaModeEnabled(any());
+ mockGetSystemService(Context.USER_SERVICE, UserManager.class);
mockGetSystemService(
Context.BATTERY_STATS_SERVICE, BatteryStatsManager.class, mBatteryStatsManager);
@@ -196,6 +195,7 @@ public class AdapterServiceFactoryResetTest {
Context.COMPANION_DEVICE_SERVICE,
CompanionDeviceManager.class,
mCompanionDeviceManager);
+ mockGetSystemService(Context.DISPLAY_SERVICE, DisplayManager.class, mDisplayManager);
mockGetSystemService(
Context.PERMISSION_CHECKER_SERVICE,
PermissionCheckerManager.class,
@@ -221,8 +221,6 @@ public class AdapterServiceFactoryResetTest {
UserHandle callingUser = UserHandle.getUserHandleForUid(callingUid);
Utils.setForegroundUserId(callingUser.getIdentifier());
- when(mMockDevicePolicyManager.isCommonCriteriaModeEnabled(any())).thenReturn(false);
-
when(mIBluetoothCallback.asBinder()).thenReturn(mBinder);
doReturn(Process.BLUETOOTH_UID).when(mMockPackageManager)
diff --git a/android/app/tests/unit/src/com/android/bluetooth/btservice/AdapterServiceRestartTest.java b/android/app/tests/unit/src/com/android/bluetooth/btservice/AdapterServiceRestartTest.java
index 96ccb11add..e02a34d8d4 100644
--- a/android/app/tests/unit/src/com/android/bluetooth/btservice/AdapterServiceRestartTest.java
+++ b/android/app/tests/unit/src/com/android/bluetooth/btservice/AdapterServiceRestartTest.java
@@ -162,6 +162,9 @@ public class AdapterServiceRestartTest {
when(mMockContext.getCacheDir()).thenReturn(InstrumentationRegistry.getTargetContext()
.getCacheDir());
+ when(mMockContext.getUser())
+ .thenReturn(InstrumentationRegistry.getTargetContext().getUser());
+ when(mMockContext.getPackageName()).thenReturn("com.android.bluetooth");
when(mMockContext.getApplicationInfo()).thenReturn(mMockApplicationInfo);
when(mMockContext.getContentResolver()).thenReturn(mMockContentResolver);
when(mMockContext.getApplicationContext()).thenReturn(mMockContext);
diff --git a/android/app/tests/unit/src/com/android/bluetooth/btservice/AdapterServiceTest.java b/android/app/tests/unit/src/com/android/bluetooth/btservice/AdapterServiceTest.java
index 61aefd7b9f..db52e36d63 100644
--- a/android/app/tests/unit/src/com/android/bluetooth/btservice/AdapterServiceTest.java
+++ b/android/app/tests/unit/src/com/android/bluetooth/btservice/AdapterServiceTest.java
@@ -26,6 +26,7 @@ import static android.bluetooth.BluetoothAdapter.STATE_TURNING_OFF;
import static android.bluetooth.BluetoothAdapter.STATE_TURNING_ON;
import static com.google.common.truth.Truth.assertThat;
+import static com.google.common.truth.Truth.assertWithMessage;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.*;
@@ -43,6 +44,7 @@ import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.content.pm.PermissionInfo;
import android.content.res.Resources;
+import android.hardware.display.DisplayManager;
import android.media.AudioManager;
import android.os.BatteryStatsManager;
import android.os.Binder;
@@ -142,16 +144,10 @@ public class AdapterServiceTest {
private @Mock android.app.Application mApplication;
private @Mock MetricsLogger mMockMetricsLogger;
- // Mocked SystemService
- private @Mock AlarmManager mMockAlarmManager;
- private @Mock AppOpsManager mMockAppOpsManager;
- private @Mock AudioManager mMockAudioManager;
- private @Mock DevicePolicyManager mMockDevicePolicyManager;
- private @Mock UserManager mMockUserManager;
-
// SystemService that are not mocked
private BluetoothManager mBluetoothManager;
private CompanionDeviceManager mCompanionDeviceManager;
+ private DisplayManager mDisplayManager;
private PowerManager mPowerManager;
private PermissionCheckerManager mPermissionCheckerManager;
private PermissionManager mPermissionManager;
@@ -222,8 +218,11 @@ public class AdapterServiceTest {
}
<T> void mockGetSystemService(String serviceName, Class<T> serviceClass, T mockService) {
- when(mMockContext.getSystemService(eq(serviceName))).thenReturn(mockService);
- when(mMockContext.getSystemServiceName(eq(serviceClass))).thenReturn(serviceName);
+ TestUtils.mockGetSystemService(mMockContext, serviceName, serviceClass, mockService);
+ }
+
+ <T> T mockGetSystemService(String serviceName, Class<T> serviceClass) {
+ return TestUtils.mockGetSystemService(mMockContext, serviceName, serviceClass);
}
@Before
@@ -251,23 +250,20 @@ public class AdapterServiceTest {
}
});
- mPowerManager = InstrumentationRegistry.getTargetContext()
- .getSystemService(PowerManager.class);
- mPermissionCheckerManager = InstrumentationRegistry.getTargetContext()
- .getSystemService(PermissionCheckerManager.class);
-
- mPermissionManager = InstrumentationRegistry.getTargetContext()
- .getSystemService(PermissionManager.class);
+ Context targetContext = InstrumentationRegistry.getTargetContext();
- mBluetoothManager = InstrumentationRegistry.getTargetContext()
- .getSystemService(BluetoothManager.class);
-
- mCompanionDeviceManager =
- InstrumentationRegistry.getTargetContext()
- .getSystemService(CompanionDeviceManager.class);
+ mBluetoothManager = targetContext.getSystemService(BluetoothManager.class);
+ mCompanionDeviceManager = targetContext.getSystemService(CompanionDeviceManager.class);
+ mDisplayManager = targetContext.getSystemService(DisplayManager.class);
+ mPermissionCheckerManager = targetContext.getSystemService(PermissionCheckerManager.class);
+ mPermissionManager = targetContext.getSystemService(PermissionManager.class);
+ mPowerManager = targetContext.getSystemService(PowerManager.class);
when(mMockContext.getCacheDir()).thenReturn(InstrumentationRegistry.getTargetContext()
.getCacheDir());
+ when(mMockContext.getUser())
+ .thenReturn(InstrumentationRegistry.getTargetContext().getUser());
+ when(mMockContext.getPackageName()).thenReturn("com.android.bluetooth");
when(mMockContext.getApplicationInfo()).thenReturn(mMockApplicationInfo);
when(mMockContext.getContentResolver()).thenReturn(mMockContentResolver);
when(mMockContext.getApplicationContext()).thenReturn(mMockContext);
@@ -277,12 +273,13 @@ public class AdapterServiceTest {
when(mMockContext.getUserId()).thenReturn(Process.BLUETOOTH_UID);
when(mMockContext.getPackageManager()).thenReturn(mMockPackageManager);
- mockGetSystemService(Context.ALARM_SERVICE, AlarmManager.class, mMockAlarmManager);
- mockGetSystemService(Context.APP_OPS_SERVICE, AppOpsManager.class, mMockAppOpsManager);
- mockGetSystemService(Context.AUDIO_SERVICE, AudioManager.class, mMockAudioManager);
- mockGetSystemService(
- Context.DEVICE_POLICY_SERVICE, DevicePolicyManager.class, mMockDevicePolicyManager);
- mockGetSystemService(Context.USER_SERVICE, UserManager.class, mMockUserManager);
+ mockGetSystemService(Context.ALARM_SERVICE, AlarmManager.class);
+ mockGetSystemService(Context.APP_OPS_SERVICE, AppOpsManager.class);
+ mockGetSystemService(Context.AUDIO_SERVICE, AudioManager.class);
+ DevicePolicyManager dpm =
+ mockGetSystemService(Context.DEVICE_POLICY_SERVICE, DevicePolicyManager.class);
+ doReturn(false).when(dpm).isCommonCriteriaModeEnabled(any());
+ mockGetSystemService(Context.USER_SERVICE, UserManager.class);
mockGetSystemService(
Context.BATTERY_STATS_SERVICE, BatteryStatsManager.class, mBatteryStatsManager);
@@ -291,6 +288,7 @@ public class AdapterServiceTest {
Context.COMPANION_DEVICE_SERVICE,
CompanionDeviceManager.class,
mCompanionDeviceManager);
+ mockGetSystemService(Context.DISPLAY_SERVICE, DisplayManager.class, mDisplayManager);
mockGetSystemService(
Context.PERMISSION_CHECKER_SERVICE,
PermissionCheckerManager.class,
@@ -303,8 +301,6 @@ public class AdapterServiceTest {
.thenReturn(InstrumentationRegistry.getTargetContext()
.getSharedPreferences("AdapterServiceTestPrefs", Context.MODE_PRIVATE));
- doReturn(true).when(mMockContext).bindServiceAsUser(any(), any(), anyInt(), any());
-
doAnswer(invocation -> {
Object[] args = invocation.getArguments();
return InstrumentationRegistry.getTargetContext().getDatabasePath((String) args[0]);
@@ -316,8 +312,6 @@ public class AdapterServiceTest {
UserHandle callingUser = UserHandle.getUserHandleForUid(callingUid);
Utils.setForegroundUserId(callingUser.getIdentifier());
- when(mMockDevicePolicyManager.isCommonCriteriaModeEnabled(any())).thenReturn(false);
-
when(mIBluetoothCallback.asBinder()).thenReturn(mBinder);
doReturn(Process.BLUETOOTH_UID).when(mMockPackageManager)
@@ -367,14 +361,23 @@ public class AdapterServiceTest {
syncHandler(mLooper, what);
}
+ private void dropNextMessage(int what) {
+ Message msg = mLooper.nextMessage();
+ assertThat(msg).isNotNull();
+ assertWithMessage("Not the expected Message:\n" + msg).that(msg.what).isEqualTo(what);
+ Log.d(TAG, "Message dropped on purpose: " + msg);
+ }
+
private static void syncHandler(TestLooper looper, int... what) {
IntStream.of(what)
.forEach(
w -> {
Message msg = looper.nextMessage();
assertThat(msg).isNotNull();
- assertThat(msg.what).isEqualTo(w);
- Log.d(TAG, "Processing message: " + msg.what);
+ assertWithMessage("Not the expected Message:\n" + msg)
+ .that(msg.what)
+ .isEqualTo(w);
+ Log.d(TAG, "Processing message: " + msg);
msg.getTarget().dispatchMessage(msg);
});
}
@@ -422,12 +425,9 @@ public class AdapterServiceTest {
adapter.enable(false);
syncHandler(looper, AdapterState.BLE_TURN_ON);
verifyStateChange(callback, STATE_OFF, STATE_BLE_TURNING_ON);
- verify(ctx).bindServiceAsUser(any(), any(), anyInt(), any());
- adapter.addProfile(gattService);
syncHandler(looper, MESSAGE_PROFILE_SERVICE_REGISTERED);
- adapter.onProfileServiceStateChanged(gattService, STATE_ON);
syncHandler(looper, MESSAGE_PROFILE_SERVICE_STATE_CHANGED);
// Native loop is not in TestLooper and it will send a event later
@@ -550,9 +550,7 @@ public class AdapterServiceTest {
adapter.stopBle();
syncHandler(looper, AdapterState.BLE_TURN_OFF);
verifyStateChange(callback, STATE_BLE_ON, STATE_BLE_TURNING_OFF);
- verify(ctx).unbindService(any());
- adapter.onProfileServiceStateChanged(gattService, STATE_OFF);
syncHandler(looper, MESSAGE_PROFILE_SERVICE_STATE_CHANGED);
// Native loop is not in TestLooper and it will send a event later
@@ -630,14 +628,15 @@ public class AdapterServiceTest {
mAdapterService.enable(false);
syncHandler(AdapterState.BLE_TURN_ON);
verifyStateChange(STATE_OFF, STATE_BLE_TURNING_ON);
- verify(mMockContext).bindServiceAsUser(any(), any(), anyInt(), any());
-
- mAdapterService.addProfile(mMockGattService);
+ assertThat(mAdapterService.getBluetoothGatt()).isNotNull();
syncHandler(MESSAGE_PROFILE_SERVICE_REGISTERED);
+ // Fetch next message and never process it to simulate a timeout.
+ dropNextMessage(MESSAGE_PROFILE_SERVICE_STATE_CHANGED);
+
mLooper.moveTimeForward(120_000); // Skip time so the timeout fires
syncHandler(AdapterState.BLE_START_TIMEOUT);
- verify(mMockContext).unbindService(any());
+ assertThat(mAdapterService.getBluetoothGatt()).isNull();
// Native loop is not in TestLooper and it will send a event later
mLooper.startAutoDispatch();
@@ -666,7 +665,11 @@ public class AdapterServiceTest {
mAdapterService.stopBle();
syncHandler(AdapterState.BLE_TURN_OFF);
verifyStateChange(STATE_BLE_ON, STATE_BLE_TURNING_OFF, CONTEXT_SWITCH_MS);
- verify(mMockContext).unbindService(any()); // Stop GATT
+ assertThat(mAdapterService.getBluetoothGatt()).isNull();
+
+ // Fetch Gatt message and never process it to simulate a timeout.
+ dropNextMessage(MESSAGE_PROFILE_SERVICE_STATE_CHANGED);
+ dropNextMessage(MESSAGE_PROFILE_SERVICE_UNREGISTERED);
mLooper.moveTimeForward(120_000); // Skip time so the timeout fires
syncHandler(AdapterState.BLE_STOP_TIMEOUT);
@@ -711,7 +714,7 @@ public class AdapterServiceTest {
verifyStateChange(STATE_TURNING_OFF, STATE_BLE_ON);
// Ensure GATT is still running
- verify(mMockContext, times(0)).unbindService(any());
+ assertThat(mAdapterService.getBluetoothGatt()).isNotNull();
}
/**
@@ -735,10 +738,9 @@ public class AdapterServiceTest {
mLooper.moveTimeForward(120_000); // Skip time so the timeout fires
syncHandler(AdapterState.BREDR_STOP_TIMEOUT);
verifyStateChange(STATE_TURNING_OFF, STATE_BLE_TURNING_OFF);
- verify(mMockContext).unbindService(any());
- mAdapterService.onProfileServiceStateChanged(mMockGattService, STATE_OFF);
syncHandler(MESSAGE_PROFILE_SERVICE_STATE_CHANGED);
+ syncHandler(MESSAGE_PROFILE_SERVICE_UNREGISTERED);
// TODO(b/280518177): The only timeout to fire here should be the BREDR
mLooper.moveTimeForward(120_000); // Skip time so the timeout fires
@@ -778,10 +780,7 @@ public class AdapterServiceTest {
// Do not call stopBle(). The Adapter should turn itself off.
syncHandler(AdapterState.BLE_TURN_OFF);
verifyStateChange(STATE_BLE_ON, STATE_BLE_TURNING_OFF, CONTEXT_SWITCH_MS);
- verify(mMockContext).unbindService(any()); // stop Gatt
-
- mAdapterService.onProfileServiceStateChanged(mMockGattService, STATE_OFF);
- syncHandler(MESSAGE_PROFILE_SERVICE_STATE_CHANGED);
+ syncHandler(MESSAGE_PROFILE_SERVICE_STATE_CHANGED); // stop GATT
// Native loop is not in TestLooper and it will send a event later
mLooper.startAutoDispatch();
diff --git a/android/app/tests/unit/src/com/android/bluetooth/btservice/ProfileServiceTest.java b/android/app/tests/unit/src/com/android/bluetooth/btservice/ProfileServiceTest.java
index 4cc055e35d..15721bb004 100644
--- a/android/app/tests/unit/src/com/android/bluetooth/btservice/ProfileServiceTest.java
+++ b/android/app/tests/unit/src/com/android/bluetooth/btservice/ProfileServiceTest.java
@@ -16,6 +16,10 @@
package com.android.bluetooth.btservice;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyBoolean;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.*;
@@ -32,6 +36,7 @@ import androidx.test.runner.AndroidJUnit4;
import com.android.bluetooth.TestUtils;
import com.android.bluetooth.btservice.storage.DatabaseManager;
+import com.android.bluetooth.gatt.GattService;
import org.junit.After;
import org.junit.Assert;
@@ -78,7 +83,13 @@ public class ProfileServiceTest {
}
private void setAllProfilesState(int state, int invocationNumber) throws TimeoutException {
+ int profileCount = mProfiles.length;
for (Class profile : mProfiles) {
+ if (profile == GattService.class) {
+ // GattService is no longer a service to be start independently
+ profileCount--;
+ continue;
+ }
setProfileState(profile, state);
}
if (invocationNumber == 0) {
@@ -87,11 +98,15 @@ public class ProfileServiceTest {
return;
}
ArgumentCaptor<ProfileService> argument = ArgumentCaptor.forClass(ProfileService.class);
- verify(mMockAdapterService, timeout(PROFILE_START_MILLIS).times(
- mProfiles.length * invocationNumber)).onProfileServiceStateChanged(
- argument.capture(), eq(state));
+ verify(
+ mMockAdapterService,
+ timeout(PROFILE_START_MILLIS).times(profileCount * invocationNumber))
+ .onProfileServiceStateChanged(argument.capture(), eq(state));
List<ProfileService> argumentProfiles = argument.getAllValues();
for (Class profile : mProfiles) {
+ if (profile == GattService.class) {
+ continue;
+ }
int matches = 0;
for (ProfileService arg : argumentProfiles) {
if (arg.getClass().getName().equals(profile.getName())) {
@@ -118,27 +133,41 @@ public class ProfileServiceTest {
return mStartedProfileMap.get((String) args[0]);
}
});
+ doReturn(mDatabaseManager).when(mMockAdapterService).getDatabase();
+
when(mMockAdapterService.getSystemService(Context.LOCATION_SERVICE))
.thenReturn(mLocationManager);
when(mMockAdapterService.getSystemServiceName(LocationManager.class))
.thenReturn(Context.LOCATION_SERVICE);
+ // Despite calling on the Mock of adapterService, mockito cannot handle native method and
+ // will call the real method instead, allowing to initialize the native library
+ // when(mMockAdapterService.initNative(anyBoolean(), anyBoolean(), anyInt(), any(),
+ // anyBoolean(), anyString())).thenCallRealMethod();
+ doCallRealMethod()
+ .when(mMockAdapterService)
+ .initNative(anyBoolean(), anyBoolean(), anyInt(), any(), anyBoolean(), anyString());
+ doCallRealMethod().when(mMockAdapterService).enableNative();
+ doCallRealMethod().when(mMockAdapterService).disableNative();
+ doCallRealMethod().when(mMockAdapterService).cleanupNative();
+
mProfiles = Config.getSupportedProfiles();
+ TestUtils.setAdapterService(mMockAdapterService);
+
+ Assert.assertNotNull(AdapterService.getAdapterService());
mMockAdapterService.initNative(false /* is_restricted */,
false /* is_common_criteria_mode */, 0 /* config_compare_result */,
new String[0], false, "");
-
- TestUtils.setAdapterService(mMockAdapterService);
- doReturn(mDatabaseManager).when(mMockAdapterService).getDatabase();
-
- Assert.assertNotNull(AdapterService.getAdapterService());
+ mMockAdapterService.enableNative();
}
@After
public void tearDown()
throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
+ mMockAdapterService.disableNative();
mMockAdapterService.cleanupNative();
+
TestUtils.clearAdapterService(mMockAdapterService);
mMockAdapterService = null;
mProfiles = null;
@@ -172,13 +201,18 @@ public class ProfileServiceTest {
*/
@Test
public void testEnableDisableInterleaved() throws TimeoutException {
+ int invocationNumber = mProfiles.length;
for (Class profile : mProfiles) {
+ if (profile == GattService.class) {
+ // GattService is no longer a service to be start independently
+ invocationNumber--;
+ continue;
+ }
setProfileState(profile, BluetoothAdapter.STATE_ON);
setProfileState(profile, BluetoothAdapter.STATE_OFF);
}
ArgumentCaptor<ProfileService> starts = ArgumentCaptor.forClass(ProfileService.class);
ArgumentCaptor<ProfileService> stops = ArgumentCaptor.forClass(ProfileService.class);
- int invocationNumber = mProfiles.length;
verify(mMockAdapterService,
timeout(PROFILE_START_MILLIS).times(invocationNumber)).onProfileServiceStateChanged(
starts.capture(), eq(BluetoothAdapter.STATE_ON));
@@ -204,6 +238,10 @@ public class ProfileServiceTest {
public void testRepeatedEnableDisableSingly() throws TimeoutException {
int profileNumber = 0;
for (Class profile : mProfiles) {
+ if (profile == GattService.class) {
+ // GattService is no longer a service to be start independently
+ continue;
+ }
for (int i = 0; i < NUM_REPEATS; i++) {
setProfileState(profile, BluetoothAdapter.STATE_ON);
ArgumentCaptor<ProfileService> start =
@@ -230,6 +268,10 @@ public class ProfileServiceTest {
public void testProfileServiceRegisterUnregister() throws TimeoutException {
int profileNumber = 0;
for (Class profile : mProfiles) {
+ if (profile == GattService.class) {
+ // GattService is no longer a service to be start independently
+ continue;
+ }
for (int i = 0; i < NUM_REPEATS; i++) {
setProfileState(profile, BluetoothAdapter.STATE_ON);
ArgumentCaptor<ProfileService> start =
diff --git a/android/app/tests/unit/src/com/android/bluetooth/gatt/AppScanStatsTest.java b/android/app/tests/unit/src/com/android/bluetooth/gatt/AppScanStatsTest.java
index 359ad3104e..b1bed3da63 100644
--- a/android/app/tests/unit/src/com/android/bluetooth/gatt/AppScanStatsTest.java
+++ b/android/app/tests/unit/src/com/android/bluetooth/gatt/AppScanStatsTest.java
@@ -18,9 +18,6 @@ package com.android.bluetooth.gatt;
import static com.google.common.truth.Truth.assertThat;
-import static org.mockito.ArgumentMatchers.anyString;
-import static org.mockito.Mockito.doReturn;
-import static org.mockito.Mockito.when;
import android.bluetooth.le.ScanFilter;
import android.bluetooth.le.ScanSettings;
@@ -28,6 +25,7 @@ import android.content.Context;
import android.location.LocationManager;
import android.os.WorkSource;
+import androidx.test.InstrumentationRegistry;
import androidx.test.filters.SmallTest;
import androidx.test.rule.ServiceTestRule;
import androidx.test.runner.AndroidJUnit4;
@@ -64,28 +62,23 @@ public class AppScanStatsTest {
@Mock
private AdapterService mAdapterService;
- @Mock private LocationManager mLocationManager;
-
@Before
public void setUp() throws Exception {
MockitoAnnotations.initMocks(this);
TestUtils.setAdapterService(mAdapterService);
- doReturn(true).when(mAdapterService).isStartedProfile(anyString());
- when(mAdapterService.getSystemService(Context.LOCATION_SERVICE))
- .thenReturn(mLocationManager);
- when(mAdapterService.getSystemServiceName(LocationManager.class))
- .thenReturn(Context.LOCATION_SERVICE);
-
- TestUtils.startService(mServiceRule, GattService.class);
- mService = GattService.getGattService();
+
+ TestUtils.mockGetSystemService(
+ mAdapterService, Context.LOCATION_SERVICE, LocationManager.class);
+
+ mService = new GattService(InstrumentationRegistry.getTargetContext());
+ mService.start();
}
@After
public void tearDown() throws Exception {
- doReturn(false).when(mAdapterService).isStartedProfile(anyString());
- TestUtils.stopService(mServiceRule, GattService.class);
- mService = GattService.getGattService();
+ mService.stop();
+ mService = null;
TestUtils.clearAdapterService(mAdapterService);
}
diff --git a/android/app/tests/unit/src/com/android/bluetooth/gatt/ContextMapTest.java b/android/app/tests/unit/src/com/android/bluetooth/gatt/ContextMapTest.java
index 3ff84eea8d..e391a38c95 100644
--- a/android/app/tests/unit/src/com/android/bluetooth/gatt/ContextMapTest.java
+++ b/android/app/tests/unit/src/com/android/bluetooth/gatt/ContextMapTest.java
@@ -18,10 +18,8 @@ package com.android.bluetooth.gatt;
import static com.google.common.truth.Truth.assertThat;
-import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
import android.bluetooth.le.AdvertiseData;
import android.bluetooth.le.AdvertisingSetParameters;
@@ -30,6 +28,7 @@ import android.content.Context;
import android.location.LocationManager;
import android.os.Binder;
+import androidx.test.InstrumentationRegistry;
import androidx.test.filters.SmallTest;
import androidx.test.rule.ServiceTestRule;
import androidx.test.runner.AndroidJUnit4;
@@ -64,8 +63,6 @@ public class ContextMapTest {
@Mock
private AdapterService mAdapterService;
- @Mock private LocationManager mLocationManager;
-
@Mock
private AppAdvertiseStats appAdvertiseStats;
@@ -78,23 +75,20 @@ public class ContextMapTest {
BluetoothMethodProxy.setInstanceForTesting(mMapMethodProxy);
TestUtils.setAdapterService(mAdapterService);
- doReturn(true).when(mAdapterService).isStartedProfile(anyString());
- when(mAdapterService.getSystemService(Context.LOCATION_SERVICE))
- .thenReturn(mLocationManager);
- when(mAdapterService.getSystemServiceName(LocationManager.class))
- .thenReturn(Context.LOCATION_SERVICE);
-
- TestUtils.startService(mServiceRule, GattService.class);
- mService = GattService.getGattService();
+
+ TestUtils.mockGetSystemService(
+ mAdapterService, Context.LOCATION_SERVICE, LocationManager.class);
+
+ mService = new GattService(InstrumentationRegistry.getTargetContext());
+ mService.start();
}
@After
public void tearDown() throws Exception {
BluetoothMethodProxy.setInstanceForTesting(null);
- doReturn(false).when(mAdapterService).isStartedProfile(anyString());
- TestUtils.stopService(mServiceRule, GattService.class);
- mService = GattService.getGattService();
+ mService.stop();
+ mService = null;
TestUtils.clearAdapterService(mAdapterService);
}
diff --git a/android/app/tests/unit/src/com/android/bluetooth/gatt/GattServiceBinderTest.java b/android/app/tests/unit/src/com/android/bluetooth/gatt/GattServiceBinderTest.java
index 714e911a41..1c1fda0007 100644
--- a/android/app/tests/unit/src/com/android/bluetooth/gatt/GattServiceBinderTest.java
+++ b/android/app/tests/unit/src/com/android/bluetooth/gatt/GattServiceBinderTest.java
@@ -756,13 +756,6 @@ public class GattServiceBinderTest {
}
@Test
- public void unregAll() throws Exception {
- mBinder.unregAll(mAttributionSource);
-
- verify(mService).unregAll(mAttributionSource);
- }
-
- @Test
public void numHwTrackFiltersAvailable() throws Exception {
mBinder.numHwTrackFiltersAvailable(mAttributionSource, SynchronousResultReceiver.get());
diff --git a/android/app/tests/unit/src/com/android/bluetooth/gatt/GattServiceTest.java b/android/app/tests/unit/src/com/android/bluetooth/gatt/GattServiceTest.java
index bf3c8364a9..6d092c0787 100644
--- a/android/app/tests/unit/src/com/android/bluetooth/gatt/GattServiceTest.java
+++ b/android/app/tests/unit/src/com/android/bluetooth/gatt/GattServiceTest.java
@@ -25,21 +25,17 @@ import static org.mockito.Mockito.verify;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothGatt;
-import android.bluetooth.BluetoothGattService;
import android.bluetooth.BluetoothProfile;
import android.bluetooth.BluetoothStatusCodes;
import android.bluetooth.IBluetoothGattCallback;
-import android.bluetooth.IBluetoothGattServerCallback;
import android.bluetooth.le.AdvertiseData;
import android.bluetooth.le.AdvertisingSetParameters;
import android.bluetooth.le.DistanceMeasurementMethod;
import android.bluetooth.le.DistanceMeasurementParams;
-import android.bluetooth.le.IAdvertisingSetCallback;
import android.bluetooth.le.IDistanceMeasurementCallback;
import android.bluetooth.le.IPeriodicAdvertisingCallback;
import android.bluetooth.le.IScannerCallback;
import android.bluetooth.le.PeriodicAdvertisingParameters;
-import android.bluetooth.le.ScanFilter;
import android.bluetooth.le.ScanResult;
import android.bluetooth.le.ScanSettings;
import android.content.AttributionSource;
@@ -47,7 +43,6 @@ import android.content.Context;
import android.content.res.Resources;
import android.location.LocationManager;
import android.os.Binder;
-import android.os.ParcelUuid;
import android.os.RemoteException;
import android.os.WorkSource;
@@ -56,14 +51,12 @@ import androidx.test.filters.SmallTest;
import androidx.test.rule.ServiceTestRule;
import androidx.test.runner.AndroidJUnit4;
-import com.android.bluetooth.R;
import com.android.bluetooth.TestUtils;
import com.android.bluetooth.btservice.AdapterService;
import com.android.bluetooth.btservice.CompanionManager;
import org.junit.After;
import org.junit.Assert;
-import org.junit.Assume;
import org.junit.Before;
import org.junit.Ignore;
import org.junit.Rule;
@@ -102,7 +95,6 @@ public class GattServiceTest {
@Mock private Set<String> mReliableQueue;
@Mock private GattService.ServerMap mServerMap;
@Mock private DistanceMeasurementManager mDistanceMeasurementManager;
- @Mock private LocationManager mLocationManager;
@Rule public final ServiceTestRule mServiceRule = new ServiceTestRule();
@@ -123,7 +115,6 @@ public class GattServiceTest {
MockitoAnnotations.initMocks(this);
TestUtils.setAdapterService(mAdapterService);
- doReturn(true).when(mAdapterService).isStartedProfile(anyString());
GattObjectsFactory.setInstanceForTesting(mFactory);
doReturn(mNativeInterface).when(mFactory).getNativeInterface();
@@ -141,17 +132,15 @@ public class GattServiceTest {
when(mAdapterService.getSharedPreferences(anyString(), anyInt()))
.thenReturn(InstrumentationRegistry.getTargetContext()
.getSharedPreferences("GattServiceTestPrefs", Context.MODE_PRIVATE));
- when(mAdapterService.getSystemService(Context.LOCATION_SERVICE))
- .thenReturn(mLocationManager);
- when(mAdapterService.getSystemServiceName(LocationManager.class))
- .thenReturn(Context.LOCATION_SERVICE);
+
+ TestUtils.mockGetSystemService(
+ mAdapterService, Context.LOCATION_SERVICE, LocationManager.class);
mBtCompanionManager = new CompanionManager(mAdapterService, null);
doReturn(mBtCompanionManager).when(mAdapterService).getCompanionManager();
- TestUtils.startService(mServiceRule, GattService.class);
- mService = GattService.getGattService();
- Assert.assertNotNull(mService);
+ mService = new GattService(InstrumentationRegistry.getTargetContext());
+ mService.start();
mService.mClientMap = mClientMap;
mService.mScannerMap = mScannerMap;
@@ -161,40 +150,25 @@ public class GattServiceTest {
@After
public void tearDown() throws Exception {
- doReturn(false).when(mAdapterService).isStartedProfile(anyString());
- TestUtils.stopService(mServiceRule, GattService.class);
- mService = GattService.getGattService();
- Assert.assertNull(mService);
+ mService.stop();
+ mService = null;
+
TestUtils.clearAdapterService(mAdapterService);
GattObjectsFactory.setInstanceForTesting(null);
}
@Test
- public void testInitialize() {
- Assert.assertEquals(mService, GattService.getGattService());
- verify(mNativeInterface).init(eq(mService));
- }
-
- @Test
public void testServiceUpAndDown() throws Exception {
for (int i = 0; i < TIMES_UP_AND_DOWN; i++) {
- GattService gattService = GattService.getGattService();
- doReturn(false).when(mAdapterService).isStartedProfile(anyString());
- TestUtils.stopService(mServiceRule, GattService.class);
- mService = GattService.getGattService();
- Assert.assertNull(mService);
- gattService.cleanup();
+ mService.stop();
+ mService = null;
+
TestUtils.clearAdapterService(mAdapterService);
reset(mAdapterService);
TestUtils.setAdapterService(mAdapterService);
- doReturn(true).when(mAdapterService).isStartedProfile(anyString());
- when(mAdapterService.getSystemService(Context.LOCATION_SERVICE))
- .thenReturn(mLocationManager);
- when(mAdapterService.getSystemServiceName(LocationManager.class))
- .thenReturn(Context.LOCATION_SERVICE);
- TestUtils.startService(mServiceRule, GattService.class);
- mService = GattService.getGattService();
- Assert.assertNotNull(mService);
+
+ mService = new GattService(InstrumentationRegistry.getTargetContext());
+ mService.start();
}
}
diff --git a/android/app/tests/unit/src/com/android/bluetooth/gatt/ScanManagerTest.java b/android/app/tests/unit/src/com/android/bluetooth/gatt/ScanManagerTest.java
index 9f6961e206..42d26f77b0 100644
--- a/android/app/tests/unit/src/com/android/bluetooth/gatt/ScanManagerTest.java
+++ b/android/app/tests/unit/src/com/android/bluetooth/gatt/ScanManagerTest.java
@@ -29,7 +29,6 @@ import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.anyLong;
-import static org.mockito.Mockito.anyString;
import static org.mockito.Mockito.atLeastOnce;
import static org.mockito.Mockito.atMost;
import static org.mockito.Mockito.doReturn;
@@ -118,17 +117,15 @@ public class ScanManagerTest {
MockitoAnnotations.initMocks(this);
TestUtils.setAdapterService(mAdapterService);
- doReturn(true).when(mAdapterService).isStartedProfile(anyString());
when(mAdapterService.getScanTimeoutMillis()).
thenReturn((long) DELAY_DEFAULT_SCAN_TIMEOUT_MS);
when(mAdapterService.getNumOfOffloadedScanFilterSupported())
.thenReturn(DEFAULT_NUM_OFFLOAD_SCAN_FILTER);
when(mAdapterService.getOffloadedScanResultStorage())
.thenReturn(DEFAULT_BYTES_OFFLOAD_SCAN_RESULT_STORAGE);
- when(mAdapterService.getSystemService(Context.LOCATION_SERVICE))
- .thenReturn(mLocationManager);
- when(mAdapterService.getSystemServiceName(LocationManager.class))
- .thenReturn(Context.LOCATION_SERVICE);
+
+ TestUtils.mockGetSystemService(
+ mAdapterService, Context.LOCATION_SERVICE, LocationManager.class, mLocationManager);
doReturn(true).when(mLocationManager).isLocationEnabled();
BluetoothAdapterProxy.setInstanceForTesting(mBluetoothAdapterProxy);
@@ -143,9 +140,8 @@ public class ScanManagerTest {
MetricsLogger.setInstanceForTesting(mMetricsLogger);
- TestUtils.startService(mServiceRule, GattService.class);
- mService = GattService.getGattService();
- assertThat(mService).isNotNull();
+ mService = new GattService(InstrumentationRegistry.getTargetContext());
+ mService.start();
mScanManager = mService.getScanManager();
assertThat(mScanManager).isNotNull();
@@ -161,10 +157,9 @@ public class ScanManagerTest {
@After
public void tearDown() throws Exception {
- doReturn(false).when(mAdapterService).isStartedProfile(anyString());
- TestUtils.stopService(mServiceRule, GattService.class);
- mService = GattService.getGattService();
- assertThat(mService).isNull();
+ mService.stop();
+ mService = null;
+
TestUtils.clearAdapterService(mAdapterService);
BluetoothAdapterProxy.setInstanceForTesting(null);
GattObjectsFactory.setInstanceForTesting(null);
diff --git a/system/binder/android/bluetooth/IBluetoothGatt.aidl b/system/binder/android/bluetooth/IBluetoothGatt.aidl
index 221deaa7b1..8c5305e02a 100644
--- a/system/binder/android/bluetooth/IBluetoothGatt.aidl
+++ b/system/binder/android/bluetooth/IBluetoothGatt.aidl
@@ -47,11 +47,6 @@ import com.android.modules.utils.SynchronousResultReceiver;
*/
oneway interface IBluetoothGatt {
@JavaPassthrough(annotation="@android.annotation.RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)")
- void startService();
- @JavaPassthrough(annotation="@android.annotation.RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)")
- void stopService();
-
- @JavaPassthrough(annotation="@android.annotation.RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)")
void getDevicesMatchingConnectionStates(in int[] states, in AttributionSource attributionSource, in SynchronousResultReceiver receiver);
@JavaPassthrough(annotation="@android.annotation.RequiresPermission(android.Manifest.permission.BLUETOOTH_SCAN)")
@@ -181,8 +176,6 @@ oneway interface IBluetoothGatt {
@JavaPassthrough(annotation="@android.annotation.RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)")
void disconnectAll(in AttributionSource attributionSource, in SynchronousResultReceiver receiver);
@JavaPassthrough(annotation="@android.annotation.RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)")
- void unregAll(in AttributionSource attributionSource);
- @JavaPassthrough(annotation="@android.annotation.RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)")
void numHwTrackFiltersAvailable(in AttributionSource attributionSource, in SynchronousResultReceiver receiver);
@JavaPassthrough(annotation="@android.annotation.RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)")
void leSubrateRequest(in int clientIf, in String address, in int subrateMin, in int subrateMax, in int maxLatency,