diff options
192 files changed, 3257 insertions, 2204 deletions
diff --git a/TEST_MAPPING b/TEST_MAPPING index 8f167cf47b..e5812efb4f 100644 --- a/TEST_MAPPING +++ b/TEST_MAPPING @@ -333,6 +333,9 @@ "name": "CtsStrictJavaPackagesTestCases" }, { + "name": "net_test_bta_jv" + }, + { "name": "asrc_resampler_test" } ] diff --git a/android/app/jni/com_android_bluetooth_gatt.cpp b/android/app/jni/com_android_bluetooth_gatt.cpp index aaf908a798..95a90f3c58 100644 --- a/android/app/jni/com_android_bluetooth_gatt.cpp +++ b/android/app/jni/com_android_bluetooth_gatt.cpp @@ -2827,10 +2827,10 @@ static int register_com_android_bluetooth_gatt_(JNIEnv* env) { &method_onBatchScanThresholdCrossed}, {"createOnTrackAdvFoundLostObject", "(II[BI[BIIILjava/lang/String;IIII)" - "Lcom/android/bluetooth/gatt/AdvtFilterOnFoundOnLostInfo;", + "Lcom/android/bluetooth/le_scan/AdvtFilterOnFoundOnLostInfo;", &method_createOnTrackAdvFoundLostObject}, {"onTrackAdvFoundLost", - "(Lcom/android/bluetooth/gatt/AdvtFilterOnFoundOnLostInfo;)V", + "(Lcom/android/bluetooth/le_scan/AdvtFilterOnFoundOnLostInfo;)V", &method_onTrackAdvFoundLost}, {"onScanParamSetupCompleted", "(II)V", &method_onScanParamSetupCompleted}, {"getSampleGattDbElement", "()Lcom/android/bluetooth/gatt/GattDbElement;", diff --git a/android/app/src/com/android/bluetooth/gatt/CallbackInfo.java b/android/app/src/com/android/bluetooth/gatt/CallbackInfo.java index ab3fe4ea4b..be01605b24 100644 --- a/android/app/src/com/android/bluetooth/gatt/CallbackInfo.java +++ b/android/app/src/com/android/bluetooth/gatt/CallbackInfo.java @@ -16,11 +16,12 @@ package com.android.bluetooth.gatt; /** - * Helper class that keeps track of callback parameters for app callbacks. - * These are held during congestion and reported when congestion clears. + * Helper class that keeps track of callback parameters for app callbacks. These are held during + * congestion and reported when congestion clears. + * * @hide */ -/* package */ class CallbackInfo { +public class CallbackInfo { public String address; public int status; public int handle; diff --git a/android/app/src/com/android/bluetooth/gatt/ContextMap.java b/android/app/src/com/android/bluetooth/gatt/ContextMap.java index 3457ed7e59..7492f8a139 100644 --- a/android/app/src/com/android/bluetooth/gatt/ContextMap.java +++ b/android/app/src/com/android/bluetooth/gatt/ContextMap.java @@ -18,6 +18,7 @@ package com.android.bluetooth.gatt; import android.bluetooth.le.AdvertiseData; import android.bluetooth.le.AdvertisingSetParameters; import android.bluetooth.le.PeriodicAdvertisingParameters; +import android.content.Context; import android.os.Binder; import android.os.IBinder; import android.os.IInterface; @@ -27,10 +28,11 @@ import android.os.UserHandle; import android.os.WorkSource; import android.util.Log; -import androidx.annotation.VisibleForTesting; import com.android.bluetooth.BluetoothMethodProxy; import com.android.bluetooth.le_scan.AppScanStats; +import com.android.bluetooth.le_scan.TransitionalScanHelper; +import com.android.bluetooth.le_scan.TransitionalScanHelper.PendingIntentInfo; import com.android.internal.annotations.GuardedBy; import com.google.common.collect.EvictingQueue; @@ -98,27 +100,27 @@ public class ContextMap<C, T> { public Boolean isCongested = false; /** Whether the calling app has location permission */ - boolean hasLocationPermission; + public boolean hasLocationPermission; /** Whether the calling app has bluetooth privileged permission */ - boolean hasBluetoothPrivilegedPermission; + public boolean hasBluetoothPrivilegedPermission; /** The user handle of the app that started the scan */ - UserHandle mUserHandle; + public UserHandle mUserHandle; /** Whether the calling app has the network settings permission */ - boolean mHasNetworkSettingsPermission; + public boolean mHasNetworkSettingsPermission; /** Whether the calling app has the network setup wizard permission */ - boolean mHasNetworkSetupWizardPermission; + public boolean mHasNetworkSetupWizardPermission; /** Whether the calling app has the network setup wizard permission */ - boolean mHasScanWithoutLocationPermission; + public boolean mHasScanWithoutLocationPermission; /** Whether the calling app has disavowed the use of bluetooth for location */ - boolean mHasDisavowedLocation; + public boolean mHasDisavowedLocation; - boolean mEligibleForSanitizedExposureNotification; + public boolean mEligibleForSanitizedExposureNotification; public List<String> mAssociatedDevices; @@ -145,10 +147,8 @@ public class ContextMap<C, T> { this.name = name; } - /** - * Link death recipient - */ - void linkToDeath(IBinder.DeathRecipient deathRecipient) { + /** Link death recipient */ + public void linkToDeath(IBinder.DeathRecipient deathRecipient) { // It might not be a binder object if (callback == null) { return; @@ -162,10 +162,8 @@ public class ContextMap<C, T> { } } - /** - * Unlink death recipient - */ - void unlinkToDeath() { + /** Unlink death recipient */ + public void unlinkToDeath() { if (mDeathRecipient != null) { try { IBinder binder = ((IInterface) callback).asBinder(); @@ -176,11 +174,11 @@ public class ContextMap<C, T> { } } - void queueCallback(CallbackInfo callbackInfo) { + public void queueCallback(CallbackInfo callbackInfo) { mCongestionQueue.add(callbackInfo); } - CallbackInfo popQueuedCallback() { + public CallbackInfo popQueuedCallback() { if (mCongestionQueue.size() == 0) { return null; } @@ -210,12 +208,13 @@ public class ContextMap<C, T> { private final Object mConnectionsLock = new Object(); /** Add an entry to the application context list. */ - protected App add( + public App add( UUID uuid, WorkSource workSource, C callback, - GattService.PendingIntentInfo piInfo, - GattService service) { + PendingIntentInfo piInfo, + Context context, + TransitionalScanHelper scanHelper) { int appUid; String appName = null; if (piInfo != null) { @@ -223,16 +222,18 @@ public class ContextMap<C, T> { appName = piInfo.callingPackage; } else { appUid = Binder.getCallingUid(); - appName = service.getPackageManager().getNameForUid(appUid); + appName = context.getPackageManager().getNameForUid(appUid); } if (appName == null) { // Assign an app name if one isn't found appName = "Unknown App (UID: " + appUid + ")"; } synchronized (mAppsLock) { + // TODO(b/327849650): AppScanStats appears to be only needed for the ScannerMap. + // Consider refactoring this. AppScanStats appScanStats = mAppScanStats.get(appUid); if (appScanStats == null) { - appScanStats = new AppScanStats(appName, workSource, this, service); + appScanStats = new AppScanStats(appName, workSource, this, context, scanHelper); mAppScanStats.put(appUid, appScanStats); } App app = new App(uuid, callback, (T) piInfo, appName, appScanStats); @@ -242,10 +243,8 @@ public class ContextMap<C, T> { } } - /** - * Add an entry to the application context list for advertiser. - */ - App add(int id, C callback, GattService service) { + /** Add an entry to the application context list for advertiser. */ + public App add(int id, C callback, GattService service) { int appUid = Binder.getCallingUid(); String appName = service.getPackageManager().getNameForUid(appUid); if (appName == null) { @@ -270,10 +269,8 @@ public class ContextMap<C, T> { } } - /** - * Remove the context for a given UUID - */ - void remove(UUID uuid) { + /** Remove the context for a given UUID */ + public void remove(UUID uuid) { synchronized (mAppsLock) { Iterator<App> i = mApps.iterator(); while (i.hasNext()) { @@ -288,10 +285,8 @@ public class ContextMap<C, T> { } } - /** - * Remove the context for a given application ID. - */ - protected void remove(int id) { + /** Remove the context for a given application ID. */ + public void remove(int id) { boolean find = false; synchronized (mAppsLock) { Iterator<App> i = mApps.iterator(); @@ -311,7 +306,7 @@ public class ContextMap<C, T> { } } - protected List<Integer> getAllAppsIds() { + public List<Integer> getAllAppsIds() { List<Integer> appIds = new ArrayList(); synchronized (mAppsLock) { Iterator<App> i = mApps.iterator(); @@ -366,10 +361,8 @@ public class ContextMap<C, T> { } } - /** - * Get an application context by ID. - */ - protected App getById(int id) { + /** Get an application context by ID. */ + public App getById(int id) { synchronized (mAppsLock) { Iterator<App> i = mApps.iterator(); while (i.hasNext()) { @@ -383,10 +376,8 @@ public class ContextMap<C, T> { return null; } - /** - * Get an application context by UUID. - */ - protected App getByUuid(UUID uuid) { + /** Get an application context by UUID. */ + public App getByUuid(UUID uuid) { synchronized (mAppsLock) { Iterator<App> i = mApps.iterator(); while (i.hasNext()) { @@ -417,10 +408,8 @@ public class ContextMap<C, T> { return null; } - /** - * Get an application context by the context info object. - */ - protected App getByContextInfo(T contextInfo) { + /** Get an application context by the context info object. */ + public App getByContextInfo(T contextInfo) { synchronized (mAppsLock) { Iterator<App> i = mApps.iterator(); while (i.hasNext()) { @@ -434,10 +423,8 @@ public class ContextMap<C, T> { return null; } - /** - * Get Logging info by ID - */ - protected AppScanStats getAppScanStatsById(int id) { + /** Get Logging info by ID */ + public AppScanStats getAppScanStatsById(int id) { App temp = getById(id); if (temp != null) { return temp.appScanStats; @@ -670,10 +657,8 @@ public class ContextMap<C, T> { return currentConnections; } - /** - * Erases all application context entries. - */ - protected void clear() { + /** Erases all application context entries. */ + public void clear() { synchronized (mAppsLock) { Iterator<App> i = mApps.iterator(); while (i.hasNext()) { diff --git a/android/app/src/com/android/bluetooth/gatt/GattNativeInterface.java b/android/app/src/com/android/bluetooth/gatt/GattNativeInterface.java index 9c8fa539d5..1167bea931 100644 --- a/android/app/src/com/android/bluetooth/gatt/GattNativeInterface.java +++ b/android/app/src/com/android/bluetooth/gatt/GattNativeInterface.java @@ -18,6 +18,8 @@ package com.android.bluetooth.gatt; import android.os.RemoteException; +import com.android.bluetooth.le_scan.AdvtFilterOnFoundOnLostInfo; +import com.android.bluetooth.le_scan.TransitionalScanHelper; import com.android.internal.annotations.GuardedBy; import com.android.internal.annotations.VisibleForTesting; @@ -70,13 +72,24 @@ public class GattNativeInterface { void onScanResult(int eventType, int addressType, String address, int primaryPhy, int secondaryPhy, int advertisingSid, int txPower, int rssi, int periodicAdvInt, byte[] advData, String originalAddress) { - getGattService().onScanResult(eventType, addressType, address, primaryPhy, secondaryPhy, - advertisingSid, txPower, rssi, periodicAdvInt, advData, originalAddress); + getTransitionalScanHelper() + .onScanResult( + eventType, + addressType, + address, + primaryPhy, + secondaryPhy, + advertisingSid, + txPower, + rssi, + periodicAdvInt, + advData, + originalAddress); } void onScannerRegistered(int status, int scannerId, long uuidLsb, long uuidMsb) throws RemoteException { - getGattService().onScannerRegistered(status, scannerId, uuidLsb, uuidMsb); + getTransitionalScanHelper().onScannerRegistered(status, scannerId, uuidLsb, uuidMsb); } void onClientRegistered(int status, int clientIf, long uuidLsb, long uuidMsb) @@ -187,50 +200,65 @@ public class GattNativeInterface { } void onScanFilterEnableDisabled(int action, int status, int clientIf) { - getGattService().onScanFilterEnableDisabled(action, status, clientIf); + getTransitionalScanHelper().onScanFilterEnableDisabled(action, status, clientIf); } void onScanFilterParamsConfigured(int action, int status, int clientIf, int availableSpace) { - getGattService().onScanFilterParamsConfigured(action, status, clientIf, availableSpace); + getTransitionalScanHelper() + .onScanFilterParamsConfigured(action, status, clientIf, availableSpace); } void onScanFilterConfig(int action, int status, int clientIf, int filterType, int availableSpace) { - getGattService().onScanFilterConfig(action, status, clientIf, filterType, availableSpace); + getTransitionalScanHelper() + .onScanFilterConfig(action, status, clientIf, filterType, availableSpace); } void onBatchScanStorageConfigured(int status, int clientIf) { - getGattService().onBatchScanStorageConfigured(status, clientIf); + getTransitionalScanHelper().onBatchScanStorageConfigured(status, clientIf); } void onBatchScanStartStopped(int startStopAction, int status, int clientIf) { - getGattService().onBatchScanStartStopped(startStopAction, status, clientIf); + getTransitionalScanHelper().onBatchScanStartStopped(startStopAction, status, clientIf); } void onBatchScanReports(int status, int scannerId, int reportType, int numRecords, byte[] recordData) throws RemoteException { - getGattService().onBatchScanReports(status, scannerId, reportType, numRecords, recordData); + getTransitionalScanHelper() + .onBatchScanReports(status, scannerId, reportType, numRecords, recordData); } void onBatchScanThresholdCrossed(int clientIf) { - getGattService().onBatchScanThresholdCrossed(clientIf); + getTransitionalScanHelper().onBatchScanThresholdCrossed(clientIf); } AdvtFilterOnFoundOnLostInfo createOnTrackAdvFoundLostObject(int clientIf, int advPktLen, byte[] advPkt, int scanRspLen, byte[] scanRsp, int filtIndex, int advState, int advInfoPresent, String address, int addrType, int txPower, int rssiValue, int timeStamp) { - return getGattService().createOnTrackAdvFoundLostObject(clientIf, advPktLen, advPkt, - scanRspLen, scanRsp, filtIndex, advState, advInfoPresent, address, addrType, - txPower, rssiValue, timeStamp); + return getTransitionalScanHelper() + .createOnTrackAdvFoundLostObject( + clientIf, + advPktLen, + advPkt, + scanRspLen, + scanRsp, + filtIndex, + advState, + advInfoPresent, + address, + addrType, + txPower, + rssiValue, + timeStamp); } void onTrackAdvFoundLost(AdvtFilterOnFoundOnLostInfo trackingInfo) throws RemoteException { - getGattService().onTrackAdvFoundLost(trackingInfo); + getTransitionalScanHelper().onTrackAdvFoundLost(trackingInfo); } void onScanParamSetupCompleted(int status, int scannerId) throws RemoteException { - getGattService().onScanParamSetupCompleted(status, scannerId); + getTransitionalScanHelper().onScanParamSetupCompleted(status, scannerId); } void onConfigureMTU(int connId, int status, int mtu) throws RemoteException { @@ -665,5 +693,11 @@ public class GattNativeInterface { int p1, int p2, int p3, int p4, int p5) { gattTestNative(command, uuid1Lsb, uuid1Msb, bda1, p1, p2, p3, p4, p5); } + + // TODO(b/327849650): Callbacks that reference this helper should be moved into the appropriate + // native interface (ScanNativeInterface, PeriodicScanNativeInterface, etc.). + private TransitionalScanHelper getTransitionalScanHelper() { + return mGattService.getTransitionalScanHelper(); + } } diff --git a/android/app/src/com/android/bluetooth/gatt/GattObjectsFactory.java b/android/app/src/com/android/bluetooth/gatt/GattObjectsFactory.java index 3cc02b851b..0a02c2d142 100644 --- a/android/app/src/com/android/bluetooth/gatt/GattObjectsFactory.java +++ b/android/app/src/com/android/bluetooth/gatt/GattObjectsFactory.java @@ -16,6 +16,7 @@ package com.android.bluetooth.gatt; +import android.content.Context; import android.os.Looper; import android.util.Log; @@ -25,6 +26,7 @@ import com.android.bluetooth.btservice.BluetoothAdapterProxy; import com.android.bluetooth.le_scan.PeriodicScanManager; import com.android.bluetooth.le_scan.ScanManager; import com.android.bluetooth.le_scan.ScanNativeInterface; +import com.android.bluetooth.le_scan.TransitionalScanHelper; /** * Factory class for object initialization to help with unit testing @@ -75,18 +77,20 @@ public class GattObjectsFactory { /** * Create an instance of ScanManager * - * @param service a GattService instance + * @param context a Context instance + * @param scanHelper a TransitionalScanHelper instance * @param adapterService an AdapterService instance * @param bluetoothAdapterProxy a bluetoothAdapterProxy instance * @param looper the looper to be used for processing messages * @return the created ScanManager instance */ public ScanManager createScanManager( - GattService service, + Context context, + TransitionalScanHelper scanHelper, AdapterService adapterService, BluetoothAdapterProxy bluetoothAdapterProxy, Looper looper) { - return new ScanManager(service, adapterService, bluetoothAdapterProxy, looper); + return new ScanManager(context, scanHelper, adapterService, bluetoothAdapterProxy, looper); } public PeriodicScanManager createPeriodicScanManager(AdapterService adapterService) { diff --git a/android/app/src/com/android/bluetooth/gatt/GattService.java b/android/app/src/com/android/bluetooth/gatt/GattService.java index 4f4dab7325..690c841bdd 100644 --- a/android/app/src/com/android/bluetooth/gatt/GattService.java +++ b/android/app/src/com/android/bluetooth/gatt/GattService.java @@ -25,7 +25,6 @@ import static com.android.bluetooth.Utils.enforceBluetoothPrivilegedPermission; import android.annotation.RequiresPermission; import android.annotation.SuppressLint; import android.app.ActivityManager; -import android.app.AppOpsManager; import android.app.PendingIntent; import android.bluetooth.BluetoothAdapter; import android.bluetooth.BluetoothDevice; @@ -42,7 +41,6 @@ import android.bluetooth.IBluetoothGattCallback; import android.bluetooth.IBluetoothGattServerCallback; import android.bluetooth.le.AdvertiseData; import android.bluetooth.le.AdvertisingSetParameters; -import android.bluetooth.le.BluetoothLeScanner; import android.bluetooth.le.ChannelSoundingParams; import android.bluetooth.le.DistanceMeasurementMethod; import android.bluetooth.le.DistanceMeasurementParams; @@ -51,22 +49,15 @@ import android.bluetooth.le.IDistanceMeasurementCallback; import android.bluetooth.le.IPeriodicAdvertisingCallback; import android.bluetooth.le.IScannerCallback; import android.bluetooth.le.PeriodicAdvertisingParameters; -import android.bluetooth.le.ScanCallback; import android.bluetooth.le.ScanFilter; -import android.bluetooth.le.ScanRecord; import android.bluetooth.le.ScanResult; 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; import android.content.pm.PackageManager.NameNotFoundException; import android.content.pm.PackageManager.PackageInfoFlags; import android.content.res.Resources; -import android.net.MacAddress; -import android.os.Binder; import android.os.Build; import android.os.Handler; import android.os.HandlerThread; @@ -74,10 +65,7 @@ import android.os.IBinder; import android.os.Message; import android.os.ParcelUuid; import android.os.RemoteException; -import android.os.SystemClock; -import android.os.UserHandle; import android.os.WorkSource; -import android.provider.DeviceConfig; import android.provider.Settings; import android.sysprop.BluetoothProperties; import android.text.format.DateUtils; @@ -94,29 +82,20 @@ import com.android.bluetooth.btservice.CompanionManager; import com.android.bluetooth.btservice.MetricsLogger; import com.android.bluetooth.btservice.ProfileService; import com.android.bluetooth.flags.Flags; -import com.android.bluetooth.le_scan.AppScanStats; -import com.android.bluetooth.le_scan.PeriodicScanManager; -import com.android.bluetooth.le_scan.ScanClient; -import com.android.bluetooth.le_scan.ScanManager; import com.android.bluetooth.le_scan.TransitionalScanHelper; -import com.android.bluetooth.util.NumberUtils; import com.android.internal.annotations.VisibleForTesting; import com.android.modules.utils.SynchronousResultReceiver; import libcore.util.HexEncoding; -import java.util.ArrayDeque; import java.util.ArrayList; import java.util.Arrays; -import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; import java.util.UUID; -import java.util.concurrent.TimeUnit; -import java.util.function.Predicate; /** * Provides Bluetooth Gatt profile, as a service in @@ -130,47 +109,7 @@ public class GattService extends ProfileService { private static final String UUID_SUFFIX = "-0000-1000-8000-00805f9b34fb"; private static final String UUID_ZERO_PAD = "00000000"; - static final int SCAN_FILTER_ENABLED = 1; - static final int SCAN_FILTER_MODIFIED = 2; - private static final int MAC_ADDRESS_LENGTH = 6; - // Batch scan related constants. - private static final int TRUNCATED_RESULT_SIZE = 11; - private static final int TIME_STAMP_LENGTH = 2; - - private enum MatchOrigin { - PSEUDO_ADDRESS, - ORIGINAL_ADDRESS - } - - private static class MatchResult { - private final boolean mMatches; - private final MatchOrigin mOrigin; - private MatchResult(boolean matches, MatchOrigin origin) { - this.mMatches = matches; - this.mOrigin = origin; - } - - public boolean getMatches() { - return mMatches; - } - - public MatchOrigin getMatchOrigin() { - return mOrigin; - } - } - - /** - * The default floor value for LE batch scan report delays greater than 0 - */ - @VisibleForTesting - static final long DEFAULT_REPORT_DELAY_FLOOR = 5000; - - // onFoundLost related constants - private static final int ADVT_STATE_ONFOUND = 0; - private static final int ADVT_STATE_ONLOST = 1; - - private static final int ET_LEGACY_MASK = 0x10; private static final UUID HID_SERVICE_UUID = UUID.fromString("00001812-0000-1000-8000-00805F9B34FB"); @@ -209,34 +148,8 @@ public class GattService extends ProfileService { "0201061AFF4C000215426C7565436861726D426561636F6E730EFE1355C509168020691E0EFE13551109426C7565436861726D5F31363936383500000000", }; - /** - * Keep the arguments passed in for the PendingIntent. - */ - public static class PendingIntentInfo { - public PendingIntent intent; - public ScanSettings settings; - public List<ScanFilter> filters; - public String callingPackage; - public int callingUid; - - @Override - public boolean equals(Object other) { - if (!(other instanceof PendingIntentInfo)) { - return false; - } - return intent.equals(((PendingIntentInfo) other).intent); - } - } - - private final PendingIntent.CancelListener mScanIntentCancelListener = - new PendingIntent.CancelListener(){ - public void onCanceled(PendingIntent intent) { - Log.d(TAG, "scanning PendingIntent canceled"); - stopScan(intent, getAttributionSource()); - } - }; - - public final TransitionalScanHelper mTransitionalScanHelper = new TransitionalScanHelper(); + public final TransitionalScanHelper mTransitionalScanHelper = + new TransitionalScanHelper(this, this::isTestModeEnabled); /** * List of our registered advertisers. @@ -265,16 +178,6 @@ public class GattService extends ProfileService { HandleMap mHandleMap = new HandleMap(); private List<UUID> mAdvertisingServiceUuids = new ArrayList<UUID>(); - private int mMaxScanFilters; - - private static final int NUM_SCAN_EVENTS_KEPT = 20; - - /** - * Internal list of scan events to use with the proto - */ - private final ArrayDeque<BluetoothMetricsProto.ScanEvent> mScanEvents = - new ArrayDeque<>(NUM_SCAN_EVENTS_KEPT); - /** * Set of restricted (which require a BLUETOOTH_PRIVILEGED permission) handles per connectionId. */ @@ -289,12 +192,7 @@ public class GattService extends ProfileService { private AdapterService mAdapterService; private BluetoothAdapterProxy mBluetoothAdapterProxy; AdvertiseManager mAdvertiseManager; - PeriodicScanManager mPeriodicScanManager; DistanceMeasurementManager mDistanceMeasurementManager; - ScanManager mScanManager; - private AppOpsManager mAppOps; - private CompanionDeviceManager mCompanionManager; - private String mExposureNotificationPackage; private Handler mTestModeHandler; private ActivityManager mActivityManager; private PackageManager mPackageManager; @@ -309,23 +207,6 @@ public class GattService extends ProfileService { } /** - */ - private final Predicate<ScanResult> mLocationDenylistPredicate = (scanResult) -> { - final MacAddress parsedAddress = MacAddress - .fromString(scanResult.getDevice().getAddress()); - if (mAdapterService.getLocationDenylistMac().test(parsedAddress.toByteArray())) { - Log.v(TAG, "Skipping device matching denylist: " + scanResult.getDevice()); - return true; - } - final ScanRecord scanRecord = scanResult.getScanRecord(); - if (scanRecord.matchesAnyField(mAdapterService.getLocationDenylistAdvertisingData())) { - Log.v(TAG, "Skipping data matching denylist: " + scanRecord); - return true; - } - return false; - }; - - /** * Reliable write queue */ @VisibleForTesting @@ -343,7 +224,6 @@ public class GattService extends ProfileService { if (DBG) { Log.d(TAG, "start()"); } - mExposureNotificationPackage = getString(R.string.exposure_notification_package); Settings.Global.putInt( getContentResolver(), "bluetooth_sanitized_exposure_notification_supported", 1); @@ -351,8 +231,6 @@ public class GattService extends ProfileService { mNativeInterface.init(this); mAdapterService = AdapterService.getAdapterService(); mBluetoothAdapterProxy = BluetoothAdapterProxy.getInstance(); - mCompanionManager = getSystemService(CompanionDeviceManager.class); - mAppOps = getSystemService(AppOpsManager.class); mAdvertiseManager = new AdvertiseManager( this, @@ -362,14 +240,7 @@ public class GattService extends ProfileService { HandlerThread thread = new HandlerThread("BluetoothScanManager"); thread.start(); - mScanManager = - GattObjectsFactory.getInstance() - .createScanManager( - this, mAdapterService, mBluetoothAdapterProxy, thread.getLooper()); - - mPeriodicScanManager = GattObjectsFactory.getInstance() - .createPeriodicScanManager(mAdapterService); - + mTransitionalScanHelper.start(thread.getLooper()); mDistanceMeasurementManager = GattObjectsFactory.getInstance() .createDistanceMeasurementManager(mAdapterService); @@ -382,7 +253,7 @@ public class GattService extends ProfileService { if (DBG) { Log.d(TAG, "stop()"); } - mTransitionalScanHelper.getScannerMap().clear(); + mTransitionalScanHelper.stop(); mAdvertiserMap.clear(); mClientMap.clear(); if (Flags.gattCleanupRestrictedHandles()) { @@ -406,15 +277,14 @@ public class GattService extends ProfileService { if (mAdvertiseManager != null) { mAdvertiseManager.cleanup(); } - if (mScanManager != null) { - mScanManager.cleanup(); - } - if (mPeriodicScanManager != null) { - mPeriodicScanManager.cleanup(); - } if (mDistanceMeasurementManager != null) { mDistanceMeasurementManager.cleanup(); } + mTransitionalScanHelper.cleanup(); + } + + TransitionalScanHelper getTransitionalScanHelper() { + return mTransitionalScanHelper; } // While test mode is enabled, pretend as if the underlying stack @@ -423,21 +293,31 @@ public class GattService extends ProfileService { protected void setTestModeEnabled(boolean enableTestMode) { synchronized (mTestModeLock) { if (mTestModeHandler == null) { - mTestModeHandler = new Handler(getMainLooper()) { - public void handleMessage(Message msg) { - synchronized (mTestModeLock) { - if (!GattService.this.isTestModeEnabled()) { - return; + mTestModeHandler = + new Handler(getMainLooper()) { + public void handleMessage(Message msg) { + synchronized (mTestModeLock) { + if (!GattService.this.isTestModeEnabled()) { + return; + } + for (String test : TEST_MODE_BEACONS) { + mTransitionalScanHelper.onScanResultInternal( + 0x1b, + 0x1, + "DD:34:02:05:5C:4D", + 1, + 0, + 0xff, + 127, + -54, + 0x0, + HexEncoding.decode(test), + "DD:34:02:05:5C:4E"); + } + sendEmptyMessageDelayed(0, DateUtils.SECOND_IN_MILLIS); + } } - for (String test : TEST_MODE_BEACONS) { - onScanResultInternal(0x1b, 0x1, "DD:34:02:05:5C:4D", 1, 0, 0xff, - 127, -54, 0x0, HexEncoding.decode(test), - "DD:34:02:05:5C:4E"); - } - sendEmptyMessageDelayed(0, DateUtils.SECOND_IN_MILLIS); - } - } - }; + }; } if (enableTestMode && !isTestModeEnabled()) { super.setTestModeEnabled(true); @@ -451,15 +331,6 @@ public class GattService extends ProfileService { } } - @VisibleForTesting - ScanManager getScanManager() { - if (mScanManager == null) { - Log.w(TAG, "getScanManager(): scan manager is null"); - return null; - } - return mScanManager; - } - // Suppressed because we are conditionally enforcing @SuppressLint("AndroidFrameworkRequiresPermission") private void permissionCheck(UUID characteristicUuid) { @@ -495,63 +366,7 @@ public class GattService extends ProfileService { /** Notify Scan manager of bluetooth profile connection state changes */ public void notifyProfileConnectionStateChange(int profile, int fromState, int toState) { - if (mScanManager == null) { - Log.w(TAG, "scan manager is null"); - return; - } - mScanManager.handleBluetoothProfileConnectionStateChanged(profile, fromState, toState); - } - - /** - * DeathReceipient handlers used to unregister applications that - * disconnect ungracefully (ie. crash or forced close). - */ - - class ScannerDeathRecipient implements IBinder.DeathRecipient { - int mScannerId; - private String mPackageName; - - ScannerDeathRecipient(int scannerId, String packageName) { - mScannerId = scannerId; - mPackageName = packageName; - } - - @Override - public void binderDied() { - if (DBG) { - Log.d( - TAG, - "Binder is dead - unregistering scanner (" - + mPackageName - + " " - + mScannerId - + ")!"); - } - - ScanClient client = getScanClient(mScannerId); - if (client != null) { - if (Flags.leScanFixRemoteException()) { - handleDeadScanClient(client); - } else { - client.appDied = true; - stopScan(client.scannerId, getAttributionSource()); - } - } - } - - private ScanClient getScanClient(int clientIf) { - for (ScanClient client : mScanManager.getRegularScanQueue()) { - if (client.scannerId == clientIf) { - return client; - } - } - for (ScanClient client : mScanManager.getBatchScanQueue()) { - if (client.scannerId == clientIf) { - return client; - } - } - return null; - } + mTransitionalScanHelper.notifyProfileConnectionStateChange(profile, fromState, toState); } class ServerDeathRecipient implements IBinder.DeathRecipient { @@ -700,7 +515,8 @@ public class GattService extends ProfileService { if (service == null) { return; } - service.registerScanner(callback, workSource, attributionSource); + service.getTransitionalScanHelper() + .registerScanner(callback, workSource, attributionSource); } @Override @@ -718,7 +534,7 @@ public class GattService extends ProfileService { if (service == null) { return; } - service.unregisterScanner(scannerId, attributionSource); + service.getTransitionalScanHelper().unregisterScanner(scannerId, attributionSource); } @Override @@ -738,7 +554,8 @@ public class GattService extends ProfileService { if (service == null) { return; } - service.startScan(scannerId, settings, filters, attributionSource); + service.getTransitionalScanHelper() + .startScan(scannerId, settings, filters, attributionSource); } @Override @@ -761,7 +578,8 @@ public class GattService extends ProfileService { if (service == null) { return; } - service.registerPiAndStartScan(intent, settings, filters, attributionSource); + service.getTransitionalScanHelper() + .registerPiAndStartScan(intent, settings, filters, attributionSource); } @Override @@ -780,7 +598,7 @@ public class GattService extends ProfileService { if (service == null) { return; } - service.stopScan(intent, attributionSource); + service.getTransitionalScanHelper().stopScan(intent, attributionSource); } @Override @@ -798,7 +616,7 @@ public class GattService extends ProfileService { if (service == null) { return; } - service.stopScan(scannerId, attributionSource); + service.getTransitionalScanHelper().stopScan(scannerId, attributionSource); } @Override @@ -816,7 +634,8 @@ public class GattService extends ProfileService { if (service == null) { return; } - service.flushPendingBatchResults(scannerId, attributionSource); + service.getTransitionalScanHelper() + .flushPendingBatchResults(scannerId, attributionSource); } @Override @@ -1686,7 +1505,8 @@ public class GattService extends ProfileService { if (service == null) { return; } - service.registerSync(scanResult, skip, timeout, callback, attributionSource); + service.getTransitionalScanHelper() + .registerSync(scanResult, skip, timeout, callback, attributionSource); } @Override @@ -1705,7 +1525,8 @@ public class GattService extends ProfileService { if (service == null) { return; } - service.transferSync(bda, serviceData , syncHandle, attributionSource); + service.getTransitionalScanHelper() + .transferSync(bda, serviceData, syncHandle, attributionSource); } @Override @@ -1725,7 +1546,8 @@ public class GattService extends ProfileService { if (service == null) { return; } - service.transferSetInfo(bda, serviceData , advHandle, callback, attributionSource); + service.getTransitionalScanHelper() + .transferSetInfo(bda, serviceData, advHandle, callback, attributionSource); } @Override @@ -1744,7 +1566,7 @@ public class GattService extends ProfileService { if (service == null) { return; } - service.unregisterSync(callback, attributionSource); + service.getTransitionalScanHelper().unregisterSync(callback, attributionSource); } @Override @@ -1922,302 +1744,6 @@ public class GattService extends ProfileService { * Callback functions - CLIENT *************************************************************************/ - // EN format defined here: - // https://blog.google/documents/70/Exposure_Notification_-_Bluetooth_Specification_v1.2.2.pdf - private static final byte[] EXPOSURE_NOTIFICATION_FLAGS_PREAMBLE = new byte[] { - // size 2, flag field, flags byte (value is not important) - (byte) 0x02, (byte) 0x01 - }; - private static final int EXPOSURE_NOTIFICATION_FLAGS_LENGTH = 0x2 + 1; - private static final byte[] EXPOSURE_NOTIFICATION_PAYLOAD_PREAMBLE = new byte[] { - // size 3, complete 16 bit UUID, EN UUID - (byte) 0x03, (byte) 0x03, (byte) 0x6F, (byte) 0xFD, - // size 23, data for 16 bit UUID, EN UUID - (byte) 0x17, (byte) 0x16, (byte) 0x6F, (byte) 0xFD, - // ...payload - }; - private static final int EXPOSURE_NOTIFICATION_PAYLOAD_LENGTH = 0x03 + 0x17 + 2; - - private static boolean arrayStartsWith(byte[] array, byte[] prefix) { - if (array.length < prefix.length) { - return false; - } - for (int i = 0; i < prefix.length; i++) { - if (prefix[i] != array[i]) { - return false; - } - } - return true; - } - - ScanResult getSanitizedExposureNotification(ScanResult result) { - ScanRecord record = result.getScanRecord(); - // Remove the flags part of the payload, if present - if (record.getBytes().length > EXPOSURE_NOTIFICATION_FLAGS_LENGTH - && arrayStartsWith(record.getBytes(), EXPOSURE_NOTIFICATION_FLAGS_PREAMBLE)) { - record = ScanRecord.parseFromBytes( - Arrays.copyOfRange( - record.getBytes(), - EXPOSURE_NOTIFICATION_FLAGS_LENGTH, - record.getBytes().length)); - } - - if (record.getBytes().length != EXPOSURE_NOTIFICATION_PAYLOAD_LENGTH) { - return null; - } - if (!arrayStartsWith(record.getBytes(), EXPOSURE_NOTIFICATION_PAYLOAD_PREAMBLE)) { - return null; - } - - return new ScanResult(null, 0, 0, 0, 0, 0, result.getRssi(), 0, record, 0); - } - - void onScanResult(int eventType, int addressType, String address, int primaryPhy, - int secondaryPhy, int advertisingSid, int txPower, int rssi, int periodicAdvInt, - byte[] advData, String originalAddress) { - // When in testing mode, ignore all real-world events - if (isTestModeEnabled()) return; - - AppScanStats.recordScanRadioResultCount(); - onScanResultInternal(eventType, addressType, address, primaryPhy, secondaryPhy, - advertisingSid, txPower, rssi, periodicAdvInt, advData, originalAddress); - } - - void onScanResultInternal(int eventType, int addressType, String address, int primaryPhy, - int secondaryPhy, int advertisingSid, int txPower, int rssi, int periodicAdvInt, - byte[] advData, String originalAddress) { - if (VDBG) { - Log.d(TAG, "onScanResult() - eventType=0x" + Integer.toHexString(eventType) - + ", addressType=" + addressType + ", address=" + address + ", primaryPhy=" - + primaryPhy + ", secondaryPhy=" + secondaryPhy + ", advertisingSid=0x" - + Integer.toHexString(advertisingSid) + ", txPower=" + txPower + ", rssi=" - + rssi + ", periodicAdvInt=0x" + Integer.toHexString(periodicAdvInt) - + ", originalAddress=" + originalAddress); - } - - String identityAddress = mAdapterService.getIdentityAddress(address); - if (!address.equals(identityAddress)) { - if (VDBG) { - Log.d(TAG, "found identityAddress of " + address + ", replace originalAddress as " - + identityAddress); - } - originalAddress = identityAddress; - } - - - byte[] legacyAdvData = Arrays.copyOfRange(advData, 0, 62); - - for (ScanClient client : mScanManager.getRegularScanQueue()) { - TransitionalScanHelper.ScannerMap.App app = - mTransitionalScanHelper.getScannerMap().getById(client.scannerId); - if (app == null) { - if (VDBG) { - Log.d(TAG, "App is null; skip."); - } - continue; - } - - BluetoothDevice device = - BluetoothAdapter.getDefaultAdapter().getRemoteLeDevice(address, addressType); - - ScanSettings settings = client.settings; - byte[] scanRecordData; - // This is for compability with applications that assume fixed size scan data. - if (settings.getLegacy()) { - if ((eventType & ET_LEGACY_MASK) == 0) { - // If this is legacy scan, but nonlegacy result - skip. - if (VDBG) { - Log.d(TAG, "Legacy scan, non legacy result; skip."); - } - continue; - } else { - // Some apps are used to fixed-size advertise data. - scanRecordData = legacyAdvData; - } - } else { - scanRecordData = advData; - } - - ScanRecord scanRecord = ScanRecord.parseFromBytes(scanRecordData); - ScanResult result = - new ScanResult(device, eventType, primaryPhy, secondaryPhy, advertisingSid, - txPower, rssi, periodicAdvInt, scanRecord, - SystemClock.elapsedRealtimeNanos()); - - if (client.hasDisavowedLocation) { - if (mLocationDenylistPredicate.test(result)) { - Log.i(TAG, "Skipping client for location deny list"); - continue; - } - } - - boolean hasPermission = hasScanResultPermission(client); - if (!hasPermission) { - for (String associatedDevice : client.associatedDevices) { - if (associatedDevice.equalsIgnoreCase(address)) { - hasPermission = true; - break; - } - } - } - if (!hasPermission && client.eligibleForSanitizedExposureNotification) { - ScanResult sanitized = getSanitizedExposureNotification(result); - if (sanitized != null) { - hasPermission = true; - result = sanitized; - } - } - MatchResult matchResult = matchesFilters(client, result, originalAddress); - if (!hasPermission || !matchResult.getMatches()) { - if (VDBG) { - Log.d(TAG, "Skipping client: permission=" - + hasPermission + " matches=" + matchResult.getMatches()); - } - continue; - } - - int callbackType = settings.getCallbackType(); - if (!(callbackType == ScanSettings.CALLBACK_TYPE_ALL_MATCHES - || callbackType == ScanSettings.CALLBACK_TYPE_ALL_MATCHES_AUTO_BATCH)) { - if (VDBG) { - Log.d(TAG, "Skipping client: CALLBACK_TYPE_ALL_MATCHES"); - } - continue; - } - - try { - app.appScanStats.addResult(client.scannerId); - if (app.callback != null) { - app.callback.onScanResult(result); - } else { - // Send the PendingIntent - ArrayList<ScanResult> results = new ArrayList<>(); - results.add(result); - sendResultsByPendingIntent(app.info, results, - ScanSettings.CALLBACK_TYPE_ALL_MATCHES); - } - } catch (RemoteException | PendingIntent.CanceledException e) { - Log.e(TAG, "Exception: " + e); - if (Flags.leScanFixRemoteException()) { - handleDeadScanClient(client); - } else { - mTransitionalScanHelper.getScannerMap().remove(client.scannerId); - mScanManager.stopScan(client.scannerId); - } - } - } - } - - private void sendResultByPendingIntent(PendingIntentInfo pii, ScanResult result, - int callbackType, ScanClient client) { - ArrayList<ScanResult> results = new ArrayList<>(); - results.add(result); - try { - sendResultsByPendingIntent(pii, results, callbackType); - } catch (PendingIntent.CanceledException e) { - final long token = Binder.clearCallingIdentity(); - try { - stopScan(client.scannerId, getAttributionSource()); - unregisterScanner(client.scannerId, getAttributionSource()); - } finally { - Binder.restoreCallingIdentity(token); - } - } - } - - private void sendResultsByPendingIntent(PendingIntentInfo pii, ArrayList<ScanResult> results, - int callbackType) throws PendingIntent.CanceledException { - Intent extrasIntent = new Intent(); - extrasIntent.putParcelableArrayListExtra(BluetoothLeScanner.EXTRA_LIST_SCAN_RESULT, - results); - extrasIntent.putExtra(BluetoothLeScanner.EXTRA_CALLBACK_TYPE, callbackType); - pii.intent.send(this, 0, extrasIntent); - } - - private void sendErrorByPendingIntent(PendingIntentInfo pii, int errorCode) - throws PendingIntent.CanceledException { - Intent extrasIntent = new Intent(); - extrasIntent.putExtra(BluetoothLeScanner.EXTRA_ERROR_CODE, errorCode); - pii.intent.send(this, 0, extrasIntent); - } - - void onScannerRegistered(int status, int scannerId, long uuidLsb, long uuidMsb) - throws RemoteException { - UUID uuid = new UUID(uuidMsb, uuidLsb); - if (DBG) { - Log.d(TAG, "onScannerRegistered() - UUID=" + uuid + ", scannerId=" + scannerId - + ", status=" + status); - } - - // First check the callback map - TransitionalScanHelper.ScannerMap.App cbApp = - mTransitionalScanHelper.getScannerMap().getByUuid(uuid); - if (cbApp != null) { - if (status == 0) { - cbApp.id = scannerId; - // If app is callback based, setup a death recipient. App will initiate the start. - // Otherwise, if PendingIntent based, start the scan directly. - if (cbApp.callback != null) { - cbApp.linkToDeath(new ScannerDeathRecipient(scannerId, cbApp.name)); - } else { - continuePiStartScan(scannerId, cbApp); - } - } else { - mTransitionalScanHelper.getScannerMap().remove(scannerId); - } - if (cbApp.callback != null) { - cbApp.callback.onScannerRegistered(status, scannerId); - } - } - } - - /** Determines if the given scan client has the appropriate permissions to receive callbacks. */ - private boolean hasScanResultPermission(final ScanClient client) { - if (client.hasNetworkSettingsPermission - || client.hasNetworkSetupWizardPermission - || client.hasScanWithoutLocationPermission) { - return true; - } - if (client.hasDisavowedLocation) { - return true; - } - return client.hasLocationPermission && !Utils.blockedByLocationOff(this, client.userHandle); - } - - // Check if a scan record matches a specific filters. - private MatchResult matchesFilters(ScanClient client, ScanResult scanResult) { - return matchesFilters(client, scanResult, null); - } - - // Check if a scan record matches a specific filters or original address - private MatchResult matchesFilters(ScanClient client, ScanResult scanResult, - String originalAddress) { - if (client.filters == null || client.filters.isEmpty()) { - // TODO: Do we really wanna return true here? - return new MatchResult(true, MatchOrigin.PSEUDO_ADDRESS); - } - for (ScanFilter filter : client.filters) { - // Need to check the filter matches, and the original address without changing the API - if (filter.matches(scanResult)) { - return new MatchResult(true, MatchOrigin.PSEUDO_ADDRESS); - } - if (originalAddress != null - && originalAddress.equalsIgnoreCase(filter.getDeviceAddress())) { - return new MatchResult(true, MatchOrigin.ORIGINAL_ADDRESS); - } - } - return new MatchResult(false, MatchOrigin.PSEUDO_ADDRESS); - } - - private void handleDeadScanClient(ScanClient client) { - if (client.appDied) { - Log.w(TAG, "Already dead client " + client.scannerId); - return; - } - client.appDied = true; - stopScan(client.scannerId, getAttributionSource()); - } - void onClientRegistered(int status, int clientIf, long uuidLsb, long uuidMsb) throws RemoteException { UUID uuid = new UUID(uuidMsb, uuidLsb); @@ -2719,404 +2245,6 @@ public class GattService extends ProfileService { } } - void onScanFilterEnableDisabled(int action, int status, int clientIf) { - if (DBG) { - Log.d(TAG, "onScanFilterEnableDisabled() - clientIf=" + clientIf + ", status=" + status - + ", action=" + action); - } - mScanManager.callbackDone(clientIf, status); - } - - void onScanFilterParamsConfigured(int action, int status, int clientIf, int availableSpace) { - if (DBG) { - Log.d(TAG, - "onScanFilterParamsConfigured() - clientIf=" + clientIf + ", status=" + status - + ", action=" + action + ", availableSpace=" + availableSpace); - } - mScanManager.callbackDone(clientIf, status); - } - - void onScanFilterConfig(int action, int status, int clientIf, int filterType, - int availableSpace) { - if (DBG) { - Log.d(TAG, "onScanFilterConfig() - clientIf=" + clientIf + ", action = " + action - + " status = " + status + ", filterType=" + filterType + ", availableSpace=" - + availableSpace); - } - - mScanManager.callbackDone(clientIf, status); - } - - void onBatchScanStorageConfigured(int status, int clientIf) { - if (DBG) { - Log.d(TAG, - "onBatchScanStorageConfigured() - clientIf=" + clientIf + ", status=" + status); - } - mScanManager.callbackDone(clientIf, status); - } - - // TODO: split into two different callbacks : onBatchScanStarted and onBatchScanStopped. - void onBatchScanStartStopped(int startStopAction, int status, int clientIf) { - if (DBG) { - Log.d(TAG, "onBatchScanStartStopped() - clientIf=" + clientIf + ", status=" + status - + ", startStopAction=" + startStopAction); - } - mScanManager.callbackDone(clientIf, status); - } - - ScanClient findBatchScanClientById(int scannerId) { - for (ScanClient client : mScanManager.getBatchScanQueue()) { - if (client.scannerId == scannerId) { - return client; - } - } - return null; - } - - void onBatchScanReports(int status, int scannerId, int reportType, int numRecords, - byte[] recordData) throws RemoteException { - // When in testing mode, ignore all real-world events - if (isTestModeEnabled()) return; - - AppScanStats.recordBatchScanRadioResultCount(numRecords); - onBatchScanReportsInternal(status, scannerId, reportType, numRecords, recordData); - } - - void onBatchScanReportsInternal(int status, int scannerId, int reportType, int numRecords, - byte[] recordData) throws RemoteException { - if (DBG) { - Log.d(TAG, "onBatchScanReports() - scannerId=" + scannerId + ", status=" + status - + ", reportType=" + reportType + ", numRecords=" + numRecords); - } - - Set<ScanResult> results = parseBatchScanResults(numRecords, reportType, recordData); - if (reportType == ScanManager.SCAN_RESULT_TYPE_TRUNCATED) { - // We only support single client for truncated mode. - TransitionalScanHelper.ScannerMap.App app = - mTransitionalScanHelper.getScannerMap().getById(scannerId); - if (app == null) { - return; - } - - ScanClient client = findBatchScanClientById(scannerId); - if (client == null) { - return; - } - - ArrayList<ScanResult> permittedResults; - if (hasScanResultPermission(client)) { - permittedResults = new ArrayList<ScanResult>(results); - } else { - permittedResults = new ArrayList<ScanResult>(); - for (ScanResult scanResult : results) { - for (String associatedDevice : client.associatedDevices) { - if (associatedDevice.equalsIgnoreCase(scanResult.getDevice() - .getAddress())) { - permittedResults.add(scanResult); - } - } - } - if (permittedResults.isEmpty()) { - return; - } - } - - if (client.hasDisavowedLocation) { - permittedResults.removeIf(mLocationDenylistPredicate); - } - - if (app.callback != null) { - app.callback.onBatchScanResults(permittedResults); - } else { - // PendingIntent based - try { - sendResultsByPendingIntent(app.info, permittedResults, - ScanSettings.CALLBACK_TYPE_ALL_MATCHES); - } catch (PendingIntent.CanceledException e) { - } - } - } else { - for (ScanClient client : mScanManager.getFullBatchScanQueue()) { - // Deliver results for each client. - deliverBatchScan(client, results); - } - } - mScanManager.callbackDone(scannerId, status); - } - - private void sendBatchScanResults(TransitionalScanHelper.ScannerMap.App app, ScanClient client, - ArrayList<ScanResult> results) { - try { - if (app.callback != null) { - if (mScanManager.isAutoBatchScanClientEnabled(client)) { - if (DBG) { - Log.d(TAG, "sendBatchScanResults() to onScanResult()" + client); - } - for (ScanResult result : results) { - app.appScanStats.addResult(client.scannerId); - app.callback.onScanResult(result); - } - } else { - if (DBG) { - Log.d(TAG, "sendBatchScanResults() to onBatchScanResults()" + client); - } - app.callback.onBatchScanResults(results); - } - } else { - sendResultsByPendingIntent(app.info, results, - ScanSettings.CALLBACK_TYPE_ALL_MATCHES); - } - } catch (RemoteException | PendingIntent.CanceledException e) { - Log.e(TAG, "Exception: " + e); - if (Flags.leScanFixRemoteException()) { - handleDeadScanClient(client); - } else { - mTransitionalScanHelper.getScannerMap().remove(client.scannerId); - mScanManager.stopScan(client.scannerId); - } - } - } - - // Check and deliver scan results for different scan clients. - private void deliverBatchScan(ScanClient client, Set<ScanResult> allResults) - throws RemoteException { - ContextMap.App app = mTransitionalScanHelper.getScannerMap().getById(client.scannerId); - if (app == null) { - return; - } - - ArrayList<ScanResult> permittedResults; - if (hasScanResultPermission(client)) { - permittedResults = new ArrayList<ScanResult>(allResults); - } else { - permittedResults = new ArrayList<ScanResult>(); - for (ScanResult scanResult : allResults) { - for (String associatedDevice : client.associatedDevices) { - if (associatedDevice.equalsIgnoreCase(scanResult.getDevice().getAddress())) { - permittedResults.add(scanResult); - } - } - } - if (permittedResults.isEmpty()) { - return; - } - } - - if (client.filters == null || client.filters.isEmpty()) { - sendBatchScanResults(app, client, permittedResults); - // TODO: Question to reviewer: Shouldn't there be a return here? - } - // Reconstruct the scan results. - ArrayList<ScanResult> results = new ArrayList<ScanResult>(); - for (ScanResult scanResult : permittedResults) { - if (matchesFilters(client, scanResult).getMatches()) { - results.add(scanResult); - } - } - sendBatchScanResults(app, client, results); - } - - private Set<ScanResult> parseBatchScanResults(int numRecords, int reportType, - byte[] batchRecord) { - if (numRecords == 0) { - return Collections.emptySet(); - } - if (DBG) { - Log.d(TAG, "current time is " + SystemClock.elapsedRealtimeNanos()); - } - if (reportType == ScanManager.SCAN_RESULT_TYPE_TRUNCATED) { - return parseTruncatedResults(numRecords, batchRecord); - } else { - return parseFullResults(numRecords, batchRecord); - } - } - - private Set<ScanResult> parseTruncatedResults(int numRecords, byte[] batchRecord) { - if (DBG) { - Log.d(TAG, "batch record " + Arrays.toString(batchRecord)); - } - Set<ScanResult> results = new HashSet<ScanResult>(numRecords); - long now = SystemClock.elapsedRealtimeNanos(); - for (int i = 0; i < numRecords; ++i) { - byte[] record = - extractBytes(batchRecord, i * TRUNCATED_RESULT_SIZE, TRUNCATED_RESULT_SIZE); - byte[] address = extractBytes(record, 0, 6); - reverse(address); - BluetoothDevice device = BluetoothAdapter.getDefaultAdapter().getRemoteDevice(address); - int rssi = record[8]; - long timestampNanos = now - parseTimestampNanos(extractBytes(record, 9, 2)); - results.add(new ScanResult(device, ScanRecord.parseFromBytes(new byte[0]), rssi, - timestampNanos)); - } - return results; - } - - @VisibleForTesting - long parseTimestampNanos(byte[] data) { - long timestampUnit = NumberUtils.littleEndianByteArrayToInt(data); - // Timestamp is in every 50 ms. - return TimeUnit.MILLISECONDS.toNanos(timestampUnit * 50); - } - - private Set<ScanResult> parseFullResults(int numRecords, byte[] batchRecord) { - if (DBG) { - Log.d(TAG, "Batch record : " + Arrays.toString(batchRecord)); - } - Set<ScanResult> results = new HashSet<ScanResult>(numRecords); - int position = 0; - long now = SystemClock.elapsedRealtimeNanos(); - while (position < batchRecord.length) { - byte[] address = extractBytes(batchRecord, position, 6); - // TODO: remove temp hack. - reverse(address); - BluetoothDevice device = BluetoothAdapter.getDefaultAdapter().getRemoteDevice(address); - position += 6; - // Skip address type. - position++; - // Skip tx power level. - position++; - int rssi = batchRecord[position++]; - long timestampNanos = now - parseTimestampNanos(extractBytes(batchRecord, position, 2)); - position += 2; - - // Combine advertise packet and scan response packet. - int advertisePacketLen = batchRecord[position++]; - byte[] advertiseBytes = extractBytes(batchRecord, position, advertisePacketLen); - position += advertisePacketLen; - int scanResponsePacketLen = batchRecord[position++]; - byte[] scanResponseBytes = extractBytes(batchRecord, position, scanResponsePacketLen); - position += scanResponsePacketLen; - byte[] scanRecord = new byte[advertisePacketLen + scanResponsePacketLen]; - System.arraycopy(advertiseBytes, 0, scanRecord, 0, advertisePacketLen); - System.arraycopy(scanResponseBytes, 0, scanRecord, advertisePacketLen, - scanResponsePacketLen); - if (DBG) { - Log.d(TAG, "ScanRecord : " + Arrays.toString(scanRecord)); - } - results.add(new ScanResult(device, ScanRecord.parseFromBytes(scanRecord), rssi, - timestampNanos)); - } - return results; - } - - // Reverse byte array. - private void reverse(byte[] address) { - int len = address.length; - for (int i = 0; i < len / 2; ++i) { - byte b = address[i]; - address[i] = address[len - 1 - i]; - address[len - 1 - i] = b; - } - } - - // Helper method to extract bytes from byte array. - private static byte[] extractBytes(byte[] scanRecord, int start, int length) { - byte[] bytes = new byte[length]; - System.arraycopy(scanRecord, start, bytes, 0, length); - return bytes; - } - - @RequiresPermission(android.Manifest.permission.BLUETOOTH_SCAN) - void onBatchScanThresholdCrossed(int clientIf) { - if (DBG) { - Log.d(TAG, "onBatchScanThresholdCrossed() - clientIf=" + clientIf); - } - flushPendingBatchResults(clientIf, getAttributionSource()); - } - - AdvtFilterOnFoundOnLostInfo createOnTrackAdvFoundLostObject(int clientIf, int advPktLen, - byte[] advPkt, int scanRspLen, byte[] scanRsp, int filtIndex, int advState, - int advInfoPresent, String address, int addrType, int txPower, int rssiValue, - int timeStamp) { - - return new AdvtFilterOnFoundOnLostInfo(clientIf, advPktLen, advPkt, scanRspLen, scanRsp, - filtIndex, advState, advInfoPresent, address, addrType, txPower, rssiValue, - timeStamp); - } - - void onTrackAdvFoundLost(AdvtFilterOnFoundOnLostInfo trackingInfo) throws RemoteException { - if (DBG) { - Log.d(TAG, "onTrackAdvFoundLost() - scannerId= " + trackingInfo.getClientIf() - + " address = " + trackingInfo.getAddress() + " adv_state = " - + trackingInfo.getAdvState()); - } - - TransitionalScanHelper.ScannerMap.App app = - mTransitionalScanHelper.getScannerMap().getById(trackingInfo.getClientIf()); - if (app == null || (app.callback == null && app.info == null)) { - Log.e(TAG, "app or callback is null"); - return; - } - - BluetoothDevice device = BluetoothAdapter.getDefaultAdapter() - .getRemoteDevice(trackingInfo.getAddress()); - int advertiserState = trackingInfo.getAdvState(); - ScanResult result = - new ScanResult(device, ScanRecord.parseFromBytes(trackingInfo.getResult()), - trackingInfo.getRSSIValue(), SystemClock.elapsedRealtimeNanos()); - - for (ScanClient client : mScanManager.getRegularScanQueue()) { - if (client.scannerId == trackingInfo.getClientIf()) { - ScanSettings settings = client.settings; - if ((advertiserState == ADVT_STATE_ONFOUND) && ( - (settings.getCallbackType() & ScanSettings.CALLBACK_TYPE_FIRST_MATCH) - != 0)) { - if (app.callback != null) { - app.callback.onFoundOrLost(true, result); - } else { - sendResultByPendingIntent(app.info, result, - ScanSettings.CALLBACK_TYPE_FIRST_MATCH, client); - } - } else if ((advertiserState == ADVT_STATE_ONLOST) && ( - (settings.getCallbackType() & ScanSettings.CALLBACK_TYPE_MATCH_LOST) - != 0)) { - if (app.callback != null) { - app.callback.onFoundOrLost(false, result); - } else { - sendResultByPendingIntent(app.info, result, - ScanSettings.CALLBACK_TYPE_MATCH_LOST, client); - } - } else { - if (DBG) { - Log.d(TAG, "Not reporting onlost/onfound : " + advertiserState - + " scannerId = " + client.scannerId + " callbackType " - + settings.getCallbackType()); - } - } - } - } - } - - void onScanParamSetupCompleted(int status, int scannerId) throws RemoteException { - ContextMap.App app = mTransitionalScanHelper.getScannerMap().getById(scannerId); - if (app == null || app.callback == null) { - Log.e(TAG, "Advertise app or callback is null"); - return; - } - if (DBG) { - Log.d(TAG, "onScanParamSetupCompleted : " + status); - } - } - - // callback from ScanManager for dispatch of errors apps. - public void onScanManagerErrorCallback(int scannerId, int errorCode) throws RemoteException { - TransitionalScanHelper.ScannerMap.App app = - mTransitionalScanHelper.getScannerMap().getById(scannerId); - if (app == null || (app.callback == null && app.info == null)) { - Log.e(TAG, "App or callback is null"); - return; - } - if (app.callback != null) { - app.callback.onScanManagerErrorCallback(errorCode); - } else { - try { - sendErrorByPendingIntent(app.info, errorCode); - } catch (PendingIntent.CanceledException e) { - Log.e(TAG, "Error sending error code via PendingIntent:" + e); - } - } - } - void onConfigureMTU(int connId, int status, int mtu) throws RemoteException { String address = mClientMap.addressByConnId(connId); @@ -3203,292 +2331,6 @@ public class GattService extends ProfileService { return deviceList; } - @RequiresPermission(android.Manifest.permission.BLUETOOTH_SCAN) - void registerScanner(IScannerCallback callback, WorkSource workSource, - AttributionSource attributionSource) throws RemoteException { - if (!Utils.checkScanPermissionForDataDelivery( - this, attributionSource, "GattService registerScanner")) { - return; - } - - UUID uuid = UUID.randomUUID(); - if (DBG) { - Log.d(TAG, "registerScanner() - UUID=" + uuid); - } - - enforceImpersonatationPermissionIfNeeded(workSource); - - AppScanStats app = mTransitionalScanHelper.getScannerMap() - .getAppScanStatsByUid(Binder.getCallingUid()); - if (app != null && app.isScanningTooFrequently() - && !Utils.checkCallerHasPrivilegedPermission(this)) { - Log.e(TAG, "App '" + app.appName + "' is scanning too frequently"); - callback.onScannerRegistered(ScanCallback.SCAN_FAILED_SCANNING_TOO_FREQUENTLY, -1); - return; - } - - mTransitionalScanHelper - .getScannerMap().add(uuid, workSource, callback, null, this); - mScanManager.registerScanner(uuid); - } - - @RequiresPermission(android.Manifest.permission.BLUETOOTH_SCAN) - public void unregisterScanner(int scannerId, AttributionSource attributionSource) { - if (!Utils.checkScanPermissionForDataDelivery( - this, attributionSource, "GattService unregisterScanner")) { - return; - } - - if (DBG) { - Log.d(TAG, "unregisterScanner() - scannerId=" + scannerId); - } - mTransitionalScanHelper.getScannerMap().remove(scannerId); - mScanManager.unregisterScanner(scannerId); - } - - private List<String> getAssociatedDevices(String callingPackage) { - if (mCompanionManager == null) { - return Collections.emptyList(); - } - - List<String> macAddresses = new ArrayList(); - - final long identity = Binder.clearCallingIdentity(); - try { - for (AssociationInfo info : Utils.getCdmAssociations(mCompanionManager)) { - if (info.getPackageName().equals(callingPackage) && !info.isSelfManaged() - && info.getDeviceMacAddress() != null) { - macAddresses.add(info.getDeviceMacAddress().toString()); - } - } - } catch (SecurityException se) { - // Not an app with associated devices - } catch (Exception e) { - Log.e(TAG, "Cannot check device associations for " + callingPackage, e); - } finally { - Binder.restoreCallingIdentity(identity); - } - return macAddresses; - } - - @RequiresPermission(android.Manifest.permission.BLUETOOTH_SCAN) - void startScan(int scannerId, ScanSettings settings, List<ScanFilter> filters, - AttributionSource attributionSource) { - if (DBG) { - Log.d(TAG, "start scan with filters"); - } - - if (!Utils.checkScanPermissionForDataDelivery( - this, attributionSource, "Starting GATT scan.")) { - return; - } - - enforcePrivilegedPermissionIfNeeded(settings); - String callingPackage = attributionSource.getPackageName(); - settings = enforceReportDelayFloor(settings); - enforcePrivilegedPermissionIfNeeded(filters); - final ScanClient scanClient = new ScanClient(scannerId, settings, filters); - scanClient.userHandle = Binder.getCallingUserHandle(); - mAppOps.checkPackage(Binder.getCallingUid(), callingPackage); - scanClient.eligibleForSanitizedExposureNotification = - callingPackage.equals(mExposureNotificationPackage); - - scanClient.hasDisavowedLocation = - Utils.hasDisavowedLocationForScan(this, attributionSource, isTestModeEnabled()); - - scanClient.isQApp = checkCallerTargetSdk(this, callingPackage, Build.VERSION_CODES.Q); - if (!scanClient.hasDisavowedLocation) { - if (scanClient.isQApp) { - scanClient.hasLocationPermission = Utils.checkCallerHasFineLocation( - this, attributionSource, scanClient.userHandle); - } else { - scanClient.hasLocationPermission = Utils.checkCallerHasCoarseOrFineLocation( - this, attributionSource, scanClient.userHandle); - } - } - scanClient.hasNetworkSettingsPermission = - Utils.checkCallerHasNetworkSettingsPermission(this); - scanClient.hasNetworkSetupWizardPermission = - Utils.checkCallerHasNetworkSetupWizardPermission(this); - scanClient.hasScanWithoutLocationPermission = - Utils.checkCallerHasScanWithoutLocationPermission(this); - scanClient.associatedDevices = getAssociatedDevices(callingPackage); - - AppScanStats app = mTransitionalScanHelper.getScannerMap().getAppScanStatsById(scannerId); - ContextMap.App cbApp = mTransitionalScanHelper.getScannerMap().getById(scannerId); - if (app != null) { - scanClient.stats = app; - boolean isFilteredScan = (filters != null) && !filters.isEmpty(); - boolean isCallbackScan = false; - if (cbApp != null) { - isCallbackScan = cbApp.callback != null; - } - app.recordScanStart(settings, filters, isFilteredScan, isCallbackScan, scannerId); - } - - mScanManager.startScan(scanClient); - } - - @RequiresPermission(android.Manifest.permission.BLUETOOTH_SCAN) - void registerPiAndStartScan(PendingIntent pendingIntent, ScanSettings settings, - List<ScanFilter> filters, AttributionSource attributionSource) { - if (DBG) { - Log.d(TAG, "start scan with filters, for PendingIntent"); - } - - if (!Utils.checkScanPermissionForDataDelivery( - this, attributionSource, "Starting GATT scan.")) { - return; - } - enforcePrivilegedPermissionIfNeeded(settings); - settings = enforceReportDelayFloor(settings); - enforcePrivilegedPermissionIfNeeded(filters); - UUID uuid = UUID.randomUUID(); - String callingPackage = attributionSource.getPackageName(); - int callingUid = attributionSource.getUid(); - PendingIntentInfo piInfo = new PendingIntentInfo(); - piInfo.intent = pendingIntent; - piInfo.settings = settings; - piInfo.filters = filters; - piInfo.callingPackage = callingPackage; - piInfo.callingUid = callingUid; - if (DBG) { - Log.d( - TAG, - "startScan(PI) -" - + (" UUID=" + uuid) - + (" Package=" + callingPackage) - + (" UID=" + callingUid)); - } - - // Don't start scan if the Pi scan already in mScannerMap. - if (mTransitionalScanHelper.getScannerMap().getByContextInfo(piInfo) != null) { - Log.d(TAG, "Don't startScan(PI) since the same Pi scan already in mScannerMap."); - return; - } - - ContextMap.App app = - mTransitionalScanHelper.getScannerMap().add(uuid, null, null, piInfo, this); - - app.mUserHandle = UserHandle.getUserHandleForUid(Binder.getCallingUid()); - mAppOps.checkPackage(Binder.getCallingUid(), callingPackage); - app.mEligibleForSanitizedExposureNotification = - callingPackage.equals(mExposureNotificationPackage); - - app.mHasDisavowedLocation = - Utils.hasDisavowedLocationForScan(this, attributionSource, isTestModeEnabled()); - - if (!app.mHasDisavowedLocation) { - try { - if (checkCallerTargetSdk(this, callingPackage, Build.VERSION_CODES.Q)) { - app.hasLocationPermission = Utils.checkCallerHasFineLocation( - this, attributionSource, app.mUserHandle); - } else { - app.hasLocationPermission = Utils.checkCallerHasCoarseOrFineLocation( - this, attributionSource, app.mUserHandle); - } - } catch (SecurityException se) { - // No need to throw here. Just mark as not granted. - app.hasLocationPermission = false; - } - } - app.mHasNetworkSettingsPermission = - Utils.checkCallerHasNetworkSettingsPermission(this); - app.mHasNetworkSetupWizardPermission = - Utils.checkCallerHasNetworkSetupWizardPermission(this); - app.mHasScanWithoutLocationPermission = - Utils.checkCallerHasScanWithoutLocationPermission(this); - app.mAssociatedDevices = getAssociatedDevices(callingPackage); - mScanManager.registerScanner(uuid); - - // If this fails, we should stop the scan immediately. - if (!pendingIntent.addCancelListener(Runnable::run, mScanIntentCancelListener)) { - Log.d(TAG, "scanning PendingIntent is already cancelled, stopping scan."); - stopScan(pendingIntent, attributionSource); - } - } - - void continuePiStartScan(int scannerId, TransitionalScanHelper.ScannerMap.App app) { - final PendingIntentInfo piInfo = app.info; - final ScanClient scanClient = - new ScanClient(scannerId, piInfo.settings, piInfo.filters, piInfo.callingUid); - scanClient.hasLocationPermission = app.hasLocationPermission; - scanClient.userHandle = app.mUserHandle; - scanClient.isQApp = checkCallerTargetSdk(this, app.name, Build.VERSION_CODES.Q); - scanClient.eligibleForSanitizedExposureNotification = - app.mEligibleForSanitizedExposureNotification; - scanClient.hasNetworkSettingsPermission = app.mHasNetworkSettingsPermission; - scanClient.hasNetworkSetupWizardPermission = app.mHasNetworkSetupWizardPermission; - scanClient.hasScanWithoutLocationPermission = app.mHasScanWithoutLocationPermission; - scanClient.associatedDevices = app.mAssociatedDevices; - scanClient.hasDisavowedLocation = app.mHasDisavowedLocation; - - AppScanStats scanStats = - mTransitionalScanHelper.getScannerMap().getAppScanStatsById(scannerId); - if (scanStats != null) { - scanClient.stats = scanStats; - boolean isFilteredScan = (piInfo.filters != null) && !piInfo.filters.isEmpty(); - scanStats.recordScanStart( - piInfo.settings, piInfo.filters, isFilteredScan, false, scannerId); - } - - mScanManager.startScan(scanClient); - } - - @RequiresPermission(android.Manifest.permission.BLUETOOTH_SCAN) - void flushPendingBatchResults(int scannerId, AttributionSource attributionSource) { - if (!Utils.checkScanPermissionForDataDelivery( - this, attributionSource, "GattService flushPendingBatchResults")) { - return; - } - if (DBG) { - Log.d(TAG, "flushPendingBatchResults - scannerId=" + scannerId); - } - mScanManager.flushBatchScanResults(new ScanClient(scannerId)); - } - - @RequiresPermission(android.Manifest.permission.BLUETOOTH_SCAN) - void stopScan(int scannerId, AttributionSource attributionSource) { - if (!Utils.checkScanPermissionForDataDelivery( - this, attributionSource, "GattService stopScan")) { - return; - } - int scanQueueSize = - mScanManager.getBatchScanQueue().size() + mScanManager.getRegularScanQueue().size(); - if (DBG) { - Log.d(TAG, "stopScan() - queue size =" + scanQueueSize); - } - - AppScanStats app = null; - app = mTransitionalScanHelper.getScannerMap().getAppScanStatsById(scannerId); - if (app != null) { - app.recordScanStop(scannerId); - } - - mScanManager.stopScan(scannerId); - } - - @RequiresPermission(android.Manifest.permission.BLUETOOTH_SCAN) - void stopScan(PendingIntent intent, AttributionSource attributionSource) { - if (!Utils.checkScanPermissionForDataDelivery( - this, attributionSource, "GattService stopScan")) { - return; - } - PendingIntentInfo pii = new PendingIntentInfo(); - pii.intent = intent; - ContextMap.App app = mTransitionalScanHelper.getScannerMap().getByContextInfo(pii); - if (VDBG) { - Log.d(TAG, "stopScan(PendingIntent): app found = " + app); - } - if (app != null) { - intent.removeCancelListener(mScanIntentCancelListener); - final int scannerId = app.id; - stopScan(scannerId, attributionSource); - // Also unregister the scanner - unregisterScanner(scannerId, attributionSource); - } - } - @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) void disconnectAll(AttributionSource attributionSource) { if (DBG) { @@ -3515,48 +2357,6 @@ public class GattService extends ProfileService { } /************************************************************************** - * PERIODIC SCANNING - *************************************************************************/ - @RequiresPermission(android.Manifest.permission.BLUETOOTH_SCAN) - void registerSync(ScanResult scanResult, int skip, int timeout, - IPeriodicAdvertisingCallback callback, AttributionSource attributionSource) { - if (!Utils.checkScanPermissionForDataDelivery( - this, attributionSource, "GattService registerSync")) { - return; - } - mPeriodicScanManager.startSync(scanResult, skip, timeout, callback); - } - - @RequiresPermission(android.Manifest.permission.BLUETOOTH_SCAN) - void unregisterSync( - IPeriodicAdvertisingCallback callback, AttributionSource attributionSource) { - if (!Utils.checkScanPermissionForDataDelivery( - this, attributionSource, "GattService unregisterSync")) { - return; - } - mPeriodicScanManager.stopSync(callback); - } - - void transferSync(BluetoothDevice bda, int serviceData, int syncHandle, - AttributionSource attributionSource) { - if (!Utils.checkScanPermissionForDataDelivery( - this, attributionSource, "GattService transferSync")) { - return; - } - mPeriodicScanManager.transferSync(bda, serviceData, syncHandle); - } - - void transferSetInfo(BluetoothDevice bda, int serviceData, - int advHandle, IPeriodicAdvertisingCallback callback, - AttributionSource attributionSource) { - if (!Utils.checkScanPermissionForDataDelivery( - this, attributionSource, "GattService transferSetInfo")) { - return; - } - mPeriodicScanManager.transferSetInfo(bda, serviceData, advHandle, callback); - } - - /************************************************************************** * ADVERTISING SET *************************************************************************/ @RequiresPermission(android.Manifest.permission.BLUETOOTH_ADVERTISE) @@ -3712,7 +2512,7 @@ public class GattService extends ProfileService { if (DBG) { Log.d(TAG, "registerClient() - UUID=" + uuid); } - mClientMap.add(uuid, null, callback, null, this); + mClientMap.add(uuid, null, callback, null, this, mTransitionalScanHelper); mNativeInterface.gattClientRegisterApp(uuid.getLeastSignificantBits(), uuid.getMostSignificantBits(), eatt_support); } @@ -3822,7 +2622,7 @@ public class GattService extends ProfileService { return 0; } return (AdapterService.getAdapterService().getTotalNumOfTrackableAdvertisements() - - mScanManager.getCurrentUsedTrackingAdvertisement()); + - mTransitionalScanHelper.getCurrentUsedTrackingAdvertisement()); } @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) @@ -4608,7 +3408,7 @@ public class GattService extends ProfileService { if (DBG) { Log.d(TAG, "registerServer() - UUID=" + uuid); } - mServerMap.add(uuid, null, callback, null, this); + mServerMap.add(uuid, null, callback, null, this, mTransitionalScanHelper); mNativeInterface.gattServerRegisterApp(uuid.getLeastSignificantBits(), uuid.getMostSignificantBits(), eatt_support); } @@ -4878,87 +3678,6 @@ public class GattService extends ProfileService { return type; } - private boolean needsPrivilegedPermissionForScan(ScanSettings settings) { - // BLE scan only mode needs special permission. - if (mAdapterService.getState() != BluetoothAdapter.STATE_ON) { - return true; - } - - // Regular scan, no special permission. - if (settings == null) { - return false; - } - - // Ambient discovery mode, needs privileged permission. - if (settings.getScanMode() == ScanSettings.SCAN_MODE_AMBIENT_DISCOVERY) { - return true; - } - - // Regular scan, no special permission. - if (settings.getReportDelayMillis() == 0) { - return false; - } - - // Batch scan, truncated mode needs permission. - return settings.getScanResultType() == ScanSettings.SCAN_RESULT_TYPE_ABBREVIATED; - } - - /* - * The {@link ScanFilter#setDeviceAddress} API overloads are @SystemApi access methods. This - * requires that the permissions be BLUETOOTH_PRIVILEGED. - */ - @SuppressLint("AndroidFrameworkRequiresPermission") - private void enforcePrivilegedPermissionIfNeeded(List<ScanFilter> filters) { - if (DBG) { - Log.d(TAG, "enforcePrivilegedPermissionIfNeeded(" + filters + ")"); - } - // Some 3p API cases may have null filters, need to allow - if (filters != null) { - for (ScanFilter filter : filters) { - // The only case to enforce here is if there is an address - // If there is an address, enforce if the correct combination criteria is met. - if (filter.getDeviceAddress() != null) { - // At this point we have an address, that means a caller used the - // setDeviceAddress(address) public API for the ScanFilter - // We don't want to enforce if the type is PUBLIC and the IRK is null - // However, if we have a different type that means the caller used a new - // @SystemApi such as setDeviceAddress(address, type) or - // setDeviceAddress(address, type, irk) which are both @SystemApi and require - // permissions to be enforced - if (filter.getAddressType() - == BluetoothDevice.ADDRESS_TYPE_PUBLIC && filter.getIrk() == null) { - // Do not enforce - } else { - enforceBluetoothPrivilegedPermission(this); - } - } - } - } - } - - @SuppressLint("AndroidFrameworkRequiresPermission") - private void enforcePrivilegedPermissionIfNeeded(ScanSettings settings) { - if (needsPrivilegedPermissionForScan(settings)) { - enforceBluetoothPrivilegedPermission(this); - } - } - - // Enforce caller has UPDATE_DEVICE_STATS permission, which allows the caller to blame other - // apps for Bluetooth usage. A {@link SecurityException} will be thrown if the caller app does - // not have UPDATE_DEVICE_STATS permission. - @RequiresPermission(android.Manifest.permission.UPDATE_DEVICE_STATS) - private void enforceImpersonatationPermission() { - enforceCallingOrSelfPermission(android.Manifest.permission.UPDATE_DEVICE_STATS, - "Need UPDATE_DEVICE_STATS permission"); - } - - @SuppressLint("AndroidFrameworkRequiresPermission") - private void enforceImpersonatationPermissionIfNeeded(WorkSource workSource) { - if (workSource != null) { - enforceImpersonatationPermission(); - } - } - private void logClientForegroundInfo(int uid, boolean isDirect) { if (mPackageManager == null) { return; @@ -5015,45 +3734,6 @@ public class GattService extends ProfileService { } } - /** - * Ensures the report delay is either 0 or at least the floor value (5000ms) - * - * @param settings are the scan settings passed into a request to start le scanning - * @return the passed in ScanSettings object if the report delay is 0 or above the floor value; - * a new ScanSettings object with the report delay being the floor value if the original - * report delay was between 0 and the floor value (exclusive of both) - */ - @VisibleForTesting - ScanSettings enforceReportDelayFloor(ScanSettings settings) { - if (settings.getReportDelayMillis() == 0) { - return settings; - } - - // Need to clear identity to pass device config permission check - final long callerToken = Binder.clearCallingIdentity(); - try { - long floor = DeviceConfig.getLong(DeviceConfig.NAMESPACE_BLUETOOTH, "report_delay", - DEFAULT_REPORT_DELAY_FLOOR); - - if (settings.getReportDelayMillis() > floor) { - return settings; - } else { - return new ScanSettings.Builder() - .setCallbackType(settings.getCallbackType()) - .setLegacy(settings.getLegacy()) - .setMatchMode(settings.getMatchMode()) - .setNumOfMatches(settings.getNumOfMatches()) - .setPhy(settings.getPhy()) - .setReportDelay(floor) - .setScanMode(settings.getScanMode()) - .setScanResultType(settings.getScanResultType()) - .build(); - } - } finally { - Binder.restoreCallingIdentity(callerToken); - } - } - private void stopNextService(int serverIf, int status) throws RemoteException { if (DBG) { Log.d(TAG, "stopNextService() - serverIf=" + serverIf + ", status=" + status); @@ -5122,8 +3802,6 @@ public class GattService extends ProfileService { println(sb, " " + uuid); } - println(sb, "mMaxScanFilters: " + mMaxScanFilters); - sb.append("\nRegistered App\n"); dumpRegisterId(sb); @@ -5143,15 +3821,6 @@ public class GattService extends ProfileService { mHandleMap.dump(sb); } - public void addScanEvent(BluetoothMetricsProto.ScanEvent event) { - synchronized (mScanEvents) { - if (mScanEvents.size() == NUM_SCAN_EVENTS_KEPT) { - mScanEvents.remove(); - } - mScanEvents.add(event); - } - } - private void statsLogAppPackage(String address, int applicationUid, int sessionIndex) { BluetoothDevice device = BluetoothAdapter.getDefaultAdapter().getRemoteDevice(address); BluetoothStatsLog.write( @@ -5181,9 +3850,7 @@ public class GattService extends ProfileService { @Override public void dumpProto(BluetoothMetricsProto.BluetoothLog.Builder builder) { - synchronized (mScanEvents) { - builder.addAllScanEvent(mScanEvents); - } + mTransitionalScanHelper.dumpProto(builder); } /************************************************************************** diff --git a/android/app/src/com/android/bluetooth/hearingaid/HearingAidService.java b/android/app/src/com/android/bluetooth/hearingaid/HearingAidService.java index 5937b07dd6..3d85f02dd2 100644 --- a/android/app/src/com/android/bluetooth/hearingaid/HearingAidService.java +++ b/android/app/src/com/android/bluetooth/hearingaid/HearingAidService.java @@ -954,15 +954,17 @@ public class HearingAidService extends ProfileService { @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) private HearingAidService getService(AttributionSource source) { + // Cache mService because it can change while getService is called b/327929337 + HearingAidService service = mService; if (mIsTesting) { - return mService; + return service; } - if (!Utils.checkServiceAvailable(mService, TAG) - || !Utils.checkCallerIsSystemOrActiveOrManagedUser(mService, TAG) - || !Utils.checkConnectPermissionForDataDelivery(mService, source, TAG)) { + if (!Utils.checkServiceAvailable(service, TAG) + || !Utils.checkCallerIsSystemOrActiveOrManagedUser(service, TAG) + || !Utils.checkConnectPermissionForDataDelivery(service, source, TAG)) { return null; } - return mService; + return service; } BluetoothHearingAidBinder(HearingAidService svc) { diff --git a/android/app/src/com/android/bluetooth/hfp/HeadsetService.java b/android/app/src/com/android/bluetooth/hfp/HeadsetService.java index ed8c462109..985ac9de81 100644 --- a/android/app/src/com/android/bluetooth/hfp/HeadsetService.java +++ b/android/app/src/com/android/bluetooth/hfp/HeadsetService.java @@ -76,6 +76,7 @@ import java.util.HashMap; import java.util.List; import java.util.Objects; import java.util.Optional; +import java.util.concurrent.FutureTask; /** * Provides Bluetooth Headset and Handsfree profile, as a service in the Bluetooth application. @@ -1889,7 +1890,8 @@ public class HeadsetService extends ProfileService { mSystemInterface.getHeadsetPhoneState().setCallState(callState); // Suspend A2DP when call about is about to become active if (mActiveDevice != null && callState != HeadsetHalConstants.CALL_STATE_DISCONNECTED - && !mSystemInterface.isCallIdle() && isCallIdleBefore) { + && !mSystemInterface.isCallIdle() && isCallIdleBefore + && !Flags.isScoManagedByAudio()) { mSystemInterface.getAudioManager().setA2dpSuspended(true); if (isAtLeastU()) { mSystemInterface.getAudioManager().setLeAudioSuspended(true); @@ -1899,9 +1901,25 @@ public class HeadsetService extends ProfileService { doForEachConnectedStateMachine( stateMachine -> stateMachine.sendMessage(HeadsetStateMachine.CALL_STATE_CHANGED, new HeadsetCallState(numActive, numHeld, callState, number, type, name))); + if (Flags.isScoManagedByAudio()) { + if (mActiveDevice == null) { + Log.i(TAG, "HeadsetService's active device is null"); + } else { + // wait until mActiveDevice's state machine processed CALL_STATE_CHANGED message, + // then Audio Framework starts the SCO connection + FutureTask task = new FutureTask(() -> {}, null); + mStateMachines.get(mActiveDevice).getHandler().post(task); + try { + task.get(); + } catch (Exception e) { + Log.e(TAG, + "Exception when waiting for CALL_STATE_CHANGED message" + e.toString()); + } + } + } getStateMachinesThreadHandler().post(() -> { if (callState == HeadsetHalConstants.CALL_STATE_IDLE - && mSystemInterface.isCallIdle() && !isAudioOn()) { + && mSystemInterface.isCallIdle() && !isAudioOn() && !Flags.isScoManagedByAudio()) { // Resume A2DP when call ended and SCO is not connected mSystemInterface.getAudioManager().setA2dpSuspended(false); if (isAtLeastU()) { diff --git a/android/app/src/com/android/bluetooth/gatt/AdvtFilterOnFoundOnLostInfo.java b/android/app/src/com/android/bluetooth/le_scan/AdvtFilterOnFoundOnLostInfo.java index c16f8269ba..5db51efb79 100644 --- a/android/app/src/com/android/bluetooth/gatt/AdvtFilterOnFoundOnLostInfo.java +++ b/android/app/src/com/android/bluetooth/le_scan/AdvtFilterOnFoundOnLostInfo.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.android.bluetooth.gatt; +package com.android.bluetooth.le_scan; import android.annotation.Nullable; diff --git a/android/app/src/com/android/bluetooth/le_scan/AppScanStats.java b/android/app/src/com/android/bluetooth/le_scan/AppScanStats.java index e2ce19a0b7..1851ecef9a 100644 --- a/android/app/src/com/android/bluetooth/le_scan/AppScanStats.java +++ b/android/app/src/com/android/bluetooth/le_scan/AppScanStats.java @@ -19,6 +19,7 @@ package com.android.bluetooth.le_scan; import android.bluetooth.BluetoothProtoEnums; import android.bluetooth.le.ScanFilter; import android.bluetooth.le.ScanSettings; +import android.content.Context; import android.os.BatteryStatsManager; import android.os.Binder; import android.os.SystemClock; @@ -29,7 +30,6 @@ import com.android.bluetooth.BluetoothStatsLog; import com.android.bluetooth.btservice.AdapterService; import com.android.bluetooth.btservice.MetricsLogger; import com.android.bluetooth.gatt.ContextMap; -import com.android.bluetooth.gatt.GattService; import com.android.bluetooth.util.WorkSourceUtil; import com.android.internal.annotations.GuardedBy; @@ -66,8 +66,8 @@ public class AppScanStats { // ContextMap here is needed to grab Apps and Connections ContextMap mContextMap; - // GattService is needed to add scan event protos to be dumped later - final GattService mGattService; + // TransitionalScanHelper is needed to add scan event protos to be dumped later + final TransitionalScanHelper mScanHelper; // Battery stats is used to keep track of scans and result stats BatteryStatsManager mBatteryStatsManager; @@ -149,11 +149,16 @@ public class AppScanStats { private long stopTime = 0; private int results = 0; - public AppScanStats(String name, WorkSource source, ContextMap map, GattService service) { + public AppScanStats( + String name, + WorkSource source, + ContextMap map, + Context context, + TransitionalScanHelper scanHelper) { appName = name; mContextMap = map; - mGattService = service; - mBatteryStatsManager = service.getSystemService(BatteryStatsManager.class); + mScanHelper = scanHelper; + mBatteryStatsManager = context.getSystemService(BatteryStatsManager.class); if (source == null) { // Bill the caller if the work source isn't passed through @@ -263,7 +268,7 @@ public class AppScanStats { BluetoothMetricsProto.ScanEvent.ScanTechnologyType.SCAN_TECH_TYPE_LE) .setEventTimeMillis(System.currentTimeMillis()) .setInitiator(truncateAppName(appName)).build(); - mGattService.addScanEvent(scanEvent); + mScanHelper.addScanEvent(scanEvent); if (!isScanning()) { mScanStartTime = startTime; @@ -308,7 +313,7 @@ public class AppScanStats { .setInitiator(truncateAppName(appName)) .setNumberResults(scan.results) .build(); - mGattService.addScanEvent(scanEvent); + mScanHelper.addScanEvent(scanEvent); mTotalScanTime += scanDuration; long activeDuration = scanDuration - scan.suspendDuration; diff --git a/android/app/src/com/android/bluetooth/le_scan/ScanManager.java b/android/app/src/com/android/bluetooth/le_scan/ScanManager.java index f39115a34e..162633f5e6 100644 --- a/android/app/src/com/android/bluetooth/le_scan/ScanManager.java +++ b/android/app/src/com/android/bluetooth/le_scan/ScanManager.java @@ -49,7 +49,6 @@ import com.android.bluetooth.btservice.BluetoothAdapterProxy; import com.android.bluetooth.flags.Flags; import com.android.bluetooth.gatt.FilterParams; import com.android.bluetooth.gatt.GattObjectsFactory; -import com.android.bluetooth.gatt.GattService; import com.android.bluetooth.gatt.GattServiceConfig; import com.android.internal.annotations.GuardedBy; import com.android.internal.annotations.VisibleForTesting; @@ -88,9 +87,9 @@ public class ScanManager { public static final int SCAN_MODE_SCREEN_OFF_BALANCED_WINDOW_MS = 183; public static final int SCAN_MODE_SCREEN_OFF_BALANCED_INTERVAL_MS = 730; - // Result type defined in bt stack. Need to be accessed by GattService. - public static final int SCAN_RESULT_TYPE_TRUNCATED = 1; - public static final int SCAN_RESULT_TYPE_FULL = 2; + // Result type defined in bt stack. Need to be accessed by TransitionalScanHelper. + static final int SCAN_RESULT_TYPE_TRUNCATED = 1; + static final int SCAN_RESULT_TYPE_FULL = 2; static final int SCAN_RESULT_TYPE_BOTH = 3; // Messages for handling BLE scan operations. @@ -123,7 +122,8 @@ public class ScanManager { @GuardedBy("mCurUsedTrackableAdvertisementsLock") private int mCurUsedTrackableAdvertisements = 0; - private final GattService mService; + private final Context mContext; + private final TransitionalScanHelper mScanHelper; private final AdapterService mAdapterService; private BroadcastReceiver mBatchAlarmReceiver; private boolean mBatchAlarmReceiverRegistered; @@ -164,7 +164,8 @@ public class ScanManager { } public ScanManager( - GattService service, + Context context, + TransitionalScanHelper scanHelper, AdapterService adapterService, BluetoothAdapterProxy bluetoothAdapterProxy, Looper looper) { @@ -173,11 +174,12 @@ public class ScanManager { mBatchClients = Collections.newSetFromMap(new ConcurrentHashMap<ScanClient, Boolean>()); mSuspendedScanClients = Collections.newSetFromMap(new ConcurrentHashMap<ScanClient, Boolean>()); - mService = service; + mContext = context; + mScanHelper = scanHelper; mAdapterService = adapterService; mScanNative = new ScanNative(); - mDm = mService.getSystemService(DisplayManager.class); - mActivityManager = mService.getSystemService(ActivityManager.class); + mDm = mContext.getSystemService(DisplayManager.class); + mActivityManager = mContext.getSystemService(ActivityManager.class); mLocationManager = mAdapterService.getSystemService(LocationManager.class); mBluetoothAdapterProxy = bluetoothAdapterProxy; mIsConnecting = false; @@ -204,7 +206,7 @@ public class ScanManager { } IntentFilter locationIntentFilter = new IntentFilter(LocationManager.MODE_CHANGED_ACTION); locationIntentFilter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY); - mService.registerReceiver(mLocationReceiver, locationIntentFilter); + mContext.registerReceiver(mLocationReceiver, locationIntentFilter); } public void cleanup() { @@ -236,7 +238,7 @@ public class ScanManager { } try { - mService.unregisterReceiver(mLocationReceiver); + mContext.unregisterReceiver(mLocationReceiver); } catch (IllegalArgumentException e) { Log.w(TAG, "exception when invoking unregisterReceiver(mLocationReceiver)", e); } @@ -523,7 +525,7 @@ public class ScanManager { if (DBG) { Log.d(TAG, "app died, unregister scanner - " + client.scannerId); } - mService.unregisterScanner(client.scannerId, mService.getAttributionSource()); + mScanHelper.unregisterScanner(client.scannerId, mContext.getAttributionSource()); } } @@ -1023,10 +1025,11 @@ public class ScanManager { mFilterIndexStack = new ArrayDeque<Integer>(); mClientFilterIndexMap = new HashMap<Integer, Deque<Integer>>(); - mAlarmManager = mService.getSystemService(AlarmManager.class); + mAlarmManager = mContext.getSystemService(AlarmManager.class); Intent batchIntent = new Intent(ACTION_REFRESH_BATCHED_SCAN, null); - mBatchScanIntervalIntent = PendingIntent.getBroadcast(mService, 0, batchIntent, - PendingIntent.FLAG_IMMUTABLE); + mBatchScanIntervalIntent = + PendingIntent.getBroadcast( + mContext, 0, batchIntent, PendingIntent.FLAG_IMMUTABLE); IntentFilter filter = new IntentFilter(); filter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY); filter.addAction(ACTION_REFRESH_BATCHED_SCAN); @@ -1047,7 +1050,7 @@ public class ScanManager { } } }; - mService.registerReceiver(mBatchAlarmReceiver, filter); + mContext.registerReceiver(mBatchAlarmReceiver, filter); mBatchAlarmReceiverRegistered = true; } @@ -1292,7 +1295,7 @@ public class ScanManager { // infrequently anyway. To avoid redefining paramete sets, map to the low duty cycle // parameter set as follows. private int getBatchScanWindowMillis(int scanMode) { - ContentResolver resolver = mService.getContentResolver(); + ContentResolver resolver = mContext.getContentResolver(); switch (scanMode) { case ScanSettings.SCAN_MODE_LOW_LATENCY: return Settings.Global.getInt( @@ -1310,7 +1313,7 @@ public class ScanManager { } private int getBatchScanIntervalMillis(int scanMode) { - ContentResolver resolver = mService.getContentResolver(); + ContentResolver resolver = mContext.getContentResolver(); switch (scanMode) { case ScanSettings.SCAN_MODE_LOW_LATENCY: return Settings.Global.getInt( @@ -1357,8 +1360,8 @@ public class ScanManager { Log.e(TAG, "Error freeing for onfound/onlost filter resources " + entriesToFree); try { - mService.onScanManagerErrorCallback(client.scannerId, - ScanCallback.SCAN_FAILED_INTERNAL_ERROR); + mScanHelper.onScanManagerErrorCallback( + client.scannerId, ScanCallback.SCAN_FAILED_INTERNAL_ERROR); } catch (RemoteException e) { Log.e(TAG, "failed on onScanManagerCallback at freeing", e); } @@ -1480,7 +1483,7 @@ public class ScanManager { mAlarmManager.cancel(mBatchScanIntervalIntent); // Protect against multiple calls of cleanup. if (mBatchAlarmReceiverRegistered) { - mService.unregisterReceiver(mBatchAlarmReceiver); + mContext.unregisterReceiver(mBatchAlarmReceiver); } mBatchAlarmReceiverRegistered = false; } @@ -1547,8 +1550,8 @@ public class ScanManager { + trackEntries); client.stats.recordTrackingHwFilterNotAvailableCountMetrics(); try { - mService.onScanManagerErrorCallback(scannerId, - ScanCallback.SCAN_FAILED_INTERNAL_ERROR); + mScanHelper.onScanManagerErrorCallback( + scannerId, ScanCallback.SCAN_FAILED_INTERNAL_ERROR); } catch (RemoteException e) { Log.e(TAG, "failed on onScanManagerCallback", e); } @@ -1706,7 +1709,7 @@ public class ScanManager { } private int getScanWindowMillis(ScanSettings settings) { - ContentResolver resolver = mService.getContentResolver(); + ContentResolver resolver = mContext.getContentResolver(); if (settings == null) { return Settings.Global.getInt( resolver, @@ -1744,7 +1747,7 @@ public class ScanManager { } private int getScanIntervalMillis(ScanSettings settings) { - ContentResolver resolver = mService.getContentResolver(); + ContentResolver resolver = mContext.getContentResolver(); if (settings == null) { return Settings.Global.getInt( resolver, @@ -1919,8 +1922,7 @@ public class ScanManager { new ActivityManager.OnUidImportanceListener() { @Override public void onUidImportance(final int uid, final int importance) { - if (mService.mTransitionalScanHelper.getScannerMap().getAppScanStatsByUid(uid) - != null) { + if (mScanHelper.getScannerMap().getAppScanStatsByUid(uid) != null) { Message message = new Message(); message.what = MSG_IMPORTANCE_CHANGE; message.obj = new UidImportance(uid, importance); diff --git a/android/app/src/com/android/bluetooth/le_scan/TransitionalScanHelper.java b/android/app/src/com/android/bluetooth/le_scan/TransitionalScanHelper.java index 913cc40478..35cceca4b9 100644 --- a/android/app/src/com/android/bluetooth/le_scan/TransitionalScanHelper.java +++ b/android/app/src/com/android/bluetooth/le_scan/TransitionalScanHelper.java @@ -16,12 +16,63 @@ package com.android.bluetooth.le_scan; +import static com.android.bluetooth.Utils.checkCallerTargetSdk; +import static com.android.bluetooth.Utils.enforceBluetoothPrivilegedPermission; + +import android.annotation.RequiresPermission; +import android.annotation.SuppressLint; +import android.app.AppOpsManager; +import android.app.PendingIntent; +import android.bluetooth.BluetoothAdapter; +import android.bluetooth.BluetoothDevice; +import android.bluetooth.le.BluetoothLeScanner; +import android.bluetooth.le.IPeriodicAdvertisingCallback; import android.bluetooth.le.IScannerCallback; +import android.bluetooth.le.ScanCallback; +import android.bluetooth.le.ScanFilter; +import android.bluetooth.le.ScanRecord; +import android.bluetooth.le.ScanResult; +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.net.MacAddress; +import android.os.Binder; +import android.os.Build; +import android.os.IBinder; +import android.os.Looper; +import android.os.RemoteException; +import android.os.SystemClock; +import android.os.UserHandle; +import android.os.WorkSource; +import android.provider.DeviceConfig; +import android.util.Log; +import com.android.bluetooth.BluetoothMetricsProto; +import com.android.bluetooth.R; +import com.android.bluetooth.Utils; +import com.android.bluetooth.btservice.AdapterService; +import com.android.bluetooth.btservice.BluetoothAdapterProxy; +import com.android.bluetooth.flags.Flags; import com.android.bluetooth.gatt.ContextMap; -import com.android.bluetooth.gatt.GattService; +import com.android.bluetooth.gatt.GattObjectsFactory; +import com.android.bluetooth.gatt.GattServiceConfig; +import com.android.bluetooth.util.NumberUtils; import com.android.internal.annotations.VisibleForTesting; +import java.util.ArrayDeque; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import java.util.UUID; +import java.util.concurrent.TimeUnit; +import java.util.function.Predicate; + /** * A helper class which contains all scan related functions extracted from {@link * com.android.bluetooth.gatt.GattService}. The purpose of this class is to preserve scan @@ -31,12 +82,102 @@ import com.android.internal.annotations.VisibleForTesting; * @hide */ public class TransitionalScanHelper { + private static final boolean DBG = GattServiceConfig.DBG; + private static final boolean VDBG = GattServiceConfig.VDBG; + private static final String TAG = GattServiceConfig.TAG_PREFIX + "ScanHelper"; + + // Batch scan related constants. + private static final int TRUNCATED_RESULT_SIZE = 11; + private static final int TIME_STAMP_LENGTH = 2; + + static final int SCAN_FILTER_ENABLED = 1; + static final int SCAN_FILTER_MODIFIED = 2; + + /** The default floor value for LE batch scan report delays greater than 0 */ + @VisibleForTesting static final long DEFAULT_REPORT_DELAY_FLOOR = 5000; + + private static final int NUM_SCAN_EVENTS_KEPT = 20; + + // onFoundLost related constants + private static final int ADVT_STATE_ONFOUND = 0; + private static final int ADVT_STATE_ONLOST = 1; + + private static final int ET_LEGACY_MASK = 0x10; /** List of our registered scanners. */ - public static class ScannerMap - extends ContextMap<IScannerCallback, GattService.PendingIntentInfo> {} + // TODO(b/327849650): Remove as this class adds no value. Using generics this ways is considered + // an anti-pattern. + public static class ScannerMap extends ContextMap<IScannerCallback, PendingIntentInfo> {} + + /** Keep the arguments passed in for the PendingIntent. */ + public static class PendingIntentInfo { + public PendingIntent intent; + public ScanSettings settings; + public List<ScanFilter> filters; + public String callingPackage; + public int callingUid; + + @Override + public boolean equals(Object other) { + if (!(other instanceof PendingIntentInfo)) { + return false; + } + return intent.equals(((PendingIntentInfo) other).intent); + } + + @Override + public int hashCode() { + return intent == null ? 0 : intent.hashCode(); + } + } + + public interface TestModeAccessor { + /** Indicates if bluetooth test mode is enabled. */ + boolean isTestModeEnabled(); + } + + private enum MatchOrigin { + PSEUDO_ADDRESS, + ORIGINAL_ADDRESS + } + + private static class MatchResult { + private final boolean mMatches; + private final MatchOrigin mOrigin; + + private MatchResult(boolean matches, MatchOrigin origin) { + this.mMatches = matches; + this.mOrigin = origin; + } + + public boolean getMatches() { + return mMatches; + } + + public MatchOrigin getMatchOrigin() { + return mOrigin; + } + } + + private final PendingIntent.CancelListener mScanIntentCancelListener = + new PendingIntent.CancelListener() { + public void onCanceled(PendingIntent intent) { + Log.d(TAG, "scanning PendingIntent canceled"); + stopScan(intent, mContext.getAttributionSource()); + } + }; + + private Context mContext; + private TestModeAccessor mTestModeAccessor; + + private AppOpsManager mAppOps; + private CompanionDeviceManager mCompanionManager; + private PeriodicScanManager mPeriodicScanManager; + private ScanManager mScanManager; + private AdapterService mAdapterService; private ScannerMap mScannerMap = new ScannerMap(); + private String mExposureNotificationPackage; public ScannerMap getScannerMap() { return mScannerMap; @@ -46,4 +187,1475 @@ public class TransitionalScanHelper { public void setScannerMap(ScannerMap scannerMap) { mScannerMap = scannerMap; } + + /** Internal list of scan events to use with the proto */ + private final ArrayDeque<BluetoothMetricsProto.ScanEvent> mScanEvents = + new ArrayDeque<>(NUM_SCAN_EVENTS_KEPT); + + /** */ + private final Predicate<ScanResult> mLocationDenylistPredicate = + (scanResult) -> { + final MacAddress parsedAddress = + MacAddress.fromString(scanResult.getDevice().getAddress()); + if (mAdapterService.getLocationDenylistMac().test(parsedAddress.toByteArray())) { + Log.v(TAG, "Skipping device matching denylist: " + scanResult.getDevice()); + return true; + } + final ScanRecord scanRecord = scanResult.getScanRecord(); + if (scanRecord.matchesAnyField( + mAdapterService.getLocationDenylistAdvertisingData())) { + Log.v(TAG, "Skipping data matching denylist: " + scanRecord); + return true; + } + return false; + }; + + public TransitionalScanHelper(Context context, TestModeAccessor testModeAccessor) { + mContext = context; + mTestModeAccessor = testModeAccessor; + } + + /** + * Starts the LE scanning component. + * + * @param looper for scan operations + */ + public void start(Looper looper) { + mExposureNotificationPackage = mContext.getString(R.string.exposure_notification_package); + mAppOps = mContext.getSystemService(AppOpsManager.class); + mCompanionManager = mContext.getSystemService(CompanionDeviceManager.class); + mAdapterService = AdapterService.getAdapterService(); + mScanManager = + GattObjectsFactory.getInstance() + .createScanManager( + mContext, + this, + mAdapterService, + BluetoothAdapterProxy.getInstance(), + looper); + + mPeriodicScanManager = + GattObjectsFactory.getInstance().createPeriodicScanManager(mAdapterService); + } + + /** Stops the scanning component. */ + public void stop() { + mScannerMap.clear(); + } + + /** Cleans up the scanning component. */ + public void cleanup() { + if (mScanManager != null) { + mScanManager.cleanup(); + } + if (mPeriodicScanManager != null) { + mPeriodicScanManager.cleanup(); + } + } + + /** Notifies scan manager of bluetooth profile connection state changes */ + public void notifyProfileConnectionStateChange(int profile, int fromState, int toState) { + if (mScanManager == null) { + Log.w(TAG, "scan manager is null"); + return; + } + mScanManager.handleBluetoothProfileConnectionStateChanged(profile, fromState, toState); + } + + public int getCurrentUsedTrackingAdvertisement() { + return mScanManager.getCurrentUsedTrackingAdvertisement(); + } + + /************************************************************************** + * Callback functions - CLIENT + *************************************************************************/ + + // EN format defined here: + // https://blog.google/documents/70/Exposure_Notification_-_Bluetooth_Specification_v1.2.2.pdf + private static final byte[] EXPOSURE_NOTIFICATION_FLAGS_PREAMBLE = + new byte[] { + // size 2, flag field, flags byte (value is not important) + (byte) 0x02, (byte) 0x01 + }; + + private static final int EXPOSURE_NOTIFICATION_FLAGS_LENGTH = 0x2 + 1; + private static final byte[] EXPOSURE_NOTIFICATION_PAYLOAD_PREAMBLE = + new byte[] { + // size 3, complete 16 bit UUID, EN UUID + (byte) 0x03, (byte) 0x03, (byte) 0x6F, (byte) 0xFD, + // size 23, data for 16 bit UUID, EN UUID + (byte) 0x17, (byte) 0x16, (byte) 0x6F, (byte) 0xFD, + // ...payload + }; + private static final int EXPOSURE_NOTIFICATION_PAYLOAD_LENGTH = 0x03 + 0x17 + 2; + + private static boolean arrayStartsWith(byte[] array, byte[] prefix) { + if (array.length < prefix.length) { + return false; + } + for (int i = 0; i < prefix.length; i++) { + if (prefix[i] != array[i]) { + return false; + } + } + return true; + } + + private ScanResult getSanitizedExposureNotification(ScanResult result) { + ScanRecord record = result.getScanRecord(); + // Remove the flags part of the payload, if present + if (record.getBytes().length > EXPOSURE_NOTIFICATION_FLAGS_LENGTH + && arrayStartsWith(record.getBytes(), EXPOSURE_NOTIFICATION_FLAGS_PREAMBLE)) { + record = + ScanRecord.parseFromBytes( + Arrays.copyOfRange( + record.getBytes(), + EXPOSURE_NOTIFICATION_FLAGS_LENGTH, + record.getBytes().length)); + } + + if (record.getBytes().length != EXPOSURE_NOTIFICATION_PAYLOAD_LENGTH) { + return null; + } + if (!arrayStartsWith(record.getBytes(), EXPOSURE_NOTIFICATION_PAYLOAD_PREAMBLE)) { + return null; + } + + return new ScanResult(null, 0, 0, 0, 0, 0, result.getRssi(), 0, record, 0); + } + + /** Callback method for a scan result. */ + public void onScanResult( + int eventType, + int addressType, + String address, + int primaryPhy, + int secondaryPhy, + int advertisingSid, + int txPower, + int rssi, + int periodicAdvInt, + byte[] advData, + String originalAddress) { + // When in testing mode, ignore all real-world events + if (mTestModeAccessor.isTestModeEnabled()) return; + + AppScanStats.recordScanRadioResultCount(); + onScanResultInternal( + eventType, + addressType, + address, + primaryPhy, + secondaryPhy, + advertisingSid, + txPower, + rssi, + periodicAdvInt, + advData, + originalAddress); + } + + // TODO(b/327849650): Refactor to reduce the visibility of this method. + public void onScanResultInternal( + int eventType, + int addressType, + String address, + int primaryPhy, + int secondaryPhy, + int advertisingSid, + int txPower, + int rssi, + int periodicAdvInt, + byte[] advData, + String originalAddress) { + if (VDBG) { + Log.d( + TAG, + "onScanResult() - eventType=0x" + + Integer.toHexString(eventType) + + ", addressType=" + + addressType + + ", address=" + + address + + ", primaryPhy=" + + primaryPhy + + ", secondaryPhy=" + + secondaryPhy + + ", advertisingSid=0x" + + Integer.toHexString(advertisingSid) + + ", txPower=" + + txPower + + ", rssi=" + + rssi + + ", periodicAdvInt=0x" + + Integer.toHexString(periodicAdvInt) + + ", originalAddress=" + + originalAddress); + } + + String identityAddress = mAdapterService.getIdentityAddress(address); + if (!address.equals(identityAddress)) { + if (VDBG) { + Log.d( + TAG, + "found identityAddress of " + + address + + ", replace originalAddress as " + + identityAddress); + } + originalAddress = identityAddress; + } + + byte[] legacyAdvData = Arrays.copyOfRange(advData, 0, 62); + + for (ScanClient client : mScanManager.getRegularScanQueue()) { + ScannerMap.App app = mScannerMap.getById(client.scannerId); + if (app == null) { + if (VDBG) { + Log.d(TAG, "App is null; skip."); + } + continue; + } + + BluetoothDevice device = + BluetoothAdapter.getDefaultAdapter().getRemoteLeDevice(address, addressType); + + ScanSettings settings = client.settings; + byte[] scanRecordData; + // This is for compatibility with applications that assume fixed size scan data. + if (settings.getLegacy()) { + if ((eventType & ET_LEGACY_MASK) == 0) { + // If this is legacy scan, but nonlegacy result - skip. + if (VDBG) { + Log.d(TAG, "Legacy scan, non legacy result; skip."); + } + continue; + } else { + // Some apps are used to fixed-size advertise data. + scanRecordData = legacyAdvData; + } + } else { + scanRecordData = advData; + } + + ScanRecord scanRecord = ScanRecord.parseFromBytes(scanRecordData); + ScanResult result = + new ScanResult( + device, + eventType, + primaryPhy, + secondaryPhy, + advertisingSid, + txPower, + rssi, + periodicAdvInt, + scanRecord, + SystemClock.elapsedRealtimeNanos()); + + if (client.hasDisavowedLocation) { + if (mLocationDenylistPredicate.test(result)) { + Log.i(TAG, "Skipping client for location deny list"); + continue; + } + } + + boolean hasPermission = hasScanResultPermission(client); + if (!hasPermission) { + for (String associatedDevice : client.associatedDevices) { + if (associatedDevice.equalsIgnoreCase(address)) { + hasPermission = true; + break; + } + } + } + if (!hasPermission && client.eligibleForSanitizedExposureNotification) { + ScanResult sanitized = getSanitizedExposureNotification(result); + if (sanitized != null) { + hasPermission = true; + result = sanitized; + } + } + MatchResult matchResult = matchesFilters(client, result, originalAddress); + if (!hasPermission || !matchResult.getMatches()) { + if (VDBG) { + Log.d( + TAG, + "Skipping client: permission=" + + hasPermission + + " matches=" + + matchResult.getMatches()); + } + continue; + } + + int callbackType = settings.getCallbackType(); + if (!(callbackType == ScanSettings.CALLBACK_TYPE_ALL_MATCHES + || callbackType == ScanSettings.CALLBACK_TYPE_ALL_MATCHES_AUTO_BATCH)) { + if (VDBG) { + Log.d(TAG, "Skipping client: CALLBACK_TYPE_ALL_MATCHES"); + } + continue; + } + + try { + app.appScanStats.addResult(client.scannerId); + if (app.callback != null) { + app.callback.onScanResult(result); + } else { + // Send the PendingIntent + ArrayList<ScanResult> results = new ArrayList<>(); + results.add(result); + sendResultsByPendingIntent( + app.info, results, ScanSettings.CALLBACK_TYPE_ALL_MATCHES); + } + } catch (RemoteException | PendingIntent.CanceledException e) { + Log.e(TAG, "Exception: " + e); + if (Flags.leScanFixRemoteException()) { + handleDeadScanClient(client); + } else { + mScannerMap.remove(client.scannerId); + mScanManager.stopScan(client.scannerId); + } + } + } + } + + private void sendResultByPendingIntent( + PendingIntentInfo pii, ScanResult result, int callbackType, ScanClient client) { + ArrayList<ScanResult> results = new ArrayList<>(); + results.add(result); + try { + sendResultsByPendingIntent(pii, results, callbackType); + } catch (PendingIntent.CanceledException e) { + final long token = Binder.clearCallingIdentity(); + try { + stopScan(client.scannerId, mContext.getAttributionSource()); + unregisterScanner(client.scannerId, mContext.getAttributionSource()); + } finally { + Binder.restoreCallingIdentity(token); + } + } + } + + private void sendResultsByPendingIntent( + PendingIntentInfo pii, ArrayList<ScanResult> results, int callbackType) + throws PendingIntent.CanceledException { + Intent extrasIntent = new Intent(); + extrasIntent.putParcelableArrayListExtra( + BluetoothLeScanner.EXTRA_LIST_SCAN_RESULT, results); + extrasIntent.putExtra(BluetoothLeScanner.EXTRA_CALLBACK_TYPE, callbackType); + pii.intent.send(mContext, 0, extrasIntent); + } + + private void sendErrorByPendingIntent(PendingIntentInfo pii, int errorCode) + throws PendingIntent.CanceledException { + Intent extrasIntent = new Intent(); + extrasIntent.putExtra(BluetoothLeScanner.EXTRA_ERROR_CODE, errorCode); + pii.intent.send(mContext, 0, extrasIntent); + } + + /** Callback method for scanner registration. */ + public void onScannerRegistered(int status, int scannerId, long uuidLsb, long uuidMsb) + throws RemoteException { + UUID uuid = new UUID(uuidMsb, uuidLsb); + if (DBG) { + Log.d( + TAG, + "onScannerRegistered() - UUID=" + + uuid + + ", scannerId=" + + scannerId + + ", status=" + + status); + } + + // First check the callback map + ScannerMap.App cbApp = mScannerMap.getByUuid(uuid); + if (cbApp != null) { + if (status == 0) { + cbApp.id = scannerId; + // If app is callback based, setup a death recipient. App will initiate the start. + // Otherwise, if PendingIntent based, start the scan directly. + if (cbApp.callback != null) { + cbApp.linkToDeath(new ScannerDeathRecipient(scannerId, cbApp.name)); + } else { + continuePiStartScan(scannerId, cbApp); + } + } else { + mScannerMap.remove(scannerId); + } + if (cbApp.callback != null) { + cbApp.callback.onScannerRegistered(status, scannerId); + } + } + } + + /** Determines if the given scan client has the appropriate permissions to receive callbacks. */ + private boolean hasScanResultPermission(final ScanClient client) { + if (client.hasNetworkSettingsPermission + || client.hasNetworkSetupWizardPermission + || client.hasScanWithoutLocationPermission) { + return true; + } + if (client.hasDisavowedLocation) { + return true; + } + return client.hasLocationPermission + && !Utils.blockedByLocationOff(mContext, client.userHandle); + } + + // Check if a scan record matches a specific filters. + private MatchResult matchesFilters(ScanClient client, ScanResult scanResult) { + return matchesFilters(client, scanResult, null); + } + + // Check if a scan record matches a specific filters or original address + private MatchResult matchesFilters( + ScanClient client, ScanResult scanResult, String originalAddress) { + if (client.filters == null || client.filters.isEmpty()) { + // TODO: Do we really wanna return true here? + return new MatchResult(true, MatchOrigin.PSEUDO_ADDRESS); + } + for (ScanFilter filter : client.filters) { + // Need to check the filter matches, and the original address without changing the API + if (filter.matches(scanResult)) { + return new MatchResult(true, MatchOrigin.PSEUDO_ADDRESS); + } + if (originalAddress != null + && originalAddress.equalsIgnoreCase(filter.getDeviceAddress())) { + return new MatchResult(true, MatchOrigin.ORIGINAL_ADDRESS); + } + } + return new MatchResult(false, MatchOrigin.PSEUDO_ADDRESS); + } + + private void handleDeadScanClient(ScanClient client) { + if (client.appDied) { + Log.w(TAG, "Already dead client " + client.scannerId); + return; + } + client.appDied = true; + stopScan(client.scannerId, mContext.getAttributionSource()); + } + + /** Callback method for scan filter enablement/disablement. */ + public void onScanFilterEnableDisabled(int action, int status, int clientIf) { + if (DBG) { + Log.d( + TAG, + "onScanFilterEnableDisabled() - clientIf=" + + clientIf + + ", status=" + + status + + ", action=" + + action); + } + mScanManager.callbackDone(clientIf, status); + } + + /** Callback method for configuration of scan filter params. */ + public void onScanFilterParamsConfigured( + int action, int status, int clientIf, int availableSpace) { + if (DBG) { + Log.d( + TAG, + "onScanFilterParamsConfigured() - clientIf=" + + clientIf + + ", status=" + + status + + ", action=" + + action + + ", availableSpace=" + + availableSpace); + } + mScanManager.callbackDone(clientIf, status); + } + + /** Callback method for configuration of scan filter. */ + public void onScanFilterConfig( + int action, int status, int clientIf, int filterType, int availableSpace) { + if (DBG) { + Log.d( + TAG, + "onScanFilterConfig() - clientIf=" + + clientIf + + ", action = " + + action + + " status = " + + status + + ", filterType=" + + filterType + + ", availableSpace=" + + availableSpace); + } + + mScanManager.callbackDone(clientIf, status); + } + + /** Callback method for configuration of batch scan storage. */ + public void onBatchScanStorageConfigured(int status, int clientIf) { + if (DBG) { + Log.d( + TAG, + "onBatchScanStorageConfigured() - clientIf=" + clientIf + ", status=" + status); + } + mScanManager.callbackDone(clientIf, status); + } + + /** Callback method for start/stop of batch scan. */ + // TODO: split into two different callbacks : onBatchScanStarted and onBatchScanStopped. + public void onBatchScanStartStopped(int startStopAction, int status, int clientIf) { + if (DBG) { + Log.d( + TAG, + "onBatchScanStartStopped() - clientIf=" + + clientIf + + ", status=" + + status + + ", startStopAction=" + + startStopAction); + } + mScanManager.callbackDone(clientIf, status); + } + + ScanClient findBatchScanClientById(int scannerId) { + for (ScanClient client : mScanManager.getBatchScanQueue()) { + if (client.scannerId == scannerId) { + return client; + } + } + return null; + } + + /** Callback method for batch scan reports */ + public void onBatchScanReports( + int status, int scannerId, int reportType, int numRecords, byte[] recordData) + throws RemoteException { + // When in testing mode, ignore all real-world events + if (mTestModeAccessor.isTestModeEnabled()) return; + + AppScanStats.recordBatchScanRadioResultCount(numRecords); + onBatchScanReportsInternal(status, scannerId, reportType, numRecords, recordData); + } + + @VisibleForTesting + void onBatchScanReportsInternal( + int status, int scannerId, int reportType, int numRecords, byte[] recordData) + throws RemoteException { + if (DBG) { + Log.d( + TAG, + "onBatchScanReports() - scannerId=" + + scannerId + + ", status=" + + status + + ", reportType=" + + reportType + + ", numRecords=" + + numRecords); + } + + Set<ScanResult> results = parseBatchScanResults(numRecords, reportType, recordData); + if (reportType == ScanManager.SCAN_RESULT_TYPE_TRUNCATED) { + // We only support single client for truncated mode. + ScannerMap.App app = mScannerMap.getById(scannerId); + if (app == null) { + return; + } + + ScanClient client = findBatchScanClientById(scannerId); + if (client == null) { + return; + } + + ArrayList<ScanResult> permittedResults; + if (hasScanResultPermission(client)) { + permittedResults = new ArrayList<ScanResult>(results); + } else { + permittedResults = new ArrayList<ScanResult>(); + for (ScanResult scanResult : results) { + for (String associatedDevice : client.associatedDevices) { + if (associatedDevice.equalsIgnoreCase( + scanResult.getDevice().getAddress())) { + permittedResults.add(scanResult); + } + } + } + if (permittedResults.isEmpty()) { + return; + } + } + + if (client.hasDisavowedLocation) { + permittedResults.removeIf(mLocationDenylistPredicate); + } + + if (app.callback != null) { + app.callback.onBatchScanResults(permittedResults); + } else { + // PendingIntent based + try { + sendResultsByPendingIntent( + app.info, permittedResults, ScanSettings.CALLBACK_TYPE_ALL_MATCHES); + } catch (PendingIntent.CanceledException e) { + } + } + } else { + for (ScanClient client : mScanManager.getFullBatchScanQueue()) { + // Deliver results for each client. + deliverBatchScan(client, results); + } + } + mScanManager.callbackDone(scannerId, status); + } + + private void sendBatchScanResults( + ScannerMap.App app, ScanClient client, ArrayList<ScanResult> results) { + try { + if (app.callback != null) { + if (mScanManager.isAutoBatchScanClientEnabled(client)) { + if (DBG) { + Log.d(TAG, "sendBatchScanResults() to onScanResult()" + client); + } + for (ScanResult result : results) { + app.appScanStats.addResult(client.scannerId); + app.callback.onScanResult(result); + } + } else { + if (DBG) { + Log.d(TAG, "sendBatchScanResults() to onBatchScanResults()" + client); + } + app.callback.onBatchScanResults(results); + } + } else { + sendResultsByPendingIntent( + app.info, results, ScanSettings.CALLBACK_TYPE_ALL_MATCHES); + } + } catch (RemoteException | PendingIntent.CanceledException e) { + Log.e(TAG, "Exception: " + e); + if (Flags.leScanFixRemoteException()) { + handleDeadScanClient(client); + } else { + mScannerMap.remove(client.scannerId); + mScanManager.stopScan(client.scannerId); + } + } + } + + // Check and deliver scan results for different scan clients. + private void deliverBatchScan(ScanClient client, Set<ScanResult> allResults) + throws RemoteException { + ContextMap.App app = mScannerMap.getById(client.scannerId); + if (app == null) { + return; + } + + ArrayList<ScanResult> permittedResults; + if (hasScanResultPermission(client)) { + permittedResults = new ArrayList<ScanResult>(allResults); + } else { + permittedResults = new ArrayList<ScanResult>(); + for (ScanResult scanResult : allResults) { + for (String associatedDevice : client.associatedDevices) { + if (associatedDevice.equalsIgnoreCase(scanResult.getDevice().getAddress())) { + permittedResults.add(scanResult); + } + } + } + if (permittedResults.isEmpty()) { + return; + } + } + + if (client.filters == null || client.filters.isEmpty()) { + sendBatchScanResults(app, client, permittedResults); + // TODO: Question to reviewer: Shouldn't there be a return here? + } + // Reconstruct the scan results. + ArrayList<ScanResult> results = new ArrayList<ScanResult>(); + for (ScanResult scanResult : permittedResults) { + if (matchesFilters(client, scanResult).getMatches()) { + results.add(scanResult); + } + } + sendBatchScanResults(app, client, results); + } + + private Set<ScanResult> parseBatchScanResults( + int numRecords, int reportType, byte[] batchRecord) { + if (numRecords == 0) { + return Collections.emptySet(); + } + if (DBG) { + Log.d(TAG, "current time is " + SystemClock.elapsedRealtimeNanos()); + } + if (reportType == ScanManager.SCAN_RESULT_TYPE_TRUNCATED) { + return parseTruncatedResults(numRecords, batchRecord); + } else { + return parseFullResults(numRecords, batchRecord); + } + } + + private Set<ScanResult> parseTruncatedResults(int numRecords, byte[] batchRecord) { + if (DBG) { + Log.d(TAG, "batch record " + Arrays.toString(batchRecord)); + } + Set<ScanResult> results = new HashSet<ScanResult>(numRecords); + long now = SystemClock.elapsedRealtimeNanos(); + for (int i = 0; i < numRecords; ++i) { + byte[] record = + extractBytes(batchRecord, i * TRUNCATED_RESULT_SIZE, TRUNCATED_RESULT_SIZE); + byte[] address = extractBytes(record, 0, 6); + reverse(address); + BluetoothDevice device = BluetoothAdapter.getDefaultAdapter().getRemoteDevice(address); + int rssi = record[8]; + long timestampNanos = now - parseTimestampNanos(extractBytes(record, 9, 2)); + results.add( + new ScanResult( + device, ScanRecord.parseFromBytes(new byte[0]), rssi, timestampNanos)); + } + return results; + } + + @VisibleForTesting + long parseTimestampNanos(byte[] data) { + long timestampUnit = NumberUtils.littleEndianByteArrayToInt(data); + // Timestamp is in every 50 ms. + return TimeUnit.MILLISECONDS.toNanos(timestampUnit * 50); + } + + private Set<ScanResult> parseFullResults(int numRecords, byte[] batchRecord) { + if (DBG) { + Log.d(TAG, "Batch record : " + Arrays.toString(batchRecord)); + } + Set<ScanResult> results = new HashSet<ScanResult>(numRecords); + int position = 0; + long now = SystemClock.elapsedRealtimeNanos(); + while (position < batchRecord.length) { + byte[] address = extractBytes(batchRecord, position, 6); + // TODO: remove temp hack. + reverse(address); + BluetoothDevice device = BluetoothAdapter.getDefaultAdapter().getRemoteDevice(address); + position += 6; + // Skip address type. + position++; + // Skip tx power level. + position++; + int rssi = batchRecord[position++]; + long timestampNanos = now - parseTimestampNanos(extractBytes(batchRecord, position, 2)); + position += 2; + + // Combine advertise packet and scan response packet. + int advertisePacketLen = batchRecord[position++]; + byte[] advertiseBytes = extractBytes(batchRecord, position, advertisePacketLen); + position += advertisePacketLen; + int scanResponsePacketLen = batchRecord[position++]; + byte[] scanResponseBytes = extractBytes(batchRecord, position, scanResponsePacketLen); + position += scanResponsePacketLen; + byte[] scanRecord = new byte[advertisePacketLen + scanResponsePacketLen]; + System.arraycopy(advertiseBytes, 0, scanRecord, 0, advertisePacketLen); + System.arraycopy( + scanResponseBytes, 0, scanRecord, advertisePacketLen, scanResponsePacketLen); + if (DBG) { + Log.d(TAG, "ScanRecord : " + Arrays.toString(scanRecord)); + } + results.add( + new ScanResult( + device, ScanRecord.parseFromBytes(scanRecord), rssi, timestampNanos)); + } + return results; + } + + // Reverse byte array. + private void reverse(byte[] address) { + int len = address.length; + for (int i = 0; i < len / 2; ++i) { + byte b = address[i]; + address[i] = address[len - 1 - i]; + address[len - 1 - i] = b; + } + } + + // Helper method to extract bytes from byte array. + private static byte[] extractBytes(byte[] scanRecord, int start, int length) { + byte[] bytes = new byte[length]; + System.arraycopy(scanRecord, start, bytes, 0, length); + return bytes; + } + + @RequiresPermission(android.Manifest.permission.BLUETOOTH_SCAN) + public void onBatchScanThresholdCrossed(int clientIf) { + if (DBG) { + Log.d(TAG, "onBatchScanThresholdCrossed() - clientIf=" + clientIf); + } + flushPendingBatchResults(clientIf, mContext.getAttributionSource()); + } + + public AdvtFilterOnFoundOnLostInfo createOnTrackAdvFoundLostObject( + int clientIf, + int advPktLen, + byte[] advPkt, + int scanRspLen, + byte[] scanRsp, + int filtIndex, + int advState, + int advInfoPresent, + String address, + int addrType, + int txPower, + int rssiValue, + int timeStamp) { + + return new AdvtFilterOnFoundOnLostInfo( + clientIf, + advPktLen, + advPkt, + scanRspLen, + scanRsp, + filtIndex, + advState, + advInfoPresent, + address, + addrType, + txPower, + rssiValue, + timeStamp); + } + + public void onTrackAdvFoundLost(AdvtFilterOnFoundOnLostInfo trackingInfo) + throws RemoteException { + if (DBG) { + Log.d( + TAG, + "onTrackAdvFoundLost() - scannerId= " + + trackingInfo.getClientIf() + + " address = " + + trackingInfo.getAddress() + + " adv_state = " + + trackingInfo.getAdvState()); + } + + ScannerMap.App app = mScannerMap.getById(trackingInfo.getClientIf()); + if (app == null || (app.callback == null && app.info == null)) { + Log.e(TAG, "app or callback is null"); + return; + } + + BluetoothDevice device = + BluetoothAdapter.getDefaultAdapter().getRemoteDevice(trackingInfo.getAddress()); + int advertiserState = trackingInfo.getAdvState(); + ScanResult result = + new ScanResult( + device, + ScanRecord.parseFromBytes(trackingInfo.getResult()), + trackingInfo.getRSSIValue(), + SystemClock.elapsedRealtimeNanos()); + + for (ScanClient client : mScanManager.getRegularScanQueue()) { + if (client.scannerId == trackingInfo.getClientIf()) { + ScanSettings settings = client.settings; + if ((advertiserState == ADVT_STATE_ONFOUND) + && ((settings.getCallbackType() & ScanSettings.CALLBACK_TYPE_FIRST_MATCH) + != 0)) { + if (app.callback != null) { + app.callback.onFoundOrLost(true, result); + } else { + sendResultByPendingIntent( + app.info, result, ScanSettings.CALLBACK_TYPE_FIRST_MATCH, client); + } + } else if ((advertiserState == ADVT_STATE_ONLOST) + && ((settings.getCallbackType() & ScanSettings.CALLBACK_TYPE_MATCH_LOST) + != 0)) { + if (app.callback != null) { + app.callback.onFoundOrLost(false, result); + } else { + sendResultByPendingIntent( + app.info, result, ScanSettings.CALLBACK_TYPE_MATCH_LOST, client); + } + } else { + if (DBG) { + Log.d( + TAG, + "Not reporting onlost/onfound : " + + advertiserState + + " scannerId = " + + client.scannerId + + " callbackType " + + settings.getCallbackType()); + } + } + } + } + } + + public void onScanParamSetupCompleted(int status, int scannerId) throws RemoteException { + ContextMap.App app = mScannerMap.getById(scannerId); + if (app == null || app.callback == null) { + Log.e(TAG, "Advertise app or callback is null"); + return; + } + if (DBG) { + Log.d(TAG, "onScanParamSetupCompleted : " + status); + } + } + + // callback from ScanManager for dispatch of errors apps. + public void onScanManagerErrorCallback(int scannerId, int errorCode) throws RemoteException { + ScannerMap.App app = mScannerMap.getById(scannerId); + if (app == null || (app.callback == null && app.info == null)) { + Log.e(TAG, "App or callback is null"); + return; + } + if (app.callback != null) { + app.callback.onScanManagerErrorCallback(errorCode); + } else { + try { + sendErrorByPendingIntent(app.info, errorCode); + } catch (PendingIntent.CanceledException e) { + Log.e(TAG, "Error sending error code via PendingIntent:" + e); + } + } + } + + /************************************************************************** + * GATT Service functions - Shared CLIENT/SERVER + *************************************************************************/ + + @RequiresPermission(android.Manifest.permission.BLUETOOTH_SCAN) + public void registerScanner( + IScannerCallback callback, WorkSource workSource, AttributionSource attributionSource) + throws RemoteException { + if (!Utils.checkScanPermissionForDataDelivery( + mContext, attributionSource, "ScanHelper registerScanner")) { + return; + } + + UUID uuid = UUID.randomUUID(); + if (DBG) { + Log.d(TAG, "registerScanner() - UUID=" + uuid); + } + + enforceImpersonatationPermissionIfNeeded(workSource); + + AppScanStats app = mScannerMap.getAppScanStatsByUid(Binder.getCallingUid()); + if (app != null + && app.isScanningTooFrequently() + && !Utils.checkCallerHasPrivilegedPermission(mContext)) { + Log.e(TAG, "App '" + app.appName + "' is scanning too frequently"); + callback.onScannerRegistered(ScanCallback.SCAN_FAILED_SCANNING_TOO_FREQUENTLY, -1); + return; + } + + mScannerMap.add(uuid, workSource, callback, null, mContext, this); + mScanManager.registerScanner(uuid); + } + + @RequiresPermission(android.Manifest.permission.BLUETOOTH_SCAN) + public void unregisterScanner(int scannerId, AttributionSource attributionSource) { + if (!Utils.checkScanPermissionForDataDelivery( + mContext, attributionSource, "ScanHelper unregisterScanner")) { + return; + } + + if (DBG) { + Log.d(TAG, "unregisterScanner() - scannerId=" + scannerId); + } + mScannerMap.remove(scannerId); + mScanManager.unregisterScanner(scannerId); + } + + private List<String> getAssociatedDevices(String callingPackage) { + if (mCompanionManager == null) { + return Collections.emptyList(); + } + + List<String> macAddresses = new ArrayList(); + + final long identity = Binder.clearCallingIdentity(); + try { + for (AssociationInfo info : Utils.getCdmAssociations(mCompanionManager)) { + if (info.getPackageName().equals(callingPackage) + && !info.isSelfManaged() + && info.getDeviceMacAddress() != null) { + macAddresses.add(info.getDeviceMacAddress().toString()); + } + } + } catch (SecurityException se) { + // Not an app with associated devices + } catch (Exception e) { + Log.e(TAG, "Cannot check device associations for " + callingPackage, e); + } finally { + Binder.restoreCallingIdentity(identity); + } + return macAddresses; + } + + @RequiresPermission(android.Manifest.permission.BLUETOOTH_SCAN) + public void startScan( + int scannerId, + ScanSettings settings, + List<ScanFilter> filters, + AttributionSource attributionSource) { + if (DBG) { + Log.d(TAG, "start scan with filters"); + } + + if (!Utils.checkScanPermissionForDataDelivery( + mContext, attributionSource, "Starting GATT scan.")) { + return; + } + + enforcePrivilegedPermissionIfNeeded(settings); + String callingPackage = attributionSource.getPackageName(); + settings = enforceReportDelayFloor(settings); + enforcePrivilegedPermissionIfNeeded(filters); + final ScanClient scanClient = new ScanClient(scannerId, settings, filters); + scanClient.userHandle = Binder.getCallingUserHandle(); + mAppOps.checkPackage(Binder.getCallingUid(), callingPackage); + scanClient.eligibleForSanitizedExposureNotification = + callingPackage.equals(mExposureNotificationPackage); + + scanClient.hasDisavowedLocation = + Utils.hasDisavowedLocationForScan( + mContext, attributionSource, mTestModeAccessor.isTestModeEnabled()); + + scanClient.isQApp = checkCallerTargetSdk(mContext, callingPackage, Build.VERSION_CODES.Q); + if (!scanClient.hasDisavowedLocation) { + if (scanClient.isQApp) { + scanClient.hasLocationPermission = + Utils.checkCallerHasFineLocation( + mContext, attributionSource, scanClient.userHandle); + } else { + scanClient.hasLocationPermission = + Utils.checkCallerHasCoarseOrFineLocation( + mContext, attributionSource, scanClient.userHandle); + } + } + scanClient.hasNetworkSettingsPermission = + Utils.checkCallerHasNetworkSettingsPermission(mContext); + scanClient.hasNetworkSetupWizardPermission = + Utils.checkCallerHasNetworkSetupWizardPermission(mContext); + scanClient.hasScanWithoutLocationPermission = + Utils.checkCallerHasScanWithoutLocationPermission(mContext); + scanClient.associatedDevices = getAssociatedDevices(callingPackage); + + AppScanStats app = mScannerMap.getAppScanStatsById(scannerId); + ContextMap.App cbApp = mScannerMap.getById(scannerId); + if (app != null) { + scanClient.stats = app; + boolean isFilteredScan = (filters != null) && !filters.isEmpty(); + boolean isCallbackScan = false; + if (cbApp != null) { + isCallbackScan = cbApp.callback != null; + } + app.recordScanStart(settings, filters, isFilteredScan, isCallbackScan, scannerId); + } + + mScanManager.startScan(scanClient); + } + + @RequiresPermission(android.Manifest.permission.BLUETOOTH_SCAN) + public void registerPiAndStartScan( + PendingIntent pendingIntent, + ScanSettings settings, + List<ScanFilter> filters, + AttributionSource attributionSource) { + if (DBG) { + Log.d(TAG, "start scan with filters, for PendingIntent"); + } + + if (!Utils.checkScanPermissionForDataDelivery( + mContext, attributionSource, "Starting GATT scan.")) { + return; + } + enforcePrivilegedPermissionIfNeeded(settings); + settings = enforceReportDelayFloor(settings); + enforcePrivilegedPermissionIfNeeded(filters); + UUID uuid = UUID.randomUUID(); + String callingPackage = attributionSource.getPackageName(); + int callingUid = attributionSource.getUid(); + PendingIntentInfo piInfo = new PendingIntentInfo(); + piInfo.intent = pendingIntent; + piInfo.settings = settings; + piInfo.filters = filters; + piInfo.callingPackage = callingPackage; + piInfo.callingUid = callingUid; + if (DBG) { + Log.d( + TAG, + "startScan(PI) -" + + (" UUID=" + uuid) + + (" Package=" + callingPackage) + + (" UID=" + callingUid)); + } + + // Don't start scan if the Pi scan already in mScannerMap. + if (mScannerMap.getByContextInfo(piInfo) != null) { + Log.d(TAG, "Don't startScan(PI) since the same Pi scan already in mScannerMap."); + return; + } + + ContextMap.App app = mScannerMap.add(uuid, null, null, piInfo, mContext, this); + + app.mUserHandle = UserHandle.getUserHandleForUid(Binder.getCallingUid()); + mAppOps.checkPackage(Binder.getCallingUid(), callingPackage); + app.mEligibleForSanitizedExposureNotification = + callingPackage.equals(mExposureNotificationPackage); + + app.mHasDisavowedLocation = + Utils.hasDisavowedLocationForScan( + mContext, attributionSource, mTestModeAccessor.isTestModeEnabled()); + + if (!app.mHasDisavowedLocation) { + try { + if (checkCallerTargetSdk(mContext, callingPackage, Build.VERSION_CODES.Q)) { + app.hasLocationPermission = + Utils.checkCallerHasFineLocation( + mContext, attributionSource, app.mUserHandle); + } else { + app.hasLocationPermission = + Utils.checkCallerHasCoarseOrFineLocation( + mContext, attributionSource, app.mUserHandle); + } + } catch (SecurityException se) { + // No need to throw here. Just mark as not granted. + app.hasLocationPermission = false; + } + } + app.mHasNetworkSettingsPermission = Utils.checkCallerHasNetworkSettingsPermission(mContext); + app.mHasNetworkSetupWizardPermission = + Utils.checkCallerHasNetworkSetupWizardPermission(mContext); + app.mHasScanWithoutLocationPermission = + Utils.checkCallerHasScanWithoutLocationPermission(mContext); + app.mAssociatedDevices = getAssociatedDevices(callingPackage); + mScanManager.registerScanner(uuid); + + // If this fails, we should stop the scan immediately. + if (!pendingIntent.addCancelListener(Runnable::run, mScanIntentCancelListener)) { + Log.d(TAG, "scanning PendingIntent is already cancelled, stopping scan."); + stopScan(pendingIntent, attributionSource); + } + } + + public void continuePiStartScan(int scannerId, ScannerMap.App app) { + final PendingIntentInfo piInfo = app.info; + final ScanClient scanClient = + new ScanClient(scannerId, piInfo.settings, piInfo.filters, piInfo.callingUid); + scanClient.hasLocationPermission = app.hasLocationPermission; + scanClient.userHandle = app.mUserHandle; + scanClient.isQApp = checkCallerTargetSdk(mContext, app.name, Build.VERSION_CODES.Q); + scanClient.eligibleForSanitizedExposureNotification = + app.mEligibleForSanitizedExposureNotification; + scanClient.hasNetworkSettingsPermission = app.mHasNetworkSettingsPermission; + scanClient.hasNetworkSetupWizardPermission = app.mHasNetworkSetupWizardPermission; + scanClient.hasScanWithoutLocationPermission = app.mHasScanWithoutLocationPermission; + scanClient.associatedDevices = app.mAssociatedDevices; + scanClient.hasDisavowedLocation = app.mHasDisavowedLocation; + + AppScanStats scanStats = mScannerMap.getAppScanStatsById(scannerId); + if (scanStats != null) { + scanClient.stats = scanStats; + boolean isFilteredScan = (piInfo.filters != null) && !piInfo.filters.isEmpty(); + scanStats.recordScanStart( + piInfo.settings, piInfo.filters, isFilteredScan, false, scannerId); + } + + mScanManager.startScan(scanClient); + } + + @RequiresPermission(android.Manifest.permission.BLUETOOTH_SCAN) + public void flushPendingBatchResults(int scannerId, AttributionSource attributionSource) { + if (!Utils.checkScanPermissionForDataDelivery( + mContext, attributionSource, "ScanHelper flushPendingBatchResults")) { + return; + } + if (DBG) { + Log.d(TAG, "flushPendingBatchResults - scannerId=" + scannerId); + } + mScanManager.flushBatchScanResults(new ScanClient(scannerId)); + } + + @RequiresPermission(android.Manifest.permission.BLUETOOTH_SCAN) + public void stopScan(int scannerId, AttributionSource attributionSource) { + if (!Utils.checkScanPermissionForDataDelivery( + mContext, attributionSource, "ScanHelper stopScan")) { + return; + } + int scanQueueSize = + mScanManager.getBatchScanQueue().size() + mScanManager.getRegularScanQueue().size(); + if (DBG) { + Log.d(TAG, "stopScan() - queue size =" + scanQueueSize); + } + + AppScanStats app = null; + app = mScannerMap.getAppScanStatsById(scannerId); + if (app != null) { + app.recordScanStop(scannerId); + } + + mScanManager.stopScan(scannerId); + } + + @RequiresPermission(android.Manifest.permission.BLUETOOTH_SCAN) + public void stopScan(PendingIntent intent, AttributionSource attributionSource) { + if (!Utils.checkScanPermissionForDataDelivery( + mContext, attributionSource, "ScanHelper stopScan")) { + return; + } + PendingIntentInfo pii = new PendingIntentInfo(); + pii.intent = intent; + ContextMap.App app = mScannerMap.getByContextInfo(pii); + if (VDBG) { + Log.d(TAG, "stopScan(PendingIntent): app found = " + app); + } + if (app != null) { + intent.removeCancelListener(mScanIntentCancelListener); + final int scannerId = app.id; + stopScan(scannerId, attributionSource); + // Also unregister the scanner + unregisterScanner(scannerId, attributionSource); + } + } + + /************************************************************************** + * PERIODIC SCANNING + *************************************************************************/ + @RequiresPermission(android.Manifest.permission.BLUETOOTH_SCAN) + public void registerSync( + ScanResult scanResult, + int skip, + int timeout, + IPeriodicAdvertisingCallback callback, + AttributionSource attributionSource) { + if (!Utils.checkScanPermissionForDataDelivery( + mContext, attributionSource, "ScanHelper registerSync")) { + return; + } + mPeriodicScanManager.startSync(scanResult, skip, timeout, callback); + } + + @RequiresPermission(android.Manifest.permission.BLUETOOTH_SCAN) + public void unregisterSync( + IPeriodicAdvertisingCallback callback, AttributionSource attributionSource) { + if (!Utils.checkScanPermissionForDataDelivery( + mContext, attributionSource, "ScanHelper unregisterSync")) { + return; + } + mPeriodicScanManager.stopSync(callback); + } + + public void transferSync( + BluetoothDevice bda, + int serviceData, + int syncHandle, + AttributionSource attributionSource) { + if (!Utils.checkScanPermissionForDataDelivery( + mContext, attributionSource, "ScanHelper transferSync")) { + return; + } + mPeriodicScanManager.transferSync(bda, serviceData, syncHandle); + } + + public void transferSetInfo( + BluetoothDevice bda, + int serviceData, + int advHandle, + IPeriodicAdvertisingCallback callback, + AttributionSource attributionSource) { + if (!Utils.checkScanPermissionForDataDelivery( + mContext, attributionSource, "ScanHelper transferSetInfo")) { + return; + } + mPeriodicScanManager.transferSetInfo(bda, serviceData, advHandle, callback); + } + + /** + * DeathRecipient handler used to unregister applications that disconnect ungracefully (ie. + * crash or forced close). + */ + class ScannerDeathRecipient implements IBinder.DeathRecipient { + int mScannerId; + private String mPackageName; + + ScannerDeathRecipient(int scannerId, String packageName) { + mScannerId = scannerId; + mPackageName = packageName; + } + + @Override + public void binderDied() { + if (DBG) { + Log.d( + TAG, + "Binder is dead - unregistering scanner (" + + mPackageName + + " " + + mScannerId + + ")!"); + } + + ScanClient client = getScanClient(mScannerId); + if (client != null) { + if (Flags.leScanFixRemoteException()) { + handleDeadScanClient(client); + } else { + client.appDied = true; + stopScan(client.scannerId, mContext.getAttributionSource()); + } + } + } + + private ScanClient getScanClient(int clientIf) { + for (ScanClient client : mScanManager.getRegularScanQueue()) { + if (client.scannerId == clientIf) { + return client; + } + } + for (ScanClient client : mScanManager.getBatchScanQueue()) { + if (client.scannerId == clientIf) { + return client; + } + } + return null; + } + } + + private boolean needsPrivilegedPermissionForScan(ScanSettings settings) { + // BLE scan only mode needs special permission. + if (mAdapterService.getState() != BluetoothAdapter.STATE_ON) { + return true; + } + + // Regular scan, no special permission. + if (settings == null) { + return false; + } + + // Ambient discovery mode, needs privileged permission. + if (settings.getScanMode() == ScanSettings.SCAN_MODE_AMBIENT_DISCOVERY) { + return true; + } + + // Regular scan, no special permission. + if (settings.getReportDelayMillis() == 0) { + return false; + } + + // Batch scan, truncated mode needs permission. + return settings.getScanResultType() == ScanSettings.SCAN_RESULT_TYPE_ABBREVIATED; + } + + /* + * The {@link ScanFilter#setDeviceAddress} API overloads are @SystemApi access methods. This + * requires that the permissions be BLUETOOTH_PRIVILEGED. + */ + @SuppressLint("AndroidFrameworkRequiresPermission") + private void enforcePrivilegedPermissionIfNeeded(List<ScanFilter> filters) { + if (DBG) { + Log.d(TAG, "enforcePrivilegedPermissionIfNeeded(" + filters + ")"); + } + // Some 3p API cases may have null filters, need to allow + if (filters != null) { + for (ScanFilter filter : filters) { + // The only case to enforce here is if there is an address + // If there is an address, enforce if the correct combination criteria is met. + if (filter.getDeviceAddress() != null) { + // At this point we have an address, that means a caller used the + // setDeviceAddress(address) public API for the ScanFilter + // We don't want to enforce if the type is PUBLIC and the IRK is null + // However, if we have a different type that means the caller used a new + // @SystemApi such as setDeviceAddress(address, type) or + // setDeviceAddress(address, type, irk) which are both @SystemApi and require + // permissions to be enforced + if (filter.getAddressType() == BluetoothDevice.ADDRESS_TYPE_PUBLIC + && filter.getIrk() == null) { + // Do not enforce + } else { + enforceBluetoothPrivilegedPermission(mContext); + } + } + } + } + } + + @SuppressLint("AndroidFrameworkRequiresPermission") + private void enforcePrivilegedPermissionIfNeeded(ScanSettings settings) { + if (needsPrivilegedPermissionForScan(settings)) { + enforceBluetoothPrivilegedPermission(mContext); + } + } + + // Enforce caller has UPDATE_DEVICE_STATS permission, which allows the caller to blame other + // apps for Bluetooth usage. A {@link SecurityException} will be thrown if the caller app does + // not have UPDATE_DEVICE_STATS permission. + @RequiresPermission(android.Manifest.permission.UPDATE_DEVICE_STATS) + private void enforceImpersonatationPermission() { + mContext.enforceCallingOrSelfPermission( + android.Manifest.permission.UPDATE_DEVICE_STATS, + "Need UPDATE_DEVICE_STATS permission"); + } + + @SuppressLint("AndroidFrameworkRequiresPermission") + private void enforceImpersonatationPermissionIfNeeded(WorkSource workSource) { + if (workSource != null) { + enforceImpersonatationPermission(); + } + } + + /** + * Ensures the report delay is either 0 or at least the floor value (5000ms) + * + * @param settings are the scan settings passed into a request to start le scanning + * @return the passed in ScanSettings object if the report delay is 0 or above the floor value; + * a new ScanSettings object with the report delay being the floor value if the original + * report delay was between 0 and the floor value (exclusive of both) + */ + @VisibleForTesting + ScanSettings enforceReportDelayFloor(ScanSettings settings) { + if (settings.getReportDelayMillis() == 0) { + return settings; + } + + // Need to clear identity to pass device config permission check + final long callerToken = Binder.clearCallingIdentity(); + try { + long floor = + DeviceConfig.getLong( + DeviceConfig.NAMESPACE_BLUETOOTH, + "report_delay", + DEFAULT_REPORT_DELAY_FLOOR); + + if (settings.getReportDelayMillis() > floor) { + return settings; + } else { + return new ScanSettings.Builder() + .setCallbackType(settings.getCallbackType()) + .setLegacy(settings.getLegacy()) + .setMatchMode(settings.getMatchMode()) + .setNumOfMatches(settings.getNumOfMatches()) + .setPhy(settings.getPhy()) + .setReportDelay(floor) + .setScanMode(settings.getScanMode()) + .setScanResultType(settings.getScanResultType()) + .build(); + } + } finally { + Binder.restoreCallingIdentity(callerToken); + } + } + + public void addScanEvent(BluetoothMetricsProto.ScanEvent event) { + synchronized (mScanEvents) { + if (mScanEvents.size() == NUM_SCAN_EVENTS_KEPT) { + mScanEvents.remove(); + } + mScanEvents.add(event); + } + } + + public void dumpProto(BluetoothMetricsProto.BluetoothLog.Builder builder) { + synchronized (mScanEvents) { + builder.addAllScanEvent(mScanEvents); + } + } } diff --git a/android/app/tests/robotests/src/com/android/bluetooth/opp/OppSendFileInfoTest.java b/android/app/tests/robotests/src/com/android/bluetooth/opp/OppSendFileInfoTest.java index 22a4284ae1..ea712ef84c 100644 --- a/android/app/tests/robotests/src/com/android/bluetooth/opp/OppSendFileInfoTest.java +++ b/android/app/tests/robotests/src/com/android/bluetooth/opp/OppSendFileInfoTest.java @@ -26,11 +26,12 @@ import android.content.ContentResolver; import android.content.Context; import android.net.Uri; -import org.junit.Before; +import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; -import org.mockito.MockitoAnnotations; +import org.mockito.junit.MockitoJUnit; +import org.mockito.junit.MockitoRule; import org.robolectric.RobolectricTestRunner; import java.io.FileInputStream; @@ -43,15 +44,12 @@ public class OppSendFileInfoTest { private static final int TEST_FILE_SIZE = 10; private static final int MAXIMUM_FILE_SIZE = 0xFFFFFFFF; + @Rule public MockitoRule mockitoRule = MockitoJUnit.rule(); + @Mock private Context mContext; @Mock private ContentResolver mContentResolver; @Mock private FileInputStream mFileInputStream; - @Before - public void setUp() { - MockitoAnnotations.initMocks(this); - } - /** * Test a BluetoothOppSendFileInfo generated from a local file (MIME type: text/plain, * size: #TEST_FILE_SIZE). diff --git a/android/app/tests/unit/src/com/android/bluetooth/a2dp/A2dpCodecConfigTest.java b/android/app/tests/unit/src/com/android/bluetooth/a2dp/A2dpCodecConfigTest.java index 52f2736345..97cf8e0f86 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/a2dp/A2dpCodecConfigTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/a2dp/A2dpCodecConfigTest.java @@ -34,10 +34,12 @@ import com.android.bluetooth.R; import org.junit.After; import org.junit.Assert; import org.junit.Before; +import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; -import org.mockito.MockitoAnnotations; +import org.mockito.junit.MockitoJUnit; +import org.mockito.junit.MockitoRule; import java.util.Arrays; @@ -49,6 +51,8 @@ public class A2dpCodecConfigTest { private BluetoothDevice mTestDevice; private A2dpCodecConfig mA2dpCodecConfig; + @Rule public MockitoRule mockitoRule = MockitoJUnit.rule(); + @Mock private Context mMockContext; @Mock private Resources mMockResources; @Mock private A2dpNativeInterface mA2dpNativeInterface; @@ -159,8 +163,6 @@ public class A2dpCodecConfigTest { @Before public void setUp() throws Exception { - // Set up mocks and test assets - MockitoAnnotations.initMocks(this); mTargetContext = InstrumentationRegistry.getTargetContext(); when(mMockContext.getResources()).thenReturn(mMockResources); diff --git a/android/app/tests/unit/src/com/android/bluetooth/a2dp/A2dpServiceBinderTest.java b/android/app/tests/unit/src/com/android/bluetooth/a2dp/A2dpServiceBinderTest.java index 58655f6a2c..cc7a361d3b 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/a2dp/A2dpServiceBinderTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/a2dp/A2dpServiceBinderTest.java @@ -45,7 +45,8 @@ import org.junit.Before; import org.junit.Rule; import org.junit.Test; import org.mockito.Mock; -import org.mockito.MockitoAnnotations; +import org.mockito.junit.MockitoJUnit; +import org.mockito.junit.MockitoRule; import java.util.List; @@ -56,6 +57,8 @@ public class A2dpServiceBinderTest { @Rule public final SetFlagsRule mSetFlagsRule = new SetFlagsRule(); + @Rule public MockitoRule mockitoRule = MockitoJUnit.rule(); + @Mock private A2dpService mA2dpService; @Mock private AudioRoutingManager mAudioRoutingManager; @Mock private PackageManager mPackageManager; @@ -64,7 +67,6 @@ public class A2dpServiceBinderTest { @Before public void setUp() throws Exception { - MockitoAnnotations.initMocks(this); doReturn(mAudioRoutingManager).when(mA2dpService).getActiveDeviceManager(); doReturn(mPackageManager).when(mA2dpService).getPackageManager(); ApplicationInfo appInfo = new ApplicationInfo(); diff --git a/android/app/tests/unit/src/com/android/bluetooth/a2dp/A2dpServiceTest.java b/android/app/tests/unit/src/com/android/bluetooth/a2dp/A2dpServiceTest.java index 857c663b28..21d4645798 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/a2dp/A2dpServiceTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/a2dp/A2dpServiceTest.java @@ -50,13 +50,15 @@ import org.hamcrest.core.AllOf; import org.junit.After; import org.junit.Assert; import org.junit.Before; +import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.ArgumentCaptor; import org.mockito.InOrder; import org.mockito.Mock; -import org.mockito.MockitoAnnotations; import org.mockito.hamcrest.MockitoHamcrest; +import org.mockito.junit.MockitoJUnit; +import org.mockito.junit.MockitoRule; import java.time.Duration; import java.util.Arrays; @@ -72,6 +74,8 @@ public class A2dpServiceTest { private static final BluetoothDevice sTestDevice = sAdapter.getRemoteDevice("00:01:02:03:04:05"); + @Rule public MockitoRule mockitoRule = MockitoJUnit.rule(); + @Mock private A2dpNativeInterface mMockNativeInterface; @Mock private ActiveDeviceManager mActiveDeviceManager; @Mock private AdapterService mAdapterService; @@ -84,8 +88,6 @@ public class A2dpServiceTest { @Before public void setUp() throws Exception { - // Set up mocks and test assets - MockitoAnnotations.initMocks(this); mInOrder = inOrder(mAdapterService); TestUtils.mockGetSystemService( diff --git a/android/app/tests/unit/src/com/android/bluetooth/a2dp/A2dpStateMachineTest.java b/android/app/tests/unit/src/com/android/bluetooth/a2dp/A2dpStateMachineTest.java index 0c6fdc6936..98cee48f89 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/a2dp/A2dpStateMachineTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/a2dp/A2dpStateMachineTest.java @@ -42,11 +42,13 @@ import org.hamcrest.core.IsInstanceOf; import org.junit.After; import org.junit.Assert; import org.junit.Before; +import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.ArgumentCaptor; import org.mockito.Mock; -import org.mockito.MockitoAnnotations; +import org.mockito.junit.MockitoJUnit; +import org.mockito.junit.MockitoRule; import java.util.Arrays; @@ -64,6 +66,8 @@ public class A2dpStateMachineTest { private BluetoothCodecConfig mCodecConfigAac; private BluetoothCodecConfig mCodecConfigOpus; + @Rule public MockitoRule mockitoRule = MockitoJUnit.rule(); + @Mock private AdapterService mAdapterService; @Mock private ActiveDeviceManager mActiveDeviceManager; @Mock private SilenceDeviceManager mSilenceDeviceManager; @@ -73,8 +77,6 @@ public class A2dpStateMachineTest { @Before public void setUp() throws Exception { mTargetContext = InstrumentationRegistry.getTargetContext(); - // Set up mocks and test assets - MockitoAnnotations.initMocks(this); doReturn(mActiveDeviceManager).when(mAdapterService).getActiveDeviceManager(); doReturn(mSilenceDeviceManager).when(mAdapterService).getSilenceDeviceManager(); diff --git a/android/app/tests/unit/src/com/android/bluetooth/a2dpsink/A2dpSinkServiceBinderTest.java b/android/app/tests/unit/src/com/android/bluetooth/a2dpsink/A2dpSinkServiceBinderTest.java index 0d1650ee00..23641be621 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/a2dpsink/A2dpSinkServiceBinderTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/a2dpsink/A2dpSinkServiceBinderTest.java @@ -29,20 +29,23 @@ import com.android.bluetooth.x.com.android.modules.utils.SynchronousResultReceiv import org.junit.After; import org.junit.Before; +import org.junit.Rule; import org.junit.Test; import org.mockito.Mock; -import org.mockito.MockitoAnnotations; +import org.mockito.junit.MockitoJUnit; +import org.mockito.junit.MockitoRule; import java.util.List; public class A2dpSinkServiceBinderTest { + @Rule public MockitoRule mockitoRule = MockitoJUnit.rule(); + @Mock private A2dpSinkService mService; private A2dpSinkService.A2dpSinkServiceBinder mBinder; private BluetoothAdapter mAdapter; @Before public void setUp() throws Exception { - MockitoAnnotations.initMocks(this); mAdapter = BluetoothAdapter.getDefaultAdapter(); mBinder = new A2dpSinkService.A2dpSinkServiceBinder(mService); } diff --git a/android/app/tests/unit/src/com/android/bluetooth/a2dpsink/A2dpSinkServiceTest.java b/android/app/tests/unit/src/com/android/bluetooth/a2dpsink/A2dpSinkServiceTest.java index 6f546daa9d..d19e6aa5a9 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/a2dpsink/A2dpSinkServiceTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/a2dpsink/A2dpSinkServiceTest.java @@ -43,7 +43,8 @@ import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; -import org.mockito.MockitoAnnotations; +import org.mockito.junit.MockitoJUnit; +import org.mockito.junit.MockitoRule; import java.util.ArrayList; import java.util.List; @@ -57,6 +58,8 @@ public class A2dpSinkServiceTest { @Rule public final ServiceTestRule mServiceRule = new ServiceTestRule(); + @Rule public MockitoRule mockitoRule = MockitoJUnit.rule(); + @Mock private AdapterService mAdapterService; @Mock private DatabaseManager mDatabaseManager; @Mock private A2dpSinkNativeInterface mNativeInterface; @@ -76,7 +79,6 @@ public class A2dpSinkServiceTest { @Before public void setUp() throws Exception { mTargetContext = InstrumentationRegistry.getTargetContext(); - MockitoAnnotations.initMocks(this); mLooper = new TestLooper(); diff --git a/android/app/tests/unit/src/com/android/bluetooth/a2dpsink/A2dpSinkStateMachineTest.java b/android/app/tests/unit/src/com/android/bluetooth/a2dpsink/A2dpSinkStateMachineTest.java index 03d95a3a77..aac7f7f675 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/a2dpsink/A2dpSinkStateMachineTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/a2dpsink/A2dpSinkStateMachineTest.java @@ -38,16 +38,20 @@ import com.android.bluetooth.TestUtils; import org.junit.After; import org.junit.Before; +import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; -import org.mockito.MockitoAnnotations; +import org.mockito.junit.MockitoJUnit; +import org.mockito.junit.MockitoRule; @RunWith(AndroidJUnit4.class) public class A2dpSinkStateMachineTest { private static final String DEVICE_ADDRESS = "11:11:11:11:11:11"; private static final int UNHANDLED_MESSAGE = 9999; + @Rule public MockitoRule mockitoRule = MockitoJUnit.rule(); + @Mock private A2dpSinkService mService; @Mock private A2dpSinkNativeInterface mNativeInterface; @@ -60,7 +64,6 @@ public class A2dpSinkStateMachineTest { @Before public void setUp() throws Exception { mTargetContext = InstrumentationRegistry.getTargetContext(); - MockitoAnnotations.initMocks(this); mLooper = new TestLooper(); diff --git a/android/app/tests/unit/src/com/android/bluetooth/a2dpsink/A2dpSinkStreamHandlerTest.java b/android/app/tests/unit/src/com/android/bluetooth/a2dpsink/A2dpSinkStreamHandlerTest.java index 4b25bbba1d..fe49e05bf6 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/a2dpsink/A2dpSinkStreamHandlerTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/a2dpsink/A2dpSinkStreamHandlerTest.java @@ -45,7 +45,8 @@ import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; -import org.mockito.MockitoAnnotations; +import org.mockito.junit.MockitoJUnit; +import org.mockito.junit.MockitoRule; @MediumTest @RunWith(AndroidJUnit4.class) @@ -56,6 +57,8 @@ public class A2dpSinkStreamHandlerTest { private A2dpSinkStreamHandler mStreamHandler; private Context mTargetContext; + @Rule public MockitoRule mockitoRule = MockitoJUnit.rule(); + @Mock private A2dpSinkService mMockA2dpSink; @Mock private A2dpSinkNativeInterface mMockNativeInterface; @@ -76,7 +79,6 @@ public class A2dpSinkStreamHandlerTest { @Before public void setUp() throws Exception { mTargetContext = InstrumentationRegistry.getTargetContext(); - MockitoAnnotations.initMocks(this); // Mock the looper if (Looper.myLooper() == null) { Looper.prepare(); diff --git a/android/app/tests/unit/src/com/android/bluetooth/audio_util/BrowsablePlayerConnectorTest.java b/android/app/tests/unit/src/com/android/bluetooth/audio_util/BrowsablePlayerConnectorTest.java index 5d4f49d98c..c2426563b5 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/audio_util/BrowsablePlayerConnectorTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/audio_util/BrowsablePlayerConnectorTest.java @@ -33,10 +33,12 @@ import androidx.test.InstrumentationRegistry; import androidx.test.runner.AndroidJUnit4; import org.junit.Before; +import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; -import org.mockito.MockitoAnnotations; +import org.mockito.junit.MockitoJUnit; +import org.mockito.junit.MockitoRule; import java.util.ArrayList; import java.util.Collections; @@ -51,11 +53,12 @@ public final class BrowsablePlayerConnectorTest { Context mContext; TestLooper mTestLooper; List<ResolveInfo> mPlayerList; + @Rule public MockitoRule mockitoRule = MockitoJUnit.rule(); + @Mock MediaBrowser mMediaBrowser; MediaBrowser.ConnectionCallback mConnectionCallback; @Before public void setUp() { - MockitoAnnotations.initMocks(this); mContext = InstrumentationRegistry.getTargetContext(); mTestLooper = new TestLooper(); diff --git a/android/app/tests/unit/src/com/android/bluetooth/audio_util/BrowserPlayerWrapperTest.java b/android/app/tests/unit/src/com/android/bluetooth/audio_util/BrowserPlayerWrapperTest.java index c5d6fd22d2..dcf1b069d9 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/audio_util/BrowserPlayerWrapperTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/audio_util/BrowserPlayerWrapperTest.java @@ -44,12 +44,14 @@ import com.android.bluetooth.TestUtils; import org.junit.After; import org.junit.Assert; import org.junit.Before; +import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.ArgumentCaptor; import org.mockito.Captor; import org.mockito.Mock; -import org.mockito.MockitoAnnotations; +import org.mockito.junit.MockitoJUnit; +import org.mockito.junit.MockitoRule; import java.io.InputStream; import java.util.ArrayList; @@ -64,6 +66,8 @@ public class BrowserPlayerWrapperTest { @Captor ArgumentCaptor<MediaController.Callback> mControllerCb; @Captor ArgumentCaptor<Handler> mTimeoutHandler; @Captor ArgumentCaptor<List<ListItem>> mWrapperBrowseCb; + @Rule public MockitoRule mockitoRule = MockitoJUnit.rule(); + @Mock MediaBrowser mMockBrowser; @Mock BrowsedPlayerWrapper.ConnectionCallback mConnCb; @Mock BrowsedPlayerWrapper.BrowseCallback mBrowseCb; @@ -91,7 +95,6 @@ public class BrowserPlayerWrapperTest { @Before public void setUp() { - MockitoAnnotations.initMocks(this); mTargetContext = InstrumentationRegistry.getTargetContext(); mTestResources = TestUtils.getTestApplicationResources(mTargetContext); diff --git a/android/app/tests/unit/src/com/android/bluetooth/audio_util/ImageTest.java b/android/app/tests/unit/src/com/android/bluetooth/audio_util/ImageTest.java index 7e2106b5eb..4d7d339d86 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/audio_util/ImageTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/audio_util/ImageTest.java @@ -41,10 +41,12 @@ import com.android.bluetooth.TestUtils; import org.junit.After; import org.junit.Before; +import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; -import org.mockito.MockitoAnnotations; +import org.mockito.junit.MockitoJUnit; +import org.mockito.junit.MockitoRule; import java.io.InputStream; @@ -52,6 +54,8 @@ import java.io.InputStream; public class ImageTest { private Context mTargetContext; + @Rule public MockitoRule mockitoRule = MockitoJUnit.rule(); + private @Mock Context mMockContext; private @Mock Resources mMockResources; private Resources mTestResources; @@ -78,7 +82,6 @@ public class ImageTest { @Before public void setUp() throws Exception { - MockitoAnnotations.initMocks(this); mTargetContext = InstrumentationRegistry.getTargetContext(); mTestResources = TestUtils.getTestApplicationResources(mTargetContext); diff --git a/android/app/tests/unit/src/com/android/bluetooth/audio_util/MediaPlayerListTest.java b/android/app/tests/unit/src/com/android/bluetooth/audio_util/MediaPlayerListTest.java index 353e6badba..6b7af24254 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/audio_util/MediaPlayerListTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/audio_util/MediaPlayerListTest.java @@ -33,12 +33,14 @@ import androidx.test.runner.AndroidJUnit4; import org.junit.After; import org.junit.Assert; import org.junit.Before; +import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.ArgumentCaptor; import org.mockito.Captor; import org.mockito.Mock; -import org.mockito.MockitoAnnotations; +import org.mockito.junit.MockitoJUnit; +import org.mockito.junit.MockitoRule; import java.util.ArrayList; @@ -50,6 +52,8 @@ public class MediaPlayerListTest { private @Captor ArgumentCaptor<AudioManager.AudioPlaybackCallback> mAudioCb; private @Captor ArgumentCaptor<MediaPlayerWrapper.Callback> mPlayerWrapperCb; private @Captor ArgumentCaptor<MediaData> mMediaUpdateData; + @Rule public MockitoRule mockitoRule = MockitoJUnit.rule(); + private @Mock Context mMockContext; private @Mock MediaPlayerList.MediaUpdateCallback mMediaUpdateCallback; private @Mock MediaController mMockController; @@ -70,7 +74,6 @@ public class MediaPlayerListTest { } Assert.assertNotNull(Looper.myLooper()); - MockitoAnnotations.initMocks(this); AudioManager mockAudioManager = mock(AudioManager.class); when(mMockContext.getSystemService(Context.AUDIO_SERVICE)).thenReturn(mockAudioManager); diff --git a/android/app/tests/unit/src/com/android/bluetooth/audio_util/MediaPlayerWrapperTest.java b/android/app/tests/unit/src/com/android/bluetooth/audio_util/MediaPlayerWrapperTest.java index 9ed1fa0c96..4503968683 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/audio_util/MediaPlayerWrapperTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/audio_util/MediaPlayerWrapperTest.java @@ -41,12 +41,14 @@ import com.android.bluetooth.TestUtils; import org.junit.Assert; import org.junit.Before; +import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.ArgumentCaptor; import org.mockito.Captor; import org.mockito.Mock; -import org.mockito.MockitoAnnotations; +import org.mockito.junit.MockitoJUnit; +import org.mockito.junit.MockitoRule; import java.io.InputStream; import java.util.ArrayList; @@ -68,6 +70,8 @@ public class MediaPlayerWrapperTest { @Captor ArgumentCaptor<MediaController.Callback> mControllerCbs; @Captor ArgumentCaptor<MediaData> mMediaUpdateData; + @Rule public MockitoRule mockitoRule = MockitoJUnit.rule(); + @Mock Log.TerribleFailureHandler mFailHandler; @Mock MediaController mMockController; @Mock MediaPlayerWrapper.Callback mTestCbs; @@ -89,7 +93,6 @@ public class MediaPlayerWrapperTest { @Before public void setUp() { - MockitoAnnotations.initMocks(this); mTestResources = TestUtils.getTestApplicationResources( InstrumentationRegistry.getTargetContext()); diff --git a/android/app/tests/unit/src/com/android/bluetooth/audio_util/MetadataTest.java b/android/app/tests/unit/src/com/android/bluetooth/audio_util/MetadataTest.java index f36b13bf20..8b8940815e 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/audio_util/MetadataTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/audio_util/MetadataTest.java @@ -44,10 +44,12 @@ import com.android.bluetooth.TestUtils; import org.junit.After; import org.junit.Assert; import org.junit.Before; +import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; -import org.mockito.MockitoAnnotations; +import org.mockito.junit.MockitoJUnit; +import org.mockito.junit.MockitoRule; import java.io.InputStream; @@ -55,6 +57,8 @@ import java.io.InputStream; public class MetadataTest { private Context mTargetContext; + @Rule public MockitoRule mockitoRule = MockitoJUnit.rule(); + private @Mock Context mMockContext; private @Mock Resources mMockResources; private Resources mTestResources; @@ -88,7 +92,6 @@ public class MetadataTest { @Before public void setUp() throws Exception { - MockitoAnnotations.initMocks(this); mTargetContext = InstrumentationRegistry.getTargetContext(); mTestResources = TestUtils.getTestApplicationResources(mTargetContext); diff --git a/android/app/tests/unit/src/com/android/bluetooth/avrcp/AvrcpVolumeManagerTest.java b/android/app/tests/unit/src/com/android/bluetooth/avrcp/AvrcpVolumeManagerTest.java index 0a187f294b..d79e16ff18 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/avrcp/AvrcpVolumeManagerTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/avrcp/AvrcpVolumeManagerTest.java @@ -37,11 +37,13 @@ import androidx.test.runner.AndroidJUnit4; import org.junit.After; import org.junit.Before; +import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; import org.mockito.Mockito; -import org.mockito.MockitoAnnotations; +import org.mockito.junit.MockitoJUnit; +import org.mockito.junit.MockitoRule; @SmallTest @RunWith(AndroidJUnit4.class) @@ -49,6 +51,8 @@ public class AvrcpVolumeManagerTest { private static final String REMOTE_DEVICE_ADDRESS = "00:01:02:03:04:05"; private static final int TEST_DEVICE_MAX_VOUME = 25; + @Rule public MockitoRule mockitoRule = MockitoJUnit.rule(); + @Mock AvrcpNativeInterface mNativeInterface; @@ -61,7 +65,6 @@ public class AvrcpVolumeManagerTest { @Before public void setUp() throws Exception { - MockitoAnnotations.initMocks(this); mContext = InstrumentationRegistry.getTargetContext(); when(mAudioManager.getStreamMaxVolume(AudioManager.STREAM_MUSIC)) .thenReturn(TEST_DEVICE_MAX_VOUME); diff --git a/android/app/tests/unit/src/com/android/bluetooth/avrcpcontroller/AvrcpBipClientTest.java b/android/app/tests/unit/src/com/android/bluetooth/avrcpcontroller/AvrcpBipClientTest.java index e3dd565833..ee6481b197 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/avrcpcontroller/AvrcpBipClientTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/avrcpcontroller/AvrcpBipClientTest.java @@ -40,7 +40,8 @@ import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; -import org.mockito.MockitoAnnotations; +import org.mockito.junit.MockitoJUnit; +import org.mockito.junit.MockitoRule; @SmallTest @RunWith(AndroidJUnit4.class) @@ -50,6 +51,8 @@ public class AvrcpBipClientTest { @Rule public final ServiceTestRule mBluetoothBrowserMediaServiceTestRule = new ServiceTestRule(); + @Rule public MockitoRule mockitoRule = MockitoJUnit.rule(); + @Mock private AdapterService mAdapterService; @Mock private AvrcpControllerNativeInterface mNativeInterface; @@ -62,7 +65,6 @@ public class AvrcpBipClientTest { @Before public void setUp() throws Exception { Context targetContext = InstrumentationRegistry.getTargetContext(); - MockitoAnnotations.initMocks(this); TestUtils.setAdapterService(mAdapterService); AvrcpControllerNativeInterface.setInstance(mNativeInterface); mService = new AvrcpControllerService(targetContext, mNativeInterface); diff --git a/android/app/tests/unit/src/com/android/bluetooth/avrcpcontroller/AvrcpControllerServiceBinderTest.java b/android/app/tests/unit/src/com/android/bluetooth/avrcpcontroller/AvrcpControllerServiceBinderTest.java index c30d989a13..97117a2f85 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/avrcpcontroller/AvrcpControllerServiceBinderTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/avrcpcontroller/AvrcpControllerServiceBinderTest.java @@ -28,16 +28,20 @@ import androidx.test.runner.AndroidJUnit4; import com.android.bluetooth.x.com.android.modules.utils.SynchronousResultReceiver; import org.junit.Before; +import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; -import org.mockito.MockitoAnnotations; +import org.mockito.junit.MockitoJUnit; +import org.mockito.junit.MockitoRule; @SmallTest @RunWith(AndroidJUnit4.class) public class AvrcpControllerServiceBinderTest { private static final String REMOTE_DEVICE_ADDRESS = "00:00:00:00:00:00"; + @Rule public MockitoRule mockitoRule = MockitoJUnit.rule(); + @Mock private AvrcpControllerService mService; @@ -47,7 +51,6 @@ public class AvrcpControllerServiceBinderTest { @Before public void setUp() throws Exception { - MockitoAnnotations.initMocks(this); mRemoteDevice = BluetoothAdapter.getDefaultAdapter().getRemoteDevice(REMOTE_DEVICE_ADDRESS); mBinder = new AvrcpControllerService.AvrcpControllerServiceBinder(mService); } diff --git a/android/app/tests/unit/src/com/android/bluetooth/avrcpcontroller/AvrcpControllerServiceTest.java b/android/app/tests/unit/src/com/android/bluetooth/avrcpcontroller/AvrcpControllerServiceTest.java index 19b8f6c95e..f74372bca1 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/avrcpcontroller/AvrcpControllerServiceTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/avrcpcontroller/AvrcpControllerServiceTest.java @@ -49,7 +49,8 @@ import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.ArgumentCaptor; import org.mockito.Mock; -import org.mockito.MockitoAnnotations; +import org.mockito.junit.MockitoJUnit; +import org.mockito.junit.MockitoRule; import java.util.ArrayList; import java.util.Arrays; @@ -67,6 +68,8 @@ public class AvrcpControllerServiceTest { @Rule public final ServiceTestRule mBluetoothBrowserMediaServiceTestRule = new ServiceTestRule(); + @Rule public MockitoRule mockitoRule = MockitoJUnit.rule(); + @Mock private AdapterService mAdapterService; @Mock private AvrcpControllerStateMachine mStateMachine; @Mock private AvrcpControllerNativeInterface mNativeInterface; @@ -76,7 +79,6 @@ public class AvrcpControllerServiceTest { @Before public void setUp() throws Exception { Context targetContext = InstrumentationRegistry.getTargetContext(); - MockitoAnnotations.initMocks(this); TestUtils.setAdapterService(mAdapterService); AvrcpControllerNativeInterface.setInstance(mNativeInterface); mService = new AvrcpControllerService(targetContext, mNativeInterface); diff --git a/android/app/tests/unit/src/com/android/bluetooth/avrcpcontroller/AvrcpControllerStateMachineTest.java b/android/app/tests/unit/src/com/android/bluetooth/avrcpcontroller/AvrcpControllerStateMachineTest.java index d01d565524..e8181d283f 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/avrcpcontroller/AvrcpControllerStateMachineTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/avrcpcontroller/AvrcpControllerStateMachineTest.java @@ -56,7 +56,8 @@ import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.ArgumentCaptor; import org.mockito.Mock; -import org.mockito.MockitoAnnotations; +import org.mockito.junit.MockitoJUnit; +import org.mockito.junit.MockitoRule; import java.util.ArrayList; import java.util.List; @@ -74,6 +75,8 @@ public class AvrcpControllerStateMachineTest { @Rule public final ServiceTestRule mAvrcpServiceRule = new ServiceTestRule(); @Rule public final ServiceTestRule mA2dpServiceRule = new ServiceTestRule(); + @Rule public MockitoRule mockitoRule = MockitoJUnit.rule(); + @Mock private AdapterService mA2dpAdapterService; @Mock private AdapterService mAvrcpAdapterService; @Mock private A2dpSinkService mA2dpSinkService; @@ -97,7 +100,6 @@ public class AvrcpControllerStateMachineTest { } Assert.assertNotNull(Looper.myLooper()); - MockitoAnnotations.initMocks(this); // Start a real A2dpSinkService so we can replace the static instance with our mock doReturn(mDatabaseManager).when(mA2dpAdapterService).getDatabase(); diff --git a/android/app/tests/unit/src/com/android/bluetooth/avrcpcontroller/AvrcpCoverArtProviderTest.java b/android/app/tests/unit/src/com/android/bluetooth/avrcpcontroller/AvrcpCoverArtProviderTest.java index d55695d949..ddddbd08fe 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/avrcpcontroller/AvrcpCoverArtProviderTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/avrcpcontroller/AvrcpCoverArtProviderTest.java @@ -38,7 +38,8 @@ import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; -import org.mockito.MockitoAnnotations; +import org.mockito.junit.MockitoJUnit; +import org.mockito.junit.MockitoRule; import java.io.FileNotFoundException; @@ -55,13 +56,14 @@ public class AvrcpCoverArtProviderTest { @Rule public final ServiceTestRule mServiceRule = new ServiceTestRule(); + @Rule public MockitoRule mockitoRule = MockitoJUnit.rule(); + @Mock private Uri mUri; @Mock private AdapterService mAdapterService; @Mock private AvrcpControllerNativeInterface mNativeInterface; @Before public void setUp() throws Exception { - MockitoAnnotations.initMocks(this); TestUtils.setAdapterService(mAdapterService); AvrcpControllerNativeInterface.setInstance(mNativeInterface); mAdapter = BluetoothAdapter.getDefaultAdapter(); diff --git a/android/app/tests/unit/src/com/android/bluetooth/avrcpcontroller/AvrcpPlayerTest.java b/android/app/tests/unit/src/com/android/bluetooth/avrcpcontroller/AvrcpPlayerTest.java index 30e9c62132..4f6b44d55a 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/avrcpcontroller/AvrcpPlayerTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/avrcpcontroller/AvrcpPlayerTest.java @@ -26,9 +26,11 @@ import android.net.Uri; import android.support.v4.media.session.PlaybackStateCompat; import org.junit.Before; +import org.junit.Rule; import org.junit.Test; import org.mockito.Mock; -import org.mockito.MockitoAnnotations; +import org.mockito.junit.MockitoJUnit; +import org.mockito.junit.MockitoRule; public class AvrcpPlayerTest { private static final int TEST_PLAYER_ID = 1; @@ -44,12 +46,13 @@ public class AvrcpPlayerTest { private BluetoothAdapter mAdapter; private BluetoothDevice mTestDevice = null; + @Rule public MockitoRule mockitoRule = MockitoJUnit.rule(); + @Mock private PlayerApplicationSettings mPlayerApplicationSettings; @Before public void setUp() { - MockitoAnnotations.initMocks(this); mAdapter = BluetoothAdapter.getDefaultAdapter(); mTestDevice = mAdapter.getRemoteDevice(mTestAddress); } diff --git a/android/app/tests/unit/src/com/android/bluetooth/bas/BatteryServiceBinderTest.java b/android/app/tests/unit/src/com/android/bluetooth/bas/BatteryServiceBinderTest.java index 91b6af8ad1..cdc9de99f0 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/bas/BatteryServiceBinderTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/bas/BatteryServiceBinderTest.java @@ -28,13 +28,17 @@ import com.android.bluetooth.x.com.android.modules.utils.SynchronousResultReceiv import org.junit.After; import org.junit.Before; +import org.junit.Rule; import org.junit.Test; import org.mockito.Mock; -import org.mockito.MockitoAnnotations; +import org.mockito.junit.MockitoJUnit; +import org.mockito.junit.MockitoRule; import java.util.List; public class BatteryServiceBinderTest { + @Rule public MockitoRule mockitoRule = MockitoJUnit.rule(); + @Mock private BatteryService mService; private BatteryService.BluetoothBatteryBinder mBinder; @@ -42,7 +46,6 @@ public class BatteryServiceBinderTest { @Before public void setUp() throws Exception { - MockitoAnnotations.initMocks(this); mAdapter = BluetoothAdapter.getDefaultAdapter(); mBinder = new BatteryService.BluetoothBatteryBinder(mService); } diff --git a/android/app/tests/unit/src/com/android/bluetooth/bass_client/BassClientServiceTest.java b/android/app/tests/unit/src/com/android/bluetooth/bass_client/BassClientServiceTest.java index 7d7fb8aa6d..a4b11d38e5 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/bass_client/BassClientServiceTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/bass_client/BassClientServiceTest.java @@ -74,13 +74,15 @@ import com.android.bluetooth.le_audio.LeAudioService; import org.junit.After; import org.junit.Assert; import org.junit.Before; +import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.ArgumentCaptor; import org.mockito.Mock; import org.mockito.Mockito; -import org.mockito.MockitoAnnotations; import org.mockito.Spy; +import org.mockito.junit.MockitoJUnit; +import org.mockito.junit.MockitoRule; import java.util.ArrayList; import java.util.Arrays; @@ -140,6 +142,8 @@ public class BassClientServiceTest { private BassIntentReceiver mBassIntentReceiver; @Spy private BassObjectsFactory mObjectsFactory = BassObjectsFactory.getInstance(); + @Rule public MockitoRule mockitoRule = MockitoJUnit.rule(); + @Mock private AdapterService mAdapterService; @Mock private DatabaseManager mDatabaseManager; @Mock private BluetoothLeScannerWrapper mBluetoothLeScannerWrapper; @@ -200,7 +204,6 @@ public class BassClientServiceTest { } mTargetContext = InstrumentationRegistry.getTargetContext(); - MockitoAnnotations.initMocks(this); TestUtils.setAdapterService(mAdapterService); BassObjectsFactory.setInstanceForTesting(mObjectsFactory); diff --git a/android/app/tests/unit/src/com/android/bluetooth/bass_client/BleBroadcastAssistantBinderTest.java b/android/app/tests/unit/src/com/android/bluetooth/bass_client/BleBroadcastAssistantBinderTest.java index 678b6b1a02..0f7034a075 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/bass_client/BleBroadcastAssistantBinderTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/bass_client/BleBroadcastAssistantBinderTest.java @@ -34,12 +34,14 @@ import android.bluetooth.le.ScanFilter; import com.android.bluetooth.TestUtils; import org.junit.Before; +import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.JUnit4; import org.mockito.Mock; import org.mockito.Mockito; -import org.mockito.MockitoAnnotations; +import org.mockito.junit.MockitoJUnit; +import org.mockito.junit.MockitoRule; import java.util.Collections; import java.util.List; @@ -47,6 +49,8 @@ import java.util.List; @RunWith(JUnit4.class) public class BleBroadcastAssistantBinderTest { + @Rule public MockitoRule mockitoRule = MockitoJUnit.rule(); + @Mock private BassClientService mService; private BassClientService.BluetoothLeBroadcastAssistantBinder mBinder; @@ -54,7 +58,6 @@ public class BleBroadcastAssistantBinderTest { @Before public void setUp() { - MockitoAnnotations.initMocks(this); mBinder = new BassClientService.BluetoothLeBroadcastAssistantBinder(mService); mAdapter = BluetoothAdapter.getDefaultAdapter(); } diff --git a/android/app/tests/unit/src/com/android/bluetooth/btservice/ActiveDeviceManagerTest.java b/android/app/tests/unit/src/com/android/bluetooth/btservice/ActiveDeviceManagerTest.java index 7cc9aecb6c..b344a37fb6 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/btservice/ActiveDeviceManagerTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/btservice/ActiveDeviceManagerTest.java @@ -67,8 +67,9 @@ import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; import org.mockito.Mockito; -import org.mockito.MockitoAnnotations; import org.mockito.Spy; +import org.mockito.junit.MockitoJUnit; +import org.mockito.junit.MockitoRule; import java.util.ArrayList; import java.util.List; @@ -100,6 +101,8 @@ public class ActiveDeviceManagerTest { private TestLooper mTestLooper; @Rule public final SetFlagsRule mSetFlagsRule = new SetFlagsRule(); + @Rule public MockitoRule mockitoRule = MockitoJUnit.rule(); + @Mock private AdapterService mAdapterService; @Mock private ServiceFactory mServiceFactory; @Mock private A2dpService mA2dpService; @@ -111,8 +114,6 @@ public class ActiveDeviceManagerTest { @Before public void setUp() throws Exception { - // Set up mocks and test assets - MockitoAnnotations.initMocks(this); mTestLooper = new TestLooper(); BluetoothMethodProxy.setInstanceForTesting(mMethodProxy); doReturn(mTestLooper.getLooper()).when(mMethodProxy).handlerThreadGetLooper(any()); diff --git a/android/app/tests/unit/src/com/android/bluetooth/btservice/AdapterPropertiesTest.java b/android/app/tests/unit/src/com/android/bluetooth/btservice/AdapterPropertiesTest.java index 436151b46d..2b7283ed34 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/btservice/AdapterPropertiesTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/btservice/AdapterPropertiesTest.java @@ -36,11 +36,13 @@ import androidx.test.runner.AndroidJUnit4; import com.android.bluetooth.Utils; import org.junit.Before; +import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.ArgumentCaptor; import org.mockito.Mock; -import org.mockito.MockitoAnnotations; +import org.mockito.junit.MockitoJUnit; +import org.mockito.junit.MockitoRule; @MediumTest @RunWith(AndroidJUnit4.class) @@ -54,6 +56,8 @@ public class AdapterPropertiesTest { private HandlerThread mHandlerThread; private Context mTargetContext; + @Rule public MockitoRule mockitoRule = MockitoJUnit.rule(); + @Mock private AdapterService mAdapterService; @Mock private AdapterNativeInterface mNativeInterface; @@ -61,7 +65,6 @@ public class AdapterPropertiesTest { public void setUp() throws Exception { mTargetContext = InstrumentationRegistry.getTargetContext(); - MockitoAnnotations.initMocks(this); doReturn(mNativeInterface).when(mAdapterService).getNative(); mHandlerThread = new HandlerThread("RemoteDevicesTestHandlerThread"); mHandlerThread.start(); diff --git a/android/app/tests/unit/src/com/android/bluetooth/btservice/AdapterServiceBinderTest.java b/android/app/tests/unit/src/com/android/bluetooth/btservice/AdapterServiceBinderTest.java index 68ac543169..729ae74b79 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/btservice/AdapterServiceBinderTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/btservice/AdapterServiceBinderTest.java @@ -31,14 +31,18 @@ import com.android.bluetooth.x.com.android.modules.utils.SynchronousResultReceiv import org.junit.After; import org.junit.Before; +import org.junit.Rule; import org.junit.Test; import org.mockito.Mock; import org.mockito.Mockito; -import org.mockito.MockitoAnnotations; +import org.mockito.junit.MockitoJUnit; +import org.mockito.junit.MockitoRule; import java.io.FileDescriptor; public class AdapterServiceBinderTest { + @Rule public MockitoRule mockitoRule = MockitoJUnit.rule(); + @Mock private AdapterService mService; @Mock private AdapterProperties mAdapterProperties; @@ -47,7 +51,6 @@ public class AdapterServiceBinderTest { @Before public void setUp() { - MockitoAnnotations.initMocks(this); mService.mAdapterProperties = mAdapterProperties; doReturn(true).when(mService).isAvailable(); doNothing().when(mService).enforceCallingOrSelfPermission(any(), any()); 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 099c29970a..898e6fd791 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 @@ -71,10 +71,12 @@ import com.android.internal.app.IBatteryStats; import org.junit.After; import org.junit.Before; import org.junit.Ignore; +import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; -import org.mockito.MockitoAnnotations; +import org.mockito.junit.MockitoJUnit; +import org.mockito.junit.MockitoRule; import java.util.HashMap; import java.util.List; @@ -86,6 +88,8 @@ public class AdapterServiceFactoryResetTest { private AdapterService mAdapterService; + @Rule public MockitoRule mockitoRule = MockitoJUnit.rule(); + private @Mock Context mMockContext; private @Mock ApplicationInfo mMockApplicationInfo; private @Mock Resources mMockResources; @@ -143,7 +147,6 @@ public class AdapterServiceFactoryResetTest { @Before public void setUp() throws PackageManager.NameNotFoundException { Log.e(TAG, "setUp()"); - MockitoAnnotations.initMocks(this); mLooper = new TestLooper(); Handler handler = new Handler(mLooper.getLooper()); 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 12dac99161..93a6688fe4 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 @@ -66,10 +66,12 @@ import com.android.internal.app.IBatteryStats; import org.junit.After; import org.junit.Before; import org.junit.Ignore; +import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; -import org.mockito.MockitoAnnotations; +import org.mockito.junit.MockitoJUnit; +import org.mockito.junit.MockitoRule; import java.util.HashMap; @@ -80,6 +82,8 @@ public class AdapterServiceRestartTest { private AdapterService mAdapterService; + @Rule public MockitoRule mockitoRule = MockitoJUnit.rule(); + private @Mock Context mMockContext; private @Mock ApplicationInfo mMockApplicationInfo; private @Mock Resources mMockResources; @@ -124,7 +128,6 @@ public class AdapterServiceRestartTest { @Before public void setUp() throws PackageManager.NameNotFoundException { Log.e(TAG, "setUp()"); - MockitoAnnotations.initMocks(this); mLooper = new TestLooper(); Handler handler = new Handler(mLooper.getLooper()); 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 cc84dbc68f..1e1fcc8447 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 @@ -90,7 +90,8 @@ import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; -import org.mockito.MockitoAnnotations; +import org.mockito.junit.MockitoJUnit; +import org.mockito.junit.MockitoRule; import java.io.FileDescriptor; import java.io.PrintWriter; @@ -115,6 +116,8 @@ public class AdapterServiceTest { private AdapterService mAdapterService; + @Rule public MockitoRule mockitoRule = MockitoJUnit.rule(); + private @Mock Context mMockContext; private @Mock ApplicationInfo mMockApplicationInfo; private @Mock Resources mMockResources; @@ -186,7 +189,6 @@ public class AdapterServiceTest { @Before public void setUp() throws PackageManager.NameNotFoundException { Log.e(TAG, "setUp()"); - MockitoAnnotations.initMocks(this); mLooper = new TestLooper(); Handler handler = new Handler(mLooper.getLooper()); diff --git a/android/app/tests/unit/src/com/android/bluetooth/btservice/AudioRoutingManagerTest.java b/android/app/tests/unit/src/com/android/bluetooth/btservice/AudioRoutingManagerTest.java index d294c33e77..f4da3aa7e1 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/btservice/AudioRoutingManagerTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/btservice/AudioRoutingManagerTest.java @@ -56,12 +56,14 @@ import com.android.bluetooth.le_audio.LeAudioService; import org.junit.After; import org.junit.Assume; import org.junit.Before; +import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; import org.mockito.Mockito; -import org.mockito.MockitoAnnotations; import org.mockito.Spy; +import org.mockito.junit.MockitoJUnit; +import org.mockito.junit.MockitoRule; import java.util.ArrayList; import java.util.Collections; @@ -91,6 +93,8 @@ public class AudioRoutingManagerTest { private TestDatabaseManager mDatabaseManager; private TestLooper mTestLooper; + @Rule public MockitoRule mockitoRule = MockitoJUnit.rule(); + @Mock private AdapterService mAdapterService; @Mock private ServiceFactory mServiceFactory; @Mock private A2dpService mA2dpService; @@ -102,8 +106,6 @@ public class AudioRoutingManagerTest { @Before public void setUp() throws Exception { - // Set up mocks and test assets - MockitoAnnotations.initMocks(this); mTestLooper = new TestLooper(); BluetoothMethodProxy.setInstanceForTesting(mMethodProxy); doReturn(mTestLooper.getLooper()).when(mMethodProxy).handlerThreadGetLooper(any()); diff --git a/android/app/tests/unit/src/com/android/bluetooth/btservice/BondStateMachineTest.java b/android/app/tests/unit/src/com/android/bluetooth/btservice/BondStateMachineTest.java index 91aee3700e..4e571d24e9 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/btservice/BondStateMachineTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/btservice/BondStateMachineTest.java @@ -40,11 +40,13 @@ import com.android.bluetooth.Utils; import org.junit.After; import org.junit.Assert; import org.junit.Before; +import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.ArgumentCaptor; import org.mockito.Mock; -import org.mockito.MockitoAnnotations; +import org.mockito.junit.MockitoJUnit; +import org.mockito.junit.MockitoRule; @MediumTest @RunWith(AndroidJUnit4.class) @@ -69,13 +71,14 @@ public class BondStateMachineTest { private RemoteDevices.DeviceProperties mDeviceProperties; private int mVerifyCount = 0; + @Rule public MockitoRule mockitoRule = MockitoJUnit.rule(); + @Mock private AdapterService mAdapterService; @Mock private AdapterNativeInterface mNativeInterface; @Before public void setUp() throws Exception { mTargetContext = InstrumentationRegistry.getTargetContext(); - MockitoAnnotations.initMocks(this); TestUtils.setAdapterService(mAdapterService); doReturn(mNativeInterface).when(mAdapterService).getNative(); mHandlerThread = new HandlerThread("BondStateMachineTestHandlerThread"); diff --git a/android/app/tests/unit/src/com/android/bluetooth/btservice/CompanionManagerTest.java b/android/app/tests/unit/src/com/android/bluetooth/btservice/CompanionManagerTest.java index f2f091fa43..3e9f37b74c 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/btservice/CompanionManagerTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/btservice/CompanionManagerTest.java @@ -32,10 +32,12 @@ import com.android.bluetooth.TestUtils; import org.junit.After; import org.junit.Assert; import org.junit.Before; +import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; -import org.mockito.MockitoAnnotations; +import org.mockito.junit.MockitoJUnit; +import org.mockito.junit.MockitoRule; @MediumTest @RunWith(AndroidJUnit4.class) @@ -49,6 +51,8 @@ public class CompanionManagerTest { private HandlerThread mHandlerThread; + @Rule public MockitoRule mockitoRule = MockitoJUnit.rule(); + @Mock private AdapterService mAdapterService; @Mock @@ -58,7 +62,6 @@ public class CompanionManagerTest { @Before public void setUp() throws Exception { - MockitoAnnotations.initMocks(this); mTargetContext = InstrumentationRegistry.getTargetContext(); // Prepare the TestUtils TestUtils.setAdapterService(mAdapterService); diff --git a/android/app/tests/unit/src/com/android/bluetooth/btservice/DataMigrationTest.java b/android/app/tests/unit/src/com/android/bluetooth/btservice/DataMigrationTest.java index ea39f2871d..f1de518872 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/btservice/DataMigrationTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/btservice/DataMigrationTest.java @@ -50,10 +50,12 @@ import com.android.bluetooth.opp.BluetoothShare; import org.junit.After; import org.junit.Before; +import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; -import org.mockito.MockitoAnnotations; +import org.mockito.junit.MockitoJUnit; +import org.mockito.junit.MockitoRule; import java.util.ArrayList; import java.util.Arrays; @@ -73,11 +75,12 @@ public class DataMigrationTest { private Context mTargetContext; private SharedPreferences mPrefs; + @Rule public MockitoRule mockitoRule = MockitoJUnit.rule(); + @Mock private Context mMockContext; @Before public void setUp() throws Exception { - MockitoAnnotations.initMocks(this); mTargetContext = InstrumentationRegistry.getTargetContext(); mTargetContext.deleteSharedPreferences(TEST_PREF); diff --git a/android/app/tests/unit/src/com/android/bluetooth/btservice/MetricsLoggerTest.java b/android/app/tests/unit/src/com/android/bluetooth/btservice/MetricsLoggerTest.java index b642319699..273ac96b22 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/btservice/MetricsLoggerTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/btservice/MetricsLoggerTest.java @@ -31,10 +31,12 @@ import com.google.common.hash.Funnels; import org.junit.After; import org.junit.Assert; import org.junit.Before; +import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; -import org.mockito.MockitoAnnotations; +import org.mockito.junit.MockitoJUnit; +import org.mockito.junit.MockitoRule; import java.io.ByteArrayInputStream; import java.io.IOException; @@ -50,6 +52,8 @@ public class MetricsLoggerTest { private static final String TEST_BLOOMFILTER_NAME = "TestBloomfilter"; private TestableMetricsLogger mTestableMetricsLogger; + @Rule public MockitoRule mockitoRule = MockitoJUnit.rule(); + @Mock private AdapterService mMockAdapterService; @@ -80,7 +84,6 @@ public class MetricsLoggerTest { @Before public void setUp() { - MockitoAnnotations.initMocks(this); // Dump metrics to clean up internal states MetricsLogger.dumpProto(BluetoothLog.newBuilder()); mTestableMetricsLogger = new TestableMetricsLogger(); diff --git a/android/app/tests/unit/src/com/android/bluetooth/btservice/PhonePolicyTest.java b/android/app/tests/unit/src/com/android/bluetooth/btservice/PhonePolicyTest.java index f08886106a..f0cf9e32c6 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/btservice/PhonePolicyTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/btservice/PhonePolicyTest.java @@ -50,7 +50,8 @@ import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; -import org.mockito.MockitoAnnotations; +import org.mockito.junit.MockitoJUnit; +import org.mockito.junit.MockitoRule; import java.util.ArrayList; import java.util.Collections; @@ -72,6 +73,8 @@ public class PhonePolicyTest { private PhonePolicy mPhonePolicy; private boolean mOriginalDualModeState; + @Rule public MockitoRule mockitoRule = MockitoJUnit.rule(); + @Mock private AdapterService mAdapterService; @Mock private ServiceFactory mServiceFactory; @Mock private HeadsetService mHeadsetService; @@ -81,7 +84,6 @@ public class PhonePolicyTest { @Before public void setUp() throws Exception { - MockitoAnnotations.initMocks(this); // Stub A2DP and HFP when(mHeadsetService.connect(any(BluetoothDevice.class))).thenReturn(true); when(mA2dpService.connect(any(BluetoothDevice.class))).thenReturn(true); 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 660fdb78dc..fb8e0ba914 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 @@ -47,12 +47,14 @@ import com.android.bluetooth.vc.VolumeControlNativeInterface; import org.junit.After; import org.junit.Assert; import org.junit.Before; +import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.ArgumentCaptor; import org.mockito.Mock; -import org.mockito.MockitoAnnotations; import org.mockito.Spy; +import org.mockito.junit.MockitoJUnit; +import org.mockito.junit.MockitoRule; import java.lang.reflect.InvocationTargetException; import java.util.List; @@ -69,6 +71,8 @@ public class ProfileServiceTest { private AdapterService mAdapterService = new AdapterService(InstrumentationRegistry.getTargetContext()); + @Rule public MockitoRule mockitoRule = MockitoJUnit.rule(); + @Mock private DatabaseManager mDatabaseManager; private int[] mProfiles; @@ -132,7 +136,6 @@ public class ProfileServiceTest { } Assert.assertNotNull(Looper.myLooper()); - MockitoAnnotations.initMocks(this); doReturn(mDatabaseManager).when(mAdapterService).getDatabase(); doNothing().when(mAdapterService).addProfile(any()); diff --git a/android/app/tests/unit/src/com/android/bluetooth/btservice/RemoteDevicesTest.java b/android/app/tests/unit/src/com/android/bluetooth/btservice/RemoteDevicesTest.java index 54d3e7bf10..5cbd92d4b3 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/btservice/RemoteDevicesTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/btservice/RemoteDevicesTest.java @@ -31,11 +31,13 @@ import org.junit.After; import org.junit.Assert; import org.junit.Before; import org.junit.Ignore; +import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.ArgumentCaptor; import org.mockito.Mock; -import org.mockito.MockitoAnnotations; +import org.mockito.junit.MockitoJUnit; +import org.mockito.junit.MockitoRule; import java.util.ArrayList; @@ -54,13 +56,14 @@ public class RemoteDevicesTest { private Context mTargetContext; private BluetoothManager mBluetoothManager; + @Rule public MockitoRule mockitoRule = MockitoJUnit.rule(); + @Mock private AdapterService mAdapterService; @Before public void setUp() { mTargetContext = InstrumentationRegistry.getTargetContext(); - MockitoAnnotations.initMocks(this); mDevice1 = BluetoothAdapter.getDefaultAdapter().getRemoteDevice(TEST_BT_ADDR_1); mHandlerThread = new HandlerThread("RemoteDevicesTestHandlerThread"); mHandlerThread.start(); diff --git a/android/app/tests/unit/src/com/android/bluetooth/btservice/SilenceDeviceManagerTest.java b/android/app/tests/unit/src/com/android/bluetooth/btservice/SilenceDeviceManagerTest.java index 23aac3991c..36be66af70 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/btservice/SilenceDeviceManagerTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/btservice/SilenceDeviceManagerTest.java @@ -41,11 +41,13 @@ import com.android.bluetooth.hfp.HeadsetService; import org.junit.After; import org.junit.Assert; import org.junit.Before; +import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.ArgumentCaptor; import org.mockito.Mock; -import org.mockito.MockitoAnnotations; +import org.mockito.junit.MockitoJUnit; +import org.mockito.junit.MockitoRule; @MediumTest @RunWith(AndroidJUnit4.class) @@ -59,6 +61,8 @@ public class SilenceDeviceManagerTest { private static final String TEST_BT_ADDR = "11:22:33:44:55:66"; private int mVerifyCount = 0; + @Rule public MockitoRule mockitoRule = MockitoJUnit.rule(); + @Mock private AdapterService mAdapterService; @Mock private ServiceFactory mServiceFactory; @Mock private A2dpService mA2dpService; @@ -69,8 +73,6 @@ public class SilenceDeviceManagerTest { public void setUp() throws Exception { mContext = InstrumentationRegistry.getTargetContext(); - // Set up mocks and test assets - MockitoAnnotations.initMocks(this); TestUtils.setAdapterService(mAdapterService); when(mServiceFactory.getA2dpService()).thenReturn(mA2dpService); when(mServiceFactory.getHeadsetService()).thenReturn(mHeadsetService); diff --git a/android/app/tests/unit/src/com/android/bluetooth/btservice/bluetoothKeystore/BluetoothKeystoreServiceTest.java b/android/app/tests/unit/src/com/android/bluetooth/btservice/bluetoothKeystore/BluetoothKeystoreServiceTest.java index 1e78e0c86b..ae60fb4d7e 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/btservice/bluetoothKeystore/BluetoothKeystoreServiceTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/btservice/bluetoothKeystore/BluetoothKeystoreServiceTest.java @@ -24,11 +24,13 @@ import org.junit.After; import org.junit.Assert; import org.junit.Assume; import org.junit.Before; +import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.JUnit4; import org.mockito.Mock; -import org.mockito.MockitoAnnotations; +import org.mockito.junit.MockitoJUnit; +import org.mockito.junit.MockitoRule; import java.io.IOException; import java.nio.file.Files; @@ -44,6 +46,8 @@ public final class BluetoothKeystoreServiceTest { private static final String TAG = "BluetoothKeystoreServiceTest"; private BluetoothKeystoreService mBluetoothKeystoreService; + @Rule public MockitoRule mockitoRule = MockitoJUnit.rule(); + @Mock private BluetoothKeystoreNativeInterface mMockNativeInterface; // Please also check bt_stack string configuration if you want to change the content. @@ -123,7 +127,6 @@ public final class BluetoothKeystoreServiceTest { @Before public void setUp() { - MockitoAnnotations.initMocks(this); Assume.assumeTrue("Ignore test when the user is not primary.", isPrimaryUser()); mBluetoothKeystoreService = new BluetoothKeystoreService(mMockNativeInterface, true); Assert.assertNotNull(mBluetoothKeystoreService); diff --git a/android/app/tests/unit/src/com/android/bluetooth/btservice/storage/DatabaseManagerTest.java b/android/app/tests/unit/src/com/android/bluetooth/btservice/storage/DatabaseManagerTest.java index 679850bed7..94c1993b40 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/btservice/storage/DatabaseManagerTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/btservice/storage/DatabaseManagerTest.java @@ -61,7 +61,8 @@ import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; -import org.mockito.MockitoAnnotations; +import org.mockito.junit.MockitoJUnit; +import org.mockito.junit.MockitoRule; import org.mockito.stubbing.Answer; import java.io.IOException; @@ -74,6 +75,8 @@ import java.util.concurrent.TimeUnit; @RunWith(AndroidJUnit4.class) public final class DatabaseManagerTest { + @Rule public MockitoRule mockitoRule = MockitoJUnit.rule(); + @Mock private AdapterService mAdapterService; private MetadataDatabase mDatabase; @@ -103,7 +106,6 @@ public final class DatabaseManagerTest { new FrameworkSQLiteOpenHelperFactory()); @Before public void setUp() throws Exception { - MockitoAnnotations.initMocks(this); TestUtils.setAdapterService(mAdapterService); mTestDevice = BluetoothAdapter.getDefaultAdapter().getRemoteDevice(TEST_BT_ADDR); diff --git a/android/app/tests/unit/src/com/android/bluetooth/content_profiles/ContentProfileErrorReportUtilsTest.java b/android/app/tests/unit/src/com/android/bluetooth/content_profiles/ContentProfileErrorReportUtilsTest.java index bdfe10d5dc..dc4e6dc5e8 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/content_profiles/ContentProfileErrorReportUtilsTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/content_profiles/ContentProfileErrorReportUtilsTest.java @@ -22,7 +22,6 @@ import android.os.SystemClock; import androidx.test.filters.SmallTest; import androidx.test.runner.AndroidJUnit4; -import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; diff --git a/android/app/tests/unit/src/com/android/bluetooth/csip/BluetoothCsisBinderTest.java b/android/app/tests/unit/src/com/android/bluetooth/csip/BluetoothCsisBinderTest.java index 9b9b0b9d4e..460d9df200 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/csip/BluetoothCsisBinderTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/csip/BluetoothCsisBinderTest.java @@ -29,13 +29,17 @@ import android.os.ParcelUuid; import com.android.bluetooth.x.com.android.modules.utils.SynchronousResultReceiver; import org.junit.Before; +import org.junit.Rule; import org.junit.Test; import org.mockito.Mock; -import org.mockito.MockitoAnnotations; +import org.mockito.junit.MockitoJUnit; +import org.mockito.junit.MockitoRule; public class BluetoothCsisBinderTest { private static final String TEST_DEVICE_ADDRESS = "00:00:00:00:00:00"; + @Rule public MockitoRule mockitoRule = MockitoJUnit.rule(); + @Mock private CsipSetCoordinatorService mService; @@ -46,7 +50,6 @@ public class BluetoothCsisBinderTest { @Before public void setUp() throws Exception { - MockitoAnnotations.initMocks(this); mBinder = new CsipSetCoordinatorService.BluetoothCsisBinder(mService); mAttributionSource = new AttributionSource.Builder(1).build(); mTestDevice = BluetoothAdapter.getDefaultAdapter().getRemoteDevice(TEST_DEVICE_ADDRESS); diff --git a/android/app/tests/unit/src/com/android/bluetooth/csip/CsipSetCoordinatorServiceTest.java b/android/app/tests/unit/src/com/android/bluetooth/csip/CsipSetCoordinatorServiceTest.java index 7c3bd07096..d212f044b0 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/csip/CsipSetCoordinatorServiceTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/csip/CsipSetCoordinatorServiceTest.java @@ -43,11 +43,13 @@ import com.android.bluetooth.le_audio.LeAudioService; import org.junit.After; import org.junit.Assert; import org.junit.Before; +import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; -import org.mockito.MockitoAnnotations; import org.mockito.Spy; +import org.mockito.junit.MockitoJUnit; +import org.mockito.junit.MockitoRule; import java.util.HashMap; import java.util.List; @@ -72,6 +74,8 @@ public class CsipSetCoordinatorServiceTest { private CsipSetCoordinatorStateMachine mCsipSetCoordinatorStateMachine; private static final int TIMEOUT_MS = 1000; + @Rule public MockitoRule mockitoRule = MockitoJUnit.rule(); + @Mock private AdapterService mAdapterService; @Mock private LeAudioService mLeAudioService; @Spy @@ -92,8 +96,6 @@ public class CsipSetCoordinatorServiceTest { } Assert.assertNotNull(Looper.myLooper()); - // Set up mocks and test assets - MockitoAnnotations.initMocks(this); TestUtils.setAdapterService(mAdapterService); doReturn(mDatabaseManager).when(mAdapterService).getDatabase(); diff --git a/android/app/tests/unit/src/com/android/bluetooth/csip/CsipSetCoordinatorStateMachineTest.java b/android/app/tests/unit/src/com/android/bluetooth/csip/CsipSetCoordinatorStateMachineTest.java index 0c09204d33..230bf6c33d 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/csip/CsipSetCoordinatorStateMachineTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/csip/CsipSetCoordinatorStateMachineTest.java @@ -33,17 +33,22 @@ import android.content.Intent; import android.os.HandlerThread; import android.os.Looper; import android.os.Message; + import androidx.test.filters.MediumTest; import androidx.test.runner.AndroidJUnit4; + import com.android.bluetooth.TestUtils; import com.android.bluetooth.btservice.AdapterService; + import org.hamcrest.core.IsInstanceOf; import org.junit.*; +import org.junit.Rule; import org.junit.runner.RunWith; import org.mockito.ArgumentCaptor; import org.mockito.Mock; import org.mockito.Mockito; -import org.mockito.MockitoAnnotations; +import org.mockito.junit.MockitoJUnit; +import org.mockito.junit.MockitoRule; @MediumTest @RunWith(AndroidJUnit4.class) @@ -56,6 +61,8 @@ public class CsipSetCoordinatorStateMachineTest { private CsipSetCoordinatorStateMachineWrapper mStateMachine; private static final int TIMEOUT_MS = 1000; + @Rule public MockitoRule mockitoRule = MockitoJUnit.rule(); + @Mock private AdapterService mAdapterService; @Mock private CsipSetCoordinatorService mService; @Mock private CsipSetCoordinatorNativeInterface mNativeInterface; @@ -66,8 +73,6 @@ public class CsipSetCoordinatorStateMachineTest { System.setProperty("dexmaker.share_classloader", "true"); } - // Set up mocks and test assets - MockitoAnnotations.initMocks(this); TestUtils.setAdapterService(mAdapterService); mAdapter = BluetoothAdapter.getDefaultAdapter(); diff --git a/android/app/tests/unit/src/com/android/bluetooth/gatt/AdvertiseManagerTest.java b/android/app/tests/unit/src/com/android/bluetooth/gatt/AdvertiseManagerTest.java index c7bf403325..9c884df9ad 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/gatt/AdvertiseManagerTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/gatt/AdvertiseManagerTest.java @@ -37,10 +37,12 @@ import com.android.bluetooth.btservice.AdapterService; import org.junit.After; import org.junit.Before; +import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; -import org.mockito.MockitoAnnotations; +import org.mockito.junit.MockitoJUnit; +import org.mockito.junit.MockitoRule; /** * Test cases for {@link AdvertiseManager}. @@ -49,6 +51,8 @@ import org.mockito.MockitoAnnotations; @RunWith(AndroidJUnit4.class) public class AdvertiseManagerTest { + @Rule public MockitoRule mockitoRule = MockitoJUnit.rule(); + @Mock private AdapterService mAdapterService; @@ -71,7 +75,6 @@ public class AdvertiseManagerTest { @Before public void setUp() throws Exception { - MockitoAnnotations.initMocks(this); TestUtils.setAdapterService(mAdapterService); diff --git a/android/app/tests/unit/src/com/android/bluetooth/gatt/AppAdvertiseStatsTest.java b/android/app/tests/unit/src/com/android/bluetooth/gatt/AppAdvertiseStatsTest.java index 6b054f3b7e..66d0750116 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/gatt/AppAdvertiseStatsTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/gatt/AppAdvertiseStatsTest.java @@ -34,11 +34,13 @@ import com.android.bluetooth.btservice.MetricsLogger; import org.junit.After; import org.junit.Before; +import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; import org.mockito.Mockito; -import org.mockito.MockitoAnnotations; +import org.mockito.junit.MockitoJUnit; +import org.mockito.junit.MockitoRule; /** * Test cases for {@link AppAdvertiseStats}. @@ -47,6 +49,8 @@ import org.mockito.MockitoAnnotations; @RunWith(AndroidJUnit4.class) public class AppAdvertiseStatsTest { + @Rule public MockitoRule mockitoRule = MockitoJUnit.rule(); + @Mock private ContextMap map; @@ -58,7 +62,6 @@ public class AppAdvertiseStatsTest { @Before public void setUp() throws Exception { - MockitoAnnotations.initMocks(this); MetricsLogger.setInstanceForTesting(mMetricsLogger); } 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 6d7ba9c22d..d29e96d781 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 @@ -35,6 +35,7 @@ import androidx.test.runner.AndroidJUnit4; import com.android.bluetooth.BluetoothMethodProxy; import com.android.bluetooth.TestUtils; import com.android.bluetooth.btservice.AdapterService; +import com.android.bluetooth.le_scan.TransitionalScanHelper; import org.junit.After; import org.junit.Before; @@ -42,8 +43,9 @@ import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; -import org.mockito.MockitoAnnotations; import org.mockito.Spy; +import org.mockito.junit.MockitoJUnit; +import org.mockito.junit.MockitoRule; import java.util.UUID; @@ -58,9 +60,12 @@ public class ContextMapTest { @Rule public final ServiceTestRule mServiceRule = new ServiceTestRule(); + @Rule public MockitoRule mockitoRule = MockitoJUnit.rule(); + @Mock private AdapterService mAdapterService; @Mock private AppAdvertiseStats appAdvertiseStats; @Mock private GattService mMockGatt; + @Mock private TransitionalScanHelper mMockScanHelper; @Mock private PackageManager mMockPackageManager; @Spy @@ -68,7 +73,6 @@ public class ContextMapTest { @Before public void setUp() throws Exception { - MockitoAnnotations.initMocks(this); BluetoothMethodProxy.setInstanceForTesting(mMapMethodProxy); TestUtils.setAdapterService(mAdapterService); @@ -91,7 +95,7 @@ public class ContextMapTest { int id = 12345; contextMap.add(id, null, mMockGatt); - contextMap.add(UUID.randomUUID(), null, null, null, mMockGatt); + contextMap.add(UUID.randomUUID(), null, null, null, mMockGatt, mMockScanHelper); int appUid = Binder.getCallingUid(); @@ -169,7 +173,7 @@ public class ContextMapTest { int id = 12345; contextMap.add(id, null, mMockGatt); - contextMap.add(UUID.randomUUID(), null, null, null, mMockGatt); + contextMap.add(UUID.randomUUID(), null, null, null, mMockGatt, mMockScanHelper); contextMap.recordAdvertiseStop(id); diff --git a/android/app/tests/unit/src/com/android/bluetooth/gatt/DistanceMeasurementManagerTest.java b/android/app/tests/unit/src/com/android/bluetooth/gatt/DistanceMeasurementManagerTest.java index 5d1eea0ade..077d2b9f4b 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/gatt/DistanceMeasurementManagerTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/gatt/DistanceMeasurementManagerTest.java @@ -40,11 +40,13 @@ import com.android.bluetooth.btservice.AdapterService; import org.junit.After; import org.junit.Before; +import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.ArgumentCaptor; import org.mockito.Mock; -import org.mockito.MockitoAnnotations; +import org.mockito.junit.MockitoJUnit; +import org.mockito.junit.MockitoRule; import java.util.UUID; @@ -54,6 +56,8 @@ import java.util.UUID; @SmallTest @RunWith(AndroidJUnit4.class) public class DistanceMeasurementManagerTest { + @Rule public MockitoRule mockitoRule = MockitoJUnit.rule(); + @Mock private DistanceMeasurementNativeInterface mDistanceMeasurementNativeInterface; @Mock private AdapterService mAdapterService; @Mock private IDistanceMeasurementCallback mCallback; @@ -66,7 +70,6 @@ public class DistanceMeasurementManagerTest { @Before public void setUp() throws Exception { - MockitoAnnotations.initMocks(this); doReturn(IDENTITY_ADDRESS).when(mAdapterService).getIdentityAddress(IDENTITY_ADDRESS); DistanceMeasurementNativeInterface.setInstance(mDistanceMeasurementNativeInterface); mDistanceMeasurementManager = new DistanceMeasurementManager(mAdapterService); diff --git a/android/app/tests/unit/src/com/android/bluetooth/gatt/DistanceMeasurementTrackerTest.java b/android/app/tests/unit/src/com/android/bluetooth/gatt/DistanceMeasurementTrackerTest.java index d3e562207d..603b20fe45 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/gatt/DistanceMeasurementTrackerTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/gatt/DistanceMeasurementTrackerTest.java @@ -34,10 +34,12 @@ import androidx.test.runner.AndroidJUnit4; import org.junit.After; import org.junit.Before; +import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; -import org.mockito.MockitoAnnotations; +import org.mockito.junit.MockitoJUnit; +import org.mockito.junit.MockitoRule; import java.util.UUID; @@ -47,6 +49,8 @@ import java.util.UUID; @SmallTest @RunWith(AndroidJUnit4.class) public class DistanceMeasurementTrackerTest { + @Rule public MockitoRule mockitoRule = MockitoJUnit.rule(); + @Mock private DistanceMeasurementManager mDistanceMeasurementManager; @Mock private IDistanceMeasurementCallback mCallback; private DistanceMeasurementTracker mTracker; @@ -61,7 +65,6 @@ public class DistanceMeasurementTrackerTest { @Before public void setUp() throws Exception { - MockitoAnnotations.initMocks(this); mUuid = UUID.randomUUID(); mDevice = BluetoothAdapter.getDefaultAdapter().getRemoteDevice(IDENTITY_ADDRESS); mParams = new DistanceMeasurementParams.Builder(mDevice) diff --git a/android/app/tests/unit/src/com/android/bluetooth/gatt/GattDebugUtilsTest.java b/android/app/tests/unit/src/com/android/bluetooth/gatt/GattDebugUtilsTest.java index ab83f1d6e4..8d7f4aafe7 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/gatt/GattDebugUtilsTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/gatt/GattDebugUtilsTest.java @@ -25,11 +25,12 @@ import android.content.Intent; import androidx.test.filters.SmallTest; import androidx.test.runner.AndroidJUnit4; -import org.junit.Before; +import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; -import org.mockito.MockitoAnnotations; +import org.mockito.junit.MockitoJUnit; +import org.mockito.junit.MockitoRule; /** * Test cases for {@link GattDebugUtils}. @@ -38,14 +39,11 @@ import org.mockito.MockitoAnnotations; @RunWith(AndroidJUnit4.class) public class GattDebugUtilsTest { + @Rule public MockitoRule mockitoRule = MockitoJUnit.rule(); + @Mock private GattService mService; - @Before - public void setUp() throws Exception { - MockitoAnnotations.initMocks(this); - } - @Test public void handleDebugAction() { Intent intent = new Intent(GattDebugUtils.ACTION_GATT_TEST_USAGE); 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 1c1fda0007..0bec207562 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 @@ -46,13 +46,16 @@ import androidx.test.InstrumentationRegistry; import androidx.test.filters.SmallTest; import androidx.test.runner.AndroidJUnit4; +import com.android.bluetooth.le_scan.TransitionalScanHelper; import com.android.bluetooth.x.com.android.modules.utils.SynchronousResultReceiver; import org.junit.Before; +import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; -import org.mockito.MockitoAnnotations; +import org.mockito.junit.MockitoJUnit; +import org.mockito.junit.MockitoRule; import java.util.ArrayList; import java.util.List; @@ -64,8 +67,11 @@ public class GattServiceBinderTest { private static final String REMOTE_DEVICE_ADDRESS = "00:00:00:00:00:00"; + @Rule public MockitoRule mockitoRule = MockitoJUnit.rule(); + @Mock private GattService mService; + @Mock private TransitionalScanHelper mScanHelper; private Context mContext; private BluetoothDevice mDevice; @@ -80,8 +86,8 @@ public class GattServiceBinderTest { Intent intent = new Intent(); mPendingIntent = PendingIntent.getBroadcast(mContext, 0, intent, PendingIntent.FLAG_IMMUTABLE); - MockitoAnnotations.initMocks(this); when(mService.isAvailable()).thenReturn(true); + when(mService.getTransitionalScanHelper()).thenReturn(mScanHelper); mBinder = new GattService.BluetoothGattBinder(mService); mAttributionSource = new AttributionSource.Builder(1).build(); mDevice = BluetoothAdapter.getDefaultAdapter().getRemoteDevice(REMOTE_DEVICE_ADDRESS); @@ -126,7 +132,7 @@ public class GattServiceBinderTest { mBinder.registerScanner(callback, workSource, mAttributionSource, SynchronousResultReceiver.get()); - verify(mService).registerScanner(callback, workSource, mAttributionSource); + verify(mScanHelper).registerScanner(callback, workSource, mAttributionSource); } @Test @@ -135,7 +141,7 @@ public class GattServiceBinderTest { mBinder.unregisterScanner(scannerId, mAttributionSource, SynchronousResultReceiver.get()); - verify(mService).unregisterScanner(scannerId, mAttributionSource); + verify(mScanHelper).unregisterScanner(scannerId, mAttributionSource); } @Test @@ -147,7 +153,7 @@ public class GattServiceBinderTest { mBinder.startScan(scannerId, settings, filters, mAttributionSource, SynchronousResultReceiver.get()); - verify(mService).startScan(scannerId, settings, filters, mAttributionSource); + verify(mScanHelper).startScan(scannerId, settings, filters, mAttributionSource); } @Test @@ -158,8 +164,8 @@ public class GattServiceBinderTest { mBinder.startScanForIntent(mPendingIntent, settings, filters, mAttributionSource, SynchronousResultReceiver.get()); - verify(mService).registerPiAndStartScan(mPendingIntent, settings, filters, - mAttributionSource); + verify(mScanHelper) + .registerPiAndStartScan(mPendingIntent, settings, filters, mAttributionSource); } @Test @@ -167,7 +173,7 @@ public class GattServiceBinderTest { mBinder.stopScanForIntent(mPendingIntent, mAttributionSource, SynchronousResultReceiver.get()); - verify(mService).stopScan(mPendingIntent, mAttributionSource); + verify(mScanHelper).stopScan(mPendingIntent, mAttributionSource); } @Test @@ -176,7 +182,7 @@ public class GattServiceBinderTest { mBinder.stopScan(scannerId, mAttributionSource, SynchronousResultReceiver.get()); - verify(mService).stopScan(scannerId, mAttributionSource); + verify(mScanHelper).stopScan(scannerId, mAttributionSource); } @Test @@ -186,7 +192,7 @@ public class GattServiceBinderTest { mBinder.flushPendingBatchResults(scannerId, mAttributionSource, SynchronousResultReceiver.get()); - verify(mService).flushPendingBatchResults(scannerId, mAttributionSource); + verify(mScanHelper).flushPendingBatchResults(scannerId, mAttributionSource); } @Test @@ -710,7 +716,7 @@ public class GattServiceBinderTest { mBinder.registerSync(scanResult, skip, timeout, callback, mAttributionSource, SynchronousResultReceiver.get()); - verify(mService).registerSync(scanResult, skip, timeout, callback, mAttributionSource); + verify(mScanHelper).registerSync(scanResult, skip, timeout, callback, mAttributionSource); } @Test @@ -721,7 +727,7 @@ public class GattServiceBinderTest { mBinder.transferSync(mDevice, serviceData, syncHandle, mAttributionSource, SynchronousResultReceiver.get()); - verify(mService).transferSync(mDevice, serviceData, syncHandle, mAttributionSource); + verify(mScanHelper).transferSync(mDevice, serviceData, syncHandle, mAttributionSource); } @Test @@ -733,8 +739,8 @@ public class GattServiceBinderTest { mBinder.transferSetInfo(mDevice, serviceData, advHandle, callback, mAttributionSource, SynchronousResultReceiver.get()); - verify(mService).transferSetInfo(mDevice, serviceData, advHandle, callback, - mAttributionSource); + verify(mScanHelper) + .transferSetInfo(mDevice, serviceData, advHandle, callback, mAttributionSource); } @Test @@ -743,7 +749,7 @@ public class GattServiceBinderTest { mBinder.unregisterSync(callback, mAttributionSource, SynchronousResultReceiver.get()); - verify(mService).unregisterSync(callback, mAttributionSource); + verify(mScanHelper).unregisterSync(callback, mAttributionSource); } @Test 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 9f2390e44c..50083b6d96 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 @@ -33,18 +33,11 @@ import android.bluetooth.le.AdvertisingSetParameters; import android.bluetooth.le.DistanceMeasurementMethod; import android.bluetooth.le.DistanceMeasurementParams; import android.bluetooth.le.IDistanceMeasurementCallback; -import android.bluetooth.le.IPeriodicAdvertisingCallback; -import android.bluetooth.le.IScannerCallback; import android.bluetooth.le.PeriodicAdvertisingParameters; -import android.bluetooth.le.ScanResult; -import android.bluetooth.le.ScanSettings; import android.content.AttributionSource; import android.content.Context; import android.content.res.Resources; import android.location.LocationManager; -import android.os.Binder; -import android.os.RemoteException; -import android.os.WorkSource; import android.platform.test.flag.junit.SetFlagsRule; import androidx.test.InstrumentationRegistry; @@ -55,26 +48,21 @@ import androidx.test.runner.AndroidJUnit4; import com.android.bluetooth.TestUtils; import com.android.bluetooth.btservice.AdapterService; import com.android.bluetooth.btservice.CompanionManager; -import com.android.bluetooth.le_scan.AppScanStats; -import com.android.bluetooth.le_scan.PeriodicScanManager; -import com.android.bluetooth.le_scan.ScanClient; import com.android.bluetooth.le_scan.ScanManager; import com.android.bluetooth.le_scan.TransitionalScanHelper; import com.android.bluetooth.flags.Flags; import org.junit.After; -import org.junit.Assert; import org.junit.Before; import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; -import org.mockito.ArgumentMatcher; import org.mockito.Mock; -import org.mockito.MockitoAnnotations; +import org.mockito.junit.MockitoJUnit; +import org.mockito.junit.MockitoRule; import java.util.ArrayList; -import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.List; @@ -95,6 +83,8 @@ public class GattServiceTest { private static final int TIMEOUT_MS = 5_000; private Context mTargetContext; private GattService mService; + @Rule public MockitoRule mockitoRule = MockitoJUnit.rule(); + @Mock private GattService.ClientMap mClientMap; @Mock private TransitionalScanHelper.ScannerMap mScannerMap; @@ -102,8 +92,6 @@ public class GattServiceTest { @Mock private TransitionalScanHelper.ScannerMap.App mApp; - @Mock private GattService.PendingIntentInfo mPiInfo; - @Mock private PeriodicScanManager mPeriodicScanManager; @Mock private ScanManager mScanManager; @Mock private Set<String> mReliableQueue; @Mock private GattService.ServerMap mServerMap; @@ -128,13 +116,11 @@ public class GattServiceTest { public void setUp() throws Exception { mTargetContext = InstrumentationRegistry.getTargetContext(); - MockitoAnnotations.initMocks(this); TestUtils.setAdapterService(mAdapterService); GattObjectsFactory.setInstanceForTesting(mFactory); doReturn(mNativeInterface).when(mFactory).getNativeInterface(); - doReturn(mScanManager).when(mFactory).createScanManager(any(), any(), any(), any()); - doReturn(mPeriodicScanManager).when(mFactory).createPeriodicScanManager(any()); + doReturn(mScanManager).when(mFactory).createScanManager(any(), any(), any(), any(), any()); doReturn(mDistanceMeasurementManager).when(mFactory) .createDistanceMeasurementManager(any()); @@ -190,14 +176,6 @@ public class GattServiceTest { } @Test - public void testParseBatchTimestamp() { - long timestampNanos = mService.parseTimestampNanos(new byte[]{ - -54, 7 - }); - Assert.assertEquals(99700000000L, timestampNanos); - } - - @Test public void emptyClearServices() { int serverIf = 1; @@ -261,81 +239,6 @@ public class GattServiceTest { } @Test - public void continuePiStartScan() { - int scannerId = 1; - - mPiInfo.settings = new ScanSettings.Builder().build(); - mApp.info = mPiInfo; - - AppScanStats appScanStats = mock(AppScanStats.class); - doReturn(appScanStats).when(mScannerMap).getAppScanStatsById(scannerId); - - mService.continuePiStartScan(scannerId, mApp); - - verify(appScanStats).recordScanStart( - mPiInfo.settings, mPiInfo.filters, false, false, scannerId); - verify(mScanManager).startScan(any()); - } - - @Test - public void continuePiStartScanCheckUid() { - int scannerId = 1; - - mPiInfo.settings = new ScanSettings.Builder().build(); - mPiInfo.callingUid = 123; - mApp.info = mPiInfo; - - AppScanStats appScanStats = mock(AppScanStats.class); - doReturn(appScanStats).when(mScannerMap).getAppScanStatsById(scannerId); - - mService.continuePiStartScan(scannerId, mApp); - - verify(appScanStats) - .recordScanStart(mPiInfo.settings, mPiInfo.filters, false, false, scannerId); - verify(mScanManager) - .startScan( - argThat( - new ArgumentMatcher<ScanClient>() { - @Override - public boolean matches(ScanClient client) { - return mPiInfo.callingUid == client.appUid; - } - })); - } - - @Test - public void onBatchScanReportsInternal_deliverBatchScan() throws RemoteException { - int status = 1; - int scannerId = 2; - int reportType = ScanManager.SCAN_RESULT_TYPE_FULL; - int numRecords = 1; - byte[] recordData = new byte[]{0x01, 0x02, 0x03, 0x04, 0x05, - 0x06, 0x07, 0x08, 0x09, 0x00, 0x00, 0x00, 0x00}; - - Set<ScanClient> scanClientSet = new HashSet<>(); - ScanClient scanClient = new ScanClient(scannerId); - scanClient.associatedDevices = new ArrayList<>(); - scanClient.associatedDevices.add("02:00:00:00:00:00"); - scanClient.scannerId = scannerId; - scanClientSet.add(scanClient); - doReturn(scanClientSet).when(mScanManager).getFullBatchScanQueue(); - doReturn(mApp).when(mScannerMap).getById(scanClient.scannerId); - - mService.onBatchScanReportsInternal(status, scannerId, reportType, numRecords, recordData); - verify(mScanManager).callbackDone(scannerId, status); - - reportType = ScanManager.SCAN_RESULT_TYPE_TRUNCATED; - recordData = new byte[]{0x00, 0x00, 0x00, 0x00, 0x00, 0x02, - 0x06, 0x04, 0x02, 0x02, 0x00, 0x00, 0x02}; - doReturn(scanClientSet).when(mScanManager).getBatchScanQueue(); - IScannerCallback callback = mock(IScannerCallback.class); - mApp.callback = callback; - - mService.onBatchScanReportsInternal(status, scannerId, reportType, numRecords, recordData); - verify(callback).onBatchScanResults(any()); - } - - @Test public void clientConnect() throws Exception { int clientIf = 1; String address = REMOTE_DEVICE_ADDRESS; @@ -367,28 +270,6 @@ public class GattServiceTest { } @Test - public void enforceReportDelayFloor() { - long reportDelayFloorHigher = GattService.DEFAULT_REPORT_DELAY_FLOOR + 1; - ScanSettings scanSettings = new ScanSettings.Builder() - .setReportDelay(reportDelayFloorHigher) - .build(); - - ScanSettings newScanSettings = mService.enforceReportDelayFloor(scanSettings); - - assertThat(newScanSettings.getReportDelayMillis()) - .isEqualTo(scanSettings.getReportDelayMillis()); - - ScanSettings scanSettingsFloor = new ScanSettings.Builder() - .setReportDelay(1) - .build(); - - ScanSettings newScanSettingsFloor = mService.enforceReportDelayFloor(scanSettingsFloor); - - assertThat(newScanSettingsFloor.getReportDelayMillis()) - .isEqualTo(GattService.DEFAULT_REPORT_DELAY_FLOOR); - } - - @Test public void setAdvertisingData() { int advertiserId = 1; AdvertiseData data = new AdvertiseData.Builder().build(); @@ -481,84 +362,6 @@ public class GattServiceTest { } @Test - public void registerScanner() throws Exception { - IScannerCallback callback = mock(IScannerCallback.class); - WorkSource workSource = mock(WorkSource.class); - - AppScanStats appScanStats = mock(AppScanStats.class); - doReturn(appScanStats).when(mScannerMap).getAppScanStatsByUid(Binder.getCallingUid()); - - mService.registerScanner(callback, workSource, mAttributionSource); - verify(mScannerMap).add(any(), eq(workSource), eq(callback), eq(null), eq(mService)); - verify(mScanManager).registerScanner(any()); - } - - @Test - public void flushPendingBatchResults() { - int scannerId = 3; - - mService.flushPendingBatchResults(scannerId, mAttributionSource); - verify(mScanManager).flushBatchScanResults(new ScanClient(scannerId)); - } - - @Test - public void onScanResult_remoteException_clientDied() throws Exception { - mSetFlagsRule.enableFlags(Flags.FLAG_LE_SCAN_FIX_REMOTE_EXCEPTION); - int scannerId = 1; - - int eventType = 0; - int addressType = 0; - String address = "02:00:00:00:00:00"; - int primaryPhy = 0; - int secondPhy = 0; - int advertisingSid = 0; - int txPower = 0; - int rssi = 0; - int periodicAdvInt = 0; - byte[] advData = new byte[0]; - - ScanClient scanClient = new ScanClient(scannerId); - scanClient.scannerId = scannerId; - scanClient.hasNetworkSettingsPermission = true; - scanClient.settings = - new ScanSettings.Builder() - .setCallbackType(ScanSettings.CALLBACK_TYPE_ALL_MATCHES) - .setLegacy(false) - .build(); - - AppScanStats appScanStats = mock(AppScanStats.class); - IScannerCallback callback = mock(IScannerCallback.class); - - mApp.callback = callback; - mApp.appScanStats = appScanStats; - Set<ScanClient> scanClientSet = Collections.singleton(scanClient); - - doReturn(address).when(mAdapterService).getIdentityAddress(anyString()); - doReturn(scanClientSet).when(mScanManager).getRegularScanQueue(); - doReturn(mApp).when(mScannerMap).getById(scanClient.scannerId); - doReturn(appScanStats).when(mScannerMap).getAppScanStatsById(scanClient.scannerId); - - // Simulate remote client crash - doThrow(new RemoteException()).when(callback).onScanResult(any()); - - mService.onScanResult( - eventType, - addressType, - address, - primaryPhy, - secondPhy, - advertisingSid, - txPower, - rssi, - periodicAdvInt, - advData, - address); - - assertThat(scanClient.appDied).isTrue(); - verify(appScanStats).recordScanStop(scannerId); - } - - @Test public void readCharacteristic() { int clientIf = 1; String address = REMOTE_DEVICE_ADDRESS; @@ -789,45 +592,6 @@ public class GattServiceTest { } @Test - public void registerSync() { - ScanResult scanResult = new ScanResult(mDevice, 1, 2, 3, 4, 5, 6, 7, null, 8); - int skip = 1; - int timeout = 2; - IPeriodicAdvertisingCallback callback = mock(IPeriodicAdvertisingCallback.class); - - mService.registerSync(scanResult, skip, timeout, callback, mAttributionSource); - verify(mPeriodicScanManager).startSync(scanResult, skip, timeout, callback); - } - - @Test - public void transferSync() { - int serviceData = 1; - int syncHandle = 2; - - mService.transferSync(mDevice, serviceData, syncHandle, mAttributionSource); - verify(mPeriodicScanManager).transferSync(mDevice, serviceData, syncHandle); - } - - @Test - public void transferSetInfo() { - int serviceData = 1; - int advHandle = 2; - IPeriodicAdvertisingCallback callback = mock(IPeriodicAdvertisingCallback.class); - - mService.transferSetInfo(mDevice, serviceData, advHandle, callback, - mAttributionSource); - verify(mPeriodicScanManager).transferSetInfo(mDevice, serviceData, advHandle, callback); - } - - @Test - public void unregisterSync() { - IPeriodicAdvertisingCallback callback = mock(IPeriodicAdvertisingCallback.class); - - mService.unregisterSync(callback, mAttributionSource); - verify(mPeriodicScanManager).stopSync(callback); - } - - @Test public void unregAll() throws Exception { int appId = 1; List<Integer> appIds = new ArrayList<>(); diff --git a/android/app/tests/unit/src/com/android/bluetooth/hap/HapClientNativeInterfaceTest.java b/android/app/tests/unit/src/com/android/bluetooth/hap/HapClientNativeInterfaceTest.java index 1d4ecbe2e7..1229c97080 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/hap/HapClientNativeInterfaceTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/hap/HapClientNativeInterfaceTest.java @@ -26,14 +26,18 @@ import android.bluetooth.BluetoothProfile; import org.junit.After; import org.junit.Before; +import org.junit.Rule; import org.junit.Test; import org.mockito.ArgumentCaptor; import org.mockito.Mock; -import org.mockito.MockitoAnnotations; +import org.mockito.junit.MockitoJUnit; +import org.mockito.junit.MockitoRule; public class HapClientNativeInterfaceTest { private static final byte[] TEST_DEVICE_ADDRESS = new byte[] { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; + @Rule public MockitoRule mockitoRule = MockitoJUnit.rule(); + @Mock HapClientService mService; @@ -41,7 +45,6 @@ public class HapClientNativeInterfaceTest { @Before public void setUp() throws Exception { - MockitoAnnotations.initMocks(this); when(mService.isAvailable()).thenReturn(true); HapClientService.setHapClient(mService); mNativeInterface = HapClientNativeInterface.getInstance(); diff --git a/android/app/tests/unit/src/com/android/bluetooth/hap/HapClientStateMachineTest.java b/android/app/tests/unit/src/com/android/bluetooth/hap/HapClientStateMachineTest.java index 8e1024dbdb..4c878d896f 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/hap/HapClientStateMachineTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/hap/HapClientStateMachineTest.java @@ -31,20 +31,25 @@ import android.bluetooth.BluetoothProfile; import android.content.Intent; import android.os.HandlerThread; import android.os.Message; + import androidx.test.filters.MediumTest; import androidx.test.runner.AndroidJUnit4; + import com.android.bluetooth.TestUtils; import com.android.bluetooth.btservice.AdapterService; + import org.hamcrest.core.IsInstanceOf; import org.junit.After; import org.junit.Assert; import org.junit.Before; +import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.ArgumentCaptor; import org.mockito.Mock; import org.mockito.Mockito; -import org.mockito.MockitoAnnotations; +import org.mockito.junit.MockitoJUnit; +import org.mockito.junit.MockitoRule; @MediumTest @RunWith(AndroidJUnit4.class) @@ -56,6 +61,8 @@ public class HapClientStateMachineTest { private static final int TIMEOUT_MS = 1000; boolean mIsAdapterServiceSet; + @Rule public MockitoRule mockitoRule = MockitoJUnit.rule(); + @Mock private AdapterService mAdapterService; @Mock @@ -65,8 +72,6 @@ public class HapClientStateMachineTest { @Before public void setUp() throws Exception { - // Set up mocks and test assets - MockitoAnnotations.initMocks(this); TestUtils.setAdapterService(mAdapterService); mIsAdapterServiceSet = true; diff --git a/android/app/tests/unit/src/com/android/bluetooth/hap/HapClientTest.java b/android/app/tests/unit/src/com/android/bluetooth/hap/HapClientTest.java index 8fc9fbe179..fc24a7ec05 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/hap/HapClientTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/hap/HapClientTest.java @@ -71,13 +71,15 @@ import com.android.bluetooth.x.com.android.modules.utils.SynchronousResultReceiv import org.junit.After; import org.junit.Assert; import org.junit.Before; +import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.ArgumentCaptor; import org.mockito.InOrder; import org.mockito.Mock; import org.mockito.Mockito; -import org.mockito.MockitoAnnotations; +import org.mockito.junit.MockitoJUnit; +import org.mockito.junit.MockitoRule; import java.time.Duration; import java.util.ArrayList; @@ -102,6 +104,8 @@ public class HapClientTest { private HapClientService.BluetoothHapClientBinder mServiceBinder; private AttributionSource mAttributionSource; + @Rule public MockitoRule mockitoRule = MockitoJUnit.rule(); + @Mock private AdapterService mAdapterService; @Mock private DatabaseManager mDatabaseManager; @Mock private HapClientNativeInterface mNativeInterface; @@ -116,8 +120,6 @@ public class HapClientTest { System.setProperty("dexmaker.share_classloader", "true"); } - // Set up mocks and test assets - MockitoAnnotations.initMocks(this); HapClientStateMachine.sConnectTimeoutMs = TIMEOUT_MS; diff --git a/android/app/tests/unit/src/com/android/bluetooth/hearingaid/HearingAidNativeInterfaceTest.java b/android/app/tests/unit/src/com/android/bluetooth/hearingaid/HearingAidNativeInterfaceTest.java index 27e1c152f2..c730910e33 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/hearingaid/HearingAidNativeInterfaceTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/hearingaid/HearingAidNativeInterfaceTest.java @@ -32,14 +32,18 @@ import com.android.bluetooth.Utils; import org.junit.After; import org.junit.Before; +import org.junit.Rule; import org.junit.Test; import org.mockito.ArgumentCaptor; import org.mockito.Mock; import org.mockito.Mockito; -import org.mockito.MockitoAnnotations; +import org.mockito.junit.MockitoJUnit; +import org.mockito.junit.MockitoRule; public class HearingAidNativeInterfaceTest { + @Rule public MockitoRule mockitoRule = MockitoJUnit.rule(); + @Mock private HearingAidService mService; private HearingAidNativeInterface mNativeInterface; @@ -47,7 +51,6 @@ public class HearingAidNativeInterfaceTest { @Before public void setUp() throws Exception { - MockitoAnnotations.initMocks(this); when(mService.isAvailable()).thenReturn(true); HearingAidService.setHearingAidService(mService); mNativeInterface = HearingAidNativeInterface.getInstance(); diff --git a/android/app/tests/unit/src/com/android/bluetooth/hearingaid/HearingAidServiceTest.java b/android/app/tests/unit/src/com/android/bluetooth/hearingaid/HearingAidServiceTest.java index f690d6502c..f7580331ab 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/hearingaid/HearingAidServiceTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/hearingaid/HearingAidServiceTest.java @@ -66,8 +66,9 @@ import org.junit.runner.RunWith; import org.mockito.ArgumentCaptor; import org.mockito.InOrder; import org.mockito.Mock; -import org.mockito.MockitoAnnotations; import org.mockito.hamcrest.MockitoHamcrest; +import org.mockito.junit.MockitoJUnit; +import org.mockito.junit.MockitoRule; import java.time.Duration; import java.util.HashMap; @@ -91,6 +92,8 @@ public class HearingAidServiceTest { private HearingAidService.BluetoothHearingAidBinder mServiceBinder; private HashMap<BluetoothDevice, LinkedBlockingQueue<Intent>> mDeviceQueueMap; + @Rule public MockitoRule mockitoRule = MockitoJUnit.rule(); + @Mock private AdapterService mAdapterService; @Mock private ActiveDeviceManager mActiveDeviceManager; @Mock private AudioRoutingManager mAudioRoutingManager; @@ -103,8 +106,6 @@ public class HearingAidServiceTest { @Before public void setUp() throws Exception { - // Set up mocks and test assets - MockitoAnnotations.initMocks(this); mInOrder = inOrder(mContext); TestUtils.mockGetSystemService( diff --git a/android/app/tests/unit/src/com/android/bluetooth/hearingaid/HearingAidStateMachineTest.java b/android/app/tests/unit/src/com/android/bluetooth/hearingaid/HearingAidStateMachineTest.java index e5ed3151fc..f35f6b3435 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/hearingaid/HearingAidStateMachineTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/hearingaid/HearingAidStateMachineTest.java @@ -37,11 +37,13 @@ import org.hamcrest.core.IsInstanceOf; import org.junit.After; import org.junit.Assert; import org.junit.Before; +import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.ArgumentCaptor; import org.mockito.Mock; -import org.mockito.MockitoAnnotations; +import org.mockito.junit.MockitoJUnit; +import org.mockito.junit.MockitoRule; @MediumTest @RunWith(AndroidJUnit4.class) @@ -53,6 +55,8 @@ public class HearingAidStateMachineTest { private BluetoothDevice mTestDevice; private static final int TIMEOUT_MS = 1000; + @Rule public MockitoRule mockitoRule = MockitoJUnit.rule(); + @Mock private AdapterService mAdapterService; @Mock private HearingAidService mHearingAidService; @Mock private HearingAidNativeInterface mHearingAidNativeInterface; @@ -60,8 +64,6 @@ public class HearingAidStateMachineTest { @Before public void setUp() throws Exception { mTargetContext = InstrumentationRegistry.getTargetContext(); - // Set up mocks and test assets - MockitoAnnotations.initMocks(this); TestUtils.setAdapterService(mAdapterService); mAdapter = BluetoothAdapter.getDefaultAdapter(); diff --git a/android/app/tests/unit/src/com/android/bluetooth/hfp/AtPhonebookTest.java b/android/app/tests/unit/src/com/android/bluetooth/hfp/AtPhonebookTest.java index 131c886c52..1ca0830d79 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/hfp/AtPhonebookTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/hfp/AtPhonebookTest.java @@ -46,11 +46,13 @@ import com.android.internal.telephony.GsmAlphabet; import org.junit.After; import org.junit.Before; +import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; -import org.mockito.MockitoAnnotations; import org.mockito.Spy; +import org.mockito.junit.MockitoJUnit; +import org.mockito.junit.MockitoRule; @RunWith(AndroidJUnit4.class) public class AtPhonebookTest { @@ -59,6 +61,8 @@ public class AtPhonebookTest { private BluetoothAdapter mAdapter; private BluetoothDevice mTestDevice; + @Rule public MockitoRule mockitoRule = MockitoJUnit.rule(); + @Mock private AdapterService mAdapterService; @Mock private HeadsetNativeInterface mNativeInterface; @@ -69,7 +73,6 @@ public class AtPhonebookTest { @Before public void setUp() throws Exception { mTargetContext = InstrumentationRegistry.getTargetContext(); - MockitoAnnotations.initMocks(this); TestUtils.setAdapterService(mAdapterService); BluetoothMethodProxy.setInstanceForTesting(mHfpMethodProxy); diff --git a/android/app/tests/unit/src/com/android/bluetooth/hfp/BluetoothHeadsetBinderTest.java b/android/app/tests/unit/src/com/android/bluetooth/hfp/BluetoothHeadsetBinderTest.java index 61e488ebd8..215991d285 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/hfp/BluetoothHeadsetBinderTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/hfp/BluetoothHeadsetBinderTest.java @@ -26,13 +26,17 @@ import android.content.AttributionSource; import com.android.bluetooth.x.com.android.modules.utils.SynchronousResultReceiver; import org.junit.Before; +import org.junit.Rule; import org.junit.Test; import org.mockito.Mock; -import org.mockito.MockitoAnnotations; +import org.mockito.junit.MockitoJUnit; +import org.mockito.junit.MockitoRule; public class BluetoothHeadsetBinderTest { private static final String TEST_DEVICE_ADDRESS = "00:00:00:00:00:00"; + @Rule public MockitoRule mockitoRule = MockitoJUnit.rule(); + @Mock private HeadsetService mService; @@ -43,7 +47,6 @@ public class BluetoothHeadsetBinderTest { @Before public void setUp() throws Exception { - MockitoAnnotations.initMocks(this); mBinder = new HeadsetService.BluetoothHeadsetBinder(mService); mAttributionSource = new AttributionSource.Builder(1).build(); mTestDevice = BluetoothAdapter.getDefaultAdapter().getRemoteDevice(TEST_DEVICE_ADDRESS); diff --git a/android/app/tests/unit/src/com/android/bluetooth/hfp/HeadsetPhoneStateTest.java b/android/app/tests/unit/src/com/android/bluetooth/hfp/HeadsetPhoneStateTest.java index 58e3116399..2fb01939b7 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/hfp/HeadsetPhoneStateTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/hfp/HeadsetPhoneStateTest.java @@ -39,10 +39,12 @@ import com.android.internal.telephony.ISub; import org.junit.After; import org.junit.Before; +import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; -import org.mockito.MockitoAnnotations; +import org.mockito.junit.MockitoJUnit; +import org.mockito.junit.MockitoRule; import java.util.HashMap; @@ -52,6 +54,8 @@ import java.util.HashMap; @MediumTest @RunWith(AndroidJUnit4.class) public class HeadsetPhoneStateTest { + @Rule public MockitoRule mockitoRule = MockitoJUnit.rule(); + @Mock private ISub mISub; @Mock private IBinder mISubBinder; @Mock private HeadsetService mHeadsetService; @@ -69,7 +73,6 @@ public class HeadsetPhoneStateTest { Looper.prepare(); } IpcDataCache.disableForTestMode(); - MockitoAnnotations.initMocks(this); SubscriptionManager.disableCaching(); TelephonyManager.disableServiceHandleCaching(); // Mock SubscriptionManager.getDefaultSubscriptionId() to return a valid value diff --git a/android/app/tests/unit/src/com/android/bluetooth/hfp/HeadsetServiceAndStateMachineTest.java b/android/app/tests/unit/src/com/android/bluetooth/hfp/HeadsetServiceAndStateMachineTest.java index 94af16dc78..5c097e9756 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/hfp/HeadsetServiceAndStateMachineTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/hfp/HeadsetServiceAndStateMachineTest.java @@ -69,8 +69,9 @@ import org.junit.runner.RunWith; import org.mockito.ArgumentCaptor; import org.mockito.InOrder; import org.mockito.Mock; -import org.mockito.MockitoAnnotations; import org.mockito.Spy; +import org.mockito.junit.MockitoJUnit; +import org.mockito.junit.MockitoRule; import java.lang.reflect.Method; import java.util.Collections; @@ -110,6 +111,8 @@ public class HeadsetServiceAndStateMachineTest { boolean mIsAdapterServiceSet; boolean mIsHeadsetServiceStarted; + @Rule public MockitoRule mockitoRule = MockitoJUnit.rule(); + @Mock private HeadsetNativeInterface mNativeInterface; private class HeadsetIntentReceiver extends BroadcastReceiver { @@ -165,7 +168,6 @@ public class HeadsetServiceAndStateMachineTest { @Before public void setUp() throws Exception { mTargetContext = InstrumentationRegistry.getTargetContext(); - MockitoAnnotations.initMocks(this); PowerManager powerManager = mTargetContext.getSystemService(PowerManager.class); mVoiceRecognitionWakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "VoiceRecognitionTest"); @@ -1260,6 +1262,46 @@ public class HeadsetServiceAndStateMachineTest { verify(mNativeInterface, times(0)).connectAudio(device); } + /** + * Test to verify the following behavior regarding phoneStateChanged when the SCO is managed by + * the Audio: When phoneStateChange returns, HeadsetStateMachine completes processing + * mActiveDevice's CALL_STATE_CHANGED message + */ + @Test + public void testPhoneStateChange_SynchronousCallStateChanged() { + mSetFlagsRule.enableFlags(Flags.FLAG_IS_SCO_MANAGED_BY_AUDIO); + + BluetoothDevice device = TestUtils.getTestDevice(mAdapter, 0); + Assert.assertNotNull(device); + connectTestDevice(device); + + BluetoothDevice device2 = TestUtils.getTestDevice(mAdapter, 1); + Assert.assertNotNull(device2); + connectTestDevice(device2); + + BluetoothDevice device3 = TestUtils.getTestDevice(mAdapter, 2); + Assert.assertNotNull(device3); + connectTestDevice(device3); + + mHeadsetService.setActiveDevice(device); + Assert.assertTrue(mHeadsetService.setActiveDevice(device)); + + HeadsetCallState headsetCallState = + new HeadsetCallState( + 0, 0, HeadsetHalConstants.CALL_STATE_INCOMING, TEST_PHONE_NUMBER, 128, ""); + mHeadsetService.phoneStateChanged( + headsetCallState.mNumActive, + headsetCallState.mNumHeld, + headsetCallState.mCallState, + headsetCallState.mNumber, + headsetCallState.mType, + headsetCallState.mName, + false); + // verify phoneStateChanged runs synchronously, which means when phoneStateChange returns, + // HeadsetStateMachine completes processing CALL_STATE_CHANGED message + verify(mNativeInterface, times(1)).phoneStateChange(device, headsetCallState); + } + private void connectTestDevice(BluetoothDevice device) { when(mDatabaseManager.getProfileConnectionPolicy(device, BluetoothProfile.HEADSET)) .thenReturn(BluetoothProfile.CONNECTION_POLICY_UNKNOWN); diff --git a/android/app/tests/unit/src/com/android/bluetooth/hfp/HeadsetServiceTest.java b/android/app/tests/unit/src/com/android/bluetooth/hfp/HeadsetServiceTest.java index 2aa1e1ff0d..95d70a9aa2 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/hfp/HeadsetServiceTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/hfp/HeadsetServiceTest.java @@ -59,11 +59,13 @@ import org.hamcrest.Matchers; import org.junit.After; import org.junit.Assert; import org.junit.Before; +import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; -import org.mockito.MockitoAnnotations; import org.mockito.Spy; +import org.mockito.junit.MockitoJUnit; +import org.mockito.junit.MockitoRule; import java.lang.reflect.Method; import java.util.ArrayList; @@ -89,6 +91,8 @@ public class HeadsetServiceTest { private final HashMap<BluetoothDevice, HeadsetStateMachine> mStateMachines = new HashMap<>(); @Spy private HeadsetObjectsFactory mObjectsFactory = HeadsetObjectsFactory.getInstance(); + @Rule public MockitoRule mockitoRule = MockitoJUnit.rule(); + @Mock private AdapterService mAdapterService; @Mock private ActiveDeviceManager mActiveDeviceManager; @Mock private SilenceDeviceManager mSilenceDeviceManager; @@ -102,7 +106,6 @@ public class HeadsetServiceTest { @Before public void setUp() throws Exception { mTargetContext = InstrumentationRegistry.getTargetContext(); - MockitoAnnotations.initMocks(this); TestUtils.setAdapterService(mAdapterService); // We cannot mock HeadsetObjectsFactory.getInstance() with Mockito. // Hence we need to use reflection to call a private method to diff --git a/android/app/tests/unit/src/com/android/bluetooth/hfp/HeadsetStateMachineTest.java b/android/app/tests/unit/src/com/android/bluetooth/hfp/HeadsetStateMachineTest.java index 74372219df..c5fcd84cf4 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/hfp/HeadsetStateMachineTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/hfp/HeadsetStateMachineTest.java @@ -71,7 +71,8 @@ import org.junit.runner.RunWith; import org.mockito.ArgumentCaptor; import org.mockito.Mock; import org.mockito.Mockito; -import org.mockito.MockitoAnnotations; +import org.mockito.junit.MockitoJUnit; +import org.mockito.junit.MockitoRule; import java.util.ArrayList; @@ -96,6 +97,8 @@ public class HeadsetStateMachineTest { private BluetoothDevice mTestDevice; private ArgumentCaptor<Intent> mIntentArgument = ArgumentCaptor.forClass(Intent.class); + @Rule public MockitoRule mockitoRule = MockitoJUnit.rule(); + @Mock private AdapterService mAdapterService; @Mock private ActiveDeviceManager mActiveDeviceManager; @Mock private SilenceDeviceManager mSilenceDeviceManager; @@ -113,7 +116,6 @@ public class HeadsetStateMachineTest { public void setUp() throws Exception { mTargetContext = InstrumentationRegistry.getTargetContext(); // Setup mocks and test assets - MockitoAnnotations.initMocks(this); TestUtils.setAdapterService(mAdapterService); // Stub system interface doReturn(mPhoneState).when(mSystemInterface).getHeadsetPhoneState(); diff --git a/android/app/tests/unit/src/com/android/bluetooth/hfpclient/HeadsetClientServiceBinderTest.java b/android/app/tests/unit/src/com/android/bluetooth/hfpclient/HeadsetClientServiceBinderTest.java index 9f686827ca..5fee0b31c9 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/hfpclient/HeadsetClientServiceBinderTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/hfpclient/HeadsetClientServiceBinderTest.java @@ -28,16 +28,20 @@ import androidx.test.runner.AndroidJUnit4; import com.android.bluetooth.x.com.android.modules.utils.SynchronousResultReceiver; import org.junit.Before; +import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; -import org.mockito.MockitoAnnotations; +import org.mockito.junit.MockitoJUnit; +import org.mockito.junit.MockitoRule; @SmallTest @RunWith(AndroidJUnit4.class) public class HeadsetClientServiceBinderTest { private static final String REMOTE_DEVICE_ADDRESS = "00:00:00:00:00:00"; + @Rule public MockitoRule mockitoRule = MockitoJUnit.rule(); + @Mock private HeadsetClientService mService; @@ -47,7 +51,6 @@ public class HeadsetClientServiceBinderTest { @Before public void setUp() throws Exception { - MockitoAnnotations.initMocks(this); mRemoteDevice = BluetoothAdapter.getDefaultAdapter().getRemoteDevice(REMOTE_DEVICE_ADDRESS); mBinder = new HeadsetClientService.BluetoothHeadsetClientBinder(mService); } diff --git a/android/app/tests/unit/src/com/android/bluetooth/hfpclient/HeadsetClientServiceTest.java b/android/app/tests/unit/src/com/android/bluetooth/hfpclient/HeadsetClientServiceTest.java index a6288f647f..fc08492d05 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/hfpclient/HeadsetClientServiceTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/hfpclient/HeadsetClientServiceTest.java @@ -47,11 +47,13 @@ import org.junit.After; import org.junit.Assert; import org.junit.Before; import org.junit.Ignore; +import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; import org.mockito.Mockito; -import org.mockito.MockitoAnnotations; +import org.mockito.junit.MockitoJUnit; +import org.mockito.junit.MockitoRule; @MediumTest @RunWith(AndroidJUnit4.class) @@ -64,6 +66,8 @@ public class HeadsetClientServiceTest { private static final int STANDARD_WAIT_MILLIS = 1000; + @Rule public MockitoRule mockitoRule = MockitoJUnit.rule(); + @Mock private AdapterService mAdapterService; @Mock private HeadsetClientStateMachine mStateMachine; @Mock private NativeInterface mNativeInterface; @@ -73,7 +77,6 @@ public class HeadsetClientServiceTest { @Before public void setUp() throws Exception { mTargetContext = InstrumentationRegistry.getTargetContext(); - MockitoAnnotations.initMocks(this); TestUtils.setAdapterService(mAdapterService); mIsAdapterServiceSet = true; diff --git a/android/app/tests/unit/src/com/android/bluetooth/hfpclient/HeadsetClientStateMachineTest.java b/android/app/tests/unit/src/com/android/bluetooth/hfpclient/HeadsetClientStateMachineTest.java index f95bd870e6..1228ba1be5 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/hfpclient/HeadsetClientStateMachineTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/hfpclient/HeadsetClientStateMachineTest.java @@ -68,13 +68,15 @@ import org.hamcrest.core.IsInstanceOf; import org.junit.After; import org.junit.Assert; import org.junit.Before; +import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.ArgumentCaptor; import org.mockito.Mock; import org.mockito.Mockito; -import org.mockito.MockitoAnnotations; import org.mockito.hamcrest.MockitoHamcrest; +import org.mockito.junit.MockitoJUnit; +import org.mockito.junit.MockitoRule; import java.util.List; import java.util.Set; @@ -91,6 +93,8 @@ public class HeadsetClientStateMachineTest { private BluetoothDevice mTestDevice; private Context mTargetContext; + @Rule public MockitoRule mockitoRule = MockitoJUnit.rule(); + @Mock private AdapterService mAdapterService; @Mock private Resources mMockHfpResources; @Mock private HeadsetService mHeadsetService; @@ -110,7 +114,6 @@ public class HeadsetClientStateMachineTest { public void setUp() throws Exception { mTargetContext = InstrumentationRegistry.getTargetContext(); // Setup mocks and test assets - MockitoAnnotations.initMocks(this); // Set a valid volume when(mAudioManager.getStreamVolume(anyInt())).thenReturn(2); when(mAudioManager.getStreamMaxVolume(anyInt())).thenReturn(10); diff --git a/android/app/tests/unit/src/com/android/bluetooth/hfpclient/HfpNativeInterfaceTest.java b/android/app/tests/unit/src/com/android/bluetooth/hfpclient/HfpNativeInterfaceTest.java index 1db59c0774..5dc40be314 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/hfpclient/HfpNativeInterfaceTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/hfpclient/HfpNativeInterfaceTest.java @@ -27,14 +27,18 @@ import com.android.bluetooth.btservice.AdapterService; import org.junit.After; import org.junit.Before; +import org.junit.Rule; import org.junit.Test; import org.mockito.ArgumentCaptor; import org.mockito.Mock; -import org.mockito.MockitoAnnotations; +import org.mockito.junit.MockitoJUnit; +import org.mockito.junit.MockitoRule; public class HfpNativeInterfaceTest { private static final byte[] TEST_DEVICE_ADDRESS = new byte[] { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; + @Rule public MockitoRule mockitoRule = MockitoJUnit.rule(); + @Mock HeadsetClientService mService; @Mock @@ -44,7 +48,6 @@ public class HfpNativeInterfaceTest { @Before public void setUp() throws Exception { - MockitoAnnotations.initMocks(this); when(mService.isAvailable()).thenReturn(true); HeadsetClientService.setHeadsetClientService(mService); TestUtils.setAdapterService(mAdapterService); diff --git a/android/app/tests/unit/src/com/android/bluetooth/hfpclient/VendorCommandResponseProcessorTest.java b/android/app/tests/unit/src/com/android/bluetooth/hfpclient/VendorCommandResponseProcessorTest.java index 3876a4aa27..48428b7044 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/hfpclient/VendorCommandResponseProcessorTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/hfpclient/VendorCommandResponseProcessorTest.java @@ -32,10 +32,12 @@ import com.android.bluetooth.btservice.AdapterService; import org.junit.After; import org.junit.Before; +import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; -import org.mockito.MockitoAnnotations; +import org.mockito.junit.MockitoJUnit; +import org.mockito.junit.MockitoRule; @SmallTest @RunWith(AndroidJUnit4.class) @@ -44,6 +46,8 @@ public class VendorCommandResponseProcessorTest { private BluetoothAdapter mAdapter; private BluetoothDevice mTestDevice; + @Rule public MockitoRule mockitoRule = MockitoJUnit.rule(); + @Mock private NativeInterface mNativeInterface; private VendorCommandResponseProcessor mProcessor; @@ -54,7 +58,6 @@ public class VendorCommandResponseProcessorTest { @Before public void setUp() throws Exception { - MockitoAnnotations.initMocks(this); TestUtils.setAdapterService(mAdapterService); mAdapter = BluetoothAdapter.getDefaultAdapter(); diff --git a/android/app/tests/unit/src/com/android/bluetooth/hfpclient/connserv/HeadsetClientServiceInterfaceTest.java b/android/app/tests/unit/src/com/android/bluetooth/hfpclient/connserv/HeadsetClientServiceInterfaceTest.java index c35ed99425..68918e5965 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/hfpclient/connserv/HeadsetClientServiceInterfaceTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/hfpclient/connserv/HeadsetClientServiceInterfaceTest.java @@ -31,10 +31,12 @@ import androidx.test.runner.AndroidJUnit4; import org.junit.After; import org.junit.Before; +import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; -import org.mockito.MockitoAnnotations; +import org.mockito.junit.MockitoJUnit; +import org.mockito.junit.MockitoRule; import java.util.List; import java.util.Set; @@ -58,12 +60,13 @@ public class HeadsetClientServiceInterfaceTest { TEST_BUNDLE.putInt("test_int", 0); } + @Rule public MockitoRule mockitoRule = MockitoJUnit.rule(); + @Mock private HeadsetClientService mMockHeadsetClientService; private HeadsetClientServiceInterface mServiceInterface; @Before public void setUp() { - MockitoAnnotations.initMocks(this); HeadsetClientService.setHeadsetClientService(mMockHeadsetClientService); mServiceInterface = new HeadsetClientServiceInterface(); } diff --git a/android/app/tests/unit/src/com/android/bluetooth/hfpclient/connserv/HfpClientConnectionServiceTest.java b/android/app/tests/unit/src/com/android/bluetooth/hfpclient/connserv/HfpClientConnectionServiceTest.java index 4be3028948..a4258951d6 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/hfpclient/connserv/HfpClientConnectionServiceTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/hfpclient/connserv/HfpClientConnectionServiceTest.java @@ -49,10 +49,12 @@ import com.android.bluetooth.btservice.AdapterService; import org.junit.After; import org.junit.Before; +import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; -import org.mockito.MockitoAnnotations; +import org.mockito.junit.MockitoJUnit; +import org.mockito.junit.MockitoRule; import java.util.Arrays; import java.util.List; @@ -67,6 +69,8 @@ public class HfpClientConnectionServiceTest { .getAdapter().getRemoteDevice(TEST_DEVICE_ADDRESS); private static final String TEST_NUMBER = "000-111-2222"; + @Rule public MockitoRule mockitoRule = MockitoJUnit.rule(); + @Mock private AdapterService mAdapterService; @Mock private HeadsetClientService mMockHeadsetClientService; @Mock private TelecomManager mMockTelecomManager; @@ -77,7 +81,6 @@ public class HfpClientConnectionServiceTest { @Before public void setUp() { - MockitoAnnotations.initMocks(this); Context targetContext = InstrumentationRegistry.getTargetContext(); diff --git a/android/app/tests/unit/src/com/android/bluetooth/hfpclient/connserv/HfpClientDeviceBlockTest.java b/android/app/tests/unit/src/com/android/bluetooth/hfpclient/connserv/HfpClientDeviceBlockTest.java index f9839328f5..c30e2b86a3 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/hfpclient/connserv/HfpClientDeviceBlockTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/hfpclient/connserv/HfpClientDeviceBlockTest.java @@ -33,11 +33,13 @@ import androidx.test.runner.AndroidJUnit4; import org.junit.Before; import org.junit.Ignore; +import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.ArgumentCaptor; import org.mockito.Mock; -import org.mockito.MockitoAnnotations; +import org.mockito.junit.MockitoJUnit; +import org.mockito.junit.MockitoRule; @MediumTest @RunWith(AndroidJUnit4.class) @@ -47,6 +49,8 @@ public class HfpClientDeviceBlockTest { private static final String KEY_SCO_STATE = "com.android.bluetooth.hfpclient.SCO_STATE"; private static final String TEST_PACKAGE = "test"; + @Rule public MockitoRule mockitoRule = MockitoJUnit.rule(); + @Mock private HeadsetClientService mHeadsetClientService; @Mock @@ -65,7 +69,6 @@ public class HfpClientDeviceBlockTest { @Before public void setUp() { - MockitoAnnotations.initMocks(this); // HfpClientConnectionService.createAccount is static and can't be mocked, so the // application context and resources must be mocked to avoid NPE when creating an diff --git a/android/app/tests/unit/src/com/android/bluetooth/hid/BluetoothHidDeviceBinderTest.java b/android/app/tests/unit/src/com/android/bluetooth/hid/BluetoothHidDeviceBinderTest.java index 2138729b74..6c6b311240 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/hid/BluetoothHidDeviceBinderTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/hid/BluetoothHidDeviceBinderTest.java @@ -34,14 +34,18 @@ import android.content.AttributionSource; import com.android.bluetooth.x.com.android.modules.utils.SynchronousResultReceiver; import org.junit.Before; +import org.junit.Rule; import org.junit.Test; import org.mockito.Mock; -import org.mockito.MockitoAnnotations; +import org.mockito.junit.MockitoJUnit; +import org.mockito.junit.MockitoRule; public class BluetoothHidDeviceBinderTest { private static final String TEST_DEVICE_ADDRESS = "00:00:00:00:00:00"; + @Rule public MockitoRule mockitoRule = MockitoJUnit.rule(); + @Mock private HidDeviceService mService; private AttributionSource mAttributionSource; @@ -50,7 +54,6 @@ public class BluetoothHidDeviceBinderTest { @Before public void setUp() throws Exception { - MockitoAnnotations.initMocks(this); when(mService.isAvailable()).thenReturn(true); mBinder = new HidDeviceService.BluetoothHidDeviceBinder(mService); mAttributionSource = new AttributionSource.Builder(1).build(); diff --git a/android/app/tests/unit/src/com/android/bluetooth/hid/HidDeviceNativeInterfaceTest.java b/android/app/tests/unit/src/com/android/bluetooth/hid/HidDeviceNativeInterfaceTest.java index fd70351493..41b4006ee8 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/hid/HidDeviceNativeInterfaceTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/hid/HidDeviceNativeInterfaceTest.java @@ -29,13 +29,17 @@ import com.android.bluetooth.btservice.AdapterService; import org.junit.After; import org.junit.Before; +import org.junit.Rule; import org.junit.Test; import org.mockito.Mock; -import org.mockito.MockitoAnnotations; +import org.mockito.junit.MockitoJUnit; +import org.mockito.junit.MockitoRule; public class HidDeviceNativeInterfaceTest { private static final byte[] TEST_DEVICE_ADDRESS = new byte[] { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; + @Rule public MockitoRule mockitoRule = MockitoJUnit.rule(); + @Mock HidDeviceService mService; @Mock @@ -45,7 +49,6 @@ public class HidDeviceNativeInterfaceTest { @Before public void setUp() throws Exception { - MockitoAnnotations.initMocks(this); when(mService.isAvailable()).thenReturn(true); HidDeviceService.setHidDeviceService(mService); TestUtils.setAdapterService(mAdapterService); diff --git a/android/app/tests/unit/src/com/android/bluetooth/hid/HidDeviceTest.java b/android/app/tests/unit/src/com/android/bluetooth/hid/HidDeviceTest.java index db4a62ee35..4b6672ec6c 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/hid/HidDeviceTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/hid/HidDeviceTest.java @@ -41,10 +41,12 @@ import com.android.bluetooth.btservice.storage.DatabaseManager; import org.junit.After; import org.junit.Assert; import org.junit.Before; +import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; -import org.mockito.MockitoAnnotations; +import org.mockito.junit.MockitoJUnit; +import org.mockito.junit.MockitoRule; import java.lang.reflect.Field; import java.lang.reflect.Method; @@ -70,6 +72,8 @@ public class HidDeviceTest { private static final int CALLBACK_ON_INTR_DATA = 5; private static final int CALLBACK_ON_VIRTUAL_UNPLUG = 6; + @Rule public MockitoRule mockitoRule = MockitoJUnit.rule(); + @Mock private AdapterService mAdapterService; @Mock private DatabaseManager mDatabaseManager; @Mock private HidDeviceNativeInterface mHidDeviceNativeInterface; @@ -100,8 +104,6 @@ public class HidDeviceTest { } Assert.assertNotNull(Looper.myLooper()); - // Set up mocks and test assets - MockitoAnnotations.initMocks(this); TestUtils.setAdapterService(mAdapterService); doReturn(mDatabaseManager).when(mAdapterService).getDatabase(); setHidDeviceNativeInterfaceInstance(mHidDeviceNativeInterface); diff --git a/android/app/tests/unit/src/com/android/bluetooth/hid/HidHostServiceBinderTest.java b/android/app/tests/unit/src/com/android/bluetooth/hid/HidHostServiceBinderTest.java index 8bedfb3e2a..aeabb31e42 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/hid/HidHostServiceBinderTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/hid/HidHostServiceBinderTest.java @@ -30,7 +30,8 @@ import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; -import org.mockito.MockitoAnnotations; +import org.mockito.junit.MockitoJUnit; +import org.mockito.junit.MockitoRule; @SmallTest @RunWith(AndroidJUnit4.class) @@ -38,6 +39,8 @@ public class HidHostServiceBinderTest { @Rule public final SetFlagsRule mSetFlagsRule = new SetFlagsRule(); private static final String REMOTE_DEVICE_ADDRESS = "00:00:00:00:00:00"; + @Rule public MockitoRule mockitoRule = MockitoJUnit.rule(); + @Mock private HidHostService mService; @@ -47,7 +50,6 @@ public class HidHostServiceBinderTest { @Before public void setUp() throws Exception { - MockitoAnnotations.initMocks(this); mRemoteDevice = BluetoothAdapter.getDefaultAdapter().getRemoteDevice(REMOTE_DEVICE_ADDRESS); mBinder = new HidHostService.BluetoothHidHostBinder(mService); } diff --git a/android/app/tests/unit/src/com/android/bluetooth/hid/HidHostServiceTest.java b/android/app/tests/unit/src/com/android/bluetooth/hid/HidHostServiceTest.java index 41652ab673..e21145d79d 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/hid/HidHostServiceTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/hid/HidHostServiceTest.java @@ -33,10 +33,12 @@ import com.android.bluetooth.btservice.storage.DatabaseManager; import org.junit.After; import org.junit.Assert; import org.junit.Before; +import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; -import org.mockito.MockitoAnnotations; +import org.mockito.junit.MockitoJUnit; +import org.mockito.junit.MockitoRule; @MediumTest @RunWith(AndroidJUnit4.class) @@ -46,6 +48,8 @@ public class HidHostServiceTest { private BluetoothDevice mTestDevice; private Context mTargetContext; + @Rule public MockitoRule mockitoRule = MockitoJUnit.rule(); + @Mock private AdapterService mAdapterService; @Mock private DatabaseManager mDatabaseManager; @Mock private HidHostNativeInterface mNativeInterface; @@ -53,7 +57,6 @@ public class HidHostServiceTest { @Before public void setUp() throws Exception { mTargetContext = InstrumentationRegistry.getTargetContext(); - MockitoAnnotations.initMocks(this); TestUtils.setAdapterService(mAdapterService); when(mAdapterService.getDatabase()).thenReturn(mDatabaseManager); HidHostNativeInterface.setInstance(mNativeInterface); diff --git a/android/app/tests/unit/src/com/android/bluetooth/le_audio/ContentControlIdKeeperTest.java b/android/app/tests/unit/src/com/android/bluetooth/le_audio/ContentControlIdKeeperTest.java index 9e8ebe5d36..6a3443387d 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/le_audio/ContentControlIdKeeperTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/le_audio/ContentControlIdKeeperTest.java @@ -30,10 +30,12 @@ import com.android.bluetooth.btservice.ServiceFactory; import org.junit.After; import org.junit.Assert; import org.junit.Before; +import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; -import org.mockito.MockitoAnnotations; +import org.mockito.junit.MockitoJUnit; +import org.mockito.junit.MockitoRule; import java.util.Map; import java.util.UUID; @@ -41,6 +43,8 @@ import java.util.UUID; @MediumTest @RunWith(AndroidJUnit4.class) public class ContentControlIdKeeperTest { + @Rule public MockitoRule mockitoRule = MockitoJUnit.rule(); + @Mock ServiceFactory mServiceFactoryMock; @Mock @@ -48,7 +52,6 @@ public class ContentControlIdKeeperTest { @Before public void setUp() throws Exception { - MockitoAnnotations.initMocks(this); doReturn(mLeAudioServiceMock).when(mServiceFactoryMock).getLeAudioService(); ContentControlIdKeeper.initForTesting(mServiceFactoryMock); diff --git a/android/app/tests/unit/src/com/android/bluetooth/le_audio/LeAudioBinderTest.java b/android/app/tests/unit/src/com/android/bluetooth/le_audio/LeAudioBinderTest.java index d7f7d419d3..df2877473f 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/le_audio/LeAudioBinderTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/le_audio/LeAudioBinderTest.java @@ -52,7 +52,8 @@ import org.junit.Rule; import org.junit.Test; import org.mockito.Mock; import org.mockito.Mockito; -import org.mockito.MockitoAnnotations; +import org.mockito.junit.MockitoJUnit; +import org.mockito.junit.MockitoRule; import java.util.List; import java.util.UUID; @@ -62,6 +63,8 @@ public class LeAudioBinderTest { @Rule public final SetFlagsRule mSetFlagsRule = new SetFlagsRule(); private LeAudioService mLeAudioService; + @Rule public MockitoRule mockitoRule = MockitoJUnit.rule(); + @Mock private AdapterService mAdapterService; @Mock private LeAudioNativeInterface mNativeInterface; @Mock private DatabaseManager mDatabaseManager; @@ -79,7 +82,6 @@ public class LeAudioBinderTest { @Before public void setUp() throws Exception { - MockitoAnnotations.initMocks(this); TestUtils.setAdapterService(mAdapterService); doReturn(false).when(mAdapterService).isQuietModeEnabled(); doReturn(mDatabaseManager).when(mAdapterService).getDatabase(); diff --git a/android/app/tests/unit/src/com/android/bluetooth/le_audio/LeAudioBroadcastServiceTest.java b/android/app/tests/unit/src/com/android/bluetooth/le_audio/LeAudioBroadcastServiceTest.java index 17057c9f3e..8a6a4de6c5 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/le_audio/LeAudioBroadcastServiceTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/le_audio/LeAudioBroadcastServiceTest.java @@ -54,8 +54,9 @@ import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; import org.mockito.Mockito; -import org.mockito.MockitoAnnotations; import org.mockito.Spy; +import org.mockito.junit.MockitoJUnit; +import org.mockito.junit.MockitoRule; import java.util.List; import java.util.concurrent.LinkedBlockingQueue; @@ -76,6 +77,8 @@ public class LeAudioBroadcastServiceTest { private LeAudioService mService; private LeAudioIntentReceiver mLeAudioIntentReceiver; private LinkedBlockingQueue<Intent> mIntentQueue; + @Rule public MockitoRule mockitoRule = MockitoJUnit.rule(); + @Mock private ActiveDeviceManager mActiveDeviceManager; @Mock private AdapterService mAdapterService; @@ -195,8 +198,6 @@ public class LeAudioBroadcastServiceTest { public void setUp() throws Exception { mTargetContext = InstrumentationRegistry.getTargetContext(); - // Set up mocks and test assets - MockitoAnnotations.initMocks(this); // Use spied objects factory doNothing().when(mTmapGattServer).start(anyInt()); diff --git a/android/app/tests/unit/src/com/android/bluetooth/le_audio/LeAudioBroadcasterNativeInterfaceTest.java b/android/app/tests/unit/src/com/android/bluetooth/le_audio/LeAudioBroadcasterNativeInterfaceTest.java index 5e4e44a9e6..045b5a2667 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/le_audio/LeAudioBroadcasterNativeInterfaceTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/le_audio/LeAudioBroadcasterNativeInterfaceTest.java @@ -27,14 +27,18 @@ import androidx.test.runner.AndroidJUnit4; import org.junit.After; import org.junit.Before; +import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.ArgumentCaptor; import org.mockito.Mock; -import org.mockito.MockitoAnnotations; +import org.mockito.junit.MockitoJUnit; +import org.mockito.junit.MockitoRule; @RunWith(AndroidJUnit4.class) public class LeAudioBroadcasterNativeInterfaceTest { + @Rule public MockitoRule mockitoRule = MockitoJUnit.rule(); + @Mock private LeAudioService mMockService; @@ -42,7 +46,6 @@ public class LeAudioBroadcasterNativeInterfaceTest { @Before public void setUp() throws Exception { - MockitoAnnotations.initMocks(this); when(mMockService.isAvailable()).thenReturn(true); LeAudioService.setLeAudioService(mMockService); mNativeInterface = LeAudioBroadcasterNativeInterface.getInstance(); diff --git a/android/app/tests/unit/src/com/android/bluetooth/le_audio/LeAudioNativeInterfaceTest.java b/android/app/tests/unit/src/com/android/bluetooth/le_audio/LeAudioNativeInterfaceTest.java index 7b45a9fa64..cf88ce4925 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/le_audio/LeAudioNativeInterfaceTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/le_audio/LeAudioNativeInterfaceTest.java @@ -28,14 +28,18 @@ import androidx.test.runner.AndroidJUnit4; import org.junit.After; import org.junit.Before; +import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.ArgumentCaptor; import org.mockito.Mock; -import org.mockito.MockitoAnnotations; +import org.mockito.junit.MockitoJUnit; +import org.mockito.junit.MockitoRule; @RunWith(AndroidJUnit4.class) public class LeAudioNativeInterfaceTest { + @Rule public MockitoRule mockitoRule = MockitoJUnit.rule(); + @Mock private LeAudioService mMockService; @@ -43,7 +47,6 @@ public class LeAudioNativeInterfaceTest { @Before public void setUp() throws Exception { - MockitoAnnotations.initMocks(this); when(mMockService.isAvailable()).thenReturn(true); LeAudioService.setLeAudioService(mMockService); mNativeInterface = LeAudioNativeInterface.getInstance(); diff --git a/android/app/tests/unit/src/com/android/bluetooth/le_audio/LeAudioServiceTest.java b/android/app/tests/unit/src/com/android/bluetooth/le_audio/LeAudioServiceTest.java index 30bb834a44..9ae849428d 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/le_audio/LeAudioServiceTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/le_audio/LeAudioServiceTest.java @@ -78,8 +78,9 @@ import org.junit.runner.RunWith; import org.mockito.ArgumentCaptor; import org.mockito.Mock; import org.mockito.Mockito; -import org.mockito.MockitoAnnotations; import org.mockito.Spy; +import org.mockito.junit.MockitoJUnit; +import org.mockito.junit.MockitoRule; import java.util.HashMap; import java.util.HashSet; @@ -118,6 +119,8 @@ public class LeAudioServiceTest { private BroadcastReceiver mLeAudioIntentReceiver; + @Rule public MockitoRule mockitoRule = MockitoJUnit.rule(); + @Mock private AdapterService mAdapterService; @Mock private ActiveDeviceManager mActiveDeviceManager; @Mock private AudioManager mAudioManager; @@ -166,8 +169,6 @@ public class LeAudioServiceTest { public void setUp() throws Exception { mTargetContext = InstrumentationRegistry.getTargetContext(); - // Set up mocks and test assets - MockitoAnnotations.initMocks(this); // Use spied objects factory doNothing().when(mTmapGattServer).start(anyInt()); diff --git a/android/app/tests/unit/src/com/android/bluetooth/le_audio/LeAudioStateMachineTest.java b/android/app/tests/unit/src/com/android/bluetooth/le_audio/LeAudioStateMachineTest.java index d372c172fd..2921483669 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/le_audio/LeAudioStateMachineTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/le_audio/LeAudioStateMachineTest.java @@ -45,10 +45,12 @@ import com.android.bluetooth.btservice.AdapterService; import org.junit.After; import org.junit.Before; +import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; -import org.mockito.MockitoAnnotations; +import org.mockito.junit.MockitoJUnit; +import org.mockito.junit.MockitoRule; @MediumTest @RunWith(AndroidJUnit4.class) @@ -60,6 +62,8 @@ public class LeAudioStateMachineTest { private BluetoothDevice mTestDevice; private static final int TIMEOUT_MS = 1000; + @Rule public MockitoRule mockitoRule = MockitoJUnit.rule(); + @Mock private AdapterService mAdapterService; @Mock private LeAudioService mLeAudioService; @Mock private LeAudioNativeInterface mLeAudioNativeInterface; @@ -67,8 +71,6 @@ public class LeAudioStateMachineTest { @Before public void setUp() throws Exception { mTargetContext = InstrumentationRegistry.getTargetContext(); - // Set up mocks and test assets - MockitoAnnotations.initMocks(this); TestUtils.setAdapterService(mAdapterService); mAdapter = BluetoothAdapter.getDefaultAdapter(); diff --git a/android/app/tests/unit/src/com/android/bluetooth/le_audio/LeAudioTmapGattServerTest.java b/android/app/tests/unit/src/com/android/bluetooth/le_audio/LeAudioTmapGattServerTest.java index da9e348712..6afe455ca1 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/le_audio/LeAudioTmapGattServerTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/le_audio/LeAudioTmapGattServerTest.java @@ -37,11 +37,13 @@ import androidx.test.runner.AndroidJUnit4; import org.junit.After; import org.junit.Before; +import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.ArgumentCaptor; import org.mockito.Mock; -import org.mockito.MockitoAnnotations; +import org.mockito.junit.MockitoJUnit; +import org.mockito.junit.MockitoRule; @MediumTest @RunWith(AndroidJUnit4.class) @@ -49,6 +51,8 @@ public class LeAudioTmapGattServerTest { private static final int TEST_ROLE_MASK = LeAudioTmapGattServer.TMAP_ROLE_FLAG_CG | LeAudioTmapGattServer.TMAP_ROLE_FLAG_UMS; + @Rule public MockitoRule mockitoRule = MockitoJUnit.rule(); + @Mock private LeAudioTmapGattServer.BluetoothGattServerProxy mGattServerProxy; @@ -56,7 +60,6 @@ public class LeAudioTmapGattServerTest { @Before public void setUp() { - MockitoAnnotations.initMocks(this); doReturn(true).when(mGattServerProxy).open(any()); doReturn(true).when(mGattServerProxy).addService(any()); mServer = new LeAudioTmapGattServer(mGattServerProxy); diff --git a/android/app/tests/unit/src/com/android/bluetooth/gatt/AdvtFilterOnFoundOnLostInfoTest.java b/android/app/tests/unit/src/com/android/bluetooth/le_scan/AdvtFilterOnFoundOnLostInfoTest.java index 3eade702b5..674278dee7 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/gatt/AdvtFilterOnFoundOnLostInfoTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/le_scan/AdvtFilterOnFoundOnLostInfoTest.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.android.bluetooth.gatt; +package com.android.bluetooth.le_scan; import static com.google.common.truth.Truth.assertThat; diff --git a/android/app/tests/unit/src/com/android/bluetooth/le_scan/AppScanStatsTest.java b/android/app/tests/unit/src/com/android/bluetooth/le_scan/AppScanStatsTest.java index 4f0b434cac..d7b92e0ec6 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/le_scan/AppScanStatsTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/le_scan/AppScanStatsTest.java @@ -33,7 +33,6 @@ import androidx.test.runner.AndroidJUnit4; import com.android.bluetooth.TestUtils; import com.android.bluetooth.btservice.AdapterService; import com.android.bluetooth.gatt.ContextMap; -import com.android.bluetooth.gatt.GattService; import com.android.internal.app.IBatteryStats; import org.junit.After; @@ -42,7 +41,8 @@ import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; -import org.mockito.MockitoAnnotations; +import org.mockito.junit.MockitoJUnit; +import org.mockito.junit.MockitoRule; import java.util.ArrayList; import java.util.List; @@ -57,10 +57,13 @@ public class AppScanStatsTest { @Rule public final ServiceTestRule mServiceRule = new ServiceTestRule(); + @Rule public MockitoRule mockitoRule = MockitoJUnit.rule(); + @Mock private ContextMap map; - @Mock private GattService mMockGatt; + @Mock private Context mMockContext; + @Mock private TransitionalScanHelper mMockScanHelper; @Mock private AdapterService mAdapterService; // BatteryStatsManager is final and cannot be mocked with regular mockito, so just mock the @@ -70,12 +73,11 @@ public class AppScanStatsTest { @Before public void setUp() throws Exception { - MockitoAnnotations.initMocks(this); TestUtils.setAdapterService(mAdapterService); TestUtils.mockGetSystemService( - mMockGatt, + mMockContext, Context.BATTERY_STATS_SERVICE, BatteryStatsManager.class, mBatteryStatsManager); @@ -91,10 +93,11 @@ public class AppScanStatsTest { String name = "appName"; WorkSource source = null; - AppScanStats appScanStats = new AppScanStats(name, source, map, mMockGatt); + AppScanStats appScanStats = + new AppScanStats(name, source, map, mMockContext, mMockScanHelper); assertThat(appScanStats.mContextMap).isEqualTo(map); - assertThat(appScanStats.mGattService).isEqualTo(mMockGatt); + assertThat(appScanStats.mScanHelper).isEqualTo(mMockScanHelper); assertThat(appScanStats.isScanning()).isEqualTo(false); } @@ -104,7 +107,8 @@ public class AppScanStatsTest { String name = "appName"; WorkSource source = null; - AppScanStats appScanStats = new AppScanStats(name, source, map, mMockGatt); + AppScanStats appScanStats = + new AppScanStats(name, source, map, mMockContext, mMockScanHelper); ScanSettings settings = new ScanSettings.Builder().build(); List<ScanFilter> filters = new ArrayList<>(); diff --git a/android/app/tests/unit/src/com/android/bluetooth/le_scan/PeriodicScanManagerTest.java b/android/app/tests/unit/src/com/android/bluetooth/le_scan/PeriodicScanManagerTest.java index 61517270c3..1137a51dc8 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/le_scan/PeriodicScanManagerTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/le_scan/PeriodicScanManagerTest.java @@ -42,16 +42,20 @@ import com.android.bluetooth.btservice.AdapterService; import org.junit.After; import org.junit.Before; +import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.ArgumentCaptor; import org.mockito.Mock; -import org.mockito.MockitoAnnotations; +import org.mockito.junit.MockitoJUnit; +import org.mockito.junit.MockitoRule; /** Test cases for {@link PeriodicScanManagerTest}. */ @SmallTest @RunWith(AndroidJUnit4.class) public class PeriodicScanManagerTest { + @Rule public MockitoRule mockitoRule = MockitoJUnit.rule(); + @Mock private PeriodicScanNativeInterface mPeriodicScanNativeInterface; @Mock private AdapterService mAdapterService; @Mock private IPeriodicAdvertisingCallback mCallback; @@ -68,7 +72,6 @@ public class PeriodicScanManagerTest { @Before public void setUp() throws Exception { mTargetContext = InstrumentationRegistry.getTargetContext(); - MockitoAnnotations.initMocks(this); PeriodicScanNativeInterface.setInstance(mPeriodicScanNativeInterface); mPeriodicScanManager = new PeriodicScanManager(mAdapterService); diff --git a/android/app/tests/unit/src/com/android/bluetooth/le_scan/ScanManagerTest.java b/android/app/tests/unit/src/com/android/bluetooth/le_scan/ScanManagerTest.java index 97dfb0326f..b1804031b9 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/le_scan/ScanManagerTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/le_scan/ScanManagerTest.java @@ -85,8 +85,9 @@ import org.mockito.ArgumentCaptor; import org.mockito.Captor; import org.mockito.Mock; import org.mockito.Mockito; -import org.mockito.MockitoAnnotations; import org.mockito.Spy; +import org.mockito.junit.MockitoJUnit; +import org.mockito.junit.MockitoRule; import java.util.ArrayList; import java.util.List; @@ -125,8 +126,11 @@ public class ScanManagerTest { @Rule public final ServiceTestRule mServiceRule = new ServiceTestRule(); @Rule public final SetFlagsRule mSetFlagsRule = new SetFlagsRule(); + @Rule public MockitoRule mockitoRule = MockitoJUnit.rule(); + @Mock private AdapterService mAdapterService; @Mock private GattService mMockGattService; + @Mock private TransitionalScanHelper mMockScanHelper; @Mock private BluetoothAdapterProxy mBluetoothAdapterProxy; @Mock private LocationManager mLocationManager; @Spy private GattObjectsFactory mFactory = GattObjectsFactory.getInstance(); @@ -141,7 +145,6 @@ public class ScanManagerTest { @Before public void setUp() throws Exception { mTargetContext = InstrumentationRegistry.getTargetContext(); - MockitoAnnotations.initMocks(this); TestUtils.setAdapterService(mAdapterService); when(mAdapterService.getScanTimeoutMillis()) @@ -197,6 +200,7 @@ public class ScanManagerTest { mScanManager = new ScanManager( mMockGattService, + mMockScanHelper, mAdapterService, mBluetoothAdapterProxy, mTestLooper.getLooper()); @@ -208,7 +212,8 @@ public class ScanManagerTest { assertThat(mLatch).isNotNull(); mScanReportDelay = DEFAULT_SCAN_REPORT_DELAY_MS; - mMockAppScanStats = spy(new AppScanStats("Test", null, null, mMockGattService)); + mMockAppScanStats = + spy(new AppScanStats("Test", null, null, mMockGattService, mMockScanHelper)); } @After diff --git a/android/app/tests/unit/src/com/android/bluetooth/le_scan/TransitionalScanHelperTest.java b/android/app/tests/unit/src/com/android/bluetooth/le_scan/TransitionalScanHelperTest.java new file mode 100644 index 0000000000..45aff753b0 --- /dev/null +++ b/android/app/tests/unit/src/com/android/bluetooth/le_scan/TransitionalScanHelperTest.java @@ -0,0 +1,400 @@ +/* + * Copyright 2023 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.bluetooth.le_scan; + +import static com.google.common.truth.Truth.assertThat; + +import static org.mockito.ArgumentMatchers.anyInt; +import static org.mockito.Mockito.any; +import static org.mockito.Mockito.anyString; +import static org.mockito.Mockito.argThat; +import static org.mockito.Mockito.doReturn; +import static org.mockito.Mockito.doThrow; +import static org.mockito.Mockito.eq; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import android.bluetooth.BluetoothAdapter; +import android.bluetooth.BluetoothDevice; +import android.bluetooth.BluetoothProfile; +import android.bluetooth.le.IPeriodicAdvertisingCallback; +import android.bluetooth.le.IScannerCallback; +import android.bluetooth.le.ScanResult; +import android.bluetooth.le.ScanSettings; +import android.content.AttributionSource; +import android.content.Context; +import android.content.res.Resources; +import android.location.LocationManager; +import android.os.Binder; +import android.os.RemoteException; +import android.os.WorkSource; +import android.os.test.TestLooper; +import android.platform.test.flag.junit.SetFlagsRule; + +import androidx.test.InstrumentationRegistry; +import androidx.test.filters.SmallTest; +import androidx.test.rule.ServiceTestRule; +import androidx.test.runner.AndroidJUnit4; + +import com.android.bluetooth.TestUtils; +import com.android.bluetooth.btservice.AdapterService; +import com.android.bluetooth.btservice.CompanionManager; +import com.android.bluetooth.gatt.GattObjectsFactory; +import com.android.bluetooth.gatt.GattNativeInterface; + +import com.android.bluetooth.flags.Flags; + +import org.junit.After; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.ArgumentMatcher; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashSet; +import java.util.Set; + +/** Test cases for {@link TransitionalScanHelper}. */ +@SmallTest +@RunWith(AndroidJUnit4.class) +public class TransitionalScanHelperTest { + + private static final String REMOTE_DEVICE_ADDRESS = "00:00:00:00:00:00"; + + private TransitionalScanHelper mScanHelper; + @Mock private TransitionalScanHelper.ScannerMap mScannerMap; + + @SuppressWarnings("NonCanonicalType") + @Mock + private TransitionalScanHelper.ScannerMap.App mApp; + + @Mock private TransitionalScanHelper.PendingIntentInfo mPiInfo; + @Mock private PeriodicScanManager mPeriodicScanManager; + @Mock private ScanManager mScanManager; + + @Rule public final ServiceTestRule mServiceRule = new ServiceTestRule(); + @Rule public final SetFlagsRule mSetFlagsRule = new SetFlagsRule(); + + private BluetoothDevice mDevice; + private BluetoothAdapter mAdapter; + private AttributionSource mAttributionSource; + + @Mock private Resources mResources; + @Mock private AdapterService mAdapterService; + @Mock private GattObjectsFactory mFactory; + @Mock private GattNativeInterface mNativeInterface; + private CompanionManager mBtCompanionManager; + + @Before + public void setUp() throws Exception { + MockitoAnnotations.initMocks(this); + TestUtils.setAdapterService(mAdapterService); + + GattObjectsFactory.setInstanceForTesting(mFactory); + doReturn(mNativeInterface).when(mFactory).getNativeInterface(); + doReturn(mScanManager).when(mFactory).createScanManager(any(), any(), any(), any(), any()); + doReturn(mPeriodicScanManager).when(mFactory).createPeriodicScanManager(any()); + + mAdapter = BluetoothAdapter.getDefaultAdapter(); + mAttributionSource = mAdapter.getAttributionSource(); + mDevice = BluetoothAdapter.getDefaultAdapter().getRemoteDevice(REMOTE_DEVICE_ADDRESS); + + when(mAdapterService.getResources()).thenReturn(mResources); + when(mResources.getInteger(anyInt())).thenReturn(0); + when(mAdapterService.getSharedPreferences(anyString(), anyInt())) + .thenReturn( + InstrumentationRegistry.getTargetContext() + .getSharedPreferences( + "GattServiceTestPrefs", Context.MODE_PRIVATE)); + + TestUtils.mockGetSystemService( + mAdapterService, Context.LOCATION_SERVICE, LocationManager.class); + + mBtCompanionManager = new CompanionManager(mAdapterService, null); + doReturn(mBtCompanionManager).when(mAdapterService).getCompanionManager(); + + TestLooper testLooper = new TestLooper(); + testLooper.startAutoDispatch(); + + mScanHelper = + new TransitionalScanHelper(InstrumentationRegistry.getTargetContext(), () -> false); + mScanHelper.start(testLooper.getLooper()); + + mScanHelper.setScannerMap(mScannerMap); + } + + @After + public void tearDown() throws Exception { + mScanHelper.stop(); + mScanHelper = null; + + TestUtils.clearAdapterService(mAdapterService); + GattObjectsFactory.setInstanceForTesting(null); + } + + @Test + public void testParseBatchTimestamp() { + long timestampNanos = mScanHelper.parseTimestampNanos(new byte[] {-54, 7}); + assertThat(timestampNanos).isEqualTo(99700000000L); + } + + @Test + public void continuePiStartScan() { + int scannerId = 1; + + mPiInfo.settings = new ScanSettings.Builder().build(); + mApp.info = mPiInfo; + + AppScanStats appScanStats = mock(AppScanStats.class); + doReturn(appScanStats).when(mScannerMap).getAppScanStatsById(scannerId); + + mScanHelper.continuePiStartScan(scannerId, mApp); + + verify(appScanStats) + .recordScanStart(mPiInfo.settings, mPiInfo.filters, false, false, scannerId); + verify(mScanManager).startScan(any()); + } + + @Test + public void continuePiStartScanCheckUid() { + int scannerId = 1; + + mPiInfo.settings = new ScanSettings.Builder().build(); + mPiInfo.callingUid = 123; + mApp.info = mPiInfo; + + AppScanStats appScanStats = mock(AppScanStats.class); + doReturn(appScanStats).when(mScannerMap).getAppScanStatsById(scannerId); + + mScanHelper.continuePiStartScan(scannerId, mApp); + + verify(appScanStats) + .recordScanStart(mPiInfo.settings, mPiInfo.filters, false, false, scannerId); + verify(mScanManager) + .startScan( + argThat( + new ArgumentMatcher<ScanClient>() { + @Override + public boolean matches(ScanClient client) { + return mPiInfo.callingUid == client.appUid; + } + })); + } + + @Test + public void onBatchScanReportsInternal_deliverBatchScan() throws RemoteException { + int status = 1; + int scannerId = 2; + int reportType = ScanManager.SCAN_RESULT_TYPE_FULL; + int numRecords = 1; + byte[] recordData = + new byte[] { + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x00, 0x00, 0x00, 0x00 + }; + + Set<ScanClient> scanClientSet = new HashSet<>(); + ScanClient scanClient = new ScanClient(scannerId); + scanClient.associatedDevices = new ArrayList<>(); + scanClient.associatedDevices.add("02:00:00:00:00:00"); + scanClient.scannerId = scannerId; + scanClientSet.add(scanClient); + doReturn(scanClientSet).when(mScanManager).getFullBatchScanQueue(); + doReturn(mApp).when(mScannerMap).getById(scanClient.scannerId); + + mScanHelper.onBatchScanReportsInternal( + status, scannerId, reportType, numRecords, recordData); + verify(mScanManager).callbackDone(scannerId, status); + + reportType = ScanManager.SCAN_RESULT_TYPE_TRUNCATED; + recordData = + new byte[] { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x06, 0x04, 0x02, 0x02, 0x00, 0x00, 0x02 + }; + doReturn(scanClientSet).when(mScanManager).getBatchScanQueue(); + IScannerCallback callback = mock(IScannerCallback.class); + mApp.callback = callback; + + mScanHelper.onBatchScanReportsInternal( + status, scannerId, reportType, numRecords, recordData); + verify(callback).onBatchScanResults(any()); + } + + @Test + public void enforceReportDelayFloor() { + long reportDelayFloorHigher = TransitionalScanHelper.DEFAULT_REPORT_DELAY_FLOOR + 1; + ScanSettings scanSettings = + new ScanSettings.Builder().setReportDelay(reportDelayFloorHigher).build(); + + ScanSettings newScanSettings = mScanHelper.enforceReportDelayFloor(scanSettings); + + assertThat(newScanSettings.getReportDelayMillis()) + .isEqualTo(scanSettings.getReportDelayMillis()); + + ScanSettings scanSettingsFloor = new ScanSettings.Builder().setReportDelay(1).build(); + + ScanSettings newScanSettingsFloor = mScanHelper.enforceReportDelayFloor(scanSettingsFloor); + + assertThat(newScanSettingsFloor.getReportDelayMillis()) + .isEqualTo(TransitionalScanHelper.DEFAULT_REPORT_DELAY_FLOOR); + } + + @Test + public void registerScanner() throws Exception { + IScannerCallback callback = mock(IScannerCallback.class); + WorkSource workSource = mock(WorkSource.class); + + AppScanStats appScanStats = mock(AppScanStats.class); + doReturn(appScanStats).when(mScannerMap).getAppScanStatsByUid(Binder.getCallingUid()); + + mScanHelper.registerScanner(callback, workSource, mAttributionSource); + verify(mScannerMap) + .add(any(), eq(workSource), eq(callback), eq(null), any(), eq(mScanHelper)); + verify(mScanManager).registerScanner(any()); + } + + @Test + public void flushPendingBatchResults() { + int scannerId = 3; + + mScanHelper.flushPendingBatchResults(scannerId, mAttributionSource); + verify(mScanManager).flushBatchScanResults(new ScanClient(scannerId)); + } + + @Test + public void onScanResult_remoteException_clientDied() throws Exception { + mSetFlagsRule.enableFlags(Flags.FLAG_LE_SCAN_FIX_REMOTE_EXCEPTION); + int scannerId = 1; + + int eventType = 0; + int addressType = 0; + String address = "02:00:00:00:00:00"; + int primaryPhy = 0; + int secondPhy = 0; + int advertisingSid = 0; + int txPower = 0; + int rssi = 0; + int periodicAdvInt = 0; + byte[] advData = new byte[0]; + + ScanClient scanClient = new ScanClient(scannerId); + scanClient.scannerId = scannerId; + scanClient.hasNetworkSettingsPermission = true; + scanClient.settings = + new ScanSettings.Builder() + .setCallbackType(ScanSettings.CALLBACK_TYPE_ALL_MATCHES) + .setLegacy(false) + .build(); + + AppScanStats appScanStats = mock(AppScanStats.class); + IScannerCallback callback = mock(IScannerCallback.class); + + mApp.callback = callback; + mApp.appScanStats = appScanStats; + Set<ScanClient> scanClientSet = Collections.singleton(scanClient); + + doReturn(address).when(mAdapterService).getIdentityAddress(anyString()); + doReturn(scanClientSet).when(mScanManager).getRegularScanQueue(); + doReturn(mApp).when(mScannerMap).getById(scanClient.scannerId); + doReturn(appScanStats).when(mScannerMap).getAppScanStatsById(scanClient.scannerId); + + // Simulate remote client crash + doThrow(new RemoteException()).when(callback).onScanResult(any()); + + mScanHelper.onScanResult( + eventType, + addressType, + address, + primaryPhy, + secondPhy, + advertisingSid, + txPower, + rssi, + periodicAdvInt, + advData, + address); + + assertThat(scanClient.appDied).isTrue(); + verify(appScanStats).recordScanStop(scannerId); + } + + @Test + public void registerSync() { + ScanResult scanResult = new ScanResult(mDevice, 1, 2, 3, 4, 5, 6, 7, null, 8); + int skip = 1; + int timeout = 2; + IPeriodicAdvertisingCallback callback = mock(IPeriodicAdvertisingCallback.class); + + mScanHelper.registerSync(scanResult, skip, timeout, callback, mAttributionSource); + verify(mPeriodicScanManager).startSync(scanResult, skip, timeout, callback); + } + + @Test + public void transferSync() { + int serviceData = 1; + int syncHandle = 2; + + mScanHelper.transferSync(mDevice, serviceData, syncHandle, mAttributionSource); + verify(mPeriodicScanManager).transferSync(mDevice, serviceData, syncHandle); + } + + @Test + public void transferSetInfo() { + int serviceData = 1; + int advHandle = 2; + IPeriodicAdvertisingCallback callback = mock(IPeriodicAdvertisingCallback.class); + + mScanHelper.transferSetInfo(mDevice, serviceData, advHandle, callback, mAttributionSource); + verify(mPeriodicScanManager).transferSetInfo(mDevice, serviceData, advHandle, callback); + } + + @Test + public void unregisterSync() { + IPeriodicAdvertisingCallback callback = mock(IPeriodicAdvertisingCallback.class); + + mScanHelper.unregisterSync(callback, mAttributionSource); + verify(mPeriodicScanManager).stopSync(callback); + } + + @Test + public void getCurrentUsedTrackingAdvertisement() { + mScanHelper.getCurrentUsedTrackingAdvertisement(); + verify(mScanManager).getCurrentUsedTrackingAdvertisement(); + } + + @Test + public void cleanUp_doesNotCrash() { + mScanHelper.cleanup(); + } + + @Test + public void profileConnectionStateChanged_notifyScanManager() { + mScanHelper.notifyProfileConnectionStateChange( + BluetoothProfile.A2DP, + BluetoothProfile.STATE_CONNECTING, + BluetoothProfile.STATE_CONNECTED); + verify(mScanManager) + .handleBluetoothProfileConnectionStateChanged( + BluetoothProfile.A2DP, + BluetoothProfile.STATE_CONNECTING, + BluetoothProfile.STATE_CONNECTED); + } +} diff --git a/android/app/tests/unit/src/com/android/bluetooth/map/BluetoothMapContentObserverTest.java b/android/app/tests/unit/src/com/android/bluetooth/map/BluetoothMapContentObserverTest.java index 8d052d2455..3607fbb035 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/map/BluetoothMapContentObserverTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/map/BluetoothMapContentObserverTest.java @@ -53,12 +53,14 @@ import com.google.android.mms.pdu.PduHeaders; import org.junit.After; import org.junit.Assert; import org.junit.Before; +import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; import org.mockito.Mockito; -import org.mockito.MockitoAnnotations; import org.mockito.Spy; +import org.mockito.junit.MockitoJUnit; +import org.mockito.junit.MockitoRule; import java.io.IOException; import java.text.SimpleDateFormat; @@ -116,6 +118,8 @@ public class BluetoothMapContentObserverTest { static final int TEST_PRIORITY = 1; static final int TEST_LAST_ONLINE = 1; + @Rule public MockitoRule mockitoRule = MockitoJUnit.rule(); + @Mock private BluetoothMnsObexClient mClient; @Mock @@ -171,7 +175,6 @@ public class BluetoothMapContentObserverTest { @Before public void setUp() throws Exception { - MockitoAnnotations.initMocks(this); BluetoothMethodProxy.setInstanceForTesting(mMapMethodProxy); if (Looper.myLooper() == null) { Looper.prepare(); diff --git a/android/app/tests/unit/src/com/android/bluetooth/map/BluetoothMapContentTest.java b/android/app/tests/unit/src/com/android/bluetooth/map/BluetoothMapContentTest.java index 71f2f5af38..20237fe896 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/map/BluetoothMapContentTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/map/BluetoothMapContentTest.java @@ -54,11 +54,13 @@ import com.google.android.mms.pdu.PduHeaders; import org.junit.After; import org.junit.Before; +import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; -import org.mockito.MockitoAnnotations; import org.mockito.Spy; +import org.mockito.junit.MockitoJUnit; +import org.mockito.junit.MockitoRule; import java.io.ByteArrayInputStream; import java.io.FileDescriptor; @@ -111,6 +113,8 @@ public class BluetoothMapContentTest { private static final String TEST_RECEPTION_STATUS = "complete"; private static final String TEST_EMAIL = "test@google.com"; + @Rule public MockitoRule mockitoRule = MockitoJUnit.rule(); + @Mock private BluetoothMapAccountItem mAccountItem; @Mock @@ -134,7 +138,6 @@ public class BluetoothMapContentTest { @Before public void setUp() { - MockitoAnnotations.initMocks(this); BluetoothMethodProxy.setInstanceForTesting(mMapMethodProxy); mContent = new BluetoothMapContent(mContext, mAccountItem, mMasInstance); diff --git a/android/app/tests/unit/src/com/android/bluetooth/map/BluetoothMapConvoContactElementTest.java b/android/app/tests/unit/src/com/android/bluetooth/map/BluetoothMapConvoContactElementTest.java index 35c4a3e2e5..68d0e0d92e 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/map/BluetoothMapConvoContactElementTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/map/BluetoothMapConvoContactElementTest.java @@ -26,11 +26,12 @@ import androidx.test.runner.AndroidJUnit4; import com.android.bluetooth.SignedLongLong; -import org.junit.Before; +import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; -import org.mockito.MockitoAnnotations; +import org.mockito.junit.MockitoJUnit; +import org.mockito.junit.MockitoRule; import org.xmlpull.v1.XmlPullParser; import org.xmlpull.v1.XmlPullParserFactory; import org.xmlpull.v1.XmlSerializer; @@ -53,14 +54,11 @@ public class BluetoothMapConvoContactElementTest { private final SimpleDateFormat format = new SimpleDateFormat("yyyyMMdd'T'HHmmss"); + @Rule public MockitoRule mockitoRule = MockitoJUnit.rule(); + @Mock private MapContact mMapContact; - @Before - public void setUp() throws Exception { - MockitoAnnotations.initMocks(this); - } - @Test public void constructorWithArguments() { BluetoothMapConvoContactElement contactElement = @@ -201,4 +199,4 @@ public class BluetoothMapConvoContactElementTest { assertThat(contactElement.compareTo(contactElementSameLastActivity)).isEqualTo(0); } -}
\ No newline at end of file +} diff --git a/android/app/tests/unit/src/com/android/bluetooth/map/BluetoothMapMasInstanceTest.java b/android/app/tests/unit/src/com/android/bluetooth/map/BluetoothMapMasInstanceTest.java index 34105afb67..b985cd3a4a 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/map/BluetoothMapMasInstanceTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/map/BluetoothMapMasInstanceTest.java @@ -26,10 +26,12 @@ import androidx.test.filters.SmallTest; import androidx.test.runner.AndroidJUnit4; import org.junit.Before; +import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; -import org.mockito.MockitoAnnotations; +import org.mockito.junit.MockitoJUnit; +import org.mockito.junit.MockitoRule; @SmallTest @RunWith(AndroidJUnit4.class) @@ -47,6 +49,8 @@ public class BluetoothMapMasInstanceTest { private BluetoothMapAccountItem mAccountItem; + @Rule public MockitoRule mockitoRule = MockitoJUnit.rule(); + @Mock private Context mContext; @Mock @@ -54,7 +58,6 @@ public class BluetoothMapMasInstanceTest { @Before public void setUp() { - MockitoAnnotations.initMocks(this); mAccountItem = BluetoothMapAccountItem.create(TEST_ID, TEST_NAME, TEST_PACKAGE_NAME, TEST_PROVIDER_AUTHORITY, TEST_DRAWABLE, TEST_TYPE, TEST_UCI, TEST_UCI_PREFIX); diff --git a/android/app/tests/unit/src/com/android/bluetooth/map/BluetoothMapObexServerTest.java b/android/app/tests/unit/src/com/android/bluetooth/map/BluetoothMapObexServerTest.java index 5aedef3c26..40503a775f 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/map/BluetoothMapObexServerTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/map/BluetoothMapObexServerTest.java @@ -42,11 +42,13 @@ import com.android.bluetooth.mapapi.BluetoothMapContract; import com.android.obex.ResponseCodes; import org.junit.Before; +import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; -import org.mockito.MockitoAnnotations; import org.mockito.Spy; +import org.mockito.junit.MockitoJUnit; +import org.mockito.junit.MockitoRule; @SmallTest @RunWith(AndroidJUnit4.class) @@ -67,6 +69,8 @@ public class BluetoothMapObexServerTest { private BluetoothMapObexServer mObexServer; private BluetoothMapAppParams mParams; + @Rule public MockitoRule mockitoRule = MockitoJUnit.rule(); + @Mock private Context mContext; @Mock @@ -80,7 +84,6 @@ public class BluetoothMapObexServerTest { @Before public void setUp() throws Exception { - MockitoAnnotations.initMocks(this); BluetoothMethodProxy.setInstanceForTesting(mMapMethodProxy); doReturn(mProviderClient).when( mMapMethodProxy).contentResolverAcquireUnstableContentProviderClient(any(), any()); diff --git a/android/app/tests/unit/src/com/android/bluetooth/map/BluetoothMapServiceBinderTest.java b/android/app/tests/unit/src/com/android/bluetooth/map/BluetoothMapServiceBinderTest.java index 498fefa79c..e87c55b7d9 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/map/BluetoothMapServiceBinderTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/map/BluetoothMapServiceBinderTest.java @@ -28,16 +28,20 @@ import androidx.test.runner.AndroidJUnit4; import com.android.bluetooth.x.com.android.modules.utils.SynchronousResultReceiver; import org.junit.Before; +import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; -import org.mockito.MockitoAnnotations; +import org.mockito.junit.MockitoJUnit; +import org.mockito.junit.MockitoRule; @SmallTest @RunWith(AndroidJUnit4.class) public class BluetoothMapServiceBinderTest { private static final String REMOTE_DEVICE_ADDRESS = "00:00:00:00:00:00"; + @Rule public MockitoRule mockitoRule = MockitoJUnit.rule(); + @Mock private BluetoothMapService mService; @@ -47,7 +51,6 @@ public class BluetoothMapServiceBinderTest { @Before public void setUp() throws Exception { - MockitoAnnotations.initMocks(this); mRemoteDevice = BluetoothAdapter.getDefaultAdapter().getRemoteDevice(REMOTE_DEVICE_ADDRESS); mBinder = new BluetoothMapService.BluetoothMapBinder(mService); } diff --git a/android/app/tests/unit/src/com/android/bluetooth/map/BluetoothMapServiceTest.java b/android/app/tests/unit/src/com/android/bluetooth/map/BluetoothMapServiceTest.java index 5989177b80..009d79d494 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/map/BluetoothMapServiceTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/map/BluetoothMapServiceTest.java @@ -48,10 +48,12 @@ import com.android.bluetooth.btservice.storage.DatabaseManager; import org.junit.After; import org.junit.Before; +import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; -import org.mockito.MockitoAnnotations; +import org.mockito.junit.MockitoJUnit; +import org.mockito.junit.MockitoRule; @MediumTest @RunWith(AndroidJUnit4.class) @@ -62,6 +64,7 @@ public class BluetoothMapServiceTest { private BluetoothAdapter mAdapter = null; private BluetoothDevice mRemoteDevice; + @Rule public MockitoRule mockitoRule = MockitoJUnit.rule(); @Mock private AdapterService mAdapterService; @Mock private DatabaseManager mDatabaseManager; @@ -69,7 +72,6 @@ public class BluetoothMapServiceTest { @Before public void setUp() throws Exception { Context targetContext = InstrumentationRegistry.getTargetContext(); - MockitoAnnotations.initMocks(this); TestUtils.setAdapterService(mAdapterService); doReturn(mDatabaseManager).when(mAdapterService).getDatabase(); mService = new BluetoothMapService(targetContext); diff --git a/android/app/tests/unit/src/com/android/bluetooth/map/BluetoothMapSmsPduTest.java b/android/app/tests/unit/src/com/android/bluetooth/map/BluetoothMapSmsPduTest.java index f8bed9641c..ab6f9cf469 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/map/BluetoothMapSmsPduTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/map/BluetoothMapSmsPduTest.java @@ -33,10 +33,12 @@ import com.android.bluetooth.map.BluetoothMapSmsPdu.SmsPdu; import org.junit.Assume; import org.junit.Before; +import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; -import org.mockito.MockitoAnnotations; +import org.mockito.junit.MockitoJUnit; +import org.mockito.junit.MockitoRule; import java.io.ByteArrayInputStream; import java.io.InputStream; @@ -57,6 +59,8 @@ public class BluetoothMapSmsPduTest { private int TEST_LANGUAGE_TABLE; private SmsManager mSmsManager = SmsManager.getDefault(); + @Rule public MockitoRule mockitoRule = MockitoJUnit.rule(); + @Mock private Context mTargetContext; @Mock @@ -64,7 +68,6 @@ public class BluetoothMapSmsPduTest { @Before public void setUp() throws Exception { - MockitoAnnotations.initMocks(this); when(mTargetContext.getSystemServiceName(TelephonyManager.class)).thenReturn( "TELEPHONY_SERVICE"); when(mTargetContext.getSystemService("TELEPHONY_SERVICE")).thenReturn(mTelephonyManager); diff --git a/android/app/tests/unit/src/com/android/bluetooth/map/SmsMmsContactsTest.java b/android/app/tests/unit/src/com/android/bluetooth/map/SmsMmsContactsTest.java index c65053e81c..38f9ca46b2 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/map/SmsMmsContactsTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/map/SmsMmsContactsTest.java @@ -31,11 +31,13 @@ import com.android.bluetooth.BluetoothMethodProxy; import org.junit.After; import org.junit.Before; +import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; -import org.mockito.MockitoAnnotations; import org.mockito.Spy; +import org.mockito.junit.MockitoJUnit; +import org.mockito.junit.MockitoRule; @SmallTest @RunWith(AndroidJUnit4.class) @@ -46,6 +48,8 @@ public class SmsMmsContactsTest { private static final String TEST_PHONE = "test_phone"; private static final String TEST_CONTACT_NAME_FILTER = "test_contact_name_filter"; + @Rule public MockitoRule mockitoRule = MockitoJUnit.rule(); + @Mock private ContentResolver mResolver; @Spy @@ -55,7 +59,6 @@ public class SmsMmsContactsTest { @Before public void setUp() throws Exception { - MockitoAnnotations.initMocks(this); BluetoothMethodProxy.setInstanceForTesting(mMapMethodProxy); mContacts = new SmsMmsContacts(); } diff --git a/android/app/tests/unit/src/com/android/bluetooth/mapapi/BluetoothMapEmailProviderTest.java b/android/app/tests/unit/src/com/android/bluetooth/mapapi/BluetoothMapEmailProviderTest.java index 0ef6e4e95a..c109dcceb4 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/mapapi/BluetoothMapEmailProviderTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/mapapi/BluetoothMapEmailProviderTest.java @@ -36,10 +36,12 @@ import androidx.test.InstrumentationRegistry; import androidx.test.runner.AndroidJUnit4; import org.junit.Before; +import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; -import org.mockito.MockitoAnnotations; import org.mockito.Spy; +import org.mockito.junit.MockitoJUnit; +import org.mockito.junit.MockitoRule; import java.io.FileInputStream; import java.io.FileOutputStream; @@ -55,12 +57,13 @@ public class BluetoothMapEmailProviderTest { private Context mContext; + @Rule public MockitoRule mockitoRule = MockitoJUnit.rule(); + @Spy private BluetoothMapEmailProvider mProvider = new TestBluetoothMapEmailProvider(); @Before public void setUp() throws Exception { - MockitoAnnotations.initMocks(this); mContext = InstrumentationRegistry.getTargetContext(); } diff --git a/android/app/tests/unit/src/com/android/bluetooth/mapapi/BluetoothMapIMProviderTest.java b/android/app/tests/unit/src/com/android/bluetooth/mapapi/BluetoothMapIMProviderTest.java index f9e6bb35c8..cae5876491 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/mapapi/BluetoothMapIMProviderTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/mapapi/BluetoothMapIMProviderTest.java @@ -41,11 +41,13 @@ import androidx.test.InstrumentationRegistry; import androidx.test.runner.AndroidJUnit4; import org.junit.Before; +import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mockito; -import org.mockito.MockitoAnnotations; import org.mockito.Spy; +import org.mockito.junit.MockitoJUnit; +import org.mockito.junit.MockitoRule; import java.time.Instant; import java.util.AbstractMap; @@ -66,12 +68,13 @@ public class BluetoothMapIMProviderTest { private Context mContext; + @Rule public MockitoRule mockitoRule = MockitoJUnit.rule(); + @Spy private BluetoothMapIMProvider mProvider = new TestBluetoothMapIMProvider(); @Before public void setUp() throws Exception { - MockitoAnnotations.initMocks(this); mContext = InstrumentationRegistry.getTargetContext(); } diff --git a/android/app/tests/unit/src/com/android/bluetooth/mapclient/MapClientContentTest.java b/android/app/tests/unit/src/com/android/bluetooth/mapclient/MapClientContentTest.java index 5c735c9d45..f58e0992ca 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/mapclient/MapClientContentTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/mapclient/MapClientContentTest.java @@ -55,12 +55,14 @@ import com.android.vcard.VCardProperty; import org.junit.After; import org.junit.Assert; import org.junit.Before; +import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.ArgumentCaptor; import org.mockito.Mock; import org.mockito.Mockito; -import org.mockito.MockitoAnnotations; +import org.mockito.junit.MockitoJUnit; +import org.mockito.junit.MockitoRule; import java.util.Arrays; import java.util.HashMap; @@ -92,6 +94,8 @@ public class MapClientContentTest { private MapClientContent mMapClientContent; + @Rule public MockitoRule mockitoRule = MockitoJUnit.rule(); + @Mock private AdapterService mAdapterService; @Mock @@ -115,7 +119,6 @@ public class MapClientContentTest { @Before public void setUp() throws Exception { - MockitoAnnotations.initMocks(this); mMockSmsContentProvider = new FakeContentProvider(mMockContext); mMockMmsContentProvider = new FakeContentProvider(mMockContext); diff --git a/android/app/tests/unit/src/com/android/bluetooth/mapclient/MapClientServiceBinderTest.java b/android/app/tests/unit/src/com/android/bluetooth/mapclient/MapClientServiceBinderTest.java index 1604459c36..e95088f583 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/mapclient/MapClientServiceBinderTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/mapclient/MapClientServiceBinderTest.java @@ -29,16 +29,20 @@ import androidx.test.runner.AndroidJUnit4; import com.android.bluetooth.x.com.android.modules.utils.SynchronousResultReceiver; import org.junit.Before; +import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; -import org.mockito.MockitoAnnotations; +import org.mockito.junit.MockitoJUnit; +import org.mockito.junit.MockitoRule; @MediumTest @RunWith(AndroidJUnit4.class) public class MapClientServiceBinderTest { private static final String REMOTE_DEVICE_ADDRESS = "00:00:00:00:00:00"; + @Rule public MockitoRule mockitoRule = MockitoJUnit.rule(); + @Mock private MapClientService mService; @@ -48,7 +52,6 @@ public class MapClientServiceBinderTest { @Before public void setUp() throws Exception { - MockitoAnnotations.initMocks(this); mRemoteDevice = BluetoothAdapter.getDefaultAdapter().getRemoteDevice(REMOTE_DEVICE_ADDRESS); mBinder = new MapClientService.Binder(mService); } diff --git a/android/app/tests/unit/src/com/android/bluetooth/mapclient/MapClientServiceTest.java b/android/app/tests/unit/src/com/android/bluetooth/mapclient/MapClientServiceTest.java index 0622a7eba3..c24df8b84d 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/mapclient/MapClientServiceTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/mapclient/MapClientServiceTest.java @@ -44,16 +44,19 @@ import com.android.bluetooth.btservice.storage.DatabaseManager; import org.junit.After; import org.junit.Before; +import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; -import org.mockito.MockitoAnnotations; +import org.mockito.junit.MockitoJUnit; +import org.mockito.junit.MockitoRule; @MediumTest @RunWith(AndroidJUnit4.class) public class MapClientServiceTest { private static final String REMOTE_DEVICE_ADDRESS = "00:00:00:00:00:00"; + @Rule public MockitoRule mockitoRule = MockitoJUnit.rule(); @Mock private AdapterService mAdapterService; @Mock private DatabaseManager mDatabaseManager; @@ -66,7 +69,6 @@ public class MapClientServiceTest { @Before public void setUp() throws Exception { Context targetContext = InstrumentationRegistry.getTargetContext(); - MockitoAnnotations.initMocks(this); TestUtils.setAdapterService(mAdapterService); doReturn(mDatabaseManager).when(mAdapterService).getDatabase(); diff --git a/android/app/tests/unit/src/com/android/bluetooth/mapclient/MapClientStateMachineTest.java b/android/app/tests/unit/src/com/android/bluetooth/mapclient/MapClientStateMachineTest.java index baadbd75e7..2c18e366ff 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/mapclient/MapClientStateMachineTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/mapclient/MapClientStateMachineTest.java @@ -74,7 +74,8 @@ import org.junit.runner.RunWith; import org.mockito.ArgumentCaptor; import org.mockito.Mock; import org.mockito.Mockito; -import org.mockito.MockitoAnnotations; +import org.mockito.junit.MockitoJUnit; +import org.mockito.junit.MockitoRule; import java.time.Instant; import java.util.ArrayList; @@ -125,6 +126,8 @@ public class MapClientStateMachineTest { private Context mTargetContext; private Handler mHandler; private ArgumentCaptor<Intent> mIntentArgument = ArgumentCaptor.forClass(Intent.class); + @Rule public MockitoRule mockitoRule = MockitoJUnit.rule(); + @Mock private AdapterService mAdapterService; @Mock @@ -202,7 +205,6 @@ public class MapClientStateMachineTest { @Before public void setUp() throws Exception { mTargetContext = InstrumentationRegistry.getTargetContext(); - MockitoAnnotations.initMocks(this); TestUtils.setAdapterService(mAdapterService); mIsAdapterServiceSet = true; mMockContentProvider = new MockSmsContentProvider(); diff --git a/android/app/tests/unit/src/com/android/bluetooth/mapclient/MapClientTest.java b/android/app/tests/unit/src/com/android/bluetooth/mapclient/MapClientTest.java index ab5f97b95d..e36a25ab8d 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/mapclient/MapClientTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/mapclient/MapClientTest.java @@ -37,10 +37,12 @@ import com.android.bluetooth.btservice.storage.DatabaseManager; import org.junit.After; import org.junit.Assert; import org.junit.Before; +import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; -import org.mockito.MockitoAnnotations; +import org.mockito.junit.MockitoJUnit; +import org.mockito.junit.MockitoRule; import java.util.ArrayList; import java.util.List; @@ -56,6 +58,8 @@ public class MapClientTest { private boolean mIsAdapterServiceSet; private boolean mIsMapClientServiceStarted; + @Rule public MockitoRule mockitoRule = MockitoJUnit.rule(); + @Mock private AdapterService mAdapterService; @Mock private MnsService mMockMnsService; @Mock private DatabaseManager mDatabaseManager; @@ -64,7 +68,6 @@ public class MapClientTest { @Before public void setUp() throws Exception { mTargetContext = InstrumentationRegistry.getTargetContext(); - MockitoAnnotations.initMocks(this); TestUtils.setAdapterService(mAdapterService); mIsAdapterServiceSet = true; when(mAdapterService.getDatabase()).thenReturn(mDatabaseManager); diff --git a/android/app/tests/unit/src/com/android/bluetooth/mapclient/MnsObexServerTest.java b/android/app/tests/unit/src/com/android/bluetooth/mapclient/MnsObexServerTest.java index fb9d899cf3..ffef488313 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/mapclient/MnsObexServerTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/mapclient/MnsObexServerTest.java @@ -31,10 +31,12 @@ import com.android.obex.Operation; import com.android.obex.ResponseCodes; import org.junit.Before; +import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; -import org.mockito.MockitoAnnotations; +import org.mockito.junit.MockitoJUnit; +import org.mockito.junit.MockitoRule; import java.io.ByteArrayInputStream; import java.io.DataInputStream; @@ -43,6 +45,8 @@ import java.io.DataInputStream; @RunWith(AndroidJUnit4.class) public class MnsObexServerTest { + @Rule public MockitoRule mockitoRule = MockitoJUnit.rule(); + @Mock MceStateMachine mStateMachine; @@ -50,7 +54,6 @@ public class MnsObexServerTest { @Before public void setUp() throws Exception { - MockitoAnnotations.initMocks(this); mServer = new MnsObexServer(mStateMachine, null); } diff --git a/android/app/tests/unit/src/com/android/bluetooth/mcp/McpServiceTest.java b/android/app/tests/unit/src/com/android/bluetooth/mcp/McpServiceTest.java index 5c77c88ba5..ceb34661f2 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/mcp/McpServiceTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/mcp/McpServiceTest.java @@ -34,10 +34,12 @@ import com.android.bluetooth.btservice.AdapterService; import org.junit.After; import org.junit.Assert; import org.junit.Before; +import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; -import org.mockito.MockitoAnnotations; +import org.mockito.junit.MockitoJUnit; +import org.mockito.junit.MockitoRule; @MediumTest @RunWith(AndroidJUnit4.class) @@ -46,6 +48,8 @@ public class McpServiceTest { private McpService mMcpService; private Context mTargetContext; + @Rule public MockitoRule mockitoRule = MockitoJUnit.rule(); + @Mock private AdapterService mAdapterService; @Mock @@ -60,7 +64,6 @@ public class McpServiceTest { Looper.prepare(); } - MockitoAnnotations.initMocks(this); TestUtils.setAdapterService(mAdapterService); mAdapter = BluetoothAdapter.getDefaultAdapter(); diff --git a/android/app/tests/unit/src/com/android/bluetooth/mcp/MediaControlGattServiceTest.java b/android/app/tests/unit/src/com/android/bluetooth/mcp/MediaControlGattServiceTest.java index 6f16c76557..f57c002c56 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/mcp/MediaControlGattServiceTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/mcp/MediaControlGattServiceTest.java @@ -48,7 +48,8 @@ import org.junit.runner.RunWith; import org.mockito.ArgumentCaptor; import org.mockito.Captor; import org.mockito.Mock; -import org.mockito.MockitoAnnotations; +import org.mockito.junit.MockitoJUnit; +import org.mockito.junit.MockitoRule; import java.nio.ByteBuffer; import java.nio.ByteOrder; @@ -73,6 +74,8 @@ public class MediaControlGattServiceTest { private MediaControlGattService mMcpService; + @Rule public MockitoRule mockitoRule = MockitoJUnit.rule(); + @Mock private AdapterService mAdapterService; @Mock private MediaControlGattService.BluetoothGattServerProxy mMockGattServer; @Mock private McpService mMockMcpService; @@ -88,7 +91,6 @@ public class MediaControlGattServiceTest { Looper.prepare(); } - MockitoAnnotations.initMocks(this); TestUtils.setAdapterService(mAdapterService); mAdapter = BluetoothAdapter.getDefaultAdapter(); diff --git a/android/app/tests/unit/src/com/android/bluetooth/mcp/MediaControlProfileTest.java b/android/app/tests/unit/src/com/android/bluetooth/mcp/MediaControlProfileTest.java index e230378e3e..7ce0374564 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/mcp/MediaControlProfileTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/mcp/MediaControlProfileTest.java @@ -43,12 +43,14 @@ import com.android.bluetooth.btservice.AdapterService; import org.junit.After; import org.junit.Assert; import org.junit.Before; +import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.ArgumentCaptor; import org.mockito.Captor; import org.mockito.Mock; -import org.mockito.MockitoAnnotations; +import org.mockito.junit.MockitoJUnit; +import org.mockito.junit.MockitoRule; import java.util.ArrayList; import java.util.HashMap; @@ -71,6 +73,8 @@ public class MediaControlProfileTest { private CharSequence charSequence = "TestPlayer"; private MediaControlServiceCallbacks mMcpServiceCallbacks; + @Rule public MockitoRule mockitoRule = MockitoJUnit.rule(); + @Mock private AdapterService mAdapterService; @Mock private MediaData mMockMediaData; @Mock private MediaPlayerList mMockMediaPlayerList; @@ -94,7 +98,6 @@ public class MediaControlProfileTest { mTargetContext = InstrumentationRegistry.getTargetContext(); MediaControlProfile.ListCallback listCallback; - MockitoAnnotations.initMocks(this); TestUtils.setAdapterService(mAdapterService); mAdapter = BluetoothAdapter.getDefaultAdapter(); diff --git a/android/app/tests/unit/src/com/android/bluetooth/opp/BluetoothOppBtEnableActivityTest.java b/android/app/tests/unit/src/com/android/bluetooth/opp/BluetoothOppBtEnableActivityTest.java index 7156c70804..08f539de2d 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/opp/BluetoothOppBtEnableActivityTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/opp/BluetoothOppBtEnableActivityTest.java @@ -42,7 +42,6 @@ import org.junit.After; import org.junit.Before; import org.junit.Rule; import org.junit.Test; -import org.mockito.MockitoAnnotations; public class BluetoothOppBtEnableActivityTest { @@ -56,7 +55,6 @@ public class BluetoothOppBtEnableActivityTest { @Before public void setUp() throws Exception { - MockitoAnnotations.initMocks(this); mTargetContext = InstrumentationRegistry.getInstrumentation().getTargetContext(); mIntent = new Intent(); mIntent.setClass(mTargetContext, BluetoothOppBtEnableActivity.class); diff --git a/android/app/tests/unit/src/com/android/bluetooth/opp/BluetoothOppBtEnablingActivityTest.java b/android/app/tests/unit/src/com/android/bluetooth/opp/BluetoothOppBtEnablingActivityTest.java index c4abf9a292..07b634279f 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/opp/BluetoothOppBtEnablingActivityTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/opp/BluetoothOppBtEnablingActivityTest.java @@ -48,13 +48,16 @@ import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mockito; -import org.mockito.MockitoAnnotations; import org.mockito.Spy; +import org.mockito.junit.MockitoJUnit; +import org.mockito.junit.MockitoRule; import java.util.concurrent.atomic.AtomicBoolean; @RunWith(AndroidJUnit4.class) public class BluetoothOppBtEnablingActivityTest { + @Rule public MockitoRule mockitoRule = MockitoJUnit.rule(); + @Spy BluetoothMethodProxy mBluetoothMethodProxy; @@ -70,7 +73,6 @@ public class BluetoothOppBtEnablingActivityTest { @Before public void setUp() throws Exception { - MockitoAnnotations.initMocks(this); mBluetoothMethodProxy = Mockito.spy(BluetoothMethodProxy.getInstance()); BluetoothMethodProxy.setInstanceForTesting(mBluetoothMethodProxy); diff --git a/android/app/tests/unit/src/com/android/bluetooth/opp/BluetoothOppHandoverReceiverTest.java b/android/app/tests/unit/src/com/android/bluetooth/opp/BluetoothOppHandoverReceiverTest.java index fd6261e308..b27740bf0b 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/opp/BluetoothOppHandoverReceiverTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/opp/BluetoothOppHandoverReceiverTest.java @@ -39,10 +39,12 @@ import com.android.bluetooth.BluetoothMethodProxy; import org.junit.After; import org.junit.Before; +import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; -import org.mockito.MockitoAnnotations; import org.mockito.Spy; +import org.mockito.junit.MockitoJUnit; +import org.mockito.junit.MockitoRule; import java.util.ArrayList; import java.util.List; @@ -52,12 +54,13 @@ import java.util.List; public class BluetoothOppHandoverReceiverTest { Context mContext; + @Rule public MockitoRule mockitoRule = MockitoJUnit.rule(); + @Spy BluetoothMethodProxy mCallProxy = BluetoothMethodProxy.getInstance(); @Before public void setUp() { - MockitoAnnotations.initMocks(this); mContext = InstrumentationRegistry.getInstrumentation().getTargetContext(); BluetoothMethodProxy.setInstanceForTesting(mCallProxy); doReturn(0).when(mCallProxy).contentResolverDelete(any(), any(Uri.class), any(), any()); diff --git a/android/app/tests/unit/src/com/android/bluetooth/opp/BluetoothOppLauncherActivityTest.java b/android/app/tests/unit/src/com/android/bluetooth/opp/BluetoothOppLauncherActivityTest.java index 58ee1b6067..ddd18d5250 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/opp/BluetoothOppLauncherActivityTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/opp/BluetoothOppLauncherActivityTest.java @@ -57,7 +57,8 @@ import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.ArgumentCaptor; import org.mockito.Mock; -import org.mockito.MockitoAnnotations; +import org.mockito.junit.MockitoJUnit; +import org.mockito.junit.MockitoRule; import java.io.File; @@ -68,6 +69,8 @@ public class BluetoothOppLauncherActivityTest { Intent mIntent; BluetoothMethodProxy mMethodProxy; + @Rule public MockitoRule mockitoRule = MockitoJUnit.rule(); + @Mock BluetoothOppManager mBluetoothOppManager; @@ -78,7 +81,6 @@ public class BluetoothOppLauncherActivityTest { @Before public void setUp() throws Exception { - MockitoAnnotations.initMocks(this); mTargetContext = spy(new ContextWrapper( ApplicationProvider.getApplicationContext())); mMethodProxy = spy(BluetoothMethodProxy.getInstance()); diff --git a/android/app/tests/unit/src/com/android/bluetooth/opp/BluetoothOppManagerTest.java b/android/app/tests/unit/src/com/android/bluetooth/opp/BluetoothOppManagerTest.java index b588b2c1b9..695703c1f3 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/opp/BluetoothOppManagerTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/opp/BluetoothOppManagerTest.java @@ -51,7 +51,6 @@ import org.junit.Before; import org.junit.Ignore; import org.junit.Test; import org.junit.runner.RunWith; -import org.mockito.MockitoAnnotations; import java.util.ArrayList; import java.util.List; @@ -65,7 +64,6 @@ public class BluetoothOppManagerTest { @Before public void setUp() { - MockitoAnnotations.initMocks(this); mContext = spy(new ContextWrapper( InstrumentationRegistry.getInstrumentation().getTargetContext())); diff --git a/android/app/tests/unit/src/com/android/bluetooth/opp/BluetoothOppNotificationTest.java b/android/app/tests/unit/src/com/android/bluetooth/opp/BluetoothOppNotificationTest.java index 3dc2a51674..f76d5e859e 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/opp/BluetoothOppNotificationTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/opp/BluetoothOppNotificationTest.java @@ -53,13 +53,16 @@ import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; -import org.mockito.MockitoAnnotations; +import org.mockito.junit.MockitoJUnit; +import org.mockito.junit.MockitoRule; @RunWith(AndroidJUnit4.class) public class BluetoothOppNotificationTest { static final int TIMEOUT_MS = 3000; static final int WORKAROUND_TIMEOUT = 3000; + @Rule public MockitoRule mockitoRule = MockitoJUnit.rule(); + @Mock BluetoothMethodProxy mMethodProxy; @@ -77,7 +80,6 @@ public class BluetoothOppNotificationTest { @Before public void setUp() throws Exception { - MockitoAnnotations.initMocks(this); mTargetContext = spy(new ContextWrapper( ApplicationProvider.getApplicationContext())); BluetoothMethodProxy.setInstanceForTesting(mMethodProxy); diff --git a/android/app/tests/unit/src/com/android/bluetooth/opp/BluetoothOppObexClientSessionTest.java b/android/app/tests/unit/src/com/android/bluetooth/opp/BluetoothOppObexClientSessionTest.java index 4cc481020a..60a04b6149 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/opp/BluetoothOppObexClientSessionTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/opp/BluetoothOppObexClientSessionTest.java @@ -44,10 +44,12 @@ import com.android.obex.ClientSession; import org.junit.After; import org.junit.Before; +import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; -import org.mockito.MockitoAnnotations; +import org.mockito.junit.MockitoJUnit; +import org.mockito.junit.MockitoRule; import java.io.IOException; import java.io.InputStream; @@ -57,6 +59,8 @@ import java.util.concurrent.TimeUnit; @RunWith(AndroidJUnit4.class) public class BluetoothOppObexClientSessionTest { + @Rule public MockitoRule mockitoRule = MockitoJUnit.rule(); + @Mock BluetoothMethodProxy mMethodProxy; @@ -68,7 +72,6 @@ public class BluetoothOppObexClientSessionTest { @Before public void setUp() throws IOException { - MockitoAnnotations.initMocks(this); mTargetContext = InstrumentationRegistry.getInstrumentation().getTargetContext(); mClientSession = new BluetoothOppObexClientSession(mTargetContext, mTransport); diff --git a/android/app/tests/unit/src/com/android/bluetooth/opp/BluetoothOppObexServerSessionTest.java b/android/app/tests/unit/src/com/android/bluetooth/opp/BluetoothOppObexServerSessionTest.java index 3971d0e7b0..2e5bf6383e 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/opp/BluetoothOppObexServerSessionTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/opp/BluetoothOppObexServerSessionTest.java @@ -47,10 +47,12 @@ import com.android.obex.ResponseCodes; import org.junit.After; import org.junit.Assume; import org.junit.Before; +import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; -import org.mockito.MockitoAnnotations; +import org.mockito.junit.MockitoJUnit; +import org.mockito.junit.MockitoRule; import java.io.IOException; import java.io.InputStream; @@ -58,6 +60,8 @@ import java.io.OutputStream; @RunWith(AndroidJUnit4.class) public class BluetoothOppObexServerSessionTest { + @Rule public MockitoRule mockitoRule = MockitoJUnit.rule(); + @Mock BluetoothMethodProxy mMethodProxy; @@ -74,7 +78,6 @@ public class BluetoothOppObexServerSessionTest { @Before public void setUp() throws IOException { - MockitoAnnotations.initMocks(this); mTargetContext = spy( new ContextWrapper( InstrumentationRegistry.getInstrumentation().getTargetContext())); diff --git a/android/app/tests/unit/src/com/android/bluetooth/opp/BluetoothOppPreferenceTest.java b/android/app/tests/unit/src/com/android/bluetooth/opp/BluetoothOppPreferenceTest.java index 8869f282c1..fa690958bc 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/opp/BluetoothOppPreferenceTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/opp/BluetoothOppPreferenceTest.java @@ -39,7 +39,6 @@ import org.junit.After; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; -import org.mockito.MockitoAnnotations; @RunWith(AndroidJUnit4.class) public class BluetoothOppPreferenceTest { @@ -49,7 +48,6 @@ public class BluetoothOppPreferenceTest { @Before public void setUp() { - MockitoAnnotations.initMocks(this); mContext = spy(new ContextWrapper( InstrumentationRegistry.getInstrumentation().getTargetContext())); diff --git a/android/app/tests/unit/src/com/android/bluetooth/opp/BluetoothOppReceiverTest.java b/android/app/tests/unit/src/com/android/bluetooth/opp/BluetoothOppReceiverTest.java index faadf25f6e..3887ade6f5 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/opp/BluetoothOppReceiverTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/opp/BluetoothOppReceiverTest.java @@ -62,7 +62,8 @@ import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; -import org.mockito.MockitoAnnotations; +import org.mockito.junit.MockitoJUnit; +import org.mockito.junit.MockitoRule; import java.util.ArrayList; import java.util.List; @@ -74,13 +75,14 @@ public class BluetoothOppReceiverTest { Context mContext; + @Rule public MockitoRule mockitoRule = MockitoJUnit.rule(); + @Mock BluetoothMethodProxy mBluetoothMethodProxy; BluetoothOppReceiver mReceiver; @Before public void setUp() throws Exception { - MockitoAnnotations.initMocks(this); mContext = spy(new ContextWrapper( InstrumentationRegistry.getInstrumentation().getTargetContext())); diff --git a/android/app/tests/unit/src/com/android/bluetooth/opp/BluetoothOppSendFileInfoTest.java b/android/app/tests/unit/src/com/android/bluetooth/opp/BluetoothOppSendFileInfoTest.java index de7de37b5d..7d39d32d37 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/opp/BluetoothOppSendFileInfoTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/opp/BluetoothOppSendFileInfoTest.java @@ -39,10 +39,12 @@ import com.android.bluetooth.BluetoothMethodProxy; import org.junit.After; import org.junit.Before; +import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; -import org.mockito.MockitoAnnotations; +import org.mockito.junit.MockitoJUnit; +import org.mockito.junit.MockitoRule; import java.io.FileInputStream; import java.io.IOException; @@ -52,12 +54,13 @@ public class BluetoothOppSendFileInfoTest { Context mContext; MatrixCursor mCursor; + @Rule public MockitoRule mockitoRule = MockitoJUnit.rule(); + @Mock BluetoothMethodProxy mCallProxy; @Before public void setUp() { - MockitoAnnotations.initMocks(this); mContext = InstrumentationRegistry.getInstrumentation().getTargetContext(); BluetoothMethodProxy.setInstanceForTesting(mCallProxy); } diff --git a/android/app/tests/unit/src/com/android/bluetooth/opp/BluetoothOppServiceCleanupTest.java b/android/app/tests/unit/src/com/android/bluetooth/opp/BluetoothOppServiceCleanupTest.java index 04ab4ee821..f2f566e6cd 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/opp/BluetoothOppServiceCleanupTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/opp/BluetoothOppServiceCleanupTest.java @@ -40,7 +40,8 @@ import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; -import org.mockito.MockitoAnnotations; +import org.mockito.junit.MockitoJUnit; +import org.mockito.junit.MockitoRule; @SmallTest @RunWith(AndroidJUnit4.class) @@ -51,11 +52,12 @@ public class BluetoothOppServiceCleanupTest { private Context mTargetContext; + @Rule public MockitoRule mockitoRule = MockitoJUnit.rule(); + @Mock private AdapterService mAdapterService; @Before public void setUp() throws Exception { - MockitoAnnotations.initMocks(this); mTargetContext = InstrumentationRegistry.getInstrumentation().getTargetContext(); TestUtils.setAdapterService(mAdapterService); diff --git a/android/app/tests/unit/src/com/android/bluetooth/opp/BluetoothOppServiceTest.java b/android/app/tests/unit/src/com/android/bluetooth/opp/BluetoothOppServiceTest.java index 05b0460834..95acf7749e 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/opp/BluetoothOppServiceTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/opp/BluetoothOppServiceTest.java @@ -45,11 +45,13 @@ import com.android.bluetooth.btservice.AdapterService; import org.junit.After; import org.junit.Assert; import org.junit.Before; +import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; import org.mockito.Mockito; -import org.mockito.MockitoAnnotations; +import org.mockito.junit.MockitoJUnit; +import org.mockito.junit.MockitoRule; @MediumTest @RunWith(AndroidJUnit4.class) @@ -59,6 +61,7 @@ public class BluetoothOppServiceTest { private boolean mIsAdapterServiceSet; private boolean mIsBluetoothOppServiceStarted; + @Rule public MockitoRule mockitoRule = MockitoJUnit.rule(); @Mock BluetoothMethodProxy mBluetoothMethodProxy; @@ -67,7 +70,6 @@ public class BluetoothOppServiceTest { @Before public void setUp() throws Exception { Context targetContext = InstrumentationRegistry.getInstrumentation().getTargetContext(); - MockitoAnnotations.initMocks(this); BluetoothMethodProxy.setInstanceForTesting(mBluetoothMethodProxy); // BluetoothOppService can create a UpdateThread, which will call diff --git a/android/app/tests/unit/src/com/android/bluetooth/opp/BluetoothOppTransferActivityTest.java b/android/app/tests/unit/src/com/android/bluetooth/opp/BluetoothOppTransferActivityTest.java index 40580e651f..2fef847508 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/opp/BluetoothOppTransferActivityTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/opp/BluetoothOppTransferActivityTest.java @@ -50,8 +50,9 @@ import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; import org.mockito.Mockito; -import org.mockito.MockitoAnnotations; import org.mockito.Spy; +import org.mockito.junit.MockitoJUnit; +import org.mockito.junit.MockitoRule; import java.util.ArrayList; import java.util.List; @@ -59,6 +60,8 @@ import java.util.concurrent.atomic.AtomicBoolean; @RunWith(AndroidJUnit4.class) public class BluetoothOppTransferActivityTest { + @Rule public MockitoRule mockitoRule = MockitoJUnit.rule(); + @Mock Cursor mCursor; @Spy @@ -76,7 +79,6 @@ public class BluetoothOppTransferActivityTest { @Before public void setUp() throws Exception { - MockitoAnnotations.initMocks(this); mBluetoothMethodProxy = Mockito.spy(BluetoothMethodProxy.getInstance()); BluetoothMethodProxy.setInstanceForTesting(mBluetoothMethodProxy); diff --git a/android/app/tests/unit/src/com/android/bluetooth/opp/BluetoothOppTransferHistoryTest.java b/android/app/tests/unit/src/com/android/bluetooth/opp/BluetoothOppTransferHistoryTest.java index 7739c3109d..9cc3c0397b 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/opp/BluetoothOppTransferHistoryTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/opp/BluetoothOppTransferHistoryTest.java @@ -57,8 +57,9 @@ import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; import org.mockito.Mockito; -import org.mockito.MockitoAnnotations; import org.mockito.Spy; +import org.mockito.junit.MockitoJUnit; +import org.mockito.junit.MockitoRule; import java.util.ArrayList; import java.util.List; @@ -68,6 +69,8 @@ import java.util.List; */ @RunWith(AndroidJUnit4.class) public class BluetoothOppTransferHistoryTest { + @Rule public MockitoRule mockitoRule = MockitoJUnit.rule(); + @Mock Cursor mCursor; @Spy @@ -85,7 +88,6 @@ public class BluetoothOppTransferHistoryTest { @Before public void setUp() throws Exception { - MockitoAnnotations.initMocks(this); mBluetoothMethodProxy = Mockito.spy(BluetoothMethodProxy.getInstance()); BluetoothMethodProxy.setInstanceForTesting(mBluetoothMethodProxy); diff --git a/android/app/tests/unit/src/com/android/bluetooth/opp/BluetoothOppTransferTest.java b/android/app/tests/unit/src/com/android/bluetooth/opp/BluetoothOppTransferTest.java index f1e2a777fb..b9905a000e 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/opp/BluetoothOppTransferTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/opp/BluetoothOppTransferTest.java @@ -53,10 +53,12 @@ import com.android.obex.ObexTransport; import org.junit.After; import org.junit.Before; +import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; -import org.mockito.MockitoAnnotations; +import org.mockito.junit.MockitoJUnit; +import org.mockito.junit.MockitoRule; import java.util.Objects; @@ -77,6 +79,8 @@ public class BluetoothOppTransferTest { private final int mTimestamp = 123456789; private final boolean mMediaScanned = false; + @Rule public MockitoRule mockitoRule = MockitoJUnit.rule(); + @Mock BluetoothOppObexSession mSession; @Mock @@ -89,7 +93,6 @@ public class BluetoothOppTransferTest { @Before public void setUp() throws Exception { - MockitoAnnotations.initMocks(this); BluetoothMethodProxy.setInstanceForTesting(mCallProxy); doReturn(0).when(mCallProxy).contentResolverDelete(any(), nullable(Uri.class), nullable(String.class), nullable(String[].class)); diff --git a/android/app/tests/unit/src/com/android/bluetooth/opp/BluetoothOppUtilityTest.java b/android/app/tests/unit/src/com/android/bluetooth/opp/BluetoothOppUtilityTest.java index b6bcba8720..9f447e4744 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/opp/BluetoothOppUtilityTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/opp/BluetoothOppUtilityTest.java @@ -50,10 +50,12 @@ import com.android.bluetooth.opp.BluetoothOppTestUtils.CursorMockData; import org.junit.After; import org.junit.Before; +import org.junit.Rule; import org.junit.Test; import org.mockito.Mock; -import org.mockito.MockitoAnnotations; import org.mockito.Spy; +import org.mockito.junit.MockitoJUnit; +import org.mockito.junit.MockitoRule; import java.io.FileNotFoundException; import java.util.ArrayList; @@ -68,6 +70,8 @@ public class BluetoothOppUtilityTest { private static final Uri INCORRECT_FORMAT_URI = Uri.parse("www.google.com"); Context mContext; + @Rule public MockitoRule mockitoRule = MockitoJUnit.rule(); + @Mock Cursor mCursor; @@ -77,7 +81,6 @@ public class BluetoothOppUtilityTest { @Before public void setUp() throws Exception { - MockitoAnnotations.initMocks(this); mContext = InstrumentationRegistry.getInstrumentation().getTargetContext(); BluetoothMethodProxy.setInstanceForTesting(mCallProxy); TestUtils.setUpUiTest(); diff --git a/android/app/tests/unit/src/com/android/bluetooth/opp/IncomingFileConfirmActivityTest.java b/android/app/tests/unit/src/com/android/bluetooth/opp/IncomingFileConfirmActivityTest.java index 77872410ce..68756b67e6 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/opp/IncomingFileConfirmActivityTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/opp/IncomingFileConfirmActivityTest.java @@ -61,8 +61,9 @@ import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; import org.mockito.Mockito; -import org.mockito.MockitoAnnotations; import org.mockito.Spy; +import org.mockito.junit.MockitoJUnit; +import org.mockito.junit.MockitoRule; import java.util.ArrayList; import java.util.List; @@ -71,6 +72,8 @@ import java.util.concurrent.atomic.AtomicBoolean; // Long class name cause problem with Junit4. It will raise java.lang.NoClassDefFoundError @RunWith(AndroidJUnit4.class) public class IncomingFileConfirmActivityTest { + @Rule public MockitoRule mockitoRule = MockitoJUnit.rule(); + @Mock Cursor mCursor; @Spy @@ -90,7 +93,6 @@ public class IncomingFileConfirmActivityTest { @Before public void setUp() throws Exception { - MockitoAnnotations.initMocks(this); mBluetoothMethodProxy = Mockito.spy(BluetoothMethodProxy.getInstance()); BluetoothMethodProxy.setInstanceForTesting(mBluetoothMethodProxy); diff --git a/android/app/tests/unit/src/com/android/bluetooth/pan/BluetoothTetheringNetworkFactoryTest.java b/android/app/tests/unit/src/com/android/bluetooth/pan/BluetoothTetheringNetworkFactoryTest.java index 8357e12fb7..4adb1889e9 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/pan/BluetoothTetheringNetworkFactoryTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/pan/BluetoothTetheringNetworkFactoryTest.java @@ -32,11 +32,12 @@ import androidx.test.core.app.ApplicationProvider; import androidx.test.filters.SmallTest; import androidx.test.runner.AndroidJUnit4; -import org.junit.Before; +import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; -import org.mockito.MockitoAnnotations; +import org.mockito.junit.MockitoJUnit; +import org.mockito.junit.MockitoRule; import java.util.ArrayList; import java.util.List; @@ -48,16 +49,13 @@ import java.util.List; @RunWith(AndroidJUnit4.class) public class BluetoothTetheringNetworkFactoryTest { + @Rule public MockitoRule mockitoRule = MockitoJUnit.rule(); + @Mock private PanService mPanService; private Context mContext = ApplicationProvider.getApplicationContext(); - @Before - public void setUp() { - MockitoAnnotations.initMocks(this); - } - @Test public void networkStartReverseTetherEmptyIface() { if (Looper.myLooper() == null) { diff --git a/android/app/tests/unit/src/com/android/bluetooth/pan/PanServiceBinderTest.java b/android/app/tests/unit/src/com/android/bluetooth/pan/PanServiceBinderTest.java index 51e1ae7529..fe54c79872 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/pan/PanServiceBinderTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/pan/PanServiceBinderTest.java @@ -28,16 +28,20 @@ import androidx.test.runner.AndroidJUnit4; import com.android.bluetooth.x.com.android.modules.utils.SynchronousResultReceiver; import org.junit.Before; +import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; -import org.mockito.MockitoAnnotations; +import org.mockito.junit.MockitoJUnit; +import org.mockito.junit.MockitoRule; @SmallTest @RunWith(AndroidJUnit4.class) public class PanServiceBinderTest { private static final String REMOTE_DEVICE_ADDRESS = "00:00:00:00:00:00"; + @Rule public MockitoRule mockitoRule = MockitoJUnit.rule(); + @Mock private PanService mService; @@ -47,7 +51,6 @@ public class PanServiceBinderTest { @Before public void setUp() throws Exception { - MockitoAnnotations.initMocks(this); mRemoteDevice = BluetoothAdapter.getDefaultAdapter().getRemoteDevice(REMOTE_DEVICE_ADDRESS); mBinder = new PanService.BluetoothPanBinder(mService); } diff --git a/android/app/tests/unit/src/com/android/bluetooth/pan/PanServiceTest.java b/android/app/tests/unit/src/com/android/bluetooth/pan/PanServiceTest.java index e08f5207d9..f1daf38341 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/pan/PanServiceTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/pan/PanServiceTest.java @@ -42,10 +42,12 @@ import com.android.bluetooth.pan.PanService.BluetoothPanDevice; import org.junit.After; import org.junit.Before; +import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; -import org.mockito.MockitoAnnotations; +import org.mockito.junit.MockitoJUnit; +import org.mockito.junit.MockitoRule; @MediumTest @RunWith(AndroidJUnit4.class) @@ -57,6 +59,7 @@ public class PanServiceTest { private BluetoothAdapter mAdapter = null; private BluetoothDevice mRemoteDevice; + @Rule public MockitoRule mockitoRule = MockitoJUnit.rule(); @Mock private AdapterService mAdapterService; @Mock private DatabaseManager mDatabaseManager; @@ -66,7 +69,6 @@ public class PanServiceTest { @Before public void setUp() throws Exception { Context targetContext = InstrumentationRegistry.getTargetContext(); - MockitoAnnotations.initMocks(this); TestUtils.setAdapterService(mAdapterService); doReturn(mDatabaseManager).when(mAdapterService).getDatabase(); PanNativeInterface.setInstance(mNativeInterface); diff --git a/android/app/tests/unit/src/com/android/bluetooth/pbap/BluetoothPbapAuthenticatorTest.java b/android/app/tests/unit/src/com/android/bluetooth/pbap/BluetoothPbapAuthenticatorTest.java index 431c8cd599..9c00501b63 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/pbap/BluetoothPbapAuthenticatorTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/pbap/BluetoothPbapAuthenticatorTest.java @@ -27,10 +27,12 @@ import androidx.test.runner.AndroidJUnit4; import com.android.obex.PasswordAuthentication; import org.junit.Before; +import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; -import org.mockito.MockitoAnnotations; +import org.mockito.junit.MockitoJUnit; +import org.mockito.junit.MockitoRule; @MediumTest @RunWith(AndroidJUnit4.class) @@ -38,12 +40,13 @@ public class BluetoothPbapAuthenticatorTest { private BluetoothPbapAuthenticator mAuthenticator; + @Rule public MockitoRule mockitoRule = MockitoJUnit.rule(); + @Mock PbapStateMachine mMockPbapStateMachine; @Before public void setUp() throws Exception { - MockitoAnnotations.initMocks(this); mAuthenticator = new BluetoothPbapAuthenticator(mMockPbapStateMachine); } diff --git a/android/app/tests/unit/src/com/android/bluetooth/pbap/BluetoothPbapCallLogComposerTest.java b/android/app/tests/unit/src/com/android/bluetooth/pbap/BluetoothPbapCallLogComposerTest.java index 33089f4cc0..1ea6786e8b 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/pbap/BluetoothPbapCallLogComposerTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/pbap/BluetoothPbapCallLogComposerTest.java @@ -42,11 +42,13 @@ import com.android.bluetooth.BluetoothMethodProxy; import org.junit.After; import org.junit.Before; +import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; -import org.mockito.MockitoAnnotations; import org.mockito.Spy; +import org.mockito.junit.MockitoJUnit; +import org.mockito.junit.MockitoRule; @SmallTest @RunWith(AndroidJUnit4.class) @@ -65,12 +67,13 @@ public class BluetoothPbapCallLogComposerTest { @Spy BluetoothMethodProxy mPbapCallProxy = BluetoothMethodProxy.getInstance(); + @Rule public MockitoRule mockitoRule = MockitoJUnit.rule(); + @Mock Cursor mMockCursor; @Before public void setUp() throws Exception { - MockitoAnnotations.initMocks(this); BluetoothMethodProxy.setInstanceForTesting(mPbapCallProxy); doReturn(mMockCursor).when(mPbapCallProxy) diff --git a/android/app/tests/unit/src/com/android/bluetooth/pbap/BluetoothPbapConfigTest.java b/android/app/tests/unit/src/com/android/bluetooth/pbap/BluetoothPbapConfigTest.java index 097f46d8d5..30445b1399 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/pbap/BluetoothPbapConfigTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/pbap/BluetoothPbapConfigTest.java @@ -29,15 +29,19 @@ import androidx.test.runner.AndroidJUnit4; import com.android.bluetooth.R; import org.junit.Before; +import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; -import org.mockito.MockitoAnnotations; +import org.mockito.junit.MockitoJUnit; +import org.mockito.junit.MockitoRule; @SmallTest @RunWith(AndroidJUnit4.class) public class BluetoothPbapConfigTest { + @Rule public MockitoRule mockitoRule = MockitoJUnit.rule(); + @Mock Context mContext; @@ -46,7 +50,6 @@ public class BluetoothPbapConfigTest { @Before public void setUp() throws Exception { - MockitoAnnotations.initMocks(this); when(mContext.getResources()).thenReturn(mResources); } diff --git a/android/app/tests/unit/src/com/android/bluetooth/pbap/BluetoothPbapObexServerTest.java b/android/app/tests/unit/src/com/android/bluetooth/pbap/BluetoothPbapObexServerTest.java index 62834b49d8..6d22c2e78c 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/pbap/BluetoothPbapObexServerTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/pbap/BluetoothPbapObexServerTest.java @@ -67,11 +67,13 @@ import com.android.obex.ResponseCodes; import org.junit.After; import org.junit.Before; +import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; -import org.mockito.MockitoAnnotations; import org.mockito.Spy; +import org.mockito.junit.MockitoJUnit; +import org.mockito.junit.MockitoRule; import java.io.IOException; import java.io.OutputStream; @@ -82,6 +84,8 @@ public class BluetoothPbapObexServerTest { private static final String TAG = BluetoothPbapObexServerTest.class.getSimpleName(); + @Rule public MockitoRule mockitoRule = MockitoJUnit.rule(); + @Mock Handler mMockHandler; @Mock PbapStateMachine mMockStateMachine; @@ -107,7 +111,6 @@ public class BluetoothPbapObexServerTest { @Before public void setUp() throws Exception { - MockitoAnnotations.initMocks(this); BluetoothMethodProxy.setInstanceForTesting(mPbapMethodProxy); mServer = new BluetoothPbapObexServer( mMockHandler, InstrumentationRegistry.getTargetContext(), mMockStateMachine); diff --git a/android/app/tests/unit/src/com/android/bluetooth/pbap/BluetoothPbapServiceBinderTest.java b/android/app/tests/unit/src/com/android/bluetooth/pbap/BluetoothPbapServiceBinderTest.java index 4bd3a10e31..116fe9e743 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/pbap/BluetoothPbapServiceBinderTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/pbap/BluetoothPbapServiceBinderTest.java @@ -26,16 +26,20 @@ import androidx.test.filters.MediumTest; import androidx.test.runner.AndroidJUnit4; import org.junit.Before; +import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; -import org.mockito.MockitoAnnotations; +import org.mockito.junit.MockitoJUnit; +import org.mockito.junit.MockitoRule; @MediumTest @RunWith(AndroidJUnit4.class) public class BluetoothPbapServiceBinderTest { private static final String REMOTE_DEVICE_ADDRESS = "00:00:00:00:00:00"; + @Rule public MockitoRule mockitoRule = MockitoJUnit.rule(); + @Mock private BluetoothPbapService mService; @@ -45,7 +49,6 @@ public class BluetoothPbapServiceBinderTest { @Before public void setUp() throws Exception { - MockitoAnnotations.initMocks(this); mRemoteDevice = BluetoothAdapter.getDefaultAdapter().getRemoteDevice(REMOTE_DEVICE_ADDRESS); mBinder = new BluetoothPbapService.PbapBinder(mService); } diff --git a/android/app/tests/unit/src/com/android/bluetooth/pbap/BluetoothPbapServiceTest.java b/android/app/tests/unit/src/com/android/bluetooth/pbap/BluetoothPbapServiceTest.java index 69dac461ad..b509e7e7c4 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/pbap/BluetoothPbapServiceTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/pbap/BluetoothPbapServiceTest.java @@ -44,12 +44,14 @@ import com.android.bluetooth.btservice.storage.DatabaseManager; import org.junit.After; import org.junit.Before; +import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.ArgumentCaptor; import org.mockito.Mock; -import org.mockito.MockitoAnnotations; import org.mockito.Spy; +import org.mockito.junit.MockitoJUnit; +import org.mockito.junit.MockitoRule; @MediumTest @RunWith(AndroidJUnit4.class) @@ -63,6 +65,7 @@ public class BluetoothPbapServiceTest { private boolean mIsBluetoothPabpServiceStarted; private TestLooper mTestLooper; + @Rule public MockitoRule mockitoRule = MockitoJUnit.rule(); @Mock private AdapterService mAdapterService; @Mock private DatabaseManager mDatabaseManager; @@ -71,7 +74,6 @@ public class BluetoothPbapServiceTest { @Before public void setUp() throws Exception { Context targetContext = InstrumentationRegistry.getTargetContext(); - MockitoAnnotations.initMocks(this); mTestLooper = new TestLooper(); BluetoothMethodProxy.setInstanceForTesting(mMethodProxy); doReturn(mTestLooper.getLooper()).when(mMethodProxy).handlerThreadGetLooper(any()); diff --git a/android/app/tests/unit/src/com/android/bluetooth/pbap/BluetoothPbapSimVcardManagerTest.java b/android/app/tests/unit/src/com/android/bluetooth/pbap/BluetoothPbapSimVcardManagerTest.java index 46302cb441..2e46515c56 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/pbap/BluetoothPbapSimVcardManagerTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/pbap/BluetoothPbapSimVcardManagerTest.java @@ -41,10 +41,12 @@ import com.android.obex.ResponseCodes; import org.junit.After; import org.junit.Before; +import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; -import org.mockito.MockitoAnnotations; import org.mockito.Spy; +import org.mockito.junit.MockitoJUnit; +import org.mockito.junit.MockitoRule; import org.mockito.stubbing.Answer; import java.io.OutputStream; @@ -60,6 +62,8 @@ public class BluetoothPbapSimVcardManagerTest { private static final String TAG = BluetoothPbapSimVcardManagerTest.class.getSimpleName(); + @Rule public MockitoRule mockitoRule = MockitoJUnit.rule(); + @Spy BluetoothMethodProxy mPbapMethodProxy = BluetoothMethodProxy.getInstance(); @@ -70,7 +74,6 @@ public class BluetoothPbapSimVcardManagerTest { @Before public void setUp() { - MockitoAnnotations.initMocks(this); BluetoothMethodProxy.setInstanceForTesting(mPbapMethodProxy); mContext = InstrumentationRegistry.getTargetContext(); mManager = new BluetoothPbapSimVcardManager(mContext); diff --git a/android/app/tests/unit/src/com/android/bluetooth/pbap/BluetoothPbapUtilsTest.java b/android/app/tests/unit/src/com/android/bluetooth/pbap/BluetoothPbapUtilsTest.java index 875042f8b0..a98d782fdd 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/pbap/BluetoothPbapUtilsTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/pbap/BluetoothPbapUtilsTest.java @@ -48,11 +48,13 @@ import com.android.vcard.VCardConfig; import org.junit.After; import org.junit.Before; +import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; -import org.mockito.MockitoAnnotations; import org.mockito.Spy; +import org.mockito.junit.MockitoJUnit; +import org.mockito.junit.MockitoRule; import java.util.ArrayList; import java.util.Calendar; @@ -62,6 +64,8 @@ import java.util.List; @RunWith(AndroidJUnit4.class) public class BluetoothPbapUtilsTest { + @Rule public MockitoRule mockitoRule = MockitoJUnit.rule(); + @Mock Context mContext; @@ -73,7 +77,6 @@ public class BluetoothPbapUtilsTest { @Before public void setUp() throws Exception { - MockitoAnnotations.initMocks(this); BluetoothMethodProxy.setInstanceForTesting(mProxy); when(mContext.getResources()).thenReturn(mResources); diff --git a/android/app/tests/unit/src/com/android/bluetooth/pbap/BluetoothPbapVcardManagerNestedClassesTest.java b/android/app/tests/unit/src/com/android/bluetooth/pbap/BluetoothPbapVcardManagerNestedClassesTest.java index a6c16aaa42..9fab5c1d8f 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/pbap/BluetoothPbapVcardManagerNestedClassesTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/pbap/BluetoothPbapVcardManagerNestedClassesTest.java @@ -34,10 +34,12 @@ import com.android.bluetooth.pbap.BluetoothPbapVcardManager.PropertySelector; import com.android.bluetooth.pbap.BluetoothPbapVcardManager.VCardFilter; import org.junit.Before; +import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; -import org.mockito.MockitoAnnotations; +import org.mockito.junit.MockitoJUnit; +import org.mockito.junit.MockitoRule; import java.util.concurrent.atomic.AtomicInteger; @@ -45,6 +47,8 @@ import java.util.concurrent.atomic.AtomicInteger; @RunWith(AndroidJUnit4.class) public class BluetoothPbapVcardManagerNestedClassesTest { + @Rule public MockitoRule mockitoRule = MockitoJUnit.rule(); + @Mock Context mContext; @@ -53,7 +57,6 @@ public class BluetoothPbapVcardManagerNestedClassesTest { @Before public void setUp() throws Exception { - MockitoAnnotations.initMocks(this); when(mContext.getResources()).thenReturn(mResources); } diff --git a/android/app/tests/unit/src/com/android/bluetooth/pbap/BluetoothPbapVcardManagerTest.java b/android/app/tests/unit/src/com/android/bluetooth/pbap/BluetoothPbapVcardManagerTest.java index a6ed5593ca..3c623679f5 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/pbap/BluetoothPbapVcardManagerTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/pbap/BluetoothPbapVcardManagerTest.java @@ -39,10 +39,12 @@ import com.android.bluetooth.R; import org.junit.After; import org.junit.Before; +import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; -import org.mockito.MockitoAnnotations; import org.mockito.Spy; +import org.mockito.junit.MockitoJUnit; +import org.mockito.junit.MockitoRule; import org.mockito.stubbing.Answer; import java.util.Arrays; @@ -55,6 +57,8 @@ public class BluetoothPbapVcardManagerTest { private static final String TAG = BluetoothPbapVcardManagerTest.class.getSimpleName(); + @Rule public MockitoRule mockitoRule = MockitoJUnit.rule(); + @Spy BluetoothMethodProxy mPbapMethodProxy = BluetoothMethodProxy.getInstance(); @@ -63,7 +67,6 @@ public class BluetoothPbapVcardManagerTest { @Before public void setUp() { - MockitoAnnotations.initMocks(this); BluetoothMethodProxy.setInstanceForTesting(mPbapMethodProxy); mContext = InstrumentationRegistry.getTargetContext(); mManager = new BluetoothPbapVcardManager(mContext); diff --git a/android/app/tests/unit/src/com/android/bluetooth/pbap/HandlerForStringBufferTest.java b/android/app/tests/unit/src/com/android/bluetooth/pbap/HandlerForStringBufferTest.java index 3e8dd1fff4..6c1e252aab 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/pbap/HandlerForStringBufferTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/pbap/HandlerForStringBufferTest.java @@ -30,10 +30,12 @@ import androidx.test.runner.AndroidJUnit4; import com.android.obex.Operation; import org.junit.Before; +import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; -import org.mockito.MockitoAnnotations; +import org.mockito.junit.MockitoJUnit; +import org.mockito.junit.MockitoRule; import java.io.IOException; import java.io.OutputStream; @@ -42,6 +44,8 @@ import java.io.OutputStream; @RunWith(AndroidJUnit4.class) public class HandlerForStringBufferTest { + @Rule public MockitoRule mockitoRule = MockitoJUnit.rule(); + @Mock private Operation mOperation; @@ -50,7 +54,6 @@ public class HandlerForStringBufferTest { @Before public void setUp() throws Exception { - MockitoAnnotations.initMocks(this); when(mOperation.openOutputStream()).thenReturn(mOutputStream); } diff --git a/android/app/tests/unit/src/com/android/bluetooth/pbap/PbapStateMachineTest.java b/android/app/tests/unit/src/com/android/bluetooth/pbap/PbapStateMachineTest.java index b372f18ad5..978f9dfb0e 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/pbap/PbapStateMachineTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/pbap/PbapStateMachineTest.java @@ -38,10 +38,12 @@ import org.junit.After; import org.junit.Assert; import org.junit.Before; import org.junit.Ignore; +import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; -import org.mockito.MockitoAnnotations; +import org.mockito.junit.MockitoJUnit; +import org.mockito.junit.MockitoRule; @MediumTest @RunWith(AndroidJUnit4.class) @@ -58,12 +60,13 @@ public class PbapStateMachineTest { private BluetoothPbapService mBluetoothPbapService; private boolean mIsAdapterServiceSet; + @Rule public MockitoRule mockitoRule = MockitoJUnit.rule(); + @Mock private AdapterService mAdapterService; @Before public void setUp() throws Exception { mTargetContext = InstrumentationRegistry.getTargetContext(); - MockitoAnnotations.initMocks(this); TestUtils.setAdapterService(mAdapterService); mIsAdapterServiceSet = true; // This line must be called to make sure relevant objects are initialized properly diff --git a/android/app/tests/unit/src/com/android/bluetooth/pbapclient/BluetoothPbapRequestTest.java b/android/app/tests/unit/src/com/android/bluetooth/pbapclient/BluetoothPbapRequestTest.java index e258921547..b947c62dc2 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/pbapclient/BluetoothPbapRequestTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/pbapclient/BluetoothPbapRequestTest.java @@ -30,10 +30,12 @@ import com.android.obex.ObexTransport; import com.android.obex.ResponseCodes; import org.junit.Before; +import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; -import org.mockito.MockitoAnnotations; +import org.mockito.junit.MockitoJUnit; +import org.mockito.junit.MockitoRule; import java.io.InputStream; @@ -43,12 +45,13 @@ public class BluetoothPbapRequestTest { private BluetoothPbapRequest mRequest = new BluetoothPbapRequest() {}; + @Rule public MockitoRule mockitoRule = MockitoJUnit.rule(); + @Mock private ObexTransport mObexTransport; @Before public void setUp() throws Exception { - MockitoAnnotations.initMocks(this); mRequest = new BluetoothPbapRequest() {}; } diff --git a/android/app/tests/unit/src/com/android/bluetooth/pbapclient/CallLogPullRequestTest.java b/android/app/tests/unit/src/com/android/bluetooth/pbapclient/CallLogPullRequestTest.java index ceb85e5727..6a5440ad74 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/pbapclient/CallLogPullRequestTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/pbapclient/CallLogPullRequestTest.java @@ -39,10 +39,12 @@ import com.android.vcard.VCardProperty; import org.junit.After; import org.junit.Before; +import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; -import org.mockito.MockitoAnnotations; import org.mockito.Spy; +import org.mockito.junit.MockitoJUnit; +import org.mockito.junit.MockitoRule; import java.util.ArrayList; import java.util.HashMap; @@ -56,12 +58,13 @@ public class CallLogPullRequestTest { private final HashMap<String, Integer> mCallCounter = new HashMap<>(); private Context mTargetContext; + @Rule public MockitoRule mockitoRule = MockitoJUnit.rule(); + @Spy private BluetoothMethodProxy mMapMethodProxy = BluetoothMethodProxy.getInstance(); @Before public void setUp() { - MockitoAnnotations.initMocks(this); BluetoothMethodProxy.setInstanceForTesting(mMapMethodProxy); mTargetContext = InstrumentationRegistry.getInstrumentation().getTargetContext(); } diff --git a/android/app/tests/unit/src/com/android/bluetooth/pbapclient/PbapClientConnectionHandlerTest.java b/android/app/tests/unit/src/com/android/bluetooth/pbapclient/PbapClientConnectionHandlerTest.java index 50f96db865..84806cc383 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/pbapclient/PbapClientConnectionHandlerTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/pbapclient/PbapClientConnectionHandlerTest.java @@ -42,10 +42,12 @@ import com.android.bluetooth.btservice.storage.DatabaseManager; import org.junit.After; import org.junit.Before; +import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; -import org.mockito.MockitoAnnotations; +import org.mockito.junit.MockitoJUnit; +import org.mockito.junit.MockitoRule; @SmallTest @RunWith(AndroidJUnit4.class) @@ -59,6 +61,8 @@ public class PbapClientConnectionHandlerTest { private Context mTargetContext; private BluetoothDevice mRemoteDevice; + @Rule public MockitoRule mockitoRule = MockitoJUnit.rule(); + @Mock private AdapterService mAdapterService; @@ -77,7 +81,6 @@ public class PbapClientConnectionHandlerTest { public void setUp() throws Exception { mTargetContext = spy(new ContextWrapper( InstrumentationRegistry.getInstrumentation().getTargetContext())); - MockitoAnnotations.initMocks(this); TestUtils.setAdapterService(mAdapterService); doReturn(mDatabaseManager).when(mAdapterService).getDatabase(); mService = new PbapClientService(mTargetContext); diff --git a/android/app/tests/unit/src/com/android/bluetooth/pbapclient/PbapClientServiceTest.java b/android/app/tests/unit/src/com/android/bluetooth/pbapclient/PbapClientServiceTest.java index 06e63c9519..959439d1dd 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/pbapclient/PbapClientServiceTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/pbapclient/PbapClientServiceTest.java @@ -48,11 +48,13 @@ import com.android.bluetooth.x.com.android.modules.utils.SynchronousResultReceiv import org.junit.After; import org.junit.Assert; import org.junit.Before; +import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.ArgumentCaptor; import org.mockito.Mock; -import org.mockito.MockitoAnnotations; +import org.mockito.junit.MockitoJUnit; +import org.mockito.junit.MockitoRule; @MediumTest @RunWith(AndroidJUnit4.class) @@ -66,6 +68,8 @@ public class PbapClientServiceTest { boolean mIsAdapterServiceSet; boolean mIsPbapClientServiceStarted; + @Rule public MockitoRule mockitoRule = MockitoJUnit.rule(); + @Mock private AdapterService mAdapterService; @Mock private DatabaseManager mDatabaseManager; @@ -73,7 +77,6 @@ public class PbapClientServiceTest { @Before public void setUp() throws Exception { mTargetContext = InstrumentationRegistry.getTargetContext(); - MockitoAnnotations.initMocks(this); TestUtils.setAdapterService(mAdapterService); mIsAdapterServiceSet = true; doReturn(mDatabaseManager).when(mAdapterService).getDatabase(); diff --git a/android/app/tests/unit/src/com/android/bluetooth/pbapclient/PbapClientStateMachineTest.java b/android/app/tests/unit/src/com/android/bluetooth/pbapclient/PbapClientStateMachineTest.java index ae3bd808a7..d40aa8d5d1 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/pbapclient/PbapClientStateMachineTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/pbapclient/PbapClientStateMachineTest.java @@ -38,12 +38,14 @@ import com.android.bluetooth.TestUtils; import org.junit.After; import org.junit.Before; +import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.ArgumentCaptor; import org.mockito.Mock; import org.mockito.Mockito; -import org.mockito.MockitoAnnotations; +import org.mockito.junit.MockitoJUnit; +import org.mockito.junit.MockitoRule; @MediumTest @RunWith(AndroidJUnit4.class) @@ -52,6 +54,8 @@ public class PbapClientStateMachineTest{ private PbapClientStateMachine mPbapClientStateMachine = null; + @Rule public MockitoRule mockitoRule = MockitoJUnit.rule(); + @Mock private PbapClientService mMockPbapClientService; @Mock @@ -69,7 +73,6 @@ public class PbapClientStateMachineTest{ @Before public void setUp() throws Exception { - MockitoAnnotations.initMocks(this); // This line must be called to make sure relevant objects are initialized properly mAdapter = BluetoothAdapter.getDefaultAdapter(); diff --git a/android/app/tests/unit/src/com/android/bluetooth/sap/SapRilReceiverHidlTest.java b/android/app/tests/unit/src/com/android/bluetooth/sap/SapRilReceiverHidlTest.java index 0fa5520c12..94565511f0 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/sap/SapRilReceiverHidlTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/sap/SapRilReceiverHidlTest.java @@ -60,12 +60,14 @@ import com.android.bluetooth.x.android.hardware.radio.V1_0.ISap; import org.junit.After; import org.junit.Before; +import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.ArgumentMatcher; import org.mockito.Mock; -import org.mockito.MockitoAnnotations; import org.mockito.Spy; +import org.mockito.junit.MockitoJUnit; +import org.mockito.junit.MockitoRule; import java.util.ArrayList; import java.util.Arrays; @@ -82,6 +84,8 @@ public class SapRilReceiverHidlTest { @Spy private TestHandlerCallback mCallback = new TestHandlerCallback(); + @Rule public MockitoRule mockitoRule = MockitoJUnit.rule(); + @Mock private Handler mServiceHandler; @@ -92,7 +96,6 @@ public class SapRilReceiverHidlTest { @Before public void setUp() throws Exception { - MockitoAnnotations.initMocks(this); mHandlerThread = new HandlerThread("SapRilReceiverTest"); mHandlerThread.start(); diff --git a/android/app/tests/unit/src/com/android/bluetooth/sap/SapRilReceiverTest.java b/android/app/tests/unit/src/com/android/bluetooth/sap/SapRilReceiverTest.java index 3d0e350fb9..293b892a7d 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/sap/SapRilReceiverTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/sap/SapRilReceiverTest.java @@ -63,12 +63,14 @@ import androidx.test.runner.AndroidJUnit4; import org.junit.After; import org.junit.Before; +import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.ArgumentMatcher; import org.mockito.Mock; -import org.mockito.MockitoAnnotations; import org.mockito.Spy; +import org.mockito.junit.MockitoJUnit; +import org.mockito.junit.MockitoRule; import java.util.Arrays; @@ -84,6 +86,8 @@ public class SapRilReceiverTest { @Spy private TestHandlerCallback mCallback = new TestHandlerCallback(); + @Rule public MockitoRule mockitoRule = MockitoJUnit.rule(); + @Mock private Handler mServiceHandler; @@ -94,7 +98,6 @@ public class SapRilReceiverTest { @Before public void setUp() throws Exception { - MockitoAnnotations.initMocks(this); mHandlerThread = new HandlerThread("SapRilReceiverTest"); mHandlerThread.start(); diff --git a/android/app/tests/unit/src/com/android/bluetooth/sap/SapServerTest.java b/android/app/tests/unit/src/com/android/bluetooth/sap/SapServerTest.java index e88c5f122b..0de1343d3a 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/sap/SapServerTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/sap/SapServerTest.java @@ -71,13 +71,15 @@ import androidx.test.runner.AndroidJUnit4; import org.junit.After; import org.junit.Before; +import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.ArgumentCaptor; import org.mockito.ArgumentMatcher; import org.mockito.Mock; -import org.mockito.MockitoAnnotations; import org.mockito.Spy; +import org.mockito.junit.MockitoJUnit; +import org.mockito.junit.MockitoRule; import java.io.InputStream; import java.io.OutputStream; @@ -98,6 +100,8 @@ public class SapServerTest { @Spy private TestHandlerCallback mCallback = new TestHandlerCallback(); + @Rule public MockitoRule mockitoRule = MockitoJUnit.rule(); + @Mock private InputStream mInputStream; @@ -108,7 +112,6 @@ public class SapServerTest { @Before public void setUp() throws Exception { - MockitoAnnotations.initMocks(this); mHandlerThread = new HandlerThread("SapServerTest"); mHandlerThread.start(); diff --git a/android/app/tests/unit/src/com/android/bluetooth/sap/SapServiceTest.java b/android/app/tests/unit/src/com/android/bluetooth/sap/SapServiceTest.java index 27cb3a96dc..6e3071ea4e 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/sap/SapServiceTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/sap/SapServiceTest.java @@ -36,11 +36,12 @@ import com.android.bluetooth.btservice.storage.DatabaseManager; import org.junit.After; import org.junit.Before; +import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; -import org.mockito.MockitoAnnotations; - +import org.mockito.junit.MockitoJUnit; +import org.mockito.junit.MockitoRule; @MediumTest @RunWith(AndroidJUnit4.class) @@ -51,6 +52,8 @@ public class SapServiceTest { private BluetoothAdapter mAdapter = null; private Context mTargetContext; + @Rule public MockitoRule mockitoRule = MockitoJUnit.rule(); + @Mock private AdapterService mAdapterService; @Mock private DatabaseManager mDatabaseManager; private BluetoothDevice mDevice; @@ -58,7 +61,6 @@ public class SapServiceTest { @Before public void setUp() throws Exception { mTargetContext = InstrumentationRegistry.getTargetContext(); - MockitoAnnotations.initMocks(this); TestUtils.setAdapterService(mAdapterService); mService = new SapService(mTargetContext); mService.start(); diff --git a/android/app/tests/unit/src/com/android/bluetooth/sdp/DipTest.java b/android/app/tests/unit/src/com/android/bluetooth/sdp/DipTest.java index 60dfc9df71..5292940b12 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/sdp/DipTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/sdp/DipTest.java @@ -41,11 +41,13 @@ import com.android.bluetooth.btservice.AdapterService; import org.junit.After; import org.junit.Before; +import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.ArgumentCaptor; import org.mockito.Mock; -import org.mockito.MockitoAnnotations; +import org.mockito.junit.MockitoJUnit; +import org.mockito.junit.MockitoRule; @SmallTest @RunWith(AndroidJUnit4.class) @@ -59,14 +61,14 @@ public class DipTest { private ArgumentCaptor<String> mStringArgument = ArgumentCaptor.forClass(String.class); private ArgumentCaptor<Bundle> mBundleArgument = ArgumentCaptor.forClass(Bundle.class); + @Rule public MockitoRule mockitoRule = MockitoJUnit.rule(); + @Mock private AdapterService mAdapterService = null; @Mock private SdpManagerNativeInterface mNativeInterface; @Before public void setUp() throws Exception { mTargetContext = InstrumentationRegistry.getTargetContext(); - // Set up mocks and test assets - MockitoAnnotations.initMocks(this); SdpManagerNativeInterface.setInstance(mNativeInterface); TestUtils.setAdapterService(mAdapterService); diff --git a/android/app/tests/unit/src/com/android/bluetooth/tbs/TbsGattTest.java b/android/app/tests/unit/src/com/android/bluetooth/tbs/TbsGattTest.java index f56789f1ce..d619b6136f 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/tbs/TbsGattTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/tbs/TbsGattTest.java @@ -46,7 +46,8 @@ import org.junit.runner.RunWith; import org.mockito.ArgumentCaptor; import org.mockito.Captor; import org.mockito.Mock; -import org.mockito.MockitoAnnotations; +import org.mockito.junit.MockitoJUnit; +import org.mockito.junit.MockitoRule; import java.nio.charset.StandardCharsets; import java.util.ArrayList; @@ -72,6 +73,8 @@ public class TbsGattTest { private TbsGatt mTbsGatt; + @Rule public MockitoRule mockitoRule = MockitoJUnit.rule(); + @Mock private AdapterService mAdapterService; @Mock @@ -95,7 +98,6 @@ public class TbsGattTest { getInstrumentation().getUiAutomation().adoptShellPermissionIdentity(); - MockitoAnnotations.initMocks(this); TestUtils.setAdapterService(mAdapterService); mAdapter = BluetoothAdapter.getDefaultAdapter(); diff --git a/android/app/tests/unit/src/com/android/bluetooth/tbs/TbsGenericTest.java b/android/app/tests/unit/src/com/android/bluetooth/tbs/TbsGenericTest.java index 856845fda8..7d6b512f48 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/tbs/TbsGenericTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/tbs/TbsGenericTest.java @@ -35,12 +35,14 @@ import com.android.bluetooth.le_audio.LeAudioService; import org.junit.After; import org.junit.Before; +import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.ArgumentCaptor; import org.mockito.Captor; import org.mockito.Mock; -import org.mockito.MockitoAnnotations; +import org.mockito.junit.MockitoJUnit; +import org.mockito.junit.MockitoRule; import java.util.ArrayList; import java.util.Arrays; @@ -56,6 +58,8 @@ public class TbsGenericTest { private TbsGeneric mTbsGeneric; + @Rule public MockitoRule mockitoRule = MockitoJUnit.rule(); + private @Mock TbsGatt mTbsGatt; private @Mock IBluetoothLeCallControlCallback mIBluetoothLeCallControlCallback; private @Captor ArgumentCaptor<Integer> mGtbsCcidCaptor; @@ -70,7 +74,6 @@ public class TbsGenericTest { @Before public void setUp() throws Exception { - MockitoAnnotations.initMocks(this); mAdapter = BluetoothAdapter.getDefaultAdapter(); mContext = getInstrumentation().getTargetContext(); diff --git a/android/app/tests/unit/src/com/android/bluetooth/telephony/BluetoothInCallServiceTest.java b/android/app/tests/unit/src/com/android/bluetooth/telephony/BluetoothInCallServiceTest.java index 5b295f4b55..060fdee686 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/telephony/BluetoothInCallServiceTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/telephony/BluetoothInCallServiceTest.java @@ -60,7 +60,8 @@ import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.ArgumentCaptor; import org.mockito.Mock; -import org.mockito.MockitoAnnotations; +import org.mockito.junit.MockitoJUnit; +import org.mockito.junit.MockitoRule; import java.util.ArrayList; import java.util.Arrays; @@ -102,6 +103,8 @@ public class BluetoothInCallServiceTest { public final ServiceTestRule mServiceRule = ServiceTestRule.withTimeout(1, TimeUnit.SECONDS); + @Rule public MockitoRule mockitoRule = MockitoJUnit.rule(); + @Mock private BluetoothHeadsetProxy mMockBluetoothHeadset; @Mock @@ -136,7 +139,6 @@ public class BluetoothInCallServiceTest { @Before public void setUp() throws Exception { - MockitoAnnotations.initMocks(this); InstrumentationRegistry.getInstrumentation().getUiAutomation().adoptShellPermissionIdentity(); // Create the service Intent. diff --git a/android/app/tests/unit/src/com/android/bluetooth/telephony/CallInfoTest.java b/android/app/tests/unit/src/com/android/bluetooth/telephony/CallInfoTest.java index af77f4fac5..102389c364 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/telephony/CallInfoTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/telephony/CallInfoTest.java @@ -36,10 +36,12 @@ import androidx.test.runner.AndroidJUnit4; import org.junit.After; import org.junit.Before; +import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; -import org.mockito.MockitoAnnotations; +import org.mockito.junit.MockitoJUnit; +import org.mockito.junit.MockitoRule; import java.util.ArrayList; import java.util.LinkedHashSet; @@ -53,6 +55,8 @@ public class CallInfoTest { private static final String TEST_ACCOUNT_ADDRESS = "https://foo.com/"; private static final int TEST_ACCOUNT_INDEX = 0; + @Rule public MockitoRule mockitoRule = MockitoJUnit.rule(); + @Mock private TelecomManager mMockTelecomManager; @@ -61,7 +65,6 @@ public class CallInfoTest { @Before public void setUp() throws Exception { - MockitoAnnotations.initMocks(this); mBluetoothInCallService = new BluetoothInCallService(); mMockCallInfo = spy(mBluetoothInCallService.new CallInfo()); diff --git a/android/app/tests/unit/src/com/android/bluetooth/vc/VolumeControlNativeInterfaceTest.java b/android/app/tests/unit/src/com/android/bluetooth/vc/VolumeControlNativeInterfaceTest.java index fbf4697121..7d19671151 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/vc/VolumeControlNativeInterfaceTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/vc/VolumeControlNativeInterfaceTest.java @@ -25,14 +25,18 @@ import androidx.test.runner.AndroidJUnit4; import org.junit.After; import org.junit.Before; +import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.ArgumentCaptor; import org.mockito.Mock; -import org.mockito.MockitoAnnotations; +import org.mockito.junit.MockitoJUnit; +import org.mockito.junit.MockitoRule; @RunWith(AndroidJUnit4.class) public class VolumeControlNativeInterfaceTest { + @Rule public MockitoRule mockitoRule = MockitoJUnit.rule(); + @Mock private VolumeControlService mService; @@ -40,7 +44,6 @@ public class VolumeControlNativeInterfaceTest { @Before public void setUp() throws Exception { - MockitoAnnotations.initMocks(this); when(mService.isAvailable()).thenReturn(true); VolumeControlService.setVolumeControlService(mService); mNativeInterface = VolumeControlNativeInterface.getInstance(); diff --git a/android/app/tests/unit/src/com/android/bluetooth/vc/VolumeControlServiceTest.java b/android/app/tests/unit/src/com/android/bluetooth/vc/VolumeControlServiceTest.java index 79a327cd7a..5c00afb406 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/vc/VolumeControlServiceTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/vc/VolumeControlServiceTest.java @@ -58,7 +58,8 @@ import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; import org.mockito.Mockito; -import org.mockito.MockitoAnnotations; +import org.mockito.junit.MockitoJUnit; +import org.mockito.junit.MockitoRule; import java.time.Duration; import java.util.Arrays; @@ -88,6 +89,8 @@ public class VolumeControlServiceTest { private BroadcastReceiver mVolumeControlIntentReceiver; private FakeFeatureFlagsImpl mFakeFlagsImpl; + @Rule public MockitoRule mockitoRule = MockitoJUnit.rule(); + @Mock private AdapterService mAdapterService; @Mock private LeAudioService mLeAudioService; @Mock private DatabaseManager mDatabaseManager; @@ -101,8 +104,6 @@ public class VolumeControlServiceTest { @Before public void setUp() throws Exception { mTargetContext = InstrumentationRegistry.getTargetContext(); - // Set up mocks and test assets - MockitoAnnotations.initMocks(this); if (Looper.myLooper() == null) { Looper.prepare(); diff --git a/android/app/tests/unit/src/com/android/bluetooth/vc/VolumeControlStateMachineTest.java b/android/app/tests/unit/src/com/android/bluetooth/vc/VolumeControlStateMachineTest.java index 2082abd598..80d25bdb4f 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/vc/VolumeControlStateMachineTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/vc/VolumeControlStateMachineTest.java @@ -44,12 +44,14 @@ import org.hamcrest.core.IsInstanceOf; import org.junit.After; import org.junit.Assert; import org.junit.Before; +import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.ArgumentCaptor; import org.mockito.Mock; import org.mockito.Mockito; -import org.mockito.MockitoAnnotations; +import org.mockito.junit.MockitoJUnit; +import org.mockito.junit.MockitoRule; @MediumTest @RunWith(AndroidJUnit4.class) @@ -61,6 +63,8 @@ public class VolumeControlStateMachineTest { private BluetoothDevice mTestDevice; private static final int TIMEOUT_MS = 1000; + @Rule public MockitoRule mockitoRule = MockitoJUnit.rule(); + @Mock private AdapterService mAdapterService; @Mock private VolumeControlService mVolumeControlService; @Mock private VolumeControlNativeInterface mVolumeControlNativeInterface; @@ -69,8 +73,6 @@ public class VolumeControlStateMachineTest { public void setUp() throws Exception { mTargetContext = InstrumentationRegistry.getTargetContext(); InstrumentationRegistry.getInstrumentation().getUiAutomation().adoptShellPermissionIdentity(); - // Set up mocks and test assets - MockitoAnnotations.initMocks(this); TestUtils.setAdapterService(mAdapterService); mAdapter = BluetoothAdapter.getDefaultAdapter(); diff --git a/flags/gap.aconfig b/flags/gap.aconfig index 05d6ea38f5..5098a7461f 100644 --- a/flags/gap.aconfig +++ b/flags/gap.aconfig @@ -112,3 +112,10 @@ flag { description: "Remove ACL when there is not resource to handle more gatt connections." bug: "325929235" } + +flag { + name: "ble_scan_adv_metrics_redesign" + namespace: "bluetooth" + description: "Reimplement BLE scan and advertisement metrics logging." + bug: "328303508" +} diff --git a/flags/map.aconfig b/flags/map.aconfig new file mode 100644 index 0000000000..341b2b80e1 --- /dev/null +++ b/flags/map.aconfig @@ -0,0 +1,8 @@ +package: "com.android.bluetooth.flags" + +flag { + name: "map_limit_notification" + namespace: "bluetooth" + description: "Skip notyfing old messages in MAP" + bug: "325863406" +} diff --git a/framework/api/system-current.txt b/framework/api/system-current.txt index 04a169142f..2e39f52773 100644 --- a/framework/api/system-current.txt +++ b/framework/api/system-current.txt @@ -492,6 +492,8 @@ package android.bluetooth { field public static final int AUDIO_LOCATION_TOP_SIDE_LEFT = 262144; // 0x40000 field public static final int AUDIO_LOCATION_TOP_SIDE_RIGHT = 524288; // 0x80000 field public static final String EXTRA_LE_AUDIO_GROUP_ID = "android.bluetooth.extra.LE_AUDIO_GROUP_ID"; + field @FlaggedApi("com.android.bluetooth.flags.leaudio_callback_on_group_stream_status") public static final int GROUP_STREAM_STATUS_IDLE = 0; // 0x0 + field @FlaggedApi("com.android.bluetooth.flags.leaudio_callback_on_group_stream_status") public static final int GROUP_STREAM_STATUS_STREAMING = 1; // 0x1 } public static interface BluetoothLeAudio.Callback { diff --git a/framework/java/android/bluetooth/BluetoothAdapter.java b/framework/java/android/bluetooth/BluetoothAdapter.java index e0cdc2ce7b..509f8f3b80 100644 --- a/framework/java/android/bluetooth/BluetoothAdapter.java +++ b/framework/java/android/bluetooth/BluetoothAdapter.java @@ -5810,9 +5810,8 @@ public final class BluetoothAdapter { try { return mManagerService.isAutoOnSupported(); } catch (RemoteException e) { - e.rethrowFromSystemServer(); + throw e.rethrowFromSystemServer(); } - return false; } /** @@ -5829,9 +5828,8 @@ public final class BluetoothAdapter { try { return mManagerService.isAutoOnEnabled(); } catch (RemoteException e) { - e.rethrowFromSystemServer(); + throw e.rethrowFromSystemServer(); } - return false; } /** diff --git a/framework/java/android/bluetooth/BluetoothLeAudio.java b/framework/java/android/bluetooth/BluetoothLeAudio.java index ae0883b9b9..68bbdd9406 100644 --- a/framework/java/android/bluetooth/BluetoothLeAudio.java +++ b/framework/java/android/bluetooth/BluetoothLeAudio.java @@ -668,6 +668,7 @@ public final class BluetoothLeAudio implements BluetoothProfile, AutoCloseable { * @hide */ @FlaggedApi(Flags.FLAG_LEAUDIO_CALLBACK_ON_GROUP_STREAM_STATUS) + @SystemApi public static final int GROUP_STREAM_STATUS_IDLE = IBluetoothLeAudio.GROUP_STREAM_STATUS_IDLE; /** @@ -676,6 +677,7 @@ public final class BluetoothLeAudio implements BluetoothProfile, AutoCloseable { * @hide */ @FlaggedApi(Flags.FLAG_LEAUDIO_CALLBACK_ON_GROUP_STREAM_STATUS) + @SystemApi public static final int GROUP_STREAM_STATUS_STREAMING = IBluetoothLeAudio.GROUP_STREAM_STATUS_STREAMING; diff --git a/sysprop/Android.bp b/sysprop/Android.bp index b399a8d7b8..c2e71a97c8 100644 --- a/sysprop/Android.bp +++ b/sysprop/Android.bp @@ -10,6 +10,7 @@ sysprop_library { "avrcp.sysprop", "ble.sysprop", "bta.sysprop", + "device_id.sysprop", "hfp.sysprop", ], property_owner: "Platform", diff --git a/sysprop/device_id.sysprop b/sysprop/device_id.sysprop new file mode 100644 index 0000000000..b220abbe01 --- /dev/null +++ b/sysprop/device_id.sysprop @@ -0,0 +1,26 @@ +module: "android.sysprop.bluetooth.DeviceIDProperties" +owner: Platform + +prop { + api_name: "vendor_id" + type: Integer + scope: Internal + access: Readonly + prop_name: "bluetooth.device_id.vendor_id" +} + +prop { + api_name: "vendor_id_source" + type: Integer + scope: Internal + access: Readonly + prop_name: "bluetooth.device_id.vendor_id_source" +} + +prop { + api_name: "product_id" + type: Integer + scope: Internal + access: Readonly + prop_name: "bluetooth.device_id.product_id" +} diff --git a/sysprop/exported_include/android_bluetooth_sysprop.h b/sysprop/exported_include/android_bluetooth_sysprop.h index 3e76262114..e76411ef95 100644 --- a/sysprop/exported_include/android_bluetooth_sysprop.h +++ b/sysprop/exported_include/android_bluetooth_sysprop.h @@ -22,6 +22,7 @@ #include <avrcp.sysprop.h> #include <ble.sysprop.h> #include <bta.sysprop.h> +#include <device_id.sysprop.h> #include <hfp.sysprop.h> #define GET_SYSPROP(namespace, prop, default) \ diff --git a/system/bta/le_audio/client.cc b/system/bta/le_audio/client.cc index 4378553822..4c69c6f3c4 100644 --- a/system/bta/le_audio/client.cc +++ b/system/bta/le_audio/client.cc @@ -3442,10 +3442,6 @@ class LeAudioClientImpl : public LeAudioClient { return; } - if (DsaDataConsume(group, cis_conn_hdl, data, size, timestamp)) { - return; - } - uint16_t left_cis_handle = 0; uint16_t right_cis_handle = 0; for (auto [cis_handle, audio_location] : @@ -5262,6 +5258,10 @@ class LeAudioClientImpl : public LeAudioClient { auto* event = static_cast<bluetooth::hci::iso_manager::cis_data_evt*>(data); + if (DsaDataConsume(event)) { + return; + } + if (audio_receiver_state_ != AudioState::STARTED) { LOG_ERROR("receiver state not ready, current state=%s", ToString(audio_receiver_state_).c_str()); @@ -5809,16 +5809,34 @@ class LeAudioClientImpl : public LeAudioClient { le_audio::MetricsCollector::Get()->OnStreamEnded(active_group_id_); } - bool DsaDataConsume(LeAudioDeviceGroup* group, uint16_t cis_conn_hdl, - uint8_t* data, uint16_t size, uint32_t timestamp) { + bool DsaDataConsume(bluetooth::hci::iso_manager::cis_data_evt* event) { if (!IS_FLAG_ENABLED(leaudio_dynamic_spatial_audio)) { return false; } - if (iso_data_callback == nullptr || !group->dsa_.active || - group->dsa_.mode != DsaMode::ISO_SW) { + if (active_group_id_ == bluetooth::groups::kGroupUnknown) { return false; } + LeAudioDeviceGroup* group = aseGroups_.FindById(active_group_id_); + if (!group || !group->dsa_.active) { + return false; + } + + if (group->dsa_.mode != DsaMode::ISO_SW) { + LOG_WARN("ISO packets received over HCI in DSA mode: %d", + group->dsa_.mode); + return false; + } + + if (iso_data_callback == nullptr) { + LOG_WARN("Dsa data consumer not registered"); + return false; + } + + uint16_t cis_conn_hdl = event->cis_conn_hdl; + uint8_t* data = event->p_msg->data + event->p_msg->offset; + uint16_t size = event->p_msg->len - event->p_msg->offset; + uint32_t timestamp = event->ts; // Find LE Audio device LeAudioDevice* leAudioDevice = group->GetFirstDevice(); @@ -6202,6 +6220,7 @@ bool LeAudioClient::RegisterIsoDataConsumer(LeAudioIsoDataCallback callback) { return false; } + LOG_INFO("ISO data consumer changed"); iso_data_callback = callback; return true; } diff --git a/system/btif/Android.bp b/system/btif/Android.bp index 263ca2048a..6faaac5095 100644 --- a/system/btif/Android.bp +++ b/system/btif/Android.bp @@ -244,6 +244,7 @@ cc_library_static { "libbt-platform-protos-lite", "libbt-stack-core", "libbt_shim_bridge", + "libcom.android.sysprop.bluetooth.wrapped", "libflatbuffers-cpp", "libstatslog_bt", ], diff --git a/system/btif/src/btif_a2dp.cc b/system/btif/src/btif_a2dp.cc index 08af45e970..a76d317037 100644 --- a/system/btif/src/btif_a2dp.cc +++ b/system/btif/src/btif_a2dp.cc @@ -136,26 +136,46 @@ void btif_a2dp_on_stopped(tBTA_AV_SUSPEND* p_av_suspend, const A2dpType local_a2dp_type) { log::info("## ON A2DP STOPPED ## p_av_suspend={}", fmt::ptr(p_av_suspend)); - if (btif_av_get_peer_sep(local_a2dp_type) == AVDT_TSEP_SRC) { + const uint8_t peer_type_sep = btif_av_get_peer_sep(local_a2dp_type); + if (peer_type_sep == AVDT_TSEP_SRC) { btif_a2dp_sink_on_stopped(p_av_suspend); return; } - if (bluetooth::audio::a2dp::is_hal_enabled() || - !btif_av_is_a2dp_offload_running()) { - btif_a2dp_source_on_stopped(p_av_suspend); + if (!IS_FLAG_ENABLED(a2dp_concurrent_source_sink)) { + if (bluetooth::audio::a2dp::is_hal_enabled() || + !btif_av_is_a2dp_offload_running()) { + btif_a2dp_source_on_stopped(p_av_suspend); + return; + } + } else if (peer_type_sep == AVDT_TSEP_SNK) { + if (bluetooth::audio::a2dp::is_hal_enabled() || + !btif_av_is_a2dp_offload_running()) { + btif_a2dp_source_on_stopped(p_av_suspend); + return; + } } } void btif_a2dp_on_suspended(tBTA_AV_SUSPEND* p_av_suspend, const A2dpType local_a2dp_type) { log::info("## ON A2DP SUSPENDED ## p_av_suspend={}", fmt::ptr(p_av_suspend)); - if (btif_av_get_peer_sep(local_a2dp_type) == AVDT_TSEP_SRC) { + const uint8_t peer_type_sep = btif_av_get_peer_sep(local_a2dp_type); + if (peer_type_sep == AVDT_TSEP_SRC) { btif_a2dp_sink_on_suspended(p_av_suspend); return; } - if (bluetooth::audio::a2dp::is_hal_enabled() || - !btif_av_is_a2dp_offload_running()) { - btif_a2dp_source_on_suspended(p_av_suspend); + if (!IS_FLAG_ENABLED(a2dp_concurrent_source_sink)) { + if (bluetooth::audio::a2dp::is_hal_enabled() || + !btif_av_is_a2dp_offload_running()) { + btif_a2dp_source_on_suspended(p_av_suspend); + return; + } + } else if (peer_type_sep == AVDT_TSEP_SNK) { + if (bluetooth::audio::a2dp::is_hal_enabled() || + !btif_av_is_a2dp_offload_running()) { + btif_a2dp_source_on_suspended(p_av_suspend); + return; + } } } diff --git a/system/btif/src/btif_core.cc b/system/btif/src/btif_core.cc index 56ffd20f1e..9afbd01ec9 100644 --- a/system/btif/src/btif_core.cc +++ b/system/btif/src/btif_core.cc @@ -28,6 +28,8 @@ #define LOG_TAG "bt_btif_core" +#include <android_bluetooth_flags.h> +#include <android_bluetooth_sysprop.h> #include <base/at_exit.h> #include <base/functional/bind.h> #include <base/logging.h> @@ -216,8 +218,25 @@ void btif_enable_bluetooth_evt() { GetInterfaceToProfiles()->onBluetoothEnabled(); - /* load did configuration */ - bte_load_did_conf(BTE_DID_CONF_FILE); + if (!IS_FLAG_ENABLED(load_did_config_from_sysprops)) { + bte_load_did_conf(BTE_DID_CONF_FILE); + } else { + tSDP_DI_RECORD record = { + .vendor = uint16_t( + GET_SYSPROP(DeviceIDProperties, vendor_id, LMP_COMPID_GOOGLE)), + .vendor_id_source = uint16_t(GET_SYSPROP( + DeviceIDProperties, vendor_id_source, DI_VENDOR_ID_SOURCE_BTSIG)), + .product = uint16_t(GET_SYSPROP(DeviceIDProperties, product_id, 0)), + .primary_record = true, + }; + + uint32_t record_handle; + tBTA_STATUS status = BTA_DmSetLocalDiRecord(&record, &record_handle); + if (status != BTA_SUCCESS) { + log::error("unable to set device ID record error {}.", + bta_status_text(status)); + } + } btif_dm_load_local_oob(); diff --git a/system/btif/src/btif_sock.cc b/system/btif/src/btif_sock.cc index a8416c359d..944297113a 100644 --- a/system/btif/src/btif_sock.cc +++ b/system/btif/src/btif_sock.cc @@ -269,7 +269,6 @@ static bt_status_t btsock_listen(btsock_type_t type, const char* service_name, *sock_fd = INVALID_FD; bt_status_t status = BT_STATUS_FAIL; - int original_channel = channel; log_socket_connection_state(RawAddress::kEmpty, 0, type, android::bluetooth::SocketConnectionstateEnum:: @@ -286,19 +285,8 @@ static bt_status_t btsock_listen(btsock_type_t type, const char* service_name, btsock_l2cap_listen(service_name, channel, sock_fd, flags, app_uid); break; case BTSOCK_L2CAP_LE: - if (flags & BTSOCK_FLAG_NO_SDP) { - /* Set channel to zero so that it will be assigned */ - channel = 0; - } else if (channel <= 0) { - log::error("type BTSOCK_L2CAP_LE: invalid channel={}", channel); - break; - } - flags |= BTSOCK_FLAG_LE_COC; - log::info( - "type=BTSOCK_L2CAP_LE, channel=0x{:x}, original=0x{:x}, flags=0x{:x}", - channel, original_channel, flags); - status = - btsock_l2cap_listen(service_name, channel, sock_fd, flags, app_uid); + status = btsock_l2cap_listen(service_name, channel, sock_fd, + flags | BTSOCK_FLAG_LE_COC, app_uid); break; case BTSOCK_SCO: status = btsock_sco_listen(sock_fd, flags); diff --git a/system/btif/src/btif_sock_l2cap.cc b/system/btif/src/btif_sock_l2cap.cc index 528274a005..0ba85551b2 100644 --- a/system/btif/src/btif_sock_l2cap.cc +++ b/system/btif/src/btif_sock_l2cap.cc @@ -786,15 +786,25 @@ static bt_status_t btsock_l2cap_listen_or_connect(const char* name, int channel, int* sock_fd, int flags, char listen, int app_uid) { + if (!is_inited()) return BT_STATUS_NOT_READY; + bool is_le_coc = (flags & BTSOCK_FLAG_LE_COC) != 0; + if (is_le_coc && listen) { + if (flags & BTSOCK_FLAG_NO_SDP) { + /* For LE COC server; set channel to zero so that it will be assigned */ + channel = 0; + } else if (channel <= 0) { + log::error("type BTSOCK_L2CAP_LE: invalid channel={}", channel); + return BT_STATUS_FAIL; + } + } + if (!sock_fd) { log::info("Invalid socket descriptor"); return BT_STATUS_PARM_INVALID; } - if (!is_inited()) return BT_STATUS_NOT_READY; - // TODO: This is kind of bad to lock here, but it is needed for the current // design. std::unique_lock<std::mutex> lock(state_lock); diff --git a/system/log/src/vlog_android.cc b/system/log/src/vlog_android.cc index e5ca8f1fc8..0f235b0b6f 100644 --- a/system/log/src/vlog_android.cc +++ b/system/log/src/vlog_android.cc @@ -33,8 +33,13 @@ void vlog(Level level, char const* tag, char const* file_name, int line, } // Format to stack buffer. + // liblog uses a different default depending on the execution context + // (host or device); the file and line are not systematically included. + // In order to have consistent logs we include it manually in the log + // message. truncating_buffer<kBufferSize> buffer; - fmt::format_to(std::back_insert_iterator(buffer), "{}: ", function_name); + fmt::format_to(std::back_insert_iterator(buffer), "{}:{} {}: ", file_name, + line, function_name); fmt::vformat_to(std::back_insert_iterator(buffer), fmt, vargs); // Send message to liblog. @@ -43,8 +48,8 @@ void vlog(Level level, char const* tag, char const* file_name, int line, .buffer_id = LOG_ID_MAIN, .priority = static_cast<android_LogPriority>(level), .tag = tag, - .file = file_name, - .line = static_cast<uint32_t>(line), + .file = nullptr, + .line = 0, .message = buffer.c_str(), }; __android_log_write_log_message(&message); diff --git a/system/log/src/vlog_test.cc b/system/log/src/vlog_test.cc index f5f41b6c5d..5e341c7a33 100644 --- a/system/log/src/vlog_test.cc +++ b/system/log/src/vlog_test.cc @@ -51,10 +51,11 @@ TEST(BluetoothLoggerTest, verbose) { ASSERT_TRUE(androidLogMessage.has_value()); EXPECT_EQ(androidLogMessage->priority, ANDROID_LOG_VERBOSE); EXPECT_STREQ(androidLogMessage->tag, LOG_TAG); - EXPECT_STREQ(androidLogMessage->file, - "packages/modules/Bluetooth/system/log/src/vlog_test.cc"); - EXPECT_EQ(androidLogMessage->line, 49); - EXPECT_STREQ(androidLogMessage->message, "TestBody: verbose test"); + EXPECT_EQ(androidLogMessage->file, nullptr); + EXPECT_EQ(androidLogMessage->line, 0); + EXPECT_STREQ(androidLogMessage->message, + "packages/modules/Bluetooth/system/log/src/vlog_test.cc:49 " + "TestBody: verbose test"); } TEST(BluetoothLoggerTest, debug) { @@ -65,10 +66,11 @@ TEST(BluetoothLoggerTest, debug) { ASSERT_TRUE(androidLogMessage.has_value()); EXPECT_EQ(androidLogMessage->priority, ANDROID_LOG_DEBUG); EXPECT_STREQ(androidLogMessage->tag, LOG_TAG); - EXPECT_STREQ(androidLogMessage->file, - "packages/modules/Bluetooth/system/log/src/vlog_test.cc"); - EXPECT_EQ(androidLogMessage->line, 63); - EXPECT_STREQ(androidLogMessage->message, "TestBody: debug test"); + EXPECT_STREQ(androidLogMessage->file, nullptr); + EXPECT_EQ(androidLogMessage->line, 0); + EXPECT_STREQ(androidLogMessage->message, + "packages/modules/Bluetooth/system/log/src/vlog_test.cc:64 " + "TestBody: debug test"); } TEST(BluetoothLoggerTest, info) { @@ -79,10 +81,11 @@ TEST(BluetoothLoggerTest, info) { ASSERT_TRUE(androidLogMessage.has_value()); EXPECT_EQ(androidLogMessage->priority, ANDROID_LOG_INFO); EXPECT_STREQ(androidLogMessage->tag, LOG_TAG); - EXPECT_STREQ(androidLogMessage->file, - "packages/modules/Bluetooth/system/log/src/vlog_test.cc"); - EXPECT_EQ(androidLogMessage->line, 77); - EXPECT_STREQ(androidLogMessage->message, "TestBody: info test"); + EXPECT_STREQ(androidLogMessage->file, nullptr); + EXPECT_EQ(androidLogMessage->line, 0); + EXPECT_STREQ(androidLogMessage->message, + "packages/modules/Bluetooth/system/log/src/vlog_test.cc:79 " + "TestBody: info test"); } TEST(BluetoothLoggerTest, warn) { @@ -93,10 +96,11 @@ TEST(BluetoothLoggerTest, warn) { ASSERT_TRUE(androidLogMessage.has_value()); EXPECT_EQ(androidLogMessage->priority, ANDROID_LOG_WARN); EXPECT_STREQ(androidLogMessage->tag, LOG_TAG); - EXPECT_STREQ(androidLogMessage->file, - "packages/modules/Bluetooth/system/log/src/vlog_test.cc"); - EXPECT_EQ(androidLogMessage->line, 91); - EXPECT_STREQ(androidLogMessage->message, "TestBody: warn test"); + EXPECT_STREQ(androidLogMessage->file, nullptr); + EXPECT_EQ(androidLogMessage->line, 0); + EXPECT_STREQ(androidLogMessage->message, + "packages/modules/Bluetooth/system/log/src/vlog_test.cc:94 " + "TestBody: warn test"); } TEST(BluetoothLoggerTest, error) { @@ -107,10 +111,11 @@ TEST(BluetoothLoggerTest, error) { ASSERT_TRUE(androidLogMessage.has_value()); EXPECT_EQ(androidLogMessage->priority, ANDROID_LOG_ERROR); EXPECT_STREQ(androidLogMessage->tag, LOG_TAG); - EXPECT_STREQ(androidLogMessage->file, - "packages/modules/Bluetooth/system/log/src/vlog_test.cc"); - EXPECT_EQ(androidLogMessage->line, 105); - EXPECT_STREQ(androidLogMessage->message, "TestBody: error test"); + EXPECT_STREQ(androidLogMessage->file, nullptr); + EXPECT_EQ(androidLogMessage->line, 0); + EXPECT_STREQ(androidLogMessage->message, + "packages/modules/Bluetooth/system/log/src/vlog_test.cc:109 " + "TestBody: error test"); } TEST(BluetoothLoggerTest, null_string_parameter) { @@ -118,17 +123,23 @@ TEST(BluetoothLoggerTest, null_string_parameter) { char const* const_null_str = nullptr; log::info("input: {}", const_null_str); - EXPECT_STREQ(androidLogMessage->message, "TestBody: input: (nullptr)"); + EXPECT_STREQ(androidLogMessage->message, + "packages/modules/Bluetooth/system/log/src/vlog_test.cc:125 " + "TestBody: input: (nullptr)"); androidLogMessage.reset(); char* null_str = nullptr; log::info("input: {}", null_str); - EXPECT_STREQ(androidLogMessage->message, "TestBody: input: (nullptr)"); + EXPECT_STREQ(androidLogMessage->message, + "packages/modules/Bluetooth/system/log/src/vlog_test.cc:133 " + "TestBody: input: (nullptr)"); androidLogMessage.reset(); char const* nonnull_str = "hello world"; log::info("input: {}", nonnull_str); - EXPECT_STREQ(androidLogMessage->message, "TestBody: input: hello world"); + EXPECT_STREQ(androidLogMessage->message, + "packages/modules/Bluetooth/system/log/src/vlog_test.cc:141 " + "TestBody: input: hello world"); } diff --git a/system/test/suite/Android.bp b/system/test/suite/Android.bp index fcfe5c88fa..505d7ab089 100644 --- a/system/test/suite/Android.bp +++ b/system/test/suite/Android.bp @@ -41,9 +41,6 @@ cc_defaults { "adapter/bluetooth_test.cc", ], shared_libs: [ - "android.hardware.bluetooth.audio@2.0", - "android.hardware.bluetooth.audio@2.1", - "android.system.suspend-V1-ndk", "libPlatformProperties", "libaaudio", "libbinder", @@ -57,7 +54,13 @@ cc_defaults { "libutils", ], static_libs: [ + "android.hardware.audio.common@5.0", "android.hardware.bluetooth.a2dp@1.0", + "android.hardware.bluetooth.audio@2.0", + "android.hardware.bluetooth.audio@2.1", + "android.hardware.common-V2-ndk", + "android.hardware.common.fmq-V1-ndk", + "android.system.suspend-V1-ndk", "android.system.suspend.control-V1-ndk", "avrcp-target-service", "lib-bt-packets", |