diff options
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, |