diff options
56 files changed, 470 insertions, 3406 deletions
diff --git a/android/app/jni/com_android_bluetooth_btservice_AdapterService.cpp b/android/app/jni/com_android_bluetooth_btservice_AdapterService.cpp index 78db0b3a10..b8efc561cb 100644 --- a/android/app/jni/com_android_bluetooth_btservice_AdapterService.cpp +++ b/android/app/jni/com_android_bluetooth_btservice_AdapterService.cpp @@ -1727,21 +1727,6 @@ static void dumpNative(JNIEnv* env, jobject /* obj */, jobject fdObj, jobjectArr delete[] argObjs; } -static jbyteArray dumpMetricsNative(JNIEnv* env, jobject /* obj */) { - log::info(""); - if (!sBluetoothInterface) { - return env->NewByteArray(0); - } - - std::string output; - sBluetoothInterface->dumpMetrics(&output); - jsize output_size = output.size() * sizeof(char); - jbyteArray output_bytes = env->NewByteArray(output_size); - env->SetByteArrayRegion(output_bytes, 0, output_size, - reinterpret_cast<const jbyte*>(output.data())); - return output_bytes; -} - static jboolean factoryResetNative(JNIEnv* /* env */, jobject /* obj */) { log::verbose(""); if (!sBluetoothInterface) { @@ -2307,7 +2292,6 @@ static int register_com_android_bluetooth_btservice_AdapterService(JNIEnv* env) {"readEnergyInfoNative", "()I", reinterpret_cast<void*>(readEnergyInfoNative)}, {"dumpNative", "(Ljava/io/FileDescriptor;[Ljava/lang/String;)V", reinterpret_cast<void*>(dumpNative)}, - {"dumpMetricsNative", "()[B", reinterpret_cast<void*>(dumpMetricsNative)}, {"factoryResetNative", "()Z", reinterpret_cast<void*>(factoryResetNative)}, {"obfuscateAddressNative", "([B)[B", reinterpret_cast<void*>(obfuscateAddressNative)}, {"setBufferLengthMillisNative", "(II)Z", diff --git a/android/app/src/com/android/bluetooth/avrcpcontroller/AvrcpControllerService.java b/android/app/src/com/android/bluetooth/avrcpcontroller/AvrcpControllerService.java index 12344bd56d..4551f320da 100644 --- a/android/app/src/com/android/bluetooth/avrcpcontroller/AvrcpControllerService.java +++ b/android/app/src/com/android/bluetooth/avrcpcontroller/AvrcpControllerService.java @@ -125,13 +125,13 @@ public class AvrcpControllerService extends ProfileService { "Image downloaded [device: " + device + ", uuid: " - + event.getUuid() + + event.uuid() + ", uri: " - + event.getUri()); + + event.uri()); AvrcpControllerStateMachine stateMachine = getStateMachine(device); if (stateMachine == null) { Log.e(TAG, "No state machine found for device " + device); - mCoverArtManager.removeImage(device, event.getUuid()); + mCoverArtManager.removeImage(device, event.uuid()); return; } stateMachine.sendMessage( diff --git a/android/app/src/com/android/bluetooth/avrcpcontroller/AvrcpControllerStateMachine.java b/android/app/src/com/android/bluetooth/avrcpcontroller/AvrcpControllerStateMachine.java index a7475476b4..a74ec6c0e9 100644 --- a/android/app/src/com/android/bluetooth/avrcpcontroller/AvrcpControllerStateMachine.java +++ b/android/app/src/com/android/bluetooth/avrcpcontroller/AvrcpControllerStateMachine.java @@ -722,8 +722,8 @@ class AvrcpControllerStateMachine extends StateMachine { case MESSAGE_PROCESS_IMAGE_DOWNLOADED: AvrcpCoverArtManager.DownloadEvent event = (AvrcpCoverArtManager.DownloadEvent) msg.obj; - String uuid = event.getUuid(); - Uri uri = event.getUri(); + String uuid = event.uuid(); + Uri uri = event.uri(); debug("Connected: Received image for " + uuid + " at " + uri.toString()); // Let the addressed player know we got an image so it can see if the current diff --git a/android/app/src/com/android/bluetooth/avrcpcontroller/AvrcpCoverArtManager.java b/android/app/src/com/android/bluetooth/avrcpcontroller/AvrcpCoverArtManager.java index 64648082fe..5a64436f9f 100644 --- a/android/app/src/com/android/bluetooth/avrcpcontroller/AvrcpCoverArtManager.java +++ b/android/app/src/com/android/bluetooth/avrcpcontroller/AvrcpCoverArtManager.java @@ -39,43 +39,35 @@ import java.util.concurrent.ConcurrentHashMap; * <p>When given an image handle and device, this manager will negotiate the downloaded image * properties, download the image, and place it into a Content Provider for others to retrieve from */ -public class AvrcpCoverArtManager { +class AvrcpCoverArtManager { private static final String TAG = AvrcpCoverArtManager.class.getSimpleName(); // Image Download Schemes for cover art - public static final String AVRCP_CONTROLLER_COVER_ART_SCHEME = + private static final String AVRCP_CONTROLLER_COVER_ART_SCHEME = "persist.bluetooth.avrcpcontroller.BIP_DOWNLOAD_SCHEME"; - public static final String SCHEME_NATIVE = "native"; - public static final String SCHEME_THUMBNAIL = "thumbnail"; + private static final String SCHEME_NATIVE = "native"; + private static final String SCHEME_THUMBNAIL = "thumbnail"; - private final AvrcpControllerService mService; - protected final Map<BluetoothDevice, AvrcpBipClient> mClients = new ConcurrentHashMap<>(1); + private final Map<BluetoothDevice, AvrcpBipClient> mClients = new ConcurrentHashMap<>(1); private final Map<BluetoothDevice, AvrcpBipSession> mBipSessions = new ConcurrentHashMap<>(1); + private final AvrcpControllerService mService; private final AvrcpCoverArtStorage mCoverArtStorage; private final Callback mCallback; private final String mDownloadScheme; + AvrcpCoverArtManager(AvrcpControllerService service, Callback callback) { + mService = service; + mCoverArtStorage = new AvrcpCoverArtStorage(mService); + mCallback = callback; + mDownloadScheme = SystemProperties.get(AVRCP_CONTROLLER_COVER_ART_SCHEME, SCHEME_THUMBNAIL); + mCoverArtStorage.clear(); + } + /** * An object representing an image download event. Contains the information necessary to * retrieve the image from storage. */ - public static class DownloadEvent { - final String mImageUuid; - final Uri mUri; - - public DownloadEvent(String uuid, Uri uri) { - mImageUuid = uuid; - mUri = uri; - } - - public String getUuid() { - return mImageUuid; - } - - public Uri getUri() { - return mUri; - } - } + record DownloadEvent(String uuid, Uri uri) {} interface Callback { /** @@ -97,7 +89,7 @@ public class AvrcpCoverArtManager { private final Map<String, String> mUuids = new ConcurrentHashMap<>(1); // handle -> UUID private final Map<String, String> mHandles = new ConcurrentHashMap<>(1); // UUID -> handle - public String getHandleUuid(String handle) { + private String getHandleUuid(String handle) { if (!isValidImageHandle(handle)) return null; String newUuid = UUID.randomUUID().toString(); String existingUuid = mUuids.putIfAbsent(handle, newUuid); @@ -106,16 +98,16 @@ public class AvrcpCoverArtManager { return newUuid; } - public String getUuidHandle(String uuid) { + private String getUuidHandle(String uuid) { return mHandles.get(uuid); } - public void clearHandleUuids() { + private void clearHandleUuids() { mUuids.clear(); mHandles.clear(); } - public Set<String> getSessionHandles() { + private Set<String> getSessionHandles() { return mUuids.keySet(); } } @@ -128,7 +120,7 @@ public class AvrcpCoverArtManager { * * @return True if the input string is a valid image handle */ - public static boolean isValidImageHandle(String handle) { + static boolean isValidImageHandle(String handle) { if (handle == null || handle.length() != 7) return false; for (int i = 0; i < handle.length(); i++) { char c = handle.charAt(i); @@ -139,14 +131,6 @@ public class AvrcpCoverArtManager { return true; } - public AvrcpCoverArtManager(AvrcpControllerService service, Callback callback) { - mService = service; - mCoverArtStorage = new AvrcpCoverArtStorage(mService); - mCallback = callback; - mDownloadScheme = SystemProperties.get(AVRCP_CONTROLLER_COVER_ART_SCHEME, SCHEME_THUMBNAIL); - mCoverArtStorage.clear(); - } - /** * Create a client and connect to a remote device's BIP Image Pull Server * @@ -154,7 +138,7 @@ public class AvrcpCoverArtManager { * @param psm The Protocol Service Multiplexer that the remote device is hosting the server on * @return True if the connection is successfully queued, False otherwise. */ - public synchronized boolean connect(BluetoothDevice device, int psm) { + synchronized boolean connect(BluetoothDevice device, int psm) { debug("Connect " + device + ", psm: " + psm); if (mClients.containsKey(device)) return false; AvrcpBipClient client = new AvrcpBipClient(device, psm, new BipClientCallback(device)); @@ -170,7 +154,7 @@ public class AvrcpCoverArtManager { * @param device The remote Bluetooth device you wish to refresh * @return True if the refresh is successfully queued, False otherwise. */ - public synchronized boolean refreshSession(BluetoothDevice device) { + synchronized boolean refreshSession(BluetoothDevice device) { debug("Refresh OBEX session for " + device); AvrcpBipClient client = getClient(device); if (client == null) { @@ -187,7 +171,7 @@ public class AvrcpCoverArtManager { * @param device The remote Bluetooth device you wish to disconnect from * @return True if the disconnection is successfully queued, False otherwise. */ - public synchronized boolean disconnect(BluetoothDevice device) { + synchronized boolean disconnect(BluetoothDevice device) { debug("Disconnect " + device); AvrcpBipClient client = getClient(device); if (client == null) { @@ -206,7 +190,7 @@ public class AvrcpCoverArtManager { * * <p>Please call when you've committed to shutting down the service. */ - public synchronized void cleanup() { + synchronized void cleanup() { debug("Clean up and shutdown"); for (BluetoothDevice device : mClients.keySet()) { disconnect(device); @@ -219,7 +203,7 @@ public class AvrcpCoverArtManager { * @param device The Bluetooth device you want connection status for * @return Connection status, based on STATE_* constants */ - public int getState(BluetoothDevice device) { + int getState(BluetoothDevice device) { AvrcpBipClient client = getClient(device); if (client == null) return STATE_DISCONNECTED; return client.getState(); @@ -241,7 +225,7 @@ public class AvrcpCoverArtManager { * @return A string UUID by which the handle can be identified during the life of the BIP * connection. */ - public String getUuidForHandle(BluetoothDevice device, String handle) { + String getUuidForHandle(BluetoothDevice device, String handle) { AvrcpBipSession session = getSession(device); if (session == null || !isValidImageHandle(handle)) return null; return session.getHandleUuid(handle); @@ -256,13 +240,13 @@ public class AvrcpCoverArtManager { * @param uuid The UUID you want the associated handle for * @return The image handle associated with this UUID if it exists, null otherwise. */ - public String getHandleForUuid(BluetoothDevice device, String uuid) { + String getHandleForUuid(BluetoothDevice device, String uuid) { AvrcpBipSession session = getSession(device); if (session == null || uuid == null) return null; return session.getUuidHandle(uuid); } - private void clearHandleUuids(BluetoothDevice device) { + void clearHandleUuids(BluetoothDevice device) { AvrcpBipSession session = getSession(device); if (session == null) return; session.clearHandleUuids(); @@ -275,7 +259,7 @@ public class AvrcpCoverArtManager { * @param imageUuid The UUID associated with the image you want * @return A Uri the image can be found at, null if it does not exist */ - public Uri getImageUri(BluetoothDevice device, String imageUuid) { + Uri getImageUri(BluetoothDevice device, String imageUuid) { if (mCoverArtStorage.doesImageExist(device, imageUuid)) { return AvrcpCoverArtProvider.getImageUri(device, imageUuid); } @@ -296,7 +280,7 @@ public class AvrcpCoverArtManager { * translated into an image handle. * @return A Uri that will be assign to the image once the download is complete */ - public Uri downloadImage(BluetoothDevice device, String imageUuid) { + Uri downloadImage(BluetoothDevice device, String imageUuid) { debug("Download Image - device: " + device + ", Handle: " + imageUuid); AvrcpBipClient client = getClient(device); if (client == null) { @@ -331,7 +315,7 @@ public class AvrcpCoverArtManager { * @param device The remote Bluetooth device associated with the image * @param imageUuid The UUID associated with the image you wish to retrieve */ - public Bitmap getImage(BluetoothDevice device, String imageUuid) { + Bitmap getImage(BluetoothDevice device, String imageUuid) { return mCoverArtStorage.getImage(device, imageUuid); } @@ -341,7 +325,7 @@ public class AvrcpCoverArtManager { * @param device The remote Bluetooth device associated with the image * @param imageUuid The UUID associated with the image you wish to remove */ - public void removeImage(BluetoothDevice device, String imageUuid) { + void removeImage(BluetoothDevice device, String imageUuid) { mCoverArtStorage.removeImage(device, imageUuid); } @@ -396,7 +380,7 @@ public class AvrcpCoverArtManager { /** Callback for facilitating image download */ class BipClientCallback implements AvrcpBipClient.Callback { - final BluetoothDevice mDevice; + private final BluetoothDevice mDevice; BipClientCallback(BluetoothDevice device) { mDevice = device; diff --git a/android/app/src/com/android/bluetooth/btservice/AdapterNativeInterface.java b/android/app/src/com/android/bluetooth/btservice/AdapterNativeInterface.java index 244e132a66..63d11202a1 100644 --- a/android/app/src/com/android/bluetooth/btservice/AdapterNativeInterface.java +++ b/android/app/src/com/android/bluetooth/btservice/AdapterNativeInterface.java @@ -179,10 +179,6 @@ public class AdapterNativeInterface { dumpNative(fd, arguments); } - byte[] dumpMetrics() { - return dumpMetricsNative(); - } - byte[] obfuscateAddress(byte[] address) { return obfuscateAddressNative(address); } @@ -401,8 +397,6 @@ public class AdapterNativeInterface { private native void dumpNative(FileDescriptor fd, String[] arguments); - private native byte[] dumpMetricsNative(); - private native byte[] obfuscateAddressNative(byte[] address); private native boolean setBufferLengthMillisNative(int codec, int value); diff --git a/android/app/src/com/android/bluetooth/btservice/AdapterService.java b/android/app/src/com/android/bluetooth/btservice/AdapterService.java index 39c8eda0dc..c428d0b14f 100644 --- a/android/app/src/com/android/bluetooth/btservice/AdapterService.java +++ b/android/app/src/com/android/bluetooth/btservice/AdapterService.java @@ -1109,7 +1109,7 @@ public class AdapterService extends Service { if (mScanController == null) { mAdapterStateMachine.sendMessage(AdapterState.BLE_STOPPED); } else { - mScanController.stop(); + mScanController.cleanup(); mScanController = null; mNativeInterface.disable(); } @@ -6670,12 +6670,6 @@ public class AdapterService extends Service { return; } - Log.v(TAG, "dumpsys arguments, check for protobuf output: " + TextUtils.join(" ", args)); - if (args[0].equals("--proto-bin")) { - dumpMetrics(fd); - return; - } - writer.println(); mAdapterProperties.dump(fd, writer, args); @@ -6737,39 +6731,6 @@ public class AdapterService extends Service { } } - private void dumpMetrics(FileDescriptor fd) { - BluetoothMetricsProto.BluetoothLog.Builder metricsBuilder = - BluetoothMetricsProto.BluetoothLog.newBuilder(); - byte[] nativeMetricsBytes = mNativeInterface.dumpMetrics(); - Log.d(TAG, "dumpMetrics: native metrics size is " + nativeMetricsBytes.length); - if (nativeMetricsBytes.length > 0) { - try { - metricsBuilder.mergeFrom(nativeMetricsBytes); - } catch (InvalidProtocolBufferException ex) { - Log.w(TAG, "dumpMetrics: problem parsing metrics protobuf, " + ex.getMessage()); - return; - } - } - metricsBuilder.setNumBondedDevices(getBondedDevices().length); - MetricsLogger.dumpProto(metricsBuilder); - for (ProfileService profile : mRegisteredProfiles) { - profile.dumpProto(metricsBuilder); - } - if (Flags.onlyStartScanDuringBleOn()) { - ScanController scanController = mScanController; - if (scanController != null) { - scanController.dumpProto(metricsBuilder); - } - } - byte[] metricsBytes = Base64.encode(metricsBuilder.build().toByteArray(), Base64.DEFAULT); - Log.d(TAG, "dumpMetrics: combined metrics size is " + metricsBytes.length); - try (FileOutputStream protoOut = new FileOutputStream(fd)) { - protoOut.write(metricsBytes); - } catch (IOException e) { - Log.e(TAG, "dumpMetrics: error writing combined protobuf to fd, " + e.getMessage()); - } - } - @SuppressLint("AndroidFrameworkRequiresPermission") private void enforceBluetoothPrivilegedPermissionIfNeeded( OobData remoteP192Data, OobData remoteP256Data) { diff --git a/android/app/src/com/android/bluetooth/gatt/AdvertiseManager.java b/android/app/src/com/android/bluetooth/gatt/AdvertiseManager.java index 1785ee2e5a..53a90d58fc 100644 --- a/android/app/src/com/android/bluetooth/gatt/AdvertiseManager.java +++ b/android/app/src/com/android/bluetooth/gatt/AdvertiseManager.java @@ -16,6 +16,8 @@ package com.android.bluetooth.gatt; +import static com.android.bluetooth.gatt.AdvertiseHelper.advertiseDataToBytes; + import android.app.ActivityManager; import android.bluetooth.le.AdvertiseCallback; import android.bluetooth.le.AdvertiseData; @@ -50,15 +52,15 @@ public class AdvertiseManager { private static final long RUN_SYNC_WAIT_TIME_MS = 2000L; + private final Map<IBinder, AdvertiserInfo> mAdvertisers = new HashMap<>(); + private final AdapterService mService; private final AdvertiseManagerNativeInterface mNativeInterface; private final AdvertiseBinder mAdvertiseBinder; private final AdvertiserMap mAdvertiserMap; private final ActivityManager mActivityManager; - - private final Map<IBinder, AdvertiserInfo> mAdvertisers = new HashMap<>(); - private final Handler mHandler; + private volatile boolean mIsAvailable = true; @VisibleForTesting int mTempRegistrationId = -1; @@ -81,7 +83,6 @@ public class AdvertiseManager { mNativeInterface = nativeInterface; mAdvertiserMap = advertiserMap; mActivityManager = mService.getSystemService(ActivityManager.class); - mNativeInterface.init(this); mHandler = new Handler(advertiseLooper); mAdvertiseBinder = new AdvertiseBinder(service, this); @@ -108,22 +109,12 @@ public class AdvertiseManager { return mAdvertiseBinder; } - static class AdvertiserInfo { - /* When id is negative, the registration is ongoing. When the registration finishes, id - * becomes equal to advertiser_id */ - public Integer id; - public AdvertisingSetDeathRecipient deathRecipient; - public IAdvertisingSetCallback callback; - - AdvertiserInfo( - Integer id, - AdvertisingSetDeathRecipient deathRecipient, - IAdvertisingSetCallback callback) { - this.id = id; - this.deathRecipient = deathRecipient; - this.callback = callback; - } - } + private record AdvertiserInfo( + /* When id is negative, the registration is ongoing. When the registration finishes, id + * becomes equal to advertiser_id */ + Integer id, + AdvertisingSetDeathRecipient deathRecipient, + IAdvertisingSetCallback callback) {} private interface CallbackWrapper { void call() throws RemoteException; @@ -150,14 +141,10 @@ public class AdvertiseManager { } private Map.Entry<IBinder, AdvertiserInfo> findAdvertiser(int advertiserId) { - Map.Entry<IBinder, AdvertiserInfo> entry = null; - for (Map.Entry<IBinder, AdvertiserInfo> e : mAdvertisers.entrySet()) { - if (e.getValue().id == advertiserId) { - entry = e; - break; - } - } - return entry; + return mAdvertisers.entrySet().stream() + .filter(e -> e.getValue().id == advertiserId) + .findFirst() + .orElse(null); } void onAdvertisingSetStarted(int regId, int advertiserId, int txPower, int status) { @@ -172,7 +159,6 @@ public class AdvertiseManager { checkThread(); Map.Entry<IBinder, AdvertiserInfo> entry = findAdvertiser(regId); - if (entry == null) { Log.i(TAG, "onAdvertisingSetStarted() - no callback found for regId " + regId); // Advertising set was stopped before it was properly registered. @@ -180,15 +166,14 @@ public class AdvertiseManager { return; } + AdvertisingSetDeathRecipient deathRecipient = entry.getValue().deathRecipient; IAdvertisingSetCallback callback = entry.getValue().callback; if (status == 0) { - entry.setValue( - new AdvertiserInfo(advertiserId, entry.getValue().deathRecipient, callback)); - + entry.setValue(new AdvertiserInfo(advertiserId, deathRecipient, callback)); mAdvertiserMap.setAdvertiserIdByRegId(regId, advertiserId); } else { IBinder binder = entry.getKey(); - binder.unlinkToDeath(entry.getValue().deathRecipient, 0); + binder.unlinkToDeath(deathRecipient, 0); mAdvertisers.remove(binder); AppAdvertiseStats stats = mAdvertiserMap.getAppAdvertiseStatsById(regId); @@ -304,13 +289,11 @@ public class AdvertiseManager { throw new IllegalArgumentException("Can't link to advertiser's death"); } - String deviceName = mService.getName(); + final String deviceName = mService.getName(); try { - byte[] advDataBytes = AdvertiseHelper.advertiseDataToBytes(advertiseData, deviceName); - byte[] scanResponseBytes = - AdvertiseHelper.advertiseDataToBytes(scanResponse, deviceName); - byte[] periodicDataBytes = - AdvertiseHelper.advertiseDataToBytes(periodicData, deviceName); + byte[] advDataBytes = advertiseDataToBytes(advertiseData, deviceName); + byte[] scanResponseBytes = advertiseDataToBytes(scanResponse, deviceName); + byte[] periodicDataBytes = advertiseDataToBytes(periodicData, deviceName); int cbId = --mTempRegistrationId; mAdvertisers.put(binder, new AdvertiserInfo(cbId, deathRecipient, callback)); @@ -430,10 +413,10 @@ public class AdvertiseManager { Log.w(TAG, "setAdvertisingData() - bad advertiserId " + advertiserId); return; } - String deviceName = mService.getName(); + final String deviceName = mService.getName(); try { mNativeInterface.setAdvertisingData( - advertiserId, AdvertiseHelper.advertiseDataToBytes(data, deviceName)); + advertiserId, advertiseDataToBytes(data, deviceName)); mAdvertiserMap.setAdvertisingData(advertiserId, data); } catch (IllegalArgumentException e) { @@ -453,10 +436,10 @@ public class AdvertiseManager { Log.w(TAG, "setScanResponseData() - bad advertiserId " + advertiserId); return; } - String deviceName = mService.getName(); + final String deviceName = mService.getName(); try { mNativeInterface.setScanResponseData( - advertiserId, AdvertiseHelper.advertiseDataToBytes(data, deviceName)); + advertiserId, advertiseDataToBytes(data, deviceName)); mAdvertiserMap.setScanResponseData(advertiserId, data); } catch (IllegalArgumentException e) { @@ -501,10 +484,10 @@ public class AdvertiseManager { Log.w(TAG, "setPeriodicAdvertisingData() - bad advertiserId " + advertiserId); return; } - String deviceName = mService.getName(); + final String deviceName = mService.getName(); try { mNativeInterface.setPeriodicAdvertisingData( - advertiserId, AdvertiseHelper.advertiseDataToBytes(data, deviceName)); + advertiserId, advertiseDataToBytes(data, deviceName)); mAdvertiserMap.setPeriodicAdvertisingData(advertiserId, data); } catch (IllegalArgumentException e) { diff --git a/android/app/src/com/android/bluetooth/gatt/GattService.java b/android/app/src/com/android/bluetooth/gatt/GattService.java index 09c648f2be..65e0497420 100644 --- a/android/app/src/com/android/bluetooth/gatt/GattService.java +++ b/android/app/src/com/android/bluetooth/gatt/GattService.java @@ -228,7 +228,7 @@ public class GattService extends ProfileService { setGattService(null); } if (mScanController != null) { - mScanController.stop(); + mScanController.cleanup(); } mClientMap.clear(); mRestrictedHandles.clear(); diff --git a/android/app/src/com/android/bluetooth/le_scan/ScanController.java b/android/app/src/com/android/bluetooth/le_scan/ScanController.java index abccaaefc5..6e1678d97e 100644 --- a/android/app/src/com/android/bluetooth/le_scan/ScanController.java +++ b/android/app/src/com/android/bluetooth/le_scan/ScanController.java @@ -114,26 +114,6 @@ public class ScanController { "0201061AFF4C000215426C7565436861726D426561636F6E730EFE1355C509168020691E0EFE13551109426C7565436861726D5F31363936383500000000", }; - record PendingIntentInfo( - PendingIntent intent, - ScanSettings settings, - List<ScanFilter> filters, - String callingPackage, - 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(); - } - } - private final PendingIntent.CancelListener mScanIntentCancelListener = new PendingIntent.CancelListener() { public void onCanceled(PendingIntent intent) { @@ -142,34 +122,29 @@ public class ScanController { } }; - private final BluetoothAdapter mAdapter; - private final AdapterService mAdapterService; + /** Internal list of scan events to use with the proto */ + private final Deque<BluetoothMetricsProto.ScanEvent> mScanEvents = + new ArrayDeque<>(NUM_SCAN_EVENTS_KEPT); private final Map<Integer, Integer> mFilterIndexToMsftAdvMonitorMap = new HashMap<>(); - private final String mExposureNotificationPackage; + private final Object mTestModeLock = new Object(); + private final BluetoothAdapter mAdapter; + private final AdapterService mAdapterService; + private final String mExposureNotificationPackage; + private final Predicate<ScanResult> mLocationDenylistPredicate; + private final Looper mMainLooper; + private final ScanBinder mBinder; + private final HandlerThread mScanThread; private final AppOpsManager mAppOps; private final CompanionDeviceManager mCompanionManager; - private final PeriodicScanManager mPeriodicScanManager; private final ScanManager mScanManager; + private final PeriodicScanManager mPeriodicScanManager; - private final ScanBinder mBinder; - private final HandlerThread mScanThread; - - /** Internal list of scan events to use with the proto */ - private final Deque<BluetoothMetricsProto.ScanEvent> mScanEvents = - new ArrayDeque<>(NUM_SCAN_EVENTS_KEPT); - - private final Predicate<ScanResult> mLocationDenylistPredicate; - + private volatile boolean mTestModeEnabled = false; private ScannerMap mScannerMap = new ScannerMap(); - private boolean mIsAvailable; - - private volatile boolean mTestModeEnabled = false; - private final Looper mMainLooper; private Handler mTestModeHandler; - private final Object mTestModeLock = new Object(); public ScanController(AdapterService adapterService) { mAdapter = BluetoothAdapter.getDefaultAdapter(); @@ -211,8 +186,8 @@ public class ScanController { mPeriodicScanManager = ScanObjectsFactory.getInstance().createPeriodicScanManager(); } - public void stop() { - Log.d(TAG, "stop()"); + public void cleanup() { + Log.i(TAG, "Cleanup ScanController"); mIsAvailable = false; mBinder.clearScanController(); mScanThread.quitSafely(); @@ -282,6 +257,26 @@ public class ScanController { } } + record PendingIntentInfo( + PendingIntent intent, + ScanSettings settings, + List<ScanFilter> filters, + String callingPackage, + 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(); + } + } + /************************************************************************** * Callback functions - CLIENT *************************************************************************/ @@ -430,8 +425,8 @@ public class ScanController { continue; } - ScanSettings settings = client.mSettings; - byte[] scanRecordData; + final ScanSettings settings = client.mSettings; + final byte[] scanRecordData; // This is for compatibility with applications that assume fixed size scan data. if (settings.getLegacy()) { if ((eventType & ET_LEGACY_MASK) == 0) { @@ -494,7 +489,7 @@ public class ScanController { int callbackType = settings.getCallbackType(); if (!(callbackType == ScanSettings.CALLBACK_TYPE_ALL_MATCHES || callbackType == ScanSettings.CALLBACK_TYPE_ALL_MATCHES_AUTO_BATCH)) { - Log.v(TAG, "Skipping client: CALLBACK_TYPE_ALL_MATCHES"); + Log.v(TAG, "Skipping client: Not CALLBACK_TYPE_ALL_MATCHES"); continue; } @@ -504,7 +499,6 @@ public class ScanController { app.mCallback.onScanResult(result); } else { Log.v(TAG, "Callback is null, sending scan results by pendingIntent"); - // Send the PendingIntent List<ScanResult> results = new ArrayList<>(Arrays.asList(result)); sendResultsByPendingIntent( app.mInfo, results, ScanSettings.CALLBACK_TYPE_ALL_MATCHES); @@ -1097,14 +1091,14 @@ public class ScanController { } /************************************************************************** - * GATT Service functions - Shared CLIENT/SERVER + * Scan functions - Shared CLIENT/SERVER *************************************************************************/ @RequiresPermission(BLUETOOTH_SCAN) void registerScanner( IScannerCallback callback, WorkSource workSource, AttributionSource source) { if (!Utils.checkScanPermissionForDataDelivery( - mAdapterService, source, "ScanHelper registerScanner")) { + mAdapterService, source, "ScanController registerScanner")) { return; } @@ -1138,7 +1132,7 @@ public class ScanController { @RequiresPermission(BLUETOOTH_SCAN) void unregisterScanner(int scannerId, AttributionSource source) { if (!Utils.checkScanPermissionForDataDelivery( - mAdapterService, source, "ScanHelper unregisterScanner")) { + mAdapterService, source, "ScanController unregisterScanner")) { return; } @@ -1183,10 +1177,8 @@ public class ScanController { ScanSettings settings, List<ScanFilter> filters, AttributionSource source) { - Log.d(TAG, "start scan with filters"); - - if (!Utils.checkScanPermissionForDataDelivery( - mAdapterService, source, "Starting GATT scan.")) { + Log.d(TAG, "Start scan with filters"); + if (!Utils.checkScanPermissionForDataDelivery(mAdapterService, source, "Starting scan.")) { return; } @@ -1277,12 +1269,11 @@ public class ScanController { ScanSettings settings, List<ScanFilter> filters, AttributionSource source) { - Log.d(TAG, "start scan with filters, for PendingIntent"); - - if (!Utils.checkScanPermissionForDataDelivery( - mAdapterService, source, "Starting GATT scan.")) { + Log.d(TAG, "Start scan with filters, for PendingIntent"); + if (!Utils.checkScanPermissionForDataDelivery(mAdapterService, source, "Starting scan.")) { return; } + enforcePrivilegedPermissionIfNeeded(settings); settings = enforceReportDelayFloor(settings); enforcePrivilegedPermissionIfNeeded(filters); @@ -1384,7 +1375,7 @@ public class ScanController { @RequiresPermission(BLUETOOTH_SCAN) void flushPendingBatchResults(int scannerId, AttributionSource source) { if (!Utils.checkScanPermissionForDataDelivery( - mAdapterService, source, "ScanHelper flushPendingBatchResults")) { + mAdapterService, source, "ScanController flushPendingBatchResults")) { return; } flushPendingBatchResultsInternal(scannerId); @@ -1398,7 +1389,7 @@ public class ScanController { @RequiresPermission(BLUETOOTH_SCAN) void stopScan(int scannerId, AttributionSource source) { if (!Utils.checkScanPermissionForDataDelivery( - mAdapterService, source, "ScanHelper stopScan")) { + mAdapterService, source, "ScanController stopScan")) { return; } stopScanInternal(scannerId); @@ -1421,7 +1412,7 @@ public class ScanController { @RequiresPermission(BLUETOOTH_SCAN) void stopScan(PendingIntent intent, AttributionSource source) { if (!Utils.checkScanPermissionForDataDelivery( - mAdapterService, source, "ScanHelper stopScan")) { + mAdapterService, source, "ScanController stopScan")) { return; } stopScanInternal(intent); @@ -1451,7 +1442,7 @@ public class ScanController { IPeriodicAdvertisingCallback callback, AttributionSource source) { if (!Utils.checkScanPermissionForDataDelivery( - mAdapterService, source, "ScanHelper registerSync")) { + mAdapterService, source, "ScanController registerSync")) { return; } mPeriodicScanManager.startSync(scanResult, skip, timeout, callback); @@ -1460,7 +1451,7 @@ public class ScanController { @RequiresPermission(BLUETOOTH_SCAN) void unregisterSync(IPeriodicAdvertisingCallback callback, AttributionSource source) { if (!Utils.checkScanPermissionForDataDelivery( - mAdapterService, source, "ScanHelper unregisterSync")) { + mAdapterService, source, "ScanController unregisterSync")) { return; } mPeriodicScanManager.stopSync(callback); @@ -1470,7 +1461,7 @@ public class ScanController { void transferSync( BluetoothDevice bda, int serviceData, int syncHandle, AttributionSource source) { if (!Utils.checkScanPermissionForDataDelivery( - mAdapterService, source, "ScanHelper transferSync")) { + mAdapterService, source, "ScanController transferSync")) { return; } mPeriodicScanManager.transferSync(bda, serviceData, syncHandle); @@ -1484,7 +1475,7 @@ public class ScanController { IPeriodicAdvertisingCallback callback, AttributionSource source) { if (!Utils.checkScanPermissionForDataDelivery( - mAdapterService, source, "ScanHelper transferSetInfo")) { + mAdapterService, source, "ScanController transferSetInfo")) { return; } mPeriodicScanManager.transferSetInfo(bda, serviceData, advHandle, callback); @@ -1493,7 +1484,7 @@ public class ScanController { @RequiresPermission(BLUETOOTH_SCAN) int numHwTrackFiltersAvailable(AttributionSource source) { if (!Utils.checkScanPermissionForDataDelivery( - mAdapterService, source, "ScanHelper numHwTrackFiltersAvailable")) { + mAdapterService, source, "ScanController numHwTrackFiltersAvailable")) { return 0; } return (mAdapterService.getTotalNumOfTrackableAdvertisements() 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 e44d8a54c3..cf6ef7d928 100644 --- a/android/app/src/com/android/bluetooth/le_scan/ScanManager.java +++ b/android/app/src/com/android/bluetooth/le_scan/ScanManager.java @@ -58,7 +58,6 @@ import com.android.bluetooth.btservice.AdapterService; import com.android.bluetooth.btservice.BluetoothAdapterProxy; import com.android.bluetooth.flags.Flags; import com.android.bluetooth.gatt.FilterParams; -import com.android.bluetooth.gatt.GattServiceConfig; import com.android.bluetooth.util.SystemProperties; import com.android.internal.annotations.GuardedBy; import com.android.internal.annotations.VisibleForTesting; @@ -79,8 +78,7 @@ import java.util.stream.Collectors; /** Class that handles Bluetooth LE scan related operations. */ public class ScanManager { - private static final String TAG = - GattServiceConfig.TAG_PREFIX + ScanManager.class.getSimpleName(); + private static final String TAG = ScanManager.class.getSimpleName(); public static final int SCAN_MODE_SCREEN_OFF_LOW_POWER_WINDOW_MS = 512; public static final int SCAN_MODE_SCREEN_OFF_LOW_POWER_INTERVAL_MS = 10240; @@ -1629,7 +1627,7 @@ public class ScanManager { } void flushBatchResults(int scannerId) { - Log.d(TAG, "flushPendingBatchResults - scannerId = " + scannerId); + Log.d(TAG, "flushBatchResults - scannerId = " + scannerId); if (mBatchScanParams.mFullScanScannerId != -1) { resetCountDownLatch(); mNativeInterface.gattClientReadScanReports( diff --git a/android/app/src/com/android/bluetooth/le_scan/ScanNativeInterface.java b/android/app/src/com/android/bluetooth/le_scan/ScanNativeInterface.java index 2973dc5e56..e641d00c94 100644 --- a/android/app/src/com/android/bluetooth/le_scan/ScanNativeInterface.java +++ b/android/app/src/com/android/bluetooth/le_scan/ScanNativeInterface.java @@ -299,7 +299,7 @@ public class ScanNativeInterface { byte[] advData, String originalAddress) { if (mScanController == null) { - Log.e(TAG, "Scan helper is null!"); + Log.e(TAG, "ScanController is null!"); return; } mScanController.onScanResult( @@ -319,7 +319,7 @@ public class ScanNativeInterface { void onScannerRegistered(int status, int scannerId, long uuidLsb, long uuidMsb) throws RemoteException { if (mScanController == null) { - Log.e(TAG, "Scan helper is null!"); + Log.e(TAG, "ScanController is null!"); return; } mScanController.onScannerRegistered(status, scannerId, uuidLsb, uuidMsb); @@ -327,7 +327,7 @@ public class ScanNativeInterface { void onScanFilterEnableDisabled(int action, int status, int clientIf) { if (mScanController == null) { - Log.e(TAG, "Scan helper is null!"); + Log.e(TAG, "ScanController is null!"); return; } mScanController.onScanFilterEnableDisabled(action, status, clientIf); @@ -335,7 +335,7 @@ public class ScanNativeInterface { void onScanFilterParamsConfigured(int action, int status, int clientIf, int availableSpace) { if (mScanController == null) { - Log.e(TAG, "Scan helper is null!"); + Log.e(TAG, "ScanController is null!"); return; } mScanController.onScanFilterParamsConfigured(action, status, clientIf, availableSpace); @@ -344,7 +344,7 @@ public class ScanNativeInterface { void onScanFilterConfig( int action, int status, int clientIf, int filterType, int availableSpace) { if (mScanController == null) { - Log.e(TAG, "Scan helper is null!"); + Log.e(TAG, "ScanController is null!"); return; } mScanController.onScanFilterConfig(action, status, clientIf, filterType, availableSpace); @@ -352,7 +352,7 @@ public class ScanNativeInterface { void onBatchScanStorageConfigured(int status, int clientIf) { if (mScanController == null) { - Log.e(TAG, "Scan helper is null!"); + Log.e(TAG, "ScanController is null!"); return; } mScanController.onBatchScanStorageConfigured(status, clientIf); @@ -360,7 +360,7 @@ public class ScanNativeInterface { void onBatchScanStartStopped(int startStopAction, int status, int clientIf) { if (mScanController == null) { - Log.e(TAG, "Scan helper is null!"); + Log.e(TAG, "ScanController is null!"); return; } mScanController.onBatchScanStartStopped(startStopAction, status, clientIf); @@ -370,7 +370,7 @@ public class ScanNativeInterface { int status, int scannerId, int reportType, int numRecords, byte[] recordData) throws RemoteException { if (mScanController == null) { - Log.e(TAG, "Scan helper is null!"); + Log.e(TAG, "ScanController is null!"); return; } mScanController.onBatchScanReports(status, scannerId, reportType, numRecords, recordData); @@ -378,7 +378,7 @@ public class ScanNativeInterface { void onBatchScanThresholdCrossed(int clientIf) { if (mScanController == null) { - Log.e(TAG, "Scan helper is null!"); + Log.e(TAG, "ScanController is null!"); return; } mScanController.onBatchScanThresholdCrossed(clientIf); @@ -400,7 +400,7 @@ public class ScanNativeInterface { int rssiValue, int timeStamp) { if (mScanController == null) { - Log.e(TAG, "Scan helper is null!"); + Log.e(TAG, "ScanController is null!"); return null; } return mScanController.createOnTrackAdvFoundLostObject( @@ -421,7 +421,7 @@ public class ScanNativeInterface { void onTrackAdvFoundLost(AdvtFilterOnFoundOnLostInfo trackingInfo) throws RemoteException { if (mScanController == null) { - Log.e(TAG, "Scan helper is null!"); + Log.e(TAG, "ScanController is null!"); return; } mScanController.onTrackAdvFoundLost(trackingInfo); @@ -429,7 +429,7 @@ public class ScanNativeInterface { void onScanParamSetupCompleted(int status, int scannerId) throws RemoteException { if (mScanController == null) { - Log.e(TAG, "Scan helper is null!"); + Log.e(TAG, "ScanController is null!"); return; } mScanController.onScanParamSetupCompleted(status, scannerId); @@ -437,7 +437,7 @@ public class ScanNativeInterface { void onMsftAdvMonitorAdd(int filter_index, int monitor_handle, int status) { if (mScanController == null) { - Log.e(TAG, "Scan helper is null!"); + Log.e(TAG, "ScanController is null!"); return; } mScanController.onMsftAdvMonitorAdd(filter_index, monitor_handle, status); @@ -445,7 +445,7 @@ public class ScanNativeInterface { void onMsftAdvMonitorRemove(int filter_index, int status) { if (mScanController == null) { - Log.e(TAG, "Scan helper is null!"); + Log.e(TAG, "ScanController is null!"); return; } mScanController.onMsftAdvMonitorRemove(filter_index, status); @@ -453,7 +453,7 @@ public class ScanNativeInterface { void onMsftAdvMonitorEnable(int status) { if (mScanController == null) { - Log.e(TAG, "Scan helper is null!"); + Log.e(TAG, "ScanController is null!"); return; } mScanController.onMsftAdvMonitorEnable(status); diff --git a/android/app/src/com/android/bluetooth/map/BluetoothMapContent.java b/android/app/src/com/android/bluetooth/map/BluetoothMapContent.java index 99ed3c709c..43d0b463cc 100644 --- a/android/app/src/com/android/bluetooth/map/BluetoothMapContent.java +++ b/android/app/src/com/android/bluetooth/map/BluetoothMapContent.java @@ -3469,7 +3469,7 @@ public class BluetoothMapContent { + addr + ", contact name: " + (contact != null - ? contact.getName() + ", X-BT-UID: " + contact.getXBtUid() + ? contact.name() + ", X-BT-UID: " + contact.getXBtUid() : "null")); if (contact == null) { continue; diff --git a/android/app/src/com/android/bluetooth/map/BluetoothMapConvoContactElement.java b/android/app/src/com/android/bluetooth/map/BluetoothMapConvoContactElement.java index 39f5359392..d22dfe24b1 100644 --- a/android/app/src/com/android/bluetooth/map/BluetoothMapConvoContactElement.java +++ b/android/app/src/com/android/bluetooth/map/BluetoothMapConvoContactElement.java @@ -63,8 +63,8 @@ public class BluetoothMapConvoContactElement BluetoothMapConvoContactElement newElement = new BluetoothMapConvoContactElement(); newElement.mUci = address; // TODO: For now we use the ID as BT-UID - newElement.mBtUid = new SignedLongLong(contact.getId(), 0); - newElement.mDisplayName = contact.getName(); + newElement.mBtUid = new SignedLongLong(contact.id(), 0); + newElement.mDisplayName = contact.name(); return newElement; } diff --git a/android/app/src/com/android/bluetooth/map/MapContact.java b/android/app/src/com/android/bluetooth/map/MapContact.java index d3be152c63..8ff5eb1207 100644 --- a/android/app/src/com/android/bluetooth/map/MapContact.java +++ b/android/app/src/com/android/bluetooth/map/MapContact.java @@ -17,43 +17,24 @@ package com.android.bluetooth.map; import com.android.bluetooth.SignedLongLong; /** Local representation of an Android contact */ -public class MapContact { - private final String mName; - private final long mId; - - private MapContact(long id, String name) { - mId = id; - mName = name; - } - - public static MapContact create(long id, String name) { - return new MapContact(id, name); - } - - public String getName() { - return mName; - } - - public long getId() { - return mId; - } +record MapContact(long id, String name) { public String getXBtUidString() { - if (mId > 0) { - return BluetoothMapUtils.getLongLongAsString(mId, 0); + if (id > 0) { + return BluetoothMapUtils.getLongLongAsString(id, 0); } return null; } public SignedLongLong getXBtUid() { - if (mId > 0) { - return new SignedLongLong(mId, 0); + if (id > 0) { + return new SignedLongLong(id, 0); } return null; } @Override public String toString() { - return mName; + return name; } } diff --git a/android/app/src/com/android/bluetooth/map/SmsMmsContacts.java b/android/app/src/com/android/bluetooth/map/SmsMmsContacts.java index 053d5c8d95..33d1b797ad 100644 --- a/android/app/src/com/android/bluetooth/map/SmsMmsContacts.java +++ b/android/app/src/com/android/bluetooth/map/SmsMmsContacts.java @@ -186,7 +186,7 @@ public class SmsMmsContacts { MapContact contact = mNames.get(phone); if (contact != null) { - if (contact.getId() < 0) { + if (contact.id() < 0) { return null; } if (contactNameFilter == null) { @@ -196,7 +196,7 @@ public class SmsMmsContacts { String searchString = contactNameFilter.replace("*", ".*"); searchString = ".*" + searchString + ".*"; Pattern p = Pattern.compile(Pattern.quote(searchString), Pattern.CASE_INSENSITIVE); - if (p.matcher(contact.getName()).find()) { + if (p.matcher(contact.name()).find()) { return contact; } return null; @@ -222,10 +222,10 @@ public class SmsMmsContacts { c.moveToFirst(); long id = c.getLong(COL_CONTACT_ID); String name = c.getString(COL_CONTACT_NAME); - contact = MapContact.create(id, name); + contact = new MapContact(id, name); mNames.put(phone, contact); } else { - contact = MapContact.create(-1, null); + contact = new MapContact(-1, null); mNames.put(phone, contact); contact = null; } diff --git a/android/app/src/com/android/bluetooth/opp/BluetoothOppLauncherActivity.java b/android/app/src/com/android/bluetooth/opp/BluetoothOppLauncherActivity.java index 96714c37d0..048c134848 100644 --- a/android/app/src/com/android/bluetooth/opp/BluetoothOppLauncherActivity.java +++ b/android/app/src/com/android/bluetooth/opp/BluetoothOppLauncherActivity.java @@ -127,11 +127,9 @@ public class BluetoothOppLauncherActivity extends Activity { final String type = intent.getType(); final Uri stream = (Uri) intent.getParcelableExtra(Intent.EXTRA_STREAM); CharSequence extraText = intent.getCharSequenceExtra(Intent.EXTRA_TEXT); - // If we get ACTION_SEND intent with EXTRA_STREAM, we'll use the - // uri data; - // If we get ACTION_SEND intent without EXTRA_STREAM, but with - // EXTRA_TEXT, we will try send this TEXT out; Currently in - // Browser, share one link goes to this case; + // If we get ACTION_SEND intent with EXTRA_STREAM, we'll use the uri data; + // If we get ACTION_SEND intent without EXTRA_STREAM, but with EXTRA_TEXT, we will + // try send this TEXT out; Currently in Browser, share one link goes to this case; if (stream != null && type != null) { Log.v(TAG, "Get ACTION_SEND intent: Uri = " + stream + "; mimetype = " + type); if (Flags.oppCheckContentUriPermissions() && SdkLevel.isAtLeastV()) { @@ -144,22 +142,16 @@ public class BluetoothOppLauncherActivity extends Activity { } else { Log.v(TAG, "Did not check sender permissions to Uri = " + stream); } - // Save type/stream, will be used when adding transfer - // session to DB. - Thread t = - new Thread( - new Runnable() { - @Override - public void run() { - sendFileInfo( - type, - stream.toString(), - false /* isHandover */, - true /* - fromExternal */); - } - }); - t.start(); + // Save type/stream, will be used when adding transfer session to DB. + new Thread( + () -> { + sendFileInfo( + type, + stream.toString(), + false /* isHandover */, + true /* fromExternal */); + }) + .start(); return; } else if (extraText != null && type != null) { Log.v( @@ -172,19 +164,15 @@ public class BluetoothOppLauncherActivity extends Activity { createFileForSharedContent( this.createCredentialProtectedStorageContext(), extraText); if (fileUri != null) { - Thread t = - new Thread( - new Runnable() { - @Override - public void run() { - sendFileInfo( - type, - fileUri.toString(), - false /* isHandover */, - false /* fromExternal */); - } - }); - t.start(); + new Thread( + () -> { + sendFileInfo( + type, + fileUri.toString(), + false /* isHandover */, + false /* fromExternal */); + }) + .start(); return; } else { Log.w(TAG, "Error trying to do set text...File not created!"); @@ -250,37 +238,33 @@ public class BluetoothOppLauncherActivity extends Activity { permittedUris = uris; Log.v(TAG, "Did not check sender permissions to uris in " + uris); } - Thread t = - new Thread( - new Runnable() { - @Override - public void run() { - try { - BluetoothOppManager.getInstance( - BluetoothOppLauncherActivity.this) - .saveSendingFileInfo( - mimeType, - permittedUris, - false /* isHandover */, - true /* fromExternal */); - // Done getting file info..Launch device picker - // and finish this activity - launchDevicePicker(); - finish(); - } catch (IllegalArgumentException exception) { - ContentProfileErrorReportUtils.report( - BluetoothProfile.OPP, - BluetoothProtoEnums - .BLUETOOTH_OPP_LAUNCHER_ACTIVITY, - BluetoothStatsLog - .BLUETOOTH_CONTENT_PROFILE_ERROR_REPORTED__TYPE__EXCEPTION, - 3); - showToast(exception.getMessage()); - finish(); - } + new Thread( + () -> { + try { + BluetoothOppManager.getInstance( + BluetoothOppLauncherActivity.this) + .saveSendingFileInfo( + mimeType, + permittedUris, + false /* isHandover */, + true /* fromExternal */); + // Done getting file info..Launch device picker + // and finish this activity + launchDevicePicker(); + finish(); + } catch (IllegalArgumentException exception) { + ContentProfileErrorReportUtils.report( + BluetoothProfile.OPP, + BluetoothProtoEnums + .BLUETOOTH_OPP_LAUNCHER_ACTIVITY, + BluetoothStatsLog + .BLUETOOTH_CONTENT_PROFILE_ERROR_REPORTED__TYPE__EXCEPTION, + 3); + showToast(exception.getMessage()); + finish(); } - }); - t.start(); + }) + .start(); return; } else { Log.e(TAG, "type is null; or sending files URIs are null"); @@ -587,11 +571,6 @@ public class BluetoothOppLauncherActivity extends Activity { private void showToast(final String msg) { BluetoothOppLauncherActivity.this.runOnUiThread( - new Runnable() { - @Override - public void run() { - Toast.makeText(getApplicationContext(), msg, Toast.LENGTH_SHORT).show(); - } - }); + () -> Toast.makeText(getApplicationContext(), msg, Toast.LENGTH_SHORT).show()); } } diff --git a/android/app/src/com/android/bluetooth/pbapclient/PbapClientStateMachine.java b/android/app/src/com/android/bluetooth/pbapclient/PbapClientStateMachine.java index caa9584445..d42cfec25e 100644 --- a/android/app/src/com/android/bluetooth/pbapclient/PbapClientStateMachine.java +++ b/android/app/src/com/android/bluetooth/pbapclient/PbapClientStateMachine.java @@ -144,9 +144,9 @@ class PbapClientStateMachine extends StateMachine { } public int getTotalNumberOfContacts() { - return (mMetadata == null || mMetadata.getSize() == PbapPhonebookMetadata.INVALID_SIZE) + return (mMetadata == null || mMetadata.size() == PbapPhonebookMetadata.INVALID_SIZE) ? 0 - : mMetadata.getSize(); + : mMetadata.size(); } public int getNumberOfContactsDownloaded() { @@ -163,24 +163,24 @@ class PbapClientStateMachine extends StateMachine { + "/ UNKNOWN] (db:UNKNOWN, pc:UNKNOWN, sc:UNKNOWN)"; } - String databaseIdentifier = mMetadata.getDatabaseIdentifier(); + String databaseIdentifier = mMetadata.databaseIdentifier(); if (databaseIdentifier == PbapPhonebookMetadata.INVALID_DATABASE_IDENTIFIER) { databaseIdentifier = "UNKNOWN"; } - String primaryVersionCounter = mMetadata.getPrimaryVersionCounter(); + String primaryVersionCounter = mMetadata.primaryVersionCounter(); if (primaryVersionCounter == PbapPhonebookMetadata.INVALID_VERSION_COUNTER) { primaryVersionCounter = "UNKNOWN"; } - String secondaryVersionCounter = mMetadata.getSecondaryVersionCounter(); + String secondaryVersionCounter = mMetadata.secondaryVersionCounter(); if (secondaryVersionCounter == PbapPhonebookMetadata.INVALID_VERSION_COUNTER) { secondaryVersionCounter = "UNKNOWN"; } String totalContactsExpected = "UNKNOWN"; - if (mMetadata.getSize() != PbapPhonebookMetadata.INVALID_SIZE) { - totalContactsExpected = Integer.toString(mMetadata.getSize()); + if (mMetadata.size() != PbapPhonebookMetadata.INVALID_SIZE) { + totalContactsExpected = Integer.toString(mMetadata.size()); } return mName @@ -605,7 +605,7 @@ class PbapClientStateMachine extends StateMachine { case MSG_PHONEBOOK_METADATA_RECEIVED: PbapPhonebookMetadata metadata = (PbapPhonebookMetadata) message.obj; - phonebook = metadata.getPhonebook(); + phonebook = metadata.phonebook(); if (currentPhonebook != null && currentPhonebook.equals(phonebook)) { info("Downloading: received metadata=" + metadata); @@ -613,7 +613,7 @@ class PbapClientStateMachine extends StateMachine { mPhonebooks.get(phonebook).setMetadata(metadata); // If phonebook has contacts, begin downloading them - if (metadata.getSize() > 0) { + if (metadata.size() > 0) { downloadPhonebook(currentPhonebook, 0, CONTACT_DOWNLOAD_BATCH_SIZE); } else { warn( diff --git a/android/app/src/com/android/bluetooth/pbapclient/obex/PbapClientConnectionHandler.java b/android/app/src/com/android/bluetooth/pbapclient/obex/PbapClientConnectionHandler.java index 472dc96ac3..c735dc655d 100644 --- a/android/app/src/com/android/bluetooth/pbapclient/obex/PbapClientConnectionHandler.java +++ b/android/app/src/com/android/bluetooth/pbapclient/obex/PbapClientConnectionHandler.java @@ -354,14 +354,14 @@ class PbapClientConnectionHandler extends Handler { PbapApplicationParameters.PROPERTIES_ALL, /* format, unused */ (byte) 0, PbapApplicationParameters.RETURN_SIZE_ONLY, - /* list start offeset, start from beginning */ 0); + /* list startOffset, start from beginning */ 0); // Download contacts in batches of size DEFAULT_BATCH_SIZE RequestPullPhonebookMetadata requestPbSize = new RequestPullPhonebookMetadata(path, params); requestPbSize.execute(mObexSession); - int numberOfContactsRemaining = requestPbSize.getMetadata().getSize(); + int numberOfContactsRemaining = requestPbSize.getMetadata().size(); int startOffset = 0; if (PbapPhonebook.LOCAL_PHONEBOOK_PATH.equals(path)) { // PBAP v1.2.3, Sec 3.1.5. The first contact in pb is owner card 0.vcf, which we diff --git a/android/app/src/com/android/bluetooth/pbapclient/obex/PbapPhonebookMetadata.java b/android/app/src/com/android/bluetooth/pbapclient/obex/PbapPhonebookMetadata.java index 3badee4de6..4fb04dc036 100644 --- a/android/app/src/com/android/bluetooth/pbapclient/obex/PbapPhonebookMetadata.java +++ b/android/app/src/com/android/bluetooth/pbapclient/obex/PbapPhonebookMetadata.java @@ -16,7 +16,16 @@ package com.android.bluetooth.pbapclient; -public class PbapPhonebookMetadata { +record PbapPhonebookMetadata( + String phonebook, + // 2 byte number + int size, + // 16 byte number as string + String databaseIdentifier, + // 16 byte number as string + String primaryVersionCounter, + // 16 byte number as string + String secondaryVersionCounter) { private static final String TAG = PbapPhonebookMetadata.class.getSimpleName(); public static final int INVALID_SIZE = -1; @@ -24,54 +33,15 @@ public class PbapPhonebookMetadata { public static final String DEFAULT_DATABASE_IDENTIFIER = "0"; public static final String INVALID_VERSION_COUNTER = null; - private final String mPhonebook; - private int mSize = INVALID_SIZE; // 2 byte number - private String mDatabaseIdentifier = INVALID_DATABASE_IDENTIFIER; // 16 byte number as string - private String mPrimaryVersionCounter = INVALID_VERSION_COUNTER; // 16 byte number as string - private String mSecondaryVersionCounter = INVALID_VERSION_COUNTER; // 16 byte number as string - - PbapPhonebookMetadata( - String phonebook, - int size, - String databaseIdentifier, - String primaryVersionCounter, - String secondaryVersionCounter) { - mPhonebook = phonebook; - mSize = size; - mDatabaseIdentifier = databaseIdentifier; - mPrimaryVersionCounter = primaryVersionCounter; - mSecondaryVersionCounter = secondaryVersionCounter; - } - - public String getPhonebook() { - return mPhonebook; - } - - public int getSize() { - return mSize; - } - - public String getDatabaseIdentifier() { - return mDatabaseIdentifier; - } - - public String getPrimaryVersionCounter() { - return mPrimaryVersionCounter; - } - - public String getSecondaryVersionCounter() { - return mSecondaryVersionCounter; - } - @Override public String toString() { return "<" + TAG - + (" phonebook=" + mPhonebook) - + (" size=" + mSize) - + (" databaseIdentifier=" + mDatabaseIdentifier) - + (" primaryVersionCounter=" + mPrimaryVersionCounter) - + (" secondaryVersionCounter=" + mSecondaryVersionCounter) + + (" phonebook=" + phonebook) + + (" size=" + size) + + (" databaseIdentifier=" + databaseIdentifier) + + (" primaryVersionCounter=" + primaryVersionCounter) + + (" secondaryVersionCounter=" + secondaryVersionCounter) + ">"; } } diff --git a/android/app/src/com/android/bluetooth/tbs/TbsGatt.java b/android/app/src/com/android/bluetooth/tbs/TbsGatt.java index 871e6d7b62..23d62b3ec2 100644 --- a/android/app/src/com/android/bluetooth/tbs/TbsGatt.java +++ b/android/app/src/com/android/bluetooth/tbs/TbsGatt.java @@ -41,6 +41,8 @@ import com.android.bluetooth.btservice.AdapterService; import com.android.internal.annotations.GuardedBy; import com.android.internal.annotations.VisibleForTesting; +import com.google.protobuf.ByteString; + import java.io.ByteArrayOutputStream; import java.nio.ByteBuffer; import java.nio.ByteOrder; @@ -96,6 +98,8 @@ public class TbsGatt { static final int CALL_CONTROL_POINT_RESULT_STATE_MISMATCH = 0x04; static final int CALL_CONTROL_POINT_RESULT_INVALID_OUTGOING_URI = 0x06; + private static final int LOG_NB_EVENTS = 200; + private final Object mPendingGattOperationsLock = new Object(); private final Map<BluetoothDevice, Integer> mStatusFlagValue = new HashMap<>(); @@ -124,46 +128,9 @@ public class TbsGatt { private final GattCharacteristic mCallFriendlyNameCharacteristic; private Callback mCallback; - private boolean mSilentMode = false; - - private static final int LOG_NB_EVENTS = 200; private BluetoothEventLogger mEventLogger = null; - private static String tbsUuidToString(UUID uuid) { - if (uuid.equals(UUID_BEARER_PROVIDER_NAME)) { - return "BEARER_PROVIDER_NAME"; - } else if (uuid.equals(UUID_BEARER_UCI)) { - return "BEARER_UCI"; - } else if (uuid.equals(UUID_BEARER_TECHNOLOGY)) { - return "BEARER_TECHNOLOGY"; - } else if (uuid.equals(UUID_BEARER_URI_SCHEMES_SUPPORTED_LIST)) { - return "BEARER_URI_SCHEMES_SUPPORTED_LIST"; - } else if (uuid.equals(UUID_BEARER_LIST_CURRENT_CALLS)) { - return "BEARER_LIST_CURRENT_CALLS"; - } else if (uuid.equals(UUID_CONTENT_CONTROL_ID)) { - return "CONTENT_CONTROL_ID"; - } else if (uuid.equals(UUID_STATUS_FLAGS)) { - return "STATUS_FLAGS"; - } else if (uuid.equals(UUID_CALL_STATE)) { - return "CALL_STATE"; - } else if (uuid.equals(UUID_CALL_CONTROL_POINT)) { - return "CALL_CONTROL_POINT"; - } else if (uuid.equals(UUID_CALL_CONTROL_POINT_OPTIONAL_OPCODES)) { - return "CALL_CONTROL_POINT_OPTIONAL_OPCODES"; - } else if (uuid.equals(UUID_TERMINATION_REASON)) { - return "TERMINATION_REASON"; - } else if (uuid.equals(UUID_INCOMING_CALL)) { - return "INCOMING_CALL"; - } else if (uuid.equals(UUID_CALL_FRIENDLY_NAME)) { - return "CALL_FRIENDLY_NAME"; - } else if (uuid.equals(UUID_CLIENT_CHARACTERISTIC_CONFIGURATION)) { - return "CLIENT_CHARACTERISTIC_CONFIGURATION"; - } else { - return "UNKNOWN(" + uuid + ")"; - } - } - public abstract static class Callback { public abstract void onServiceAdded(boolean success); @@ -180,7 +147,15 @@ public class TbsGatt { public abstract boolean isInbandRingtoneEnabled(BluetoothDevice device); } - private static class GattOpContext { + private record GattOpContext( + Operation operation, + int requestId, + BluetoothGattCharacteristic characteristic, + BluetoothGattDescriptor descriptor, + boolean preparedWrite, + boolean responseNeeded, + int offset, + ByteString value) { public enum Operation { READ_CHARACTERISTIC, WRITE_CHARACTERISTIC, @@ -193,44 +168,9 @@ public class TbsGatt { int requestId, BluetoothGattCharacteristic characteristic, BluetoothGattDescriptor descriptor, - boolean preparedWrite, - boolean responseNeeded, - int offset, - byte[] value) { - mOperation = operation; - mRequestId = requestId; - mCharacteristic = characteristic; - mDescriptor = descriptor; - mPreparedWrite = preparedWrite; - mResponseNeeded = responseNeeded; - mOffset = offset; - mValue = value; - } - - GattOpContext( - Operation operation, - int requestId, - BluetoothGattCharacteristic characteristic, - BluetoothGattDescriptor descriptor, int offset) { - mOperation = operation; - mRequestId = requestId; - mCharacteristic = characteristic; - mDescriptor = descriptor; - mPreparedWrite = false; - mResponseNeeded = false; - mOffset = offset; - mValue = null; + this(operation, requestId, characteristic, descriptor, false, false, offset, null); } - - public final Operation mOperation; - public final int mRequestId; - public final BluetoothGattCharacteristic mCharacteristic; - public final BluetoothGattDescriptor mDescriptor; - public final boolean mPreparedWrite; - public final boolean mResponseNeeded; - public final int mOffset; - public final byte[] mValue; } TbsGatt(AdapterService adapterService, TbsService tbsService) { @@ -314,7 +254,6 @@ public class TbsGatt { BluetoothGattCharacteristic.PROPERTY_READ | BluetoothGattCharacteristic.PROPERTY_NOTIFY, BluetoothGattCharacteristic.PERMISSION_READ_ENCRYPTED); - } public boolean init( @@ -372,12 +311,45 @@ public class TbsGatt { public void cleanup() { mAdapterService.unregisterBluetoothStateCallback(mBluetoothStateChangeCallback); - mBluetoothGattServer.close(); } + private static String tbsUuidToString(UUID uuid) { + if (uuid.equals(UUID_BEARER_PROVIDER_NAME)) { + return "BEARER_PROVIDER_NAME"; + } else if (uuid.equals(UUID_BEARER_UCI)) { + return "BEARER_UCI"; + } else if (uuid.equals(UUID_BEARER_TECHNOLOGY)) { + return "BEARER_TECHNOLOGY"; + } else if (uuid.equals(UUID_BEARER_URI_SCHEMES_SUPPORTED_LIST)) { + return "BEARER_URI_SCHEMES_SUPPORTED_LIST"; + } else if (uuid.equals(UUID_BEARER_LIST_CURRENT_CALLS)) { + return "BEARER_LIST_CURRENT_CALLS"; + } else if (uuid.equals(UUID_CONTENT_CONTROL_ID)) { + return "CONTENT_CONTROL_ID"; + } else if (uuid.equals(UUID_STATUS_FLAGS)) { + return "STATUS_FLAGS"; + } else if (uuid.equals(UUID_CALL_STATE)) { + return "CALL_STATE"; + } else if (uuid.equals(UUID_CALL_CONTROL_POINT)) { + return "CALL_CONTROL_POINT"; + } else if (uuid.equals(UUID_CALL_CONTROL_POINT_OPTIONAL_OPCODES)) { + return "CALL_CONTROL_POINT_OPTIONAL_OPCODES"; + } else if (uuid.equals(UUID_TERMINATION_REASON)) { + return "TERMINATION_REASON"; + } else if (uuid.equals(UUID_INCOMING_CALL)) { + return "INCOMING_CALL"; + } else if (uuid.equals(UUID_CALL_FRIENDLY_NAME)) { + return "CALL_FRIENDLY_NAME"; + } else if (uuid.equals(UUID_CLIENT_CHARACTERISTIC_CONFIGURATION)) { + return "CLIENT_CHARACTERISTIC_CONFIGURATION"; + } else { + return "UNKNOWN(" + uuid + ")"; + } + } + private void removeUuidFromMetadata(ParcelUuid charUuid, BluetoothDevice device) { - List<ParcelUuid> uuidList; + final List<ParcelUuid> uuidList; byte[] gtbs_cccd = mAdapterService.getMetadata(device, METADATA_GTBS_CCCD); if ((gtbs_cccd == null) || (gtbs_cccd.length == 0)) { @@ -402,7 +374,7 @@ public class TbsGatt { } private void addUuidToMetadata(ParcelUuid charUuid, BluetoothDevice device) { - List<ParcelUuid> uuidList; + final List<ParcelUuid> uuidList; byte[] gtbs_cccd = mAdapterService.getMetadata(device, METADATA_GTBS_CCCD); if ((gtbs_cccd == null) || (gtbs_cccd.length == 0)) { @@ -1010,57 +982,57 @@ public class TbsGatt { @SuppressWarnings("EnumOrdinal") private void onRejectedAuthorizationGattOperation(BluetoothDevice device, GattOpContext op) { - UUID charUuid = - (op.mCharacteristic != null - ? op.mCharacteristic.getUuid() - : (op.mDescriptor != null - ? op.mDescriptor.getCharacteristic().getUuid() + final UUID charUuid = + (op.characteristic != null + ? op.characteristic.getUuid() + : (op.descriptor != null + ? op.descriptor.getCharacteristic().getUuid() : null)); mEventLogger.logw( TAG, "onRejectedAuthorizationGattOperation device: " + device + ", opcode= " - + op.mOperation + + op.operation + ", characteristic= " + (charUuid != null ? tbsUuidToString(charUuid) : "UNKNOWN")); - switch (op.mOperation) { + switch (op.operation) { case READ_CHARACTERISTIC: case READ_DESCRIPTOR: mBluetoothGattServer.sendResponse( device, - op.mRequestId, + op.requestId, BluetoothGatt.GATT_INSUFFICIENT_AUTHORIZATION, - op.mOffset, + op.offset, null); break; case WRITE_CHARACTERISTIC: - if (op.mResponseNeeded) { + if (op.responseNeeded) { mBluetoothGattServer.sendResponse( device, - op.mRequestId, + op.requestId, BluetoothGatt.GATT_INSUFFICIENT_AUTHORIZATION, - op.mOffset, + op.offset, null); } else { // In case of control point operations we can send an application error code - if (op.mCharacteristic.getUuid().equals(UUID_CALL_CONTROL_POINT)) { + if (op.characteristic.getUuid().equals(UUID_CALL_CONTROL_POINT)) { setCallControlPointResult( device, - op.mOperation.ordinal(), + op.operation.ordinal(), 0, TbsGatt.CALL_CONTROL_POINT_RESULT_OPERATION_NOT_POSSIBLE); } } break; case WRITE_DESCRIPTOR: - if (op.mResponseNeeded) { + if (op.responseNeeded) { mBluetoothGattServer.sendResponse( device, - op.mRequestId, + op.requestId, BluetoothGatt.GATT_INSUFFICIENT_AUTHORIZATION, - op.mOffset, + op.offset, null); } break; @@ -1071,7 +1043,7 @@ public class TbsGatt { } private void onUnauthorizedCharRead(BluetoothDevice device, GattOpContext op) { - UUID charUuid = op.mCharacteristic.getUuid(); + final UUID charUuid = op.characteristic.getUuid(); boolean allowToReadRealValue = false; byte[] buffer = null; @@ -1131,83 +1103,86 @@ public class TbsGatt { } if (allowToReadRealValue) { - if (op.mCharacteristic.getValue() != null) { + if (op.characteristic.getValue() != null) { buffer = Arrays.copyOfRange( - op.mCharacteristic.getValue(), - op.mOffset, - op.mCharacteristic.getValue().length); + op.characteristic.getValue(), + op.offset, + op.characteristic.getValue().length); } } if (buffer != null) { mBluetoothGattServer.sendResponse( - device, op.mRequestId, BluetoothGatt.GATT_SUCCESS, op.mOffset, buffer); + device, op.requestId, BluetoothGatt.GATT_SUCCESS, op.offset, buffer); } else { mEventLogger.loge( TAG, "Missing characteristic value for char: " + tbsUuidToString(charUuid)); mBluetoothGattServer.sendResponse( device, - op.mRequestId, + op.requestId, BluetoothGatt.GATT_INVALID_ATTRIBUTE_LENGTH, - op.mOffset, + op.offset, buffer); } } private void onUnauthorizedGattOperation(BluetoothDevice device, GattOpContext op) { - UUID charUuid = - (op.mCharacteristic != null - ? op.mCharacteristic.getUuid() - : (op.mDescriptor != null - ? op.mDescriptor.getCharacteristic().getUuid() + final UUID charUuid = + (op.characteristic != null + ? op.characteristic.getUuid() + : (op.descriptor != null + ? op.descriptor.getCharacteristic().getUuid() : null)); mEventLogger.logw( TAG, "onUnauthorizedGattOperation device: " + device + ", opcode= " - + op.mOperation + + op.operation + ", characteristic= " + (charUuid != null ? tbsUuidToString(charUuid) : "UNKNOWN")); int status = BluetoothGatt.GATT_SUCCESS; - switch (op.mOperation) { + switch (op.operation) { /* Allow not yet authorized devices to subscribe for notifications */ case READ_DESCRIPTOR: - byte[] value = getCccBytes(device, op.mDescriptor.getCharacteristic().getUuid()); - if (value.length < op.mOffset) { + byte[] value = getCccBytes(device, op.descriptor.getCharacteristic().getUuid()); + if (value.length < op.offset) { Log.e( TAG, ("Wrong offset read for: " - + op.mDescriptor.getCharacteristic().getUuid()) - + (": offset " + op.mOffset) + + op.descriptor.getCharacteristic().getUuid()) + + (": offset " + op.offset) + (", total len: " + value.length)); status = BluetoothGatt.GATT_INVALID_OFFSET; value = new byte[] {}; } else { - value = Arrays.copyOfRange(value, op.mOffset, value.length); + value = Arrays.copyOfRange(value, op.offset, value.length); status = BluetoothGatt.GATT_SUCCESS; } - mBluetoothGattServer.sendResponse(device, op.mRequestId, status, op.mOffset, value); + mBluetoothGattServer.sendResponse(device, op.requestId, status, op.offset, value); return; case WRITE_DESCRIPTOR: - if (op.mPreparedWrite) { + if (op.preparedWrite) { status = BluetoothGatt.GATT_FAILURE; - } else if (op.mOffset > 0) { + } else if (op.offset > 0) { status = BluetoothGatt.GATT_INVALID_OFFSET; - } else if (op.mValue.length != 2) { + } else if (op.value.toByteArray().length != 2) { status = BluetoothGatt.GATT_INVALID_ATTRIBUTE_LENGTH; } else { status = BluetoothGatt.GATT_SUCCESS; - setCcc(device, op.mDescriptor.getCharacteristic().getUuid(), op.mValue); + setCcc( + device, + op.descriptor.getCharacteristic().getUuid(), + op.value.toByteArray()); } - if (op.mResponseNeeded) { + if (op.responseNeeded) { mBluetoothGattServer.sendResponse( - device, op.mRequestId, status, op.mOffset, op.mValue); + device, op.requestId, status, op.offset, op.value.toByteArray()); } return; case READ_CHARACTERISTIC: @@ -1236,26 +1211,26 @@ public class TbsGatt { } private void onAuthorizedGattOperation(BluetoothDevice device, GattOpContext op) { - int status = BluetoothGatt.GATT_SUCCESS; - ClientCharacteristicConfigurationDescriptor cccd; - byte[] value; - - UUID charUuid = - (op.mCharacteristic != null - ? op.mCharacteristic.getUuid() - : (op.mDescriptor != null - ? op.mDescriptor.getCharacteristic().getUuid() + final UUID charUuid = + (op.characteristic != null + ? op.characteristic.getUuid() + : (op.descriptor != null + ? op.descriptor.getCharacteristic().getUuid() : null)); mEventLogger.logd( TAG, "onAuthorizedGattOperation device: " + device + ", opcode= " - + op.mOperation + + op.operation + ", characteristic= " + (charUuid != null ? tbsUuidToString(charUuid) : "UNKNOWN")); - switch (op.mOperation) { + int status = BluetoothGatt.GATT_SUCCESS; + ClientCharacteristicConfigurationDescriptor cccd; + byte[] value; + + switch (op.operation) { case READ_CHARACTERISTIC: Log.d(TAG, "onCharacteristicReadRequest: device=" + device); @@ -1264,7 +1239,7 @@ public class TbsGatt { return; } - if (op.mCharacteristic.getUuid().equals(UUID_STATUS_FLAGS)) { + if (op.characteristic.getUuid().equals(UUID_STATUS_FLAGS)) { value = new byte[2]; int valueInt = mSilentMode ? STATUS_FLAG_SILENT_MODE_ENABLED : 0; if (mStatusFlagValue.containsKey(device)) { @@ -1275,27 +1250,27 @@ public class TbsGatt { value[0] = (byte) (valueInt & 0xFF); value[1] = (byte) ((valueInt >> 8) & 0xFF); } else { - GattCharacteristic gattCharacteristic = (GattCharacteristic) op.mCharacteristic; + GattCharacteristic gattCharacteristic = (GattCharacteristic) op.characteristic; value = gattCharacteristic.getValue(); if (value == null) { value = new byte[0]; } } - if (value.length < op.mOffset) { + if (value.length < op.offset) { status = BluetoothGatt.GATT_INVALID_OFFSET; Log.e( TAG, - ("Wrong offset read for: " + op.mCharacteristic.getUuid()) - + (": offset " + op.mOffset) + ("Wrong offset read for: " + op.characteristic.getUuid()) + + (": offset " + op.offset) + (", total len: " + value.length)); value = new byte[] {}; } else { - value = Arrays.copyOfRange(value, op.mOffset, value.length); + value = Arrays.copyOfRange(value, op.offset, value.length); status = BluetoothGatt.GATT_SUCCESS; } - mBluetoothGattServer.sendResponse(device, op.mRequestId, status, op.mOffset, value); + mBluetoothGattServer.sendResponse(device, op.requestId, status, op.offset, value); break; case WRITE_CHARACTERISTIC: @@ -1306,20 +1281,20 @@ public class TbsGatt { return; } - GattCharacteristic gattCharacteristic = (GattCharacteristic) op.mCharacteristic; - if (op.mPreparedWrite) { + GattCharacteristic gattCharacteristic = (GattCharacteristic) op.characteristic; + if (op.preparedWrite) { status = BluetoothGatt.GATT_FAILURE; - } else if (op.mOffset > 0) { + } else if (op.offset > 0) { status = BluetoothGatt.GATT_INVALID_OFFSET; } else { gattCharacteristic.handleWriteRequest( - device, op.mRequestId, op.mResponseNeeded, op.mValue); + device, op.requestId, op.responseNeeded, op.value.toByteArray()); return; } - if (op.mResponseNeeded) { + if (op.responseNeeded) { mBluetoothGattServer.sendResponse( - device, op.mRequestId, status, op.mOffset, op.mValue); + device, op.requestId, status, op.offset, op.value.toByteArray()); } break; @@ -1331,17 +1306,17 @@ public class TbsGatt { return; } - cccd = (ClientCharacteristicConfigurationDescriptor) op.mDescriptor; + cccd = (ClientCharacteristicConfigurationDescriptor) op.descriptor; value = cccd.getValue(device); - if (value.length < op.mOffset) { + if (value.length < op.offset) { status = BluetoothGatt.GATT_INVALID_OFFSET; value = new byte[] {}; } else { - value = Arrays.copyOfRange(value, op.mOffset, value.length); + value = Arrays.copyOfRange(value, op.offset, value.length); status = BluetoothGatt.GATT_SUCCESS; } - mBluetoothGattServer.sendResponse(device, op.mRequestId, status, op.mOffset, value); + mBluetoothGattServer.sendResponse(device, op.requestId, status, op.offset, value); break; case WRITE_DESCRIPTOR: @@ -1352,21 +1327,21 @@ public class TbsGatt { return; } - cccd = (ClientCharacteristicConfigurationDescriptor) op.mDescriptor; - if (op.mPreparedWrite) { + cccd = (ClientCharacteristicConfigurationDescriptor) op.descriptor; + if (op.preparedWrite) { // TODO: handle prepareWrite status = BluetoothGatt.GATT_FAILURE; - } else if (op.mOffset > 0) { + } else if (op.offset > 0) { status = BluetoothGatt.GATT_INVALID_OFFSET; - } else if (op.mValue.length != 2) { + } else if (op.value.toByteArray().length != 2) { status = BluetoothGatt.GATT_INVALID_ATTRIBUTE_LENGTH; } else { - status = cccd.setValue(device, op.mValue); + status = cccd.setValue(device, op.value.toByteArray()); } - if (op.mResponseNeeded) { + if (op.responseNeeded) { mBluetoothGattServer.sendResponse( - device, op.mRequestId, status, op.mOffset, op.mValue); + device, op.requestId, status, op.offset, op.value.toByteArray()); } break; @@ -1591,7 +1566,7 @@ public class TbsGatt { preparedWrite, responseNeeded, offset, - value); + ByteString.copyFrom(value)); switch (getDeviceAuthorization(device)) { case BluetoothDevice.ACCESS_REJECTED: onRejectedAuthorizationGattOperation(device, op); @@ -1686,7 +1661,7 @@ public class TbsGatt { preparedWrite, responseNeeded, offset, - value); + ByteString.copyFrom(value)); switch (getDeviceAuthorization(device)) { case BluetoothDevice.ACCESS_REJECTED: onRejectedAuthorizationGattOperation(device, op); diff --git a/android/app/tests/unit/src/com/android/bluetooth/avrcp/AvrcpTargetServiceTest.java b/android/app/tests/unit/src/com/android/bluetooth/avrcp/AvrcpTargetServiceTest.java index 172692a4e9..611a04eac6 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/avrcp/AvrcpTargetServiceTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/avrcp/AvrcpTargetServiceTest.java @@ -24,7 +24,7 @@ import static com.android.bluetooth.TestUtils.mockGetSystemService; import static com.google.common.truth.Truth.assertThat; import static org.mockito.Mockito.anyInt; -import static org.mockito.Mockito.anyObject; +import static org.mockito.Mockito.any; import static org.mockito.Mockito.anyString; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.verify; @@ -170,7 +170,7 @@ public class AvrcpTargetServiceTest { mLooper.getLooper()); verify(mMockAudioManager) - .registerAudioDeviceCallback(mAudioDeviceCb.capture(), anyObject()); + .registerAudioDeviceCallback(mAudioDeviceCb.capture(), any()); service.cleanup(); assertThat(mAudioDeviceCb.getValue()).isNotNull(); 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 9fd3d19837..4e510e75a0 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 @@ -1020,8 +1020,6 @@ public class AdapterServiceTest { mAdapterService.dump(fd, writer, new String[] {}); mAdapterService.dump(fd, writer, new String[] {"set-test-mode", "enabled"}); - doReturn(new byte[0]).when(mNativeInterface).dumpMetrics(); - mAdapterService.dump(fd, writer, new String[] {"--proto-bin"}); mAdapterService.dump(fd, writer, new String[] {"random", "arguments"}); assertThat(mLooper.nextMessage()).isNull(); } 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 52741b9746..cdd59bfce3 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 @@ -97,7 +97,7 @@ public class HeadsetPhoneStateTest { public void testListenForPhoneState_NoneResultsNoListen() { BluetoothDevice device1 = getTestDevice(1); mHeadsetPhoneState.listenForPhoneState(device1, PhoneStateListener.LISTEN_NONE); - verifyZeroInteractions(mTelephonyManager); + verifyNoMoreInteractions(mTelephonyManager); } /** 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 0905e185d4..d4b2b39825 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 @@ -773,7 +773,7 @@ public class HeadsetServiceAndStateMachineTest { verify(mSystemInterface).activateVoiceRecognition(); verify(mNativeInterface).atResponseCode(device, HeadsetHalConstants.AT_RESPONSE_ERROR, 0); verifyNoMoreInteractions(ignoreStubs(mNativeInterface)); - verifyZeroInteractions(mAudioManager); + verifyNoMoreInteractions(mAudioManager); } /** @@ -814,7 +814,7 @@ public class HeadsetServiceAndStateMachineTest { anyBoolean(), eq(device)); verifyNoMoreInteractions(ignoreStubs(mNativeInterface)); - verifyZeroInteractions(mAudioManager); + verifyNoMoreInteractions(mAudioManager); } /** @@ -914,7 +914,7 @@ public class HeadsetServiceAndStateMachineTest { assertThat(mHeadsetService.startVoiceRecognition(disconnectedDevice)).isFalse(); mTestLooper.dispatchAll(); verifyNoMoreInteractions(mNativeInterface); - verifyZeroInteractions(mAudioManager); + verifyNoMoreInteractions(mAudioManager); } /** 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 fcfd85fb28..c824c3be86 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 @@ -130,7 +130,7 @@ public class HeadsetStateMachineTest { // Stub system interface doReturn(mPhoneState).when(mSystemInterface).getHeadsetPhoneState(); doReturn(mAudioManager).when(mSystemInterface).getAudioManager(); - doReturn(true).when(mDatabaseManager).setAudioPolicyMetadata(anyObject(), anyObject()); + doReturn(true).when(mDatabaseManager).setAudioPolicyMetadata(any(), any()); doReturn(true).when(mNativeInterface).connectHfp(mDevice); doReturn(true).when(mNativeInterface).disconnectHfp(mDevice); doReturn(true).when(mNativeInterface).connectAudio(mDevice); @@ -1897,7 +1897,7 @@ public class HeadsetStateMachineTest { mDevice)); expectCallTimes++; verify(mDatabaseManager, timeout(ASYNC_CALL_TIMEOUT_MILLIS).times(expectCallTimes)) - .setAudioPolicyMetadata(anyObject(), anyObject()); + .setAudioPolicyMetadata(any(), any()); // receive and not set android policy mHeadsetStateMachine.sendMessage( @@ -1907,7 +1907,7 @@ public class HeadsetStateMachineTest { "AT+ANDROID=PROBE,1,1,\"PQGHRSBCTU__\"", mDevice)); verify(mDatabaseManager, timeout(ASYNC_CALL_TIMEOUT_MILLIS).times(expectCallTimes)) - .setAudioPolicyMetadata(anyObject(), anyObject()); + .setAudioPolicyMetadata(any(), any()); } /** A test to verify whether the sink audio policy command is valid */ @@ -2200,7 +2200,7 @@ public class HeadsetStateMachineTest { new HeadsetStackEvent( HeadsetStackEvent.EVENT_TYPE_UNKNOWN_AT, "+ANDROID=?", mDevice)); verify(mNativeInterface, timeout(ASYNC_CALL_TIMEOUT_MILLIS)) - .atResponseString(anyObject(), anyString()); + .atResponseString(any(), anyString()); } private void configureHeadsetServiceForAptxVoice(boolean enable) { 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 243928ee26..e3f54ca620 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 @@ -126,7 +126,7 @@ public class HeadsetClientStateMachineTest { .getInteger(eq(R.integer.hfp_clcc_poll_interval_during_call)); doReturn(mRemoteDevices).when(mAdapterService).getRemoteDevices(); - doReturn(true).when(mNativeInterface).sendAndroidAt(anyObject(), anyString()); + doReturn(true).when(mNativeInterface).sendAndroidAt(any(), anyString()); doReturn(true).when(mNativeInterface).disconnect(any(BluetoothDevice.class)); @@ -374,7 +374,7 @@ public class HeadsetClientStateMachineTest { doReturn(true).when(mPackageManager).hasSystemFeature(FEATURE_WATCH); // Skip over the Android AT commands to test this code path - doReturn(false).when(mNativeInterface).sendAndroidAt(anyObject(), anyString()); + doReturn(false).when(mNativeInterface).sendAndroidAt(any(), anyString()); // Send an incoming connection event StackEvent event = new StackEvent(StackEvent.EVENT_TYPE_CONNECTION_STATE_CHANGED); @@ -1025,7 +1025,7 @@ public class HeadsetClientStateMachineTest { mHeadsetClientStateMachine.mQueuedActions.clear(); // Test if fail to sendAndroidAt - doReturn(false).when(mNativeInterface).sendAndroidAt(anyObject(), anyString()); + doReturn(false).when(mNativeInterface).sendAndroidAt(any(), anyString()); mHeadsetClientStateMachine.setAudioPolicy(dummyAudioPolicy); assertThat(mHeadsetClientStateMachine.mQueuedActions).isEmpty(); } diff --git a/android/app/tests/unit/src/com/android/bluetooth/le_scan/ScanControllerTest.java b/android/app/tests/unit/src/com/android/bluetooth/le_scan/ScanControllerTest.java index dd8785ccdf..8f2b58cdd8 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/le_scan/ScanControllerTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/le_scan/ScanControllerTest.java @@ -137,14 +137,12 @@ public class ScanControllerTest { testLooper.startAutoDispatch(); mScanController = new ScanController(mAdapterService); - // mScanController.start(testLooper.getLooper()); - mScanController.setScannerMap(mScannerMap); } @After public void tearDown() throws Exception { - mScanController.stop(); + mScanController.cleanup(); GattObjectsFactory.setInstanceForTesting(null); ScanObjectsFactory.setInstanceForTesting(null); 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 08529c26ba..aa203dcdec 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 @@ -16,22 +16,16 @@ package com.android.bluetooth.map; -import static com.android.bluetooth.TestUtils.MockitoRule; - import static com.google.common.truth.Truth.assertThat; -import static org.mockito.Mockito.when; - import android.util.Xml; import androidx.test.runner.AndroidJUnit4; import com.android.bluetooth.SignedLongLong; -import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; -import org.mockito.Mock; import org.xmlpull.v1.XmlPullParser; import org.xmlpull.v1.XmlPullParserFactory; import org.xmlpull.v1.XmlSerializer; @@ -54,10 +48,6 @@ public class BluetoothMapConvoContactElementTest { private final SimpleDateFormat format = new SimpleDateFormat("yyyyMMdd'T'HHmmss"); - @Rule public final MockitoRule mMockitoRule = new MockitoRule(); - - @Mock private MapContact mMapContact; - @Test public void constructorWithArguments() { BluetoothMapConvoContactElement contactElement = @@ -88,10 +78,9 @@ public class BluetoothMapConvoContactElementTest { public void createFromMapContact() { final long id = 1111; final SignedLongLong signedLongLong = new SignedLongLong(id, 0); - when(mMapContact.getId()).thenReturn(id); - when(mMapContact.getName()).thenReturn(TEST_DISPLAY_NAME); + MapContact mapContact = new MapContact(id, TEST_DISPLAY_NAME); BluetoothMapConvoContactElement contactElement = - BluetoothMapConvoContactElement.createFromMapContact(mMapContact, TEST_UCI); + BluetoothMapConvoContactElement.createFromMapContact(mapContact, TEST_UCI); assertThat(contactElement.getContactId()).isEqualTo(TEST_UCI); assertThat(contactElement.getBtUid()).isEqualTo(signedLongLong.toHexString()); assertThat(contactElement.getDisplayName()).isEqualTo(TEST_DISPLAY_NAME); diff --git a/android/app/tests/unit/src/com/android/bluetooth/map/MapContactTest.java b/android/app/tests/unit/src/com/android/bluetooth/map/MapContactTest.java index ce5ef8f05f..ea0490b173 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/map/MapContactTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/map/MapContactTest.java @@ -35,22 +35,22 @@ public class MapContactTest { @Test public void constructor() { - MapContact contact = MapContact.create(TEST_NON_ZERO_ID, TEST_NAME); + MapContact contact = new MapContact(TEST_NON_ZERO_ID, TEST_NAME); - assertThat(contact.getId()).isEqualTo(TEST_NON_ZERO_ID); - assertThat(contact.getName()).isEqualTo(TEST_NAME); + assertThat(contact.id()).isEqualTo(TEST_NON_ZERO_ID); + assertThat(contact.name()).isEqualTo(TEST_NAME); } @Test public void getXBtUidString_withZeroId() { - MapContact contact = MapContact.create(TEST_ZERO_ID, TEST_NAME); + MapContact contact = new MapContact(TEST_ZERO_ID, TEST_NAME); assertThat(contact.getXBtUidString()).isNull(); } @Test public void getXBtUidString_withNonZeroId() { - MapContact contact = MapContact.create(TEST_NON_ZERO_ID, TEST_NAME); + MapContact contact = new MapContact(TEST_NON_ZERO_ID, TEST_NAME); assertThat(contact.getXBtUidString()) .isEqualTo(BluetoothMapUtils.getLongLongAsString(TEST_NON_ZERO_ID, 0)); @@ -58,21 +58,21 @@ public class MapContactTest { @Test public void getXBtUid_withZeroId() { - MapContact contact = MapContact.create(TEST_ZERO_ID, TEST_NAME); + MapContact contact = new MapContact(TEST_ZERO_ID, TEST_NAME); assertThat(contact.getXBtUid()).isNull(); } @Test public void getXBtUid_withNonZeroId() { - MapContact contact = MapContact.create(TEST_NON_ZERO_ID, TEST_NAME); + MapContact contact = new MapContact(TEST_NON_ZERO_ID, TEST_NAME); assertThat(contact.getXBtUid()).isEqualTo(new SignedLongLong(TEST_NON_ZERO_ID, 0)); } @Test public void toString_returnsName() { - MapContact contact = MapContact.create(TEST_NON_ZERO_ID, TEST_NAME); + MapContact contact = new MapContact(TEST_NON_ZERO_ID, TEST_NAME); assertThat(contact.toString()).isEqualTo(TEST_NAME); } 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 eea885ba4c..1397f06280 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 @@ -126,7 +126,7 @@ public class SmsMmsContactsTest { doReturn(cursor) .when(mMapMethodProxy) .contentResolverQuery(any(), any(), any(), any(), any(), any()); - MapContact contact = MapContact.create(TEST_ID, TEST_PHONE); + MapContact contact = new MapContact(TEST_ID, TEST_PHONE); mContacts.mNames.put(TEST_PHONE, contact); mContacts.fillPhoneCache(mResolver); @@ -148,7 +148,7 @@ public class SmsMmsContactsTest { .when(mMapMethodProxy) .contentResolverQuery(any(), any(), any(), any(), any(), any()); - MapContact expected = MapContact.create(TEST_ID, TEST_NAME); + MapContact expected = new MapContact(TEST_ID, TEST_NAME); assertThat( mContacts .getContactNameFromPhone( @@ -181,7 +181,7 @@ public class SmsMmsContactsTest { @Test public void getContactNameFromPhone_withNonNullContact_andZeroId() { long zeroId = 0; - MapContact contact = MapContact.create(zeroId, TEST_PHONE); + MapContact contact = new MapContact(zeroId, TEST_PHONE); mContacts.mNames.put(TEST_PHONE, contact); assertThat( @@ -192,7 +192,7 @@ public class SmsMmsContactsTest { @Test public void getContactNameFromPhone_withNonNullContact_andNullFilter() { - MapContact contact = MapContact.create(TEST_ID, TEST_PHONE); + MapContact contact = new MapContact(TEST_ID, TEST_PHONE); mContacts.mNames.put(TEST_PHONE, contact); assertThat(mContacts.getContactNameFromPhone(TEST_PHONE, mResolver, null)) @@ -201,7 +201,7 @@ public class SmsMmsContactsTest { @Test public void getContactNameFromPhone_withNonNullContact_andNonMatchingFilter() { - MapContact contact = MapContact.create(TEST_ID, TEST_PHONE); + MapContact contact = new MapContact(TEST_ID, TEST_PHONE); mContacts.mNames.put(TEST_PHONE, contact); String nonMatchingFilter = "non_matching_filter"; diff --git a/android/app/tests/unit/src/com/android/bluetooth/pbapclient/PbapClientObexClientTest.java b/android/app/tests/unit/src/com/android/bluetooth/pbapclient/PbapClientObexClientTest.java index fef6b763de..39a0e229fe 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/pbapclient/PbapClientObexClientTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/pbapclient/PbapClientObexClientTest.java @@ -223,8 +223,8 @@ public class PbapClientObexClientTest { .onGetPhonebookMetadataComplete( eq(160), eq(PbapPhonebook.LOCAL_PHONEBOOK_PATH), mMetadataCaptor.capture()); PbapPhonebookMetadata metadata = mMetadataCaptor.getValue(); - assertThat(metadata.getPhonebook()).isEqualTo(PbapPhonebook.LOCAL_PHONEBOOK_PATH); - assertThat(metadata.getSize()).isEqualTo(2); + assertThat(metadata.phonebook()).isEqualTo(PbapPhonebook.LOCAL_PHONEBOOK_PATH); + assertThat(metadata.size()).isEqualTo(2); } // ********************************************************************************************* diff --git a/android/app/tests/unit/src/com/android/bluetooth/pbapclient/PbapPhonebookMetadataTest.java b/android/app/tests/unit/src/com/android/bluetooth/pbapclient/PbapPhonebookMetadataTest.java index ce339d4618..cdd57f8a9c 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/pbapclient/PbapPhonebookMetadataTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/pbapclient/PbapPhonebookMetadataTest.java @@ -40,11 +40,11 @@ public class PbapPhonebookMetadataTest { PRIMARY_VERSION_COUNTER, SECONDARY_VERSION_COUNTER); - assertThat(metadata.getPhonebook()).isEqualTo(PbapPhonebook.FAVORITES_PATH); - assertThat(metadata.getSize()).isEqualTo(SIZE); - assertThat(metadata.getDatabaseIdentifier()).isEqualTo(DATABASE_IDENTIFIER); - assertThat(metadata.getPrimaryVersionCounter()).isEqualTo(PRIMARY_VERSION_COUNTER); - assertThat(metadata.getSecondaryVersionCounter()).isEqualTo(SECONDARY_VERSION_COUNTER); + assertThat(metadata.phonebook()).isEqualTo(PbapPhonebook.FAVORITES_PATH); + assertThat(metadata.size()).isEqualTo(SIZE); + assertThat(metadata.databaseIdentifier()).isEqualTo(DATABASE_IDENTIFIER); + assertThat(metadata.primaryVersionCounter()).isEqualTo(PRIMARY_VERSION_COUNTER); + assertThat(metadata.secondaryVersionCounter()).isEqualTo(SECONDARY_VERSION_COUNTER); String str = metadata.toString(); assertThat(str).isNotNull(); @@ -61,11 +61,11 @@ public class PbapPhonebookMetadataTest { PRIMARY_VERSION_COUNTER, SECONDARY_VERSION_COUNTER); - assertThat(metadata.getPhonebook()).isEqualTo(PbapPhonebook.LOCAL_PHONEBOOK_PATH); - assertThat(metadata.getSize()).isEqualTo(SIZE); - assertThat(metadata.getDatabaseIdentifier()).isEqualTo(DATABASE_IDENTIFIER); - assertThat(metadata.getPrimaryVersionCounter()).isEqualTo(PRIMARY_VERSION_COUNTER); - assertThat(metadata.getSecondaryVersionCounter()).isEqualTo(SECONDARY_VERSION_COUNTER); + assertThat(metadata.phonebook()).isEqualTo(PbapPhonebook.LOCAL_PHONEBOOK_PATH); + assertThat(metadata.size()).isEqualTo(SIZE); + assertThat(metadata.databaseIdentifier()).isEqualTo(DATABASE_IDENTIFIER); + assertThat(metadata.primaryVersionCounter()).isEqualTo(PRIMARY_VERSION_COUNTER); + assertThat(metadata.secondaryVersionCounter()).isEqualTo(SECONDARY_VERSION_COUNTER); String str = metadata.toString(); assertThat(str).isNotNull(); @@ -82,11 +82,11 @@ public class PbapPhonebookMetadataTest { PRIMARY_VERSION_COUNTER, SECONDARY_VERSION_COUNTER); - assertThat(metadata.getPhonebook()).isEqualTo(PbapPhonebook.SIM_PHONEBOOK_PATH); - assertThat(metadata.getSize()).isEqualTo(SIZE); - assertThat(metadata.getDatabaseIdentifier()).isEqualTo(DATABASE_IDENTIFIER); - assertThat(metadata.getPrimaryVersionCounter()).isEqualTo(PRIMARY_VERSION_COUNTER); - assertThat(metadata.getSecondaryVersionCounter()).isEqualTo(SECONDARY_VERSION_COUNTER); + assertThat(metadata.phonebook()).isEqualTo(PbapPhonebook.SIM_PHONEBOOK_PATH); + assertThat(metadata.size()).isEqualTo(SIZE); + assertThat(metadata.databaseIdentifier()).isEqualTo(DATABASE_IDENTIFIER); + assertThat(metadata.primaryVersionCounter()).isEqualTo(PRIMARY_VERSION_COUNTER); + assertThat(metadata.secondaryVersionCounter()).isEqualTo(SECONDARY_VERSION_COUNTER); String str = metadata.toString(); assertThat(str).isNotNull(); @@ -103,13 +103,13 @@ public class PbapPhonebookMetadataTest { PbapPhonebookMetadata.INVALID_VERSION_COUNTER, PbapPhonebookMetadata.INVALID_VERSION_COUNTER); - assertThat(metadata.getPhonebook()).isEqualTo(PbapPhonebook.ICH_PATH); - assertThat(metadata.getSize()).isEqualTo(SIZE); - assertThat(metadata.getDatabaseIdentifier()) + assertThat(metadata.phonebook()).isEqualTo(PbapPhonebook.ICH_PATH); + assertThat(metadata.size()).isEqualTo(SIZE); + assertThat(metadata.databaseIdentifier()) .isEqualTo(PbapPhonebookMetadata.INVALID_DATABASE_IDENTIFIER); - assertThat(metadata.getPrimaryVersionCounter()) + assertThat(metadata.primaryVersionCounter()) .isEqualTo(PbapPhonebookMetadata.INVALID_VERSION_COUNTER); - assertThat(metadata.getSecondaryVersionCounter()) + assertThat(metadata.secondaryVersionCounter()) .isEqualTo(PbapPhonebookMetadata.INVALID_VERSION_COUNTER); String str = metadata.toString(); @@ -127,13 +127,13 @@ public class PbapPhonebookMetadataTest { PbapPhonebookMetadata.INVALID_VERSION_COUNTER, PbapPhonebookMetadata.INVALID_VERSION_COUNTER); - assertThat(metadata.getPhonebook()).isEqualTo(PbapPhonebook.OCH_PATH); - assertThat(metadata.getSize()).isEqualTo(SIZE); - assertThat(metadata.getDatabaseIdentifier()) + assertThat(metadata.phonebook()).isEqualTo(PbapPhonebook.OCH_PATH); + assertThat(metadata.size()).isEqualTo(SIZE); + assertThat(metadata.databaseIdentifier()) .isEqualTo(PbapPhonebookMetadata.INVALID_DATABASE_IDENTIFIER); - assertThat(metadata.getPrimaryVersionCounter()) + assertThat(metadata.primaryVersionCounter()) .isEqualTo(PbapPhonebookMetadata.INVALID_VERSION_COUNTER); - assertThat(metadata.getSecondaryVersionCounter()) + assertThat(metadata.secondaryVersionCounter()) .isEqualTo(PbapPhonebookMetadata.INVALID_VERSION_COUNTER); String str = metadata.toString(); @@ -151,13 +151,13 @@ public class PbapPhonebookMetadataTest { PbapPhonebookMetadata.INVALID_VERSION_COUNTER, PbapPhonebookMetadata.INVALID_VERSION_COUNTER); - assertThat(metadata.getPhonebook()).isEqualTo(PbapPhonebook.MCH_PATH); - assertThat(metadata.getSize()).isEqualTo(SIZE); - assertThat(metadata.getDatabaseIdentifier()) + assertThat(metadata.phonebook()).isEqualTo(PbapPhonebook.MCH_PATH); + assertThat(metadata.size()).isEqualTo(SIZE); + assertThat(metadata.databaseIdentifier()) .isEqualTo(PbapPhonebookMetadata.INVALID_DATABASE_IDENTIFIER); - assertThat(metadata.getPrimaryVersionCounter()) + assertThat(metadata.primaryVersionCounter()) .isEqualTo(PbapPhonebookMetadata.INVALID_VERSION_COUNTER); - assertThat(metadata.getSecondaryVersionCounter()) + assertThat(metadata.secondaryVersionCounter()) .isEqualTo(PbapPhonebookMetadata.INVALID_VERSION_COUNTER); String str = metadata.toString(); @@ -175,13 +175,13 @@ public class PbapPhonebookMetadataTest { PbapPhonebookMetadata.INVALID_VERSION_COUNTER, PbapPhonebookMetadata.INVALID_VERSION_COUNTER); - assertThat(metadata.getPhonebook()).isEqualTo(PbapPhonebook.SIM_ICH_PATH); - assertThat(metadata.getSize()).isEqualTo(SIZE); - assertThat(metadata.getDatabaseIdentifier()) + assertThat(metadata.phonebook()).isEqualTo(PbapPhonebook.SIM_ICH_PATH); + assertThat(metadata.size()).isEqualTo(SIZE); + assertThat(metadata.databaseIdentifier()) .isEqualTo(PbapPhonebookMetadata.INVALID_DATABASE_IDENTIFIER); - assertThat(metadata.getPrimaryVersionCounter()) + assertThat(metadata.primaryVersionCounter()) .isEqualTo(PbapPhonebookMetadata.INVALID_VERSION_COUNTER); - assertThat(metadata.getSecondaryVersionCounter()) + assertThat(metadata.secondaryVersionCounter()) .isEqualTo(PbapPhonebookMetadata.INVALID_VERSION_COUNTER); String str = metadata.toString(); @@ -199,13 +199,13 @@ public class PbapPhonebookMetadataTest { PbapPhonebookMetadata.INVALID_VERSION_COUNTER, PbapPhonebookMetadata.INVALID_VERSION_COUNTER); - assertThat(metadata.getPhonebook()).isEqualTo(PbapPhonebook.SIM_OCH_PATH); - assertThat(metadata.getSize()).isEqualTo(SIZE); - assertThat(metadata.getDatabaseIdentifier()) + assertThat(metadata.phonebook()).isEqualTo(PbapPhonebook.SIM_OCH_PATH); + assertThat(metadata.size()).isEqualTo(SIZE); + assertThat(metadata.databaseIdentifier()) .isEqualTo(PbapPhonebookMetadata.INVALID_DATABASE_IDENTIFIER); - assertThat(metadata.getPrimaryVersionCounter()) + assertThat(metadata.primaryVersionCounter()) .isEqualTo(PbapPhonebookMetadata.INVALID_VERSION_COUNTER); - assertThat(metadata.getSecondaryVersionCounter()) + assertThat(metadata.secondaryVersionCounter()) .isEqualTo(PbapPhonebookMetadata.INVALID_VERSION_COUNTER); String str = metadata.toString(); @@ -223,13 +223,13 @@ public class PbapPhonebookMetadataTest { PbapPhonebookMetadata.INVALID_VERSION_COUNTER, PbapPhonebookMetadata.INVALID_VERSION_COUNTER); - assertThat(metadata.getPhonebook()).isEqualTo(PbapPhonebook.SIM_MCH_PATH); - assertThat(metadata.getSize()).isEqualTo(SIZE); - assertThat(metadata.getDatabaseIdentifier()) + assertThat(metadata.phonebook()).isEqualTo(PbapPhonebook.SIM_MCH_PATH); + assertThat(metadata.size()).isEqualTo(SIZE); + assertThat(metadata.databaseIdentifier()) .isEqualTo(PbapPhonebookMetadata.INVALID_DATABASE_IDENTIFIER); - assertThat(metadata.getPrimaryVersionCounter()) + assertThat(metadata.primaryVersionCounter()) .isEqualTo(PbapPhonebookMetadata.INVALID_VERSION_COUNTER); - assertThat(metadata.getSecondaryVersionCounter()) + assertThat(metadata.secondaryVersionCounter()) .isEqualTo(PbapPhonebookMetadata.INVALID_VERSION_COUNTER); String str = metadata.toString(); diff --git a/android/app/tests/unit/src/com/android/bluetooth/pbapclient/RequestPullPhonebookMetadataTest.java b/android/app/tests/unit/src/com/android/bluetooth/pbapclient/RequestPullPhonebookMetadataTest.java index 44744c837a..bdad362075 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/pbapclient/RequestPullPhonebookMetadataTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/pbapclient/RequestPullPhonebookMetadataTest.java @@ -81,13 +81,13 @@ public class RequestPullPhonebookMetadataTest { assertThat(mRequest.getPhonebook()).isEqualTo(PHONEBOOK_NAME); PbapPhonebookMetadata metadata = mRequest.getMetadata(); - assertThat(metadata.getPhonebook()).isEqualTo(PHONEBOOK_NAME); - assertThat(metadata.getSize()).isEqualTo(200); - assertThat(metadata.getDatabaseIdentifier()) + assertThat(metadata.phonebook()).isEqualTo(PHONEBOOK_NAME); + assertThat(metadata.size()).isEqualTo(200); + assertThat(metadata.databaseIdentifier()) .isEqualTo(PbapPhonebookMetadata.INVALID_DATABASE_IDENTIFIER); - assertThat(metadata.getPrimaryVersionCounter()) + assertThat(metadata.primaryVersionCounter()) .isEqualTo(PbapPhonebookMetadata.INVALID_VERSION_COUNTER); - assertThat(metadata.getSecondaryVersionCounter()) + assertThat(metadata.secondaryVersionCounter()) .isEqualTo(PbapPhonebookMetadata.INVALID_VERSION_COUNTER); } @@ -101,13 +101,13 @@ public class RequestPullPhonebookMetadataTest { assertThat(mRequest.getPhonebook()).isEqualTo(PHONEBOOK_NAME); PbapPhonebookMetadata metadata = mRequest.getMetadata(); - assertThat(metadata.getPhonebook()).isEqualTo(PHONEBOOK_NAME); - assertThat(metadata.getSize()).isEqualTo(PbapPhonebookMetadata.INVALID_SIZE); - assertThat(metadata.getDatabaseIdentifier()) + assertThat(metadata.phonebook()).isEqualTo(PHONEBOOK_NAME); + assertThat(metadata.size()).isEqualTo(PbapPhonebookMetadata.INVALID_SIZE); + assertThat(metadata.databaseIdentifier()) .isEqualTo(PbapPhonebookMetadata.INVALID_DATABASE_IDENTIFIER); - assertThat(metadata.getPrimaryVersionCounter()) + assertThat(metadata.primaryVersionCounter()) .isEqualTo(PbapPhonebookMetadata.INVALID_VERSION_COUNTER); - assertThat(metadata.getSecondaryVersionCounter()) + assertThat(metadata.secondaryVersionCounter()) .isEqualTo(PbapPhonebookMetadata.INVALID_VERSION_COUNTER); } @@ -122,8 +122,7 @@ public class RequestPullPhonebookMetadataTest { try { HeaderSet headerSet = new HeaderSet(); mRequest.readResponseHeaders(headerSet); - assertThat(mRequest.getMetadata().getSize()) - .isEqualTo(PbapPhonebookMetadata.INVALID_SIZE); + assertThat(mRequest.getMetadata().size()).isEqualTo(PbapPhonebookMetadata.INVALID_SIZE); } catch (Exception e) { assertWithMessage("Exception should not happen.").fail(); } diff --git a/system/audio_hal_interface/Android.bp b/system/audio_hal_interface/Android.bp index a171e79fa5..c792ff1186 100644 --- a/system/audio_hal_interface/Android.bp +++ b/system/audio_hal_interface/Android.bp @@ -224,7 +224,6 @@ cc_defaults { "android.hardware.common.fmq-V1-ndk", "libFraunhoferAAC", "libbase", - "libbluetooth-protos", "libbluetooth-types", "libbluetooth_core_rs", "libbluetooth_crypto_toolbox", diff --git a/system/audio_hal_interface/aidl/a2dp/a2dp_encoding_aidl.cc b/system/audio_hal_interface/aidl/a2dp/a2dp_encoding_aidl.cc index cfb0d020d4..01924e2e17 100644 --- a/system/audio_hal_interface/aidl/a2dp/a2dp_encoding_aidl.cc +++ b/system/audio_hal_interface/aidl/a2dp/a2dp_encoding_aidl.cc @@ -832,6 +832,11 @@ provider::get_a2dp_configuration( break; } + auto codec = provider_info->GetCodec(user_preferences.codec_type); + if (codec.has_value()) { + hint.codecId = codec.value()->id; + } + log::info("remote capabilities:"); for (auto const& sep : a2dp_remote_capabilities) { log::info("- {}", sep.toString()); diff --git a/system/audio_hal_interface/fuzzer/Android.bp b/system/audio_hal_interface/fuzzer/Android.bp index faf52cb3b9..a594041275 100644 --- a/system/audio_hal_interface/fuzzer/Android.bp +++ b/system/audio_hal_interface/fuzzer/Android.bp @@ -59,7 +59,6 @@ cc_defaults { "bluetooth_flags_c_lib", "libFraunhoferAAC", "libbase", - "libbluetooth-protos", "libbluetooth-types", "libbluetooth_core_rs", "libbluetooth_crypto_toolbox", diff --git a/system/btcore/fuzzer/Android.bp b/system/btcore/fuzzer/Android.bp index c930086694..07b8c28f89 100644 --- a/system/btcore/fuzzer/Android.bp +++ b/system/btcore/fuzzer/Android.bp @@ -31,7 +31,6 @@ cc_defaults { ], static_libs: [ "libbase", - "libbluetooth-protos", "libbluetooth-types", "libbluetooth_crypto_toolbox", "libbluetooth_log", diff --git a/system/btif/src/bluetooth.cc b/system/btif/src/bluetooth.cc index 1e3db0be50..5741b05c4f 100644 --- a/system/btif/src/bluetooth.cc +++ b/system/btif/src/bluetooth.cc @@ -82,7 +82,6 @@ #include "btif/include/core_callbacks.h" #include "btif/include/stack_manager_t.h" #include "common/address_obfuscator.h" -#include "common/metrics.h" #include "common/os_utils.h" #include "device/include/device_iot_config.h" #include "device/include/esco_parameters.h" @@ -896,10 +895,6 @@ static void dump(int fd, const char** /*arguments*/) { log::debug("Finished bluetooth dumpsys"); } -static void dumpMetrics(std::string* output) { - bluetooth::common::BluetoothMetricsLogger::GetInstance()->WriteString(output); -} - static int get_remote_pbap_pce_version(const RawAddress* bd_addr) { // Read and restore the PCE version from local storage uint16_t pce_version = 0; @@ -1246,7 +1241,6 @@ EXPORT_SYMBOL bt_interface_t bluetoothInterface = { .set_os_callouts = set_os_callouts, .read_energy_info = read_energy_info, .dump = dump, - .dumpMetrics = dumpMetrics, .config_clear = config_clear, .interop_database_clear = interop_database_clear, .interop_database_add = interop_database_add, diff --git a/system/btif/src/btif_a2dp_source.cc b/system/btif/src/btif_a2dp_source.cc index 25a5fe7093..b8ace80b07 100644 --- a/system/btif/src/btif_a2dp_source.cc +++ b/system/btif/src/btif_a2dp_source.cc @@ -71,8 +71,6 @@ #endif using bluetooth::audio::a2dp::Status; -using bluetooth::common::A2dpSessionMetrics; -using bluetooth::common::BluetoothMetricsLogger; using bluetooth::common::RepeatingTimer; using namespace bluetooth; @@ -492,11 +490,6 @@ static void btif_a2dp_source_start_session_delayed(const RawAddress& peer_addres if (bluetooth::audio::a2dp::is_hal_enabled()) { bluetooth::audio::a2dp::start_session(); bluetooth::audio::a2dp::set_remote_delay(btif_av_get_audio_delay(A2dpType::kSource)); - BluetoothMetricsLogger::GetInstance()->LogBluetoothSessionStart( - bluetooth::common::CONNECTION_TECHNOLOGY_TYPE_BREDR, 0); - } else { - BluetoothMetricsLogger::GetInstance()->LogBluetoothSessionStart( - bluetooth::common::CONNECTION_TECHNOLOGY_TYPE_BREDR, 0); } peer_ready_promise.set_value(); @@ -550,11 +543,6 @@ static void btif_a2dp_source_end_session_delayed(const RawAddress& peer_address) } if (bluetooth::audio::a2dp::is_hal_enabled()) { bluetooth::audio::a2dp::end_session(); - BluetoothMetricsLogger::GetInstance()->LogBluetoothSessionEnd( - bluetooth::common::DISCONNECT_REASON_UNKNOWN, 0); - } else { - BluetoothMetricsLogger::GetInstance()->LogBluetoothSessionEnd( - bluetooth::common::DISCONNECT_REASON_UNKNOWN, 0); } } @@ -1267,9 +1255,24 @@ void btif_a2dp_source_debug_dump(int fd) { (unsigned long long)ave_time_us / 1000); } +struct A2dpSessionMetrics { + int64_t audio_duration_ms = -1; + int32_t media_timer_min_ms = -1; + int32_t media_timer_max_ms = -1; + int32_t media_timer_avg_ms = -1; + int64_t total_scheduling_count = -1; + int32_t buffer_overruns_max_count = -1; + int32_t buffer_overruns_total = -1; + float buffer_underruns_average = -1; + int32_t buffer_underruns_count = -1; + int64_t codec_index = -1; + bool is_a2dp_offload = false; +}; + static void btif_a2dp_source_update_metrics(void) { BtifMediaStats stats = btif_a2dp_source_cb.stats; SchedulingStats enqueue_stats = stats.tx_queue_enqueue_stats; + A2dpSessionMetrics metrics; metrics.codec_index = stats.codec_index; metrics.is_a2dp_offload = btif_av_is_a2dp_offload_running(); @@ -1303,7 +1306,6 @@ static void btif_a2dp_source_update_metrics(void) { (float)stats.media_read_total_underflow_bytes / metrics.buffer_underruns_count; } } - BluetoothMetricsLogger::GetInstance()->LogA2dpSession(metrics); if (metrics.audio_duration_ms != -1) { log_a2dp_session_metrics_event(btif_av_source_active_peer(), metrics.audio_duration_ms, diff --git a/system/btif/src/btif_config.cc b/system/btif/src/btif_config.cc index f17548cf63..2ee8fe494d 100644 --- a/system/btif/src/btif_config.cc +++ b/system/btif/src/btif_config.cc @@ -34,7 +34,6 @@ #include "btif_keystore.h" #include "btif_metrics_logging.h" #include "common/address_obfuscator.h" -#include "common/metric_id_allocator.h" #include "main/shim/config.h" #include "main/shim/shim.h" #include "storage/config_keys.h" @@ -50,7 +49,6 @@ using bluetooth::bluetooth_keystore::BluetoothKeystoreInterface; using bluetooth::common::AddressObfuscator; -using bluetooth::common::MetricIdAllocator; using namespace bluetooth; // Key attestation @@ -124,11 +122,10 @@ static void init_metric_id_allocator() { } // Initialize MetricIdAllocator - MetricIdAllocator::Callback save_device_callback = [](const RawAddress& address, const int id) { + auto save_device_callback = [](const RawAddress& address, const int id) { return btif_config_set_int(address.ToString(), BTIF_STORAGE_KEY_METRICS_ID_KEY, id); }; - MetricIdAllocator::Callback forget_device_callback = [](const RawAddress& address, - const int /* id */) { + auto forget_device_callback = [](const RawAddress& address, const int /* id */) { return btif_config_remove(address.ToString(), BTIF_STORAGE_KEY_METRICS_ID_KEY); }; if (!init_metric_id_allocator(paired_device_map, std::move(save_device_callback), diff --git a/system/btif/src/btif_dm.cc b/system/btif/src/btif_dm.cc index 84c7b7e1f6..96ed5848b1 100644 --- a/system/btif/src/btif_dm.cc +++ b/system/btif/src/btif_dm.cc @@ -62,7 +62,6 @@ #include "btif_storage.h" #include "btif_util.h" #include "common/lru_cache.h" -#include "common/metrics.h" #include "common/strings.h" #include "device/include/interop.h" #include "hci/controller_interface.h" @@ -3873,29 +3872,6 @@ static void btif_stats_add_bond_event(const RawAddress& bd_addr, bt_bond_functio if (btif_events_end_index == btif_events_start_index) { btif_events_start_index = (btif_events_start_index + 1) % (MAX_BTIF_BOND_EVENT_ENTRIES + 1); } - - int type; - btif_get_device_type(bd_addr, &type); - - bluetooth::common::device_type_t device_type; - switch (type) { - case BT_DEVICE_TYPE_BREDR: - device_type = bluetooth::common::DEVICE_TYPE_BREDR; - break; - case BT_DEVICE_TYPE_BLE: - device_type = bluetooth::common::DEVICE_TYPE_LE; - break; - case BT_DEVICE_TYPE_DUMO: - device_type = bluetooth::common::DEVICE_TYPE_DUMO; - break; - default: - device_type = bluetooth::common::DEVICE_TYPE_UNKNOWN; - break; - } - - uint32_t cod = btif_get_cod(&bd_addr); - uint64_t ts = event->timestamp.tv_sec * 1000 + event->timestamp.tv_nsec / 1000000; - bluetooth::common::BluetoothMetricsLogger::GetInstance()->LogPairEvent(0, ts, cod, device_type); } void btif_debug_bond_event_dump(int fd) { diff --git a/system/btif/src/btif_hf.cc b/system/btif/src/btif_hf.cc index 49e183d06b..33fb900e07 100644 --- a/system/btif/src/btif_hf.cc +++ b/system/btif/src/btif_hf.cc @@ -55,7 +55,6 @@ #include "btif/include/btif_profile_queue.h" #include "btif/include/btif_util.h" #include "btm_api_types.h" -#include "common/metrics.h" #include "device/include/device_iot_conf_defs.h" #include "device/include/device_iot_config.h" #include "hardware/bluetooth.h" @@ -434,8 +433,6 @@ static void btif_hf_upstreams_evt(uint16_t event, char* p_param) { btif_hf_cb[idx].state = BTHF_CONNECTION_STATE_CONNECTED; btif_hf_cb[idx].peer_feat = 0; clear_phone_state_multihf(&btif_hf_cb[idx]); - bluetooth::common::BluetoothMetricsLogger::GetInstance()->LogHeadsetProfileRfcConnection( - p_data->open.service_id); bt_hf_callbacks->ConnectionStateCallback(btif_hf_cb[idx].state, &btif_hf_cb[idx].connected_bda); } else { diff --git a/system/common/Android.bp b/system/common/Android.bp index e4efd7156e..98e99e6d7b 100644 --- a/system/common/Android.bp +++ b/system/common/Android.bp @@ -22,7 +22,6 @@ cc_library_static { "address_obfuscator.cc", "le_conn_params.cc", "message_loop_thread.cc", - "metric_id_allocator.cc", "os_utils.cc", "repeating_timer.cc", "stop_watch_legacy.cc", @@ -36,7 +35,6 @@ cc_library_static { target: { android: { srcs: [ - ":bluetooth-metrics-proto", "metrics.cc", ], static_libs: ["libstatslog_bt"], @@ -83,14 +81,12 @@ cc_test { "leaky_bonded_queue_unittest.cc", "lru_unittest.cc", "message_loop_thread_unittest.cc", - "metric_id_allocator_unittest.cc", "repeating_timer_unittest.cc", "state_machine_unittest.cc", "time_util_unittest.cc", ], target: { android: { - srcs: ["metrics_unittest.cc"], shared_libs: ["libstatssocket"], }, }, diff --git a/system/common/metric_id_allocator.cc b/system/common/metric_id_allocator.cc deleted file mode 100644 index 041e272815..0000000000 --- a/system/common/metric_id_allocator.cc +++ /dev/null @@ -1,200 +0,0 @@ -/****************************************************************************** - * - * Copyright 2020 Google, Inc. - * - * 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. - * - ******************************************************************************/ - -#include "metric_id_allocator.h" - -#include <bluetooth/log.h> - -#include <functional> -#include <mutex> -#include <thread> - -#include "types/raw_address.h" - -namespace bluetooth { - -namespace common { - -const std::string MetricIdAllocator::LOGGING_TAG = "BluetoothMetricIdAllocator"; -const size_t MetricIdAllocator::kMaxNumUnpairedDevicesInMemory = 200; -const size_t MetricIdAllocator::kMaxNumPairedDevicesInMemory = 65000; -const int MetricIdAllocator::kMinId = 1; -const int MetricIdAllocator::kMaxId = 65534; // 2^16 - 2 - -// id space should always be larger than kMaxNumPairedDevicesInMemory + -// kMaxNumUnpairedDevicesInMemory -static_assert((MetricIdAllocator::kMaxNumUnpairedDevicesInMemory + - MetricIdAllocator::kMaxNumPairedDevicesInMemory) < - (MetricIdAllocator::kMaxId - MetricIdAllocator::kMinId), - "id space should always be larger than " - "kMaxNumPairedDevicesInMemory + MaxNumUnpairedDevicesInMemory"); - -MetricIdAllocator::MetricIdAllocator() - : paired_device_cache_(kMaxNumPairedDevicesInMemory, LOGGING_TAG), - temporary_device_cache_(kMaxNumUnpairedDevicesInMemory, LOGGING_TAG) {} - -bool MetricIdAllocator::Init(const std::unordered_map<RawAddress, int>& paired_device_map, - Callback save_id_callback, Callback forget_device_callback) { - std::lock_guard<std::mutex> lock(id_allocator_mutex_); - if (initialized_) { - return false; - } - - // init paired_devices_map - if (paired_device_map.size() > kMaxNumPairedDevicesInMemory) { - log::fatal("{}Paired device map is bigger than kMaxNumPairedDevicesInMemory", LOGGING_TAG); - // fail loudly to let caller know - return false; - } - - next_id_ = kMinId; - for (const auto& p : paired_device_map) { - if (p.second < kMinId || p.second > kMaxId) { - log::fatal("{}Invalid Bluetooth Metric Id in config", LOGGING_TAG); - } - auto evicted = paired_device_cache_.Put(p.first, p.second); - if (evicted) { - ForgetDevicePostprocess(evicted->first, evicted->second); - } - id_set_.insert(p.second); - next_id_ = std::max(next_id_, p.second + 1); - } - if (next_id_ > kMaxId) { - next_id_ = kMinId; - } - - // init callbacks - save_id_callback_ = save_id_callback; - forget_device_callback_ = forget_device_callback; - - return initialized_ = true; -} - -MetricIdAllocator::~MetricIdAllocator() { Close(); } - -bool MetricIdAllocator::Close() { - std::lock_guard<std::mutex> lock(id_allocator_mutex_); - if (!initialized_) { - return false; - } - paired_device_cache_.Clear(); - temporary_device_cache_.Clear(); - id_set_.clear(); - initialized_ = false; - return true; -} - -MetricIdAllocator& MetricIdAllocator::GetInstance() { - static MetricIdAllocator metric_id_allocator; - return metric_id_allocator; -} - -bool MetricIdAllocator::IsEmpty() const { - std::lock_guard<std::mutex> lock(id_allocator_mutex_); - return paired_device_cache_.Size() == 0 && temporary_device_cache_.Size() == 0; -} - -// call this function when a new device is scanned -int MetricIdAllocator::AllocateId(const RawAddress& mac_address) { - std::lock_guard<std::mutex> lock(id_allocator_mutex_); - int id = 0; - // if already have an id, return it - if (paired_device_cache_.Get(mac_address, &id)) { - return id; - } - if (temporary_device_cache_.Get(mac_address, &id)) { - return id; - } - - // find next available id - while (id_set_.count(next_id_) > 0) { - next_id_++; - if (next_id_ > kMaxId) { - next_id_ = kMinId; - log::warn("{}Bluetooth metric id overflow.", LOGGING_TAG); - } - } - id = next_id_++; - id_set_.insert(id); - auto evicted = temporary_device_cache_.Put(mac_address, id); - if (evicted) { - this->id_set_.erase(evicted->second); - } - - if (next_id_ > kMaxId) { - next_id_ = kMinId; - } - return id; -} - -// call this function when a device is paired -bool MetricIdAllocator::SaveDevice(const RawAddress& mac_address) { - std::lock_guard<std::mutex> lock(id_allocator_mutex_); - int id = 0; - if (paired_device_cache_.Get(mac_address, &id)) { - return true; - } - if (!temporary_device_cache_.Get(mac_address, &id)) { - log::error( - "{}Failed to save device because device is not in " - "temporary_device_cache_", - LOGGING_TAG); - return false; - } - if (!temporary_device_cache_.Remove(mac_address)) { - log::error("{}Failed to remove device from temporary_device_cache_", LOGGING_TAG); - return false; - } - auto evicted = paired_device_cache_.Put(mac_address, id); - if (evicted) { - ForgetDevicePostprocess(evicted->first, evicted->second); - } - if (!save_id_callback_(mac_address, id)) { - log::error("{}Callback returned false after saving the device", LOGGING_TAG); - return false; - } - return true; -} - -// call this function when a device is forgotten -void MetricIdAllocator::ForgetDevice(const RawAddress& mac_address) { - std::lock_guard<std::mutex> lock(id_allocator_mutex_); - int id = 0; - if (!paired_device_cache_.Get(mac_address, &id)) { - log::error( - "{}Failed to forget device because device is not in " - "paired_device_cache_", - LOGGING_TAG); - return; - } - if (!paired_device_cache_.Remove(mac_address)) { - log::error("{}Failed to remove device from paired_device_cache_", LOGGING_TAG); - return; - } - ForgetDevicePostprocess(mac_address, id); -} - -bool MetricIdAllocator::IsValidId(const int id) { return id >= kMinId && id <= kMaxId; } - -void MetricIdAllocator::ForgetDevicePostprocess(const RawAddress& mac_address, const int id) { - id_set_.erase(id); - forget_device_callback_(mac_address, id); -} - -} // namespace common -} // namespace bluetooth diff --git a/system/common/metric_id_allocator.h b/system/common/metric_id_allocator.h deleted file mode 100644 index adc70bb073..0000000000 --- a/system/common/metric_id_allocator.h +++ /dev/null @@ -1,139 +0,0 @@ -/****************************************************************************** - * - * Copyright 2020 Google, Inc. - * - * 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. - * - ******************************************************************************/ - -#pragma once - -#include <mutex> -#include <string> -#include <thread> -#include <unordered_set> - -#include "lru.h" -#include "types/raw_address.h" - -namespace bluetooth { - -namespace common { - -class MetricIdAllocator { -public: - using Callback = std::function<bool(const RawAddress& address, const int id)>; - - static const size_t kMaxNumUnpairedDevicesInMemory; - static const size_t kMaxNumPairedDevicesInMemory; - - static const int kMinId; - static const int kMaxId; - - ~MetricIdAllocator(); - - /** - * Get the instance of singleton - * - * @return MetricIdAllocator& - */ - static MetricIdAllocator& GetInstance(); - - /** - * Initialize the allocator - * - * @param paired_device_map map from mac_address to id already saved - * in the disk before init - * @param save_id_callback a callback that will be called after successfully - * saving id for a paired device - * @param forget_device_callback a callback that will be called after - * successful id deletion for forgotten device, - * @return true if successfully initialized - */ - bool Init(const std::unordered_map<RawAddress, int>& paired_device_map, Callback save_id_callback, - Callback forget_device_callback); - - /** - * Close the allocator. should be called when Bluetooth process is killed - * - * @return true if successfully close - */ - bool Close(); - - /** - * Check if no id saved in memory - * - * @return true if no id is saved - */ - bool IsEmpty() const; - - /** - * Allocate an id for a scanned device, or return the id if there is already - * one - * - * @param mac_address mac address of Bluetooth device - * @return the id of device - */ - int AllocateId(const RawAddress& mac_address); - - /** - * Save the id for a paired device - * - * @param mac_address mac address of Bluetooth device - * @return true if save successfully - */ - bool SaveDevice(const RawAddress& mac_address); - - /** - * Delete the id for a device to be forgotten - * - * @param mac_address mac address of Bluetooth device - */ - void ForgetDevice(const RawAddress& mac_address); - - /** - * Check if an id is valid. - * The id should be less than or equal to kMaxId and bigger than or equal to - * kMinId - * - * @param mac_address mac address of Bluetooth device - * @return true if delete successfully - */ - static bool IsValidId(const int id); - -protected: - // Singleton - MetricIdAllocator(); - -private: - static const std::string LOGGING_TAG; - mutable std::mutex id_allocator_mutex_; - - LegacyLruCache<RawAddress, int> paired_device_cache_; - LegacyLruCache<RawAddress, int> temporary_device_cache_; - std::unordered_set<int> id_set_; - - int next_id_{kMinId}; - bool initialized_{false}; - Callback save_id_callback_; - Callback forget_device_callback_; - - void ForgetDevicePostprocess(const RawAddress& mac_address, const int id); - - // delete copy constructor for singleton - MetricIdAllocator(MetricIdAllocator const&) = delete; - MetricIdAllocator& operator=(MetricIdAllocator const&) = delete; -}; - -} // namespace common -} // namespace bluetooth diff --git a/system/common/metric_id_allocator_unittest.cc b/system/common/metric_id_allocator_unittest.cc deleted file mode 100644 index 8172d57319..0000000000 --- a/system/common/metric_id_allocator_unittest.cc +++ /dev/null @@ -1,432 +0,0 @@ -/****************************************************************************** - * - * Copyright 2020 Google, Inc. - * - * 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. - * - ******************************************************************************/ - -#include "common/metric_id_allocator.h" - -#include <gmock/gmock.h> -#include <gtest/gtest.h> - -#include <thread> - -#include "types/raw_address.h" - -namespace testing { - -using bluetooth::common::MetricIdAllocator; - -static RawAddress kthAddress(uint32_t k) { - uint8_t array[6] = {0, 0, 0, 0, 0, 0}; - for (int i = 5; i >= 2; i--) { - array[i] = k % 256; - k = k / 256; - } - RawAddress addr(array); - return addr; -} - -static std::unordered_map<RawAddress, int> generateAddresses(const uint32_t num) { - // generate first num of mac address -> id pairs - // input may is always valid 256^6 = 2^48 > 2^32 - std::unordered_map<RawAddress, int> device_map; - for (size_t key = 0; key < num; key++) { - device_map[kthAddress(key)] = key + MetricIdAllocator::kMinId; - } - return device_map; -} - -TEST(BluetoothMetricIdAllocatorTest, MetricIdAllocatorInitCloseTest) { - auto& allocator = MetricIdAllocator::GetInstance(); - std::unordered_map<RawAddress, int> paired_device_map; - MetricIdAllocator::Callback callback = [](const RawAddress&, const int) { return true; }; - EXPECT_TRUE(allocator.Init(paired_device_map, callback, callback)); - EXPECT_FALSE(allocator.Init(paired_device_map, callback, callback)); - EXPECT_TRUE(allocator.Close()); -} - -TEST(BluetoothMetricIdAllocatorTest, MetricIdAllocatorNotCloseTest) { - auto& allocator = MetricIdAllocator::GetInstance(); - std::unordered_map<RawAddress, int> paired_device_map; - MetricIdAllocator::Callback callback = [](const RawAddress&, const int) { return true; }; - EXPECT_TRUE(allocator.Init(paired_device_map, callback, callback)); - - // should fail because it isn't closed - EXPECT_FALSE(allocator.Init(paired_device_map, callback, callback)); - EXPECT_TRUE(allocator.Close()); -} - -TEST(BluetoothMetricIdAllocatorTest, MetricIdAllocatorScanDeviceFromEmptyTest) { - auto& allocator = MetricIdAllocator::GetInstance(); - std::unordered_map<RawAddress, int> paired_device_map; - MetricIdAllocator::Callback callback = [](const RawAddress&, const int) { return true; }; - // test empty map, next id should be kMinId - EXPECT_TRUE(allocator.Init(paired_device_map, callback, callback)); - EXPECT_EQ(allocator.AllocateId(kthAddress(0)), MetricIdAllocator::kMinId); - EXPECT_EQ(allocator.AllocateId(kthAddress(1)), MetricIdAllocator::kMinId + 1); - EXPECT_EQ(allocator.AllocateId(kthAddress(0)), MetricIdAllocator::kMinId); - EXPECT_EQ(allocator.AllocateId(kthAddress(2)), MetricIdAllocator::kMinId + 2); - EXPECT_TRUE(allocator.Close()); -} - -TEST(BluetoothMetricIdAllocatorTest, MetricIdAllocatorScanDeviceFromFilledTest) { - auto& allocator = MetricIdAllocator::GetInstance(); - std::unordered_map<RawAddress, int> paired_device_map; - MetricIdAllocator::Callback callback = [](const RawAddress&, const int) { return true; }; - int id = static_cast<int>(MetricIdAllocator::kMaxNumPairedDevicesInMemory) + - MetricIdAllocator::kMinId; - // next id should be MetricIdAllocator::kMaxNumPairedDevicesInMemory - paired_device_map = generateAddresses(MetricIdAllocator::kMaxNumPairedDevicesInMemory); - EXPECT_TRUE(allocator.Init(paired_device_map, callback, callback)); - // try new values not in the map, should get new id. - EXPECT_EQ(allocator.AllocateId(kthAddress(INT_MAX)), id); - EXPECT_EQ(allocator.AllocateId(kthAddress(INT_MAX - 1)), id + 1); - EXPECT_EQ(allocator.AllocateId(kthAddress(INT_MAX)), id); - EXPECT_EQ(allocator.AllocateId(kthAddress(INT_MAX - 2)), id + 2); - EXPECT_TRUE(allocator.Close()); -} - -TEST(BluetoothMetricIdAllocatorTest, MetricIdAllocatorAllocateExistingTest) { - auto& allocator = MetricIdAllocator::GetInstance(); - std::unordered_map<RawAddress, int> paired_device_map = - generateAddresses(MetricIdAllocator::kMaxNumPairedDevicesInMemory); - - MetricIdAllocator::Callback callback = [](const RawAddress&, const int) { return true; }; - int id = MetricIdAllocator::kMinId; - // next id should be MetricIdAllocator::kMaxNumPairedDevicesInMemory - EXPECT_TRUE(allocator.Init(paired_device_map, callback, callback)); - - // try values already in the map, should get new id. - EXPECT_EQ(allocator.AllocateId(RawAddress({0, 0, 0, 0, 0, 0})), id); - EXPECT_EQ(allocator.AllocateId(RawAddress({0, 0, 0, 0, 0, 1})), id + 1); - EXPECT_EQ(allocator.AllocateId(RawAddress({0, 0, 0, 0, 0, 0})), id); - EXPECT_EQ(allocator.AllocateId(RawAddress({0, 0, 0, 0, 0, 2})), id + 2); - EXPECT_TRUE(allocator.Close()); -} - -TEST(BluetoothMetricIdAllocatorTest, MetricIdAllocatorMainTest1) { - auto& allocator = MetricIdAllocator::GetInstance(); - std::unordered_map<RawAddress, int> paired_device_map; - int dummy = 22; - int* pointer = &dummy; - MetricIdAllocator::Callback save_callback = [pointer](const RawAddress&, const int) { - *pointer = *pointer * 2; - return true; - }; - MetricIdAllocator::Callback forget_callback = [pointer](const RawAddress&, const int) { - *pointer = *pointer / 2; - return true; - }; - - EXPECT_TRUE(allocator.Init(paired_device_map, save_callback, forget_callback)); - EXPECT_EQ(allocator.AllocateId(RawAddress({0, 0, 0, 0, 0, 0})), MetricIdAllocator::kMinId); - // save it and make sure the callback is called - EXPECT_TRUE(allocator.SaveDevice(RawAddress({0, 0, 0, 0, 0, 0}))); - EXPECT_EQ(dummy, 44); - - // should fail, since id of device is not allocated - EXPECT_FALSE(allocator.SaveDevice(RawAddress({0, 0, 0, 0, 0, 1}))); - EXPECT_EQ(dummy, 44); - - // save it and make sure the callback is called - EXPECT_EQ(allocator.AllocateId(RawAddress({0, 0, 0, 0, 0, 2})), MetricIdAllocator::kMinId + 1); - EXPECT_EQ(allocator.AllocateId(RawAddress({0, 0, 0, 0, 0, 3})), MetricIdAllocator::kMinId + 2); - EXPECT_TRUE(allocator.SaveDevice(RawAddress({0, 0, 0, 0, 0, 2}))); - EXPECT_EQ(dummy, 88); - EXPECT_TRUE(allocator.SaveDevice(RawAddress({0, 0, 0, 0, 0, 3}))); - EXPECT_EQ(dummy, 176); - - // should be true but callback won't be called, since id had been saved - EXPECT_TRUE(allocator.SaveDevice(RawAddress({0, 0, 0, 0, 0, 0}))); - EXPECT_EQ(dummy, 176); - - // forget - allocator.ForgetDevice(RawAddress({0, 0, 0, 0, 0, 1})); - EXPECT_EQ(dummy, 176); - allocator.ForgetDevice(RawAddress({0, 0, 0, 0, 0, 2})); - EXPECT_EQ(dummy, 88); - - EXPECT_TRUE(allocator.Close()); -} - -TEST(BluetoothMetricIdAllocatorTest, MetricIdAllocatorFullPairedMap) { - auto& allocator = MetricIdAllocator::GetInstance(); - // preset a full map - std::unordered_map<RawAddress, int> paired_device_map = - generateAddresses(MetricIdAllocator::kMaxNumPairedDevicesInMemory); - int dummy = 243; - int* pointer = &dummy; - MetricIdAllocator::Callback save_callback = [pointer](const RawAddress&, const int) { - *pointer = *pointer * 2; - return true; - }; - MetricIdAllocator::Callback forget_callback = [pointer](const RawAddress&, const int) { - *pointer = *pointer / 3; - return true; - }; - - EXPECT_TRUE(allocator.Init(paired_device_map, save_callback, forget_callback)); - - // check if all preset ids are there. - // comments based on kMaxNumPairedDevicesInMemory = 200. It can change. - int key = 0; - for (key = 0; key < static_cast<int>(MetricIdAllocator::kMaxNumPairedDevicesInMemory); key++) { - EXPECT_EQ(allocator.AllocateId(kthAddress(key)), key + MetricIdAllocator::kMinId); - } - // paired: 0, 1, 2 ... 199, - // scanned: - - int id = static_cast<int>(MetricIdAllocator::kMaxNumPairedDevicesInMemory + - MetricIdAllocator::kMinId); - // next id should be MetricIdAllocator::kMaxNumPairedDevicesInMemory + - // MetricIdAllocator::kMinId - - EXPECT_EQ(allocator.AllocateId(kthAddress(key)), id++); - // paired: 0, 1, 2 ... 199, - // scanned: 200 - - // save it and make sure the callback is called - EXPECT_TRUE(allocator.SaveDevice(kthAddress(key))); - EXPECT_EQ(dummy, 162); // one key is evicted, another key is saved so *2/3 - - // paired: 1, 2 ... 199, 200, - // scanned: - - EXPECT_EQ(allocator.AllocateId(kthAddress(0)), id++); - // paired: 1, 2 ... 199, 200 - // scanned: 0 - - // key == 200 - // should fail, since id of device is not allocated - EXPECT_FALSE(allocator.SaveDevice(kthAddress(key + 1))); - EXPECT_EQ(dummy, 162); - // paired: 1, 2 ... 199, 200, - // scanned: 0 - - EXPECT_EQ(allocator.AllocateId(kthAddress(key + 1)), id++); - EXPECT_TRUE(allocator.SaveDevice(kthAddress(key + 1))); - EXPECT_EQ(dummy, 108); // one key is evicted, another key is saved so *2/3, - // paired: 2 ... 199, 200, 201 - // scanned: 0 - - EXPECT_EQ(allocator.AllocateId(kthAddress(1)), id++); - // paired: 2 ... 199, 200, 201, - // scanned: 0, 1 - - // save it and make sure the callback is called - EXPECT_EQ(allocator.AllocateId(kthAddress(key + 2)), id++); - EXPECT_EQ(allocator.AllocateId(kthAddress(key + 3)), id++); - // paired: 2 ... 199, 200, 201, - // scanned: 0, 1, 202, 203 - - dummy = 9; - EXPECT_TRUE(allocator.SaveDevice(kthAddress(key + 2))); - EXPECT_EQ(dummy, 6); // one key is evicted, another key is saved so *2/3, - EXPECT_TRUE(allocator.SaveDevice(kthAddress(key + 3))); - EXPECT_EQ(dummy, 4); // one key is evicted, another key is saved so *2/3, - // paired: 4 ... 199, 200, 201, 202, 203 - // scanned: 0, 1 - - // should be true but callback won't be called, since id had been saved - EXPECT_TRUE(allocator.SaveDevice(kthAddress(key + 2))); - EXPECT_EQ(dummy, 4); - - dummy = 27; - // forget - allocator.ForgetDevice(kthAddress(key + 200)); - EXPECT_EQ(dummy, 27); // should fail, no such a key - allocator.ForgetDevice(kthAddress(key + 2)); - EXPECT_EQ(dummy, 9); - // paired: 4 ... 199, 200, 201, 203 - // scanned: 0, 1 - - // save it and make sure the callback is called - EXPECT_EQ(allocator.AllocateId(kthAddress(key + 2)), id++); - EXPECT_EQ(allocator.AllocateId(kthAddress(key + 4)), id++); - EXPECT_EQ(allocator.AllocateId(kthAddress(key + 5)), id++); - // paired: 4 ... 199, 200, 201, 203 - // scanned: 0, 1, 202, 204, 205 - - EXPECT_TRUE(allocator.SaveDevice(kthAddress(key + 2))); - EXPECT_EQ(dummy, 18); // no key is evicted, a key is saved so *2, - - // should be true but callback won't be called, since id had been saved - EXPECT_TRUE(allocator.SaveDevice(kthAddress(key + 3))); - EXPECT_EQ(dummy, 18); // no such a key in scanned - EXPECT_TRUE(allocator.SaveDevice(kthAddress(key + 4))); - EXPECT_EQ(dummy, 12); // one key is evicted, another key is saved so *2/3, - // paired: 5 6 ... 199, 200, 201, 203, 202, 204 - // scanned: 0, 1, 205 - - // verify paired: - for (key = 5; key <= 199; key++) { - dummy = 3; - allocator.ForgetDevice(kthAddress(key)); - EXPECT_EQ(dummy, 1); - } - for (size_t k = MetricIdAllocator::kMaxNumPairedDevicesInMemory; - k <= MetricIdAllocator::kMaxNumPairedDevicesInMemory + 4; k++) { - dummy = 3; - allocator.ForgetDevice(kthAddress(k)); - EXPECT_EQ(dummy, 1); - } - - // verify scanned - dummy = 4; - EXPECT_TRUE(allocator.SaveDevice(kthAddress(0))); - EXPECT_TRUE(allocator.SaveDevice(kthAddress(1))); - EXPECT_TRUE( - allocator.SaveDevice(kthAddress(MetricIdAllocator::kMaxNumPairedDevicesInMemory + 5))); - EXPECT_EQ(dummy, 32); - - EXPECT_TRUE(allocator.Close()); -} - -TEST(BluetoothMetricIdAllocatorTest, MetricIdAllocatorFullScannedMap) { - auto& allocator = MetricIdAllocator::GetInstance(); - std::unordered_map<RawAddress, int> paired_device_map; - int dummy = 22; - int* pointer = &dummy; - MetricIdAllocator::Callback save_callback = [pointer](const RawAddress&, const int) { - *pointer = *pointer * 2; - return true; - }; - MetricIdAllocator::Callback forget_callback = [pointer](const RawAddress&, const int) { - *pointer = *pointer / 2; - return true; - }; - - EXPECT_TRUE(allocator.Init(paired_device_map, save_callback, forget_callback)); - - // allocate kMaxNumUnpairedDevicesInMemory ids - // comments based on kMaxNumUnpairedDevicesInMemory = 200 - for (int key = 0; key < static_cast<int>(MetricIdAllocator::kMaxNumUnpairedDevicesInMemory); - key++) { - EXPECT_EQ(allocator.AllocateId(kthAddress(key)), key + MetricIdAllocator::kMinId); - } - // scanned: 0, 1, 2 ... 199, - // paired: - - int id = MetricIdAllocator::kMaxNumUnpairedDevicesInMemory + MetricIdAllocator::kMinId; - RawAddress addr = kthAddress(MetricIdAllocator::kMaxNumUnpairedDevicesInMemory); - EXPECT_EQ(allocator.AllocateId(addr), id); - // scanned: 1, 2 ... 199, 200 - - // save it and make sure the callback is called - EXPECT_TRUE(allocator.SaveDevice(addr)); - EXPECT_EQ(allocator.AllocateId(addr), id); - EXPECT_EQ(dummy, 44); - // paired: 200, - // scanned: 1, 2 ... 199, - id++; - - addr = kthAddress(MetricIdAllocator::kMaxNumUnpairedDevicesInMemory + 1); - EXPECT_EQ(allocator.AllocateId(addr), id++); - // paired: 200, - // scanned: 1, 2 ... 199, 201 - - // try to allocate for device 0, 1, 2, 3, 4....199 - // we should have a new id every time, - // since the scanned map is full at this point - for (int key = 0; key < static_cast<int>(MetricIdAllocator::kMaxNumUnpairedDevicesInMemory); - key++) { - EXPECT_EQ(allocator.AllocateId(kthAddress(key)), id++); - } - EXPECT_TRUE(allocator.Close()); -} - -TEST(BluetoothMetricIdAllocatorTest, MetricIdAllocatorMultiThreadPressureTest) { - std::unordered_map<RawAddress, int> paired_device_map; - auto& allocator = MetricIdAllocator::GetInstance(); - int dummy = 22; - int* pointer = &dummy; - MetricIdAllocator::Callback save_callback = [pointer](const RawAddress&, const int) { - *pointer = *pointer + 1; - return true; - }; - MetricIdAllocator::Callback forget_callback = [pointer](const RawAddress&, const int) { - *pointer = *pointer - 1; - return true; - }; - EXPECT_TRUE(allocator.Init(paired_device_map, save_callback, forget_callback)); - - // make sure no deadlock - std::vector<std::thread> workers; - for (int key = 0; key < static_cast<int>(MetricIdAllocator::kMaxNumUnpairedDevicesInMemory); - key++) { - workers.push_back(std::thread([key]() { - auto& allocator = MetricIdAllocator::GetInstance(); - RawAddress fake_mac_address = kthAddress(key); - allocator.AllocateId(fake_mac_address); - EXPECT_TRUE(allocator.SaveDevice(fake_mac_address)); - allocator.ForgetDevice(fake_mac_address); - })); - } - for (auto& worker : workers) { - worker.join(); - } - EXPECT_TRUE(allocator.IsEmpty()); - EXPECT_TRUE(allocator.Close()); -} - -TEST(BluetoothMetricIdAllocatorTest, MetricIdAllocatorWrapAroundTest1) { - std::unordered_map<RawAddress, int> paired_device_map; - auto& allocator = MetricIdAllocator::GetInstance(); - MetricIdAllocator::Callback callback = [](const RawAddress&, const int) { return true; }; - - // make a sparse paired_device_map - int min_id = MetricIdAllocator::kMinId; - paired_device_map[kthAddress(min_id)] = min_id; - paired_device_map[kthAddress(min_id + 1)] = min_id + 1; - paired_device_map[kthAddress(min_id + 3)] = min_id + 3; - paired_device_map[kthAddress(min_id + 4)] = min_id + 4; - - int max_id = MetricIdAllocator::kMaxId; - paired_device_map[kthAddress(max_id - 3)] = max_id - 3; - paired_device_map[kthAddress(max_id - 4)] = max_id - 4; - - EXPECT_TRUE(allocator.Init(paired_device_map, callback, callback)); - - // next id should be max_id - 2, max_id - 1, max_id, min_id + 2, min_id + 5 - EXPECT_EQ(allocator.AllocateId(kthAddress(max_id - 2)), max_id - 2); - EXPECT_EQ(allocator.AllocateId(kthAddress(max_id - 1)), max_id - 1); - EXPECT_EQ(allocator.AllocateId(kthAddress(max_id)), max_id); - EXPECT_EQ(allocator.AllocateId(kthAddress(min_id + 2)), min_id + 2); - EXPECT_EQ(allocator.AllocateId(kthAddress(min_id + 5)), min_id + 5); - - EXPECT_TRUE(allocator.Close()); -} - -TEST(BluetoothMetricIdAllocatorTest, MetricIdAllocatorWrapAroundTest2) { - std::unordered_map<RawAddress, int> paired_device_map; - auto& allocator = MetricIdAllocator::GetInstance(); - MetricIdAllocator::Callback callback = [](const RawAddress&, const int) { return true; }; - - // make a sparse paired_device_map - int min_id = MetricIdAllocator::kMinId; - int max_id = MetricIdAllocator::kMaxId; - paired_device_map[kthAddress(max_id)] = max_id; - - EXPECT_TRUE(allocator.Init(paired_device_map, callback, callback)); - - // next id should be min_id, min_id + 1 - EXPECT_EQ(allocator.AllocateId(kthAddress(min_id)), min_id); - EXPECT_EQ(allocator.AllocateId(kthAddress(min_id + 1)), min_id + 1); - - EXPECT_TRUE(allocator.Close()); -} - -} // namespace testing diff --git a/system/common/metrics.cc b/system/common/metrics.cc index 1ece069ab3..45b11acf46 100644 --- a/system/common/metrics.cc +++ b/system/common/metrics.cc @@ -33,7 +33,6 @@ #include <mutex> // NOLINT #include <utility> -#include "bluetooth/metrics/bluetooth.pb.h" #include "common/address_obfuscator.h" #include "common/leaky_bonded_queue.h" #include "common/time_util.h" @@ -64,480 +63,6 @@ namespace bluetooth { namespace common { using bluetooth::hci::Address; -using bluetooth::metrics::BluetoothMetricsProto::A2DPSession; -using bluetooth::metrics::BluetoothMetricsProto::A2dpSourceCodec; -using bluetooth::metrics::BluetoothMetricsProto::BluetoothLog; -using bluetooth::metrics::BluetoothMetricsProto::BluetoothSession; -using bluetooth::metrics::BluetoothMetricsProto::BluetoothSession_ConnectionTechnologyType; -using bluetooth::metrics::BluetoothMetricsProto::BluetoothSession_DisconnectReasonType; -using bluetooth::metrics::BluetoothMetricsProto::DeviceInfo; -using bluetooth::metrics::BluetoothMetricsProto::DeviceInfo_DeviceType; -using bluetooth::metrics::BluetoothMetricsProto::HeadsetProfileConnectionStats; -using bluetooth::metrics::BluetoothMetricsProto::HeadsetProfileType; -using bluetooth::metrics::BluetoothMetricsProto::HeadsetProfileType_ARRAYSIZE; -using bluetooth::metrics::BluetoothMetricsProto::HeadsetProfileType_IsValid; -using bluetooth::metrics::BluetoothMetricsProto::HeadsetProfileType_MAX; -using bluetooth::metrics::BluetoothMetricsProto::HeadsetProfileType_MIN; -using bluetooth::metrics::BluetoothMetricsProto::PairEvent; -using bluetooth::metrics::BluetoothMetricsProto::ScanEvent; -using bluetooth::metrics::BluetoothMetricsProto::ScanEvent_ScanEventType; -using bluetooth::metrics::BluetoothMetricsProto::ScanEvent_ScanTechnologyType; -using bluetooth::metrics::BluetoothMetricsProto::WakeEvent; -using bluetooth::metrics::BluetoothMetricsProto::WakeEvent_WakeEventType; - -static float combine_averages(float avg_a, int64_t ct_a, float avg_b, int64_t ct_b) { - if (ct_a > 0 && ct_b > 0) { - return (avg_a * ct_a + avg_b * ct_b) / (ct_a + ct_b); - } else if (ct_b > 0) { - return avg_b; - } else { - return avg_a; - } -} - -static int32_t combine_averages(int32_t avg_a, int64_t ct_a, int32_t avg_b, int64_t ct_b) { - if (ct_a > 0 && ct_b > 0) { - return (avg_a * ct_a + avg_b * ct_b) / (ct_a + ct_b); - } else if (ct_b > 0) { - return avg_b; - } else { - return avg_a; - } -} - -void A2dpSessionMetrics::Update(const A2dpSessionMetrics& metrics) { - if (metrics.audio_duration_ms >= 0) { - audio_duration_ms = std::max(static_cast<int64_t>(0), audio_duration_ms); - audio_duration_ms += metrics.audio_duration_ms; - } - if (metrics.media_timer_min_ms >= 0) { - if (media_timer_min_ms < 0) { - media_timer_min_ms = metrics.media_timer_min_ms; - } else { - media_timer_min_ms = std::min(media_timer_min_ms, metrics.media_timer_min_ms); - } - } - if (metrics.media_timer_max_ms >= 0) { - media_timer_max_ms = std::max(media_timer_max_ms, metrics.media_timer_max_ms); - } - if (metrics.media_timer_avg_ms >= 0 && metrics.total_scheduling_count >= 0) { - if (media_timer_avg_ms < 0 || total_scheduling_count < 0) { - media_timer_avg_ms = metrics.media_timer_avg_ms; - total_scheduling_count = metrics.total_scheduling_count; - } else { - media_timer_avg_ms = - combine_averages(media_timer_avg_ms, total_scheduling_count, - metrics.media_timer_avg_ms, metrics.total_scheduling_count); - total_scheduling_count += metrics.total_scheduling_count; - } - } - if (metrics.buffer_overruns_max_count >= 0) { - buffer_overruns_max_count = - std::max(buffer_overruns_max_count, metrics.buffer_overruns_max_count); - } - if (metrics.buffer_overruns_total >= 0) { - buffer_overruns_total = std::max(static_cast<int32_t>(0), buffer_overruns_total); - buffer_overruns_total += metrics.buffer_overruns_total; - } - if (metrics.buffer_underruns_average >= 0 && metrics.buffer_underruns_count >= 0) { - if (buffer_underruns_average < 0 || buffer_underruns_count < 0) { - buffer_underruns_average = metrics.buffer_underruns_average; - buffer_underruns_count = metrics.buffer_underruns_count; - } else { - buffer_underruns_average = - combine_averages(buffer_underruns_average, buffer_underruns_count, - metrics.buffer_underruns_average, metrics.buffer_underruns_count); - buffer_underruns_count += metrics.buffer_underruns_count; - } - } - if (codec_index < 0) { - codec_index = metrics.codec_index; - } - if (!is_a2dp_offload) { - is_a2dp_offload = metrics.is_a2dp_offload; - } -} - -bool A2dpSessionMetrics::operator==(const A2dpSessionMetrics& rhs) const { - return audio_duration_ms == rhs.audio_duration_ms && - media_timer_min_ms == rhs.media_timer_min_ms && - media_timer_max_ms == rhs.media_timer_max_ms && - media_timer_avg_ms == rhs.media_timer_avg_ms && - total_scheduling_count == rhs.total_scheduling_count && - buffer_overruns_max_count == rhs.buffer_overruns_max_count && - buffer_overruns_total == rhs.buffer_overruns_total && - buffer_underruns_average == rhs.buffer_underruns_average && - buffer_underruns_count == rhs.buffer_underruns_count && codec_index == rhs.codec_index && - is_a2dp_offload == rhs.is_a2dp_offload; -} - -static DeviceInfo_DeviceType get_device_type(device_type_t type) { - switch (type) { - case DEVICE_TYPE_BREDR: - return DeviceInfo_DeviceType::DeviceInfo_DeviceType_DEVICE_TYPE_BREDR; - case DEVICE_TYPE_LE: - return DeviceInfo_DeviceType::DeviceInfo_DeviceType_DEVICE_TYPE_LE; - case DEVICE_TYPE_DUMO: - return DeviceInfo_DeviceType::DeviceInfo_DeviceType_DEVICE_TYPE_DUMO; - case DEVICE_TYPE_UNKNOWN: - default: - return DeviceInfo_DeviceType::DeviceInfo_DeviceType_DEVICE_TYPE_UNKNOWN; - } -} - -static BluetoothSession_ConnectionTechnologyType get_connection_tech_type(connection_tech_t type) { - switch (type) { - case CONNECTION_TECHNOLOGY_TYPE_LE: - return BluetoothSession_ConnectionTechnologyType:: - BluetoothSession_ConnectionTechnologyType_CONNECTION_TECHNOLOGY_TYPE_LE; - case CONNECTION_TECHNOLOGY_TYPE_BREDR: - return BluetoothSession_ConnectionTechnologyType:: - BluetoothSession_ConnectionTechnologyType_CONNECTION_TECHNOLOGY_TYPE_BREDR; - case CONNECTION_TECHNOLOGY_TYPE_UNKNOWN: - default: - return BluetoothSession_ConnectionTechnologyType:: - BluetoothSession_ConnectionTechnologyType_CONNECTION_TECHNOLOGY_TYPE_UNKNOWN; - } -} - -static ScanEvent_ScanTechnologyType get_scan_tech_type(scan_tech_t type) { - switch (type) { - case SCAN_TECH_TYPE_LE: - return ScanEvent_ScanTechnologyType::ScanEvent_ScanTechnologyType_SCAN_TECH_TYPE_LE; - case SCAN_TECH_TYPE_BREDR: - return ScanEvent_ScanTechnologyType::ScanEvent_ScanTechnologyType_SCAN_TECH_TYPE_BREDR; - case SCAN_TECH_TYPE_BOTH: - return ScanEvent_ScanTechnologyType::ScanEvent_ScanTechnologyType_SCAN_TECH_TYPE_BOTH; - case SCAN_TYPE_UNKNOWN: - default: - return ScanEvent_ScanTechnologyType::ScanEvent_ScanTechnologyType_SCAN_TYPE_UNKNOWN; - } -} - -static WakeEvent_WakeEventType get_wake_event_type(wake_event_type_t type) { - switch (type) { - case WAKE_EVENT_ACQUIRED: - return WakeEvent_WakeEventType::WakeEvent_WakeEventType_ACQUIRED; - case WAKE_EVENT_RELEASED: - return WakeEvent_WakeEventType::WakeEvent_WakeEventType_RELEASED; - case WAKE_EVENT_UNKNOWN: - default: - return WakeEvent_WakeEventType::WakeEvent_WakeEventType_UNKNOWN; - } -} - -static BluetoothSession_DisconnectReasonType get_disconnect_reason_type(disconnect_reason_t type) { - switch (type) { - case DISCONNECT_REASON_METRICS_DUMP: - return BluetoothSession_DisconnectReasonType:: - BluetoothSession_DisconnectReasonType_METRICS_DUMP; - case DISCONNECT_REASON_NEXT_START_WITHOUT_END_PREVIOUS: - return BluetoothSession_DisconnectReasonType:: - BluetoothSession_DisconnectReasonType_NEXT_START_WITHOUT_END_PREVIOUS; - case DISCONNECT_REASON_UNKNOWN: - default: - return BluetoothSession_DisconnectReasonType::BluetoothSession_DisconnectReasonType_UNKNOWN; - } -} - -static A2dpSourceCodec get_a2dp_source_codec(int64_t codec_index) { - switch (codec_index) { - case BTAV_A2DP_CODEC_INDEX_SOURCE_SBC: - return A2dpSourceCodec::A2DP_SOURCE_CODEC_SBC; - case BTAV_A2DP_CODEC_INDEX_SOURCE_AAC: - return A2dpSourceCodec::A2DP_SOURCE_CODEC_AAC; - case BTAV_A2DP_CODEC_INDEX_SOURCE_APTX: - return A2dpSourceCodec::A2DP_SOURCE_CODEC_APTX; - case BTAV_A2DP_CODEC_INDEX_SOURCE_APTX_HD: - return A2dpSourceCodec::A2DP_SOURCE_CODEC_APTX_HD; - case BTAV_A2DP_CODEC_INDEX_SOURCE_LDAC: - return A2dpSourceCodec::A2DP_SOURCE_CODEC_LDAC; - default: - return A2dpSourceCodec::A2DP_SOURCE_CODEC_UNKNOWN; - } -} - -struct BluetoothMetricsLogger::impl { - impl(size_t max_bluetooth_session, size_t max_pair_event, size_t max_wake_event, - size_t max_scan_event) - : bt_session_queue_(new LeakyBondedQueue<BluetoothSession>(max_bluetooth_session)), - pair_event_queue_(new LeakyBondedQueue<PairEvent>(max_pair_event)), - wake_event_queue_(new LeakyBondedQueue<WakeEvent>(max_wake_event)), - scan_event_queue_(new LeakyBondedQueue<ScanEvent>(max_scan_event)) { - bluetooth_log_ = BluetoothLog::default_instance().New(); - headset_profile_connection_counts_.fill(0); - bluetooth_session_ = nullptr; - bluetooth_session_start_time_ms_ = 0; - a2dp_session_metrics_ = A2dpSessionMetrics(); - } - - /* Bluetooth log lock protected */ - BluetoothLog* bluetooth_log_; - std::array<int, HeadsetProfileType_ARRAYSIZE> headset_profile_connection_counts_; - std::recursive_mutex bluetooth_log_lock_; - /* End Bluetooth log lock protected */ - /* Bluetooth session lock protected */ - BluetoothSession* bluetooth_session_; - uint64_t bluetooth_session_start_time_ms_; - A2dpSessionMetrics a2dp_session_metrics_; - std::recursive_mutex bluetooth_session_lock_; - /* End bluetooth session lock protected */ - std::unique_ptr<LeakyBondedQueue<BluetoothSession>> bt_session_queue_; - std::unique_ptr<LeakyBondedQueue<PairEvent>> pair_event_queue_; - std::unique_ptr<LeakyBondedQueue<WakeEvent>> wake_event_queue_; - std::unique_ptr<LeakyBondedQueue<ScanEvent>> scan_event_queue_; -}; - -BluetoothMetricsLogger::BluetoothMetricsLogger() - : pimpl_(new impl(kMaxNumBluetoothSession, kMaxNumPairEvent, kMaxNumWakeEvent, - kMaxNumScanEvent)) {} - -void BluetoothMetricsLogger::LogPairEvent(uint32_t disconnect_reason, uint64_t timestamp_ms, - uint32_t device_class, device_type_t device_type) { - PairEvent* event = new PairEvent(); - DeviceInfo* info = event->mutable_device_paired_with(); - info->set_device_class(device_class); - info->set_device_type(get_device_type(device_type)); - event->set_disconnect_reason(disconnect_reason); - event->set_event_time_millis(timestamp_ms); - pimpl_->pair_event_queue_->Enqueue(event); - { - std::lock_guard<std::recursive_mutex> lock(pimpl_->bluetooth_log_lock_); - pimpl_->bluetooth_log_->set_num_pair_event(pimpl_->bluetooth_log_->num_pair_event() + 1); - } -} - -void BluetoothMetricsLogger::LogWakeEvent(wake_event_type_t type, const std::string& requestor, - const std::string& name, uint64_t timestamp_ms) { - WakeEvent* event = new WakeEvent(); - event->set_wake_event_type(get_wake_event_type(type)); - event->set_requestor(requestor); - event->set_name(name); - event->set_event_time_millis(timestamp_ms); - pimpl_->wake_event_queue_->Enqueue(event); - { - std::lock_guard<std::recursive_mutex> lock(pimpl_->bluetooth_log_lock_); - pimpl_->bluetooth_log_->set_num_wake_event(pimpl_->bluetooth_log_->num_wake_event() + 1); - } -} - -void BluetoothMetricsLogger::LogScanEvent(bool start, const std::string& initiator, - scan_tech_t type, uint32_t results, - uint64_t timestamp_ms) { - ScanEvent* event = new ScanEvent(); - if (start) { - event->set_scan_event_type(ScanEvent::SCAN_EVENT_START); - } else { - event->set_scan_event_type(ScanEvent::SCAN_EVENT_STOP); - } - event->set_initiator(initiator); - event->set_scan_technology_type(get_scan_tech_type(type)); - event->set_number_results(results); - event->set_event_time_millis(timestamp_ms); - pimpl_->scan_event_queue_->Enqueue(event); - { - std::lock_guard<std::recursive_mutex> lock(pimpl_->bluetooth_log_lock_); - pimpl_->bluetooth_log_->set_num_scan_event(pimpl_->bluetooth_log_->num_scan_event() + 1); - } -} - -void BluetoothMetricsLogger::LogBluetoothSessionStart(connection_tech_t connection_tech_type, - uint64_t timestamp_ms) { - std::lock_guard<std::recursive_mutex> lock(pimpl_->bluetooth_session_lock_); - if (pimpl_->bluetooth_session_ != nullptr) { - LogBluetoothSessionEnd(DISCONNECT_REASON_NEXT_START_WITHOUT_END_PREVIOUS, 0); - } - if (timestamp_ms == 0) { - timestamp_ms = bluetooth::common::time_get_os_boottime_ms(); - } - pimpl_->bluetooth_session_start_time_ms_ = timestamp_ms; - pimpl_->bluetooth_session_ = new BluetoothSession(); - pimpl_->bluetooth_session_->set_connection_technology_type( - get_connection_tech_type(connection_tech_type)); -} - -void BluetoothMetricsLogger::LogBluetoothSessionEnd(disconnect_reason_t disconnect_reason, - uint64_t timestamp_ms) { - std::lock_guard<std::recursive_mutex> lock(pimpl_->bluetooth_session_lock_); - if (pimpl_->bluetooth_session_ == nullptr) { - return; - } - if (timestamp_ms == 0) { - timestamp_ms = bluetooth::common::time_get_os_boottime_ms(); - } - int64_t session_duration_sec = (timestamp_ms - pimpl_->bluetooth_session_start_time_ms_) / 1000; - pimpl_->bluetooth_session_->set_session_duration_sec(session_duration_sec); - pimpl_->bluetooth_session_->set_disconnect_reason_type( - get_disconnect_reason_type(disconnect_reason)); - pimpl_->bt_session_queue_->Enqueue(pimpl_->bluetooth_session_); - pimpl_->bluetooth_session_ = nullptr; - pimpl_->a2dp_session_metrics_ = A2dpSessionMetrics(); - { - std::lock_guard<std::recursive_mutex> log_lock(pimpl_->bluetooth_log_lock_); - pimpl_->bluetooth_log_->set_num_bluetooth_session( - pimpl_->bluetooth_log_->num_bluetooth_session() + 1); - } -} - -void BluetoothMetricsLogger::LogBluetoothSessionDeviceInfo(uint32_t device_class, - device_type_t device_type) { - std::lock_guard<std::recursive_mutex> lock(pimpl_->bluetooth_session_lock_); - if (pimpl_->bluetooth_session_ == nullptr) { - LogBluetoothSessionStart(CONNECTION_TECHNOLOGY_TYPE_UNKNOWN, 0); - } - DeviceInfo* info = pimpl_->bluetooth_session_->mutable_device_connected_to(); - info->set_device_class(device_class); - info->set_device_type(get_device_type(device_type)); -} - -void BluetoothMetricsLogger::LogA2dpSession(const A2dpSessionMetrics& a2dp_session_metrics) { - std::lock_guard<std::recursive_mutex> lock(pimpl_->bluetooth_session_lock_); - if (pimpl_->bluetooth_session_ == nullptr) { - // When no bluetooth session exist, create one on system's behalf - // Set connection type: for A2DP it is always BR/EDR - LogBluetoothSessionStart(CONNECTION_TECHNOLOGY_TYPE_BREDR, 0); - LogBluetoothSessionDeviceInfo(BTM_COD_MAJOR_AUDIO, DEVICE_TYPE_BREDR); - } - // Accumulate metrics - pimpl_->a2dp_session_metrics_.Update(a2dp_session_metrics); - // Get or allocate new A2DP session object - A2DPSession* a2dp_session = pimpl_->bluetooth_session_->mutable_a2dp_session(); - a2dp_session->set_audio_duration_millis(pimpl_->a2dp_session_metrics_.audio_duration_ms); - a2dp_session->set_media_timer_min_millis(pimpl_->a2dp_session_metrics_.media_timer_min_ms); - a2dp_session->set_media_timer_max_millis(pimpl_->a2dp_session_metrics_.media_timer_max_ms); - a2dp_session->set_media_timer_avg_millis(pimpl_->a2dp_session_metrics_.media_timer_avg_ms); - a2dp_session->set_buffer_overruns_max_count( - pimpl_->a2dp_session_metrics_.buffer_overruns_max_count); - a2dp_session->set_buffer_overruns_total(pimpl_->a2dp_session_metrics_.buffer_overruns_total); - a2dp_session->set_buffer_underruns_average( - pimpl_->a2dp_session_metrics_.buffer_underruns_average); - a2dp_session->set_buffer_underruns_count(pimpl_->a2dp_session_metrics_.buffer_underruns_count); - a2dp_session->set_source_codec(get_a2dp_source_codec(pimpl_->a2dp_session_metrics_.codec_index)); - a2dp_session->set_is_a2dp_offload(pimpl_->a2dp_session_metrics_.is_a2dp_offload); -} - -void BluetoothMetricsLogger::LogHeadsetProfileRfcConnection(tBTA_SERVICE_ID service_id) { - std::lock_guard<std::recursive_mutex> lock(pimpl_->bluetooth_log_lock_); - switch (service_id) { - case BTA_HSP_SERVICE_ID: - pimpl_->headset_profile_connection_counts_[HeadsetProfileType::HSP]++; - break; - case BTA_HFP_SERVICE_ID: - pimpl_->headset_profile_connection_counts_[HeadsetProfileType::HFP]++; - break; - default: - pimpl_->headset_profile_connection_counts_[HeadsetProfileType::HEADSET_PROFILE_UNKNOWN]++; - break; - } - return; -} - -void BluetoothMetricsLogger::WriteString(std::string* serialized) { - std::lock_guard<std::recursive_mutex> lock(pimpl_->bluetooth_log_lock_); - log::info("building metrics"); - Build(); - log::info("serializing metrics"); - if (!pimpl_->bluetooth_log_->SerializeToString(serialized)) { - log::error("error serializing metrics"); - } - // Always clean up log objects - pimpl_->bluetooth_log_->Clear(); -} - -void BluetoothMetricsLogger::WriteBase64String(std::string* serialized) { - this->WriteString(serialized); - base::Base64Encode(*serialized, serialized); -} - -void BluetoothMetricsLogger::WriteBase64(int fd) { - std::string protoBase64; - this->WriteBase64String(&protoBase64); - ssize_t ret; - OSI_NO_INTR(ret = write(fd, protoBase64.c_str(), protoBase64.size())); - if (ret == -1) { - log::error("error writing to dumpsys fd: {} ({})", strerror(errno), errno); - } -} - -void BluetoothMetricsLogger::CutoffSession() { - std::lock_guard<std::recursive_mutex> lock(pimpl_->bluetooth_session_lock_); - if (pimpl_->bluetooth_session_ != nullptr) { - BluetoothSession* new_bt_session = new BluetoothSession(*pimpl_->bluetooth_session_); - new_bt_session->clear_a2dp_session(); - new_bt_session->clear_rfcomm_session(); - LogBluetoothSessionEnd(DISCONNECT_REASON_METRICS_DUMP, 0); - pimpl_->bluetooth_session_ = new_bt_session; - pimpl_->bluetooth_session_start_time_ms_ = bluetooth::common::time_get_os_boottime_ms(); - pimpl_->a2dp_session_metrics_ = A2dpSessionMetrics(); - } -} - -void BluetoothMetricsLogger::Build() { - std::lock_guard<std::recursive_mutex> lock(pimpl_->bluetooth_log_lock_); - CutoffSession(); - BluetoothLog* bluetooth_log = pimpl_->bluetooth_log_; - while (!pimpl_->bt_session_queue_->Empty() && - static_cast<size_t>(bluetooth_log->session_size()) <= - pimpl_->bt_session_queue_->Capacity()) { - bluetooth_log->mutable_session()->AddAllocated(pimpl_->bt_session_queue_->Dequeue()); - } - while (!pimpl_->pair_event_queue_->Empty() && - static_cast<size_t>(bluetooth_log->pair_event_size()) <= - pimpl_->pair_event_queue_->Capacity()) { - bluetooth_log->mutable_pair_event()->AddAllocated(pimpl_->pair_event_queue_->Dequeue()); - } - while (!pimpl_->scan_event_queue_->Empty() && - static_cast<size_t>(bluetooth_log->scan_event_size()) <= - pimpl_->scan_event_queue_->Capacity()) { - bluetooth_log->mutable_scan_event()->AddAllocated(pimpl_->scan_event_queue_->Dequeue()); - } - while (!pimpl_->wake_event_queue_->Empty() && - static_cast<size_t>(bluetooth_log->wake_event_size()) <= - pimpl_->wake_event_queue_->Capacity()) { - bluetooth_log->mutable_wake_event()->AddAllocated(pimpl_->wake_event_queue_->Dequeue()); - } - while (!pimpl_->bt_session_queue_->Empty() && - static_cast<size_t>(bluetooth_log->wake_event_size()) <= - pimpl_->wake_event_queue_->Capacity()) { - bluetooth_log->mutable_wake_event()->AddAllocated(pimpl_->wake_event_queue_->Dequeue()); - } - for (size_t i = 0; i < HeadsetProfileType_ARRAYSIZE; ++i) { - int num_times_connected = pimpl_->headset_profile_connection_counts_[i]; - if (HeadsetProfileType_IsValid(i) && num_times_connected > 0) { - HeadsetProfileConnectionStats* headset_profile_connection_stats = - bluetooth_log->add_headset_profile_connection_stats(); - // Able to static_cast because HeadsetProfileType_IsValid(i) is true - headset_profile_connection_stats->set_headset_profile_type( - static_cast<HeadsetProfileType>(i)); - headset_profile_connection_stats->set_num_times_connected(num_times_connected); - } - } - pimpl_->headset_profile_connection_counts_.fill(0); -} - -void BluetoothMetricsLogger::ResetSession() { - std::lock_guard<std::recursive_mutex> lock(pimpl_->bluetooth_session_lock_); - if (pimpl_->bluetooth_session_ != nullptr) { - delete pimpl_->bluetooth_session_; - pimpl_->bluetooth_session_ = nullptr; - } - pimpl_->bluetooth_session_start_time_ms_ = 0; - pimpl_->a2dp_session_metrics_ = A2dpSessionMetrics(); -} - -void BluetoothMetricsLogger::ResetLog() { - std::lock_guard<std::recursive_mutex> lock(pimpl_->bluetooth_log_lock_); - pimpl_->bluetooth_log_->Clear(); -} - -void BluetoothMetricsLogger::Reset() { - ResetSession(); - ResetLog(); - pimpl_->bt_session_queue_->Clear(); - pimpl_->pair_event_queue_->Clear(); - pimpl_->wake_event_queue_->Clear(); - pimpl_->scan_event_queue_->Clear(); -} void LogLinkLayerConnectionEvent(const RawAddress* address, uint32_t connection_handle, android::bluetooth::DirectionEnum direction, uint16_t link_type, diff --git a/system/common/metrics.h b/system/common/metrics.h index 8cd41bd6db..0aad20819e 100644 --- a/system/common/metrics.h +++ b/system/common/metrics.h @@ -36,252 +36,6 @@ namespace bluetooth { namespace common { -// Typedefs to hide protobuf definition to the rest of stack - -typedef enum { - DEVICE_TYPE_UNKNOWN, - DEVICE_TYPE_BREDR, - DEVICE_TYPE_LE, - DEVICE_TYPE_DUMO, -} device_type_t; - -typedef enum { - WAKE_EVENT_UNKNOWN, - WAKE_EVENT_ACQUIRED, - WAKE_EVENT_RELEASED, -} wake_event_type_t; - -typedef enum { - SCAN_TYPE_UNKNOWN, - SCAN_TECH_TYPE_LE, - SCAN_TECH_TYPE_BREDR, - SCAN_TECH_TYPE_BOTH, -} scan_tech_t; - -typedef enum { - CONNECTION_TECHNOLOGY_TYPE_UNKNOWN, - CONNECTION_TECHNOLOGY_TYPE_LE, - CONNECTION_TECHNOLOGY_TYPE_BREDR, -} connection_tech_t; - -typedef enum { - DISCONNECT_REASON_UNKNOWN, - DISCONNECT_REASON_METRICS_DUMP, - DISCONNECT_REASON_NEXT_START_WITHOUT_END_PREVIOUS, -} disconnect_reason_t; - -/* Values of A2DP metrics that we care about - * - * audio_duration_ms : sum of audio duration (in milliseconds). - * device_class: device class of the paired device. - * media_timer_min_ms : minimum scheduled time (in milliseconds) - * of the media timer. - * media_timer_max_ms: maximum scheduled time (in milliseconds) - * of the media timer. - * media_timer_avg_ms: average scheduled time (in milliseconds) - * of the media timer. - * buffer_overruns_max_count: TODO - not clear what this is. - * buffer_overruns_total : number of times the media buffer with - * audio data has overrun - * buffer_underruns_average: TODO - not clear what this is. - * buffer_underruns_count: number of times there was no enough - * audio data to add to the media buffer. - * NOTE: Negative values are invalid - */ -class A2dpSessionMetrics { -public: - A2dpSessionMetrics() {} - - /* - * Update the metrics value in the current metrics object using the metrics - * objects supplied - */ - void Update(const A2dpSessionMetrics& metrics); - - /* - * Compare whether two metrics objects are equal - */ - bool operator==(const A2dpSessionMetrics& rhs) const; - - /* - * Initialize all values to -1 which is invalid in order to make a distinction - * between 0 and invalid values - */ - int64_t audio_duration_ms = -1; - int32_t media_timer_min_ms = -1; - int32_t media_timer_max_ms = -1; - int32_t media_timer_avg_ms = -1; - int64_t total_scheduling_count = -1; - int32_t buffer_overruns_max_count = -1; - int32_t buffer_overruns_total = -1; - float buffer_underruns_average = -1; - int32_t buffer_underruns_count = -1; - int64_t codec_index = -1; - bool is_a2dp_offload = false; -}; - -class BluetoothMetricsLogger { -public: - static BluetoothMetricsLogger* GetInstance() { - static BluetoothMetricsLogger* instance = new BluetoothMetricsLogger(); - return instance; - } - - /* - * Record a pairing event - * - * Parameters: - * timestamp_ms: Unix epoch time in milliseconds - * device_class: class of remote device - * device_type: type of remote device - * disconnect_reason: HCI reason for pairing disconnection. - * See: stack/include/hcidefs.h - */ - void LogPairEvent(uint32_t disconnect_reason, uint64_t timestamp_ms, uint32_t device_class, - device_type_t device_type); - - /* - * Record a wake event - * - * Parameters: - * timestamp_ms: Unix epoch time in milliseconds - * type: whether it was acquired or released - * requestor: if provided is the service requesting the wake lock - * name: the name of the wake lock held - */ - void LogWakeEvent(wake_event_type_t type, const std::string& requestor, const std::string& name, - uint64_t timestamp_ms); - - /* - * Record a scan event - * - * Parameters - * timestamp_ms : Unix epoch time in milliseconds - * start : true if this is the beginning of the scan - * initiator: a unique ID identifying the app starting the scan - * type: whether the scan reports BR/EDR, LE, or both. - * results: number of results to be reported. - */ - void LogScanEvent(bool start, const std::string& initiator, scan_tech_t type, uint32_t results, - uint64_t timestamp_ms); - - /* - * Start logging a Bluetooth session - * - * A Bluetooth session is defined a a connection between this device and - * another remote device which may include multiple profiles and protocols - * - * Only one Bluetooth session can exist at one time. Calling this method twice - * without LogBluetoothSessionEnd will result in logging a premature end of - * current Bluetooth session - * - * Parameters: - * connection_tech_type : type of connection technology - * timestamp_ms : the timestamp for session start, 0 means now - * - */ - void LogBluetoothSessionStart(connection_tech_t connection_tech_type, uint64_t timestamp_ms); - - /* - * Stop logging a Bluetooth session and pushes it to the log queue - * - * If no Bluetooth session exist, this method exits immediately - * - * Parameters: - * disconnect_reason : A string representation of disconnect reason - * timestamp_ms : the timestamp of session end, 0 means now - * - */ - void LogBluetoothSessionEnd(disconnect_reason_t disconnect_reason, uint64_t timestamp_ms); - - /* - * Log information about remote device in a current Bluetooth session - * - * If a Bluetooth session does not exist, create one with default parameter - * and timestamp now - * - * Parameters: - * device_class : device_class defined in btm_api_types.h - * device_type : type of remote device - */ - void LogBluetoothSessionDeviceInfo(uint32_t device_class, device_type_t device_type); - - /* - * Log A2DP Audio Session Information - * - * - Repeated calls to this method will override previous metrics if in the - * same Bluetooth connection - * - If a Bluetooth session does not exist, create one with default parameter - * and timestamp now - * - * Parameters: - * a2dp_session_metrics - pointer to struct holding a2dp stats - * - */ - void LogA2dpSession(const A2dpSessionMetrics& a2dp_session_metrics); - - /** - * Log Headset profile RFCOMM connection event - * - * @param service_id the BTA service ID for this headset connection - */ - void LogHeadsetProfileRfcConnection(tBTA_SERVICE_ID service_id); - - /* - * Writes the metrics, in base64 protobuf format, into the descriptor FD, - * metrics events are always cleared after dump - */ - void WriteBase64(int fd); - void WriteBase64String(std::string* serialized); - void WriteString(std::string* serialized); - - /* - * Reset the metrics logger by cleaning up its staging queues and existing - * protobuf objects. - */ - void Reset(); - - /* - * Maximum number of log entries for each session or event - */ - static const size_t kMaxNumBluetoothSession = 50; - static const size_t kMaxNumPairEvent = 50; - static const size_t kMaxNumWakeEvent = 1000; - static const size_t kMaxNumScanEvent = 50; - -private: - BluetoothMetricsLogger(); - - /* - * When a Bluetooth session is on and the user initiates a metrics dump, we - * need to be able to upload whatever we have first. This method breaks the - * ongoing Bluetooth session into two sessions with the previous one labeled - * as "METRICS_DUMP" for the disconnect reason. - */ - void CutoffSession(); - - /* - * Build the internal metrics object using information gathered - */ - void Build(); - - /* - * Reset objects related to current Bluetooth session - */ - void ResetSession(); - - /* - * Reset the underlining BluetoothLog object - */ - void ResetLog(); - - /* - * PIMPL style implementation to hide internal dependencies - */ - struct impl; - std::unique_ptr<impl> const pimpl_; -}; - /** * Unknown connection handle for metrics purpose */ diff --git a/system/common/metrics_linux.cc b/system/common/metrics_linux.cc index 009d16878e..e49dd1d2cf 100644 --- a/system/common/metrics_linux.cc +++ b/system/common/metrics_linux.cc @@ -25,64 +25,6 @@ namespace bluetooth { namespace common { -void A2dpSessionMetrics::Update(const A2dpSessionMetrics& /* metrics */) {} - -bool A2dpSessionMetrics::operator==(const A2dpSessionMetrics& /* rhs */) const { - log::info("UNIMPLEMENTED"); - return true; -} - -struct BluetoothMetricsLogger::impl { - impl(size_t /* max_bluetooth_session */, size_t /* max_pair_event */, size_t /* max_wake_event */, - size_t /* max_scan_event */) {} -}; - -BluetoothMetricsLogger::BluetoothMetricsLogger() - : pimpl_(new impl(kMaxNumBluetoothSession, kMaxNumPairEvent, kMaxNumWakeEvent, - kMaxNumScanEvent)) {} - -void BluetoothMetricsLogger::LogPairEvent(uint32_t /* disconnect_reason */, - uint64_t /* timestamp_ms */, uint32_t /* device_class */, - device_type_t /* device_type */) {} - -void BluetoothMetricsLogger::LogWakeEvent(wake_event_type_t /* type */, - const std::string& /* requestor */, - const std::string& /* name */, - uint64_t /* timestamp_ms */) {} - -void BluetoothMetricsLogger::LogScanEvent(bool /* start */, const std::string& /* initiator */, - scan_tech_t /* type */, uint32_t /* results */, - uint64_t /* timestamp_ms */) {} - -void BluetoothMetricsLogger::LogBluetoothSessionStart(connection_tech_t /* connection_tech_type */, - uint64_t /* timestamp_ms */) {} - -void BluetoothMetricsLogger::LogBluetoothSessionEnd(disconnect_reason_t /* disconnect_reason */, - uint64_t /* timestamp_ms */) {} - -void BluetoothMetricsLogger::LogBluetoothSessionDeviceInfo(uint32_t /* device_class */, - device_type_t /* device_type */) {} - -void BluetoothMetricsLogger::LogA2dpSession(const A2dpSessionMetrics& /* a2dp_session_metrics */) {} - -void BluetoothMetricsLogger::LogHeadsetProfileRfcConnection(tBTA_SERVICE_ID /* service_id */) {} - -void BluetoothMetricsLogger::WriteString(std::string* /* serialized */) {} - -void BluetoothMetricsLogger::WriteBase64String(std::string* /* serialized */) {} - -void BluetoothMetricsLogger::WriteBase64(int /* fd */) {} - -void BluetoothMetricsLogger::CutoffSession() {} - -void BluetoothMetricsLogger::Build() {} - -void BluetoothMetricsLogger::ResetSession() {} - -void BluetoothMetricsLogger::ResetLog() {} - -void BluetoothMetricsLogger::Reset() {} - void LogClassicPairingEvent(const RawAddress& /* address */, uint16_t /* handle */, uint32_t /* hci_cmd */, uint16_t /* hci_event */, uint16_t /* cmd_status */, uint16_t /* reason_code */, diff --git a/system/common/metrics_unittest.cc b/system/common/metrics_unittest.cc deleted file mode 100644 index 4bbabb242a..0000000000 --- a/system/common/metrics_unittest.cc +++ /dev/null @@ -1,944 +0,0 @@ -/****************************************************************************** - * - * Copyright 2016 Google, Inc. - * - * 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. - * - ******************************************************************************/ -#include "common/metrics.h" - -#include <gmock/gmock.h> -#include <gtest/gtest.h> -#include <include/hardware/bt_av.h> - -#include <chrono> -#include <cstdint> -#include <string> -#include <thread> -#include <vector> - -#include "bluetooth/metrics/bluetooth.pb.h" -#include "common/time_util.h" - -#define BTM_COD_MAJOR_AUDIO_TEST 0x04 - -namespace testing { - -using bluetooth::common::A2dpSessionMetrics; -using bluetooth::common::BluetoothMetricsLogger; -using bluetooth::metrics::BluetoothMetricsProto::A2DPSession; -using bluetooth::metrics::BluetoothMetricsProto::A2dpSourceCodec; -using bluetooth::metrics::BluetoothMetricsProto::BluetoothLog; -using bluetooth::metrics::BluetoothMetricsProto::BluetoothSession; -using bluetooth::metrics::BluetoothMetricsProto::BluetoothSession_ConnectionTechnologyType; -using bluetooth::metrics::BluetoothMetricsProto::BluetoothSession_DisconnectReasonType; -using bluetooth::metrics::BluetoothMetricsProto::DeviceInfo; -using bluetooth::metrics::BluetoothMetricsProto::DeviceInfo_DeviceType; -using bluetooth::metrics::BluetoothMetricsProto::HeadsetProfileConnectionStats; -using bluetooth::metrics::BluetoothMetricsProto::HeadsetProfileType; -using bluetooth::metrics::BluetoothMetricsProto::PairEvent; -using bluetooth::metrics::BluetoothMetricsProto::RFCommSession; -using bluetooth::metrics::BluetoothMetricsProto::ScanEvent; -using bluetooth::metrics::BluetoothMetricsProto::ScanEvent_ScanEventType; -using bluetooth::metrics::BluetoothMetricsProto::ScanEvent_ScanTechnologyType; -using bluetooth::metrics::BluetoothMetricsProto::WakeEvent; -using bluetooth::metrics::BluetoothMetricsProto::WakeEvent_WakeEventType; - -namespace { -const size_t kMaxEventGenerationLimit = 5000; -} - -static void sleep_ms(int64_t t) { std::this_thread::sleep_for(std::chrono::milliseconds(t)); } - -static DeviceInfo* MakeDeviceInfo(int32_t device_class, DeviceInfo_DeviceType device_type) { - DeviceInfo* info = new DeviceInfo(); - info->set_device_class(device_class); - info->set_device_type(device_type); - return info; -} - -static PairEvent* MakePairEvent(int32_t disconnect_reason, int64_t timestamp_ms, - DeviceInfo* device_info) { - PairEvent* event = new PairEvent(); - event->set_disconnect_reason(disconnect_reason); - event->set_event_time_millis(timestamp_ms); - if (device_info) { - event->set_allocated_device_paired_with(device_info); - } - return event; -} - -static WakeEvent* MakeWakeEvent(WakeEvent_WakeEventType event_type, const std::string& requestor, - const std::string& name, int64_t timestamp_ms) { - WakeEvent* event = new WakeEvent(); - event->set_wake_event_type(event_type); - event->set_requestor(requestor); - event->set_name(name); - event->set_event_time_millis(timestamp_ms); - return event; -} - -static ScanEvent* MakeScanEvent(ScanEvent_ScanEventType event_type, const std::string& initiator, - ScanEvent_ScanTechnologyType tech_type, int32_t num_results, - int64_t timestamp_ms) { - ScanEvent* event = new ScanEvent(); - event->set_scan_event_type(event_type); - event->set_initiator(initiator); - event->set_scan_technology_type(tech_type); - event->set_number_results(num_results); - event->set_event_time_millis(timestamp_ms); - return event; -} - -static A2DPSession* MakeA2DPSession(const A2dpSessionMetrics& metrics, - A2dpSourceCodec source_codec) { - A2DPSession* session = new A2DPSession(); - session->set_media_timer_min_millis(metrics.media_timer_min_ms); - session->set_media_timer_max_millis(metrics.media_timer_max_ms); - session->set_media_timer_avg_millis(metrics.media_timer_avg_ms); - session->set_buffer_overruns_max_count(metrics.buffer_overruns_max_count); - session->set_buffer_overruns_total(metrics.buffer_overruns_total); - session->set_buffer_underruns_average(metrics.buffer_underruns_average); - session->set_buffer_underruns_count(metrics.buffer_underruns_count); - session->set_audio_duration_millis(metrics.audio_duration_ms); - session->set_source_codec(source_codec); - session->set_is_a2dp_offload(metrics.is_a2dp_offload); - return session; -} - -static BluetoothSession* MakeBluetoothSession( - int64_t session_duration_sec, BluetoothSession_ConnectionTechnologyType conn_type, - BluetoothSession_DisconnectReasonType disconnect_reason, DeviceInfo* device_info, - RFCommSession* rfcomm_session, A2DPSession* a2dp_session) { - BluetoothSession* session = new BluetoothSession(); - if (a2dp_session) { - session->set_allocated_a2dp_session(a2dp_session); - } - if (rfcomm_session) { - session->set_allocated_rfcomm_session(rfcomm_session); - } - if (device_info) { - session->set_allocated_device_connected_to(device_info); - } - session->set_session_duration_sec(session_duration_sec); - session->set_connection_technology_type(conn_type); - session->set_disconnect_reason_type(disconnect_reason); - return session; -} - -static void GenerateWakeEvents(size_t start, size_t end, std::vector<WakeEvent*>* wake_events) { - for (size_t i = start; i < end; ++i) { - wake_events->push_back( - MakeWakeEvent(i % 2 == 0 ? WakeEvent_WakeEventType::WakeEvent_WakeEventType_ACQUIRED - : WakeEvent_WakeEventType::WakeEvent_WakeEventType_RELEASED, - "TEST_REQ", "TEST_NAME", i)); - } -} - -#define COMPARE_A2DP_METRICS(a, b) \ - do { \ - EXPECT_EQ((a).audio_duration_ms, (b).audio_duration_ms); \ - EXPECT_EQ((a).media_timer_min_ms, (b).media_timer_min_ms); \ - EXPECT_EQ((a).media_timer_max_ms, (b).media_timer_max_ms); \ - EXPECT_EQ((a).media_timer_avg_ms, (b).media_timer_avg_ms); \ - EXPECT_EQ((a).total_scheduling_count, (b).total_scheduling_count); \ - EXPECT_EQ((a).buffer_overruns_max_count, (b).buffer_overruns_max_count); \ - EXPECT_EQ((a).buffer_overruns_total, (b).buffer_overruns_total); \ - EXPECT_THAT((a).buffer_underruns_average, FloatNear((b).buffer_underruns_average, 0.01)); \ - (a).buffer_underruns_average = (b).buffer_underruns_average; \ - EXPECT_EQ((a).buffer_underruns_count, (b).buffer_underruns_count); \ - EXPECT_EQ((a).codec_index, (b).codec_index); \ - EXPECT_EQ((a).is_a2dp_offload, (b).is_a2dp_offload); \ - } while (0) - -/* - * metrics_sum = metrics1 + metrics2 - */ -TEST(BluetoothA2DPSessionMetricsTest, TestUpdateNormal) { - A2dpSessionMetrics metrics1; - A2dpSessionMetrics metrics2; - A2dpSessionMetrics metrics_sum; - metrics1.audio_duration_ms = 10; - metrics2.audio_duration_ms = 25; - metrics_sum.audio_duration_ms = 35; - metrics1.media_timer_min_ms = 10; - metrics2.media_timer_min_ms = 25; - metrics_sum.media_timer_min_ms = 10; - metrics1.media_timer_max_ms = 100; - metrics2.media_timer_max_ms = 200; - metrics_sum.media_timer_max_ms = 200; - metrics1.media_timer_avg_ms = 50; - metrics1.total_scheduling_count = 50; - metrics2.media_timer_avg_ms = 100; - metrics2.total_scheduling_count = 50; - metrics_sum.media_timer_avg_ms = 75; - metrics_sum.total_scheduling_count = 100; - metrics1.buffer_overruns_max_count = 70; - metrics2.buffer_overruns_max_count = 80; - metrics_sum.buffer_overruns_max_count = 80; - metrics1.buffer_underruns_average = 80; - metrics1.buffer_underruns_count = 1200; - metrics2.buffer_underruns_average = 130; - metrics2.buffer_underruns_count = 2400; - metrics_sum.buffer_underruns_average = 113.33333333; - metrics_sum.buffer_underruns_count = 3600; - metrics1.codec_index = -1; - metrics2.codec_index = BTAV_A2DP_CODEC_INDEX_SOURCE_AAC; - metrics_sum.codec_index = BTAV_A2DP_CODEC_INDEX_SOURCE_AAC; - metrics1.is_a2dp_offload = false; - metrics2.is_a2dp_offload = true; - metrics_sum.is_a2dp_offload = true; - metrics1.Update(metrics2); - COMPARE_A2DP_METRICS(metrics1, metrics_sum); - EXPECT_TRUE(metrics1 == metrics_sum); - EXPECT_EQ(metrics1, metrics_sum); -} - -TEST(BluetoothA2DPSessionMetricsTest, TestUpdateNew) { - A2dpSessionMetrics metrics1; - A2dpSessionMetrics metrics2; - A2dpSessionMetrics metrics_sum; - metrics2.audio_duration_ms = 25; - metrics_sum.audio_duration_ms = 25; - metrics2.media_timer_min_ms = 25; - metrics_sum.media_timer_min_ms = 25; - metrics2.media_timer_max_ms = 200; - metrics_sum.media_timer_max_ms = 200; - metrics2.media_timer_avg_ms = 100; - metrics2.total_scheduling_count = 50; - metrics_sum.media_timer_avg_ms = 100; - metrics_sum.total_scheduling_count = 50; - metrics2.buffer_overruns_max_count = 80; - metrics_sum.buffer_overruns_max_count = 80; - metrics2.buffer_underruns_average = 130; - metrics2.buffer_underruns_count = 2400; - metrics_sum.buffer_underruns_average = 130; - metrics_sum.buffer_underruns_count = 2400; - metrics2.codec_index = BTAV_A2DP_CODEC_INDEX_SOURCE_APTX; - metrics_sum.codec_index = BTAV_A2DP_CODEC_INDEX_SOURCE_APTX; - metrics2.is_a2dp_offload = true; - metrics_sum.is_a2dp_offload = true; - metrics1.Update(metrics2); - COMPARE_A2DP_METRICS(metrics1, metrics_sum); - EXPECT_TRUE(metrics1 == metrics_sum); - EXPECT_EQ(metrics1, metrics_sum); -} - -TEST(BluetoothA2DPSessionMetricsTest, TestNullUpdate) { - A2dpSessionMetrics metrics1; - A2dpSessionMetrics metrics2; - A2dpSessionMetrics metrics_sum; - metrics2.audio_duration_ms = 25; - metrics_sum.audio_duration_ms = 25; - metrics2.media_timer_min_ms = 25; - metrics_sum.media_timer_min_ms = 25; - metrics2.media_timer_max_ms = 200; - metrics_sum.media_timer_max_ms = 200; - metrics2.media_timer_avg_ms = 100; - metrics2.total_scheduling_count = 50; - metrics_sum.media_timer_avg_ms = 100; - metrics_sum.total_scheduling_count = 50; - metrics2.buffer_overruns_max_count = 80; - metrics_sum.buffer_overruns_max_count = 80; - metrics2.buffer_underruns_average = 130; - metrics2.buffer_underruns_count = 2400; - metrics_sum.buffer_underruns_average = 130; - metrics_sum.buffer_underruns_count = 2400; - metrics2.codec_index = BTAV_A2DP_CODEC_INDEX_SOURCE_APTX_HD; - metrics_sum.codec_index = BTAV_A2DP_CODEC_INDEX_SOURCE_APTX_HD; - metrics2.is_a2dp_offload = true; - metrics_sum.is_a2dp_offload = true; - metrics2.Update(metrics1); - COMPARE_A2DP_METRICS(metrics2, metrics_sum); - EXPECT_TRUE(metrics2 == metrics_sum); - EXPECT_EQ(metrics2, metrics_sum); -} - -TEST(BluetoothA2DPSessionMetricsTest, TestPartialUpdate) { - A2dpSessionMetrics metrics1; - A2dpSessionMetrics metrics2; - A2dpSessionMetrics metrics_sum; - metrics1.audio_duration_ms = 10; - metrics2.audio_duration_ms = 25; - metrics_sum.audio_duration_ms = 35; - metrics1.media_timer_min_ms = 10; - metrics_sum.media_timer_min_ms = 10; - metrics1.media_timer_max_ms = 100; - metrics_sum.media_timer_max_ms = 100; - metrics1.media_timer_avg_ms = 50; - metrics1.total_scheduling_count = 50; - metrics2.media_timer_avg_ms = 100; - metrics_sum.media_timer_avg_ms = 50; - metrics_sum.total_scheduling_count = 50; - metrics1.buffer_overruns_max_count = 70; - metrics_sum.buffer_overruns_max_count = 70; - metrics1.buffer_underruns_average = 80; - metrics1.buffer_underruns_count = 1200; - metrics2.buffer_underruns_count = 2400; - metrics_sum.buffer_underruns_average = 80; - metrics_sum.buffer_underruns_count = 1200; - metrics1.Update(metrics2); - COMPARE_A2DP_METRICS(metrics1, metrics_sum); - EXPECT_TRUE(metrics1 == metrics_sum); - EXPECT_EQ(metrics1, metrics_sum); -} - -class BluetoothMetricsLoggerTest : public Test { -protected: - // Use to hold test protos - std::vector<PairEvent*> pair_events_; - std::vector<WakeEvent*> wake_events_; - std::vector<ScanEvent*> scan_events_; - std::vector<BluetoothSession*> bt_sessions_; - int64_t num_pair_event_ = 0; - int64_t num_wake_event_ = 0; - int64_t num_scan_event_ = 0; - int64_t num_bt_session_ = 0; - BluetoothLog* bt_log_; - std::string bt_log_str_; - std::string bt_log_ascii_str_; - - void UpdateLog() { - for (BluetoothSession* session : bt_sessions_) { - bt_log_->mutable_session()->AddAllocated(session); - } - if (num_bt_session_ > 0) { - bt_log_->set_num_bluetooth_session(num_bt_session_); - } else if (bt_sessions_.size() > 0) { - bt_log_->set_num_bluetooth_session(bt_sessions_.size()); - } - bt_sessions_.clear(); - for (PairEvent* event : pair_events_) { - bt_log_->mutable_pair_event()->AddAllocated(event); - } - if (num_pair_event_ > 0) { - bt_log_->set_num_pair_event(num_pair_event_); - } else if (pair_events_.size() > 0) { - bt_log_->set_num_pair_event(pair_events_.size()); - } - pair_events_.clear(); - for (WakeEvent* event : wake_events_) { - bt_log_->mutable_wake_event()->AddAllocated(event); - } - if (num_wake_event_ > 0) { - bt_log_->set_num_wake_event(num_wake_event_); - } else if (wake_events_.size() > 0) { - bt_log_->set_num_wake_event(wake_events_.size()); - } - wake_events_.clear(); - for (ScanEvent* event : scan_events_) { - bt_log_->mutable_scan_event()->AddAllocated(event); - } - if (num_scan_event_ > 0) { - bt_log_->set_num_scan_event(num_scan_event_); - } else if (scan_events_.size() > 0) { - bt_log_->set_num_scan_event(scan_events_.size()); - } - scan_events_.clear(); - bt_log_->SerializeToString(&bt_log_str_); - } - - void ClearLog() { - for (BluetoothSession* session : bt_sessions_) { - session->Clear(); - delete session; - } - bt_sessions_.clear(); - for (PairEvent* event : pair_events_) { - event->Clear(); - delete event; - } - pair_events_.clear(); - for (WakeEvent* event : wake_events_) { - event->Clear(); - delete event; - } - wake_events_.clear(); - for (ScanEvent* event : scan_events_) { - event->Clear(); - delete event; - } - scan_events_.clear(); - bt_log_->Clear(); - } - - void SetUp() override { - bt_log_ = new BluetoothLog(); - // Clear existing metrics entries, if any - BluetoothMetricsLogger::GetInstance()->Reset(); - } - void TearDown() override { - // Clear remaining metrics entries, if any - BluetoothMetricsLogger::GetInstance()->Reset(); - ClearLog(); - delete bt_log_; - } - -public: -}; - -TEST_F(BluetoothMetricsLoggerTest, PairEventTest) { - pair_events_.push_back(MakePairEvent( - 35, 12345, - MakeDeviceInfo(42, DeviceInfo_DeviceType::DeviceInfo_DeviceType_DEVICE_TYPE_BREDR))); - UpdateLog(); - BluetoothMetricsLogger::GetInstance()->LogPairEvent(35, 12345, 42, - bluetooth::common::DEVICE_TYPE_BREDR); - std::string msg_str; - BluetoothMetricsLogger::GetInstance()->WriteString(&msg_str); - EXPECT_THAT(msg_str, StrEq(bt_log_str_)); -} - -TEST_F(BluetoothMetricsLoggerTest, WakeEventTest) { - wake_events_.push_back(MakeWakeEvent(WakeEvent_WakeEventType::WakeEvent_WakeEventType_ACQUIRED, - "TEST_REQ", "TEST_NAME", 12345)); - UpdateLog(); - BluetoothMetricsLogger::GetInstance()->LogWakeEvent(bluetooth::common::WAKE_EVENT_ACQUIRED, - "TEST_REQ", "TEST_NAME", 12345); - std::string msg_str; - BluetoothMetricsLogger::GetInstance()->WriteString(&msg_str); - EXPECT_THAT(msg_str, StrEq(bt_log_str_)); -} - -TEST_F(BluetoothMetricsLoggerTest, WakeEventOverrunTest) { - GenerateWakeEvents(kMaxEventGenerationLimit - BluetoothMetricsLogger::kMaxNumWakeEvent, - kMaxEventGenerationLimit, &wake_events_); - num_wake_event_ = kMaxEventGenerationLimit; - UpdateLog(); - for (size_t i = 0; i < kMaxEventGenerationLimit; ++i) { - BluetoothMetricsLogger::GetInstance()->LogWakeEvent( - i % 2 == 0 ? bluetooth::common::WAKE_EVENT_ACQUIRED - : bluetooth::common::WAKE_EVENT_RELEASED, - "TEST_REQ", "TEST_NAME", i); - } - std::string msg_str; - BluetoothMetricsLogger::GetInstance()->WriteString(&msg_str); - EXPECT_THAT(msg_str, StrEq(bt_log_str_)); -} - -TEST_F(BluetoothMetricsLoggerTest, ScanEventTest) { - scan_events_.push_back(MakeScanEvent( - ScanEvent_ScanEventType::ScanEvent_ScanEventType_SCAN_EVENT_STOP, "TEST_INITIATOR", - ScanEvent_ScanTechnologyType::ScanEvent_ScanTechnologyType_SCAN_TECH_TYPE_BREDR, 42, - 123456)); - UpdateLog(); - BluetoothMetricsLogger::GetInstance()->LogScanEvent( - false, "TEST_INITIATOR", bluetooth::common::SCAN_TECH_TYPE_BREDR, 42, 123456); - std::string msg_str; - BluetoothMetricsLogger::GetInstance()->WriteString(&msg_str); - EXPECT_THAT(msg_str, StrEq(bt_log_str_)); -} - -TEST_F(BluetoothMetricsLoggerTest, BluetoothSessionTest) { - bt_sessions_.push_back(MakeBluetoothSession( - 10, - BluetoothSession_ConnectionTechnologyType:: - BluetoothSession_ConnectionTechnologyType_CONNECTION_TECHNOLOGY_TYPE_LE, - BluetoothSession_DisconnectReasonType::BluetoothSession_DisconnectReasonType_UNKNOWN, - nullptr, nullptr, nullptr)); - UpdateLog(); - BluetoothMetricsLogger::GetInstance()->LogBluetoothSessionStart( - bluetooth::common::CONNECTION_TECHNOLOGY_TYPE_LE, 123456); - BluetoothMetricsLogger::GetInstance()->LogBluetoothSessionEnd( - bluetooth::common::DISCONNECT_REASON_UNKNOWN, 133456); - std::string msg_str; - BluetoothMetricsLogger::GetInstance()->WriteString(&msg_str); - EXPECT_THAT(msg_str, StrEq(bt_log_str_)); -} - -TEST_F(BluetoothMetricsLoggerTest, BluetoothSessionDumpBeforeEndTest) { - bt_sessions_.push_back(MakeBluetoothSession( - 1, - BluetoothSession_ConnectionTechnologyType:: - BluetoothSession_ConnectionTechnologyType_CONNECTION_TECHNOLOGY_TYPE_LE, - BluetoothSession_DisconnectReasonType::BluetoothSession_DisconnectReasonType_METRICS_DUMP, - nullptr, nullptr, nullptr)); - UpdateLog(); - BluetoothMetricsLogger::GetInstance()->LogBluetoothSessionStart( - bluetooth::common::CONNECTION_TECHNOLOGY_TYPE_LE, - bluetooth::common::time_get_os_boottime_ms()); - sleep_ms(1000); - std::string msg_str; - BluetoothMetricsLogger::GetInstance()->WriteString(&msg_str); - EXPECT_THAT(msg_str, StrEq(bt_log_str_)); -} - -TEST_F(BluetoothMetricsLoggerTest, BluetoothSessionStartBeforeEndTest) { - bt_sessions_.push_back(MakeBluetoothSession( - 1, - BluetoothSession_ConnectionTechnologyType:: - BluetoothSession_ConnectionTechnologyType_CONNECTION_TECHNOLOGY_TYPE_UNKNOWN, - BluetoothSession_DisconnectReasonType:: - BluetoothSession_DisconnectReasonType_NEXT_START_WITHOUT_END_PREVIOUS, - nullptr, nullptr, nullptr)); - bt_sessions_.push_back(MakeBluetoothSession( - 2, - BluetoothSession_ConnectionTechnologyType:: - BluetoothSession_ConnectionTechnologyType_CONNECTION_TECHNOLOGY_TYPE_LE, - BluetoothSession_DisconnectReasonType::BluetoothSession_DisconnectReasonType_METRICS_DUMP, - nullptr, nullptr, nullptr)); - UpdateLog(); - BluetoothMetricsLogger::GetInstance()->LogBluetoothSessionStart( - bluetooth::common::CONNECTION_TECHNOLOGY_TYPE_UNKNOWN, 0); - sleep_ms(1000); - BluetoothMetricsLogger::GetInstance()->LogBluetoothSessionStart( - bluetooth::common::CONNECTION_TECHNOLOGY_TYPE_LE, 0); - sleep_ms(2000); - std::string msg_str; - BluetoothMetricsLogger::GetInstance()->WriteString(&msg_str); - EXPECT_THAT(msg_str, StrEq(bt_log_str_)); -} - -/* - * Test Case: A2DPSessionTwoUpdatesTest - * - * 1. Create Instance - * 2. LogBluetoothSessionStart - * 3. LogBluetoothSessionDeviceInfo - * 4. LogA2dpSession - * 5. LogA2dpSession - * 6. LogBluetoothSessionEnd - * 7. WriteString - * - */ -TEST_F(BluetoothMetricsLoggerTest, A2DPSessionTwoUpdatesTest) { - /* Same metrics from BluetoothA2DPSessionMetricsTest.TestUpdateNormal */ - A2dpSessionMetrics metrics1; - A2dpSessionMetrics metrics2; - A2dpSessionMetrics metrics_sum; - metrics1.audio_duration_ms = 10; - metrics2.audio_duration_ms = 25; - metrics_sum.audio_duration_ms = 35; - metrics1.media_timer_min_ms = 10; - metrics2.media_timer_min_ms = 25; - metrics_sum.media_timer_min_ms = 10; - metrics1.media_timer_max_ms = 100; - metrics2.media_timer_max_ms = 200; - metrics_sum.media_timer_max_ms = 200; - metrics1.media_timer_avg_ms = 50; - metrics1.total_scheduling_count = 50; - metrics2.media_timer_avg_ms = 100; - metrics2.total_scheduling_count = 50; - metrics_sum.media_timer_avg_ms = 75; - metrics_sum.total_scheduling_count = 100; - metrics1.buffer_overruns_max_count = 70; - metrics2.buffer_overruns_max_count = 80; - metrics_sum.buffer_overruns_max_count = 80; - metrics1.buffer_underruns_average = 80; - metrics1.buffer_underruns_count = 1200; - metrics2.buffer_underruns_average = 130; - metrics2.buffer_underruns_count = 2400; - metrics_sum.buffer_underruns_average = 113.33333333; - metrics_sum.buffer_underruns_count = 3600; - metrics1.codec_index = -1; - metrics2.codec_index = BTAV_A2DP_CODEC_INDEX_SOURCE_AAC; - metrics_sum.codec_index = BTAV_A2DP_CODEC_INDEX_SOURCE_AAC; - metrics1.is_a2dp_offload = false; - metrics2.is_a2dp_offload = true; - metrics_sum.is_a2dp_offload = true; - DeviceInfo* info = MakeDeviceInfo(BTM_COD_MAJOR_AUDIO_TEST, - DeviceInfo_DeviceType::DeviceInfo_DeviceType_DEVICE_TYPE_BREDR); - A2DPSession* session = MakeA2DPSession(metrics_sum, A2dpSourceCodec::A2DP_SOURCE_CODEC_AAC); - bt_sessions_.push_back(MakeBluetoothSession( - 10, - BluetoothSession_ConnectionTechnologyType:: - BluetoothSession_ConnectionTechnologyType_CONNECTION_TECHNOLOGY_TYPE_BREDR, - BluetoothSession_DisconnectReasonType::BluetoothSession_DisconnectReasonType_UNKNOWN, - info, nullptr, session)); - UpdateLog(); - BluetoothMetricsLogger::GetInstance()->LogBluetoothSessionStart( - bluetooth::common::CONNECTION_TECHNOLOGY_TYPE_BREDR, 123456); - BluetoothMetricsLogger::GetInstance()->LogBluetoothSessionDeviceInfo( - BTM_COD_MAJOR_AUDIO_TEST, bluetooth::common::DEVICE_TYPE_BREDR); - BluetoothMetricsLogger::GetInstance()->LogA2dpSession(metrics1); - BluetoothMetricsLogger::GetInstance()->LogA2dpSession(metrics2); - BluetoothMetricsLogger::GetInstance()->LogBluetoothSessionEnd( - bluetooth::common::DISCONNECT_REASON_UNKNOWN, 133456); - std::string msg_str; - BluetoothMetricsLogger::GetInstance()->WriteString(&msg_str); - EXPECT_THAT(msg_str, StrEq(bt_log_str_)); -} - -/* - * Test Case: A2DPSessionTwoUpdatesSeparatedbyDumpTest - * - * 1. Create Instance - * 2. LogBluetoothSessionStart - * 3. LogBluetoothSessionDeviceInfo - * 4. LogA2dpSession - * 5. WriteString - * 6. LogA2dpSession - * 7. LogBluetoothSessionEnd - * 8. WriteString - * - */ -TEST_F(BluetoothMetricsLoggerTest, A2DPSessionTwoUpdatesSeparatedbyDumpTest) { - /* Same metrics from BluetoothA2DPSessionMetricsTest.TestUpdateNormal */ - A2dpSessionMetrics metrics1; - A2dpSessionMetrics metrics2; - metrics1.audio_duration_ms = 10; - metrics2.audio_duration_ms = 25; - metrics1.media_timer_min_ms = 10; - metrics2.media_timer_min_ms = 25; - metrics1.media_timer_max_ms = 100; - metrics2.media_timer_max_ms = 200; - metrics1.media_timer_avg_ms = 50; - metrics1.total_scheduling_count = 50; - metrics2.media_timer_avg_ms = 100; - metrics2.total_scheduling_count = 50; - metrics1.buffer_overruns_max_count = 70; - metrics2.buffer_overruns_max_count = 80; - metrics1.buffer_underruns_average = 80; - metrics1.buffer_underruns_count = 1200; - metrics2.buffer_underruns_average = 130; - metrics2.buffer_underruns_count = 2400; - metrics1.codec_index = BTAV_A2DP_CODEC_INDEX_SOURCE_SBC; - metrics2.codec_index = BTAV_A2DP_CODEC_INDEX_SOURCE_AAC; - DeviceInfo* info = MakeDeviceInfo(BTM_COD_MAJOR_AUDIO_TEST, - DeviceInfo_DeviceType::DeviceInfo_DeviceType_DEVICE_TYPE_BREDR); - A2DPSession* session = MakeA2DPSession(metrics1, A2dpSourceCodec::A2DP_SOURCE_CODEC_SBC); - bt_sessions_.push_back(MakeBluetoothSession( - 1, - BluetoothSession_ConnectionTechnologyType:: - BluetoothSession_ConnectionTechnologyType_CONNECTION_TECHNOLOGY_TYPE_BREDR, - BluetoothSession_DisconnectReasonType::BluetoothSession_DisconnectReasonType_METRICS_DUMP, - info, nullptr, session)); - UpdateLog(); - BluetoothMetricsLogger::GetInstance()->LogBluetoothSessionStart( - bluetooth::common::CONNECTION_TECHNOLOGY_TYPE_BREDR, 0); - BluetoothMetricsLogger::GetInstance()->LogBluetoothSessionDeviceInfo( - BTM_COD_MAJOR_AUDIO_TEST, bluetooth::common::DEVICE_TYPE_BREDR); - BluetoothMetricsLogger::GetInstance()->LogA2dpSession(metrics1); - sleep_ms(1000); - std::string msg_str; - BluetoothMetricsLogger::GetInstance()->WriteString(&msg_str); - EXPECT_THAT(msg_str, StrEq(bt_log_str_)); - ClearLog(); - info = MakeDeviceInfo(BTM_COD_MAJOR_AUDIO_TEST, - DeviceInfo_DeviceType::DeviceInfo_DeviceType_DEVICE_TYPE_BREDR); - session = MakeA2DPSession(metrics2, A2dpSourceCodec::A2DP_SOURCE_CODEC_AAC); - bt_sessions_.push_back(MakeBluetoothSession( - 1, - BluetoothSession_ConnectionTechnologyType:: - BluetoothSession_ConnectionTechnologyType_CONNECTION_TECHNOLOGY_TYPE_BREDR, - BluetoothSession_DisconnectReasonType::BluetoothSession_DisconnectReasonType_UNKNOWN, - info, nullptr, session)); - UpdateLog(); - sleep_ms(1000); - BluetoothMetricsLogger::GetInstance()->LogA2dpSession(metrics2); - BluetoothMetricsLogger::GetInstance()->LogBluetoothSessionEnd( - bluetooth::common::DISCONNECT_REASON_UNKNOWN, 0); - msg_str.clear(); - BluetoothMetricsLogger::GetInstance()->WriteString(&msg_str); - EXPECT_THAT(msg_str, StrEq(bt_log_str_)); -} - -/* - * Test Case: A2DPSessionTwoUpdatesSeparatedbyEndTest - * - * 1. Create Instance - * 2. LogBluetoothSessionStart - * 3. LogA2dpSession - * 4. LogBluetoothSessionEnd - * 5. LogBluetoothSessionStart - * 6. LogA2dpSession - * 7. LogBluetoothSessionEnd - * 8. WriteString - * - */ -TEST_F(BluetoothMetricsLoggerTest, A2DPSessionTwoUpdatesSeparatedbyEndTest) { - /* Same metrics from BluetoothA2DPSessionMetricsTest.TestUpdateNormal */ - A2dpSessionMetrics metrics1; - metrics1.audio_duration_ms = 10; - metrics1.media_timer_min_ms = 10; - metrics1.media_timer_max_ms = 100; - metrics1.media_timer_avg_ms = 50; - metrics1.total_scheduling_count = 50; - metrics1.buffer_overruns_max_count = 70; - metrics1.buffer_underruns_average = 80; - metrics1.buffer_underruns_count = 1200; - metrics1.codec_index = BTAV_A2DP_CODEC_INDEX_SOURCE_SBC; - DeviceInfo* info = MakeDeviceInfo(BTM_COD_MAJOR_AUDIO_TEST, - DeviceInfo_DeviceType::DeviceInfo_DeviceType_DEVICE_TYPE_BREDR); - A2DPSession* session = MakeA2DPSession(metrics1, A2dpSourceCodec::A2DP_SOURCE_CODEC_SBC); - bt_sessions_.push_back(MakeBluetoothSession( - 1, - BluetoothSession_ConnectionTechnologyType:: - BluetoothSession_ConnectionTechnologyType_CONNECTION_TECHNOLOGY_TYPE_BREDR, - BluetoothSession_DisconnectReasonType::BluetoothSession_DisconnectReasonType_UNKNOWN, - info, nullptr, session)); - UpdateLog(); - BluetoothMetricsLogger::GetInstance()->LogBluetoothSessionStart( - bluetooth::common::CONNECTION_TECHNOLOGY_TYPE_BREDR, 0); - BluetoothMetricsLogger::GetInstance()->LogBluetoothSessionDeviceInfo( - BTM_COD_MAJOR_AUDIO_TEST, bluetooth::common::DEVICE_TYPE_BREDR); - BluetoothMetricsLogger::GetInstance()->LogA2dpSession(metrics1); - sleep_ms(1000); - BluetoothMetricsLogger::GetInstance()->LogBluetoothSessionEnd( - bluetooth::common::DISCONNECT_REASON_UNKNOWN, 0); - std::string msg_str; - BluetoothMetricsLogger::GetInstance()->WriteString(&msg_str); - EXPECT_THAT(msg_str, StrEq(bt_log_str_)); - ClearLog(); - A2dpSessionMetrics metrics2; - metrics2.audio_duration_ms = 25; - metrics2.media_timer_min_ms = 25; - metrics2.media_timer_max_ms = 200; - metrics2.media_timer_avg_ms = 100; - metrics2.total_scheduling_count = 50; - metrics2.buffer_overruns_max_count = 80; - metrics2.buffer_underruns_average = 130; - metrics2.buffer_underruns_count = 2400; - metrics2.codec_index = BTAV_A2DP_CODEC_INDEX_SOURCE_AAC; - session = MakeA2DPSession(metrics2, A2dpSourceCodec::A2DP_SOURCE_CODEC_AAC); - bt_sessions_.push_back(MakeBluetoothSession( - 1, - BluetoothSession_ConnectionTechnologyType:: - BluetoothSession_ConnectionTechnologyType_CONNECTION_TECHNOLOGY_TYPE_BREDR, - BluetoothSession_DisconnectReasonType::BluetoothSession_DisconnectReasonType_UNKNOWN, - nullptr, nullptr, session)); - UpdateLog(); - BluetoothMetricsLogger::GetInstance()->LogBluetoothSessionStart( - bluetooth::common::CONNECTION_TECHNOLOGY_TYPE_BREDR, 0); - sleep_ms(1000); - BluetoothMetricsLogger::GetInstance()->LogA2dpSession(metrics2); - BluetoothMetricsLogger::GetInstance()->LogBluetoothSessionEnd( - bluetooth::common::DISCONNECT_REASON_UNKNOWN, 0); - msg_str.clear(); - BluetoothMetricsLogger::GetInstance()->WriteString(&msg_str); - EXPECT_THAT(msg_str, StrEq(bt_log_str_)); -} - -/* - * Test Case 1: A2DPSessionOnlyTest - * - * 1. Create Instance - * 4. LogA2dpSession - * 5. WriteString - * 6. LogA2dpSession - * 8. WriteString - * - */ -TEST_F(BluetoothMetricsLoggerTest, A2DPSessionOnlyTest) { - /* Same metrics from BluetoothA2DPSessionMetricsTest.TestUpdateNormal */ - A2dpSessionMetrics metrics1; - A2dpSessionMetrics metrics2; - A2dpSessionMetrics metrics_sum; - metrics1.audio_duration_ms = 10; - metrics2.audio_duration_ms = 25; - metrics_sum.audio_duration_ms = 35; - metrics1.media_timer_min_ms = 10; - metrics2.media_timer_min_ms = 25; - metrics_sum.media_timer_min_ms = 10; - metrics1.media_timer_max_ms = 100; - metrics2.media_timer_max_ms = 200; - metrics_sum.media_timer_max_ms = 200; - metrics1.media_timer_avg_ms = 50; - metrics1.total_scheduling_count = 50; - metrics2.media_timer_avg_ms = 100; - metrics2.total_scheduling_count = 50; - metrics_sum.media_timer_avg_ms = 75; - metrics_sum.total_scheduling_count = 100; - metrics1.buffer_overruns_max_count = 70; - metrics2.buffer_overruns_max_count = 80; - metrics_sum.buffer_overruns_max_count = 80; - metrics1.buffer_underruns_average = 80; - metrics1.buffer_underruns_count = 1200; - metrics2.buffer_underruns_average = 130; - metrics2.buffer_underruns_count = 2400; - metrics_sum.buffer_underruns_average = 113.33333333; - metrics_sum.buffer_underruns_count = 3600; - metrics1.codec_index = BTAV_A2DP_CODEC_INDEX_SOURCE_SBC; - metrics2.codec_index = BTAV_A2DP_CODEC_INDEX_SOURCE_AAC; - metrics_sum.codec_index = BTAV_A2DP_CODEC_INDEX_SOURCE_SBC; - DeviceInfo* info = MakeDeviceInfo(BTM_COD_MAJOR_AUDIO_TEST, - DeviceInfo_DeviceType::DeviceInfo_DeviceType_DEVICE_TYPE_BREDR); - A2DPSession* session = MakeA2DPSession(metrics_sum, A2dpSourceCodec::A2DP_SOURCE_CODEC_SBC); - bt_sessions_.push_back(MakeBluetoothSession( - 1, - BluetoothSession_ConnectionTechnologyType:: - BluetoothSession_ConnectionTechnologyType_CONNECTION_TECHNOLOGY_TYPE_BREDR, - BluetoothSession_DisconnectReasonType::BluetoothSession_DisconnectReasonType_METRICS_DUMP, - info, nullptr, session)); - UpdateLog(); - BluetoothMetricsLogger::GetInstance()->LogA2dpSession(metrics1); - BluetoothMetricsLogger::GetInstance()->LogA2dpSession(metrics2); - sleep_ms(1000); - std::string msg_str; - BluetoothMetricsLogger::GetInstance()->WriteString(&msg_str); - EXPECT_THAT(msg_str, StrEq(bt_log_str_)); -} - -/* - * Test Case: A2DPSessionDumpBeforeTwoUpdatesTest - * - * 1. Create Instance - * 2. LogBluetoothSessionStart - * 3. LogBluetoothSessionDeviceInfo - * 5. WriteString - * 6. LogA2dpSession - * 7. LogA2dpSession - * 8. LogBluetoothSessionEnd - * 9. WriteString - * - */ -TEST_F(BluetoothMetricsLoggerTest, A2DPSessionDumpBeforeTwoUpdatesTest) { - /* Same metrics from BluetoothA2DPSessionMetricsTest.TestUpdateNormal */ - A2dpSessionMetrics metrics1; - A2dpSessionMetrics metrics2; - A2dpSessionMetrics metrics_sum; - metrics1.audio_duration_ms = 10; - metrics2.audio_duration_ms = 25; - metrics_sum.audio_duration_ms = 35; - metrics1.media_timer_min_ms = 10; - metrics2.media_timer_min_ms = 25; - metrics_sum.media_timer_min_ms = 10; - metrics1.media_timer_max_ms = 100; - metrics2.media_timer_max_ms = 200; - metrics_sum.media_timer_max_ms = 200; - metrics1.media_timer_avg_ms = 50; - metrics1.total_scheduling_count = 50; - metrics2.media_timer_avg_ms = 100; - metrics2.total_scheduling_count = 50; - metrics_sum.media_timer_avg_ms = 75; - metrics_sum.total_scheduling_count = 100; - metrics1.buffer_overruns_max_count = 70; - metrics2.buffer_overruns_max_count = 80; - metrics_sum.buffer_overruns_max_count = 80; - metrics1.buffer_underruns_average = 80; - metrics1.buffer_underruns_count = 1200; - metrics2.buffer_underruns_average = 130; - metrics2.buffer_underruns_count = 2400; - metrics_sum.buffer_underruns_average = 113.33333333; - metrics_sum.buffer_underruns_count = 3600; - metrics1.codec_index = BTAV_A2DP_CODEC_INDEX_SOURCE_SBC; - metrics2.codec_index = BTAV_A2DP_CODEC_INDEX_SOURCE_AAC; - metrics_sum.codec_index = BTAV_A2DP_CODEC_INDEX_SOURCE_SBC; - DeviceInfo* info = MakeDeviceInfo(BTM_COD_MAJOR_AUDIO_TEST, - DeviceInfo_DeviceType::DeviceInfo_DeviceType_DEVICE_TYPE_BREDR); - bt_sessions_.push_back(MakeBluetoothSession( - 1, - BluetoothSession_ConnectionTechnologyType:: - BluetoothSession_ConnectionTechnologyType_CONNECTION_TECHNOLOGY_TYPE_BREDR, - BluetoothSession_DisconnectReasonType::BluetoothSession_DisconnectReasonType_METRICS_DUMP, - info, nullptr, nullptr)); - UpdateLog(); - BluetoothMetricsLogger::GetInstance()->LogBluetoothSessionStart( - bluetooth::common::CONNECTION_TECHNOLOGY_TYPE_BREDR, 0); - BluetoothMetricsLogger::GetInstance()->LogBluetoothSessionDeviceInfo( - BTM_COD_MAJOR_AUDIO_TEST, bluetooth::common::DEVICE_TYPE_BREDR); - sleep_ms(1000); - std::string msg_str; - BluetoothMetricsLogger::GetInstance()->WriteString(&msg_str); - EXPECT_THAT(msg_str, StrEq(bt_log_str_)); - ClearLog(); - info = MakeDeviceInfo(BTM_COD_MAJOR_AUDIO_TEST, - DeviceInfo_DeviceType::DeviceInfo_DeviceType_DEVICE_TYPE_BREDR); - A2DPSession* session = MakeA2DPSession(metrics_sum, A2dpSourceCodec::A2DP_SOURCE_CODEC_SBC); - bt_sessions_.push_back(MakeBluetoothSession( - 1, - BluetoothSession_ConnectionTechnologyType:: - BluetoothSession_ConnectionTechnologyType_CONNECTION_TECHNOLOGY_TYPE_BREDR, - BluetoothSession_DisconnectReasonType::BluetoothSession_DisconnectReasonType_UNKNOWN, - info, nullptr, session)); - UpdateLog(); - BluetoothMetricsLogger::GetInstance()->LogA2dpSession(metrics1); - BluetoothMetricsLogger::GetInstance()->LogA2dpSession(metrics2); - sleep_ms(1000); - BluetoothMetricsLogger::GetInstance()->LogBluetoothSessionEnd( - bluetooth::common::DISCONNECT_REASON_UNKNOWN, 0); - msg_str.clear(); - BluetoothMetricsLogger::GetInstance()->WriteString(&msg_str); - EXPECT_THAT(msg_str, StrEq(bt_log_str_)); -} - -TEST_F(BluetoothMetricsLoggerTest, LogHeadsetProfileRfcConnectionTest) { - BluetoothMetricsLogger::GetInstance()->LogHeadsetProfileRfcConnection(BTA_HSP_SERVICE_ID); - BluetoothMetricsLogger::GetInstance()->LogHeadsetProfileRfcConnection(BTA_HFP_SERVICE_ID); - BluetoothMetricsLogger::GetInstance()->LogHeadsetProfileRfcConnection(BTA_HFP_SERVICE_ID); - std::string msg_str; - BluetoothMetricsLogger::GetInstance()->WriteString(&msg_str); - BluetoothLog* metrics = BluetoothLog::default_instance().New(); - metrics->ParseFromString(msg_str); - EXPECT_EQ(metrics->headset_profile_connection_stats_size(), 2); - bool hfp_correct = false; - bool hsp_correct = false; - for (const HeadsetProfileConnectionStats& headset_profile_connection_stats : - metrics->headset_profile_connection_stats()) { - switch (headset_profile_connection_stats.headset_profile_type()) { - case HeadsetProfileType::HFP: - EXPECT_EQ(headset_profile_connection_stats.num_times_connected(), 2); - hfp_correct = true; - break; - case HeadsetProfileType::HSP: - EXPECT_EQ(headset_profile_connection_stats.num_times_connected(), 1); - hsp_correct = true; - break; - default: - FAIL(); - } - } - EXPECT_TRUE(hfp_correct); - EXPECT_TRUE(hsp_correct); - metrics->clear_headset_profile_connection_stats(); - EXPECT_EQ(metrics->headset_profile_connection_stats_size(), 0); - msg_str.clear(); - // Verify that dump after clean up result in an empty list - BluetoothMetricsLogger::GetInstance()->WriteString(&msg_str); - metrics->ParseFromString(msg_str); - EXPECT_EQ(metrics->headset_profile_connection_stats_size(), 0); - delete metrics; -} - -TEST_F(BluetoothMetricsLoggerTest, LogHeadsetProfileRfcConnectionErrorTest) { - BluetoothMetricsLogger::GetInstance()->LogHeadsetProfileRfcConnection(BTA_HSP_SERVICE_ID); - BluetoothMetricsLogger::GetInstance()->LogHeadsetProfileRfcConnection(BTA_HFP_SERVICE_ID); - BluetoothMetricsLogger::GetInstance()->LogHeadsetProfileRfcConnection(BTA_BIP_SERVICE_ID); - BluetoothMetricsLogger::GetInstance()->LogHeadsetProfileRfcConnection(BTA_HSP_SERVICE_ID); - std::string msg_str; - BluetoothMetricsLogger::GetInstance()->WriteString(&msg_str); - BluetoothLog* metrics = BluetoothLog::default_instance().New(); - metrics->ParseFromString(msg_str); - EXPECT_EQ(metrics->headset_profile_connection_stats_size(), 3); - bool hfp_correct = false; - bool hsp_correct = false; - bool unknown_correct = false; - for (const HeadsetProfileConnectionStats& headset_profile_connection_stats : - metrics->headset_profile_connection_stats()) { - switch (headset_profile_connection_stats.headset_profile_type()) { - case HeadsetProfileType::HFP: - EXPECT_EQ(headset_profile_connection_stats.num_times_connected(), 1); - hfp_correct = true; - break; - case HeadsetProfileType::HSP: - EXPECT_EQ(headset_profile_connection_stats.num_times_connected(), 2); - hsp_correct = true; - break; - default: - EXPECT_EQ(headset_profile_connection_stats.num_times_connected(), 1); - unknown_correct = true; - break; - } - } - EXPECT_TRUE(hfp_correct); - EXPECT_TRUE(hsp_correct); - EXPECT_TRUE(unknown_correct); - metrics->clear_headset_profile_connection_stats(); - EXPECT_EQ(metrics->headset_profile_connection_stats_size(), 0); - // Verify that dump after clean up result in an empty list - BluetoothMetricsLogger::GetInstance()->WriteString(&msg_str); - metrics->ParseFromString(msg_str); - EXPECT_EQ(metrics->headset_profile_connection_stats_size(), 0); - delete metrics; -} -} // namespace testing diff --git a/system/gd/Android.bp b/system/gd/Android.bp index 2c60271ff7..26f31f0b8e 100644 --- a/system/gd/Android.bp +++ b/system/gd/Android.bp @@ -170,7 +170,6 @@ cc_defaults { static_libs: [ "libaconfig_storage_read_api_cc", "libbase", - "libbluetooth-protos", "libbluetooth-types", "libbluetooth_crypto_toolbox", "libbluetooth_log", @@ -418,7 +417,6 @@ cc_test { static_libs: [ "bluetooth_flags_c_lib_for_test", "libbase", - "libbluetooth-protos", "libbluetooth-types", "libbluetooth_crypto_toolbox", "libbluetooth_gd_unit_tests", @@ -510,7 +508,6 @@ cc_defaults { ], static_libs: [ "bluetooth_flags_c_lib", - "libbluetooth-protos", "libbluetooth-types", "libbluetooth_crypto_toolbox", "libbluetooth_gd_fuzzing", diff --git a/system/gd/proto/Android.bp b/system/gd/proto/Android.bp index 1f7e72687f..e7aa3e48e6 100644 --- a/system/gd/proto/Android.bp +++ b/system/gd/proto/Android.bp @@ -20,25 +20,3 @@ java_library_static { min_sdk_version: "30", sdk_version: "current", } - -filegroup { - name: "bluetooth-metrics-proto", - srcs: [ - "bluetooth/metrics/bluetooth.proto", - ], -} - -cc_library_static { - name: "libbluetooth-protos", - host_supported: true, - proto: { - export_proto_headers: true, - type: "lite", - include_dirs: ["external/protobuf/src"], - }, - srcs: [ - "bluetooth/metrics/bluetooth.proto", - ], - apex_available: ["com.android.bt"], - min_sdk_version: "30", -} diff --git a/system/gd/proto/BUILD.gn b/system/gd/proto/BUILD.gn deleted file mode 100644 index ba5cd4eaaf..0000000000 --- a/system/gd/proto/BUILD.gn +++ /dev/null @@ -1,10 +0,0 @@ -import("//common-mk/proto_library.gni") - -proto_library("libbt-protos-lite") { - sources = [ - "bluetooth/metrics/bluetooth.proto", - ] - - proto_in_dir = "./bluetooth/metrics" - proto_out_dir = "include/bluetooth/metrics" -} diff --git a/system/include/hardware/bluetooth.h b/system/include/hardware/bluetooth.h index a2020b0e7f..41757cc556 100644 --- a/system/include/hardware/bluetooth.h +++ b/system/include/hardware/bluetooth.h @@ -836,14 +836,6 @@ typedef struct { void (*dump)(int fd, const char** arguments); /** - * Native support for metrics protobuf dumping. The dumping format will be - * raw byte array - * - * @param output an externally allocated string to dump serialized protobuf - */ - void (*dumpMetrics)(std::string* output); - - /** * Clear /data/misc/bt_config.conf and erase all stored connections */ int (*config_clear)(void); diff --git a/system/osi/src/wakelock.cc b/system/osi/src/wakelock.cc index 5cae5ed580..e6a41c3c12 100644 --- a/system/osi/src/wakelock.cc +++ b/system/osi/src/wakelock.cc @@ -33,10 +33,8 @@ #include <mutex> #include <string> -#include "common/metrics.h" #include "osi/include/osi.h" -using bluetooth::common::BluetoothMetricsLogger; using namespace bluetooth; static bt_os_callouts_t* wakelock_os_callouts = NULL; @@ -279,9 +277,6 @@ static void update_wakelock_acquired_stats(bt_status_t acquired_status) { wakelock_stats.is_acquired = true; wakelock_stats.acquired_count++; wakelock_stats.last_acquired_timestamp_ms = just_now_ms; - - BluetoothMetricsLogger::GetInstance()->LogWakeEvent(bluetooth::common::WAKE_EVENT_ACQUIRED, "", - "", just_now_ms); } // @@ -320,9 +315,6 @@ static void update_wakelock_released_stats(bt_status_t released_status) { } wakelock_stats.last_acquired_interval_ms = delta_ms; wakelock_stats.total_acquired_interval_ms += delta_ms; - - BluetoothMetricsLogger::GetInstance()->LogWakeEvent(bluetooth::common::WAKE_EVENT_RELEASED, "", - "", just_now_ms); } void wakelock_debug_dump(int fd) { diff --git a/system/tools/scripts/dump_metrics_ascii.py b/system/tools/scripts/dump_metrics_ascii.py deleted file mode 100755 index 0adb278322..0000000000 --- a/system/tools/scripts/dump_metrics_ascii.py +++ /dev/null @@ -1,139 +0,0 @@ -#!/usr/bin/env python3 -# Copyright 2018 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. - -import base64 -import logging -import os -import subprocess -import sys -import tempfile -from distutils.spawn import find_executable -import google.protobuf.text_format as text_format -from importlib import import_module - - -def compile_proto(proto_path, output_dir): - """Invoke Protocol Compiler to generate python from given source .proto.""" - # Find compiler path - protoc = None - if 'PROTOC' in os.environ and os.path.exists(os.environ['PROTOC']): - protoc = os.environ['PROTOC'] - if not protoc: - protoc = find_executable('protoc') - if not protoc: - logging.error("Cannot find Protobuf compiler (>=3.0.0), please install" - "protobuf-compiler package. Prefer copying from <top>/prebuilts/tools") - logging.error(" prebuilts/tools/linux-x86_64/protoc/bin/protoc") - logging.error("If prebuilts are not available, use apt-get:") - logging.error(" sudo apt-get install protobuf-compiler") - return None - # Validate input proto path - if not os.path.exists(proto_path): - logging.error('Can\'t find required file: %s\n' % proto_path) - return None - # Validate output py-proto path - if not os.path.exists(output_dir): - os.mkdirs(output_dir) - elif not os.path.isdir(output_dir): - logging.error("Output path is not a valid directory: %s" % (output_dir)) - return None - input_dir = os.path.dirname(proto_path) - output_filename = os.path.basename(proto_path).replace('.proto', '_pb2.py') - output_path = os.path.join(output_dir, output_filename) - protoc_command = [protoc, '-I=%s' % (input_dir), '--python_out=%s' % (output_dir), proto_path] - if subprocess.call(protoc_command, stderr=subprocess.STDOUT) != 0: - logging.error("Fail to compile proto") - return None - output_module_name = os.path.splitext(output_filename)[0] - return output_module_name - - -def compile_import_proto(output_dir, proto_path): - """ - Compile protobuf from PROTO_PATH and put the result in OUTPUT_DIR. - Return the imported module to caller. - :param output_dir: To store generated python proto library - :param proto_path: Path to the .proto file that needs to be compiled - :return: python proto module - """ - output_module_name = compile_proto(proto_path, output_dir) - if not output_module_name: - return None - sys.path.append(output_dir) - output_module = None - try: - output_module = import_module(output_module_name) - except ImportError: - logging.error("Cannot import generated py-proto %s" % (output_module_name)) - return output_module - - -def parse_proto_to_ascii(binary_proto_msg): - """ - Parse binary protobuf message to human readable ascii string - :param binary_proto_msg: - :return: ascii string of the message - """ - return text_format.MessageToString(binary_proto_msg) - - -def dump_metrics(): - os.system('adb wait-for-device') - p = subprocess.Popen( - "adb shell dumpsys bluetooth_manager --proto-bin", - shell=True, - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, - stdin=subprocess.PIPE) - return p.communicate() - - -def get_bluetooth_metrics(proto_native_str_64, bluetooth_proto_module): - bluetooth_log = bluetooth_proto_module.BluetoothLog() - proto_native_str = base64.b64decode(proto_native_str_64) - bluetooth_log.MergeFromString(proto_native_str) - return bluetooth_log - - -def main(): - root = logging.getLogger() - root.setLevel(logging.DEBUG) - log_handler = logging.StreamHandler(sys.stderr) - log_handler.setLevel(logging.DEBUG) - formatter = logging.Formatter("%(asctime)s %(levelname)s %(message)s") - log_handler.setFormatter(formatter) - root.addHandler(log_handler) - if len(sys.argv) < 2: - logging.error("Not enough arguments. Need at least 2") - logging.error("Usage: " + sys.argv[0] + " <path_to_metric_proto>") - sys.exit(1) - if sys.argv[1] == "-h": - logging.info("Usage: " + sys.argv[0] + " <path_to_metric_proto>") - logging.info("Requires Protobuf compiler, protoc, version >=3.0.0") - sys.exit(0) - bluetooth_proto_module = compile_import_proto(tempfile.gettempdir(), sys.argv[1]) - if not bluetooth_proto_module: - logging.error("Cannot compile " + sys.argv[1]) - sys.exit(1) - stdout, stderr = dump_metrics() - stdout = stdout.strip() - stderr = stderr.strip() - bluetooth_log = get_bluetooth_metrics(stdout, bluetooth_proto_module) - bluetooth_log_ascii = parse_proto_to_ascii(bluetooth_log) - print(bluetooth_log_ascii) - - -if __name__ == "__main__": - main() |