diff options
1011 files changed, 9289 insertions, 13137 deletions
diff --git a/Android.bp b/Android.bp index 89fa45ba46..34d17b71f2 100644 --- a/Android.bp +++ b/Android.bp @@ -121,8 +121,11 @@ java_defaults { javacflags: [ "-Xep:AlmostJavadoc:ERROR", "-Xep:AlreadyChecked:ERROR", + "-Xep:AmbiguousMethodReference:ERROR", "-Xep:ArrayRecordComponent:ERROR", + "-Xep:AttemptedNegativeZero:ERROR", "-Xep:BadImport:ERROR", + "-Xep:BadInstanceof:ERROR", "-Xep:CatchAndPrintStackTrace:ERROR", "-Xep:CatchFail:ERROR", "-Xep:CheckReturnValue:ERROR", @@ -146,11 +149,14 @@ java_defaults { "-Xep:GuardedBy:ERROR", "-Xep:HidingField:ERROR", "-Xep:InconsistentHashCode:ERROR", + "-Xep:IncrementInForLoopAndHeader:ERROR", "-Xep:InlineFormatString:ERROR", "-Xep:InlineMeInliner:ERROR", "-Xep:InvalidBlockTag:ERROR", "-Xep:InvalidInlineTag:ERROR", + "-Xep:InvalidLink:ERROR", "-Xep:InvalidParam:ERROR", + "-Xep:JavaLangClash:ERROR", "-Xep:JavaUtilDate:ERROR", "-Xep:JdkObsolete:ERROR", "-Xep:LockOnNonEnclosingClassLiteral:ERROR", @@ -168,9 +174,12 @@ java_defaults { "-Xep:NonAtomicVolatileUpdate:ERROR", "-Xep:NonCanonicalType:ERROR", "-Xep:NotJavadoc:ERROR", + "-Xep:NullOptional:ERROR", + "-Xep:NullableOptional:ERROR", "-Xep:NullablePrimitive:ERROR", "-Xep:NullableVoid:ERROR", "-Xep:ObjectEqualsForPrimitives:ERROR", + // "-Xep:ObjectToString:ERROR", // Wrongfully reporting errors "-Xep:OperatorPrecedence:ERROR", "-Xep:RedundantControlFlow:ERROR", "-Xep:ReferenceEquality:ERROR", @@ -181,10 +190,13 @@ java_defaults { "-Xep:StaticGuardedByInstance:ERROR", "-Xep:StringCaseLocaleUsage:ERROR", "-Xep:StringCharset:ERROR", + // "-Xep:StringSplitter:ERROR", // Not enabled in android platform "-Xep:SynchronizeOnNonFinalField:ERROR", "-Xep:ThreadJoinLoop:ERROR", "-Xep:ToStringReturnsNull:ERROR", + "-Xep:TruthAssertExpected:ERROR", "-Xep:TruthConstantAsserts:ERROR", + "-Xep:TruthGetOrDefault:ERROR", "-Xep:TruthIncompatibleType:ERROR", "-Xep:UndefinedEquals:ERROR", "-Xep:UnnecessaryAssignment:ERROR", @@ -193,6 +205,7 @@ java_defaults { "-Xep:UnrecognisedJavadocTag:ERROR", "-Xep:UnusedMethod:ERROR", "-Xep:UnusedNestedClass:ERROR", + "-Xep:UnusedTypeParameter:ERROR", "-Xep:UnusedVariable:ERROR", "-Xep:VariableNameSameAsType:ERROR", "-Xep:WaitNotInLoop:ERROR", diff --git a/CPPLINT.cfg b/CPPLINT.cfg index d04adc0048..e9f429df17 100644 --- a/CPPLINT.cfg +++ b/CPPLINT.cfg @@ -1,5 +1,4 @@ set noparent -linelength=100 # Do not check access modifier indentation. # CPPLint enforces +1, but our rule is no indentation. filter=-whitespace/indent @@ -38,3 +37,4 @@ filter=-readability/casting # The following checks are either covered by clang-format, # or can produce diagnostics that contradict clang-format. filter=-build/include_order +filter=-whitespace/line_length diff --git a/PREUPLOAD.cfg b/PREUPLOAD.cfg index dbdc14449e..9b5297d570 100644 --- a/PREUPLOAD.cfg +++ b/PREUPLOAD.cfg @@ -18,7 +18,6 @@ ktfmt = --kotlinlang-style rustfmt = --config-path=rustfmt.toml [Hook Scripts] -aosp_first = ${REPO_ROOT}/frameworks/base/tools/aosp/aosp_sha.sh ${PREUPLOAD_COMMIT} ${PREUPLOAD_FILES} # google_java_format only fixes indentation. This has Android specific checks like "m" prefix. checkstyle_hook = ${REPO_ROOT}/prebuilts/checkstyle/checkstyle.py --sha ${PREUPLOAD_COMMIT} --config_xml checkstyle.xml diff --git a/android/app/Android.bp b/android/app/Android.bp index 6bdbe3282b..7606a10b73 100644 --- a/android/app/Android.bp +++ b/android/app/Android.bp @@ -246,7 +246,6 @@ android_library { "ExtraText", "ExtraTranslation", "GestureBackNavigation", - "GetterSetterNullability", "GuardedLogInvocation", "HandlerLeak", "InflateParams", @@ -319,7 +318,6 @@ android_app { "ExtraText", "ExtraTranslation", "GestureBackNavigation", - "GetterSetterNullability", "GuardedLogInvocation", "HandlerLeak", "InflateParams", diff --git a/android/app/aidl/android/bluetooth/BluetoothAudioConfig.aidl b/android/app/aidl/android/bluetooth/BluetoothAudioConfig.aidl index 2ef113d9fa..63be5cff87 100644 --- a/android/app/aidl/android/bluetooth/BluetoothAudioConfig.aidl +++ b/android/app/aidl/android/bluetooth/BluetoothAudioConfig.aidl @@ -1,5 +1,5 @@ /* - * Copyright 2009 The Android Open Source Project + * Copyright (C) 2009 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. diff --git a/android/app/aidl/android/bluetooth/BluetoothAvrcpPlayerSettings.aidl b/android/app/aidl/android/bluetooth/BluetoothAvrcpPlayerSettings.aidl index 41b8af6d78..590fd63eda 100644 --- a/android/app/aidl/android/bluetooth/BluetoothAvrcpPlayerSettings.aidl +++ b/android/app/aidl/android/bluetooth/BluetoothAvrcpPlayerSettings.aidl @@ -1,5 +1,5 @@ /* - * Copyright 2015 The Android Open Source Project + * Copyright (C) 2015 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. diff --git a/android/app/aidl/android/bluetooth/BluetoothCodecConfig.aidl b/android/app/aidl/android/bluetooth/BluetoothCodecConfig.aidl index 58906374ba..553e66e1da 100644 --- a/android/app/aidl/android/bluetooth/BluetoothCodecConfig.aidl +++ b/android/app/aidl/android/bluetooth/BluetoothCodecConfig.aidl @@ -1,5 +1,5 @@ /* - * Copyright 2016 The Android Open Source Project + * Copyright (C) 2016 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. diff --git a/android/app/aidl/android/bluetooth/BluetoothCodecStatus.aidl b/android/app/aidl/android/bluetooth/BluetoothCodecStatus.aidl index f674db77bd..f9c3a3de2f 100644 --- a/android/app/aidl/android/bluetooth/BluetoothCodecStatus.aidl +++ b/android/app/aidl/android/bluetooth/BluetoothCodecStatus.aidl @@ -1,5 +1,5 @@ /* - * Copyright 2017 The Android Open Source Project + * Copyright (C) 2017 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. diff --git a/android/app/aidl/android/bluetooth/BluetoothCodecType.aidl b/android/app/aidl/android/bluetooth/BluetoothCodecType.aidl index 2365b126ca..dfd81057ee 100644 --- a/android/app/aidl/android/bluetooth/BluetoothCodecType.aidl +++ b/android/app/aidl/android/bluetooth/BluetoothCodecType.aidl @@ -1,5 +1,5 @@ /* - * Copyright 2024 The Android Open Source Project + * Copyright (C) 2024 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. diff --git a/android/app/aidl/android/bluetooth/BluetoothGattCharacteristic.aidl b/android/app/aidl/android/bluetooth/BluetoothGattCharacteristic.aidl index 463b7a70b7..bbb8623e21 100644 --- a/android/app/aidl/android/bluetooth/BluetoothGattCharacteristic.aidl +++ b/android/app/aidl/android/bluetooth/BluetoothGattCharacteristic.aidl @@ -1,5 +1,5 @@ /* - * Copyright 2016 The Android Open Source Project + * Copyright (C) 2016 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. diff --git a/android/app/aidl/android/bluetooth/BluetoothGattDescriptor.aidl b/android/app/aidl/android/bluetooth/BluetoothGattDescriptor.aidl index 6d4cdeb848..4393273316 100644 --- a/android/app/aidl/android/bluetooth/BluetoothGattDescriptor.aidl +++ b/android/app/aidl/android/bluetooth/BluetoothGattDescriptor.aidl @@ -1,5 +1,5 @@ /* - * Copyright 2016 The Android Open Source Project + * Copyright (C) 2016 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. diff --git a/android/app/aidl/android/bluetooth/BluetoothGattIncludedService.aidl b/android/app/aidl/android/bluetooth/BluetoothGattIncludedService.aidl index d911973467..1ef427edc3 100644 --- a/android/app/aidl/android/bluetooth/BluetoothGattIncludedService.aidl +++ b/android/app/aidl/android/bluetooth/BluetoothGattIncludedService.aidl @@ -1,5 +1,5 @@ /* - * Copyright 2016 The Android Open Source Project + * Copyright (C) 2016 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. diff --git a/android/app/aidl/android/bluetooth/BluetoothGattService.aidl b/android/app/aidl/android/bluetooth/BluetoothGattService.aidl index 8e72ba91a4..84314d2072 100644 --- a/android/app/aidl/android/bluetooth/BluetoothGattService.aidl +++ b/android/app/aidl/android/bluetooth/BluetoothGattService.aidl @@ -1,5 +1,5 @@ /* - * Copyright 2016 The Android Open Source Project + * Copyright (C) 2016 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. diff --git a/android/app/aidl/android/bluetooth/BluetoothHeadsetClientCall.aidl b/android/app/aidl/android/bluetooth/BluetoothHeadsetClientCall.aidl index 5403d5149c..35f792387e 100644 --- a/android/app/aidl/android/bluetooth/BluetoothHeadsetClientCall.aidl +++ b/android/app/aidl/android/bluetooth/BluetoothHeadsetClientCall.aidl @@ -1,5 +1,5 @@ /* - * Copyright 2014 The Android Open Source Project + * Copyright (C) 2014 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. diff --git a/android/app/aidl/android/bluetooth/BluetoothHearingAid.aidl b/android/app/aidl/android/bluetooth/BluetoothHearingAid.aidl index 48c4772c03..bcb2466bda 100644 --- a/android/app/aidl/android/bluetooth/BluetoothHearingAid.aidl +++ b/android/app/aidl/android/bluetooth/BluetoothHearingAid.aidl @@ -1,5 +1,5 @@ /* - * Copyright 2024 The Android Open Source Project + * Copyright (C) 2024 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. diff --git a/android/app/aidl/android/bluetooth/BluetoothLeAudioCodecConfig.aidl b/android/app/aidl/android/bluetooth/BluetoothLeAudioCodecConfig.aidl index e32217eff7..3eb42f18e9 100644 --- a/android/app/aidl/android/bluetooth/BluetoothLeAudioCodecConfig.aidl +++ b/android/app/aidl/android/bluetooth/BluetoothLeAudioCodecConfig.aidl @@ -1,5 +1,5 @@ /* - * Copyright 2022 The Android Open Source Project + * Copyright (C) 2022 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. diff --git a/android/app/aidl/android/bluetooth/BluetoothLeAudioCodecStatus.aidl b/android/app/aidl/android/bluetooth/BluetoothLeAudioCodecStatus.aidl index 7c50d6ebe9..52cdf692bc 100644 --- a/android/app/aidl/android/bluetooth/BluetoothLeAudioCodecStatus.aidl +++ b/android/app/aidl/android/bluetooth/BluetoothLeAudioCodecStatus.aidl @@ -1,5 +1,5 @@ /* - * Copyright 2022 The Android Open Source Project + * Copyright (C) 2022 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. diff --git a/android/app/aidl/android/bluetooth/BluetoothLeAudioContentMetadata.aidl b/android/app/aidl/android/bluetooth/BluetoothLeAudioContentMetadata.aidl index 8962810c62..eb4712a9bb 100644 --- a/android/app/aidl/android/bluetooth/BluetoothLeAudioContentMetadata.aidl +++ b/android/app/aidl/android/bluetooth/BluetoothLeAudioContentMetadata.aidl @@ -1,5 +1,5 @@ /* - * Copyright 2022 The Android Open Source Project + * Copyright (C) 2022 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. diff --git a/android/app/aidl/android/bluetooth/BluetoothLeBroadcastMetadata.aidl b/android/app/aidl/android/bluetooth/BluetoothLeBroadcastMetadata.aidl index eb00836ec0..5ce8f6ba30 100644 --- a/android/app/aidl/android/bluetooth/BluetoothLeBroadcastMetadata.aidl +++ b/android/app/aidl/android/bluetooth/BluetoothLeBroadcastMetadata.aidl @@ -1,5 +1,5 @@ /* - * Copyright 2022 The Android Open Source Project + * Copyright (C) 2022 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. diff --git a/android/app/aidl/android/bluetooth/BluetoothLeBroadcastReceiveState.aidl b/android/app/aidl/android/bluetooth/BluetoothLeBroadcastReceiveState.aidl index e3f13b0fbc..1ae4036cdf 100644 --- a/android/app/aidl/android/bluetooth/BluetoothLeBroadcastReceiveState.aidl +++ b/android/app/aidl/android/bluetooth/BluetoothLeBroadcastReceiveState.aidl @@ -1,5 +1,5 @@ /* - * Copyright 2022 The Android Open Source Project + * Copyright (C) 2022 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. diff --git a/android/app/aidl/android/bluetooth/BluetoothLeBroadcastSettings.aidl b/android/app/aidl/android/bluetooth/BluetoothLeBroadcastSettings.aidl index 69ec550745..b36d69c374 100644 --- a/android/app/aidl/android/bluetooth/BluetoothLeBroadcastSettings.aidl +++ b/android/app/aidl/android/bluetooth/BluetoothLeBroadcastSettings.aidl @@ -1,5 +1,5 @@ /* - * Copyright 2023 The Android Open Source Project + * Copyright (C) 2023 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/android/app/aidl/android/bluetooth/BluetoothSinkAudioPolicy.aidl b/android/app/aidl/android/bluetooth/BluetoothSinkAudioPolicy.aidl index 740249c84f..edb81dd6a2 100644 --- a/android/app/aidl/android/bluetooth/BluetoothSinkAudioPolicy.aidl +++ b/android/app/aidl/android/bluetooth/BluetoothSinkAudioPolicy.aidl @@ -1,5 +1,5 @@ /* - * Copyright 2022 The Android Open Source Project + * Copyright (C) 2022 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. diff --git a/android/app/aidl/android/bluetooth/IAudioInputCallback.aidl b/android/app/aidl/android/bluetooth/IAudioInputCallback.aidl index 133dfbebbb..9b358940bd 100644 --- a/android/app/aidl/android/bluetooth/IAudioInputCallback.aidl +++ b/android/app/aidl/android/bluetooth/IAudioInputCallback.aidl @@ -1,5 +1,5 @@ /* - * Copyright 2024 The Android Open Source Project + * Copyright (C) 2024 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. diff --git a/android/app/aidl/android/bluetooth/IBluetooth.aidl b/android/app/aidl/android/bluetooth/IBluetooth.aidl index b9cf6bca14..bc46353f7c 100644 --- a/android/app/aidl/android/bluetooth/IBluetooth.aidl +++ b/android/app/aidl/android/bluetooth/IBluetooth.aidl @@ -100,7 +100,9 @@ interface IBluetooth @JavaPassthrough(annotation="@android.annotation.RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)") List<BluetoothDevice> getBondedDevices(in AttributionSource attributionSource); @JavaPassthrough(annotation="@android.annotation.RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)") - boolean createBond(in BluetoothDevice device, in int transport, in OobData p192Data, in OobData p256Data, in AttributionSource attributionSource); + boolean createBond(in BluetoothDevice device, in int transport, in AttributionSource attributionSource); + @JavaPassthrough(annotation="@android.annotation.RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT,android.Manifest.permission.BLUETOOTH_PRIVILEGED})") + boolean createBondOutOfBand(in BluetoothDevice device, in int transport, in OobData p192Data, in OobData p256Data, in AttributionSource attributionSource); @JavaPassthrough(annotation="@android.annotation.RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT,android.Manifest.permission.BLUETOOTH_PRIVILEGED})") boolean cancelBondProcess(in BluetoothDevice device, in AttributionSource attributionSource); @JavaPassthrough(annotation="@android.annotation.RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)") diff --git a/android/app/aidl/android/bluetooth/IBluetoothA2dp.aidl b/android/app/aidl/android/bluetooth/IBluetoothA2dp.aidl index fa5d1362ac..3eeaf4de82 100644 --- a/android/app/aidl/android/bluetooth/IBluetoothA2dp.aidl +++ b/android/app/aidl/android/bluetooth/IBluetoothA2dp.aidl @@ -1,5 +1,5 @@ /* - * Copyright 2008 The Android Open Source Project + * Copyright (C) 2008 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. diff --git a/android/app/aidl/android/bluetooth/IBluetoothA2dpSink.aidl b/android/app/aidl/android/bluetooth/IBluetoothA2dpSink.aidl index 53c12167bb..0e09962668 100644 --- a/android/app/aidl/android/bluetooth/IBluetoothA2dpSink.aidl +++ b/android/app/aidl/android/bluetooth/IBluetoothA2dpSink.aidl @@ -1,5 +1,5 @@ /* - * Copyright 2014 The Android Open Source Project + * Copyright (C) 2014 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. diff --git a/android/app/aidl/android/bluetooth/IBluetoothAvrcpController.aidl b/android/app/aidl/android/bluetooth/IBluetoothAvrcpController.aidl index 4eae036576..f9226ccca6 100644 --- a/android/app/aidl/android/bluetooth/IBluetoothAvrcpController.aidl +++ b/android/app/aidl/android/bluetooth/IBluetoothAvrcpController.aidl @@ -1,5 +1,5 @@ /* - * Copyright 2014 The Android Open Source Project + * Copyright (C) 2014 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. diff --git a/android/app/aidl/android/bluetooth/IBluetoothConnectionCallback.aidl b/android/app/aidl/android/bluetooth/IBluetoothConnectionCallback.aidl index 56de49c519..acbccedbb8 100644 --- a/android/app/aidl/android/bluetooth/IBluetoothConnectionCallback.aidl +++ b/android/app/aidl/android/bluetooth/IBluetoothConnectionCallback.aidl @@ -1,5 +1,5 @@ /* - * Copyright 2020 The Android Open Source Project + * Copyright (C) 2020 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. diff --git a/android/app/aidl/android/bluetooth/IBluetoothGatt.aidl b/android/app/aidl/android/bluetooth/IBluetoothGatt.aidl index 40976dbf00..225da3e126 100644 --- a/android/app/aidl/android/bluetooth/IBluetoothGatt.aidl +++ b/android/app/aidl/android/bluetooth/IBluetoothGatt.aidl @@ -1,5 +1,5 @@ /* - * Copyright 2013 The Android Open Source Project + * Copyright (C) 2013 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. diff --git a/android/app/aidl/android/bluetooth/IBluetoothGattCallback.aidl b/android/app/aidl/android/bluetooth/IBluetoothGattCallback.aidl index 78fc874b1c..81ec765973 100644 --- a/android/app/aidl/android/bluetooth/IBluetoothGattCallback.aidl +++ b/android/app/aidl/android/bluetooth/IBluetoothGattCallback.aidl @@ -1,5 +1,5 @@ /* - * Copyright 2013 The Android Open Source Project + * Copyright (C) 2013 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. diff --git a/android/app/aidl/android/bluetooth/IBluetoothGattServerCallback.aidl b/android/app/aidl/android/bluetooth/IBluetoothGattServerCallback.aidl index f79546dd34..cc0ff314de 100644 --- a/android/app/aidl/android/bluetooth/IBluetoothGattServerCallback.aidl +++ b/android/app/aidl/android/bluetooth/IBluetoothGattServerCallback.aidl @@ -1,5 +1,5 @@ /* - * Copyright 2017 The Android Open Source Project + * Copyright (C) 2017 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. diff --git a/android/app/aidl/android/bluetooth/IBluetoothHapClientCallback.aidl b/android/app/aidl/android/bluetooth/IBluetoothHapClientCallback.aidl index 2480b305e9..96d1c88eb0 100644 --- a/android/app/aidl/android/bluetooth/IBluetoothHapClientCallback.aidl +++ b/android/app/aidl/android/bluetooth/IBluetoothHapClientCallback.aidl @@ -1,5 +1,5 @@ /* - * Copyright 2022 The Android Open Source Project + * Copyright (C) 2022 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. diff --git a/android/app/aidl/android/bluetooth/IBluetoothHciVendorSpecificCallback.aidl b/android/app/aidl/android/bluetooth/IBluetoothHciVendorSpecificCallback.aidl index 2aac21b158..ee122fd6b3 100644 --- a/android/app/aidl/android/bluetooth/IBluetoothHciVendorSpecificCallback.aidl +++ b/android/app/aidl/android/bluetooth/IBluetoothHciVendorSpecificCallback.aidl @@ -1,5 +1,5 @@ /* - * Copyright 2024 The Android Open Source Project + * Copyright (C) 2024 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. diff --git a/android/app/aidl/android/bluetooth/IBluetoothHeadset.aidl b/android/app/aidl/android/bluetooth/IBluetoothHeadset.aidl index 3b3292cd16..6653bd2320 100644 --- a/android/app/aidl/android/bluetooth/IBluetoothHeadset.aidl +++ b/android/app/aidl/android/bluetooth/IBluetoothHeadset.aidl @@ -1,5 +1,5 @@ /* - * Copyright 2008 The Android Open Source Project + * Copyright (C) 2008 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. diff --git a/android/app/aidl/android/bluetooth/IBluetoothHeadsetClient.aidl b/android/app/aidl/android/bluetooth/IBluetoothHeadsetClient.aidl index 59c5f98bfb..2693a0df0a 100644 --- a/android/app/aidl/android/bluetooth/IBluetoothHeadsetClient.aidl +++ b/android/app/aidl/android/bluetooth/IBluetoothHeadsetClient.aidl @@ -1,5 +1,5 @@ /* - * Copyright 2014 The Android Open Source Project + * Copyright (C) 2014 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. diff --git a/android/app/aidl/android/bluetooth/IBluetoothHearingAid.aidl b/android/app/aidl/android/bluetooth/IBluetoothHearingAid.aidl index 29e5a1f792..e21da24ef0 100644 --- a/android/app/aidl/android/bluetooth/IBluetoothHearingAid.aidl +++ b/android/app/aidl/android/bluetooth/IBluetoothHearingAid.aidl @@ -1,5 +1,5 @@ /* - * Copyright 2018 The Android Open Source Project + * Copyright (C) 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. diff --git a/android/app/aidl/android/bluetooth/IBluetoothHidDevice.aidl b/android/app/aidl/android/bluetooth/IBluetoothHidDevice.aidl index c53d1e63fb..dd82eb5ba1 100644 --- a/android/app/aidl/android/bluetooth/IBluetoothHidDevice.aidl +++ b/android/app/aidl/android/bluetooth/IBluetoothHidDevice.aidl @@ -1,5 +1,5 @@ /* - * Copyright 2016 The Android Open Source Project + * Copyright (C) 2016 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. diff --git a/android/app/aidl/android/bluetooth/IBluetoothHidHost.aidl b/android/app/aidl/android/bluetooth/IBluetoothHidHost.aidl index 69ffdc227a..7d44385b1e 100644 --- a/android/app/aidl/android/bluetooth/IBluetoothHidHost.aidl +++ b/android/app/aidl/android/bluetooth/IBluetoothHidHost.aidl @@ -1,5 +1,5 @@ /* - * Copyright 2012 The Android Open Source Project + * Copyright (C) 2012 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. diff --git a/android/app/aidl/android/bluetooth/IBluetoothLeAudioCallback.aidl b/android/app/aidl/android/bluetooth/IBluetoothLeAudioCallback.aidl index f333405f5e..c1c0480bba 100644 --- a/android/app/aidl/android/bluetooth/IBluetoothLeAudioCallback.aidl +++ b/android/app/aidl/android/bluetooth/IBluetoothLeAudioCallback.aidl @@ -1,5 +1,5 @@ /* - * Copyright 2022 The Android Open Source Project + * Copyright (C) 2022 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. diff --git a/android/app/aidl/android/bluetooth/IBluetoothLeBroadcastAssistant.aidl b/android/app/aidl/android/bluetooth/IBluetoothLeBroadcastAssistant.aidl index 54b947c061..9c00f3b8c2 100644 --- a/android/app/aidl/android/bluetooth/IBluetoothLeBroadcastAssistant.aidl +++ b/android/app/aidl/android/bluetooth/IBluetoothLeBroadcastAssistant.aidl @@ -1,5 +1,5 @@ /* - * Copyright 2022 The Android Open Source Project + * Copyright (C) 2022 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. diff --git a/android/app/aidl/android/bluetooth/IBluetoothLeBroadcastAssistantCallback.aidl b/android/app/aidl/android/bluetooth/IBluetoothLeBroadcastAssistantCallback.aidl index 9a09254c50..eff415a5b5 100644 --- a/android/app/aidl/android/bluetooth/IBluetoothLeBroadcastAssistantCallback.aidl +++ b/android/app/aidl/android/bluetooth/IBluetoothLeBroadcastAssistantCallback.aidl @@ -1,5 +1,5 @@ /* - * Copyright 2022 The Android Open Source Project + * Copyright (C) 2022 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. diff --git a/android/app/aidl/android/bluetooth/IBluetoothLeBroadcastCallback.aidl b/android/app/aidl/android/bluetooth/IBluetoothLeBroadcastCallback.aidl index aa9f3925cc..78289a01bc 100644 --- a/android/app/aidl/android/bluetooth/IBluetoothLeBroadcastCallback.aidl +++ b/android/app/aidl/android/bluetooth/IBluetoothLeBroadcastCallback.aidl @@ -1,5 +1,5 @@ /* - * Copyright 2022 The Android Open Source Project + * Copyright (C) 2022 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. diff --git a/android/app/aidl/android/bluetooth/IBluetoothMap.aidl b/android/app/aidl/android/bluetooth/IBluetoothMap.aidl index 2862005ae2..798f34d08a 100644 --- a/android/app/aidl/android/bluetooth/IBluetoothMap.aidl +++ b/android/app/aidl/android/bluetooth/IBluetoothMap.aidl @@ -1,5 +1,5 @@ /* - * Copyright 2008 The Android Open Source Project + * Copyright (C) 2008 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. diff --git a/android/app/aidl/android/bluetooth/IBluetoothMapClient.aidl b/android/app/aidl/android/bluetooth/IBluetoothMapClient.aidl index a06a7fc0dc..6dba53c4c1 100644 --- a/android/app/aidl/android/bluetooth/IBluetoothMapClient.aidl +++ b/android/app/aidl/android/bluetooth/IBluetoothMapClient.aidl @@ -1,5 +1,5 @@ /* - * Copyright 2016 The Android Open Source Project + * Copyright (C) 2016 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. diff --git a/android/app/aidl/android/bluetooth/IBluetoothMetadataListener.aidl b/android/app/aidl/android/bluetooth/IBluetoothMetadataListener.aidl index e08919fedb..57f6fcb886 100644 --- a/android/app/aidl/android/bluetooth/IBluetoothMetadataListener.aidl +++ b/android/app/aidl/android/bluetooth/IBluetoothMetadataListener.aidl @@ -1,5 +1,5 @@ /* - * Copyright 2019 The Android Open Source Project + * Copyright (C) 2019 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. diff --git a/android/app/aidl/android/bluetooth/IBluetoothOobDataCallback.aidl b/android/app/aidl/android/bluetooth/IBluetoothOobDataCallback.aidl index 00975b6bbe..a2a635fa45 100644 --- a/android/app/aidl/android/bluetooth/IBluetoothOobDataCallback.aidl +++ b/android/app/aidl/android/bluetooth/IBluetoothOobDataCallback.aidl @@ -1,5 +1,5 @@ /* - * Copyright 2021 The Android Open Source Project + * Copyright (C) 2021 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. diff --git a/android/app/aidl/android/bluetooth/IBluetoothPan.aidl b/android/app/aidl/android/bluetooth/IBluetoothPan.aidl index 2d9172fc97..b636e57c1e 100644 --- a/android/app/aidl/android/bluetooth/IBluetoothPan.aidl +++ b/android/app/aidl/android/bluetooth/IBluetoothPan.aidl @@ -1,5 +1,5 @@ /* - * Copyright 2012 The Android Open Source Project + * Copyright (C) 2012 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. diff --git a/android/app/aidl/android/bluetooth/IBluetoothPanCallback.aidl b/android/app/aidl/android/bluetooth/IBluetoothPanCallback.aidl index 898794a227..24886ae529 100644 --- a/android/app/aidl/android/bluetooth/IBluetoothPanCallback.aidl +++ b/android/app/aidl/android/bluetooth/IBluetoothPanCallback.aidl @@ -1,5 +1,5 @@ /* - * Copyright 2012 The Android Open Source Project + * Copyright (C) 2012 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. diff --git a/android/app/aidl/android/bluetooth/IBluetoothPbap.aidl b/android/app/aidl/android/bluetooth/IBluetoothPbap.aidl index 5d4f33431a..0e538b33a9 100644 --- a/android/app/aidl/android/bluetooth/IBluetoothPbap.aidl +++ b/android/app/aidl/android/bluetooth/IBluetoothPbap.aidl @@ -1,5 +1,5 @@ /* - * Copyright 2008 The Android Open Source Project + * Copyright (C) 2008 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. diff --git a/android/app/aidl/android/bluetooth/IBluetoothPbapClient.aidl b/android/app/aidl/android/bluetooth/IBluetoothPbapClient.aidl index 7cc66d08ac..cfc5cb78e0 100644 --- a/android/app/aidl/android/bluetooth/IBluetoothPbapClient.aidl +++ b/android/app/aidl/android/bluetooth/IBluetoothPbapClient.aidl @@ -1,5 +1,5 @@ /* - * Copyright 2016 The Android Open Source Project + * Copyright (C) 2016 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. diff --git a/android/app/aidl/android/bluetooth/IBluetoothPreferredAudioProfilesCallback.aidl b/android/app/aidl/android/bluetooth/IBluetoothPreferredAudioProfilesCallback.aidl index f7ab3ff975..534f54c28c 100644 --- a/android/app/aidl/android/bluetooth/IBluetoothPreferredAudioProfilesCallback.aidl +++ b/android/app/aidl/android/bluetooth/IBluetoothPreferredAudioProfilesCallback.aidl @@ -1,5 +1,5 @@ /* - * Copyright 2023 The Android Open Source Project + * Copyright (C) 2023 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/android/app/aidl/android/bluetooth/IBluetoothProfileServiceConnection.aidl b/android/app/aidl/android/bluetooth/IBluetoothProfileServiceConnection.aidl index 5a048cf7e2..0a10d60c4e 100644 --- a/android/app/aidl/android/bluetooth/IBluetoothProfileServiceConnection.aidl +++ b/android/app/aidl/android/bluetooth/IBluetoothProfileServiceConnection.aidl @@ -1,5 +1,5 @@ /* - * Copyright 2014 The Android Open Source Project + * Copyright (C) 2014 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. diff --git a/android/app/aidl/android/bluetooth/IBluetoothQualityReportReadyCallback.aidl b/android/app/aidl/android/bluetooth/IBluetoothQualityReportReadyCallback.aidl index 7a92a20811..43d3473262 100644 --- a/android/app/aidl/android/bluetooth/IBluetoothQualityReportReadyCallback.aidl +++ b/android/app/aidl/android/bluetooth/IBluetoothQualityReportReadyCallback.aidl @@ -1,5 +1,5 @@ /* - * Copyright 2023 The Android Open Source Project + * Copyright (C) 2023 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/android/app/aidl/android/bluetooth/IBluetoothSap.aidl b/android/app/aidl/android/bluetooth/IBluetoothSap.aidl index 94641bf4d5..019d66df0c 100644 --- a/android/app/aidl/android/bluetooth/IBluetoothSap.aidl +++ b/android/app/aidl/android/bluetooth/IBluetoothSap.aidl @@ -1,5 +1,5 @@ /* - * Copyright 2013 The Android Open Source Project + * Copyright (C) 2013 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. diff --git a/android/app/aidl/android/bluetooth/IBluetoothVolumeControlCallback.aidl b/android/app/aidl/android/bluetooth/IBluetoothVolumeControlCallback.aidl index e067989739..e5239b4b8b 100644 --- a/android/app/aidl/android/bluetooth/IBluetoothVolumeControlCallback.aidl +++ b/android/app/aidl/android/bluetooth/IBluetoothVolumeControlCallback.aidl @@ -1,5 +1,5 @@ /* - * Copyright 2022 The Android Open Source Project + * Copyright (C) 2022 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. diff --git a/android/app/aidl/android/bluetooth/IDistanceMeasurement.aidl b/android/app/aidl/android/bluetooth/IDistanceMeasurement.aidl index 78c793a351..ead28c8ebd 100644 --- a/android/app/aidl/android/bluetooth/IDistanceMeasurement.aidl +++ b/android/app/aidl/android/bluetooth/IDistanceMeasurement.aidl @@ -1,5 +1,5 @@ /* - * Copyright 2025 The Android Open Source Project + * Copyright (C) 2025 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/android/app/aidl/android/bluetooth/OobData.aidl b/android/app/aidl/android/bluetooth/OobData.aidl index 529e0b0a42..d831c64776 100644 --- a/android/app/aidl/android/bluetooth/OobData.aidl +++ b/android/app/aidl/android/bluetooth/OobData.aidl @@ -1,5 +1,5 @@ /* - * Copyright 2016 The Android Open Source Project + * Copyright (C) 2016 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. diff --git a/android/app/aidl/android/bluetooth/le/AdvertiseData.aidl b/android/app/aidl/android/bluetooth/le/AdvertiseData.aidl index 713635d5ce..bcbf2243e1 100644 --- a/android/app/aidl/android/bluetooth/le/AdvertiseData.aidl +++ b/android/app/aidl/android/bluetooth/le/AdvertiseData.aidl @@ -1,5 +1,5 @@ /* - * Copyright 2014 The Android Open Source Project + * Copyright (C) 2014 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. diff --git a/android/app/aidl/android/bluetooth/le/AdvertiseSettings.aidl b/android/app/aidl/android/bluetooth/le/AdvertiseSettings.aidl index 3677e752e6..9f47d74ca5 100644 --- a/android/app/aidl/android/bluetooth/le/AdvertiseSettings.aidl +++ b/android/app/aidl/android/bluetooth/le/AdvertiseSettings.aidl @@ -1,5 +1,5 @@ /* - * Copyright 2014 The Android Open Source Project + * Copyright (C) 2014 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. diff --git a/android/app/aidl/android/bluetooth/le/AdvertisingSetParameters.aidl b/android/app/aidl/android/bluetooth/le/AdvertisingSetParameters.aidl index 3918864bd1..39034a001f 100644 --- a/android/app/aidl/android/bluetooth/le/AdvertisingSetParameters.aidl +++ b/android/app/aidl/android/bluetooth/le/AdvertisingSetParameters.aidl @@ -1,5 +1,5 @@ /* - * Copyright 2017 The Android Open Source Project + * Copyright (C) 2017 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. diff --git a/android/app/aidl/android/bluetooth/le/DistanceMeasurementMethod.aidl b/android/app/aidl/android/bluetooth/le/DistanceMeasurementMethod.aidl index ee341d30a0..08612dad3f 100644 --- a/android/app/aidl/android/bluetooth/le/DistanceMeasurementMethod.aidl +++ b/android/app/aidl/android/bluetooth/le/DistanceMeasurementMethod.aidl @@ -1,5 +1,5 @@ /* - * Copyright 2022 The Android Open Source Project + * Copyright (C) 2022 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. diff --git a/android/app/aidl/android/bluetooth/le/DistanceMeasurementParams.aidl b/android/app/aidl/android/bluetooth/le/DistanceMeasurementParams.aidl index be0eba3606..19ec0c0379 100644 --- a/android/app/aidl/android/bluetooth/le/DistanceMeasurementParams.aidl +++ b/android/app/aidl/android/bluetooth/le/DistanceMeasurementParams.aidl @@ -1,5 +1,5 @@ /* - * Copyright 2022 The Android Open Source Project + * Copyright (C) 2022 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. diff --git a/android/app/aidl/android/bluetooth/le/DistanceMeasurementResult.aidl b/android/app/aidl/android/bluetooth/le/DistanceMeasurementResult.aidl index eb4b0c84fa..dc4cfd9cda 100644 --- a/android/app/aidl/android/bluetooth/le/DistanceMeasurementResult.aidl +++ b/android/app/aidl/android/bluetooth/le/DistanceMeasurementResult.aidl @@ -1,5 +1,5 @@ /* - * Copyright 2022 The Android Open Source Project + * Copyright (C) 2022 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. diff --git a/android/app/aidl/android/bluetooth/le/IAdvertisingSetCallback.aidl b/android/app/aidl/android/bluetooth/le/IAdvertisingSetCallback.aidl index 449b173309..b5d492905e 100644 --- a/android/app/aidl/android/bluetooth/le/IAdvertisingSetCallback.aidl +++ b/android/app/aidl/android/bluetooth/le/IAdvertisingSetCallback.aidl @@ -1,5 +1,5 @@ /* - * Copyright 2017 The Android Open Source Project + * Copyright (C) 2017 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. diff --git a/android/app/aidl/android/bluetooth/le/IDistanceMeasurementCallback.aidl b/android/app/aidl/android/bluetooth/le/IDistanceMeasurementCallback.aidl index 19f4ba72e5..518b0be4a6 100644 --- a/android/app/aidl/android/bluetooth/le/IDistanceMeasurementCallback.aidl +++ b/android/app/aidl/android/bluetooth/le/IDistanceMeasurementCallback.aidl @@ -1,5 +1,5 @@ /* - * Copyright 2022 The Android Open Source Project + * Copyright (C) 2022 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. diff --git a/android/app/aidl/android/bluetooth/le/IPeriodicAdvertisingCallback.aidl b/android/app/aidl/android/bluetooth/le/IPeriodicAdvertisingCallback.aidl index 579ec086b7..b70b03f392 100644 --- a/android/app/aidl/android/bluetooth/le/IPeriodicAdvertisingCallback.aidl +++ b/android/app/aidl/android/bluetooth/le/IPeriodicAdvertisingCallback.aidl @@ -1,5 +1,5 @@ /* - * Copyright 2017 The Android Open Source Project + * Copyright (C) 2017 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. diff --git a/android/app/aidl/android/bluetooth/le/IScannerCallback.aidl b/android/app/aidl/android/bluetooth/le/IScannerCallback.aidl index 025e7ffbba..8cbbaef41a 100644 --- a/android/app/aidl/android/bluetooth/le/IScannerCallback.aidl +++ b/android/app/aidl/android/bluetooth/le/IScannerCallback.aidl @@ -1,5 +1,5 @@ /* - * Copyright 2016 The Android Open Source Project + * Copyright (C) 2016 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. diff --git a/android/app/aidl/android/bluetooth/le/PeriodicAdvertisingParameters.aidl b/android/app/aidl/android/bluetooth/le/PeriodicAdvertisingParameters.aidl index 3f714f0813..f4bea22a12 100644 --- a/android/app/aidl/android/bluetooth/le/PeriodicAdvertisingParameters.aidl +++ b/android/app/aidl/android/bluetooth/le/PeriodicAdvertisingParameters.aidl @@ -1,5 +1,5 @@ /* - * Copyright 2017 The Android Open Source Project + * Copyright (C) 2017 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. diff --git a/android/app/aidl/android/bluetooth/le/PeriodicAdvertisingReport.aidl b/android/app/aidl/android/bluetooth/le/PeriodicAdvertisingReport.aidl index 986ac6165c..547d09611f 100644 --- a/android/app/aidl/android/bluetooth/le/PeriodicAdvertisingReport.aidl +++ b/android/app/aidl/android/bluetooth/le/PeriodicAdvertisingReport.aidl @@ -1,5 +1,5 @@ /* - * Copyright 2017 The Android Open Source Project + * Copyright (C) 2017 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. diff --git a/android/app/aidl/android/bluetooth/le/ResultStorageDescriptor.aidl b/android/app/aidl/android/bluetooth/le/ResultStorageDescriptor.aidl index afc1b41fdf..f218a01a5d 100644 --- a/android/app/aidl/android/bluetooth/le/ResultStorageDescriptor.aidl +++ b/android/app/aidl/android/bluetooth/le/ResultStorageDescriptor.aidl @@ -1,5 +1,5 @@ /* - * Copyright 2014 The Android Open Source Project + * Copyright (C) 2014 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. diff --git a/android/app/aidl/android/bluetooth/le/ScanFilter.aidl b/android/app/aidl/android/bluetooth/le/ScanFilter.aidl index e3ebd857f4..4cecfe62e1 100644 --- a/android/app/aidl/android/bluetooth/le/ScanFilter.aidl +++ b/android/app/aidl/android/bluetooth/le/ScanFilter.aidl @@ -1,5 +1,5 @@ /* - * Copyright 2014 The Android Open Source Project + * Copyright (C) 2014 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. diff --git a/android/app/aidl/android/bluetooth/le/ScanResult.aidl b/android/app/aidl/android/bluetooth/le/ScanResult.aidl index f16dc18d43..39430350da 100644 --- a/android/app/aidl/android/bluetooth/le/ScanResult.aidl +++ b/android/app/aidl/android/bluetooth/le/ScanResult.aidl @@ -1,5 +1,5 @@ /* - * Copyright 2014 The Android Open Source Project + * Copyright (C) 2014 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. diff --git a/android/app/aidl/android/bluetooth/le/ScanSettings.aidl b/android/app/aidl/android/bluetooth/le/ScanSettings.aidl index e84e078ed0..eb169c1209 100644 --- a/android/app/aidl/android/bluetooth/le/ScanSettings.aidl +++ b/android/app/aidl/android/bluetooth/le/ScanSettings.aidl @@ -1,5 +1,5 @@ /* - * Copyright 2014 The Android Open Source Project + * Copyright (C) 2014 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. diff --git a/android/app/jni/com_android_bluetooth_BluetoothHciVendorSpecific.cpp b/android/app/jni/com_android_bluetooth_BluetoothHciVendorSpecific.cpp index 96c15300af..75cf1efea8 100644 --- a/android/app/jni/com_android_bluetooth_BluetoothHciVendorSpecific.cpp +++ b/android/app/jni/com_android_bluetooth_BluetoothHciVendorSpecific.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2024 The Android Open Source Project + * Copyright (C) 2024 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. diff --git a/android/app/jni/com_android_bluetooth_BluetoothQualityReport.cpp b/android/app/jni/com_android_bluetooth_BluetoothQualityReport.cpp index b59bc9116f..8a225555b1 100644 --- a/android/app/jni/com_android_bluetooth_BluetoothQualityReport.cpp +++ b/android/app/jni/com_android_bluetooth_BluetoothQualityReport.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2023 The Android Open Source Project + * Copyright (C) 2023 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. 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/jni/com_android_bluetooth_btservice_BluetoothKeystore.cpp b/android/app/jni/com_android_bluetooth_btservice_BluetoothKeystore.cpp index 5151bbff2f..b95ccf202d 100644 --- a/android/app/jni/com_android_bluetooth_btservice_BluetoothKeystore.cpp +++ b/android/app/jni/com_android_bluetooth_btservice_BluetoothKeystore.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2020 The Android Open Source Project + * Copyright (C) 2020 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. diff --git a/android/app/jni/com_android_bluetooth_gatt.cpp b/android/app/jni/com_android_bluetooth_gatt.cpp index 85ba34bf9d..acd609f8bd 100644 --- a/android/app/jni/com_android_bluetooth_gatt.cpp +++ b/android/app/jni/com_android_bluetooth_gatt.cpp @@ -141,7 +141,6 @@ static jmethodID method_onDisconnected; static jmethodID method_onReadCharacteristic; static jmethodID method_onWriteCharacteristic; static jmethodID method_onExecuteCompleted; -static jmethodID method_onSearchCompleted; static jmethodID method_onReadDescriptor; static jmethodID method_onWriteDescriptor; static jmethodID method_onNotify; @@ -279,16 +278,6 @@ static void btgattc_close_cb(int conn_id, int status, int clientIf, const RawAdd address.get()); } -static void btgattc_search_complete_cb(int conn_id, int status) { - std::shared_lock<std::shared_mutex> lock(callbacks_mutex); - CallbackEnv sCallbackEnv(__func__); - if (!sCallbackEnv.valid() || !mCallbacksObj) { - return; - } - - sCallbackEnv->CallVoidMethod(mCallbacksObj, method_onSearchCompleted, conn_id, status); -} - static void btgattc_register_for_notification_cb(int conn_id, int registered, int status, uint16_t handle) { std::shared_lock<std::shared_mutex> lock(callbacks_mutex); @@ -562,7 +551,6 @@ static const btgatt_client_callbacks_t sGattClientCallbacks = { btgattc_register_app_cb, btgattc_open_cb, btgattc_close_cb, - btgattc_search_complete_cb, btgattc_register_for_notification_cb, btgattc_notify_cb, btgattc_read_characteristic_cb, @@ -1415,14 +1403,6 @@ static void gattClientDiscoverServiceByUuidNative(JNIEnv* /* env */, jobject /* sGattIf->client->btif_gattc_discover_service_by_uuid(conn_id, uuid); } -static void gattClientGetGattDbNative(JNIEnv* /* env */, jobject /* object */, jint conn_id) { - if (!sGattIf) { - return; - } - - sGattIf->client->get_gatt_db(conn_id); -} - static void gattClientReadCharacteristicNative(JNIEnv* /* env */, jobject /* object */, jint conn_id, jint handle, jint authReq) { if (!sGattIf) { @@ -1565,40 +1545,40 @@ static void gattClientScanFilterParamAddNative(JNIEnv* env, jobject /* object */ jmethodID methodId = 0; ScopedLocalRef<jclass> filtparam(env, env->GetObjectClass(params)); - methodId = env->GetMethodID(filtparam.get(), "getClientIf", "()I"); + methodId = env->GetMethodID(filtparam.get(), "clientInterface", "()I"); uint8_t client_if = env->CallIntMethod(params, methodId); - methodId = env->GetMethodID(filtparam.get(), "getFiltIndex", "()I"); + methodId = env->GetMethodID(filtparam.get(), "filterIndex", "()I"); uint8_t filt_index = env->CallIntMethod(params, methodId); - methodId = env->GetMethodID(filtparam.get(), "getFeatSeln", "()I"); + methodId = env->GetMethodID(filtparam.get(), "featureSelection", "()I"); filt_params->feat_seln = env->CallIntMethod(params, methodId); - methodId = env->GetMethodID(filtparam.get(), "getListLogicType", "()I"); + methodId = env->GetMethodID(filtparam.get(), "listLogicType", "()I"); filt_params->list_logic_type = env->CallIntMethod(params, methodId); - methodId = env->GetMethodID(filtparam.get(), "getFiltLogicType", "()I"); + methodId = env->GetMethodID(filtparam.get(), "filterLogicType", "()I"); filt_params->filt_logic_type = env->CallIntMethod(params, methodId); - methodId = env->GetMethodID(filtparam.get(), "getDelyMode", "()I"); + methodId = env->GetMethodID(filtparam.get(), "delayMode", "()I"); filt_params->dely_mode = env->CallIntMethod(params, methodId); - methodId = env->GetMethodID(filtparam.get(), "getFoundTimeout", "()I"); + methodId = env->GetMethodID(filtparam.get(), "foundTimeout", "()I"); filt_params->found_timeout = env->CallIntMethod(params, methodId); - methodId = env->GetMethodID(filtparam.get(), "getLostTimeout", "()I"); + methodId = env->GetMethodID(filtparam.get(), "lostTimeout", "()I"); filt_params->lost_timeout = env->CallIntMethod(params, methodId); - methodId = env->GetMethodID(filtparam.get(), "getFoundTimeOutCnt", "()I"); + methodId = env->GetMethodID(filtparam.get(), "foundTimeoutCount", "()I"); filt_params->found_timeout_cnt = env->CallIntMethod(params, methodId); - methodId = env->GetMethodID(filtparam.get(), "getNumOfTrackEntries", "()I"); + methodId = env->GetMethodID(filtparam.get(), "numberOfTrackEntries", "()I"); filt_params->num_of_tracking_entries = env->CallIntMethod(params, methodId); - methodId = env->GetMethodID(filtparam.get(), "getRSSIHighValue", "()I"); + methodId = env->GetMethodID(filtparam.get(), "rssiHighValue", "()I"); filt_params->rssi_high_thres = env->CallIntMethod(params, methodId); - methodId = env->GetMethodID(filtparam.get(), "getRSSILowValue", "()I"); + methodId = env->GetMethodID(filtparam.get(), "rssiLowValue", "()I"); filt_params->rssi_low_thres = env->CallIntMethod(params, methodId); sScanner->ScanFilterParamSetup(client_if, add_scan_filter_params_action, filt_index, @@ -2958,7 +2938,6 @@ static int register_com_android_bluetooth_gatt_(JNIEnv* env) { {"gattClientSearchServiceNative", "(IZJJ)V", (void*)gattClientSearchServiceNative}, {"gattClientDiscoverServiceByUuidNative", "(IJJ)V", (void*)gattClientDiscoverServiceByUuidNative}, - {"gattClientGetGattDbNative", "(I)V", (void*)gattClientGetGattDbNative}, {"gattClientReadCharacteristicNative", "(III)V", (void*)gattClientReadCharacteristicNative}, {"gattClientReadUsingCharacteristicUuidNative", "(IJJIII)V", @@ -3008,7 +2987,6 @@ static int register_com_android_bluetooth_gatt_(JNIEnv* env) { {"onReadCharacteristic", "(III[B)V", &method_onReadCharacteristic}, {"onWriteCharacteristic", "(III[B)V", &method_onWriteCharacteristic}, {"onExecuteCompleted", "(II)V", &method_onExecuteCompleted}, - {"onSearchCompleted", "(II)V", &method_onSearchCompleted}, {"onReadDescriptor", "(III[B)V", &method_onReadDescriptor}, {"onWriteDescriptor", "(III[B)V", &method_onWriteDescriptor}, {"onNotify", "(ILjava/lang/String;IZ[B)V", &method_onNotify}, diff --git a/android/app/jni/com_android_bluetooth_hearing_aid.cpp b/android/app/jni/com_android_bluetooth_hearing_aid.cpp index dbe2439ed4..312961db41 100644 --- a/android/app/jni/com_android_bluetooth_hearing_aid.cpp +++ b/android/app/jni/com_android_bluetooth_hearing_aid.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2018 The Android Open Source Project + * Copyright (C) 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. diff --git a/android/app/lib-lint-baseline.xml b/android/app/lib-lint-baseline.xml index c2a527c3fc..ac5565be67 100644 --- a/android/app/lib-lint-baseline.xml +++ b/android/app/lib-lint-baseline.xml @@ -2,17 +2,6 @@ <issues format="6" by="lint 8.4.0-alpha08" type="baseline" client="" dependencies="true" name="" variant="all" version="8.4.0-alpha08"> <issue - id="UnknownIssueId" - message="Unknown issue id "GetterSetterNullability"" - errorLine1=" <issue id='GetterSetterNullability' severity='error' />" - errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> - <location - file="./out/lint.xml" - line="125" - column="3"/> - </issue> - - <issue id="GestureBackNavigation" message="If intercepting back events, this should be handled through the registration of callbacks on the window level; Please see https://developer.android.com/about/versions/13/features/predictive-back-gesture" errorLine1=" if (keyCode == KeyEvent.KEYCODE_BACK) {" @@ -68,332 +57,13 @@ </issue> <issue - id="DefaultLocale" - message="Implicitly using the default locale is a common source of bugs: Use `String.format(Locale, ...)` instead" - errorLine1=" String.format(" - errorLine2=" ^"> - <location - file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/avrcp/AvrcpVolumeManager.java" - line="460" - column="25"/> - </issue> - - <issue - id="DefaultLocale" - message="Implicitly using the default locale is a common source of bugs: Use `String.format(Locale, ...)` instead" - errorLine1=" offsetString = String.format("%1$02d", -(offset));" - errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> - <location - file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/map/BluetoothMapSmsPdu.java" - line="403" - column="32"/> - </issue> - - <issue - id="DefaultLocale" - message="Implicitly using the default locale is a common source of bugs: Use `String.format(Locale, ...)` instead" - errorLine1=" offsetString = String.format("%1$02d", offset);" - errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> - <location - file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/map/BluetoothMapSmsPdu.java" - line="407" - column="32"/> - </issue> - - <issue - id="DefaultLocale" - message="Implicitly using the default locale is a common source of bugs: Use `String.format(Locale, ...)` instead" - errorLine1=" return String.format(" - errorLine2=" ^"> - <location - file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/mapclient/MapClientContent.java" - line="911" - column="20"/> - </issue> - - <issue - id="SimpleDateFormat" - message="To get local formatting use `getDateInstance()`, `getDateTimeInstance()`, or `getTimeInstance()`, or use `new SimpleDateFormat(String template, Locale locale)` with for example `Locale.US` for ASCII dates." - errorLine1=" ThreadLocal.withInitial(() -> new SimpleDateFormat("MM-dd HH:mm:ss"));" - errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> - <location - file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/le_scan/AppScanStats.java" - line="53" - column="43"/> - </issue> - - <issue - id="SimpleDateFormat" - message="To get local formatting use `getDateInstance()`, `getDateTimeInstance()`, or `getTimeInstance()`, or use `new SimpleDateFormat(String template, Locale locale)` with for example `Locale.US` for ASCII dates." - errorLine1=" SimpleDateFormat format = new SimpleDateFormat("yyyyMMdd'T'HHmmss");" - errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> - <location - file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/map/BluetoothMapAppParams.java" - line="1228" - column="35"/> - </issue> - - <issue - id="SimpleDateFormat" - message="To get local formatting use `getDateInstance()`, `getDateTimeInstance()`, or `getTimeInstance()`, or use `new SimpleDateFormat(String template, Locale locale)` with for example `Locale.US` for ASCII dates." - errorLine1=" SimpleDateFormat format = new SimpleDateFormat("yyyyMMdd'T'HHmmss");" - errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> - <location - file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/map/BluetoothMapAppParams.java" - line="1239" - column="35"/> - </issue> - - <issue - id="SimpleDateFormat" - message="To get local formatting use `getDateInstance()`, `getDateTimeInstance()`, or `getTimeInstance()`, or use `new SimpleDateFormat(String template, Locale locale)` with for example `Locale.US` for ASCII dates." - errorLine1=" SimpleDateFormat format = new SimpleDateFormat("yyyyMMdd'T'HHmmss");" - errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> - <location - file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/map/BluetoothMapAppParams.java" - line="1250" - column="35"/> - </issue> - - <issue - id="SimpleDateFormat" - message="To get local formatting use `getDateInstance()`, `getDateTimeInstance()`, or `getTimeInstance()`, or use `new SimpleDateFormat(String template, Locale locale)` with for example `Locale.US` for ASCII dates." - errorLine1=" SimpleDateFormat format = new SimpleDateFormat("yyyyMMdd'T'HHmmss");" - errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> - <location - file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/map/BluetoothMapAppParams.java" - line="1261" - column="35"/> - </issue> - - <issue - id="SimpleDateFormat" - message="To get local formatting use `getDateInstance()`, `getDateTimeInstance()`, or `getTimeInstance()`, or use `new SimpleDateFormat(String template, Locale locale)` with for example `Locale.US` for ASCII dates." - errorLine1=" SimpleDateFormat format = new SimpleDateFormat("yyyyMMdd'T'HHmmss");" - errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> - <location - file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/map/BluetoothMapAppParams.java" - line="1276" - column="35"/> - </issue> - - <issue - id="SimpleDateFormat" - message="To get local formatting use `getDateInstance()`, `getDateTimeInstance()`, or `getTimeInstance()`, or use `new SimpleDateFormat(String template, Locale locale)` with for example `Locale.US` for ASCII dates." - errorLine1=" SimpleDateFormat format = new SimpleDateFormat("yyyyMMdd'T'HHmmss");" - errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> - <location - file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/map/BluetoothMapAppParams.java" - line="1287" - column="35"/> - </issue> - - <issue - id="SimpleDateFormat" - message="To get local formatting use `getDateInstance()`, `getDateTimeInstance()`, or `getTimeInstance()`, or use `new SimpleDateFormat(String template, Locale locale)` with for example `Locale.US` for ASCII dates." - errorLine1=" SimpleDateFormat format = new SimpleDateFormat("yyyyMMdd'T'HHmmss");" - errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> - <location - file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/map/BluetoothMapAppParams.java" - line="1294" - column="35"/> - </issue> - - <issue - id="SimpleDateFormat" - message="To get local formatting use `getDateInstance()`, `getDateTimeInstance()`, or `getTimeInstance()`, or use `new SimpleDateFormat(String template, Locale locale)` with for example `Locale.US` for ASCII dates." - errorLine1=" SimpleDateFormat format = new SimpleDateFormat("yyyyMMdd'T'HHmmss");" - errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> - <location - file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/map/BluetoothMapAppParams.java" - line="1305" - column="35"/> - </issue> - - <issue - id="SimpleDateFormat" - message="To get local formatting use `getDateInstance()`, `getDateTimeInstance()`, or `getTimeInstance()`, or use `new SimpleDateFormat(String template, Locale locale)` with for example `Locale.US` for ASCII dates." - errorLine1=" SimpleDateFormat format = new SimpleDateFormat("yyyyMMdd'T'HHmmssZ");" - errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> - <location - file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/map/BluetoothMapAppParams.java" - line="1510" - column="35"/> - </issue> - - <issue - id="SimpleDateFormat" - message="To get local formatting use `getDateInstance()`, `getDateTimeInstance()`, or `getTimeInstance()`, or use `new SimpleDateFormat(String template, Locale locale)` with for example `Locale.US` for ASCII dates." - errorLine1=" SimpleDateFormat format = new SimpleDateFormat("yyyyMMdd'T'HHmmssZ");" - errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> - <location - file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/map/BluetoothMapAppParams.java" - line="1521" - column="35"/> - </issue> - - <issue - id="SimpleDateFormat" - message="To get local formatting use `getDateInstance()`, `getDateTimeInstance()`, or `getTimeInstance()`, or use `new SimpleDateFormat(String template, Locale locale)` with for example `Locale.US` for ASCII dates." - errorLine1=" SimpleDateFormat format = new SimpleDateFormat("yyyyMMdd'T'HHmmssZ");" - errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> - <location - file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/map/BluetoothMapAppParams.java" - line="1758" - column="35"/> - </issue> - - <issue - id="SimpleDateFormat" - message="To get local formatting use `getDateInstance()`, `getDateTimeInstance()`, or `getTimeInstance()`, or use `new SimpleDateFormat(String template, Locale locale)` with for example `Locale.US` for ASCII dates." - errorLine1=" SimpleDateFormat format = new SimpleDateFormat("yyyyMMdd'T'HHmmssZ");" - errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> - <location - file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/map/BluetoothMapAppParams.java" - line="1769" - column="35"/> - </issue> - - <issue - id="SimpleDateFormat" - message="To get local formatting use `getDateInstance()`, `getDateTimeInstance()`, or `getTimeInstance()`, or use `new SimpleDateFormat(String template, Locale locale)` with for example `Locale.US` for ASCII dates." - errorLine1=" SimpleDateFormat format = new SimpleDateFormat("yyyyMMdd'T'HHmmss");" - errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> - <location - file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/map/BluetoothMapConvoContactElement.java" - line="161" - column="35"/> - </issue> - - <issue - id="SimpleDateFormat" - message="To get local formatting use `getDateInstance()`, `getDateTimeInstance()`, or `getTimeInstance()`, or use `new SimpleDateFormat(String template, Locale locale)` with for example `Locale.US` for ASCII dates." - errorLine1=" SimpleDateFormat format = new SimpleDateFormat("yyyyMMdd'T'HHmmss");" - errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> - <location - file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/map/BluetoothMapConvoContactElement.java" - line="172" - column="35"/> - </issue> - - <issue - id="SimpleDateFormat" - message="To get local formatting use `getDateInstance()`, `getDateTimeInstance()`, or `getTimeInstance()`, or use `new SimpleDateFormat(String template, Locale locale)` with for example `Locale.US` for ASCII dates." - errorLine1=" SimpleDateFormat format = new SimpleDateFormat("yyyyMMdd'T'HHmmss");" - errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> - <location - file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/map/BluetoothMapConvoListingElement.java" - line="149" - column="35"/> - </issue> - - <issue - id="SimpleDateFormat" - message="To get local formatting use `getDateInstance()`, `getDateTimeInstance()`, or `getTimeInstance()`, or use `new SimpleDateFormat(String template, Locale locale)` with for example `Locale.US` for ASCII dates." - errorLine1=" SimpleDateFormat format = new SimpleDateFormat("yyyyMMdd'T'HHmmss");" - errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> - <location - file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/map/BluetoothMapConvoListingElement.java" - line="162" - column="35"/> - </issue> - - <issue - id="SimpleDateFormat" - message="To get local formatting use `getDateInstance()`, `getDateTimeInstance()`, or `getTimeInstance()`, or use `new SimpleDateFormat(String template, Locale locale)` with for example `Locale.US` for ASCII dates." - errorLine1=" SimpleDateFormat format = new SimpleDateFormat("yyyyMMdd'T'HHmmss");" - errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> - <location - file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/map/BluetoothMapMessageListingElement.java" - line="81" - column="35"/> - </issue> - - <issue - id="SimpleDateFormat" - message="To get local formatting use `getDateInstance()`, `getDateTimeInstance()`, or `getTimeInstance()`, or use `new SimpleDateFormat(String template, Locale locale)` with for example `Locale.US` for ASCII dates." - errorLine1=" SimpleDateFormat format = new SimpleDateFormat("yyMMddHHmmss");" - errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> - <location - file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/map/BluetoothMapSmsPdu.java" - line="385" - column="39"/> - </issue> - - <issue - id="SimpleDateFormat" - message="To get local formatting use `getDateInstance()`, `getDateTimeInstance()`, or `getTimeInstance()`, or use `new SimpleDateFormat(String template, Locale locale)` with for example `Locale.US` for ASCII dates." - errorLine1=" ? new SimpleDateFormat("yyyyMMdd'T'HHmmssZ")" - errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> - <location - file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/map/BluetoothMapUtils.java" - line="740" - column="27"/> - </issue> - - <issue - id="SimpleDateFormat" - message="To get local formatting use `getDateInstance()`, `getDateTimeInstance()`, or `getTimeInstance()`, or use `new SimpleDateFormat(String template, Locale locale)` with for example `Locale.US` for ASCII dates." - errorLine1=" : new SimpleDateFormat("yyyyMMdd'T'HHmmss");" - errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> - <location - file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/map/BluetoothMapUtils.java" - line="741" - column="27"/> - </issue> - - <issue - id="SimpleDateFormat" - message="To get local formatting use `getDateInstance()`, `getDateTimeInstance()`, or `getTimeInstance()`, or use `new SimpleDateFormat(String template, Locale locale)` with for example `Locale.US` for ASCII dates." - errorLine1=" DateFormat dateFormat = new SimpleDateFormat("_hhmmss");" - errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> - <location - file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/opp/BluetoothOppReceiveFileInfo.java" - line="167" - column="33"/> - </issue> - - <issue - id="SimpleDateFormat" - message="To get local formatting use `getDateInstance()`, `getDateTimeInstance()`, or `getTimeInstance()`, or use `new SimpleDateFormat(String template, Locale locale)` with for example `Locale.US` for ASCII dates." - errorLine1=" SimpleDateFormat df = new SimpleDateFormat(RFC_2455_FORMAT);" - errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> - <location - file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/pbap/BluetoothPbapCallLogComposer.java" - line="226" - column="31"/> - </issue> - - <issue - id="SimpleDateFormat" - message="To get local formatting use `getDateInstance()`, `getDateTimeInstance()`, or `getTimeInstance()`, or use `new SimpleDateFormat(String template, Locale locale)` with for example `Locale.US` for ASCII dates." - errorLine1=" SimpleDateFormat parser = new SimpleDateFormat(TIMESTAMP_FORMAT);" - errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> - <location - file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/pbapclient/obex/CallLogPullRequest.java" - line="109" - column="43"/> - </issue> - - <issue - id="SimpleDateFormat" - message="To get local formatting use `getDateInstance()`, `getDateTimeInstance()`, or `getTimeInstance()`, or use `new SimpleDateFormat(String template, Locale locale)` with for example `Locale.US` for ASCII dates." - errorLine1=" SimpleDateFormat parser = new SimpleDateFormat(TIMESTAMP_FORMAT);" - errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> - <location - file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/pbapclient/PbapClientContactsStorage.java" - line="508" - column="35"/> - </issue> - - <issue id="GuardedLogInvocation" message="Do not guard log invocations with if blocks using log enforcement variables or isLoggable(). The Log framework does this check for you. Remove the surrounding if block and call to log completely unguarded" errorLine1=" if (Log.isLoggable(TAG, Log.DEBUG)) {" errorLine2=" ^"> <location file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/a2dp/A2dpStateMachine.java" - line="679" + line="677" column="9"/> </issue> @@ -404,7 +74,7 @@ errorLine2=" ^"> <location file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/a2dp/A2dpStateMachine.java" - line="679" + line="677" column="9"/> </issue> @@ -415,7 +85,7 @@ errorLine2=" ^"> <location file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/a2dp/A2dpStateMachine.java" - line="679" + line="677" column="9"/> </issue> @@ -426,7 +96,7 @@ errorLine2=" ^"> <location file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/map/BluetoothMapService.java" - line="807" + line="805" column="9"/> </issue> @@ -437,7 +107,7 @@ errorLine2=" ^"> <location file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/map/BluetoothMapService.java" - line="807" + line="805" column="9"/> </issue> @@ -448,7 +118,7 @@ errorLine2=" ^"> <location file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/map/BluetoothMapService.java" - line="807" + line="805" column="9"/> </issue> @@ -459,7 +129,7 @@ errorLine2=" ^"> <location file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/map/BluetoothMapService.java" - line="807" + line="805" column="9"/> </issue> @@ -547,7 +217,7 @@ errorLine2=" ~~~~"> <location file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/opp/BluetoothOppTransferActivity.java" - line="240" + line="239" column="69"/> </issue> @@ -565,154 +235,11 @@ <issue id="VisibleForTests" message="This method should only be accessed from tests or within private scope" - errorLine1=" return mDatabaseManager.getA2dpSupportsOptionalCodecs(device);" - errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> - <location - file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/a2dp/A2dpService.java" - line="802" - column="33"/> - </issue> - - <issue - id="VisibleForTests" - message="This method should only be accessed from tests or within private scope" - errorLine1=" mDatabaseManager.setA2dpSupportsOptionalCodecs(device, value);" - errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> - <location - file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/a2dp/A2dpService.java" - line="810" - column="26"/> - </issue> - - <issue - id="VisibleForTests" - message="This method should only be accessed from tests or within private scope" - errorLine1=" return mDatabaseManager.getA2dpOptionalCodecsEnabled(device);" - errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> - <location - file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/a2dp/A2dpService.java" - line="823" - column="33"/> - </issue> - - <issue - id="VisibleForTests" - message="This method should only be accessed from tests or within private scope" - errorLine1=" mDatabaseManager.setA2dpOptionalCodecsEnabled(device, value);" - errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> - <location - file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/a2dp/A2dpService.java" - line="843" - column="26"/> - </issue> - - <issue - id="VisibleForTests" - message="This method should only be accessed from tests or within private scope" - errorLine1=" sm.sendMessage(A2dpStateMachine.MESSAGE_STACK_EVENT, stackEvent);" - errorLine2=" ~~~~~~~~~~~~~~~~~~~"> - <location - file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/a2dp/A2dpService.java" - line="918" - column="45"/> - </issue> - - <issue - id="VisibleForTests" - message="This method should only be accessed from tests or within private scope" - errorLine1=" Config.setProfileEnabled(BluetoothProfile.LE_AUDIO_BROADCAST, false);" - errorLine2=" ~~~~~~~~~~~~~~~~~"> - <location - file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/btservice/AdapterService.java" - line="1149" - column="20"/> - </issue> - - <issue - id="VisibleForTests" - message="This method should only be accessed from tests or within private scope" - errorLine1=" Config.setProfileEnabled(profileId, false);" - errorLine2=" ~~~~~~~~~~~~~~~~~"> - <location - file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/btservice/AdapterService.java" - line="1154" - column="20"/> - </issue> - - <issue - id="VisibleForTests" - message="This method should only be accessed from tests or within private scope" - errorLine1=" mMapService = BluetoothMapService.getBluetoothMapService();" - errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~"> - <location - file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/btservice/AdapterService.java" - line="1996" - column="43"/> - </issue> - - <issue - id="VisibleForTests" - message="This method should only be accessed from tests or within private scope" - errorLine1=" mPbapService = BluetoothPbapService.getBluetoothPbapService();" - errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~"> - <location - file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/btservice/AdapterService.java" - line="2001" - column="45"/> - </issue> - - <issue - id="VisibleForTests" - message="This method should only be accessed from tests or within private scope" - errorLine1=" mSapService = SapService.getSapService();" - errorLine2=" ~~~~~~~~~~~~~"> - <location - file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/btservice/AdapterService.java" - line="2005" - column="34"/> - </issue> - - <issue - id="VisibleForTests" - message="This method should only be accessed from tests or within private scope" - errorLine1=" return mDatabaseManager.setCustomMeta(device, key, value);" - errorLine2=" ~~~~~~~~~~~~~"> - <location - file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/btservice/AdapterService.java" - line="2237" - column="33"/> - </issue> - - <issue - id="VisibleForTests" - message="This method should only be accessed from tests or within private scope" - errorLine1=" mRemoteDevices.resetBatteryLevel(device, isBas);" - errorLine2=" ~~~~~~~~~~~~~~~~~"> - <location - file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/btservice/AdapterService.java" - line="7293" - column="28"/> - </issue> - - <issue - id="VisibleForTests" - message="This method should only be accessed from tests or within private scope" - errorLine1=" mRemoteDevices.updateBatteryLevel(device, batteryLevel, isBas);" - errorLine2=" ~~~~~~~~~~~~~~~~~~"> - <location - file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/btservice/AdapterService.java" - line="7295" - column="28"/> - </issue> - - <issue - id="VisibleForTests" - message="This method should only be accessed from tests or within private scope" errorLine1=" mNativeInterface.atResponseCode(device, atCommandResult, atCommandErrorCode);" errorLine2=" ~~~~~~~~~~~~~~"> <location file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfp/AtPhonebook.java" - line="182" + line="187" column="38"/> </issue> @@ -723,7 +250,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~"> <location file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfp/AtPhonebook.java" - line="203" + line="208" column="30"/> </issue> @@ -734,7 +261,7 @@ errorLine2=" ~~~~~~~~~~~~~~"> <location file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfp/AtPhonebook.java" - line="205" + line="210" column="26"/> </issue> @@ -745,7 +272,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~"> <location file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfp/AtPhonebook.java" - line="274" + line="279" column="30"/> </issue> @@ -756,7 +283,7 @@ errorLine2=" ~~~~~~~~~~~~~~"> <location file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfp/AtPhonebook.java" - line="276" + line="281" column="26"/> </issue> @@ -767,7 +294,7 @@ errorLine2=" ~~~~~~~~~~~~~~"> <location file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfp/AtPhonebook.java" - line="299" + line="304" column="42"/> </issue> @@ -778,7 +305,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~"> <location file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfp/AtPhonebook.java" - line="314" + line="319" column="34"/> </issue> @@ -789,7 +316,7 @@ errorLine2=" ~~~~~~~~~~~~~~"> <location file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfp/AtPhonebook.java" - line="315" + line="320" column="34"/> </issue> @@ -800,7 +327,7 @@ errorLine2=" ~~~~~~~~~~~~~~"> <location file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfp/AtPhonebook.java" - line="326" + line="331" column="38"/> </issue> @@ -811,7 +338,7 @@ errorLine2=" ~~~~~~~~~~~~~~"> <location file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfp/AtPhonebook.java" - line="334" + line="339" column="38"/> </issue> @@ -822,7 +349,7 @@ errorLine2=" ~~~~~~~~~~~~~~"> <location file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfp/AtPhonebook.java" - line="354" + line="359" column="38"/> </issue> @@ -833,7 +360,7 @@ errorLine2=" ~~~~~~~~~~~~~~"> <location file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfp/AtPhonebook.java" - line="367" + line="372" column="38"/> </issue> @@ -844,7 +371,7 @@ errorLine2=" ~~~~~~~~~~~~~~"> <location file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfp/AtPhonebook.java" - line="373" + line="378" column="38"/> </issue> @@ -855,7 +382,7 @@ errorLine2=" ~~~~~~~~~~~~~~"> <location file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfp/AtPhonebook.java" - line="387" + line="392" column="34"/> </issue> @@ -866,7 +393,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~"> <location file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfp/AtPhonebook.java" - line="640" + line="645" column="30"/> </issue> @@ -1016,66 +543,11 @@ <issue id="VisibleForTests" message="This method should only be accessed from tests or within private scope" - errorLine1=" BluetoothMapService.getBluetoothMapService()" - errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~"> - <location - file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/map/BluetoothMapContent.java" - line="1261" - column="49"/> - </issue> - - <issue - id="VisibleForTests" - message="This method should only be accessed from tests or within private scope" - errorLine1=" BluetoothMapService.getBluetoothMapService()" - errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~"> - <location - file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/map/BluetoothMapMessageListing.java" - line="104" - column="49"/> - </issue> - - <issue - id="VisibleForTests" - message="This method should only be accessed from tests or within private scope" - errorLine1=" BluetoothMapService.getBluetoothMapService().getRemoteDevice().getAddress()," - errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~"> - <location - file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/map/BluetoothMapMessageListing.java" - line="153" - column="45"/> - </issue> - - <issue - id="VisibleForTests" - message="This method should only be accessed from tests or within private scope" - errorLine1=" BluetoothMapService.getBluetoothMapService().getRemoteDevice().getAddress()," - errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~"> - <location - file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/map/BluetoothMapMessageListingElement.java" - line="276" - column="41"/> - </issue> - - <issue - id="VisibleForTests" - message="This method should only be accessed from tests or within private scope" - errorLine1=" BluetoothMapService.getBluetoothMapService().getRemoteDevice().getAddress();" - errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~"> - <location - file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/map/BluetoothMapbMessageSms.java" - line="93" - column="41"/> - </issue> - - <issue - id="VisibleForTests" - message="This method should only be accessed from tests or within private scope" errorLine1=" mRemoteDevices.addDeviceProperties(address);" errorLine2=" ~~~~~~~~~~~~~~~~~~~"> <location file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/btservice/BondStateMachine.java" - line="656" + line="657" column="28"/> </issue> @@ -1086,7 +558,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~"> <location file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/btservice/BondStateMachine.java" - line="693" + line="694" column="28"/> </issue> @@ -1097,7 +569,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~"> <location file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/btservice/BondStateMachine.java" - line="723" + line="724" column="28"/> </issue> @@ -1108,7 +580,7 @@ errorLine2=" ~~~~~~~~~~~"> <location file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/csip/CsipSetCoordinatorService.java" - line="855" + line="860" column="63"/> </issue> @@ -1119,7 +591,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~"> <location file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hap/HapClientService.java" - line="157" + line="162" column="16"/> </issue> @@ -1130,7 +602,7 @@ errorLine2=" ~~~~~~~~~~"> <location file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfpclient/HeadsetClientService.java" - line="105" + line="111" column="26"/> </issue> @@ -1141,7 +613,7 @@ errorLine2=" ~~~~~~~"> <location file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfpclient/HeadsetClientService.java" - line="177" + line="183" column="26"/> </issue> @@ -1152,7 +624,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~"> <location file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfpclient/HeadsetClientStateMachine.java" - line="418" + line="423" column="26"/> </issue> @@ -1163,7 +635,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~"> <location file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfpclient/HeadsetClientStateMachine.java" - line="671" + line="676" column="30"/> </issue> @@ -1174,7 +646,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~"> <location file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfpclient/HeadsetClientStateMachine.java" - line="712" + line="717" column="30"/> </issue> @@ -1185,7 +657,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~"> <location file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfpclient/HeadsetClientStateMachine.java" - line="737" + line="742" column="30"/> </issue> @@ -1196,7 +668,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~"> <location file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfpclient/HeadsetClientStateMachine.java" - line="760" + line="765" column="34"/> </issue> @@ -1207,7 +679,7 @@ errorLine2=" ~~~~~~~~~~"> <location file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfpclient/HeadsetClientStateMachine.java" - line="1008" + line="1013" column="30"/> </issue> @@ -1218,7 +690,7 @@ errorLine2=" ~~~~~~~"> <location file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfpclient/HeadsetClientStateMachine.java" - line="1098" + line="1095" column="43"/> </issue> @@ -1229,7 +701,7 @@ errorLine2=" ~~~~~~~~~~"> <location file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfpclient/HeadsetClientStateMachine.java" - line="1152" + line="1146" column="42"/> </issue> @@ -1240,7 +712,7 @@ errorLine2=" ~~~~~~~~~~"> <location file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfpclient/HeadsetClientStateMachine.java" - line="1316" + line="1304" column="42"/> </issue> @@ -1251,7 +723,7 @@ errorLine2=" ~~~~~~~~~"> <location file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfpclient/HeadsetClientStateMachine.java" - line="1324" + line="1312" column="46"/> </issue> @@ -1262,7 +734,7 @@ errorLine2=" ~~~~~~~"> <location file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfpclient/HeadsetClientStateMachine.java" - line="1435" + line="1413" column="38"/> </issue> @@ -1273,7 +745,7 @@ errorLine2=" ~~~~~~~~~~"> <location file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfpclient/HeadsetClientStateMachine.java" - line="1443" + line="1421" column="47"/> </issue> @@ -1284,7 +756,7 @@ errorLine2=" ~~~~~~~~~~"> <location file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfpclient/HeadsetClientStateMachine.java" - line="1447" + line="1425" column="50"/> </issue> @@ -1295,7 +767,7 @@ errorLine2=" ~~~~~~~~~~~~"> <location file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfpclient/HeadsetClientStateMachine.java" - line="1453" + line="1431" column="43"/> </issue> @@ -1306,7 +778,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~"> <location file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfpclient/HeadsetClientStateMachine.java" - line="1473" + line="1451" column="46"/> </issue> @@ -1317,7 +789,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> <location file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfpclient/HeadsetClientStateMachine.java" - line="1483" + line="1461" column="46"/> </issue> @@ -1328,7 +800,7 @@ errorLine2=" ~~~~~~~~~"> <location file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfpclient/HeadsetClientStateMachine.java" - line="1505" + line="1483" column="46"/> </issue> @@ -1339,7 +811,7 @@ errorLine2=" ~~~~~~~~~"> <location file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfpclient/HeadsetClientStateMachine.java" - line="1526" + line="1504" column="46"/> </issue> @@ -1350,7 +822,7 @@ errorLine2=" ~~~~"> <location file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfpclient/HeadsetClientStateMachine.java" - line="1537" + line="1515" column="42"/> </issue> @@ -1361,7 +833,7 @@ errorLine2=" ~~~~~~~~"> <location file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfpclient/HeadsetClientStateMachine.java" - line="1568" + line="1546" column="42"/> </issue> @@ -1372,7 +844,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~"> <location file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfpclient/HeadsetClientStateMachine.java" - line="1575" + line="1553" column="42"/> </issue> @@ -1383,7 +855,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~"> <location file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfpclient/HeadsetClientStateMachine.java" - line="1641" + line="1619" column="54"/> </issue> @@ -1394,7 +866,7 @@ errorLine2=" ~~~~~~~~~~~~~"> <location file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfpclient/HeadsetClientStateMachine.java" - line="2544" + line="2519" column="31"/> </issue> @@ -1405,7 +877,7 @@ errorLine2=" ~~~~~~~~~~~~~"> <location file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfpclient/HeadsetClientStateMachine.java" - line="2554" + line="2529" column="31"/> </issue> @@ -1427,7 +899,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~"> <location file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfp/HeadsetService.java" - line="273" + line="277" column="38"/> </issue> @@ -1438,7 +910,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~"> <location file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfp/HeadsetService.java" - line="275" + line="279" column="42"/> </issue> @@ -1449,7 +921,7 @@ errorLine2=" ~~~~~~~"> <location file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfp/HeadsetService.java" - line="288" + line="292" column="26"/> </issue> @@ -1460,18 +932,18 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> <location file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfp/HeadsetService.java" - line="436" + line="440" column="42"/> </issue> <issue id="VisibleForTests" message="This method should only be accessed from tests or within private scope" - errorLine1=" if (stateMachine.getConnectionState() != BluetoothProfile.STATE_DISCONNECTED) {" + errorLine1=" if (stateMachine.getConnectionState() != STATE_DISCONNECTED) {" errorLine2=" ~~~~~~~~~~~~~~~~~~"> <location file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfp/HeadsetService.java" - line="508" + line="512" column="30"/> </issue> @@ -1482,7 +954,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~"> <location file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfp/HeadsetService.java" - line="866" + line="870" column="48"/> </issue> @@ -1493,18 +965,18 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~"> <location file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfp/HeadsetService.java" - line="914" + line="917" column="48"/> </issue> <issue id="VisibleForTests" message="This method should only be accessed from tests or within private scope" - errorLine1=" if (stateMachine.getConnectionState() == BluetoothProfile.STATE_CONNECTED) {" + errorLine1=" if (stateMachine.getConnectionState() == STATE_CONNECTED) {" errorLine2=" ~~~~~~~~~~~~~~~~~~"> <location file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfp/HeadsetService.java" - line="934" + line="936" column="34"/> </issue> @@ -1515,7 +987,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~"> <location file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfp/HeadsetService.java" - line="982" + line="984" column="33"/> </issue> @@ -1526,7 +998,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~"> <location file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfp/HeadsetService.java" - line="1096" + line="1098" column="38"/> </issue> @@ -1537,7 +1009,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~"> <location file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfp/HeadsetService.java" - line="1098" + line="1100" column="42"/> </issue> @@ -1548,7 +1020,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~"> <location file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfp/HeadsetService.java" - line="1114" + line="1116" column="48"/> </issue> @@ -1559,7 +1031,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~"> <location file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfp/HeadsetService.java" - line="1188" + line="1200" column="48"/> </issue> @@ -1570,7 +1042,7 @@ errorLine2=" ~~~~~~~~~~~~~"> <location file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfp/HeadsetService.java" - line="1243" + line="1265" column="26"/> </issue> @@ -1581,7 +1053,7 @@ errorLine2=" ~~~~~~~~~~~~~~~"> <location file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfp/HeadsetService.java" - line="1379" + line="1401" column="30"/> </issue> @@ -1592,7 +1064,7 @@ errorLine2=" ~~~~~~~~~~~~~~~"> <location file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfp/HeadsetService.java" - line="1422" + line="1444" column="35"/> </issue> @@ -1603,7 +1075,7 @@ errorLine2=" ~~~~~~~~~"> <location file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfp/HeadsetService.java" - line="1433" + line="1455" column="65"/> </issue> @@ -1614,7 +1086,7 @@ errorLine2=" ~~~~~~~~~~~~~~~"> <location file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfp/HeadsetService.java" - line="1451" + line="1473" column="38"/> </issue> @@ -1625,18 +1097,18 @@ errorLine2=" ~~~~~~~~~~~~~~~"> <location file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfp/HeadsetService.java" - line="1490" + line="1512" column="42"/> </issue> <issue id="VisibleForTests" message="This method should only be accessed from tests or within private scope" - errorLine1=" if (stateMachine.getConnectionState() != BluetoothProfile.STATE_CONNECTED) {" + errorLine1=" if (stateMachine.getConnectionState() != STATE_CONNECTED) {" errorLine2=" ~~~~~~~~~~~~~~~~~~"> <location file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfp/HeadsetService.java" - line="1549" + line="1571" column="30"/> </issue> @@ -1647,7 +1119,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~"> <location file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfp/HeadsetService.java" - line="1784" + line="1831" column="38"/> </issue> @@ -1658,7 +1130,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~"> <location file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfp/HeadsetService.java" - line="1786" + line="1833" column="42"/> </issue> @@ -1669,7 +1141,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~"> <location file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfp/HeadsetService.java" - line="1868" + line="1920" column="35"/> </issue> @@ -1680,7 +1152,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~"> <location file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfp/HeadsetService.java" - line="1881" + line="1933" column="35"/> </issue> @@ -1691,7 +1163,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~"> <location file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfp/HeadsetService.java" - line="1882" + line="1934" column="34"/> </issue> @@ -1702,7 +1174,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~"> <location file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfp/HeadsetService.java" - line="1909" + line="1966" column="38"/> </issue> @@ -1713,7 +1185,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~"> <location file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfp/HeadsetService.java" - line="1911" + line="1968" column="42"/> </issue> @@ -1724,7 +1196,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~"> <location file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfp/HeadsetService.java" - line="1932" + line="1989" column="35"/> </issue> @@ -1735,7 +1207,7 @@ errorLine2=" ~~~~~~~~~~"> <location file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfp/HeadsetService.java" - line="1984" + line="2046" column="65"/> </issue> @@ -1746,7 +1218,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> <location file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfp/HeadsetService.java" - line="1985" + line="2047" column="38"/> </issue> @@ -1757,7 +1229,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> <location file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfp/HeadsetService.java" - line="1986" + line="2048" column="38"/> </issue> @@ -1768,7 +1240,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> <location file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfp/HeadsetService.java" - line="1987" + line="2049" column="38"/> </issue> @@ -1779,7 +1251,7 @@ errorLine2=" ~~~~~~~~~~"> <location file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfp/HeadsetService.java" - line="1991" + line="2058" column="50"/> </issue> @@ -1790,7 +1262,7 @@ errorLine2=" ~~~~~~~~~~"> <location file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfp/HeadsetService.java" - line="2009" + line="2076" column="49"/> </issue> @@ -1801,7 +1273,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~"> <location file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfp/HeadsetService.java" - line="2078" + line="2149" column="48"/> </issue> @@ -1812,7 +1284,7 @@ errorLine2=" ~~~~~~~~~~"> <location file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfp/HeadsetService.java" - line="2226" + line="2294" column="86"/> </issue> @@ -1823,7 +1295,7 @@ errorLine2=" ~~~~~~~~~~"> <location file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfp/HeadsetService.java" - line="2234" + line="2302" column="52"/> </issue> @@ -1834,7 +1306,7 @@ errorLine2=" ~~~~~~~~~"> <location file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfp/HeadsetService.java" - line="2263" + line="2331" column="38"/> </issue> @@ -1845,7 +1317,7 @@ errorLine2=" ~~~~~~~~~~~"> <location file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfp/HeadsetService.java" - line="2493" + line="2561" column="56"/> </issue> @@ -1856,7 +1328,7 @@ errorLine2=" ~~~~~~~~~"> <location file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfp/HeadsetService.java" - line="2562" + line="2630" column="48"/> </issue> @@ -1867,40 +1339,18 @@ errorLine2=" ~~~~~~~~~"> <location file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfp/HeadsetService.java" - line="2641" + line="2709" column="83"/> </issue> <issue id="VisibleForTests" message="This method should only be accessed from tests or within private scope" - errorLine1=" mDatabaseManager.getAudioPolicyMetadata(device);" - errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~"> - <location - file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfp/HeadsetStateMachine.java" - line="208" - column="34"/> - </issue> - - <issue - id="VisibleForTests" - message="This method should only be accessed from tests or within private scope" - errorLine1=" mDatabaseManager.setAudioPolicyMetadata(device, mHsClientAudioPolicy);" - errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~"> - <location - file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfp/HeadsetStateMachine.java" - line="212" - column="30"/> - </issue> - - <issue - id="VisibleForTests" - message="This method should only be accessed from tests or within private scope" errorLine1=" mHeadsetService.onConnectionStateChangedFromStateMachine(device, fromState, toState);" errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> <location file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfp/HeadsetStateMachine.java" - line="347" + line="352" column="29"/> </issue> @@ -1911,7 +1361,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> <location file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfp/HeadsetStateMachine.java" - line="372" + line="377" column="29"/> </issue> @@ -1922,7 +1372,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~"> <location file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfp/HeadsetStateMachine.java" - line="527" + line="532" column="39"/> </issue> @@ -1933,7 +1383,7 @@ errorLine2=" ~~~~~~~~~~"> <location file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfp/HeadsetStateMachine.java" - line="588" + line="604" column="43"/> </issue> @@ -1944,7 +1394,7 @@ errorLine2=" ~~~~~~~~~~~~~"> <location file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfp/HeadsetStateMachine.java" - line="663" + line="684" column="47"/> </issue> @@ -1955,7 +1405,7 @@ errorLine2=" ~~~~~~~~~~"> <location file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfp/HeadsetStateMachine.java" - line="845" + line="871" column="46"/> </issue> @@ -1966,7 +1416,7 @@ errorLine2=" ~~~~~~~~~~"> <location file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfp/HeadsetStateMachine.java" - line="849" + line="875" column="46"/> </issue> @@ -1977,7 +1427,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~"> <location file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfp/HeadsetStateMachine.java" - line="1021" + line="1047" column="47"/> </issue> @@ -1988,7 +1438,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> <location file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfp/HeadsetStateMachine.java" - line="1037" + line="1063" column="47"/> </issue> @@ -1999,7 +1449,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~"> <location file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfp/HeadsetStateMachine.java" - line="1047" + line="1073" column="43"/> </issue> @@ -2010,7 +1460,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~"> <location file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfp/HeadsetStateMachine.java" - line="1060" + line="1086" column="38"/> </issue> @@ -2021,7 +1471,7 @@ errorLine2=" ~~~~~~~~~~~~"> <location file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfp/HeadsetStateMachine.java" - line="1073" + line="1099" column="42"/> </issue> @@ -2032,7 +1482,7 @@ errorLine2=" ~~~~~~~~"> <location file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfp/HeadsetStateMachine.java" - line="1081" + line="1107" column="38"/> </issue> @@ -2043,7 +1493,7 @@ errorLine2=" ~~~~~~~~~~~~~~"> <location file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfp/HeadsetStateMachine.java" - line="1093" + line="1119" column="42"/> </issue> @@ -2054,7 +1504,7 @@ errorLine2=" ~~~~~~~~~~~~~~"> <location file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfp/HeadsetStateMachine.java" - line="1113" + line="1139" column="46"/> </issue> @@ -2065,7 +1515,7 @@ errorLine2=" ~~~~~~~~~~"> <location file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfp/HeadsetStateMachine.java" - line="1147" + line="1173" column="46"/> </issue> @@ -2076,7 +1526,7 @@ errorLine2=" ~~~~~~~~~~"> <location file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfp/HeadsetStateMachine.java" - line="1150" + line="1176" column="46"/> </issue> @@ -2087,7 +1537,7 @@ errorLine2=" ~~~~~~~~~"> <location file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfp/HeadsetStateMachine.java" - line="1253" + line="1279" column="34"/> </issue> @@ -2098,7 +1548,7 @@ errorLine2=" ~~~~~~~~~~~~~~~"> <location file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfp/HeadsetStateMachine.java" - line="1274" + line="1300" column="34"/> </issue> @@ -2109,7 +1559,7 @@ errorLine2=" ~~~~~~~~~~~~~"> <location file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfp/HeadsetStateMachine.java" - line="1307" + line="1342" column="47"/> </issue> @@ -2120,7 +1570,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~"> <location file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfp/HeadsetStateMachine.java" - line="1334" + line="1366" column="53"/> </issue> @@ -2131,7 +1581,7 @@ errorLine2=" ~~~~~~~~~~~~"> <location file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfp/HeadsetStateMachine.java" - line="1345" + line="1377" column="43"/> </issue> @@ -2142,7 +1592,7 @@ errorLine2=" ~~~~~~~~~~~~~~~"> <location file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfp/HeadsetStateMachine.java" - line="1377" + line="1409" column="47"/> </issue> @@ -2153,7 +1603,7 @@ errorLine2=" ~~~~~~~~~~~~~~~"> <location file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfp/HeadsetStateMachine.java" - line="1393" + line="1425" column="47"/> </issue> @@ -2164,7 +1614,7 @@ errorLine2=" ~~~~~~~~~~~~~~~"> <location file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfp/HeadsetStateMachine.java" - line="1581" + line="1618" column="47"/> </issue> @@ -2175,7 +1625,7 @@ errorLine2=" ~~~~~~~~~~~~~~~"> <location file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfp/HeadsetStateMachine.java" - line="1611" + line="1648" column="46"/> </issue> @@ -2186,7 +1636,7 @@ errorLine2=" ~~~~~~~~~~~~~~"> <location file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfp/HeadsetStateMachine.java" - line="1923" + line="1960" column="30"/> </issue> @@ -2197,7 +1647,7 @@ errorLine2=" ~~~~~~~~~~~~~~"> <location file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfp/HeadsetStateMachine.java" - line="1930" + line="1967" column="34"/> </issue> @@ -2208,7 +1658,7 @@ errorLine2=" ~~~~~~~~~~~~~~"> <location file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfp/HeadsetStateMachine.java" - line="1938" + line="1975" column="34"/> </issue> @@ -2219,7 +1669,7 @@ errorLine2=" ~~~~~~~~~~~~~~"> <location file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfp/HeadsetStateMachine.java" - line="1945" + line="1982" column="34"/> </issue> @@ -2230,7 +1680,7 @@ errorLine2=" ~~~~~~~~~~~~~~"> <location file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfp/HeadsetStateMachine.java" - line="1957" + line="1994" column="30"/> </issue> @@ -2241,7 +1691,7 @@ errorLine2=" ~~~~~~~~~~~~~~"> <location file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfp/HeadsetStateMachine.java" - line="1966" + line="2003" column="34"/> </issue> @@ -2252,7 +1702,7 @@ errorLine2=" ~~~~~~~~~~~~~~"> <location file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfp/HeadsetStateMachine.java" - line="1970" + line="2007" column="34"/> </issue> @@ -2263,7 +1713,7 @@ errorLine2=" ~~~~~~~~~~~~~~"> <location file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfp/HeadsetStateMachine.java" - line="1972" + line="2009" column="34"/> </issue> @@ -2274,7 +1724,7 @@ errorLine2=" ~~~~~~~~~~~~~~"> <location file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfp/HeadsetStateMachine.java" - line="1975" + line="2012" column="30"/> </issue> @@ -2285,7 +1735,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> <location file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfp/HeadsetStateMachine.java" - line="2103" + line="2140" column="63"/> </issue> @@ -2296,7 +1746,7 @@ errorLine2=" ~~~~~~~~~~~~"> <location file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfp/HeadsetStateMachine.java" - line="2141" + line="2178" column="26"/> </issue> @@ -2307,18 +1757,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~"> <location file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfp/HeadsetStateMachine.java" - line="2406" - column="26"/> - </issue> - - <issue - id="VisibleForTests" - message="This method should only be accessed from tests or within private scope" - errorLine1=" mDatabaseManager.setAudioPolicyMetadata(mDevice, policies);" - errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~"> - <location - file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfp/HeadsetStateMachine.java" - line="2467" + line="2443" column="26"/> </issue> @@ -2329,7 +1768,7 @@ errorLine2=" ~~~~~~~~~"> <location file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfp/HeadsetStateMachine.java" - line="2584" + line="2621" column="30"/> </issue> @@ -2340,7 +1779,7 @@ errorLine2=" ~~~~~~~~~~"> <location file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfp/HeadsetStateMachine.java" - line="2585" + line="2622" column="30"/> </issue> @@ -2351,7 +1790,7 @@ errorLine2=" ~~~~~~~~~~"> <location file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfp/HeadsetStateMachine.java" - line="2593" + line="2630" column="34"/> </issue> @@ -2362,7 +1801,7 @@ errorLine2=" ~~~~~~~~~~~~~~~"> <location file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfp/HeadsetStateMachine.java" - line="2596" + line="2633" column="35"/> </issue> @@ -2373,7 +1812,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~"> <location file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfp/HeadsetStateMachine.java" - line="2723" + line="2765" column="26"/> </issue> @@ -2384,7 +1823,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~"> <location file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hfp/HeadsetStateMachine.java" - line="2723" + line="2765" column="49"/> </issue> @@ -2395,7 +1834,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~"> <location file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hearingaid/HearingAidService.java" - line="624" + line="626" column="51"/> </issue> @@ -2439,7 +1878,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~"> <location file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/le_audio/LeAudioService.java" - line="204" + line="207" column="5"/> </issue> @@ -2450,7 +1889,7 @@ errorLine2=" ~~~~~"> <location file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/le_audio/LeAudioService.java" - line="593" + line="607" column="29"/> </issue> @@ -2461,7 +1900,7 @@ errorLine2=" ~~~~"> <location file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/le_audio/LeAudioService.java" - line="683" + line="695" column="29"/> </issue> @@ -2472,7 +1911,7 @@ errorLine2=" ~~~~~~~~~~~"> <location file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/le_audio/LeAudioService.java" - line="2775" + line="2796" column="52"/> </issue> @@ -2483,7 +1922,7 @@ errorLine2=" ~~~~~~~~~~~"> <location file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/le_audio/LeAudioService.java" - line="3516" + line="3545" column="52"/> </issue> @@ -2494,7 +1933,7 @@ errorLine2=" ~~~~~~~~~"> <location file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/le_audio/LeAudioService.java" - line="4765" + line="4759" column="29"/> </issue> @@ -2505,7 +1944,7 @@ errorLine2=" ~~~~~~~~~~~~~"> <location file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/mapclient/MceStateMachine.java" - line="287" + line="289" column="22"/> </issue> @@ -2516,7 +1955,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~"> <location file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/pan/PanNativeInterface.java" - line="61" + line="65" column="21"/> </issue> @@ -2527,7 +1966,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~"> <location file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/btservice/PhonePolicy.java" - line="196" + line="198" column="34"/> </issue> @@ -2538,7 +1977,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~"> <location file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/btservice/PhonePolicy.java" - line="201" + line="203" column="33"/> </issue> @@ -2549,7 +1988,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~"> <location file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/btservice/PhonePolicy.java" - line="586" + line="588" column="37"/> </issue> @@ -2560,7 +1999,7 @@ errorLine2=" ~~~~~~~~~~~~~~"> <location file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/btservice/SilenceDeviceManager.java" - line="249" + line="238" column="25"/> </issue> @@ -2571,7 +2010,7 @@ errorLine2=" ~~~~~~~~~~~~~~"> <location file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/btservice/SilenceDeviceManager.java" - line="253" + line="242" column="28"/> </issue> @@ -2582,7 +2021,7 @@ errorLine2=" ~~~~~~~~~"> <location file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/tbs/TbsGeneric.java" - line="175" + line="177" column="48"/> </issue> @@ -2598,24 +2037,13 @@ </issue> <issue - id="ExportedContentProvider" - message="Exported content providers can provide access to potentially sensitive data" - errorLine1=" <provider android:process="@string/process" android:name="com.android.bluetooth.avrcpcontroller.AvrcpCoverArtProvider" android:authorities="com.android.bluetooth.avrcpcontroller.AvrcpCoverArtProvider" android:enabled="false" android:grantUriPermissions="true" android:exported="true">" - errorLine2=" ~~~~~~~~"> - <location - file="./out/soong/.intermediates/packages/modules/Bluetooth/android/app/BluetoothLib/android_common_apex35/manifest_fixer/AndroidManifest.xml" - line="98" - column="10"/> - </issue> - - <issue id="ExportedReceiver" message="Exported receiver does not require permission" errorLine1=" <receiver android:process="@string/process" android:name="com.android.bluetooth.opp.BluetoothOppReceiver" android:exported="true" android:enabled="false">" errorLine2=" ~~~~~~~~"> <location - file="./out/soong/.intermediates/packages/modules/Bluetooth/android/app/BluetoothLib/android_common_apex35/manifest_fixer/AndroidManifest.xml" - line="125" + file="./out/soong/.intermediates/packages/modules/Bluetooth/android/app/BluetoothLib/android_common_apex36/manifest_fixer/AndroidManifest.xml" + line="40" column="10"/> </issue> @@ -2625,8 +2053,8 @@ errorLine1=" <service android:process="@string/process" android:name="com.android.bluetooth.avrcpcontroller.BluetoothMediaBrowserService" android:enabled="true" android:exported="true" android:label="@string/a2dp_sink_mbs_label">" errorLine2=" ~~~~~~~"> <location - file="./out/soong/.intermediates/packages/modules/Bluetooth/android/app/BluetoothLib/android_common_apex35/manifest_fixer/AndroidManifest.xml" - line="92" + file="./out/soong/.intermediates/packages/modules/Bluetooth/android/app/BluetoothLib/android_common_apex36/manifest_fixer/AndroidManifest.xml" + line="17" column="10"/> </issue> @@ -2636,63 +2064,41 @@ errorLine1=" <service android:process="@string/process" android:name="com.android.bluetooth.pbapclient.PbapClientAccountAuthenticatorService" android:enabled="false" android:exported="true">" errorLine2=" ~~~~~~~"> <location - file="./out/soong/.intermediates/packages/modules/Bluetooth/android/app/BluetoothLib/android_common_apex35/manifest_fixer/AndroidManifest.xml" - line="200" + file="./out/soong/.intermediates/packages/modules/Bluetooth/android/app/BluetoothLib/android_common_apex36/manifest_fixer/AndroidManifest.xml" + line="113" column="10"/> </issue> <issue - id="InvalidPermission" - message="Protecting an unsupported element with a permission is a no-op and potentially dangerous" - errorLine1=" <path-permission android:pathPrefix="/btopp" android:permission="android.permission.ACCESS_BLUETOOTH_SHARE"/>" - errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> - <location - file="./out/soong/.intermediates/packages/modules/Bluetooth/android/app/BluetoothLib/android_common_apex35/manifest_fixer/AndroidManifest.xml" - line="123" - column="58"/> - </issue> - - <issue id="ExpiredTargetSdkVersion" message="Google Play requires that apps target API level 33 or higher." errorLine1=" <uses-sdk android:minSdkVersion="33" android:targetSdkVersion="16"/>" errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> <location - file="./out/soong/.intermediates/packages/modules/Bluetooth/android/app/BluetoothLib/android_common_apex35/manifest_fixer/AndroidManifest.xml" - line="74" + file="./out/soong/.intermediates/packages/modules/Bluetooth/android/app/BluetoothLib/android_common_apex36/manifest_fixer/AndroidManifest.xml" + line="3" column="42"/> </issue> <issue - id="QueryAllPackagesPermission" - message="A `<queries>` declaration should generally be used instead of QUERY_ALL_PACKAGES; see https://g.co/dev/packagevisibility for details" - errorLine1=" <uses-permission android:name="android.permission.QUERY_ALL_PACKAGES"/>" - errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> - <location - file="./out/soong/.intermediates/packages/modules/Bluetooth/android/app/BluetoothLib/android_common_apex35/manifest_fixer/AndroidManifest.xml" - line="47" - column="22"/> - </issue> - - <issue id="Wakelock" message="The `release()` call is not always reached (can exit the method via path acquire() → d() → removeMessages() → sendMessageDelayed() → obtainMessage() → break → exit; use try/finally to ensure `release` is always called)" errorLine1=" mWakeLock.release();" errorLine2=" ~~~~~~~"> <location file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/map/BluetoothMapService.java" - line="467" + line="470" column="35"/> </issue> <issue id="Wakelock" - message="The `release()` call is not always reached (because of a possible exception in the path acquire() → try → sleep() → if → ! → then → connect() → = → loop → if → ! → then → doSend() → exit; use try/finally to ensure `release` is always called)" + message="The `release()` call is not always reached (because of a possible exception in the path acquire() → try → sleep() → if → ! → then → connect() → loop → if → ! → then → doSend() → exit; use try/finally to ensure `release` is always called)" errorLine1=" mWakeLock.release();" errorLine2=" ~~~~~~~"> <location file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/opp/BluetoothOppObexClientSession.java" - line="201" + line="196" column="27"/> </issue> @@ -2703,7 +2109,7 @@ errorLine2=" ~~~~~~~"> <location file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/pbap/BluetoothPbapService.java" - line="574" + line="580" column="35"/> </issue> @@ -2714,7 +2120,7 @@ errorLine2=" ~~~~~~~"> <location file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/sap/SapService.java" - line="511" + line="515" column="43"/> </issue> @@ -2725,7 +2131,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~"> <location file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/btservice/AdapterService.java" - line="6561" + line="6457" column="17"/> </issue> @@ -2736,7 +2142,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~"> <location file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/map/BluetoothMapService.java" - line="273" + line="276" column="13"/> </issue> @@ -2747,7 +2153,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~"> <location file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/map/BluetoothMapService.java" - line="456" + line="459" column="25"/> </issue> @@ -2758,7 +2164,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~"> <location file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/opp/BluetoothOppObexClientSession.java" - line="162" + line="158" column="13"/> </issue> @@ -2769,7 +2175,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~"> <location file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/opp/BluetoothOppObexServerSession.java" - line="310" + line="307" column="13"/> </issue> @@ -2780,7 +2186,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~"> <location file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/pbap/BluetoothPbapService.java" - line="558" + line="564" column="25"/> </issue> @@ -2791,7 +2197,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~"> <location file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/sap/SapService.java" - line="302" + line="306" column="13"/> </issue> @@ -2802,7 +2208,7 @@ errorLine2=" ~~~~~~~~~~~~~~~~~~~"> <location file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/sap/SapService.java" - line="500" + line="504" column="33"/> </issue> @@ -2813,18 +2219,40 @@ errorLine2="~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> <location file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/btservice/AdapterSuspend.java" - line="36" + line="37" column="1"/> </issue> <issue id="ObsoleteSdkInt" + message="Unnecessary; SDK_INT is always >= 35" + errorLine1=" @RequiresApi(Build.VERSION_CODES.VANILLA_ICE_CREAM)" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> + <location + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/BluetoothMethodProxy.java" + line="304" + column="5"/> + </issue> + + <issue + id="ObsoleteSdkInt" + message="Unnecessary; SDK_INT is always >= 35" + errorLine1=" @RequiresApi(Build.VERSION_CODES.VANILLA_ICE_CREAM)" + errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> + <location + file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/opp/BluetoothOppLauncherActivity.java" + line="337" + column="5"/> + </issue> + + <issue + id="ObsoleteSdkInt" message="Unnecessary; SDK_INT is always >= 34" errorLine1=" @RequiresApi(Build.VERSION_CODES.UPSIDE_DOWN_CAKE)" errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> <location file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/btservice/MetricsLogger.java" - line="628" + line="585" column="5"/> </issue> @@ -2835,7 +2263,7 @@ errorLine2=" ^"> <location file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/btservice/AdapterService.java" - line="755" + line="746" column="9"/> </issue> @@ -2912,7 +2340,7 @@ errorLine2=" ^"> <location file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/opp/BluetoothOppNotification.java" - line="230" + line="228" column="13"/> </issue> @@ -2945,7 +2373,7 @@ errorLine2=" ^"> <location file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/hid/HidHostService.java" - line="335" + line="331" column="13"/> </issue> @@ -2956,7 +2384,7 @@ errorLine2=" ^"> <location file="packages/modules/Bluetooth/android/app/src/com/android/bluetooth/sap/SapService.java" - line="462" + line="466" column="13"/> </issue> @@ -3942,17 +3370,6 @@ <issue id="TypographyEllipsis" message="Replace "..." with ellipsis character (…, &#8230;) ?" - errorLine1=" <string name="enabling_progress_title" msgid="5262637688863903594">"Palun oodake ..."</string>" - errorLine2=" ~~~~~~~~~~~~~~~~~~"> - <location - file="packages/modules/Bluetooth/android/app/res/values-et/strings.xml" - line="77" - column="72"/> - </issue> - - <issue - id="TypographyEllipsis" - message="Replace "..." with ellipsis character (…, &#8230;) ?" errorLine1=" <string name="enabling_progress_title" msgid="5262637688863903594">"Veuillez patienter..."</string>" errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~"> <location diff --git a/android/app/lint-baseline.xml b/android/app/lint-baseline.xml index 256dbfab50..c50678ee6d 100644 --- a/android/app/lint-baseline.xml +++ b/android/app/lint-baseline.xml @@ -2,17 +2,6 @@ <issues format="6" by="lint 8.4.0-alpha08" type="baseline" client="" dependencies="true" name="" variant="all" version="8.4.0-alpha08"> <issue - id="UnknownIssueId" - message="Unknown issue id "GetterSetterNullability"" - errorLine1=" <issue id='GetterSetterNullability' severity='error' />" - errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> - <location - file="./out/lint.xml" - line="125" - column="3"/> - </issue> - - <issue id="ScrollViewSize" message="This LinearLayout should use `android:layout_height="wrap_content"`" errorLine1=" android:layout_height="match_parent"" @@ -51,7 +40,7 @@ errorLine1="<manifest xmlns:android="http://schemas.android.com/apk/res/android"" errorLine2=" ~~~~~~~~"> <location - file="./out/soong/.intermediates/packages/modules/Bluetooth/android/app/Bluetooth/android_common_apex35/manifest_merger/AndroidManifest.xml" + file="./out/soong/.intermediates/packages/modules/Bluetooth/android/app/Bluetooth/android_common_apex36/manifest_merger/AndroidManifest.xml" line="2" column="2"/> </issue> @@ -62,7 +51,7 @@ errorLine1="<manifest xmlns:android="http://schemas.android.com/apk/res/android"" errorLine2=" ~~~~~~~~"> <location - file="./out/soong/.intermediates/packages/modules/Bluetooth/android/app/Bluetooth/android_common_apex35/manifest_merger/AndroidManifest.xml" + file="./out/soong/.intermediates/packages/modules/Bluetooth/android/app/Bluetooth/android_common_apex36/manifest_merger/AndroidManifest.xml" line="2" column="2"/> </issue> @@ -73,7 +62,7 @@ errorLine1=" <provider" errorLine2=" ~~~~~~~~"> <location - file="./out/soong/.intermediates/packages/modules/Bluetooth/android/app/Bluetooth/android_common_apex35/manifest_merger/AndroidManifest.xml" + file="./out/soong/.intermediates/packages/modules/Bluetooth/android/app/Bluetooth/android_common_apex36/manifest_merger/AndroidManifest.xml" line="144" column="10"/> </issue> @@ -84,7 +73,7 @@ errorLine1=" <receiver" errorLine2=" ~~~~~~~~"> <location - file="./out/soong/.intermediates/packages/modules/Bluetooth/android/app/Bluetooth/android_common_apex35/manifest_merger/AndroidManifest.xml" + file="./out/soong/.intermediates/packages/modules/Bluetooth/android/app/Bluetooth/android_common_apex36/manifest_merger/AndroidManifest.xml" line="209" column="10"/> </issue> @@ -95,7 +84,7 @@ errorLine1=" <service" errorLine2=" ~~~~~~~"> <location - file="./out/soong/.intermediates/packages/modules/Bluetooth/android/app/Bluetooth/android_common_apex35/manifest_merger/AndroidManifest.xml" + file="./out/soong/.intermediates/packages/modules/Bluetooth/android/app/Bluetooth/android_common_apex36/manifest_merger/AndroidManifest.xml" line="129" column="10"/> </issue> @@ -106,7 +95,7 @@ errorLine1=" <service" errorLine2=" ~~~~~~~"> <location - file="./out/soong/.intermediates/packages/modules/Bluetooth/android/app/Bluetooth/android_common_apex35/manifest_merger/AndroidManifest.xml" + file="./out/soong/.intermediates/packages/modules/Bluetooth/android/app/Bluetooth/android_common_apex36/manifest_merger/AndroidManifest.xml" line="348" column="10"/> </issue> @@ -117,7 +106,7 @@ errorLine1=" android:permission="android.permission.ACCESS_BLUETOOTH_SHARE" />" errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> <location - file="./out/soong/.intermediates/packages/modules/Bluetooth/android/app/Bluetooth/android_common_apex35/manifest_merger/AndroidManifest.xml" + file="./out/soong/.intermediates/packages/modules/Bluetooth/android/app/Bluetooth/android_common_apex36/manifest_merger/AndroidManifest.xml" line="206" column="17"/> </issue> @@ -128,7 +117,7 @@ errorLine1=" <uses-permission android:name="android.permission.QUERY_ALL_PACKAGES" />" errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"> <location - file="./out/soong/.intermediates/packages/modules/Bluetooth/android/app/Bluetooth/android_common_apex35/manifest_merger/AndroidManifest.xml" + file="./out/soong/.intermediates/packages/modules/Bluetooth/android/app/Bluetooth/android_common_apex36/manifest_merger/AndroidManifest.xml" line="61" column="22"/> </issue> @@ -1126,17 +1115,6 @@ <issue id="TypographyEllipsis" message="Replace "..." with ellipsis character (…, &#8230;) ?" - errorLine1=" <string name="enabling_progress_title" msgid="5262637688863903594">"Palun oodake ..."</string>" - errorLine2=" ~~~~~~~~~~~~~~~~~~"> - <location - file="packages/modules/Bluetooth/android/app/res/values-et/strings.xml" - line="77" - column="72"/> - </issue> - - <issue - id="TypographyEllipsis" - message="Replace "..." with ellipsis character (…, &#8230;) ?" errorLine1=" <string name="enabling_progress_title" msgid="5262637688863903594">"Veuillez patienter..."</string>" errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~"> <location diff --git a/android/app/src/com/android/bluetooth/BluetoothEventLogger.java b/android/app/src/com/android/bluetooth/BluetoothEventLogger.java index 9a5f811bcf..db2d7f56ef 100644 --- a/android/app/src/com/android/bluetooth/BluetoothEventLogger.java +++ b/android/app/src/com/android/bluetooth/BluetoothEventLogger.java @@ -1,5 +1,5 @@ /* - * Copyright 2019 The Android Open Source Project + * Copyright (C) 2019 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. @@ -18,37 +18,35 @@ package com.android.bluetooth; import android.util.Log; -import com.google.common.collect.EvictingQueue; +import java.util.ArrayDeque; +import java.util.Queue; /** This class is to store logs for given size. */ public class BluetoothEventLogger { private final String mTitle; - private final EvictingQueue<Event> mEvents; - - // Event class contain timestamp and log context. - private static class Event { - private final String mTimeStamp; - private final String mMsg; - - Event(String msg) { - mTimeStamp = Utils.getLocalTimeString(); - mMsg = msg; - } - - public String toString() { - return mTimeStamp + " " + mMsg; - } - } + private final Queue<String> mEvents; + private final int mSize; public BluetoothEventLogger(int size, String title) { - mEvents = EvictingQueue.create(size); + if (size <= 0) { + throw new IllegalArgumentException("Size must be > 0"); + } + mSize = size; + mEvents = new ArrayDeque<>(size); mTitle = title; } /** Add the event record */ public synchronized void add(String msg) { - Event event = new Event(msg); - mEvents.add(event); + if (mEvents.size() == mSize) { + mEvents.remove(); + } + mEvents.add(Utils.getLocalTimeString() + " " + msg); + } + + /** Add the event record */ + public synchronized void clear() { + mEvents.clear(); } /** Add the event record and log message */ @@ -78,8 +76,8 @@ public class BluetoothEventLogger { /** Dump all the events */ public synchronized void dump(StringBuilder sb) { sb.append(mTitle).append(":\n"); - for (Event event : mEvents) { - sb.append(" ").append(event.toString()).append("\n"); + for (String msg : mEvents) { + sb.append(" ").append(msg).append("\n"); } } } diff --git a/android/app/src/com/android/bluetooth/BluetoothMethodProxy.java b/android/app/src/com/android/bluetooth/BluetoothMethodProxy.java index 3141b83af0..d4fc9d54e8 100644 --- a/android/app/src/com/android/bluetooth/BluetoothMethodProxy.java +++ b/android/app/src/com/android/bluetooth/BluetoothMethodProxy.java @@ -1,5 +1,5 @@ /* - * Copyright 2022 The Android Open Source Project + * Copyright (C) 2022 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. diff --git a/android/app/src/com/android/bluetooth/DeviceWorkArounds.java b/android/app/src/com/android/bluetooth/DeviceWorkArounds.java index ed7e816d95..710c49c065 100644 --- a/android/app/src/com/android/bluetooth/DeviceWorkArounds.java +++ b/android/app/src/com/android/bluetooth/DeviceWorkArounds.java @@ -16,17 +16,17 @@ package com.android.bluetooth; -import com.google.common.base.Ascii; +import java.util.Locale; public final class DeviceWorkArounds { - public static final String PCM_CARKIT = "9C:DF:03"; - public static final String FORD_SYNC_CARKIT = "00:1E:AE"; - public static final String HONDA_CARKIT = "64:D4:BD"; - public static final String SYNC_CARKIT = "D0:39:72"; + public static final String PCM_CARKIT = "9c:df:03"; + public static final String FORD_SYNC_CARKIT = "00:1e:ae"; + public static final String HONDA_CARKIT = "64:d4:bd"; + public static final String SYNC_CARKIT = "d0:39:72"; public static final String BREZZA_ZDI_CARKIT = "28:a1:83"; public static final String MERCEDES_BENZ_CARKIT = "00:26:e8"; public static boolean addressStartsWith(String bdAddr, String carkitAddr) { - return Ascii.toLowerCase(bdAddr).startsWith(Ascii.toLowerCase(carkitAddr)); + return bdAddr.toLowerCase(Locale.ROOT).startsWith(carkitAddr); } } diff --git a/android/app/src/com/android/bluetooth/ObexServerSockets.java b/android/app/src/com/android/bluetooth/ObexServerSockets.java index 712049d561..0294ff3e05 100644 --- a/android/app/src/com/android/bluetooth/ObexServerSockets.java +++ b/android/app/src/com/android/bluetooth/ObexServerSockets.java @@ -29,7 +29,7 @@ import java.io.IOException; /** * Wraps multiple BluetoothServerSocket objects to make it possible to accept connections on both a * RFCOMM and L2CAP channel in parallel.<br> - * Create an instance using {@link #create()}, which will block until the sockets have been created + * Create an instance using {@link #create}, which will block until the sockets have been created * and channel numbers have been assigned.<br> * Use {@link #getRfcommChannel()} and {@link #getL2capPsm()} to get the channel numbers to put into * the SDP record.<br> diff --git a/android/app/src/com/android/bluetooth/SignedLongLong.java b/android/app/src/com/android/bluetooth/SignedLongLong.java index ea2e57e559..7bd96eb0c6 100644 --- a/android/app/src/com/android/bluetooth/SignedLongLong.java +++ b/android/app/src/com/android/bluetooth/SignedLongLong.java @@ -17,22 +17,13 @@ package com.android.bluetooth; import com.android.bluetooth.map.BluetoothMapUtils; -import java.util.Objects; - /** * Class to represent a 128bit value using two long member variables. Has functionality to convert * to/from hex-strings. Mind that since signed variables are used to store the value internally is * used, the MSB/LSB long values can be negative. */ -public class SignedLongLong implements Comparable<SignedLongLong> { - - private final long mMostSigBits; - private final long mLeastSigBits; - - public SignedLongLong(long leastSigBits, long mostSigBits) { - this.mMostSigBits = mostSigBits; - this.mLeastSigBits = leastSigBits; - } +public record SignedLongLong(long leastSignificantBits, long mostSignificantBits) + implements Comparable<SignedLongLong> { /** * Create a SignedLongLong from a Hex-String without "0x" prefix @@ -68,16 +59,16 @@ public class SignedLongLong implements Comparable<SignedLongLong> { @Override public int compareTo(SignedLongLong another) { - if (mMostSigBits == another.mMostSigBits) { - if (mLeastSigBits == another.mLeastSigBits) { + if (mostSignificantBits == another.mostSignificantBits) { + if (leastSignificantBits == another.leastSignificantBits) { return 0; } - if (mLeastSigBits < another.mLeastSigBits) { + if (leastSignificantBits < another.leastSignificantBits) { return -1; } return 1; } - if (mMostSigBits < another.mMostSigBits) { + if (mostSignificantBits < another.mostSignificantBits) { return -1; } return 1; @@ -92,40 +83,6 @@ public class SignedLongLong implements Comparable<SignedLongLong> { * @return a hex-string representation of the object values */ public String toHexString() { - return BluetoothMapUtils.getLongLongAsString(mLeastSigBits, mMostSigBits); - } - - @Override - public boolean equals(Object obj) { - if (this == obj) { - return true; - } - if (obj == null) { - return false; - } - if (!(obj instanceof SignedLongLong)) { - return false; - } - SignedLongLong other = (SignedLongLong) obj; - if (mLeastSigBits != other.mLeastSigBits) { - return false; - } - if (mMostSigBits != other.mMostSigBits) { - return false; - } - return true; - } - - @Override - public int hashCode() { - return Objects.hash(mLeastSigBits, mMostSigBits); - } - - public long getMostSignificantBits() { - return mMostSigBits; - } - - public long getLeastSignificantBits() { - return mLeastSigBits; + return BluetoothMapUtils.getLongLongAsString(leastSignificantBits, mostSignificantBits); } } diff --git a/android/app/src/com/android/bluetooth/Utils.java b/android/app/src/com/android/bluetooth/Utils.java index dc2fdc12ec..ce23339f0b 100644 --- a/android/app/src/com/android/bluetooth/Utils.java +++ b/android/app/src/com/android/bluetooth/Utils.java @@ -27,6 +27,7 @@ import static android.Manifest.permission.NETWORK_SETUP_WIZARD; import static android.Manifest.permission.RADIO_SCAN_WITHOUT_LOCATION; import static android.Manifest.permission.RENOUNCE_PERMISSIONS; import static android.Manifest.permission.WRITE_SMS; +import static android.bluetooth.BluetoothUtils.RemoteExceptionIgnoringRunnable; import static android.bluetooth.BluetoothUtils.USER_HANDLE_NULL; import static android.content.pm.PackageManager.GET_PERMISSIONS; import static android.content.pm.PackageManager.MATCH_UNINSTALLED_PACKAGES; @@ -62,7 +63,6 @@ import android.os.Build; import android.os.ParcelUuid; import android.os.PowerExemptionManager; import android.os.Process; -import android.os.RemoteException; import android.os.SystemProperties; import android.os.UserHandle; import android.os.UserManager; @@ -95,12 +95,19 @@ import java.util.UUID; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.TimeUnit; -import java.util.function.Consumer; public final class Utils { public static final String TAG_PREFIX_BLUETOOTH = "Bluetooth"; private static final String TAG = TAG_PREFIX_BLUETOOTH + Utils.class.getSimpleName(); + public static final int BD_ADDR_LEN = 6; // bytes + private static final int BD_UUID_LEN = 16; // bytes + + /** Thread pool to handle background and outgoing blocking task */ + public static final ExecutorService BackgroundExecutor = Executors.newSingleThreadExecutor(); + + public static final String PAIRING_UI_PROPERTY = "bluetooth.pairing_ui_package.name"; + private static final int MICROS_PER_UNIT = 625; private static final String PTS_TEST_MODE_PROPERTY = "persist.bluetooth.pts"; @@ -116,13 +123,22 @@ public final class Utils { private static final String KEY_TEMP_ALLOW_LIST_DURATION_MS = "temp_allow_list_duration_ms"; private static final long DEFAULT_TEMP_ALLOW_LIST_DURATION_MS = 20_000; - static final int BD_ADDR_LEN = 6; // bytes - static final int BD_UUID_LEN = 16; // bytes + private static int sSystemUiUid = USER_HANDLE_NULL.getIdentifier(); + private static int sForegroundUserId = USER_HANDLE_NULL.getIdentifier(); - /** Thread pool to handle background and outgoing blocking task */ - public static final ExecutorService BackgroundExecutor = Executors.newSingleThreadExecutor(); + private Utils() {} - public static final String PAIRING_UI_PROPERTY = "bluetooth.pairing_ui_package.name"; + public static void setSystemUiUid(int uid) { + sSystemUiUid = uid; + } + + public static int getForegroundUserId() { + return sForegroundUserId; + } + + public static void setForegroundUserId(int userId) { + sForegroundUserId = userId; + } /** * Check if dual mode audio is enabled. This is set via the system property @@ -348,17 +364,6 @@ public final class Utils { return converter.getLong(offset); } - public static String byteArrayToString(byte[] valueBuf) { - StringBuilder sb = new StringBuilder(); - for (int idx = 0; idx < valueBuf.length; idx++) { - if (idx != 0) { - sb.append(" "); - } - sb.append(formatSimple("%02x", valueBuf[idx])); - } - return sb.toString(); - } - /** * A parser to transfer a byte array to a UTF8 string * @@ -430,22 +435,6 @@ public final class Utils { return puuids; } - static int sSystemUiUid = USER_HANDLE_NULL.getIdentifier(); - - public static void setSystemUiUid(int uid) { - Utils.sSystemUiUid = uid; - } - - static int sForegroundUserId = USER_HANDLE_NULL.getIdentifier(); - - public static int getForegroundUserId() { - return Utils.sForegroundUserId; - } - - public static void setForegroundUserId(int userId) { - Utils.sForegroundUserId = userId; - } - /** * Enforces that a Companion Device Manager (CDM) association exists between the calling * application and the Bluetooth Device. @@ -575,16 +564,16 @@ public final class Utils { private static boolean checkPermissionForDataDelivery( Context context, @PermissionName String permission, - AttributionSource attributionSource, + AttributionSource source, String message) { if (isInstrumentationTestMode()) { return true; } // STOPSHIP(b/188391719): enable this security enforcement - // attributionSource.enforceCallingUid(); + // source.enforceCallingUid(); AttributionSource currentAttribution = new AttributionSource.Builder(context.getAttributionSource()) - .setNext(requireNonNull(attributionSource)) + .setNext(requireNonNull(source)) .build(); PermissionManager pm = context.getSystemService(PermissionManager.class); if (pm == null) { @@ -631,9 +620,8 @@ public final class Utils { @SuppressLint("AndroidFrameworkRequiresPermission") // This method enforce the permission @RequiresPermission(BLUETOOTH_CONNECT) public static boolean checkConnectPermissionForDataDelivery( - Context context, AttributionSource attributionSource, String message) { - return checkPermissionForDataDelivery( - context, BLUETOOTH_CONNECT, attributionSource, message); + Context context, AttributionSource source, String message) { + return checkPermissionForDataDelivery(context, BLUETOOTH_CONNECT, source, message); } /** @@ -658,8 +646,8 @@ public final class Utils { @SuppressLint("AndroidFrameworkRequiresPermission") // This method enforce the permission @RequiresPermission(BLUETOOTH_SCAN) public static boolean checkScanPermissionForDataDelivery( - Context context, AttributionSource attributionSource, String message) { - return checkPermissionForDataDelivery(context, BLUETOOTH_SCAN, attributionSource, message); + Context context, AttributionSource source, String message) { + return checkPermissionForDataDelivery(context, BLUETOOTH_SCAN, source, message); } /** @@ -686,9 +674,8 @@ public final class Utils { @SuppressLint("AndroidFrameworkRequiresPermission") // This method enforce the permission @RequiresPermission(BLUETOOTH_ADVERTISE) public static boolean checkAdvertisePermissionForDataDelivery( - Context context, AttributionSource attributionSource, String message) { - return checkPermissionForDataDelivery( - context, BLUETOOTH_ADVERTISE, attributionSource, message); + Context context, AttributionSource source, String message) { + return checkPermissionForDataDelivery(context, BLUETOOTH_ADVERTISE, source, message); } /** @@ -699,11 +686,11 @@ public final class Utils { // Suppressed since we're not actually enforcing here @SuppressLint("AndroidFrameworkRequiresPermission") public static boolean hasDisavowedLocationForScan( - Context context, AttributionSource attributionSource, boolean inTestMode) { + Context context, AttributionSource source, boolean inTestMode) { // Check every step along the attribution chain for a renouncement. // If location has been renounced anywhere in the chain we treat it as a disavowal. - AttributionSource currentAttrib = attributionSource; + AttributionSource currentAttrib = source; while (true) { if (currentAttrib.getRenouncedPermissions().contains(ACCESS_FINE_LOCATION) && (inTestMode @@ -753,7 +740,7 @@ public final class Utils { || (UserHandle.getAppId(Process.SYSTEM_UID) == UserHandle.getAppId(callingUid)); } - public static boolean checkCallerIsSystemOrActiveUser(String tag) { + static boolean checkCallerIsSystemOrActiveUser(String tag) { final boolean res = checkCallerIsSystemOrActiveUser(); if (!res) { Log.w(TAG, tag + " - Not allowed for non-active user and non-system user"); @@ -761,10 +748,6 @@ public final class Utils { return res; } - public static boolean callerIsSystemOrActiveUser(String tag, String method) { - return checkCallerIsSystemOrActiveUser(tag + "." + method + "()"); - } - /** * Checks if the caller to the method is system server. * @@ -858,17 +841,17 @@ public final class Utils { // Suppressed since we're not actually enforcing here @SuppressLint("AndroidFrameworkRequiresPermission") public static boolean checkCallerHasCoarseLocation( - Context context, AttributionSource attributionSource, UserHandle userHandle) { + Context context, AttributionSource source, UserHandle userHandle) { if (blockedByLocationOff(context, userHandle)) { Log.e(TAG, "Permission denial: Location is off."); return false; } AttributionSource currentAttribution = new AttributionSource.Builder(context.getAttributionSource()) - .setNext(requireNonNull(attributionSource)) + .setNext(requireNonNull(source)) .build(); // STOPSHIP(b/188391719): enable this security enforcement - // attributionSource.enforceCallingUid(); + // source.enforceCallingUid(); PermissionManager pm = context.getSystemService(PermissionManager.class); if (pm == null) { return false; @@ -890,7 +873,7 @@ public final class Utils { // Suppressed since we're not actually enforcing here @SuppressLint("AndroidFrameworkRequiresPermission") public static boolean checkCallerHasCoarseOrFineLocation( - Context context, AttributionSource attributionSource, UserHandle userHandle) { + Context context, AttributionSource source, UserHandle userHandle) { if (blockedByLocationOff(context, userHandle)) { Log.e(TAG, "Permission denial: Location is off."); return false; @@ -898,10 +881,10 @@ public final class Utils { final AttributionSource currentAttribution = new AttributionSource.Builder(context.getAttributionSource()) - .setNext(requireNonNull(attributionSource)) + .setNext(requireNonNull(source)) .build(); // STOPSHIP(b/188391719): enable this security enforcement - // attributionSource.enforceCallingUid(); + // source.enforceCallingUid(); PermissionManager pm = context.getSystemService(PermissionManager.class); if (pm == null) { return false; @@ -929,7 +912,7 @@ public final class Utils { // Suppressed since we're not actually enforcing here @SuppressLint("AndroidFrameworkRequiresPermission") public static boolean checkCallerHasFineLocation( - Context context, AttributionSource attributionSource, UserHandle userHandle) { + Context context, AttributionSource source, UserHandle userHandle) { if (blockedByLocationOff(context, userHandle)) { Log.e(TAG, "Permission denial: Location is off."); return false; @@ -937,10 +920,10 @@ public final class Utils { AttributionSource currentAttribution = new AttributionSource.Builder(context.getAttributionSource()) - .setNext(requireNonNull(attributionSource)) + .setNext(requireNonNull(source)) .build(); // STOPSHIP(b/188391719): enable this security enforcement - // attributionSource.enforceCallingUid(); + // source.enforceCallingUid(); PermissionManager pm = context.getSystemService(PermissionManager.class); if (pm == null) { return false; @@ -1192,13 +1175,15 @@ public final class Utils { return "NO SUBSCRIPTION"; } - if (BigInteger.valueOf(cccValue).testBit(0) && BigInteger.valueOf(cccValue).testBit(1)) { + final boolean isBit0Set = BigInteger.valueOf(cccValue).testBit(0); + final boolean isBit1Set = BigInteger.valueOf(cccValue).testBit(1); + if (isBit0Set && isBit1Set) { return "NOTIFICATION|INDICATION"; } - if (BigInteger.valueOf(cccValue).testBit(0)) { + if (isBit0Set) { return "NOTIFICATION"; } - if (BigInteger.valueOf(cccValue).testBit(1)) { + if (isBit1Set) { return "INDICATION"; } return ""; @@ -1246,20 +1231,16 @@ public final class Utils { || pm.hasSystemFeature(PackageManager.FEATURE_LEANBACK); } - /** A {@link Consumer} that automatically ignores any {@link RemoteException}s. */ - @FunctionalInterface - @SuppressWarnings("FunctionalInterfaceMethodChanged") - public interface RemoteExceptionIgnoringConsumer<T> extends Consumer<T> { - /** Called by {@code accept}. */ - void acceptOrThrow(T t) throws RemoteException; - - @Override - default void accept(T t) { - try { - acceptOrThrow(t); - } catch (RemoteException ex) { - // Ignore RemoteException - } + /** + * Reverses the elements of {@code array}. This is equivalent to {@code + * Collections.reverse(Bytes.asList(array))}, but is likely to be more efficient. + */ + public static void reverse(byte[] array) { + requireNonNull(array); + for (int i = 0, j = array.length - 1; i < j; i++, j--) { + byte tmp = array[i]; + array[i] = array[j]; + array[j] = tmp; } } @@ -1331,4 +1312,28 @@ public final class Utils { return android.os.SystemClock.elapsedRealtime(); } } + + /** Execute a remote callback without propagating the RemoteException of a dead app */ + public static void callbackToApp(RemoteExceptionIgnoringRunnable callback) { + callback.run(); + } + + /** Invokes {@code toJoin.}{@link Thread#join() join()} uninterruptibly. */ + public static void joinUninterruptibly(Thread toJoin) { + boolean interrupted = false; + try { + while (true) { + try { + toJoin.join(); + return; + } catch (InterruptedException e) { + interrupted = true; + } + } + } finally { + if (interrupted) { + Thread.currentThread().interrupt(); + } + } + } } diff --git a/android/app/src/com/android/bluetooth/a2dp/A2dpCodecConfig.java b/android/app/src/com/android/bluetooth/a2dp/A2dpCodecConfig.java index 340827bd09..30733e2a7f 100644 --- a/android/app/src/com/android/bluetooth/a2dp/A2dpCodecConfig.java +++ b/android/app/src/com/android/bluetooth/a2dp/A2dpCodecConfig.java @@ -1,5 +1,5 @@ /* - * Copyright 2018 The Android Open Source Project + * Copyright (C) 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. diff --git a/android/app/src/com/android/bluetooth/a2dp/A2dpNativeCallback.java b/android/app/src/com/android/bluetooth/a2dp/A2dpNativeCallback.java index 314811f71c..5fd94dfea0 100644 --- a/android/app/src/com/android/bluetooth/a2dp/A2dpNativeCallback.java +++ b/android/app/src/com/android/bluetooth/a2dp/A2dpNativeCallback.java @@ -1,5 +1,5 @@ /* - * Copyright 2024 The Android Open Source Project + * Copyright (C) 2024 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. diff --git a/android/app/src/com/android/bluetooth/a2dp/A2dpNativeInterface.java b/android/app/src/com/android/bluetooth/a2dp/A2dpNativeInterface.java index 67beb274d5..fe74b2facd 100644 --- a/android/app/src/com/android/bluetooth/a2dp/A2dpNativeInterface.java +++ b/android/app/src/com/android/bluetooth/a2dp/A2dpNativeInterface.java @@ -1,5 +1,5 @@ /* - * Copyright 2017 The Android Open Source Project + * Copyright (C) 2017 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. diff --git a/android/app/src/com/android/bluetooth/a2dp/A2dpService.java b/android/app/src/com/android/bluetooth/a2dp/A2dpService.java index e739c24c99..9481146d61 100644 --- a/android/app/src/com/android/bluetooth/a2dp/A2dpService.java +++ b/android/app/src/com/android/bluetooth/a2dp/A2dpService.java @@ -59,7 +59,6 @@ import android.os.Looper; import android.sysprop.BluetoothProperties; import android.util.Log; -import com.android.bluetooth.BluetoothMetricsProto; import com.android.bluetooth.BluetoothStatsLog; import com.android.bluetooth.Utils; import com.android.bluetooth.btservice.ActiveDeviceManager; @@ -1306,9 +1305,6 @@ public class A2dpService extends ProfileService { if ((device == null) || (fromState == toState)) { return; } - if (toState == STATE_CONNECTED) { - MetricsLogger.logProfileConnectionEvent(BluetoothMetricsProto.ProfileId.A2DP); - } // Set the active device if only one connected device is supported and it was connected if (toState == STATE_CONNECTED && (mMaxConnectedAudioDevices == 1)) { setActiveDevice(device); diff --git a/android/app/src/com/android/bluetooth/a2dp/A2dpStackEvent.java b/android/app/src/com/android/bluetooth/a2dp/A2dpStackEvent.java index 6c66f0119b..314beefbaa 100644 --- a/android/app/src/com/android/bluetooth/a2dp/A2dpStackEvent.java +++ b/android/app/src/com/android/bluetooth/a2dp/A2dpStackEvent.java @@ -1,5 +1,5 @@ /* - * Copyright 2017 The Android Open Source Project + * Copyright (C) 2017 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. diff --git a/android/app/src/com/android/bluetooth/a2dp/A2dpStateMachine.java b/android/app/src/com/android/bluetooth/a2dp/A2dpStateMachine.java index a2e4d0b4d2..697529e63c 100644 --- a/android/app/src/com/android/bluetooth/a2dp/A2dpStateMachine.java +++ b/android/app/src/com/android/bluetooth/a2dp/A2dpStateMachine.java @@ -80,7 +80,7 @@ final class A2dpStateMachine extends StateMachine { static final int MESSAGE_CONNECT = 1; static final int MESSAGE_DISCONNECT = 2; - @VisibleForTesting static final int MESSAGE_STACK_EVENT = 101; + static final int MESSAGE_STACK_EVENT = 101; private static final int MESSAGE_CONNECT_TIMEOUT = 201; @VisibleForTesting static final Duration CONNECT_TIMEOUT = Duration.ofSeconds(30); @@ -132,9 +132,7 @@ final class A2dpStateMachine extends StateMachine { public void doQuit() { log("doQuit for device " + mDevice); - if (Flags.a2dpBroadcastConnectionStateWhenTurnedOff() - && mConnectionState != STATE_DISCONNECTED - && mLastConnectionState != -1) { + if (mConnectionState != STATE_DISCONNECTED && mLastConnectionState != -1) { // Broadcast CONNECTION_STATE_CHANGED when A2dpService is turned off while // the device is connected broadcastConnectionState(STATE_DISCONNECTED, mConnectionState); diff --git a/android/app/src/com/android/bluetooth/a2dpsink/A2dpSinkStateMachine.java b/android/app/src/com/android/bluetooth/a2dpsink/A2dpSinkStateMachine.java index 18d956b594..7ec05af50d 100644 --- a/android/app/src/com/android/bluetooth/a2dpsink/A2dpSinkStateMachine.java +++ b/android/app/src/com/android/bluetooth/a2dpsink/A2dpSinkStateMachine.java @@ -34,7 +34,6 @@ import android.os.Looper; import android.os.Message; import android.util.Log; -import com.android.bluetooth.BluetoothMetricsProto; import com.android.bluetooth.Utils; import com.android.bluetooth.btservice.MetricsLogger; import com.android.bluetooth.btservice.ProfileService; @@ -316,9 +315,6 @@ class A2dpSinkStateMachine extends StateMachine { if (mMostRecentState == currentState) { return; } - if (currentState == STATE_CONNECTED) { - MetricsLogger.logProfileConnectionEvent(BluetoothMetricsProto.ProfileId.A2DP_SINK); - } Log.d(TAG, "[" + mDevice + "] Connection state: " + mMostRecentState + "->" + currentState); Intent intent = new Intent(BluetoothA2dpSink.ACTION_CONNECTION_STATE_CHANGED); intent.putExtra(BluetoothProfile.EXTRA_PREVIOUS_STATE, mMostRecentState); diff --git a/android/app/src/com/android/bluetooth/audio_util/BrowsablePlayerConnector.java b/android/app/src/com/android/bluetooth/audio_util/BrowsablePlayerConnector.java index 12908fde53..156a54db8e 100644 --- a/android/app/src/com/android/bluetooth/audio_util/BrowsablePlayerConnector.java +++ b/android/app/src/com/android/bluetooth/audio_util/BrowsablePlayerConnector.java @@ -1,5 +1,5 @@ /* - * Copyright 2018 The Android Open Source Project + * Copyright (C) 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. diff --git a/android/app/src/com/android/bluetooth/audio_util/BrowsedPlayerWrapper.java b/android/app/src/com/android/bluetooth/audio_util/BrowsedPlayerWrapper.java index 02598dae03..8b9b73d160 100644 --- a/android/app/src/com/android/bluetooth/audio_util/BrowsedPlayerWrapper.java +++ b/android/app/src/com/android/bluetooth/audio_util/BrowsedPlayerWrapper.java @@ -1,5 +1,5 @@ /* - * Copyright 2018 The Android Open Source Project + * Copyright (C) 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. diff --git a/android/app/src/com/android/bluetooth/audio_util/GPMWrapper.java b/android/app/src/com/android/bluetooth/audio_util/GPMWrapper.java index a69a6be6f9..e7c45de50e 100644 --- a/android/app/src/com/android/bluetooth/audio_util/GPMWrapper.java +++ b/android/app/src/com/android/bluetooth/audio_util/GPMWrapper.java @@ -1,5 +1,5 @@ /* - * Copyright 2018 The Android Open Source Project + * Copyright (C) 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. diff --git a/android/app/src/com/android/bluetooth/audio_util/MediaBrowserWrapper.java b/android/app/src/com/android/bluetooth/audio_util/MediaBrowserWrapper.java index ecf3ca2233..3c235cce76 100644 --- a/android/app/src/com/android/bluetooth/audio_util/MediaBrowserWrapper.java +++ b/android/app/src/com/android/bluetooth/audio_util/MediaBrowserWrapper.java @@ -1,5 +1,5 @@ /* - * Copyright 2024 The Android Open Source Project + * Copyright (C) 2024 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. diff --git a/android/app/src/com/android/bluetooth/audio_util/MediaPlayerList.java b/android/app/src/com/android/bluetooth/audio_util/MediaPlayerList.java index d592a36481..1098cda6fa 100644 --- a/android/app/src/com/android/bluetooth/audio_util/MediaPlayerList.java +++ b/android/app/src/com/android/bluetooth/audio_util/MediaPlayerList.java @@ -1,5 +1,5 @@ /* - * Copyright 2018 The Android Open Source Project + * Copyright (C) 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. @@ -347,12 +347,12 @@ public class MediaPlayerList { return id; } - /** Returns the {@link #MediaPlayerWrapper} with ID matching {@link #mActivePlayerId}. */ + /** Returns the {@link MediaPlayerWrapper} with ID matching {@link #mActivePlayerId}. */ public MediaPlayerWrapper getActivePlayer() { return mMediaPlayers.get(mActivePlayerId); } - /** Returns the {@link #MediaPlayerWrapper} with ID matching {@link #mAddressedPlayerId}. */ + /** Returns the {@link MediaPlayerWrapper} with ID matching {@link #mAddressedPlayerId}. */ public MediaPlayerWrapper getAddressedPlayer() { return mMediaPlayers.get(mAddressedPlayerId); } @@ -1009,7 +1009,7 @@ public class MediaPlayerList { * Sets {@code playerId} as the new active player and sends the new player's {@link Mediadata} * to the AVRCP service. * - * <p>Also informs the {@link #PlayerSettingsManager} about the change of active player. + * <p>Also informs the {@link PlayerSettingsManager} about the change of active player. */ void setActivePlayer(int playerId) { if (!haveMediaPlayer(playerId)) { @@ -1113,7 +1113,8 @@ public class MediaPlayerList { * <p>Note: This does not set the current active player, only adds the new {@link * MediaController} to the {@link #mMediaPlayerIds} and {@link mMediaPlayers} maps. * - * <p>See {@link #onMediaKeyEventSessionChanged}. + * <p>See {@link + * MediaSessionManager.OnMediaKeyEventSessionChangedListener#onMediaKeyEventSessionChanged}. */ @VisibleForTesting final MediaSessionManager.OnActiveSessionsChangedListener mActiveSessionsChangedListener = @@ -1291,7 +1292,7 @@ public class MediaPlayerList { /** * Saves the reference to {@link MediaPlayerSettingsEventListener} to be called when the active - * player changed, so that {@link #PlayerSettingsManager} always has the right player. + * player changed, so that {@link PlayerSettingsManager} always has the right player. */ void setPlayerSettingsCallback(MediaPlayerSettingsEventListener listener) { mPlayerSettingsListener = listener; @@ -1340,10 +1341,12 @@ public class MediaPlayerList { /** * Callback from {@link MediaPlayerWrapper}. * - * <p>{@link #mediaUpdatedCallback} listens for {@link #MediaData} changes on the active player. + * <p>{@link MediaPlayerWrapper.Callback#mediaUpdatedCallback} listens for {@link MediaData} + * changes on the active player. * - * <p>{@link #sessionUpdatedCallback} is called when the active session is destroyed so we need - * to remove the media player from the {@link #mMediaPlayerIds} and {@link mMediaPlayers} maps. + * <p>{@link MediaPlayerWrapper.Callback#sessionUpdatedCallback} is called when the active + * session is destroyed so we need to remove the media player from the {@link #mMediaPlayerIds} + * and {@link mMediaPlayers} maps. */ private final MediaPlayerWrapper.Callback mMediaPlayerCallback = new MediaPlayerWrapper.Callback() { diff --git a/android/app/src/com/android/bluetooth/audio_util/MediaPlayerWrapper.java b/android/app/src/com/android/bluetooth/audio_util/MediaPlayerWrapper.java index cca53936a5..29efeaf0be 100644 --- a/android/app/src/com/android/bluetooth/audio_util/MediaPlayerWrapper.java +++ b/android/app/src/com/android/bluetooth/audio_util/MediaPlayerWrapper.java @@ -1,5 +1,5 @@ /* - * Copyright 2018 The Android Open Source Project + * Copyright (C) 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. diff --git a/android/app/src/com/android/bluetooth/audio_util/PlayerSettingsManager.java b/android/app/src/com/android/bluetooth/audio_util/PlayerSettingsManager.java index 43733ec15e..6a0f9bd2d7 100644 --- a/android/app/src/com/android/bluetooth/audio_util/PlayerSettingsManager.java +++ b/android/app/src/com/android/bluetooth/audio_util/PlayerSettingsManager.java @@ -1,5 +1,5 @@ /* - * Copyright 2023 The Android Open Source Project + * Copyright (C) 2023 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/android/app/src/com/android/bluetooth/audio_util/helpers/PlayStatus.java b/android/app/src/com/android/bluetooth/audio_util/helpers/PlayStatus.java index adca4be6a9..eccabe6087 100644 --- a/android/app/src/com/android/bluetooth/audio_util/helpers/PlayStatus.java +++ b/android/app/src/com/android/bluetooth/audio_util/helpers/PlayStatus.java @@ -1,5 +1,5 @@ /* - * Copyright 2018 The Android Open Source Project + * Copyright (C) 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. diff --git a/android/app/src/com/android/bluetooth/audio_util/helpers/PlayerInfo.java b/android/app/src/com/android/bluetooth/audio_util/helpers/PlayerInfo.java index ada64292f7..a6f5c4ee2f 100644 --- a/android/app/src/com/android/bluetooth/audio_util/helpers/PlayerInfo.java +++ b/android/app/src/com/android/bluetooth/audio_util/helpers/PlayerInfo.java @@ -1,5 +1,5 @@ /* - * Copyright 2018 The Android Open Source Project + * Copyright (C) 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. diff --git a/android/app/src/com/android/bluetooth/audio_util/mockable/MediaBrowser.java b/android/app/src/com/android/bluetooth/audio_util/mockable/MediaBrowser.java index 93ef130d43..31063529fa 100644 --- a/android/app/src/com/android/bluetooth/audio_util/mockable/MediaBrowser.java +++ b/android/app/src/com/android/bluetooth/audio_util/mockable/MediaBrowser.java @@ -1,5 +1,5 @@ /* - * Copyright 2018 The Android Open Source Project + * Copyright (C) 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. diff --git a/android/app/src/com/android/bluetooth/audio_util/mockable/MediaBrowserFactory.java b/android/app/src/com/android/bluetooth/audio_util/mockable/MediaBrowserFactory.java index 4570af982a..835c09c79e 100644 --- a/android/app/src/com/android/bluetooth/audio_util/mockable/MediaBrowserFactory.java +++ b/android/app/src/com/android/bluetooth/audio_util/mockable/MediaBrowserFactory.java @@ -1,5 +1,5 @@ /* - * Copyright 2018 The Android Open Source Project + * Copyright (C) 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. diff --git a/android/app/src/com/android/bluetooth/audio_util/mockable/MediaController.java b/android/app/src/com/android/bluetooth/audio_util/mockable/MediaController.java index a0081b2190..ceec1065f8 100644 --- a/android/app/src/com/android/bluetooth/audio_util/mockable/MediaController.java +++ b/android/app/src/com/android/bluetooth/audio_util/mockable/MediaController.java @@ -1,5 +1,5 @@ /* - * Copyright 2018 The Android Open Source Project + * Copyright (C) 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. diff --git a/android/app/src/com/android/bluetooth/audio_util/mockable/MediaControllerFactory.java b/android/app/src/com/android/bluetooth/audio_util/mockable/MediaControllerFactory.java index ff477ac7b4..81734c5bae 100644 --- a/android/app/src/com/android/bluetooth/audio_util/mockable/MediaControllerFactory.java +++ b/android/app/src/com/android/bluetooth/audio_util/mockable/MediaControllerFactory.java @@ -1,5 +1,5 @@ /* - * Copyright 2018 The Android Open Source Project + * Copyright (C) 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. diff --git a/android/app/src/com/android/bluetooth/audio_util/mockable/MediaPlayerWrapperFactory.java b/android/app/src/com/android/bluetooth/audio_util/mockable/MediaPlayerWrapperFactory.java index cb2798bdc3..5a8dfe4ab7 100644 --- a/android/app/src/com/android/bluetooth/audio_util/mockable/MediaPlayerWrapperFactory.java +++ b/android/app/src/com/android/bluetooth/audio_util/mockable/MediaPlayerWrapperFactory.java @@ -1,5 +1,5 @@ /* - * Copyright 2019 The Android Open Source Project + * Copyright (C) 2019 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. diff --git a/android/app/src/com/android/bluetooth/avrcp/AvrcpBipObexServer.java b/android/app/src/com/android/bluetooth/avrcp/AvrcpBipObexServer.java index 9df35f9388..fc760cd1ae 100644 --- a/android/app/src/com/android/bluetooth/avrcp/AvrcpBipObexServer.java +++ b/android/app/src/com/android/bluetooth/avrcp/AvrcpBipObexServer.java @@ -1,5 +1,5 @@ /* - * Copyright 2020 The Android Open Source Project + * Copyright (C) 2020 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. diff --git a/android/app/src/com/android/bluetooth/avrcp/AvrcpCoverArtService.java b/android/app/src/com/android/bluetooth/avrcp/AvrcpCoverArtService.java index 2351f30fc2..7f8823ea35 100644 --- a/android/app/src/com/android/bluetooth/avrcp/AvrcpCoverArtService.java +++ b/android/app/src/com/android/bluetooth/avrcp/AvrcpCoverArtService.java @@ -1,5 +1,5 @@ /* - * Copyright 2020 The Android Open Source Project + * Copyright (C) 2020 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. diff --git a/android/app/src/com/android/bluetooth/avrcp/AvrcpCoverArtStorage.java b/android/app/src/com/android/bluetooth/avrcp/AvrcpCoverArtStorage.java index cd97e9970c..4146139a12 100644 --- a/android/app/src/com/android/bluetooth/avrcp/AvrcpCoverArtStorage.java +++ b/android/app/src/com/android/bluetooth/avrcp/AvrcpCoverArtStorage.java @@ -1,5 +1,5 @@ /* - * Copyright 2020 The Android Open Source Project + * Copyright (C) 2020 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. diff --git a/android/app/src/com/android/bluetooth/avrcp/AvrcpNativeInterface.java b/android/app/src/com/android/bluetooth/avrcp/AvrcpNativeInterface.java index 1e2e5607cb..720ce84dd8 100644 --- a/android/app/src/com/android/bluetooth/avrcp/AvrcpNativeInterface.java +++ b/android/app/src/com/android/bluetooth/avrcp/AvrcpNativeInterface.java @@ -1,5 +1,5 @@ /* - * Copyright 2018 The Android Open Source Project + * Copyright (C) 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. diff --git a/android/app/src/com/android/bluetooth/avrcp/AvrcpTargetService.java b/android/app/src/com/android/bluetooth/avrcp/AvrcpTargetService.java index 29e6e6676b..81667dca2c 100644 --- a/android/app/src/com/android/bluetooth/avrcp/AvrcpTargetService.java +++ b/android/app/src/com/android/bluetooth/avrcp/AvrcpTargetService.java @@ -1,5 +1,5 @@ /* - * Copyright 2018 The Android Open Source Project + * Copyright (C) 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. @@ -36,7 +36,6 @@ import android.util.Log; import android.view.KeyEvent; import com.android.bluetooth.BluetoothEventLogger; -import com.android.bluetooth.BluetoothMetricsProto; import com.android.bluetooth.a2dp.A2dpService; import com.android.bluetooth.audio_util.ListItem; import com.android.bluetooth.audio_util.MediaData; @@ -47,7 +46,6 @@ import com.android.bluetooth.audio_util.PlayStatus; import com.android.bluetooth.audio_util.PlayerInfo; import com.android.bluetooth.audio_util.PlayerSettingsManager; import com.android.bluetooth.btservice.AdapterService; -import com.android.bluetooth.btservice.MetricsLogger; import com.android.bluetooth.btservice.ProfileService; import com.android.bluetooth.btservice.ServiceFactory; import com.android.bluetooth.flags.Flags; @@ -308,7 +306,6 @@ public class AvrcpTargetService extends ProfileService { void deviceConnected(BluetoothDevice device, boolean absoluteVolume) { Log.i(TAG, "deviceConnected: device=" + device + " absoluteVolume=" + absoluteVolume); mVolumeManager.deviceConnected(device, absoluteVolume); - MetricsLogger.logProfileConnectionEvent(BluetoothMetricsProto.ProfileId.AVRCP); } /** Informs {@link AvrcpVolumeManager} that a device is disconnected */ diff --git a/android/app/src/com/android/bluetooth/avrcp/AvrcpVolumeManager.java b/android/app/src/com/android/bluetooth/avrcp/AvrcpVolumeManager.java index 91f602815a..010538116f 100644 --- a/android/app/src/com/android/bluetooth/avrcp/AvrcpVolumeManager.java +++ b/android/app/src/com/android/bluetooth/avrcp/AvrcpVolumeManager.java @@ -1,5 +1,5 @@ /* - * Copyright 2018 The Android Open Source Project + * Copyright (C) 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. @@ -34,6 +34,7 @@ import com.android.bluetooth.btservice.AdapterService; import com.android.internal.annotations.VisibleForTesting; import java.util.HashMap; +import java.util.Locale; import java.util.Map; import java.util.Objects; import java.util.concurrent.CompletableFuture; @@ -458,8 +459,12 @@ class AvrcpVolumeManager extends AudioDeviceCallback { if (value instanceof Integer) { sb.append( String.format( + Locale.ROOT, " %-17s : %-14s : %3d : %s\n", - d.getAddress(), deviceName, (Integer) value, absoluteVolume)); + d.getAddress(), + deviceName, + (Integer) value, + absoluteVolume)); } } diff --git a/android/app/src/com/android/bluetooth/avrcpcontroller/AvrcpControllerNativeInterface.java b/android/app/src/com/android/bluetooth/avrcpcontroller/AvrcpControllerNativeInterface.java index 0b29c00f3e..345c4ef4d7 100644 --- a/android/app/src/com/android/bluetooth/avrcpcontroller/AvrcpControllerNativeInterface.java +++ b/android/app/src/com/android/bluetooth/avrcpcontroller/AvrcpControllerNativeInterface.java @@ -1,5 +1,5 @@ /* - * Copyright 2023 The Android Open Source Project + * Copyright (C) 2023 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. 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..8b987e301d 100644 --- a/android/app/src/com/android/bluetooth/avrcpcontroller/AvrcpControllerStateMachine.java +++ b/android/app/src/com/android/bluetooth/avrcpcontroller/AvrcpControllerStateMachine.java @@ -38,12 +38,10 @@ import android.support.v4.media.session.PlaybackStateCompat; import android.util.Log; import android.util.SparseArray; -import com.android.bluetooth.BluetoothMetricsProto; import com.android.bluetooth.R; import com.android.bluetooth.Utils; import com.android.bluetooth.a2dpsink.A2dpSinkService; import com.android.bluetooth.btservice.AdapterService; -import com.android.bluetooth.btservice.MetricsLogger; import com.android.bluetooth.btservice.ProfileService; import com.android.bluetooth.flags.Flags; import com.android.internal.annotations.VisibleForTesting; @@ -722,8 +720,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 @@ -1405,10 +1403,7 @@ class AvrcpControllerStateMachine extends StateMachine { if (mMostRecentState == currentState) { return; } - if (currentState == STATE_CONNECTED) { - MetricsLogger.logProfileConnectionEvent( - BluetoothMetricsProto.ProfileId.AVRCP_CONTROLLER); - } + mAdapterService.updateProfileConnectionAdapterProperties( mDevice, BluetoothProfile.AVRCP_CONTROLLER, currentState, mMostRecentState); 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/avrcpcontroller/BluetoothMediaBrowserService.java b/android/app/src/com/android/bluetooth/avrcpcontroller/BluetoothMediaBrowserService.java index e0becffe60..c72077423f 100644 --- a/android/app/src/com/android/bluetooth/avrcpcontroller/BluetoothMediaBrowserService.java +++ b/android/app/src/com/android/bluetooth/avrcpcontroller/BluetoothMediaBrowserService.java @@ -186,7 +186,7 @@ public class BluetoothMediaBrowserService extends MediaBrowserServiceCompat { * the media ID is invalid. 5. ERROR_NO_AVRCP_SERVICE - Contents could not be retrieved as * AvrcpControllerService is not connected. */ - public static class BrowseResult { + record BrowseResult(List<MediaItem> results, byte status) { // Possible statuses for onLoadChildren public static final byte SUCCESS = 0x00; public static final byte DOWNLOAD_PENDING = 0x01; @@ -194,19 +194,8 @@ public class BluetoothMediaBrowserService extends MediaBrowserServiceCompat { public static final byte ERROR_MEDIA_ID_INVALID = 0x03; public static final byte ERROR_NO_AVRCP_SERVICE = 0x04; - private final List<MediaItem> mResults; - private final byte mStatus; - - List<MediaItem> getResults() { - return mResults; - } - - byte getStatus() { - return mStatus; - } - String getStatusString() { - switch (mStatus) { + switch (status) { case DOWNLOAD_PENDING: return "DOWNLOAD_PENDING"; case SUCCESS: @@ -221,11 +210,6 @@ public class BluetoothMediaBrowserService extends MediaBrowserServiceCompat { return "UNDEFINED_ERROR_CASE"; } } - - BrowseResult(List<MediaItem> results, byte status) { - mResults = results; - mStatus = status; - } } BrowseResult getContents(final String parentMediaId) { @@ -275,8 +259,8 @@ public class BluetoothMediaBrowserService extends MediaBrowserServiceCompat { final String parentMediaId, final Result<List<MediaItem>> result) { Log.d(TAG, "Request for contents, id= " + parentMediaId); BrowseResult contents = getContents(parentMediaId); - byte status = contents.getStatus(); - List<MediaItem> results = contents.getResults(); + byte status = contents.status(); + List<MediaItem> results = contents.results(); if (status == BrowseResult.DOWNLOAD_PENDING && results == null) { Log.i(TAG, "Download pending - no results, id= " + parentMediaId); result.detach(); diff --git a/android/app/src/com/android/bluetooth/avrcpcontroller/BrowseTree.java b/android/app/src/com/android/bluetooth/avrcpcontroller/BrowseTree.java index dfb48897c7..573dc423b8 100644 --- a/android/app/src/com/android/bluetooth/avrcpcontroller/BrowseTree.java +++ b/android/app/src/com/android/bluetooth/avrcpcontroller/BrowseTree.java @@ -25,8 +25,7 @@ import android.util.Log; import com.android.bluetooth.Utils; import com.android.bluetooth.flags.Flags; - -import com.google.common.annotations.VisibleForTesting; +import com.android.internal.annotations.VisibleForTesting; import java.util.ArrayList; import java.util.Collections; diff --git a/android/app/src/com/android/bluetooth/avrcpcontroller/bip/BipEncoding.java b/android/app/src/com/android/bluetooth/avrcpcontroller/bip/BipEncoding.java index b64572e094..05343c9d50 100644 --- a/android/app/src/com/android/bluetooth/avrcpcontroller/bip/BipEncoding.java +++ b/android/app/src/com/android/bluetooth/avrcpcontroller/bip/BipEncoding.java @@ -18,9 +18,8 @@ package com.android.bluetooth.avrcpcontroller; import android.util.SparseArray; -import com.google.common.base.Ascii; - import java.util.HashMap; +import java.util.Locale; import java.util.Objects; /** @@ -86,7 +85,7 @@ public class BipEncoding { if (encoding == null) { throw new ParseException("Encoding input invalid"); } - encoding = Ascii.toUpperCase(encoding.trim()); + encoding = encoding.trim().toUpperCase(Locale.ROOT); mType = determineEncoding(encoding); String proprietaryEncodingId = null; @@ -120,7 +119,7 @@ public class BipEncoding { throw new IllegalArgumentException( "Received invalid user defined encoding id '" + proprietaryId + "'"); } - proprietaryEncodingId = Ascii.toUpperCase(proprietaryId); + proprietaryEncodingId = proprietaryId.toUpperCase(Locale.ROOT); } mProprietaryEncodingId = proprietaryEncodingId; } diff --git a/android/app/src/com/android/bluetooth/avrcpcontroller/bip/BipTransformation.java b/android/app/src/com/android/bluetooth/avrcpcontroller/bip/BipTransformation.java index 2e2818d97b..e75b2738c3 100644 --- a/android/app/src/com/android/bluetooth/avrcpcontroller/bip/BipTransformation.java +++ b/android/app/src/com/android/bluetooth/avrcpcontroller/bip/BipTransformation.java @@ -19,9 +19,8 @@ package com.android.bluetooth.avrcpcontroller; import android.annotation.SuppressLint; import android.util.Log; -import com.google.common.base.Ascii; - import java.util.HashSet; +import java.util.Locale; import java.util.Objects; /** @@ -57,7 +56,7 @@ public class BipTransformation { public BipTransformation(String transformations) { if (transformations == null) return; - transformations = Ascii.toLowerCase(transformations.trim()); + transformations = transformations.trim().toLowerCase(Locale.ROOT); String[] tokens = transformations.split(" "); for (String token : tokens) { switch (token) { diff --git a/android/app/src/com/android/bluetooth/avrcpcontroller/bip/ParseException.java b/android/app/src/com/android/bluetooth/avrcpcontroller/bip/ParseException.java index bd23be2972..ee00cef211 100644 --- a/android/app/src/com/android/bluetooth/avrcpcontroller/bip/ParseException.java +++ b/android/app/src/com/android/bluetooth/avrcpcontroller/bip/ParseException.java @@ -1,5 +1,5 @@ /* - * Copyright 2019 The Android Open Source Project + * Copyright (C) 2019 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. diff --git a/android/app/src/com/android/bluetooth/bas/BatteryService.java b/android/app/src/com/android/bluetooth/bas/BatteryService.java index ac5eaab2f9..0b32dbf837 100644 --- a/android/app/src/com/android/bluetooth/bas/BatteryService.java +++ b/android/app/src/com/android/bluetooth/bas/BatteryService.java @@ -1,5 +1,5 @@ /* - * Copyright 2022 The Android Open Source Project + * Copyright (C) 2022 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. diff --git a/android/app/src/com/android/bluetooth/bas/BatteryStateMachine.java b/android/app/src/com/android/bluetooth/bas/BatteryStateMachine.java index 991a77cb93..62be4fb838 100644 --- a/android/app/src/com/android/bluetooth/bas/BatteryStateMachine.java +++ b/android/app/src/com/android/bluetooth/bas/BatteryStateMachine.java @@ -1,5 +1,5 @@ /* - * Copyright 2022 The Android Open Source Project + * Copyright (C) 2022 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. diff --git a/android/app/src/com/android/bluetooth/bass_client/BaseData.java b/android/app/src/com/android/bluetooth/bass_client/BaseData.java index ee768d5a2d..200bfe76a3 100644 --- a/android/app/src/com/android/bluetooth/bass_client/BaseData.java +++ b/android/app/src/com/android/bluetooth/bass_client/BaseData.java @@ -1,5 +1,5 @@ /* - * Copyright 2022 The Android Open Source Project + * Copyright (C) 2022 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. @@ -27,7 +27,11 @@ import java.util.Locale; import java.util.MissingResourceException; /** Helper class to parse the Broadcast Announcement BASE data */ -class BaseData { +record BaseData( + BaseInformation levelOne, + List<BaseInformation> levelTwo, + List<BaseInformation> levelThree, + int numberOfBISIndices) { private static final String TAG = BassClientService.TAG + "." + BaseData.class.getSimpleName(); private static final int METADATA_LEVEL1 = 1; @@ -51,77 +55,58 @@ class BaseData { private static final int CODEC_AUDIO_FRAME_DURATION_7P5MS = 0x00; private static final int CODEC_AUDIO_FRAME_DURATION_10MS = 0x01; - private final BaseInformation mLevelOne; - private final List<BaseInformation> mLevelTwo; - private final List<BaseInformation> mLevelThree; - - private int mNumBISIndices = 0; - - public static class BaseInformation { - public byte[] presentationDelay = new byte[3]; - public byte[] codecId = new byte[5]; - public int codecConfigLength; - public byte[] codecConfigInfo; - public int metaDataLength; - public byte[] metaData; - public byte numSubGroups; - public byte index; - public int subGroupId; - public int level; + static class BaseInformation { + final byte[] mPresentationDelay = new byte[3]; + final byte[] mCodecId = new byte[5]; + int mCodecConfigLength; + byte[] mCodecConfigInfo; + int mMetaDataLength; + byte[] mMetaData; + byte mNumSubGroups; + byte mIndex; + int mSubGroupId; + int mLevel; BaseInformation() { - presentationDelay = new byte[3]; - codecId = new byte[5]; - codecConfigLength = 0; - codecConfigInfo = new byte[0]; - metaDataLength = 0; - metaData = new byte[0]; - numSubGroups = 0; - index = (byte) 0xFF; - level = 0; + mCodecConfigLength = 0; + mCodecConfigInfo = new byte[0]; + mMetaDataLength = 0; + mMetaData = new byte[0]; + mNumSubGroups = 0; + mIndex = (byte) 0xFF; + mLevel = 0; log("BaseInformation is Initialized"); } void print() { log("**BEGIN: Base Information**"); - log("**Level: " + level + "***"); - if (level == 1) { - log("presentationDelay: " + Arrays.toString(presentationDelay)); + log("**Level: " + mLevel + "***"); + if (mLevel == 1) { + log("mPresentationDelay: " + Arrays.toString(mPresentationDelay)); } - if (level == 2) { - log("codecId: " + Arrays.toString(codecId)); + if (mLevel == 2) { + log("mCodecId: " + Arrays.toString(mCodecId)); } - if (level == 2 || level == 3) { - log("codecConfigLength: " + codecConfigLength); - log("subGroupId: " + subGroupId); + if (mLevel == 2 || mLevel == 3) { + log("mCodecConfigLength: " + mCodecConfigLength); + log("mSubGroupId: " + mSubGroupId); } - if (codecConfigLength != 0) { - log("codecConfigInfo: " + Arrays.toString(codecConfigInfo)); + if (mCodecConfigLength != 0) { + log("mCodecConfigInfo: " + Arrays.toString(mCodecConfigInfo)); } - if (level == 2) { - log("metaDataLength: " + metaDataLength); - if (metaDataLength != 0) { - log("metaData: " + Arrays.toString(metaData)); + if (mLevel == 2) { + log("mMetaDataLength: " + mMetaDataLength); + if (mMetaDataLength != 0) { + log("metaData: " + Arrays.toString(mMetaData)); } - if (level == 1 || level == 2) { - log("numSubGroups: " + numSubGroups); + if (mLevel == 1 || mLevel == 2) { + log("mNumSubGroups: " + mNumSubGroups); } } log("**END: Base Information****"); } } - BaseData( - BaseInformation levelOne, - List<BaseInformation> levelTwo, - List<BaseInformation> levelThree, - int numOfBISIndices) { - mLevelOne = levelOne; - mLevelTwo = levelTwo; - mLevelThree = levelThree; - mNumBISIndices = numOfBISIndices; - } - static BaseData parseBaseData(byte[] serviceData) { if (serviceData == null) { Log.e(TAG, "Invalid service data for BaseData construction"); @@ -134,14 +119,14 @@ class BaseData { log("BASE input" + Arrays.toString(serviceData)); // Parse Level 1 base - levelOne.level = METADATA_LEVEL1; + levelOne.mLevel = METADATA_LEVEL1; int offset = 0; - System.arraycopy(serviceData, offset, levelOne.presentationDelay, 0, 3); + System.arraycopy(serviceData, offset, levelOne.mPresentationDelay, 0, 3); offset += METADATA_PRESENTATION_DELAY_LENGTH; - levelOne.numSubGroups = serviceData[offset++]; + levelOne.mNumSubGroups = serviceData[offset++]; levelOne.print(); - log("levelOne subgroups" + levelOne.numSubGroups); - for (int i = 0; i < (int) levelOne.numSubGroups; i++) { + log("levelOne subgroups" + levelOne.mNumSubGroups); + for (int i = 0; i < (int) levelOne.mNumSubGroups; i++) { if (offset >= serviceData.length) { Log.e(TAG, "Error: parsing Level 2"); return null; @@ -153,11 +138,11 @@ class BaseData { return null; } BaseInformation node2 = pair1.first; - numOfBISIndices += node2.numSubGroups; + numOfBISIndices += node2.mNumSubGroups; levelTwo.add(node2); node2.print(); offset = pair1.second; - for (int k = 0; k < node2.numSubGroups; k++) { + for (int k = 0; k < node2.mNumSubGroups; k++) { if (offset >= serviceData.length) { Log.e(TAG, "Error: parsing Level 3"); return null; @@ -182,19 +167,19 @@ class BaseData { byte[] serviceData, int groupIndex, int offset) { log("Parsing Level 2"); BaseInformation node = new BaseInformation(); - node.level = METADATA_LEVEL2; - node.subGroupId = groupIndex; + node.mLevel = METADATA_LEVEL2; + node.mSubGroupId = groupIndex; int bufferLengthLeft = (serviceData.length - offset); - // Min. length expected is: codecID (5) + numBis (1) + codecSpecCfgLen (1) + metadataLen (1) + // Min. length expected is: mCodecID(5) + numBis(1) + codecSpecCfgLen(1) + metadataLen(1) final int minNodeBufferLen = METADATA_CODEC_LENGTH + 3; if (bufferLengthLeft < minNodeBufferLen) { Log.e(TAG, "Error: Invalid Lvl2 buffer length."); return null; } - node.numSubGroups = serviceData[offset++]; // NumBis - System.arraycopy(serviceData, offset, node.codecId, 0, METADATA_CODEC_LENGTH); + node.mNumSubGroups = serviceData[offset++]; // NumBis + System.arraycopy(serviceData, offset, node.mCodecId, 0, METADATA_CODEC_LENGTH); offset += METADATA_CODEC_LENGTH; // Declared codec specific data length @@ -207,10 +192,11 @@ class BaseData { } if (declaredLength != 0) { - node.codecConfigLength = declaredLength; - node.codecConfigInfo = new byte[node.codecConfigLength]; - System.arraycopy(serviceData, offset, node.codecConfigInfo, 0, node.codecConfigLength); - offset += node.codecConfigLength; + node.mCodecConfigLength = declaredLength; + node.mCodecConfigInfo = new byte[node.mCodecConfigLength]; + System.arraycopy( + serviceData, offset, node.mCodecConfigInfo, 0, node.mCodecConfigLength); + offset += node.mCodecConfigLength; } // Verify the buffer size left @@ -229,10 +215,10 @@ class BaseData { } if (declaredLength != 0) { - node.metaDataLength = declaredLength; - node.metaData = new byte[node.metaDataLength]; - System.arraycopy(serviceData, offset, node.metaData, 0, node.metaDataLength); - offset += node.metaDataLength; + node.mMetaDataLength = declaredLength; + node.mMetaData = new byte[node.mMetaDataLength]; + System.arraycopy(serviceData, offset, node.mMetaData, 0, node.mMetaDataLength); + offset += node.mMetaDataLength; } return new Pair<BaseInformation, Integer>(node, offset); } @@ -240,7 +226,7 @@ class BaseData { private static Pair<BaseInformation, Integer> parseLevelThree(byte[] serviceData, int offset) { log("Parsing Level 3"); BaseInformation node = new BaseInformation(); - node.level = METADATA_LEVEL3; + node.mLevel = METADATA_LEVEL3; int bufferLengthLeft = (serviceData.length - offset); // Min. length expected is: bisIdx (1) + codecSpecCfgLen (1) @@ -249,7 +235,7 @@ class BaseData { Log.e(TAG, "Error: Invalid Lvl2 buffer length."); return null; } - node.index = serviceData[offset++]; + node.mIndex = serviceData[offset++]; // Verify the buffer size left int declaredLength = serviceData[offset++] & 0xff; @@ -261,10 +247,11 @@ class BaseData { } if (declaredLength != 0) { - node.codecConfigLength = declaredLength; - node.codecConfigInfo = new byte[node.codecConfigLength]; - System.arraycopy(serviceData, offset, node.codecConfigInfo, 0, node.codecConfigLength); - offset += node.codecConfigLength; + node.mCodecConfigLength = declaredLength; + node.mCodecConfigInfo = new byte[node.mCodecConfigLength]; + System.arraycopy( + serviceData, offset, node.mCodecConfigInfo, 0, node.mCodecConfigLength); + offset += node.mCodecConfigLength; } return new Pair<BaseInformation, Integer>(node, offset); } @@ -275,9 +262,9 @@ class BaseData { int children = 0; for (int i = 0; i < levelTwo.size(); i++) { startIdx = startIdx + children; - children = children + levelTwo.get(i).numSubGroups; + children = children + levelTwo.get(i).mNumSubGroups; consolidateBaseOfLevelThree( - levelTwo, levelThree, i, startIdx, levelTwo.get(i).numSubGroups); + levelTwo, levelThree, i, startIdx, levelTwo.get(i).mNumSubGroups); } } @@ -288,41 +275,25 @@ class BaseData { int startIdx, int numNodes) { for (int i = startIdx; i < startIdx + numNodes || i < levelThree.size(); i++) { - levelThree.get(i).subGroupId = levelTwo.get(parentSubgroup).subGroupId; + levelThree.get(i).mSubGroupId = levelTwo.get(parentSubgroup).mSubGroupId; } } - public int getNumberOfIndices() { - return mNumBISIndices; - } - - public BaseInformation getLevelOne() { - return mLevelOne; - } - - public List<BaseInformation> getLevelTwo() { - return mLevelTwo; - } - - public List<BaseInformation> getLevelThree() { - return mLevelThree; - } - public byte getNumberOfSubGroupsOfBIG() { byte ret = 0; - if (mLevelOne != null) { - ret = mLevelOne.numSubGroups; + if (levelOne != null) { + ret = levelOne.mNumSubGroups; } return ret; } public List<BaseInformation> getBISIndexInfos() { - return mLevelThree; + return levelThree; } byte[] getMetadata(int subGroup) { - if (mLevelTwo != null) { - return mLevelTwo.get(subGroup).metaData; + if (levelTwo != null) { + return levelTwo.get(subGroup).mMetaData; } return null; } @@ -411,15 +382,11 @@ class BaseData { } void print() { - mLevelOne.print(); + levelOne.print(); log("----- Level TWO BASE ----"); - for (int i = 0; i < mLevelTwo.size(); i++) { - mLevelTwo.get(i).print(); - } + levelTwo.stream().forEach(BaseInformation::print); log("----- Level THREE BASE ----"); - for (int i = 0; i < mLevelThree.size(); i++) { - mLevelThree.get(i).print(); - } + levelThree.stream().forEach(BaseInformation::print); } static void log(String msg) { diff --git a/android/app/src/com/android/bluetooth/bass_client/BassClientPeriodicAdvertisingManager.java b/android/app/src/com/android/bluetooth/bass_client/BassClientPeriodicAdvertisingManager.java index 28d9f79d12..f54fc44c1a 100644 --- a/android/app/src/com/android/bluetooth/bass_client/BassClientPeriodicAdvertisingManager.java +++ b/android/app/src/com/android/bluetooth/bass_client/BassClientPeriodicAdvertisingManager.java @@ -1,5 +1,5 @@ /* - * Copyright 2024 The Android Open Source Project + * Copyright (C) 2024 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. diff --git a/android/app/src/com/android/bluetooth/bass_client/BassClientService.java b/android/app/src/com/android/bluetooth/bass_client/BassClientService.java index b6e99dc2e1..2b2b495ce4 100644 --- a/android/app/src/com/android/bluetooth/bass_client/BassClientService.java +++ b/android/app/src/com/android/bluetooth/bass_client/BassClientService.java @@ -1,5 +1,5 @@ /* - * Copyright 2022 The Android Open Source Project + * Copyright (C) 2022 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. @@ -212,7 +212,6 @@ public class BassClientService extends ProfileService { private static final int LOG_NB_EVENTS = 100; private static final BluetoothEventLogger sEventLogger = new BluetoothEventLogger(LOG_NB_EVENTS, TAG + " event log"); - ; @VisibleForTesting ServiceFactory mServiceFactory = new ServiceFactory(); @@ -524,42 +523,22 @@ public class BassClientService extends ProfileService { return BluetoothProperties.isProfileBapBroadcastAssistEnabled().orElse(false); } - private static class SourceSyncRequest { - private final ScanResult mScanResult; - private final boolean mHasPriority; - private final int mSyncFailureCounter; - - SourceSyncRequest(ScanResult scanResult, boolean hasPriority, int syncFailureCounter) { - this.mScanResult = scanResult; - this.mHasPriority = hasPriority; - this.mSyncFailureCounter = syncFailureCounter; - } - - public ScanResult getScanResult() { - return mScanResult; - } + private record SourceSyncRequest( + ScanResult scanResult, boolean hasPriority, int syncFailureCounter) { public int getRssi() { - return mScanResult.getRssi(); - } - - public boolean hasPriority() { - return mHasPriority; - } - - public int getFailsCounter() { - return mSyncFailureCounter; + return scanResult.getRssi(); } @Override public String toString() { return "SourceSyncRequest{" - + "mScanResult=" - + mScanResult - + ", mHasPriority=" - + mHasPriority - + ", mSyncFailureCounter=" - + mSyncFailureCounter + + "scanResult=" + + scanResult + + ", hasPriority=" + + hasPriority + + ", syncFailureCounter=" + + syncFailureCounter + '}'; } } @@ -568,33 +547,21 @@ public class BassClientService extends ProfileService { new Comparator<SourceSyncRequest>() { @Override public int compare(SourceSyncRequest ssr1, SourceSyncRequest ssr2) { - if (ssr1.hasPriority() && !ssr2.hasPriority()) { + if (ssr1.hasPriority && !ssr2.hasPriority) { return -1; - } else if (!ssr1.hasPriority() && ssr2.hasPriority()) { + } else if (!ssr1.hasPriority && ssr2.hasPriority) { return 1; } else if (leaudioSortScansToSyncByFails() - && (ssr1.getFailsCounter() != ssr2.getFailsCounter())) { - return Integer.compare(ssr1.getFailsCounter(), ssr2.getFailsCounter()); + && (ssr1.syncFailureCounter != ssr2.syncFailureCounter)) { + return Integer.compare(ssr1.syncFailureCounter, ssr2.syncFailureCounter); } else { return Integer.compare(ssr2.getRssi(), ssr1.getRssi()); } } }; - private static class AddSourceData { - final BluetoothDevice mSink; - final BluetoothLeBroadcastMetadata mSourceMetadata; - final boolean mIsGroupOp; - - AddSourceData( - BluetoothDevice sink, - BluetoothLeBroadcastMetadata sourceMetadata, - boolean isGroupOp) { - mSink = sink; - mSourceMetadata = sourceMetadata; - mIsGroupOp = isGroupOp; - } - } + private record AddSourceData( + BluetoothDevice sink, BluetoothLeBroadcastMetadata sourceMetadata, boolean isGroupOp) {} void updatePeriodicAdvertisementResultMap( BluetoothDevice device, @@ -1054,8 +1021,7 @@ public class BassClientService extends ProfileService { /* Don't bother active group (external broadcaster scenario) with SOUND EFFECTS */ if (!mIsAllowedContextOfActiveGroupModified && isDevicePartOfActiveUnicastGroup(sink)) { leAudioService.setActiveGroupAllowedContextMask( - BluetoothLeAudio.CONTEXTS_ALL - & ~BluetoothLeAudio.CONTEXT_TYPE_SOUND_EFFECTS, + BluetoothLeAudio.CONTEXTS_ALL & ~BluetoothLeAudio.CONTEXT_TYPE_SOUND_EFFECTS, BluetoothLeAudio.CONTEXTS_ALL); mIsAllowedContextOfActiveGroupModified = true; } @@ -1626,7 +1592,7 @@ public class BassClientService extends ProfileService { } synchronized (mPendingSourcesToAdd) { mPendingSourcesToAdd.removeIf( - pendingSourcesToAdd -> pendingSourcesToAdd.mSink.equals(device)); + pendingSourcesToAdd -> pendingSourcesToAdd.sink.equals(device)); } int bondState = mAdapterService.getBondState(device); @@ -1837,7 +1803,6 @@ public class BassClientService extends ProfileService { devices.add(sm.getDevice()); } } - log("getConnectedDevices: " + devices); return devices; } } @@ -2152,7 +2117,7 @@ public class BassClientService extends ProfileService { while (iterator.hasNext()) { SourceSyncRequest sourceSyncRequest = iterator.next(); Integer queuedBroadcastId = - BassUtils.getBroadcastId(sourceSyncRequest.getScanResult()); + BassUtils.getBroadcastId(sourceSyncRequest.scanResult); if (!broadcastsToKeepSynced.contains(queuedBroadcastId)) { iterator.remove(); } @@ -2296,14 +2261,14 @@ public class BassClientService extends ProfileService { Iterator<AddSourceData> iterator = mPendingSourcesToAdd.iterator(); while (iterator.hasNext()) { AddSourceData pendingSourcesToAdd = iterator.next(); - if (pendingSourcesToAdd.mSourceMetadata.getBroadcastId() == broadcastId) { + if (pendingSourcesToAdd.sourceMetadata.getBroadcastId() == broadcastId) { if (!notifiedOfLost) { notifiedOfLost = true; mCallbacks.notifySourceLost(broadcastId); } mCallbacks.notifySourceAddFailed( - pendingSourcesToAdd.mSink, - pendingSourcesToAdd.mSourceMetadata, + pendingSourcesToAdd.sink, + pendingSourcesToAdd.sourceMetadata, BluetoothStatusCodes.ERROR_LOCAL_NOT_ENOUGH_RESOURCES); iterator.remove(); } @@ -2402,9 +2367,9 @@ public class BassClientService extends ProfileService { Iterator<AddSourceData> addIterator = mPendingSourcesToAdd.iterator(); while (addIterator.hasNext()) { AddSourceData pendingSourcesToAdd = addIterator.next(); - if (pendingSourcesToAdd.mSourceMetadata.getBroadcastId() + if (pendingSourcesToAdd.sourceMetadata.getBroadcastId() == broadcastId - && pendingSourcesToAdd.mSink.equals(sinkDevice)) { + && pendingSourcesToAdd.sink.equals(sinkDevice)) { addIterator.remove(); } } @@ -2418,15 +2383,15 @@ public class BassClientService extends ProfileService { Iterator<AddSourceData> iterator = mPendingSourcesToAdd.iterator(); while (iterator.hasNext()) { AddSourceData pendingSourceToAdd = iterator.next(); - if (pendingSourceToAdd.mSourceMetadata.getBroadcastId() == broadcastId) { + if (pendingSourceToAdd.sourceMetadata.getBroadcastId() == broadcastId) { boolean addSource = true; - if (pendingSourceToAdd.mIsGroupOp && !pendingSourcesToAdd.isEmpty()) { + if (pendingSourceToAdd.isGroupOp && !pendingSourcesToAdd.isEmpty()) { List<BluetoothDevice> deviceGroup = getTargetDeviceList( - pendingSourceToAdd.mSink, /* isGroupOp */ true); + pendingSourceToAdd.sink, /* isGroupOp */ true); for (AddSourceData addSourceData : pendingSourcesToAdd) { - if (addSourceData.mIsGroupOp - && deviceGroup.contains(addSourceData.mSink)) { + if (addSourceData.isGroupOp + && deviceGroup.contains(addSourceData.sink)) { addSource = false; } } @@ -2439,9 +2404,9 @@ public class BassClientService extends ProfileService { } for (AddSourceData addSourceData : pendingSourcesToAdd) { addSource( - addSourceData.mSink, - addSourceData.mSourceMetadata, - addSourceData.mIsGroupOp); + addSourceData.sink, + addSourceData.sourceMetadata, + addSourceData.isGroupOp); } } handleSelectSourceRequest(); @@ -2589,8 +2554,7 @@ public class BassClientService extends ProfileService { synchronized (mPendingSourcesToAdd) { mPendingSourcesToAdd.removeIf( pendingSourcesToAdd -> - pendingSourcesToAdd.mSourceMetadata.getBroadcastId() - == broadcastId); + pendingSourcesToAdd.sourceMetadata.getBroadcastId() == broadcastId); } synchronized (mSinksWaitingForPast) { mSinksWaitingForPast @@ -2611,19 +2575,19 @@ public class BassClientService extends ProfileService { BaseData baseData, BluetoothDevice device, int syncHandle, boolean encrypted) { BluetoothLeBroadcastMetadata.Builder metaData = new BluetoothLeBroadcastMetadata.Builder(); int index = 0; - for (BaseData.BaseInformation baseLevel2 : baseData.getLevelTwo()) { + for (BaseData.BaseInformation baseLevel2 : baseData.levelTwo()) { BluetoothLeBroadcastSubgroup.Builder subGroup = new BluetoothLeBroadcastSubgroup.Builder(); - for (int j = 0; j < baseLevel2.numSubGroups; j++) { - BaseData.BaseInformation baseLevel3 = baseData.getLevelThree().get(index++); + for (int j = 0; j < baseLevel2.mNumSubGroups; j++) { + BaseData.BaseInformation baseLevel3 = baseData.levelThree().get(index++); BluetoothLeBroadcastChannel.Builder channel = new BluetoothLeBroadcastChannel.Builder(); - channel.setChannelIndex(baseLevel3.index); + channel.setChannelIndex(baseLevel3.mIndex); channel.setSelected(false); try { channel.setCodecMetadata( BluetoothLeAudioCodecConfigMetadata.fromRawBytes( - baseLevel3.codecConfigInfo)); + baseLevel3.mCodecConfigInfo)); } catch (IllegalArgumentException e) { Log.w(TAG, "Invalid metadata, adding empty data. Error: " + e); channel.setCodecMetadata( @@ -2631,7 +2595,7 @@ public class BassClientService extends ProfileService { } subGroup.addChannel(channel.build()); } - byte[] arrayCodecId = baseLevel2.codecId; + byte[] arrayCodecId = baseLevel2.mCodecId; long codeId = ((long) (arrayCodecId[4] & 0xff)) << 32 | (arrayCodecId[3] & 0xff) << 24 @@ -2642,7 +2606,7 @@ public class BassClientService extends ProfileService { try { subGroup.setCodecSpecificConfig( BluetoothLeAudioCodecConfigMetadata.fromRawBytes( - baseLevel2.codecConfigInfo)); + baseLevel2.mCodecConfigInfo)); } catch (IllegalArgumentException e) { Log.w(TAG, "Invalid config, adding empty one. Error: " + e); subGroup.setCodecSpecificConfig( @@ -2651,7 +2615,7 @@ public class BassClientService extends ProfileService { try { subGroup.setContentMetadata( - BluetoothLeAudioContentMetadata.fromRawBytes(baseLevel2.metaData)); + BluetoothLeAudioContentMetadata.fromRawBytes(baseLevel2.mMetaData)); } catch (IllegalArgumentException e) { Log.w(TAG, "Invalid metadata, adding empty one. Error: " + e); subGroup.setContentMetadata( @@ -2661,7 +2625,7 @@ public class BassClientService extends ProfileService { metaData.addSubgroup(subGroup.build()); } metaData.setSourceDevice(device, device.getAddressType()); - byte[] arrayPresentationDelay = baseData.getLevelOne().presentationDelay; + byte[] arrayPresentationDelay = baseData.levelOne().mPresentationDelay; int presentationDelay = (int) ((arrayPresentationDelay[2] & 0xff) << 16 @@ -2798,13 +2762,6 @@ public class BassClientService extends ProfileService { } void addSelectSourceRequest(int broadcastId, boolean hasPriority) { - sEventLogger.logd( - TAG, - "Add Select Broadcast Source, broadcastId: " - + broadcastId - + ", hasPriority: " - + hasPriority); - if (getActiveSyncedSources().contains(getSyncHandleForBroadcastId(broadcastId))) { log("addSelectSourceRequest: Already synced"); return; @@ -2815,6 +2772,13 @@ public class BassClientService extends ProfileService { return; } + sEventLogger.logd( + TAG, + "Add Select Broadcast Source, broadcastId: " + + broadcastId + + ", hasPriority: " + + hasPriority); + ScanResult scanRes = getCachedBroadcast(broadcastId); if (scanRes == null) { log("addSelectSourceRequest: ScanResult empty"); @@ -2857,7 +2821,7 @@ public class BassClientService extends ProfileService { return; } - scanRes = mSourceSyncRequestsQueue.poll().getScanResult(); + scanRes = mSourceSyncRequestsQueue.poll().scanResult; ScanRecord scanRecord = scanRes.getScanRecord(); sEventLogger.logd(TAG, "Select Broadcast Source, result: " + scanRes); @@ -3125,8 +3089,8 @@ public class BassClientService extends ProfileService { } for (SourceSyncRequest sourceSyncRequest : mSourceSyncRequestsQueue) { - if (BassUtils.getBroadcastId(sourceSyncRequest.getScanResult()) == broadcastId) { - return !priorityImportant || sourceSyncRequest.hasPriority(); + if (BassUtils.getBroadcastId(sourceSyncRequest.scanResult) == broadcastId) { + return !priorityImportant || sourceSyncRequest.hasPriority; } } } @@ -3502,25 +3466,6 @@ public class BassClientService extends ProfileService { * * @param sink representing the Broadcast Sink from which a Broadcast Source should be removed * @param sourceId source ID as delivered in onSourceAdded - */ - private void removeSourceInternal(BluetoothDevice sink, int sourceId) { - log("removeSourceInternal prepare: device: " + sink + ", sourceId: " + sourceId); - - BassClientStateMachine stateMachine = getOrCreateStateMachine(sink); - int statusCode = validateParametersForSourceOperation(stateMachine, sink, sourceId); - if (statusCode != BluetoothStatusCodes.SUCCESS) { - mCallbacks.notifySourceRemoveFailed(sink, sourceId, statusCode); - return; - } - BluetoothLeBroadcastMetadata metaData = stateMachine.getCurrentBroadcastMetadata(sourceId); - removeSourceInternal(sink, sourceId, stateMachine, metaData); - } - - /** - * Removes the Broadcast Source from a single Broadcast Sink - * - * @param sink representing the Broadcast Sink from which a Broadcast Source should be removed - * @param sourceId source ID as delivered in onSourceAdded * @param stateMachine stateMachine for this sink * @param metaData current broadcast metadata for this sink */ @@ -3577,7 +3522,6 @@ public class BassClientService extends ProfileService { * @return the list of Broadcast Receive State {@link BluetoothLeBroadcastReceiveState} */ public List<BluetoothLeBroadcastReceiveState> getAllSources(BluetoothDevice sink) { - log("getAllSources for " + sink); synchronized (mStateMachines) { BassClientStateMachine stateMachine = getOrCreateStateMachine(sink); if (stateMachine == null) { @@ -3723,9 +3667,9 @@ public class BassClientService extends ProfileService { * @param broadcastId The broadcast ID for which the receivers should be stopped or suspended */ private void suspendSourceReceivers(int broadcastId) { - log("stopSourceReceivers broadcastId: " + broadcastId); + log("suspendSourceReceivers broadcastId: " + broadcastId); - Map<BluetoothDevice, Integer> sourcesToRemove = new HashMap<>(); + List<Pair<BluetoothDevice, Integer>> sourcesToModify = new ArrayList<>(); HashSet<Integer> broadcastIdsToStopMonitoring = new HashSet<>(); for (BluetoothDevice device : getConnectedDevices()) { if (!leaudioBroadcastResyncHelper()) { @@ -3746,7 +3690,8 @@ public class BassClientService extends ProfileService { sEventLogger.logd(TAG, "Add broadcast sink to paused cache: " + device); mPausedBroadcastSinks.add(device); - sourcesToRemove.put(device, receiveState.getSourceId()); + sourcesToModify.add( + new Pair<BluetoothDevice, Integer>(device, receiveState.getSourceId())); } } else { for (BluetoothLeBroadcastReceiveState receiveState : getAllSources(device)) { @@ -3760,11 +3705,8 @@ public class BassClientService extends ProfileService { broadcastIdsToStopMonitoring.add(receiveState.getBroadcastId()); - if (!mPausedBroadcastSinks.contains(device) - || isSinkUnintentionalPauseType(receiveState.getBroadcastId())) { - // Remove device if not paused yet - sourcesToRemove.put(device, receiveState.getSourceId()); - } + sourcesToModify.add( + new Pair<BluetoothDevice, Integer>(device, receiveState.getSourceId())); sEventLogger.logd(TAG, "Add broadcast sink to paused cache: " + device); mPausedBroadcastSinks.add(device); @@ -3776,8 +3718,35 @@ public class BassClientService extends ProfileService { stopBigMonitoring(broadcastIdToStopMonitoring, /* hostInitiated */ true); } - for (Map.Entry<BluetoothDevice, Integer> entry : sourcesToRemove.entrySet()) { - removeSourceInternal(entry.getKey(), entry.getValue()); + /* Suspend all previously marked sources with modify source operation */ + for (Pair<BluetoothDevice, Integer> pair : sourcesToModify) { + BluetoothDevice device = pair.first; + + BassClientStateMachine sm = mStateMachines.get(device); + if (sm == null) { + Log.e( + TAG, + "suspendSourceReceivers: invalid state machine for device: " + pair.first); + continue; + } + + int sourceId = pair.second; + int paSyncValue = BassConstants.PA_SYNC_DO_NOT_SYNC; + BluetoothLeBroadcastMetadata metadata = sm.getCurrentBroadcastMetadata(sourceId); + + sEventLogger.logd( + TAG, + "Modify Broadcast Source: " + + ("device: " + device) + + (", sourceId: " + sourceId) + + (", PA sync value: " + paSyncValue) + + (", updatedBroadcastId: " + metadata.getBroadcastId()) + + (", updatedBroadcastName: " + metadata.getBroadcastName())); + Message message = sm.obtainMessage(BassClientStateMachine.UPDATE_BCAST_SOURCE); + message.arg1 = sourceId; + message.arg2 = paSyncValue; + message.obj = metadata; + sm.sendMessage(message); } if (leaudioBroadcastResyncHelper()) { @@ -3940,10 +3909,9 @@ public class BassClientService extends ProfileService { Iterator<AddSourceData> iterator = mPendingSourcesToAdd.iterator(); while (iterator.hasNext()) { AddSourceData pendingSourcesToAdd = iterator.next(); - if (pendingSourcesToAdd.mSink.equals(sink)) { + if (pendingSourcesToAdd.sink.equals(sink)) { Log.d(TAG, "handleBassStateReady: retry adding source with device, " + sink); - addSource( - pendingSourcesToAdd.mSink, pendingSourcesToAdd.mSourceMetadata, false); + addSource(pendingSourcesToAdd.sink, pendingSourcesToAdd.sourceMetadata, false); iterator.remove(); return; } @@ -3958,10 +3926,10 @@ public class BassClientService extends ProfileService { Iterator<AddSourceData> iterator = mPendingSourcesToAdd.iterator(); while (iterator.hasNext()) { AddSourceData pendingSourcesToAdd = iterator.next(); - if (pendingSourcesToAdd.mSink.equals(sink)) { + if (pendingSourcesToAdd.sink.equals(sink)) { mCallbacks.notifySourceAddFailed( - pendingSourcesToAdd.mSink, - pendingSourcesToAdd.mSourceMetadata, + pendingSourcesToAdd.sink, + pendingSourcesToAdd.sourceMetadata, BluetoothStatusCodes.ERROR_REMOTE_NOT_ENOUGH_RESOURCES); iterator.remove(); return; @@ -4232,12 +4200,11 @@ public class BassClientService extends ProfileService { if ((leaudioMonitorUnicastSourceWhenManagedByBroadcastDelegator() && hasPrimaryDeviceManagedExternalBroadcast()) || (!leaudioMonitorUnicastSourceWhenManagedByBroadcastDelegator() - && areReceiversReceivingOnlyExternalBroadcast(getConnectedDevices()))) { + && areReceiversReceivingOnlyExternalBroadcast(getConnectedDevices()))) { cacheSuspendingSources(BassConstants.INVALID_BROADCAST_ID); List<Pair<BluetoothLeBroadcastReceiveState, BluetoothDevice>> sourcesToStop = getReceiveStateDevicePairs(BassConstants.INVALID_BROADCAST_ID); - for (Pair<BluetoothLeBroadcastReceiveState, BluetoothDevice> pair : - sourcesToStop) { + for (Pair<BluetoothLeBroadcastReceiveState, BluetoothDevice> pair : sourcesToStop) { stopBigMonitoring(pair.first.getBroadcastId(), /* hostInitiated */ true); } } @@ -4417,53 +4384,38 @@ public class BassClientService extends ProfileService { } private Set<Integer> getBroadcastIdsOfSyncedBroadcasters() { - HashSet<Integer> broadcastIds = new HashSet<>(); - List<Integer> activeSyncedSrc = new ArrayList<>(getActiveSyncedSources()); - for (int syncHandle : activeSyncedSrc) { - broadcastIds.add(getBroadcastIdForSyncHandle(syncHandle)); - } - return broadcastIds; + return getActiveSyncedSources().stream() + .map(this::getBroadcastIdForSyncHandle) + .collect(Collectors.toCollection(HashSet::new)); } private Set<Integer> getBroadcastIdsWaitingForPAST() { - HashSet<Integer> broadcastIds = new HashSet<>(); synchronized (mSinksWaitingForPast) { - for (Map.Entry<BluetoothDevice, Pair<Integer, Integer>> entry : - mSinksWaitingForPast.entrySet()) { - broadcastIds.add(entry.getValue().first); - } + return mSinksWaitingForPast.values().stream() + .map(pair -> pair.first) + .collect(Collectors.toCollection(HashSet::new)); } - return broadcastIds; } private Set<Integer> getBroadcastIdsWaitingForAddSource() { - HashSet<Integer> broadcastIds = new HashSet<>(); synchronized (mPendingSourcesToAdd) { - for (AddSourceData pendingSourcesToAdd : mPendingSourcesToAdd) { - broadcastIds.add(pendingSourcesToAdd.mSourceMetadata.getBroadcastId()); - } + return mPendingSourcesToAdd.stream() + .map(pendingSource -> pendingSource.sourceMetadata.getBroadcastId()) + .collect(Collectors.toCollection(HashSet::new)); } - return broadcastIds; } private Set<Integer> getPausedBroadcastIdsBasedOnSinks() { - HashSet<Integer> broadcastIds = new HashSet<>(); - for (BluetoothDevice pausedSink : mPausedBroadcastSinks) { - Map<Integer, BluetoothLeBroadcastMetadata> entry = - mBroadcastMetadataMap.getOrDefault(pausedSink, Collections.emptyMap()); - broadcastIds.addAll(entry.keySet()); - } - return broadcastIds; + return mPausedBroadcastSinks.stream() + .map(paused -> mBroadcastMetadataMap.getOrDefault(paused, Collections.emptyMap())) + .flatMap(entry -> entry.keySet().stream()) + .collect(Collectors.toCollection(HashSet::new)); } private Set<Integer> getUnintentionallyPausedBroadcastIds() { - HashSet<Integer> broadcastIds = new HashSet<>(); - for (int pausedBroadcastId : mPausedBroadcastIds.keySet()) { - if (isSinkUnintentionalPauseType(pausedBroadcastId)) { - broadcastIds.add(pausedBroadcastId); - } - } - return broadcastIds; + return mPausedBroadcastIds.keySet().stream() + .filter(this::isSinkUnintentionalPauseType) + .collect(Collectors.toCollection(HashSet::new)); } /** Handle broadcast state changed */ @@ -4536,9 +4488,9 @@ public class BassClientService extends ProfileService { case MSG_SOURCE_ADDED: case MSG_SOURCE_ADDED_FAILED: ObjParams param = (ObjParams) msg.obj; - sink = (BluetoothDevice) param.mObj1; + sink = param.device; sService.checkForPendingGroupOpRequest( - sink, reason, BassClientStateMachine.ADD_BCAST_SOURCE, param.mObj2); + sink, reason, BassClientStateMachine.ADD_BCAST_SOURCE, param.obj2); break; case MSG_SOURCE_REMOVED: case MSG_SOURCE_REMOVED_FAILED: @@ -4603,15 +4555,7 @@ public class BassClientService extends ProfileService { } } - private static class ObjParams { - final Object mObj1; - final Object mObj2; - - ObjParams(Object o1, Object o2) { - mObj1 = o1; - mObj2 = o2; - } - } + private record ObjParams(BluetoothDevice device, Object obj2) {} private static void invokeCallback( IBluetoothLeBroadcastAssistantCallback callback, Message msg) @@ -4639,14 +4583,14 @@ public class BassClientService extends ProfileService { break; case MSG_SOURCE_ADDED: param = (ObjParams) msg.obj; - sink = (BluetoothDevice) param.mObj1; + sink = param.device; callback.onSourceAdded(sink, sourceId, reason); break; case MSG_SOURCE_ADDED_FAILED: param = (ObjParams) msg.obj; - sink = (BluetoothDevice) param.mObj1; + sink = param.device; BluetoothLeBroadcastMetadata metadata = - (BluetoothLeBroadcastMetadata) param.mObj2; + (BluetoothLeBroadcastMetadata) param.obj2; callback.onSourceAddFailed(sink, metadata, reason); break; case MSG_SOURCE_MODIFIED: @@ -4665,9 +4609,9 @@ public class BassClientService extends ProfileService { break; case MSG_RECEIVESTATE_CHANGED: param = (ObjParams) msg.obj; - sink = (BluetoothDevice) param.mObj1; + sink = param.device; BluetoothLeBroadcastReceiveState state = - (BluetoothLeBroadcastReceiveState) param.mObj2; + (BluetoothLeBroadcastReceiveState) param.obj2; callback.onReceiveStateChanged(sink, sourceId, state); break; case MSG_SOURCE_LOST: diff --git a/android/app/src/com/android/bluetooth/bass_client/BassClientStateMachine.java b/android/app/src/com/android/bluetooth/bass_client/BassClientStateMachine.java index 706f886911..2ebcd5d5d2 100644 --- a/android/app/src/com/android/bluetooth/bass_client/BassClientStateMachine.java +++ b/android/app/src/com/android/bluetooth/bass_client/BassClientStateMachine.java @@ -1,5 +1,5 @@ /* - * Copyright 2022 The Android Open Source Project + * Copyright (C) 2022 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. @@ -63,8 +63,6 @@ import com.android.internal.annotations.VisibleForTesting; import com.android.internal.util.State; import com.android.internal.util.StateMachine; -import com.google.common.primitives.Bytes; - import java.io.ByteArrayOutputStream; import java.io.FileDescriptor; import java.io.PrintWriter; @@ -452,9 +450,8 @@ class BassClientStateMachine extends StateMachine { if (state == BluetoothLeBroadcastReceiveState.PA_SYNC_STATE_SYNCINFO_REQUEST) { log("Initiate PAST procedure"); int sourceId = recvState.getSourceId(); - BluetoothLeBroadcastMetadata currentMetadata = getCurrentBroadcastMetadata(sourceId); - if (mService.isLocalBroadcast(currentMetadata)) { - int advHandle = currentMetadata.getSourceAdvertisingSid(); + if (mService.isLocalBroadcast(recvState)) { + int advHandle = recvState.getSourceAdvertisingSid(); serviceData = 0x000000FF & sourceId; serviceData = serviceData << 8; // Address we set in the Source Address can differ from the address in the air @@ -763,7 +760,7 @@ class BassClientStateMachine extends StateMachine { BassConstants.BCAST_RCVR_STATE_SRC_ADDR_SIZE); byte sourceAddressType = receiverState[BassConstants.BCAST_RCVR_STATE_SRC_ADDR_TYPE_IDX]; - Bytes.reverse(sourceAddress); + Utils.reverse(sourceAddress); String address = Utils.getAddressStringFromByte(sourceAddress); BluetoothDevice device = BluetoothAdapter.getDefaultAdapter() @@ -814,8 +811,8 @@ class BassClientStateMachine extends StateMachine { } if (leaudioBroadcastResyncHelper()) { // Notify service BASS state ready for operations - mService.getCallbacks().notifyBassStateReady(mDevice); mBassStateReady = true; + mService.getCallbacks().notifyBassStateReady(mDevice); } } else { log("Updated receiver state: " + recvState); @@ -984,7 +981,7 @@ class BassClientStateMachine extends StateMachine { BassConstants.BCAST_RCVR_STATE_SRC_ADDR_SIZE); byte sourceAddressType = receiverState[BassConstants.BCAST_RCVR_STATE_SRC_ADDR_TYPE_IDX]; - Bytes.reverse(sourceAddress); + Utils.reverse(sourceAddress); String address = Utils.getAddressStringFromByte(sourceAddress); BluetoothDevice device = BluetoothAdapter.getDefaultAdapter() @@ -1191,8 +1188,8 @@ class BassClientStateMachine extends StateMachine { mNumOfReadyBroadcastReceiverStates++; if (mNumOfReadyBroadcastReceiverStates == mNumOfBroadcastReceiverStates) { // Notify service BASS state ready for operations - mService.getCallbacks().notifyBassStateReady(mDevice); mBassStateReady = true; + mService.getCallbacks().notifyBassStateReady(mDevice); } } else { processBroadcastReceiverStateObsolete( @@ -1566,7 +1563,7 @@ class BassClientStateMachine extends StateMachine { // Advertiser_Address byte[] bcastSourceAddr = Utils.getBytesFromAddress(advSource.getAddress()); - Bytes.reverse(bcastSourceAddr); + Utils.reverse(bcastSourceAddr); stream.write(bcastSourceAddr, 0, 6); // Advertising_SID diff --git a/android/app/src/com/android/bluetooth/bass_client/BassConstants.java b/android/app/src/com/android/bluetooth/bass_client/BassConstants.java index 13b0339853..e68454d829 100644 --- a/android/app/src/com/android/bluetooth/bass_client/BassConstants.java +++ b/android/app/src/com/android/bluetooth/bass_client/BassConstants.java @@ -1,5 +1,5 @@ /* - * Copyright 2022 The Android Open Source Project + * Copyright (C) 2022 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. diff --git a/android/app/src/com/android/bluetooth/bass_client/BassUtils.java b/android/app/src/com/android/bluetooth/bass_client/BassUtils.java index 69d61ce234..f84ae4c730 100644 --- a/android/app/src/com/android/bluetooth/bass_client/BassUtils.java +++ b/android/app/src/com/android/bluetooth/bass_client/BassUtils.java @@ -1,5 +1,5 @@ /* - * Copyright 2022 The Android Open Source Project + * Copyright (C) 2022 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. diff --git a/android/app/src/com/android/bluetooth/bass_client/PeriodicAdvertisementResult.java b/android/app/src/com/android/bluetooth/bass_client/PeriodicAdvertisementResult.java index e36f0de976..992e0a4c7e 100644 --- a/android/app/src/com/android/bluetooth/bass_client/PeriodicAdvertisementResult.java +++ b/android/app/src/com/android/bluetooth/bass_client/PeriodicAdvertisementResult.java @@ -1,5 +1,5 @@ /* - * Copyright 2022 The Android Open Source Project + * Copyright (C) 2022 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. diff --git a/android/app/src/com/android/bluetooth/bass_client/PublicBroadcastData.java b/android/app/src/com/android/bluetooth/bass_client/PublicBroadcastData.java index 4cd4062906..536c939b59 100644 --- a/android/app/src/com/android/bluetooth/bass_client/PublicBroadcastData.java +++ b/android/app/src/com/android/bluetooth/bass_client/PublicBroadcastData.java @@ -1,5 +1,5 @@ /* - * Copyright 2023 The Android Open Source Project + * Copyright (C) 2023 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/android/app/src/com/android/bluetooth/btservice/AdapterNativeInterface.java b/android/app/src/com/android/bluetooth/btservice/AdapterNativeInterface.java index 244e132a66..dafcc8cecc 100644 --- a/android/app/src/com/android/bluetooth/btservice/AdapterNativeInterface.java +++ b/android/app/src/com/android/bluetooth/btservice/AdapterNativeInterface.java @@ -1,5 +1,5 @@ /* - * Copyright 2023 The Android Open Source Project + * Copyright (C) 2023 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -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/AdapterProperties.java b/android/app/src/com/android/bluetooth/btservice/AdapterProperties.java index 9385004747..bd483f5925 100644 --- a/android/app/src/com/android/bluetooth/btservice/AdapterProperties.java +++ b/android/app/src/com/android/bluetooth/btservice/AdapterProperties.java @@ -24,6 +24,8 @@ import static android.bluetooth.BluetoothProfile.STATE_CONNECTING; import static android.bluetooth.BluetoothProfile.STATE_DISCONNECTED; import static android.bluetooth.BluetoothProfile.STATE_DISCONNECTING; +import static com.android.bluetooth.Utils.BD_ADDR_LEN; + import android.annotation.NonNull; import android.app.BroadcastOptions; import android.bluetooth.BluetoothA2dp; @@ -79,7 +81,6 @@ class AdapterProperties { private static final long DEFAULT_DISCOVERY_TIMEOUT_MS = 12800; @VisibleForTesting static final int BLUETOOTH_NAME_MAX_LENGTH_BYTES = 248; - private static final int BD_ADDR_LEN = 6; // in bytes private static final int SYSTEM_CONNECTION_LATENCY_METRIC = 65536; private volatile String mName; @@ -812,15 +813,10 @@ class AdapterProperties { } void adapterPropertyChangedCallback(int[] types, byte[][] values) { - if (Flags.adapterPropertiesLooper()) { - mHandler.post(() -> adapterPropertyChangedCallbackInternal(types, values)); - } else { - adapterPropertyChangedCallbackInternal(types, values); - } + mHandler.post(() -> adapterPropertyChangedCallbackInternal(types, values)); } private void adapterPropertyChangedCallbackInternal(int[] types, byte[][] values) { - Intent intent; int type; byte[] val; for (int i = 0; i < types.length; i++) { @@ -831,45 +827,21 @@ class AdapterProperties { switch (type) { case AbstractionLayer.BT_PROPERTY_BDNAME: String name = new String(val); - if (Flags.getNameAndAddressAsCallback() && name.equals(mName)) { + if (name.equals(mName)) { debugLog("Name already set: " + mName); break; } mName = name; - if (Flags.getNameAndAddressAsCallback()) { - mService.updateAdapterName(mName); - break; - } - intent = new Intent(BluetoothAdapter.ACTION_LOCAL_NAME_CHANGED); - intent.putExtra(BluetoothAdapter.EXTRA_LOCAL_NAME, mName); - intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); - mService.sendBroadcastAsUser( - intent, - UserHandle.ALL, - BLUETOOTH_CONNECT, - Utils.getTempBroadcastOptions().toBundle()); - debugLog("Name is: " + mName); + mService.updateAdapterName(mName); break; case AbstractionLayer.BT_PROPERTY_BDADDR: - if (Flags.getNameAndAddressAsCallback() && Arrays.equals(mAddress, val)) { + if (Arrays.equals(mAddress, val)) { debugLog("Address already set"); break; } mAddress = val; String address = Utils.getAddressStringFromByte(mAddress); - if (Flags.getNameAndAddressAsCallback()) { - mService.updateAdapterAddress(address); - // ACTION_BLUETOOTH_ADDRESS_CHANGED is redundant - break; - } - intent = new Intent(BluetoothAdapter.ACTION_BLUETOOTH_ADDRESS_CHANGED); - intent.putExtra(BluetoothAdapter.EXTRA_BLUETOOTH_ADDRESS, address); - intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); - mService.sendBroadcastAsUser( - intent, - UserHandle.ALL, - BLUETOOTH_CONNECT, - Utils.getTempBroadcastOptions().toBundle()); + mService.updateAdapterAddress(address); break; case AbstractionLayer.BT_PROPERTY_CLASS_OF_DEVICE: if (val == null || val.length != 3) { diff --git a/android/app/src/com/android/bluetooth/btservice/AdapterService.java b/android/app/src/com/android/bluetooth/btservice/AdapterService.java index 791b513d9d..0eeeb7f6bd 100644 --- a/android/app/src/com/android/bluetooth/btservice/AdapterService.java +++ b/android/app/src/com/android/bluetooth/btservice/AdapterService.java @@ -20,15 +20,12 @@ package com.android.bluetooth.btservice; import static android.Manifest.permission.BLUETOOTH_CONNECT; import static android.Manifest.permission.BLUETOOTH_PRIVILEGED; import static android.Manifest.permission.BLUETOOTH_SCAN; -import static android.Manifest.permission.DUMP; -import static android.Manifest.permission.LOCAL_MAC_ADDRESS; -import static android.Manifest.permission.MODIFY_PHONE_STATE; import static android.bluetooth.BluetoothAdapter.SCAN_MODE_CONNECTABLE; import static android.bluetooth.BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE; import static android.bluetooth.BluetoothAdapter.SCAN_MODE_NONE; +import static android.bluetooth.BluetoothAdapter.nameForState; import static android.bluetooth.BluetoothDevice.BATTERY_LEVEL_UNKNOWN; import static android.bluetooth.BluetoothDevice.BOND_NONE; -import static android.bluetooth.BluetoothDevice.TRANSPORT_AUTO; import static android.bluetooth.BluetoothProfile.CONNECTION_POLICY_ALLOWED; import static android.bluetooth.BluetoothProfile.CONNECTION_POLICY_FORBIDDEN; import static android.bluetooth.BluetoothProfile.CONNECTION_POLICY_UNKNOWN; @@ -36,13 +33,11 @@ import static android.bluetooth.BluetoothProfile.STATE_CONNECTED; import static android.bluetooth.BluetoothProfile.STATE_CONNECTING; import static android.bluetooth.BluetoothProfile.STATE_DISCONNECTED; import static android.bluetooth.BluetoothProfile.getProfileName; +import static android.bluetooth.BluetoothUtils.RemoteExceptionIgnoringConsumer; import static android.bluetooth.IBluetoothLeAudio.LE_AUDIO_GROUP_ID_INVALID; import static android.text.format.DateUtils.MINUTE_IN_MILLIS; import static android.text.format.DateUtils.SECOND_IN_MILLIS; -import static com.android.bluetooth.ChangeIds.ENFORCE_CONNECT; -import static com.android.bluetooth.Utils.callerIsSystem; -import static com.android.bluetooth.Utils.callerIsSystemOrActiveOrManagedUser; import static com.android.bluetooth.Utils.getBytesFromAddress; import static com.android.bluetooth.Utils.isDualModeAudioEnabled; import static com.android.bluetooth.Utils.isPackageNameAccurate; @@ -58,7 +53,6 @@ import android.app.AppOpsManager; import android.app.PendingIntent; import android.app.Service; import android.app.admin.DevicePolicyManager; -import android.app.compat.CompatChanges; import android.bluetooth.BluetoothA2dp; import android.bluetooth.BluetoothActivityEnergyInfo; import android.bluetooth.BluetoothAdapter; @@ -70,7 +64,6 @@ import android.bluetooth.BluetoothFrameworkInitializer; import android.bluetooth.BluetoothLeAudio; import android.bluetooth.BluetoothMap; import android.bluetooth.BluetoothProfile; -import android.bluetooth.BluetoothProtoEnums; import android.bluetooth.BluetoothQualityReport; import android.bluetooth.BluetoothSap; import android.bluetooth.BluetoothServerSocket; @@ -80,16 +73,12 @@ import android.bluetooth.BluetoothStatusCodes; import android.bluetooth.BluetoothUtils; import android.bluetooth.BluetoothUuid; import android.bluetooth.BufferConstraints; -import android.bluetooth.IBluetooth; -import android.bluetooth.IBluetoothActivityEnergyInfoListener; import android.bluetooth.IBluetoothCallback; import android.bluetooth.IBluetoothConnectionCallback; -import android.bluetooth.IBluetoothHciVendorSpecificCallback; import android.bluetooth.IBluetoothMetadataListener; import android.bluetooth.IBluetoothOobDataCallback; import android.bluetooth.IBluetoothPreferredAudioProfilesCallback; import android.bluetooth.IBluetoothQualityReportReadyCallback; -import android.bluetooth.IBluetoothSocketManager; import android.bluetooth.IncomingRfcommSocketInfo; import android.bluetooth.OobData; import android.bluetooth.UidTraffic; @@ -113,7 +102,6 @@ import android.os.Message; import android.os.ParcelUuid; import android.os.Parcelable; import android.os.PowerManager; -import android.os.Process; import android.os.RemoteCallbackList; import android.os.RemoteException; import android.os.SystemClock; @@ -123,12 +111,11 @@ import android.provider.DeviceConfig; import android.provider.Settings; import android.sysprop.BluetoothProperties; import android.text.TextUtils; -import android.util.Base64; import android.util.Log; import android.util.Pair; import android.util.SparseArray; -import com.android.bluetooth.BluetoothMetricsProto; +import com.android.bluetooth.BluetoothEventLogger; import com.android.bluetooth.BluetoothStatsLog; import com.android.bluetooth.R; import com.android.bluetooth.Utils; @@ -170,18 +157,10 @@ import com.android.bluetooth.telephony.BluetoothInCallService; import com.android.bluetooth.vc.VolumeControlService; import com.android.internal.annotations.GuardedBy; import com.android.internal.annotations.VisibleForTesting; -import com.android.modules.expresslog.Counter; import com.android.modules.utils.BackgroundThread; import com.android.modules.utils.BytesMatcher; -import libcore.util.SneakyThrow; - -import com.google.common.base.Ascii; -import com.google.common.collect.EvictingQueue; -import com.google.protobuf.InvalidProtocolBufferException; - import java.io.FileDescriptor; -import java.io.FileOutputStream; import java.io.IOException; import java.io.PrintWriter; import java.nio.file.FileVisitResult; @@ -195,25 +174,22 @@ import java.time.Instant; import java.util.ArrayDeque; import java.util.ArrayList; import java.util.Arrays; -import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; import java.util.List; +import java.util.Locale; import java.util.Map; import java.util.Objects; import java.util.Optional; import java.util.Set; import java.util.UUID; -import java.util.concurrent.CompletableFuture; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentLinkedQueue; import java.util.concurrent.Executor; -import java.util.function.Consumer; import java.util.function.Function; import java.util.function.Predicate; import java.util.regex.Pattern; -import java.util.stream.Collectors; public class AdapterService extends Service { private static final String TAG = @@ -225,9 +201,6 @@ public class AdapterService extends Service { private static final int MESSAGE_PREFERRED_AUDIO_PROFILES_AUDIO_FRAMEWORK_TIMEOUT = 4; private static final int CONTROLLER_ENERGY_UPDATE_TIMEOUT_MILLIS = 100; - private static final int MIN_ADVT_INSTANCES_FOR_MA = 5; - private static final int MIN_OFFLOADED_FILTERS = 10; - private static final int MIN_OFFLOADED_SCAN_STORAGE_BYTES = 1024; private static final Duration PENDING_SOCKET_HANDOFF_TIMEOUT = Duration.ofMinutes(1); private static final Duration GENERATE_LOCAL_OOB_DATA_TIMEOUT = Duration.ofSeconds(2); @@ -280,12 +253,13 @@ public class AdapterService extends Service { mPreferredAudioProfilesCallbacks = new RemoteCallbackList<>(); private final RemoteCallbackList<IBluetoothQualityReportReadyCallback> mBluetoothQualityReportReadyCallbacks = new RemoteCallbackList<>(); - private final RemoteCallbackList<IBluetoothCallback> mRemoteCallbacks = + private final RemoteCallbackList<IBluetoothCallback> mSystemServerCallbacks = new RemoteCallbackList<>(); private final RemoteCallbackList<IBluetoothConnectionCallback> mBluetoothConnectionCallbacks = new RemoteCallbackList<>(); - private final EvictingQueue<String> mScanModeChanges = EvictingQueue.create(10); + private final BluetoothEventLogger mScanModeChanges = + new BluetoothEventLogger(10, "Scan Mode Changes"); private final DeviceConfigListener mDeviceConfigListener = new DeviceConfigListener(); @@ -308,7 +282,7 @@ public class AdapterService extends Service { new ArrayList<>(); private BluetoothAdapter mAdapter; - @VisibleForTesting AdapterProperties mAdapterProperties; + private AdapterProperties mAdapterProperties; private AdapterState mAdapterStateMachine; private BondStateMachine mBondStateMachine; private RemoteDevices mRemoteDevices; @@ -421,10 +395,6 @@ public class AdapterService extends Service { return sAdapterService; } - AdapterNativeInterface getNative() { - return mNativeInterface; - } - /** Allow test to set an AdapterService to be return by AdapterService.getAdapterService() */ @VisibleForTesting public static synchronized void setAdapterService(AdapterService instance) { @@ -477,7 +447,7 @@ public class AdapterService extends Service { */ public void onProfileServiceStateChanged(ProfileService profile, int state) { if (state != BluetoothAdapter.STATE_ON && state != BluetoothAdapter.STATE_OFF) { - throw new IllegalArgumentException(BluetoothAdapter.nameForState(state)); + throw new IllegalArgumentException(nameForState(state)); } Message m = mHandler.obtainMessage(MESSAGE_PROFILE_SERVICE_STATE_CHANGED); m.obj = profile; @@ -521,10 +491,10 @@ public class AdapterService extends Service { Log.e( TAG, "Preferred audio profiles change audio framework timeout for " - + ("device " + request.mDeviceRequested)); + + ("device " + request.device)); sendPreferredAudioProfilesCallbackToApps( - request.mDeviceRequested, - request.mRequestedPreferences, + request.device, + request.preferences, BluetoothStatusCodes.ERROR_TIMEOUT); } break; @@ -615,29 +585,13 @@ public class AdapterService extends Service { * Stores information about requests made to the audio framework arising from calls to {@link * BluetoothAdapter#setPreferredAudioProfiles(BluetoothDevice, Bundle)}. */ - private static class PendingAudioProfilePreferenceRequest { - // The newly requested preferences - final Bundle mRequestedPreferences; - // Reference counter for how many calls are pending completion in the audio framework - final int mRemainingRequestsToAudioFramework; - // The device with which the request was made. Used for sending the callback. - final BluetoothDevice mDeviceRequested; - - /** - * Constructs an entity to store information about pending preferred audio profile changes. - * - * @param preferences newly requested preferences - * @param numRequestsToAudioFramework how many active device changed requests are sent to - * the audio framework - * @param device the device with which the request was made - */ - PendingAudioProfilePreferenceRequest( - Bundle preferences, int numRequestsToAudioFramework, BluetoothDevice device) { - mRequestedPreferences = preferences; - mRemainingRequestsToAudioFramework = numRequestsToAudioFramework; - mDeviceRequested = device; - } - } + private record PendingAudioProfilePreferenceRequest( + // The newly requested preferences + Bundle preferences, + // Reference counter for how many calls are pending completion in the audio framework + int numberOfRemainingRequestsToAudioFramework, + // The device with which the request was made. Used for sending the callback. + BluetoothDevice device) {} final @NonNull <T> T getNonNullSystemService(@NonNull Class<T> clazz) { return requireNonNull(getSystemService(clazz)); @@ -743,8 +697,6 @@ public class AdapterService extends Service { mActiveDeviceManager = new ActiveDeviceManager(this, new ServiceFactory()); mActiveDeviceManager.start(); - mSilenceDeviceManager.start(); - mBtCompanionManager = new CompanionManager(this, new ServiceFactory()); mBluetoothSocketManagerBinder = new BluetoothSocketManagerBinder(this); @@ -808,10 +760,76 @@ public class AdapterService extends Service { return mActiveDeviceManager; } + public RemoteDevices getRemoteDevices() { + return mRemoteDevices; + } + public SilenceDeviceManager getSilenceDeviceManager() { return mSilenceDeviceManager; } + AdapterNativeInterface getNative() { + return mNativeInterface; + } + + AdapterServiceHandler getHandler() { + return mHandler; + } + + DatabaseManager getDatabaseManager() { + return mDatabaseManager; + } + + AdapterProperties getAdapterProperties() { + return mAdapterProperties; + } + + Map<BluetoothDevice, RemoteCallbackList<IBluetoothMetadataListener>> getMetadataListeners() { + return mMetadataListeners; + } + + Map<String, CallerInfo> getBondAttemptCallerInfo() { + return mBondAttemptCallerInfo; + } + + Optional<PhonePolicy> getPhonePolicy() { + return mPhonePolicy; + } + + BondStateMachine getBondStateMachine() { + return mBondStateMachine; + } + + CompanionDeviceManager getCompanionDeviceManager() { + return mCompanionDeviceManager; + } + + BluetoothSocketManagerBinder getBluetoothSocketManagerBinder() { + return mBluetoothSocketManagerBinder; + } + + RemoteCallbackList<IBluetoothConnectionCallback> getBluetoothConnectionCallbacks() { + return mBluetoothConnectionCallbacks; + } + + RemoteCallbackList<IBluetoothPreferredAudioProfilesCallback> + getPreferredAudioProfilesCallbacks() { + return mPreferredAudioProfilesCallbacks; + } + + RemoteCallbackList<IBluetoothQualityReportReadyCallback> + getBluetoothQualityReportReadyCallbacks() { + return mBluetoothQualityReportReadyCallbacks; + } + + BluetoothHciVendorSpecificDispatcher getBluetoothHciVendorSpecificDispatcher() { + return mBluetoothHciVendorSpecificDispatcher; + } + + BluetoothHciVendorSpecificNativeInterface getBluetoothHciVendorSpecificNativeInterface() { + return mBluetoothHciVendorSpecificNativeInterface; + } + /** * Log L2CAP CoC Server Connection Metrics * @@ -1126,20 +1144,12 @@ public class AdapterService extends Service { if (mScanController == null) { mAdapterStateMachine.sendMessage(AdapterState.BLE_STOPPED); } else { - mScanController.stop(); + mScanController.cleanup(); mScanController = null; mNativeInterface.disable(); } } - private static void invalidateBluetoothGetStateCache() { - if (Flags.getStateFromSystemServer()) { - // State is managed by the system server - return; - } - BluetoothAdapter.invalidateBluetoothGetStateCache(); - } - void updateLeAudioProfileServiceState() { Set<Integer> nonSupportedProfiles = new HashSet<>(); @@ -1166,76 +1176,40 @@ public class AdapterService extends Service { } } - void updateAdapterName(String name) { - if (Flags.adapterPropertiesLooper()) { - updateAdapterNameInternal(name); - } else { - mHandler.post(() -> updateAdapterNameInternal(name)); + private void broadcastToSystemServerCallbacks( + String logAction, RemoteExceptionIgnoringConsumer<IBluetoothCallback> action) { + final int itemCount = mSystemServerCallbacks.beginBroadcast(); + Log.d(TAG, "Broadcasting [" + logAction + "] to " + itemCount + " receivers."); + for (int i = 0; i < itemCount; i++) { + action.accept(mSystemServerCallbacks.getBroadcastItem(i)); } + mSystemServerCallbacks.finishBroadcast(); } - private void updateAdapterNameInternal(String name) { - int n = mRemoteCallbacks.beginBroadcast(); - Log.d(TAG, "updateAdapterName(" + name + ")"); - for (int i = 0; i < n; i++) { - try { - mRemoteCallbacks.getBroadcastItem(i).onAdapterNameChange(name); - } catch (RemoteException e) { - Log.d(TAG, "updateAdapterName() - Callback #" + i + " failed (" + e + ")"); - } - } - mRemoteCallbacks.finishBroadcast(); + void updateAdapterName(String name) { + broadcastToSystemServerCallbacks( + "updateAdapterName(" + name + ")", (c) -> c.onAdapterNameChange(name)); } void updateAdapterAddress(String address) { - if (Flags.adapterPropertiesLooper()) { - updateAdapterAddressInternal(address); - } else { - mHandler.post(() -> updateAdapterAddressInternal(address)); - } + broadcastToSystemServerCallbacks( + "updateAdapterAddress(" + BluetoothUtils.toAnonymizedAddress(address) + ")", + (c) -> c.onAdapterAddressChange(address)); } - private void updateAdapterAddressInternal(String address) { - int n = mRemoteCallbacks.beginBroadcast(); - Log.d(TAG, "updateAdapterAddress(" + BluetoothUtils.toAnonymizedAddress(address) + ")"); - for (int i = 0; i < n; i++) { - try { - mRemoteCallbacks.getBroadcastItem(i).onAdapterAddressChange(address); - } catch (RemoteException e) { - Log.d(TAG, "updateAdapterAddress() - Callback #" + i + " failed (" + e + ")"); - } - } - mRemoteCallbacks.finishBroadcast(); - } + void updateAdapterState(int from, int to) { + mAdapterProperties.setState(to); - void updateAdapterState(int prevState, int newState) { - mAdapterProperties.setState(newState); - invalidateBluetoothGetStateCache(); - - // Only BluetoothManagerService should be registered - int n = mRemoteCallbacks.beginBroadcast(); - Log.d( - TAG, - "updateAdapterState() - Broadcasting state " - + BluetoothAdapter.nameForState(newState) - + " to " - + n - + " receivers."); - for (int i = 0; i < n; i++) { - try { - mRemoteCallbacks.getBroadcastItem(i).onBluetoothStateChange(prevState, newState); - } catch (RemoteException e) { - Log.d(TAG, "updateAdapterState() - Callback #" + i + " failed (" + e + ")"); - } - } - mRemoteCallbacks.finishBroadcast(); + broadcastToSystemServerCallbacks( + "updateAdapterState(" + nameForState(from) + ", " + nameForState(to) + ")", + (c) -> c.onBluetoothStateChange(from, to)); for (Map.Entry<BluetoothStateCallback, Executor> e : mLocalCallbacks.entrySet()) { - e.getValue().execute(() -> e.getKey().onBluetoothStateChange(prevState, newState)); + e.getValue().execute(() -> e.getKey().onBluetoothStateChange(from, to)); } // Turn the Adapter all the way off if we are disabling and the snoop log setting changed. - if (newState == BluetoothAdapter.STATE_BLE_TURNING_ON) { + if (to == BluetoothAdapter.STATE_BLE_TURNING_ON) { sSnoopLogSettingAtEnable = BluetoothProperties.snoop_log_mode() .orElse(BluetoothProperties.snoop_log_mode_values.EMPTY); @@ -1267,8 +1241,7 @@ public class AdapterService extends Service { BluetoothProperties.snoop_default_mode(value); } } - } else if (newState == BluetoothAdapter.STATE_BLE_ON - && prevState != BluetoothAdapter.STATE_OFF) { + } else if (to == BluetoothAdapter.STATE_BLE_ON && from != BluetoothAdapter.STATE_OFF) { var snoopLogSetting = BluetoothProperties.snoop_log_mode() .orElse(BluetoothProperties.snoop_log_mode_values.EMPTY); @@ -1511,7 +1484,7 @@ public class AdapterService extends Service { mBluetoothConnectionCallbacks.kill(); - mRemoteCallbacks.kill(); + mSystemServerCallbacks.kill(); mMetadataListeners.values().forEach(v -> v.kill()); } @@ -1520,9 +1493,6 @@ public class AdapterService extends Service { BluetoothAdapter.invalidateGetProfileConnectionStateCache(); BluetoothAdapter.invalidateIsOffloadedFilteringSupportedCache(); BluetoothDevice.invalidateBluetoothGetBondStateCache(); - if (!Flags.getStateFromSystemServer()) { - BluetoothAdapter.invalidateBluetoothGetStateCache(); - } BluetoothAdapter.invalidateGetAdapterConnectionStateCache(); BluetoothMap.invalidateBluetoothGetConnectionStateCache(); BluetoothSap.invalidateBluetoothGetConnectionStateCache(); @@ -1997,7 +1967,7 @@ public class AdapterService extends Service { @BluetoothAdapter.RfcommListenerResult @RequiresPermission(BLUETOOTH_CONNECT) - private int startRfcommListener( + int startRfcommListener( String name, ParcelUuid uuid, PendingIntent pendingIntent, AttributionSource source) { if (mBluetoothServerSockets.containsKey(uuid.getUuid())) { Log.d(TAG, "Cannot start RFCOMM listener: UUID " + uuid.getUuid() + "already in use."); @@ -2014,7 +1984,6 @@ public class AdapterService extends Service { } @BluetoothAdapter.RfcommListenerResult - @VisibleForTesting int stopRfcommListener(ParcelUuid uuid, AttributionSource source) { RfcommListenerData listenerData = mBluetoothServerSockets.get(uuid.getUuid()); @@ -2023,7 +1992,7 @@ public class AdapterService extends Service { return BluetoothStatusCodes.RFCOMM_LISTENER_OPERATION_FAILED_NO_MATCHING_SERVICE_RECORD; } - if (source.getUid() != listenerData.mAttributionSource.getUid()) { + if (source.getUid() != listenerData.source.getUid()) { return BluetoothStatusCodes.RFCOMM_LISTENER_OPERATION_FAILED_DIFFERENT_APP; } @@ -2033,7 +2002,6 @@ public class AdapterService extends Service { return listenerData.closeServerAndPendingSockets(mHandler); } - @VisibleForTesting IncomingRfcommSocketInfo retrievePendingSocketForServiceRecord( ParcelUuid uuid, AttributionSource source) { IncomingRfcommSocketInfo socketInfo = new IncomingRfcommSocketInfo(); @@ -2047,12 +2015,12 @@ public class AdapterService extends Service { return socketInfo; } - if (source.getUid() != listenerData.mAttributionSource.getUid()) { + if (source.getUid() != listenerData.source.getUid()) { socketInfo.status = BluetoothStatusCodes.RFCOMM_LISTENER_OPERATION_FAILED_DIFFERENT_APP; return socketInfo; } - BluetoothSocket socket = listenerData.mPendingSockets.poll(); + BluetoothSocket socket = listenerData.pendingSockets.poll(); if (socket == null) { socketInfo.status = BluetoothStatusCodes.RFCOMM_LISTENER_NO_SOCKET_AVAILABLE; @@ -2074,20 +2042,20 @@ public class AdapterService extends Service { while (true) { BluetoothSocket socket; try { - socket = listenerData.mServerSocket.accept(); + socket = listenerData.serverSocket.accept(); } catch (IOException e) { if (mBluetoothServerSockets.containsKey(uuid)) { // The uuid still being in the map indicates that the accept failure is // unexpected. Try and restart the listener. - Log.e(TAG, "Failed to accept socket on " + listenerData.mServerSocket, e); + Log.e(TAG, "Failed to accept socket on " + listenerData.serverSocket, e); restartRfcommListener(listenerData, uuid); } return; } - listenerData.mPendingSockets.add(socket); + listenerData.pendingSockets.add(socket); try { - listenerData.mPendingIntent.send(); + listenerData.pendingIntent.send(); } catch (PendingIntent.CanceledException e) { Log.e(TAG, "PendingIntent for RFCOMM socket notifications cancelled.", e); // The pending intent was cancelled, close the server as there is no longer any way @@ -2109,10 +2077,7 @@ public class AdapterService extends Service { listenerData.closeServerAndPendingSockets(mHandler); try { startRfcommListenerInternal( - listenerData.mName, - uuid, - listenerData.mPendingIntent, - listenerData.mAttributionSource); + listenerData.name, uuid, listenerData.pendingIntent, listenerData.source); } catch (IOException e) { Log.e(TAG, "Failed to recreate rfcomm server socket", e); @@ -2122,7 +2087,7 @@ public class AdapterService extends Service { private static void pendingSocketTimeoutRunnable( RfcommListenerData listenerData, BluetoothSocket socket) { - boolean socketFound = listenerData.mPendingSockets.remove(socket); + boolean socketFound = listenerData.pendingSockets.remove(socket); if (socketFound) { try { socket.close(); @@ -2141,7 +2106,8 @@ public class AdapterService extends Service { mAdapter.listenUsingRfcommWithServiceRecord(name, uuid); RfcommListenerData listenerData = - new RfcommListenerData(bluetoothServerSocket, name, intent, source); + new RfcommListenerData( + bluetoothServerSocket, name, intent, source, new ConcurrentLinkedQueue<>()); mBluetoothServerSockets.put(uuid, listenerData); @@ -2157,40 +2123,27 @@ public class AdapterService extends Service { } } - private static class RfcommListenerData { - final BluetoothServerSocket mServerSocket; - // Service record name - final String mName; - // The Intent which contains the Service info to which the incoming socket connections are - // handed off to. - final PendingIntent mPendingIntent; - // AttributionSource for the requester of the RFCOMM listener - final AttributionSource mAttributionSource; - // Contains the connected sockets which are pending transfer to the app which requested the - // listener. - final ConcurrentLinkedQueue<BluetoothSocket> mPendingSockets = - new ConcurrentLinkedQueue<>(); - - RfcommListenerData( - BluetoothServerSocket serverSocket, - String name, - PendingIntent pendingIntent, - AttributionSource source) { - mServerSocket = serverSocket; - mName = name; - mPendingIntent = pendingIntent; - mAttributionSource = source; - } + private record RfcommListenerData( + BluetoothServerSocket serverSocket, + // Service record name + String name, + // Contains the Service info to which the incoming socket connections are handed off to + PendingIntent pendingIntent, + // AttributionSource for the requester of the RFCOMM listener + AttributionSource source, + // Contains the connected sockets which are pending transfer to the app which requested + // the listener. + ConcurrentLinkedQueue<BluetoothSocket> pendingSockets) { int closeServerAndPendingSockets(Handler handler) { int result = BluetoothStatusCodes.SUCCESS; try { - mServerSocket.close(); + serverSocket.close(); } catch (IOException e) { Log.e(TAG, "Failed to call close on rfcomm server socket", e); result = BluetoothStatusCodes.RFCOMM_LISTENER_FAILED_TO_CLOSE_SERVER_SOCKET; } - mPendingSockets.forEach( + pendingSockets.forEach( pendingSocket -> { handler.removeCallbacksAndMessages(pendingSocket); try { @@ -2199,13 +2152,11 @@ public class AdapterService extends Service { Log.e(TAG, "Failed to close socket", e); } }); - mPendingSockets.clear(); - + pendingSockets.clear(); return result; } } - @VisibleForTesting boolean isAvailable() { return !mCleaningUp; } @@ -2241,2208 +2192,6 @@ public class AdapterService extends Service { } /** - * There is no leak of this binder since it is never re-used and the process is systematically - * killed - */ - @VisibleForTesting - public static class AdapterServiceBinder extends IBluetooth.Stub { - private final AdapterService mService; - - AdapterServiceBinder(AdapterService svc) { - mService = svc; - if (Flags.getStateFromSystemServer()) { - return; - } - mService.invalidateBluetoothGetStateCache(); - BluetoothAdapter.getDefaultAdapter().disableBluetoothGetStateCache(); - } - - public AdapterService getService() { - if (!mService.isAvailable()) { - return null; - } - return mService; - } - - @Override - public int getState() { - AdapterService service = getService(); - if (service == null) { - return BluetoothAdapter.STATE_OFF; - } - - return service.getState(); - } - - @Override - public void killBluetoothProcess() { - mService.enforceCallingPermission(BLUETOOTH_PRIVILEGED, null); - - Runnable killAction = - () -> { - if (Flags.killInsteadOfExit()) { - Log.i(TAG, "killBluetoothProcess: Calling killProcess(myPid())"); - Process.killProcess(Process.myPid()); - } else { - Log.i(TAG, "killBluetoothProcess: Calling System.exit"); - System.exit(0); - } - }; - - // Post on the main handler to let the cleanup complete before calling exit - mService.mHandler.post(killAction); - - try { - // Wait for Bluetooth to be killed from its main thread - Thread.sleep(1_000); // SystemServer is waiting 2000 ms, we need to wait less here - } catch (InterruptedException e) { - Log.e(TAG, "killBluetoothProcess: Interrupted while waiting for kill"); - } - - // Bluetooth cannot be killed on the main thread; it is in a deadLock. - // Trying to recover by killing the Bluetooth from the binder thread. - // This is bad :( - Counter.logIncrement("bluetooth.value_kill_from_binder_thread"); - Log.wtf(TAG, "Failed to kill Bluetooth using its main thread. Trying from binder"); - killAction.run(); - } - - @Override - public void offToBleOn(boolean quietMode, AttributionSource source) { - AdapterService service = getService(); - if (service == null - || !callerIsSystemOrActiveOrManagedUser(service, TAG, "offToBleOn")) { - return; - } - - service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null); - - service.offToBleOn(quietMode); - } - - @Override - public void onToBleOn(AttributionSource source) { - AdapterService service = getService(); - if (service == null - || !callerIsSystemOrActiveOrManagedUser(service, TAG, "onToBleOn")) { - return; - } - - service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null); - - service.onToBleOn(); - } - - @Override - public String getAddress(AttributionSource source) { - AdapterService service = getService(); - if (service == null - || !callerIsSystemOrActiveOrManagedUser(service, TAG, "getAddress") - || !Utils.checkConnectPermissionForDataDelivery( - service, source, "AdapterService getAddress")) { - return null; - } - - service.enforceCallingOrSelfPermission(LOCAL_MAC_ADDRESS, null); - - return Utils.getAddressStringFromByte(service.mAdapterProperties.getAddress()); - } - - @Override - public List<ParcelUuid> getUuids(AttributionSource source) { - AdapterService service = getService(); - if (service == null - || !callerIsSystemOrActiveOrManagedUser(service, TAG, "getUuids") - || !Utils.checkConnectPermissionForDataDelivery( - service, source, "AdapterService getUuids")) { - return Collections.emptyList(); - } - - ParcelUuid[] parcels = service.mAdapterProperties.getUuids(); - if (parcels == null) { - parcels = new ParcelUuid[0]; - } - return Arrays.asList(parcels); - } - - @Override - public String getIdentityAddress(String address) { - AdapterService service = getService(); - if (service == null - || !callerIsSystemOrActiveOrManagedUser(service, TAG, "getIdentityAddress") - || !Utils.checkConnectPermissionForDataDelivery( - service, - Utils.getCallingAttributionSource(mService), - "AdapterService getIdentityAddress")) { - return null; - } - service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null); - return service.getIdentityAddress(address); - } - - @Override - @NonNull - public BluetoothAddress getIdentityAddressWithType(@NonNull String address) { - AdapterService service = getService(); - if (service == null - || !callerIsSystemOrActiveOrManagedUser( - service, TAG, "getIdentityAddressWithType") - || !Utils.checkConnectPermissionForDataDelivery( - service, - Utils.getCallingAttributionSource(mService), - "AdapterService getIdentityAddressWithType")) { - return new BluetoothAddress(null, BluetoothDevice.ADDRESS_TYPE_UNKNOWN); - } - service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null); - return service.getIdentityAddressWithType(address); - } - - @Override - public String getName(AttributionSource source) { - AdapterService service = getService(); - if (service == null - || !callerIsSystemOrActiveOrManagedUser(service, TAG, "getName") - || !Utils.checkConnectPermissionForDataDelivery( - service, source, "AdapterService getName")) { - return null; - } - - return service.getName(); - } - - @Override - public int getNameLengthForAdvertise(AttributionSource source) { - AdapterService service = getService(); - if (service == null - || !callerIsSystemOrActiveOrManagedUser( - service, TAG, "getNameLengthForAdvertise") - || !Utils.checkAdvertisePermissionForDataDelivery(service, source, TAG)) { - return -1; - } - - return service.getNameLengthForAdvertise(); - } - - @Override - public boolean setName(String name, AttributionSource source) { - AdapterService service = getService(); - if (service == null - || !callerIsSystemOrActiveOrManagedUser(service, TAG, "setName") - || !Utils.checkConnectPermissionForDataDelivery( - service, source, "AdapterService setName")) { - return false; - } - - if (Flags.emptyNamesAreInvalid()) { - requireNonNull(name); - name = name.trim(); - if (name.isEmpty()) { - throw new IllegalArgumentException("Empty names are not valid"); - } - } - - Log.d(TAG, "AdapterServiceBinder.setName(" + name + ")"); - return service.mAdapterProperties.setName(name); - } - - @Override - public int getScanMode(AttributionSource source) { - AdapterService service = getService(); - if (service == null - || !callerIsSystemOrActiveOrManagedUser(service, TAG, "getScanMode") - || !Utils.checkScanPermissionForDataDelivery( - service, source, "AdapterService getScanMode")) { - return SCAN_MODE_NONE; - } - - return service.getScanMode(); - } - - @Override - public int setScanMode(int mode, AttributionSource source) { - AdapterService service = getService(); - if (service == null - || !callerIsSystemOrActiveOrManagedUser(service, TAG, "setScanMode") - || !Utils.checkScanPermissionForDataDelivery( - service, source, "AdapterService setScanMode")) { - return BluetoothStatusCodes.ERROR_MISSING_BLUETOOTH_SCAN_PERMISSION; - } - service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null); - - String logCaller = Utils.getUidPidString() + " packageName=" + source.getPackageName(); - CompletableFuture<Boolean> future = new CompletableFuture<>(); - mService.mHandler.post( - () -> - future.complete( - service.getState() == BluetoothAdapter.STATE_ON - && service.setScanMode(mode, logCaller))); - return future.join() - ? BluetoothStatusCodes.SUCCESS - : BluetoothStatusCodes.ERROR_UNKNOWN; - } - - @Override - public long getDiscoverableTimeout(AttributionSource source) { - AdapterService service = getService(); - if (service == null - || !callerIsSystemOrActiveOrManagedUser(service, TAG, "getDiscoverableTimeout") - || !Utils.checkScanPermissionForDataDelivery( - service, source, "AdapterService getDiscoverableTimeout")) { - return -1; - } - - return service.mAdapterProperties.getDiscoverableTimeout(); - } - - @Override - public int setDiscoverableTimeout(long timeout, AttributionSource source) { - AdapterService service = getService(); - if (service == null - || !callerIsSystemOrActiveOrManagedUser(service, TAG, "setDiscoverableTimeout") - || !Utils.checkScanPermissionForDataDelivery( - service, source, "AdapterService setDiscoverableTimeout")) { - return BluetoothStatusCodes.ERROR_MISSING_BLUETOOTH_SCAN_PERMISSION; - } - service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null); - - return service.mAdapterProperties.setDiscoverableTimeout((int) timeout) - ? BluetoothStatusCodes.SUCCESS - : BluetoothStatusCodes.ERROR_UNKNOWN; - } - - @Override - public boolean startDiscovery(AttributionSource source) { - AdapterService service = getService(); - if (service == null - || !callerIsSystemOrActiveOrManagedUser(service, TAG, "startDiscovery")) { - return false; - } - - if (!Utils.checkScanPermissionForDataDelivery(service, source, "Starting discovery.")) { - return false; - } - - Log.i(TAG, "startDiscovery: from " + Utils.getUidPidString()); - return service.startDiscovery(source); - } - - @Override - public boolean cancelDiscovery(AttributionSource source) { - AdapterService service = getService(); - if (service == null - || !callerIsSystemOrActiveOrManagedUser(service, TAG, "cancelDiscovery") - || !Utils.checkScanPermissionForDataDelivery( - service, source, "AdapterService cancelDiscovery")) { - return false; - } - - Log.i(TAG, "cancelDiscovery: from " + Utils.getUidPidString()); - return service.mNativeInterface.cancelDiscovery(); - } - - @Override - public boolean isDiscovering(AttributionSource source) { - AdapterService service = getService(); - if (service == null - || !callerIsSystemOrActiveOrManagedUser(service, TAG, "isDiscovering") - || !Utils.checkScanPermissionForDataDelivery( - service, source, "AdapterService isDiscovering")) { - return false; - } - - return service.mAdapterProperties.isDiscovering(); - } - - @Override - public long getDiscoveryEndMillis(AttributionSource source) { - AdapterService service = getService(); - if (service == null - || !callerIsSystemOrActiveOrManagedUser(service, TAG, "getDiscoveryEndMillis") - || !Utils.checkConnectPermissionForDataDelivery(service, source, TAG)) { - return -1; - } - - service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null); - - return service.mAdapterProperties.discoveryEndMillis(); - } - - @Override - public List<BluetoothDevice> getMostRecentlyConnectedDevices(AttributionSource source) { - // don't check caller, may be called from system UI - AdapterService service = getService(); - if (service == null - || !Utils.checkConnectPermissionForDataDelivery( - service, source, "AdapterService getMostRecentlyConnectedDevices")) { - return Collections.emptyList(); - } - - service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null); - - return service.mDatabaseManager.getMostRecentlyConnectedDevices(); - } - - @Override - public List<BluetoothDevice> getBondedDevices(AttributionSource source) { - // don't check caller, may be called from system UI - AdapterService service = getService(); - if (service == null - || !Utils.checkConnectPermissionForDataDelivery( - service, source, "AdapterService getBondedDevices")) { - return Collections.emptyList(); - } - - return Arrays.asList(service.getBondedDevices()); - } - - @Override - public int getAdapterConnectionState() { - // don't check caller, may be called from system UI - AdapterService service = getService(); - if (service == null) { - return BluetoothAdapter.STATE_DISCONNECTED; - } - - return service.mAdapterProperties.getConnectionState(); - } - - /** - * This method has an associated binder cache. The invalidation methods must be changed if - * the logic behind this method changes. - */ - @Override - public int getProfileConnectionState(int profile, AttributionSource source) { - AdapterService service = getService(); - boolean checkConnect = false; - final int callingUid = Binder.getCallingUid(); - final long token = Binder.clearCallingIdentity(); - try { - checkConnect = CompatChanges.isChangeEnabled(ENFORCE_CONNECT, callingUid); - } finally { - Binder.restoreCallingIdentity(token); - } - if (service == null - || !callerIsSystemOrActiveOrManagedUser( - service, TAG, "getProfileConnectionState") - || (checkConnect - && !Utils.checkConnectPermissionForDataDelivery( - service, source, "AdapterService getProfileConnectionState"))) { - return STATE_DISCONNECTED; - } - - return service.mAdapterProperties.getProfileConnectionState(profile); - } - - @Override - public boolean createBond( - BluetoothDevice device, - int transport, - OobData remoteP192Data, - OobData remoteP256Data, - AttributionSource source) { - AdapterService service = getService(); - if (service == null - || !callerIsSystemOrActiveOrManagedUser(service, TAG, "createBond") - || !Utils.checkConnectPermissionForDataDelivery( - service, source, "AdapterService createBond")) { - return false; - } - - // This conditional is required to satisfy permission dependencies - // since createBond calls createBondOutOfBand with null value passed as data. - // BluetoothDevice#createBond requires BLUETOOTH_ADMIN only. - service.enforceBluetoothPrivilegedPermissionIfNeeded(remoteP192Data, remoteP256Data); - - Log.i( - TAG, - "createBond:" - + (" device=" + device) - + (" transport=" + transport) - + (" from " + Utils.getUidPidString())); - return service.createBond( - device, transport, remoteP192Data, remoteP256Data, source.getPackageName()); - } - - @Override - public boolean cancelBondProcess(BluetoothDevice device, AttributionSource source) { - AdapterService service = getService(); - if (service == null - || !callerIsSystemOrActiveOrManagedUser(service, TAG, "cancelBondProcess") - || !Utils.checkConnectPermissionForDataDelivery( - service, source, "AdapterService cancelBondProcess")) { - return false; - } - - service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null); - - Log.i(TAG, "cancelBondProcess: device=" + device + ", from " + Utils.getUidPidString()); - - DeviceProperties deviceProp = service.mRemoteDevices.getDeviceProperties(device); - if (deviceProp != null) { - deviceProp.setBondingInitiatedLocally(false); - } - - service.logUserBondResponse(device, false, source); - return service.mNativeInterface.cancelBond(getBytesFromAddress(device.getAddress())); - } - - @Override - public boolean removeBond(BluetoothDevice device, AttributionSource source) { - AdapterService service = getService(); - if (service == null - || !callerIsSystemOrActiveOrManagedUser(service, TAG, "removeBond") - || !Utils.checkConnectPermissionForDataDelivery( - service, source, "AdapterService removeBond")) { - return false; - } - - Log.i(TAG, "removeBond: device=" + device + ", from " + Utils.getUidPidString()); - - DeviceProperties deviceProp = service.mRemoteDevices.getDeviceProperties(device); - if (deviceProp == null || deviceProp.getBondState() != BluetoothDevice.BOND_BONDED) { - Log.w( - TAG, - device - + " cannot be removed since " - + ((deviceProp == null) - ? "properties are empty" - : "bond state is " + deviceProp.getBondState())); - return false; - } - service.logUserBondResponse(device, false, source); - service.mBondAttemptCallerInfo.remove(device.getAddress()); - service.mPhonePolicy.ifPresent(policy -> policy.onRemoveBondRequest(device)); - deviceProp.setBondingInitiatedLocally(false); - - Message msg = service.mBondStateMachine.obtainMessage(BondStateMachine.REMOVE_BOND); - msg.obj = device; - service.mBondStateMachine.sendMessage(msg); - return true; - } - - @Override - public int getBondState(BluetoothDevice device, AttributionSource source) { - // don't check caller, may be called from system UI - AdapterService service = getService(); - if (service == null - || !Utils.checkConnectPermissionForDataDelivery( - service, source, "AdapterService getBondState")) { - return BluetoothDevice.BOND_NONE; - } - - return service.getBondState(device); - } - - @Override - public boolean isBondingInitiatedLocally(BluetoothDevice device, AttributionSource source) { - // don't check caller, may be called from system UI - AdapterService service = getService(); - if (service == null - || !Utils.checkConnectPermissionForDataDelivery( - service, source, "AdapterService isBondingInitiatedLocally")) { - return false; - } - - DeviceProperties deviceProp = service.mRemoteDevices.getDeviceProperties(device); - return deviceProp != null && deviceProp.isBondingInitiatedLocally(); - } - - @Override - public void generateLocalOobData( - int transport, IBluetoothOobDataCallback callback, AttributionSource source) { - AdapterService service = getService(); - if (service == null - || !callerIsSystemOrActiveOrManagedUser(service, TAG, "generateLocalOobData") - || !Utils.checkConnectPermissionForDataDelivery(service, source, TAG)) { - return; - } - service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null); - service.generateLocalOobData(transport, callback); - } - - @Override - public long getSupportedProfiles(AttributionSource source) { - AdapterService service = getService(); - if (service == null - || !Utils.checkConnectPermissionForDataDelivery(service, source, TAG)) { - return 0; - } - service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null); - - return Config.getSupportedProfilesBitMask(); - } - - @Override - public int getConnectionState(BluetoothDevice device, AttributionSource source) { - AdapterService service = getService(); - if (service == null - || !Utils.checkConnectPermissionForDataDelivery( - service, source, "AdapterService getConnectionState")) { - return BluetoothDevice.CONNECTION_STATE_DISCONNECTED; - } - - return service.getConnectionState(device); - } - - @Override - public int getConnectionHandle( - BluetoothDevice device, int transport, AttributionSource source) { - AdapterService service = getService(); - if (service == null - || !callerIsSystemOrActiveOrManagedUser(service, TAG, "getConnectionHandle") - || !Utils.checkConnectPermissionForDataDelivery(service, source, TAG)) { - return BluetoothDevice.ERROR; - } - - service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null); - - return service.getConnectionHandle(device, transport); - } - - @Override - public boolean canBondWithoutDialog(BluetoothDevice device, AttributionSource source) { - AdapterService service = getService(); - if (service == null - || !Utils.checkConnectPermissionForDataDelivery(service, source, TAG)) { - return false; - } - - service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null); - - return service.canBondWithoutDialog(device); - } - - @Override - public String getPackageNameOfBondingApplication( - BluetoothDevice device, AttributionSource source) { - AdapterService service = getService(); - - if (service == null - || !Utils.checkConnectPermissionForDataDelivery(service, source, TAG)) { - return null; - } - - service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null); - - return service.getPackageNameOfBondingApplication(device); - } - - @Override - public boolean removeActiveDevice(@ActiveDeviceUse int profiles, AttributionSource source) { - AdapterService service = getService(); - if (service == null - || !callerIsSystemOrActiveOrManagedUser(service, TAG, "removeActiveDevice") - || !Utils.checkConnectPermissionForDataDelivery(service, source, TAG)) { - return false; - } - - service.enforceCallingOrSelfPermission(MODIFY_PHONE_STATE, null); - service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null); - - Log.i( - TAG, - "removeActiveDevice: profiles=" - + profiles - + ", from " - + Utils.getUidPidString()); - return service.setActiveDevice(null, profiles); - } - - @Override - public boolean setActiveDevice( - BluetoothDevice device, @ActiveDeviceUse int profiles, AttributionSource source) { - AdapterService service = getService(); - if (service == null - || !callerIsSystemOrActiveOrManagedUser(service, TAG, "setActiveDevice") - || !Utils.checkConnectPermissionForDataDelivery(service, source, TAG)) { - return false; - } - - service.enforceCallingOrSelfPermission(MODIFY_PHONE_STATE, null); - service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null); - - Log.i( - TAG, - "setActiveDevice: device=" - + device - + ", profiles=" - + profiles - + ", from " - + Utils.getUidPidString()); - - return service.setActiveDevice(device, profiles); - } - - @Override - public List<BluetoothDevice> getActiveDevices( - @ActiveDeviceProfile int profile, AttributionSource source) { - AdapterService service = getService(); - if (service == null - || !callerIsSystemOrActiveOrManagedUser(service, TAG, "getActiveDevices") - || !Utils.checkConnectPermissionForDataDelivery(service, source, TAG)) { - return Collections.emptyList(); - } - - service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null); - - return service.getActiveDevices(profile); - } - - @Override - public int connectAllEnabledProfiles(BluetoothDevice device, AttributionSource source) { - AdapterService service = getService(); - if (service == null || !service.isEnabled()) { - return BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ENABLED; - } - if (!callerIsSystemOrActiveOrManagedUser(service, TAG, "connectAllEnabledProfiles")) { - return BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ALLOWED; - } - if (device == null) { - throw new IllegalArgumentException("device cannot be null"); - } - if (!BluetoothAdapter.checkBluetoothAddress(device.getAddress())) { - throw new IllegalArgumentException("device cannot have an invalid address"); - } - if (!Utils.checkConnectPermissionForDataDelivery(service, source, TAG)) { - return BluetoothStatusCodes.ERROR_MISSING_BLUETOOTH_CONNECT_PERMISSION; - } - - service.enforceCallingOrSelfPermission(MODIFY_PHONE_STATE, null); - service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null); - - Log.i( - TAG, - "connectAllEnabledProfiles: device=" - + device - + ", from " - + Utils.getUidPidString()); - MetricsLogger.getInstance() - .logBluetoothEvent( - device, - BluetoothStatsLog - .BLUETOOTH_CROSS_LAYER_EVENT_REPORTED__EVENT_TYPE__INITIATOR_CONNECTION, - BluetoothStatsLog.BLUETOOTH_CROSS_LAYER_EVENT_REPORTED__STATE__START, - source.getUid()); - - try { - return service.connectAllEnabledProfiles(device); - } catch (Exception e) { - Log.v(TAG, "connectAllEnabledProfiles() failed", e); - SneakyThrow.sneakyThrow(e); - throw new RuntimeException(e); - } - } - - @Override - public int disconnectAllEnabledProfiles(BluetoothDevice device, AttributionSource source) { - AdapterService service = getService(); - if (service == null) { - return BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ENABLED; - } - if (!callerIsSystemOrActiveOrManagedUser( - service, TAG, "disconnectAllEnabledProfiles")) { - return BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ALLOWED; - } - if (device == null) { - throw new IllegalArgumentException("device cannot be null"); - } - if (!BluetoothAdapter.checkBluetoothAddress(device.getAddress())) { - throw new IllegalArgumentException("device cannot have an invalid address"); - } - if (!Utils.checkConnectPermissionForDataDelivery(service, source, TAG)) { - return BluetoothStatusCodes.ERROR_MISSING_BLUETOOTH_CONNECT_PERMISSION; - } - - service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null); - - Log.i( - TAG, - "disconnectAllEnabledProfiles: device=" - + device - + ", from " - + Utils.getUidPidString()); - - try { - return service.disconnectAllEnabledProfiles(device); - } catch (Exception e) { - Log.v(TAG, "disconnectAllEnabledProfiles() failed", e); - SneakyThrow.sneakyThrow(e); - throw new RuntimeException(e); - } - } - - @Override - public String getRemoteName(BluetoothDevice device, AttributionSource source) { - AdapterService service = getService(); - if (service == null - || !callerIsSystemOrActiveOrManagedUser(service, TAG, "getRemoteName") - || !Utils.checkConnectPermissionForDataDelivery( - service, source, "AdapterService getRemoteName")) { - return null; - } - - return service.getRemoteName(device); - } - - @Override - public int getRemoteType(BluetoothDevice device, AttributionSource source) { - AdapterService service = getService(); - if (service == null - || !callerIsSystemOrActiveOrManagedUser(service, TAG, "getRemoteType") - || !Utils.checkConnectPermissionForDataDelivery( - service, source, "AdapterService getRemoteType")) { - return BluetoothDevice.DEVICE_TYPE_UNKNOWN; - } - - return service.getRemoteType(device); - } - - @Override - public String getRemoteAlias(BluetoothDevice device, AttributionSource source) { - AdapterService service = getService(); - if (service == null - || !callerIsSystemOrActiveOrManagedUser(service, TAG, "getRemoteAlias") - || !Utils.checkConnectPermissionForDataDelivery( - service, source, "AdapterService getRemoteAlias")) { - return null; - } - - DeviceProperties deviceProp = service.mRemoteDevices.getDeviceProperties(device); - return deviceProp != null ? deviceProp.getAlias() : null; - } - - @Override - public int setRemoteAlias(BluetoothDevice device, String name, AttributionSource source) { - AdapterService service = getService(); - if (service == null) { - return BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ENABLED; - } - if (!callerIsSystemOrActiveOrManagedUser(service, TAG, "setRemoteAlias")) { - return BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ALLOWED; - } - if (name != null && name.isEmpty()) { - throw new IllegalArgumentException("alias cannot be the empty string"); - } - - if (!Utils.checkConnectPermissionForDataDelivery( - service, source, "AdapterService setRemoteAlias")) { - return BluetoothStatusCodes.ERROR_MISSING_BLUETOOTH_CONNECT_PERMISSION; - } - - Utils.enforceCdmAssociationIfNotBluetoothPrivileged( - service, service.mCompanionDeviceManager, source, device); - - DeviceProperties deviceProp = service.mRemoteDevices.getDeviceProperties(device); - if (deviceProp == null) { - return BluetoothStatusCodes.ERROR_DEVICE_NOT_BONDED; - } - deviceProp.setAlias(device, name); - return BluetoothStatusCodes.SUCCESS; - } - - @Override - public int getRemoteClass(BluetoothDevice device, AttributionSource source) { - AdapterService service = getService(); - if (service == null - || !callerIsSystemOrActiveOrManagedUser(service, TAG, "getRemoteClass") - || !Utils.checkConnectPermissionForDataDelivery( - service, source, "AdapterService getRemoteClass")) { - return 0; - } - - return service.getRemoteClass(device); - } - - @Override - public List<ParcelUuid> getRemoteUuids(BluetoothDevice device, AttributionSource source) { - AdapterService service = getService(); - if (service == null - || !callerIsSystemOrActiveOrManagedUser(service, TAG, "getRemoteUuids") - || !Utils.checkConnectPermissionForDataDelivery( - service, source, "AdapterService getRemoteUuids")) { - return Collections.emptyList(); - } - - final ParcelUuid[] parcels = service.getRemoteUuids(device); - if (parcels == null) { - return null; - } - return Arrays.asList(parcels); - } - - @Override - public boolean fetchRemoteUuids( - BluetoothDevice device, int transport, AttributionSource source) { - AdapterService service = getService(); - if (service == null - || !callerIsSystemOrActiveOrManagedUser(service, TAG, "fetchRemoteUuids") - || !Utils.checkConnectPermissionForDataDelivery( - service, source, "AdapterService fetchRemoteUuids")) { - return false; - } - if (transport != TRANSPORT_AUTO) { - service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null); - } - - Log.i( - TAG, - "fetchRemoteUuids: device=" - + device - + ", transport=" - + transport - + ", from " - + Utils.getUidPidString()); - - service.mRemoteDevices.fetchUuids(device, transport); - MetricsLogger.getInstance().cacheCount(BluetoothProtoEnums.SDP_FETCH_UUID_REQUEST, 1); - return true; - } - - @Override - public boolean setPin( - BluetoothDevice device, - boolean accept, - int len, - byte[] pinCode, - AttributionSource source) { - AdapterService service = getService(); - if (service == null - || !callerIsSystemOrActiveOrManagedUser(service, TAG, "setPin") - || !Utils.checkConnectPermissionForDataDelivery( - service, source, "AdapterService setPin")) { - return false; - } - - DeviceProperties deviceProp = service.mRemoteDevices.getDeviceProperties(device); - // Only allow setting a pin in bonding state, or bonded state in case of security - // upgrade. - if (deviceProp == null || !deviceProp.isBondingOrBonded()) { - Log.e(TAG, "setPin: device=" + device + ", not bonding"); - return false; - } - if (pinCode.length != len) { - android.util.EventLog.writeEvent( - 0x534e4554, "139287605", -1, "PIN code length mismatch"); - return false; - } - service.logUserBondResponse(device, accept, source); - Log.i( - TAG, - "setPin: device=" - + device - + ", accept=" - + accept - + ", from " - + Utils.getUidPidString()); - return service.mNativeInterface.pinReply( - getBytesFromAddress(device.getAddress()), accept, len, pinCode); - } - - @Override - public boolean setPasskey( - BluetoothDevice device, - boolean accept, - int len, - byte[] passkey, - AttributionSource source) { - AdapterService service = getService(); - if (service == null - || !callerIsSystemOrActiveOrManagedUser(service, TAG, "setPasskey") - || !Utils.checkConnectPermissionForDataDelivery( - service, source, "AdapterService setPasskey")) { - return false; - } - - DeviceProperties deviceProp = service.mRemoteDevices.getDeviceProperties(device); - if (deviceProp == null || !deviceProp.isBonding()) { - Log.e(TAG, "setPasskey: device=" + device + ", not bonding"); - return false; - } - if (passkey.length != len) { - android.util.EventLog.writeEvent( - 0x534e4554, "139287605", -1, "Passkey length mismatch"); - return false; - } - service.logUserBondResponse(device, accept, source); - Log.i( - TAG, - "setPasskey: device=" - + device - + ", accept=" - + accept - + ", from " - + Utils.getUidPidString()); - - return service.mNativeInterface.sspReply( - getBytesFromAddress(device.getAddress()), - AbstractionLayer.BT_SSP_VARIANT_PASSKEY_ENTRY, - accept, - Utils.byteArrayToInt(passkey)); - } - - @Override - public boolean setPairingConfirmation( - BluetoothDevice device, boolean accept, AttributionSource source) { - AdapterService service = getService(); - if (service == null - || !callerIsSystemOrActiveOrManagedUser(service, TAG, "setPairingConfirmation") - || !Utils.checkConnectPermissionForDataDelivery(service, source, TAG)) { - return false; - } - - service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null); - - DeviceProperties deviceProp = service.mRemoteDevices.getDeviceProperties(device); - if (deviceProp == null || !deviceProp.isBonding()) { - Log.e(TAG, "setPairingConfirmation: device=" + device + ", not bonding"); - return false; - } - service.logUserBondResponse(device, accept, source); - Log.i( - TAG, - "setPairingConfirmation: device=" - + device - + ", accept=" - + accept - + ", from " - + Utils.getUidPidString()); - - return service.mNativeInterface.sspReply( - getBytesFromAddress(device.getAddress()), - AbstractionLayer.BT_SSP_VARIANT_PASSKEY_CONFIRMATION, - accept, - 0); - } - - @Override - public boolean getSilenceMode(BluetoothDevice device, AttributionSource source) { - AdapterService service = getService(); - if (service == null - || !callerIsSystemOrActiveOrManagedUser(service, TAG, "getSilenceMode") - || !Utils.checkConnectPermissionForDataDelivery(service, source, TAG)) { - return false; - } - - service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null); - - return service.mSilenceDeviceManager.getSilenceMode(device); - } - - @Override - public boolean setSilenceMode( - BluetoothDevice device, boolean silence, AttributionSource source) { - AdapterService service = getService(); - if (service == null - || !callerIsSystemOrActiveOrManagedUser(service, TAG, "setSilenceMode") - || !Utils.checkConnectPermissionForDataDelivery(service, source, TAG)) { - return false; - } - - service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null); - - service.mSilenceDeviceManager.setSilenceMode(device, silence); - return true; - } - - @Override - public int getPhonebookAccessPermission(BluetoothDevice device, AttributionSource source) { - AdapterService service = getService(); - if (service == null - || !callerIsSystemOrActiveOrManagedUser( - service, TAG, "getPhonebookAccessPermission") - || !Utils.checkConnectPermissionForDataDelivery( - service, source, "AdapterService getPhonebookAccessPermission")) { - return BluetoothDevice.ACCESS_UNKNOWN; - } - - return service.getPhonebookAccessPermission(device); - } - - @Override - public boolean setPhonebookAccessPermission( - BluetoothDevice device, int value, AttributionSource source) { - AdapterService service = getService(); - if (service == null - || !callerIsSystemOrActiveOrManagedUser( - service, TAG, "setPhonebookAccessPermission") - || !Utils.checkConnectPermissionForDataDelivery(service, source, TAG)) { - return false; - } - - service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null); - - service.setPhonebookAccessPermission(device, value); - return true; - } - - @Override - public int getMessageAccessPermission(BluetoothDevice device, AttributionSource source) { - AdapterService service = getService(); - if (service == null - || !callerIsSystemOrActiveOrManagedUser( - service, TAG, "getMessageAccessPermission") - || !Utils.checkConnectPermissionForDataDelivery( - service, source, "AdapterService getMessageAccessPermission")) { - return BluetoothDevice.ACCESS_UNKNOWN; - } - - return service.getMessageAccessPermission(device); - } - - @Override - public boolean setMessageAccessPermission( - BluetoothDevice device, int value, AttributionSource source) { - AdapterService service = getService(); - if (service == null - || !callerIsSystemOrActiveOrManagedUser( - service, TAG, "setMessageAccessPermission") - || !Utils.checkConnectPermissionForDataDelivery(service, source, TAG)) { - return false; - } - - service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null); - - service.setMessageAccessPermission(device, value); - return true; - } - - @Override - public int getSimAccessPermission(BluetoothDevice device, AttributionSource source) { - AdapterService service = getService(); - if (service == null - || !callerIsSystemOrActiveOrManagedUser(service, TAG, "getSimAccessPermission") - || !Utils.checkConnectPermissionForDataDelivery( - service, source, "AdapterService getSimAccessPermission")) { - return BluetoothDevice.ACCESS_UNKNOWN; - } - - return service.getSimAccessPermission(device); - } - - @Override - public boolean setSimAccessPermission( - BluetoothDevice device, int value, AttributionSource source) { - AdapterService service = getService(); - if (service == null - || !callerIsSystemOrActiveOrManagedUser(service, TAG, "setSimAccessPermission") - || !Utils.checkConnectPermissionForDataDelivery(service, source, TAG)) { - return false; - } - - service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null); - - service.setSimAccessPermission(device, value); - return true; - } - - @Override - public void logL2capcocServerConnection( - BluetoothDevice device, - int port, - boolean isSecured, - int result, - long socketCreationTimeMillis, - long socketCreationLatencyMillis, - long socketConnectionTimeMillis, - long timeoutMillis) { - AdapterService service = getService(); - if (service == null) { - return; - } - service.logL2capcocServerConnection( - device, - port, - isSecured, - result, - socketCreationTimeMillis, - socketCreationLatencyMillis, - socketConnectionTimeMillis, - timeoutMillis, - Binder.getCallingUid()); - } - - @Override - public IBluetoothSocketManager getSocketManager() { - AdapterService service = getService(); - if (service == null) { - return null; - } - - return IBluetoothSocketManager.Stub.asInterface(service.mBluetoothSocketManagerBinder); - } - - @Override - public void logL2capcocClientConnection( - BluetoothDevice device, - int port, - boolean isSecured, - int result, - long socketCreationTimeNanos, - long socketCreationLatencyNanos, - long socketConnectionTimeNanos) { - AdapterService service = getService(); - if (service == null) { - return; - } - service.logL2capcocClientConnection( - device, - port, - isSecured, - result, - socketCreationTimeNanos, - socketCreationLatencyNanos, - socketConnectionTimeNanos, - Binder.getCallingUid()); - } - - @Override - public void logRfcommConnectionAttempt( - BluetoothDevice device, - boolean isSecured, - int resultCode, - long socketCreationTimeNanos, - boolean isSerialPort) { - AdapterService service = getService(); - if (service == null) { - return; - } - service.logRfcommConnectionAttempt( - device, - isSecured, - resultCode, - socketCreationTimeNanos, - isSerialPort, - Binder.getCallingUid()); - } - - @Override - public boolean sdpSearch( - BluetoothDevice device, ParcelUuid uuid, AttributionSource source) { - AdapterService service = getService(); - if (service == null - || !callerIsSystemOrActiveOrManagedUser(service, TAG, "sdpSearch") - || !Utils.checkConnectPermissionForDataDelivery( - service, source, "AdapterService sdpSearch")) { - return false; - } - return service.sdpSearch(device, uuid); - } - - @Override - public int getBatteryLevel(BluetoothDevice device, AttributionSource source) { - AdapterService service = getService(); - if (service == null - || !callerIsSystemOrActiveOrManagedUser(service, TAG, "getBatteryLevel") - || !Utils.checkConnectPermissionForDataDelivery( - service, source, "AdapterService getBatteryLevel")) { - return BluetoothDevice.BATTERY_LEVEL_UNKNOWN; - } - - DeviceProperties deviceProp = service.mRemoteDevices.getDeviceProperties(device); - if (deviceProp == null) { - return BluetoothDevice.BATTERY_LEVEL_UNKNOWN; - } - return deviceProp.getBatteryLevel(); - } - - @Override - public int getMaxConnectedAudioDevices(AttributionSource source) { - // don't check caller, may be called from system UI - AdapterService service = getService(); - if (service == null - || !Utils.checkConnectPermissionForDataDelivery( - service, source, "AdapterService getMaxConnectedAudioDevices")) { - return -1; - } - - return service.getMaxConnectedAudioDevices(); - } - - @Override - public boolean factoryReset(AttributionSource source) { - AdapterService service = getService(); - if (service == null - || !Utils.checkConnectPermissionForDataDelivery(service, source, TAG)) { - return false; - } - - service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null); - return service.factoryReset(); - } - - @Override - public void registerBluetoothConnectionCallback( - IBluetoothConnectionCallback callback, AttributionSource source) { - AdapterService service = getService(); - if (service == null - || !callerIsSystemOrActiveOrManagedUser( - service, TAG, "registerBluetoothConnectionCallback") - || !Utils.checkConnectPermissionForDataDelivery(service, source, TAG)) { - return; - } - service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null); - service.mBluetoothConnectionCallbacks.register(callback); - } - - @Override - public void unregisterBluetoothConnectionCallback( - IBluetoothConnectionCallback callback, AttributionSource source) { - AdapterService service = getService(); - if (service == null - || !callerIsSystemOrActiveOrManagedUser( - service, TAG, "unregisterBluetoothConnectionCallback") - || !Utils.checkConnectPermissionForDataDelivery(service, source, TAG)) { - return; - } - service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null); - service.mBluetoothConnectionCallbacks.unregister(callback); - } - - @Override - public void registerCallback(IBluetoothCallback callback, AttributionSource source) { - AdapterService service = getService(); - if (service == null - || !callerIsSystemOrActiveOrManagedUser(service, TAG, "registerCallback") - || !Utils.checkConnectPermissionForDataDelivery(service, source, TAG)) { - return; - } - - service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null); - - service.registerRemoteCallback(callback); - } - - @Override - public void unregisterCallback(IBluetoothCallback callback, AttributionSource source) { - AdapterService service = getService(); - if (service == null - || !callerIsSystemOrActiveOrManagedUser(service, TAG, "unregisterCallback") - || !Utils.checkConnectPermissionForDataDelivery(service, source, TAG)) { - return; - } - - service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null); - - service.unregisterRemoteCallback(callback); - } - - @Override - public boolean isMultiAdvertisementSupported() { - AdapterService service = getService(); - if (service == null) { - return false; - } - - int val = service.mAdapterProperties.getNumOfAdvertisementInstancesSupported(); - return val >= MIN_ADVT_INSTANCES_FOR_MA; - } - - /** - * This method has an associated binder cache. The invalidation methods must be changed if - * the logic behind this method changes. - */ - @Override - public boolean isOffloadedFilteringSupported() { - AdapterService service = getService(); - if (service == null) { - return false; - } - - int val = service.getNumOfOffloadedScanFilterSupported(); - return val >= MIN_OFFLOADED_FILTERS; - } - - @Override - public boolean isOffloadedScanBatchingSupported() { - AdapterService service = getService(); - if (service == null) { - return false; - } - - int val = service.getOffloadedScanResultStorage(); - return val >= MIN_OFFLOADED_SCAN_STORAGE_BYTES; - } - - @Override - public boolean isLe2MPhySupported() { - AdapterService service = getService(); - if (service == null) { - return false; - } - - return service.isLe2MPhySupported(); - } - - @Override - public boolean isLeCodedPhySupported() { - AdapterService service = getService(); - if (service == null) { - return false; - } - - return service.isLeCodedPhySupported(); - } - - @Override - public boolean isLeExtendedAdvertisingSupported() { - AdapterService service = getService(); - if (service == null) { - return false; - } - - return service.isLeExtendedAdvertisingSupported(); - } - - @Override - public boolean isLePeriodicAdvertisingSupported() { - AdapterService service = getService(); - if (service == null) { - return false; - } - - return service.isLePeriodicAdvertisingSupported(); - } - - @Override - public int isLeAudioSupported() { - AdapterService service = getService(); - if (service == null) { - return BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ENABLED; - } - - Set<Integer> supportedProfileServices = - Arrays.stream(Config.getSupportedProfiles()) - .boxed() - .collect(Collectors.toSet()); - int[] leAudioUnicastProfiles = Config.getLeAudioUnicastProfiles(); - - if (Arrays.stream(leAudioUnicastProfiles) - .allMatch(supportedProfileServices::contains)) { - return BluetoothStatusCodes.FEATURE_SUPPORTED; - } - - return BluetoothStatusCodes.FEATURE_NOT_SUPPORTED; - } - - @Override - public int isLeAudioBroadcastSourceSupported() { - AdapterService service = getService(); - if (service == null) { - return BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ENABLED; - } - - long supportBitMask = Config.getSupportedProfilesBitMask(); - if ((supportBitMask & (1 << BluetoothProfile.LE_AUDIO_BROADCAST)) != 0) { - return BluetoothStatusCodes.FEATURE_SUPPORTED; - } - - return BluetoothStatusCodes.FEATURE_NOT_SUPPORTED; - } - - @Override - public int isLeAudioBroadcastAssistantSupported() { - AdapterService service = getService(); - if (service == null) { - return BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ENABLED; - } - - int[] supportedProfileServices = Config.getSupportedProfiles(); - - if (Arrays.stream(supportedProfileServices) - .anyMatch( - profileId -> - profileId == BluetoothProfile.LE_AUDIO_BROADCAST_ASSISTANT)) { - return BluetoothStatusCodes.FEATURE_SUPPORTED; - } - - return BluetoothStatusCodes.FEATURE_NOT_SUPPORTED; - } - - @Override - public int isDistanceMeasurementSupported(AttributionSource source) { - AdapterService service = getService(); - if (service == null) { - return BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ENABLED; - } else if (!callerIsSystemOrActiveOrManagedUser( - service, TAG, "isDistanceMeasurementSupported")) { - return BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ALLOWED; - } else if (!Utils.checkConnectPermissionForDataDelivery(service, source, TAG)) { - return BluetoothStatusCodes.ERROR_MISSING_BLUETOOTH_CONNECT_PERMISSION; - } - service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null); - return BluetoothStatusCodes.FEATURE_SUPPORTED; - } - - @Override - public int getLeMaximumAdvertisingDataLength() { - AdapterService service = getService(); - if (service == null) { - return 0; - } - - return service.getLeMaximumAdvertisingDataLength(); - } - - @Override - public boolean isActivityAndEnergyReportingSupported() { - AdapterService service = getService(); - if (service == null) { - return false; - } - - return service.mAdapterProperties.isActivityAndEnergyReportingSupported(); - } - - @Override - public BluetoothActivityEnergyInfo reportActivityInfo(AttributionSource source) { - AdapterService service = getService(); - if (service == null - || !Utils.checkConnectPermissionForDataDelivery(service, source, TAG)) { - return null; - } - - service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null); - - return service.reportActivityInfo(); - } - - @Override - public boolean registerMetadataListener( - IBluetoothMetadataListener listener, - BluetoothDevice device, - AttributionSource source) { - requireNonNull(device); - requireNonNull(listener); - AdapterService service = getService(); - if (service == null - || !callerIsSystemOrActiveOrManagedUser( - service, TAG, "registerMetadataListener") - || !Utils.checkConnectPermissionForDataDelivery(service, source, TAG)) { - return false; - } - - service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null); - - service.mHandler.post( - () -> - service.mMetadataListeners - .computeIfAbsent(device, k -> new RemoteCallbackList()) - .register(listener)); - - return true; - } - - @Override - public boolean unregisterMetadataListener( - IBluetoothMetadataListener listener, - BluetoothDevice device, - AttributionSource source) { - requireNonNull(device); - requireNonNull(listener); - AdapterService service = getService(); - if (service == null - || !callerIsSystemOrActiveOrManagedUser( - service, TAG, "unregisterMetadataListener") - || !Utils.checkConnectPermissionForDataDelivery(service, source, TAG)) { - return false; - } - - service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null); - - service.mHandler.post( - () -> - service.mMetadataListeners.computeIfPresent( - device, - (k, v) -> { - v.unregister(listener); - if (v.getRegisteredCallbackCount() == 0) { - return null; - } - return v; - })); - return true; - } - - @Override - public boolean setMetadata( - BluetoothDevice device, int key, byte[] value, AttributionSource source) { - AdapterService service = getService(); - if (service == null - || !callerIsSystemOrActiveOrManagedUser(service, TAG, "setMetadata") - || !Utils.checkConnectPermissionForDataDelivery(service, source, TAG)) { - return false; - } - - service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null); - return service.setMetadata(device, key, value); - } - - @Override - public byte[] getMetadata(BluetoothDevice device, int key, AttributionSource source) { - AdapterService service = getService(); - if (service == null - || !callerIsSystemOrActiveOrManagedUser(service, TAG, "getMetadata") - || !Utils.checkConnectPermissionForDataDelivery(service, source, TAG)) { - return null; - } - - service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null); - - return service.getMetadata(device, key); - } - - @Override - public int isRequestAudioPolicyAsSinkSupported( - BluetoothDevice device, AttributionSource source) { - AdapterService service = getService(); - if (service == null - || !callerIsSystemOrActiveOrManagedUser( - service, TAG, "isRequestAudioPolicyAsSinkSupported") - || !Utils.checkConnectPermissionForDataDelivery(service, source, TAG)) { - return BluetoothStatusCodes.FEATURE_NOT_CONFIGURED; - } - service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null); - return service.isRequestAudioPolicyAsSinkSupported(device); - } - - @Override - public int requestAudioPolicyAsSink( - BluetoothDevice device, - BluetoothSinkAudioPolicy policies, - AttributionSource source) { - AdapterService service = getService(); - if (service == null) { - return BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ENABLED; - } else if (!callerIsSystemOrActiveOrManagedUser( - service, TAG, "requestAudioPolicyAsSink")) { - return BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ALLOWED; - } else if (!Utils.checkConnectPermissionForDataDelivery(service, source, TAG)) { - return BluetoothStatusCodes.ERROR_MISSING_BLUETOOTH_CONNECT_PERMISSION; - } - service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null); - return service.requestAudioPolicyAsSink(device, policies); - } - - @Override - public BluetoothSinkAudioPolicy getRequestedAudioPolicyAsSink( - BluetoothDevice device, AttributionSource source) { - AdapterService service = getService(); - if (service == null - || !callerIsSystemOrActiveOrManagedUser( - service, TAG, "getRequestedAudioPolicyAsSink") - || !Utils.checkConnectPermissionForDataDelivery(service, source, TAG)) { - return null; - } - service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null); - return service.getRequestedAudioPolicyAsSink(device); - } - - @Override - public void requestActivityInfo( - IBluetoothActivityEnergyInfoListener listener, AttributionSource source) { - BluetoothActivityEnergyInfo info = reportActivityInfo(source); - try { - listener.onBluetoothActivityEnergyInfoAvailable(info); - } catch (RemoteException e) { - Log.e(TAG, "onBluetoothActivityEnergyInfo: RemoteException", e); - } - } - - @Override - public void bleOnToOn(AttributionSource source) { - AdapterService service = getService(); - if (service == null - || !callerIsSystemOrActiveOrManagedUser(service, TAG, "bleOnToOn")) { - return; - } - - service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null); - - service.bleOnToOn(); - } - - @Override - public void bleOnToOff(AttributionSource source) { - AdapterService service = getService(); - if (service == null - || !callerIsSystemOrActiveOrManagedUser(service, TAG, "bleOnToOff")) { - return; - } - - service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null); - - service.bleOnToOff(); - } - - @Override - public void dump(FileDescriptor fd, String[] args) { - PrintWriter writer = new PrintWriter(new FileOutputStream(fd)); - AdapterService service = getService(); - if (service == null) { - return; - } - - service.enforceCallingOrSelfPermission(DUMP, null); - - service.dump(fd, writer, args); - writer.close(); - } - - @Override - public boolean allowLowLatencyAudio(boolean allowed, BluetoothDevice device) { - AdapterService service = getService(); - if (service == null - || !callerIsSystemOrActiveOrManagedUser(service, TAG, "allowLowLatencyAudio") - || !Utils.checkConnectPermissionForDataDelivery( - service, - Utils.getCallingAttributionSource(service), - "AdapterService allowLowLatencyAudio")) { - return false; - } - service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null); - return service.allowLowLatencyAudio(allowed, device); - } - - @Override - public int startRfcommListener( - String name, - ParcelUuid uuid, - PendingIntent pendingIntent, - AttributionSource source) { - AdapterService service = getService(); - if (service == null - || !callerIsSystemOrActiveOrManagedUser(service, TAG, "startRfcommListener") - || !Utils.checkConnectPermissionForDataDelivery( - service, source, "AdapterService startRfcommListener")) { - return BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ALLOWED; - } - service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null); - return service.startRfcommListener(name, uuid, pendingIntent, source); - } - - @Override - public int stopRfcommListener(ParcelUuid uuid, AttributionSource source) { - AdapterService service = getService(); - if (service == null - || !callerIsSystemOrActiveOrManagedUser(service, TAG, "stopRfcommListener") - || !Utils.checkConnectPermissionForDataDelivery( - service, source, "AdapterService stopRfcommListener")) { - return BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ALLOWED; - } - service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null); - return service.stopRfcommListener(uuid, source); - } - - @Override - public IncomingRfcommSocketInfo retrievePendingSocketForServiceRecord( - ParcelUuid uuid, AttributionSource source) { - AdapterService service = getService(); - if (service == null - || !callerIsSystemOrActiveOrManagedUser( - service, TAG, "retrievePendingSocketForServiceRecord") - || !Utils.checkConnectPermissionForDataDelivery( - service, - source, - "AdapterService retrievePendingSocketForServiceRecord")) { - return null; - } - service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null); - return service.retrievePendingSocketForServiceRecord(uuid, source); - } - - @Override - public void setForegroundUserId(int userId, AttributionSource source) { - AdapterService service = getService(); - if (service == null - || !Utils.checkConnectPermissionForDataDelivery( - service, - Utils.getCallingAttributionSource(mService), - "AdapterService setForegroundUserId")) { - return; - } - service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null); - Utils.setForegroundUserId(userId); - } - - @Override - public int setPreferredAudioProfiles( - BluetoothDevice device, Bundle modeToProfileBundle, AttributionSource source) { - AdapterService service = getService(); - if (service == null) { - return BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ENABLED; - } - if (!callerIsSystemOrActiveOrManagedUser(service, TAG, "setPreferredAudioProfiles")) { - return BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ALLOWED; - } - requireNonNull(device); - requireNonNull(modeToProfileBundle); - if (!BluetoothAdapter.checkBluetoothAddress(device.getAddress())) { - throw new IllegalArgumentException("device cannot have an invalid address"); - } - if (service.getBondState(device) != BluetoothDevice.BOND_BONDED) { - return BluetoothStatusCodes.ERROR_DEVICE_NOT_BONDED; - } - if (!Utils.checkConnectPermissionForDataDelivery(service, source, TAG)) { - return BluetoothStatusCodes.ERROR_MISSING_BLUETOOTH_CONNECT_PERMISSION; - } - service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null); - - return service.setPreferredAudioProfiles(device, modeToProfileBundle); - } - - @Override - public Bundle getPreferredAudioProfiles(BluetoothDevice device, AttributionSource source) { - AdapterService service = getService(); - if (service == null) { - return Bundle.EMPTY; - } - if (!callerIsSystemOrActiveOrManagedUser(service, TAG, "getPreferredAudioProfiles")) { - return Bundle.EMPTY; - } - requireNonNull(device); - if (!BluetoothAdapter.checkBluetoothAddress(device.getAddress())) { - throw new IllegalArgumentException("device cannot have an invalid address"); - } - if (service.getBondState(device) != BluetoothDevice.BOND_BONDED) { - return Bundle.EMPTY; - } - if (!Utils.checkConnectPermissionForDataDelivery(service, source, TAG)) { - return Bundle.EMPTY; - } - service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null); - - return service.getPreferredAudioProfiles(device); - } - - @Override - public int notifyActiveDeviceChangeApplied( - BluetoothDevice device, AttributionSource source) { - AdapterService service = getService(); - if (service == null) { - return BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ENABLED; - } - if (!callerIsSystem(TAG, "notifyActiveDeviceChangeApplied")) { - return BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ALLOWED; - } - requireNonNull(device); - if (!BluetoothAdapter.checkBluetoothAddress(device.getAddress())) { - throw new IllegalArgumentException("device cannot have an invalid address"); - } - if (service.getBondState(device) != BluetoothDevice.BOND_BONDED) { - return BluetoothStatusCodes.ERROR_DEVICE_NOT_BONDED; - } - if (!Utils.checkConnectPermissionForDataDelivery(service, source, TAG)) { - return BluetoothStatusCodes.ERROR_MISSING_BLUETOOTH_CONNECT_PERMISSION; - } - service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null); - - return service.notifyActiveDeviceChangeApplied(device); - } - - @Override - public int isDualModeAudioEnabled(AttributionSource source) { - AdapterService service = getService(); - if (service == null) { - return BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ENABLED; - } - if (!Utils.checkConnectPermissionForDataDelivery(service, source, TAG)) { - return BluetoothStatusCodes.ERROR_MISSING_BLUETOOTH_CONNECT_PERMISSION; - } - service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null); - - if (!Utils.isDualModeAudioEnabled()) { - return BluetoothStatusCodes.FEATURE_NOT_SUPPORTED; - } - - return BluetoothStatusCodes.SUCCESS; - } - - @Override - public int registerPreferredAudioProfilesChangedCallback( - IBluetoothPreferredAudioProfilesCallback callback, AttributionSource source) { - AdapterService service = getService(); - if (service == null) { - return BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ENABLED; - } - if (!callerIsSystemOrActiveOrManagedUser( - service, TAG, "registerPreferredAudioProfilesChangedCallback")) { - return BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ALLOWED; - } - requireNonNull(callback); - if (!Utils.checkConnectPermissionForDataDelivery(service, source, TAG)) { - return BluetoothStatusCodes.ERROR_MISSING_BLUETOOTH_CONNECT_PERMISSION; - } - service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null); - - // If LE only mode is enabled, the dual mode audio feature is disabled - if (!Utils.isDualModeAudioEnabled()) { - return BluetoothStatusCodes.FEATURE_NOT_SUPPORTED; - } - - service.mPreferredAudioProfilesCallbacks.register(callback); - return BluetoothStatusCodes.SUCCESS; - } - - @Override - public int unregisterPreferredAudioProfilesChangedCallback( - IBluetoothPreferredAudioProfilesCallback callback, AttributionSource source) { - AdapterService service = getService(); - if (service == null) { - return BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ENABLED; - } - if (!callerIsSystemOrActiveOrManagedUser( - service, TAG, "unregisterPreferredAudioProfilesChangedCallback")) { - return BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ALLOWED; - } - requireNonNull(callback); - if (!Utils.checkConnectPermissionForDataDelivery(service, source, TAG)) { - return BluetoothStatusCodes.ERROR_MISSING_BLUETOOTH_CONNECT_PERMISSION; - } - service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null); - - if (!service.mPreferredAudioProfilesCallbacks.unregister(callback)) { - Log.e( - TAG, - "unregisterPreferredAudioProfilesChangedCallback: callback was never " - + "registered"); - return BluetoothStatusCodes.ERROR_CALLBACK_NOT_REGISTERED; - } - return BluetoothStatusCodes.SUCCESS; - } - - @Override - public int registerBluetoothQualityReportReadyCallback( - IBluetoothQualityReportReadyCallback callback, AttributionSource source) { - AdapterService service = getService(); - if (service == null) { - return BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ENABLED; - } - if (!callerIsSystemOrActiveOrManagedUser( - service, TAG, "registerBluetoothQualityReportReadyCallback")) { - return BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ALLOWED; - } - requireNonNull(callback); - if (!Utils.checkConnectPermissionForDataDelivery(service, source, TAG)) { - return BluetoothStatusCodes.ERROR_MISSING_BLUETOOTH_CONNECT_PERMISSION; - } - service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null); - - service.mBluetoothQualityReportReadyCallbacks.register(callback); - return BluetoothStatusCodes.SUCCESS; - } - - @Override - public int unregisterBluetoothQualityReportReadyCallback( - IBluetoothQualityReportReadyCallback callback, AttributionSource source) { - AdapterService service = getService(); - if (service == null) { - return BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ENABLED; - } - if (!callerIsSystemOrActiveOrManagedUser( - service, TAG, "unregisterBluetoothQualityReportReadyCallback")) { - return BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ALLOWED; - } - requireNonNull(callback); - if (!Utils.checkConnectPermissionForDataDelivery(service, source, TAG)) { - return BluetoothStatusCodes.ERROR_MISSING_BLUETOOTH_CONNECT_PERMISSION; - } - service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null); - - if (!service.mBluetoothQualityReportReadyCallbacks.unregister(callback)) { - Log.e( - TAG, - "unregisterBluetoothQualityReportReadyCallback: callback was never " - + "registered"); - return BluetoothStatusCodes.ERROR_CALLBACK_NOT_REGISTERED; - } - return BluetoothStatusCodes.SUCCESS; - } - - @Override - public void registerHciVendorSpecificCallback( - IBluetoothHciVendorSpecificCallback callback, int[] eventCodes) { - AdapterService service = getService(); - if (service == null) { - return; - } - if (!callerIsSystemOrActiveOrManagedUser( - service, TAG, "registerHciVendorSpecificCallback")) { - throw new SecurityException("not allowed"); - } - service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null); - requireNonNull(callback); - requireNonNull(eventCodes); - - Set<Integer> eventCodesSet = - Arrays.stream(eventCodes).boxed().collect(Collectors.toSet()); - if (eventCodesSet.stream() - .anyMatch((n) -> (n < 0) || (n >= 0x52 && n < 0x60) || (n > 0xff))) { - throw new IllegalArgumentException("invalid vendor-specific event code"); - } - - service.mBluetoothHciVendorSpecificDispatcher.register(callback, eventCodesSet); - } - - @Override - public void unregisterHciVendorSpecificCallback( - IBluetoothHciVendorSpecificCallback callback) { - AdapterService service = getService(); - if (service == null) { - return; - } - if (!callerIsSystemOrActiveOrManagedUser( - service, TAG, "unregisterHciVendorSpecificCallback")) { - throw new SecurityException("not allowed"); - } - service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null); - requireNonNull(callback); - - service.mBluetoothHciVendorSpecificDispatcher.unregister(callback); - } - - @Override - public void sendHciVendorSpecificCommand( - int ocf, byte[] parameters, IBluetoothHciVendorSpecificCallback callback) { - AdapterService service = getService(); - if (service == null) { - return; - } - if (!callerIsSystemOrActiveOrManagedUser( - service, TAG, "sendHciVendorSpecificCommand")) { - throw new SecurityException("not allowed"); - } - service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null); - - // Open this no-op android command for test purpose - int getVendorCapabilitiesOcf = 0x153; - if (ocf < 0 - || (ocf >= 0x150 && ocf < 0x160 && ocf != getVendorCapabilitiesOcf) - || (ocf > 0x3ff)) { - throw new IllegalArgumentException("invalid vendor-specific event code"); - } - requireNonNull(parameters); - if (parameters.length > 255) { - throw new IllegalArgumentException("Parameters size is too big"); - } - - Optional<byte[]> cookie = - service.mBluetoothHciVendorSpecificDispatcher.getRegisteredCookie(callback); - if (!cookie.isPresent()) { - Log.e(TAG, "send command without registered callback"); - throw new IllegalStateException("callback not registered"); - } - - service.mBluetoothHciVendorSpecificNativeInterface.sendCommand( - ocf, parameters, cookie.get()); - } - - @Override - public int getOffloadedTransportDiscoveryDataScanSupported(AttributionSource source) { - AdapterService service = getService(); - if (service == null - || !callerIsSystemOrActiveOrManagedUser( - service, TAG, "getOffloadedTransportDiscoveryDataScanSupported") - || !Utils.checkScanPermissionForDataDelivery( - service, source, "getOffloadedTransportDiscoveryDataScanSupported")) { - return BluetoothStatusCodes.ERROR_MISSING_BLUETOOTH_SCAN_PERMISSION; - } - service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null); - - return service.getOffloadedTransportDiscoveryDataScanSupported(); - } - - @Override - public boolean isMediaProfileConnected(AttributionSource source) { - AdapterService service = getService(); - if (service == null - || !Utils.checkConnectPermissionForDataDelivery( - service, source, "AdapterService.isMediaProfileConnected")) { - return false; - } - service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null); - - return service.isMediaProfileConnected(); - } - - @Override - public IBinder getBluetoothGatt() { - AdapterService service = getService(); - return service == null ? null : service.getBluetoothGatt(); - } - - @Override - public IBinder getBluetoothScan() { - AdapterService service = getService(); - return service == null ? null : service.getBluetoothScan(); - } - - @Override - public void unregAllGattClient(AttributionSource source) { - AdapterService service = getService(); - if (service == null) { - return; - } - service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null); - service.unregAllGattClient(source); - } - - @Override - public IBinder getProfile(int profileId) { - AdapterService service = getService(); - if (service == null) { - return null; - } - - return service.getProfile(profileId); - } - - @Override - public int setActiveAudioDevicePolicy( - BluetoothDevice device, int activeAudioDevicePolicy, AttributionSource source) { - AdapterService service = getService(); - if (service == null) { - return BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ENABLED; - } - if (!callerIsSystemOrActiveOrManagedUser(service, TAG, "setActiveAudioDevicePolicy")) { - return BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ALLOWED; - } - if (!BluetoothAdapter.checkBluetoothAddress(device.getAddress())) { - throw new IllegalArgumentException("device cannot have an invalid address"); - } - if (!Utils.checkConnectPermissionForDataDelivery(service, source, TAG)) { - return BluetoothStatusCodes.ERROR_MISSING_BLUETOOTH_CONNECT_PERMISSION; - } - - service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null); - return service.mDatabaseManager.setActiveAudioDevicePolicy( - device, activeAudioDevicePolicy); - } - - @Override - public int getActiveAudioDevicePolicy(BluetoothDevice device, AttributionSource source) { - AdapterService service = getService(); - if (service == null) { - return BluetoothDevice.ACTIVE_AUDIO_DEVICE_POLICY_DEFAULT; - } - if (!callerIsSystemOrActiveOrManagedUser(service, TAG, "getActiveAudioDevicePolicy")) { - throw new IllegalStateException( - "Caller is not the system or part of the active/managed user"); - } - if (!BluetoothAdapter.checkBluetoothAddress(device.getAddress())) { - throw new IllegalArgumentException("device cannot have an invalid address"); - } - if (!Utils.checkConnectPermissionForDataDelivery(service, source, TAG)) { - return BluetoothDevice.ACTIVE_AUDIO_DEVICE_POLICY_DEFAULT; - } - - service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null); - return service.mDatabaseManager.getActiveAudioDevicePolicy(device); - } - - @Override - public int setMicrophonePreferredForCalls( - BluetoothDevice device, boolean enabled, AttributionSource source) { - requireNonNull(device); - AdapterService service = getService(); - if (service == null) { - return BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ENABLED; - } - if (!callerIsSystemOrActiveOrManagedUser( - service, TAG, "setMicrophonePreferredForCalls")) { - return BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ALLOWED; - } - if (!BluetoothAdapter.checkBluetoothAddress(device.getAddress())) { - throw new IllegalArgumentException("device cannot have an invalid address"); - } - if (!Utils.checkConnectPermissionForDataDelivery( - service, source, "AdapterService setMicrophonePreferredForCalls")) { - return BluetoothStatusCodes.ERROR_MISSING_BLUETOOTH_CONNECT_PERMISSION; - } - - service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null); - return service.mDatabaseManager.setMicrophonePreferredForCalls(device, enabled); - } - - @Override - public boolean isMicrophonePreferredForCalls( - BluetoothDevice device, AttributionSource source) { - requireNonNull(device); - AdapterService service = getService(); - if (service == null) { - return true; - } - if (!callerIsSystemOrActiveOrManagedUser( - service, TAG, "isMicrophonePreferredForCalls")) { - throw new IllegalStateException( - "Caller is not the system or part of the active/managed user"); - } - if (!BluetoothAdapter.checkBluetoothAddress(device.getAddress())) { - throw new IllegalArgumentException("device cannot have an invalid address"); - } - if (!Utils.checkConnectPermissionForDataDelivery( - service, source, "AdapterService isMicrophonePreferredForCalls")) { - return true; - } - - service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null); - return service.mDatabaseManager.isMicrophonePreferredForCalls(device); - } - - @Override - public boolean isLeCocSocketOffloadSupported(AttributionSource source) { - AdapterService service = getService(); - if (service == null) { - return false; - } - service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null); - return service.isLeCocSocketOffloadSupported(); - } - - @Override - public boolean isRfcommSocketOffloadSupported(AttributionSource source) { - AdapterService service = getService(); - if (service == null) { - return false; - } - service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null); - return service.isRfcommSocketOffloadSupported(); - } - - @Override - public IBinder getBluetoothAdvertise() { - AdapterService service = getService(); - return service == null ? null : service.getBluetoothAdvertise(); - } - - @Override - public IBinder getDistanceMeasurement() { - AdapterService service = getService(); - return service == null ? null : service.getDistanceMeasurement(); - } - - @Override - public int getKeyMissingCount(BluetoothDevice device, AttributionSource source) { - AdapterService service = getService(); - if (service == null) { - return -1; - } - if (!callerIsSystemOrActiveOrManagedUser(service, TAG, "getKeyMissingCount")) { - throw new IllegalStateException( - "Caller is not the system or part of the active/managed user"); - } - if (!BluetoothAdapter.checkBluetoothAddress(device.getAddress())) { - throw new IllegalArgumentException("device cannot have an invalid address"); - } - if (!Utils.checkConnectPermissionForDataDelivery( - service, source, "AdapterService getKeyMissingCount")) { - return -1; - } - - return service.mDatabaseManager.getKeyMissingCount(device); - } - } - - /** * Gets the preferred audio profiles for the device. See {@link * BluetoothAdapter#getPreferredAudioProfiles(BluetoothDevice)} for more details. * @@ -4515,7 +2264,7 @@ public class AdapterService extends Service { * @param modeToProfileBundle is the preferences we want to set for the device * @return whether the preferences were successfully requested */ - private int setPreferredAudioProfiles(BluetoothDevice device, Bundle modeToProfileBundle) { + int setPreferredAudioProfiles(BluetoothDevice device, Bundle modeToProfileBundle) { Log.i(TAG, "setPreferredAudioProfiles for device=" + device); if (!isDualModeAudioEnabled()) { Log.e(TAG, "setPreferredAudioProfiles called while sysprop is disabled"); @@ -4735,7 +2484,7 @@ public class AdapterService extends Service { * @param device the remote device whose preferred audio profiles have been changed * @return whether the Bluetooth stack acknowledged the change successfully */ - private int notifyActiveDeviceChangeApplied(BluetoothDevice device) { + int notifyActiveDeviceChangeApplied(BluetoothDevice device) { if (mLeAudioService == null) { Log.e(TAG, "LE Audio profile not enabled"); return BluetoothStatusCodes.ERROR_PROFILE_NOT_CONNECTED; @@ -4760,36 +2509,36 @@ public class AdapterService extends Service { mCsipGroupsPendingAudioProfileChanges.get(groupId); // If this is the final audio framework request, send callback to apps - if (pendingRequest.mRemainingRequestsToAudioFramework == 1) { + if (pendingRequest.numberOfRemainingRequestsToAudioFramework == 1) { Log.i( TAG, "notifyActiveDeviceChangeApplied: Complete for device " - + pendingRequest.mDeviceRequested); + + pendingRequest.device); sendPreferredAudioProfilesCallbackToApps( - pendingRequest.mDeviceRequested, - pendingRequest.mRequestedPreferences, + pendingRequest.device, + pendingRequest.preferences, BluetoothStatusCodes.SUCCESS); // Removes the timeout from the handler mHandler.removeMessages( MESSAGE_PREFERRED_AUDIO_PROFILES_AUDIO_FRAMEWORK_TIMEOUT, groupId); - } else if (pendingRequest.mRemainingRequestsToAudioFramework > 1) { + } else if (pendingRequest.numberOfRemainingRequestsToAudioFramework > 1) { PendingAudioProfilePreferenceRequest updatedPendingRequest = new PendingAudioProfilePreferenceRequest( - pendingRequest.mRequestedPreferences, - pendingRequest.mRemainingRequestsToAudioFramework - 1, - pendingRequest.mDeviceRequested); + pendingRequest.preferences, + pendingRequest.numberOfRemainingRequestsToAudioFramework - 1, + pendingRequest.device); Log.i( TAG, "notifyActiveDeviceChangeApplied: Updating device " - + updatedPendingRequest.mDeviceRequested + + updatedPendingRequest.device + " with new remaining requests count=" - + updatedPendingRequest.mRemainingRequestsToAudioFramework); + + updatedPendingRequest.numberOfRemainingRequestsToAudioFramework); mCsipGroupsPendingAudioProfileChanges.put(groupId, updatedPendingRequest); } else { Log.i( TAG, "notifyActiveDeviceChangeApplied: " - + pendingRequest.mDeviceRequested + + pendingRequest.device + " has no remaining requests to audio framework, but is still" + " present in mCsipGroupsPendingAudioProfileChanges"); } @@ -4957,7 +2706,8 @@ public class AdapterService extends Service { public String getIdentityAddress(String address) { BluetoothDevice device = - BluetoothAdapter.getDefaultAdapter().getRemoteDevice(Ascii.toUpperCase(address)); + BluetoothAdapter.getDefaultAdapter() + .getRemoteDevice(address.toUpperCase(Locale.ROOT)); DeviceProperties deviceProp = mRemoteDevices.getDeviceProperties(device); if (deviceProp != null && deviceProp.getIdentityAddress() != null) { return deviceProp.getIdentityAddress(); @@ -4981,7 +2731,8 @@ public class AdapterService extends Service { @NonNull public BluetoothAddress getIdentityAddressWithType(@NonNull String address) { BluetoothDevice device = - BluetoothAdapter.getDefaultAdapter().getRemoteDevice(Ascii.toUpperCase(address)); + BluetoothAdapter.getDefaultAdapter() + .getRemoteDevice(address.toUpperCase(Locale.ROOT)); DeviceProperties deviceProp = mRemoteDevices.getDeviceProperties(device); String identityAddress = null; @@ -5003,10 +2754,7 @@ public class AdapterService extends Service { return new BluetoothAddress(identityAddress, identityAddressType); } - private static class CallerInfo { - public String callerPackageName; - public UserHandle user; - } + private record CallerInfo(String callerPackageName, UserHandle user) {} boolean createBond( BluetoothDevice device, @@ -5029,9 +2777,7 @@ public class AdapterService extends Service { return false; } - CallerInfo createBondCaller = new CallerInfo(); - createBondCaller.callerPackageName = callingPackage; - createBondCaller.user = Binder.getCallingUserHandle(); + CallerInfo createBondCaller = new CallerInfo(callingPackage, Binder.getCallingUserHandle()); mBondAttemptCallerInfo.put(device.getAddress(), createBondCaller); mRemoteDevices.setBondingInitiatedLocally(Utils.getByteAddress(device)); @@ -5930,7 +3676,8 @@ public class AdapterService extends Service { return mRemoteDevices.getUuids(device); } - void aclStateChangeBroadcastCallback(Consumer<IBluetoothConnectionCallback> cb) { + void aclStateChangeBroadcastCallback( + RemoteExceptionIgnoringConsumer<IBluetoothConnectionCallback> cb) { int n = mBluetoothConnectionCallbacks.beginBroadcast(); Log.d(TAG, "aclStateChangeBroadcastCallback() - Broadcasting to " + n + " receivers."); for (int i = 0; i < n; i++) { @@ -6193,27 +3940,22 @@ public class AdapterService extends Service { mLocalCallbacks.remove(callback); } - @VisibleForTesting void registerRemoteCallback(IBluetoothCallback callback) { - mRemoteCallbacks.register(callback); + mSystemServerCallbacks.register(callback); } - @VisibleForTesting void unregisterRemoteCallback(IBluetoothCallback callback) { - mRemoteCallbacks.unregister(callback); + mSystemServerCallbacks.unregister(callback); } - @VisibleForTesting void bleOnToOn() { mAdapterStateMachine.sendMessage(AdapterState.USER_TURN_ON); } - @VisibleForTesting void bleOnToOff() { mAdapterStateMachine.sendMessage(AdapterState.BLE_TURN_OFF); } - @VisibleForTesting boolean factoryReset() { mDatabaseManager.factoryReset(); @@ -6232,13 +3974,12 @@ public class AdapterService extends Service { return mNativeInterface.factoryReset(); } - @VisibleForTesting int getScanMode() { return mScanMode; } - private boolean setScanMode(int mode, String from) { - mScanModeChanges.add(Utils.getLocalTimeString() + " (" + from + ") " + dumpScanMode(mode)); + boolean setScanMode(int mode, String from) { + mScanModeChanges.add(from + ": " + scanModeName(mode)); if (!mNativeInterface.setScanMode(convertScanModeToHal(mode))) { return false; } @@ -6251,7 +3992,6 @@ public class AdapterService extends Service { return true; } - @VisibleForTesting BluetoothActivityEnergyInfo reportActivityInfo() { if (mAdapterProperties.getState() != BluetoothAdapter.STATE_ON || !mAdapterProperties.isActivityAndEnergyReportingSupported()) { @@ -6697,21 +4437,13 @@ public class AdapterService extends Service { return BluetoothProperties.getHardwareOperatingVoltageMv().orElse(0) / 1000.0; } - public RemoteDevices getRemoteDevices() { - return mRemoteDevices; - } - - private static String dumpScanMode(int scanMode) { - switch (scanMode) { - case SCAN_MODE_NONE: - return "SCAN_MODE_NONE"; - case SCAN_MODE_CONNECTABLE: - return "SCAN_MODE_CONNECTABLE"; - case SCAN_MODE_CONNECTABLE_DISCOVERABLE: - return "SCAN_MODE_CONNECTABLE_DISCOVERABLE"; - default: - return "Unknown Scan Mode " + scanMode; - } + private static String scanModeName(int scanMode) { + return switch (scanMode) { + case SCAN_MODE_NONE -> "SCAN_MODE_NONE"; + case SCAN_MODE_CONNECTABLE -> "SCAN_MODE_CONNECTABLE"; + case SCAN_MODE_CONNECTABLE_DISCOVERABLE -> "SCAN_MODE_CONNECTABLE_DISCOVERABLE"; + default -> "Unknown Scan Mode " + scanMode; + }; } @Override @@ -6734,20 +4466,13 @@ 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); - writer.println("ScanMode: " + dumpScanMode(getScanMode())); - writer.println("Scan Mode Changes:"); - for (String log : mScanModeChanges) { - writer.println(" " + log); - } + writer.println("ScanMode: " + scanModeName(getScanMode())); + StringBuilder sb = new StringBuilder(); + mScanModeChanges.dump(sb); + writer.println(sb.toString()); writer.println(); writer.println("sSnoopLogSettingAtEnable = " + sSnoopLogSettingAtEnable); writer.println("sDefaultSnoopLogSettingAtEnable = " + sDefaultSnoopLogSettingAtEnable); @@ -6767,7 +4492,11 @@ public class AdapterService extends Service { mAdapterStateMachine.dump(fd, writer, args); - StringBuilder sb = new StringBuilder(); + sb = new StringBuilder(); + + mSilenceDeviceManager.dump(sb); + mDatabaseManager.dump(sb); + for (ProfileService profile : mRegisteredProfiles) { profile.dump(sb); } @@ -6778,11 +4507,8 @@ public class AdapterService extends Service { scanController.dump(sb); } } - mSilenceDeviceManager.dump(fd, writer, args); - mDatabaseManager.dump(writer); writer.write(sb.toString()); - writer.flush(); final int currentState = mAdapterProperties.getState(); if (currentState == BluetoothAdapter.STATE_OFF @@ -6790,56 +4516,15 @@ public class AdapterService extends Service { || currentState == BluetoothAdapter.STATE_TURNING_OFF || currentState == BluetoothAdapter.STATE_BLE_TURNING_OFF) { writer.println(); - writer.println( - "Impossible to dump native stack. state=" - + BluetoothAdapter.nameForState(currentState)); + writer.println("Impossible to dump native stack. state=" + nameForState(currentState)); writer.println(); + writer.flush(); } else { + writer.flush(); mNativeInterface.dump(fd, args); } } - 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) { - if (remoteP192Data != null || remoteP256Data != null) { - this.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null); - } - } - private final Object mDeviceConfigLock = new Object(); /** diff --git a/android/app/src/com/android/bluetooth/btservice/AdapterServiceBinder.java b/android/app/src/com/android/bluetooth/btservice/AdapterServiceBinder.java new file mode 100644 index 0000000000..57776bc560 --- /dev/null +++ b/android/app/src/com/android/bluetooth/btservice/AdapterServiceBinder.java @@ -0,0 +1,2266 @@ +/* + * Copyright (C) 2025 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.bluetooth.btservice; + +import static android.Manifest.permission.BLUETOOTH_PRIVILEGED; +import static android.Manifest.permission.DUMP; +import static android.Manifest.permission.LOCAL_MAC_ADDRESS; +import static android.Manifest.permission.MODIFY_PHONE_STATE; +import static android.bluetooth.BluetoothAdapter.SCAN_MODE_NONE; +import static android.bluetooth.BluetoothDevice.TRANSPORT_AUTO; +import static android.bluetooth.BluetoothProfile.STATE_DISCONNECTED; + +import static com.android.bluetooth.ChangeIds.ENFORCE_CONNECT; +import static com.android.bluetooth.Utils.callerIsSystem; +import static com.android.bluetooth.Utils.callerIsSystemOrActiveOrManagedUser; +import static com.android.bluetooth.Utils.getBytesFromAddress; + +import static java.util.Objects.requireNonNull; + +import android.annotation.NonNull; +import android.app.PendingIntent; +import android.app.compat.CompatChanges; +import android.bluetooth.BluetoothActivityEnergyInfo; +import android.bluetooth.BluetoothAdapter; +import android.bluetooth.BluetoothAdapter.ActiveDeviceProfile; +import android.bluetooth.BluetoothAdapter.ActiveDeviceUse; +import android.bluetooth.BluetoothDevice; +import android.bluetooth.BluetoothDevice.BluetoothAddress; +import android.bluetooth.BluetoothProfile; +import android.bluetooth.BluetoothProtoEnums; +import android.bluetooth.BluetoothSinkAudioPolicy; +import android.bluetooth.BluetoothStatusCodes; +import android.bluetooth.IBluetooth; +import android.bluetooth.IBluetoothActivityEnergyInfoListener; +import android.bluetooth.IBluetoothCallback; +import android.bluetooth.IBluetoothConnectionCallback; +import android.bluetooth.IBluetoothHciVendorSpecificCallback; +import android.bluetooth.IBluetoothMetadataListener; +import android.bluetooth.IBluetoothOobDataCallback; +import android.bluetooth.IBluetoothPreferredAudioProfilesCallback; +import android.bluetooth.IBluetoothQualityReportReadyCallback; +import android.bluetooth.IBluetoothSocketManager; +import android.bluetooth.IncomingRfcommSocketInfo; +import android.bluetooth.OobData; +import android.content.AttributionSource; +import android.os.Binder; +import android.os.Bundle; +import android.os.IBinder; +import android.os.Message; +import android.os.ParcelUuid; +import android.os.Process; +import android.os.RemoteCallbackList; +import android.os.RemoteException; +import android.util.Log; + +import com.android.bluetooth.BluetoothStatsLog; +import com.android.bluetooth.Utils; +import com.android.bluetooth.btservice.RemoteDevices.DeviceProperties; +import com.android.bluetooth.flags.Flags; +import com.android.modules.expresslog.Counter; + +import libcore.util.SneakyThrow; + +import java.io.FileDescriptor; +import java.io.FileOutputStream; +import java.io.PrintWriter; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import java.util.Optional; +import java.util.Set; +import java.util.concurrent.CompletableFuture; +import java.util.stream.Collectors; + +/** + * There is no leak of this binder since it is never re-used and the process is systematically + * killed + */ +class AdapterServiceBinder extends IBluetooth.Stub { + private static final String TAG = + Utils.TAG_PREFIX_BLUETOOTH + AdapterServiceBinder.class.getSimpleName(); + + private static final int MIN_ADVT_INSTANCES_FOR_MA = 5; + private static final int MIN_OFFLOADED_FILTERS = 10; + private static final int MIN_OFFLOADED_SCAN_STORAGE_BYTES = 1024; + + private final AdapterService mService; + + AdapterServiceBinder(AdapterService svc) { + mService = svc; + } + + public AdapterService getService() { + if (!mService.isAvailable()) { + return null; + } + return mService; + } + + @Override + public int getState() { + AdapterService service = getService(); + if (service == null) { + return BluetoothAdapter.STATE_OFF; + } + + return service.getState(); + } + + @Override + public void killBluetoothProcess() { + mService.enforceCallingPermission(BLUETOOTH_PRIVILEGED, null); + + Runnable killAction = + () -> { + if (Flags.killInsteadOfExit()) { + Log.i(TAG, "killBluetoothProcess: Calling killProcess(myPid())"); + Process.killProcess(Process.myPid()); + } else { + Log.i(TAG, "killBluetoothProcess: Calling System.exit"); + System.exit(0); + } + }; + + // Post on the main handler to let the cleanup complete before calling exit + mService.getHandler().post(killAction); + + try { + // Wait for Bluetooth to be killed from its main thread + Thread.sleep(1_000); // SystemServer is waiting 2000 ms, we need to wait less here + } catch (InterruptedException e) { + Log.e(TAG, "killBluetoothProcess: Interrupted while waiting for kill"); + } + + // Bluetooth cannot be killed on the main thread; it is in a deadLock. + // Trying to recover by killing the Bluetooth from the binder thread. + // This is bad :( + Counter.logIncrement("bluetooth.value_kill_from_binder_thread"); + Log.wtf(TAG, "Failed to kill Bluetooth using its main thread. Trying from binder"); + killAction.run(); + } + + @Override + public void offToBleOn(boolean quietMode, AttributionSource source) { + AdapterService service = getService(); + if (service == null || !callerIsSystemOrActiveOrManagedUser(service, TAG, "offToBleOn")) { + return; + } + + service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null); + + service.offToBleOn(quietMode); + } + + @Override + public void onToBleOn(AttributionSource source) { + AdapterService service = getService(); + if (service == null || !callerIsSystemOrActiveOrManagedUser(service, TAG, "onToBleOn")) { + return; + } + + service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null); + + service.onToBleOn(); + } + + @Override + public String getAddress(AttributionSource source) { + AdapterService service = getService(); + if (service == null + || !callerIsSystemOrActiveOrManagedUser(service, TAG, "getAddress") + || !Utils.checkConnectPermissionForDataDelivery( + service, source, "AdapterService getAddress")) { + return null; + } + + service.enforceCallingOrSelfPermission(LOCAL_MAC_ADDRESS, null); + + return Utils.getAddressStringFromByte(service.getAdapterProperties().getAddress()); + } + + @Override + public List<ParcelUuid> getUuids(AttributionSource source) { + AdapterService service = getService(); + if (service == null + || !callerIsSystemOrActiveOrManagedUser(service, TAG, "getUuids") + || !Utils.checkConnectPermissionForDataDelivery( + service, source, "AdapterService getUuids")) { + return Collections.emptyList(); + } + + ParcelUuid[] parcels = service.getAdapterProperties().getUuids(); + if (parcels == null) { + parcels = new ParcelUuid[0]; + } + return Arrays.asList(parcels); + } + + @Override + public String getIdentityAddress(String address) { + AdapterService service = getService(); + if (service == null + || !callerIsSystemOrActiveOrManagedUser(service, TAG, "getIdentityAddress") + || !Utils.checkConnectPermissionForDataDelivery( + service, + Utils.getCallingAttributionSource(mService), + "AdapterService getIdentityAddress")) { + return null; + } + service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null); + return service.getIdentityAddress(address); + } + + @Override + @NonNull + public BluetoothAddress getIdentityAddressWithType(@NonNull String address) { + AdapterService service = getService(); + if (service == null + || !callerIsSystemOrActiveOrManagedUser(service, TAG, "getIdentityAddressWithType") + || !Utils.checkConnectPermissionForDataDelivery( + service, + Utils.getCallingAttributionSource(mService), + "AdapterService getIdentityAddressWithType")) { + return new BluetoothAddress(null, BluetoothDevice.ADDRESS_TYPE_UNKNOWN); + } + service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null); + return service.getIdentityAddressWithType(address); + } + + @Override + public String getName(AttributionSource source) { + AdapterService service = getService(); + if (service == null + || !callerIsSystemOrActiveOrManagedUser(service, TAG, "getName") + || !Utils.checkConnectPermissionForDataDelivery( + service, source, "AdapterService getName")) { + return null; + } + + return service.getName(); + } + + @Override + public int getNameLengthForAdvertise(AttributionSource source) { + AdapterService service = getService(); + if (service == null + || !callerIsSystemOrActiveOrManagedUser(service, TAG, "getNameLengthForAdvertise") + || !Utils.checkAdvertisePermissionForDataDelivery(service, source, TAG)) { + return -1; + } + + return service.getNameLengthForAdvertise(); + } + + @Override + public boolean setName(String name, AttributionSource source) { + AdapterService service = getService(); + if (service == null + || !callerIsSystemOrActiveOrManagedUser(service, TAG, "setName") + || !Utils.checkConnectPermissionForDataDelivery( + service, source, "AdapterService setName")) { + return false; + } + + if (Flags.emptyNamesAreInvalid()) { + requireNonNull(name); + name = name.trim(); + if (name.isEmpty()) { + throw new IllegalArgumentException("Empty names are not valid"); + } + } + + Log.d(TAG, "AdapterServiceBinder.setName(" + name + ")"); + return service.getAdapterProperties().setName(name); + } + + @Override + public int getScanMode(AttributionSource source) { + AdapterService service = getService(); + if (service == null + || !callerIsSystemOrActiveOrManagedUser(service, TAG, "getScanMode") + || !Utils.checkScanPermissionForDataDelivery( + service, source, "AdapterService getScanMode")) { + return SCAN_MODE_NONE; + } + + return service.getScanMode(); + } + + @Override + public int setScanMode(int mode, AttributionSource source) { + AdapterService service = getService(); + if (service == null + || !callerIsSystemOrActiveOrManagedUser(service, TAG, "setScanMode") + || !Utils.checkScanPermissionForDataDelivery( + service, source, "AdapterService setScanMode")) { + return BluetoothStatusCodes.ERROR_MISSING_BLUETOOTH_SCAN_PERMISSION; + } + service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null); + + String logCaller = Utils.getUidPidString() + " packageName=" + source.getPackageName(); + CompletableFuture<Boolean> future = new CompletableFuture<>(); + mService.getHandler() + .post( + () -> + future.complete( + service.getState() == BluetoothAdapter.STATE_ON + && service.setScanMode(mode, logCaller))); + return future.join() ? BluetoothStatusCodes.SUCCESS : BluetoothStatusCodes.ERROR_UNKNOWN; + } + + @Override + public long getDiscoverableTimeout(AttributionSource source) { + AdapterService service = getService(); + if (service == null + || !callerIsSystemOrActiveOrManagedUser(service, TAG, "getDiscoverableTimeout") + || !Utils.checkScanPermissionForDataDelivery( + service, source, "AdapterService getDiscoverableTimeout")) { + return -1; + } + + return service.getAdapterProperties().getDiscoverableTimeout(); + } + + @Override + public int setDiscoverableTimeout(long timeout, AttributionSource source) { + AdapterService service = getService(); + if (service == null + || !callerIsSystemOrActiveOrManagedUser(service, TAG, "setDiscoverableTimeout") + || !Utils.checkScanPermissionForDataDelivery( + service, source, "AdapterService setDiscoverableTimeout")) { + return BluetoothStatusCodes.ERROR_MISSING_BLUETOOTH_SCAN_PERMISSION; + } + service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null); + + return service.getAdapterProperties().setDiscoverableTimeout((int) timeout) + ? BluetoothStatusCodes.SUCCESS + : BluetoothStatusCodes.ERROR_UNKNOWN; + } + + @Override + public boolean startDiscovery(AttributionSource source) { + AdapterService service = getService(); + if (service == null + || !callerIsSystemOrActiveOrManagedUser(service, TAG, "startDiscovery")) { + return false; + } + + if (!Utils.checkScanPermissionForDataDelivery(service, source, "Starting discovery.")) { + return false; + } + + Log.i(TAG, "startDiscovery: from " + Utils.getUidPidString()); + return service.startDiscovery(source); + } + + @Override + public boolean cancelDiscovery(AttributionSource source) { + AdapterService service = getService(); + if (service == null + || !callerIsSystemOrActiveOrManagedUser(service, TAG, "cancelDiscovery") + || !Utils.checkScanPermissionForDataDelivery( + service, source, "AdapterService cancelDiscovery")) { + return false; + } + + Log.i(TAG, "cancelDiscovery: from " + Utils.getUidPidString()); + return service.getNative().cancelDiscovery(); + } + + @Override + public boolean isDiscovering(AttributionSource source) { + AdapterService service = getService(); + if (service == null + || !callerIsSystemOrActiveOrManagedUser(service, TAG, "isDiscovering") + || !Utils.checkScanPermissionForDataDelivery( + service, source, "AdapterService isDiscovering")) { + return false; + } + + return service.getAdapterProperties().isDiscovering(); + } + + @Override + public long getDiscoveryEndMillis(AttributionSource source) { + AdapterService service = getService(); + if (service == null + || !callerIsSystemOrActiveOrManagedUser(service, TAG, "getDiscoveryEndMillis") + || !Utils.checkConnectPermissionForDataDelivery(service, source, TAG)) { + return -1; + } + + service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null); + + return service.getAdapterProperties().discoveryEndMillis(); + } + + @Override + public List<BluetoothDevice> getMostRecentlyConnectedDevices(AttributionSource source) { + // don't check caller, may be called from system UI + AdapterService service = getService(); + if (service == null + || !Utils.checkConnectPermissionForDataDelivery( + service, source, "AdapterService getMostRecentlyConnectedDevices")) { + return Collections.emptyList(); + } + + service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null); + + return service.getDatabaseManager().getMostRecentlyConnectedDevices(); + } + + @Override + public List<BluetoothDevice> getBondedDevices(AttributionSource source) { + // don't check caller, may be called from system UI + AdapterService service = getService(); + if (service == null + || !Utils.checkConnectPermissionForDataDelivery( + service, source, "AdapterService getBondedDevices")) { + return Collections.emptyList(); + } + + return Arrays.asList(service.getBondedDevices()); + } + + @Override + public int getAdapterConnectionState() { + // don't check caller, may be called from system UI + AdapterService service = getService(); + if (service == null) { + return BluetoothAdapter.STATE_DISCONNECTED; + } + + return service.getAdapterProperties().getConnectionState(); + } + + /** + * This method has an associated binder cache. The invalidation methods must be changed if the + * logic behind this method changes. + */ + @Override + public int getProfileConnectionState(int profile, AttributionSource source) { + AdapterService service = getService(); + boolean checkConnect = false; + final int callingUid = Binder.getCallingUid(); + final long token = Binder.clearCallingIdentity(); + try { + checkConnect = CompatChanges.isChangeEnabled(ENFORCE_CONNECT, callingUid); + } finally { + Binder.restoreCallingIdentity(token); + } + if (service == null + || !callerIsSystemOrActiveOrManagedUser(service, TAG, "getProfileConnectionState") + || (checkConnect + && !Utils.checkConnectPermissionForDataDelivery( + service, source, "AdapterService getProfileConnectionState"))) { + return STATE_DISCONNECTED; + } + + return service.getAdapterProperties().getProfileConnectionState(profile); + } + + @Override + public boolean createBond(BluetoothDevice device, int transport, AttributionSource source) { + AdapterService service = getService(); + if (service == null + || !callerIsSystemOrActiveOrManagedUser(service, TAG, "createBond") + || !Utils.checkConnectPermissionForDataDelivery( + service, source, "AdapterService createBond")) { + return false; + } + + Log.i( + TAG, + "createBond:" + + (" device=" + device) + + (" transport=" + transport) + + (" from " + Utils.getUidPidString())); + return service.createBond(device, transport, null, null, source.getPackageName()); + } + + @Override + public boolean createBondOutOfBand( + BluetoothDevice device, + int transport, + OobData remoteP192Data, + OobData remoteP256Data, + AttributionSource source) { + AdapterService service = getService(); + if (service == null + || !callerIsSystemOrActiveOrManagedUser(service, TAG, "createBond") + || !Utils.checkConnectPermissionForDataDelivery( + service, source, "AdapterService createBond")) { + return false; + } + + service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null); + + Log.i( + TAG, + "createBondOutOfBand:" + + (" device=" + device) + + (" transport=" + transport) + + (" from " + Utils.getUidPidString())); + return service.createBond( + device, transport, remoteP192Data, remoteP256Data, source.getPackageName()); + } + + @Override + public boolean cancelBondProcess(BluetoothDevice device, AttributionSource source) { + AdapterService service = getService(); + if (service == null + || !callerIsSystemOrActiveOrManagedUser(service, TAG, "cancelBondProcess") + || !Utils.checkConnectPermissionForDataDelivery( + service, source, "AdapterService cancelBondProcess")) { + return false; + } + + service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null); + + Log.i(TAG, "cancelBondProcess: device=" + device + ", from " + Utils.getUidPidString()); + + DeviceProperties deviceProp = service.getRemoteDevices().getDeviceProperties(device); + if (deviceProp != null) { + deviceProp.setBondingInitiatedLocally(false); + } + + service.logUserBondResponse(device, false, source); + return service.getNative().cancelBond(getBytesFromAddress(device.getAddress())); + } + + @Override + public boolean removeBond(BluetoothDevice device, AttributionSource source) { + AdapterService service = getService(); + if (service == null + || !callerIsSystemOrActiveOrManagedUser(service, TAG, "removeBond") + || !Utils.checkConnectPermissionForDataDelivery( + service, source, "AdapterService removeBond")) { + return false; + } + + Log.i(TAG, "removeBond: device=" + device + ", from " + Utils.getUidPidString()); + + DeviceProperties deviceProp = service.getRemoteDevices().getDeviceProperties(device); + if (deviceProp == null || deviceProp.getBondState() != BluetoothDevice.BOND_BONDED) { + Log.w( + TAG, + device + + " cannot be removed since " + + ((deviceProp == null) + ? "properties are empty" + : "bond state is " + deviceProp.getBondState())); + return false; + } + service.logUserBondResponse(device, false, source); + service.getBondAttemptCallerInfo().remove(device.getAddress()); + service.getPhonePolicy().ifPresent(policy -> policy.onRemoveBondRequest(device)); + deviceProp.setBondingInitiatedLocally(false); + + Message msg = service.getBondStateMachine().obtainMessage(BondStateMachine.REMOVE_BOND); + msg.obj = device; + service.getBondStateMachine().sendMessage(msg); + return true; + } + + @Override + public int getBondState(BluetoothDevice device, AttributionSource source) { + // don't check caller, may be called from system UI + AdapterService service = getService(); + if (service == null + || !Utils.checkConnectPermissionForDataDelivery( + service, source, "AdapterService getBondState")) { + return BluetoothDevice.BOND_NONE; + } + + return service.getBondState(device); + } + + @Override + public boolean isBondingInitiatedLocally(BluetoothDevice device, AttributionSource source) { + // don't check caller, may be called from system UI + AdapterService service = getService(); + if (service == null + || !Utils.checkConnectPermissionForDataDelivery( + service, source, "AdapterService isBondingInitiatedLocally")) { + return false; + } + + DeviceProperties deviceProp = service.getRemoteDevices().getDeviceProperties(device); + return deviceProp != null && deviceProp.isBondingInitiatedLocally(); + } + + @Override + public void generateLocalOobData( + int transport, IBluetoothOobDataCallback callback, AttributionSource source) { + AdapterService service = getService(); + if (service == null + || !callerIsSystemOrActiveOrManagedUser(service, TAG, "generateLocalOobData") + || !Utils.checkConnectPermissionForDataDelivery(service, source, TAG)) { + return; + } + service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null); + service.generateLocalOobData(transport, callback); + } + + @Override + public long getSupportedProfiles(AttributionSource source) { + AdapterService service = getService(); + if (service == null || !Utils.checkConnectPermissionForDataDelivery(service, source, TAG)) { + return 0; + } + service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null); + + return Config.getSupportedProfilesBitMask(); + } + + @Override + public int getConnectionState(BluetoothDevice device, AttributionSource source) { + AdapterService service = getService(); + if (service == null + || !Utils.checkConnectPermissionForDataDelivery( + service, source, "AdapterService getConnectionState")) { + return BluetoothDevice.CONNECTION_STATE_DISCONNECTED; + } + + return service.getConnectionState(device); + } + + @Override + public int getConnectionHandle( + BluetoothDevice device, int transport, AttributionSource source) { + AdapterService service = getService(); + if (service == null + || !callerIsSystemOrActiveOrManagedUser(service, TAG, "getConnectionHandle") + || !Utils.checkConnectPermissionForDataDelivery(service, source, TAG)) { + return BluetoothDevice.ERROR; + } + + service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null); + + return service.getConnectionHandle(device, transport); + } + + @Override + public boolean canBondWithoutDialog(BluetoothDevice device, AttributionSource source) { + AdapterService service = getService(); + if (service == null || !Utils.checkConnectPermissionForDataDelivery(service, source, TAG)) { + return false; + } + + service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null); + + return service.canBondWithoutDialog(device); + } + + @Override + public String getPackageNameOfBondingApplication( + BluetoothDevice device, AttributionSource source) { + AdapterService service = getService(); + + if (service == null || !Utils.checkConnectPermissionForDataDelivery(service, source, TAG)) { + return null; + } + + service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null); + + return service.getPackageNameOfBondingApplication(device); + } + + @Override + public boolean removeActiveDevice(@ActiveDeviceUse int profiles, AttributionSource source) { + AdapterService service = getService(); + if (service == null + || !callerIsSystemOrActiveOrManagedUser(service, TAG, "removeActiveDevice") + || !Utils.checkConnectPermissionForDataDelivery(service, source, TAG)) { + return false; + } + + service.enforceCallingOrSelfPermission(MODIFY_PHONE_STATE, null); + service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null); + + Log.i( + TAG, + "removeActiveDevice: profiles=" + profiles + ", from " + Utils.getUidPidString()); + return service.setActiveDevice(null, profiles); + } + + @Override + public boolean setActiveDevice( + BluetoothDevice device, @ActiveDeviceUse int profiles, AttributionSource source) { + AdapterService service = getService(); + if (service == null + || !callerIsSystemOrActiveOrManagedUser(service, TAG, "setActiveDevice") + || !Utils.checkConnectPermissionForDataDelivery(service, source, TAG)) { + return false; + } + + service.enforceCallingOrSelfPermission(MODIFY_PHONE_STATE, null); + service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null); + + Log.i( + TAG, + "setActiveDevice: device=" + + device + + ", profiles=" + + profiles + + ", from " + + Utils.getUidPidString()); + + return service.setActiveDevice(device, profiles); + } + + @Override + public List<BluetoothDevice> getActiveDevices( + @ActiveDeviceProfile int profile, AttributionSource source) { + AdapterService service = getService(); + if (service == null + || !callerIsSystemOrActiveOrManagedUser(service, TAG, "getActiveDevices") + || !Utils.checkConnectPermissionForDataDelivery(service, source, TAG)) { + return Collections.emptyList(); + } + + service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null); + + return service.getActiveDevices(profile); + } + + @Override + public int connectAllEnabledProfiles(BluetoothDevice device, AttributionSource source) { + AdapterService service = getService(); + if (service == null || !service.isEnabled()) { + return BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ENABLED; + } + if (!callerIsSystemOrActiveOrManagedUser(service, TAG, "connectAllEnabledProfiles")) { + return BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ALLOWED; + } + if (device == null) { + throw new IllegalArgumentException("device cannot be null"); + } + if (!BluetoothAdapter.checkBluetoothAddress(device.getAddress())) { + throw new IllegalArgumentException("device cannot have an invalid address"); + } + if (!Utils.checkConnectPermissionForDataDelivery(service, source, TAG)) { + return BluetoothStatusCodes.ERROR_MISSING_BLUETOOTH_CONNECT_PERMISSION; + } + + service.enforceCallingOrSelfPermission(MODIFY_PHONE_STATE, null); + service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null); + + Log.i( + TAG, + "connectAllEnabledProfiles: device=" + + device + + ", from " + + Utils.getUidPidString()); + MetricsLogger.getInstance() + .logBluetoothEvent( + device, + BluetoothStatsLog + .BLUETOOTH_CROSS_LAYER_EVENT_REPORTED__EVENT_TYPE__INITIATOR_CONNECTION, + BluetoothStatsLog.BLUETOOTH_CROSS_LAYER_EVENT_REPORTED__STATE__START, + source.getUid()); + + try { + return service.connectAllEnabledProfiles(device); + } catch (Exception e) { + Log.v(TAG, "connectAllEnabledProfiles() failed", e); + SneakyThrow.sneakyThrow(e); + throw new RuntimeException(e); + } + } + + @Override + public int disconnectAllEnabledProfiles(BluetoothDevice device, AttributionSource source) { + AdapterService service = getService(); + if (service == null) { + return BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ENABLED; + } + if (!callerIsSystemOrActiveOrManagedUser(service, TAG, "disconnectAllEnabledProfiles")) { + return BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ALLOWED; + } + if (device == null) { + throw new IllegalArgumentException("device cannot be null"); + } + if (!BluetoothAdapter.checkBluetoothAddress(device.getAddress())) { + throw new IllegalArgumentException("device cannot have an invalid address"); + } + if (!Utils.checkConnectPermissionForDataDelivery(service, source, TAG)) { + return BluetoothStatusCodes.ERROR_MISSING_BLUETOOTH_CONNECT_PERMISSION; + } + + service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null); + + Log.i( + TAG, + "disconnectAllEnabledProfiles: device=" + + device + + ", from " + + Utils.getUidPidString()); + + try { + return service.disconnectAllEnabledProfiles(device); + } catch (Exception e) { + Log.v(TAG, "disconnectAllEnabledProfiles() failed", e); + SneakyThrow.sneakyThrow(e); + throw new RuntimeException(e); + } + } + + @Override + public String getRemoteName(BluetoothDevice device, AttributionSource source) { + AdapterService service = getService(); + if (service == null + || !callerIsSystemOrActiveOrManagedUser(service, TAG, "getRemoteName") + || !Utils.checkConnectPermissionForDataDelivery( + service, source, "AdapterService getRemoteName")) { + return null; + } + + return service.getRemoteName(device); + } + + @Override + public int getRemoteType(BluetoothDevice device, AttributionSource source) { + AdapterService service = getService(); + if (service == null + || !callerIsSystemOrActiveOrManagedUser(service, TAG, "getRemoteType") + || !Utils.checkConnectPermissionForDataDelivery( + service, source, "AdapterService getRemoteType")) { + return BluetoothDevice.DEVICE_TYPE_UNKNOWN; + } + + return service.getRemoteType(device); + } + + @Override + public String getRemoteAlias(BluetoothDevice device, AttributionSource source) { + AdapterService service = getService(); + if (service == null + || !callerIsSystemOrActiveOrManagedUser(service, TAG, "getRemoteAlias") + || !Utils.checkConnectPermissionForDataDelivery( + service, source, "AdapterService getRemoteAlias")) { + return null; + } + + DeviceProperties deviceProp = service.getRemoteDevices().getDeviceProperties(device); + return deviceProp != null ? deviceProp.getAlias() : null; + } + + @Override + public int setRemoteAlias(BluetoothDevice device, String name, AttributionSource source) { + AdapterService service = getService(); + if (service == null) { + return BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ENABLED; + } + if (!callerIsSystemOrActiveOrManagedUser(service, TAG, "setRemoteAlias")) { + return BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ALLOWED; + } + if (name != null && name.isEmpty()) { + throw new IllegalArgumentException("alias cannot be the empty string"); + } + + if (!Utils.checkConnectPermissionForDataDelivery( + service, source, "AdapterService setRemoteAlias")) { + return BluetoothStatusCodes.ERROR_MISSING_BLUETOOTH_CONNECT_PERMISSION; + } + + Utils.enforceCdmAssociationIfNotBluetoothPrivileged( + service, service.getCompanionDeviceManager(), source, device); + + DeviceProperties deviceProp = service.getRemoteDevices().getDeviceProperties(device); + if (deviceProp == null) { + return BluetoothStatusCodes.ERROR_DEVICE_NOT_BONDED; + } + deviceProp.setAlias(device, name); + return BluetoothStatusCodes.SUCCESS; + } + + @Override + public int getRemoteClass(BluetoothDevice device, AttributionSource source) { + AdapterService service = getService(); + if (service == null + || !callerIsSystemOrActiveOrManagedUser(service, TAG, "getRemoteClass") + || !Utils.checkConnectPermissionForDataDelivery( + service, source, "AdapterService getRemoteClass")) { + return 0; + } + + return service.getRemoteClass(device); + } + + @Override + public List<ParcelUuid> getRemoteUuids(BluetoothDevice device, AttributionSource source) { + AdapterService service = getService(); + if (service == null + || !callerIsSystemOrActiveOrManagedUser(service, TAG, "getRemoteUuids") + || !Utils.checkConnectPermissionForDataDelivery( + service, source, "AdapterService getRemoteUuids")) { + return Collections.emptyList(); + } + + final ParcelUuid[] parcels = service.getRemoteUuids(device); + if (parcels == null) { + return null; + } + return Arrays.asList(parcels); + } + + @Override + public boolean fetchRemoteUuids( + BluetoothDevice device, int transport, AttributionSource source) { + AdapterService service = getService(); + if (service == null + || !callerIsSystemOrActiveOrManagedUser(service, TAG, "fetchRemoteUuids") + || !Utils.checkConnectPermissionForDataDelivery( + service, source, "AdapterService fetchRemoteUuids")) { + return false; + } + if (transport != TRANSPORT_AUTO) { + service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null); + } + + Log.i( + TAG, + "fetchRemoteUuids: device=" + + device + + ", transport=" + + transport + + ", from " + + Utils.getUidPidString()); + + service.getRemoteDevices().fetchUuids(device, transport); + MetricsLogger.getInstance().cacheCount(BluetoothProtoEnums.SDP_FETCH_UUID_REQUEST, 1); + return true; + } + + @Override + public boolean setPin( + BluetoothDevice device, + boolean accept, + int len, + byte[] pinCode, + AttributionSource source) { + AdapterService service = getService(); + if (service == null + || !callerIsSystemOrActiveOrManagedUser(service, TAG, "setPin") + || !Utils.checkConnectPermissionForDataDelivery( + service, source, "AdapterService setPin")) { + return false; + } + + DeviceProperties deviceProp = service.getRemoteDevices().getDeviceProperties(device); + // Only allow setting a pin in bonding state, or bonded state in case of security + // upgrade. + if (deviceProp == null || !deviceProp.isBondingOrBonded()) { + Log.e(TAG, "setPin: device=" + device + ", not bonding"); + return false; + } + if (pinCode.length != len) { + android.util.EventLog.writeEvent( + 0x534e4554, "139287605", -1, "PIN code length mismatch"); + return false; + } + service.logUserBondResponse(device, accept, source); + Log.i( + TAG, + "setPin: device=" + + device + + ", accept=" + + accept + + ", from " + + Utils.getUidPidString()); + return service.getNative() + .pinReply(getBytesFromAddress(device.getAddress()), accept, len, pinCode); + } + + @Override + public boolean setPasskey( + BluetoothDevice device, + boolean accept, + int len, + byte[] passkey, + AttributionSource source) { + AdapterService service = getService(); + if (service == null + || !callerIsSystemOrActiveOrManagedUser(service, TAG, "setPasskey") + || !Utils.checkConnectPermissionForDataDelivery( + service, source, "AdapterService setPasskey")) { + return false; + } + + DeviceProperties deviceProp = service.getRemoteDevices().getDeviceProperties(device); + if (deviceProp == null || !deviceProp.isBonding()) { + Log.e(TAG, "setPasskey: device=" + device + ", not bonding"); + return false; + } + if (passkey.length != len) { + android.util.EventLog.writeEvent( + 0x534e4554, "139287605", -1, "Passkey length mismatch"); + return false; + } + service.logUserBondResponse(device, accept, source); + Log.i( + TAG, + "setPasskey: device=" + + device + + ", accept=" + + accept + + ", from " + + Utils.getUidPidString()); + + return service.getNative() + .sspReply( + getBytesFromAddress(device.getAddress()), + AbstractionLayer.BT_SSP_VARIANT_PASSKEY_ENTRY, + accept, + Utils.byteArrayToInt(passkey)); + } + + @Override + public boolean setPairingConfirmation( + BluetoothDevice device, boolean accept, AttributionSource source) { + AdapterService service = getService(); + if (service == null + || !callerIsSystemOrActiveOrManagedUser(service, TAG, "setPairingConfirmation") + || !Utils.checkConnectPermissionForDataDelivery(service, source, TAG)) { + return false; + } + + service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null); + + DeviceProperties deviceProp = service.getRemoteDevices().getDeviceProperties(device); + if (deviceProp == null || !deviceProp.isBonding()) { + Log.e(TAG, "setPairingConfirmation: device=" + device + ", not bonding"); + return false; + } + service.logUserBondResponse(device, accept, source); + Log.i( + TAG, + "setPairingConfirmation: device=" + + device + + ", accept=" + + accept + + ", from " + + Utils.getUidPidString()); + + return service.getNative() + .sspReply( + getBytesFromAddress(device.getAddress()), + AbstractionLayer.BT_SSP_VARIANT_PASSKEY_CONFIRMATION, + accept, + 0); + } + + @Override + public boolean getSilenceMode(BluetoothDevice device, AttributionSource source) { + AdapterService service = getService(); + if (service == null + || !callerIsSystemOrActiveOrManagedUser(service, TAG, "getSilenceMode") + || !Utils.checkConnectPermissionForDataDelivery(service, source, TAG)) { + return false; + } + + service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null); + + return service.getSilenceDeviceManager().getSilenceMode(device); + } + + @Override + public boolean setSilenceMode( + BluetoothDevice device, boolean silence, AttributionSource source) { + AdapterService service = getService(); + if (service == null + || !callerIsSystemOrActiveOrManagedUser(service, TAG, "setSilenceMode") + || !Utils.checkConnectPermissionForDataDelivery(service, source, TAG)) { + return false; + } + + service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null); + + service.getSilenceDeviceManager().setSilenceMode(device, silence); + return true; + } + + @Override + public int getPhonebookAccessPermission(BluetoothDevice device, AttributionSource source) { + AdapterService service = getService(); + if (service == null + || !callerIsSystemOrActiveOrManagedUser( + service, TAG, "getPhonebookAccessPermission") + || !Utils.checkConnectPermissionForDataDelivery( + service, source, "AdapterService getPhonebookAccessPermission")) { + return BluetoothDevice.ACCESS_UNKNOWN; + } + + return service.getPhonebookAccessPermission(device); + } + + @Override + public boolean setPhonebookAccessPermission( + BluetoothDevice device, int value, AttributionSource source) { + AdapterService service = getService(); + if (service == null + || !callerIsSystemOrActiveOrManagedUser( + service, TAG, "setPhonebookAccessPermission") + || !Utils.checkConnectPermissionForDataDelivery(service, source, TAG)) { + return false; + } + + service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null); + + service.setPhonebookAccessPermission(device, value); + return true; + } + + @Override + public int getMessageAccessPermission(BluetoothDevice device, AttributionSource source) { + AdapterService service = getService(); + if (service == null + || !callerIsSystemOrActiveOrManagedUser(service, TAG, "getMessageAccessPermission") + || !Utils.checkConnectPermissionForDataDelivery( + service, source, "AdapterService getMessageAccessPermission")) { + return BluetoothDevice.ACCESS_UNKNOWN; + } + + return service.getMessageAccessPermission(device); + } + + @Override + public boolean setMessageAccessPermission( + BluetoothDevice device, int value, AttributionSource source) { + AdapterService service = getService(); + if (service == null + || !callerIsSystemOrActiveOrManagedUser(service, TAG, "setMessageAccessPermission") + || !Utils.checkConnectPermissionForDataDelivery(service, source, TAG)) { + return false; + } + + service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null); + + service.setMessageAccessPermission(device, value); + return true; + } + + @Override + public int getSimAccessPermission(BluetoothDevice device, AttributionSource source) { + AdapterService service = getService(); + if (service == null + || !callerIsSystemOrActiveOrManagedUser(service, TAG, "getSimAccessPermission") + || !Utils.checkConnectPermissionForDataDelivery( + service, source, "AdapterService getSimAccessPermission")) { + return BluetoothDevice.ACCESS_UNKNOWN; + } + + return service.getSimAccessPermission(device); + } + + @Override + public boolean setSimAccessPermission( + BluetoothDevice device, int value, AttributionSource source) { + AdapterService service = getService(); + if (service == null + || !callerIsSystemOrActiveOrManagedUser(service, TAG, "setSimAccessPermission") + || !Utils.checkConnectPermissionForDataDelivery(service, source, TAG)) { + return false; + } + + service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null); + + service.setSimAccessPermission(device, value); + return true; + } + + @Override + public void logL2capcocServerConnection( + BluetoothDevice device, + int port, + boolean isSecured, + int result, + long socketCreationTimeMillis, + long socketCreationLatencyMillis, + long socketConnectionTimeMillis, + long timeoutMillis) { + AdapterService service = getService(); + if (service == null) { + return; + } + service.logL2capcocServerConnection( + device, + port, + isSecured, + result, + socketCreationTimeMillis, + socketCreationLatencyMillis, + socketConnectionTimeMillis, + timeoutMillis, + Binder.getCallingUid()); + } + + @Override + public IBluetoothSocketManager getSocketManager() { + AdapterService service = getService(); + if (service == null) { + return null; + } + + return IBluetoothSocketManager.Stub.asInterface(service.getBluetoothSocketManagerBinder()); + } + + @Override + public void logL2capcocClientConnection( + BluetoothDevice device, + int port, + boolean isSecured, + int result, + long socketCreationTimeNanos, + long socketCreationLatencyNanos, + long socketConnectionTimeNanos) { + AdapterService service = getService(); + if (service == null) { + return; + } + service.logL2capcocClientConnection( + device, + port, + isSecured, + result, + socketCreationTimeNanos, + socketCreationLatencyNanos, + socketConnectionTimeNanos, + Binder.getCallingUid()); + } + + @Override + public void logRfcommConnectionAttempt( + BluetoothDevice device, + boolean isSecured, + int resultCode, + long socketCreationTimeNanos, + boolean isSerialPort) { + AdapterService service = getService(); + if (service == null) { + return; + } + service.logRfcommConnectionAttempt( + device, + isSecured, + resultCode, + socketCreationTimeNanos, + isSerialPort, + Binder.getCallingUid()); + } + + @Override + public boolean sdpSearch(BluetoothDevice device, ParcelUuid uuid, AttributionSource source) { + AdapterService service = getService(); + if (service == null + || !callerIsSystemOrActiveOrManagedUser(service, TAG, "sdpSearch") + || !Utils.checkConnectPermissionForDataDelivery( + service, source, "AdapterService sdpSearch")) { + return false; + } + return service.sdpSearch(device, uuid); + } + + @Override + public int getBatteryLevel(BluetoothDevice device, AttributionSource source) { + AdapterService service = getService(); + if (service == null + || !callerIsSystemOrActiveOrManagedUser(service, TAG, "getBatteryLevel") + || !Utils.checkConnectPermissionForDataDelivery( + service, source, "AdapterService getBatteryLevel")) { + return BluetoothDevice.BATTERY_LEVEL_UNKNOWN; + } + + DeviceProperties deviceProp = service.getRemoteDevices().getDeviceProperties(device); + if (deviceProp == null) { + return BluetoothDevice.BATTERY_LEVEL_UNKNOWN; + } + return deviceProp.getBatteryLevel(); + } + + @Override + public int getMaxConnectedAudioDevices(AttributionSource source) { + // don't check caller, may be called from system UI + AdapterService service = getService(); + if (service == null + || !Utils.checkConnectPermissionForDataDelivery( + service, source, "AdapterService getMaxConnectedAudioDevices")) { + return -1; + } + + return service.getMaxConnectedAudioDevices(); + } + + @Override + public boolean factoryReset(AttributionSource source) { + AdapterService service = getService(); + if (service == null || !Utils.checkConnectPermissionForDataDelivery(service, source, TAG)) { + return false; + } + + service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null); + return service.factoryReset(); + } + + @Override + public void registerBluetoothConnectionCallback( + IBluetoothConnectionCallback callback, AttributionSource source) { + AdapterService service = getService(); + if (service == null + || !callerIsSystemOrActiveOrManagedUser( + service, TAG, "registerBluetoothConnectionCallback") + || !Utils.checkConnectPermissionForDataDelivery(service, source, TAG)) { + return; + } + service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null); + service.getBluetoothConnectionCallbacks().register(callback); + } + + @Override + public void unregisterBluetoothConnectionCallback( + IBluetoothConnectionCallback callback, AttributionSource source) { + AdapterService service = getService(); + if (service == null + || !callerIsSystemOrActiveOrManagedUser( + service, TAG, "unregisterBluetoothConnectionCallback") + || !Utils.checkConnectPermissionForDataDelivery(service, source, TAG)) { + return; + } + service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null); + service.getBluetoothConnectionCallbacks().unregister(callback); + } + + @Override + public void registerCallback(IBluetoothCallback callback, AttributionSource source) { + AdapterService service = getService(); + if (service == null + || !callerIsSystemOrActiveOrManagedUser(service, TAG, "registerCallback") + || !Utils.checkConnectPermissionForDataDelivery(service, source, TAG)) { + return; + } + + service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null); + + service.registerRemoteCallback(callback); + } + + @Override + public void unregisterCallback(IBluetoothCallback callback, AttributionSource source) { + AdapterService service = getService(); + if (service == null + || !callerIsSystemOrActiveOrManagedUser(service, TAG, "unregisterCallback") + || !Utils.checkConnectPermissionForDataDelivery(service, source, TAG)) { + return; + } + + service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null); + + service.unregisterRemoteCallback(callback); + } + + @Override + public boolean isMultiAdvertisementSupported() { + AdapterService service = getService(); + if (service == null) { + return false; + } + + int val = service.getAdapterProperties().getNumOfAdvertisementInstancesSupported(); + return val >= MIN_ADVT_INSTANCES_FOR_MA; + } + + /** + * This method has an associated binder cache. The invalidation methods must be changed if the + * logic behind this method changes. + */ + @Override + public boolean isOffloadedFilteringSupported() { + AdapterService service = getService(); + if (service == null) { + return false; + } + + int val = service.getNumOfOffloadedScanFilterSupported(); + return val >= MIN_OFFLOADED_FILTERS; + } + + @Override + public boolean isOffloadedScanBatchingSupported() { + AdapterService service = getService(); + if (service == null) { + return false; + } + + int val = service.getOffloadedScanResultStorage(); + return val >= MIN_OFFLOADED_SCAN_STORAGE_BYTES; + } + + @Override + public boolean isLe2MPhySupported() { + AdapterService service = getService(); + if (service == null) { + return false; + } + + return service.isLe2MPhySupported(); + } + + @Override + public boolean isLeCodedPhySupported() { + AdapterService service = getService(); + if (service == null) { + return false; + } + + return service.isLeCodedPhySupported(); + } + + @Override + public boolean isLeExtendedAdvertisingSupported() { + AdapterService service = getService(); + if (service == null) { + return false; + } + + return service.isLeExtendedAdvertisingSupported(); + } + + @Override + public boolean isLePeriodicAdvertisingSupported() { + AdapterService service = getService(); + if (service == null) { + return false; + } + + return service.isLePeriodicAdvertisingSupported(); + } + + @Override + public int isLeAudioSupported() { + AdapterService service = getService(); + if (service == null) { + return BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ENABLED; + } + + Set<Integer> supportedProfileServices = + Arrays.stream(Config.getSupportedProfiles()).boxed().collect(Collectors.toSet()); + int[] leAudioUnicastProfiles = Config.getLeAudioUnicastProfiles(); + + if (Arrays.stream(leAudioUnicastProfiles).allMatch(supportedProfileServices::contains)) { + return BluetoothStatusCodes.FEATURE_SUPPORTED; + } + + return BluetoothStatusCodes.FEATURE_NOT_SUPPORTED; + } + + @Override + public int isLeAudioBroadcastSourceSupported() { + AdapterService service = getService(); + if (service == null) { + return BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ENABLED; + } + + long supportBitMask = Config.getSupportedProfilesBitMask(); + if ((supportBitMask & (1 << BluetoothProfile.LE_AUDIO_BROADCAST)) != 0) { + return BluetoothStatusCodes.FEATURE_SUPPORTED; + } + + return BluetoothStatusCodes.FEATURE_NOT_SUPPORTED; + } + + @Override + public int isLeAudioBroadcastAssistantSupported() { + AdapterService service = getService(); + if (service == null) { + return BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ENABLED; + } + + int[] supportedProfileServices = Config.getSupportedProfiles(); + + if (Arrays.stream(supportedProfileServices) + .anyMatch( + profileId -> profileId == BluetoothProfile.LE_AUDIO_BROADCAST_ASSISTANT)) { + return BluetoothStatusCodes.FEATURE_SUPPORTED; + } + + return BluetoothStatusCodes.FEATURE_NOT_SUPPORTED; + } + + @Override + public int isDistanceMeasurementSupported(AttributionSource source) { + AdapterService service = getService(); + if (service == null) { + return BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ENABLED; + } else if (!callerIsSystemOrActiveOrManagedUser( + service, TAG, "isDistanceMeasurementSupported")) { + return BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ALLOWED; + } else if (!Utils.checkConnectPermissionForDataDelivery(service, source, TAG)) { + return BluetoothStatusCodes.ERROR_MISSING_BLUETOOTH_CONNECT_PERMISSION; + } + service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null); + return BluetoothStatusCodes.FEATURE_SUPPORTED; + } + + @Override + public int getLeMaximumAdvertisingDataLength() { + AdapterService service = getService(); + if (service == null) { + return 0; + } + + return service.getLeMaximumAdvertisingDataLength(); + } + + @Override + public boolean isActivityAndEnergyReportingSupported() { + AdapterService service = getService(); + if (service == null) { + return false; + } + + return service.getAdapterProperties().isActivityAndEnergyReportingSupported(); + } + + @Override + public BluetoothActivityEnergyInfo reportActivityInfo(AttributionSource source) { + AdapterService service = getService(); + if (service == null || !Utils.checkConnectPermissionForDataDelivery(service, source, TAG)) { + return null; + } + + service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null); + + return service.reportActivityInfo(); + } + + @Override + public boolean registerMetadataListener( + IBluetoothMetadataListener listener, BluetoothDevice device, AttributionSource source) { + requireNonNull(device); + requireNonNull(listener); + AdapterService service = getService(); + if (service == null + || !callerIsSystemOrActiveOrManagedUser(service, TAG, "registerMetadataListener") + || !Utils.checkConnectPermissionForDataDelivery(service, source, TAG)) { + return false; + } + + service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null); + + service.getHandler() + .post( + () -> + service.getMetadataListeners() + .computeIfAbsent(device, k -> new RemoteCallbackList()) + .register(listener)); + + return true; + } + + @Override + public boolean unregisterMetadataListener( + IBluetoothMetadataListener listener, BluetoothDevice device, AttributionSource source) { + requireNonNull(device); + requireNonNull(listener); + AdapterService service = getService(); + if (service == null + || !callerIsSystemOrActiveOrManagedUser(service, TAG, "unregisterMetadataListener") + || !Utils.checkConnectPermissionForDataDelivery(service, source, TAG)) { + return false; + } + + service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null); + + service.getHandler() + .post( + () -> + service.getMetadataListeners() + .computeIfPresent( + device, + (k, v) -> { + v.unregister(listener); + if (v.getRegisteredCallbackCount() == 0) { + return null; + } + return v; + })); + return true; + } + + @Override + public boolean setMetadata( + BluetoothDevice device, int key, byte[] value, AttributionSource source) { + AdapterService service = getService(); + if (service == null + || !callerIsSystemOrActiveOrManagedUser(service, TAG, "setMetadata") + || !Utils.checkConnectPermissionForDataDelivery(service, source, TAG)) { + return false; + } + + service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null); + return service.setMetadata(device, key, value); + } + + @Override + public byte[] getMetadata(BluetoothDevice device, int key, AttributionSource source) { + AdapterService service = getService(); + if (service == null + || !callerIsSystemOrActiveOrManagedUser(service, TAG, "getMetadata") + || !Utils.checkConnectPermissionForDataDelivery(service, source, TAG)) { + return null; + } + + service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null); + + return service.getMetadata(device, key); + } + + @Override + public int isRequestAudioPolicyAsSinkSupported( + BluetoothDevice device, AttributionSource source) { + AdapterService service = getService(); + if (service == null + || !callerIsSystemOrActiveOrManagedUser( + service, TAG, "isRequestAudioPolicyAsSinkSupported") + || !Utils.checkConnectPermissionForDataDelivery(service, source, TAG)) { + return BluetoothStatusCodes.FEATURE_NOT_CONFIGURED; + } + service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null); + return service.isRequestAudioPolicyAsSinkSupported(device); + } + + @Override + public int requestAudioPolicyAsSink( + BluetoothDevice device, BluetoothSinkAudioPolicy policies, AttributionSource source) { + AdapterService service = getService(); + if (service == null) { + return BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ENABLED; + } else if (!callerIsSystemOrActiveOrManagedUser(service, TAG, "requestAudioPolicyAsSink")) { + return BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ALLOWED; + } else if (!Utils.checkConnectPermissionForDataDelivery(service, source, TAG)) { + return BluetoothStatusCodes.ERROR_MISSING_BLUETOOTH_CONNECT_PERMISSION; + } + service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null); + return service.requestAudioPolicyAsSink(device, policies); + } + + @Override + public BluetoothSinkAudioPolicy getRequestedAudioPolicyAsSink( + BluetoothDevice device, AttributionSource source) { + AdapterService service = getService(); + if (service == null + || !callerIsSystemOrActiveOrManagedUser( + service, TAG, "getRequestedAudioPolicyAsSink") + || !Utils.checkConnectPermissionForDataDelivery(service, source, TAG)) { + return null; + } + service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null); + return service.getRequestedAudioPolicyAsSink(device); + } + + @Override + public void requestActivityInfo( + IBluetoothActivityEnergyInfoListener listener, AttributionSource source) { + BluetoothActivityEnergyInfo info = reportActivityInfo(source); + try { + listener.onBluetoothActivityEnergyInfoAvailable(info); + } catch (RemoteException e) { + Log.e(TAG, "onBluetoothActivityEnergyInfo: RemoteException", e); + } + } + + @Override + public void bleOnToOn(AttributionSource source) { + AdapterService service = getService(); + if (service == null || !callerIsSystemOrActiveOrManagedUser(service, TAG, "bleOnToOn")) { + return; + } + + service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null); + + service.bleOnToOn(); + } + + @Override + public void bleOnToOff(AttributionSource source) { + AdapterService service = getService(); + if (service == null || !callerIsSystemOrActiveOrManagedUser(service, TAG, "bleOnToOff")) { + return; + } + + service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null); + + service.bleOnToOff(); + } + + @Override + public void dump(FileDescriptor fd, String[] args) { + PrintWriter writer = new PrintWriter(new FileOutputStream(fd)); + AdapterService service = getService(); + if (service == null) { + return; + } + + service.enforceCallingOrSelfPermission(DUMP, null); + + service.dump(fd, writer, args); + writer.close(); + } + + @Override + public boolean allowLowLatencyAudio(boolean allowed, BluetoothDevice device) { + AdapterService service = getService(); + if (service == null + || !callerIsSystemOrActiveOrManagedUser(service, TAG, "allowLowLatencyAudio") + || !Utils.checkConnectPermissionForDataDelivery( + service, + Utils.getCallingAttributionSource(service), + "AdapterService allowLowLatencyAudio")) { + return false; + } + service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null); + return service.allowLowLatencyAudio(allowed, device); + } + + @Override + public int startRfcommListener( + String name, ParcelUuid uuid, PendingIntent pendingIntent, AttributionSource source) { + AdapterService service = getService(); + if (service == null + || !callerIsSystemOrActiveOrManagedUser(service, TAG, "startRfcommListener") + || !Utils.checkConnectPermissionForDataDelivery( + service, source, "AdapterService startRfcommListener")) { + return BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ALLOWED; + } + service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null); + return service.startRfcommListener(name, uuid, pendingIntent, source); + } + + @Override + public int stopRfcommListener(ParcelUuid uuid, AttributionSource source) { + AdapterService service = getService(); + if (service == null + || !callerIsSystemOrActiveOrManagedUser(service, TAG, "stopRfcommListener") + || !Utils.checkConnectPermissionForDataDelivery( + service, source, "AdapterService stopRfcommListener")) { + return BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ALLOWED; + } + service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null); + return service.stopRfcommListener(uuid, source); + } + + @Override + public IncomingRfcommSocketInfo retrievePendingSocketForServiceRecord( + ParcelUuid uuid, AttributionSource source) { + AdapterService service = getService(); + if (service == null + || !callerIsSystemOrActiveOrManagedUser( + service, TAG, "retrievePendingSocketForServiceRecord") + || !Utils.checkConnectPermissionForDataDelivery( + service, source, "AdapterService retrievePendingSocketForServiceRecord")) { + return null; + } + service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null); + return service.retrievePendingSocketForServiceRecord(uuid, source); + } + + @Override + public void setForegroundUserId(int userId, AttributionSource source) { + AdapterService service = getService(); + if (service == null + || !Utils.checkConnectPermissionForDataDelivery( + service, + Utils.getCallingAttributionSource(mService), + "AdapterService setForegroundUserId")) { + return; + } + service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null); + Utils.setForegroundUserId(userId); + } + + @Override + public int setPreferredAudioProfiles( + BluetoothDevice device, Bundle modeToProfileBundle, AttributionSource source) { + AdapterService service = getService(); + if (service == null) { + return BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ENABLED; + } + if (!callerIsSystemOrActiveOrManagedUser(service, TAG, "setPreferredAudioProfiles")) { + return BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ALLOWED; + } + requireNonNull(device); + requireNonNull(modeToProfileBundle); + if (!BluetoothAdapter.checkBluetoothAddress(device.getAddress())) { + throw new IllegalArgumentException("device cannot have an invalid address"); + } + if (service.getBondState(device) != BluetoothDevice.BOND_BONDED) { + return BluetoothStatusCodes.ERROR_DEVICE_NOT_BONDED; + } + if (!Utils.checkConnectPermissionForDataDelivery(service, source, TAG)) { + return BluetoothStatusCodes.ERROR_MISSING_BLUETOOTH_CONNECT_PERMISSION; + } + service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null); + + return service.setPreferredAudioProfiles(device, modeToProfileBundle); + } + + @Override + public Bundle getPreferredAudioProfiles(BluetoothDevice device, AttributionSource source) { + AdapterService service = getService(); + if (service == null) { + return Bundle.EMPTY; + } + if (!callerIsSystemOrActiveOrManagedUser(service, TAG, "getPreferredAudioProfiles")) { + return Bundle.EMPTY; + } + requireNonNull(device); + if (!BluetoothAdapter.checkBluetoothAddress(device.getAddress())) { + throw new IllegalArgumentException("device cannot have an invalid address"); + } + if (service.getBondState(device) != BluetoothDevice.BOND_BONDED) { + return Bundle.EMPTY; + } + if (!Utils.checkConnectPermissionForDataDelivery(service, source, TAG)) { + return Bundle.EMPTY; + } + service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null); + + return service.getPreferredAudioProfiles(device); + } + + @Override + public int notifyActiveDeviceChangeApplied(BluetoothDevice device, AttributionSource source) { + AdapterService service = getService(); + if (service == null) { + return BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ENABLED; + } + if (!callerIsSystem(TAG, "notifyActiveDeviceChangeApplied")) { + return BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ALLOWED; + } + requireNonNull(device); + if (!BluetoothAdapter.checkBluetoothAddress(device.getAddress())) { + throw new IllegalArgumentException("device cannot have an invalid address"); + } + if (service.getBondState(device) != BluetoothDevice.BOND_BONDED) { + return BluetoothStatusCodes.ERROR_DEVICE_NOT_BONDED; + } + if (!Utils.checkConnectPermissionForDataDelivery(service, source, TAG)) { + return BluetoothStatusCodes.ERROR_MISSING_BLUETOOTH_CONNECT_PERMISSION; + } + service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null); + + return service.notifyActiveDeviceChangeApplied(device); + } + + @Override + public int isDualModeAudioEnabled(AttributionSource source) { + AdapterService service = getService(); + if (service == null) { + return BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ENABLED; + } + if (!Utils.checkConnectPermissionForDataDelivery(service, source, TAG)) { + return BluetoothStatusCodes.ERROR_MISSING_BLUETOOTH_CONNECT_PERMISSION; + } + service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null); + + if (!Utils.isDualModeAudioEnabled()) { + return BluetoothStatusCodes.FEATURE_NOT_SUPPORTED; + } + + return BluetoothStatusCodes.SUCCESS; + } + + @Override + public int registerPreferredAudioProfilesChangedCallback( + IBluetoothPreferredAudioProfilesCallback callback, AttributionSource source) { + AdapterService service = getService(); + if (service == null) { + return BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ENABLED; + } + if (!callerIsSystemOrActiveOrManagedUser( + service, TAG, "registerPreferredAudioProfilesChangedCallback")) { + return BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ALLOWED; + } + requireNonNull(callback); + if (!Utils.checkConnectPermissionForDataDelivery(service, source, TAG)) { + return BluetoothStatusCodes.ERROR_MISSING_BLUETOOTH_CONNECT_PERMISSION; + } + service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null); + + // If LE only mode is enabled, the dual mode audio feature is disabled + if (!Utils.isDualModeAudioEnabled()) { + return BluetoothStatusCodes.FEATURE_NOT_SUPPORTED; + } + + service.getPreferredAudioProfilesCallbacks().register(callback); + return BluetoothStatusCodes.SUCCESS; + } + + @Override + public int unregisterPreferredAudioProfilesChangedCallback( + IBluetoothPreferredAudioProfilesCallback callback, AttributionSource source) { + AdapterService service = getService(); + if (service == null) { + return BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ENABLED; + } + if (!callerIsSystemOrActiveOrManagedUser( + service, TAG, "unregisterPreferredAudioProfilesChangedCallback")) { + return BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ALLOWED; + } + requireNonNull(callback); + if (!Utils.checkConnectPermissionForDataDelivery(service, source, TAG)) { + return BluetoothStatusCodes.ERROR_MISSING_BLUETOOTH_CONNECT_PERMISSION; + } + service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null); + + if (!service.getPreferredAudioProfilesCallbacks().unregister(callback)) { + Log.e( + TAG, + "unregisterPreferredAudioProfilesChangedCallback: callback was never " + + "registered"); + return BluetoothStatusCodes.ERROR_CALLBACK_NOT_REGISTERED; + } + return BluetoothStatusCodes.SUCCESS; + } + + @Override + public int registerBluetoothQualityReportReadyCallback( + IBluetoothQualityReportReadyCallback callback, AttributionSource source) { + AdapterService service = getService(); + if (service == null) { + return BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ENABLED; + } + if (!callerIsSystemOrActiveOrManagedUser( + service, TAG, "registerBluetoothQualityReportReadyCallback")) { + return BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ALLOWED; + } + requireNonNull(callback); + if (!Utils.checkConnectPermissionForDataDelivery(service, source, TAG)) { + return BluetoothStatusCodes.ERROR_MISSING_BLUETOOTH_CONNECT_PERMISSION; + } + service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null); + + service.getBluetoothQualityReportReadyCallbacks().register(callback); + return BluetoothStatusCodes.SUCCESS; + } + + @Override + public int unregisterBluetoothQualityReportReadyCallback( + IBluetoothQualityReportReadyCallback callback, AttributionSource source) { + AdapterService service = getService(); + if (service == null) { + return BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ENABLED; + } + if (!callerIsSystemOrActiveOrManagedUser( + service, TAG, "unregisterBluetoothQualityReportReadyCallback")) { + return BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ALLOWED; + } + requireNonNull(callback); + if (!Utils.checkConnectPermissionForDataDelivery(service, source, TAG)) { + return BluetoothStatusCodes.ERROR_MISSING_BLUETOOTH_CONNECT_PERMISSION; + } + service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null); + + if (!service.getBluetoothQualityReportReadyCallbacks().unregister(callback)) { + Log.e( + TAG, + "unregisterBluetoothQualityReportReadyCallback: callback was never " + + "registered"); + return BluetoothStatusCodes.ERROR_CALLBACK_NOT_REGISTERED; + } + return BluetoothStatusCodes.SUCCESS; + } + + @Override + public void registerHciVendorSpecificCallback( + IBluetoothHciVendorSpecificCallback callback, int[] eventCodes) { + AdapterService service = getService(); + if (service == null) { + return; + } + if (!callerIsSystemOrActiveOrManagedUser( + service, TAG, "registerHciVendorSpecificCallback")) { + throw new SecurityException("not allowed"); + } + service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null); + requireNonNull(callback); + requireNonNull(eventCodes); + + Set<Integer> eventCodesSet = Arrays.stream(eventCodes).boxed().collect(Collectors.toSet()); + if (eventCodesSet.stream() + .anyMatch((n) -> (n < 0) || (n >= 0x52 && n < 0x60) || (n > 0xff))) { + throw new IllegalArgumentException("invalid vendor-specific event code"); + } + + service.getBluetoothHciVendorSpecificDispatcher().register(callback, eventCodesSet); + } + + @Override + public void unregisterHciVendorSpecificCallback(IBluetoothHciVendorSpecificCallback callback) { + AdapterService service = getService(); + if (service == null) { + return; + } + if (!callerIsSystemOrActiveOrManagedUser( + service, TAG, "unregisterHciVendorSpecificCallback")) { + throw new SecurityException("not allowed"); + } + service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null); + requireNonNull(callback); + + service.getBluetoothHciVendorSpecificDispatcher().unregister(callback); + } + + @Override + public void sendHciVendorSpecificCommand( + int ocf, byte[] parameters, IBluetoothHciVendorSpecificCallback callback) { + AdapterService service = getService(); + if (service == null) { + return; + } + if (!callerIsSystemOrActiveOrManagedUser(service, TAG, "sendHciVendorSpecificCommand")) { + throw new SecurityException("not allowed"); + } + service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null); + + // Open this no-op android command for test purpose + int getVendorCapabilitiesOcf = 0x153; + if (ocf < 0 + || (ocf >= 0x150 && ocf < 0x160 && ocf != getVendorCapabilitiesOcf) + || (ocf > 0x3ff)) { + throw new IllegalArgumentException("invalid vendor-specific event code"); + } + requireNonNull(parameters); + if (parameters.length > 255) { + throw new IllegalArgumentException("Parameters size is too big"); + } + + Optional<byte[]> cookie = + service.getBluetoothHciVendorSpecificDispatcher().getRegisteredCookie(callback); + if (!cookie.isPresent()) { + Log.e(TAG, "send command without registered callback"); + throw new IllegalStateException("callback not registered"); + } + + service.getBluetoothHciVendorSpecificNativeInterface() + .sendCommand(ocf, parameters, cookie.get()); + } + + @Override + public int getOffloadedTransportDiscoveryDataScanSupported(AttributionSource source) { + AdapterService service = getService(); + if (service == null + || !callerIsSystemOrActiveOrManagedUser( + service, TAG, "getOffloadedTransportDiscoveryDataScanSupported") + || !Utils.checkScanPermissionForDataDelivery( + service, source, "getOffloadedTransportDiscoveryDataScanSupported")) { + return BluetoothStatusCodes.ERROR_MISSING_BLUETOOTH_SCAN_PERMISSION; + } + service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null); + + return service.getOffloadedTransportDiscoveryDataScanSupported(); + } + + @Override + public boolean isMediaProfileConnected(AttributionSource source) { + AdapterService service = getService(); + if (service == null + || !Utils.checkConnectPermissionForDataDelivery( + service, source, "AdapterService.isMediaProfileConnected")) { + return false; + } + service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null); + + return service.isMediaProfileConnected(); + } + + @Override + public IBinder getBluetoothGatt() { + AdapterService service = getService(); + return service == null ? null : service.getBluetoothGatt(); + } + + @Override + public IBinder getBluetoothScan() { + AdapterService service = getService(); + return service == null ? null : service.getBluetoothScan(); + } + + @Override + public void unregAllGattClient(AttributionSource source) { + AdapterService service = getService(); + if (service == null) { + return; + } + service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null); + service.unregAllGattClient(source); + } + + @Override + public IBinder getProfile(int profileId) { + AdapterService service = getService(); + if (service == null) { + return null; + } + + return service.getProfile(profileId); + } + + @Override + public int setActiveAudioDevicePolicy( + BluetoothDevice device, int activeAudioDevicePolicy, AttributionSource source) { + AdapterService service = getService(); + if (service == null) { + return BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ENABLED; + } + if (!callerIsSystemOrActiveOrManagedUser(service, TAG, "setActiveAudioDevicePolicy")) { + return BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ALLOWED; + } + if (!BluetoothAdapter.checkBluetoothAddress(device.getAddress())) { + throw new IllegalArgumentException("device cannot have an invalid address"); + } + if (!Utils.checkConnectPermissionForDataDelivery(service, source, TAG)) { + return BluetoothStatusCodes.ERROR_MISSING_BLUETOOTH_CONNECT_PERMISSION; + } + + service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null); + return service.getDatabaseManager() + .setActiveAudioDevicePolicy(device, activeAudioDevicePolicy); + } + + @Override + public int getActiveAudioDevicePolicy(BluetoothDevice device, AttributionSource source) { + AdapterService service = getService(); + if (service == null) { + return BluetoothDevice.ACTIVE_AUDIO_DEVICE_POLICY_DEFAULT; + } + if (!callerIsSystemOrActiveOrManagedUser(service, TAG, "getActiveAudioDevicePolicy")) { + throw new IllegalStateException( + "Caller is not the system or part of the active/managed user"); + } + if (!BluetoothAdapter.checkBluetoothAddress(device.getAddress())) { + throw new IllegalArgumentException("device cannot have an invalid address"); + } + if (!Utils.checkConnectPermissionForDataDelivery(service, source, TAG)) { + return BluetoothDevice.ACTIVE_AUDIO_DEVICE_POLICY_DEFAULT; + } + + service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null); + return service.getDatabaseManager().getActiveAudioDevicePolicy(device); + } + + @Override + public int setMicrophonePreferredForCalls( + BluetoothDevice device, boolean enabled, AttributionSource source) { + requireNonNull(device); + AdapterService service = getService(); + if (service == null) { + return BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ENABLED; + } + if (!callerIsSystemOrActiveOrManagedUser(service, TAG, "setMicrophonePreferredForCalls")) { + return BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ALLOWED; + } + if (!BluetoothAdapter.checkBluetoothAddress(device.getAddress())) { + throw new IllegalArgumentException("device cannot have an invalid address"); + } + if (!Utils.checkConnectPermissionForDataDelivery( + service, source, "AdapterService setMicrophonePreferredForCalls")) { + return BluetoothStatusCodes.ERROR_MISSING_BLUETOOTH_CONNECT_PERMISSION; + } + + service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null); + return service.getDatabaseManager().setMicrophonePreferredForCalls(device, enabled); + } + + @Override + public boolean isMicrophonePreferredForCalls(BluetoothDevice device, AttributionSource source) { + requireNonNull(device); + AdapterService service = getService(); + if (service == null) { + return true; + } + if (!callerIsSystemOrActiveOrManagedUser(service, TAG, "isMicrophonePreferredForCalls")) { + throw new IllegalStateException( + "Caller is not the system or part of the active/managed user"); + } + if (!BluetoothAdapter.checkBluetoothAddress(device.getAddress())) { + throw new IllegalArgumentException("device cannot have an invalid address"); + } + if (!Utils.checkConnectPermissionForDataDelivery( + service, source, "AdapterService isMicrophonePreferredForCalls")) { + return true; + } + + service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null); + return service.getDatabaseManager().isMicrophonePreferredForCalls(device); + } + + @Override + public boolean isLeCocSocketOffloadSupported(AttributionSource source) { + AdapterService service = getService(); + if (service == null) { + return false; + } + service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null); + return service.isLeCocSocketOffloadSupported(); + } + + @Override + public boolean isRfcommSocketOffloadSupported(AttributionSource source) { + AdapterService service = getService(); + if (service == null) { + return false; + } + service.enforceCallingOrSelfPermission(BLUETOOTH_PRIVILEGED, null); + return service.isRfcommSocketOffloadSupported(); + } + + @Override + public IBinder getBluetoothAdvertise() { + AdapterService service = getService(); + return service == null ? null : service.getBluetoothAdvertise(); + } + + @Override + public IBinder getDistanceMeasurement() { + AdapterService service = getService(); + return service == null ? null : service.getDistanceMeasurement(); + } + + @Override + public int getKeyMissingCount(BluetoothDevice device, AttributionSource source) { + AdapterService service = getService(); + if (service == null) { + return -1; + } + if (!callerIsSystemOrActiveOrManagedUser(service, TAG, "getKeyMissingCount")) { + throw new IllegalStateException( + "Caller is not the system or part of the active/managed user"); + } + if (!BluetoothAdapter.checkBluetoothAddress(device.getAddress())) { + throw new IllegalArgumentException("device cannot have an invalid address"); + } + if (!Utils.checkConnectPermissionForDataDelivery( + service, source, "AdapterService getKeyMissingCount")) { + return -1; + } + + return service.getDatabaseManager().getKeyMissingCount(device); + } +} diff --git a/android/app/src/com/android/bluetooth/btservice/AdapterSuspend.java b/android/app/src/com/android/bluetooth/btservice/AdapterSuspend.java index d49865e1ce..e7e9e870b8 100644 --- a/android/app/src/com/android/bluetooth/btservice/AdapterSuspend.java +++ b/android/app/src/com/android/bluetooth/btservice/AdapterSuspend.java @@ -1,5 +1,5 @@ /* - * Copyright 2024 The Android Open Source Project + * Copyright (C) 2024 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. diff --git a/android/app/src/com/android/bluetooth/btservice/BluetoothAdapterProxy.java b/android/app/src/com/android/bluetooth/btservice/BluetoothAdapterProxy.java index b7a67a7e66..20d3f5577f 100644 --- a/android/app/src/com/android/bluetooth/btservice/BluetoothAdapterProxy.java +++ b/android/app/src/com/android/bluetooth/btservice/BluetoothAdapterProxy.java @@ -1,5 +1,5 @@ /* - * Copyright 2022 The Android Open Source Project + * Copyright (C) 2022 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. diff --git a/android/app/src/com/android/bluetooth/btservice/BluetoothHciVendorSpecificDispatcher.java b/android/app/src/com/android/bluetooth/btservice/BluetoothHciVendorSpecificDispatcher.java index 626e4cf61f..a767c6a3c9 100644 --- a/android/app/src/com/android/bluetooth/btservice/BluetoothHciVendorSpecificDispatcher.java +++ b/android/app/src/com/android/bluetooth/btservice/BluetoothHciVendorSpecificDispatcher.java @@ -1,5 +1,5 @@ /* - * Copyright 2024 The Android Open Source Project + * Copyright (C) 2024 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. @@ -16,13 +16,14 @@ package com.android.bluetooth.btservice; +import static android.bluetooth.BluetoothUtils.RemoteExceptionIgnoringConsumer; + import android.bluetooth.IBluetoothHciVendorSpecificCallback; import android.os.IBinder; import android.os.RemoteException; import android.util.ArrayMap; import android.util.Log; -import com.android.bluetooth.Utils; import com.android.internal.annotations.GuardedBy; import java.nio.ByteBuffer; @@ -99,7 +100,7 @@ class BluetoothHciVendorSpecificDispatcher { void dispatchCommandStatusOrComplete( byte[] cookie, - Utils.RemoteExceptionIgnoringConsumer<IBluetoothHciVendorSpecificCallback> action) { + RemoteExceptionIgnoringConsumer<IBluetoothHciVendorSpecificCallback> action) { ByteBuffer cookieBb = ByteBuffer.wrap(cookie); UUID uuid = new UUID(cookieBb.getLong(), cookieBb.getLong()); synchronized (mRegistrations) { @@ -119,7 +120,7 @@ class BluetoothHciVendorSpecificDispatcher { void broadcastEvent( int eventCode, - Utils.RemoteExceptionIgnoringConsumer<IBluetoothHciVendorSpecificCallback> action) { + RemoteExceptionIgnoringConsumer<IBluetoothHciVendorSpecificCallback> action) { synchronized (mRegistrations) { mRegistrations.values().stream() .filter((r) -> r.mEventCodes.contains(eventCode)) diff --git a/android/app/src/com/android/bluetooth/btservice/BluetoothHciVendorSpecificNativeInterface.java b/android/app/src/com/android/bluetooth/btservice/BluetoothHciVendorSpecificNativeInterface.java index 010b1e6ce5..58c55978a7 100644 --- a/android/app/src/com/android/bluetooth/btservice/BluetoothHciVendorSpecificNativeInterface.java +++ b/android/app/src/com/android/bluetooth/btservice/BluetoothHciVendorSpecificNativeInterface.java @@ -1,5 +1,5 @@ /* - * Copyright 2024 The Android Open Source Project + * Copyright (C) 2024 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. diff --git a/android/app/src/com/android/bluetooth/btservice/BluetoothQualityReportNativeInterface.java b/android/app/src/com/android/bluetooth/btservice/BluetoothQualityReportNativeInterface.java index 2f4c03c17c..88f6e13638 100644 --- a/android/app/src/com/android/bluetooth/btservice/BluetoothQualityReportNativeInterface.java +++ b/android/app/src/com/android/bluetooth/btservice/BluetoothQualityReportNativeInterface.java @@ -1,5 +1,5 @@ /* - * Copyright 2023 The Android Open Source Project + * Copyright (C) 2023 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/android/app/src/com/android/bluetooth/btservice/Config.java b/android/app/src/com/android/bluetooth/btservice/Config.java index 1cac6b8c8b..a0e9d3fab9 100644 --- a/android/app/src/com/android/bluetooth/btservice/Config.java +++ b/android/app/src/com/android/bluetooth/btservice/Config.java @@ -48,7 +48,6 @@ import com.android.bluetooth.pbapclient.PbapClientService; import com.android.bluetooth.sap.SapService; import com.android.bluetooth.tbs.TbsService; import com.android.bluetooth.vc.VolumeControlService; -import com.android.internal.annotations.VisibleForTesting; import java.util.Arrays; @@ -126,9 +125,11 @@ public class Config { LeAudioService.isBroadcastEnabled(), BluetoothProfile.LE_AUDIO_BROADCAST), }; - /** A test function to allow for dynamic enabled */ - @VisibleForTesting - public static void setProfileEnabled(int profileId, boolean enabled) { + /** + * A test function to allow for dynamic enabled TODO: b/402559309 Remove non test usages + * (LeAudio) + */ + static void setProfileEnabled(int profileId, boolean enabled) { for (ProfileConfig profile : PROFILE_SERVICES_AND_FLAGS) { if (profileId == profile.mProfileId) { profile.mSupported = enabled; diff --git a/android/app/src/com/android/bluetooth/btservice/DiscoveringPackage.java b/android/app/src/com/android/bluetooth/btservice/DiscoveringPackage.java index f13bf94a8d..1e96abce86 100644 --- a/android/app/src/com/android/bluetooth/btservice/DiscoveringPackage.java +++ b/android/app/src/com/android/bluetooth/btservice/DiscoveringPackage.java @@ -1,5 +1,5 @@ /* - * Copyright 2019 The Android Open Source Project + * Copyright (C) 2019 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. @@ -19,29 +19,5 @@ package com.android.bluetooth.btservice; import android.annotation.NonNull; import android.annotation.Nullable; -final class DiscoveringPackage { - private final @NonNull String mPackageName; - private final @Nullable String mPermission; - private final boolean mHasDisavowedLocation; - - DiscoveringPackage( - @NonNull String packageName, - @Nullable String permission, - boolean hasDisavowedLocation) { - mPackageName = packageName; - mPermission = permission; - mHasDisavowedLocation = hasDisavowedLocation; - } - - public @NonNull String getPackageName() { - return mPackageName; - } - - public @Nullable String getPermission() { - return mPermission; - } - - public boolean hasDisavowedLocation() { - return mHasDisavowedLocation; - } -} +record DiscoveringPackage( + @NonNull String packageName, @Nullable String permission, boolean hasDisavowedLocation) {} diff --git a/android/app/src/com/android/bluetooth/btservice/MetricsLogger.java b/android/app/src/com/android/bluetooth/btservice/MetricsLogger.java index 06758cea38..87794605dc 100644 --- a/android/app/src/com/android/bluetooth/btservice/MetricsLogger.java +++ b/android/app/src/com/android/bluetooth/btservice/MetricsLogger.java @@ -1,5 +1,5 @@ /* - * Copyright 2018 The Android Open Source Project + * Copyright (C) 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. @@ -15,6 +15,7 @@ */ package com.android.bluetooth.btservice; +import static android.app.ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND_SERVICE; import static android.bluetooth.BluetoothProfile.STATE_CONNECTING; import static com.android.bluetooth.BluetoothStatsLog.BLUETOOTH_CROSS_LAYER_EVENT_REPORTED__EVENT_TYPE__BOND; @@ -69,17 +70,13 @@ import android.util.proto.ProtoOutputStream; import androidx.annotation.RequiresApi; -import com.android.bluetooth.BluetoothMetricsProto.BluetoothLog; import com.android.bluetooth.BluetoothMetricsProto.BluetoothRemoteDeviceInformation; -import com.android.bluetooth.BluetoothMetricsProto.ProfileConnectionStats; -import com.android.bluetooth.BluetoothMetricsProto.ProfileId; import com.android.bluetooth.BluetoothStatsLog; import com.android.bluetooth.BtRestrictedStatsLog; import com.android.bluetooth.Utils; import com.android.bluetooth.bass_client.BassConstants; +import com.android.internal.annotations.VisibleForTesting; -import com.google.common.annotations.VisibleForTesting; -import com.google.common.base.Ascii; import com.google.common.hash.BloomFilter; import com.google.common.hash.Funnels; @@ -94,6 +91,7 @@ import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; import java.util.List; +import java.util.Locale; /** Class of Bluetooth Metrics */ public class MetricsLogger { @@ -111,8 +109,6 @@ public class MetricsLogger { private static final long BLUETOOTH_COUNTER_METRICS_ACTION_DURATION_MILLIS = 6L * 3600L * 1000L; private static final int MAX_WORDS_ALLOWED_IN_DEVICE_NAME = 7; - private static final HashMap<ProfileId, Integer> sProfileConnectionCounts = new HashMap<>(); - HashMap<Integer, Long> mCounters = new HashMap<>(); private static volatile MetricsLogger sInstance = null; private AdapterService mAdapterService = null; @@ -388,37 +384,6 @@ public class MetricsLogger { return true; } - /** - * Log profile connection event by incrementing an internal counter for that profile. This log - * persists over adapter enable/disable and only get cleared when metrics are dumped or when - * Bluetooth process is killed. - * - * @param profileId Bluetooth profile that is connected at this event - */ - public static void logProfileConnectionEvent(ProfileId profileId) { - synchronized (sProfileConnectionCounts) { - sProfileConnectionCounts.merge(profileId, 1, Integer::sum); - } - } - - /** - * Dump collected metrics into proto using a builder. Clean up internal data after the dump. - * - * @param metricsBuilder proto builder for {@link BluetoothLog} - */ - public static void dumpProto(BluetoothLog.Builder metricsBuilder) { - synchronized (sProfileConnectionCounts) { - sProfileConnectionCounts.forEach( - (key, value) -> - metricsBuilder.addProfileConnectionStats( - ProfileConnectionStats.newBuilder() - .setProfileId(key) - .setNumTimesConnected(value) - .build())); - sProfileConnectionCounts.clear(); - } - } - protected void scheduleDrains() { Log.i(TAG, "setCounterMetricsAlarm()"); if (mAlarmManager == null) { @@ -569,31 +534,16 @@ public class MetricsLogger { } String deviceTypeMetaData = new String(deviceTypeMetaDataBytes, StandardCharsets.UTF_8); - switch (deviceTypeMetaData) { - case "Watch": - return BluetoothProtoEnums.WATCH; - - case "Untethered Headset": - return BluetoothProtoEnums.UNTETHERED_HEADSET; - - case "Stylus": - return BluetoothProtoEnums.STYLUS; - - case "Speaker": - return BluetoothProtoEnums.SPEAKER; - - case "Headset": - return BluetoothProtoEnums.HEADSET; - - case "Carkit": - return BluetoothProtoEnums.CARKIT; - - case "Default": - return BluetoothProtoEnums.DEFAULT; - - default: - return BluetoothProtoEnums.NOT_AVAILABLE; - } + return switch (deviceTypeMetaData) { + case "Watch" -> BluetoothProtoEnums.WATCH; + case "Untethered Headset" -> BluetoothProtoEnums.UNTETHERED_HEADSET; + case "Stylus" -> BluetoothProtoEnums.STYLUS; + case "Speaker" -> BluetoothProtoEnums.SPEAKER; + case "Headset" -> BluetoothProtoEnums.HEADSET; + case "Carkit" -> BluetoothProtoEnums.CARKIT; + case "Default" -> BluetoothProtoEnums.DEFAULT; + default -> BluetoothProtoEnums.NOT_AVAILABLE; + }; } private static int getOui(BluetoothDevice device) { @@ -607,7 +557,11 @@ public class MetricsLogger { // remove more than one spaces in a row deviceName = deviceName.trim().replaceAll(" +", " "); // remove non alphanumeric characters and spaces, and transform to lower cases. - String[] words = Ascii.toLowerCase(deviceName.replaceAll("[^a-zA-Z0-9 ]", "")).split(" "); + String[] words = + deviceName + .replaceAll("[^a-zA-Z0-9 ]", "") + .toLowerCase(Locale.ROOT) + .split(" ", MAX_WORDS_ALLOWED_IN_DEVICE_NAME + 1); if (words.length > MAX_WORDS_ALLOWED_IN_DEVICE_NAME) { // Validity checking here to avoid excessively long sequences @@ -665,6 +619,18 @@ public class MetricsLogger { return matchedString; } + private static int convertAppImportance(int importance) { + if (importance < IMPORTANCE_FOREGROUND_SERVICE) { + return BluetoothStatsLog + .LE_APP_SCAN_STATE_CHANGED__APP_IMPORTANCE__IMPORTANCE_HIGHER_THAN_FGS; + } + if (importance > IMPORTANCE_FOREGROUND_SERVICE) { + return BluetoothStatsLog + .LE_APP_SCAN_STATE_CHANGED__APP_IMPORTANCE__IMPORTANCE_LOWER_THAN_FGS; + } + return BluetoothStatsLog.LE_APP_SCAN_STATE_CHANGED__APP_IMPORTANCE__IMPORTANCE_EQUAL_TO_FGS; + } + /** Logs the app scan stats with app attribution when the app scan state changed. */ public void logAppScanStateChanged( int[] uids, @@ -679,7 +645,9 @@ public class MetricsLogger { long scanDurationMillis, int numOngoingScan, boolean isScreenOn, - boolean isAppDead) { + boolean isAppDead, + int appImportance, + String attributionTag) { BluetoothStatsLog.write( BluetoothStatsLog.LE_APP_SCAN_STATE_CHANGED, uids, @@ -694,7 +662,9 @@ public class MetricsLogger { scanDurationMillis, numOngoingScan, isScreenOn, - isAppDead); + isAppDead, + convertAppImportance(appImportance), + attributionTag); } /** Logs the radio scan stats with app attribution when the radio scan stopped. */ @@ -706,7 +676,9 @@ public class MetricsLogger { long scanIntervalMillis, long scanWindowMillis, boolean isScreenOn, - long scanDurationMillis) { + long scanDurationMillis, + int appImportance, + String attributionTag) { BluetoothStatsLog.write( BluetoothStatsLog.LE_RADIO_SCAN_STOPPED, uids, @@ -716,7 +688,9 @@ public class MetricsLogger { scanIntervalMillis, scanWindowMillis, isScreenOn, - scanDurationMillis); + scanDurationMillis, + convertAppImportance(appImportance), + attributionTag); } /** Logs the advertise stats with app attribution when the advertise state changed. */ @@ -731,7 +705,9 @@ public class MetricsLogger { boolean hasScanResponse, boolean isExtendedAdv, int instanceCount, - long advDurationMs) { + long advDurationMs, + int appImportance, + String attributionTag) { BluetoothStatsLog.write( BluetoothStatsLog.LE_ADV_STATE_CHANGED, uids, @@ -744,7 +720,9 @@ public class MetricsLogger { hasScanResponse, isExtendedAdv, instanceCount, - advDurationMs); + advDurationMs, + convertAppImportance(appImportance), + attributionTag); } protected String getAllowlistedDeviceNameHash( diff --git a/android/app/src/com/android/bluetooth/btservice/PhonePolicy.java b/android/app/src/com/android/bluetooth/btservice/PhonePolicy.java index 048602338f..0999690a73 100644 --- a/android/app/src/com/android/bluetooth/btservice/PhonePolicy.java +++ b/android/app/src/com/android/bluetooth/btservice/PhonePolicy.java @@ -64,6 +64,7 @@ import java.time.Duration; import java.util.ArrayList; import java.util.HashSet; import java.util.List; +import java.util.Set; // Describes the phone policy // @@ -96,13 +97,25 @@ public class PhonePolicy implements AdapterService.BluetoothStateCallback { private final AdapterService mAdapterService; private final ServiceFactory mFactory; private final Handler mHandler; - private final HashSet<BluetoothDevice> mHeadsetRetrySet = new HashSet<>(); - private final HashSet<BluetoothDevice> mA2dpRetrySet = new HashSet<>(); - private final HashSet<BluetoothDevice> mConnectOtherProfilesDeviceSet = new HashSet<>(); + private final Set<BluetoothDevice> mHeadsetRetrySet = new HashSet<>(); + private final Set<BluetoothDevice> mA2dpRetrySet = new HashSet<>(); + private final Set<BluetoothDevice> mConnectOtherProfilesDeviceSet = new HashSet<>(); @VisibleForTesting boolean mAutoConnectProfilesSupported; @VisibleForTesting boolean mLeAudioEnabledByDefault; + PhonePolicy(AdapterService service, Looper looper, ServiceFactory factory) { + mAdapterService = service; + mDatabaseManager = requireNonNull(service.getDatabase()); + mFactory = factory; + mHandler = new Handler(looper); + mAutoConnectProfilesSupported = + SystemProperties.getBoolean(AUTO_CONNECT_PROFILES_PROPERTY, false); + mLeAudioEnabledByDefault = + SystemProperties.getBoolean(LE_AUDIO_CONNECTION_BY_DEFAULT_PROPERTY, true); + mAdapterService.registerBluetoothStateCallback(mHandler::post, this); + } + @Override public void onBluetoothStateChange(int prevState, int newState) { // Only act if the adapter has actually changed state from non-ON to ON. @@ -144,18 +157,6 @@ public class PhonePolicy implements AdapterService.BluetoothStateCallback { resetStates(); } - PhonePolicy(AdapterService service, Looper looper, ServiceFactory factory) { - mAdapterService = service; - mDatabaseManager = requireNonNull(service.getDatabase()); - mFactory = factory; - mHandler = new Handler(looper); - mAutoConnectProfilesSupported = - SystemProperties.getBoolean(AUTO_CONNECT_PROFILES_PROPERTY, false); - mLeAudioEnabledByDefault = - SystemProperties.getBoolean(LE_AUDIO_CONNECTION_BY_DEFAULT_PROPERTY, true); - mAdapterService.registerBluetoothStateCallback(mHandler::post, this); - } - boolean isLeAudioOnlyGroup(BluetoothDevice device) { String log = "isLeAudioOnlyGroup(" + device + "): "; if (!Flags.leaudioAllowLeaudioOnlyDevices()) { diff --git a/android/app/src/com/android/bluetooth/btservice/ProfileService.java b/android/app/src/com/android/bluetooth/btservice/ProfileService.java index 8a0fc82555..e8ea20de03 100644 --- a/android/app/src/com/android/bluetooth/btservice/ProfileService.java +++ b/android/app/src/com/android/bluetooth/btservice/ProfileService.java @@ -24,7 +24,6 @@ import android.content.pm.PackageManager; import android.os.IBinder; import android.util.Log; -import com.android.bluetooth.BluetoothMetricsProto; import com.android.bluetooth.Utils; /** Base class for a background service that runs a Bluetooth profile */ @@ -147,17 +146,6 @@ public abstract class ProfileService extends ContextWrapper { } /** - * Support dumping scan events from GattService - * - * @param builder metrics proto builder - */ - // Suppressed since this is called from framework - @SuppressLint("AndroidFrameworkRequiresPermission") - public void dumpProto(BluetoothMetricsProto.BluetoothLog.Builder builder) { - // Do nothing - } - - /** * Append an indented String for adding dumpsys support to subclasses. * * @param sb StringBuilder from the profile. diff --git a/android/app/src/com/android/bluetooth/btservice/RemoteDevices.java b/android/app/src/com/android/bluetooth/btservice/RemoteDevices.java index 2f97c879c7..456545a42a 100644 --- a/android/app/src/com/android/bluetooth/btservice/RemoteDevices.java +++ b/android/app/src/com/android/bluetooth/btservice/RemoteDevices.java @@ -21,6 +21,7 @@ import static android.Manifest.permission.BLUETOOTH_PRIVILEGED; import static android.Manifest.permission.BLUETOOTH_SCAN; import static android.bluetooth.BluetoothProfile.STATE_CONNECTED; import static android.bluetooth.BluetoothProfile.STATE_DISCONNECTED; +import static android.bluetooth.BluetoothUtils.RemoteExceptionIgnoringConsumer; import static com.android.modules.utils.build.SdkLevel.isAtLeastV; @@ -909,15 +910,6 @@ public class RemoteDevices { properties.setBondingInitiatedLocally(true); } - /** - * Update battery level in device properties - * - * @param device The remote device to be updated - * @param batteryLevel Battery level Indicator between 0-100, {@link - * BluetoothDevice#BATTERY_LEVEL_UNKNOWN} is error - * @param isBas true if the battery level is from the battery service - */ - @VisibleForTesting void updateBatteryLevel(BluetoothDevice device, int batteryLevel, boolean isBas) { if (device == null || batteryLevel < 0 || batteryLevel > 100) { warnLog( @@ -951,12 +943,6 @@ public class RemoteDevices { Log.d(TAG, "Updated device " + device + " battery level to " + newBatteryLevel + "%"); } - /** - * Reset battery level property to {@link BluetoothDevice#BATTERY_LEVEL_UNKNOWN} for a device - * - * @param device device whose battery level property needs to be reset - */ - @VisibleForTesting void resetBatteryLevel(BluetoothDevice device, boolean isBas) { if (device == null) { warnLog("Device is null"); @@ -1263,12 +1249,12 @@ public class RemoteDevices { } } - intent.setPackage(pkg.getPackageName()); + intent.setPackage(pkg.packageName()); - if (pkg.getPermission() != null) { + if (pkg.permission() != null) { mAdapterService.sendBroadcastMultiplePermissions( intent, - new String[] {BLUETOOTH_SCAN, pkg.getPermission()}, + new String[] {BLUETOOTH_SCAN, pkg.permission()}, Utils.getTempBroadcastOptions()); } else { mAdapterService.sendBroadcastMultiplePermissions( @@ -1472,15 +1458,29 @@ public class RemoteDevices { mAdapterService.sendBroadcast( intent, BLUETOOTH_CONNECT, Utils.getTempBroadcastOptions().toBundle()); - Utils.RemoteExceptionIgnoringConsumer<IBluetoothConnectionCallback> - connectionChangeConsumer; + RemoteExceptionIgnoringConsumer<IBluetoothConnectionCallback> connectionChangeConsumer; if (connectionState == BluetoothAdapter.STATE_CONNECTED) { connectionChangeConsumer = cb -> cb.onDeviceConnected(device); } else { + final int disconnectReason; + if (hciReason == 0x16 /* HCI_ERR_CONN_CAUSE_LOCAL_HOST */ + && mAdapterService.getDatabase().getKeyMissingCount(device) > 0) { + // Native stack disconnects the link on detecting the bond loss. Native GATT would + // return HCI_ERR_CONN_CAUSE_LOCAL_HOST in such case, but the apps should see + // HCI_ERR_AUTH_FAILURE. + Log.d( + TAG, + "aclStateChangeCallback() - disconnected due to bond loss for device=" + + device); + disconnectReason = 0x05; /* HCI_ERR_AUTH_FAILURE */ + } else { + disconnectReason = hciReason; + } connectionChangeConsumer = cb -> cb.onDeviceDisconnected( - device, AdapterService.hciToAndroidDisconnectReason(hciReason)); + device, + AdapterService.hciToAndroidDisconnectReason(disconnectReason)); } mAdapterService.aclStateChangeBroadcastCallback(connectionChangeConsumer); diff --git a/android/app/src/com/android/bluetooth/btservice/SilenceDeviceManager.java b/android/app/src/com/android/bluetooth/btservice/SilenceDeviceManager.java index 4d6c706e06..90d9a4bee6 100644 --- a/android/app/src/com/android/bluetooth/btservice/SilenceDeviceManager.java +++ b/android/app/src/com/android/bluetooth/btservice/SilenceDeviceManager.java @@ -1,5 +1,5 @@ /* - * Copyright 2019 The Android Open Source Project + * Copyright (C) 2019 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. @@ -31,10 +31,7 @@ import android.util.Log; import com.android.bluetooth.Utils; import com.android.bluetooth.a2dp.A2dpService; import com.android.bluetooth.hfp.HeadsetService; -import com.android.internal.annotations.VisibleForTesting; -import java.io.FileDescriptor; -import java.io.PrintWriter; import java.util.ArrayList; import java.util.HashMap; import java.util.List; @@ -56,8 +53,7 @@ public class SilenceDeviceManager { private final AdapterService mAdapterService; private final ServiceFactory mFactory; - private Handler mHandler = null; - private Looper mLooper = null; + private final Handler mHandler; private final Map<BluetoothDevice, Boolean> mSilenceDevices = new HashMap<>(); private final List<BluetoothDevice> mA2dpConnectedDevices = new ArrayList<>(); @@ -115,6 +111,7 @@ public class SilenceDeviceManager { } class SilenceDeviceManagerHandler extends Handler { + SilenceDeviceManagerHandler(Looper looper) { super(looper); } @@ -199,12 +196,7 @@ public class SilenceDeviceManager { SilenceDeviceManager(AdapterService service, ServiceFactory factory, Looper looper) { mAdapterService = service; mFactory = factory; - mLooper = looper; - } - - void start() { - Log.v(TAG, "start()"); - mHandler = new SilenceDeviceManagerHandler(mLooper); + mHandler = new SilenceDeviceManagerHandler(looper); } void cleanup() { @@ -212,20 +204,14 @@ public class SilenceDeviceManager { mSilenceDevices.clear(); } - @VisibleForTesting boolean setSilenceMode(BluetoothDevice device, boolean silence) { - if (mHandler == null) { - Log.e(TAG, "setSilenceMode() mHandler is null!"); - return false; - } Log.d(TAG, "setSilenceMode: " + device + ", " + silence); - Message message = - mHandler.obtainMessage( + mHandler.obtainMessage( MSG_SILENCE_DEVICE_STATE_CHANGED, silence ? ENABLE_SILENCE : DISABLE_SILENCE, 0, - device); - mHandler.sendMessage(message); + device) + .sendToTarget(); return true; } @@ -254,10 +240,10 @@ public class SilenceDeviceManager { headsetService.setSilenceMode(device, state); } Log.i(TAG, "Silence mode change " + device + ": " + oldState + " -> " + state); - broadcastSilenceStateChange(device, state); + broadcastSilenceStateChange(device); } - void broadcastSilenceStateChange(BluetoothDevice device, boolean state) { + private void broadcastSilenceStateChange(BluetoothDevice device) { Intent intent = new Intent(BluetoothDevice.ACTION_SILENCE_MODE_CHANGED); intent.putExtra(BluetoothDevice.EXTRA_DEVICE, device); mAdapterService.sendBroadcastAsUser( @@ -267,7 +253,6 @@ public class SilenceDeviceManager { Utils.getTempBroadcastOptions().toBundle()); } - @VisibleForTesting boolean getSilenceMode(BluetoothDevice device) { boolean state = false; if (mSilenceDevices.containsKey(device)) { @@ -276,7 +261,7 @@ public class SilenceDeviceManager { return state; } - void addConnectedDevice(BluetoothDevice device, int profile) { + private void addConnectedDevice(BluetoothDevice device, int profile) { Log.d( TAG, "addConnectedDevice: " @@ -297,7 +282,7 @@ public class SilenceDeviceManager { } } - void removeConnectedDevice(BluetoothDevice device, int profile) { + private void removeConnectedDevice(BluetoothDevice device, int profile) { Log.d( TAG, "removeConnectedDevice: " @@ -318,15 +303,19 @@ public class SilenceDeviceManager { } } - boolean isBluetoothAudioConnected(BluetoothDevice device) { + private boolean isBluetoothAudioConnected(BluetoothDevice device) { return (mA2dpConnectedDevices.contains(device) || mHfpConnectedDevices.contains(device)); } - protected void dump(FileDescriptor fd, PrintWriter writer, String[] args) { - writer.println("\nSilenceDeviceManager:"); - writer.println(" Address | Is silenced?"); + protected void dump(StringBuilder sb) { + sb.append("SilenceDeviceManager:\n"); + sb.append(" Address | Is silenced?\n"); for (BluetoothDevice device : mSilenceDevices.keySet()) { - writer.println(" " + device + " | " + getSilenceMode(device)); + sb.append(" ") + .append(device) + .append(" | ") + .append(getSilenceMode(device)) + .append("\n"); } } } diff --git a/android/app/src/com/android/bluetooth/btservice/bluetoothKeystore/BluetoothKeystoreNativeInterface.java b/android/app/src/com/android/bluetooth/btservice/bluetoothKeystore/BluetoothKeystoreNativeInterface.java index 073aa34302..09761f58d9 100644 --- a/android/app/src/com/android/bluetooth/btservice/bluetoothKeystore/BluetoothKeystoreNativeInterface.java +++ b/android/app/src/com/android/bluetooth/btservice/bluetoothKeystore/BluetoothKeystoreNativeInterface.java @@ -1,5 +1,5 @@ /* - * Copyright 2020 The Android Open Source Project + * Copyright (C) 2020 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. diff --git a/android/app/src/com/android/bluetooth/btservice/bluetoothKeystore/BluetoothKeystoreService.java b/android/app/src/com/android/bluetooth/btservice/bluetoothKeystore/BluetoothKeystoreService.java index 020692ae6f..26922d0aff 100644 --- a/android/app/src/com/android/bluetooth/btservice/bluetoothKeystore/BluetoothKeystoreService.java +++ b/android/app/src/com/android/bluetooth/btservice/bluetoothKeystore/BluetoothKeystoreService.java @@ -1,5 +1,5 @@ /* - * Copyright 2020 The Android Open Source Project + * Copyright (C) 2020 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. diff --git a/android/app/src/com/android/bluetooth/btservice/storage/AudioPolicyEntity.java b/android/app/src/com/android/bluetooth/btservice/storage/AudioPolicyEntity.java index 76ba89e0a4..2f70150270 100644 --- a/android/app/src/com/android/bluetooth/btservice/storage/AudioPolicyEntity.java +++ b/android/app/src/com/android/bluetooth/btservice/storage/AudioPolicyEntity.java @@ -1,5 +1,5 @@ /* - * Copyright 2022 The Android Open Source Project + * Copyright (C) 2022 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. diff --git a/android/app/src/com/android/bluetooth/btservice/storage/BluetoothDatabaseMigration.java b/android/app/src/com/android/bluetooth/btservice/storage/BluetoothDatabaseMigration.java index c083c04e01..bcaad1ef16 100644 --- a/android/app/src/com/android/bluetooth/btservice/storage/BluetoothDatabaseMigration.java +++ b/android/app/src/com/android/bluetooth/btservice/storage/BluetoothDatabaseMigration.java @@ -1,5 +1,5 @@ /* - * Copyright 2022 The Android Open Source Project + * Copyright (C) 2022 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. diff --git a/android/app/src/com/android/bluetooth/btservice/storage/CustomizedMetadataEntity.java b/android/app/src/com/android/bluetooth/btservice/storage/CustomizedMetadataEntity.java index 4b224c24d0..d7cb75cbbf 100644 --- a/android/app/src/com/android/bluetooth/btservice/storage/CustomizedMetadataEntity.java +++ b/android/app/src/com/android/bluetooth/btservice/storage/CustomizedMetadataEntity.java @@ -1,5 +1,5 @@ /* - * Copyright 2019 The Android Open Source Project + * Copyright (C) 2019 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. diff --git a/android/app/src/com/android/bluetooth/btservice/storage/DatabaseManager.java b/android/app/src/com/android/bluetooth/btservice/storage/DatabaseManager.java index ee8b2d3fc1..b5724c4fa4 100644 --- a/android/app/src/com/android/bluetooth/btservice/storage/DatabaseManager.java +++ b/android/app/src/com/android/bluetooth/btservice/storage/DatabaseManager.java @@ -1,5 +1,5 @@ /* - * Copyright 2019 The Android Open Source Project + * Copyright (C) 2019 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. @@ -46,6 +46,7 @@ import android.os.Message; import android.provider.Settings; import android.util.Log; +import com.android.bluetooth.BluetoothEventLogger; import com.android.bluetooth.BluetoothStatsLog; import com.android.bluetooth.Utils; import com.android.bluetooth.btservice.AdapterService; @@ -53,9 +54,6 @@ import com.android.bluetooth.flags.Flags; import com.android.internal.annotations.GuardedBy; import com.android.internal.annotations.VisibleForTesting; -import com.google.common.collect.EvictingQueue; - -import java.io.PrintWriter; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; @@ -99,8 +97,6 @@ public class DatabaseManager { private static final String LEGACY_HEARING_AID_PRIORITY_PREFIX = "bluetooth_hearing_aid_priority_"; - private static final int METADATA_CHANGED_LOG_MAX_SIZE = 20; - private final BluetoothAdapter mAdapter; private final AdapterService mAdapterService; private HandlerThread mHandlerThread = null; @@ -111,13 +107,13 @@ public class DatabaseManager { @VisibleForTesting final Map<String, Metadata> mMetadataCache = new HashMap<>(); private final Semaphore mSemaphore = new Semaphore(1); - private final EvictingQueue<String> mMetadataChangedLog; + private final BluetoothEventLogger mMetadataChangedLog = + new BluetoothEventLogger(20, "Metadata Changes"); /** Constructor of the DatabaseManager */ public DatabaseManager(AdapterService service) { mAdapter = BluetoothAdapter.getDefaultAdapter(); mAdapterService = requireNonNull(service); - mMetadataChangedLog = EvictingQueue.create(METADATA_CHANGED_LOG_MAX_SIZE); } private class DatabaseHandler extends Handler { @@ -1187,8 +1183,7 @@ public class DatabaseManager { /** Clear all persistence data in database */ public void factoryReset() { Log.w(TAG, "factoryReset"); - Message message = mHandler.obtainMessage(MSG_CLEAR_DATABASE); - mHandler.sendMessage(message); + mHandler.sendEmptyMessage(MSG_CLEAR_DATABASE); } /** Close and de-init the DatabaseManager */ @@ -1463,8 +1458,7 @@ public class DatabaseManager { private void loadDatabase() { Log.d(TAG, "Load Database"); - Message message = mHandler.obtainMessage(MSG_LOAD_DATABASE); - mHandler.sendMessage(message); + mHandler.sendEmptyMessage(MSG_LOAD_DATABASE); try { // Lock the thread until handler thread finish loading database. mSemaphore.tryAcquire(LOAD_DATABASE_TIMEOUT_MS, TimeUnit.MILLISECONDS); @@ -1479,9 +1473,7 @@ public class DatabaseManager { return; } Log.d(TAG, "updateDatabase " + data.getAnonymizedAddress()); - Message message = mHandler.obtainMessage(MSG_UPDATE_DATABASE); - message.obj = data; - mHandler.sendMessage(message); + mHandler.obtainMessage(MSG_UPDATE_DATABASE, data).sendToTarget(); } @VisibleForTesting @@ -1492,9 +1484,7 @@ public class DatabaseManager { return; } logMetadataChange(data, "Metadata deleted"); - Message message = mHandler.obtainMessage(MSG_DELETE_DATABASE); - message.obj = data.getAddress(); - mHandler.sendMessage(message); + mHandler.obtainMessage(MSG_DELETE_DATABASE, data.getAddress()).sendToTarget(); } private void logManufacturerInfo(BluetoothDevice device, int key, byte[] bytesValue) { @@ -1539,30 +1529,20 @@ public class DatabaseManager { } private void logMetadataChange(Metadata data, String log) { - String time = Utils.getLocalTimeString(); String uidPid = Utils.getUidPidString(); - mMetadataChangedLog.add( - time + " (" + uidPid + ") " + data.getAnonymizedAddress() + " " + log); + mMetadataChangedLog.add(uidPid + ": " + data.getAnonymizedAddress() + " " + log); } - /** - * Dump database info to a PrintWriter - * - * @param writer the PrintWriter to write log - */ - public void dump(PrintWriter writer) { - writer.println("\nBluetoothDatabase:"); - writer.println(" Metadata Changes:"); - for (String log : mMetadataChangedLog) { - writer.println(" " + log); - } - writer.println("\nMetadata:"); + /** Dump database info */ + public void dump(StringBuilder sb) { + mMetadataChangedLog.dump(sb); + sb.append("Metadata:\n"); for (Map.Entry<String, Metadata> entry : mMetadataCache.entrySet()) { if (entry.getKey().equals(LOCAL_STORAGE)) { // No need to dump local storage continue; } - writer.println(" " + entry.getValue()); + sb.append(" ").append(entry.getValue()).append("\n"); } } diff --git a/android/app/src/com/android/bluetooth/btservice/storage/Metadata.java b/android/app/src/com/android/bluetooth/btservice/storage/Metadata.java index 28b286280f..d60ccadc21 100644 --- a/android/app/src/com/android/bluetooth/btservice/storage/Metadata.java +++ b/android/app/src/com/android/bluetooth/btservice/storage/Metadata.java @@ -1,5 +1,5 @@ /* - * Copyright 2019 The Android Open Source Project + * Copyright (C) 2019 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. diff --git a/android/app/src/com/android/bluetooth/btservice/storage/MetadataDao.java b/android/app/src/com/android/bluetooth/btservice/storage/MetadataDao.java index 7db45bf9e3..be485b5c1e 100644 --- a/android/app/src/com/android/bluetooth/btservice/storage/MetadataDao.java +++ b/android/app/src/com/android/bluetooth/btservice/storage/MetadataDao.java @@ -1,5 +1,5 @@ /* - * Copyright 2019 The Android Open Source Project + * Copyright (C) 2019 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. diff --git a/android/app/src/com/android/bluetooth/btservice/storage/MetadataDatabase.java b/android/app/src/com/android/bluetooth/btservice/storage/MetadataDatabase.java index 00c52734a8..d535ab5ff8 100644 --- a/android/app/src/com/android/bluetooth/btservice/storage/MetadataDatabase.java +++ b/android/app/src/com/android/bluetooth/btservice/storage/MetadataDatabase.java @@ -1,5 +1,5 @@ /* - * Copyright 2019 The Android Open Source Project + * Copyright (C) 2019 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. diff --git a/android/app/src/com/android/bluetooth/btservice/storage/ProfilePrioritiesEntity.java b/android/app/src/com/android/bluetooth/btservice/storage/ProfilePrioritiesEntity.java index 5fb23b9267..758a17e1c2 100644 --- a/android/app/src/com/android/bluetooth/btservice/storage/ProfilePrioritiesEntity.java +++ b/android/app/src/com/android/bluetooth/btservice/storage/ProfilePrioritiesEntity.java @@ -1,5 +1,5 @@ /* - * Copyright 2019 The Android Open Source Project + * Copyright (C) 2019 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. diff --git a/android/app/src/com/android/bluetooth/content_profiles/ContentProfileErrorReportUtils.java b/android/app/src/com/android/bluetooth/content_profiles/ContentProfileErrorReportUtils.java index 72be2ec6b3..0b6d2179d6 100644 --- a/android/app/src/com/android/bluetooth/content_profiles/ContentProfileErrorReportUtils.java +++ b/android/app/src/com/android/bluetooth/content_profiles/ContentProfileErrorReportUtils.java @@ -1,5 +1,5 @@ /* - * Copyright 2023 The Android Open Source Project + * Copyright (C) 2023 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/android/app/src/com/android/bluetooth/gatt/AdvertiseBinder.kt b/android/app/src/com/android/bluetooth/gatt/AdvertiseBinder.kt index 02f4f9ff98..9d08625db7 100644 --- a/android/app/src/com/android/bluetooth/gatt/AdvertiseBinder.kt +++ b/android/app/src/com/android/bluetooth/gatt/AdvertiseBinder.kt @@ -1,5 +1,5 @@ /* - * Copyright 2025 The Android Open Source Project + * Copyright (C) 2025 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/android/app/src/com/android/bluetooth/gatt/AdvertiseHelper.java b/android/app/src/com/android/bluetooth/gatt/AdvertiseHelper.java index f61f56cd16..5f3f763e44 100644 --- a/android/app/src/com/android/bluetooth/gatt/AdvertiseHelper.java +++ b/android/app/src/com/android/bluetooth/gatt/AdvertiseHelper.java @@ -44,22 +44,21 @@ class AdvertiseHelper { private static final int SERVICE_DATA_128_BIT_UUID = 0X21; private static final int MANUFACTURER_SPECIFIC_DATA = 0XFF; - public static byte[] advertiseDataToBytes(AdvertiseData data, String name) { + private AdvertiseHelper() {} + static byte[] advertiseDataToBytes(AdvertiseData data, String name) { if (data == null) { return new byte[0]; } - // Flags are added by lower layers of the stack, only if needed; - // no need to add them here. - + // Flags are added by lower layers of the stack, only if needed no need to add them here. ByteArrayOutputStream ret = new ByteArrayOutputStream(); if (data.getIncludeDeviceName()) { byte[] nameBytes = name.getBytes(StandardCharsets.UTF_8); int nameLength = nameBytes.length; - byte type; + final byte type; // TODO(jpawlowski) put a better limit on device name! if (nameLength > DEVICE_NAME_MAX) { @@ -76,7 +75,7 @@ class AdvertiseHelper { } for (int i = 0; i < data.getManufacturerSpecificData().size(); i++) { - int manufacturerId = data.getManufacturerSpecificData().keyAt(i); + final int manufacturerId = data.getManufacturerSpecificData().keyAt(i); byte[] manufacturerData = data.getManufacturerSpecificData().get(manufacturerId); int dataLen = 2 + (manufacturerData == null ? 0 : manufacturerData.length); @@ -106,7 +105,7 @@ class AdvertiseHelper { ByteArrayOutputStream serviceUuids128 = new ByteArrayOutputStream(); for (ParcelUuid parcelUuid : data.getServiceUuids()) { - byte[] uuid = BluetoothUuid.uuidToBytes(parcelUuid); + final byte[] uuid = BluetoothUuid.uuidToBytes(parcelUuid); if (uuid.length == BluetoothUuid.UUID_BYTES_16_BIT) { serviceUuids16.write(uuid, 0, uuid.length); @@ -141,31 +140,29 @@ class AdvertiseHelper { if (!data.getServiceData().isEmpty()) { for (ParcelUuid parcelUuid : data.getServiceData().keySet()) { - byte[] serviceData = data.getServiceData().get(parcelUuid); - - byte[] uuid = BluetoothUuid.uuidToBytes(parcelUuid); - int uuidLen = uuid.length; + final byte[] serviceData = data.getServiceData().get(parcelUuid); + final byte[] uuid = BluetoothUuid.uuidToBytes(parcelUuid); + final int uuidLen = uuid.length; + final int dataLen = uuidLen + (serviceData == null ? 0 : serviceData.length); - int dataLen = uuidLen + (serviceData == null ? 0 : serviceData.length); byte[] concatenated = new byte[dataLen]; - System.arraycopy(uuid, 0, concatenated, 0, uuidLen); if (serviceData != null) { System.arraycopy(serviceData, 0, concatenated, uuidLen, serviceData.length); } - if (uuid.length == BluetoothUuid.UUID_BYTES_16_BIT) { + if (uuidLen == BluetoothUuid.UUID_BYTES_16_BIT) { check_length(SERVICE_DATA_16_BIT_UUID, concatenated.length + 1); ret.write(concatenated.length + 1); ret.write(SERVICE_DATA_16_BIT_UUID); ret.write(concatenated, 0, concatenated.length); - } else if (uuid.length == BluetoothUuid.UUID_BYTES_32_BIT) { + } else if (uuidLen == BluetoothUuid.UUID_BYTES_32_BIT) { check_length(SERVICE_DATA_32_BIT_UUID, concatenated.length + 1); ret.write(concatenated.length + 1); ret.write(SERVICE_DATA_32_BIT_UUID); ret.write(concatenated, 0, concatenated.length); - } else /*if (uuid.length == BluetoothUuid.UUID_BYTES_128_BIT)*/ { + } else /*if (uuidLen == BluetoothUuid.UUID_BYTES_128_BIT)*/ { check_length(SERVICE_DATA_128_BIT_UUID, concatenated.length + 1); ret.write(concatenated.length + 1); ret.write(SERVICE_DATA_128_BIT_UUID); @@ -180,7 +177,7 @@ class AdvertiseHelper { ByteArrayOutputStream serviceUuids128 = new ByteArrayOutputStream(); for (ParcelUuid parcelUuid : data.getServiceSolicitationUuids()) { - byte[] uuid = BluetoothUuid.uuidToBytes(parcelUuid); + final byte[] uuid = BluetoothUuid.uuidToBytes(parcelUuid); if (uuid.length == BluetoothUuid.UUID_BYTES_16_BIT) { serviceUuids16.write(uuid, 0, uuid.length); diff --git a/android/app/src/com/android/bluetooth/gatt/AdvertiseManager.java b/android/app/src/com/android/bluetooth/gatt/AdvertiseManager.java index e6d0d6612a..53a90d58fc 100644 --- a/android/app/src/com/android/bluetooth/gatt/AdvertiseManager.java +++ b/android/app/src/com/android/bluetooth/gatt/AdvertiseManager.java @@ -16,12 +16,16 @@ 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; import android.bluetooth.le.AdvertisingSetParameters; import android.bluetooth.le.IAdvertisingSetCallback; import android.bluetooth.le.PeriodicAdvertisingParameters; import android.content.AttributionSource; +import android.content.pm.PackageManager; import android.os.Binder; import android.os.Handler; import android.os.IBinder; @@ -48,14 +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 Map<IBinder, AdvertiserInfo> mAdvertisers = new HashMap<>(); - + private final ActivityManager mActivityManager; private final Handler mHandler; + private volatile boolean mIsAvailable = true; @VisibleForTesting int mTempRegistrationId = -1; @@ -77,7 +82,7 @@ public class AdvertiseManager { mService = service; mNativeInterface = nativeInterface; mAdvertiserMap = advertiserMap; - + mActivityManager = mService.getSystemService(ActivityManager.class); mNativeInterface.init(this); mHandler = new Handler(advertiseLooper); mAdvertiseBinder = new AdvertiseBinder(service, this); @@ -104,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; @@ -146,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) { @@ -168,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. @@ -176,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); @@ -234,6 +223,26 @@ public class AdvertiseManager { } } + private void fetchAppForegroundState(int id) { + PackageManager packageManager = mService.getPackageManager(); + if (mActivityManager == null || packageManager == null) { + return; + } + int appUid = Binder.getCallingUid(); + String[] packages = packageManager.getPackagesForUid(appUid); + if (packages == null || packages.length == 0) { + return; + } + int importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_CACHED; + for (String packageName : packages) { + importance = Math.min(importance, mActivityManager.getPackageImportance(packageName)); + } + AppAdvertiseStats stats = mAdvertiserMap.getAppAdvertiseStatsById(id); + if (stats != null) { + stats.setAppImportance(importance); + } + } + void startAdvertisingSet( AdvertisingSetParameters parameters, AdvertiseData advertiseData, @@ -280,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)); @@ -294,6 +301,7 @@ public class AdvertiseManager { Log.d(TAG, "startAdvertisingSet() - reg_id=" + cbId + ", callback: " + binder); mAdvertiserMap.addAppAdvertiseStats(cbId, mService, attrSource); + fetchAppForegroundState(cbId); mAdvertiserMap.recordAdvertiseStart( cbId, parameters, @@ -392,6 +400,7 @@ public class AdvertiseManager { Log.w(TAG, "enableAdvertisingSet() - bad advertiserId " + advertiserId); return; } + fetchAppForegroundState(advertiserId); mNativeInterface.enableAdvertisingSet(advertiserId, enable, duration, maxExtAdvEvents); mAdvertiserMap.enableAdvertisingSet(advertiserId, enable, duration, maxExtAdvEvents); @@ -404,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) { @@ -427,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) { @@ -475,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/AdvertiserMap.java b/android/app/src/com/android/bluetooth/gatt/AdvertiserMap.java index e3aac31354..fc5adf3c32 100644 --- a/android/app/src/com/android/bluetooth/gatt/AdvertiserMap.java +++ b/android/app/src/com/android/bluetooth/gatt/AdvertiserMap.java @@ -25,10 +25,9 @@ import android.util.Log; import androidx.annotation.VisibleForTesting; +import com.android.bluetooth.BluetoothEventLogger; import com.android.internal.annotations.GuardedBy; -import com.google.common.collect.EvictingQueue; - import java.util.HashMap; /** Helper class that keeps track of advertiser stats. */ @@ -40,11 +39,8 @@ class AdvertiserMap { @GuardedBy("this") private final HashMap<Integer, AppAdvertiseStats> mAppAdvertiseStats = new HashMap<>(); - private static final int ADVERTISE_STATE_MAX_SIZE = 5; - - @GuardedBy("this") - private final EvictingQueue<AppAdvertiseStats> mLastAdvertises = - EvictingQueue.create(ADVERTISE_STATE_MAX_SIZE); + private final BluetoothEventLogger mLastAdvertises = + new BluetoothEventLogger(5, "Last Advertising"); /** Add an entry to the stats map if it doesn't already exist. */ void addAppAdvertiseStats(int id, Context context, AttributionSource attrSource) { @@ -122,7 +118,10 @@ class AdvertiserMap { } stats.recordAdvertiseStop(mAppAdvertiseStats.size()); mAppAdvertiseStats.remove(id); - mLastAdvertises.add(stats); + + StringBuilder sb = new StringBuilder(); + AppAdvertiseStats.dumpToString(sb, stats); + mLastAdvertises.add(sb.toString()); } synchronized void enableAdvertisingSet( @@ -191,13 +190,7 @@ class AdvertiserMap { /** Logs advertiser debug information. */ synchronized void dump(StringBuilder sb) { - if (!mLastAdvertises.isEmpty()) { - sb.append("\n last ").append(mLastAdvertises.size()).append(" advertising:"); - for (AppAdvertiseStats stats : mLastAdvertises) { - AppAdvertiseStats.dumpToString(sb, stats); - } - sb.append("\n"); - } + mLastAdvertises.dump(sb); if (!mAppAdvertiseStats.isEmpty()) { sb.append(" Total number of ongoing advertising : ") diff --git a/android/app/src/com/android/bluetooth/gatt/AppAdvertiseStats.java b/android/app/src/com/android/bluetooth/gatt/AppAdvertiseStats.java index faf335e651..d997426cd5 100644 --- a/android/app/src/com/android/bluetooth/gatt/AppAdvertiseStats.java +++ b/android/app/src/com/android/bluetooth/gatt/AppAdvertiseStats.java @@ -15,6 +15,9 @@ */ package com.android.bluetooth.gatt; +import static android.app.ActivityManager.RunningAppProcessInfo.IMPORTANCE_CACHED; +import static android.app.ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND_SERVICE; + import static com.android.bluetooth.util.AttributionSourceUtil.getLastAttributionTag; import android.annotation.Nullable; @@ -78,9 +81,11 @@ class AppAdvertiseStats { public Instant stopTime = null; public int duration = 0; public int maxExtendedAdvertisingEvents = 0; + public int appImportanceOnStart; - AppAdvertiserRecord(Instant startTime) { + AppAdvertiserRecord(Instant startTime, int appImportanceOnStart) { this.startTime = startTime; + this.appImportanceOnStart = appImportanceOnStart; } } @@ -103,6 +108,7 @@ class AppAdvertiseStats { private @Nullable AppAdvertiserData mPeriodicAdvertisingData = null; private boolean mPeriodicIncludeTxPower = false; private int mPeriodicInterval = 0; + private int mAppImportance = IMPORTANCE_CACHED; public ArrayList<AppAdvertiserRecord> mAdvertiserRecords = new ArrayList<AppAdvertiserRecord>(); AppAdvertiseStats(int appUid, int id, String name, AttributionSource attrSource) { @@ -122,7 +128,7 @@ class AppAdvertiseStats { int maxExtAdvEvents, int instanceCount) { mAdvertisingEnabled = true; - AppAdvertiserRecord record = new AppAdvertiserRecord(Instant.now()); + AppAdvertiserRecord record = new AppAdvertiserRecord(Instant.now(), mAppImportance); record.duration = duration; record.maxExtendedAdvertisingEvents = maxExtAdvEvents; mAdvertiserRecords.add(record); @@ -219,7 +225,8 @@ class AppAdvertiseStats { new int[] {mAppUid}, new String[] {mAppName}, BluetoothStatsLog.LE_ADV_ERROR_REPORTED__LE_ADV_OP_CODE__ERROR_CODE_ON_START, - convertStatusCode(status)); + convertStatusCode(status), + getAttributionTag()); } MetricsLogger.getInstance().cacheCount(BluetoothProtoEnums.LE_ADV_ERROR_ON_START_COUNT, 1); } @@ -345,6 +352,14 @@ class AppAdvertiseStats { this.mId = id; } + void setAppImportance(int importance) { + mAppImportance = importance; + } + + private String getAttributionTag() { + return mAttributionTag != null ? mAttributionTag : ""; + } + private static void recordAdvertiseDurationCount( Duration duration, boolean isConnectable, boolean inPeriodic) { if (duration.compareTo(Duration.ofMinutes(1)) < 0) { @@ -419,7 +434,9 @@ class AppAdvertiseStats { mScanResponseData != null && mScannable /* hasScanResponse */, !mLegacy /* isExtendedAdv */, instanceCount, - durationMs); + durationMs, + mAppImportance, + getAttributionTag()); } if (enable) { MetricsLogger.getInstance().cacheCount(BluetoothProtoEnums.LE_ADV_COUNT_ENABLE, 1); @@ -583,6 +600,22 @@ class AppAdvertiseStats { .append(record.duration); sb.append("\n └Maximum number of extended advertising events : ") .append(record.maxExtendedAdvertisingEvents); + if (record.appImportanceOnStart < IMPORTANCE_FOREGROUND_SERVICE) { + sb.append( + "\n" + + " └App Importance : higher" + + " than Foreground Service"); + } else if (record.appImportanceOnStart > IMPORTANCE_FOREGROUND_SERVICE) { + sb.append( + "\n" + + " └App Importance : lower than" + + " Foreground Service"); + } else { + sb.append( + "\n" + + " └App Importance : Foreground" + + " Service"); + } } dumpAppAdvertiseStats(sb, stats); diff --git a/android/app/src/com/android/bluetooth/gatt/CallbackInfo.java b/android/app/src/com/android/bluetooth/gatt/CallbackInfo.java index f104b7ee19..fb7f34a602 100644 --- a/android/app/src/com/android/bluetooth/gatt/CallbackInfo.java +++ b/android/app/src/com/android/bluetooth/gatt/CallbackInfo.java @@ -15,46 +15,18 @@ */ package com.android.bluetooth.gatt; +import com.google.protobuf.ByteString; + /** * Helper class that keeps track of callback parameters for app callbacks. These are held during * congestion and reported when congestion clears. */ -public class CallbackInfo { - public String address; - public int status; - public int handle; - public byte[] value; - - static class Builder { - private final String mAddress; - private final int mStatus; - private int mHandle; - private byte[] mValue; - - Builder(String address, int status) { - mAddress = address; - mStatus = status; - } - - Builder setHandle(int handle) { - mHandle = handle; - return this; - } - - Builder setValue(byte[] value) { - mValue = value; - return this; - } - - CallbackInfo build() { - return new CallbackInfo(mAddress, mStatus, mHandle, mValue); - } +record CallbackInfo(String address, int status, int handle, ByteString value) { + CallbackInfo(String address, int status) { + this(address, status, 0, null); } - private CallbackInfo(String address, int status, int handle, byte[] value) { - this.address = address; - this.status = status; - this.handle = handle; - this.value = value; + byte[] valueByteArray() { + return value == null ? null : value.toByteArray(); } } diff --git a/android/app/src/com/android/bluetooth/gatt/DistanceMeasurementBinder.kt b/android/app/src/com/android/bluetooth/gatt/DistanceMeasurementBinder.kt index a63b757904..4d0835c175 100644 --- a/android/app/src/com/android/bluetooth/gatt/DistanceMeasurementBinder.kt +++ b/android/app/src/com/android/bluetooth/gatt/DistanceMeasurementBinder.kt @@ -1,5 +1,5 @@ /* - * Copyright 2025 The Android Open Source Project + * Copyright (C) 2025 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,6 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package com.android.bluetooth.gatt import android.Manifest diff --git a/android/app/src/com/android/bluetooth/gatt/DistanceMeasurementManager.java b/android/app/src/com/android/bluetooth/gatt/DistanceMeasurementManager.java index 7ed4fe72e6..186865c23a 100644 --- a/android/app/src/com/android/bluetooth/gatt/DistanceMeasurementManager.java +++ b/android/app/src/com/android/bluetooth/gatt/DistanceMeasurementManager.java @@ -1,5 +1,5 @@ /* - * Copyright 2022 The Android Open Source Project + * Copyright (C) 2022 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. @@ -16,6 +16,9 @@ package com.android.bluetooth.gatt; +import static android.bluetooth.le.DistanceMeasurementMethod.DISTANCE_MEASUREMENT_METHOD_AUTO; +import static android.bluetooth.le.DistanceMeasurementMethod.DISTANCE_MEASUREMENT_METHOD_CHANNEL_SOUNDING; +import static android.bluetooth.le.DistanceMeasurementMethod.DISTANCE_MEASUREMENT_METHOD_RSSI; import static android.content.pm.PackageManager.FEATURE_BLUETOOTH_LE_CHANNEL_SOUNDING; import android.bluetooth.BluetoothDevice; @@ -124,14 +127,13 @@ public class DistanceMeasurementManager { onDistanceMeasurementStopped( addressForCs, BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ENABLED, - DistanceMeasurementMethod - .DISTANCE_MEASUREMENT_METHOD_CHANNEL_SOUNDING); + DISTANCE_MEASUREMENT_METHOD_CHANNEL_SOUNDING); } for (String addressForRssi : mRssiTrackers.keySet()) { onDistanceMeasurementStopped( addressForRssi, BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ENABLED, - DistanceMeasurementMethod.DISTANCE_MEASUREMENT_METHOD_RSSI); + DISTANCE_MEASUREMENT_METHOD_RSSI); } }); } @@ -141,16 +143,13 @@ public class DistanceMeasurementManager { } List<DistanceMeasurementMethod> getSupportedDistanceMeasurementMethods() { - ArrayList<DistanceMeasurementMethod> methods = new ArrayList<DistanceMeasurementMethod>(); + List<DistanceMeasurementMethod> methods = new ArrayList<>(); methods.add( - new DistanceMeasurementMethod.Builder( - DistanceMeasurementMethod.DISTANCE_MEASUREMENT_METHOD_RSSI) - .build()); + new DistanceMeasurementMethod.Builder(DISTANCE_MEASUREMENT_METHOD_RSSI).build()); if (mHasChannelSoundingFeature && mAdapterService.isLeChannelSoundingSupported()) { methods.add( new DistanceMeasurementMethod.Builder( - DistanceMeasurementMethod - .DISTANCE_MEASUREMENT_METHOD_CHANNEL_SOUNDING) + DISTANCE_MEASUREMENT_METHOD_CHANNEL_SOUNDING) .build()); } return methods; @@ -198,11 +197,11 @@ public class DistanceMeasurementManager { new DistanceMeasurementTracker(this, params, address, uuid, interval, callback); switch (params.getMethodId()) { - case DistanceMeasurementMethod.DISTANCE_MEASUREMENT_METHOD_AUTO: - case DistanceMeasurementMethod.DISTANCE_MEASUREMENT_METHOD_RSSI: + case DISTANCE_MEASUREMENT_METHOD_AUTO: + case DISTANCE_MEASUREMENT_METHOD_RSSI: startRssiTracker(tracker); break; - case DistanceMeasurementMethod.DISTANCE_MEASUREMENT_METHOD_CHANNEL_SOUNDING: + case DISTANCE_MEASUREMENT_METHOD_CHANNEL_SOUNDING: if (!mHasChannelSoundingFeature || !mAdapterService.isLeChannelSoundingSupported()) { Log.e(TAG, "Channel Sounding is not supported."); @@ -238,9 +237,7 @@ public class DistanceMeasurementManager { return; } mDistanceMeasurementNativeInterface.startDistanceMeasurement( - tracker.mIdentityAddress, - tracker.mInterval, - DistanceMeasurementMethod.DISTANCE_MEASUREMENT_METHOD_RSSI); + tracker.mIdentityAddress, tracker.mInterval, DISTANCE_MEASUREMENT_METHOD_RSSI); } private synchronized void startCsTracker(DistanceMeasurementTracker tracker) { @@ -254,7 +251,7 @@ public class DistanceMeasurementManager { mDistanceMeasurementNativeInterface.startDistanceMeasurement( tracker.mIdentityAddress, tracker.mInterval, - DistanceMeasurementMethod.DISTANCE_MEASUREMENT_METHOD_CHANNEL_SOUNDING); + DISTANCE_MEASUREMENT_METHOD_CHANNEL_SOUNDING); } int stopDistanceMeasurement(UUID uuid, BluetoothDevice device, int method, boolean timeout) { @@ -277,10 +274,10 @@ public class DistanceMeasurementManager { + BluetoothUtils.toAnonymizedAddress(address)); switch (method) { - case DistanceMeasurementMethod.DISTANCE_MEASUREMENT_METHOD_AUTO: - case DistanceMeasurementMethod.DISTANCE_MEASUREMENT_METHOD_RSSI: + case DISTANCE_MEASUREMENT_METHOD_AUTO: + case DISTANCE_MEASUREMENT_METHOD_RSSI: return stopRssiTracker(uuid, address, timeout); - case DistanceMeasurementMethod.DISTANCE_MEASUREMENT_METHOD_CHANNEL_SOUNDING: + case DISTANCE_MEASUREMENT_METHOD_CHANNEL_SOUNDING: return stopCsTracker(uuid, address, timeout); default: Log.w(TAG, "stopDistanceMeasurement with invalid method:" + method); @@ -340,7 +337,7 @@ public class DistanceMeasurementManager { logd("no rssi tracker"); mRssiTrackers.remove(identityAddress); mDistanceMeasurementNativeInterface.stopDistanceMeasurement( - identityAddress, DistanceMeasurementMethod.DISTANCE_MEASUREMENT_METHOD_RSSI); + identityAddress, DISTANCE_MEASUREMENT_METHOD_RSSI); } return BluetoothStatusCodes.SUCCESS; } @@ -369,8 +366,7 @@ public class DistanceMeasurementManager { logd("No CS tracker exists; stop CS"); mCsTrackers.remove(identityAddress); mDistanceMeasurementNativeInterface.stopDistanceMeasurement( - identityAddress, - DistanceMeasurementMethod.DISTANCE_MEASUREMENT_METHOD_CHANNEL_SOUNDING); + identityAddress, DISTANCE_MEASUREMENT_METHOD_CHANNEL_SOUNDING); } return BluetoothStatusCodes.SUCCESS; } @@ -396,8 +392,8 @@ public class DistanceMeasurementManager { /** Convert frequency into interval in ms */ private static int getIntervalValue(int frequency, int method) { switch (method) { - case DistanceMeasurementMethod.DISTANCE_MEASUREMENT_METHOD_AUTO: - case DistanceMeasurementMethod.DISTANCE_MEASUREMENT_METHOD_RSSI: + case DISTANCE_MEASUREMENT_METHOD_AUTO: + case DISTANCE_MEASUREMENT_METHOD_RSSI: switch (frequency) { case DistanceMeasurementParams.REPORT_FREQUENCY_LOW: return RSSI_LOW_FREQUENCY_INTERVAL_MS; @@ -407,7 +403,7 @@ public class DistanceMeasurementManager { return RSSI_HIGH_FREQUENCY_INTERVAL_MS; } break; - case DistanceMeasurementMethod.DISTANCE_MEASUREMENT_METHOD_CHANNEL_SOUNDING: + case DISTANCE_MEASUREMENT_METHOD_CHANNEL_SOUNDING: switch (frequency) { case DistanceMeasurementParams.REPORT_FREQUENCY_LOW: return CS_LOW_FREQUENCY_INTERVAL_MS; @@ -432,10 +428,10 @@ public class DistanceMeasurementManager { + ", method:" + method); switch (method) { - case DistanceMeasurementMethod.DISTANCE_MEASUREMENT_METHOD_RSSI: + case DISTANCE_MEASUREMENT_METHOD_RSSI: handleRssiStarted(address); break; - case DistanceMeasurementMethod.DISTANCE_MEASUREMENT_METHOD_CHANNEL_SOUNDING: + case DISTANCE_MEASUREMENT_METHOD_CHANNEL_SOUNDING: handleCsStarted(address); break; default: @@ -491,10 +487,10 @@ public class DistanceMeasurementManager { + ", method:" + method); switch (method) { - case DistanceMeasurementMethod.DISTANCE_MEASUREMENT_METHOD_RSSI: + case DISTANCE_MEASUREMENT_METHOD_RSSI: handleRssiStopped(address, reason); break; - case DistanceMeasurementMethod.DISTANCE_MEASUREMENT_METHOD_CHANNEL_SOUNDING: + case DISTANCE_MEASUREMENT_METHOD_CHANNEL_SOUNDING: handleCsStopped(address, reason); break; default: @@ -563,10 +559,10 @@ public class DistanceMeasurementManager { .setMeasurementTimestampNanos(elapsedRealtimeNanos); switch (method) { - case DistanceMeasurementMethod.DISTANCE_MEASUREMENT_METHOD_RSSI: + case DISTANCE_MEASUREMENT_METHOD_RSSI: handleRssiResult(address, builder.build()); break; - case DistanceMeasurementMethod.DISTANCE_MEASUREMENT_METHOD_CHANNEL_SOUNDING: + case DISTANCE_MEASUREMENT_METHOD_CHANNEL_SOUNDING: if (azimuthAngle != INVALID_AZIMUTH_ANGLE_DEGREE) { builder.setAzimuthAngle(azimuthAngle); builder.setErrorAzimuthAngle(errorAzimuthAngle); @@ -697,5 +693,4 @@ public class DistanceMeasurementManager { private static void logd(String msg) { Log.d(TAG, msg); } - } diff --git a/android/app/src/com/android/bluetooth/gatt/DistanceMeasurementNativeInterface.java b/android/app/src/com/android/bluetooth/gatt/DistanceMeasurementNativeInterface.java index 8d617ecf54..8cc365c291 100644 --- a/android/app/src/com/android/bluetooth/gatt/DistanceMeasurementNativeInterface.java +++ b/android/app/src/com/android/bluetooth/gatt/DistanceMeasurementNativeInterface.java @@ -1,5 +1,5 @@ /* - * Copyright 2023 The Android Open Source Project + * Copyright (C) 2023 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -26,13 +26,6 @@ import com.android.internal.annotations.VisibleForTesting; public class DistanceMeasurementNativeInterface { private static final String TAG = DistanceMeasurementNativeInterface.class.getSimpleName(); - @GuardedBy("INSTANCE_LOCK") - private static DistanceMeasurementNativeInterface sInstance; - - private static final Object INSTANCE_LOCK = new Object(); - - private DistanceMeasurementManager mDistanceMeasurementManager; - /** * Do not modify without updating distance_measurement_manager.h match up with * DistanceMeasurementErrorCode enum of distance_measurement_manager.h @@ -47,6 +40,13 @@ public class DistanceMeasurementNativeInterface { private static final int REASON_INVALID_PARAMETERS = 6; private static final int REASON_INTERNAL_ERROR = 7; + private static final Object INSTANCE_LOCK = new Object(); + + @GuardedBy("INSTANCE_LOCK") + private static DistanceMeasurementNativeInterface sInstance; + + private DistanceMeasurementManager mDistanceMeasurementManager; + private DistanceMeasurementNativeInterface() {} /** diff --git a/android/app/src/com/android/bluetooth/gatt/DistanceMeasurementTracker.java b/android/app/src/com/android/bluetooth/gatt/DistanceMeasurementTracker.java index adebbd0d33..dee39179af 100644 --- a/android/app/src/com/android/bluetooth/gatt/DistanceMeasurementTracker.java +++ b/android/app/src/com/android/bluetooth/gatt/DistanceMeasurementTracker.java @@ -1,5 +1,5 @@ /* - * Copyright 2022 The Android Open Source Project + * Copyright (C) 2022 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. @@ -29,14 +29,15 @@ import java.util.UUID; class DistanceMeasurementTracker { private static final String TAG = DistanceMeasurementTracker.class.getSimpleName(); - final DistanceMeasurementManager mManager; final BluetoothDevice mDevice; final String mIdentityAddress; - final UUID mUuid; final int mInterval; // Report interval in ms - final int mDuration; // Report duration in s - final int mMethod; final IDistanceMeasurementCallback mCallback; + private final DistanceMeasurementManager mManager; + private final UUID mUuid; + private final int mDuration; // Report duration in s + private final int mMethod; + boolean mStarted = false; private Handler mHandler; @@ -60,12 +61,7 @@ class DistanceMeasurementTracker { void startTimer(Looper looper) { mHandler = new Handler(looper); mHandler.postDelayed( - new Runnable() { - @Override - public void run() { - mManager.stopDistanceMeasurement(mUuid, mDevice, mMethod, true); - } - }, + () -> mManager.stopDistanceMeasurement(mUuid, mDevice, mMethod, true), mDuration * 1000L); } @@ -88,15 +84,12 @@ class DistanceMeasurementTracker { @Override public boolean equals(Object o) { if (o == null) return false; - if (!(o instanceof DistanceMeasurementTracker)) return false; final DistanceMeasurementTracker u = (DistanceMeasurementTracker) o; - if (!Objects.equals(mIdentityAddress, u.mIdentityAddress)) { return false; } - if (!Objects.equals(mUuid, u.mUuid)) { return false; } diff --git a/android/app/src/com/android/bluetooth/gatt/FilterParams.java b/android/app/src/com/android/bluetooth/gatt/FilterParams.java index 762e7e8818..39a59c07e6 100644 --- a/android/app/src/com/android/bluetooth/gatt/FilterParams.java +++ b/android/app/src/com/android/bluetooth/gatt/FilterParams.java @@ -16,93 +16,17 @@ package com.android.bluetooth.gatt; -public class FilterParams { - private final int mClientIf; - private final int mFiltIndex; - private final int mFeatSeln; - private final int mListLogicType; - private final int mFiltLogicType; - private final int mRssiHighValue; - private final int mRssiLowValue; - private final int mDelyMode; - private final int mFoundTimeOut; - private final int mLostTimeOut; - private final int mFoundTimeOutCnt; - private final int mNumOfTrackEntries; - - public FilterParams( - int clientIf, - int filtIndex, - int featSeln, - int listLogicType, - int filtLogicType, - int rssiHighThres, - int rssiLowThres, - int delyMode, - int foundTimeout, - int lostTimeout, - int foundTimeoutCnt, - int numOfTrackingEntries) { - - mClientIf = clientIf; - mFiltIndex = filtIndex; - mFeatSeln = featSeln; - mListLogicType = listLogicType; - mFiltLogicType = filtLogicType; - mRssiHighValue = rssiHighThres; - mRssiLowValue = rssiLowThres; - mDelyMode = delyMode; - mFoundTimeOut = foundTimeout; - mLostTimeOut = lostTimeout; - mFoundTimeOutCnt = foundTimeoutCnt; - mNumOfTrackEntries = numOfTrackingEntries; - } - - public int getClientIf() { - return mClientIf; - } - - public int getFiltIndex() { - return mFiltIndex; - } - - public int getFeatSeln() { - return mFeatSeln; - } - - public int getDelyMode() { - return mDelyMode; - } - - public int getListLogicType() { - return mListLogicType; - } - - public int getFiltLogicType() { - return mFiltLogicType; - } - - public int getRSSIHighValue() { - return mRssiHighValue; - } - - public int getRSSILowValue() { - return mRssiLowValue; - } - - public int getFoundTimeout() { - return mFoundTimeOut; - } - - public int getFoundTimeOutCnt() { - return mFoundTimeOutCnt; - } - - public int getLostTimeout() { - return mLostTimeOut; - } - - public int getNumOfTrackEntries() { - return mNumOfTrackEntries; - } -} +// All values of this class are accessed from native; see com_android_bluetooth_gatt.cpp +public record FilterParams( + int clientInterface, + int filterIndex, + int featureSelection, + int listLogicType, + int filterLogicType, + int rssiHighValue, + int rssiLowValue, + int delayMode, + int foundTimeout, + int lostTimeout, + int foundTimeoutCount, + int numberOfTrackEntries) {} diff --git a/android/app/src/com/android/bluetooth/gatt/GattNativeInterface.java b/android/app/src/com/android/bluetooth/gatt/GattNativeInterface.java index ad4d9538e7..37699ff2e1 100644 --- a/android/app/src/com/android/bluetooth/gatt/GattNativeInterface.java +++ b/android/app/src/com/android/bluetooth/gatt/GattNativeInterface.java @@ -1,5 +1,5 @@ /* - * Copyright 2022 The Android Open Source Project + * Copyright (C) 2022 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. @@ -124,10 +124,6 @@ public class GattNativeInterface { .onServerSubrateChange(connId, subrateFactor, latency, contNum, timeout, status); } - void onSearchCompleted(int connId, int status) throws RemoteException { - getGattService().onSearchCompleted(connId, status); - } - GattDbElement getSampleGattDbElement() { return getGattService().getSampleGattDbElement(); } @@ -311,8 +307,6 @@ public class GattNativeInterface { private native void gattClientDiscoverServiceByUuidNative( int connId, long serviceUuidLsb, long serviceUuidMsb); - private native void gattClientGetGattDbNative(int connId); - private native void gattClientReadCharacteristicNative(int connId, int handle, int authReq); private native void gattClientReadUsingCharacteristicUuidNative( @@ -495,11 +489,6 @@ public class GattNativeInterface { gattClientDiscoverServiceByUuidNative(connId, serviceUuidLsb, serviceUuidMsb); } - /** Get GATT DB of the remote device */ - public void gattClientGetGattDb(int connId) { - gattClientGetGattDbNative(connId); - } - /** Read a characteristic by the given handle */ public void gattClientReadCharacteristic(int connId, int handle, int authReq) { gattClientReadCharacteristicNative(connId, handle, authReq); diff --git a/android/app/src/com/android/bluetooth/gatt/GattObjectsFactory.java b/android/app/src/com/android/bluetooth/gatt/GattObjectsFactory.java index 0279b2b199..28ecaa7b4f 100644 --- a/android/app/src/com/android/bluetooth/gatt/GattObjectsFactory.java +++ b/android/app/src/com/android/bluetooth/gatt/GattObjectsFactory.java @@ -1,5 +1,5 @@ /* - * Copyright 2022 The Android Open Source Project + * Copyright (C) 2022 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. diff --git a/android/app/src/com/android/bluetooth/gatt/GattService.java b/android/app/src/com/android/bluetooth/gatt/GattService.java index 947885020a..aaa00b45df 100644 --- a/android/app/src/com/android/bluetooth/gatt/GattService.java +++ b/android/app/src/com/android/bluetooth/gatt/GattService.java @@ -21,7 +21,9 @@ import static android.Manifest.permission.BLUETOOTH_PRIVILEGED; import static android.app.ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND_SERVICE; import static android.bluetooth.BluetoothProfile.STATE_CONNECTED; import static android.bluetooth.BluetoothProfile.STATE_DISCONNECTED; +import static android.bluetooth.BluetoothUtils.toAnonymizedAddress; +import static com.android.bluetooth.Utils.callbackToApp; import static com.android.bluetooth.Utils.callerIsSystemOrActiveOrManagedUser; import static com.android.bluetooth.Utils.checkCallerTargetSdk; import static com.android.bluetooth.util.AttributionSourceUtil.getLastAttributionTag; @@ -41,7 +43,6 @@ import android.bluetooth.BluetoothGattService; import android.bluetooth.BluetoothProfile; import android.bluetooth.BluetoothProtoEnums; import android.bluetooth.BluetoothStatusCodes; -import android.bluetooth.BluetoothUtils; import android.bluetooth.IBluetoothGatt; import android.bluetooth.IBluetoothGattCallback; import android.bluetooth.IBluetoothGattServerCallback; @@ -56,12 +57,10 @@ import android.os.Build; import android.os.HandlerThread; import android.os.IBinder; import android.os.ParcelUuid; -import android.os.RemoteException; import android.provider.Settings; import android.sysprop.BluetoothProperties; import android.util.Log; -import com.android.bluetooth.BluetoothMetricsProto; import com.android.bluetooth.BluetoothStatsLog; import com.android.bluetooth.R; import com.android.bluetooth.Utils; @@ -75,6 +74,8 @@ import com.android.bluetooth.hid.HidHostService; import com.android.bluetooth.le_scan.ScanController; import com.android.internal.annotations.VisibleForTesting; +import com.google.protobuf.ByteString; + import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; @@ -157,6 +158,7 @@ public class GattService extends ProfileService { */ private final HashMap<String, Integer> mPermits = new HashMap<>(); + private final BluetoothAdapter mAdapter; private final AdapterService mAdapterService; private final AdvertiseManager mAdvertiseManager; private final GattNativeInterface mNativeInterface; @@ -168,6 +170,7 @@ public class GattService extends ProfileService { public GattService(AdapterService adapterService) { super(requireNonNull(adapterService)); + mAdapter = BluetoothAdapter.getDefaultAdapter(); mAdapterService = adapterService; mActivityManager = requireNonNull(getSystemService(ActivityManager.class)); mPackageManager = requireNonNull(mAdapterService.getPackageManager()); @@ -224,14 +227,13 @@ public class GattService extends ProfileService { setGattService(null); } if (mScanController != null) { - mScanController.stop(); + mScanController.cleanup(); } mClientMap.clear(); mRestrictedHandles.clear(); mServerMap.clear(); mHandleMap.clear(); mReliableQueue.clear(); - mNativeInterface.cleanup(); mAdvertiseManager.cleanup(); mDistanceMeasurementManager.cleanup(); @@ -356,12 +358,12 @@ public class GattService extends ProfileService { @Override public List<BluetoothDevice> getDevicesMatchingConnectionStates( - int[] states, AttributionSource attributionSource) { + int[] states, AttributionSource source) { GattService service = getService(); if (service == null) { return Collections.emptyList(); } - return service.getDevicesMatchingConnectionStates(states, attributionSource); + return service.getDevicesMatchingConnectionStates(states, source); } @Override @@ -369,22 +371,22 @@ public class GattService extends ProfileService { ParcelUuid uuid, IBluetoothGattCallback callback, boolean eattSupport, - AttributionSource attributionSource) { + AttributionSource source) { GattService service = getService(); if (service == null) { return; } - service.registerClient(uuid.getUuid(), callback, eattSupport, attributionSource); + service.registerClient(uuid.getUuid(), callback, eattSupport, source); } @Override - public void unregisterClient(int clientIf, AttributionSource attributionSource) { + public void unregisterClient(int clientIf, AttributionSource source) { GattService service = getService(); if (service == null) { return; } service.unregisterClient( - clientIf, attributionSource, ContextMap.RemoveReason.REASON_UNREGISTER_CLIENT); + clientIf, source, ContextMap.RemoveReason.REASON_UNREGISTER_CLIENT); } @Override @@ -396,7 +398,7 @@ public class GattService extends ProfileService { int transport, boolean opportunistic, int phy, - AttributionSource attributionSource) { + AttributionSource source) { GattService service = getService(); if (service == null) { return; @@ -409,17 +411,16 @@ public class GattService extends ProfileService { transport, opportunistic, phy, - attributionSource); + source); } @Override - public void clientDisconnect( - int clientIf, String address, AttributionSource attributionSource) { + public void clientDisconnect(int clientIf, String address, AttributionSource source) { GattService service = getService(); if (service == null) { return; } - service.clientDisconnect(clientIf, address, attributionSource); + service.clientDisconnect(clientIf, address, source); } @Override @@ -429,70 +430,59 @@ public class GattService extends ProfileService { int txPhy, int rxPhy, int phyOptions, - AttributionSource attributionSource) { + AttributionSource source) { GattService service = getService(); if (service == null) { return; } - service.clientSetPreferredPhy( - clientIf, address, txPhy, rxPhy, phyOptions, attributionSource); + service.clientSetPreferredPhy(clientIf, address, txPhy, rxPhy, phyOptions, source); } @Override - public void clientReadPhy( - int clientIf, String address, AttributionSource attributionSource) { + public void clientReadPhy(int clientIf, String address, AttributionSource source) { GattService service = getService(); if (service == null) { return; } - service.clientReadPhy(clientIf, address, attributionSource); + service.clientReadPhy(clientIf, address, source); } @Override - public void refreshDevice( - int clientIf, String address, AttributionSource attributionSource) { + public void refreshDevice(int clientIf, String address, AttributionSource source) { GattService service = getService(); if (service == null) { return; } - service.refreshDevice(clientIf, address, attributionSource); + service.refreshDevice(clientIf, address, source); } @Override - public void discoverServices( - int clientIf, String address, AttributionSource attributionSource) { + public void discoverServices(int clientIf, String address, AttributionSource source) { GattService service = getService(); if (service == null) { return; } - service.discoverServices(clientIf, address, attributionSource); + service.discoverServices(clientIf, address, source); } @Override public void discoverServiceByUuid( - int clientIf, - String address, - ParcelUuid uuid, - AttributionSource attributionSource) { + int clientIf, String address, ParcelUuid uuid, AttributionSource source) { GattService service = getService(); if (service == null) { return; } - service.discoverServiceByUuid(clientIf, address, uuid.getUuid(), attributionSource); + service.discoverServiceByUuid(clientIf, address, uuid.getUuid(), source); } @Override public void readCharacteristic( - int clientIf, - String address, - int handle, - int authReq, - AttributionSource attributionSource) { + int clientIf, String address, int handle, int authReq, AttributionSource source) { GattService service = getService(); if (service == null) { return; } - service.readCharacteristic(clientIf, address, handle, authReq, attributionSource); + service.readCharacteristic(clientIf, address, handle, authReq, source); } @Override @@ -503,19 +493,13 @@ public class GattService extends ProfileService { int startHandle, int endHandle, int authReq, - AttributionSource attributionSource) { + AttributionSource source) { GattService service = getService(); if (service == null) { return; } service.readUsingCharacteristicUuid( - clientIf, - address, - uuid.getUuid(), - startHandle, - endHandle, - authReq, - attributionSource); + clientIf, address, uuid.getUuid(), startHandle, endHandle, authReq, source); } @Override @@ -526,27 +510,23 @@ public class GattService extends ProfileService { int writeType, int authReq, byte[] value, - AttributionSource attributionSource) { + AttributionSource source) { GattService service = getService(); if (service == null) { return BluetoothStatusCodes.ERROR_PROFILE_SERVICE_NOT_BOUND; } return service.writeCharacteristic( - clientIf, address, handle, writeType, authReq, value, attributionSource); + clientIf, address, handle, writeType, authReq, value, source); } @Override public void readDescriptor( - int clientIf, - String address, - int handle, - int authReq, - AttributionSource attributionSource) { + int clientIf, String address, int handle, int authReq, AttributionSource source) { GattService service = getService(); if (service == null) { return; } - service.readDescriptor(clientIf, address, handle, authReq, attributionSource); + service.readDescriptor(clientIf, address, handle, authReq, source); } @Override @@ -556,36 +536,31 @@ public class GattService extends ProfileService { int handle, int authReq, byte[] value, - AttributionSource attributionSource) { + AttributionSource source) { GattService service = getService(); if (service == null) { return BluetoothStatusCodes.ERROR_PROFILE_SERVICE_NOT_BOUND; } - return service.writeDescriptor( - clientIf, address, handle, authReq, value, attributionSource); + return service.writeDescriptor(clientIf, address, handle, authReq, value, source); } @Override - public void beginReliableWrite( - int clientIf, String address, AttributionSource attributionSource) { + public void beginReliableWrite(int clientIf, String address, AttributionSource source) { GattService service = getService(); if (service == null) { return; } - service.beginReliableWrite(clientIf, address, attributionSource); + service.beginReliableWrite(clientIf, address, source); } @Override public void endReliableWrite( - int clientIf, - String address, - boolean execute, - AttributionSource attributionSource) { + int clientIf, String address, boolean execute, AttributionSource source) { GattService service = getService(); if (service == null) { return; } - service.endReliableWrite(clientIf, address, execute, attributionSource); + service.endReliableWrite(clientIf, address, execute, source); } @Override @@ -594,46 +569,40 @@ public class GattService extends ProfileService { String address, int handle, boolean enable, - AttributionSource attributionSource) { + AttributionSource source) { GattService service = getService(); if (service == null) { return; } - service.registerForNotification(clientIf, address, handle, enable, attributionSource); + service.registerForNotification(clientIf, address, handle, enable, source); } @Override - public void readRemoteRssi( - int clientIf, String address, AttributionSource attributionSource) { + public void readRemoteRssi(int clientIf, String address, AttributionSource source) { GattService service = getService(); if (service == null) { return; } - service.readRemoteRssi(clientIf, address, attributionSource); + service.readRemoteRssi(clientIf, address, source); } @Override - public void configureMTU( - int clientIf, String address, int mtu, AttributionSource attributionSource) { + public void configureMTU(int clientIf, String address, int mtu, AttributionSource source) { GattService service = getService(); if (service == null) { return; } - service.configureMTU(clientIf, address, mtu, attributionSource); + service.configureMTU(clientIf, address, mtu, source); } @Override public void connectionParameterUpdate( - int clientIf, - String address, - int connectionPriority, - AttributionSource attributionSource) { + int clientIf, String address, int connectionPriority, AttributionSource source) { GattService service = getService(); if (service == null) { return; } - service.connectionParameterUpdate( - clientIf, address, connectionPriority, attributionSource); + service.connectionParameterUpdate(clientIf, address, connectionPriority, source); } @Override @@ -646,7 +615,7 @@ public class GattService extends ProfileService { int supervisionTimeout, int minConnectionEventLen, int maxConnectionEventLen, - AttributionSource attributionSource) { + AttributionSource source) { GattService service = getService(); if (service == null) { return; @@ -660,15 +629,12 @@ public class GattService extends ProfileService { supervisionTimeout, minConnectionEventLen, maxConnectionEventLen, - attributionSource); + source); } @Override public int subrateModeRequest( - int clientIf, - BluetoothDevice device, - int subrateMode, - AttributionSource attributionSource) { + int clientIf, BluetoothDevice device, int subrateMode, AttributionSource source) { GattService service = getService(); if (service == null) { return BluetoothStatusCodes.ERROR_BLUETOOTH_NOT_ENABLED; @@ -678,12 +644,12 @@ public class GattService extends ProfileService { } if (!Utils.checkConnectPermissionForDataDelivery( - service, attributionSource, "GattService subrateModeRequest")) { + service, source, "GattService subrateModeRequest")) { return BluetoothStatusCodes.ERROR_MISSING_BLUETOOTH_CONNECT_PERMISSION; } Utils.enforceCdmAssociationIfNotBluetoothPrivileged( - service, service.mCompanionDeviceManager, attributionSource, device); + service, service.mCompanionDeviceManager, source, device); if (subrateMode < BluetoothGatt.SUBRATE_REQUEST_MODE_BALANCED || subrateMode > BluetoothGatt.SUBRATE_REQUEST_MODE_LOW_POWER) { @@ -704,21 +670,21 @@ public class GattService extends ProfileService { ParcelUuid uuid, IBluetoothGattServerCallback callback, boolean eattSupport, - AttributionSource attributionSource) { + AttributionSource source) { GattService service = getService(); if (service == null) { return; } - service.registerServer(uuid.getUuid(), callback, eattSupport, attributionSource); + service.registerServer(uuid.getUuid(), callback, eattSupport, source); } @Override - public void unregisterServer(int serverIf, AttributionSource attributionSource) { + public void unregisterServer(int serverIf, AttributionSource source) { GattService service = getService(); if (service == null) { return; } - service.unregisterServer(serverIf, attributionSource); + service.unregisterServer(serverIf, source); } @Override @@ -728,23 +694,21 @@ public class GattService extends ProfileService { int addressType, boolean isDirect, int transport, - AttributionSource attributionSource) { + AttributionSource source) { GattService service = getService(); if (service == null) { return; } - service.serverConnect( - serverIf, address, addressType, isDirect, transport, attributionSource); + service.serverConnect(serverIf, address, addressType, isDirect, transport, source); } @Override - public void serverDisconnect( - int serverIf, String address, AttributionSource attributionSource) { + public void serverDisconnect(int serverIf, String address, AttributionSource source) { GattService service = getService(); if (service == null) { return; } - service.serverDisconnect(serverIf, address, attributionSource); + service.serverDisconnect(serverIf, address, source); } @Override @@ -754,51 +718,48 @@ public class GattService extends ProfileService { int txPhy, int rxPhy, int phyOptions, - AttributionSource attributionSource) { + AttributionSource source) { GattService service = getService(); if (service == null) { return; } - service.serverSetPreferredPhy( - serverIf, address, txPhy, rxPhy, phyOptions, attributionSource); + service.serverSetPreferredPhy(serverIf, address, txPhy, rxPhy, phyOptions, source); } @Override - public void serverReadPhy( - int clientIf, String address, AttributionSource attributionSource) { + public void serverReadPhy(int clientIf, String address, AttributionSource source) { GattService service = getService(); if (service == null) { return; } - service.serverReadPhy(clientIf, address, attributionSource); + service.serverReadPhy(clientIf, address, source); } @Override - public void addService( - int serverIf, BluetoothGattService svc, AttributionSource attributionSource) { + public void addService(int serverIf, BluetoothGattService svc, AttributionSource source) { GattService service = getService(); if (service == null) { return; } - service.addService(serverIf, svc, attributionSource); + service.addService(serverIf, svc, source); } @Override - public void removeService(int serverIf, int handle, AttributionSource attributionSource) { + public void removeService(int serverIf, int handle, AttributionSource source) { GattService service = getService(); if (service == null) { return; } - service.removeService(serverIf, handle, attributionSource); + service.removeService(serverIf, handle, source); } @Override - public void clearServices(int serverIf, AttributionSource attributionSource) { + public void clearServices(int serverIf, AttributionSource source) { GattService service = getService(); if (service == null) { return; } - service.clearServices(serverIf, attributionSource); + service.clearServices(serverIf, source); } @Override @@ -809,13 +770,12 @@ public class GattService extends ProfileService { int status, int offset, byte[] value, - AttributionSource attributionSource) { + AttributionSource source) { GattService service = getService(); if (service == null) { return; } - service.sendResponse( - serverIf, address, requestId, status, offset, value, attributionSource); + service.sendResponse(serverIf, address, requestId, status, offset, value, source); } @Override @@ -825,22 +785,21 @@ public class GattService extends ProfileService { int handle, boolean confirm, byte[] value, - AttributionSource attributionSource) { + AttributionSource source) { GattService service = getService(); if (service == null) { return BluetoothStatusCodes.ERROR_PROFILE_SERVICE_NOT_BOUND; } - return service.sendNotification( - serverIf, address, handle, confirm, value, attributionSource); + return service.sendNotification(serverIf, address, handle, confirm, value, source); } @Override - public void disconnectAll(AttributionSource attributionSource) { + public void disconnectAll(AttributionSource source) { GattService service = getService(); if (service == null) { return; } - service.disconnectAll(attributionSource); + service.disconnectAll(source); } } @@ -848,23 +807,23 @@ public class GattService extends ProfileService { * Callback functions - CLIENT *************************************************************************/ - void onClientRegistered(int status, int clientIf, long uuidLsb, long uuidMsb) - throws RemoteException { + void onClientRegistered(int status, int clientIf, long uuidLsb, long uuidMsb) { UUID uuid = new UUID(uuidMsb, uuidLsb); Log.d(TAG, "onClientRegistered() - UUID=" + uuid + ", clientIf=" + clientIf); ContextMap<IBluetoothGattCallback>.App app = mClientMap.getByUuid(uuid); - if (app != null) { - if (status == 0) { - app.id = clientIf; - app.linkToDeath(new ClientDeathRecipient(clientIf, app.name)); - } else { - mClientMap.remove(uuid, ContextMap.RemoveReason.REASON_REGISTER_FAILED); - } - app.callback.onClientRegistered(status, clientIf); + if (app == null) { + return; + } + if (status != 0) { + mClientMap.remove(uuid, ContextMap.RemoveReason.REASON_REGISTER_FAILED); + } else { + app.id = clientIf; + app.linkToDeath(new ClientDeathRecipient(clientIf, app.name)); } + callbackToApp(() -> app.callback.onClientRegistered(status, clientIf)); } - void onConnected(int clientIf, int connId, int status, String address) throws RemoteException { + void onConnected(int clientIf, int connId, int status, String address) { Log.d( TAG, "onConnected() - clientIf=" @@ -872,11 +831,13 @@ public class GattService extends ProfileService { + ", connId=" + connId + ", address=" - + BluetoothUtils.toAnonymizedAddress(address) + + toAnonymizedAddress(address) + ", status=" + status); int connectionState = BluetoothProtoEnums.CONNECTION_STATE_DISCONNECTED; - if (status == 0) { + if (status != 0) { + mAdapterService.notifyGattClientConnectFailed(clientIf, getDevice(address)); + } else { mClientMap.addConnection(clientIf, connId, address); // Allow one writeCharacteristic operation at a time for each connected remote device. @@ -884,32 +845,31 @@ public class GattService extends ProfileService { Log.d( TAG, "onConnected() - adding permit for address=" - + BluetoothUtils.toAnonymizedAddress(address)); + + toAnonymizedAddress(address)); mPermits.putIfAbsent(address, -1); } connectionState = BluetoothProtoEnums.CONNECTION_STATE_CONNECTED; - } else { - mAdapterService.notifyGattClientConnectFailed(clientIf, getDevice(address)); } ContextMap<IBluetoothGattCallback>.App app = mClientMap.getById(clientIf); - if (app != null) { - app.callback.onClientConnectionState( - status, clientIf, (status == BluetoothGatt.GATT_SUCCESS), address); - MetricsLogger.getInstance() - .logBluetoothEvent( - getDevice(address), - BluetoothStatsLog - .BLUETOOTH_CROSS_LAYER_EVENT_REPORTED__EVENT_TYPE__GATT_CONNECT_JAVA, - connectionStatusToState(status), - app.appUid); - } statsLogGattConnectionStateChange( BluetoothProfile.GATT, address, clientIf, connectionState, status); + if (app == null) { + return; + } + boolean connected = status == BluetoothGatt.GATT_SUCCESS; + callbackToApp( + () -> app.callback.onClientConnectionState(status, clientIf, connected, address)); + MetricsLogger.getInstance() + .logBluetoothEvent( + getDevice(address), + BluetoothStatsLog + .BLUETOOTH_CROSS_LAYER_EVENT_REPORTED__EVENT_TYPE__GATT_CONNECT_JAVA, + connectionStatusToState(status), + app.appUid); } - void onDisconnected(int clientIf, int connId, int status, String address) - throws RemoteException { + void onDisconnected(int clientIf, int connId, int status, String address) { Log.d( TAG, "onDisconnected() - clientIf=" @@ -917,7 +877,7 @@ public class GattService extends ProfileService { + ", connId=" + connId + ", address=" - + BluetoothUtils.toAnonymizedAddress(address)); + + toAnonymizedAddress(address)); BluetoothDevice device = getDevice(address); mClientMap.removeConnection(clientIf, connId); mAdapterService.notifyGattClientDisconnect(clientIf, device); @@ -932,7 +892,7 @@ public class GattService extends ProfileService { Log.d( TAG, "onDisconnected() - removing permit for address=" - + BluetoothUtils.toAnonymizedAddress(address)); + + toAnonymizedAddress(address)); mPermits.remove(address); } } else { @@ -941,40 +901,46 @@ public class GattService extends ProfileService { Log.d( TAG, "onDisconnected() - set permit -1 for address=" - + BluetoothUtils.toAnonymizedAddress(address)); + + toAnonymizedAddress(address)); mPermits.put(address, -1); } } } - if (app != null) { - int disconnectStatus = status; - if (status == 0x16 /* HCI_ERR_CONN_CAUSE_LOCAL_HOST */ - && mAdapterService.getDatabase().getKeyMissingCount(device) > 0) { - // Native stack disconnects the link on detecting the bond loss. Native GATT would - // return HCI_ERR_CONN_CAUSE_LOCAL_HOST in such case, but the apps should see - // HCI_ERR_AUTH_FAILURE. - Log.d(TAG, "onDisconnected() - disconnected due to bond loss for device=" + device); - disconnectStatus = 0x05 /* HCI_ERR_AUTH_FAILURE */; - } - app.callback.onClientConnectionState(disconnectStatus, clientIf, false, address); - MetricsLogger.getInstance() - .logBluetoothEvent( - device, - BluetoothStatsLog - .BLUETOOTH_CROSS_LAYER_EVENT_REPORTED__EVENT_TYPE__GATT_DISCONNECT_JAVA, - BluetoothStatsLog.BLUETOOTH_CROSS_LAYER_EVENT_REPORTED__STATE__SUCCESS, - app.appUid); - } statsLogGattConnectionStateChange( BluetoothProfile.GATT, address, clientIf, BluetoothProtoEnums.CONNECTION_STATE_DISCONNECTED, status); + if (app == null) { + return; + } + final int disconnectStatus; + if (status == 0x16 // HCI_ERR_CONN_CAUSE_LOCAL_HOST + && mAdapterService.getDatabase().getKeyMissingCount(device) > 0) { + // Native stack disconnects the link on detecting the bond loss. Native GATT would + // return HCI_ERR_CONN_CAUSE_LOCAL_HOST in such case, but the apps should see + // HCI_ERR_AUTH_FAILURE. + Log.d(TAG, "onDisconnected() - disconnected due to bond loss for device=" + device); + disconnectStatus = 0x05 /* HCI_ERR_AUTH_FAILURE */; + } else { + disconnectStatus = status; + } + callbackToApp( + () -> + app.callback.onClientConnectionState( + disconnectStatus, clientIf, false, address)); + MetricsLogger.getInstance() + .logBluetoothEvent( + device, + BluetoothStatsLog + .BLUETOOTH_CROSS_LAYER_EVENT_REPORTED__EVENT_TYPE__GATT_DISCONNECT_JAVA, + BluetoothStatsLog.BLUETOOTH_CROSS_LAYER_EVENT_REPORTED__STATE__SUCCESS, + app.appUid); } - void onClientPhyUpdate(int connId, int txPhy, int rxPhy, int status) throws RemoteException { + void onClientPhyUpdate(int connId, int txPhy, int rxPhy, int status) { Log.d(TAG, "onClientPhyUpdate() - connId=" + connId + ", status=" + status); String address = mClientMap.addressByConnId(connId); @@ -987,15 +953,14 @@ public class GattService extends ProfileService { return; } - app.callback.onPhyUpdate(address, txPhy, rxPhy, status); + callbackToApp(() -> app.callback.onPhyUpdate(address, txPhy, rxPhy, status)); } - void onClientPhyRead(int clientIf, String address, int txPhy, int rxPhy, int status) - throws RemoteException { + void onClientPhyRead(int clientIf, String address, int txPhy, int rxPhy, int status) { Log.d( TAG, "onClientPhyRead() - address=" - + BluetoothUtils.toAnonymizedAddress(address) + + toAnonymizedAddress(address) + ", status=" + status + ", clientIf=" @@ -1003,10 +968,7 @@ public class GattService extends ProfileService { Integer connId = mClientMap.connIdByAddress(clientIf, address); if (connId == null) { - Log.d( - TAG, - "onClientPhyRead() - no connection to " - + BluetoothUtils.toAnonymizedAddress(address)); + Log.d(TAG, "onClientPhyRead() - no connection to " + toAnonymizedAddress(address)); return; } @@ -1015,11 +977,10 @@ public class GattService extends ProfileService { return; } - app.callback.onPhyRead(address, txPhy, rxPhy, status); + callbackToApp(() -> app.callback.onPhyRead(address, txPhy, rxPhy, status)); } - void onClientConnUpdate(int connId, int interval, int latency, int timeout, int status) - throws RemoteException { + void onClientConnUpdate(int connId, int interval, int latency, int timeout, int status) { Log.d(TAG, "onClientConnUpdate() - connId=" + connId + ", status=" + status); String address = mClientMap.addressByConnId(connId); @@ -1032,10 +993,13 @@ public class GattService extends ProfileService { return; } - app.callback.onConnectionUpdated(address, interval, latency, timeout, status); + callbackToApp( + () -> + app.callback.onConnectionUpdated( + address, interval, latency, timeout, status)); } - void onServiceChanged(int connId) throws RemoteException { + void onServiceChanged(int connId) { Log.d(TAG, "onServiceChanged - connId=" + connId); String address = mClientMap.addressByConnId(connId); @@ -1048,12 +1012,11 @@ public class GattService extends ProfileService { return; } - app.callback.onServiceChanged(address); + callbackToApp(() -> app.callback.onServiceChanged(address)); } void onClientSubrateChange( - int connId, int subrateFactor, int latency, int contNum, int timeout, int status) - throws RemoteException { + int connId, int subrateFactor, int latency, int contNum, int timeout, int status) { Log.d(TAG, "onClientSubrateChange() - connId=" + connId + ", status=" + status); String address = mClientMap.addressByConnId(connId); @@ -1066,10 +1029,13 @@ public class GattService extends ProfileService { return; } - app.callback.onSubrateChange(address, subrateFactor, latency, contNum, timeout, status); + callbackToApp( + () -> + app.callback.onSubrateChange( + address, subrateFactor, latency, contNum, timeout, status)); } - void onServerPhyUpdate(int connId, int txPhy, int rxPhy, int status) throws RemoteException { + void onServerPhyUpdate(int connId, int txPhy, int rxPhy, int status) { Log.d(TAG, "onServerPhyUpdate() - connId=" + connId + ", status=" + status); String address = mServerMap.addressByConnId(connId); @@ -1082,24 +1048,20 @@ public class GattService extends ProfileService { return; } - app.callback.onPhyUpdate(address, txPhy, rxPhy, status); + callbackToApp(() -> app.callback.onPhyUpdate(address, txPhy, rxPhy, status)); } - void onServerPhyRead(int serverIf, String address, int txPhy, int rxPhy, int status) - throws RemoteException { + void onServerPhyRead(int serverIf, String address, int txPhy, int rxPhy, int status) { Log.d( TAG, "onServerPhyRead() - address=" - + BluetoothUtils.toAnonymizedAddress(address) + + toAnonymizedAddress(address) + ", status=" + status); Integer connId = mServerMap.connIdByAddress(serverIf, address); if (connId == null) { - Log.d( - TAG, - "onServerPhyRead() - no connection to " - + BluetoothUtils.toAnonymizedAddress(address)); + Log.d(TAG, "onServerPhyRead() - no connection to " + toAnonymizedAddress(address)); return; } @@ -1108,11 +1070,10 @@ public class GattService extends ProfileService { return; } - app.callback.onPhyRead(address, txPhy, rxPhy, status); + callbackToApp(() -> app.callback.onPhyRead(address, txPhy, rxPhy, status)); } - void onServerConnUpdate(int connId, int interval, int latency, int timeout, int status) - throws RemoteException { + void onServerConnUpdate(int connId, int interval, int latency, int timeout, int status) { Log.d(TAG, "onServerConnUpdate() - connId=" + connId + ", status=" + status); String address = mServerMap.addressByConnId(connId); @@ -1125,12 +1086,14 @@ public class GattService extends ProfileService { return; } - app.callback.onConnectionUpdated(address, interval, latency, timeout, status); + callbackToApp( + () -> + app.callback.onConnectionUpdated( + address, interval, latency, timeout, status)); } void onServerSubrateChange( - int connId, int subrateFactor, int latency, int contNum, int timeout, int status) - throws RemoteException { + int connId, int subrateFactor, int latency, int contNum, int timeout, int status) { Log.d(TAG, "onServerSubrateChange() - connId=" + connId + ", status=" + status); String address = mServerMap.addressByConnId(connId); @@ -1143,34 +1106,20 @@ public class GattService extends ProfileService { return; } - app.callback.onSubrateChange(address, subrateFactor, latency, contNum, timeout, status); - } - - void onSearchCompleted(int connId, int status) throws RemoteException { - Log.d(TAG, "onSearchCompleted() - connId=" + connId + ", status=" + status); - // Gatt DB is ready! - - // This callback was called from the jni_workqueue thread. If we make request to the stack - // on the same thread, it might cause deadlock. Schedule request on a new thread instead. - Thread t = - new Thread( - new Runnable() { - @Override - public void run() { - mNativeInterface.gattClientGetGattDb(connId); - } - }); - t.start(); + callbackToApp( + () -> + app.callback.onSubrateChange( + address, subrateFactor, latency, contNum, timeout, status)); } GattDbElement getSampleGattDbElement() { return new GattDbElement(); } - void onGetGattDb(int connId, List<GattDbElement> db) throws RemoteException { + void onGetGattDb(int connId, List<GattDbElement> db) { String address = mClientMap.addressByConnId(connId); - Log.d(TAG, "onGetGattDb() - address=" + BluetoothUtils.toAnonymizedAddress(address)); + Log.d(TAG, "onGetGattDb() - address=" + toAnonymizedAddress(address)); ContextMap<IBluetoothGattCallback>.App app = mClientMap.getByConnId(connId); if (app == null || app.callback == null) { @@ -1252,7 +1201,7 @@ public class GattService extends ProfileService { mRestrictedHandles.put(connId, restrictedIds); } // Search is complete when there was error, or nothing more to process - app.callback.onSearchComplete(address, dbOut, 0 /* status */); + callbackToApp(() -> app.callback.onSearchComplete(address, dbOut, 0 /* status */)); } void onRegisterForNotifications(int connId, int status, int registered, int handle) { @@ -1261,7 +1210,7 @@ public class GattService extends ProfileService { Log.d( TAG, "onRegisterForNotifications() - address=" - + BluetoothUtils.toAnonymizedAddress(address) + + toAnonymizedAddress(address) + ", status=" + status + ", registered=" @@ -1270,68 +1219,67 @@ public class GattService extends ProfileService { + handle); } - void onNotify(int connId, String address, int handle, boolean isNotify, byte[] data) - throws RemoteException { + void onNotify(int connId, String address, int handle, boolean isNotify, byte[] data) { Log.v( TAG, "onNotify() - address=" - + BluetoothUtils.toAnonymizedAddress(address) + + toAnonymizedAddress(address) + ", handle=" + handle + ", length=" + data.length); ContextMap<IBluetoothGattCallback>.App app = mClientMap.getByConnId(connId); - if (app != null) { - try { - permissionCheck(connId, handle); - } catch (SecurityException ex) { - // Only throws on apps with target SDK T+ as this old API did not throw prior to T - if (checkCallerTargetSdk(this, app.name, Build.VERSION_CODES.TIRAMISU)) { - throw ex; - } - Log.w(TAG, "onNotify() - permission check failed!"); - return; + if (app == null) { + return; + } + try { + permissionCheck(connId, handle); + } catch (SecurityException ex) { + // Only throws on apps with target SDK T+ as this old API did not throw prior to T + if (checkCallerTargetSdk(this, app.name, Build.VERSION_CODES.TIRAMISU)) { + throw ex; } - app.callback.onNotify(address, handle, data); + Log.w(TAG, "onNotify() - permission check failed!"); + return; } + callbackToApp(() -> app.callback.onNotify(address, handle, data)); } - void onReadCharacteristic(int connId, int status, int handle, byte[] data) - throws RemoteException { + void onReadCharacteristic(int connId, int status, int handle, byte[] data) { String address = mClientMap.addressByConnId(connId); Log.v( TAG, "onReadCharacteristic() - address=" - + BluetoothUtils.toAnonymizedAddress(address) + + toAnonymizedAddress(address) + ", status=" + status + ", length=" + data.length); ContextMap<IBluetoothGattCallback>.App app = mClientMap.getByConnId(connId); - if (app != null) { - app.callback.onCharacteristicRead(address, status, handle, data); + if (app == null) { + return; } + callbackToApp(() -> app.callback.onCharacteristicRead(address, status, handle, data)); } - void onWriteCharacteristic(int connId, int status, int handle, byte[] data) - throws RemoteException { + void onWriteCharacteristic(int connId, int status, int handle, byte[] data) { String address = mClientMap.addressByConnId(connId); synchronized (mPermits) { Log.d( TAG, "onWriteCharacteristic() - increasing permit for address=" - + BluetoothUtils.toAnonymizedAddress(address)); + + toAnonymizedAddress(address)); mPermits.put(address, -1); } Log.v( TAG, "onWriteCharacteristic() - address=" - + BluetoothUtils.toAnonymizedAddress(address) + + toAnonymizedAddress(address) + ", status=" + status + ", length=" @@ -1343,126 +1291,131 @@ public class GattService extends ProfileService { } if (!app.isCongested) { - app.callback.onCharacteristicWrite(address, status, handle, data); + callbackToApp(() -> app.callback.onCharacteristicWrite(address, status, handle, data)); } else { - if (status == BluetoothGatt.GATT_CONNECTION_CONGESTED) { - status = BluetoothGatt.GATT_SUCCESS; - } - CallbackInfo callbackInfo = - new CallbackInfo.Builder(address, status) - .setHandle(handle) - .setValue(data) - .build(); + int queuedStatus = status; + if (queuedStatus == BluetoothGatt.GATT_CONNECTION_CONGESTED) { + queuedStatus = BluetoothGatt.GATT_SUCCESS; + } + final ByteString value = ByteString.copyFrom(data); + CallbackInfo callbackInfo = new CallbackInfo(address, queuedStatus, handle, value); app.queueCallback(callbackInfo); } } - void onExecuteCompleted(int connId, int status) throws RemoteException { + void onExecuteCompleted(int connId, int status) { String address = mClientMap.addressByConnId(connId); Log.v( TAG, "onExecuteCompleted() - address=" - + BluetoothUtils.toAnonymizedAddress(address) + + toAnonymizedAddress(address) + ", status=" + status); ContextMap<IBluetoothGattCallback>.App app = mClientMap.getByConnId(connId); - if (app != null) { - app.callback.onExecuteWrite(address, status); + if (app == null) { + return; } + callbackToApp(() -> app.callback.onExecuteWrite(address, status)); } - void onReadDescriptor(int connId, int status, int handle, byte[] data) throws RemoteException { + void onReadDescriptor(int connId, int status, int handle, byte[] data) { String address = mClientMap.addressByConnId(connId); Log.v( TAG, "onReadDescriptor() - address=" - + BluetoothUtils.toAnonymizedAddress(address) + + toAnonymizedAddress(address) + ", status=" + status + ", length=" + data.length); ContextMap<IBluetoothGattCallback>.App app = mClientMap.getByConnId(connId); - if (app != null) { - app.callback.onDescriptorRead(address, status, handle, data); + if (app == null) { + return; } + callbackToApp(() -> app.callback.onDescriptorRead(address, status, handle, data)); } - void onWriteDescriptor(int connId, int status, int handle, byte[] data) throws RemoteException { + void onWriteDescriptor(int connId, int status, int handle, byte[] data) { String address = mClientMap.addressByConnId(connId); Log.v( TAG, "onWriteDescriptor() - address=" - + BluetoothUtils.toAnonymizedAddress(address) + + toAnonymizedAddress(address) + ", status=" + status + ", length=" + data.length); ContextMap<IBluetoothGattCallback>.App app = mClientMap.getByConnId(connId); - if (app != null) { - app.callback.onDescriptorWrite(address, status, handle, data); + if (app == null) { + return; } + callbackToApp(() -> app.callback.onDescriptorWrite(address, status, handle, data)); } - void onReadRemoteRssi(int clientIf, String address, int rssi, int status) - throws RemoteException { + void onReadRemoteRssi(int clientIf, String address, int rssi, int status) { Log.d( TAG, "onReadRemoteRssi() - clientIf=" + clientIf + " address=" - + BluetoothUtils.toAnonymizedAddress(address) + + toAnonymizedAddress(address) + ", rssi=" + rssi + ", status=" + status); ContextMap<IBluetoothGattCallback>.App app = mClientMap.getById(clientIf); - if (app != null) { - app.callback.onReadRemoteRssi(address, rssi, status); + if (app == null) { + return; } + callbackToApp(() -> app.callback.onReadRemoteRssi(address, rssi, status)); } - void onConfigureMTU(int connId, int status, int mtu) throws RemoteException { + void onConfigureMTU(int connId, int status, int mtu) { String address = mClientMap.addressByConnId(connId); Log.d( TAG, "onConfigureMTU() address=" - + BluetoothUtils.toAnonymizedAddress(address) + + toAnonymizedAddress(address) + ", status=" + status + ", mtu=" + mtu); ContextMap<IBluetoothGattCallback>.App app = mClientMap.getByConnId(connId); - if (app != null) { - app.callback.onConfigureMTU(address, mtu, status); + if (app == null) { + return; } + callbackToApp(() -> app.callback.onConfigureMTU(address, mtu, status)); } - void onClientCongestion(int connId, boolean congested) throws RemoteException { + void onClientCongestion(int connId, boolean congested) { Log.v(TAG, "onClientCongestion() - connId=" + connId + ", congested=" + congested); ContextMap<IBluetoothGattCallback>.App app = mClientMap.getByConnId(connId); - if (app != null) { - app.isCongested = congested; - while (!app.isCongested) { - CallbackInfo callbackInfo = app.popQueuedCallback(); - if (callbackInfo == null) { - return; - } - app.callback.onCharacteristicWrite( - callbackInfo.address, - callbackInfo.status, - callbackInfo.handle, - callbackInfo.value); + if (app == null) { + return; + } + app.isCongested = congested; + while (!app.isCongested) { + CallbackInfo callbackInfo = app.popQueuedCallback(); + if (callbackInfo == null) { + return; } + callbackToApp( + () -> + app.callback.onCharacteristicWrite( + callbackInfo.address(), + callbackInfo.status(), + callbackInfo.handle(), + callbackInfo.valueByteArray())); } } @@ -1472,16 +1425,15 @@ public class GattService extends ProfileService { @RequiresPermission(BLUETOOTH_CONNECT) List<BluetoothDevice> getDevicesMatchingConnectionStates( - int[] states, AttributionSource attributionSource) { + int[] states, AttributionSource source) { if (!Utils.checkConnectPermissionForDataDelivery( - this, attributionSource, "GattService getDevicesMatchingConnectionStates")) { + this, source, "GattService getDevicesMatchingConnectionStates")) { return Collections.emptyList(); } Map<BluetoothDevice, Integer> deviceStates = new HashMap<>(); // Add paired LE devices - BluetoothDevice[] bondedDevices = mAdapterService.getBondedDevices(); for (BluetoothDevice device : bondedDevices) { if (getDeviceType(device) != AbstractionLayer.BT_DEVICE_TYPE_BREDR) { @@ -1490,7 +1442,6 @@ public class GattService extends ProfileService { } // Add connected deviceStates - Set<String> connectedDevices = new HashSet<>(); connectedDevices.addAll(mClientMap.getConnectedDevices()); connectedDevices.addAll(mServerMap.getConnectedDevices()); @@ -1510,25 +1461,24 @@ public class GattService extends ProfileService { } @RequiresPermission(BLUETOOTH_CONNECT) - void disconnectAll(AttributionSource attributionSource) { + void disconnectAll(AttributionSource source) { Log.d(TAG, "disconnectAll()"); Map<Integer, String> connMap = mClientMap.getConnectedMap(); for (Map.Entry<Integer, String> entry : connMap.entrySet()) { Log.d(TAG, "disconnecting addr:" + entry.getValue()); - clientDisconnect(entry.getKey(), entry.getValue(), attributionSource); + clientDisconnect(entry.getKey(), entry.getValue(), source); } } @RequiresPermission(BLUETOOTH_CONNECT) - public void unregAll(AttributionSource attributionSource) { + public void unregAll(AttributionSource source) { for (Integer appId : mClientMap.getAllAppsIds()) { Log.d(TAG, "unreg:" + appId); - unregisterClient( - appId, attributionSource, ContextMap.RemoveReason.REASON_UNREGISTER_ALL); + unregisterClient(appId, source, ContextMap.RemoveReason.REASON_UNREGISTER_ALL); } for (Integer appId : mServerMap.getAllAppsIds()) { Log.d(TAG, "unreg:" + appId); - unregisterServer(appId, attributionSource); + unregisterServer(appId, source); } } @@ -1541,24 +1491,20 @@ public class GattService extends ProfileService { UUID uuid, IBluetoothGattCallback callback, boolean eatt_support, - AttributionSource attributionSource) { + AttributionSource source) { if (!Utils.checkConnectPermissionForDataDelivery( - this, attributionSource, "GattService registerClient")) { + this, source, "GattService registerClient")) { return; } if (Flags.gattClientDynamicAllocation() && mClientMap.countByAppUid(Binder.getCallingUid()) >= GATT_CLIENT_LIMIT_PER_APP) { Log.w(TAG, "registerClient() - failed due to too many clients"); - try { - callback.onClientRegistered(BluetoothGatt.GATT_FAILURE, 0); - } catch (RemoteException e) { - // do nothing - } + callbackToApp(() -> callback.onClientRegistered(BluetoothGatt.GATT_FAILURE, 0)); return; } - String name = attributionSource.getPackageName(); - String tag = getLastAttributionTag(attributionSource); + String name = source.getPackageName(); + String tag = getLastAttributionTag(source); String myPackage = AttributionSource.myAttributionSource().getPackageName(); if (myPackage.equals(name) && tag != null) { /* For clients created by Bluetooth stack, use just tag as name */ @@ -1568,17 +1514,16 @@ public class GattService extends ProfileService { } Log.d(TAG, "registerClient() - UUID=" + uuid + " name=" + name); - mClientMap.add(uuid, callback, this, attributionSource); + mClientMap.add(uuid, callback, this, source); mNativeInterface.gattClientRegisterApp( uuid.getLeastSignificantBits(), uuid.getMostSignificantBits(), name, eatt_support); } @RequiresPermission(BLUETOOTH_CONNECT) - void unregisterClient( - int clientIf, AttributionSource attributionSource, ContextMap.RemoveReason reason) { + void unregisterClient(int clientIf, AttributionSource source, ContextMap.RemoveReason reason) { if (!Utils.checkConnectPermissionForDataDelivery( - this, attributionSource, "GattService unregisterClient")) { + this, source, "GattService unregisterClient")) { return; } @@ -1590,7 +1535,7 @@ public class GattService extends ProfileService { BluetoothStatsLog .BLUETOOTH_CROSS_LAYER_EVENT_REPORTED__EVENT_TYPE__GATT_DISCONNECT_JAVA, BluetoothStatsLog.BLUETOOTH_CROSS_LAYER_EVENT_REPORTED__STATE__END, - attributionSource.getUid()); + source.getUid()); } mClientMap.remove(clientIf, reason); mNativeInterface.gattClientUnregisterApp(clientIf); @@ -1605,16 +1550,16 @@ public class GattService extends ProfileService { int transport, boolean opportunistic, int phy, - AttributionSource attributionSource) { + AttributionSource source) { if (!Utils.checkConnectPermissionForDataDelivery( - this, attributionSource, "GattService clientConnect")) { + this, source, "GattService clientConnect")) { return; } Log.d( TAG, "clientConnect() - address=" - + BluetoothUtils.toAnonymizedAddress(address) + + toAnonymizedAddress(address) + ", addressType=" + addressType + ", isDirect=" @@ -1623,9 +1568,9 @@ public class GattService extends ProfileService { + opportunistic + ", phy=" + phy); - statsLogAppPackage(address, attributionSource.getUid(), clientIf); + statsLogAppPackage(address, source.getUid(), clientIf); - logClientForegroundInfo(attributionSource.getUid(), isDirect); + logClientForegroundInfo(source.getUid(), isDirect); statsLogGattConnectionStateChange( BluetoothProfile.GATT, @@ -1644,12 +1589,12 @@ public class GattService extends ProfileService { .BLUETOOTH_CROSS_LAYER_EVENT_REPORTED__STATE__DIRECT_CONNECT : BluetoothStatsLog .BLUETOOTH_CROSS_LAYER_EVENT_REPORTED__STATE__INDIRECT_CONNECT, - attributionSource.getUid()); + source.getUid()); int preferredMtu = 0; // Some applications expect MTU to be exchanged immediately on connections - String packageName = attributionSource.getPackageName(); + String packageName = source.getPackageName(); if (packageName != null) { for (Map.Entry<String, Integer> entry : EARLY_MTU_EXCHANGE_PACKAGES.entrySet()) { if (packageName.contains(entry.getKey())) { @@ -1666,7 +1611,7 @@ public class GattService extends ProfileService { } if (transport != BluetoothDevice.TRANSPORT_BREDR && isDirect && !opportunistic) { - String attributionTag = getLastAttributionTag(attributionSource); + String attributionTag = getLastAttributionTag(source); if (packageName != null) { for (Map.Entry<String, String> entry : GATT_CLIENTS_NOTIFY_TO_ADAPTER_PACKAGES.entrySet()) { @@ -1694,9 +1639,9 @@ public class GattService extends ProfileService { } @RequiresPermission(BLUETOOTH_CONNECT) - void clientDisconnect(int clientIf, String address, AttributionSource attributionSource) { + void clientDisconnect(int clientIf, String address, AttributionSource source) { if (!Utils.checkConnectPermissionForDataDelivery( - this, attributionSource, "GattService clientDisconnect")) { + this, source, "GattService clientDisconnect")) { return; } @@ -1704,7 +1649,7 @@ public class GattService extends ProfileService { Log.d( TAG, "clientDisconnect() - address=" - + BluetoothUtils.toAnonymizedAddress(address) + + toAnonymizedAddress(address) + ", connId=" + connId); statsLogGattConnectionStateChange( @@ -1719,7 +1664,7 @@ public class GattService extends ProfileService { BluetoothStatsLog .BLUETOOTH_CROSS_LAYER_EVENT_REPORTED__EVENT_TYPE__GATT_DISCONNECT_JAVA, BluetoothStatsLog.BLUETOOTH_CROSS_LAYER_EVENT_REPORTED__STATE__START, - attributionSource.getUid()); + source.getUid()); mAdapterService.notifyGattClientDisconnect(clientIf, getDevice(address)); @@ -1733,9 +1678,9 @@ public class GattService extends ProfileService { int txPhy, int rxPhy, int phyOptions, - AttributionSource attributionSource) { + AttributionSource source) { if (!Utils.checkConnectPermissionForDataDelivery( - this, attributionSource, "GattService clientSetPreferredPhy")) { + this, source, "GattService clientSetPreferredPhy")) { return; } @@ -1743,60 +1688,53 @@ public class GattService extends ProfileService { if (connId == null) { Log.d( TAG, - "clientSetPreferredPhy() - no connection to " - + BluetoothUtils.toAnonymizedAddress(address)); + "clientSetPreferredPhy() - no connection to " + toAnonymizedAddress(address)); return; } Log.d( TAG, "clientSetPreferredPhy() - address=" - + BluetoothUtils.toAnonymizedAddress(address) + + toAnonymizedAddress(address) + ", connId=" + connId); mNativeInterface.gattClientSetPreferredPhy(clientIf, address, txPhy, rxPhy, phyOptions); } @RequiresPermission(BLUETOOTH_CONNECT) - void clientReadPhy(int clientIf, String address, AttributionSource attributionSource) { + void clientReadPhy(int clientIf, String address, AttributionSource source) { if (!Utils.checkConnectPermissionForDataDelivery( - this, attributionSource, "GattService clientReadPhy")) { + this, source, "GattService clientReadPhy")) { return; } Integer connId = mClientMap.connIdByAddress(clientIf, address); if (connId == null) { - Log.d( - TAG, - "clientReadPhy() - no connection to " - + BluetoothUtils.toAnonymizedAddress(address)); + Log.d(TAG, "clientReadPhy() - no connection to " + toAnonymizedAddress(address)); return; } Log.d( TAG, - "clientReadPhy() - address=" - + BluetoothUtils.toAnonymizedAddress(address) - + ", connId=" - + connId); + "clientReadPhy() - address=" + toAnonymizedAddress(address) + ", connId=" + connId); mNativeInterface.gattClientReadPhy(clientIf, address); } @RequiresPermission(BLUETOOTH_CONNECT) - synchronized List<ParcelUuid> getRegisteredServiceUuids(AttributionSource attributionSource) { + synchronized List<ParcelUuid> getRegisteredServiceUuids(AttributionSource source) { if (!Utils.checkConnectPermissionForDataDelivery( - this, attributionSource, "GattService getRegisteredServiceUuids")) { + this, source, "GattService getRegisteredServiceUuids")) { return Collections.emptyList(); } return mHandleMap.getEntries().stream() - .map(entry -> new ParcelUuid(entry.uuid)) + .map(entry -> new ParcelUuid(entry.mUuid)) .collect(Collectors.toList()); } @RequiresPermission(BLUETOOTH_CONNECT) - List<String> getConnectedDevices(AttributionSource attributionSource) { + List<String> getConnectedDevices(AttributionSource source) { if (!Utils.checkConnectPermissionForDataDelivery( - this, attributionSource, "GattService getConnectedDevices")) { + this, source, "GattService getConnectedDevices")) { return Collections.emptyList(); } @@ -1808,20 +1746,20 @@ public class GattService extends ProfileService { } @RequiresPermission(BLUETOOTH_CONNECT) - void refreshDevice(int clientIf, String address, AttributionSource attributionSource) { + void refreshDevice(int clientIf, String address, AttributionSource source) { if (!Utils.checkConnectPermissionForDataDelivery( - this, attributionSource, "GattService refreshDevice")) { + this, source, "GattService refreshDevice")) { return; } - Log.d(TAG, "refreshDevice() - address=" + BluetoothUtils.toAnonymizedAddress(address)); + Log.d(TAG, "refreshDevice() - address=" + toAnonymizedAddress(address)); mNativeInterface.gattClientRefresh(clientIf, address); } @RequiresPermission(BLUETOOTH_CONNECT) - void discoverServices(int clientIf, String address, AttributionSource attributionSource) { + void discoverServices(int clientIf, String address, AttributionSource source) { if (!Utils.checkConnectPermissionForDataDelivery( - this, attributionSource, "GattService discoverServices")) { + this, source, "GattService discoverServices")) { return; } @@ -1829,7 +1767,7 @@ public class GattService extends ProfileService { Log.d( TAG, "discoverServices() - address=" - + BluetoothUtils.toAnonymizedAddress(address) + + toAnonymizedAddress(address) + ", connId=" + connId); @@ -1839,16 +1777,15 @@ public class GattService extends ProfileService { Log.e( TAG, "discoverServices() - No connection for " - + BluetoothUtils.toAnonymizedAddress(address) + + toAnonymizedAddress(address) + "..."); } } @RequiresPermission(BLUETOOTH_CONNECT) - void discoverServiceByUuid( - int clientIf, String address, UUID uuid, AttributionSource attributionSource) { + void discoverServiceByUuid(int clientIf, String address, UUID uuid, AttributionSource source) { if (!Utils.checkConnectPermissionForDataDelivery( - this, attributionSource, "GattService discoverServiceByUuid")) { + this, source, "GattService discoverServiceByUuid")) { return; } @@ -1860,31 +1797,27 @@ public class GattService extends ProfileService { Log.e( TAG, "discoverServiceByUuid() - No connection for " - + BluetoothUtils.toAnonymizedAddress(address) + + toAnonymizedAddress(address) + "..."); } } @RequiresPermission(BLUETOOTH_CONNECT) void readCharacteristic( - int clientIf, - String address, - int handle, - int authReq, - AttributionSource attributionSource) { + int clientIf, String address, int handle, int authReq, AttributionSource source) { if (!Utils.checkConnectPermissionForDataDelivery( - this, attributionSource, "GattService readCharacteristic")) { + this, source, "GattService readCharacteristic")) { return; } - Log.v(TAG, "readCharacteristic() - address=" + BluetoothUtils.toAnonymizedAddress(address)); + Log.v(TAG, "readCharacteristic() - address=" + toAnonymizedAddress(address)); Integer connId = mClientMap.connIdByAddress(clientIf, address); if (connId == null) { Log.e( TAG, "readCharacteristic() - No connection for " - + BluetoothUtils.toAnonymizedAddress(address) + + toAnonymizedAddress(address) + "..."); return; } @@ -1892,7 +1825,7 @@ public class GattService extends ProfileService { try { permissionCheck(connId, handle); } catch (SecurityException ex) { - String callingPackage = attributionSource.getPackageName(); + String callingPackage = source.getPackageName(); // Only throws on apps with target SDK T+ as this old API did not throw prior to T if (checkCallerTargetSdk(this, callingPackage, Build.VERSION_CODES.TIRAMISU)) { throw ex; @@ -1912,23 +1845,20 @@ public class GattService extends ProfileService { int startHandle, int endHandle, int authReq, - AttributionSource attributionSource) { + AttributionSource source) { if (!Utils.checkConnectPermissionForDataDelivery( - this, attributionSource, "GattService readUsingCharacteristicUuid")) { + this, source, "GattService readUsingCharacteristicUuid")) { return; } - Log.v( - TAG, - "readUsingCharacteristicUuid() - address=" - + BluetoothUtils.toAnonymizedAddress(address)); + Log.v(TAG, "readUsingCharacteristicUuid() - address=" + toAnonymizedAddress(address)); Integer connId = mClientMap.connIdByAddress(clientIf, address); if (connId == null) { Log.e( TAG, "readUsingCharacteristicUuid() - No connection for " - + BluetoothUtils.toAnonymizedAddress(address) + + toAnonymizedAddress(address) + "..."); return; } @@ -1936,7 +1866,7 @@ public class GattService extends ProfileService { try { permissionCheck(uuid); } catch (SecurityException ex) { - String callingPackage = attributionSource.getPackageName(); + String callingPackage = source.getPackageName(); // Only throws on apps with target SDK T+ as this old API did not throw prior to T if (checkCallerTargetSdk(this, callingPackage, Build.VERSION_CODES.TIRAMISU)) { throw ex; @@ -1962,15 +1892,13 @@ public class GattService extends ProfileService { int writeType, int authReq, byte[] value, - AttributionSource attributionSource) { + AttributionSource source) { if (!Utils.checkConnectPermissionForDataDelivery( - this, attributionSource, "GattService writeCharacteristic")) { + this, source, "GattService writeCharacteristic")) { return BluetoothStatusCodes.ERROR_MISSING_BLUETOOTH_CONNECT_PERMISSION; } - Log.v( - TAG, - "writeCharacteristic() - address=" + BluetoothUtils.toAnonymizedAddress(address)); + Log.v(TAG, "writeCharacteristic() - address=" + toAnonymizedAddress(address)); if (mReliableQueue.contains(address)) { writeType = 3; // Prepared write @@ -1981,7 +1909,7 @@ public class GattService extends ProfileService { Log.e( TAG, "writeCharacteristic() - No connection for " - + BluetoothUtils.toAnonymizedAddress(address) + + toAnonymizedAddress(address) + "..."); return BluetoothStatusCodes.ERROR_DEVICE_NOT_CONNECTED; } @@ -2010,32 +1938,26 @@ public class GattService extends ProfileService { @RequiresPermission(BLUETOOTH_CONNECT) void readDescriptor( - int clientIf, - String address, - int handle, - int authReq, - AttributionSource attributionSource) { + int clientIf, String address, int handle, int authReq, AttributionSource source) { if (!Utils.checkConnectPermissionForDataDelivery( - this, attributionSource, "GattService readDescriptor")) { + this, source, "GattService readDescriptor")) { return; } - Log.v(TAG, "readDescriptor() - address=" + BluetoothUtils.toAnonymizedAddress(address)); + Log.v(TAG, "readDescriptor() - address=" + toAnonymizedAddress(address)); Integer connId = mClientMap.connIdByAddress(clientIf, address); if (connId == null) { Log.e( TAG, - "readDescriptor() - No connection for " - + BluetoothUtils.toAnonymizedAddress(address) - + "..."); + "readDescriptor() - No connection for " + toAnonymizedAddress(address) + "..."); return; } try { permissionCheck(connId, handle); } catch (SecurityException ex) { - String callingPackage = attributionSource.getPackageName(); + String callingPackage = source.getPackageName(); // Only throws on apps with target SDK T+ as this old API did not throw prior to T if (checkCallerTargetSdk(this, callingPackage, Build.VERSION_CODES.TIRAMISU)) { throw ex; @@ -2054,19 +1976,19 @@ public class GattService extends ProfileService { int handle, int authReq, byte[] value, - AttributionSource attributionSource) { + AttributionSource source) { if (!Utils.checkConnectPermissionForDataDelivery( - this, attributionSource, "GattService writeDescriptor")) { + this, source, "GattService writeDescriptor")) { return BluetoothStatusCodes.ERROR_MISSING_BLUETOOTH_CONNECT_PERMISSION; } - Log.v(TAG, "writeDescriptor() - address=" + BluetoothUtils.toAnonymizedAddress(address)); + Log.v(TAG, "writeDescriptor() - address=" + toAnonymizedAddress(address)); Integer connId = mClientMap.connIdByAddress(clientIf, address); if (connId == null) { Log.e( TAG, "writeDescriptor() - No connection for " - + BluetoothUtils.toAnonymizedAddress(address) + + toAnonymizedAddress(address) + "..."); return BluetoothStatusCodes.ERROR_DEVICE_NOT_CONNECTED; } @@ -2077,28 +1999,27 @@ public class GattService extends ProfileService { } @RequiresPermission(BLUETOOTH_CONNECT) - void beginReliableWrite(int clientIf, String address, AttributionSource attributionSource) { + void beginReliableWrite(int clientIf, String address, AttributionSource source) { if (!Utils.checkConnectPermissionForDataDelivery( - this, attributionSource, "GattService beginReliableWrite")) { + this, source, "GattService beginReliableWrite")) { return; } - Log.d(TAG, "beginReliableWrite() - address=" + BluetoothUtils.toAnonymizedAddress(address)); + Log.d(TAG, "beginReliableWrite() - address=" + toAnonymizedAddress(address)); mReliableQueue.add(address); } @RequiresPermission(BLUETOOTH_CONNECT) - void endReliableWrite( - int clientIf, String address, boolean execute, AttributionSource attributionSource) { + void endReliableWrite(int clientIf, String address, boolean execute, AttributionSource source) { if (!Utils.checkConnectPermissionForDataDelivery( - this, attributionSource, "GattService endReliableWrite")) { + this, source, "GattService endReliableWrite")) { return; } Log.d( TAG, "endReliableWrite() - address=" - + BluetoothUtils.toAnonymizedAddress(address) + + toAnonymizedAddress(address) + " execute: " + execute); mReliableQueue.remove(address); @@ -2111,20 +2032,16 @@ public class GattService extends ProfileService { @RequiresPermission(BLUETOOTH_CONNECT) void registerForNotification( - int clientIf, - String address, - int handle, - boolean enable, - AttributionSource attributionSource) { + int clientIf, String address, int handle, boolean enable, AttributionSource source) { if (!Utils.checkConnectPermissionForDataDelivery( - this, attributionSource, "GattService registerForNotification")) { + this, source, "GattService registerForNotification")) { return; } Log.d( TAG, "registerForNotification() - address=" - + BluetoothUtils.toAnonymizedAddress(address) + + toAnonymizedAddress(address) + " enable: " + enable); @@ -2133,7 +2050,7 @@ public class GattService extends ProfileService { Log.e( TAG, "registerForNotification() - No connection for " - + BluetoothUtils.toAnonymizedAddress(address) + + toAnonymizedAddress(address) + "..."); return; } @@ -2141,7 +2058,7 @@ public class GattService extends ProfileService { try { permissionCheck(connId, handle); } catch (SecurityException ex) { - String callingPackage = attributionSource.getPackageName(); + String callingPackage = source.getPackageName(); // Only throws on apps with target SDK T+ as this old API did not throw prior to T if (checkCallerTargetSdk(this, callingPackage, Build.VERSION_CODES.TIRAMISU)) { throw ex; @@ -2154,77 +2071,61 @@ public class GattService extends ProfileService { } @RequiresPermission(BLUETOOTH_CONNECT) - void readRemoteRssi(int clientIf, String address, AttributionSource attributionSource) { + void readRemoteRssi(int clientIf, String address, AttributionSource source) { if (!Utils.checkConnectPermissionForDataDelivery( - this, attributionSource, "GattService readRemoteRssi")) { + this, source, "GattService readRemoteRssi")) { return; } - Log.d(TAG, "readRemoteRssi() - address=" + BluetoothUtils.toAnonymizedAddress(address)); + Log.d(TAG, "readRemoteRssi() - address=" + toAnonymizedAddress(address)); mNativeInterface.gattClientReadRemoteRssi(clientIf, address); } @RequiresPermission(BLUETOOTH_CONNECT) - void configureMTU(int clientIf, String address, int mtu, AttributionSource attributionSource) { + void configureMTU(int clientIf, String address, int mtu, AttributionSource source) { if (!Utils.checkConnectPermissionForDataDelivery( - this, attributionSource, "GattService configureMTU")) { + this, source, "GattService configureMTU")) { return; } - Log.d( - TAG, - "configureMTU() - address=" - + BluetoothUtils.toAnonymizedAddress(address) - + " mtu=" - + mtu); + Log.d(TAG, "configureMTU() - address=" + toAnonymizedAddress(address) + " mtu=" + mtu); Integer connId = mClientMap.connIdByAddress(clientIf, address); if (connId != null) { mNativeInterface.gattClientConfigureMTU(connId, mtu); } else { Log.e( TAG, - "configureMTU() - No connection for " - + BluetoothUtils.toAnonymizedAddress(address) - + "..."); + "configureMTU() - No connection for " + toAnonymizedAddress(address) + "..."); } } @RequiresPermission(BLUETOOTH_CONNECT) void connectionParameterUpdate( - int clientIf, - String address, - int connectionPriority, - AttributionSource attributionSource) { + int clientIf, String address, int connectionPriority, AttributionSource source) { if (!Utils.checkConnectPermissionForDataDelivery( - this, attributionSource, "GattService connectionParameterUpdate")) { + this, source, "GattService connectionParameterUpdate")) { return; } - int minInterval; - int maxInterval; - - // Peripheral latency - int latency; - - // Link supervision timeout is measured in N * 10ms - int timeout = 500; // 5s - CompanionManager manager = mAdapterService.getCompanionManager(); - minInterval = + int minInterval = manager.getGattConnParameters( address, CompanionManager.GATT_CONN_INTERVAL_MIN, connectionPriority); - maxInterval = + int maxInterval = manager.getGattConnParameters( address, CompanionManager.GATT_CONN_INTERVAL_MAX, connectionPriority); - latency = + // Peripheral latency + int latency = manager.getGattConnParameters( address, CompanionManager.GATT_CONN_LATENCY, connectionPriority); + int timeout = 500; // 5s. Link supervision timeout is measured in N * 10ms + Log.d( TAG, "connectionParameterUpdate() - address=" - + BluetoothUtils.toAnonymizedAddress(address) + + toAnonymizedAddress(address) + " params=" + connectionPriority + " interval=" @@ -2248,16 +2149,16 @@ public class GattService extends ProfileService { int supervisionTimeout, int minConnectionEventLen, int maxConnectionEventLen, - AttributionSource attributionSource) { + AttributionSource source) { if (!Utils.checkConnectPermissionForDataDelivery( - this, attributionSource, "GattService leConnectionUpdate")) { + this, source, "GattService leConnectionUpdate")) { return; } Log.d( TAG, "leConnectionUpdate() - address=" - + BluetoothUtils.toAnonymizedAddress(address) + + toAnonymizedAddress(address) + ", intervals=" + minInterval + "/" @@ -2288,8 +2189,7 @@ public class GattService extends ProfileService { int subrateMax; int maxLatency; int contNumber; - // Link supervision timeout is measured in N * 10ms - int supervisionTimeout = 500; // 5s + int supervisionTimeout = 500; // 5s. Link supervision timeout is measured in N * 10ms Resources res = getResources(); @@ -2339,21 +2239,20 @@ public class GattService extends ProfileService { * Callback functions - SERVER *************************************************************************/ - void onServerRegistered(int status, int serverIf, long uuidLsb, long uuidMsb) - throws RemoteException { + void onServerRegistered(int status, int serverIf, long uuidLsb, long uuidMsb) { UUID uuid = new UUID(uuidMsb, uuidLsb); Log.d(TAG, "onServerRegistered() - UUID=" + uuid + ", serverIf=" + serverIf); ContextMap<IBluetoothGattServerCallback>.App app = mServerMap.getByUuid(uuid); - if (app != null) { - app.id = serverIf; - app.linkToDeath(new ServerDeathRecipient(serverIf, app.name)); - app.callback.onServerRegistered(status, serverIf); + if (app == null) { + return; } + app.id = serverIf; + app.linkToDeath(new ServerDeathRecipient(serverIf, app.name)); + callbackToApp(() -> app.callback.onServerRegistered(status, serverIf)); } - void onServiceAdded(int status, int serverIf, List<GattDbElement> service) - throws RemoteException { + void onServiceAdded(int status, int serverIf, List<GattDbElement> service) { Log.d(TAG, "onServiceAdded(), status=" + status); if (status != 0) { @@ -2409,12 +2308,14 @@ public class GattService extends ProfileService { mHandleMap.setStarted(serverIf, srvcHandle, true); ContextMap<IBluetoothGattServerCallback>.App app = mServerMap.getById(serverIf); - if (app != null) { - app.callback.onServiceAdded(status, svc); + if (app == null) { + return; } + final BluetoothGattService serviceAdded = svc; + callbackToApp(() -> app.callback.onServiceAdded(status, serviceAdded)); } - void onServiceStopped(int status, int serverIf, int srvcHandle) throws RemoteException { + void onServiceStopped(int status, int serverIf, int srvcHandle) { Log.d(TAG, "onServiceStopped() srvcHandle=" + srvcHandle + ", status=" + status); if (status == 0) { mHandleMap.setStarted(serverIf, srvcHandle, false); @@ -2427,15 +2328,14 @@ public class GattService extends ProfileService { mHandleMap.deleteService(serverIf, srvcHandle); } - void onClientConnected(String address, boolean connected, int connId, int serverIf) - throws RemoteException { + void onClientConnected(String address, boolean connected, int connId, int serverIf) { Log.d( TAG, "onClientConnected() connId=" + connId + ", address=" - + BluetoothUtils.toAnonymizedAddress(address) + + toAnonymizedAddress(address) + ", connected=" + connected); @@ -2453,30 +2353,28 @@ public class GattService extends ProfileService { } int applicationUid = -1; - try { applicationUid = this.getPackageManager().getPackageUid(app.name, PackageInfoFlags.of(0)); - } catch (NameNotFoundException e) { Log.d(TAG, "onClientConnected() uid_not_found=" + app.name); } - app.callback.onServerConnectionState((byte) 0, serverIf, connected, address); + callbackToApp( + () -> app.callback.onServerConnectionState((byte) 0, serverIf, connected, address)); statsLogAppPackage(address, applicationUid, serverIf); statsLogGattConnectionStateChange( BluetoothProfile.GATT_SERVER, address, serverIf, connectionState, -1); } void onServerReadCharacteristic( - String address, int connId, int transId, int handle, int offset, boolean isLong) - throws RemoteException { + String address, int connId, int transId, int handle, int offset, boolean isLong) { Log.v( TAG, "onServerReadCharacteristic() connId=" + connId + ", address=" - + BluetoothUtils.toAnonymizedAddress(address) + + toAnonymizedAddress(address) + ", handle=" + handle + ", requestId=" @@ -2491,23 +2389,25 @@ public class GattService extends ProfileService { mHandleMap.addRequest(connId, transId, handle); - ContextMap<IBluetoothGattServerCallback>.App app = mServerMap.getById(entry.serverIf); + ContextMap<IBluetoothGattServerCallback>.App app = mServerMap.getById(entry.mServerIf); if (app == null) { return; } - app.callback.onCharacteristicReadRequest(address, transId, offset, isLong, handle); + callbackToApp( + () -> + app.callback.onCharacteristicReadRequest( + address, transId, offset, isLong, handle)); } void onServerReadDescriptor( - String address, int connId, int transId, int handle, int offset, boolean isLong) - throws RemoteException { + String address, int connId, int transId, int handle, int offset, boolean isLong) { Log.v( TAG, "onServerReadDescriptor() connId=" + connId + ", address=" - + BluetoothUtils.toAnonymizedAddress(address) + + toAnonymizedAddress(address) + ", handle=" + handle + ", requestId=" @@ -2522,12 +2422,15 @@ public class GattService extends ProfileService { mHandleMap.addRequest(connId, transId, handle); - ContextMap<IBluetoothGattServerCallback>.App app = mServerMap.getById(entry.serverIf); + ContextMap<IBluetoothGattServerCallback>.App app = mServerMap.getById(entry.mServerIf); if (app == null) { return; } - app.callback.onDescriptorReadRequest(address, transId, offset, isLong, handle); + callbackToApp( + () -> + app.callback.onDescriptorReadRequest( + address, transId, offset, isLong, handle)); } void onServerWriteCharacteristic( @@ -2539,14 +2442,13 @@ public class GattService extends ProfileService { int length, boolean needRsp, boolean isPrep, - byte[] data) - throws RemoteException { + byte[] data) { Log.v( TAG, "onServerWriteCharacteristic() connId=" + connId + ", address=" - + BluetoothUtils.toAnonymizedAddress(address) + + toAnonymizedAddress(address) + ", handle=" + handle + ", requestId=" @@ -2563,13 +2465,15 @@ public class GattService extends ProfileService { mHandleMap.addRequest(connId, transId, handle); - ContextMap<IBluetoothGattServerCallback>.App app = mServerMap.getById(entry.serverIf); + ContextMap<IBluetoothGattServerCallback>.App app = mServerMap.getById(entry.mServerIf); if (app == null) { return; } - app.callback.onCharacteristicWriteRequest( - address, transId, offset, length, isPrep, needRsp, handle, data); + callbackToApp( + () -> + app.callback.onCharacteristicWriteRequest( + address, transId, offset, length, isPrep, needRsp, handle, data)); } void onServerWriteDescriptor( @@ -2581,14 +2485,13 @@ public class GattService extends ProfileService { int length, boolean needRsp, boolean isPrep, - byte[] data) - throws RemoteException { + byte[] data) { Log.v( TAG, "onAttributeWrite() connId=" + connId + ", address=" - + BluetoothUtils.toAnonymizedAddress(address) + + toAnonymizedAddress(address) + ", handle=" + handle + ", requestId=" @@ -2605,23 +2508,24 @@ public class GattService extends ProfileService { mHandleMap.addRequest(connId, transId, handle); - ContextMap<IBluetoothGattServerCallback>.App app = mServerMap.getById(entry.serverIf); + ContextMap<IBluetoothGattServerCallback>.App app = mServerMap.getById(entry.mServerIf); if (app == null) { return; } - app.callback.onDescriptorWriteRequest( - address, transId, offset, length, isPrep, needRsp, handle, data); + callbackToApp( + () -> + app.callback.onDescriptorWriteRequest( + address, transId, offset, length, isPrep, needRsp, handle, data)); } - void onExecuteWrite(String address, int connId, int transId, int execWrite) - throws RemoteException { + void onExecuteWrite(String address, int connId, int transId, int execWrite) { Log.d( TAG, "onExecuteWrite() connId=" + connId + ", address=" - + BluetoothUtils.toAnonymizedAddress(address) + + toAnonymizedAddress(address) + ", transId=" + transId); @@ -2630,14 +2534,14 @@ public class GattService extends ProfileService { return; } - app.callback.onExecuteWrite(address, transId, execWrite == 1); + callbackToApp(() -> app.callback.onExecuteWrite(address, transId, execWrite == 1)); } void onResponseSendCompleted(int status, int attrHandle) { Log.d(TAG, "onResponseSendCompleted() handle=" + attrHandle); } - void onNotificationSent(int connId, int status) throws RemoteException { + void onNotificationSent(int connId, int status) { Log.v(TAG, "onNotificationSent() connId=" + connId + ", status=" + status); String address = mServerMap.addressByConnId(connId); @@ -2651,16 +2555,17 @@ public class GattService extends ProfileService { } if (!app.isCongested) { - app.callback.onNotificationSent(address, status); + callbackToApp(() -> app.callback.onNotificationSent(address, status)); } else { - if (status == BluetoothGatt.GATT_CONNECTION_CONGESTED) { - status = BluetoothGatt.GATT_SUCCESS; + int queuedStatus = status; + if (queuedStatus == BluetoothGatt.GATT_CONNECTION_CONGESTED) { + queuedStatus = BluetoothGatt.GATT_SUCCESS; } - app.queueCallback(new CallbackInfo.Builder(address, status).build()); + app.queueCallback(new CallbackInfo(address, queuedStatus)); } } - void onServerCongestion(int connId, boolean congested) throws RemoteException { + void onServerCongestion(int connId, boolean congested) { Log.d(TAG, "onServerCongestion() - connId=" + connId + ", congested=" + congested); ContextMap<IBluetoothGattServerCallback>.App app = mServerMap.getByConnId(connId); @@ -2674,11 +2579,14 @@ public class GattService extends ProfileService { if (callbackInfo == null) { return; } - app.callback.onNotificationSent(callbackInfo.address, callbackInfo.status); + callbackToApp( + () -> + app.callback.onNotificationSent( + callbackInfo.address(), callbackInfo.status())); } } - void onMtuChanged(int connId, int mtu) throws RemoteException { + void onMtuChanged(int connId, int mtu) { Log.d(TAG, "onMtuChanged() - connId=" + connId + ", mtu=" + mtu); String address = mServerMap.addressByConnId(connId); @@ -2691,7 +2599,7 @@ public class GattService extends ProfileService { return; } - app.callback.onMtuChanged(address, mtu); + callbackToApp(() -> app.callback.onMtuChanged(address, mtu)); } /************************************************************************** @@ -2703,22 +2611,22 @@ public class GattService extends ProfileService { UUID uuid, IBluetoothGattServerCallback callback, boolean eatt_support, - AttributionSource attributionSource) { + AttributionSource source) { if (!Utils.checkConnectPermissionForDataDelivery( - this, attributionSource, "GattService registerServer")) { + this, source, "GattService registerServer")) { return; } Log.d(TAG, "registerServer() - UUID=" + uuid); - mServerMap.add(uuid, callback, this, attributionSource); + mServerMap.add(uuid, callback, this, source); mNativeInterface.gattServerRegisterApp( uuid.getLeastSignificantBits(), uuid.getMostSignificantBits(), eatt_support); } @RequiresPermission(BLUETOOTH_CONNECT) - void unregisterServer(int serverIf, AttributionSource attributionSource) { + void unregisterServer(int serverIf, AttributionSource source) { if (!Utils.checkConnectPermissionForDataDelivery( - this, attributionSource, "GattService unregisterServer")) { + this, source, "GattService unregisterServer")) { return; } @@ -2737,23 +2645,23 @@ public class GattService extends ProfileService { int addressType, boolean isDirect, int transport, - AttributionSource attributionSource) { + AttributionSource source) { if (!Utils.checkConnectPermissionForDataDelivery( - this, attributionSource, "GattService serverConnect")) { + this, source, "GattService serverConnect")) { return; } - Log.d(TAG, "serverConnect() - address=" + BluetoothUtils.toAnonymizedAddress(address)); + Log.d(TAG, "serverConnect() - address=" + toAnonymizedAddress(address)); - logServerForegroundInfo(attributionSource.getUid(), isDirect); + logServerForegroundInfo(source.getUid(), isDirect); mNativeInterface.gattServerConnect(serverIf, address, addressType, isDirect, transport); } @RequiresPermission(BLUETOOTH_CONNECT) - void serverDisconnect(int serverIf, String address, AttributionSource attributionSource) { + void serverDisconnect(int serverIf, String address, AttributionSource source) { if (!Utils.checkConnectPermissionForDataDelivery( - this, attributionSource, "GattService serverDisconnect")) { + this, source, "GattService serverDisconnect")) { return; } @@ -2761,7 +2669,7 @@ public class GattService extends ProfileService { Log.d( TAG, "serverDisconnect() - address=" - + BluetoothUtils.toAnonymizedAddress(address) + + toAnonymizedAddress(address) + ", connId=" + connId); @@ -2775,9 +2683,9 @@ public class GattService extends ProfileService { int txPhy, int rxPhy, int phyOptions, - AttributionSource attributionSource) { + AttributionSource source) { if (!Utils.checkConnectPermissionForDataDelivery( - this, attributionSource, "GattService serverSetPreferredPhy")) { + this, source, "GattService serverSetPreferredPhy")) { return; } @@ -2785,50 +2693,41 @@ public class GattService extends ProfileService { if (connId == null) { Log.d( TAG, - "serverSetPreferredPhy() - no connection to " - + BluetoothUtils.toAnonymizedAddress(address)); + "serverSetPreferredPhy() - no connection to " + toAnonymizedAddress(address)); return; } Log.d( TAG, "serverSetPreferredPhy() - address=" - + BluetoothUtils.toAnonymizedAddress(address) + + toAnonymizedAddress(address) + ", connId=" + connId); mNativeInterface.gattServerSetPreferredPhy(serverIf, address, txPhy, rxPhy, phyOptions); } @RequiresPermission(BLUETOOTH_CONNECT) - void serverReadPhy(int serverIf, String address, AttributionSource attributionSource) { + void serverReadPhy(int serverIf, String address, AttributionSource source) { if (!Utils.checkConnectPermissionForDataDelivery( - this, attributionSource, "GattService serverReadPhy")) { + this, source, "GattService serverReadPhy")) { return; } Integer connId = mServerMap.connIdByAddress(serverIf, address); if (connId == null) { - Log.d( - TAG, - "serverReadPhy() - no connection to " - + BluetoothUtils.toAnonymizedAddress(address)); + Log.d(TAG, "serverReadPhy() - no connection to " + toAnonymizedAddress(address)); return; } Log.d( TAG, - "serverReadPhy() - address=" - + BluetoothUtils.toAnonymizedAddress(address) - + ", connId=" - + connId); + "serverReadPhy() - address=" + toAnonymizedAddress(address) + ", connId=" + connId); mNativeInterface.gattServerReadPhy(serverIf, address); } @RequiresPermission(BLUETOOTH_CONNECT) - void addService( - int serverIf, BluetoothGattService service, AttributionSource attributionSource) { - if (!Utils.checkConnectPermissionForDataDelivery( - this, attributionSource, "GattService addService")) { + void addService(int serverIf, BluetoothGattService service, AttributionSource source) { + if (!Utils.checkConnectPermissionForDataDelivery(this, source, "GattService addService")) { return; } @@ -2872,9 +2771,9 @@ public class GattService extends ProfileService { } @RequiresPermission(BLUETOOTH_CONNECT) - void removeService(int serverIf, int handle, AttributionSource attributionSource) { + void removeService(int serverIf, int handle, AttributionSource source) { if (!Utils.checkConnectPermissionForDataDelivery( - this, attributionSource, "GattService removeService")) { + this, source, "GattService removeService")) { return; } @@ -2884,9 +2783,9 @@ public class GattService extends ProfileService { } @RequiresPermission(BLUETOOTH_CONNECT) - void clearServices(int serverIf, AttributionSource attributionSource) { + void clearServices(int serverIf, AttributionSource source) { if (!Utils.checkConnectPermissionForDataDelivery( - this, attributionSource, "GattService clearServices")) { + this, source, "GattService clearServices")) { return; } @@ -2902,16 +2801,16 @@ public class GattService extends ProfileService { int status, int offset, byte[] value, - AttributionSource attributionSource) { + AttributionSource source) { if (!Utils.checkConnectPermissionForDataDelivery( - this, attributionSource, "GattService sendResponse")) { + this, source, "GattService sendResponse")) { return; } Log.v( TAG, "sendResponse() - address=" - + BluetoothUtils.toAnonymizedAddress(address) + + toAnonymizedAddress(address) + ", requestId=" + requestId); @@ -2921,14 +2820,14 @@ public class GattService extends ProfileService { if (!Flags.gattServerRequestsFix()) { HandleMap.Entry entry = mHandleMap.getByRequestId(requestId); if (entry != null) { - handle = entry.handle; + handle = entry.mHandle; } connId = mServerMap.connIdByAddress(serverIf, address); } else { HandleMap.RequestData requestData = mHandleMap.getRequestDataByRequestId(requestId); if (requestData != null) { - handle = requestData.mHandle; - connId = requestData.mConnId; + handle = requestData.handle(); + connId = requestData.connId(); } else { connId = mServerMap.connIdByAddress(serverIf, address); } @@ -2952,16 +2851,16 @@ public class GattService extends ProfileService { int handle, boolean confirm, byte[] value, - AttributionSource attributionSource) { + AttributionSource source) { if (!Utils.checkConnectPermissionForDataDelivery( - this, attributionSource, "GattService sendNotification")) { + this, source, "GattService sendNotification")) { return BluetoothStatusCodes.ERROR_MISSING_BLUETOOTH_CONNECT_PERMISSION; } Log.v( TAG, "sendNotification() - address=" - + BluetoothUtils.toAnonymizedAddress(address) + + toAnonymizedAddress(address) + " handle=" + handle); @@ -3090,21 +2989,22 @@ public class GattService extends ProfileService { } } - private void stopNextService(int serverIf, int status) throws RemoteException { + private void stopNextService(int serverIf, int status) { Log.d(TAG, "stopNextService() - serverIf=" + serverIf + ", status=" + status); - if (status == 0) { - List<HandleMap.Entry> entries = mHandleMap.getEntries(); - for (HandleMap.Entry entry : entries) { - if (entry.type != HandleMap.TYPE_SERVICE - || entry.serverIf != serverIf - || !entry.started) { - continue; - } - - mNativeInterface.gattServerStopService(serverIf, entry.handle); - return; + if (status != 0) { + return; + } + List<HandleMap.Entry> entries = mHandleMap.getEntries(); + for (HandleMap.Entry entry : entries) { + if (entry.mType != HandleMap.TYPE_SERVICE + || entry.mServerIf != serverIf + || !entry.mStarted) { + continue; } + + mNativeInterface.gattServerStopService(serverIf, entry.mHandle); + return; } } @@ -3118,10 +3018,10 @@ public class GattService extends ProfileService { List<Integer> handleList = new ArrayList<>(); List<HandleMap.Entry> entries = mHandleMap.getEntries(); for (HandleMap.Entry entry : entries) { - if (entry.type != HandleMap.TYPE_SERVICE || entry.serverIf != serverIf) { + if (entry.mType != HandleMap.TYPE_SERVICE || entry.mServerIf != serverIf) { continue; } - handleList.add(entry.handle); + handleList.add(entry.mHandle); } /* Now actually delete the services.... */ @@ -3183,7 +3083,7 @@ public class GattService extends ProfileService { } private void statsLogAppPackage(String address, int applicationUid, int sessionIndex) { - BluetoothDevice device = BluetoothAdapter.getDefaultAdapter().getRemoteDevice(address); + BluetoothDevice device = mAdapter.getRemoteDevice(address); BluetoothStatsLog.write( BluetoothStatsLog.BLUETOOTH_GATT_APP_INFO, sessionIndex, @@ -3203,7 +3103,7 @@ public class GattService extends ProfileService { int sessionIndex, int connectionState, int connectionStatus) { - BluetoothDevice device = BluetoothAdapter.getDefaultAdapter().getRemoteDevice(address); + BluetoothDevice device = mAdapter.getRemoteDevice(address); BluetoothStatsLog.write( BluetoothStatsLog.BLUETOOTH_CONNECTION_STATE_CHANGED, connectionState, @@ -3225,13 +3125,6 @@ public class GattService extends ProfileService { + connectionStatus); } - @Override - public void dumpProto(BluetoothMetricsProto.BluetoothLog.Builder builder) { - if (mScanController != null) { - mScanController.dumpProto(builder); - } - } - private BluetoothDevice getDevice(String address) { byte[] addressBytes = Utils.getBytesFromAddress(address); return mAdapterService.getDeviceFromByte(addressBytes); @@ -3239,13 +3132,13 @@ public class GattService extends ProfileService { private static int connectionStatusToState(int status) { return switch (status) { - // GATT_SUCCESS + // GATT_SUCCESS case 0x00 -> BluetoothStatsLog.BLUETOOTH_CROSS_LAYER_EVENT_REPORTED__STATE__SUCCESS; - // GATT_CONNECTION_TIMEOUT + // GATT_CONNECTION_TIMEOUT case 0x93 -> BluetoothStatsLog .BLUETOOTH_CROSS_LAYER_EVENT_REPORTED__STATE__CONNECTION_TIMEOUT; - // For now all other errors are bucketed together. + // For now all other errors are bucketed together. default -> BluetoothStatsLog.BLUETOOTH_CROSS_LAYER_EVENT_REPORTED__STATE__FAIL; }; } diff --git a/android/app/src/com/android/bluetooth/gatt/HandleMap.java b/android/app/src/com/android/bluetooth/gatt/HandleMap.java index 8e0ce8023e..dde3a56e1c 100644 --- a/android/app/src/com/android/bluetooth/gatt/HandleMap.java +++ b/android/app/src/com/android/bluetooth/gatt/HandleMap.java @@ -27,30 +27,38 @@ class HandleMap { private static final String TAG = GattServiceConfig.TAG_PREFIX + HandleMap.class.getSimpleName(); - public static final int TYPE_UNDEFINED = 0; - public static final int TYPE_SERVICE = 1; - public static final int TYPE_CHARACTERISTIC = 2; - public static final int TYPE_DESCRIPTOR = 3; + static final int TYPE_SERVICE = 1; + private static final int TYPE_CHARACTERISTIC = 2; + private static final int TYPE_DESCRIPTOR = 3; + + private final List<Entry> mEntries = new CopyOnWriteArrayList<>(); + private final Map<Integer, RequestData> mRequestMap = new ConcurrentHashMap<>(); + private int mLastCharacteristic = 0; + + void clear() { + mEntries.clear(); + mRequestMap.clear(); + } static class Entry { - public int serverIf = 0; - public int type = TYPE_UNDEFINED; - public int handle = 0; - public UUID uuid = null; - public int instance = 0; - public int serviceType = 0; - public int serviceHandle = 0; - public int charHandle = 0; - public boolean started = false; - public boolean advertisePreferred = false; + final int mServerIf; + final int mType; + final int mHandle; + final UUID mUuid; + int mInstance = 0; + int mServiceType = 0; + int mServiceHandle = 0; + int mCharHandle = 0; + boolean mAdvertisePreferred = false; + boolean mStarted = false; Entry(int serverIf, int handle, UUID uuid, int serviceType, int instance) { - this.serverIf = serverIf; - this.type = TYPE_SERVICE; - this.handle = handle; - this.uuid = uuid; - this.instance = instance; - this.serviceType = serviceType; + mServerIf = serverIf; + mType = TYPE_SERVICE; + mHandle = handle; + mUuid = uuid; + mInstance = instance; + mServiceType = serviceType; } Entry( @@ -60,55 +68,37 @@ class HandleMap { int serviceType, int instance, boolean advertisePreferred) { - this.serverIf = serverIf; - this.type = TYPE_SERVICE; - this.handle = handle; - this.uuid = uuid; - this.instance = instance; - this.serviceType = serviceType; - this.advertisePreferred = advertisePreferred; + mServerIf = serverIf; + mType = TYPE_SERVICE; + mHandle = handle; + mUuid = uuid; + mInstance = instance; + mServiceType = serviceType; + mAdvertisePreferred = advertisePreferred; } Entry(int serverIf, int type, int handle, UUID uuid, int serviceHandle) { - this.serverIf = serverIf; - this.type = type; - this.handle = handle; - this.uuid = uuid; - this.serviceHandle = serviceHandle; + mServerIf = serverIf; + mType = type; + mHandle = handle; + mUuid = uuid; + mServiceHandle = serviceHandle; } Entry(int serverIf, int type, int handle, UUID uuid, int serviceHandle, int charHandle) { - this.serverIf = serverIf; - this.type = type; - this.handle = handle; - this.uuid = uuid; - this.serviceHandle = serviceHandle; - this.charHandle = charHandle; - } - } - - static class RequestData { - int mConnId; - int mHandle; - - RequestData(int connId, int handle) { - mConnId = connId; + mServerIf = serverIf; + mType = type; mHandle = handle; + mUuid = uuid; + mServiceHandle = serviceHandle; + mCharHandle = charHandle; } } - List<Entry> mEntries = null; - Map<Integer, RequestData> mRequestMap = null; - int mLastCharacteristic = 0; + record RequestData(int connId, int handle) {} - HandleMap() { - mEntries = new CopyOnWriteArrayList<Entry>(); - mRequestMap = new ConcurrentHashMap<Integer, RequestData>(); - } - - void clear() { - mEntries.clear(); - mRequestMap.clear(); + List<Entry> getEntries() { + return mEntries; } void addService( @@ -139,20 +129,20 @@ class HandleMap { void setStarted(int serverIf, int handle, boolean started) { for (Entry entry : mEntries) { - if (entry.type != TYPE_SERVICE - || entry.serverIf != serverIf - || entry.handle != handle) { + if (entry.mType != TYPE_SERVICE + || entry.mServerIf != serverIf + || entry.mHandle != handle) { continue; } - entry.started = started; + entry.mStarted = started; return; } } Entry getByHandle(int handle) { for (Entry entry : mEntries) { - if (entry.handle == handle) { + if (entry.mHandle == handle) { return entry; } } @@ -162,7 +152,9 @@ class HandleMap { boolean checkServiceExists(UUID uuid, int handle) { for (Entry entry : mEntries) { - if (entry.type == TYPE_SERVICE && entry.handle == handle && entry.uuid.equals(uuid)) { + if (entry.mType == TYPE_SERVICE + && entry.mHandle == handle + && entry.mUuid.equals(uuid)) { return true; } } @@ -172,13 +164,9 @@ class HandleMap { void deleteService(int serverIf, int serviceHandle) { mEntries.removeIf( entry -> - ((entry.serverIf == serverIf) - && (entry.handle == serviceHandle - || entry.serviceHandle == serviceHandle))); - } - - List<Entry> getEntries() { - return mEntries; + ((entry.mServerIf == serverIf) + && (entry.mHandle == serviceHandle + || entry.mServiceHandle == serviceHandle))); } void addRequest(int connId, int requestId, int handle) { @@ -193,7 +181,7 @@ class HandleMap { Integer handle = null; RequestData data = mRequestMap.get(requestId); if (data != null) { - handle = data.mHandle; + handle = data.handle; } if (handle == null) { @@ -211,7 +199,7 @@ class HandleMap { Log.d( TAG, ("getRequestDataByRequestId(), requestId=" + requestId) - + (", connId=" + data.mConnId + ",handle=" + data.mHandle)); + + (", connId=" + data.connId + ",handle=" + data.handle)); } return data; @@ -223,22 +211,23 @@ class HandleMap { sb.append(" Requests: ").append(mRequestMap.size()).append("\n"); for (Entry entry : mEntries) { - sb.append(" ").append(entry.serverIf).append(": [").append(entry.handle).append("] "); - switch (entry.type) { + sb.append(" ") + .append(entry.mServerIf) + .append(": [") + .append(entry.mHandle) + .append("] "); + switch (entry.mType) { case TYPE_SERVICE: - sb.append("Service ").append(entry.uuid); - sb.append(", started ").append(entry.started); + sb.append("Service ").append(entry.mUuid); + sb.append(", started ").append(entry.mStarted); break; - case TYPE_CHARACTERISTIC: - sb.append(" Characteristic ").append(entry.uuid); + sb.append(" Characteristic ").append(entry.mUuid); break; - case TYPE_DESCRIPTOR: - sb.append(" Descriptor ").append(entry.uuid); + sb.append(" Descriptor ").append(entry.mUuid); break; } - sb.append("\n"); } } diff --git a/android/app/src/com/android/bluetooth/hap/HapClientBinder.java b/android/app/src/com/android/bluetooth/hap/HapClientBinder.java index 97bd4e9f9e..eba1d9db4a 100644 --- a/android/app/src/com/android/bluetooth/hap/HapClientBinder.java +++ b/android/app/src/com/android/bluetooth/hap/HapClientBinder.java @@ -1,5 +1,5 @@ /* - * Copyright 2024 The Android Open Source Project + * Copyright (C) 2024 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. diff --git a/android/app/src/com/android/bluetooth/hap/HapClientNativeCallback.java b/android/app/src/com/android/bluetooth/hap/HapClientNativeCallback.java index 3fef07078d..5dcc0d7ed0 100644 --- a/android/app/src/com/android/bluetooth/hap/HapClientNativeCallback.java +++ b/android/app/src/com/android/bluetooth/hap/HapClientNativeCallback.java @@ -1,5 +1,5 @@ /* - * Copyright 2024 The Android Open Source Project + * Copyright (C) 2024 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. diff --git a/android/app/src/com/android/bluetooth/hap/HapClientService.java b/android/app/src/com/android/bluetooth/hap/HapClientService.java index ae8d4b6dec..731f3da90c 100644 --- a/android/app/src/com/android/bluetooth/hap/HapClientService.java +++ b/android/app/src/com/android/bluetooth/hap/HapClientService.java @@ -25,6 +25,7 @@ import static android.bluetooth.BluetoothProfile.CONNECTION_POLICY_UNKNOWN; import static android.bluetooth.BluetoothProfile.STATE_CONNECTED; import static android.bluetooth.BluetoothProfile.STATE_CONNECTING; import static android.bluetooth.BluetoothProfile.STATE_DISCONNECTED; +import static android.bluetooth.BluetoothUtils.RemoteExceptionIgnoringConsumer; import static java.util.Objects.requireNonNull; import static java.util.Objects.requireNonNullElseGet; @@ -535,7 +536,7 @@ public class HapClientService extends ProfileService { } private void broadcastToClient( - Utils.RemoteExceptionIgnoringConsumer<IBluetoothHapClientCallback> consumer) { + RemoteExceptionIgnoringConsumer<IBluetoothHapClientCallback> consumer) { synchronized (mCallbacks) { int n = mCallbacks.beginBroadcast(); for (int i = 0; i < n; i++) { diff --git a/android/app/src/com/android/bluetooth/hearingaid/HearingAidNativeInterface.java b/android/app/src/com/android/bluetooth/hearingaid/HearingAidNativeInterface.java index 23ad690a21..31761db66d 100644 --- a/android/app/src/com/android/bluetooth/hearingaid/HearingAidNativeInterface.java +++ b/android/app/src/com/android/bluetooth/hearingaid/HearingAidNativeInterface.java @@ -1,5 +1,5 @@ /* - * Copyright 2018 The Android Open Source Project + * Copyright (C) 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. diff --git a/android/app/src/com/android/bluetooth/hearingaid/HearingAidService.java b/android/app/src/com/android/bluetooth/hearingaid/HearingAidService.java index 88f158a0ed..6af6323083 100644 --- a/android/app/src/com/android/bluetooth/hearingaid/HearingAidService.java +++ b/android/app/src/com/android/bluetooth/hearingaid/HearingAidService.java @@ -1,5 +1,5 @@ /* - * Copyright 2018 The Android Open Source Project + * Copyright (C) 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. @@ -48,11 +48,9 @@ import android.os.UserHandle; import android.sysprop.BluetoothProperties; import android.util.Log; -import com.android.bluetooth.BluetoothMetricsProto; import com.android.bluetooth.BluetoothStatsLog; import com.android.bluetooth.Utils; import com.android.bluetooth.btservice.AdapterService; -import com.android.bluetooth.btservice.MetricsLogger; import com.android.bluetooth.btservice.ProfileService; import com.android.bluetooth.btservice.storage.DatabaseManager; import com.android.bluetooth.flags.Flags; @@ -830,13 +828,6 @@ public class HearingAidService extends ProfileService { } if (toState == STATE_CONNECTED) { long myHiSyncId = getHiSyncId(device); - if (myHiSyncId == BluetoothHearingAid.HI_SYNC_ID_INVALID - || getConnectedPeerDevices(myHiSyncId).size() == 1) { - // Log hearing aid connection event if we are the first device in a set - // Or when the hiSyncId has not been found - MetricsLogger.logProfileConnectionEvent( - BluetoothMetricsProto.ProfileId.HEARING_AID); - } if (!mHiSyncIdConnectedMap.getOrDefault(myHiSyncId, false)) { mHiSyncIdConnectedMap.put(myHiSyncId, true); } diff --git a/android/app/src/com/android/bluetooth/hearingaid/HearingAidStackEvent.java b/android/app/src/com/android/bluetooth/hearingaid/HearingAidStackEvent.java index 522dedc03e..98f822d898 100644 --- a/android/app/src/com/android/bluetooth/hearingaid/HearingAidStackEvent.java +++ b/android/app/src/com/android/bluetooth/hearingaid/HearingAidStackEvent.java @@ -1,5 +1,5 @@ /* - * Copyright 2018 The Android Open Source Project + * Copyright (C) 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. diff --git a/android/app/src/com/android/bluetooth/hearingaid/HearingAidStateMachine.java b/android/app/src/com/android/bluetooth/hearingaid/HearingAidStateMachine.java index bab78a2c6a..0897cc4887 100644 --- a/android/app/src/com/android/bluetooth/hearingaid/HearingAidStateMachine.java +++ b/android/app/src/com/android/bluetooth/hearingaid/HearingAidStateMachine.java @@ -1,5 +1,5 @@ /* - * Copyright 2018 The Android Open Source Project + * Copyright (C) 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. diff --git a/android/app/src/com/android/bluetooth/hfp/HeadsetAgIndicatorEnableState.java b/android/app/src/com/android/bluetooth/hfp/HeadsetAgIndicatorEnableState.java index 27c6343032..1df40d9f02 100644 --- a/android/app/src/com/android/bluetooth/hfp/HeadsetAgIndicatorEnableState.java +++ b/android/app/src/com/android/bluetooth/hfp/HeadsetAgIndicatorEnableState.java @@ -1,5 +1,5 @@ /* - * Copyright 2018 The Android Open Source Project + * Copyright (C) 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. diff --git a/android/app/src/com/android/bluetooth/hfp/HeadsetCallState.java b/android/app/src/com/android/bluetooth/hfp/HeadsetCallState.java index a0d32c7e30..b88ce47e66 100644 --- a/android/app/src/com/android/bluetooth/hfp/HeadsetCallState.java +++ b/android/app/src/com/android/bluetooth/hfp/HeadsetCallState.java @@ -1,5 +1,5 @@ /* - * Copyright 2018 The Android Open Source Project + * Copyright (C) 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. diff --git a/android/app/src/com/android/bluetooth/hfp/HeadsetClccResponse.java b/android/app/src/com/android/bluetooth/hfp/HeadsetClccResponse.java index bd47273e63..c3e92f6c0f 100644 --- a/android/app/src/com/android/bluetooth/hfp/HeadsetClccResponse.java +++ b/android/app/src/com/android/bluetooth/hfp/HeadsetClccResponse.java @@ -1,5 +1,5 @@ /* - * Copyright 2018 The Android Open Source Project + * Copyright (C) 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. diff --git a/android/app/src/com/android/bluetooth/hfp/HeadsetDeviceState.java b/android/app/src/com/android/bluetooth/hfp/HeadsetDeviceState.java index 8f69c8cf60..395290c104 100644 --- a/android/app/src/com/android/bluetooth/hfp/HeadsetDeviceState.java +++ b/android/app/src/com/android/bluetooth/hfp/HeadsetDeviceState.java @@ -1,5 +1,5 @@ /* - * Copyright 2018 The Android Open Source Project + * Copyright (C) 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. diff --git a/android/app/src/com/android/bluetooth/hfp/HeadsetMessageObject.java b/android/app/src/com/android/bluetooth/hfp/HeadsetMessageObject.java index 3d2701a57c..ec28f5dba9 100644 --- a/android/app/src/com/android/bluetooth/hfp/HeadsetMessageObject.java +++ b/android/app/src/com/android/bluetooth/hfp/HeadsetMessageObject.java @@ -1,5 +1,5 @@ /* - * Copyright 2018 The Android Open Source Project + * Copyright (C) 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. diff --git a/android/app/src/com/android/bluetooth/hfp/HeadsetNativeInterface.java b/android/app/src/com/android/bluetooth/hfp/HeadsetNativeInterface.java index 9606d32cca..9d819eca5b 100644 --- a/android/app/src/com/android/bluetooth/hfp/HeadsetNativeInterface.java +++ b/android/app/src/com/android/bluetooth/hfp/HeadsetNativeInterface.java @@ -1,5 +1,5 @@ /* - * Copyright 2017 The Android Open Source Project + * Copyright (C) 2017 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. @@ -26,7 +26,6 @@ import com.android.bluetooth.Utils; import com.android.bluetooth.btservice.AdapterService; import com.android.bluetooth.flags.Flags; import com.android.internal.annotations.GuardedBy; -import com.android.internal.annotations.VisibleForTesting; /** * Defines native calls that are used by state machine/service to either send or receive messages @@ -64,7 +63,6 @@ public class HeadsetNativeInterface { } /** Set singleton instance. */ - @VisibleForTesting public static void setInstance(HeadsetNativeInterface instance) { synchronized (INSTANCE_LOCK) { sInstance = instance; @@ -262,14 +260,12 @@ public class HeadsetNativeInterface { * @param maxHfClients maximum number of headset clients that can be connected simultaneously * @param inbandRingingEnabled whether in-band ringing is enabled on this AG */ - @VisibleForTesting - public void init(int maxHfClients, boolean inbandRingingEnabled) { + void init(int maxHfClients, boolean inbandRingingEnabled) { initializeNative(maxHfClients, inbandRingingEnabled); } /** Closes the interface */ - @VisibleForTesting - public void cleanup() { + void cleanup() { cleanupNative(); } @@ -281,8 +277,7 @@ public class HeadsetNativeInterface { * @param errorCode error code in case of ERROR * @return True on success, False on failure */ - @VisibleForTesting - public boolean atResponseCode(BluetoothDevice device, int responseCode, int errorCode) { + boolean atResponseCode(BluetoothDevice device, int responseCode, int errorCode) { return atResponseCodeNative(responseCode, errorCode, getByteAddress(device)); } @@ -293,8 +288,7 @@ public class HeadsetNativeInterface { * @param responseString formatted AT response string * @return True on success, False on failure */ - @VisibleForTesting - public boolean atResponseString(BluetoothDevice device, String responseString) { + boolean atResponseString(BluetoothDevice device, String responseString) { return atResponseStringNative(responseString, getByteAddress(device)); } @@ -304,8 +298,7 @@ public class HeadsetNativeInterface { * @param device target headset * @return True on success, False on failure */ - @VisibleForTesting - public boolean connectHfp(BluetoothDevice device) { + boolean connectHfp(BluetoothDevice device) { return connectHfpNative(getByteAddress(device)); } @@ -315,8 +308,7 @@ public class HeadsetNativeInterface { * @param device target headset * @return True on success, False on failure */ - @VisibleForTesting - public boolean disconnectHfp(BluetoothDevice device) { + boolean disconnectHfp(BluetoothDevice device) { return disconnectHfpNative(getByteAddress(device)); } @@ -326,8 +318,7 @@ public class HeadsetNativeInterface { * @param device target headset * @return True on success, False on failure */ - @VisibleForTesting - public boolean connectAudio(BluetoothDevice device) { + boolean connectAudio(BluetoothDevice device) { return connectAudioNative(getByteAddress(device)); } @@ -337,8 +328,7 @@ public class HeadsetNativeInterface { * @param device target headset * @return True on success, False on failure */ - @VisibleForTesting - public boolean disconnectAudio(BluetoothDevice device) { + boolean disconnectAudio(BluetoothDevice device) { return disconnectAudioNative(getByteAddress(device)); } @@ -349,7 +339,7 @@ public class HeadsetNativeInterface { * @param device target headset * @return true if the device support echo cancellation or noise reduction, false otherwise */ - public boolean isNoiseReductionSupported(BluetoothDevice device) { + boolean isNoiseReductionSupported(BluetoothDevice device) { return isNoiseReductionSupportedNative(getByteAddress(device)); } @@ -359,7 +349,7 @@ public class HeadsetNativeInterface { * @param device target headset * @return true if the device supports voice recognition, false otherwise */ - public boolean isVoiceRecognitionSupported(BluetoothDevice device) { + boolean isVoiceRecognitionSupported(BluetoothDevice device) { return isVoiceRecognitionSupportedNative(getByteAddress(device)); } @@ -369,8 +359,7 @@ public class HeadsetNativeInterface { * @param device target headset * @return True on success, False on failure */ - @VisibleForTesting - public boolean startVoiceRecognition(BluetoothDevice device) { + boolean startVoiceRecognition(BluetoothDevice device) { return startVoiceRecognitionNative(getByteAddress(device)); } @@ -380,8 +369,7 @@ public class HeadsetNativeInterface { * @param device target headset * @return True on success, False on failure */ - @VisibleForTesting - public boolean stopVoiceRecognition(BluetoothDevice device) { + boolean stopVoiceRecognition(BluetoothDevice device) { return stopVoiceRecognitionNative(getByteAddress(device)); } @@ -393,8 +381,7 @@ public class HeadsetNativeInterface { * @param volume value value * @return True on success, False on failure */ - @VisibleForTesting - public boolean setVolume(BluetoothDevice device, int volumeType, int volume) { + boolean setVolume(BluetoothDevice device, int volumeType, int volume) { return setVolumeNative(volumeType, volume, getByteAddress(device)); } @@ -411,8 +398,7 @@ public class HeadsetNativeInterface { * @param batteryCharge battery charge level [0-5] * @return True on success, False on failure */ - @VisibleForTesting - public boolean cindResponse( + boolean cindResponse( BluetoothDevice device, int service, int numActive, @@ -439,8 +425,7 @@ public class HeadsetNativeInterface { * @param deviceState device status object * @return True on success, False on failure */ - @VisibleForTesting - public boolean notifyDeviceStatus(BluetoothDevice device, HeadsetDeviceState deviceState) { + boolean notifyDeviceStatus(BluetoothDevice device, HeadsetDeviceState deviceState) { return notifyDeviceStatusNative( deviceState.mService, deviceState.mRoam, @@ -468,8 +453,7 @@ public class HeadsetNativeInterface { * @param type optional * @return True on success, False on failure */ - @VisibleForTesting - public boolean clccResponse( + boolean clccResponse( BluetoothDevice device, int index, int dir, @@ -489,8 +473,7 @@ public class HeadsetNativeInterface { * @param operatorName operator name * @return True on success, False on failure */ - @VisibleForTesting - public boolean copsResponse(BluetoothDevice device, String operatorName) { + boolean copsResponse(BluetoothDevice device, String operatorName) { return copsResponseNative(operatorName, getByteAddress(device)); } @@ -503,8 +486,7 @@ public class HeadsetNativeInterface { * @param callState callState structure * @return True on success, False on failure */ - @VisibleForTesting - public boolean phoneStateChange(BluetoothDevice device, HeadsetCallState callState) { + boolean phoneStateChange(BluetoothDevice device, HeadsetCallState callState) { return phoneStateChangeNative( callState.mNumActive, callState.mNumHeld, @@ -521,8 +503,7 @@ public class HeadsetNativeInterface { * @param value True to enable, False to disable * @return True on success, False on failure */ - @VisibleForTesting - public boolean setScoAllowed(boolean value) { + boolean setScoAllowed(boolean value) { return setScoAllowedNative(value); } @@ -533,8 +514,7 @@ public class HeadsetNativeInterface { * @param value True to enable, False to disable * @return True on success, False on failure */ - @VisibleForTesting - public boolean sendBsir(BluetoothDevice device, boolean value) { + boolean sendBsir(BluetoothDevice device, boolean value) { return sendBsirNative(value, getByteAddress(device)); } @@ -544,8 +524,7 @@ public class HeadsetNativeInterface { * @param device current active SCO device * @return true on success */ - @VisibleForTesting - public boolean setActiveDevice(BluetoothDevice device) { + boolean setActiveDevice(BluetoothDevice device) { return setActiveDeviceNative(getByteAddress(device)); } diff --git a/android/app/src/com/android/bluetooth/hfp/HeadsetObjectsFactory.java b/android/app/src/com/android/bluetooth/hfp/HeadsetObjectsFactory.java index 3e2948c382..89e86e7842 100644 --- a/android/app/src/com/android/bluetooth/hfp/HeadsetObjectsFactory.java +++ b/android/app/src/com/android/bluetooth/hfp/HeadsetObjectsFactory.java @@ -1,5 +1,5 @@ /* - * Copyright 2018 The Android Open Source Project + * Copyright (C) 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. diff --git a/android/app/src/com/android/bluetooth/hfp/HeadsetService.java b/android/app/src/com/android/bluetooth/hfp/HeadsetService.java index 1116e2f9a6..251f347ea2 100644 --- a/android/app/src/com/android/bluetooth/hfp/HeadsetService.java +++ b/android/app/src/com/android/bluetooth/hfp/HeadsetService.java @@ -52,6 +52,7 @@ import android.media.AudioManager; import android.media.BluetoothProfileConnectionInfo; import android.net.Uri; import android.os.BatteryManager; +import android.os.Binder; import android.os.Handler; import android.os.HandlerThread; import android.os.Looper; @@ -61,7 +62,6 @@ import android.sysprop.BluetoothProperties; import android.telecom.PhoneAccount; import android.util.Log; -import com.android.bluetooth.BluetoothMetricsProto; import com.android.bluetooth.BluetoothStatsLog; import com.android.bluetooth.Utils; import com.android.bluetooth.a2dp.A2dpService; @@ -1132,6 +1132,11 @@ public class HeadsetService extends ProfileService { } if (!Utils.isScoManagedByAudioEnabled()) { stateMachine.sendMessage(HeadsetStateMachine.CONNECT_AUDIO, device); + logScoSessionMetric( + device, + BluetoothStatsLog + .BLUETOOTH_CROSS_LAYER_EVENT_REPORTED__STATE__SCO_CONNECT_AUDIO_START, + Binder.getCallingUid()); } } @@ -1150,9 +1155,15 @@ public class HeadsetService extends ProfileService { .getAddress())) .findFirst(); if (audioDeviceInfo.isPresent()) { + BluetoothDevice finalDevice = device; mHandler.post( () -> { am.setCommunicationDevice(audioDeviceInfo.get()); + logScoSessionMetric( + finalDevice, + BluetoothStatsLog + .BLUETOOTH_CROSS_LAYER_EVENT_REPORTED__STATE__SCO_VOICE_RECOGNITION_INITIATED_START, + Binder.getCallingUid()); Log.i(TAG, "Audio Manager will initiate the SCO for Voice Recognition"); }); } else { @@ -1199,14 +1210,25 @@ public class HeadsetService extends ProfileService { stateMachine.sendMessage(HeadsetStateMachine.VOICE_RECOGNITION_STOP, device); if (!Utils.isScoManagedByAudioEnabled()) { stateMachine.sendMessage(HeadsetStateMachine.DISCONNECT_AUDIO, device); + logScoSessionMetric( + device, + BluetoothStatsLog + .BLUETOOTH_CROSS_LAYER_EVENT_REPORTED__STATE__SCO_DISCONNECT_AUDIO_END, + Binder.getCallingUid()); } } if (Utils.isScoManagedByAudioEnabled()) { // do the task outside synchronized to avoid deadlock with Audio Fwk + BluetoothDevice finalDevice = device; mHandler.post( () -> { mSystemInterface.getAudioManager().clearCommunicationDevice(); + logScoSessionMetric( + finalDevice, + BluetoothStatsLog + .BLUETOOTH_CROSS_LAYER_EVENT_REPORTED__STATE__SCO_VOICE_RECOGNITION_INITIATED_END, + Binder.getCallingUid()); }); } enableSwbCodec(HeadsetHalConstants.BTHF_SWB_CODEC_VENDOR_APTX, false, device); @@ -1552,6 +1574,11 @@ public class HeadsetService extends ProfileService { } if (stateMachine.getAudioState() != BluetoothHeadset.STATE_AUDIO_DISCONNECTED) { logD("connectAudio: audio is not idle for device " + device); + logScoSessionMetric( + device, + BluetoothStatsLog + .BLUETOOTH_CROSS_LAYER_EVENT_REPORTED__STATE__SCO_CONNECT_AUDIO_START, + Binder.getCallingUid()); return BluetoothStatusCodes.SUCCESS; } if (isAudioOn()) { @@ -1562,6 +1589,11 @@ public class HeadsetService extends ProfileService { return BluetoothStatusCodes.ERROR_AUDIO_DEVICE_ALREADY_CONNECTED; } stateMachine.sendMessage(HeadsetStateMachine.CONNECT_AUDIO, device); + logScoSessionMetric( + device, + BluetoothStatsLog + .BLUETOOTH_CROSS_LAYER_EVENT_REPORTED__STATE__SCO_CONNECT_AUDIO_START, + Binder.getCallingUid()); } return BluetoothStatusCodes.SUCCESS; } @@ -1584,6 +1616,11 @@ public class HeadsetService extends ProfileService { for (BluetoothDevice device : getNonIdleAudioDevices()) { disconnectResult = disconnectAudio(device); if (disconnectResult == BluetoothStatusCodes.SUCCESS) { + logScoSessionMetric( + device, + BluetoothStatsLog + .BLUETOOTH_CROSS_LAYER_EVENT_REPORTED__STATE__SCO_DISCONNECT_AUDIO_END, + Binder.getCallingUid()); return disconnectResult; } else { Log.e( @@ -1674,6 +1711,11 @@ public class HeadsetService extends ProfileService { phoneStateChanged(0, 0, HeadsetHalConstants.CALL_STATE_DIALING, "", 0, "", true); phoneStateChanged(0, 0, HeadsetHalConstants.CALL_STATE_ALERTING, "", 0, "", true); phoneStateChanged(1, 0, HeadsetHalConstants.CALL_STATE_IDLE, "", 0, "", true); + logScoSessionMetric( + mActiveDevice, + BluetoothStatsLog + .BLUETOOTH_CROSS_LAYER_EVENT_REPORTED__STATE__SCO_VIRTUAL_VOICE_INITIATED_START, + Binder.getCallingUid()); return true; } } @@ -1690,6 +1732,11 @@ public class HeadsetService extends ProfileService { // 2. Send virtual phone state changed to close SCO phoneStateChanged(0, 0, HeadsetHalConstants.CALL_STATE_IDLE, "", 0, "", true); } + logScoSessionMetric( + mActiveDevice, + BluetoothStatsLog + .BLUETOOTH_CROSS_LAYER_EVENT_REPORTED__STATE__SCO_VIRTUAL_VOICE_INITIATED_END, + Binder.getCallingUid()); return true; } @@ -1797,6 +1844,11 @@ public class HeadsetService extends ProfileService { 0 /* fail */, 0, mVoiceRecognitionDevice)); + logScoSessionMetric( + mActiveDevice, + BluetoothStatsLog + .BLUETOOTH_CROSS_LAYER_EVENT_REPORTED__STATE__SCO_VOICE_RECOGNITION_HEADSET_TIMEOUT, + Binder.getCallingUid()); } } @@ -1882,6 +1934,11 @@ public class HeadsetService extends ProfileService { mSystemInterface.getVoiceRecognitionWakeLock().acquire(sStartVrTimeoutMs); } enableSwbCodec(HeadsetHalConstants.BTHF_SWB_CODEC_VENDOR_APTX, true, fromDevice); + logScoSessionMetric( + mActiveDevice, + BluetoothStatsLog + .BLUETOOTH_CROSS_LAYER_EVENT_REPORTED__STATE__SCO_VOICE_RECOGNITION_HEADSET_START, + Binder.getCallingUid()); return true; } } @@ -1934,6 +1991,11 @@ public class HeadsetService extends ProfileService { return false; } enableSwbCodec(HeadsetHalConstants.BTHF_SWB_CODEC_VENDOR_APTX, false, fromDevice); + logScoSessionMetric( + mActiveDevice, + BluetoothStatsLog + .BLUETOOTH_CROSS_LAYER_EVENT_REPORTED__STATE__SCO_VOICE_RECOGNITION_HEADSET_END, + Binder.getCallingUid()); return true; } } @@ -1985,6 +2047,11 @@ public class HeadsetService extends ProfileService { mSystemInterface.getHeadsetPhoneState().setNumActiveCall(numActive); mSystemInterface.getHeadsetPhoneState().setNumHeldCall(numHeld); mSystemInterface.getHeadsetPhoneState().setCallState(callState); + logScoSessionMetric( + mActiveDevice, + BluetoothStatsLog + .BLUETOOTH_CROSS_LAYER_EVENT_REPORTED__STATE__SCO_TELECOM_INITIATED_START, + Binder.getCallingUid()); // Suspend A2DP when call about is about to become active if (mActiveDevice != null && callState != HeadsetHalConstants.CALL_STATE_DISCONNECTED @@ -2045,6 +2112,11 @@ public class HeadsetService extends ProfileService { } } } + logScoSessionMetric( + mActiveDevice, + BluetoothStatsLog + .BLUETOOTH_CROSS_LAYER_EVENT_REPORTED__STATE__SCO_TELECOM_INITIATED_END, + Binder.getCallingUid()); } } @@ -2142,7 +2214,6 @@ public class HeadsetService extends ProfileService { BluetoothDevice device, int fromState, int toState) { if (fromState != STATE_CONNECTED && toState == STATE_CONNECTED) { updateInbandRinging(device, true); - MetricsLogger.logProfileConnectionEvent(BluetoothMetricsProto.ProfileId.HEADSET); } if (fromState != STATE_DISCONNECTED && toState == STATE_DISCONNECTED) { updateInbandRinging(device, false); @@ -2666,4 +2737,14 @@ public class HeadsetService extends ProfileService { private static void logD(String message) { Log.d(TAG, message); } + + public static void logScoSessionMetric(BluetoothDevice device, int state, int uuid) { + MetricsLogger.getInstance() + .logBluetoothEvent( + device, + BluetoothStatsLog + .BLUETOOTH_CROSS_LAYER_EVENT_REPORTED__EVENT_TYPE__SCO_SESSION, + state, + uuid); + } } diff --git a/android/app/src/com/android/bluetooth/hfp/HeadsetStackEvent.java b/android/app/src/com/android/bluetooth/hfp/HeadsetStackEvent.java index 6e669e576a..e477aa14ef 100644 --- a/android/app/src/com/android/bluetooth/hfp/HeadsetStackEvent.java +++ b/android/app/src/com/android/bluetooth/hfp/HeadsetStackEvent.java @@ -1,5 +1,5 @@ /* - * Copyright 2017 The Android Open Source Project + * Copyright (C) 2017 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. diff --git a/android/app/src/com/android/bluetooth/hfp/HeadsetStateMachine.java b/android/app/src/com/android/bluetooth/hfp/HeadsetStateMachine.java index 54709d09de..4e8e14a547 100644 --- a/android/app/src/com/android/bluetooth/hfp/HeadsetStateMachine.java +++ b/android/app/src/com/android/bluetooth/hfp/HeadsetStateMachine.java @@ -1306,6 +1306,12 @@ class HeadsetStateMachine extends StateMachine { // Reset audio disconnecting retry count. Either the disconnection was successful // or the retry count reached MAX_RETRY_DISCONNECT_AUDIO. mAudioDisconnectRetry = 0; + } else if (mPrevState == mAudioConnecting || mPrevState == mAudioOn) { + HeadsetService.logScoSessionMetric( + mDevice, + BluetoothStatsLog + .BLUETOOTH_CROSS_LAYER_EVENT_REPORTED__STATE__SCO_LINK_LOSS, + 0); } broadcastStateTransitions(); @@ -1576,6 +1582,11 @@ class HeadsetStateMachine extends StateMachine { mHeadsetService.getMainExecutor(), mAudioServerStateCallback); broadcastStateTransitions(); + HeadsetService.logScoSessionMetric( + mDevice, + BluetoothStatsLog + .BLUETOOTH_CROSS_LAYER_EVENT_REPORTED__STATE__SCO_AUDIO_CONNECTED, + 0); } @Override diff --git a/android/app/src/com/android/bluetooth/hfp/HeadsetSystemInterface.java b/android/app/src/com/android/bluetooth/hfp/HeadsetSystemInterface.java index 67967e941b..97525cc913 100644 --- a/android/app/src/com/android/bluetooth/hfp/HeadsetSystemInterface.java +++ b/android/app/src/com/android/bluetooth/hfp/HeadsetSystemInterface.java @@ -1,5 +1,5 @@ /* - * Copyright 2017 The Android Open Source Project + * Copyright (C) 2017 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. @@ -16,7 +16,6 @@ package com.android.bluetooth.hfp; - import android.bluetooth.BluetoothDevice; import android.bluetooth.BluetoothHeadset; import android.bluetooth.BluetoothSinkAudioPolicy; diff --git a/android/app/src/com/android/bluetooth/hfp/HeadsetVendorSpecificResultCode.java b/android/app/src/com/android/bluetooth/hfp/HeadsetVendorSpecificResultCode.java index 4acc211087..1c56188fd5 100644 --- a/android/app/src/com/android/bluetooth/hfp/HeadsetVendorSpecificResultCode.java +++ b/android/app/src/com/android/bluetooth/hfp/HeadsetVendorSpecificResultCode.java @@ -1,5 +1,5 @@ /* - * Copyright 2018 The Android Open Source Project + * Copyright (C) 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. diff --git a/android/app/src/com/android/bluetooth/hfpclient/HeadsetClientStateMachine.java b/android/app/src/com/android/bluetooth/hfpclient/HeadsetClientStateMachine.java index 49153659fc..23ed0b7c7d 100644 --- a/android/app/src/com/android/bluetooth/hfpclient/HeadsetClientStateMachine.java +++ b/android/app/src/com/android/bluetooth/hfpclient/HeadsetClientStateMachine.java @@ -65,7 +65,6 @@ import android.os.SystemProperties; import android.util.Log; import android.util.Pair; -import com.android.bluetooth.BluetoothMetricsProto; import com.android.bluetooth.BluetoothStatsLog; import com.android.bluetooth.R; import com.android.bluetooth.Utils; @@ -1386,8 +1385,6 @@ public class HeadsetClientStateMachine extends StateMachine { if (mHeadsetService != null) { mHeadsetService.updateInbandRinging(mCurrentDevice, true); } - MetricsLogger.logProfileConnectionEvent( - BluetoothMetricsProto.ProfileId.HEADSET_CLIENT); } else if (mPrevState != mAudioOn) { String prevStateName = mPrevState == null ? "null" : mPrevState.getName(); error( diff --git a/android/app/src/com/android/bluetooth/hfpclient/VendorCommandResponseProcessor.java b/android/app/src/com/android/bluetooth/hfpclient/VendorCommandResponseProcessor.java index 603beae96b..ebd021c9ff 100644 --- a/android/app/src/com/android/bluetooth/hfpclient/VendorCommandResponseProcessor.java +++ b/android/app/src/com/android/bluetooth/hfpclient/VendorCommandResponseProcessor.java @@ -1,5 +1,5 @@ /* - * Copyright 2019 The Android Open Source Project + * Copyright (C) 2019 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. diff --git a/android/app/src/com/android/bluetooth/hid/HidDeviceNativeInterface.java b/android/app/src/com/android/bluetooth/hid/HidDeviceNativeInterface.java index 81da626bc8..2ca9078103 100644 --- a/android/app/src/com/android/bluetooth/hid/HidDeviceNativeInterface.java +++ b/android/app/src/com/android/bluetooth/hid/HidDeviceNativeInterface.java @@ -1,5 +1,5 @@ /* - * Copyright 2017 The Android Open Source Project + * Copyright (C) 2017 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. diff --git a/android/app/src/com/android/bluetooth/hid/HidDeviceService.java b/android/app/src/com/android/bluetooth/hid/HidDeviceService.java index 6e5ea040ea..2c2f11940e 100644 --- a/android/app/src/com/android/bluetooth/hid/HidDeviceService.java +++ b/android/app/src/com/android/bluetooth/hid/HidDeviceService.java @@ -48,7 +48,6 @@ import android.os.RemoteException; import android.sysprop.BluetoothProperties; import android.util.Log; -import com.android.bluetooth.BluetoothMetricsProto; import com.android.bluetooth.Utils; import com.android.bluetooth.btservice.AdapterService; import com.android.bluetooth.btservice.MetricsLogger; @@ -888,10 +887,6 @@ public class HidDeviceService extends ProfileService { mAdapterService.updateProfileConnectionAdapterProperties( device, BluetoothProfile.HID_DEVICE, newState, prevState); - if (newState == STATE_CONNECTED) { - MetricsLogger.logProfileConnectionEvent(BluetoothMetricsProto.ProfileId.HID_DEVICE); - } - Intent intent = new Intent(BluetoothHidDevice.ACTION_CONNECTION_STATE_CHANGED); intent.putExtra(BluetoothProfile.EXTRA_PREVIOUS_STATE, prevState); intent.putExtra(BluetoothProfile.EXTRA_STATE, newState); diff --git a/android/app/src/com/android/bluetooth/hid/HidHostNativeInterface.java b/android/app/src/com/android/bluetooth/hid/HidHostNativeInterface.java index 1d0294cd52..bac98af1cc 100644 --- a/android/app/src/com/android/bluetooth/hid/HidHostNativeInterface.java +++ b/android/app/src/com/android/bluetooth/hid/HidHostNativeInterface.java @@ -1,5 +1,5 @@ /* - * Copyright 2023 The Android Open Source Project + * Copyright (C) 2023 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/android/app/src/com/android/bluetooth/hid/HidHostService.java b/android/app/src/com/android/bluetooth/hid/HidHostService.java index 2712db71ad..3a29ed5b62 100644 --- a/android/app/src/com/android/bluetooth/hid/HidHostService.java +++ b/android/app/src/com/android/bluetooth/hid/HidHostService.java @@ -46,7 +46,6 @@ import android.util.Log; import androidx.annotation.VisibleForTesting; -import com.android.bluetooth.BluetoothMetricsProto; import com.android.bluetooth.Utils; import com.android.bluetooth.btservice.AdapterService; import com.android.bluetooth.btservice.MetricsLogger; @@ -54,13 +53,12 @@ import com.android.bluetooth.btservice.ProfileService; import com.android.bluetooth.btservice.storage.DatabaseManager; import com.android.bluetooth.flags.Flags; -import com.google.common.primitives.Ints; - import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.stream.Collectors; +import java.util.stream.IntStream; /** Provides Bluetooth Hid Host profile, as a service in the Bluetooth application. */ public class HidHostService extends ProfileService { @@ -988,7 +986,7 @@ public class HidHostService extends ProfileService { List<BluetoothDevice> getDevicesMatchingConnectionStates(int[] states) { Log.d(TAG, "getDevicesMatchingConnectionStates()"); return mInputDevices.entrySet().stream() - .filter(entry -> Ints.asList(states).contains(entry.getValue().getState())) + .filter(e -> IntStream.of(states).anyMatch(x -> x == e.getValue().getState())) .map(Map.Entry::getKey) .collect(Collectors.toList()); } @@ -1297,10 +1295,6 @@ public class HidHostService extends ProfileService { return; } - if (newState == STATE_CONNECTED) { - MetricsLogger.logProfileConnectionEvent(BluetoothMetricsProto.ProfileId.HID_HOST); - } - mInputDevices.put(device, inputDevice); broadcastConnectionState(device, transport, prevState, newState); diff --git a/android/app/src/com/android/bluetooth/le_audio/LeAudioService.java b/android/app/src/com/android/bluetooth/le_audio/LeAudioService.java index 2379ffbd43..cebf4270e5 100644 --- a/android/app/src/com/android/bluetooth/le_audio/LeAudioService.java +++ b/android/app/src/com/android/bluetooth/le_audio/LeAudioService.java @@ -2531,27 +2531,21 @@ public class LeAudioService extends ProfileService { * broadcaster. */ if (isAnyBroadcastInStreamingState()) { - LeAudioGroupDescriptor fallbackGroupDescriptor = getGroupDescriptor(groupId); + Log.w(TAG, "setActiveGroupWithDevice: Setting active device while broadcasting"); // If broadcast is ongoing and need to update unicast fallback active group // we need to update the cached group id and skip changing the active device - updateFallbackUnicastGroupIdForBroadcast(groupId); + if (!leaudioBroadcastApiManagePrimaryGroup()) { + updateFallbackUnicastGroupIdForBroadcast(groupId); - if (!leaudioUseAudioRecordingListener()) { - if (fallbackGroupDescriptor != null) { - if (groupId == LE_AUDIO_GROUP_ID_INVALID) { - /* In case of removing fallback unicast group, monitoring input device - * should be removed from active devices. - */ - updateActiveDevices( - groupId, - fallbackGroupDescriptor.mDirection, - AUDIO_DIRECTION_INPUT_BIT, - false, - fallbackGroupDescriptor.mHasFallbackDeviceWhenGettingInactive, - true); - } else { - if (mActiveAudioInDevice != null) { + if (!leaudioUseAudioRecordingListener()) { + LeAudioGroupDescriptor fallbackGroupDescriptor = getGroupDescriptor(groupId); + + if (fallbackGroupDescriptor != null) { + if (groupId == LE_AUDIO_GROUP_ID_INVALID) { + /* In case of removing fallback unicast group, monitoring input device + * should be removed from active devices. + */ updateActiveDevices( groupId, fallbackGroupDescriptor.mDirection, @@ -2559,6 +2553,17 @@ public class LeAudioService extends ProfileService { false, fallbackGroupDescriptor.mHasFallbackDeviceWhenGettingInactive, true); + } else { + if (mActiveAudioInDevice != null) { + updateActiveDevices( + groupId, + fallbackGroupDescriptor.mDirection, + AUDIO_DIRECTION_INPUT_BIT, + false, + fallbackGroupDescriptor + .mHasFallbackDeviceWhenGettingInactive, + true); + } } } } @@ -4242,14 +4247,6 @@ public class LeAudioService extends ProfileService { return; } - if (deviceDescriptor.mGroupId == LE_AUDIO_GROUP_ID_INVALID - || getConnectedPeerDevices(deviceDescriptor.mGroupId).size() == 1) { - // Log LE Audio connection event if we are the first device in a set - // Or when the GroupId has not been found - // MetricsLogger.logProfileConnectionEvent( - // BluetoothMetricsProto.ProfileId.LE_AUDIO); - } - LeAudioGroupDescriptor descriptor = getGroupDescriptor(deviceDescriptor.mGroupId); if (descriptor != null) { descriptor.mIsConnected = true; diff --git a/android/app/src/com/android/bluetooth/le_audio/LeAudioTmapGattServer.java b/android/app/src/com/android/bluetooth/le_audio/LeAudioTmapGattServer.java index 9f932470fb..0d503e85d3 100644 --- a/android/app/src/com/android/bluetooth/le_audio/LeAudioTmapGattServer.java +++ b/android/app/src/com/android/bluetooth/le_audio/LeAudioTmapGattServer.java @@ -1,5 +1,5 @@ /* - * Copyright 2022 The Android Open Source Project + * Copyright (C) 2022 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. diff --git a/android/app/src/com/android/bluetooth/le_scan/AppScanStats.java b/android/app/src/com/android/bluetooth/le_scan/AppScanStats.java index fdf2f334c5..97e1f5ede5 100644 --- a/android/app/src/com/android/bluetooth/le_scan/AppScanStats.java +++ b/android/app/src/com/android/bluetooth/le_scan/AppScanStats.java @@ -16,6 +16,9 @@ package com.android.bluetooth.le_scan; +import static android.app.ActivityManager.RunningAppProcessInfo.IMPORTANCE_CACHED; +import static android.app.ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND_SERVICE; + import static java.util.Objects.requireNonNull; import static java.util.Objects.requireNonNullElseGet; @@ -27,7 +30,6 @@ import android.os.BatteryStatsManager; import android.os.Binder; import android.os.WorkSource; -import com.android.bluetooth.BluetoothMetricsProto; import com.android.bluetooth.BluetoothStatsLog; import com.android.bluetooth.Utils.TimeProvider; import com.android.bluetooth.btservice.AdapterService; @@ -44,6 +46,7 @@ import java.util.Arrays; import java.util.Date; import java.util.HashMap; import java.util.List; +import java.util.Locale; import java.util.Map; import java.util.Objects; @@ -61,9 +64,6 @@ class AppScanStats { static final int LARGE_SCAN_TIME_GAP_MS = 24000; - private static final ThreadLocal<DateFormat> DATE_FORMAT = - ThreadLocal.withInitial(() -> new SimpleDateFormat("MM-dd HH:mm:ss")); - static WorkSourceUtil sRadioScanWorkSourceUtil; static int sRadioScanType; static int sRadioScanMode; @@ -71,6 +71,8 @@ class AppScanStats { static int sRadioScanIntervalMs; static boolean sIsRadioStarted = false; static boolean sIsScreenOn = false; + static int sRadioScanAppImportance = IMPORTANCE_CACHED; + @Nullable static String sRadioScanAttributionTag; @GuardedBy("sLock") static long sRadioStartTime = 0; @@ -98,6 +100,7 @@ class AppScanStats { public final int scanCallbackType; public final StringBuilder filterString; @Nullable public final String attributionTag; + public final int appImportanceOnStart; LastScan( long timestamp, @@ -107,7 +110,8 @@ class AppScanStats { int scannerId, int scanMode, int scanCallbackType, - @Nullable String attributionTag) { + @Nullable String attributionTag, + int appImportanceOnStart) { this.duration = 0; this.timestamp = timestamp; this.reportDelayMillis = reportDelayMillis; @@ -127,8 +131,13 @@ class AppScanStats { this.suspendDuration = 0; this.suspendStartTime = 0; this.isSuspended = false; + this.appImportanceOnStart = appImportanceOnStart; this.filterString = new StringBuilder(); } + + private String getAttributionTag() { + return attributionTag != null ? attributionTag : ""; + } } private final List<LastScan> mLastScans = new ArrayList<>(); @@ -162,6 +171,7 @@ class AppScanStats { private int mBalancedScan = 0; private int mLowLatencyScan = 0; private int mAmbientDiscoveryScan = 0; + private int mAppImportance = IMPORTANCE_CACHED; private long startTime = 0; private int results = 0; @@ -189,16 +199,6 @@ class AppScanStats { return mOngoingScans.get(scannerId); } - private BluetoothMetricsProto.ScanEvent.Builder createBaseScanEvent( - BluetoothMetricsProto.ScanEvent.ScanEventType type) { - return BluetoothMetricsProto.ScanEvent.newBuilder() - .setScanEventType(type) - .setScanTechnologyType( - BluetoothMetricsProto.ScanEvent.ScanTechnologyType.SCAN_TECH_TYPE_LE) - .setEventTimeMillis(System.currentTimeMillis()) - .setInitiator(truncateAppName(mAppName)); - } - synchronized void addResult(int scannerId) { LastScan scan = getScanFromScannerId(scannerId); if (scan != null) { @@ -247,6 +247,10 @@ class AppScanStats { return scan.isAutoBatchScan; } + synchronized void setAppImportance(int importance) { + mAppImportance = importance; + } + synchronized void recordScanStart( ScanSettings settings, List<ScanFilter> filters, @@ -270,7 +274,8 @@ class AppScanStats { scannerId, settings.getScanMode(), settings.getCallbackType(), - attributionTag); + attributionTag, + mAppImportance); if (settings != null) { scan.isOpportunisticScan = scan.scanMode == ScanSettings.SCAN_MODE_OPPORTUNISTIC; scan.isBackgroundScan = @@ -305,11 +310,6 @@ class AppScanStats { } } - BluetoothMetricsProto.ScanEvent scanEvent = - createBaseScanEvent(BluetoothMetricsProto.ScanEvent.ScanEventType.SCAN_EVENT_START) - .build(); - mScanController.addScanEvent(scanEvent); - if (!isScanning()) { mScanStartTime = startTime; } @@ -349,12 +349,6 @@ class AppScanStats { } mLastScans.add(scan); - BluetoothMetricsProto.ScanEvent scanEvent = - createBaseScanEvent(BluetoothMetricsProto.ScanEvent.ScanEventType.SCAN_EVENT_STOP) - .setNumberResults(scan.results) - .build(); - mScanController.addScanEvent(scanEvent); - mTotalScanTime += scanDuration; long activeDuration = scanDuration - scan.suspendDuration; mTotalActiveTime += activeDuration; @@ -414,7 +408,9 @@ class AppScanStats { 0 /* app_scan_duration_ms */, mOngoingScans.size(), sIsScreenOn, - isAppDead); + isAppDead, + mAppImportance, + scan.getAttributionTag()); } if (scan.isAutoBatchScan) { logger.cacheCount(BluetoothProtoEnums.LE_SCAN_COUNT_AUTO_BATCH_ENABLE, 1); @@ -446,7 +442,9 @@ class AppScanStats { scan.duration, mOngoingScans.size(), sIsScreenOn, - isAppDead); + isAppDead, + mAppImportance, + scan.getAttributionTag()); } if (scan.isAutoBatchScan) { logger.cacheCount(BluetoothProtoEnums.LE_SCAN_COUNT_AUTO_BATCH_DISABLE, 1); @@ -531,7 +529,8 @@ class AppScanStats { mWorkSourceUtil.getTags(), convertScanType(getScanFromScannerId(scannerId)), BluetoothStatsLog.LE_SCAN_ABUSED__LE_SCAN_ABUSE_REASON__REASON_SCAN_TIMEOUT, - scanTimeoutMillis); + scanTimeoutMillis, + getScanFromScannerId(scannerId).getAttributionTag()); } MetricsLogger.getInstance() .cacheCount(BluetoothProtoEnums.LE_SCAN_ABUSE_COUNT_SCAN_TIMEOUT, 1); @@ -546,7 +545,8 @@ class AppScanStats { mWorkSourceUtil.getTags(), convertScanType(getScanFromScannerId(scannerId)), BluetoothStatsLog.LE_SCAN_ABUSED__LE_SCAN_ABUSE_REASON__REASON_HW_FILTER_NA, - numOfFilterSupported); + numOfFilterSupported, + getScanFromScannerId(scannerId).getAttributionTag()); } MetricsLogger.getInstance() .cacheCount(BluetoothProtoEnums.LE_SCAN_ABUSE_COUNT_HW_FILTER_NOT_AVAILABLE, 1); @@ -562,7 +562,8 @@ class AppScanStats { convertScanType(getScanFromScannerId(scannerId)), BluetoothStatsLog .LE_SCAN_ABUSED__LE_SCAN_ABUSE_REASON__REASON_TRACKING_HW_FILTER_NA, - numOfTrackableAdv); + numOfTrackableAdv, + getScanFromScannerId(scannerId).getAttributionTag()); } MetricsLogger.getInstance() .cacheCount( @@ -594,6 +595,8 @@ class AppScanStats { sRadioScanWindowMs = scanWindowMs; sRadioScanIntervalMs = scanIntervalMs; sIsRadioStarted = true; + sRadioScanAppImportance = stats.mAppImportance; + sRadioScanAttributionTag = stats.getScanFromScannerId(scannerId).getAttributionTag(); } return true; } @@ -632,7 +635,9 @@ class AppScanStats { sRadioScanIntervalMs, sRadioScanWindowMs, sIsScreenOn, - radioScanDuration); + radioScanDuration, + sRadioScanAppImportance, + getRadioScanAttributionTag()); sRadioStartTime = 0; sIsRadioStarted = false; } @@ -666,6 +671,12 @@ class AppScanStats { } } + private static String getRadioScanAttributionTag() { + synchronized (sLock) { + return sRadioScanAttributionTag != null ? sRadioScanAttributionTag : ""; + } + } + @GuardedBy("sLock") private static void recordScreenOnOffMetrics(boolean isScreenOn) { if (isScreenOn) { @@ -706,7 +717,8 @@ class AppScanStats { getRadioScanTags(), 1 /* num_results */, BluetoothStatsLog.LE_SCAN_RESULT_RECEIVED__LE_SCAN_TYPE__SCAN_TYPE_REGULAR, - sIsScreenOn); + sIsScreenOn, + getRadioScanAttributionTag()); } MetricsLogger logger = MetricsLogger.getInstance(); logger.cacheCount(BluetoothProtoEnums.LE_SCAN_RESULTS_COUNT_REGULAR, 1); @@ -730,7 +742,8 @@ class AppScanStats { getRadioScanTags(), numRecords, BluetoothStatsLog.LE_SCAN_RESULT_RECEIVED__LE_SCAN_TYPE__SCAN_TYPE_BATCH, - sIsScreenOn); + sIsScreenOn, + getRadioScanAttributionTag()); } MetricsLogger logger = MetricsLogger.getInstance(); logger.cacheCount(BluetoothProtoEnums.LE_SCAN_RESULTS_COUNT_BATCH_BUNDLE, 1); @@ -836,24 +849,6 @@ class AppScanStats { < LARGE_SCAN_TIME_GAP_MS); } - // This function truncates the app name for privacy reasons. Apps with - // four part package names or more get truncated to three parts, and apps - // with three part package names names get truncated to two. Apps with two - // or less package names names are untouched. - // Examples: one.two.three.four => one.two.three - // one.two.three => one.two - private static String truncateAppName(String name) { - String initiator = name; - String[] nameSplit = initiator.split("\\."); - if (nameSplit.length > 3) { - initiator = nameSplit[0] + "." + nameSplit[1] + "." + nameSplit[2]; - } else if (nameSplit.length == 3) { - initiator = nameSplit[0] + "." + nameSplit[1]; - } - - return initiator; - } - private static String filterToStringWithoutNullParam(ScanFilter filter) { StringBuilder filterString = new StringBuilder("BluetoothLeScanFilter ["); if (filter.getDeviceName() != null) { @@ -946,6 +941,8 @@ class AppScanStats { @SuppressWarnings("JavaUtilDate") // TODO: b/365629730 -- prefer Instant or LocalDate public synchronized void dumpToString(StringBuilder sb) { + DateFormat dateFormat = new SimpleDateFormat("MM-dd HH:mm:ss", Locale.ROOT); + long currentTime = System.currentTimeMillis(); long currTime = mTimeProvider.elapsedRealtime(); long scanDuration = 0; @@ -1053,7 +1050,7 @@ class AppScanStats { for (int i = 0; i < mLastScans.size(); i++) { LastScan scan = mLastScans.get(i); Date timestamp = new Date(currentTime - currTime + scan.timestamp); - sb.append("\n ").append(DATE_FORMAT.get().format(timestamp)).append(" - "); + sb.append("\n ").append(dateFormat.format(timestamp)).append(" - "); sb.append(scan.duration).append("ms "); if (scan.isOpportunisticScan) { sb.append("Opp "); @@ -1084,6 +1081,14 @@ class AppScanStats { } else { sb.append("Regular Scan"); } + if (scan.appImportanceOnStart < IMPORTANCE_FOREGROUND_SERVICE) { + sb.append("\n └ ") + .append("App Importance: higher than Foreground Service"); + } else if (scan.appImportanceOnStart > IMPORTANCE_FOREGROUND_SERVICE) { + sb.append("\n └ ").append("App Importance: lower than Foreground Service"); + } else { + sb.append("\n └ ").append("App Importance: Foreground Service"); + } if (scan.suspendDuration != 0) { activeDuration = scan.duration - scan.suspendDuration; sb.append("\n └ ") @@ -1108,7 +1113,7 @@ class AppScanStats { sb.append("\n Ongoing scans :"); for (LastScan scan : mOngoingScans.values()) { Date timestamp = new Date(currentTime - currTime + scan.timestamp); - sb.append("\n ").append(DATE_FORMAT.get().format(timestamp)).append(" - "); + sb.append("\n ").append(dateFormat.format(timestamp)).append(" - "); sb.append((currTime - scan.timestamp)).append("ms "); if (scan.isOpportunisticScan) { sb.append("Opp "); diff --git a/android/app/src/com/android/bluetooth/le_scan/BatchScanThrottler.java b/android/app/src/com/android/bluetooth/le_scan/BatchScanThrottler.java index 3cc06fffe4..3569745bd5 100644 --- a/android/app/src/com/android/bluetooth/le_scan/BatchScanThrottler.java +++ b/android/app/src/com/android/bluetooth/le_scan/BatchScanThrottler.java @@ -1,5 +1,5 @@ /* - * Copyright 2025 The Android Open Source Project + * Copyright (C) 2025 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/android/app/src/com/android/bluetooth/le_scan/PeriodicScanNativeInterface.java b/android/app/src/com/android/bluetooth/le_scan/PeriodicScanNativeInterface.java index 0d06dfb0cc..71558cae4c 100644 --- a/android/app/src/com/android/bluetooth/le_scan/PeriodicScanNativeInterface.java +++ b/android/app/src/com/android/bluetooth/le_scan/PeriodicScanNativeInterface.java @@ -1,5 +1,5 @@ /* - * Copyright 2023 The Android Open Source Project + * Copyright (C) 2023 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/android/app/src/com/android/bluetooth/le_scan/ScanBinder.java b/android/app/src/com/android/bluetooth/le_scan/ScanBinder.java deleted file mode 100644 index 905a8b20af..0000000000 --- a/android/app/src/com/android/bluetooth/le_scan/ScanBinder.java +++ /dev/null @@ -1,186 +0,0 @@ -/* - * Copyright (C) 2025 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.bluetooth.le_scan; - -import android.app.PendingIntent; -import android.bluetooth.BluetoothDevice; -import android.bluetooth.IBluetoothScan; -import android.bluetooth.le.IPeriodicAdvertisingCallback; -import android.bluetooth.le.IScannerCallback; -import android.bluetooth.le.ScanFilter; -import android.bluetooth.le.ScanResult; -import android.bluetooth.le.ScanSettings; -import android.content.AttributionSource; -import android.os.WorkSource; -import android.util.Log; - -import java.util.List; - -class ScanBinder extends IBluetoothScan.Stub { - private static final String TAG = ScanBinder.class.getSimpleName(); - - private ScanController mScanController; - - ScanBinder(ScanController scanController) { - mScanController = scanController; - } - - @Override - public void registerScanner( - IScannerCallback callback, WorkSource workSource, AttributionSource attributionSource) { - ScanController scanController = getScanController(); - if (scanController == null) { - return; - } - scanController.registerScanner(callback, workSource, attributionSource); - } - - @Override - public void unregisterScanner(int scannerId, AttributionSource attributionSource) { - ScanController scanController = getScanController(); - if (scanController == null) { - return; - } - scanController.unregisterScanner(scannerId, attributionSource); - } - - @Override - public void startScan( - int scannerId, - ScanSettings settings, - List<ScanFilter> filters, - AttributionSource attributionSource) { - ScanController scanController = getScanController(); - if (scanController == null) { - return; - } - scanController.startScan(scannerId, settings, filters, attributionSource); - } - - @Override - public void startScanForIntent( - PendingIntent intent, - ScanSettings settings, - List<ScanFilter> filters, - AttributionSource attributionSource) { - ScanController scanController = getScanController(); - if (scanController == null) { - return; - } - scanController.registerPiAndStartScan(intent, settings, filters, attributionSource); - } - - @Override - public void stopScan(int scannerId, AttributionSource attributionSource) { - ScanController scanController = getScanController(); - if (scanController == null) { - return; - } - scanController.stopScan(scannerId, attributionSource); - } - - @Override - public void stopScanForIntent(PendingIntent intent, AttributionSource attributionSource) { - ScanController scanController = getScanController(); - if (scanController == null) { - return; - } - scanController.stopScan(intent, attributionSource); - } - - @Override - public void flushPendingBatchResults(int scannerId, AttributionSource attributionSource) { - ScanController scanController = getScanController(); - if (scanController == null) { - return; - } - scanController.flushPendingBatchResults(scannerId, attributionSource); - } - - @Override - public void registerSync( - ScanResult scanResult, - int skip, - int timeout, - IPeriodicAdvertisingCallback callback, - AttributionSource attributionSource) { - ScanController scanController = getScanController(); - if (scanController == null) { - return; - } - scanController.registerSync(scanResult, skip, timeout, callback, attributionSource); - } - - @Override - public void unregisterSync( - IPeriodicAdvertisingCallback callback, AttributionSource attributionSource) { - ScanController scanController = getScanController(); - if (scanController == null) { - return; - } - scanController.unregisterSync(callback, attributionSource); - } - - @Override - public void transferSync( - BluetoothDevice bda, - int serviceData, - int syncHandle, - AttributionSource attributionSource) { - ScanController scanController = getScanController(); - if (scanController == null) { - return; - } - scanController.transferSync(bda, serviceData, syncHandle, attributionSource); - } - - @Override - public void transferSetInfo( - BluetoothDevice bda, - int serviceData, - int advHandle, - IPeriodicAdvertisingCallback callback, - AttributionSource attributionSource) { - ScanController scanController = getScanController(); - if (scanController == null) { - return; - } - scanController.transferSetInfo(bda, serviceData, advHandle, callback, attributionSource); - } - - @Override - public int numHwTrackFiltersAvailable(AttributionSource attributionSource) { - ScanController scanController = getScanController(); - if (scanController == null) { - return 0; - } - return scanController.numHwTrackFiltersAvailable(attributionSource); - } - - void clearScanController() { - mScanController = null; - } - - private ScanController getScanController() { - ScanController controller = mScanController; - if (controller != null && controller.isAvailable()) { - return controller; - } - Log.e(TAG, "getScanController() - ScanController requested, but not available!"); - return null; - } -} diff --git a/android/app/src/com/android/bluetooth/le_scan/ScanBinder.kt b/android/app/src/com/android/bluetooth/le_scan/ScanBinder.kt new file mode 100644 index 0000000000..bd5bd6e111 --- /dev/null +++ b/android/app/src/com/android/bluetooth/le_scan/ScanBinder.kt @@ -0,0 +1,150 @@ +/* + * Copyright (C) 2025 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.bluetooth.le_scan + +import android.app.PendingIntent +import android.bluetooth.BluetoothDevice +import android.bluetooth.IBluetoothScan +import android.bluetooth.le.IPeriodicAdvertisingCallback +import android.bluetooth.le.IScannerCallback +import android.bluetooth.le.ScanFilter +import android.bluetooth.le.ScanResult +import android.bluetooth.le.ScanSettings +import android.content.AttributionSource +import android.os.WorkSource +import android.util.Log + +class ScanBinder(private val mScanController: ScanController) : IBluetoothScan.Stub() { + + companion object { + private val TAG = ScanBinder::class.java.simpleName + } + + @Volatile private var mIsAvailable = true + + fun cleanup() { + mIsAvailable = false + } + + private fun getScanController(): ScanController? { + if (mIsAvailable) { + return mScanController + } else { + Log.e(TAG, "getScanController() - ScanController requested, but not available!") + return null + } + } + + override fun registerScanner( + callback: IScannerCallback, + workSource: WorkSource?, + source: AttributionSource, + ) { + getScanController()?.let { scanController -> + scanController.registerScanner(callback, workSource, source) + } + } + + override fun unregisterScanner(scannerId: Int, source: AttributionSource) { + getScanController()?.let { scanController -> + scanController.unregisterScanner(scannerId, source) + } + } + + override fun startScan( + scannerId: Int, + settings: ScanSettings?, + filters: List<ScanFilter>?, + source: AttributionSource, + ) { + getScanController()?.let { scanController -> + scanController.startScan(scannerId, settings, filters, source) + } + } + + override fun startScanForIntent( + intent: PendingIntent, + settings: ScanSettings?, + filters: List<ScanFilter>?, + source: AttributionSource, + ) { + getScanController()?.let { scanController -> + scanController.registerPiAndStartScan(intent, settings, filters, source) + } + } + + override fun stopScan(scannerId: Int, source: AttributionSource) { + getScanController()?.let { scanController -> scanController.stopScan(scannerId, source) } + } + + override fun stopScanForIntent(intent: PendingIntent, source: AttributionSource) { + getScanController()?.let { scanController -> scanController.stopScan(intent, source) } + } + + override fun flushPendingBatchResults(scannerId: Int, source: AttributionSource) { + getScanController()?.let { scanController -> + scanController.flushPendingBatchResults(scannerId, source) + } + } + + override fun registerSync( + scanResult: ScanResult, + skip: Int, + timeout: Int, + callback: IPeriodicAdvertisingCallback, + source: AttributionSource, + ) { + getScanController()?.let { scanController -> + scanController.registerSync(scanResult, skip, timeout, callback, source) + } + } + + override fun unregisterSync(callback: IPeriodicAdvertisingCallback, source: AttributionSource) { + getScanController()?.let { scanController -> + scanController.unregisterSync(callback, source) + } + } + + override fun transferSync( + device: BluetoothDevice, + serviceData: Int, + syncHandle: Int, + source: AttributionSource, + ) { + getScanController()?.let { scanController -> + scanController.transferSync(device, serviceData, syncHandle, source) + } + } + + override fun transferSetInfo( + device: BluetoothDevice, + serviceData: Int, + advHandle: Int, + callback: IPeriodicAdvertisingCallback, + source: AttributionSource, + ) { + getScanController()?.let { scanController -> + scanController.transferSetInfo(device, serviceData, advHandle, callback, source) + } + } + + override fun numHwTrackFiltersAvailable(source: AttributionSource): Int { + return getScanController()?.let { scanController -> + scanController.numHwTrackFiltersAvailable(source) + } ?: 0 + } +} 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 ef02cb5484..82b8e10dd7 100644 --- a/android/app/src/com/android/bluetooth/le_scan/ScanController.java +++ b/android/app/src/com/android/bluetooth/le_scan/ScanController.java @@ -60,7 +60,6 @@ import android.provider.DeviceConfig; import android.text.format.DateUtils; import android.util.Log; -import com.android.bluetooth.BluetoothMetricsProto; import com.android.bluetooth.R; import com.android.bluetooth.Utils; import com.android.bluetooth.btservice.AdapterService; @@ -71,14 +70,11 @@ import com.android.internal.annotations.VisibleForTesting; import libcore.util.HexEncoding; -import com.google.common.primitives.Bytes; import com.google.protobuf.ByteString; -import java.util.ArrayDeque; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; -import java.util.Deque; import java.util.HashMap; import java.util.HashSet; import java.util.List; @@ -97,7 +93,6 @@ public class ScanController { // Batch scan related constants. private static final int TRUNCATED_RESULT_SIZE = 11; - private static final int NUM_SCAN_EVENTS_KEPT = 20; // onFoundLost related constants @VisibleForTesting static final int ADVT_STATE_ONFOUND = 0; @@ -115,26 +110,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) { @@ -143,34 +118,24 @@ public class ScanController { } }; + private final Map<Integer, Integer> mFilterIndexToMsftAdvMonitorMap = new HashMap<>(); + private final Object mTestModeLock = new Object(); + private final BluetoothAdapter mAdapter; private final AdapterService mAdapterService; - - private final Map<Integer, Integer> mFilterIndexToMsftAdvMonitorMap = new HashMap<>(); 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 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 ScannerMap mScannerMap = new ScannerMap(); - - private boolean mIsAvailable; + private final PeriodicScanManager mPeriodicScanManager; private volatile boolean mTestModeEnabled = false; - private final Looper mMainLooper; + private ScannerMap mScannerMap = new ScannerMap(); private Handler mTestModeHandler; - private final Object mTestModeLock = new Object(); public ScanController(AdapterService adapterService) { mAdapter = BluetoothAdapter.getDefaultAdapter(); @@ -197,7 +162,6 @@ public class ScanController { }; mMainLooper = adapterService.getMainLooper(); mBinder = new ScanBinder(this); - mIsAvailable = true; mScanThread = new HandlerThread("BluetoothScanManager"); mScanThread.start(); mAppOps = mAdapterService.getSystemService(AppOpsManager.class); @@ -212,20 +176,15 @@ public class ScanController { mPeriodicScanManager = ScanObjectsFactory.getInstance().createPeriodicScanManager(); } - public void stop() { - Log.d(TAG, "stop()"); - mIsAvailable = false; - mBinder.clearScanController(); + public void cleanup() { + Log.i(TAG, "Cleanup ScanController"); + mBinder.cleanup(); mScanThread.quitSafely(); mScannerMap.clear(); mScanManager.cleanup(); mPeriodicScanManager.cleanup(); } - boolean isAvailable() { - return mIsAvailable; - } - ScannerMap getScannerMap() { return mScannerMap; } @@ -283,6 +242,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 *************************************************************************/ @@ -431,8 +410,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) { @@ -495,7 +474,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; } @@ -505,7 +484,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); @@ -874,7 +852,7 @@ public class ScanController { byte[] record = extractBytes(batchRecord, i * TRUNCATED_RESULT_SIZE, TRUNCATED_RESULT_SIZE); byte[] address = extractBytes(record, 0, 6); - Bytes.reverse(address); + Utils.reverse(address); BluetoothDevice device = mAdapter.getRemoteDevice(address); int rssi = record[8]; long timestampNanos = now - parseTimestampNanos(extractBytes(record, 9, 2)); @@ -900,7 +878,7 @@ public class ScanController { while (position < batchRecord.length) { byte[] address = extractBytes(batchRecord, position, 6); // TODO: remove temp hack. - Bytes.reverse(address); + Utils.reverse(address); BluetoothDevice device = mAdapter.getRemoteDevice(address); position += 6; // Skip address type. @@ -1098,14 +1076,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 attributionSource) { + IScannerCallback callback, WorkSource workSource, AttributionSource source) { if (!Utils.checkScanPermissionForDataDelivery( - mAdapterService, attributionSource, "ScanHelper registerScanner")) { + mAdapterService, source, "ScanController registerScanner")) { return; } @@ -1123,7 +1101,7 @@ public class ScanController { } return; } - registerScannerInternal(callback, attributionSource, workSource); + registerScannerInternal(callback, source, workSource); } /** Intended for internal use within the Bluetooth app. Bypass permission check */ @@ -1137,9 +1115,9 @@ public class ScanController { } @RequiresPermission(BLUETOOTH_SCAN) - void unregisterScanner(int scannerId, AttributionSource attributionSource) { + void unregisterScanner(int scannerId, AttributionSource source) { if (!Utils.checkScanPermissionForDataDelivery( - mAdapterService, attributionSource, "ScanHelper unregisterScanner")) { + mAdapterService, source, "ScanController unregisterScanner")) { return; } @@ -1183,16 +1161,14 @@ public class ScanController { int scannerId, ScanSettings settings, List<ScanFilter> filters, - AttributionSource attributionSource) { - Log.d(TAG, "start scan with filters"); - - if (!Utils.checkScanPermissionForDataDelivery( - mAdapterService, attributionSource, "Starting GATT scan.")) { + AttributionSource source) { + Log.d(TAG, "Start scan with filters"); + if (!Utils.checkScanPermissionForDataDelivery(mAdapterService, source, "Starting scan.")) { return; } enforcePrivilegedPermissionIfNeeded(settings); - String callingPackage = attributionSource.getPackageName(); + String callingPackage = source.getPackageName(); settings = enforceReportDelayFloor(settings); enforcePrivilegedPermissionIfNeeded(filters); final ScanClient scanClient = new ScanClient(scannerId, settings, filters); @@ -1202,8 +1178,7 @@ public class ScanController { callingPackage.equals(mExposureNotificationPackage); scanClient.mHasDisavowedLocation = - Utils.hasDisavowedLocationForScan( - mAdapterService, attributionSource, mTestModeEnabled); + Utils.hasDisavowedLocationForScan(mAdapterService, source, mTestModeEnabled); scanClient.mIsQApp = checkCallerTargetSdk(mAdapterService, callingPackage, Build.VERSION_CODES.Q); @@ -1211,11 +1186,11 @@ public class ScanController { if (scanClient.mIsQApp) { scanClient.mHasLocationPermission = Utils.checkCallerHasFineLocation( - mAdapterService, attributionSource, scanClient.mUserHandle); + mAdapterService, source, scanClient.mUserHandle); } else { scanClient.mHasLocationPermission = Utils.checkCallerHasCoarseOrFineLocation( - mAdapterService, attributionSource, scanClient.mUserHandle); + mAdapterService, source, scanClient.mUserHandle); } } scanClient.mHasNetworkSettingsPermission = @@ -1253,6 +1228,7 @@ public class ScanController { AppScanStats app = mScannerMap.getAppScanStatsById(scannerId); if (app != null) { scanClient.mStats = app; + mScanManager.fetchAppForegroundState(scanClient); boolean isFilteredScan = (filters != null) && !filters.isEmpty(); boolean isCallbackScan = false; @@ -1277,19 +1253,18 @@ public class ScanController { PendingIntent pendingIntent, ScanSettings settings, List<ScanFilter> filters, - AttributionSource attributionSource) { - Log.d(TAG, "start scan with filters, for PendingIntent"); - - if (!Utils.checkScanPermissionForDataDelivery( - mAdapterService, attributionSource, "Starting GATT scan.")) { + AttributionSource source) { + Log.d(TAG, "Start scan with filters, for PendingIntent"); + if (!Utils.checkScanPermissionForDataDelivery(mAdapterService, source, "Starting scan.")) { return; } + enforcePrivilegedPermissionIfNeeded(settings); settings = enforceReportDelayFloor(settings); enforcePrivilegedPermissionIfNeeded(filters); UUID uuid = UUID.randomUUID(); - String callingPackage = attributionSource.getPackageName(); - int callingUid = attributionSource.getUid(); + String callingPackage = source.getPackageName(); + int callingUid = source.getUid(); PendingIntentInfo piInfo = new PendingIntentInfo(pendingIntent, settings, filters, callingPackage, callingUid); Log.d( @@ -1305,8 +1280,7 @@ public class ScanController { return; } - ScannerMap.ScannerApp app = - mScannerMap.add(uuid, attributionSource, piInfo, mAdapterService, this); + ScannerMap.ScannerApp app = mScannerMap.add(uuid, source, piInfo, mAdapterService, this); app.mUserHandle = UserHandle.getUserHandleForUid(Binder.getCallingUid()); mAppOps.checkPackage(Binder.getCallingUid(), callingPackage); @@ -1314,19 +1288,18 @@ public class ScanController { callingPackage.equals(mExposureNotificationPackage); app.mHasDisavowedLocation = - Utils.hasDisavowedLocationForScan( - mAdapterService, attributionSource, mTestModeEnabled); + Utils.hasDisavowedLocationForScan(mAdapterService, source, mTestModeEnabled); if (!app.mHasDisavowedLocation) { try { if (checkCallerTargetSdk(mAdapterService, callingPackage, Build.VERSION_CODES.Q)) { app.mHasLocationPermission = Utils.checkCallerHasFineLocation( - mAdapterService, attributionSource, app.mUserHandle); + mAdapterService, source, app.mUserHandle); } else { app.mHasLocationPermission = Utils.checkCallerHasCoarseOrFineLocation( - mAdapterService, attributionSource, app.mUserHandle); + mAdapterService, source, app.mUserHandle); } } catch (SecurityException se) { // No need to throw here. Just mark as not granted. @@ -1345,7 +1318,7 @@ public class ScanController { // If this fails, we should stop the scan immediately. if (!pendingIntent.addCancelListener(Runnable::run, mScanIntentCancelListener)) { Log.d(TAG, "scanning PendingIntent is already cancelled, stopping scan."); - stopScan(pendingIntent, attributionSource); + stopScan(pendingIntent, source); } } @@ -1370,6 +1343,7 @@ public class ScanController { AppScanStats scanStats = mScannerMap.getAppScanStatsById(scannerId); if (scanStats != null) { scanClient.mStats = scanStats; + mScanManager.fetchAppForegroundState(scanClient); boolean isFilteredScan = (piInfo.filters != null) && !piInfo.filters.isEmpty(); scanStats.recordScanStart( piInfo.settings, @@ -1384,9 +1358,9 @@ public class ScanController { } @RequiresPermission(BLUETOOTH_SCAN) - void flushPendingBatchResults(int scannerId, AttributionSource attributionSource) { + void flushPendingBatchResults(int scannerId, AttributionSource source) { if (!Utils.checkScanPermissionForDataDelivery( - mAdapterService, attributionSource, "ScanHelper flushPendingBatchResults")) { + mAdapterService, source, "ScanController flushPendingBatchResults")) { return; } flushPendingBatchResultsInternal(scannerId); @@ -1398,9 +1372,9 @@ public class ScanController { } @RequiresPermission(BLUETOOTH_SCAN) - void stopScan(int scannerId, AttributionSource attributionSource) { + void stopScan(int scannerId, AttributionSource source) { if (!Utils.checkScanPermissionForDataDelivery( - mAdapterService, attributionSource, "ScanHelper stopScan")) { + mAdapterService, source, "ScanController stopScan")) { return; } stopScanInternal(scannerId); @@ -1421,9 +1395,9 @@ public class ScanController { } @RequiresPermission(BLUETOOTH_SCAN) - void stopScan(PendingIntent intent, AttributionSource attributionSource) { + void stopScan(PendingIntent intent, AttributionSource source) { if (!Utils.checkScanPermissionForDataDelivery( - mAdapterService, attributionSource, "ScanHelper stopScan")) { + mAdapterService, source, "ScanController stopScan")) { return; } stopScanInternal(intent); @@ -1451,19 +1425,18 @@ public class ScanController { int skip, int timeout, IPeriodicAdvertisingCallback callback, - AttributionSource attributionSource) { + AttributionSource source) { if (!Utils.checkScanPermissionForDataDelivery( - mAdapterService, attributionSource, "ScanHelper registerSync")) { + mAdapterService, source, "ScanController registerSync")) { return; } mPeriodicScanManager.startSync(scanResult, skip, timeout, callback); } @RequiresPermission(BLUETOOTH_SCAN) - void unregisterSync( - IPeriodicAdvertisingCallback callback, AttributionSource attributionSource) { + void unregisterSync(IPeriodicAdvertisingCallback callback, AttributionSource source) { if (!Utils.checkScanPermissionForDataDelivery( - mAdapterService, attributionSource, "ScanHelper unregisterSync")) { + mAdapterService, source, "ScanController unregisterSync")) { return; } mPeriodicScanManager.stopSync(callback); @@ -1471,12 +1444,9 @@ public class ScanController { @RequiresPermission(BLUETOOTH_SCAN) void transferSync( - BluetoothDevice bda, - int serviceData, - int syncHandle, - AttributionSource attributionSource) { + BluetoothDevice bda, int serviceData, int syncHandle, AttributionSource source) { if (!Utils.checkScanPermissionForDataDelivery( - mAdapterService, attributionSource, "ScanHelper transferSync")) { + mAdapterService, source, "ScanController transferSync")) { return; } mPeriodicScanManager.transferSync(bda, serviceData, syncHandle); @@ -1488,18 +1458,18 @@ public class ScanController { int serviceData, int advHandle, IPeriodicAdvertisingCallback callback, - AttributionSource attributionSource) { + AttributionSource source) { if (!Utils.checkScanPermissionForDataDelivery( - mAdapterService, attributionSource, "ScanHelper transferSetInfo")) { + mAdapterService, source, "ScanController transferSetInfo")) { return; } mPeriodicScanManager.transferSetInfo(bda, serviceData, advHandle, callback); } @RequiresPermission(BLUETOOTH_SCAN) - int numHwTrackFiltersAvailable(AttributionSource attributionSource) { + int numHwTrackFiltersAvailable(AttributionSource source) { if (!Utils.checkScanPermissionForDataDelivery( - mAdapterService, attributionSource, "ScanHelper numHwTrackFiltersAvailable")) { + mAdapterService, source, "ScanController numHwTrackFiltersAvailable")) { return 0; } return (mAdapterService.getTotalNumOfTrackableAdvertisements() @@ -1671,15 +1641,6 @@ public class ScanController { } } - void addScanEvent(BluetoothMetricsProto.ScanEvent event) { - synchronized (mScanEvents) { - if (mScanEvents.size() == NUM_SCAN_EVENTS_KEPT) { - mScanEvents.remove(); - } - mScanEvents.add(event); - } - } - public void dumpRegisterId(StringBuilder sb) { sb.append(" Scanner:\n"); mScannerMap.dumpApps(sb, ProfileService::println); @@ -1689,10 +1650,4 @@ public class ScanController { sb.append("GATT Scanner Map\n"); mScannerMap.dump(sb); } - - public void dumpProto(BluetoothMetricsProto.BluetoothLog.Builder builder) { - synchronized (mScanEvents) { - builder.addAllScanEvent(mScanEvents); - } - } } 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 4422a0f89e..f2e1799921 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; @@ -316,6 +314,26 @@ public class ScanManager { } } + void fetchAppForegroundState(ScanClient client) { + PackageManager packageManager = mAdapterService.getPackageManager(); + if (mActivityManager == null || packageManager == null) { + return; + } + String[] packages = packageManager.getPackagesForUid(client.mAppUid); + if (packages == null || packages.length == 0) { + return; + } + int importance = IMPORTANCE_CACHED; + for (String packageName : packages) { + importance = Math.min(importance, mActivityManager.getPackageImportance(packageName)); + } + boolean isForeground = importance <= IMPORTANCE_FOREGROUND_SERVICE; + mIsUidForegroundMap.put(client.mAppUid, isForeground); + if (client.mStats != null) { + client.mStats.setAppImportance(importance); + } + } + // Handler class that handles BLE scan operations. @VisibleForTesting class ClientHandler extends Handler { @@ -718,24 +736,6 @@ public class ScanManager { return mIsUidForegroundMap.get(client.mAppUid, DEFAULT_UID_IS_FOREGROUND); } - private void fetchAppForegroundState(ScanClient client) { - PackageManager packageManager = mAdapterService.getPackageManager(); - if (mActivityManager == null || packageManager == null) { - return; - } - String[] packages = packageManager.getPackagesForUid(client.mAppUid); - if (packages == null || packages.length == 0) { - return; - } - int importance = IMPORTANCE_CACHED; - for (String packageName : packages) { - importance = - Math.min(importance, mActivityManager.getPackageImportance(packageName)); - } - boolean isForeground = importance <= IMPORTANCE_FOREGROUND_SERVICE; - mIsUidForegroundMap.put(client.mAppUid, isForeground); - } - private boolean updateScanModeBeforeStart(ScanClient client) { if (upgradeScanModeBeforeStart(client)) { return true; @@ -827,6 +827,9 @@ public class ScanManager { if (client.mAppUid != uid || mScanNative.isOpportunisticScanClient(client)) { continue; } + if (client.mStats != null) { + client.mStats.setAppImportance(importance); + } if (isForeground) { int scanMode = client.mScanModeApp; int maxScanMode = @@ -1292,7 +1295,7 @@ public class ScanManager { if (!Flags.bleScanAdvMetricsRedesign()) { if (client.mStats != null && !AppScanStats.recordScanRadioStart( - client.mSettings.getScanMode(), + client.mScanModeApp, client.mScannerId, client.mStats, getScanWindowMillis(client.mSettings), @@ -1624,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/le_scan/ScanObjectsFactory.java b/android/app/src/com/android/bluetooth/le_scan/ScanObjectsFactory.java index cca760249f..c7f3605588 100644 --- a/android/app/src/com/android/bluetooth/le_scan/ScanObjectsFactory.java +++ b/android/app/src/com/android/bluetooth/le_scan/ScanObjectsFactory.java @@ -1,5 +1,5 @@ /* - * Copyright 2024 The Android Open Source Project + * Copyright (C) 2024 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. diff --git a/android/app/src/com/android/bluetooth/le_scan/ScannerMap.java b/android/app/src/com/android/bluetooth/le_scan/ScannerMap.java index 30a7d0ffd8..eebce7c9cf 100644 --- a/android/app/src/com/android/bluetooth/le_scan/ScannerMap.java +++ b/android/app/src/com/android/bluetooth/le_scan/ScannerMap.java @@ -54,34 +54,27 @@ public class ScannerMap { /** Add an entry to the application context list with a callback. */ ScannerApp add( UUID uuid, - AttributionSource attributionSource, + AttributionSource source, WorkSource workSource, IScannerCallback callback, AdapterService adapterService, ScanController scanController) { - return add( - uuid, - attributionSource, - workSource, - callback, - null, - adapterService, - scanController); + return add(uuid, source, workSource, callback, null, adapterService, scanController); } /** Add an entry to the application context list with a pending intent. */ ScannerApp add( UUID uuid, - AttributionSource attributionSource, + AttributionSource source, ScanController.PendingIntentInfo piInfo, AdapterService adapterService, ScanController scanController) { - return add(uuid, attributionSource, null, null, piInfo, adapterService, scanController); + return add(uuid, source, null, null, piInfo, adapterService, scanController); } private ScannerApp add( UUID uuid, - AttributionSource attributionSource, + AttributionSource source, @Nullable WorkSource workSource, @Nullable IScannerCallback callback, @Nullable ScanController.PendingIntentInfo piInfo, @@ -115,7 +108,7 @@ public class ScannerMap { ScannerApp app = new ScannerApp( uuid, - getLastAttributionTag(attributionSource), + getLastAttributionTag(source), callback, piInfo, appName, diff --git a/android/app/src/com/android/bluetooth/map/BluetoothMapAppParams.java b/android/app/src/com/android/bluetooth/map/BluetoothMapAppParams.java index 0ad7618e24..ea34b20875 100644 --- a/android/app/src/com/android/bluetooth/map/BluetoothMapAppParams.java +++ b/android/app/src/com/android/bluetooth/map/BluetoothMapAppParams.java @@ -29,6 +29,7 @@ import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Arrays; import java.util.Date; +import java.util.Locale; /** This class encapsulates the appParams needed for MAP. */ // Next tag value for ContentProfileErrorReportUtils.report(): 41 @@ -188,14 +189,14 @@ public class BluetoothMapAppParams { /** * Creates an application parameter object based on a application parameter OBEX header. The - * content of the {@link appParam} byte array will be parsed, and its content will be stored in + * content of the {@code appParams} byte array will be parsed, and its content will be stored in * the member variables. {@link INVALID_VALUE_PARAMETER} can be used to determine if a value is - * set or not, where strings will be empty, if {@link appParam} did not contain the parameter. + * set or not, where strings will be empty, if {@code appParams} did not contain the parameter. * * @param appParams the byte array containing the application parameters OBEX header * @throws IllegalArgumentException when a parameter does not respect the valid ranges specified * in the MAP spec. - * @throws ParseException if a parameter string if formated incorrectly. + * @throws ParseException if a parameter string if formatted incorrectly. */ public BluetoothMapAppParams(final byte[] appParams) throws IllegalArgumentException, ParseException { @@ -208,7 +209,7 @@ public class BluetoothMapAppParams { * @param appParams the byte array containing the application parameters OBEX header * @throws IllegalArgumentException when a parameter does not respect the valid ranges specified * in the MAP spec. - * @throws ParseException if a parameter string if formated incorrectly. + * @throws ParseException if a parameter string if formatted incorrectly. */ private void parseParams(final byte[] appParams) throws ParseException, IllegalArgumentException { @@ -1137,8 +1138,8 @@ public class BluetoothMapAppParams { if (getFilterConvoId() != null) { appParamBuf.put((byte) FILTER_CONVO_ID); appParamBuf.put((byte) FILTER_CONVO_ID_LEN); - appParamBuf.putLong(getFilterConvoId().getMostSignificantBits()); - appParamBuf.putLong(getFilterConvoId().getLeastSignificantBits()); + appParamBuf.putLong(getFilterConvoId().mostSignificantBits()); + appParamBuf.putLong(getFilterConvoId().leastSignificantBits()); } if (getConvoListingSize() != INVALID_VALUE_PARAMETER) { appParamBuf.put((byte) CONVO_LISTING_SIZE); @@ -1158,8 +1159,8 @@ public class BluetoothMapAppParams { if (getChatStateConvoId() != null) { appParamBuf.put((byte) CHAT_STATE_CONVO_ID); appParamBuf.put((byte) CHAT_STATE_CONVO_ID_LEN); - appParamBuf.putLong(getChatStateConvoId().getMostSignificantBits()); - appParamBuf.putLong(getChatStateConvoId().getLeastSignificantBits()); + appParamBuf.putLong(getChatStateConvoId().mostSignificantBits()); + appParamBuf.putLong(getChatStateConvoId().leastSignificantBits()); } if (getFolderVerCounter() != null) { appParamBuf.put((byte) FOLDER_VER_COUNTER); @@ -1225,7 +1226,7 @@ public class BluetoothMapAppParams { @SuppressWarnings("JavaUtilDate") // TODO: b/365629730 -- prefer Instant or LocalDate public String getFilterPeriodBeginString() { - SimpleDateFormat format = new SimpleDateFormat("yyyyMMdd'T'HHmmss"); + SimpleDateFormat format = new SimpleDateFormat("yyyyMMdd'T'HHmmss", Locale.ROOT); Date date = new Date(mFilterPeriodBegin); return format.format(date); // Format to YYYYMMDDTHHMMSS local time } @@ -1236,7 +1237,7 @@ public class BluetoothMapAppParams { @SuppressWarnings("JavaUtilDate") // TODO: b/365629730 -- prefer Instant or LocalDate public void setFilterPeriodBegin(String filterPeriodBegin) throws ParseException { - SimpleDateFormat format = new SimpleDateFormat("yyyyMMdd'T'HHmmss"); + SimpleDateFormat format = new SimpleDateFormat("yyyyMMdd'T'HHmmss", Locale.ROOT); Date date = format.parse(filterPeriodBegin); this.mFilterPeriodBegin = date.getTime(); } @@ -1247,7 +1248,7 @@ public class BluetoothMapAppParams { @SuppressWarnings("JavaUtilDate") // TODO: b/365629730 -- prefer Instant or LocalDate public String getFilterLastActivityBeginString() { - SimpleDateFormat format = new SimpleDateFormat("yyyyMMdd'T'HHmmss"); + SimpleDateFormat format = new SimpleDateFormat("yyyyMMdd'T'HHmmss", Locale.ROOT); Date date = new Date(mFilterPeriodBegin); return format.format(date); // Format to YYYYMMDDTHHMMSS local time } @@ -1258,7 +1259,7 @@ public class BluetoothMapAppParams { @SuppressWarnings("JavaUtilDate") // TODO: b/365629730 -- prefer Instant or LocalDate public void setFilterLastActivityBegin(String filterPeriodBegin) throws ParseException { - SimpleDateFormat format = new SimpleDateFormat("yyyyMMdd'T'HHmmss"); + SimpleDateFormat format = new SimpleDateFormat("yyyyMMdd'T'HHmmss", Locale.ROOT); Date date = format.parse(filterPeriodBegin); this.mFilterPeriodBegin = date.getTime(); } @@ -1273,7 +1274,7 @@ public class BluetoothMapAppParams { @SuppressWarnings("JavaUtilDate") // TODO: b/365629730 -- prefer Instant or LocalDate public String getFilterLastActivityEndString() { - SimpleDateFormat format = new SimpleDateFormat("yyyyMMdd'T'HHmmss"); + SimpleDateFormat format = new SimpleDateFormat("yyyyMMdd'T'HHmmss", Locale.ROOT); Date date = new Date(mFilterPeriodEnd); return format.format(date); // Format to YYYYMMDDTHHMMSS local time } @@ -1284,14 +1285,14 @@ public class BluetoothMapAppParams { @SuppressWarnings("JavaUtilDate") // TODO: b/365629730 -- prefer Instant or LocalDate public void setFilterPeriodEnd(String filterPeriodEnd) throws ParseException { - SimpleDateFormat format = new SimpleDateFormat("yyyyMMdd'T'HHmmss"); + SimpleDateFormat format = new SimpleDateFormat("yyyyMMdd'T'HHmmss", Locale.ROOT); Date date = format.parse(filterPeriodEnd); this.mFilterPeriodEnd = date.getTime(); } @SuppressWarnings("JavaUtilDate") // TODO: b/365629730 -- prefer Instant or LocalDate public String getFilterPeriodEndString() { - SimpleDateFormat format = new SimpleDateFormat("yyyyMMdd'T'HHmmss"); + SimpleDateFormat format = new SimpleDateFormat("yyyyMMdd'T'HHmmss", Locale.ROOT); Date date = new Date(mFilterPeriodEnd); return format.format(date); // Format to YYYYMMDDTHHMMSS local time } @@ -1302,7 +1303,7 @@ public class BluetoothMapAppParams { @SuppressWarnings("JavaUtilDate") // TODO: b/365629730 -- prefer Instant or LocalDate public void setFilterLastActivityEnd(String filterPeriodEnd) throws ParseException { - SimpleDateFormat format = new SimpleDateFormat("yyyyMMdd'T'HHmmss"); + SimpleDateFormat format = new SimpleDateFormat("yyyyMMdd'T'HHmmss", Locale.ROOT); Date date = format.parse(filterPeriodEnd); this.mFilterPeriodEnd = date.getTime(); } @@ -1403,8 +1404,8 @@ public class BluetoothMapAppParams { public byte[] getChatStateConvoIdByteArray() { if (mChatStateConvoId != null) { ByteBuffer ret = ByteBuffer.allocate(16); - ret.putLong(mChatStateConvoId.getMostSignificantBits()); - ret.putLong(mChatStateConvoId.getLeastSignificantBits()); + ret.putLong(mChatStateConvoId.mostSignificantBits()); + ret.putLong(mChatStateConvoId.leastSignificantBits()); return ret.array(); } else { return null; @@ -1472,7 +1473,7 @@ public class BluetoothMapAppParams { public String getFilterConvoIdString() { String str = null; if (mFilterConvoId != null) { - str = BluetoothMapUtils.getLongAsString(mFilterConvoId.getLeastSignificantBits()); + str = BluetoothMapUtils.getLongAsString(mFilterConvoId.leastSignificantBits()); } return str; } @@ -1507,7 +1508,7 @@ public class BluetoothMapAppParams { @SuppressWarnings("JavaUtilDate") // TODO: b/365629730 -- prefer Instant or LocalDate public String getLastActivityString() { - SimpleDateFormat format = new SimpleDateFormat("yyyyMMdd'T'HHmmssZ"); + SimpleDateFormat format = new SimpleDateFormat("yyyyMMdd'T'HHmmssZ", Locale.ROOT); Date date = new Date(mLastActivity); return format.format(date); // Format to YYYYMMDDTHHMMSS local time } @@ -1518,7 +1519,7 @@ public class BluetoothMapAppParams { @SuppressWarnings("JavaUtilDate") // TODO: b/365629730 -- prefer Instant or LocalDate public void setLastActivity(String lastActivity) throws ParseException { - SimpleDateFormat format = new SimpleDateFormat("yyyyMMdd'T'HHmmssZ"); + SimpleDateFormat format = new SimpleDateFormat("yyyyMMdd'T'HHmmssZ", Locale.ROOT); Date date = format.parse(lastActivity); this.mLastActivity = date.getTime(); } @@ -1755,7 +1756,7 @@ public class BluetoothMapAppParams { @SuppressWarnings("JavaUtilDate") // TODO: b/365629730 -- prefer Instant or LocalDate public String getMseTimeString() { - SimpleDateFormat format = new SimpleDateFormat("yyyyMMdd'T'HHmmssZ"); + SimpleDateFormat format = new SimpleDateFormat("yyyyMMdd'T'HHmmssZ", Locale.ROOT); Date date = new Date(getMseTime()); return format.format(date); // Format to YYYYMMDDTHHMMSS±hhmm UTC time ± offset } @@ -1766,7 +1767,7 @@ public class BluetoothMapAppParams { @SuppressWarnings("JavaUtilDate") // TODO: b/365629730 -- prefer Instant or LocalDate public void setMseTime(String mseTime) throws ParseException { - SimpleDateFormat format = new SimpleDateFormat("yyyyMMdd'T'HHmmssZ"); + SimpleDateFormat format = new SimpleDateFormat("yyyyMMdd'T'HHmmssZ", Locale.ROOT); Date date = format.parse(mseTime); this.mMseTime = date.getTime(); } diff --git a/android/app/src/com/android/bluetooth/map/BluetoothMapContent.java b/android/app/src/com/android/bluetooth/map/BluetoothMapContent.java index 6a8d91b839..43d0b463cc 100644 --- a/android/app/src/com/android/bluetooth/map/BluetoothMapContent.java +++ b/android/app/src/com/android/bluetooth/map/BluetoothMapContent.java @@ -51,7 +51,6 @@ import com.android.internal.annotations.VisibleForTesting; import com.google.android.mms.pdu.CharacterSets; import com.google.android.mms.pdu.PduHeaders; -import com.google.common.base.Ascii; import java.io.ByteArrayOutputStream; import java.io.Closeable; @@ -64,6 +63,7 @@ import java.nio.charset.StandardCharsets; import java.util.Arrays; import java.util.HashMap; import java.util.List; +import java.util.Locale; import java.util.Map; import java.util.stream.Collectors; @@ -2004,7 +2004,7 @@ public class BluetoothMapContent { // Filter ConvoId long convoId = -1; if (ap.getFilterConvoId() != null) { - convoId = ap.getFilterConvoId().getLeastSignificantBits(); + convoId = ap.getFilterConvoId().leastSignificantBits(); } if (convoId > 0) { selection @@ -3413,7 +3413,7 @@ public class BluetoothMapContent { } long convoId = -1; if (ap.getFilterConvoId() != null) { - convoId = ap.getFilterConvoId().getLeastSignificantBits(); + convoId = ap.getFilterConvoId().leastSignificantBits(); } if (convoId > 0) { newUri.appendQueryParameter( @@ -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; @@ -3818,7 +3818,7 @@ public class BluetoothMapContent { } /** - * Read out the mms parts and update the bMessage object provided i {@linkplain message} + * Read out the mms parts and update the bMessage object provided i {@code message} * * @param id the content provider ID of the message * @param message the bMessage object to add the information to @@ -3889,7 +3889,7 @@ public class BluetoothMapContent { // according to spec, "charset" should not be set. However, if the attachment // is replaced with a text string, the bMessage now contains text and should // have charset set to UTF-8 according to spec. - if (!Ascii.toUpperCase(part.mContentType).contains("TEXT") + if (!part.mContentType.toUpperCase(Locale.ROOT).contains("TEXT") && !message.getIncludeAttachments()) { StringBuilder sb = new StringBuilder(); part.encodePlainText(sb); diff --git a/android/app/src/com/android/bluetooth/map/BluetoothMapContentObserver.java b/android/app/src/com/android/bluetooth/map/BluetoothMapContentObserver.java index 8fc58b950e..c1ca674e2e 100644 --- a/android/app/src/com/android/bluetooth/map/BluetoothMapContentObserver.java +++ b/android/app/src/com/android/bluetooth/map/BluetoothMapContentObserver.java @@ -65,7 +65,6 @@ import com.android.internal.annotations.VisibleForTesting; import com.android.obex.ResponseCodes; import com.google.android.mms.pdu.PduHeaders; -import com.google.common.base.Ascii; import org.xmlpull.v1.XmlSerializer; @@ -83,6 +82,7 @@ import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.List; +import java.util.Locale; import java.util.Map; import java.util.Objects; import java.util.Set; @@ -3534,7 +3534,7 @@ public class BluetoothMapContentObserver { count++; values.clear(); if (part.mContentType != null - && Ascii.toUpperCase(part.mContentType).contains("TEXT")) { + && part.mContentType.toUpperCase(Locale.ROOT).contains("TEXT")) { values.put(Mms.Part.CONTENT_TYPE, "text/plain"); values.put(Mms.Part.CHARSET, 106); if (part.mPartName != null) { @@ -3574,7 +3574,7 @@ public class BluetoothMapContentObserver { Log.v(TAG, "Added TEXT part"); } else if (part.mContentType != null - && Ascii.toUpperCase(part.mContentType).contains("SMIL")) { + && part.mContentType.toUpperCase(Locale.ROOT).contains("SMIL")) { values.put(Mms.Part.SEQ, -1); values.put(Mms.Part.CONTENT_TYPE, "application/smil"); if (part.mContentId != null) { diff --git a/android/app/src/com/android/bluetooth/map/BluetoothMapConvoContactElement.java b/android/app/src/com/android/bluetooth/map/BluetoothMapConvoContactElement.java index 39f5359392..c5642c54a5 100644 --- a/android/app/src/com/android/bluetooth/map/BluetoothMapConvoContactElement.java +++ b/android/app/src/com/android/bluetooth/map/BluetoothMapConvoContactElement.java @@ -26,6 +26,7 @@ import java.io.IOException; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Date; +import java.util.Locale; import java.util.Objects; // Next tag value for ContentProfileErrorReportUtils.report(): 1 @@ -63,8 +64,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; } @@ -158,7 +159,7 @@ public class BluetoothMapConvoContactElement @SuppressWarnings("JavaUtilDate") // TODO: b/365629730 -- prefer Instant or LocalDate public String getLastActivityString() { - SimpleDateFormat format = new SimpleDateFormat("yyyyMMdd'T'HHmmss"); + SimpleDateFormat format = new SimpleDateFormat("yyyyMMdd'T'HHmmss", Locale.ROOT); Date date = new Date(mLastActivity); return format.format(date); // Format to YYYYMMDDTHHMMSS local time } @@ -169,7 +170,7 @@ public class BluetoothMapConvoContactElement @SuppressWarnings("JavaUtilDate") // TODO: b/365629730 -- prefer Instant or LocalDate public void setLastActivity(String lastActivity) throws ParseException { - SimpleDateFormat format = new SimpleDateFormat("yyyyMMdd'T'HHmmss"); + SimpleDateFormat format = new SimpleDateFormat("yyyyMMdd'T'HHmmss", Locale.ROOT); Date date = format.parse(lastActivity); this.mLastActivity = date.getTime(); } diff --git a/android/app/src/com/android/bluetooth/map/BluetoothMapConvoListingElement.java b/android/app/src/com/android/bluetooth/map/BluetoothMapConvoListingElement.java index 9a7fc80d39..f3a7a0a79a 100644 --- a/android/app/src/com/android/bluetooth/map/BluetoothMapConvoListingElement.java +++ b/android/app/src/com/android/bluetooth/map/BluetoothMapConvoListingElement.java @@ -34,6 +34,7 @@ import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Date; import java.util.List; +import java.util.Locale; import java.util.Objects; // Next tag value for ContentProfileErrorReportUtils.report(): 2 @@ -146,7 +147,7 @@ public class BluetoothMapConvoListingElement @SuppressWarnings("JavaUtilDate") // TODO: b/365629730 -- prefer Instant or LocalDate public String getLastActivityString() { - SimpleDateFormat format = new SimpleDateFormat("yyyyMMdd'T'HHmmss"); + SimpleDateFormat format = new SimpleDateFormat("yyyyMMdd'T'HHmmss", Locale.ROOT); Date date = new Date(mLastActivity); return format.format(date); // Format to YYYYMMDDTHHMMSS local time } @@ -159,7 +160,7 @@ public class BluetoothMapConvoListingElement @SuppressWarnings("JavaUtilDate") // TODO: b/365629730 -- prefer Instant or LocalDate public void setLastActivity(String lastActivity) throws ParseException { // TODO: Encode with time-zone if MCE requests it - SimpleDateFormat format = new SimpleDateFormat("yyyyMMdd'T'HHmmss"); + SimpleDateFormat format = new SimpleDateFormat("yyyyMMdd'T'HHmmss", Locale.ROOT); Date date = format.parse(lastActivity); this.mLastActivity = date.getTime(); } @@ -207,7 +208,7 @@ public class BluetoothMapConvoListingElement } public long getCpConvoId() { - return mId.getLeastSignificantBits(); + return mId.leastSignificantBits(); } public void setSummary(String summary) { diff --git a/android/app/src/com/android/bluetooth/map/BluetoothMapFolderElement.java b/android/app/src/com/android/bluetooth/map/BluetoothMapFolderElement.java index 93f9db26e4..745cc1ad9d 100644 --- a/android/app/src/com/android/bluetooth/map/BluetoothMapFolderElement.java +++ b/android/app/src/com/android/bluetooth/map/BluetoothMapFolderElement.java @@ -23,8 +23,6 @@ import com.android.bluetooth.BluetoothStatsLog; import com.android.bluetooth.Utils; import com.android.bluetooth.content_profiles.ContentProfileErrorReportUtils; -import com.google.common.base.Ascii; - import org.xmlpull.v1.XmlPullParser; import org.xmlpull.v1.XmlPullParserException; import org.xmlpull.v1.XmlSerializer; @@ -259,7 +257,7 @@ public class BluetoothMapFolderElement implements Comparable<BluetoothMapFolderE * @return the subFolder element if found {@code null} otherwise. */ public BluetoothMapFolderElement getSubFolder(String folderName) { - return mSubFolders.get(Ascii.toLowerCase(folderName)); + return mSubFolders.get(folderName.toLowerCase(Locale.ROOT)); } public byte[] encode(int offset, int count) { diff --git a/android/app/src/com/android/bluetooth/map/BluetoothMapMessageListingElement.java b/android/app/src/com/android/bluetooth/map/BluetoothMapMessageListingElement.java index 87dd614f18..c8ee05a5bd 100644 --- a/android/app/src/com/android/bluetooth/map/BluetoothMapMessageListingElement.java +++ b/android/app/src/com/android/bluetooth/map/BluetoothMapMessageListingElement.java @@ -22,6 +22,7 @@ import org.xmlpull.v1.XmlSerializer; import java.io.IOException; import java.text.SimpleDateFormat; import java.util.Date; +import java.util.Locale; public class BluetoothMapMessageListingElement implements Comparable<BluetoothMapMessageListingElement> { @@ -78,7 +79,7 @@ public class BluetoothMapMessageListingElement public String getDateTimeString() { /* TODO: if the feature bit mask of the client supports it, add the time-zone * (as for MSETime) */ - SimpleDateFormat format = new SimpleDateFormat("yyyyMMdd'T'HHmmss"); + SimpleDateFormat format = new SimpleDateFormat("yyyyMMdd'T'HHmmss", Locale.ROOT); Date date = new Date(mDateTime); return format.format(date); // Format to YYYYMMDDTHHMMSS local time } diff --git a/android/app/src/com/android/bluetooth/map/BluetoothMapObexServer.java b/android/app/src/com/android/bluetooth/map/BluetoothMapObexServer.java index bf702a5075..d82ff355d7 100644 --- a/android/app/src/com/android/bluetooth/map/BluetoothMapObexServer.java +++ b/android/app/src/com/android/bluetooth/map/BluetoothMapObexServer.java @@ -1137,7 +1137,7 @@ public class BluetoothMapObexServer extends ServerRequestHandler { + ((tmpLongLong == null) ? "" : Long.toHexString( - tmpLongLong.getLeastSignificantBits()))); + tmpLongLong.leastSignificantBits()))); } if (!isUserUnlocked()) { Log.e(TAG, "Storage locked, " + type + " failed"); diff --git a/android/app/src/com/android/bluetooth/map/BluetoothMapService.java b/android/app/src/com/android/bluetooth/map/BluetoothMapService.java index 19694ab1af..bac8bdc247 100644 --- a/android/app/src/com/android/bluetooth/map/BluetoothMapService.java +++ b/android/app/src/com/android/bluetooth/map/BluetoothMapService.java @@ -55,12 +55,10 @@ import android.telephony.TelephonyManager; import android.util.Log; import android.util.SparseArray; -import com.android.bluetooth.BluetoothMetricsProto; import com.android.bluetooth.BluetoothStatsLog; import com.android.bluetooth.R; import com.android.bluetooth.Utils; import com.android.bluetooth.btservice.AdapterService; -import com.android.bluetooth.btservice.MetricsLogger; import com.android.bluetooth.btservice.ProfileService; import com.android.bluetooth.btservice.storage.DatabaseManager; import com.android.bluetooth.content_profiles.ContentProfileErrorReportUtils; @@ -711,11 +709,8 @@ public class BluetoothMapService extends ProfileService { } /** - * Get the current instance of {@link BluetoothMapService} - * * @return current instance of {@link BluetoothMapService} */ - @VisibleForTesting public static synchronized BluetoothMapService getBluetoothMapService() { if (sBluetoothMapService == null) { Log.w(TAG, "getBluetoothMapService(): service is null"); @@ -959,7 +954,6 @@ public class BluetoothMapService extends ProfileService { } else if (mPermission == BluetoothDevice.ACCESS_ALLOWED) { // Signal to the service that we have a incoming connection. sendConnectMessage(masInst.getMasId()); - MetricsLogger.logProfileConnectionEvent(BluetoothMetricsProto.ProfileId.MAP); } return true; } @@ -1065,7 +1059,6 @@ public class BluetoothMapService extends ProfileService { Log.d(TAG, "USER_CONFIRM_TIMEOUT ACTION Received."); sendConnectTimeoutMessage(); } else if (action.equals(BluetoothDevice.ACTION_CONNECTION_ACCESS_REPLY)) { - int requestType = intent.getIntExtra( BluetoothDevice.EXTRA_ACCESS_REQUEST_TYPE, @@ -1081,6 +1074,10 @@ public class BluetoothMapService extends ProfileService { || (requestType != BluetoothDevice.REQUEST_TYPE_MESSAGE_ACCESS)) { return; } + BluetoothDevice remoteDevice = mRemoteDevice; + if (remoteDevice == null) { + return; + } mIsWaitingAuthorization = false; if (mRemoveTimeoutMsg) { @@ -1097,13 +1094,13 @@ public class BluetoothMapService extends ProfileService { mPermission = BluetoothDevice.ACCESS_ALLOWED; if (intent.getBooleanExtra(BluetoothDevice.EXTRA_ALWAYS_ALLOWED, false)) { boolean result = - mRemoteDevice.setMessageAccessPermission( + remoteDevice.setMessageAccessPermission( BluetoothDevice.ACCESS_ALLOWED); Log.d(TAG, "setMessageAccessPermission(ACCESS_ALLOWED) result=" + result); } mAdapterService.sdpSearch( - mRemoteDevice, BluetoothMnsObexClient.BLUETOOTH_UUID_OBEX_MNS); + remoteDevice, BluetoothMnsObexClient.BLUETOOTH_UUID_OBEX_MNS); mSdpSearchInitiated = true; } else { // Auth. declined by user, serverSession should not be running, but @@ -1111,7 +1108,7 @@ public class BluetoothMapService extends ProfileService { mPermission = BluetoothDevice.ACCESS_REJECTED; if (intent.getBooleanExtra(BluetoothDevice.EXTRA_ALWAYS_ALLOWED, false)) { boolean result = - mRemoteDevice.setMessageAccessPermission( + remoteDevice.setMessageAccessPermission( BluetoothDevice.ACCESS_REJECTED); Log.d(TAG, "setMessageAccessPermission(ACCESS_REJECTED) result=" + result); } diff --git a/android/app/src/com/android/bluetooth/map/BluetoothMapSmsPdu.java b/android/app/src/com/android/bluetooth/map/BluetoothMapSmsPdu.java index 30cfebd1fe..d887860f56 100644 --- a/android/app/src/com/android/bluetooth/map/BluetoothMapSmsPdu.java +++ b/android/app/src/com/android/bluetooth/map/BluetoothMapSmsPdu.java @@ -39,6 +39,7 @@ import java.util.ArrayList; import java.util.Calendar; import java.util.Date; import java.util.List; +import java.util.Locale; import java.util.Random; // Next tag value for ContentProfileErrorReportUtils.report(): 10 @@ -382,7 +383,7 @@ public class BluetoothMapSmsPdu { @SuppressWarnings("JavaUtilDate") // TODO: b/365629730 -- prefer Instant or LocalDate private static void gsmWriteDate(ByteArrayOutputStream header, long time) { - SimpleDateFormat format = new SimpleDateFormat("yyMMddHHmmss"); + SimpleDateFormat format = new SimpleDateFormat("yyMMddHHmmss", Locale.ROOT); Date date = new Date(time); String timeStr = format.format(date); // Format to YYMMDDTHHMMSS UTC time Log.v(TAG, "Generated time string: " + timeStr); @@ -400,11 +401,11 @@ public class BluetoothMapSmsPdu { / (15 * 60 * 1000); /* offset in quarters of an hour */ String offsetString; if (offset < 0) { - offsetString = String.format("%1$02d", -(offset)); + offsetString = String.format(Locale.ROOT, "%1$02d", -(offset)); char[] offsetChars = offsetString.toCharArray(); header.write((offsetChars[1] - 0x30) << 4 | 0x40 | (offsetChars[0] - 0x30)); } else { - offsetString = String.format("%1$02d", offset); + offsetString = String.format(Locale.ROOT, "%1$02d", offset); char[] offsetChars = offsetString.toCharArray(); header.write((offsetChars[1] - 0x30) << 4 | (offsetChars[0] - 0x30)); } diff --git a/android/app/src/com/android/bluetooth/map/BluetoothMapUtils.java b/android/app/src/com/android/bluetooth/map/BluetoothMapUtils.java index 932f4a98d6..e92086ec5d 100644 --- a/android/app/src/com/android/bluetooth/map/BluetoothMapUtils.java +++ b/android/app/src/com/android/bluetooth/map/BluetoothMapUtils.java @@ -26,8 +26,6 @@ import com.android.bluetooth.BluetoothStatsLog; import com.android.bluetooth.content_profiles.ContentProfileErrorReportUtils; import com.android.bluetooth.mapapi.BluetoothMapContract; -import com.google.common.base.Ascii; - import java.io.ByteArrayOutputStream; import java.io.UnsupportedEncodingException; import java.nio.ByteBuffer; @@ -43,6 +41,7 @@ import java.time.Instant; import java.util.Arrays; import java.util.BitSet; import java.util.Calendar; +import java.util.Locale; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -640,7 +639,7 @@ public class BluetoothMapUtils { if (charset == null) { charset = "UTF-8"; } else { - charset = Ascii.toUpperCase(charset); + charset = charset.toUpperCase(Locale.ROOT); try { if (!Charset.isSupported(charset)) { charset = "UTF-8"; @@ -737,8 +736,8 @@ public class BluetoothMapUtils { static String getDateTimeString(long timestamp) { SimpleDateFormat format = (mPeerSupportUtcTimeStamp) - ? new SimpleDateFormat("yyyyMMdd'T'HHmmssZ") - : new SimpleDateFormat("yyyyMMdd'T'HHmmss"); + ? new SimpleDateFormat("yyyyMMdd'T'HHmmssZ", Locale.ROOT) + : new SimpleDateFormat("yyyyMMdd'T'HHmmss", Locale.ROOT); Calendar cal = Calendar.getInstance(); cal.setTimeInMillis(timestamp); Log.v( diff --git a/android/app/src/com/android/bluetooth/map/BluetoothMapbMessage.java b/android/app/src/com/android/bluetooth/map/BluetoothMapbMessage.java index ad2698b72b..ceee0c860d 100644 --- a/android/app/src/com/android/bluetooth/map/BluetoothMapbMessage.java +++ b/android/app/src/com/android/bluetooth/map/BluetoothMapbMessage.java @@ -24,14 +24,13 @@ import com.android.bluetooth.content_profiles.ContentProfileErrorReportUtils; import com.android.bluetooth.map.BluetoothMapUtils.TYPE; import com.android.internal.annotations.VisibleForTesting; -import com.google.common.base.Ascii; - import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.List; +import java.util.Locale; import java.util.regex.Pattern; // Next tag value for ContentProfileErrorReportUtils.report(): 10 @@ -429,7 +428,8 @@ public abstract class BluetoothMapbMessage { String line = getLine(); if (line == null || subString == null) { throw new IllegalArgumentException("Line or substring is null"); - } else if (!Ascii.toUpperCase(line).contains(Ascii.toUpperCase(subString))) { + } else if (!line.toUpperCase(Locale.ROOT) + .contains(subString.toUpperCase(Locale.ROOT))) { throw new IllegalArgumentException( "Expected \"" + subString + "\" in: \"" + line + "\""); } @@ -442,11 +442,11 @@ public abstract class BluetoothMapbMessage { */ public void expect(String subString, String subString2) throws IllegalArgumentException { String line = getLine(); - if (!Ascii.toUpperCase(line).contains(Ascii.toUpperCase(subString))) { + if (!line.toUpperCase(Locale.ROOT).contains(subString.toUpperCase(Locale.ROOT))) { throw new IllegalArgumentException( "Expected \"" + subString + "\" in: \"" + line + "\""); } - if (!Ascii.toUpperCase(line).contains(Ascii.toUpperCase(subString2))) { + if (!line.toUpperCase(Locale.ROOT).contains(subString2.toUpperCase(Locale.ROOT))) { throw new IllegalArgumentException( "Expected \"" + subString + "\" in: \"" + line + "\""); } diff --git a/android/app/src/com/android/bluetooth/map/BluetoothMapbMessageMime.java b/android/app/src/com/android/bluetooth/map/BluetoothMapbMessageMime.java index cc1ac4f7cd..520bcce4d7 100644 --- a/android/app/src/com/android/bluetooth/map/BluetoothMapbMessageMime.java +++ b/android/app/src/com/android/bluetooth/map/BluetoothMapbMessageMime.java @@ -24,8 +24,6 @@ import android.util.Log; import com.android.bluetooth.BluetoothStatsLog; import com.android.bluetooth.content_profiles.ContentProfileErrorReportUtils; -import com.google.common.base.Ascii; - import java.io.UnsupportedEncodingException; import java.nio.charset.Charset; import java.nio.charset.IllegalCharsetNameException; @@ -68,7 +66,7 @@ public class BluetoothMapbMessageMime extends BluetoothMapbMessage { if (charset == null) { charset = "UTF-8"; } else { - charset = Ascii.toUpperCase(charset); + charset = charset.toUpperCase(Locale.ROOT); try { if (!Charset.isSupported(charset)) { charset = "UTF-8"; @@ -121,8 +119,8 @@ public class BluetoothMapbMessageMime extends BluetoothMapbMessage { the below use of UTF-8 is not allowed, Base64 should be used for text. */ if (mContentType != null - && (Ascii.toUpperCase(mContentType).contains("TEXT") - || Ascii.toUpperCase(mContentType).contains("SMIL"))) { + && (mContentType.toUpperCase(Locale.ROOT).contains("TEXT") + || mContentType.toUpperCase(Locale.ROOT).contains("SMIL"))) { String text = new String(mData, StandardCharsets.UTF_8); if (text.getBytes().length == text.getBytes(StandardCharsets.UTF_8).length) { /* Add the header split empty line */ @@ -145,13 +143,14 @@ public class BluetoothMapbMessageMime extends BluetoothMapbMessage { } public void encodePlainText(StringBuilder sb) { - if (mContentType != null && Ascii.toUpperCase(mContentType).contains("TEXT")) { + if (mContentType != null && mContentType.toUpperCase(Locale.ROOT).contains("TEXT")) { String text = new String(mData, StandardCharsets.UTF_8); if (text.getBytes().length != text.getBytes(StandardCharsets.UTF_8).length) { text = BluetoothMapUtils.encodeQuotedPrintable(mData); } sb.append(text).append("\r\n"); - } else if (mContentType != null && Ascii.toUpperCase(mContentType).contains("/SMIL")) { + } else if (mContentType != null + && mContentType.toUpperCase(Locale.ROOT).contains("/SMIL")) { /* Skip the smil.xml, as no-one knows what it is. */ } else { /* Not a text part, just print the filename or part name if they exist. */ @@ -202,7 +201,7 @@ public class BluetoothMapbMessageMime extends BluetoothMapbMessage { } if (mParts != null) { for (MimePart part : mParts) { - if (Ascii.toUpperCase(part.mContentType).contains("TEXT")) { + if (part.mContentType.toUpperCase(Locale.ROOT).contains("TEXT")) { sb.append(new String(part.mData)); } } @@ -369,7 +368,7 @@ public class BluetoothMapbMessageMime extends BluetoothMapbMessage { mCharset = null; for (MimePart part : mParts) { if (part.mContentType != null - && Ascii.toUpperCase(part.mContentType).contains("TEXT")) { + && part.mContentType.toUpperCase(Locale.ROOT).contains("TEXT")) { mCharset = "UTF-8"; Log.v(TAG, "Charset set to UTF-8"); break; @@ -591,7 +590,7 @@ public class BluetoothMapbMessageMime extends BluetoothMapbMessage { return remaining.toString(); } - String headerType = Ascii.toUpperCase(headerParts[0]); + String headerType = headerParts[0].toUpperCase(Locale.ROOT); String headerValue = headerParts[1].trim(); // Address headers @@ -690,14 +689,14 @@ public class BluetoothMapbMessageMime extends BluetoothMapbMessage { continue; } Log.d(TAG, "parseMimePart: header=" + header); - String headerType = Ascii.toUpperCase(headerParts[0]); + String headerType = headerParts[0].toUpperCase(Locale.ROOT); String headerValue = headerParts[1].trim(); if (headerType.contains("CONTENT-TYPE")) { String[] contentTypeParts = SEMI_COLON.split(headerValue); newPart.mContentType = contentTypeParts[0]; // Extract the boundary if it exists for (int j = 1, n = contentTypeParts.length; j < n; j++) { - String value = Ascii.toLowerCase(contentTypeParts[j]); + String value = contentTypeParts[j].toLowerCase(Locale.ROOT); if (value.contains("charset")) { newPart.mCharsetName = CHARSET_PATTERN.split(value, 2)[1].trim(); } @@ -743,9 +742,10 @@ public class BluetoothMapbMessageMime extends BluetoothMapbMessage { } private static byte[] decodeBody(String body, String encoding, String charset) { - if (encoding != null && Ascii.toUpperCase(encoding).contains("BASE64")) { + if (encoding != null && encoding.toUpperCase(Locale.ROOT).contains("BASE64")) { return Base64.decode(body, Base64.DEFAULT); - } else if (encoding != null && Ascii.toUpperCase(encoding).contains("QUOTED-PRINTABLE")) { + } else if (encoding != null + && encoding.toUpperCase(Locale.ROOT).contains("QUOTED-PRINTABLE")) { return BluetoothMapUtils.quotedPrintableToUtf8(body, charset); } else { // TODO: handle other encoding types? - here we simply store the string data as bytes 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/mapclient/MapClientContent.java b/android/app/src/com/android/bluetooth/mapclient/MapClientContent.java index 5997d468cc..5e229d898c 100644 --- a/android/app/src/com/android/bluetooth/mapclient/MapClientContent.java +++ b/android/app/src/com/android/bluetooth/mapclient/MapClientContent.java @@ -16,6 +16,9 @@ package com.android.bluetooth.mapclient; +import static android.telephony.PhoneNumberUtils.areSamePhoneNumber; +import static android.telephony.PhoneNumberUtils.extractNetworkPortion; + import android.bluetooth.BluetoothDevice; import android.bluetooth.BluetoothMapClient; import android.content.ContentResolver; @@ -30,7 +33,6 @@ import android.provider.Telephony.Mms; import android.provider.Telephony.MmsSms; import android.provider.Telephony.Sms; import android.provider.Telephony.Threads; -import android.telephony.PhoneNumberUtils; import android.telephony.SubscriptionInfo; import android.telephony.SubscriptionManager; import android.telephony.TelephonyManager; @@ -80,17 +82,20 @@ class MapClientContent { SENT } - final BluetoothDevice mDevice; + private final HashMap<String, Uri> mHandleToUriMap = new HashMap<>(); + private final HashMap<Uri, MessageStatus> mUriToHandleMap = new HashMap<>(); + + final ContentObserver mContentObserver; private final Context mContext; + private final BluetoothDevice mDevice; private final Callbacks mCallbacks; private final ContentResolver mResolver; - ContentObserver mContentObserver; - String mPhoneNumber = null; - private int mSubscriptionId = SubscriptionManager.INVALID_SUBSCRIPTION_ID; private final SubscriptionManager mSubscriptionManager; private final TelephonyManager mTelephonyManager; - private final HashMap<String, Uri> mHandleToUriMap = new HashMap<>(); - private final HashMap<Uri, MessageStatus> mUriToHandleMap = new HashMap<>(); + + String mPhoneNumber = null; + + private int mSubscriptionId = SubscriptionManager.INVALID_SUBSCRIPTION_ID; /** Callbacks API to notify about statusChanges as observed from the content provider */ interface Callbacks { @@ -114,7 +119,6 @@ class MapClientContent { mDevice = device; mCallbacks = callbacks; mResolver = mContext.getContentResolver(); - mSubscriptionManager = mContext.getSystemService(SubscriptionManager.class); mTelephonyManager = mContext.getSystemService(TelephonyManager.class); mSubscriptionManager.addSubscriptionInfoRecord( @@ -244,7 +248,7 @@ class MapClientContent { private void storeSms(Bmessage message, String handle, Long timestamp, boolean seen) { debug("storeSms"); verbose(message.toString()); - String recipients; + final String recipients; if (INBOX_PATH.equals(message.getFolder())) { recipients = getOriginatorNumber(message); } else { @@ -498,9 +502,8 @@ class MapClientContent { /** getThreadId utilize the originator and recipients to obtain the thread id */ private long getThreadId(Bmessage message) { - Set<String> messageContacts = new ArraySet<>(); - String originator = PhoneNumberUtils.extractNetworkPortion(getOriginatorNumber(message)); + String originator = extractNetworkPortion(getOriginatorNumber(message)); if (originator != null) { messageContacts.add(originator); } @@ -512,12 +515,9 @@ class MapClientContent { if (mPhoneNumber == null) { warn("getThreadId called, mPhoneNumber never found."); } + final String networkCountryIso = mTelephonyManager.getNetworkCountryIso(); messageContacts.removeIf( - number -> - (PhoneNumberUtils.areSamePhoneNumber( - number, - mPhoneNumber, - mTelephonyManager.getNetworkCountryIso()))); + number -> areSamePhoneNumber(number, mPhoneNumber, networkCountryIso)); } verbose("Contacts = " + messageContacts.toString()); @@ -525,14 +525,11 @@ class MapClientContent { } private static void getRecipientsFromMessage(Bmessage message, Set<String> messageContacts) { - List<VCardEntry> recipients = message.getRecipients(); - for (VCardEntry recipient : recipients) { - List<VCardEntry.PhoneData> phoneData = recipient.getPhoneList(); - if (phoneData != null && !phoneData.isEmpty()) { - messageContacts.add( - PhoneNumberUtils.extractNetworkPortion(phoneData.get(0).getNumber())); - } - } + message.getRecipients().stream() + .map(recipient -> recipient.getPhoneList()) + .filter(phoneData -> phoneData != null && !phoneData.isEmpty()) + .map(phoneData -> extractNetworkPortion(phoneData.get(0).getNumber())) + .forEach(messageContacts::add); } private static String getOriginatorNumber(Bmessage message) { @@ -546,7 +543,7 @@ class MapClientContent { return null; } - return PhoneNumberUtils.extractNetworkPortion(phoneData.get(0).getNumber()); + return extractNetworkPortion(phoneData.get(0).getNumber()); } private static String getFirstRecipientNumber(Bmessage message) { @@ -669,8 +666,8 @@ class MapClientContent { } private List<MessageDumpElement> getRecentMessagesFromFolder(Folder folder) { - Uri smsUri = null; - Uri mmsUri = null; + final Uri smsUri; + final Uri mmsUri; if (folder == Folder.INBOX) { smsUri = Sms.Inbox.CONTENT_URI; mmsUri = Mms.Inbox.CONTENT_URI; @@ -682,7 +679,7 @@ class MapClientContent { return null; } - ArrayList<MessageDumpElement> messages = new ArrayList<MessageDumpElement>(); + List<MessageDumpElement> messages = new ArrayList<>(); for (Uri uri : new Uri[] {smsUri, mmsUri}) { messages.addAll(getMessagesFromUri(uri)); } @@ -702,7 +699,7 @@ class MapClientContent { private List<MessageDumpElement> getMessagesFromUri(Uri uri) { debug("getMessagesFromUri: uri=" + uri); - ArrayList<MessageDumpElement> messages = new ArrayList<MessageDumpElement>(); + List<MessageDumpElement> messages = new ArrayList<>(); if (mSubscriptionId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) { warn("getMessagesFromUri: Failed, no subscription ID"); @@ -886,20 +883,9 @@ class MapClientContent { .toLocalDateTime()); } - private static class MessageDumpElement implements Comparable<MessageDumpElement> { - private final String mMessageHandle; - private final long mTimestamp; - private final Type mType; - private final long mThreadId; - private final Uri mUri; - - MessageDumpElement(String handle, Uri uri, long timestamp, long threadId, Type type) { - mMessageHandle = handle; - mTimestamp = timestamp; - mUri = uri; - mThreadId = threadId; - mType = type; - } + private record MessageDumpElement( + String handle, Uri uri, long timestamp, long threadId, Type type) + implements Comparable<MessageDumpElement> { public static String getFormattedColumnNames() { return String.format( @@ -910,15 +896,15 @@ class MapClientContent { public String toString() { return String.format( "%-19s %8d %-16s %-4s %s", - toDatetimeString(mTimestamp), mThreadId, mMessageHandle, mType, mUri); + toDatetimeString(timestamp), threadId, handle, type, uri); } @Override public int compareTo(MessageDumpElement e) { // we want reverse chronological. - if (this.mTimestamp < e.mTimestamp) { + if (this.timestamp < e.timestamp) { return 1; - } else if (this.mTimestamp > e.mTimestamp) { + } else if (this.timestamp > e.timestamp) { return -1; } else { return 0; diff --git a/android/app/src/com/android/bluetooth/mapclient/MceStateMachine.java b/android/app/src/com/android/bluetooth/mapclient/MceStateMachine.java index 457e87c69f..c532af9b99 100644 --- a/android/app/src/com/android/bluetooth/mapclient/MceStateMachine.java +++ b/android/app/src/com/android/bluetooth/mapclient/MceStateMachine.java @@ -65,7 +65,6 @@ import android.telecom.PhoneAccount; import android.telephony.SmsManager; import android.util.Log; -import com.android.bluetooth.BluetoothMetricsProto; import com.android.bluetooth.Utils; import com.android.bluetooth.btservice.AdapterService; import com.android.bluetooth.btservice.MetricsLogger; @@ -310,9 +309,6 @@ class MceStateMachine extends StateMachine { + prevState + ", new=" + state); - if (prevState != state && state == STATE_CONNECTED) { - MetricsLogger.logProfileConnectionEvent(BluetoothMetricsProto.ProfileId.MAP_CLIENT); - } setState(state); mAdapterService.updateProfileConnectionAdapterProperties( diff --git a/android/app/src/com/android/bluetooth/mcp/GattOpContext.java b/android/app/src/com/android/bluetooth/mcp/GattOpContext.java new file mode 100644 index 0000000000..fbd8442d58 --- /dev/null +++ b/android/app/src/com/android/bluetooth/mcp/GattOpContext.java @@ -0,0 +1,48 @@ +/* + * Copyright (C) 2025 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.bluetooth.mcp; + +import android.bluetooth.BluetoothGattCharacteristic; +import android.bluetooth.BluetoothGattDescriptor; + +import com.google.protobuf.ByteString; + +public 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, + READ_DESCRIPTOR, + WRITE_DESCRIPTOR, + } + + public GattOpContext( + Operation operation, + int requestId, + BluetoothGattCharacteristic characteristic, + BluetoothGattDescriptor descriptor, + int offset) { + this(operation, requestId, characteristic, descriptor, false, false, offset, null); + } +} diff --git a/android/app/src/com/android/bluetooth/mcp/MediaControlGattService.java b/android/app/src/com/android/bluetooth/mcp/MediaControlGattService.java index 2dbc1014eb..26b5c2eb68 100644 --- a/android/app/src/com/android/bluetooth/mcp/MediaControlGattService.java +++ b/android/app/src/com/android/bluetooth/mcp/MediaControlGattService.java @@ -56,6 +56,8 @@ import com.android.bluetooth.hearingaid.HearingAidService; import com.android.bluetooth.le_audio.LeAudioService; import com.android.internal.annotations.VisibleForTesting; +import com.google.protobuf.ByteString; + import java.nio.ByteBuffer; import java.nio.ByteOrder; import java.util.ArrayList; @@ -210,59 +212,6 @@ public class MediaControlGattService implements MediaControlGattServiceInterface } } - private static class GattOpContext { - public enum Operation { - READ_CHARACTERISTIC, - WRITE_CHARACTERISTIC, - READ_DESCRIPTOR, - WRITE_DESCRIPTOR, - } - - GattOpContext( - Operation operation, - 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; - } - - 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; - } - private final Map<UUID, CharacteristicWriteHandler> mCharWriteCallback = Map.of( UUID_TRACK_POSITION, @@ -455,7 +404,7 @@ public class MediaControlGattService implements MediaControlGattServiceInterface } private void onUnauthorizedCharRead(BluetoothDevice device, GattOpContext op) { - UUID charUuid = op.mCharacteristic.getUuid(); + UUID charUuid = op.characteristic().getUuid(); byte[] buffer = null; if (charUuid.equals(UUID_PLAYER_NAME)) { @@ -545,89 +494,89 @@ public class MediaControlGattService implements MediaControlGattServiceInterface } else if (charUuid.equals(UUID_CONTENT_CONTROL_ID)) { // It is ok, to send the real value for CCID - 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: " + mcsUuidToString(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() + (op.characteristic() != null + ? op.characteristic().getUuid() + : (op.descriptor() != null + ? op.descriptor().getCharacteristic().getUuid() : null)); mEventLogger.logw( TAG, "onUnauthorizedGattOperation: device= " + device + ", opcode= " - + op.mOperation + + op.descriptor() + ", characteristic= " + (charUuid != null ? mcsUuidToString(charUuid) : "UNKNOWN")); - switch (op.mOperation) { + switch (op.operation()) { /* Allow not yet authorized devices to subscribe for notifications */ case READ_DESCRIPTOR: - if (op.mOffset > 1) { + if (op.offset() > 1) { mBluetoothGattServer.sendResponse( device, - op.mRequestId, + op.requestId(), BluetoothGatt.GATT_INVALID_OFFSET, - op.mOffset, + op.offset(), null); return; } - byte[] value = getCccBytes(device, op.mDescriptor.getCharacteristic().getUuid()); + byte[] value = getCccBytes(device, op.descriptor().getCharacteristic().getUuid()); if (value == null) { mBluetoothGattServer.sendResponse( - device, op.mRequestId, BluetoothGatt.GATT_FAILURE, op.mOffset, null); + device, op.requestId(), BluetoothGatt.GATT_FAILURE, op.offset(), null); return; } - value = Arrays.copyOfRange(value, op.mOffset, value.length); + value = Arrays.copyOfRange(value, op.offset(), value.length); mBluetoothGattServer.sendResponse( - device, op.mRequestId, BluetoothGatt.GATT_SUCCESS, op.mOffset, value); + device, op.requestId(), BluetoothGatt.GATT_SUCCESS, op.offset(), value); return; case WRITE_DESCRIPTOR: int status = BluetoothGatt.GATT_SUCCESS; - 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 { status = BluetoothGatt.GATT_SUCCESS; setCcc( device, - op.mDescriptor.getCharacteristic().getUuid(), - op.mOffset, - op.mValue, + op.descriptor().getCharacteristic().getUuid(), + op.offset(), + op.value().toByteArray(), true); } - 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: @@ -657,26 +606,26 @@ public class MediaControlGattService implements MediaControlGattServiceInterface private void onAuthorizedGattOperation(BluetoothDevice device, GattOpContext op) { UUID charUuid = - (op.mCharacteristic != null - ? op.mCharacteristic.getUuid() - : (op.mDescriptor != null - ? op.mDescriptor.getCharacteristic().getUuid() + (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 ? mcsUuidToString(charUuid) : "UNKNOWN")); int status = BluetoothGatt.GATT_SUCCESS; - switch (op.mOperation) { + switch (op.operation()) { case READ_CHARACTERISTIC: // Always ask for the latest position - if (op.mCharacteristic + if (op.characteristic() .getUuid() .equals(mCharacteristics.get(CharId.TRACK_POSITION).getUuid())) { long positionMs = mCallbacks.onGetCurrentTrackPosition(); @@ -691,110 +640,111 @@ public class MediaControlGattService implements MediaControlGattServiceInterface mBluetoothGattServer.sendResponse( device, - op.mRequestId, + op.requestId(), BluetoothGatt.GATT_SUCCESS, - op.mOffset, - Arrays.copyOfRange(bb.array(), op.mOffset, Integer.BYTES)); + op.offset(), + Arrays.copyOfRange(bb.array(), op.offset(), Integer.BYTES)); return; } - byte[] readRespValue = op.mCharacteristic.getValue(); + byte[] readRespValue = op.characteristic().getValue(); if (readRespValue != null) { - if (readRespValue.length >= op.mOffset) { + if (readRespValue.length >= op.offset()) { status = BluetoothGatt.GATT_SUCCESS; readRespValue = - Arrays.copyOfRange(readRespValue, op.mOffset, readRespValue.length); + Arrays.copyOfRange( + readRespValue, op.offset(), readRespValue.length); } else { 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: " + readRespValue.length)); status = BluetoothGatt.GATT_INVALID_OFFSET; readRespValue = new byte[] {}; } mBluetoothGattServer.sendResponse( - device, op.mRequestId, status, op.mOffset, readRespValue); + device, op.requestId(), status, op.offset(), readRespValue); } else { Log.e( TAG, "Missing characteristic value for char: " - + op.mCharacteristic.getUuid()); + + op.characteristic().getUuid()); mBluetoothGattServer.sendResponse( device, - op.mRequestId, + op.requestId(), BluetoothGatt.GATT_INVALID_ATTRIBUTE_LENGTH, - op.mOffset, + op.offset(), new byte[] {}); } break; case WRITE_CHARACTERISTIC: - 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 { CharacteristicWriteHandler handler = - mCharWriteCallback.get(op.mCharacteristic.getUuid()); + mCharWriteCallback.get(op.characteristic().getUuid()); handler.onCharacteristicWriteRequest( device, - op.mRequestId, - op.mCharacteristic, - op.mPreparedWrite, - op.mResponseNeeded, - op.mOffset, - op.mValue); + op.requestId(), + op.characteristic(), + op.preparedWrite(), + op.responseNeeded(), + op.offset(), + op.value().toByteArray()); break; } - 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; case READ_DESCRIPTOR: - if (op.mOffset > 1) { + if (op.offset() > 1) { mBluetoothGattServer.sendResponse( device, - op.mRequestId, + op.requestId(), BluetoothGatt.GATT_INVALID_OFFSET, - op.mOffset, + op.offset(), null); break; } - byte[] value = getCccBytes(device, op.mDescriptor.getCharacteristic().getUuid()); + byte[] value = getCccBytes(device, op.descriptor().getCharacteristic().getUuid()); if (value == null) { mBluetoothGattServer.sendResponse( - device, op.mRequestId, BluetoothGatt.GATT_FAILURE, op.mOffset, null); + device, op.requestId(), BluetoothGatt.GATT_FAILURE, op.offset(), null); break; } - value = Arrays.copyOfRange(value, op.mOffset, value.length); + value = Arrays.copyOfRange(value, op.offset(), value.length); mBluetoothGattServer.sendResponse( - device, op.mRequestId, BluetoothGatt.GATT_SUCCESS, op.mOffset, value); + device, op.requestId(), BluetoothGatt.GATT_SUCCESS, op.offset(), value); break; 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 { status = BluetoothGatt.GATT_SUCCESS; setCcc( device, - op.mDescriptor.getCharacteristic().getUuid(), - op.mOffset, - op.mValue, + op.descriptor().getCharacteristic().getUuid(), + op.offset(), + op.value().toByteArray(), true); } - 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; @@ -805,56 +755,56 @@ public class MediaControlGattService implements MediaControlGattServiceInterface private void onRejectedAuthorizationGattOperation(BluetoothDevice device, GattOpContext op) { UUID charUuid = - (op.mCharacteristic != null - ? op.mCharacteristic.getUuid() - : (op.mDescriptor != null - ? op.mDescriptor.getCharacteristic().getUuid() + (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 ? mcsUuidToString(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_MEDIA_CONTROL_POINT)) { + if (op.characteristic().getUuid().equals(UUID_MEDIA_CONTROL_POINT)) { setMediaControlRequestResult( - new Request(op.mValue[0], 0), + new Request(op.value().toByteArray()[0], 0), Request.Results.COMMAND_CANNOT_BE_COMPLETED); - } else if (op.mCharacteristic.getUuid().equals(UUID_SEARCH_CONTROL_POINT)) { + } else if (op.characteristic().getUuid().equals(UUID_SEARCH_CONTROL_POINT)) { setSearchRequestResult(null, SearchRequest.Results.FAILURE, 0); } } 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; @@ -1045,7 +995,7 @@ public class MediaControlGattService implements MediaControlGattServiceInterface preparedWrite, responseNeeded, offset, - value); + ByteString.copyFrom(value)); switch (getDeviceAuthorization(device)) { case BluetoothDevice.ACCESS_REJECTED: onRejectedAuthorizationGattOperation(device, op); @@ -1140,7 +1090,7 @@ public class MediaControlGattService implements MediaControlGattServiceInterface preparedWrite, responseNeeded, offset, - value); + ByteString.copyFrom(value)); switch (getDeviceAuthorization(device)) { case BluetoothDevice.ACCESS_REJECTED: onRejectedAuthorizationGattOperation(device, op); @@ -1395,7 +1345,7 @@ public class MediaControlGattService implements MediaControlGattServiceInterface if (mLeAudioService == null) { mLeAudioService = LeAudioService.getLeAudioService(); } - if (!isBroadcastActive() && req.getOpcode() == Request.Opcodes.PLAY) { + if (!isBroadcastActive() && req.opcode() == Request.Opcodes.PLAY) { if (mAdapterService.getActiveDevices(BluetoothProfile.A2DP).size() > 0) { A2dpService.getA2dpService().removeActiveDevice(false); } @@ -1586,7 +1536,7 @@ public class MediaControlGattService implements MediaControlGattServiceInterface } ByteBuffer bb = ByteBuffer.allocate(2).order(ByteOrder.LITTLE_ENDIAN); - bb.put((byte) request.getOpcode()); + bb.put((byte) request.opcode()); bb.put((byte) resultStatus.getValue()); BluetoothGattCharacteristic characteristic = diff --git a/android/app/src/com/android/bluetooth/mcp/MediaControlProfile.java b/android/app/src/com/android/bluetooth/mcp/MediaControlProfile.java index 7e25efec16..b96923ca7d 100644 --- a/android/app/src/com/android/bluetooth/mcp/MediaControlProfile.java +++ b/android/app/src/com/android/bluetooth/mcp/MediaControlProfile.java @@ -406,13 +406,13 @@ public class MediaControlProfile implements MediaControlServiceCallbacks { mEventLogger.logd( TAG, "GMCS onMediaControlRequest: opcode= " - + Request.Opcodes.toString(request.getOpcode())); + + Request.Opcodes.toString(request.opcode())); Request.Results status = Request.Results.COMMAND_CANNOT_BE_COMPLETED; if (Flags.mcpAllowPlayWithoutActivePlayer() && !Utils.isPtsTestMode() && mMediaPlayerList.getActivePlayer() == null - && request.getOpcode() == Request.Opcodes.PLAY) { + && request.opcode() == Request.Opcodes.PLAY) { Log.d(TAG, "Player is not active. GMCS send media key for PLAY"); mMediaPlayerList.sendMediaKeyEvent(BluetoothAvrcp.PASSTHROUGH_ID_PLAY, true); mMediaPlayerList.sendMediaKeyEvent(BluetoothAvrcp.PASSTHROUGH_ID_PLAY, false); @@ -430,7 +430,7 @@ public class MediaControlProfile implements MediaControlServiceCallbacks { } long actions = getCurrentPlayerSupportedActions(); - switch (request.getOpcode()) { + switch (request.opcode()) { case Request.Opcodes.PLAY: if ((actions & PlaybackState.ACTION_PLAY) != 0 || (actions & PlaybackState.ACTION_PLAY_PAUSE) != 0) { @@ -482,7 +482,7 @@ public class MediaControlProfile implements MediaControlServiceCallbacks { break; case Request.Opcodes.MOVE_RELATIVE: if ((actions & PlaybackState.ACTION_SEEK_TO) != 0) { - long requested_offset_ms = request.getIntArg(); + long requested_offset_ms = request.arg(); long current_pos_ms = getLatestTrackPosition(); long track_duration_ms = getCurrentTrackDuration(); diff --git a/android/app/src/com/android/bluetooth/mcp/Request.java b/android/app/src/com/android/bluetooth/mcp/Request.java index 8ef7d86599..30685cfba1 100644 --- a/android/app/src/com/android/bluetooth/mcp/Request.java +++ b/android/app/src/com/android/bluetooth/mcp/Request.java @@ -21,39 +21,13 @@ import static java.util.Map.entry; import java.util.Map; -/** Media control request, from client to Media Player */ -public final class Request { - private final int mOpcode; - private final Integer mIntArg; - - /** - * Media control request constructor - * - * @param opcode Control request opcode - * @param arg Control request argument - */ - public Request(int opcode, int arg) { - this.mOpcode = opcode; - this.mIntArg = arg; - } - - /** - * Media control results opcode getter - * - * @return Control request opcode - */ - public int getOpcode() { - return mOpcode; - } - - /** - * Media control results argument getter - * - * @return Control request argument - */ - public int getIntArg() { - return mIntArg; - } +/** + * Media control request, from client to Media Player + * + * @param opcode Control request opcode + * @param arg Control request argument + */ +record Request(int opcode, int arg) { /** Media control request results definition */ public enum Results { diff --git a/android/app/src/com/android/bluetooth/mcp/SearchRequest.java b/android/app/src/com/android/bluetooth/mcp/SearchRequest.java index 4c5137baeb..c1942b6e27 100644 --- a/android/app/src/com/android/bluetooth/mcp/SearchRequest.java +++ b/android/app/src/com/android/bluetooth/mcp/SearchRequest.java @@ -17,41 +17,8 @@ package com.android.bluetooth.mcp; -import android.annotation.NonNull; - /** Media search request, from client to Media Player */ -public final class SearchRequest { - private final int mType; - private final String mStringArg; - - /** - * Media search request constructor - * - * @param type Search request type - * @param arg Search request argument - */ - public SearchRequest(int type, String arg) { - this.mType = type; - this.mStringArg = arg; - } - - /** - * Media search request type getter - * - * @return Search request type - */ - public int getType() { - return mType; - } - - /** - * Media search request string argument getter - * - * @return search request argument - */ - public @NonNull String getStringArg() { - return mStringArg; - } +record SearchRequest(int type, String arg) { /** Media search request results definition */ public enum Results { diff --git a/android/app/src/com/android/bluetooth/notification/NotificationHelperService.java b/android/app/src/com/android/bluetooth/notification/NotificationHelperService.java index a9a7d9a408..e87bd90ae4 100644 --- a/android/app/src/com/android/bluetooth/notification/NotificationHelperService.java +++ b/android/app/src/com/android/bluetooth/notification/NotificationHelperService.java @@ -1,5 +1,5 @@ /* - * Copyright 2023 The Android Open Source Project + * Copyright (C) 2023 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/android/app/src/com/android/bluetooth/opp/BluetoothOppHandoverReceiver.java b/android/app/src/com/android/bluetooth/opp/BluetoothOppHandoverReceiver.java index d7865dd580..81c59f8ad2 100644 --- a/android/app/src/com/android/bluetooth/opp/BluetoothOppHandoverReceiver.java +++ b/android/app/src/com/android/bluetooth/opp/BluetoothOppHandoverReceiver.java @@ -60,22 +60,18 @@ public class BluetoothOppHandoverReceiver extends BroadcastReceiver { if (mimeType != null && uris != null && !uris.isEmpty()) { final Context finalContext = context; final ArrayList<Uri> finalUris = uris; - Thread t = - new Thread( - new Runnable() { - @Override - public void run() { - BluetoothOppManager.getInstance(finalContext) - .saveSendingFileInfo( - mimeType, - finalUris, - true /* isHandover */, - true /* fromExternal */); - BluetoothOppManager.getInstance(finalContext) - .startTransfer(device); - } - }); - t.start(); + new Thread( + () -> { + BluetoothOppManager.getInstance(finalContext) + .saveSendingFileInfo( + mimeType, + finalUris, + true /* isHandover */, + true /* fromExternal */); + BluetoothOppManager.getInstance(finalContext) + .startTransfer(device); + }) + .start(); } else { Log.d(TAG, "No mimeType or stream attached to handover request"); return; 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/opp/BluetoothOppNotification.java b/android/app/src/com/android/bluetooth/opp/BluetoothOppNotification.java index b094c60ae3..e8471acf6c 100644 --- a/android/app/src/com/android/bluetooth/opp/BluetoothOppNotification.java +++ b/android/app/src/com/android/bluetooth/opp/BluetoothOppNotification.java @@ -52,8 +52,7 @@ import com.android.bluetooth.BluetoothMethodProxy; import com.android.bluetooth.R; import com.android.bluetooth.Utils; import com.android.bluetooth.flags.Flags; - -import com.google.common.annotations.VisibleForTesting; +import com.android.internal.annotations.VisibleForTesting; import java.util.HashMap; diff --git a/android/app/src/com/android/bluetooth/opp/BluetoothOppObexClientSession.java b/android/app/src/com/android/bluetooth/opp/BluetoothOppObexClientSession.java index 6581c63644..666ed9b2fc 100644 --- a/android/app/src/com/android/bluetooth/opp/BluetoothOppObexClientSession.java +++ b/android/app/src/com/android/bluetooth/opp/BluetoothOppObexClientSession.java @@ -48,19 +48,17 @@ import android.os.SystemClock; import android.util.Log; import com.android.bluetooth.BluetoothMethodProxy; -import com.android.bluetooth.BluetoothMetricsProto; import com.android.bluetooth.BluetoothStatsLog; import com.android.bluetooth.btservice.MetricsLogger; import com.android.bluetooth.content_profiles.ContentProfileErrorReportUtils; import com.android.internal.annotations.GuardedBy; +import com.android.internal.annotations.VisibleForTesting; import com.android.obex.ClientOperation; import com.android.obex.ClientSession; import com.android.obex.HeaderSet; import com.android.obex.ObexTransport; import com.android.obex.ResponseCodes; -import com.google.common.annotations.VisibleForTesting; - import java.io.BufferedInputStream; import java.io.IOException; import java.io.InputStream; @@ -77,8 +75,6 @@ public class BluetoothOppObexClientSession implements BluetoothOppObexSession { private ClientThread mThread; private volatile boolean mInterrupted; - private int mNumFilesAttemptedToSend; - public BluetoothOppObexClientSession(Context context, ObexTransport transport) { mContext = requireNonNull(context); mTransport = requireNonNull(transport); @@ -176,7 +172,6 @@ public class BluetoothOppObexClientSession implements BluetoothOppObexSession { connect(mNumShares); } - mNumFilesAttemptedToSend = 0; while (!mInterrupted) { if (!mWaitingForShare) { doSend(); @@ -201,10 +196,6 @@ public class BluetoothOppObexClientSession implements BluetoothOppObexSession { mWakeLock.release(); } - if (mNumFilesAttemptedToSend > 0) { - // Log outgoing OPP transfer if more than one file is accepted by remote - MetricsLogger.logProfileConnectionEvent(BluetoothMetricsProto.ProfileId.OPP); - } Message msg = Message.obtain(mCallbackHandler); msg.what = BluetoothOppObexSession.MSG_SESSION_COMPLETE; msg.obj = mInfo; @@ -504,7 +495,6 @@ public class BluetoothOppObexClientSession implements BluetoothOppObexSession { updateValues.put(BluetoothShare.CURRENT_BYTES, position); mContext.getContentResolver() .update(contentUri, updateValues, null, null); - mNumFilesAttemptedToSend++; } else { Log.i(TAG, "Remote reject, Response code is " + responseCode); } diff --git a/android/app/src/com/android/bluetooth/opp/BluetoothOppObexServerSession.java b/android/app/src/com/android/bluetooth/opp/BluetoothOppObexServerSession.java index 9031df5c7d..e4d08c6fd9 100644 --- a/android/app/src/com/android/bluetooth/opp/BluetoothOppObexServerSession.java +++ b/android/app/src/com/android/bluetooth/opp/BluetoothOppObexServerSession.java @@ -47,12 +47,12 @@ import android.util.Log; import android.webkit.MimeTypeMap; import com.android.bluetooth.BluetoothMethodProxy; -import com.android.bluetooth.BluetoothMetricsProto; import com.android.bluetooth.BluetoothObexTransport; import com.android.bluetooth.BluetoothStatsLog; import com.android.bluetooth.Utils; import com.android.bluetooth.btservice.MetricsLogger; import com.android.bluetooth.content_profiles.ContentProfileErrorReportUtils; +import com.android.internal.annotations.VisibleForTesting; import com.android.obex.HeaderSet; import com.android.obex.ObexTransport; import com.android.obex.Operation; @@ -60,14 +60,12 @@ import com.android.obex.ResponseCodes; import com.android.obex.ServerRequestHandler; import com.android.obex.ServerSession; -import com.google.common.annotations.VisibleForTesting; -import com.google.common.base.Ascii; - import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.util.Arrays; +import java.util.Locale; /** This class runs as an OBEX server */ // Next tag value for ContentProfileErrorReportUtils.report(): 15 @@ -83,7 +81,6 @@ public class BluetoothOppObexServerSession extends ServerRequestHandler private long mTimestamp; private boolean mInterrupted; private int mLocalShareInfoId; // info id when we insert the record - private int mNumFilesAttemptedToReceive; @VisibleForTesting boolean mTimeoutMsgSent; @VisibleForTesting public ServerSession mSession; @VisibleForTesting BluetoothOppReceiveFileInfo mFileInfo; @@ -239,7 +236,7 @@ public class BluetoothOppObexServerSession extends ServerRequestHandler 5); return ResponseCodes.OBEX_HTTP_BAD_REQUEST; } else { - extension = Ascii.toLowerCase(name.substring(dotIndex + 1)); + extension = name.substring(dotIndex + 1).toLowerCase(Locale.ROOT); MimeTypeMap map = MimeTypeMap.getSingleton(); type = map.getMimeTypeFromExtension(extension); Log.v(TAG, "Mimetype guessed from extension " + extension + " is " + type); @@ -257,7 +254,7 @@ public class BluetoothOppObexServerSession extends ServerRequestHandler return ResponseCodes.OBEX_HTTP_UNSUPPORTED_TYPE; } } - mimeType = Ascii.toLowerCase(mimeType); + mimeType = mimeType.toLowerCase(Locale.ROOT); } // Reject anything outside the "acceptlist" plus unspecified MIME Types. @@ -363,7 +360,6 @@ public class BluetoothOppObexServerSession extends ServerRequestHandler || mAccepted == BluetoothShare.USER_CONFIRMATION_AUTO_CONFIRMED || mAccepted == BluetoothShare.USER_CONFIRMATION_HANDOVER_CONFIRMED) { /* Confirm or auto-confirm */ - mNumFilesAttemptedToReceive++; if (mFileInfo.mFileName == null) { status = mFileInfo.mStatus; @@ -650,17 +646,12 @@ public class BluetoothOppObexServerSession extends ServerRequestHandler Utils.getTempBroadcastOptions().toBundle()); } mTimestamp = System.currentTimeMillis(); - mNumFilesAttemptedToReceive = 0; return ResponseCodes.OBEX_HTTP_OK; } @Override public void onDisconnect(HeaderSet req, HeaderSet resp) { Log.d(TAG, "onDisconnect"); - if (mNumFilesAttemptedToReceive > 0) { - // Log incoming OPP transfer if more than one file is accepted by user - MetricsLogger.logProfileConnectionEvent(BluetoothMetricsProto.ProfileId.OPP); - } resp.responseCode = ResponseCodes.OBEX_HTTP_OK; } diff --git a/android/app/src/com/android/bluetooth/opp/BluetoothOppReceiveFileInfo.java b/android/app/src/com/android/bluetooth/opp/BluetoothOppReceiveFileInfo.java index 55004bbd1d..0ef16173e8 100644 --- a/android/app/src/com/android/bluetooth/opp/BluetoothOppReceiveFileInfo.java +++ b/android/app/src/com/android/bluetooth/opp/BluetoothOppReceiveFileInfo.java @@ -51,6 +51,7 @@ import java.nio.charset.StandardCharsets; import java.text.DateFormat; import java.text.SimpleDateFormat; import java.util.Calendar; +import java.util.Locale; /** * This class stores information about a single receiving file. It will only be used for inbounds @@ -164,7 +165,7 @@ public class BluetoothOppReceiveFileInfo { Log.d(Constants.TAG, "File name is too long. Name is truncated as: " + filename); } - DateFormat dateFormat = new SimpleDateFormat("_hhmmss"); + DateFormat dateFormat = new SimpleDateFormat("_hhmmss", Locale.ROOT); String currentTime = dateFormat.format(Calendar.getInstance().getTime()); String fullFilename = filename + currentTime + extension; diff --git a/android/app/src/com/android/bluetooth/opp/BluetoothOppTransferActivity.java b/android/app/src/com/android/bluetooth/opp/BluetoothOppTransferActivity.java index 6e9c0c5c19..cf8b1e3a47 100644 --- a/android/app/src/com/android/bluetooth/opp/BluetoothOppTransferActivity.java +++ b/android/app/src/com/android/bluetooth/opp/BluetoothOppTransferActivity.java @@ -54,8 +54,7 @@ import android.widget.Toast; import com.android.bluetooth.BluetoothStatsLog; import com.android.bluetooth.R; import com.android.bluetooth.content_profiles.ContentProfileErrorReportUtils; - -import com.google.common.annotations.VisibleForTesting; +import com.android.internal.annotations.VisibleForTesting; /** * Handle all transfer related dialogs: -Ongoing transfer -Receiving one file dialog -Sending one diff --git a/android/app/src/com/android/bluetooth/pan/BluetoothTetheringNetworkFactory.java b/android/app/src/com/android/bluetooth/pan/BluetoothTetheringNetworkFactory.java index 5143392d03..cd693d81f5 100644 --- a/android/app/src/com/android/bluetooth/pan/BluetoothTetheringNetworkFactory.java +++ b/android/app/src/com/android/bluetooth/pan/BluetoothTetheringNetworkFactory.java @@ -139,75 +139,68 @@ public class BluetoothTetheringNetworkFactory extends NetworkFactory { // TODO: Figure out how to replace this thread with simple invocations // of IpClient. This will likely necessitate a rethink about // NetworkAgent and associated instance lifetimes. - Thread ipProvisioningThread = - new Thread( - new Runnable() { - @Override - public void run() { - final WaitForProvisioningCallbacks ipcCallback; - final int ipClientStartIndex; + new Thread( + () -> { + final WaitForProvisioningCallbacks ipcCallback; + final int ipClientStartIndex; - synchronized (BluetoothTetheringNetworkFactory.this) { - if (TextUtils.isEmpty(mInterfaceName)) { - Log.e( - TAG, - "attempted to reverse tether without interface" - + " name"); - return; - } - log( - "ipProvisioningThread(+" - + mInterfaceName - + ") start IP provisioning"); - ipcCallback = startIpClientLocked(); - ipClientStartIndex = mIpClientStartIndex; - } - - final LinkProperties linkProperties = - ipcCallback.waitForProvisioning(); - if (linkProperties == null) { - Log.e(TAG, "IP provisioning error."); - synchronized (BluetoothTetheringNetworkFactory.this) { - stopIpClientLocked(); - setScoreFilter(-1); - } + synchronized (BluetoothTetheringNetworkFactory.this) { + if (TextUtils.isEmpty(mInterfaceName)) { + Log.e( + TAG, + "attempted to reverse tether without interface name"); return; } - final NetworkAgentConfig config = - new NetworkAgentConfig.Builder() - .setLegacyType(ConnectivityManager.TYPE_BLUETOOTH) - .setLegacyTypeName(NETWORK_TYPE) - .build(); + log( + "ipProvisioningThread(+" + + mInterfaceName + + ") start IP provisioning"); + ipcCallback = startIpClientLocked(); + ipClientStartIndex = mIpClientStartIndex; + } + final LinkProperties linkProperties = ipcCallback.waitForProvisioning(); + if (linkProperties == null) { + Log.e(TAG, "IP provisioning error."); synchronized (BluetoothTetheringNetworkFactory.this) { - // Reverse tethering has been stopped, and stopping won the race - // : there is - // no point in creating the agent (and it would be leaked), so - // bail. - if (ipClientStartIndex != mIpClientStartIndex) return; - // Create our NetworkAgent. - mNetworkAgent = - new NetworkAgent( - mContext, - getLooper(), - NETWORK_TYPE, - mNetworkCapabilities, - linkProperties, - NETWORK_SCORE, - config, - getProvider()) { - @Override - public void onNetworkUnwanted() { - BluetoothTetheringNetworkFactory.this - .onCancelRequest(); - } - }; - mNetworkAgent.register(); - mNetworkAgent.markConnected(); + stopIpClientLocked(); + setScoreFilter(-1); } + return; + } + final NetworkAgentConfig config = + new NetworkAgentConfig.Builder() + .setLegacyType(ConnectivityManager.TYPE_BLUETOOTH) + .setLegacyTypeName(NETWORK_TYPE) + .build(); + + synchronized (BluetoothTetheringNetworkFactory.this) { + // Reverse tethering has been stopped, and stopping won the race: + // there is no point in creating the agent (and it would be leaked), + // so bail. + if (ipClientStartIndex != mIpClientStartIndex) return; + // Create our NetworkAgent. + mNetworkAgent = + new NetworkAgent( + mContext, + getLooper(), + NETWORK_TYPE, + mNetworkCapabilities, + linkProperties, + NETWORK_SCORE, + config, + getProvider()) { + @Override + public void onNetworkUnwanted() { + BluetoothTetheringNetworkFactory.this + .onCancelRequest(); + } + }; + mNetworkAgent.register(); + mNetworkAgent.markConnected(); } - }); - ipProvisioningThread.start(); + }) + .start(); } // Called from NetworkFactory to indicate ConnectivityService no longer desires a Bluetooth diff --git a/android/app/src/com/android/bluetooth/pan/PanNativeInterface.java b/android/app/src/com/android/bluetooth/pan/PanNativeInterface.java index 76e91d8477..dc203821b2 100644 --- a/android/app/src/com/android/bluetooth/pan/PanNativeInterface.java +++ b/android/app/src/com/android/bluetooth/pan/PanNativeInterface.java @@ -1,5 +1,5 @@ /* - * Copyright 2023 The Android Open Source Project + * Copyright (C) 2023 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/android/app/src/com/android/bluetooth/pan/PanService.java b/android/app/src/com/android/bluetooth/pan/PanService.java index d873628c12..311e100b52 100644 --- a/android/app/src/com/android/bluetooth/pan/PanService.java +++ b/android/app/src/com/android/bluetooth/pan/PanService.java @@ -51,10 +51,8 @@ import android.os.UserManager; import android.sysprop.BluetoothProperties; import android.util.Log; -import com.android.bluetooth.BluetoothMetricsProto; import com.android.bluetooth.Utils; import com.android.bluetooth.btservice.AdapterService; -import com.android.bluetooth.btservice.MetricsLogger; import com.android.bluetooth.btservice.ProfileService; import com.android.bluetooth.btservice.storage.DatabaseManager; import com.android.bluetooth.flags.Flags; @@ -91,6 +89,7 @@ public class PanService extends ProfileService { private final TetheringManager mTetheringManager; private final UserManager mUserManager; private final int mMaxPanDevices; + private final PanServiceHandler mHandler; private String mPanIfName; @VisibleForTesting boolean mIsTethering = false; @@ -117,11 +116,11 @@ public class PanService extends ProfileService { }; public PanService(AdapterService adapterService) { - this(adapterService, null); + this(adapterService, null, Looper.getMainLooper()); } @VisibleForTesting - PanService(AdapterService adapterService, PanNativeInterface nativeInterface) { + PanService(AdapterService adapterService, PanNativeInterface nativeInterface, Looper looper) { super(requireNonNull(adapterService)); mAdapterService = adapterService; mDatabaseManager = requireNonNull(mAdapterService.getDatabase()); @@ -129,6 +128,7 @@ public class PanService extends ProfileService { requireNonNullElseGet(nativeInterface, () -> new PanNativeInterface(this)); mUserManager = requireNonNull(getSystemService(UserManager.class)); mTetheringManager = requireNonNull(getSystemService(TetheringManager.class)); + mHandler = new PanServiceHandler(looper); int maxPanDevice; try { @@ -178,7 +178,12 @@ public class PanService extends ProfileService { public void cleanup() { Log.i(TAG, "Cleanup Pan Service"); - mTetheringManager.unregisterTetheringEventCallback(mTetheringCallback); + try { + mTetheringManager.unregisterTetheringEventCallback(mTetheringCallback); + // IllegalStateException could be thrown from the manager. + } catch (IllegalStateException e) { + Log.e(TAG, "cleanup(): failed to unregister tethering event callback"); + } mNativeInterface.cleanup(); mHandler.removeCallbacksAndMessages(null); @@ -202,81 +207,74 @@ public class PanService extends ProfileService { mHandler.removeCallbacksAndMessages(null); } - private final Handler mHandler = - new Handler(Looper.getMainLooper()) { - @Override - public void handleMessage(Message msg) { - switch (msg.what) { - case MESSAGE_CONNECT: - BluetoothDevice connectDevice = (BluetoothDevice) msg.obj; - if (!mNativeInterface.connect( - Flags.identityAddressNullIfNotKnown() - ? Utils.getByteBrEdrAddress( - mAdapterService, connectDevice) - : mAdapterService.getByteIdentityAddress( - connectDevice))) { - handlePanDeviceStateChange( - connectDevice, - null, - STATE_CONNECTING, - BluetoothPan.LOCAL_PANU_ROLE, - BluetoothPan.REMOTE_NAP_ROLE); - handlePanDeviceStateChange( - connectDevice, - null, - STATE_DISCONNECTED, - BluetoothPan.LOCAL_PANU_ROLE, - BluetoothPan.REMOTE_NAP_ROLE); - } - break; - case MESSAGE_DISCONNECT: - BluetoothDevice disconnectDevice = (BluetoothDevice) msg.obj; - if (!mNativeInterface.disconnect( - Flags.identityAddressNullIfNotKnown() - ? Utils.getByteBrEdrAddress( - mAdapterService, disconnectDevice) - : mAdapterService.getByteIdentityAddress( - disconnectDevice))) { - handlePanDeviceStateChange( - disconnectDevice, - mPanIfName, - STATE_DISCONNECTING, - BluetoothPan.LOCAL_PANU_ROLE, - BluetoothPan.REMOTE_NAP_ROLE); - handlePanDeviceStateChange( - disconnectDevice, - mPanIfName, - STATE_DISCONNECTED, - BluetoothPan.LOCAL_PANU_ROLE, - BluetoothPan.REMOTE_NAP_ROLE); - } - break; - case MESSAGE_CONNECT_STATE_CHANGED: - ConnectState cs = (ConnectState) msg.obj; - final BluetoothDevice device = - mAdapterService.getDeviceFromByte(cs.addr); - // TBD get iface from the msg - Log.d( - TAG, - "MESSAGE_CONNECT_STATE_CHANGED: " - + device - + " state: " - + cs.state); - // It could be null if the connection up is coming when the - // Bluetooth is turning off. - if (device == null) { - break; - } - handlePanDeviceStateChange( - device, - mPanIfName /* iface */, - cs.state, - cs.local_role, - cs.remote_role); - break; + private class PanServiceHandler extends Handler { + PanServiceHandler(Looper looper) { + super(looper); + } + + @Override + public void handleMessage(Message msg) { + switch (msg.what) { + case MESSAGE_CONNECT: + BluetoothDevice connectDevice = (BluetoothDevice) msg.obj; + if (!mNativeInterface.connect( + Flags.identityAddressNullIfNotKnown() + ? Utils.getByteBrEdrAddress(mAdapterService, connectDevice) + : mAdapterService.getByteIdentityAddress(connectDevice))) { + handlePanDeviceStateChange( + connectDevice, + null, + STATE_CONNECTING, + BluetoothPan.LOCAL_PANU_ROLE, + BluetoothPan.REMOTE_NAP_ROLE); + handlePanDeviceStateChange( + connectDevice, + null, + STATE_DISCONNECTED, + BluetoothPan.LOCAL_PANU_ROLE, + BluetoothPan.REMOTE_NAP_ROLE); } - } - }; + break; + case MESSAGE_DISCONNECT: + BluetoothDevice disconnectDevice = (BluetoothDevice) msg.obj; + if (!mNativeInterface.disconnect( + Flags.identityAddressNullIfNotKnown() + ? Utils.getByteBrEdrAddress(mAdapterService, disconnectDevice) + : mAdapterService.getByteIdentityAddress(disconnectDevice))) { + handlePanDeviceStateChange( + disconnectDevice, + mPanIfName, + STATE_DISCONNECTING, + BluetoothPan.LOCAL_PANU_ROLE, + BluetoothPan.REMOTE_NAP_ROLE); + handlePanDeviceStateChange( + disconnectDevice, + mPanIfName, + STATE_DISCONNECTED, + BluetoothPan.LOCAL_PANU_ROLE, + BluetoothPan.REMOTE_NAP_ROLE); + } + break; + case MESSAGE_CONNECT_STATE_CHANGED: + ConnectState cs = (ConnectState) msg.obj; + final BluetoothDevice device = mAdapterService.getDeviceFromByte(cs.addr); + // TBD get iface from the msg + Log.d(TAG, "MESSAGE_CONNECT_STATE_CHANGED: " + device + " state: " + cs.state); + // It could be null if the connection up is coming when the + // Bluetooth is turning off. + if (device == null) { + break; + } + handlePanDeviceStateChange( + device, + mPanIfName /* iface */, + cs.state, + cs.local_role, + cs.remote_role); + break; + } + } + } /** Handlers for incoming service calls */ @VisibleForTesting @@ -698,9 +696,7 @@ public class PanService extends ProfileService { mPanDevices.remove(device); } } - if (state == STATE_CONNECTED) { - MetricsLogger.logProfileConnectionEvent(BluetoothMetricsProto.ProfileId.PAN); - } + mAdapterService.updateProfileConnectionAdapterProperties( device, BluetoothProfile.PAN, state, prevState); diff --git a/android/app/src/com/android/bluetooth/pbap/BluetoothPbapCallLogComposer.java b/android/app/src/com/android/bluetooth/pbap/BluetoothPbapCallLogComposer.java index 85f07b687b..6ace2fb35c 100644 --- a/android/app/src/com/android/bluetooth/pbap/BluetoothPbapCallLogComposer.java +++ b/android/app/src/com/android/bluetooth/pbap/BluetoothPbapCallLogComposer.java @@ -39,6 +39,7 @@ import com.android.vcard.VCardUtils; import java.text.SimpleDateFormat; import java.util.Arrays; import java.util.Calendar; +import java.util.Locale; /** VCard composer especially for Call Log used in Bluetooth. */ // Next tag value for ContentProfileErrorReportUtils.report(): 3 @@ -223,7 +224,7 @@ public class BluetoothPbapCallLogComposer implements AutoCloseable { String rfc2455Format = "yyyyMMdd'T'HHmmss"; Calendar cal = Calendar.getInstance(); cal.setTimeInMillis(millSecs); - SimpleDateFormat df = new SimpleDateFormat(rfc2455Format); + SimpleDateFormat df = new SimpleDateFormat(rfc2455Format, Locale.ROOT); return df.format(cal.getTime()); } diff --git a/android/app/src/com/android/bluetooth/pbap/BluetoothPbapObexServer.java b/android/app/src/com/android/bluetooth/pbap/BluetoothPbapObexServer.java index a9957e7891..88f7023b03 100644 --- a/android/app/src/com/android/bluetooth/pbap/BluetoothPbapObexServer.java +++ b/android/app/src/com/android/bluetooth/pbap/BluetoothPbapObexServer.java @@ -32,6 +32,7 @@ import android.util.Log; import com.android.bluetooth.BluetoothMethodProxy; import com.android.bluetooth.BluetoothStatsLog; import com.android.bluetooth.content_profiles.ContentProfileErrorReportUtils; +import com.android.bluetooth.flags.Flags; import com.android.internal.annotations.VisibleForTesting; import com.android.obex.ApplicationParameter; import com.android.obex.HeaderSet; @@ -39,8 +40,6 @@ import com.android.obex.Operation; import com.android.obex.ResponseCodes; import com.android.obex.ServerRequestHandler; -import com.google.common.base.Ascii; - import java.io.IOException; import java.io.OutputStream; import java.nio.ByteBuffer; @@ -50,6 +49,7 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.List; +import java.util.Locale; // Next tag value for ContentProfileErrorReportUtils.report(): 34 public class BluetoothPbapObexServer extends ServerRequestHandler { @@ -1006,7 +1006,7 @@ public class BluetoothPbapObexServer extends ServerRequestHandler { List<Integer> savedPosList = new ArrayList<>(); List<String> selectedNameList = new ArrayList<String>(); if (appParamValue.searchValue != null) { - compareValue = Ascii.toLowerCase(appParamValue.searchValue.trim()); + compareValue = appParamValue.searchValue.trim().toLowerCase(Locale.ROOT); } for (int pos = 0; pos < listSize; pos++) { @@ -1018,8 +1018,9 @@ public class BluetoothPbapObexServer extends ServerRequestHandler { if (appParamValue.searchValue != null) { if (appParamValue.searchValue.isEmpty() - || Ascii.toLowerCase(currentValue) - .startsWith(Ascii.toLowerCase(compareValue))) { + || currentValue + .toLowerCase(Locale.ROOT) + .startsWith(compareValue.toLowerCase(Locale.ROOT))) { selectedNameList.add(currentValue); savedPosList.add(pos); } @@ -1517,6 +1518,19 @@ public class BluetoothPbapObexServer extends ServerRequestHandler { startIndex = 0; lastIndex = pbSize - 1; } + + if (Flags.pbapLimitCallLog()) { + // Limit the number of call log to CALLLOG_NUM_LIMIT + if ((appParamValue.needTag != BluetoothPbapObexServer.ContentType.PHONEBOOK) + && (appParamValue.needTag != BluetoothPbapObexServer.ContentType.FAVORITES) + && (appParamValue.needTag + != BluetoothPbapObexServer.ContentType.SIM_PHONEBOOK)) { + if (requestSize > CALLLOG_NUM_LIMIT) { + requestSize = CALLLOG_NUM_LIMIT; + } + } + } + // [startPoint, endPoint] denote the range of vcf indices to send, inclusive. int startPoint = startIndex + appParamValue.listStartOffset; int endPoint = startPoint + requestSize - 1; @@ -1533,12 +1547,15 @@ public class BluetoothPbapObexServer extends ServerRequestHandler { endPoint = lastIndex; } - // Limit the number of call log to CALLLOG_NUM_LIMIT - if ((appParamValue.needTag != BluetoothPbapObexServer.ContentType.PHONEBOOK) - && (appParamValue.needTag != BluetoothPbapObexServer.ContentType.FAVORITES) - && (appParamValue.needTag != BluetoothPbapObexServer.ContentType.SIM_PHONEBOOK)) { - if (requestSize > CALLLOG_NUM_LIMIT) { - requestSize = CALLLOG_NUM_LIMIT; + if (!Flags.pbapLimitCallLog()) { + // Limit the number of call log to CALLLOG_NUM_LIMIT + if ((appParamValue.needTag != BluetoothPbapObexServer.ContentType.PHONEBOOK) + && (appParamValue.needTag != BluetoothPbapObexServer.ContentType.FAVORITES) + && (appParamValue.needTag + != BluetoothPbapObexServer.ContentType.SIM_PHONEBOOK)) { + if (requestSize > CALLLOG_NUM_LIMIT) { + requestSize = CALLLOG_NUM_LIMIT; + } } } diff --git a/android/app/src/com/android/bluetooth/pbap/BluetoothPbapService.java b/android/app/src/com/android/bluetooth/pbap/BluetoothPbapService.java index a63006065d..00194f5d78 100644 --- a/android/app/src/com/android/bluetooth/pbap/BluetoothPbapService.java +++ b/android/app/src/com/android/bluetooth/pbap/BluetoothPbapService.java @@ -24,6 +24,8 @@ import static android.bluetooth.BluetoothProfile.CONNECTION_POLICY_ALLOWED; import static android.bluetooth.BluetoothProfile.CONNECTION_POLICY_FORBIDDEN; import static android.bluetooth.BluetoothProfile.STATE_DISCONNECTED; +import static com.android.bluetooth.Utils.joinUninterruptibly; + import static java.util.Objects.requireNonNull; import android.annotation.RequiresPermission; @@ -67,12 +69,11 @@ import com.android.bluetooth.btservice.InteropUtil; import com.android.bluetooth.btservice.ProfileService; import com.android.bluetooth.btservice.storage.DatabaseManager; import com.android.bluetooth.content_profiles.ContentProfileErrorReportUtils; +import com.android.bluetooth.flags.Flags; import com.android.bluetooth.sdp.SdpManagerNativeInterface; import com.android.bluetooth.util.DevicePolicyUtils; import com.android.internal.annotations.VisibleForTesting; -import com.google.common.util.concurrent.Uninterruptibles; - import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; @@ -123,6 +124,7 @@ public class BluetoothPbapService extends ProfileService implements IObexConnect static final int ROLLOVER_COUNTERS = 7; private static final int GET_LOCAL_TELEPHONY_DETAILS = 8; private static final int HANDLE_VERSION_UPDATE_NOTIFICATION = 9; + private static final int HANDLE_ACCEPT_FAILED = 10; static final int USER_CONFIRM_TIMEOUT_VALUE = 30000; private static final int RELEASE_WAKE_LOCK_DELAY_MS = 10000; @@ -257,7 +259,6 @@ public class BluetoothPbapService extends ProfileService implements IObexConnect } } - private void parseIntent(final Intent intent) { String action = intent.getAction(); Log.d(TAG, "action: " + action); @@ -611,6 +612,9 @@ public class BluetoothPbapService extends ProfileService implements IObexConnect handleNotificationTask(remoteDev); break; + case HANDLE_ACCEPT_FAILED: + handleAcceptFailed(); + break; default: break; } @@ -740,7 +744,7 @@ public class BluetoothPbapService extends ProfileService implements IObexConnect setBluetoothPbapService(null); mSessionStatusHandler.sendEmptyMessage(SHUTDOWN); mHandlerThread.quitSafely(); - Uninterruptibles.joinUninterruptibly(mHandlerThread); + joinUninterruptibly(mHandlerThread); mContactsLoaded = false; unregisterReceiver(mPbapReceiver); mAdapterService.getContentResolver().unregisterContentObserver(mContactChangeObserver); @@ -752,11 +756,8 @@ public class BluetoothPbapService extends ProfileService implements IObexConnect } /** - * Get the current instance of {@link BluetoothPbapService} - * * @return current instance of {@link BluetoothPbapService} */ - @VisibleForTesting public static synchronized BluetoothPbapService getBluetoothPbapService() { if (sBluetoothPbapService == null) { Log.w(TAG, "getBluetoothPbapService(): service is null"); @@ -957,6 +958,14 @@ public class BluetoothPbapService extends ProfileService implements IObexConnect BluetoothStatsLog.BLUETOOTH_CONTENT_PROFILE_ERROR_REPORTED__TYPE__LOG_WARN, 11); + if (Flags.pbapCleanupUseHandler()) { + mSessionStatusHandler.sendEmptyMessage(HANDLE_ACCEPT_FAILED); + } else { + handleAcceptFailed(); + } + } + + private void handleAcceptFailed() { if (mWakeLock != null) { mWakeLock.release(); mWakeLock = null; @@ -975,32 +984,26 @@ public class BluetoothPbapService extends ProfileService implements IObexConnect private void loadAllContacts() { if (mThreadLoadContacts == null) { - Runnable r = - new Runnable() { - @Override - public void run() { - BluetoothPbapUtils.loadAllContacts( - BluetoothPbapService.this, mSessionStatusHandler); - mThreadLoadContacts = null; - } - }; - mThreadLoadContacts = new Thread(r); + mThreadLoadContacts = + new Thread( + () -> { + BluetoothPbapUtils.loadAllContacts( + BluetoothPbapService.this, mSessionStatusHandler); + mThreadLoadContacts = null; + }); mThreadLoadContacts.start(); } } private void updateSecondaryVersion() { if (mThreadUpdateSecVersionCounter == null) { - Runnable r = - new Runnable() { - @Override - public void run() { - BluetoothPbapUtils.updateSecondaryVersionCounter( - BluetoothPbapService.this, mSessionStatusHandler); - mThreadUpdateSecVersionCounter = null; - } - }; - mThreadUpdateSecVersionCounter = new Thread(r); + mThreadUpdateSecVersionCounter = + new Thread( + () -> { + BluetoothPbapUtils.updateSecondaryVersionCounter( + BluetoothPbapService.this, mSessionStatusHandler); + mThreadUpdateSecVersionCounter = null; + }); mThreadUpdateSecVersionCounter.start(); } } diff --git a/android/app/src/com/android/bluetooth/pbap/HandlerForStringBuffer.java b/android/app/src/com/android/bluetooth/pbap/HandlerForStringBuffer.java index 0d9a45b285..7d6333eea1 100644 --- a/android/app/src/com/android/bluetooth/pbap/HandlerForStringBuffer.java +++ b/android/app/src/com/android/bluetooth/pbap/HandlerForStringBuffer.java @@ -1,5 +1,5 @@ /* - * Copyright 2022 The Android Open Source Project + * Copyright (C) 2022 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. diff --git a/android/app/src/com/android/bluetooth/pbap/PbapStateMachine.java b/android/app/src/com/android/bluetooth/pbap/PbapStateMachine.java index d0a756ac0d..b0c2d11a45 100644 --- a/android/app/src/com/android/bluetooth/pbap/PbapStateMachine.java +++ b/android/app/src/com/android/bluetooth/pbap/PbapStateMachine.java @@ -1,5 +1,5 @@ /* - * Copyright 2017 The Android Open Source Project + * Copyright (C) 2017 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. @@ -39,14 +39,12 @@ import android.os.Message; import android.os.UserHandle; import android.util.Log; -import com.android.bluetooth.BluetoothMetricsProto; import com.android.bluetooth.BluetoothObexTransport; import com.android.bluetooth.BluetoothStatsLog; import com.android.bluetooth.ObexRejectServer; import com.android.bluetooth.R; import com.android.bluetooth.Utils; import com.android.bluetooth.btservice.AdapterService; -import com.android.bluetooth.btservice.MetricsLogger; import com.android.bluetooth.content_profiles.ContentProfileErrorReportUtils; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.annotations.VisibleForTesting.Visibility; @@ -355,7 +353,6 @@ public class PbapStateMachine extends StateMachine { Log.e(TAG, "Caught exception starting OBEX server session" + ex.toString()); } broadcastStateTransitions(); - MetricsLogger.logProfileConnectionEvent(BluetoothMetricsProto.ProfileId.PBAP); mService.setConnectionPolicy(mRemoteDevice, CONNECTION_POLICY_ALLOWED); } diff --git a/android/app/src/com/android/bluetooth/pbapclient/PbapClientContactsStorage.java b/android/app/src/com/android/bluetooth/pbapclient/PbapClientContactsStorage.java index 9d064c7598..e0fb87f7a8 100644 --- a/android/app/src/com/android/bluetooth/pbapclient/PbapClientContactsStorage.java +++ b/android/app/src/com/android/bluetooth/pbapclient/PbapClientContactsStorage.java @@ -42,6 +42,7 @@ import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Collections; import java.util.List; +import java.util.Locale; /** * This class owns the interface to the contacts and call history storage mechanism, namely the @@ -505,7 +506,7 @@ class PbapClientContactsStorage { } List<Pair<String, String>> irmc = call.getUnknownXData(); - SimpleDateFormat parser = new SimpleDateFormat(TIMESTAMP_FORMAT); + SimpleDateFormat parser = new SimpleDateFormat(TIMESTAMP_FORMAT, Locale.ROOT); if (irmc != null) { for (Pair<String, String> pair : irmc) { if (pair.first.startsWith(CALL_LOG_TIMESTAMP_PROPERTY)) { diff --git a/android/app/src/com/android/bluetooth/pbapclient/PbapClientStateMachine.java b/android/app/src/com/android/bluetooth/pbapclient/PbapClientStateMachine.java index caa9584445..ee09597feb 100644 --- a/android/app/src/com/android/bluetooth/pbapclient/PbapClientStateMachine.java +++ b/android/app/src/com/android/bluetooth/pbapclient/PbapClientStateMachine.java @@ -34,7 +34,6 @@ import android.os.Looper; import android.os.Message; import android.util.Log; -import com.android.bluetooth.BluetoothMetricsProto; import com.android.bluetooth.Utils; import com.android.bluetooth.btservice.AdapterService; import com.android.bluetooth.btservice.MetricsLogger; @@ -144,9 +143,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 +162,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 +604,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 +612,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( @@ -908,9 +907,6 @@ class PbapClientStateMachine extends StateMachine { private void onConnectionStateChanged(int state) { int prevState = mCurrentState; - if (prevState != state && state == STATE_CONNECTED) { - MetricsLogger.logProfileConnectionEvent(BluetoothMetricsProto.ProfileId.PBAP_CLIENT); - } Intent intent = new Intent(BluetoothPbapClient.ACTION_CONNECTION_STATE_CHANGED); intent.putExtra(BluetoothProfile.EXTRA_PREVIOUS_STATE, prevState); diff --git a/android/app/src/com/android/bluetooth/pbapclient/PbapClientStateMachineOld.java b/android/app/src/com/android/bluetooth/pbapclient/PbapClientStateMachineOld.java index 20f179579b..1cc8be9dbd 100644 --- a/android/app/src/com/android/bluetooth/pbapclient/PbapClientStateMachineOld.java +++ b/android/app/src/com/android/bluetooth/pbapclient/PbapClientStateMachineOld.java @@ -48,6 +48,8 @@ import static android.bluetooth.BluetoothProfile.STATE_CONNECTING; import static android.bluetooth.BluetoothProfile.STATE_DISCONNECTED; import static android.bluetooth.BluetoothProfile.STATE_DISCONNECTING; +import static com.android.bluetooth.Utils.joinUninterruptibly; + import android.bluetooth.BluetoothDevice; import android.bluetooth.BluetoothPbapClient; import android.bluetooth.BluetoothProfile; @@ -61,7 +63,6 @@ import android.os.Process; import android.os.UserManager; import android.util.Log; -import com.android.bluetooth.BluetoothMetricsProto; import com.android.bluetooth.Utils; import com.android.bluetooth.btservice.AdapterService; import com.android.bluetooth.btservice.MetricsLogger; @@ -72,8 +73,6 @@ import com.android.internal.util.IState; import com.android.internal.util.State; import com.android.internal.util.StateMachine; -import com.google.common.util.concurrent.Uninterruptibles; - import java.util.ArrayList; import java.util.List; @@ -403,9 +402,6 @@ class PbapClientStateMachineOld extends StateMachine { Log.w(TAG, "onConnectionStateChanged with invalid device"); return; } - if (prevState != state && state == STATE_CONNECTED) { - MetricsLogger.logProfileConnectionEvent(BluetoothMetricsProto.ProfileId.PBAP_CLIENT); - } Log.d(TAG, "Connection state " + device + ": " + prevState + "->" + state); AdapterService adapterService = AdapterService.getAdapterService(); if (adapterService != null) { @@ -442,11 +438,11 @@ class PbapClientStateMachineOld extends StateMachine { HandlerThread handlerThread = mHandlerThread; if (handlerThread != null) { handlerThread.quitSafely(); - Uninterruptibles.joinUninterruptibly(handlerThread); + joinUninterruptibly(handlerThread); mHandlerThread = null; } mSmHandlerThread.quitSafely(); - Uninterruptibles.joinUninterruptibly(mSmHandlerThread); + joinUninterruptibly(mSmHandlerThread); quitNow(); } diff --git a/android/app/src/com/android/bluetooth/pbapclient/obex/CallLogPullRequest.java b/android/app/src/com/android/bluetooth/pbapclient/obex/CallLogPullRequest.java index 3d276dd88b..aef9c9cef5 100644 --- a/android/app/src/com/android/bluetooth/pbapclient/obex/CallLogPullRequest.java +++ b/android/app/src/com/android/bluetooth/pbapclient/obex/CallLogPullRequest.java @@ -38,6 +38,7 @@ import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.List; +import java.util.Locale; import java.util.Map; public class CallLogPullRequest extends PullRequest { @@ -106,7 +107,7 @@ public class CallLogPullRequest extends PullRequest { } } List<Pair<String, String>> irmc = vcard.getUnknownXData(); - SimpleDateFormat parser = new SimpleDateFormat(TIMESTAMP_FORMAT); + SimpleDateFormat parser = new SimpleDateFormat(TIMESTAMP_FORMAT, Locale.ROOT); if (irmc != null) { for (Pair<String, String> pair : irmc) { if (pair.first.startsWith(TIMESTAMP_PROPERTY)) { 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/sap/SapService.java b/android/app/src/com/android/bluetooth/sap/SapService.java index 277acc4cf2..c8bda8e046 100644 --- a/android/app/src/com/android/bluetooth/sap/SapService.java +++ b/android/app/src/com/android/bluetooth/sap/SapService.java @@ -1,5 +1,5 @@ /* - * Copyright 2024 The Android Open Source Project + * Copyright (C) 2024 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. @@ -52,11 +52,9 @@ import android.sysprop.BluetoothProperties; import android.text.TextUtils; import android.util.Log; -import com.android.bluetooth.BluetoothMetricsProto; import com.android.bluetooth.R; import com.android.bluetooth.Utils; import com.android.bluetooth.btservice.AdapterService; -import com.android.bluetooth.btservice.MetricsLogger; import com.android.bluetooth.btservice.ProfileService; import com.android.bluetooth.sdp.SdpManagerNativeInterface; import com.android.internal.annotations.VisibleForTesting; @@ -539,9 +537,6 @@ public class SapService extends ProfileService implements AdapterService.Bluetoo private synchronized void setState(int state, int result) { if (state != mState) { Log.d(TAG, "Sap state " + mState + " -> " + state + ", result = " + result); - if (state == STATE_CONNECTED) { - MetricsLogger.logProfileConnectionEvent(BluetoothMetricsProto.ProfileId.SAP); - } int prevState = mState; mState = state; mAdapterService.updateProfileConnectionAdapterProperties( @@ -710,11 +705,8 @@ public class SapService extends ProfileService implements AdapterService.Bluetoo } /** - * Get the current instance of {@link SapService} - * * @return current instance of {@link SapService} */ - @VisibleForTesting public static synchronized SapService getSapService() { if (sSapService == null) { Log.w(TAG, "getSapService(): service is null"); diff --git a/android/app/src/com/android/bluetooth/sdp/SdpManagerNativeInterface.java b/android/app/src/com/android/bluetooth/sdp/SdpManagerNativeInterface.java index f009dd9c0e..e21d1e33e7 100644 --- a/android/app/src/com/android/bluetooth/sdp/SdpManagerNativeInterface.java +++ b/android/app/src/com/android/bluetooth/sdp/SdpManagerNativeInterface.java @@ -1,5 +1,5 @@ /* - * Copyright 2023 The Android Open Source Project + * Copyright (C) 2023 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/android/app/src/com/android/bluetooth/tbs/TbsGatt.java b/android/app/src/com/android/bluetooth/tbs/TbsGatt.java index 871e6d7b62..ce54586bd1 100644 --- a/android/app/src/com/android/bluetooth/tbs/TbsGatt.java +++ b/android/app/src/com/android/bluetooth/tbs/TbsGatt.java @@ -38,9 +38,12 @@ import android.util.Log; import com.android.bluetooth.BluetoothEventLogger; import com.android.bluetooth.Utils; import com.android.bluetooth.btservice.AdapterService; +import com.android.bluetooth.mcp.GattOpContext; 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 +99,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 +129,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,59 +148,6 @@ public class TbsGatt { public abstract boolean isInbandRingtoneEnabled(BluetoothDevice device); } - private static class GattOpContext { - public enum Operation { - READ_CHARACTERISTIC, - WRITE_CHARACTERISTIC, - READ_DESCRIPTOR, - WRITE_DESCRIPTOR, - } - - GattOpContext( - Operation operation, - 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; - } - - 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) { this(adapterService, tbsService, new BluetoothGattServerProxy(adapterService)); } @@ -314,7 +229,6 @@ public class TbsGatt { BluetoothGattCharacteristic.PROPERTY_READ | BluetoothGattCharacteristic.PROPERTY_NOTIFY, BluetoothGattCharacteristic.PERMISSION_READ_ENCRYPTED); - } public boolean init( @@ -372,12 +286,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 +349,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 +957,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 +1018,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 +1078,87 @@ 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 +1187,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 +1215,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 +1226,29 @@ 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 +1259,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 +1284,18 @@ 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 +1306,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 +1545,7 @@ public class TbsGatt { preparedWrite, responseNeeded, offset, - value); + ByteString.copyFrom(value)); switch (getDeviceAuthorization(device)) { case BluetoothDevice.ACCESS_REJECTED: onRejectedAuthorizationGattOperation(device, op); @@ -1686,7 +1640,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/src/com/android/bluetooth/util/SystemProperties.java b/android/app/src/com/android/bluetooth/util/SystemProperties.java index 29c5a1be7b..b508926daa 100644 --- a/android/app/src/com/android/bluetooth/util/SystemProperties.java +++ b/android/app/src/com/android/bluetooth/util/SystemProperties.java @@ -1,5 +1,5 @@ /* - * Copyright 2025 The Android Open Source Project + * Copyright (C) 2025 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/android/app/src/com/android/bluetooth/vc/VolumeControlInputDescriptor.java b/android/app/src/com/android/bluetooth/vc/VolumeControlInputDescriptor.java index 5a1e3580b3..c9e5dcbe12 100644 --- a/android/app/src/com/android/bluetooth/vc/VolumeControlInputDescriptor.java +++ b/android/app/src/com/android/bluetooth/vc/VolumeControlInputDescriptor.java @@ -16,7 +16,7 @@ package com.android.bluetooth.vc; -import static com.android.bluetooth.Utils.RemoteExceptionIgnoringConsumer; +import static android.bluetooth.BluetoothUtils.RemoteExceptionIgnoringConsumer; import static java.util.Objects.requireNonNull; diff --git a/android/app/src/com/android/bluetooth/vc/VolumeControlNativeCallback.java b/android/app/src/com/android/bluetooth/vc/VolumeControlNativeCallback.java index be86010bc2..a7b6234e6b 100644 --- a/android/app/src/com/android/bluetooth/vc/VolumeControlNativeCallback.java +++ b/android/app/src/com/android/bluetooth/vc/VolumeControlNativeCallback.java @@ -1,5 +1,5 @@ /* - * Copyright 2024 The Android Open Source Project + * Copyright (C) 2024 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. diff --git a/android/app/tests/instrumentation/com/android/bluetooth/opp/BluetoothOppLauncherActivityTest.java b/android/app/tests/instrumentation/com/android/bluetooth/opp/BluetoothOppLauncherActivityTest.java index 5e894594d5..fd9531105b 100644 --- a/android/app/tests/instrumentation/com/android/bluetooth/opp/BluetoothOppLauncherActivityTest.java +++ b/android/app/tests/instrumentation/com/android/bluetooth/opp/BluetoothOppLauncherActivityTest.java @@ -16,6 +16,8 @@ package com.android.bluetooth.opp; +import static android.platform.test.flag.junit.DeviceFlagsValueProvider.createCheckFlagsRule; + import static androidx.test.espresso.intent.Intents.intended; import static androidx.test.espresso.intent.matcher.IntentMatchers.hasAction; import static androidx.test.espresso.intent.matcher.IntentMatchers.hasComponent; @@ -41,9 +43,9 @@ import android.content.ContextWrapper; import android.content.Intent; import android.content.pm.PackageManager; import android.net.Uri; -import android.platform.test.annotations.DisableFlags; -import android.platform.test.annotations.EnableFlags; -import android.platform.test.flag.junit.SetFlagsRule; +import android.platform.test.annotations.RequiresFlagsDisabled; +import android.platform.test.annotations.RequiresFlagsEnabled; +import android.platform.test.flag.junit.CheckFlagsRule; import android.sysprop.BluetoothProperties; import androidx.lifecycle.Lifecycle; @@ -74,22 +76,21 @@ import java.util.List; @MediumTest @RunWith(AndroidJUnit4.class) public class BluetoothOppLauncherActivityTest { - public static final String CONTENT_TYPE = "image/png"; - - Context mTargetContext; - Intent mIntent; + // Activity tests can sometimes flaky because of external factors like system dialog, etc. + // making the expected Espresso's root not focused or the activity doesn't show up. + // Add retry rule to resolve this problem. + @Rule public TestUtils.RetryTestRule mRetryTestRule = new TestUtils.RetryTestRule(); - BluetoothMethodProxy mMethodProxy; + @Rule public final CheckFlagsRule mCheckFlagsRule = createCheckFlagsRule(); @Rule public final MockitoRule mMockitoRule = new MockitoRule(); @Mock BluetoothOppManager mBluetoothOppManager; - // Activity tests can sometimes flaky because of external factors like system dialog, etc. - // making the expected Espresso's root not focused or the activity doesn't show up. - // Add retry rule to resolve this problem. - @Rule public TestUtils.RetryTestRule mRetryTestRule = new TestUtils.RetryTestRule(); + private static final String CONTENT_TYPE = "image/png"; - @Rule public SetFlagsRule.ClassRule mSetFlagsClassRule = new SetFlagsRule.ClassRule(); + Context mTargetContext; + Intent mIntent; + BluetoothMethodProxy mMethodProxy; @Before public void setUp() throws Exception { @@ -144,7 +145,7 @@ public class BluetoothOppLauncherActivityTest { } @Test - @EnableFlags(Flags.FLAG_OPP_CHECK_CONTENT_URI_PERMISSIONS) + @RequiresFlagsEnabled(Flags.FLAG_OPP_CHECK_CONTENT_URI_PERMISSIONS) public void onCreate_withActionSend_checkEnabled_noPermission_doesNotSaveFileInfo() throws Exception { doReturn(true).when(mMethodProxy).bluetoothAdapterIsEnabled(any()); @@ -163,7 +164,7 @@ public class BluetoothOppLauncherActivityTest { } @Test - @EnableFlags(Flags.FLAG_OPP_CHECK_CONTENT_URI_PERMISSIONS) + @RequiresFlagsEnabled(Flags.FLAG_OPP_CHECK_CONTENT_URI_PERMISSIONS) public void onCreate_withActionSend_checkEnabled_hasPermission_savesFileInfo() throws Exception { doReturn(true).when(mMethodProxy).bluetoothAdapterIsEnabled(any()); @@ -182,7 +183,7 @@ public class BluetoothOppLauncherActivityTest { } @Test - @DisableFlags(Flags.FLAG_OPP_CHECK_CONTENT_URI_PERMISSIONS) + @RequiresFlagsDisabled(Flags.FLAG_OPP_CHECK_CONTENT_URI_PERMISSIONS) public void onCreate_withActionSend_checkNotEnabled_noPermission_savesFileInfo() throws Exception { doReturn(true).when(mMethodProxy).bluetoothAdapterIsEnabled(any()); @@ -201,7 +202,7 @@ public class BluetoothOppLauncherActivityTest { } @Test - @DisableFlags(Flags.FLAG_OPP_CHECK_CONTENT_URI_PERMISSIONS) + @RequiresFlagsDisabled(Flags.FLAG_OPP_CHECK_CONTENT_URI_PERMISSIONS) public void onCreate_withActionSend_checkNotEnabled_hasPermission_savesFileInfo() throws Exception { doReturn(true).when(mMethodProxy).bluetoothAdapterIsEnabled(any()); @@ -227,7 +228,7 @@ public class BluetoothOppLauncherActivityTest { } @Test - @EnableFlags(Flags.FLAG_OPP_CHECK_CONTENT_URI_PERMISSIONS) + @RequiresFlagsEnabled(Flags.FLAG_OPP_CHECK_CONTENT_URI_PERMISSIONS) public void onCreate_withActionSendMultiple_checkEnabled_noPermission_doesNotSaveFileInfos() throws Exception { doReturn(true).when(mMethodProxy).bluetoothAdapterIsEnabled(any()); @@ -249,7 +250,7 @@ public class BluetoothOppLauncherActivityTest { } @Test - @EnableFlags(Flags.FLAG_OPP_CHECK_CONTENT_URI_PERMISSIONS) + @RequiresFlagsEnabled(Flags.FLAG_OPP_CHECK_CONTENT_URI_PERMISSIONS) public void onCreate_withActionSendMultiple_checkEnabled_hasPermission_savesFileInfos() throws Exception { doReturn(true).when(mMethodProxy).bluetoothAdapterIsEnabled(any()); @@ -271,7 +272,7 @@ public class BluetoothOppLauncherActivityTest { } @Test - @EnableFlags(Flags.FLAG_OPP_CHECK_CONTENT_URI_PERMISSIONS) + @RequiresFlagsEnabled(Flags.FLAG_OPP_CHECK_CONTENT_URI_PERMISSIONS) public void onCreate_withActionSendMultiple_checkEnabled_partialPermission_savesPermittedFileInfo() throws Exception { @@ -294,7 +295,7 @@ public class BluetoothOppLauncherActivityTest { } @Test - @DisableFlags(Flags.FLAG_OPP_CHECK_CONTENT_URI_PERMISSIONS) + @RequiresFlagsDisabled(Flags.FLAG_OPP_CHECK_CONTENT_URI_PERMISSIONS) public void onCreate_withActionSendMultiple_checkNotEnabled_noPermission_savesFileInfos() throws Exception { doReturn(true).when(mMethodProxy).bluetoothAdapterIsEnabled(any()); @@ -316,7 +317,7 @@ public class BluetoothOppLauncherActivityTest { } @Test - @DisableFlags(Flags.FLAG_OPP_CHECK_CONTENT_URI_PERMISSIONS) + @RequiresFlagsDisabled(Flags.FLAG_OPP_CHECK_CONTENT_URI_PERMISSIONS) public void onCreate_withActionSendMultiple_checkNotEnabled_hasPermission_savesFileInfos() throws Exception { doReturn(true).when(mMethodProxy).bluetoothAdapterIsEnabled(any()); @@ -338,7 +339,7 @@ public class BluetoothOppLauncherActivityTest { } @Test - @DisableFlags(Flags.FLAG_OPP_CHECK_CONTENT_URI_PERMISSIONS) + @RequiresFlagsDisabled(Flags.FLAG_OPP_CHECK_CONTENT_URI_PERMISSIONS) public void onCreate_withActionSendMultiple_checkNotEnabled_partialPermission_savesFileInfos() throws Exception { doReturn(true).when(mMethodProxy).bluetoothAdapterIsEnabled(any()); diff --git a/android/app/tests/instrumentation/com/android/bluetooth/telephony/BluetoothInCallServiceTest.java b/android/app/tests/instrumentation/com/android/bluetooth/telephony/BluetoothInCallServiceTest.java index 9c6ee848fd..aa2c1a7095 100644 --- a/android/app/tests/instrumentation/com/android/bluetooth/telephony/BluetoothInCallServiceTest.java +++ b/android/app/tests/instrumentation/com/android/bluetooth/telephony/BluetoothInCallServiceTest.java @@ -16,6 +16,8 @@ package com.android.bluetooth.telephony; +import static android.platform.test.flag.junit.DeviceFlagsValueProvider.createCheckFlagsRule; + import static com.android.bluetooth.TestUtils.MockitoRule; import static com.android.bluetooth.TestUtils.mockGetSystemService; import static com.android.bluetooth.telephony.BluetoothInCallService.Result; @@ -34,8 +36,8 @@ import android.content.Intent; import android.net.Uri; import android.os.Binder; import android.os.Bundle; -import android.platform.test.annotations.EnableFlags; -import android.platform.test.flag.junit.SetFlagsRule; +import android.platform.test.annotations.RequiresFlagsEnabled; +import android.platform.test.flag.junit.CheckFlagsRule; import android.telecom.BluetoothCallQualityReport; import android.telecom.Call; import android.telecom.Connection; @@ -74,6 +76,13 @@ import java.util.UUID; public class BluetoothInCallServiceTest { private static final String TAG = "BluetoothInCallServiceTest"; + @Rule public final CheckFlagsRule mCheckFlagsRule = createCheckFlagsRule(); + @Rule public final MockitoRule mMockitoRule = new MockitoRule(); + + @Mock private HeadsetService mHeadsetService; + @Mock private BluetoothLeCallControlProxy mLeCallControl; + @Mock private BluetoothInCallService.CallInfo mMockCallInfo; + private static final int TEST_DTMF_TONE = 0; private static final String TEST_ACCOUNT_ADDRESS = "//foo.com/"; private static final int TEST_ACCOUNT_INDEX = 0; @@ -96,14 +105,6 @@ public class BluetoothInCallServiceTest { private static final int CHLD_TYPE_ADDHELDTOCONF = 3; private BluetoothInCallService mBluetoothInCallService; - - @Rule public final MockitoRule mMockitoRule = new MockitoRule(); - @Rule public final SetFlagsRule mSetFlagsRule = new SetFlagsRule(); - - @Mock private HeadsetService mHeadsetService; - @Mock private BluetoothLeCallControlProxy mLeCallControl; - @Mock private BluetoothInCallService.CallInfo mMockCallInfo; - private TelephonyManager mMockTelephonyManager; @Before @@ -900,7 +901,7 @@ public class BluetoothInCallServiceTest { } @Test - @EnableFlags({Flags.FLAG_NON_CONFERENCE_CALL_HANGUP}) + @RequiresFlagsEnabled(Flags.FLAG_NON_CONFERENCE_CALL_HANGUP) public void endActivecallWhenConferenceCallInHoldState() { doReturn("").when(mMockTelephonyManager).getNetworkCountryIso(); @@ -969,8 +970,8 @@ public class BluetoothInCallServiceTest { } @Test + @RequiresFlagsEnabled(Flags.FLAG_MAINTAIN_CALL_INDEX_AFTER_CONFERENCE) public void conferenceLastCallIndexIsMaintained() throws Exception { - mSetFlagsRule.enableFlags(Flags.FLAG_MAINTAIN_CALL_INDEX_AFTER_CONFERENCE); doReturn("").when(mMockTelephonyManager).getNetworkCountryIso(); List<BluetoothCall> calls = new ArrayList<>(); diff --git a/android/app/tests/unit/src/com/android/bluetooth/ObexAppParametersTest.java b/android/app/tests/unit/src/com/android/bluetooth/ObexAppParametersTest.java index c7bb30475e..1166a4ae10 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/ObexAppParametersTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/ObexAppParametersTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2022 The Android Open Source Project + * Copyright (C) 2022 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. diff --git a/android/app/tests/unit/src/com/android/bluetooth/SignedLongLongTest.java b/android/app/tests/unit/src/com/android/bluetooth/SignedLongLongTest.java index 8a887b71eb..00b4306532 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/SignedLongLongTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/SignedLongLongTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2023 The Android Open Source Project + * Copyright (C) 2023 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/android/app/tests/unit/src/com/android/bluetooth/TestLooper.java b/android/app/tests/unit/src/com/android/bluetooth/TestLooper.java index aa2f8ada21..4fb58f2f35 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/TestLooper.java +++ b/android/app/tests/unit/src/com/android/bluetooth/TestLooper.java @@ -18,6 +18,7 @@ package com.android.bluetooth; import static org.junit.Assert.assertTrue; +import android.os.Build; import android.os.Handler; import android.os.Looper; import android.os.Message; @@ -71,16 +72,7 @@ public class TestLooper { * Baklava introduces new {@link TestLooperManager} APIs that we can use instead of reflection. */ private static boolean isAtLeastBaklava() { - Method[] methods = TestLooperManager.class.getMethods(); - for (Method method : methods) { - if (method.getName().equals("peekWhen")) { - return true; - } - } - return false; - // TODO(shayba): delete the above, uncomment the below. - // SDK_INT has not yet ramped to Baklava in all 25Q2 builds. - // return Build.VERSION.SDK_INT >= Build.VERSION_CODES.BAKLAVA; + return Build.VERSION.SDK_INT >= Build.VERSION_CODES.BAKLAVA; } static { diff --git a/android/app/tests/unit/src/com/android/bluetooth/TestUtils.java b/android/app/tests/unit/src/com/android/bluetooth/TestUtils.java index cb61bc2853..e3ffd072d3 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/TestUtils.java +++ b/android/app/tests/unit/src/com/android/bluetooth/TestUtils.java @@ -1,5 +1,5 @@ /* - * Copyright 2018 The Android Open Source Project + * Copyright (C) 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. diff --git a/android/app/tests/unit/src/com/android/bluetooth/UtilsTest.java b/android/app/tests/unit/src/com/android/bluetooth/UtilsTest.java index ebada2d9a4..b8e26ed03b 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/UtilsTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/UtilsTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2022 The Android Open Source Project + * Copyright (C) 2022 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. @@ -47,7 +47,7 @@ import java.nio.ByteOrder; import java.nio.charset.StandardCharsets; import java.util.UUID; -/** Test for Utils.java */ +/** Test cases for {@link Utils}. */ @SmallTest @RunWith(AndroidJUnit4.class) public class UtilsTest { @@ -66,13 +66,6 @@ public class UtilsTest { } @Test - public void byteArrayToString() { - byte[] valueBuf = new byte[] {0x01, 0x02}; - String str = Utils.byteArrayToString(valueBuf); - assertThat(str).isEqualTo("01 02"); - } - - @Test public void uuidsToByteArray() { ParcelUuid[] uuids = new ParcelUuid[] { diff --git a/android/app/tests/unit/src/com/android/bluetooth/a2dp/A2dpCodecConfigTest.java b/android/app/tests/unit/src/com/android/bluetooth/a2dp/A2dpCodecConfigTest.java index d0c253523a..8f5dd839ae 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/a2dp/A2dpCodecConfigTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/a2dp/A2dpCodecConfigTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2019 The Android Open Source Project + * Copyright (C) 2019 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. diff --git a/android/app/tests/unit/src/com/android/bluetooth/a2dp/A2dpServiceBinderTest.java b/android/app/tests/unit/src/com/android/bluetooth/a2dp/A2dpServiceBinderTest.java index eb3def2b89..23e7a5ed1c 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/a2dp/A2dpServiceBinderTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/a2dp/A2dpServiceBinderTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2022 The Android Open Source Project + * Copyright (C) 2022 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. diff --git a/android/app/tests/unit/src/com/android/bluetooth/a2dp/A2dpServiceTest.java b/android/app/tests/unit/src/com/android/bluetooth/a2dp/A2dpServiceTest.java index f336cf6a69..b2fb43b362 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/a2dp/A2dpServiceTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/a2dp/A2dpServiceTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2018 The Android Open Source Project + * Copyright (C) 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. @@ -111,8 +111,7 @@ public class A2dpServiceTest { @Parameters(name = "{0}") public static List<FlagsParameterization> getParams() { - return FlagsParameterization.allCombinationsOf( - Flags.FLAG_A2DP_BROADCAST_CONNECTION_STATE_WHEN_TURNED_OFF); + return FlagsParameterization.allCombinationsOf(); } public A2dpServiceTest(FlagsParameterization flags) { @@ -194,11 +193,9 @@ public class A2dpServiceTest { mA2dpService.cleanup(); dispatchAtLeastOneMessage(); - if (Flags.a2dpBroadcastConnectionStateWhenTurnedOff()) { - // Verify that the intent CONNECTION_STATE_CHANGED is generated - // for the existing connections. - verifyConnectionStateIntent(mDevice, STATE_DISCONNECTED, STATE_CONNECTED); - } + // Verify that the intent CONNECTION_STATE_CHANGED is generated + // for the existing connections. + verifyConnectionStateIntent(mDevice, STATE_DISCONNECTED, STATE_CONNECTED); // Verify that setActiveDevice(null) was called during shutdown verify(mMockNativeInterface).setActiveDevice(null); @@ -641,11 +638,9 @@ public class A2dpServiceTest { assertThat(mA2dpService.getDevices()).contains(mDevice); // Device unbond - state machine is not removed mA2dpService.bondStateChangedFromTest(mDevice, BluetoothDevice.BOND_NONE); - if (Flags.a2dpBroadcastConnectionStateWhenTurnedOff()) { - // Verify that the intent CONNECTION_STATE_CHANGED is generated - // for the existing connections. - verifyConnectionStateIntent(mDevice, STATE_DISCONNECTED, STATE_CONNECTING); - } + // Verify that the intent CONNECTION_STATE_CHANGED is generated + // for the existing connections. + verifyConnectionStateIntent(mDevice, STATE_DISCONNECTED, STATE_CONNECTING); assertThat(mA2dpService.getDevices()).doesNotContain(mDevice); // A2DP stack event: CONNECTION_STATE_CONNECTED - state machine is not removed @@ -656,11 +651,9 @@ public class A2dpServiceTest { assertThat(mA2dpService.getDevices()).contains(mDevice); // Device unbond - state machine is not removed mA2dpService.bondStateChangedFromTest(mDevice, BluetoothDevice.BOND_NONE); - if (Flags.a2dpBroadcastConnectionStateWhenTurnedOff()) { - // Verify that the intent CONNECTION_STATE_CHANGED is generated - // for the existing connections. - verifyConnectionStateIntent(mDevice, STATE_DISCONNECTED, STATE_CONNECTED); - } + // Verify that the intent CONNECTION_STATE_CHANGED is generated + // for the existing connections. + verifyConnectionStateIntent(mDevice, STATE_DISCONNECTED, STATE_CONNECTED); assertThat(mA2dpService.getDevices()).doesNotContain(mDevice); // A2DP stack event: CONNECTION_STATE_DISCONNECTING - state machine is not removed @@ -672,11 +665,9 @@ public class A2dpServiceTest { assertThat(mA2dpService.getDevices()).contains(mDevice); // Device unbond - state machine is not removed mA2dpService.bondStateChangedFromTest(mDevice, BluetoothDevice.BOND_NONE); - if (Flags.a2dpBroadcastConnectionStateWhenTurnedOff()) { - // Verify that the intent CONNECTION_STATE_CHANGED is generated - // for the existing connections. - verifyConnectionStateIntent(mDevice, STATE_DISCONNECTED, STATE_DISCONNECTING); - } + // Verify that the intent CONNECTION_STATE_CHANGED is generated + // for the existing connections. + verifyConnectionStateIntent(mDevice, STATE_DISCONNECTED, STATE_DISCONNECTING); assertThat(mA2dpService.getDevices()).doesNotContain(mDevice); // A2DP stack event: CONNECTION_STATE_DISCONNECTED - state machine is not removed diff --git a/android/app/tests/unit/src/com/android/bluetooth/a2dp/A2dpStateMachineTest.java b/android/app/tests/unit/src/com/android/bluetooth/a2dp/A2dpStateMachineTest.java index d51bae8f63..c44094bd2c 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/a2dp/A2dpStateMachineTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/a2dp/A2dpStateMachineTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2017 The Android Open Source Project + * Copyright (C) 2017 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. diff --git a/android/app/tests/unit/src/com/android/bluetooth/a2dpsink/A2dpSinkServiceBinderTest.java b/android/app/tests/unit/src/com/android/bluetooth/a2dpsink/A2dpSinkServiceBinderTest.java index 24ead6e4b8..aad4f1019a 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/a2dpsink/A2dpSinkServiceBinderTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/a2dpsink/A2dpSinkServiceBinderTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2022 The Android Open Source Project + * Copyright (C) 2022 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. diff --git a/android/app/tests/unit/src/com/android/bluetooth/a2dpsink/A2dpSinkServiceTest.java b/android/app/tests/unit/src/com/android/bluetooth/a2dpsink/A2dpSinkServiceTest.java index 5ea9ad1d94..8b108c65e5 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/a2dpsink/A2dpSinkServiceTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/a2dpsink/A2dpSinkServiceTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2018 The Android Open Source Project + * Copyright (C) 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. diff --git a/android/app/tests/unit/src/com/android/bluetooth/a2dpsink/A2dpSinkStateMachineTest.java b/android/app/tests/unit/src/com/android/bluetooth/a2dpsink/A2dpSinkStateMachineTest.java index 5d13e09c9b..5641fbe7fc 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/a2dpsink/A2dpSinkStateMachineTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/a2dpsink/A2dpSinkStateMachineTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2021 The Android Open Source Project + * Copyright (C) 2021 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. diff --git a/android/app/tests/unit/src/com/android/bluetooth/a2dpsink/StackEventTest.java b/android/app/tests/unit/src/com/android/bluetooth/a2dpsink/StackEventTest.java index b4944c2324..5a0b67d77e 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/a2dpsink/StackEventTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/a2dpsink/StackEventTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2021 The Android Open Source Project + * Copyright (C) 2021 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. diff --git a/android/app/tests/unit/src/com/android/bluetooth/audio_util/BrowsablePlayerConnectorTest.java b/android/app/tests/unit/src/com/android/bluetooth/audio_util/BrowsablePlayerConnectorTest.java index ab08c8bafc..47109d6b16 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/audio_util/BrowsablePlayerConnectorTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/audio_util/BrowsablePlayerConnectorTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2023 The Android Open Source Project + * Copyright (C) 2023 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/android/app/tests/unit/src/com/android/bluetooth/audio_util/BrowserPlayerWrapperTest.java b/android/app/tests/unit/src/com/android/bluetooth/audio_util/BrowserPlayerWrapperTest.java index dfa391c909..7d77021833 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/audio_util/BrowserPlayerWrapperTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/audio_util/BrowserPlayerWrapperTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2017 The Android Open Source Project + * Copyright (C) 2017 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. diff --git a/android/app/tests/unit/src/com/android/bluetooth/audio_util/GPMWrapperTest.java b/android/app/tests/unit/src/com/android/bluetooth/audio_util/GPMWrapperTest.java index f6ae8a4fd3..74d63bddbf 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/audio_util/GPMWrapperTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/audio_util/GPMWrapperTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2023 The Android Open Source Project + * Copyright (C) 2023 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/android/app/tests/unit/src/com/android/bluetooth/audio_util/ImageTest.java b/android/app/tests/unit/src/com/android/bluetooth/audio_util/ImageTest.java index d74b4ecd5b..a74a0e7789 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/audio_util/ImageTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/audio_util/ImageTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2020 The Android Open Source Project + * Copyright (C) 2020 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. diff --git a/android/app/tests/unit/src/com/android/bluetooth/audio_util/MediaPlayerListTest.java b/android/app/tests/unit/src/com/android/bluetooth/audio_util/MediaPlayerListTest.java index 29a3fc2be5..c7d5458ca2 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/audio_util/MediaPlayerListTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/audio_util/MediaPlayerListTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2019 The Android Open Source Project + * Copyright (C) 2019 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. diff --git a/android/app/tests/unit/src/com/android/bluetooth/audio_util/MediaPlayerWrapperTest.java b/android/app/tests/unit/src/com/android/bluetooth/audio_util/MediaPlayerWrapperTest.java index 20784033c2..ca7d227747 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/audio_util/MediaPlayerWrapperTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/audio_util/MediaPlayerWrapperTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2017 The Android Open Source Project + * Copyright (C) 2017 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. diff --git a/android/app/tests/unit/src/com/android/bluetooth/audio_util/MetadataTest.java b/android/app/tests/unit/src/com/android/bluetooth/audio_util/MetadataTest.java index df6efa4a56..b0ac35637d 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/audio_util/MetadataTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/audio_util/MetadataTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2020 The Android Open Source Project + * Copyright (C) 2020 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. diff --git a/android/app/tests/unit/src/com/android/bluetooth/audio_util/UtilTest.java b/android/app/tests/unit/src/com/android/bluetooth/audio_util/UtilTest.java index bac99cd389..ff1b79e9a5 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/audio_util/UtilTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/audio_util/UtilTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2022 The Android Open Source Project + * Copyright (C) 2022 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. diff --git a/android/app/tests/unit/src/com/android/bluetooth/avrcp/AvrcpBipObexServerTest.java b/android/app/tests/unit/src/com/android/bluetooth/avrcp/AvrcpBipObexServerTest.java index 73978edd1e..d67e19ee60 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/avrcp/AvrcpBipObexServerTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/avrcp/AvrcpBipObexServerTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2020 The Android Open Source Project + * Copyright (C) 2020 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. diff --git a/android/app/tests/unit/src/com/android/bluetooth/avrcp/AvrcpCoverArtStorageTest.java b/android/app/tests/unit/src/com/android/bluetooth/avrcp/AvrcpCoverArtStorageTest.java index 4b0a53be21..46e24db940 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/avrcp/AvrcpCoverArtStorageTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/avrcp/AvrcpCoverArtStorageTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2020 The Android Open Source Project + * Copyright (C) 2020 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. 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..1111e05af7 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 @@ -1,5 +1,5 @@ /* - * Copyright 2024 The Android Open Source Project + * Copyright (C) 2024 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. @@ -23,8 +23,8 @@ import static com.android.bluetooth.TestUtils.mockGetSystemService; import static com.google.common.truth.Truth.assertThat; +import static org.mockito.Mockito.any; import static org.mockito.Mockito.anyInt; -import static org.mockito.Mockito.anyObject; 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/avrcp/AvrcpVolumeManagerTest.java b/android/app/tests/unit/src/com/android/bluetooth/avrcp/AvrcpVolumeManagerTest.java index f1e54d5cd2..4ce83f3a56 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/avrcp/AvrcpVolumeManagerTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/avrcp/AvrcpVolumeManagerTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2023 The Android Open Source Project + * Copyright (C) 2023 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/android/app/tests/unit/src/com/android/bluetooth/avrcp/CoverArtTest.java b/android/app/tests/unit/src/com/android/bluetooth/avrcp/CoverArtTest.java index bcf90f4066..1312a589aa 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/avrcp/CoverArtTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/avrcp/CoverArtTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2020 The Android Open Source Project + * Copyright (C) 2020 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. diff --git a/android/app/tests/unit/src/com/android/bluetooth/avrcpcontroller/AvrcpBipClientTest.java b/android/app/tests/unit/src/com/android/bluetooth/avrcpcontroller/AvrcpBipClientTest.java index d88f8122be..16360b5cce 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/avrcpcontroller/AvrcpBipClientTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/avrcpcontroller/AvrcpBipClientTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2022 The Android Open Source Project + * Copyright (C) 2022 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. diff --git a/android/app/tests/unit/src/com/android/bluetooth/avrcpcontroller/AvrcpControllerNativeInterfaceTest.java b/android/app/tests/unit/src/com/android/bluetooth/avrcpcontroller/AvrcpControllerNativeInterfaceTest.java index 38938e8472..6364c499a4 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/avrcpcontroller/AvrcpControllerNativeInterfaceTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/avrcpcontroller/AvrcpControllerNativeInterfaceTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2023 The Android Open Source Project + * Copyright (C) 2023 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/android/app/tests/unit/src/com/android/bluetooth/avrcpcontroller/AvrcpControllerServiceBinderTest.java b/android/app/tests/unit/src/com/android/bluetooth/avrcpcontroller/AvrcpControllerServiceBinderTest.java index dd12985a44..2cbd8f356a 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/avrcpcontroller/AvrcpControllerServiceBinderTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/avrcpcontroller/AvrcpControllerServiceBinderTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2022 The Android Open Source Project + * Copyright (C) 2022 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. diff --git a/android/app/tests/unit/src/com/android/bluetooth/avrcpcontroller/AvrcpControllerServiceTest.java b/android/app/tests/unit/src/com/android/bluetooth/avrcpcontroller/AvrcpControllerServiceTest.java index e082270619..ee46a1accd 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/avrcpcontroller/AvrcpControllerServiceTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/avrcpcontroller/AvrcpControllerServiceTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2018 The Android Open Source Project + * Copyright (C) 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. @@ -209,7 +209,7 @@ public class AvrcpControllerServiceTest { when(mStateMachine.findNode(parentMediaId)).thenReturn(null); BrowseResult result = mService.getContents(parentMediaId); - assertThat(result.getStatus()).isEqualTo(BrowseResult.ERROR_MEDIA_ID_INVALID); + assertThat(result.status()).isEqualTo(BrowseResult.ERROR_MEDIA_ID_INVALID); } /** @@ -222,7 +222,7 @@ public class AvrcpControllerServiceTest { String parentMediaId = BrowseTree.ROOT; BrowseResult result = mService.getContents(parentMediaId); - assertThat(result.getStatus()).isEqualTo(BrowseResult.NO_DEVICE_CONNECTED); + assertThat(result.status()).isEqualTo(BrowseResult.NO_DEVICE_CONNECTED); } /** @@ -235,7 +235,7 @@ public class AvrcpControllerServiceTest { mService.getBrowseTree().onConnected(mDevice); BrowseResult result = mService.getContents(parentMediaId); - assertThat(result.getStatus()).isEqualTo(BrowseResult.SUCCESS); + assertThat(result.status()).isEqualTo(BrowseResult.SUCCESS); } /** @@ -258,7 +258,7 @@ public class AvrcpControllerServiceTest { BrowseResult result = mService.getContents(parentMediaId); verify(mStateMachine).requestContents(eq(node)); - assertThat(result.getStatus()).isEqualTo(BrowseResult.DOWNLOAD_PENDING); + assertThat(result.status()).isEqualTo(BrowseResult.DOWNLOAD_PENDING); } /** @@ -275,7 +275,7 @@ public class AvrcpControllerServiceTest { BrowseResult result = mService.getContents(parentMediaId); - assertThat(result.getStatus()).isEqualTo(BrowseResult.SUCCESS); + assertThat(result.status()).isEqualTo(BrowseResult.SUCCESS); } @Test diff --git a/android/app/tests/unit/src/com/android/bluetooth/avrcpcontroller/AvrcpControllerStateMachineTest.java b/android/app/tests/unit/src/com/android/bluetooth/avrcpcontroller/AvrcpControllerStateMachineTest.java index ee30dfa8d1..43688601fe 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/avrcpcontroller/AvrcpControllerStateMachineTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/avrcpcontroller/AvrcpControllerStateMachineTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2019 The Android Open Source Project + * Copyright (C) 2019 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. diff --git a/android/app/tests/unit/src/com/android/bluetooth/avrcpcontroller/AvrcpCoverArtProviderTest.java b/android/app/tests/unit/src/com/android/bluetooth/avrcpcontroller/AvrcpCoverArtProviderTest.java index 02b563adbf..b2fbbe132f 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/avrcpcontroller/AvrcpCoverArtProviderTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/avrcpcontroller/AvrcpCoverArtProviderTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2022 The Android Open Source Project + * Copyright (C) 2022 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. diff --git a/android/app/tests/unit/src/com/android/bluetooth/avrcpcontroller/AvrcpCoverArtStorageTest.java b/android/app/tests/unit/src/com/android/bluetooth/avrcpcontroller/AvrcpCoverArtStorageTest.java index 98d00ebe5d..33aa418fda 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/avrcpcontroller/AvrcpCoverArtStorageTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/avrcpcontroller/AvrcpCoverArtStorageTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2019 The Android Open Source Project + * Copyright (C) 2019 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. diff --git a/android/app/tests/unit/src/com/android/bluetooth/avrcpcontroller/AvrcpItemTest.java b/android/app/tests/unit/src/com/android/bluetooth/avrcpcontroller/AvrcpItemTest.java index dbadfc526a..40c03dd0ae 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/avrcpcontroller/AvrcpItemTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/avrcpcontroller/AvrcpItemTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2019 The Android Open Source Project + * Copyright (C) 2019 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. diff --git a/android/app/tests/unit/src/com/android/bluetooth/avrcpcontroller/AvrcpPlayerTest.java b/android/app/tests/unit/src/com/android/bluetooth/avrcpcontroller/AvrcpPlayerTest.java index c1b0f52616..95d12cb2a1 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/avrcpcontroller/AvrcpPlayerTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/avrcpcontroller/AvrcpPlayerTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2022 The Android Open Source Project + * Copyright (C) 2022 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. diff --git a/android/app/tests/unit/src/com/android/bluetooth/avrcpcontroller/BrowseNodeTest.java b/android/app/tests/unit/src/com/android/bluetooth/avrcpcontroller/BrowseNodeTest.java index dab7613a9a..aa06d75c77 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/avrcpcontroller/BrowseNodeTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/avrcpcontroller/BrowseNodeTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2022 The Android Open Source Project + * Copyright (C) 2022 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. diff --git a/android/app/tests/unit/src/com/android/bluetooth/avrcpcontroller/BrowseTreeTest.java b/android/app/tests/unit/src/com/android/bluetooth/avrcpcontroller/BrowseTreeTest.java index 680f74b0c7..5d359d1ef4 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/avrcpcontroller/BrowseTreeTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/avrcpcontroller/BrowseTreeTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2022 The Android Open Source Project + * Copyright (C) 2022 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. diff --git a/android/app/tests/unit/src/com/android/bluetooth/avrcpcontroller/PlayerApplicationSettingsTest.java b/android/app/tests/unit/src/com/android/bluetooth/avrcpcontroller/PlayerApplicationSettingsTest.java index 782621d77a..a106f6e97f 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/avrcpcontroller/PlayerApplicationSettingsTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/avrcpcontroller/PlayerApplicationSettingsTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2022 The Android Open Source Project + * Copyright (C) 2022 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. diff --git a/android/app/tests/unit/src/com/android/bluetooth/avrcpcontroller/StackEventTest.java b/android/app/tests/unit/src/com/android/bluetooth/avrcpcontroller/StackEventTest.java index 82fe7c6162..ded802cbb7 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/avrcpcontroller/StackEventTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/avrcpcontroller/StackEventTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2022 The Android Open Source Project + * Copyright (C) 2022 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. diff --git a/android/app/tests/unit/src/com/android/bluetooth/avrcpcontroller/bip/BipAttachmentFormatTest.java b/android/app/tests/unit/src/com/android/bluetooth/avrcpcontroller/bip/BipAttachmentFormatTest.java index 03afb2826a..68b06e5c95 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/avrcpcontroller/bip/BipAttachmentFormatTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/avrcpcontroller/bip/BipAttachmentFormatTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2019 The Android Open Source Project + * Copyright (C) 2019 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. diff --git a/android/app/tests/unit/src/com/android/bluetooth/avrcpcontroller/bip/BipDatetimeTest.java b/android/app/tests/unit/src/com/android/bluetooth/avrcpcontroller/bip/BipDatetimeTest.java index 5d93884efb..abdee02e65 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/avrcpcontroller/bip/BipDatetimeTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/avrcpcontroller/bip/BipDatetimeTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2019 The Android Open Source Project + * Copyright (C) 2019 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. diff --git a/android/app/tests/unit/src/com/android/bluetooth/avrcpcontroller/bip/BipEncodingTest.java b/android/app/tests/unit/src/com/android/bluetooth/avrcpcontroller/bip/BipEncodingTest.java index 712c304c33..dd6c498679 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/avrcpcontroller/bip/BipEncodingTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/avrcpcontroller/bip/BipEncodingTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2019 The Android Open Source Project + * Copyright (C) 2019 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. diff --git a/android/app/tests/unit/src/com/android/bluetooth/avrcpcontroller/bip/BipImageDescriptorTest.java b/android/app/tests/unit/src/com/android/bluetooth/avrcpcontroller/bip/BipImageDescriptorTest.java index 8d0415dcaa..0d87190643 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/avrcpcontroller/bip/BipImageDescriptorTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/avrcpcontroller/bip/BipImageDescriptorTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2019 The Android Open Source Project + * Copyright (C) 2019 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. diff --git a/android/app/tests/unit/src/com/android/bluetooth/avrcpcontroller/bip/BipImageFormatTest.java b/android/app/tests/unit/src/com/android/bluetooth/avrcpcontroller/bip/BipImageFormatTest.java index 75d04f6c8b..2ee0bda8bb 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/avrcpcontroller/bip/BipImageFormatTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/avrcpcontroller/bip/BipImageFormatTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2019 The Android Open Source Project + * Copyright (C) 2019 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. diff --git a/android/app/tests/unit/src/com/android/bluetooth/avrcpcontroller/bip/BipImagePropertiesTest.java b/android/app/tests/unit/src/com/android/bluetooth/avrcpcontroller/bip/BipImagePropertiesTest.java index 8f11f9218f..a1c9829273 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/avrcpcontroller/bip/BipImagePropertiesTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/avrcpcontroller/bip/BipImagePropertiesTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2019 The Android Open Source Project + * Copyright (C) 2019 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. diff --git a/android/app/tests/unit/src/com/android/bluetooth/avrcpcontroller/bip/BipImageTest.java b/android/app/tests/unit/src/com/android/bluetooth/avrcpcontroller/bip/BipImageTest.java index 4a8f103ad1..ca98f02d21 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/avrcpcontroller/bip/BipImageTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/avrcpcontroller/bip/BipImageTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2019 The Android Open Source Project + * Copyright (C) 2019 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. diff --git a/android/app/tests/unit/src/com/android/bluetooth/avrcpcontroller/bip/BipPixelTest.java b/android/app/tests/unit/src/com/android/bluetooth/avrcpcontroller/bip/BipPixelTest.java index 8d2146218a..1f47f0c606 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/avrcpcontroller/bip/BipPixelTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/avrcpcontroller/bip/BipPixelTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2019 The Android Open Source Project + * Copyright (C) 2019 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. diff --git a/android/app/tests/unit/src/com/android/bluetooth/avrcpcontroller/bip/BipTransformationTest.java b/android/app/tests/unit/src/com/android/bluetooth/avrcpcontroller/bip/BipTransformationTest.java index 031a71c81e..7d5eb5a986 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/avrcpcontroller/bip/BipTransformationTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/avrcpcontroller/bip/BipTransformationTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2019 The Android Open Source Project + * Copyright (C) 2019 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. diff --git a/android/app/tests/unit/src/com/android/bluetooth/avrcpcontroller/bip/RequestGetImagePropertiesTest.java b/android/app/tests/unit/src/com/android/bluetooth/avrcpcontroller/bip/RequestGetImagePropertiesTest.java index fb833c757b..9633aa4f95 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/avrcpcontroller/bip/RequestGetImagePropertiesTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/avrcpcontroller/bip/RequestGetImagePropertiesTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2022 The Android Open Source Project + * Copyright (C) 2022 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. diff --git a/android/app/tests/unit/src/com/android/bluetooth/avrcpcontroller/bip/RequestGetImageTest.java b/android/app/tests/unit/src/com/android/bluetooth/avrcpcontroller/bip/RequestGetImageTest.java index d68854b91e..4d5ca54dfb 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/avrcpcontroller/bip/RequestGetImageTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/avrcpcontroller/bip/RequestGetImageTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2022 The Android Open Source Project + * Copyright (C) 2022 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. diff --git a/android/app/tests/unit/src/com/android/bluetooth/bas/BatteryServiceTest.java b/android/app/tests/unit/src/com/android/bluetooth/bas/BatteryServiceTest.java index 3e0212223d..84c9640524 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/bas/BatteryServiceTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/bas/BatteryServiceTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2022 The Android Open Source Project + * Copyright (C) 2022 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. diff --git a/android/app/tests/unit/src/com/android/bluetooth/bas/BatteryStateMachineTest.java b/android/app/tests/unit/src/com/android/bluetooth/bas/BatteryStateMachineTest.java index cf24333f8f..5e439f826b 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/bas/BatteryStateMachineTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/bas/BatteryStateMachineTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2022 The Android Open Source Project + * Copyright (C) 2022 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. diff --git a/android/app/tests/unit/src/com/android/bluetooth/bass_client/BaseDataTest.java b/android/app/tests/unit/src/com/android/bluetooth/bass_client/BaseDataTest.java index bf0d75a60a..c8305744e2 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/bass_client/BaseDataTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/bass_client/BaseDataTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2022 The Android Open Source Project + * Copyright (C) 2022 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. @@ -34,16 +34,16 @@ public class BaseDataTest { @Test public void baseInformation() { BaseData.BaseInformation info = new BaseData.BaseInformation(); - assertThat(info.presentationDelay.length).isEqualTo(3); - assertThat(info.codecId.length).isEqualTo(5); + assertThat(info.mPresentationDelay.length).isEqualTo(3); + assertThat(info.mCodecId.length).isEqualTo(5); - assertThat(info.codecId) + assertThat(info.mCodecId) .isEqualTo( new byte[] { (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00 }); - info.codecId[4] = (byte) 0xFE; - assertThat(info.codecId) + info.mCodecId[4] = (byte) 0xFE; + assertThat(info.mCodecId) .isNotEqualTo( new byte[] { (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00 @@ -52,18 +52,18 @@ public class BaseDataTest { // info.print() with different combination shouldn't crash. info.print(); - info.level = 1; - info.codecConfigLength = 1; + info.mLevel = 1; + info.mCodecConfigLength = 1; info.print(); - info.level = 2; - info.codecConfigLength = 3; - info.codecConfigInfo = new byte[] {(byte) 0x01, (byte) 0x05}; - info.metaDataLength = 4; - info.metaData = new byte[] {(byte) 0x04, (byte) 0x80, (byte) 0x79, (byte) 0x76}; + info.mLevel = 2; + info.mCodecConfigLength = 3; + info.mCodecConfigInfo = new byte[] {(byte) 0x01, (byte) 0x05}; + info.mMetaDataLength = 4; + info.mMetaData = new byte[] {(byte) 0x04, (byte) 0x80, (byte) 0x79, (byte) 0x76}; info.print(); - info.level = 3; + info.mLevel = 3; info.print(); } @@ -76,47 +76,47 @@ public class BaseDataTest { // LEVEL 1 (byte) 0x01, (byte) 0x02, - (byte) 0x03, // presentationDelay - (byte) 0x01, // numSubGroups + (byte) 0x03, // mPresentationDelay + (byte) 0x01, // mNumSubGroups // LEVEL 2 - (byte) 0x01, // numSubGroups + (byte) 0x01, // mNumSubGroups (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, // UNKNOWN_CODEC - (byte) 0x02, // codecConfigLength + (byte) 0x02, // mCodecConfigLength (byte) 0x01, - (byte) 'A', // codecConfigInfo - (byte) 0x03, // metaDataLength + (byte) 'A', // mCodecConfigInfo + (byte) 0x03, // mMetaDataLength (byte) 0x06, (byte) 0x07, - (byte) 0x08, // metaData + (byte) 0x08, // mMetaData // LEVEL 3 - (byte) 0x04, // index - (byte) 0x03, // codecConfigLength + (byte) 0x04, // mIndex + (byte) 0x03, // mCodecConfigLength (byte) 0x02, (byte) 'B', - (byte) 'C' // codecConfigInfo + (byte) 'C' // mCodecConfigInfo }; BaseData data = BaseData.parseBaseData(serviceData); - BaseData.BaseInformation level = data.getLevelOne(); - assertThat(level.presentationDelay).isEqualTo(new byte[] {0x01, 0x02, 0x03}); - assertThat(level.numSubGroups).isEqualTo(1); - - assertThat(data.getLevelTwo()).hasSize(1); - level = data.getLevelTwo().get(0); - - assertThat(level.numSubGroups).isEqualTo(1); - assertThat(level.codecId).isEqualTo(new byte[] {0x00, 0x00, 0x00, 0x00, 0x00}); - assertThat(level.codecConfigLength).isEqualTo(2); - assertThat(level.metaDataLength).isEqualTo(3); - - assertThat(data.getLevelThree()).hasSize(1); - level = data.getLevelThree().get(0); - assertThat(level.index).isEqualTo(4); - assertThat(level.codecConfigLength).isEqualTo(3); + BaseData.BaseInformation level = data.levelOne(); + assertThat(level.mPresentationDelay).isEqualTo(new byte[] {0x01, 0x02, 0x03}); + assertThat(level.mNumSubGroups).isEqualTo(1); + + assertThat(data.levelTwo()).hasSize(1); + level = data.levelTwo().get(0); + + assertThat(level.mNumSubGroups).isEqualTo(1); + assertThat(level.mCodecId).isEqualTo(new byte[] {0x00, 0x00, 0x00, 0x00, 0x00}); + assertThat(level.mCodecConfigLength).isEqualTo(2); + assertThat(level.mMetaDataLength).isEqualTo(3); + + assertThat(data.levelThree()).hasSize(1); + level = data.levelThree().get(0); + assertThat(level.mIndex).isEqualTo(4); + assertThat(level.mCodecConfigLength).isEqualTo(3); } @Test @@ -128,8 +128,8 @@ public class BaseDataTest { // LEVEL 1 (byte) 0x01, (byte) 0x02, - (byte) 0x03, // presentationDelay - (byte) 0x01, // numSubGroups + (byte) 0x03, // mPresentationDelay + (byte) 0x01, // mNumSubGroups // LEVEL 2 (byte) 0x01, // numBIS (byte) 0x06, @@ -137,9 +137,9 @@ public class BaseDataTest { (byte) 0x00, (byte) 0x00, (byte) 0x00, // Lc3 - (byte) 0x03, // codecConfigLength + (byte) 0x03, // mCodecConfigLength (byte) 0x01, - (byte) 'A', // codecConfigInfo + (byte) 'A', // mCodecConfigInfo }; assertThat(BaseData.parseBaseData(serviceData)).isNull(); @@ -154,8 +154,8 @@ public class BaseDataTest { // LEVEL 1 (byte) 0x01, (byte) 0x02, - (byte) 0x03, // presentationDelay - (byte) 0x01, // numSubGroups + (byte) 0x03, // mPresentationDelay + (byte) 0x01, // mNumSubGroups // LEVEL 2 (byte) 0x01, // numBIS (byte) 0x00, @@ -163,13 +163,13 @@ public class BaseDataTest { (byte) 0x00, (byte) 0x00, (byte) 0x00, // UNKNOWN_CODEC - (byte) 0x02, // codecConfigLength + (byte) 0x02, // mCodecConfigLength (byte) 0x01, - (byte) 'A', // codecConfigInfo - (byte) 0x04, // metaDataLength + (byte) 'A', // mCodecConfigInfo + (byte) 0x04, // mMetaDataLength (byte) 0x06, (byte) 0x07, - (byte) 0x08, // metaData + (byte) 0x08, // mMetaData }; assertThat(BaseData.parseBaseData(serviceData)).isNull(); @@ -184,8 +184,8 @@ public class BaseDataTest { // LEVEL 1 (byte) 0x01, (byte) 0x02, - (byte) 0x03, // presentationDelay - (byte) 0x01, // numSubGroups + (byte) 0x03, // mPresentationDelay + (byte) 0x01, // mNumSubGroups // LEVEL 2 (byte) 0x01, // numBIS (byte) 0x00, @@ -193,19 +193,19 @@ public class BaseDataTest { (byte) 0x00, (byte) 0x00, (byte) 0x00, // UNKNOWN_CODEC - (byte) 0x02, // codecConfigLength + (byte) 0x02, // mCodecConfigLength (byte) 0x01, - (byte) 'A', // codecConfigInfo - (byte) 0x03, // metaDataLength + (byte) 'A', // mCodecConfigInfo + (byte) 0x03, // mMetaDataLength (byte) 0x06, (byte) 0x07, - (byte) 0x08, // metaData + (byte) 0x08, // mMetaData // LEVEL 3 - (byte) 0x04, // index - (byte) 0x04, // codecConfigLength + (byte) 0x04, // mIndex + (byte) 0x04, // mCodecConfigLength (byte) 0x02, (byte) 'B', - (byte) 'C' // codecConfigInfo + (byte) 'C' // mCodecConfigInfo }; assertThat(BaseData.parseBaseData(serviceData)).isNull(); @@ -220,8 +220,8 @@ public class BaseDataTest { // LEVEL 1 (byte) 0x01, (byte) 0x02, - (byte) 0x03, // presentationDelay - (byte) 0x01, // numSubGroups + (byte) 0x03, // mPresentationDelay + (byte) 0x01, // mNumSubGroups // LEVEL 2 (byte) 0x01, // numBIS (byte) 0x06, @@ -229,40 +229,40 @@ public class BaseDataTest { (byte) 0x00, (byte) 0x00, (byte) 0x00, // LC3 - (byte) 0x02, // codecConfigLength + (byte) 0x02, // mCodecConfigLength (byte) 0x04, - (byte) 'A', // codecConfigInfo - (byte) 0x03, // metaDataLength + (byte) 'A', // mCodecConfigInfo + (byte) 0x03, // mMetaDataLength (byte) 0x06, (byte) 0x07, - (byte) 0x08, // metaData + (byte) 0x08, // mMetaData // LEVEL 3 - (byte) 0x04, // index - (byte) 0x03, // codecConfigLength + (byte) 0x04, // mIndex + (byte) 0x03, // mCodecConfigLength (byte) 0x03, (byte) 'B', - (byte) 'C' // codecConfigInfo + (byte) 'C' // mCodecConfigInfo }; BaseData data = BaseData.parseBaseData(serviceData); - BaseData.BaseInformation level = data.getLevelOne(); - assertThat(level.presentationDelay).isEqualTo(new byte[] {0x01, 0x02, 0x03}); - assertThat(level.numSubGroups).isEqualTo(1); + BaseData.BaseInformation level = data.levelOne(); + assertThat(level.mPresentationDelay).isEqualTo(new byte[] {0x01, 0x02, 0x03}); + assertThat(level.mNumSubGroups).isEqualTo(1); - assertThat(data.getLevelTwo()).hasSize(1); - level = data.getLevelTwo().get(0); + assertThat(data.levelTwo()).hasSize(1); + level = data.levelTwo().get(0); - assertThat(level.numSubGroups).isEqualTo(1); - assertThat(level.codecId).isEqualTo(new byte[] {0x06, 0x00, 0x00, 0x00, 0x00}); - assertThat(level.codecConfigLength).isEqualTo(2); - assertThat(level.metaDataLength).isEqualTo(3); + assertThat(level.mNumSubGroups).isEqualTo(1); + assertThat(level.mCodecId).isEqualTo(new byte[] {0x06, 0x00, 0x00, 0x00, 0x00}); + assertThat(level.mCodecConfigLength).isEqualTo(2); + assertThat(level.mMetaDataLength).isEqualTo(3); - assertThat(data.getLevelThree()).hasSize(1); - level = data.getLevelThree().get(0); - assertThat(level.index).isEqualTo(4); + assertThat(data.levelThree()).hasSize(1); + level = data.levelThree().get(0); + assertThat(level.mIndex).isEqualTo(4); // Got the whole config, without interpreting it as LTV - assertThat(level.codecConfigLength).isEqualTo(3); + assertThat(level.mCodecConfigLength).isEqualTo(3); } @Test @@ -274,8 +274,8 @@ public class BaseDataTest { // LEVEL 1 (byte) 0x01, (byte) 0x02, - (byte) 0x03, // presentationDelay - (byte) 0x01, // numSubGroups + (byte) 0x03, // mPresentationDelay + (byte) 0x01, // mNumSubGroups // LEVEL 2 (byte) 0x01, // numBIS (byte) 0xFF, // VENDOR_CODEC @@ -283,44 +283,44 @@ public class BaseDataTest { (byte) 0xAB, (byte) 0xBC, (byte) 0xCD, - (byte) 0x04, // codecConfigLength + (byte) 0x04, // mCodecConfigLength (byte) 0x01, (byte) 0x02, (byte) 0x03, (byte) 0x04, // opaque vendor data - (byte) 0x03, // metaDataLength + (byte) 0x03, // mMetaDataLength (byte) 0x06, (byte) 0x07, - (byte) 0x08, // metaData + (byte) 0x08, // mMetaData // LEVEL 3 - (byte) 0x04, // index - (byte) 0x03, // codecConfigLength + (byte) 0x04, // mIndex + (byte) 0x03, // mCodecConfigLength (byte) 0x03, (byte) 0x02, (byte) 0x01 // opaque vendor data }; BaseData data = BaseData.parseBaseData(serviceData); - BaseData.BaseInformation level = data.getLevelOne(); - assertThat(level.presentationDelay).isEqualTo(new byte[] {0x01, 0x02, 0x03}); - assertThat(level.numSubGroups).isEqualTo(1); + BaseData.BaseInformation level = data.levelOne(); + assertThat(level.mPresentationDelay).isEqualTo(new byte[] {0x01, 0x02, 0x03}); + assertThat(level.mNumSubGroups).isEqualTo(1); - assertThat(data.getLevelTwo()).hasSize(1); - level = data.getLevelTwo().get(0); + assertThat(data.levelTwo()).hasSize(1); + level = data.levelTwo().get(0); - assertThat(level.numSubGroups).isEqualTo(1); - assertThat(level.codecId) + assertThat(level.mNumSubGroups).isEqualTo(1); + assertThat(level.mCodecId) .isEqualTo( new byte[] { (byte) 0xFF, (byte) 0x0A, (byte) 0xAB, (byte) 0xBC, (byte) 0xCD }); - assertThat(level.codecConfigLength).isEqualTo(4); - assertThat(level.metaDataLength).isEqualTo(3); + assertThat(level.mCodecConfigLength).isEqualTo(4); + assertThat(level.mMetaDataLength).isEqualTo(3); - assertThat(data.getLevelThree()).hasSize(1); - level = data.getLevelThree().get(0); - assertThat(level.index).isEqualTo(4); - assertThat(level.codecConfigLength).isEqualTo(3); + assertThat(data.levelThree()).hasSize(1); + level = data.levelThree().get(0); + assertThat(level.mIndex).isEqualTo(4); + assertThat(level.mCodecConfigLength).isEqualTo(3); } @Test @@ -332,8 +332,8 @@ public class BaseDataTest { // LEVEL 1 (byte) 0x01, (byte) 0x02, - (byte) 0x03, // presentationDelay - (byte) 0x01, // numSubGroups + (byte) 0x03, // mPresentationDelay + (byte) 0x01, // mNumSubGroups // LEVEL 2 (byte) 0x01, // numBIS (byte) 0xFF, // VENDOR_CODEC @@ -341,34 +341,34 @@ public class BaseDataTest { (byte) 0xAB, (byte) 0xBC, (byte) 0xCD, - (byte) 0x00, // codecConfigLength - (byte) 0x00, // metaDataLength + (byte) 0x00, // mCodecConfigLength + (byte) 0x00, // mMetaDataLength // LEVEL 3 - (byte) 0x04, // index - (byte) 0x00, // codecConfigLength + (byte) 0x04, // mIndex + (byte) 0x00, // mCodecConfigLength }; BaseData data = BaseData.parseBaseData(serviceData); - BaseData.BaseInformation level = data.getLevelOne(); - assertThat(level.presentationDelay).isEqualTo(new byte[] {0x01, 0x02, 0x03}); - assertThat(level.numSubGroups).isEqualTo(1); + BaseData.BaseInformation level = data.levelOne(); + assertThat(level.mPresentationDelay).isEqualTo(new byte[] {0x01, 0x02, 0x03}); + assertThat(level.mNumSubGroups).isEqualTo(1); - assertThat(data.getLevelTwo()).hasSize(1); - level = data.getLevelTwo().get(0); + assertThat(data.levelTwo()).hasSize(1); + level = data.levelTwo().get(0); - assertThat(level.numSubGroups).isEqualTo(1); - assertThat(level.codecId) + assertThat(level.mNumSubGroups).isEqualTo(1); + assertThat(level.mCodecId) .isEqualTo( new byte[] { (byte) 0xFF, (byte) 0x0A, (byte) 0xAB, (byte) 0xBC, (byte) 0xCD }); - assertThat(level.codecConfigLength).isEqualTo(0); - assertThat(level.metaDataLength).isEqualTo(0); + assertThat(level.mCodecConfigLength).isEqualTo(0); + assertThat(level.mMetaDataLength).isEqualTo(0); - assertThat(data.getLevelThree()).hasSize(1); - level = data.getLevelThree().get(0); - assertThat(level.index).isEqualTo(4); - assertThat(level.codecConfigLength).isEqualTo(0); + assertThat(data.levelThree()).hasSize(1); + level = data.levelThree().get(0); + assertThat(level.mIndex).isEqualTo(4); + assertThat(level.mCodecConfigLength).isEqualTo(0); } @Test @@ -380,13 +380,13 @@ public class BaseDataTest { // LEVEL 1 (byte) 0x01, (byte) 0x02, - (byte) 0x03, // presentationDelay - (byte) 0x01, // numSubGroups + (byte) 0x03, // mPresentationDelay + (byte) 0x01, // mNumSubGroups // LEVEL 2 (byte) 0x00, // numBIS invalid value (byte) 0xFE, // UNKNOWN CODEC - (byte) 0x00, // codecConfigLength - (byte) 0x00, // metaDataLength + (byte) 0x00, // mCodecConfigLength + (byte) 0x00, // mMetaDataLength }; assertThat(BaseData.parseBaseData(serviceData)).isNull(); @@ -396,35 +396,35 @@ public class BaseDataTest { public void parseBaseData_longMetaData() { assertThrows(IllegalArgumentException.class, () -> BaseData.parseBaseData(null)); - int metaDataLength = 142; + int mMetaDataLength = 142; byte[] serviceDataLevel1 = new byte[] { // LEVEL 1 (byte) 0x01, (byte) 0x02, - (byte) 0x03, // presentationDelay - (byte) 0x01 // numSubGroups + (byte) 0x03, // mPresentationDelay + (byte) 0x01 // mNumSubGroups }; byte[] serviceDataLevel2 = new byte[] { // LEVEL 2 - (byte) 0x01, // numSubGroups + (byte) 0x01, // mNumSubGroups (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, // UNKNOWN_CODEC - (byte) 0x02, // codecConfigLength + (byte) 0x02, // mCodecConfigLength (byte) 0x01, - (byte) 'A', // codecConfigInfo - (byte) metaDataLength, // metaDataLength 142 + (byte) 'A', // mCodecConfigInfo + (byte) mMetaDataLength, // mMetaDataLength 142 }; byte[] metadataHeader = new byte[] { - (byte) (metaDataLength - 1), // length 141 + (byte) (mMetaDataLength - 1), // length 141 (byte) 0xFF }; @@ -434,11 +434,11 @@ public class BaseDataTest { byte[] serviceDataLevel3 = new byte[] { // LEVEL 3 - (byte) 0x04, // index - (byte) 0x03, // codecConfigLength + (byte) 0x04, // mIndex + (byte) 0x03, // mCodecConfigLength (byte) 0x02, (byte) 'B', - (byte) 'C' // codecConfigInfo + (byte) 'C' // mCodecConfigInfo }; BaseData data = @@ -447,22 +447,22 @@ public class BaseDataTest { serviceDataLevel1, Bytes.concat(serviceDataLevel2, metadataHeader, metadataPayload), serviceDataLevel3)); - BaseData.BaseInformation level = data.getLevelOne(); - assertThat(level.presentationDelay).isEqualTo(new byte[] {0x01, 0x02, 0x03}); - assertThat(level.numSubGroups).isEqualTo(1); - - assertThat(data.getLevelTwo()).hasSize(1); - level = data.getLevelTwo().get(0); - - assertThat(level.numSubGroups).isEqualTo(1); - assertThat(level.codecId).isEqualTo(new byte[] {0x00, 0x00, 0x00, 0x00, 0x00}); - assertThat(level.codecConfigLength).isEqualTo(2); - assertThat(level.metaDataLength).isEqualTo(metaDataLength); - assertThat(level.metaData).isEqualTo(Bytes.concat(metadataHeader, metadataPayload)); - - assertThat(data.getLevelThree()).hasSize(1); - level = data.getLevelThree().get(0); - assertThat(level.index).isEqualTo(4); - assertThat(level.codecConfigLength).isEqualTo(3); + BaseData.BaseInformation level = data.levelOne(); + assertThat(level.mPresentationDelay).isEqualTo(new byte[] {0x01, 0x02, 0x03}); + assertThat(level.mNumSubGroups).isEqualTo(1); + + assertThat(data.levelTwo()).hasSize(1); + level = data.levelTwo().get(0); + + assertThat(level.mNumSubGroups).isEqualTo(1); + assertThat(level.mCodecId).isEqualTo(new byte[] {0x00, 0x00, 0x00, 0x00, 0x00}); + assertThat(level.mCodecConfigLength).isEqualTo(2); + assertThat(level.mMetaDataLength).isEqualTo(mMetaDataLength); + assertThat(level.mMetaData).isEqualTo(Bytes.concat(metadataHeader, metadataPayload)); + + assertThat(data.levelThree()).hasSize(1); + level = data.levelThree().get(0); + assertThat(level.mIndex).isEqualTo(4); + assertThat(level.mCodecConfigLength).isEqualTo(3); } } diff --git a/android/app/tests/unit/src/com/android/bluetooth/bass_client/BassClientServiceTest.java b/android/app/tests/unit/src/com/android/bluetooth/bass_client/BassClientServiceTest.java index 77017748ba..464cb5c652 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/bass_client/BassClientServiceTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/bass_client/BassClientServiceTest.java @@ -1347,28 +1347,28 @@ public class BassClientServiceTest { // LEVEL 1 (byte) 0x01, (byte) 0x02, - (byte) 0x03, // presentationDelay - (byte) 0x01, // numSubGroups + (byte) 0x03, // mPresentationDelay + (byte) 0x01, // mNumSubGroups // LEVEL 2 - (byte) 0x01, // numSubGroups + (byte) 0x01, // mNumSubGroups (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, // UNKNOWN_CODEC - (byte) 0x02, // codecConfigLength + (byte) 0x02, // mCodecConfigLength (byte) 0x01, - (byte) 'A', // codecConfigInfo - (byte) 0x03, // metaDataLength + (byte) 'A', // mCodecConfigInfo + (byte) 0x03, // mMetaDataLength (byte) 0x06, (byte) 0x07, - (byte) 0x08, // metaData + (byte) 0x08, // mMetaData // LEVEL 3 - (byte) 0x04, // index - (byte) 0x03, // codecConfigLength + (byte) 0x04, // mIndex + (byte) 0x03, // mCodecConfigLength (byte) 0x02, (byte) 'B', - (byte) 'C', // codecConfigInfo + (byte) 'C', // mCodecConfigInfo (byte) 0x05, (byte) 0xff, (byte) 0xe0, @@ -1535,38 +1535,44 @@ public class BassClientServiceTest { } private void injectRemoteSourceStateChanged( + BassClientStateMachine sm, + BluetoothLeBroadcastMetadata meta, + boolean isPaSynced, + boolean isBisSynced) { + // Update receiver state + if (sm.getDevice().equals(mCurrentDevice)) { + injectRemoteSourceStateChanged( + sm, + meta, + TEST_SOURCE_ID, + isPaSynced + ? BluetoothLeBroadcastReceiveState.PA_SYNC_STATE_SYNCHRONIZED + : BluetoothLeBroadcastReceiveState.PA_SYNC_STATE_IDLE, + meta.isEncrypted() + ? BluetoothLeBroadcastReceiveState.BIG_ENCRYPTION_STATE_DECRYPTING + : BluetoothLeBroadcastReceiveState.BIG_ENCRYPTION_STATE_NOT_ENCRYPTED, + null, + isBisSynced ? (long) 0x00000001 : (long) 0x00000000); + } else if (sm.getDevice().equals(mCurrentDevice1)) { + injectRemoteSourceStateChanged( + sm, + meta, + TEST_SOURCE_ID + 1, + isPaSynced + ? BluetoothLeBroadcastReceiveState.PA_SYNC_STATE_SYNCHRONIZED + : BluetoothLeBroadcastReceiveState.PA_SYNC_STATE_IDLE, + meta.isEncrypted() + ? BluetoothLeBroadcastReceiveState.BIG_ENCRYPTION_STATE_DECRYPTING + : BluetoothLeBroadcastReceiveState.BIG_ENCRYPTION_STATE_NOT_ENCRYPTED, + null, + isBisSynced ? (long) 0x00000002 : (long) 0x00000000); + } + } + + private void injectRemoteSourceStateChanged( BluetoothLeBroadcastMetadata meta, boolean isPaSynced, boolean isBisSynced) { for (BassClientStateMachine sm : mStateMachines.values()) { - // Update receiver state - if (sm.getDevice().equals(mCurrentDevice)) { - injectRemoteSourceStateChanged( - sm, - meta, - TEST_SOURCE_ID, - isPaSynced - ? BluetoothLeBroadcastReceiveState.PA_SYNC_STATE_SYNCHRONIZED - : BluetoothLeBroadcastReceiveState.PA_SYNC_STATE_IDLE, - meta.isEncrypted() - ? BluetoothLeBroadcastReceiveState.BIG_ENCRYPTION_STATE_DECRYPTING - : BluetoothLeBroadcastReceiveState - .BIG_ENCRYPTION_STATE_NOT_ENCRYPTED, - null, - isBisSynced ? (long) 0x00000001 : (long) 0x00000000); - } else if (sm.getDevice().equals(mCurrentDevice1)) { - injectRemoteSourceStateChanged( - sm, - meta, - TEST_SOURCE_ID + 1, - isPaSynced - ? BluetoothLeBroadcastReceiveState.PA_SYNC_STATE_SYNCHRONIZED - : BluetoothLeBroadcastReceiveState.PA_SYNC_STATE_IDLE, - meta.isEncrypted() - ? BluetoothLeBroadcastReceiveState.BIG_ENCRYPTION_STATE_DECRYPTING - : BluetoothLeBroadcastReceiveState - .BIG_ENCRYPTION_STATE_NOT_ENCRYPTED, - null, - isBisSynced ? (long) 0x00000002 : (long) 0x00000000); - } + injectRemoteSourceStateChanged(sm, meta, isPaSynced, isBisSynced); } } @@ -1920,6 +1926,29 @@ public class BassClientServiceTest { } } + private void verifyModifyMessageAndInjectSourceModfified() { + for (BassClientStateMachine sm : mStateMachines.values()) { + ArgumentCaptor<Message> messageCaptor = ArgumentCaptor.forClass(Message.class); + verify(sm, atLeast(1)).sendMessage(messageCaptor.capture()); + + Optional<Message> msg = + messageCaptor.getAllValues().stream() + .filter(m -> m.what == BassClientStateMachine.UPDATE_BCAST_SOURCE) + .findFirst(); + assertThat(msg.isPresent()).isEqualTo(true); + + if (sm.getDevice().equals(mCurrentDevice)) { + assertThat(msg.get().arg1).isEqualTo(TEST_SOURCE_ID); + injectRemoteSourceStateChanged( + sm, createBroadcastMetadata(TEST_BROADCAST_ID), false, false); + } else if (sm.getDevice().equals(mCurrentDevice1)) { + assertThat(msg.get().arg1).isEqualTo(TEST_SOURCE_ID + 1); + injectRemoteSourceStateChanged( + sm, createBroadcastMetadata(TEST_BROADCAST_ID), false, false); + } + } + } + /** * Test whether service.removeSource() does send modify source if source is from remote receive * state. In this case, assistant should be able to remove source which was not managed by BASS @@ -4128,27 +4157,20 @@ public class BassClientServiceTest { 3 /* STATUS_LOCAL_STREAM_REQUESTED_NO_CONTEXT_VALIDATE */); /* Imitate broadcast source stop, sink notify about loosing BIS sync */ - verifyRemoveMessageAndInjectSourceRemoval(); + verifyModifyMessageAndInjectSourceModfified(); assertThat(mStateMachines).hasSize(2); for (BassClientStateMachine sm : mStateMachines.values()) { Mockito.clearInvocations(sm); } // Make another stream request with no context validate - // and verify sm didn't get REMOVE_BCAST_SOURCE mBassClientService.handleUnicastSourceStreamStatusChange( 3 /* STATUS_LOCAL_STREAM_REQUESTED_NO_CONTEXT_VALIDATE */); // Make another stream request - // and verify sinks to resume remain unchanged later mBassClientService.handleUnicastSourceStreamStatusChange( 0 /* STATUS_LOCAL_STREAM_REQUESTED */); - assertThat(mStateMachines).hasSize(2); - for (BassClientStateMachine sm : mStateMachines.values()) { - verify(sm, never()).sendMessage(any()); - } - /* Unicast finished streaming */ mBassClientService.handleUnicastSourceStreamStatusChange( 2 /* STATUS_LOCAL_STREAM_SUSPENDED */); @@ -4162,7 +4184,7 @@ public class BassClientServiceTest { messageCaptor.getAllValues().stream() .filter( m -> - (m.what == BassClientStateMachine.ADD_BCAST_SOURCE) + (m.what == BassClientStateMachine.UPDATE_BCAST_SOURCE) && (m.obj == meta)) .findFirst() .orElse(null); @@ -4312,9 +4334,7 @@ public class BassClientServiceTest { } @Test - @EnableFlags({ - Flags.FLAG_LEAUDIO_BIG_DEPENDS_ON_AUDIO_STATE - }) + @EnableFlags({Flags.FLAG_LEAUDIO_BIG_DEPENDS_ON_AUDIO_STATE}) public void testLocalAddSourceWhenBroadcastIsPaused() throws RemoteException { doReturn(false).when(mLeAudioService).isPlaying(TEST_BROADCAST_ID); doReturn(true).when(mLeAudioService).isPaused(TEST_BROADCAST_ID); @@ -4656,14 +4676,14 @@ public class BassClientServiceTest { // LEVEL 1 (byte) 0x01, (byte) 0x02, - (byte) 0x03, // presentationDelay - (byte) 0x01, // numSubGroups + (byte) 0x03, // mPresentationDelay + (byte) 0x01, // mNumSubGroups // LEVEL 3 - (byte) 0x04, // index - (byte) 0x03, // codecConfigLength + (byte) 0x04, // mIndex + (byte) 0x03, // mCodecConfigLength (byte) 0x02, (byte) 'B', - (byte) 'C', // codecConfigInfo + (byte) 'C', // mCodecConfigInfo (byte) 0x05, (byte) 0xff, (byte) 0xe0, @@ -4825,14 +4845,14 @@ public class BassClientServiceTest { // LEVEL 1 (byte) 0x01, (byte) 0x02, - (byte) 0x03, // presentationDelay - (byte) 0x01, // numSubGroups + (byte) 0x03, // mPresentationDelay + (byte) 0x01, // mNumSubGroups // LEVEL 3 - (byte) 0x04, // index - (byte) 0x03, // codecConfigLength + (byte) 0x04, // mIndex + (byte) 0x03, // mCodecConfigLength (byte) 0x02, (byte) 'B', - (byte) 'C', // codecConfigInfo + (byte) 'C', // mCodecConfigInfo (byte) 0x05, (byte) 0xff, (byte) 0xe0, @@ -5647,7 +5667,7 @@ public class BassClientServiceTest { // Suspend receivers, HOST_INTENTIONAL mBassClientService.suspendReceiversSourceSynchronization(TEST_BROADCAST_ID); verifyStopBigMonitoringWithUnsync(); - verifyRemoveMessageAndInjectSourceRemoval(); + verifyModifyMessageAndInjectSourceModfified(); checkNoResumeSynchronizationByBig(); checkResumeSynchronizationByHost(); } @@ -5660,7 +5680,7 @@ public class BassClientServiceTest { // Suspend receivers, HOST_INTENTIONAL mBassClientService.suspendReceiversSourceSynchronization(TEST_BROADCAST_ID); verifyStopBigMonitoringWithoutUnsync(); - verifyRemoveMessageAndInjectSourceRemoval(); + verifyModifyMessageAndInjectSourceModfified(); checkNoResumeSynchronizationByBig(); checkResumeSynchronizationByHost(); } @@ -5673,7 +5693,7 @@ public class BassClientServiceTest { // Suspend all receivers, HOST_INTENTIONAL mBassClientService.suspendAllReceiversSourceSynchronization(); verifyStopBigMonitoringWithUnsync(); - verifyRemoveMessageAndInjectSourceRemoval(); + verifyModifyMessageAndInjectSourceModfified(); checkNoResumeSynchronizationByBig(); checkResumeSynchronizationByHost(); } @@ -5686,7 +5706,7 @@ public class BassClientServiceTest { // Suspend all receivers, HOST_INTENTIONAL mBassClientService.suspendAllReceiversSourceSynchronization(); verifyStopBigMonitoringWithoutUnsync(); - verifyRemoveMessageAndInjectSourceRemoval(); + verifyModifyMessageAndInjectSourceModfified(); checkNoResumeSynchronizationByBig(); checkResumeSynchronizationByHost(); } @@ -5967,7 +5987,7 @@ public class BassClientServiceTest { mBassClientService.handleUnicastSourceStreamStatusChange( 3 /* STATUS_LOCAL_STREAM_REQUESTED_NO_CONTEXT_VALIDATE */); verifyStopBigMonitoringWithUnsync(); - verifyRemoveMessageAndInjectSourceRemoval(); + verifyModifyMessageAndInjectSourceModfified(); checkNoResumeSynchronizationByBig(); /* Unicast finished streaming */ @@ -5986,7 +6006,7 @@ public class BassClientServiceTest { mBassClientService.handleUnicastSourceStreamStatusChange( 3 /* STATUS_LOCAL_STREAM_REQUESTED_NO_CONTEXT_VALIDATE */); verifyStopBigMonitoringWithoutUnsync(); - verifyRemoveMessageAndInjectSourceRemoval(); + verifyModifyMessageAndInjectSourceModfified(); checkNoResumeSynchronizationByBig(); /* Unicast finished streaming */ @@ -6603,7 +6623,7 @@ public class BassClientServiceTest { // Suspend all receivers, HOST_INTENTIONAL mBassClientService.suspendAllReceiversSourceSynchronization(); - verifyRemoveMessageAndInjectSourceRemoval(); + verifyModifyMessageAndInjectSourceModfified(); // Start searching sources sync to paused broadcaster and remain cache startSearchingForSources(); @@ -6850,7 +6870,7 @@ public class BassClientServiceTest { mBassClientService.handleUnicastSourceStreamStatusChange( 3 /* STATUS_LOCAL_STREAM_REQUESTED_NO_CONTEXT_VALIDATE */); checkNoSinkPause(); - verifyRemoveMessageAndInjectSourceRemoval(); + verifyModifyMessageAndInjectSourceModfified(); /* Unicast finished streaming */ mBassClientService.handleUnicastSourceStreamStatusChange( @@ -6868,7 +6888,7 @@ public class BassClientServiceTest { mBassClientService.handleUnicastSourceStreamStatusChange( 3 /* STATUS_LOCAL_STREAM_REQUESTED_NO_CONTEXT_VALIDATE */); checkNoSinkPause(); - verifyRemoveMessageAndInjectSourceRemoval(); + verifyModifyMessageAndInjectSourceModfified(); /* Unicast finished streaming */ mBassClientService.handleUnicastSourceStreamStatusChange( @@ -7549,7 +7569,7 @@ public class BassClientServiceTest { /* Unicast would like to stream */ mBassClientService.handleUnicastSourceStreamStatusChange( 3 /* STATUS_LOCAL_STREAM_REQUESTED_NO_CONTEXT_VALIDATE */); - verifyRemoveMessageAndInjectSourceRemoval(); + verifyModifyMessageAndInjectSourceModfified(); for (BassClientStateMachine sm : mStateMachines.values()) { clearInvocations(sm); } @@ -7718,7 +7738,7 @@ public class BassClientServiceTest { /* Unicast would like to stream */ mBassClientService.handleUnicastSourceStreamStatusChange( 3 /* STATUS_LOCAL_STREAM_REQUESTED_NO_CONTEXT_VALIDATE */); - verifyRemoveMessageAndInjectSourceRemoval(); + verifyModifyMessageAndInjectSourceModfified(); for (BassClientStateMachine sm : mStateMachines.values()) { clearInvocations(sm); } @@ -7746,7 +7766,7 @@ public class BassClientServiceTest { /* Unicast would like to stream */ mBassClientService.handleUnicastSourceStreamStatusChange( 3 /* STATUS_LOCAL_STREAM_REQUESTED_NO_CONTEXT_VALIDATE */); - verifyRemoveMessageAndInjectSourceRemoval(); + verifyModifyMessageAndInjectSourceModfified(); for (BassClientStateMachine sm : mStateMachines.values()) { clearInvocations(sm); } @@ -7842,7 +7862,7 @@ public class BassClientServiceTest { /* Unicast would like to stream */ mBassClientService.handleUnicastSourceStreamStatusChange( 3 /* STATUS_LOCAL_STREAM_REQUESTED_NO_CONTEXT_VALIDATE */); - verifyRemoveMessageAndInjectSourceRemoval(); + verifyModifyMessageAndInjectSourceModfified(); for (BassClientStateMachine sm : mStateMachines.values()) { clearInvocations(sm); } diff --git a/android/app/tests/unit/src/com/android/bluetooth/bass_client/BassClientStateMachineTest.java b/android/app/tests/unit/src/com/android/bluetooth/bass_client/BassClientStateMachineTest.java index de0641296a..6915785794 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/bass_client/BassClientStateMachineTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/bass_client/BassClientStateMachineTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2022 The Android Open Source Project + * Copyright (C) 2022 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. @@ -30,6 +30,7 @@ import static androidx.test.espresso.intent.matcher.IntentMatchers.hasFlag; import static com.android.bluetooth.TestUtils.MockitoRule; import static com.android.bluetooth.TestUtils.getTestDevice; +import static com.android.bluetooth.Utils.joinUninterruptibly; import static com.android.bluetooth.bass_client.BassClientStateMachine.ADD_BCAST_SOURCE; import static com.android.bluetooth.bass_client.BassClientStateMachine.CANCEL_PENDING_SOURCE_OPERATION; import static com.android.bluetooth.bass_client.BassClientStateMachine.CONNECT; @@ -108,7 +109,6 @@ import com.android.bluetooth.btservice.MetricsLogger; import com.android.bluetooth.flags.Flags; import com.google.common.primitives.Bytes; -import com.google.common.util.concurrent.Uninterruptibles; import org.hamcrest.Matcher; import org.hamcrest.core.AllOf; @@ -218,7 +218,7 @@ public class BassClientStateMachineTest { MetricsLogger.setInstanceForTesting(null); mBassClientStateMachine.doQuit(); mHandlerThread.quit(); - Uninterruptibles.joinUninterruptibly(mHandlerThread); + joinUninterruptibly(mHandlerThread); TestUtils.clearAdapterService(mAdapterService); } @@ -533,7 +533,6 @@ public class BassClientStateMachineTest { assertThat(mBassClientStateMachine.isPendingRemove(invalidSourceId)).isFalse(); } - @Test public void gattCallbackOnConnectionStateChange_changedToConnected() throws InterruptedException { @@ -1214,7 +1213,7 @@ public class BassClientStateMachineTest { // Update value - PA SyncInfo Request, local broadcast mBassClientStateMachine.mPendingMetadata = createBroadcastMetadata(); - when(mBassClientService.isLocalBroadcast(any(BluetoothLeBroadcastMetadata.class))) + when(mBassClientService.isLocalBroadcast(any(BluetoothLeBroadcastReceiveState.class))) .thenReturn(true); cb.onCharacteristicChanged(null, characteristic); TestUtils.waitForLooperToFinishScheduledTask(mHandlerThread.getLooper()); @@ -1717,9 +1716,29 @@ public class BassClientStateMachineTest { mBassClientStateMachine.sendMessage(UPDATE_BCAST_SOURCE, sourceId, paSync, metadata); TestUtils.waitForLooperToFinishScheduledTask(mHandlerThread.getLooper()); - BaseData data = Mockito.mock(BaseData.class); + byte[] serviceData = + new byte[] { + // LEVEL 1 + (byte) 0x01, + (byte) 0x02, + (byte) 0x03, // mPresentationDelay + (byte) 0x01, // mNumSubGroups + // LEVEL 2 + (byte) 0x01, // numBIS + (byte) 0xFF, // VENDOR_CODEC + (byte) 0x0A, + (byte) 0xAB, + (byte) 0xBC, + (byte) 0xCD, + (byte) 0x00, // mCodecConfigLength + (byte) 0x00, // mMetaDataLength + // LEVEL 3 + (byte) 0x04, // mIndex + (byte) 0x00, // mCodecConfigLength + }; + + BaseData data = BaseData.parseBaseData(serviceData); when(mBassClientService.getBase(anyInt())).thenReturn(data); - when(data.getNumberOfSubGroupsOfBIG()).thenReturn((byte) 1); Mockito.clearInvocations(callbacks); mBassClientStateMachine.sendMessage(UPDATE_BCAST_SOURCE, sourceId, paSync, metadata); diff --git a/android/app/tests/unit/src/com/android/bluetooth/bass_client/BleBroadcastAssistantBinderTest.java b/android/app/tests/unit/src/com/android/bluetooth/bass_client/BleBroadcastAssistantBinderTest.java index d51e857efe..ae402d7d0f 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/bass_client/BleBroadcastAssistantBinderTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/bass_client/BleBroadcastAssistantBinderTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2022 The Android Open Source Project + * Copyright (C) 2022 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. diff --git a/android/app/tests/unit/src/com/android/bluetooth/bass_client/PeriodicAdvertisementResultTest.java b/android/app/tests/unit/src/com/android/bluetooth/bass_client/PeriodicAdvertisementResultTest.java index e86952a165..d7d0605fb5 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/bass_client/PeriodicAdvertisementResultTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/bass_client/PeriodicAdvertisementResultTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2023 The Android Open Source Project + * Copyright (C) 2023 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/android/app/tests/unit/src/com/android/bluetooth/bass_client/PublicBroadcastDataTest.java b/android/app/tests/unit/src/com/android/bluetooth/bass_client/PublicBroadcastDataTest.java index f8d3db6482..48c2b7935c 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/bass_client/PublicBroadcastDataTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/bass_client/PublicBroadcastDataTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2023 The Android Open Source Project + * Copyright (C) 2023 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/android/app/tests/unit/src/com/android/bluetooth/btservice/ActiveDeviceManagerTest.java b/android/app/tests/unit/src/com/android/bluetooth/btservice/ActiveDeviceManagerTest.java index 13f38272e6..2af03df4ae 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/btservice/ActiveDeviceManagerTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/btservice/ActiveDeviceManagerTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2018 The Android Open Source Project + * Copyright (C) 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. diff --git a/android/app/tests/unit/src/com/android/bluetooth/btservice/AdapterPropertiesTest.java b/android/app/tests/unit/src/com/android/bluetooth/btservice/AdapterPropertiesTest.java index 3e6180f336..db3a61cb3a 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/btservice/AdapterPropertiesTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/btservice/AdapterPropertiesTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2023 The Android Open Source Project + * Copyright (C) 2023 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/android/app/tests/unit/src/com/android/bluetooth/btservice/AdapterServiceBinderTest.java b/android/app/tests/unit/src/com/android/bluetooth/btservice/AdapterServiceBinderTest.java index 8c666babfd..955f579ce4 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/btservice/AdapterServiceBinderTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/btservice/AdapterServiceBinderTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2023 The Android Open Source Project + * Copyright (C) 2023 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -23,6 +23,7 @@ import static org.mockito.Mockito.doNothing; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.never; import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; import android.bluetooth.BluetoothAdapter; import android.bluetooth.IBluetoothOobDataCallback; @@ -37,28 +38,29 @@ import org.mockito.Mockito; import java.io.FileDescriptor; +/** Test cases for {@link AdapterServiceBinder}. */ public class AdapterServiceBinderTest { @Rule public final MockitoRule mMockitoRule = new MockitoRule(); @Mock private AdapterService mService; @Mock private AdapterProperties mAdapterProperties; - private AdapterService.AdapterServiceBinder mBinder; + private AdapterServiceBinder mBinder; private AttributionSource mAttributionSource; @Before public void setUp() { - mService.mAdapterProperties = mAdapterProperties; + when(mService.getAdapterProperties()).thenReturn(mAdapterProperties); doReturn(true).when(mService).isAvailable(); doNothing().when(mService).enforceCallingOrSelfPermission(any(), any()); - mBinder = new AdapterService.AdapterServiceBinder(mService); + mBinder = new AdapterServiceBinder(mService); mAttributionSource = new AttributionSource.Builder(0).build(); } @Test public void getAddress() { mBinder.getAddress(mAttributionSource); - verify(mService.mAdapterProperties).getAddress(); + verify(mAdapterProperties).getAddress(); } @Test @@ -116,7 +118,7 @@ public class AdapterServiceBinderTest { @Test public void isActivityAndEnergyReportingSupported() { mBinder.isActivityAndEnergyReportingSupported(); - verify(mService.mAdapterProperties).isActivityAndEnergyReportingSupported(); + verify(mAdapterProperties).isActivityAndEnergyReportingSupported(); } @Test 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..a9e01b3086 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 @@ -1,5 +1,5 @@ /* - * Copyright 2017 The Android Open Source Project + * Copyright (C) 2017 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. @@ -113,6 +113,7 @@ import java.util.Map; import javax.crypto.Mac; import javax.crypto.spec.SecretKeySpec; +/** Test cases for {@link AdapterService}. */ @MediumTest @RunWith(ParameterizedAndroidJunit4.class) public class AdapterServiceTest { @@ -1020,8 +1021,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/btservice/AdapterSuspendTest.java b/android/app/tests/unit/src/com/android/bluetooth/btservice/AdapterSuspendTest.java index c175cfaa02..bc86ce8ee1 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/btservice/AdapterSuspendTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/btservice/AdapterSuspendTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2024 The Android Open Source Project + * Copyright (C) 2024 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. diff --git a/android/app/tests/unit/src/com/android/bluetooth/btservice/BondStateMachineTest.java b/android/app/tests/unit/src/com/android/bluetooth/btservice/BondStateMachineTest.java index 044ededd4a..f420ffb43f 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/btservice/BondStateMachineTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/btservice/BondStateMachineTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2018 The Android Open Source Project + * Copyright (C) 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. diff --git a/android/app/tests/unit/src/com/android/bluetooth/btservice/CompanionManagerTest.java b/android/app/tests/unit/src/com/android/bluetooth/btservice/CompanionManagerTest.java index 2b3d692035..bea6e8ea6d 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/btservice/CompanionManagerTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/btservice/CompanionManagerTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2022 The Android Open Source Project + * Copyright (C) 2022 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. diff --git a/android/app/tests/unit/src/com/android/bluetooth/btservice/ConfigTest.java b/android/app/tests/unit/src/com/android/bluetooth/btservice/ConfigTest.java index de1c706db2..704234cf1e 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/btservice/ConfigTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/btservice/ConfigTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2023 The Android Open Source Project + * Copyright (C) 2023 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/android/app/tests/unit/src/com/android/bluetooth/btservice/MetricsLoggerTest.java b/android/app/tests/unit/src/com/android/bluetooth/btservice/MetricsLoggerTest.java index 21f04ff490..1b057b3a7e 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/btservice/MetricsLoggerTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/btservice/MetricsLoggerTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2018 The Android Open Source Project + * Copyright (C) 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. @@ -25,10 +25,7 @@ import android.bluetooth.BluetoothDevice; import androidx.test.filters.MediumTest; import androidx.test.runner.AndroidJUnit4; -import com.android.bluetooth.BluetoothMetricsProto.BluetoothLog; import com.android.bluetooth.BluetoothMetricsProto.BluetoothRemoteDeviceInformation; -import com.android.bluetooth.BluetoothMetricsProto.ProfileConnectionStats; -import com.android.bluetooth.BluetoothMetricsProto.ProfileId; import com.google.common.hash.BloomFilter; import com.google.common.hash.Funnels; @@ -44,7 +41,6 @@ import org.mockito.Mock; import java.io.ByteArrayInputStream; import java.io.IOException; import java.util.HashMap; -import java.util.List; import java.util.Map; /** Unit tests for {@link MetricsLogger} */ @@ -111,68 +107,15 @@ public class MetricsLoggerTest { @Before public void setUp() { - MetricsLogger.dumpProto(BluetoothLog.newBuilder()); mTestableMetricsLogger = new TestableMetricsLogger(); mTestableMetricsLogger.init(mAdapterService, mRemoteDevices); } @After public void tearDown() { - // Dump metrics to clean up internal states - MetricsLogger.dumpProto(BluetoothLog.newBuilder()); mTestableMetricsLogger.close(); } - /** Simple test to verify that profile connection event can be logged, dumped, and cleaned */ - @Test - public void testLogProfileConnectionEvent() { - MetricsLogger.logProfileConnectionEvent(ProfileId.AVRCP); - BluetoothLog.Builder metricsBuilder = BluetoothLog.newBuilder(); - MetricsLogger.dumpProto(metricsBuilder); - BluetoothLog metricsProto = metricsBuilder.build(); - assertThat(metricsProto.getProfileConnectionStatsCount()).isEqualTo(1); - ProfileConnectionStats profileUsageStatsAvrcp = metricsProto.getProfileConnectionStats(0); - assertThat(profileUsageStatsAvrcp.getProfileId()).isEqualTo(ProfileId.AVRCP); - assertThat(profileUsageStatsAvrcp.getNumTimesConnected()).isEqualTo(1); - // Verify that MetricsLogger's internal state is cleared after a dump - BluetoothLog.Builder metricsBuilderAfterDump = BluetoothLog.newBuilder(); - MetricsLogger.dumpProto(metricsBuilderAfterDump); - BluetoothLog metricsProtoAfterDump = metricsBuilderAfterDump.build(); - assertThat(metricsProtoAfterDump.getProfileConnectionStatsCount()).isEqualTo(0); - } - - /** Test whether multiple profile's connection events can be logged interleaving */ - @Test - public void testLogProfileConnectionEventMultipleProfile() { - MetricsLogger.logProfileConnectionEvent(ProfileId.AVRCP); - MetricsLogger.logProfileConnectionEvent(ProfileId.HEADSET); - MetricsLogger.logProfileConnectionEvent(ProfileId.AVRCP); - BluetoothLog.Builder metricsBuilder = BluetoothLog.newBuilder(); - MetricsLogger.dumpProto(metricsBuilder); - BluetoothLog metricsProto = metricsBuilder.build(); - assertThat(metricsProto.getProfileConnectionStatsCount()).isEqualTo(2); - Map<ProfileId, ProfileConnectionStats> profileConnectionCountMap = - getProfileUsageStatsMap(metricsProto.getProfileConnectionStatsList()); - assertThat(profileConnectionCountMap).containsKey(ProfileId.AVRCP); - assertThat(profileConnectionCountMap.get(ProfileId.AVRCP).getNumTimesConnected()) - .isEqualTo(2); - assertThat(profileConnectionCountMap).containsKey(ProfileId.HEADSET); - assertThat(profileConnectionCountMap.get(ProfileId.HEADSET).getNumTimesConnected()) - .isEqualTo(1); - // Verify that MetricsLogger's internal state is cleared after a dump - BluetoothLog.Builder metricsBuilderAfterDump = BluetoothLog.newBuilder(); - MetricsLogger.dumpProto(metricsBuilderAfterDump); - BluetoothLog metricsProtoAfterDump = metricsBuilderAfterDump.build(); - assertThat(metricsProtoAfterDump.getProfileConnectionStatsCount()).isEqualTo(0); - } - - private static Map<ProfileId, ProfileConnectionStats> getProfileUsageStatsMap( - List<ProfileConnectionStats> profileUsageStats) { - HashMap<ProfileId, ProfileConnectionStats> profileUsageStatsMap = new HashMap<>(); - profileUsageStats.forEach(item -> profileUsageStatsMap.put(item.getProfileId(), item)); - return profileUsageStatsMap; - } - /** Test add counters and send them to statsd */ @Test public void testAddAndSendCountersNormalCases() { diff --git a/android/app/tests/unit/src/com/android/bluetooth/btservice/PhonePolicyTest.java b/android/app/tests/unit/src/com/android/bluetooth/btservice/PhonePolicyTest.java index 906436cfbe..28188621a0 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/btservice/PhonePolicyTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/btservice/PhonePolicyTest.java @@ -119,8 +119,6 @@ public class PhonePolicyTest { doReturn(BluetoothAdapter.STATE_ON).when(mAdapterService).getState(); doReturn(MAX_CONNECTED_AUDIO_DEVICES).when(mAdapterService).getMaxConnectedAudioDevices(); doReturn(mDatabaseManager).when(mAdapterService).getDatabase(); - doReturn(mLooper.getLooper()).when(mAdapterService).getMainLooper(); - // Setup the mocked factory to return mocked services doReturn(mHeadsetService).when(mServiceFactory).getHeadsetService(); doReturn(mA2dpService).when(mServiceFactory).getA2dpService(); diff --git a/android/app/tests/unit/src/com/android/bluetooth/btservice/ProfileServiceTest.java b/android/app/tests/unit/src/com/android/bluetooth/btservice/ProfileServiceTest.java index dd7d46d661..960374ddae 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/btservice/ProfileServiceTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/btservice/ProfileServiceTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2018 The Android Open Source Project + * Copyright (C) 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. diff --git a/android/app/tests/unit/src/com/android/bluetooth/btservice/SilenceDeviceManagerTest.java b/android/app/tests/unit/src/com/android/bluetooth/btservice/SilenceDeviceManagerTest.java index 2a49540088..8cbf61d8d8 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/btservice/SilenceDeviceManagerTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/btservice/SilenceDeviceManagerTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2019 The Android Open Source Project + * Copyright (C) 2019 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. @@ -76,7 +76,6 @@ public class SilenceDeviceManagerTest { mHandlerThread.start(); mLooper = mHandlerThread.getLooper(); mSilenceDeviceManager = new SilenceDeviceManager(mAdapterService, mServiceFactory, mLooper); - mSilenceDeviceManager.start(); } @After diff --git a/android/app/tests/unit/src/com/android/bluetooth/btservice/bluetoothKeystore/BluetoothKeystoreServiceTest.java b/android/app/tests/unit/src/com/android/bluetooth/btservice/bluetoothKeystore/BluetoothKeystoreServiceTest.java index e44682c266..0b3cc08343 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/btservice/bluetoothKeystore/BluetoothKeystoreServiceTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/btservice/bluetoothKeystore/BluetoothKeystoreServiceTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2020 The Android Open Source Project + * Copyright (C) 2020 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. diff --git a/android/app/tests/unit/src/com/android/bluetooth/btservice/storage/AudioPolicyEntityTest.java b/android/app/tests/unit/src/com/android/bluetooth/btservice/storage/AudioPolicyEntityTest.java index 38dd6d6807..317153b64b 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/btservice/storage/AudioPolicyEntityTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/btservice/storage/AudioPolicyEntityTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2023 The Android Open Source Project + * Copyright (C) 2023 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/android/app/tests/unit/src/com/android/bluetooth/btservice/storage/DatabaseManagerTest.java b/android/app/tests/unit/src/com/android/bluetooth/btservice/storage/DatabaseManagerTest.java index b020dbf6d8..21449beaf5 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/btservice/storage/DatabaseManagerTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/btservice/storage/DatabaseManagerTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2019 The Android Open Source Project + * Copyright (C) 2019 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. diff --git a/android/app/tests/unit/src/com/android/bluetooth/content_profiles/ContentProfileErrorReportUtilsTest.java b/android/app/tests/unit/src/com/android/bluetooth/content_profiles/ContentProfileErrorReportUtilsTest.java index dc4e6dc5e8..e682e9af17 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/content_profiles/ContentProfileErrorReportUtilsTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/content_profiles/ContentProfileErrorReportUtilsTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2023 The Android Open Source Project + * Copyright (C) 2023 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/android/app/tests/unit/src/com/android/bluetooth/csip/BluetoothCsisBinderTest.java b/android/app/tests/unit/src/com/android/bluetooth/csip/BluetoothCsisBinderTest.java index 69e8546ac3..9233602c47 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/csip/BluetoothCsisBinderTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/csip/BluetoothCsisBinderTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2022 The Android Open Source Project + * Copyright (C) 2022 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. diff --git a/android/app/tests/unit/src/com/android/bluetooth/gatt/AdvertiseBinderTest.java b/android/app/tests/unit/src/com/android/bluetooth/gatt/AdvertiseBinderTest.java index f90223cd24..c78c9ec6db 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/gatt/AdvertiseBinderTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/gatt/AdvertiseBinderTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2025 The Android Open Source Project + * Copyright (C) 2025 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/android/app/tests/unit/src/com/android/bluetooth/gatt/AdvertiseHelperTest.java b/android/app/tests/unit/src/com/android/bluetooth/gatt/AdvertiseHelperTest.java index 5f89c4b4ca..6b461556fe 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/gatt/AdvertiseHelperTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/gatt/AdvertiseHelperTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2022 The Android Open Source Project + * Copyright (C) 2022 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. @@ -40,16 +40,12 @@ public class AdvertiseHelperTest { @Test public void advertiseDataToBytes() throws Exception { byte[] emptyBytes = AdvertiseHelper.advertiseDataToBytes(null, ""); - assertThat(emptyBytes.length).isEqualTo(0); int manufacturerId = 1; byte[] manufacturerData = new byte[] {0x30, 0x31, 0x32, 0x34}; - byte[] serviceData = new byte[] {0x10, 0x12, 0x14}; - byte[] transportDiscoveryData = new byte[] {0x40, 0x44, 0x48}; - AdvertiseData advertiseData = new AdvertiseData.Builder() .setIncludeDeviceName(true) @@ -62,18 +58,16 @@ public class AdvertiseHelperTest { new TransportDiscoveryData(transportDiscoveryData)) .build(); String deviceName = "TestDeviceName"; - int expectedAdvDataBytesLength = 86; - byte[] advDataBytes = AdvertiseHelper.advertiseDataToBytes(advertiseData, deviceName); - - String deviceNameLong = "TestDeviceNameLongTestDeviceName"; + byte[] advDataBytes = AdvertiseHelper.advertiseDataToBytes(advertiseData, deviceName); assertThat(advDataBytes.length).isEqualTo(expectedAdvDataBytesLength); + String deviceNameLong = "TestDeviceNameLongTestDeviceName"; int expectedAdvDataBytesLongNameLength = 98; + byte[] advDataBytesLongName = AdvertiseHelper.advertiseDataToBytes(advertiseData, deviceNameLong); - assertThat(advDataBytesLongName.length).isEqualTo(expectedAdvDataBytesLongNameLength); } diff --git a/android/app/tests/unit/src/com/android/bluetooth/gatt/AdvertiseManagerTest.java b/android/app/tests/unit/src/com/android/bluetooth/gatt/AdvertiseManagerTest.java index 8537795af5..5aab3db081 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/gatt/AdvertiseManagerTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/gatt/AdvertiseManagerTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2022 The Android Open Source Project + * Copyright (C) 2022 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. diff --git a/android/app/tests/unit/src/com/android/bluetooth/gatt/AdvertiserMapTest.java b/android/app/tests/unit/src/com/android/bluetooth/gatt/AdvertiserMapTest.java index df0d609e89..35d222f739 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/gatt/AdvertiserMapTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/gatt/AdvertiserMapTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2024 The Android Open Source Project + * Copyright (C) 2024 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. diff --git a/android/app/tests/unit/src/com/android/bluetooth/gatt/AppAdvertiseStatsTest.java b/android/app/tests/unit/src/com/android/bluetooth/gatt/AppAdvertiseStatsTest.java index a9fc2b6e3f..01c4000778 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/gatt/AppAdvertiseStatsTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/gatt/AppAdvertiseStatsTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2022 The Android Open Source Project + * Copyright (C) 2022 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. @@ -16,6 +16,8 @@ package com.android.bluetooth.gatt; +import static android.app.ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND_SERVICE; + import static com.android.bluetooth.TestUtils.MockitoRule; import static com.google.common.truth.Truth.assertThat; @@ -311,6 +313,8 @@ public class AppAdvertiseStatsTest { AppAdvertiseStats appAdvertiseStats = new AppAdvertiseStats(appUid, id, name, mAttributionSource); + // Set app importance as Foreground Service for the stats + appAdvertiseStats.setAppImportance(IMPORTANCE_FOREGROUND_SERVICE); AdvertisingSetParameters parameters = new AdvertisingSetParameters.Builder().setConnectable(true).build(); @@ -351,7 +355,9 @@ public class AppAdvertiseStatsTest { false, true, instanceCount, - 0); + 0, + IMPORTANCE_FOREGROUND_SERVICE, + ""); Mockito.clearInvocations(mMetricsLogger); // Wait for adv test duration @@ -384,7 +390,9 @@ public class AppAdvertiseStatsTest { eq(false), eq(true), eq(instanceCount), - mAdvDurationCaptor.capture()); + mAdvDurationCaptor.capture(), + eq(IMPORTANCE_FOREGROUND_SERVICE), + eq("")); long capturedAppScanDuration = mAdvDurationCaptor.getValue(); Log.d(TAG, "capturedDuration: " + capturedAppScanDuration); assertThat(capturedAppScanDuration).isAtLeast(advTestDuration); diff --git a/android/app/tests/unit/src/com/android/bluetooth/gatt/CallbackInfoTest.java b/android/app/tests/unit/src/com/android/bluetooth/gatt/CallbackInfoTest.java index b23cbc8b8f..ed5d1c1b6b 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/gatt/CallbackInfoTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/gatt/CallbackInfoTest.java @@ -16,34 +16,49 @@ package com.android.bluetooth.gatt; -import static com.google.common.truth.Truth.assertThat; import androidx.test.filters.SmallTest; import androidx.test.runner.AndroidJUnit4; +import com.google.common.truth.Expect; +import com.google.protobuf.ByteString; + +import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; -import java.util.Arrays; - /** Test cases for {@link CallbackInfo}. */ @SmallTest @RunWith(AndroidJUnit4.class) public class CallbackInfoTest { + @Rule public Expect expect = Expect.create(); + @Test - public void callbackInfoBuilder() { + public void callbackInfo_default() { String address = "TestAddress"; int status = 0; int handle = 1; - byte[] value = "Test Value Byte Array".getBytes(); + ByteString value = ByteString.copyFrom("Test Value Byte Array".getBytes()); + + CallbackInfo callbackInfo = new CallbackInfo(address, status, handle, value); + + expect.that(callbackInfo.address()).isEqualTo(address); + expect.that(callbackInfo.status()).isEqualTo(status); + expect.that(callbackInfo.handle()).isEqualTo(handle); + expect.that(callbackInfo.value()).isEqualTo(value); + } + + @Test + public void callbackInfo_nullValue() { + String address = "TestAddress"; + int status = 0; - CallbackInfo callbackInfo = - new CallbackInfo.Builder(address, status).setHandle(handle).setValue(value).build(); + CallbackInfo callbackInfo = new CallbackInfo(address, status); - assertThat(callbackInfo.address).isEqualTo(address); - assertThat(callbackInfo.status).isEqualTo(status); - assertThat(callbackInfo.handle).isEqualTo(handle); - assertThat(Arrays.equals(callbackInfo.value, value)).isTrue(); + expect.that(callbackInfo.address()).isEqualTo(address); + expect.that(callbackInfo.status()).isEqualTo(status); + expect.that(callbackInfo.value()).isNull(); + expect.that(callbackInfo.valueByteArray()).isNull(); } } diff --git a/android/app/tests/unit/src/com/android/bluetooth/gatt/ContextMapTest.java b/android/app/tests/unit/src/com/android/bluetooth/gatt/ContextMapTest.java index dac06a7086..6df604077d 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/gatt/ContextMapTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/gatt/ContextMapTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2022 The Android Open Source Project + * Copyright (C) 2022 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. diff --git a/android/app/tests/unit/src/com/android/bluetooth/gatt/DistanceMeasurementBinderTest.java b/android/app/tests/unit/src/com/android/bluetooth/gatt/DistanceMeasurementBinderTest.java index 9db59f4fb1..a65c805a47 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/gatt/DistanceMeasurementBinderTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/gatt/DistanceMeasurementBinderTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2025 The Android Open Source Project + * Copyright (C) 2025 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/android/app/tests/unit/src/com/android/bluetooth/gatt/FilterParamsTest.java b/android/app/tests/unit/src/com/android/bluetooth/gatt/FilterParamsTest.java index 84aebeafa6..0c9559a6c5 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/gatt/FilterParamsTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/gatt/FilterParamsTest.java @@ -16,11 +16,12 @@ package com.android.bluetooth.gatt; -import static com.google.common.truth.Truth.assertThat; - import androidx.test.filters.SmallTest; import androidx.test.runner.AndroidJUnit4; +import com.google.common.truth.Expect; + +import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; @@ -28,50 +29,49 @@ import org.junit.runner.RunWith; @SmallTest @RunWith(AndroidJUnit4.class) public class FilterParamsTest { + @Rule public final Expect expect = Expect.create(); @Test public void filterParamsProperties() { - int clientIf = 0; - int filtIndex = 1; - int featSeln = 2; + int clientInterface = 0; + int filterIndex = 1; + int featureSelection = 2; int listLogicType = 3; - int filtLogicType = 4; + int filterLogicType = 4; int rssiHighValue = 5; int rssiLowValue = 6; - int delyMode = 7; - int foundTimeOut = 8; - int lostTimeOut = 9; - int foundTimeOutCnt = 10; - int numOfTrackEntries = 11; + int delayMode = 7; + int foundTimeout = 8; + int lostTimeout = 9; + int foundTimeoutCount = 10; + int numberOfTrackEntries = 11; FilterParams filterParams = new FilterParams( - clientIf, - filtIndex, - featSeln, + clientInterface, + filterIndex, + featureSelection, listLogicType, - filtLogicType, + filterLogicType, rssiHighValue, rssiLowValue, - delyMode, - foundTimeOut, - lostTimeOut, - foundTimeOutCnt, - numOfTrackEntries); - - assertThat(filterParams).isNotNull(); + delayMode, + foundTimeout, + lostTimeout, + foundTimeoutCount, + numberOfTrackEntries); - assertThat(filterParams.getClientIf()).isEqualTo(clientIf); - assertThat(filterParams.getFiltIndex()).isEqualTo(filtIndex); - assertThat(filterParams.getFeatSeln()).isEqualTo(featSeln); - assertThat(filterParams.getListLogicType()).isEqualTo(listLogicType); - assertThat(filterParams.getFiltLogicType()).isEqualTo(filtLogicType); - assertThat(filterParams.getRSSIHighValue()).isEqualTo(rssiHighValue); - assertThat(filterParams.getRSSILowValue()).isEqualTo(rssiLowValue); - assertThat(filterParams.getDelyMode()).isEqualTo(delyMode); - assertThat(filterParams.getFoundTimeout()).isEqualTo(foundTimeOut); - assertThat(filterParams.getLostTimeout()).isEqualTo(lostTimeOut); - assertThat(filterParams.getFoundTimeOutCnt()).isEqualTo(foundTimeOutCnt); - assertThat(filterParams.getNumOfTrackEntries()).isEqualTo(numOfTrackEntries); + expect.that(filterParams.clientInterface()).isEqualTo(clientInterface); + expect.that(filterParams.filterIndex()).isEqualTo(filterIndex); + expect.that(filterParams.featureSelection()).isEqualTo(featureSelection); + expect.that(filterParams.listLogicType()).isEqualTo(listLogicType); + expect.that(filterParams.filterLogicType()).isEqualTo(filterLogicType); + expect.that(filterParams.rssiHighValue()).isEqualTo(rssiHighValue); + expect.that(filterParams.rssiLowValue()).isEqualTo(rssiLowValue); + expect.that(filterParams.delayMode()).isEqualTo(delayMode); + expect.that(filterParams.foundTimeout()).isEqualTo(foundTimeout); + expect.that(filterParams.lostTimeout()).isEqualTo(lostTimeout); + expect.that(filterParams.foundTimeoutCount()).isEqualTo(foundTimeoutCount); + expect.that(filterParams.numberOfTrackEntries()).isEqualTo(numberOfTrackEntries); } } diff --git a/android/app/tests/unit/src/com/android/bluetooth/gatt/GattDebugUtilsTest.java b/android/app/tests/unit/src/com/android/bluetooth/gatt/GattDebugUtilsTest.java index 4237759122..8b4760c42f 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/gatt/GattDebugUtilsTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/gatt/GattDebugUtilsTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2022 The Android Open Source Project + * Copyright (C) 2022 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. diff --git a/android/app/tests/unit/src/com/android/bluetooth/gatt/GattServiceBinderTest.java b/android/app/tests/unit/src/com/android/bluetooth/gatt/GattServiceBinderTest.java index a246d76b8f..36e96f6007 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/gatt/GattServiceBinderTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/gatt/GattServiceBinderTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2022 The Android Open Source Project + * Copyright (C) 2022 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. diff --git a/android/app/tests/unit/src/com/android/bluetooth/gatt/GattServiceTest.java b/android/app/tests/unit/src/com/android/bluetooth/gatt/GattServiceTest.java index f52702a24b..76d6dd53ff 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/gatt/GattServiceTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/gatt/GattServiceTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2023 The Android Open Source Project + * Copyright (C) 2023 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/android/app/tests/unit/src/com/android/bluetooth/hap/HapClientBinderTest.java b/android/app/tests/unit/src/com/android/bluetooth/hap/HapClientBinderTest.java index 7f079c79b7..dd5ede57b2 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/hap/HapClientBinderTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/hap/HapClientBinderTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2024 The Android Open Source Project + * Copyright (C) 2024 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. diff --git a/android/app/tests/unit/src/com/android/bluetooth/hap/HapClientNativeCallbackTest.java b/android/app/tests/unit/src/com/android/bluetooth/hap/HapClientNativeCallbackTest.java index a67995ffae..5e1218b202 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/hap/HapClientNativeCallbackTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/hap/HapClientNativeCallbackTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2024 The Android Open Source Project + * Copyright (C) 2024 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. diff --git a/android/app/tests/unit/src/com/android/bluetooth/hap/HapClientStackEventTest.java b/android/app/tests/unit/src/com/android/bluetooth/hap/HapClientStackEventTest.java index 249914b644..01a12b7a9b 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/hap/HapClientStackEventTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/hap/HapClientStackEventTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2022 The Android Open Source Project + * Copyright (C) 2022 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. diff --git a/android/app/tests/unit/src/com/android/bluetooth/hearingaid/HearingAidNativeInterfaceTest.java b/android/app/tests/unit/src/com/android/bluetooth/hearingaid/HearingAidNativeInterfaceTest.java index ac7c90a213..6b32743a7b 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/hearingaid/HearingAidNativeInterfaceTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/hearingaid/HearingAidNativeInterfaceTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2022 The Android Open Source Project + * Copyright (C) 2022 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. diff --git a/android/app/tests/unit/src/com/android/bluetooth/hearingaid/HearingAidServiceTest.java b/android/app/tests/unit/src/com/android/bluetooth/hearingaid/HearingAidServiceTest.java index 69bcca1087..757a6488be 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/hearingaid/HearingAidServiceTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/hearingaid/HearingAidServiceTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2018 The Android Open Source Project + * Copyright (C) 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. diff --git a/android/app/tests/unit/src/com/android/bluetooth/hearingaid/HearingAidStateMachineTest.java b/android/app/tests/unit/src/com/android/bluetooth/hearingaid/HearingAidStateMachineTest.java index 20feec9b8a..07cd5703ff 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/hearingaid/HearingAidStateMachineTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/hearingaid/HearingAidStateMachineTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2018 The Android Open Source Project + * Copyright (C) 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. diff --git a/android/app/tests/unit/src/com/android/bluetooth/hfp/AtPhonebookTest.java b/android/app/tests/unit/src/com/android/bluetooth/hfp/AtPhonebookTest.java index 123b34c178..b54da60e79 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/hfp/AtPhonebookTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/hfp/AtPhonebookTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2022 The Android Open Source Project + * Copyright (C) 2022 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. diff --git a/android/app/tests/unit/src/com/android/bluetooth/hfp/BluetoothHeadsetBinderTest.java b/android/app/tests/unit/src/com/android/bluetooth/hfp/BluetoothHeadsetBinderTest.java index 398ba1c6cd..d125fbee4c 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/hfp/BluetoothHeadsetBinderTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/hfp/BluetoothHeadsetBinderTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2022 The Android Open Source Project + * Copyright (C) 2022 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. diff --git a/android/app/tests/unit/src/com/android/bluetooth/hfp/HeadsetAgIndicatorEnableStateTest.java b/android/app/tests/unit/src/com/android/bluetooth/hfp/HeadsetAgIndicatorEnableStateTest.java index f034bf44cf..8fa050b679 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/hfp/HeadsetAgIndicatorEnableStateTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/hfp/HeadsetAgIndicatorEnableStateTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2022 The Android Open Source Project + * Copyright (C) 2022 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. diff --git a/android/app/tests/unit/src/com/android/bluetooth/hfp/HeadsetClccResponseTest.java b/android/app/tests/unit/src/com/android/bluetooth/hfp/HeadsetClccResponseTest.java index 3f6603ff3a..63e0f2632d 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/hfp/HeadsetClccResponseTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/hfp/HeadsetClccResponseTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2022 The Android Open Source Project + * Copyright (C) 2022 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. 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..edcf484239 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 @@ -1,5 +1,5 @@ /* - * Copyright 2018 The Android Open Source Project + * Copyright (C) 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. @@ -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..3edd1ff9ea 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 @@ -1,5 +1,5 @@ /* - * Copyright 2018 The Android Open Source Project + * Copyright (C) 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. @@ -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/HeadsetServiceTest.java b/android/app/tests/unit/src/com/android/bluetooth/hfp/HeadsetServiceTest.java index 18a53db436..b16578c823 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/hfp/HeadsetServiceTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/hfp/HeadsetServiceTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2018 The Android Open Source Project + * Copyright (C) 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. diff --git a/android/app/tests/unit/src/com/android/bluetooth/hfp/HeadsetStackEventTest.java b/android/app/tests/unit/src/com/android/bluetooth/hfp/HeadsetStackEventTest.java index bf90084521..d5f66da856 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/hfp/HeadsetStackEventTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/hfp/HeadsetStackEventTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2022 The Android Open Source Project + * Copyright (C) 2022 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. 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 696089931e..68c17a10f8 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 @@ -1,5 +1,5 @@ /* - * Copyright 2017 The Android Open Source Project + * Copyright (C) 2017 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. @@ -27,6 +27,7 @@ import static android.media.audio.Flags.FLAG_DEPRECATE_STREAM_BT_SCO; import static com.android.bluetooth.TestUtils.MockitoRule; import static com.android.bluetooth.TestUtils.getTestDevice; +import static com.android.bluetooth.Utils.joinUninterruptibly; import static com.google.common.truth.Truth.assertThat; @@ -73,8 +74,6 @@ import com.android.bluetooth.btservice.SilenceDeviceManager; import com.android.bluetooth.btservice.storage.DatabaseManager; import com.android.bluetooth.flags.Flags; -import com.google.common.util.concurrent.Uninterruptibles; - import org.junit.After; import org.junit.Before; import org.junit.Ignore; @@ -131,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); @@ -182,7 +181,7 @@ public class HeadsetStateMachineTest { public void tearDown() throws Exception { HeadsetObjectsFactory.getInstance().destroyStateMachine(mHeadsetStateMachine); mHandlerThread.quit(); - Uninterruptibles.joinUninterruptibly(mHandlerThread); + joinUninterruptibly(mHandlerThread); InstrumentationRegistry.getInstrumentation() .getUiAutomation() .dropShellPermissionIdentity(); @@ -1898,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( @@ -1908,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 */ @@ -2201,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/hfp/HeadsetTestUtils.java b/android/app/tests/unit/src/com/android/bluetooth/hfp/HeadsetTestUtils.java index 4b2d0b291c..b504414050 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/hfp/HeadsetTestUtils.java +++ b/android/app/tests/unit/src/com/android/bluetooth/hfp/HeadsetTestUtils.java @@ -1,5 +1,5 @@ /* - * Copyright 2018 The Android Open Source Project + * Copyright (C) 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. diff --git a/android/app/tests/unit/src/com/android/bluetooth/hfp/HeadsetVendorSpecificResultCodeTest.java b/android/app/tests/unit/src/com/android/bluetooth/hfp/HeadsetVendorSpecificResultCodeTest.java index 7b2b72923e..cfb1dea03c 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/hfp/HeadsetVendorSpecificResultCodeTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/hfp/HeadsetVendorSpecificResultCodeTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2022 The Android Open Source Project + * Copyright (C) 2022 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. diff --git a/android/app/tests/unit/src/com/android/bluetooth/hfpclient/HeadsetClientServiceBinderTest.java b/android/app/tests/unit/src/com/android/bluetooth/hfpclient/HeadsetClientServiceBinderTest.java index e96fc3a9a6..b3171bc191 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/hfpclient/HeadsetClientServiceBinderTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/hfpclient/HeadsetClientServiceBinderTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2022 The Android Open Source Project + * Copyright (C) 2022 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. diff --git a/android/app/tests/unit/src/com/android/bluetooth/hfpclient/HeadsetClientServiceTest.java b/android/app/tests/unit/src/com/android/bluetooth/hfpclient/HeadsetClientServiceTest.java index d4cb896827..a8a81b0440 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/hfpclient/HeadsetClientServiceTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/hfpclient/HeadsetClientServiceTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2017 The Android Open Source Project + * Copyright (C) 2017 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. 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..7e47efeb4a 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 @@ -1,5 +1,5 @@ /* - * Copyright 2016 The Android Open Source Project + * Copyright (C) 2016 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. @@ -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/hfpclient/HfpNativeInterfaceTest.java b/android/app/tests/unit/src/com/android/bluetooth/hfpclient/HfpNativeInterfaceTest.java index d47e70da86..bd480693e8 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/hfpclient/HfpNativeInterfaceTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/hfpclient/HfpNativeInterfaceTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2022 The Android Open Source Project + * Copyright (C) 2022 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. diff --git a/android/app/tests/unit/src/com/android/bluetooth/hfpclient/StackEventTest.java b/android/app/tests/unit/src/com/android/bluetooth/hfpclient/StackEventTest.java index 7aaba84f59..cb397e29ec 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/hfpclient/StackEventTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/hfpclient/StackEventTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2022 The Android Open Source Project + * Copyright (C) 2022 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. diff --git a/android/app/tests/unit/src/com/android/bluetooth/hfpclient/VendorCommandResponseProcessorTest.java b/android/app/tests/unit/src/com/android/bluetooth/hfpclient/VendorCommandResponseProcessorTest.java index 17af0e42bc..0c9522b05b 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/hfpclient/VendorCommandResponseProcessorTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/hfpclient/VendorCommandResponseProcessorTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2022 The Android Open Source Project + * Copyright (C) 2022 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. diff --git a/android/app/tests/unit/src/com/android/bluetooth/hid/BluetoothHidDeviceBinderTest.java b/android/app/tests/unit/src/com/android/bluetooth/hid/BluetoothHidDeviceBinderTest.java index 4b11bc7b2a..8a03fe7186 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/hid/BluetoothHidDeviceBinderTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/hid/BluetoothHidDeviceBinderTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2022 The Android Open Source Project + * Copyright (C) 2022 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. diff --git a/android/app/tests/unit/src/com/android/bluetooth/hid/HidDeviceNativeInterfaceTest.java b/android/app/tests/unit/src/com/android/bluetooth/hid/HidDeviceNativeInterfaceTest.java index 787eaacb86..d393b8dc65 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/hid/HidDeviceNativeInterfaceTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/hid/HidDeviceNativeInterfaceTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2022 The Android Open Source Project + * Copyright (C) 2022 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. diff --git a/android/app/tests/unit/src/com/android/bluetooth/hid/HidDeviceTest.java b/android/app/tests/unit/src/com/android/bluetooth/hid/HidDeviceTest.java index de64564c77..5ddb36e4c6 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/hid/HidDeviceTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/hid/HidDeviceTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2017 The Android Open Source Project + * Copyright (C) 2017 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. diff --git a/android/app/tests/unit/src/com/android/bluetooth/hid/HidHostServiceBinderTest.java b/android/app/tests/unit/src/com/android/bluetooth/hid/HidHostServiceBinderTest.java index 946d9a7c93..02bee889e8 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/hid/HidHostServiceBinderTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/hid/HidHostServiceBinderTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2022 The Android Open Source Project + * Copyright (C) 2022 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. diff --git a/android/app/tests/unit/src/com/android/bluetooth/hid/HidHostServiceTest.java b/android/app/tests/unit/src/com/android/bluetooth/hid/HidHostServiceTest.java index 341cd54333..a41f93d5d6 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/hid/HidHostServiceTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/hid/HidHostServiceTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2018 The Android Open Source Project + * Copyright (C) 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. diff --git a/android/app/tests/unit/src/com/android/bluetooth/le_audio/LeAudioBinderTest.java b/android/app/tests/unit/src/com/android/bluetooth/le_audio/LeAudioBinderTest.java index e0093fc003..15b3563df1 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/le_audio/LeAudioBinderTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/le_audio/LeAudioBinderTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2022 The Android Open Source Project + * Copyright (C) 2022 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. diff --git a/android/app/tests/unit/src/com/android/bluetooth/le_audio/LeAudioBroadcastServiceTest.java b/android/app/tests/unit/src/com/android/bluetooth/le_audio/LeAudioBroadcastServiceTest.java index 576f7cdc54..e1569ea836 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/le_audio/LeAudioBroadcastServiceTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/le_audio/LeAudioBroadcastServiceTest.java @@ -1438,7 +1438,11 @@ public class LeAudioBroadcastServiceTest { } @Test - @DisableFlags(Flags.FLAG_LEAUDIO_BROADCAST_PRIMARY_GROUP_SELECTION) + @DisableFlags({ + Flags.FLAG_LEAUDIO_BROADCAST_PRIMARY_GROUP_SELECTION, + Flags.FLAG_LEAUDIO_BROADCAST_API_MANAGE_PRIMARY_GROUP, + Flags.FLAG_LEAUDIO_USE_AUDIO_RECORDING_LISTENER + }) public void testUpdateFallbackInputDevice() { int groupId = 1; int groupId2 = 2; @@ -1663,57 +1667,6 @@ public class LeAudioBroadcastServiceTest { } @Test - @EnableFlags({ - Flags.FLAG_LEAUDIO_BROADCAST_API_MANAGE_PRIMARY_GROUP, - Flags.FLAG_LEAUDIO_BROADCAST_PRIMARY_GROUP_SELECTION - }) - public void testUpdateFallbackDeviceWhileSettingActiveDevice() throws RemoteException { - int groupId = 1; - int groupId2 = 2; - int broadcastId = 243; - byte[] code = {0x00, 0x01, 0x00, 0x02}; - List<BluetoothDevice> devices = new ArrayList<>(); - - when(mDatabaseManager.getMostRecentlyConnectedDevices()).thenReturn(devices); - - synchronized (mService.mLeAudioCallbacks) { - mService.mLeAudioCallbacks.register(mLeAudioCallbacks); - } - - initializeNative(); - devices.add(mDevice2); - prepareConnectedUnicastDevice(groupId2, mDevice2); - devices.add(mDevice); - prepareHandoverStreamingBroadcast(groupId, broadcastId, code); - - /* group 1 is deactivated due to broadcast and group 2 is set by default as broadcast to - * unicast fallback group (first add device) - */ - verify(mTbsService, never()).clearInbandRingtoneSupport(eq(mDevice2)); - verify(mTbsService, times(1)).clearInbandRingtoneSupport(eq(mDevice)); - - /* Earliest connected group (2) become fallback device */ - assertThat(mService.mUnicastGroupIdDeactivatedForBroadcastTransition).isEqualTo(groupId2); - verify(mLeAudioCallbacks).onBroadcastToUnicastFallbackGroupChanged(groupId2); - - Mockito.clearInvocations(mLeAudioCallbacks); - reset(mAudioManager); - - /* Change active device while broadcasting - result in replacing fallback group 2->1 */ - assertThat(mService.setActiveDevice(mDevice)).isTrue(); - TestUtils.waitForLooperToFinishScheduledTask(Looper.getMainLooper()); - assertThat(mService.mUnicastGroupIdDeactivatedForBroadcastTransition).isEqualTo(groupId); - verify(mLeAudioCallbacks).onBroadcastToUnicastFallbackGroupChanged(groupId); - - /* Verify that fallback device is not changed when there is no running broadcast */ - Mockito.clearInvocations(mLeAudioCallbacks); - verifyBroadcastStopped(broadcastId); - assertThat(mService.setActiveDevice(mDevice2)).isTrue(); - TestUtils.waitForLooperToFinishScheduledTask(Looper.getMainLooper()); - verify(mLeAudioCallbacks, never()).onBroadcastToUnicastFallbackGroupChanged(anyInt()); - } - - @Test public void registerUnregisterLeBroadcastCallback() { IBluetoothLeBroadcastCallback callback = Mockito.mock(IBluetoothLeBroadcastCallback.class); Binder binder = Mockito.mock(Binder.class); diff --git a/android/app/tests/unit/src/com/android/bluetooth/le_audio/LeAudioBroadcasterNativeInterfaceTest.java b/android/app/tests/unit/src/com/android/bluetooth/le_audio/LeAudioBroadcasterNativeInterfaceTest.java index d74b6caf53..f9c57e1494 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/le_audio/LeAudioBroadcasterNativeInterfaceTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/le_audio/LeAudioBroadcasterNativeInterfaceTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2022 The Android Open Source Project + * Copyright (C) 2022 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. diff --git a/android/app/tests/unit/src/com/android/bluetooth/le_audio/LeAudioNativeInterfaceTest.java b/android/app/tests/unit/src/com/android/bluetooth/le_audio/LeAudioNativeInterfaceTest.java index 03d85dfc4d..369304c608 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/le_audio/LeAudioNativeInterfaceTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/le_audio/LeAudioNativeInterfaceTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2022 The Android Open Source Project + * Copyright (C) 2022 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. diff --git a/android/app/tests/unit/src/com/android/bluetooth/le_audio/LeAudioServiceTest.java b/android/app/tests/unit/src/com/android/bluetooth/le_audio/LeAudioServiceTest.java index 7b898c389e..f0f2037358 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/le_audio/LeAudioServiceTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/le_audio/LeAudioServiceTest.java @@ -348,7 +348,7 @@ public class LeAudioServiceTest { doReturn(bondState).when(mAdapterService).getBondState(device); when(mDatabaseManager.getProfileConnectionPolicy(device, BluetoothProfile.LE_AUDIO)) .thenReturn(priority); - assertThat(expected).isEqualTo(mService.okToConnect(device)); + assertThat(mService.okToConnect(device)).isEqualTo(expected); } /** Test okToConnect method using various test cases */ @@ -1299,7 +1299,11 @@ public class LeAudioServiceTest { /** Test update unicast fallback active group when broadcast is ongoing */ @Test - @DisableFlags(Flags.FLAG_LEAUDIO_BROADCAST_PRIMARY_GROUP_SELECTION) + @DisableFlags({ + Flags.FLAG_LEAUDIO_BROADCAST_PRIMARY_GROUP_SELECTION, + Flags.FLAG_LEAUDIO_BROADCAST_API_MANAGE_PRIMARY_GROUP, + Flags.FLAG_LEAUDIO_USE_AUDIO_RECORDING_LISTENER + }) public void testUpdateUnicastFallbackActiveDeviceGroupDuringBroadcast() { List<BluetoothDevice> devices = new ArrayList<>(); int groupId = 1; diff --git a/android/app/tests/unit/src/com/android/bluetooth/le_scan/AdvtFilterOnFoundOnLostInfoTest.java b/android/app/tests/unit/src/com/android/bluetooth/le_scan/AdvtFilterOnFoundOnLostInfoTest.java index aec90ecf29..80e050d866 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/le_scan/AdvtFilterOnFoundOnLostInfoTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/le_scan/AdvtFilterOnFoundOnLostInfoTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2022 The Android Open Source Project + * Copyright (C) 2022 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. diff --git a/android/app/tests/unit/src/com/android/bluetooth/le_scan/AppScanStatsTest.java b/android/app/tests/unit/src/com/android/bluetooth/le_scan/AppScanStatsTest.java index dc823ca412..9a37679916 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/le_scan/AppScanStatsTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/le_scan/AppScanStatsTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2022 The Android Open Source Project + * Copyright (C) 2022 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. diff --git a/android/app/tests/unit/src/com/android/bluetooth/le_scan/ScanBinderTest.java b/android/app/tests/unit/src/com/android/bluetooth/le_scan/ScanBinderTest.java new file mode 100644 index 0000000000..61c7df48b8 --- /dev/null +++ b/android/app/tests/unit/src/com/android/bluetooth/le_scan/ScanBinderTest.java @@ -0,0 +1,194 @@ +/* + * Copyright (C) 2025 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.bluetooth.le_scan; + +import static com.android.bluetooth.TestUtils.MockitoRule; +import static com.android.bluetooth.TestUtils.getTestDevice; + +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; + +import android.app.PendingIntent; +import android.bluetooth.BluetoothDevice; +import android.bluetooth.BluetoothManager; +import android.bluetooth.le.IPeriodicAdvertisingCallback; +import android.bluetooth.le.IScannerCallback; +import android.bluetooth.le.ScanFilter; +import android.bluetooth.le.ScanResult; +import android.bluetooth.le.ScanSettings; +import android.content.AttributionSource; +import android.content.Intent; +import android.os.WorkSource; + +import androidx.test.filters.SmallTest; +import androidx.test.platform.app.InstrumentationRegistry; +import androidx.test.runner.AndroidJUnit4; + +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; + +import java.util.ArrayList; +import java.util.List; + +/** Test cases for {@link ScanBinder}. */ +@SmallTest +@RunWith(AndroidJUnit4.class) +public class ScanBinderTest { + @Rule public final MockitoRule mMockitoRule = new MockitoRule(); + + @Mock private ScanController mScanController; + + private final AttributionSource mAttributionSource = + InstrumentationRegistry.getInstrumentation() + .getTargetContext() + .getSystemService(BluetoothManager.class) + .getAdapter() + .getAttributionSource(); + private final BluetoothDevice mDevice = getTestDevice(89); + private ScanBinder mBinder; + + @Before + public void setUp() { + mBinder = new ScanBinder(mScanController); + } + + @Test + public void registerScanner() { + IScannerCallback callback = mock(IScannerCallback.class); + WorkSource workSource = mock(WorkSource.class); + + mBinder.registerScanner(callback, workSource, mAttributionSource); + verify(mScanController).registerScanner(callback, workSource, mAttributionSource); + } + + @Test + public void unregisterScanner() { + int scannerId = 1; + + mBinder.unregisterScanner(scannerId, mAttributionSource); + verify(mScanController).unregisterScanner(scannerId, mAttributionSource); + } + + @Test + public void startScan() { + int scannerId = 1; + ScanSettings settings = new ScanSettings.Builder().build(); + List<ScanFilter> filters = new ArrayList<>(); + + mBinder.startScan(scannerId, settings, filters, mAttributionSource); + verify(mScanController).startScan(scannerId, settings, filters, mAttributionSource); + } + + @Test + public void startScanForIntent() { + PendingIntent intent = + PendingIntent.getBroadcast( + InstrumentationRegistry.getInstrumentation().getTargetContext(), + 0, + new Intent(), + PendingIntent.FLAG_IMMUTABLE); + ScanSettings settings = new ScanSettings.Builder().build(); + List<ScanFilter> filters = new ArrayList<>(); + + mBinder.startScanForIntent(intent, settings, filters, mAttributionSource); + verify(mScanController) + .registerPiAndStartScan(intent, settings, filters, mAttributionSource); + } + + @Test + public void stopScan_withScannerId() { + int scannerId = 1; + + mBinder.stopScan(scannerId, mAttributionSource); + verify(mScanController).stopScan(scannerId, mAttributionSource); + } + + @Test + public void stopScan_withIntent() { + PendingIntent intent = + PendingIntent.getBroadcast( + InstrumentationRegistry.getInstrumentation().getTargetContext(), + 0, + new Intent(), + PendingIntent.FLAG_IMMUTABLE); + + mBinder.stopScanForIntent(intent, mAttributionSource); + verify(mScanController).stopScan(intent, mAttributionSource); + } + + @Test + public void flushPendingBatchResults() { + int scannerId = 1; + + mBinder.flushPendingBatchResults(scannerId, mAttributionSource); + verify(mScanController).flushPendingBatchResults(scannerId, mAttributionSource); + } + + @Test + public void registerSync() { + ScanResult scanResult = new ScanResult(mDevice, null, 0, 0); + int skip = 1; + int timeout = 2; + IPeriodicAdvertisingCallback callback = mock(IPeriodicAdvertisingCallback.class); + + mBinder.registerSync(scanResult, skip, timeout, callback, mAttributionSource); + verify(mScanController) + .registerSync(scanResult, skip, timeout, callback, mAttributionSource); + } + + @Test + public void unregisterSync() { + IPeriodicAdvertisingCallback callback = mock(IPeriodicAdvertisingCallback.class); + + mBinder.unregisterSync(callback, mAttributionSource); + verify(mScanController).unregisterSync(callback, mAttributionSource); + } + + @Test + public void transferSync() { + int serviceData = 1; + int syncHandle = 2; + + mBinder.transferSync(mDevice, serviceData, syncHandle, mAttributionSource); + verify(mScanController).transferSync(mDevice, serviceData, syncHandle, mAttributionSource); + } + + @Test + public void transferSetInfo() { + int serviceData = 1; + int advHandle = 2; + IPeriodicAdvertisingCallback callback = mock(IPeriodicAdvertisingCallback.class); + + mBinder.transferSetInfo(mDevice, serviceData, advHandle, callback, mAttributionSource); + verify(mScanController) + .transferSetInfo(mDevice, serviceData, advHandle, callback, mAttributionSource); + } + + @Test + public void numHwTrackFiltersAvailable() { + mBinder.numHwTrackFiltersAvailable(mAttributionSource); + verify(mScanController).numHwTrackFiltersAvailable(mAttributionSource); + } + + @Test + public void cleanup_doesNotCrash() { + mBinder.cleanup(); + } +} 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..f1d428906b 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 @@ -1,5 +1,5 @@ /* - * Copyright 2023 The Android Open Source Project + * Copyright (C) 2023 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -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/le_scan/ScanFilterQueueTest.java b/android/app/tests/unit/src/com/android/bluetooth/le_scan/ScanFilterQueueTest.java index 15dc16bbf3..da5a9d8974 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/le_scan/ScanFilterQueueTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/le_scan/ScanFilterQueueTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2022 The Android Open Source Project + * Copyright (C) 2022 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. diff --git a/android/app/tests/unit/src/com/android/bluetooth/le_scan/ScanManagerTest.java b/android/app/tests/unit/src/com/android/bluetooth/le_scan/ScanManagerTest.java index d19e0c7251..7059517c66 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/le_scan/ScanManagerTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/le_scan/ScanManagerTest.java @@ -16,6 +16,7 @@ package com.android.bluetooth.le_scan; +import static android.app.ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND_SERVICE; import static android.bluetooth.BluetoothDevice.PHY_LE_1M; import static android.bluetooth.BluetoothDevice.PHY_LE_1M_MASK; import static android.bluetooth.BluetoothDevice.PHY_LE_CODED; @@ -1269,6 +1270,8 @@ public class ScanManagerTest { mAdapterService, mScanController, mTimeProvider)); + // Set app importance as Foreground Service for the stats + appScanStats.setAppImportance(IMPORTANCE_FOREGROUND_SERVICE); // Create scan client for the app, which also records scan start ScanClient client = createScanClient(isFiltered, scanMode, UID, appScanStats); // Verify that the app scan start is logged @@ -1288,7 +1291,9 @@ public class ScanManagerTest { 0, 0, true, - false); + false, + IMPORTANCE_FOREGROUND_SERVICE, + ""); advanceTime(scanTestDuration); // Record scan stop @@ -1312,7 +1317,9 @@ public class ScanManagerTest { eq(scanTestDuration), eq(0), eq(true), - eq(false)); + eq(false), + eq(IMPORTANCE_FOREGROUND_SERVICE), + eq("")); } } @@ -1340,6 +1347,8 @@ public class ScanManagerTest { mAdapterService, mScanController, mTimeProvider)); + // Set app importance as Foreground Service for the stats + appScanStats1.setAppImportance(IMPORTANCE_FOREGROUND_SERVICE); // Create scan client for the first app ScanClient client1 = createScanClient(isFiltered, SCAN_MODE_LOW_POWER, UID_1, appScanStats1); @@ -1362,6 +1371,8 @@ public class ScanManagerTest { mAdapterService, mScanController, mTimeProvider)); + // Set app importance as Foreground Service for the stats + appScanStats2.setAppImportance(IMPORTANCE_FOREGROUND_SERVICE); // Create scan client for the second app ScanClient client2 = createScanClient(isFiltered, SCAN_MODE_BALANCED, UID_2, appScanStats2); // Start scan with higher duty cycle for the second app @@ -1380,7 +1391,9 @@ public class ScanManagerTest { eq((long) ScanManager.SCAN_MODE_LOW_POWER_INTERVAL_MS), eq((long) ScanManager.SCAN_MODE_LOW_POWER_WINDOW_MS), eq(true), - eq(scanTestDuration)); + eq(scanTestDuration), + eq(IMPORTANCE_FOREGROUND_SERVICE), + eq("")); advanceTime(scanTestDuration); // Create workSource for the third app @@ -1398,6 +1411,8 @@ public class ScanManagerTest { mAdapterService, mScanController, mTimeProvider)); + // Set app importance as Foreground Service for the stats + appScanStats3.setAppImportance(IMPORTANCE_FOREGROUND_SERVICE); // Create scan client for the third app ScanClient client3 = createScanClient(isFiltered, SCAN_MODE_LOW_LATENCY, UID_3, appScanStats3); @@ -1417,7 +1432,9 @@ public class ScanManagerTest { eq((long) ScanManager.SCAN_MODE_BALANCED_INTERVAL_MS), eq((long) ScanManager.SCAN_MODE_BALANCED_WINDOW_MS), eq(true), - eq(scanTestDuration)); + eq(scanTestDuration), + eq(IMPORTANCE_FOREGROUND_SERVICE), + eq("")); advanceTime(scanTestDuration); // Create workSource for the fourth app @@ -1435,6 +1452,8 @@ public class ScanManagerTest { mAdapterService, mScanController, mTimeProvider)); + // Set app importance as Foreground Service for the stats + appScanStats4.setAppImportance(IMPORTANCE_FOREGROUND_SERVICE); // Create scan client for the fourth app ScanClient client4 = createScanClient(isFiltered, SCAN_MODE_AMBIENT_DISCOVERY, UID_4, appScanStats4); @@ -1451,7 +1470,9 @@ public class ScanManagerTest { anyLong(), anyLong(), anyBoolean(), - anyLong()); + anyLong(), + anyInt(), + eq("")); advanceTime(scanTestDuration); // Set as background app @@ -1475,7 +1496,9 @@ public class ScanManagerTest { eq((long) ScanManager.SCAN_MODE_LOW_LATENCY_INTERVAL_MS), eq((long) ScanManager.SCAN_MODE_LOW_LATENCY_WINDOW_MS), eq(true), - eq(scanTestDuration * 2)); + eq(scanTestDuration * 2), + eq(IMPORTANCE_FOREGROUND_SERVICE), + eq("")); advanceTime(scanTestDuration); // Get the most aggressive scan client when screen is off @@ -1503,7 +1526,9 @@ public class ScanManagerTest { eq((long) SCAN_MODE_SCREEN_OFF_LOW_POWER_INTERVAL_MS), eq((long) SCAN_MODE_SCREEN_OFF_LOW_POWER_WINDOW_MS), eq(false), - eq(scanTestDuration)); + eq(scanTestDuration), + eq(IMPORTANCE_FOREGROUND_SERVICE + 1), + eq("")); advanceTime(scanTestDuration); // Stop scan for the fourth app @@ -1519,7 +1544,9 @@ public class ScanManagerTest { anyLong(), anyLong(), anyBoolean(), - anyLong()); + anyLong(), + anyInt(), + eq("")); advanceTime(scanTestDuration); // Stop scan for the third app @@ -1538,7 +1565,9 @@ public class ScanManagerTest { eq((long) ScanManager.SCAN_MODE_LOW_LATENCY_INTERVAL_MS), eq((long) ScanManager.SCAN_MODE_LOW_LATENCY_WINDOW_MS), eq(true), - eq(scanTestDuration * 2)); + eq(scanTestDuration * 2), + eq(IMPORTANCE_FOREGROUND_SERVICE), + eq("")); advanceTime(scanTestDuration); // Stop scan for the second app @@ -1557,7 +1586,9 @@ public class ScanManagerTest { eq((long) ScanManager.SCAN_MODE_BALANCED_INTERVAL_MS), eq((long) ScanManager.SCAN_MODE_BALANCED_WINDOW_MS), eq(true), - eq(scanTestDuration)); + eq(scanTestDuration), + eq(IMPORTANCE_FOREGROUND_SERVICE), + eq("")); advanceTime(scanTestDuration); // Stop scan for the first app @@ -1576,7 +1607,9 @@ public class ScanManagerTest { eq((long) ScanManager.SCAN_MODE_LOW_POWER_INTERVAL_MS), eq((long) ScanManager.SCAN_MODE_LOW_POWER_WINDOW_MS), eq(true), - eq(scanTestDuration)); + eq(scanTestDuration), + eq(IMPORTANCE_FOREGROUND_SERVICE), + eq("")); } @Test diff --git a/android/app/tests/unit/src/com/android/bluetooth/le_scan/ScannerMapTest.java b/android/app/tests/unit/src/com/android/bluetooth/le_scan/ScannerMapTest.java index e8d31e0552..ea5b2f564f 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/le_scan/ScannerMapTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/le_scan/ScannerMapTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2022 The Android Open Source Project + * Copyright (C) 2022 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. diff --git a/android/app/tests/unit/src/com/android/bluetooth/map/BluetoothMapAccountItemTest.java b/android/app/tests/unit/src/com/android/bluetooth/map/BluetoothMapAccountItemTest.java index 8e1be7da7f..6e493ee6d5 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/map/BluetoothMapAccountItemTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/map/BluetoothMapAccountItemTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2022 The Android Open Source Project + * Copyright (C) 2022 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. diff --git a/android/app/tests/unit/src/com/android/bluetooth/map/BluetoothMapAppParamsTest.java b/android/app/tests/unit/src/com/android/bluetooth/map/BluetoothMapAppParamsTest.java index 95fa60a6e8..c0defe0c21 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/map/BluetoothMapAppParamsTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/map/BluetoothMapAppParamsTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2022 The Android Open Source Project + * Copyright (C) 2022 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. @@ -219,7 +219,7 @@ public class BluetoothMapAppParamsTest { .isEqualTo( BluetoothMapUtils.getLongAsString( SignedLongLong.fromString(TEST_FILTER_CONVO_ID) - .getLeastSignificantBits())); + .leastSignificantBits())); assertThat(appParams.getFilterMsgHandle()) .isEqualTo(BluetoothMapUtils.getLongFromString(TEST_FILTER_MSG_HANDLE)); assertThat(appParams.getFilterMsgHandleString()) diff --git a/android/app/tests/unit/src/com/android/bluetooth/map/BluetoothMapContentObserverTest.java b/android/app/tests/unit/src/com/android/bluetooth/map/BluetoothMapContentObserverTest.java index a336954afe..b131039e99 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/map/BluetoothMapContentObserverTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/map/BluetoothMapContentObserverTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2016 The Android Open Source Project + * Copyright (C) 2016 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. diff --git a/android/app/tests/unit/src/com/android/bluetooth/map/BluetoothMapContentTest.java b/android/app/tests/unit/src/com/android/bluetooth/map/BluetoothMapContentTest.java index 6b8a010934..b149953287 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/map/BluetoothMapContentTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/map/BluetoothMapContentTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2022 The Android Open Source Project + * Copyright (C) 2022 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. @@ -314,7 +314,7 @@ public class BluetoothMapContentTest { expected.append(" AND ") .append(Threads._ID) .append(" = ") - .append(SignedLongLong.fromString(convoId).getLeastSignificantBits()); + .append(SignedLongLong.fromString(convoId).leastSignificantBits()); assertThat(selection.toString()).isEqualTo(expected.toString()); } 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..6e8f60f5ce 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 @@ -1,5 +1,5 @@ /* - * Copyright 2022 The Android Open Source Project + * Copyright (C) 2022 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. @@ -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/BluetoothMapConvoListingElementTest.java b/android/app/tests/unit/src/com/android/bluetooth/map/BluetoothMapConvoListingElementTest.java index 07dad9acb5..da6e865ab3 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/map/BluetoothMapConvoListingElementTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/map/BluetoothMapConvoListingElementTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2022 The Android Open Source Project + * Copyright (C) 2022 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. @@ -109,8 +109,7 @@ public class BluetoothMapConvoListingElementTest { assertThat(mListingElement.getRead()).isEqualTo("READ"); assertThat(mListingElement.getReadBool()).isEqualTo(TEST_READ); assertThat(mListingElement.getConvoId()).isEqualTo(signedLongLong.toHexString()); - assertThat(mListingElement.getCpConvoId()) - .isEqualTo(signedLongLong.getLeastSignificantBits()); + assertThat(mListingElement.getCpConvoId()).isEqualTo(signedLongLong.leastSignificantBits()); assertThat(mListingElement.getFullSummary()).isEqualTo(TEST_SUMMARY); assertThat(mListingElement.getSmsMmsContacts()).isEqualTo(TEST_SMS_MMS_CONTACTS); } diff --git a/android/app/tests/unit/src/com/android/bluetooth/map/BluetoothMapConvoListingTest.java b/android/app/tests/unit/src/com/android/bluetooth/map/BluetoothMapConvoListingTest.java index 97ec95ea25..e333d7b4bb 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/map/BluetoothMapConvoListingTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/map/BluetoothMapConvoListingTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2022 The Android Open Source Project + * Copyright (C) 2022 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. diff --git a/android/app/tests/unit/src/com/android/bluetooth/map/BluetoothMapMasInstanceTest.java b/android/app/tests/unit/src/com/android/bluetooth/map/BluetoothMapMasInstanceTest.java index b0239dfd02..87c33d6588 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/map/BluetoothMapMasInstanceTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/map/BluetoothMapMasInstanceTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2023 The Android Open Source Project + * Copyright (C) 2023 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/android/app/tests/unit/src/com/android/bluetooth/map/BluetoothMapMessageListingElementTest.java b/android/app/tests/unit/src/com/android/bluetooth/map/BluetoothMapMessageListingElementTest.java index 81fa5b5122..bf58abaebc 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/map/BluetoothMapMessageListingElementTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/map/BluetoothMapMessageListingElementTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2022 The Android Open Source Project + * Copyright (C) 2022 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. diff --git a/android/app/tests/unit/src/com/android/bluetooth/map/BluetoothMapMessageListingTest.java b/android/app/tests/unit/src/com/android/bluetooth/map/BluetoothMapMessageListingTest.java index ccc9170eee..d78405aff4 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/map/BluetoothMapMessageListingTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/map/BluetoothMapMessageListingTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2022 The Android Open Source Project + * Copyright (C) 2022 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. diff --git a/android/app/tests/unit/src/com/android/bluetooth/map/BluetoothMapObexServerTest.java b/android/app/tests/unit/src/com/android/bluetooth/map/BluetoothMapObexServerTest.java index 4d53d787b6..a5c4b8425e 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/map/BluetoothMapObexServerTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/map/BluetoothMapObexServerTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2023 The Android Open Source Project + * Copyright (C) 2023 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/android/app/tests/unit/src/com/android/bluetooth/map/BluetoothMapServiceBinderTest.java b/android/app/tests/unit/src/com/android/bluetooth/map/BluetoothMapServiceBinderTest.java index 6410ebf3f0..fa0c3d3f35 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/map/BluetoothMapServiceBinderTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/map/BluetoothMapServiceBinderTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2022 The Android Open Source Project + * Copyright (C) 2022 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. diff --git a/android/app/tests/unit/src/com/android/bluetooth/map/BluetoothMapServiceTest.java b/android/app/tests/unit/src/com/android/bluetooth/map/BluetoothMapServiceTest.java index 2f6604a486..f2c455bbc1 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/map/BluetoothMapServiceTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/map/BluetoothMapServiceTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2018 The Android Open Source Project + * Copyright (C) 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. diff --git a/android/app/tests/unit/src/com/android/bluetooth/map/BluetoothMapSmsPduTest.java b/android/app/tests/unit/src/com/android/bluetooth/map/BluetoothMapSmsPduTest.java index 285d056242..2f96c2ead9 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/map/BluetoothMapSmsPduTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/map/BluetoothMapSmsPduTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2022 The Android Open Source Project + * Copyright (C) 2022 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. diff --git a/android/app/tests/unit/src/com/android/bluetooth/map/BluetoothMapUtilsTest.java b/android/app/tests/unit/src/com/android/bluetooth/map/BluetoothMapUtilsTest.java index 7bc752db8a..57467027e1 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/map/BluetoothMapUtilsTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/map/BluetoothMapUtilsTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2022 The Android Open Source Project + * Copyright (C) 2022 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. diff --git a/android/app/tests/unit/src/com/android/bluetooth/map/BluetoothMapbMessageEmailTest.java b/android/app/tests/unit/src/com/android/bluetooth/map/BluetoothMapbMessageEmailTest.java index 2dab97af35..b3094670e2 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/map/BluetoothMapbMessageEmailTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/map/BluetoothMapbMessageEmailTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2022 The Android Open Source Project + * Copyright (C) 2022 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. diff --git a/android/app/tests/unit/src/com/android/bluetooth/map/BluetoothMapbMessageSmsTest.java b/android/app/tests/unit/src/com/android/bluetooth/map/BluetoothMapbMessageSmsTest.java index 9ef731fd90..9cec017f97 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/map/BluetoothMapbMessageSmsTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/map/BluetoothMapbMessageSmsTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2022 The Android Open Source Project + * Copyright (C) 2022 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. diff --git a/android/app/tests/unit/src/com/android/bluetooth/map/BluetoothMapbMessageTest.java b/android/app/tests/unit/src/com/android/bluetooth/map/BluetoothMapbMessageTest.java index 1344d9b0f6..d778b412a6 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/map/BluetoothMapbMessageTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/map/BluetoothMapbMessageTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2022 The Android Open Source Project + * Copyright (C) 2022 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. diff --git a/android/app/tests/unit/src/com/android/bluetooth/map/BluetoothMapbMessageVCardTest.java b/android/app/tests/unit/src/com/android/bluetooth/map/BluetoothMapbMessageVCardTest.java index a44bd9cfda..69a57b83b2 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/map/BluetoothMapbMessageVCardTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/map/BluetoothMapbMessageVCardTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2022 The Android Open Source Project + * Copyright (C) 2022 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. diff --git a/android/app/tests/unit/src/com/android/bluetooth/map/ConvoContactInfoTest.java b/android/app/tests/unit/src/com/android/bluetooth/map/ConvoContactInfoTest.java index 170c9e762f..fc99e7134e 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/map/ConvoContactInfoTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/map/ConvoContactInfoTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2022 The Android Open Source Project + * Copyright (C) 2022 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. diff --git a/android/app/tests/unit/src/com/android/bluetooth/map/EventTest.java b/android/app/tests/unit/src/com/android/bluetooth/map/EventTest.java index d1962fc37b..edd0863d4b 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/map/EventTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/map/EventTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2022 The Android Open Source Project + * Copyright (C) 2022 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. diff --git a/android/app/tests/unit/src/com/android/bluetooth/map/FilterInfoTest.java b/android/app/tests/unit/src/com/android/bluetooth/map/FilterInfoTest.java index 09183cab1f..7042e34980 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/map/FilterInfoTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/map/FilterInfoTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2022 The Android Open Source Project + * Copyright (C) 2022 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. 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..93babf8f81 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 @@ -1,5 +1,5 @@ /* - * Copyright 2022 The Android Open Source Project + * Copyright (C) 2022 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. @@ -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/MsgTest.java b/android/app/tests/unit/src/com/android/bluetooth/map/MsgTest.java index f9f0b50fa1..4a0963cd78 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/map/MsgTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/map/MsgTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2022 The Android Open Source Project + * Copyright (C) 2022 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. 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..fdf2ee67e1 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 @@ -1,5 +1,5 @@ /* - * Copyright 2022 The Android Open Source Project + * Copyright (C) 2022 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. @@ -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/mapapi/BluetoothMapContractTest.java b/android/app/tests/unit/src/com/android/bluetooth/mapapi/BluetoothMapContractTest.java index 8462d664f6..021c1ae82f 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/mapapi/BluetoothMapContractTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/mapapi/BluetoothMapContractTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2022 The Android Open Source Project + * Copyright (C) 2022 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. diff --git a/android/app/tests/unit/src/com/android/bluetooth/mapapi/BluetoothMapEmailProviderTest.java b/android/app/tests/unit/src/com/android/bluetooth/mapapi/BluetoothMapEmailProviderTest.java index 46c9d8a9cc..1dadfd906d 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/mapapi/BluetoothMapEmailProviderTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/mapapi/BluetoothMapEmailProviderTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2022 The Android Open Source Project + * Copyright (C) 2022 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. diff --git a/android/app/tests/unit/src/com/android/bluetooth/mapapi/BluetoothMapIMProviderTest.java b/android/app/tests/unit/src/com/android/bluetooth/mapapi/BluetoothMapIMProviderTest.java index 26913ee0a2..2fccf754e5 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/mapapi/BluetoothMapIMProviderTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/mapapi/BluetoothMapIMProviderTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2022 The Android Open Source Project + * Copyright (C) 2022 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. diff --git a/android/app/tests/unit/src/com/android/bluetooth/mapclient/EventReportTest.java b/android/app/tests/unit/src/com/android/bluetooth/mapclient/EventReportTest.java index 3c355e1ad1..05facb51cc 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/mapclient/EventReportTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/mapclient/EventReportTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2022 The Android Open Source Project + * Copyright (C) 2022 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. diff --git a/android/app/tests/unit/src/com/android/bluetooth/mapclient/MapClientServiceBinderTest.java b/android/app/tests/unit/src/com/android/bluetooth/mapclient/MapClientServiceBinderTest.java index d3e98577a6..0830f8b9f9 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/mapclient/MapClientServiceBinderTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/mapclient/MapClientServiceBinderTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2022 The Android Open Source Project + * Copyright (C) 2022 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. diff --git a/android/app/tests/unit/src/com/android/bluetooth/mapclient/MapClientServiceTest.java b/android/app/tests/unit/src/com/android/bluetooth/mapclient/MapClientServiceTest.java index c75333efcf..66f04951ee 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/mapclient/MapClientServiceTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/mapclient/MapClientServiceTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2022 The Android Open Source Project + * Copyright (C) 2022 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. diff --git a/android/app/tests/unit/src/com/android/bluetooth/mapclient/MapClientStateMachineTest.java b/android/app/tests/unit/src/com/android/bluetooth/mapclient/MapClientStateMachineTest.java index db55624516..73280280ca 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/mapclient/MapClientStateMachineTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/mapclient/MapClientStateMachineTest.java @@ -768,8 +768,8 @@ public class MapClientStateMachineTest { /** * Preconditions: - In {@code STATE_CONNECTED}. * - * <p>Actions: - {@link #sendMapMessage} with 'Sent' {@link PendingIntents}. - {@link - * #receiveEvent} of type {@link SENDING_SUCCESS}. + * <p>Actions: - {@link MceStateMachine#sendMapMessage} with 'Sent' {@link PendingIntents}. - + * {@link MceStateMachine#receiveEvent} of type {@link SENDING_SUCCESS}. * * <p>Outcome: - SENT_STATUS Intent was broadcast with 'Success' result code. */ @@ -785,8 +785,8 @@ public class MapClientStateMachineTest { /** * Preconditions: - In {@code STATE_CONNECTED}. * - * <p>Actions: - {@link #sendMapMessage} with 'Delivery' {@link PendingIntents}. - {@link - * #receiveEvent} of type {@link DELIVERY_SUCCESS}. + * <p>Actions: - {@link MceStateMachine#sendMapMessage} with 'Delivery' {@link PendingIntents}. + * - {@link MceStateMachine#receiveEvent} of type {@link DELIVERY_SUCCESS}. * * <p>Outcome: - DELIVERY_STATUS Intent was broadcast with 'Success' result code. */ @@ -802,9 +802,9 @@ public class MapClientStateMachineTest { /** * Preconditions: - In {@code STATE_CONNECTED}. * - * <p>Actions: - {@link #sendMapMessage} with 'null' {@link PendingIntents}. - {@link - * #receiveEvent} of type {@link SENDING_SUCCESS}. - {@link #receiveEvent} of type {@link - * DELIVERY_SUCCESS}. + * <p>Actions: - {@link MceStateMachine#sendMapMessage} with 'null' {@link PendingIntents}. - + * {@link MceStateMachine#receiveEvent} of type {@link SENDING_SUCCESS}. - {@link + * MceStateMachine#receiveEvent} of type {@link DELIVERY_SUCCESS}. * * <p>Outcome: - No Intent was broadcast. */ @@ -818,8 +818,8 @@ public class MapClientStateMachineTest { /** * Preconditions: - In {@code STATE_CONNECTED}. * - * <p>Actions: - {@link #sendMapMessage} with 'Sent' {@link PendingIntents}. - {@link - * #receiveEvent} of type {@link SENDING_FAILURE}. + * <p>Actions: - {@link MceStateMachine#sendMapMessage} with 'Sent' {@link PendingIntents}. - + * {@link MceStateMachine#receiveEvent} of type {@link SENDING_FAILURE}. * * <p>Outcome: - SENT_STATUS Intent was broadcast with 'Failure' result code. */ @@ -837,8 +837,8 @@ public class MapClientStateMachineTest { /** * Preconditions: - In {@code STATE_CONNECTED}. * - * <p>Actions: - {@link #sendMapMessage} with 'Delivery' {@link PendingIntents}. - {@link - * #receiveEvent} of type {@link DELIVERY_FAILURE}. + * <p>Actions: - {@link MceStateMachine#sendMapMessage} with 'Delivery' {@link PendingIntents}. + * - {@link MceStateMachine#receiveEvent} of type {@link DELIVERY_FAILURE}. * * <p>Outcome: - DELIVERY_STATUS Intent was broadcast with 'Failure' result code. */ diff --git a/android/app/tests/unit/src/com/android/bluetooth/mapclient/MessageTest.java b/android/app/tests/unit/src/com/android/bluetooth/mapclient/MessageTest.java index 2f95d563a4..967e5b209d 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/mapclient/MessageTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/mapclient/MessageTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2022 The Android Open Source Project + * Copyright (C) 2022 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. diff --git a/android/app/tests/unit/src/com/android/bluetooth/mapclient/MessagesFilterTest.java b/android/app/tests/unit/src/com/android/bluetooth/mapclient/MessagesFilterTest.java index 12bcf80f3c..5433d67897 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/mapclient/MessagesFilterTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/mapclient/MessagesFilterTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2023 The Android Open Source Project + * Copyright (C) 2023 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/android/app/tests/unit/src/com/android/bluetooth/mapclient/MessagesListingTest.java b/android/app/tests/unit/src/com/android/bluetooth/mapclient/MessagesListingTest.java index 48ece843fe..ab6e7a46a4 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/mapclient/MessagesListingTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/mapclient/MessagesListingTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2023 The Android Open Source Project + * Copyright (C) 2023 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/android/app/tests/unit/src/com/android/bluetooth/mapclient/MnsObexServerTest.java b/android/app/tests/unit/src/com/android/bluetooth/mapclient/MnsObexServerTest.java index 3979e3cc60..2abea296e7 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/mapclient/MnsObexServerTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/mapclient/MnsObexServerTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2022 The Android Open Source Project + * Copyright (C) 2022 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. diff --git a/android/app/tests/unit/src/com/android/bluetooth/mapclient/RequestGetMessagesListingForOwnNumberTest.java b/android/app/tests/unit/src/com/android/bluetooth/mapclient/RequestGetMessagesListingForOwnNumberTest.java index 9ca5a6e3b4..bd8bb8574c 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/mapclient/RequestGetMessagesListingForOwnNumberTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/mapclient/RequestGetMessagesListingForOwnNumberTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2022 The Android Open Source Project + * Copyright (C) 2022 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. diff --git a/android/app/tests/unit/src/com/android/bluetooth/opp/BluetoothOppBatchTest.java b/android/app/tests/unit/src/com/android/bluetooth/opp/BluetoothOppBatchTest.java index 4990c5315b..e3f764d2bc 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/opp/BluetoothOppBatchTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/opp/BluetoothOppBatchTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2022 The Android Open Source Project + * Copyright (C) 2022 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. diff --git a/android/app/tests/unit/src/com/android/bluetooth/opp/BluetoothOppHandoverReceiverTest.java b/android/app/tests/unit/src/com/android/bluetooth/opp/BluetoothOppHandoverReceiverTest.java index 59227bae0b..daa65ebba6 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/opp/BluetoothOppHandoverReceiverTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/opp/BluetoothOppHandoverReceiverTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2022 The Android Open Source Project + * Copyright (C) 2022 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. diff --git a/android/app/tests/unit/src/com/android/bluetooth/opp/BluetoothOppManagerTest.java b/android/app/tests/unit/src/com/android/bluetooth/opp/BluetoothOppManagerTest.java index 6b757ad437..b20858b647 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/opp/BluetoothOppManagerTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/opp/BluetoothOppManagerTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2022 The Android Open Source Project + * Copyright (C) 2022 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. diff --git a/android/app/tests/unit/src/com/android/bluetooth/opp/BluetoothOppNotificationTest.java b/android/app/tests/unit/src/com/android/bluetooth/opp/BluetoothOppNotificationTest.java index 7eda9cb7b2..5e5d11ce4d 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/opp/BluetoothOppNotificationTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/opp/BluetoothOppNotificationTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2022 The Android Open Source Project + * Copyright (C) 2022 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. @@ -48,8 +48,6 @@ import com.android.bluetooth.BluetoothMethodProxy; import com.android.bluetooth.R; import com.android.bluetooth.TestUtils; -import com.google.common.base.Ascii; - import org.junit.After; import org.junit.Before; import org.junit.Ignore; @@ -58,6 +56,8 @@ import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; +import java.util.Locale; + @RunWith(AndroidJUnit4.class) public class BluetoothOppNotificationTest { static final int TIMEOUT_MS = 3000; @@ -432,13 +432,13 @@ public class BluetoothOppNotificationTest { UiObject2 buttonOk = device.findObject(By.text(confirmString)); // In AOSP, all actions' titles are converted into upper case if (buttonOk == null) { - buttonOk = device.findObject(By.text(Ascii.toUpperCase(confirmString))); + buttonOk = device.findObject(By.text(confirmString.toUpperCase(Locale.ROOT))); } UiObject2 buttonDecline = device.findObject(By.text(declineString)); // In AOSP, all actions' titles are converted into upper case if (buttonDecline == null) { - buttonDecline = device.findObject(By.text(Ascii.toUpperCase(declineString))); + buttonDecline = device.findObject(By.text(declineString.toUpperCase(Locale.ROOT))); } assertThat(title).isNotNull(); @@ -456,8 +456,8 @@ public class BluetoothOppNotificationTest { assertThat(device.findObject(By.text(titleString))).isNull(); assertThat(device.findObject(By.text(confirmString))).isNull(); - assertThat(device.findObject(By.text(Ascii.toUpperCase(confirmString)))).isNull(); + assertThat(device.findObject(By.text(confirmString.toUpperCase(Locale.ROOT)))).isNull(); assertThat(device.findObject(By.text(declineString))).isNull(); - assertThat(device.findObject(By.text(Ascii.toUpperCase(declineString)))).isNull(); + assertThat(device.findObject(By.text(declineString.toUpperCase(Locale.ROOT)))).isNull(); } } diff --git a/android/app/tests/unit/src/com/android/bluetooth/opp/BluetoothOppObexClientSessionTest.java b/android/app/tests/unit/src/com/android/bluetooth/opp/BluetoothOppObexClientSessionTest.java index 2481534d3c..b216680836 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/opp/BluetoothOppObexClientSessionTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/opp/BluetoothOppObexClientSessionTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2023 The Android Open Source Project + * Copyright (C) 2023 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/android/app/tests/unit/src/com/android/bluetooth/opp/BluetoothOppObexServerSessionTest.java b/android/app/tests/unit/src/com/android/bluetooth/opp/BluetoothOppObexServerSessionTest.java index 5378dc6f41..1e850d057b 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/opp/BluetoothOppObexServerSessionTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/opp/BluetoothOppObexServerSessionTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2022 The Android Open Source Project + * Copyright (C) 2022 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. diff --git a/android/app/tests/unit/src/com/android/bluetooth/opp/BluetoothOppPreferenceTest.java b/android/app/tests/unit/src/com/android/bluetooth/opp/BluetoothOppPreferenceTest.java index 58eca97965..91b1b0b65d 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/opp/BluetoothOppPreferenceTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/opp/BluetoothOppPreferenceTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2023 The Android Open Source Project + * Copyright (C) 2023 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/android/app/tests/unit/src/com/android/bluetooth/opp/BluetoothOppReceiveFileInfoTest.java b/android/app/tests/unit/src/com/android/bluetooth/opp/BluetoothOppReceiveFileInfoTest.java index 07cea67691..3f74ac90d1 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/opp/BluetoothOppReceiveFileInfoTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/opp/BluetoothOppReceiveFileInfoTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2022 The Android Open Source Project + * Copyright (C) 2022 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. diff --git a/android/app/tests/unit/src/com/android/bluetooth/opp/BluetoothOppReceiverTest.java b/android/app/tests/unit/src/com/android/bluetooth/opp/BluetoothOppReceiverTest.java index 28ece7fcb3..0a144d7b35 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/opp/BluetoothOppReceiverTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/opp/BluetoothOppReceiverTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2022 The Android Open Source Project + * Copyright (C) 2022 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. diff --git a/android/app/tests/unit/src/com/android/bluetooth/opp/BluetoothOppSendFileInfoTest.java b/android/app/tests/unit/src/com/android/bluetooth/opp/BluetoothOppSendFileInfoTest.java index 4d991b5610..d76517320e 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/opp/BluetoothOppSendFileInfoTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/opp/BluetoothOppSendFileInfoTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2022 The Android Open Source Project + * Copyright (C) 2022 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. diff --git a/android/app/tests/unit/src/com/android/bluetooth/opp/BluetoothOppServiceTest.java b/android/app/tests/unit/src/com/android/bluetooth/opp/BluetoothOppServiceTest.java index 8055882546..a065757c01 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/opp/BluetoothOppServiceTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/opp/BluetoothOppServiceTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2018 The Android Open Source Project + * Copyright (C) 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. diff --git a/android/app/tests/unit/src/com/android/bluetooth/opp/BluetoothOppShareInfoTest.java b/android/app/tests/unit/src/com/android/bluetooth/opp/BluetoothOppShareInfoTest.java index 26b987bb0b..212f1ffef7 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/opp/BluetoothOppShareInfoTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/opp/BluetoothOppShareInfoTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2022 The Android Open Source Project + * Copyright (C) 2022 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. diff --git a/android/app/tests/unit/src/com/android/bluetooth/opp/BluetoothOppTestUtils.java b/android/app/tests/unit/src/com/android/bluetooth/opp/BluetoothOppTestUtils.java index 3345530765..e1ca5e7e7e 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/opp/BluetoothOppTestUtils.java +++ b/android/app/tests/unit/src/com/android/bluetooth/opp/BluetoothOppTestUtils.java @@ -1,5 +1,5 @@ /* - * Copyright 2022 The Android Open Source Project + * Copyright (C) 2022 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. diff --git a/android/app/tests/unit/src/com/android/bluetooth/opp/BluetoothOppTransferActivityTest.java b/android/app/tests/unit/src/com/android/bluetooth/opp/BluetoothOppTransferActivityTest.java index 5a268d1614..ece55f357e 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/opp/BluetoothOppTransferActivityTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/opp/BluetoothOppTransferActivityTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2022 The Android Open Source Project + * Copyright (C) 2022 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. diff --git a/android/app/tests/unit/src/com/android/bluetooth/opp/BluetoothOppTransferTest.java b/android/app/tests/unit/src/com/android/bluetooth/opp/BluetoothOppTransferTest.java index c122b44579..f6c393909c 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/opp/BluetoothOppTransferTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/opp/BluetoothOppTransferTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2022 The Android Open Source Project + * Copyright (C) 2022 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. diff --git a/android/app/tests/unit/src/com/android/bluetooth/opp/BluetoothOppUtilityTest.java b/android/app/tests/unit/src/com/android/bluetooth/opp/BluetoothOppUtilityTest.java index 842a0aeacd..705c91d518 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/opp/BluetoothOppUtilityTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/opp/BluetoothOppUtilityTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2022 The Android Open Source Project + * Copyright (C) 2022 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. diff --git a/android/app/tests/unit/src/com/android/bluetooth/pan/BluetoothTetheringNetworkFactoryTest.java b/android/app/tests/unit/src/com/android/bluetooth/pan/BluetoothTetheringNetworkFactoryTest.java index ddabada6bc..04843899fb 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/pan/BluetoothTetheringNetworkFactoryTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/pan/BluetoothTetheringNetworkFactoryTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2022 The Android Open Source Project + * Copyright (C) 2022 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. diff --git a/android/app/tests/unit/src/com/android/bluetooth/pan/PanServiceBinderTest.java b/android/app/tests/unit/src/com/android/bluetooth/pan/PanServiceBinderTest.java index 15763b79c3..d798666437 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/pan/PanServiceBinderTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/pan/PanServiceBinderTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2022 The Android Open Source Project + * Copyright (C) 2022 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. diff --git a/android/app/tests/unit/src/com/android/bluetooth/pan/PanServiceTest.java b/android/app/tests/unit/src/com/android/bluetooth/pan/PanServiceTest.java index c9f20f430a..1621909b73 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/pan/PanServiceTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/pan/PanServiceTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2018 The Android Open Source Project + * Copyright (C) 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. @@ -48,6 +48,7 @@ import androidx.test.filters.MediumTest; import androidx.test.platform.app.InstrumentationRegistry; import androidx.test.runner.AndroidJUnit4; +import com.android.bluetooth.TestLooper; import com.android.bluetooth.btservice.AdapterService; import com.android.bluetooth.btservice.storage.DatabaseManager; import com.android.bluetooth.pan.PanService.BluetoothPanDevice; @@ -77,6 +78,7 @@ public class PanServiceTest { InstrumentationRegistry.getInstrumentation().getTargetContext(); private PanService mService; + private TestLooper mTestLooper; @Before public void setUp() { @@ -86,7 +88,8 @@ public class PanServiceTest { mAdapterService, Context.USER_SERVICE, UserManager.class, mMockUserManager); mockGetSystemService(mAdapterService, Context.TETHERING_SERVICE, TetheringManager.class); - mService = new PanService(mAdapterService, mNativeInterface); + mTestLooper = new TestLooper(); + mService = new PanService(mAdapterService, mNativeInterface, mTestLooper.getLooper()); mService.setAvailable(true); } @@ -125,12 +128,14 @@ public class PanServiceTest { new BluetoothPanDevice(STATE_DISCONNECTED, PAN_ROLE_NONE, PAN_ROLE_NONE)); assertThat(mService.connect(mRemoteDevice)).isTrue(); + mTestLooper.dispatchAll(); verify(mNativeInterface, timeout(TIMEOUT_MS)).connect(any()); } @Test public void disconnect_returnsTrue() { assertThat(mService.disconnect(mRemoteDevice)).isTrue(); + mTestLooper.dispatchAll(); verify(mNativeInterface, timeout(TIMEOUT_MS)).disconnect(any()); } @@ -189,6 +194,7 @@ public class PanServiceTest { mRemoteDevice, BluetoothProfile.PAN, CONNECTION_POLICY_ALLOWED)) .thenReturn(true); assertThat(mService.setConnectionPolicy(mRemoteDevice, CONNECTION_POLICY_ALLOWED)).isTrue(); + mTestLooper.dispatchAll(); verify(mNativeInterface, timeout(TIMEOUT_MS)).connect(any()); when(mDatabaseManager.setProfileConnectionPolicy( @@ -196,6 +202,7 @@ public class PanServiceTest { .thenReturn(true); assertThat(mService.setConnectionPolicy(mRemoteDevice, CONNECTION_POLICY_FORBIDDEN)) .isTrue(); + mTestLooper.dispatchAll(); verify(mNativeInterface, timeout(TIMEOUT_MS)).disconnect(any()); } diff --git a/android/app/tests/unit/src/com/android/bluetooth/pbap/BluetoothPbapCallLogComposerTest.java b/android/app/tests/unit/src/com/android/bluetooth/pbap/BluetoothPbapCallLogComposerTest.java index c781ca82ac..73aa0f015f 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/pbap/BluetoothPbapCallLogComposerTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/pbap/BluetoothPbapCallLogComposerTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2022 The Android Open Source Project + * Copyright (C) 2022 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. diff --git a/android/app/tests/unit/src/com/android/bluetooth/pbap/BluetoothPbapConfigTest.java b/android/app/tests/unit/src/com/android/bluetooth/pbap/BluetoothPbapConfigTest.java index f57cbc2758..a95fbcc461 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/pbap/BluetoothPbapConfigTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/pbap/BluetoothPbapConfigTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2022 The Android Open Source Project + * Copyright (C) 2022 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. diff --git a/android/app/tests/unit/src/com/android/bluetooth/pbap/BluetoothPbapObexServerTest.java b/android/app/tests/unit/src/com/android/bluetooth/pbap/BluetoothPbapObexServerTest.java index ed78e3239c..a833c6134b 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/pbap/BluetoothPbapObexServerTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/pbap/BluetoothPbapObexServerTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2022 The Android Open Source Project + * Copyright (C) 2022 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. diff --git a/android/app/tests/unit/src/com/android/bluetooth/pbap/BluetoothPbapServiceBinderTest.java b/android/app/tests/unit/src/com/android/bluetooth/pbap/BluetoothPbapServiceBinderTest.java index becc52e836..95b2bb25ef 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/pbap/BluetoothPbapServiceBinderTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/pbap/BluetoothPbapServiceBinderTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2022 The Android Open Source Project + * Copyright (C) 2022 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. diff --git a/android/app/tests/unit/src/com/android/bluetooth/pbap/BluetoothPbapServiceTest.java b/android/app/tests/unit/src/com/android/bluetooth/pbap/BluetoothPbapServiceTest.java index d3a4de5fed..e19ca130bf 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/pbap/BluetoothPbapServiceTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/pbap/BluetoothPbapServiceTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2018 The Android Open Source Project + * Copyright (C) 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. diff --git a/android/app/tests/unit/src/com/android/bluetooth/pbap/BluetoothPbapSimVcardManagerTest.java b/android/app/tests/unit/src/com/android/bluetooth/pbap/BluetoothPbapSimVcardManagerTest.java index a2252796e3..4afce15b68 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/pbap/BluetoothPbapSimVcardManagerTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/pbap/BluetoothPbapSimVcardManagerTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2022 The Android Open Source Project + * Copyright (C) 2022 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. diff --git a/android/app/tests/unit/src/com/android/bluetooth/pbap/BluetoothPbapUtilsTest.java b/android/app/tests/unit/src/com/android/bluetooth/pbap/BluetoothPbapUtilsTest.java index 2f4760f451..df448082c2 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/pbap/BluetoothPbapUtilsTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/pbap/BluetoothPbapUtilsTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2022 The Android Open Source Project + * Copyright (C) 2022 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. diff --git a/android/app/tests/unit/src/com/android/bluetooth/pbap/BluetoothPbapVcardManagerNestedClassesTest.java b/android/app/tests/unit/src/com/android/bluetooth/pbap/BluetoothPbapVcardManagerNestedClassesTest.java index b696cef960..e95e90088a 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/pbap/BluetoothPbapVcardManagerNestedClassesTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/pbap/BluetoothPbapVcardManagerNestedClassesTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2022 The Android Open Source Project + * Copyright (C) 2022 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. diff --git a/android/app/tests/unit/src/com/android/bluetooth/pbap/BluetoothPbapVcardManagerTest.java b/android/app/tests/unit/src/com/android/bluetooth/pbap/BluetoothPbapVcardManagerTest.java index 308a40b282..3b6034cd33 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/pbap/BluetoothPbapVcardManagerTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/pbap/BluetoothPbapVcardManagerTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2022 The Android Open Source Project + * Copyright (C) 2022 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. diff --git a/android/app/tests/unit/src/com/android/bluetooth/pbap/HandlerForStringBufferTest.java b/android/app/tests/unit/src/com/android/bluetooth/pbap/HandlerForStringBufferTest.java index 7245788429..9382902122 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/pbap/HandlerForStringBufferTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/pbap/HandlerForStringBufferTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2022 The Android Open Source Project + * Copyright (C) 2022 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. diff --git a/android/app/tests/unit/src/com/android/bluetooth/pbap/PbapStateMachineTest.java b/android/app/tests/unit/src/com/android/bluetooth/pbap/PbapStateMachineTest.java index 607bf253d4..c46ea24702 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/pbap/PbapStateMachineTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/pbap/PbapStateMachineTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2017 The Android Open Source Project + * Copyright (C) 2017 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. diff --git a/android/app/tests/unit/src/com/android/bluetooth/pbapclient/CallLogPullRequestTest.java b/android/app/tests/unit/src/com/android/bluetooth/pbapclient/CallLogPullRequestTest.java index b3669a14f6..376dcd9adf 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/pbapclient/CallLogPullRequestTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/pbapclient/CallLogPullRequestTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2022 The Android Open Source Project + * Copyright (C) 2022 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. diff --git a/android/app/tests/unit/src/com/android/bluetooth/pbapclient/FakeContactsProvider.java b/android/app/tests/unit/src/com/android/bluetooth/pbapclient/FakeContactsProvider.java index 356c26d2d0..36408dc7df 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/pbapclient/FakeContactsProvider.java +++ b/android/app/tests/unit/src/com/android/bluetooth/pbapclient/FakeContactsProvider.java @@ -1,5 +1,5 @@ /* - * Copyright 2024 The Android Open Source Project + * Copyright (C) 2024 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. diff --git a/android/app/tests/unit/src/com/android/bluetooth/pbapclient/PbapApplicationParametersTest.java b/android/app/tests/unit/src/com/android/bluetooth/pbapclient/PbapApplicationParametersTest.java index 81c90a9ab3..8f8c076648 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/pbapclient/PbapApplicationParametersTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/pbapclient/PbapApplicationParametersTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2024 The Android Open Source Project + * Copyright (C) 2024 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. diff --git a/android/app/tests/unit/src/com/android/bluetooth/pbapclient/PbapClientAccountAuthenticatorServiceTest.java b/android/app/tests/unit/src/com/android/bluetooth/pbapclient/PbapClientAccountAuthenticatorServiceTest.java index e25c542889..dfc7c322a5 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/pbapclient/PbapClientAccountAuthenticatorServiceTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/pbapclient/PbapClientAccountAuthenticatorServiceTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2022 The Android Open Source Project + * Copyright (C) 2022 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. diff --git a/android/app/tests/unit/src/com/android/bluetooth/pbapclient/PbapClientAccountAuthenticatorTest.java b/android/app/tests/unit/src/com/android/bluetooth/pbapclient/PbapClientAccountAuthenticatorTest.java index 237b3215cb..fce20be7ad 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/pbapclient/PbapClientAccountAuthenticatorTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/pbapclient/PbapClientAccountAuthenticatorTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2022 The Android Open Source Project + * Copyright (C) 2022 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. diff --git a/android/app/tests/unit/src/com/android/bluetooth/pbapclient/PbapClientAccountManagerTest.java b/android/app/tests/unit/src/com/android/bluetooth/pbapclient/PbapClientAccountManagerTest.java index a2b773fc03..e3ed3884a4 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/pbapclient/PbapClientAccountManagerTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/pbapclient/PbapClientAccountManagerTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2024 The Android Open Source Project + * Copyright (C) 2024 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. diff --git a/android/app/tests/unit/src/com/android/bluetooth/pbapclient/PbapClientConnectionHandlerTest.java b/android/app/tests/unit/src/com/android/bluetooth/pbapclient/PbapClientConnectionHandlerTest.java index d3ebddfa18..eef3517311 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/pbapclient/PbapClientConnectionHandlerTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/pbapclient/PbapClientConnectionHandlerTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2022 The Android Open Source Project + * Copyright (C) 2022 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. diff --git a/android/app/tests/unit/src/com/android/bluetooth/pbapclient/PbapClientContactsStorageTest.java b/android/app/tests/unit/src/com/android/bluetooth/pbapclient/PbapClientContactsStorageTest.java index ea515ec840..afd2c2a085 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/pbapclient/PbapClientContactsStorageTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/pbapclient/PbapClientContactsStorageTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2024 The Android Open Source Project + * Copyright (C) 2024 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. diff --git a/android/app/tests/unit/src/com/android/bluetooth/pbapclient/PbapClientObexAuthenticatorTest.java b/android/app/tests/unit/src/com/android/bluetooth/pbapclient/PbapClientObexAuthenticatorTest.java index 74265a31ae..45476f1b73 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/pbapclient/PbapClientObexAuthenticatorTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/pbapclient/PbapClientObexAuthenticatorTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2022 The Android Open Source Project + * Copyright (C) 2022 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. 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..ef315042d2 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 @@ -1,5 +1,5 @@ /* - * Copyright 2024 The Android Open Source Project + * Copyright (C) 2024 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. @@ -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/PbapClientObexTransportTest.java b/android/app/tests/unit/src/com/android/bluetooth/pbapclient/PbapClientObexTransportTest.java index 29fc05c955..dfcc542467 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/pbapclient/PbapClientObexTransportTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/pbapclient/PbapClientObexTransportTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2024 The Android Open Source Project + * Copyright (C) 2024 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. diff --git a/android/app/tests/unit/src/com/android/bluetooth/pbapclient/PbapClientServiceTest.java b/android/app/tests/unit/src/com/android/bluetooth/pbapclient/PbapClientServiceTest.java index 35196f14f2..bf3014a7ac 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/pbapclient/PbapClientServiceTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/pbapclient/PbapClientServiceTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2018 The Android Open Source Project + * Copyright (C) 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. diff --git a/android/app/tests/unit/src/com/android/bluetooth/pbapclient/PbapClientSocketTest.java b/android/app/tests/unit/src/com/android/bluetooth/pbapclient/PbapClientSocketTest.java index a3380b177b..64f1979437 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/pbapclient/PbapClientSocketTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/pbapclient/PbapClientSocketTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2024 The Android Open Source Project + * Copyright (C) 2024 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. diff --git a/android/app/tests/unit/src/com/android/bluetooth/pbapclient/PbapClientStateMachineOldTest.java b/android/app/tests/unit/src/com/android/bluetooth/pbapclient/PbapClientStateMachineOldTest.java index 3518b2d418..73c1722e75 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/pbapclient/PbapClientStateMachineOldTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/pbapclient/PbapClientStateMachineOldTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2023 The Android Open Source Project + * Copyright (C) 2023 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/android/app/tests/unit/src/com/android/bluetooth/pbapclient/PbapClientStateMachineTest.java b/android/app/tests/unit/src/com/android/bluetooth/pbapclient/PbapClientStateMachineTest.java index 0f1550d868..d9b8bef9d4 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/pbapclient/PbapClientStateMachineTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/pbapclient/PbapClientStateMachineTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2024 The Android Open Source Project + * Copyright (C) 2024 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. 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..2abafedf77 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 @@ -1,5 +1,5 @@ /* - * Copyright 2024 The Android Open Source Project + * Copyright (C) 2024 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. @@ -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/PbapPhonebookTest.java b/android/app/tests/unit/src/com/android/bluetooth/pbapclient/PbapPhonebookTest.java index 994dccf85a..5c24a9f794 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/pbapclient/PbapPhonebookTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/pbapclient/PbapPhonebookTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2024 The Android Open Source Project + * Copyright (C) 2024 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. diff --git a/android/app/tests/unit/src/com/android/bluetooth/pbapclient/PbapSdpRecordTest.java b/android/app/tests/unit/src/com/android/bluetooth/pbapclient/PbapSdpRecordTest.java index 7b3189db16..3248d6e9db 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/pbapclient/PbapSdpRecordTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/pbapclient/PbapSdpRecordTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2024 The Android Open Source Project + * Copyright (C) 2024 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. diff --git a/android/app/tests/unit/src/com/android/bluetooth/pbapclient/PhonebookPullRequestTest.java b/android/app/tests/unit/src/com/android/bluetooth/pbapclient/PhonebookPullRequestTest.java index d0e462ca66..10526bac41 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/pbapclient/PhonebookPullRequestTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/pbapclient/PhonebookPullRequestTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2022 The Android Open Source Project + * Copyright (C) 2022 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. 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..2e404f9614 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 @@ -1,5 +1,5 @@ /* - * Copyright 2022 The Android Open Source Project + * Copyright (C) 2022 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. @@ -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/android/app/tests/unit/src/com/android/bluetooth/pbapclient/RequestPullPhonebookTest.java b/android/app/tests/unit/src/com/android/bluetooth/pbapclient/RequestPullPhonebookTest.java index 55eb76ab67..551d3e3d2f 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/pbapclient/RequestPullPhonebookTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/pbapclient/RequestPullPhonebookTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2022 The Android Open Source Project + * Copyright (C) 2022 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. diff --git a/android/app/tests/unit/src/com/android/bluetooth/pbapclient/Utils.java b/android/app/tests/unit/src/com/android/bluetooth/pbapclient/Utils.java index 39bbd25746..d390746a02 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/pbapclient/Utils.java +++ b/android/app/tests/unit/src/com/android/bluetooth/pbapclient/Utils.java @@ -1,5 +1,5 @@ /* - * Copyright 2024 The Android Open Source Project + * Copyright (C) 2024 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. diff --git a/android/app/tests/unit/src/com/android/bluetooth/sap/SapMessageTest.java b/android/app/tests/unit/src/com/android/bluetooth/sap/SapMessageTest.java index eab7b0f84a..174e71a954 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/sap/SapMessageTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/sap/SapMessageTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2022 The Android Open Source Project + * Copyright (C) 2022 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. diff --git a/android/app/tests/unit/src/com/android/bluetooth/sap/SapRilReceiverHidlTest.java b/android/app/tests/unit/src/com/android/bluetooth/sap/SapRilReceiverHidlTest.java index 04d4238131..5d30fa6e93 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/sap/SapRilReceiverHidlTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/sap/SapRilReceiverHidlTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2022 The Android Open Source Project + * Copyright (C) 2022 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. diff --git a/android/app/tests/unit/src/com/android/bluetooth/sap/SapRilReceiverTest.java b/android/app/tests/unit/src/com/android/bluetooth/sap/SapRilReceiverTest.java index d2e6ea5d03..80983b2eef 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/sap/SapRilReceiverTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/sap/SapRilReceiverTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2022 The Android Open Source Project + * Copyright (C) 2022 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. diff --git a/android/app/tests/unit/src/com/android/bluetooth/sap/SapServerTest.java b/android/app/tests/unit/src/com/android/bluetooth/sap/SapServerTest.java index 3bed89bda3..69d6434ff2 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/sap/SapServerTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/sap/SapServerTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2022 The Android Open Source Project + * Copyright (C) 2022 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. diff --git a/android/app/tests/unit/src/com/android/bluetooth/sap/SapServiceTest.java b/android/app/tests/unit/src/com/android/bluetooth/sap/SapServiceTest.java index d6336bcb34..06d41b2db8 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/sap/SapServiceTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/sap/SapServiceTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2018 The Android Open Source Project + * Copyright (C) 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. diff --git a/android/app/tests/unit/src/com/android/bluetooth/sdp/DipTest.java b/android/app/tests/unit/src/com/android/bluetooth/sdp/DipTest.java index c9c3c238e2..4e5042bad6 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/sdp/DipTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/sdp/DipTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2018 The Android Open Source Project + * Copyright (C) 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. diff --git a/android/app/tests/unit/src/com/android/bluetooth/telephony/BluetoothCallTest.java b/android/app/tests/unit/src/com/android/bluetooth/telephony/BluetoothCallTest.java index 884b914a4f..441ac2b603 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/telephony/BluetoothCallTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/telephony/BluetoothCallTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2022 The Android Open Source Project + * Copyright (C) 2022 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. diff --git a/android/app/tests/unit/src/com/android/bluetooth/vc/VolumeControlNativeCallbackTest.java b/android/app/tests/unit/src/com/android/bluetooth/vc/VolumeControlNativeCallbackTest.java index 4045cb9bfb..e474775f88 100644 --- a/android/app/tests/unit/src/com/android/bluetooth/vc/VolumeControlNativeCallbackTest.java +++ b/android/app/tests/unit/src/com/android/bluetooth/vc/VolumeControlNativeCallbackTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2024 The Android Open Source Project + * Copyright (C) 2024 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. diff --git a/android/leaudio/app/.classpath b/android/leaudio/app/.classpath index 4a04201ca2..bbe97e501d 100644 --- a/android/leaudio/app/.classpath +++ b/android/leaudio/app/.classpath @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="UTF-8"?> <classpath> - <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-11/"/> + <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-17/"/> <classpathentry kind="con" path="org.eclipse.buildship.core.gradleclasspathcontainer"/> <classpathentry kind="output" path="bin/default"/> </classpath> diff --git a/android/leaudio/gradle/wrapper/gradle-wrapper.jar b/android/leaudio/gradle/wrapper/gradle-wrapper.jar Binary files differindex f6b961fd5a..41d9927a4d 100644 --- a/android/leaudio/gradle/wrapper/gradle-wrapper.jar +++ b/android/leaudio/gradle/wrapper/gradle-wrapper.jar diff --git a/android/leaudio/gradle/wrapper/gradle-wrapper.properties b/android/leaudio/gradle/wrapper/gradle-wrapper.properties index bd98b5dbe3..aa991fceae 100644 --- a/android/leaudio/gradle/wrapper/gradle-wrapper.properties +++ b/android/leaudio/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,5 @@ -#Thu Oct 15 09:37:54 CEST 2020 distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-7.4.2-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-6.5-bin.zip diff --git a/android/leaudio/gradlew b/android/leaudio/gradlew index cccdd3d517..1b6c787337 100755 --- a/android/leaudio/gradlew +++ b/android/leaudio/gradlew @@ -1,78 +1,129 @@ -#!/usr/bin/env sh +#!/bin/sh + +# +# Copyright © 2015-2021 the original authors. +# +# 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 +# +# https://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. +# ############################################################################## -## -## Gradle start up script for UN*X -## +# +# Gradle start up script for POSIX generated by Gradle. +# +# Important for running: +# +# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is +# noncompliant, but you have some other compliant shell such as ksh or +# bash, then to run this script, type that shell name before the whole +# command line, like: +# +# ksh Gradle +# +# Busybox and similar reduced shells will NOT work, because this script +# requires all of these POSIX shell features: +# * functions; +# * expansions «$var», «${var}», «${var:-default}», «${var+SET}», +# «${var#prefix}», «${var%suffix}», and «$( cmd )»; +# * compound commands having a testable exit status, especially «case»; +# * various built-in commands including «command», «set», and «ulimit». +# +# Important for patching: +# +# (2) This script targets any POSIX shell, so it avoids extensions provided +# by Bash, Ksh, etc; in particular arrays are avoided. +# +# The "traditional" practice of packing multiple parameters into a +# space-separated string is a well documented source of bugs and security +# problems, so this is (mostly) avoided, by progressively accumulating +# options in "$@", and eventually passing that to Java. +# +# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS, +# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly; +# see the in-line comments for details. +# +# There are tweaks for specific operating systems such as AIX, CygWin, +# Darwin, MinGW, and NonStop. +# +# (3) This script is generated from the Groovy template +# https://github.com/gradle/gradle/blob/master/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt +# within the Gradle project. +# +# You can find Gradle at https://github.com/gradle/gradle/. +# ############################################################################## # Attempt to set APP_HOME + # Resolve links: $0 may be a link -PRG="$0" -# Need this for relative symlinks. -while [ -h "$PRG" ] ; do - ls=`ls -ld "$PRG"` - link=`expr "$ls" : '.*-> \(.*\)$'` - if expr "$link" : '/.*' > /dev/null; then - PRG="$link" - else - PRG=`dirname "$PRG"`"/$link" - fi +app_path=$0 + +# Need this for daisy-chained symlinks. +while + APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path + [ -h "$app_path" ] +do + ls=$( ls -ld "$app_path" ) + link=${ls#*' -> '} + case $link in #( + /*) app_path=$link ;; #( + *) app_path=$APP_HOME$link ;; + esac done -SAVED="`pwd`" -cd "`dirname \"$PRG\"`/" >/dev/null -APP_HOME="`pwd -P`" -cd "$SAVED" >/dev/null + +APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit APP_NAME="Gradle" -APP_BASE_NAME=`basename "$0"` +APP_BASE_NAME=${0##*/} # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -DEFAULT_JVM_OPTS="" +DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' # Use the maximum available, or set MAX_FD != -1 to use that value. -MAX_FD="maximum" +MAX_FD=maximum warn () { echo "$*" -} +} >&2 die () { echo echo "$*" echo exit 1 -} +} >&2 # OS specific support (must be 'true' or 'false'). cygwin=false msys=false darwin=false nonstop=false -case "`uname`" in - CYGWIN* ) - cygwin=true - ;; - Darwin* ) - darwin=true - ;; - MINGW* ) - msys=true - ;; - NONSTOP* ) - nonstop=true - ;; +case "$( uname )" in #( + CYGWIN* ) cygwin=true ;; #( + Darwin* ) darwin=true ;; #( + MSYS* | MINGW* ) msys=true ;; #( + NONSTOP* ) nonstop=true ;; esac CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + # Determine the Java command to use to start the JVM. if [ -n "$JAVA_HOME" ] ; then if [ -x "$JAVA_HOME/jre/sh/java" ] ; then # IBM's JDK on AIX uses strange locations for the executables - JAVACMD="$JAVA_HOME/jre/sh/java" + JAVACMD=$JAVA_HOME/jre/sh/java else - JAVACMD="$JAVA_HOME/bin/java" + JAVACMD=$JAVA_HOME/bin/java fi if [ ! -x "$JAVACMD" ] ; then die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME @@ -81,7 +132,7 @@ Please set the JAVA_HOME variable in your environment to match the location of your Java installation." fi else - JAVACMD="java" + JAVACMD=java which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. Please set the JAVA_HOME variable in your environment to match the @@ -89,84 +140,95 @@ location of your Java installation." fi # Increase the maximum file descriptors if we can. -if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then - MAX_FD_LIMIT=`ulimit -H -n` - if [ $? -eq 0 ] ; then - if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then - MAX_FD="$MAX_FD_LIMIT" - fi - ulimit -n $MAX_FD - if [ $? -ne 0 ] ; then - warn "Could not set maximum file descriptor limit: $MAX_FD" - fi - else - warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" - fi +if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then + case $MAX_FD in #( + max*) + MAX_FD=$( ulimit -H -n ) || + warn "Could not query maximum file descriptor limit" + esac + case $MAX_FD in #( + '' | soft) :;; #( + *) + ulimit -n "$MAX_FD" || + warn "Could not set maximum file descriptor limit to $MAX_FD" + esac fi -# For Darwin, add options to specify how the application appears in the dock -if $darwin; then - GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" -fi +# Collect all arguments for the java command, stacking in reverse order: +# * args from the command line +# * the main class name +# * -classpath +# * -D...appname settings +# * --module-path (only if needed) +# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables. + +# For Cygwin or MSYS, switch paths to Windows format before running java +if "$cygwin" || "$msys" ; then + APP_HOME=$( cygpath --path --mixed "$APP_HOME" ) + CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" ) + + JAVACMD=$( cygpath --unix "$JAVACMD" ) -# For Cygwin, switch paths to Windows format before running java -if $cygwin ; then - APP_HOME=`cygpath --path --mixed "$APP_HOME"` - CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` - JAVACMD=`cygpath --unix "$JAVACMD"` - - # We build the pattern for arguments to be converted via cygpath - ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` - SEP="" - for dir in $ROOTDIRSRAW ; do - ROOTDIRS="$ROOTDIRS$SEP$dir" - SEP="|" - done - OURCYGPATTERN="(^($ROOTDIRS))" - # Add a user-defined pattern to the cygpath arguments - if [ "$GRADLE_CYGPATTERN" != "" ] ; then - OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" - fi # Now convert the arguments - kludge to limit ourselves to /bin/sh - i=0 - for arg in "$@" ; do - CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` - CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option - - if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition - eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` - else - eval `echo args$i`="\"$arg\"" + for arg do + if + case $arg in #( + -*) false ;; # don't mess with options #( + /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath + [ -e "$t" ] ;; #( + *) false ;; + esac + then + arg=$( cygpath --path --ignore --mixed "$arg" ) fi - i=$((i+1)) + # Roll the args list around exactly as many times as the number of + # args, so each arg winds up back in the position where it started, but + # possibly modified. + # + # NB: a `for` loop captures its iteration list before it begins, so + # changing the positional parameters here affects neither the number of + # iterations, nor the values presented in `arg`. + shift # remove old arg + set -- "$@" "$arg" # push replacement arg done - case $i in - (0) set -- ;; - (1) set -- "$args0" ;; - (2) set -- "$args0" "$args1" ;; - (3) set -- "$args0" "$args1" "$args2" ;; - (4) set -- "$args0" "$args1" "$args2" "$args3" ;; - (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; - (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; - (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; - (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; - (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; - esac fi -# Escape application args -save () { - for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done - echo " " -} -APP_ARGS=$(save "$@") - -# Collect all arguments for the java command, following the shell quoting and substitution rules -eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" - -# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong -if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then - cd "$(dirname "$0")" -fi +# Collect all arguments for the java command; +# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of +# shell script including quotes and variable substitutions, so put them in +# double quotes to make sure that they get re-expanded; and +# * put everything else in single quotes, so that it's not re-expanded. + +set -- \ + "-Dorg.gradle.appname=$APP_BASE_NAME" \ + -classpath "$CLASSPATH" \ + org.gradle.wrapper.GradleWrapperMain \ + "$@" + +# Use "xargs" to parse quoted args. +# +# With -n1 it outputs one arg per line, with the quotes and backslashes removed. +# +# In Bash we could simply go: +# +# readarray ARGS < <( xargs -n1 <<<"$var" ) && +# set -- "${ARGS[@]}" "$@" +# +# but POSIX shell has neither arrays nor command substitution, so instead we +# post-process each arg (as a line of input to sed) to backslash-escape any +# character that might be a shell metacharacter, then use eval to reverse +# that process (while maintaining the separation between arguments), and wrap +# the whole thing up as a single "set" statement. +# +# This will of course break if any of these variables contains a newline or +# an unmatched quote. +# + +eval "set -- $( + printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" | + xargs -n1 | + sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' | + tr '\n' ' ' + )" '"$@"' exec "$JAVACMD" "$@" diff --git a/android/leaudio/gradlew.bat b/android/leaudio/gradlew.bat index e95643d6a2..ac1b06f938 100644 --- a/android/leaudio/gradlew.bat +++ b/android/leaudio/gradlew.bat @@ -1,3 +1,19 @@ +@rem
+@rem Copyright 2015 the original author or authors.
+@rem
+@rem Licensed under the Apache License, Version 2.0 (the "License");
+@rem you may not use this file except in compliance with the License.
+@rem You may obtain a copy of the License at
+@rem
+@rem https://www.apache.org/licenses/LICENSE-2.0
+@rem
+@rem Unless required by applicable law or agreed to in writing, software
+@rem distributed under the License is distributed on an "AS IS" BASIS,
+@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+@rem See the License for the specific language governing permissions and
+@rem limitations under the License.
+@rem
+
@if "%DEBUG%" == "" @echo off
@rem ##########################################################################
@rem
@@ -13,15 +29,18 @@ if "%DIRNAME%" == "" set DIRNAME=. set APP_BASE_NAME=%~n0
set APP_HOME=%DIRNAME%
+@rem Resolve any "." and ".." in APP_HOME to make it shorter.
+for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
+
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
-set DEFAULT_JVM_OPTS=
+set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
@rem Find java.exe
if defined JAVA_HOME goto findJavaFromJavaHome
set JAVA_EXE=java.exe
%JAVA_EXE% -version >NUL 2>&1
-if "%ERRORLEVEL%" == "0" goto init
+if "%ERRORLEVEL%" == "0" goto execute
echo.
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
@@ -35,7 +54,7 @@ goto fail set JAVA_HOME=%JAVA_HOME:"=%
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
-if exist "%JAVA_EXE%" goto init
+if exist "%JAVA_EXE%" goto execute
echo.
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
@@ -45,28 +64,14 @@ echo location of your Java installation. goto fail
-:init
-@rem Get command-line arguments, handling Windows variants
-
-if not "%OS%" == "Windows_NT" goto win9xME_args
-
-:win9xME_args
-@rem Slurp the command line arguments.
-set CMD_LINE_ARGS=
-set _SKIP=2
-
-:win9xME_args_slurp
-if "x%~1" == "x" goto execute
-
-set CMD_LINE_ARGS=%*
-
:execute
@rem Setup the command line
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
+
@rem Execute Gradle
-"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
+"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
:end
@rem End local scope for the variables with windows NT shell
diff --git a/android/pandora/server/configs/pts_bot_tests_config.json b/android/pandora/server/configs/pts_bot_tests_config.json index e80e123437..023cb94544 100644 --- a/android/pandora/server/configs/pts_bot_tests_config.json +++ b/android/pandora/server/configs/pts_bot_tests_config.json @@ -24,7 +24,6 @@ "A2DP/SNK/CC/BV-08-I", "A2DP/SNK/REL/BV-01-I", "A2DP/SNK/REL/BV-02-I", - "A2DP/SNK/SDP/BV-02-I", "A2DP/SNK/SET/BV-01-I", "A2DP/SNK/SET/BV-02-I", "A2DP/SNK/SET/BV-03-I", @@ -44,7 +43,6 @@ "A2DP/SRC/CC/BV-09-I", "A2DP/SRC/REL/BV-01-I", "A2DP/SRC/REL/BV-02-I", - "A2DP/SRC/SDP/BV-01-I", "A2DP/SRC/SET/BV-01-I", "A2DP/SRC/SET/BV-02-I", "A2DP/SRC/SET/BV-03-I", @@ -735,6 +733,7 @@ ], "skip": [ "A2DP/SNK/AVP/BI-07-C", + "A2DP/SNK/SDP/BV-02-I", "A2DP/SNK/SET/BV-04-I", "A2DP/SNK/SET/BV-06-I", "A2DP/SNK/SUS/BV-02-I", @@ -742,6 +741,7 @@ "A2DP/SRC/AS/BV-03-I", "A2DP/SRC/AS/BV-04-I", "A2DP/SRC/CC/BV-10-I", + "A2DP/SRC/SDP/BV-01-I", "A2DP/SRC/SET/BV-05-I", "A2DP/SRC/SET/BV-06-I", "A2DP/SRC/SUS/BV-02-I", diff --git a/flags/a2dp.aconfig b/flags/a2dp.aconfig index ccf46f8bed..e7b9aa21b0 100644 --- a/flags/a2dp.aconfig +++ b/flags/a2dp.aconfig @@ -39,16 +39,6 @@ flag { } flag { - name: "a2dp_broadcast_connection_state_when_turned_off" - namespace: "bluetooth" - description: "Broadcast CONNECTION_STATE_CHANGED when A2dpService is turned off while a device is connected" - bug: "360034472" - metadata { - purpose: PURPOSE_BUGFIX - } -} - -flag { name: "fix_avdt_rconfig_not_setting_l2cap" namespace: "bluetooth" description: "Set L2CAP flushable and high priority after A2DP reconfigure" @@ -59,26 +49,6 @@ flag { } flag { - name: "a2dp_source_threading_fix" - namespace: "bluetooth" - description: "Schedule A2DP source setup operations to bt_main_thread to prevent races" - bug: "374166531" - metadata { - purpose: PURPOSE_BUGFIX - } -} - -flag { - name: "a2dp_clear_pending_start_on_session_restart" - namespace: "bluetooth" - description: "Clear the kPendingStart flag when the audio session is restarted for codec reconfiguration" - bug: "378524655" - metadata { - purpose: PURPOSE_BUGFIX - } -} - -flag { name: "avdt_handle_suspend_cfm_bad_state" namespace: "bluetooth" description: "Close connection on AVDTP Suspend Confirmation with BAD STATE error" diff --git a/flags/adapter.aconfig b/flags/adapter.aconfig index 6ed8619dbb..0195723932 100644 --- a/flags/adapter.aconfig +++ b/flags/adapter.aconfig @@ -2,16 +2,6 @@ package: "com.android.bluetooth.flags" container: "com.android.bt" flag { - name: "adapter_properties_looper" - namespace: "bluetooth" - description: "Manage AdapterProperties threading to not conflict with main looper and handle callback from native properly" - metadata { - purpose: PURPOSE_BUGFIX - } - bug: "372777933" -} - -flag { name: "adapter_suspend_mgmt" namespace: "bluetooth" description: "Configure the BT adapter in a suspend state to avoid unexpected wake-up" diff --git a/flags/framework.aconfig b/flags/framework.aconfig index bac9c95a26..dc48541118 100644 --- a/flags/framework.aconfig +++ b/flags/framework.aconfig @@ -28,16 +28,6 @@ flag { } flag { - name: "get_profile_use_lock" - namespace: "bluetooth" - description: "Instead of bloating the main thread, use the binder thread with a synchronization lock" - bug: "370815283" - metadata { - purpose: PURPOSE_BUGFIX - } -} - -flag { name: "support_remote_device_metadata" is_exported: true namespace: "bluetooth" @@ -109,3 +99,13 @@ flag { purpose: PURPOSE_BUGFIX } } + +flag { + name: "same_handler_for_all_modules" + namespace: "bluetooth" + description: "Update all modules to use the same handler" + bug: "398195386" + metadata { + purpose: PURPOSE_BUGFIX + } +} diff --git a/flags/gap.aconfig b/flags/gap.aconfig index ecbc2aadb2..d12e294ec7 100644 --- a/flags/gap.aconfig +++ b/flags/gap.aconfig @@ -314,3 +314,13 @@ flag { purpose: PURPOSE_BUGFIX } } + +flag { + name: "start_discover_service_changed" + namespace: "bluetooth" + description: "Start discovery again when service change indication arrives." + bug: "400828637" + metadata { + purpose: PURPOSE_BUGFIX + } +} diff --git a/flags/pairing.aconfig b/flags/pairing.aconfig index 165b2dc191..bc57bafe9e 100644 --- a/flags/pairing.aconfig +++ b/flags/pairing.aconfig @@ -239,4 +239,24 @@ flag { metadata { purpose: PURPOSE_BUGFIX } -}
\ No newline at end of file +} + +flag { + name: "smp_connection_status_handling_when_no_acl" + namespace: "bluetooth" + description: "Fix SMP connection status sent from L2CAP when LE ACL is not connected" + bug: "401073843" + metadata { + purpose: PURPOSE_BUGFIX + } +} + +flag { + name: "non_zero_local_irk" + namespace: "bluetooth" + description: "Ensure that the local IRK is not zero before sending it to the controller" + bug: "401126556" + metadata { + purpose: PURPOSE_BUGFIX + } +} diff --git a/flags/pbapclient.aconfig b/flags/pbapclient.aconfig index 52b5ee3910..e78708e2c0 100644 --- a/flags/pbapclient.aconfig +++ b/flags/pbapclient.aconfig @@ -24,3 +24,13 @@ flag { purpose: PURPOSE_BUGFIX } } + +flag { + name: "pbap_limit_call_log" + namespace: "bluetooth" + description: "Limit the number of call log correctly" + bug: "401127740" + metadata { + purpose: PURPOSE_BUGFIX + } +} diff --git a/flags/security.aconfig b/flags/security.aconfig index cb7cdac795..c83dc02b24 100644 --- a/flags/security.aconfig +++ b/flags/security.aconfig @@ -114,3 +114,13 @@ flag { purpose: PURPOSE_BUGFIX } } + +flag { + name: "btsec_check_controller_sc_support" + namespace: "bluetooth" + description: "Check for controller as well as host Secure Connections support when dropping connections" + bug: "400802709" + metadata { + purpose: PURPOSE_BUGFIX + } +} diff --git a/flags/system_service.aconfig b/flags/system_service.aconfig index 65caf1e60c..ea40eb33de 100644 --- a/flags/system_service.aconfig +++ b/flags/system_service.aconfig @@ -2,36 +2,6 @@ package: "com.android.bluetooth.flags" container: "com.android.bt" flag { - name: "enforce_resolve_system_service_behavior" - namespace: "bluetooth" - description: "Loudly crash when it is not possible to find a service to start bluetooth" - metadata { - purpose: PURPOSE_BUGFIX - } - bug: "366273182" -} - -flag { - name: "get_state_from_system_server" - namespace: "bluetooth" - description: "Get Bluetooth state from system server instead of from Bluetooth app" - metadata { - purpose: PURPOSE_BUGFIX - } - bug: "362569584" -} - -flag { - name: "get_name_and_address_as_callback" - namespace: "bluetooth" - description: "Getting the name and address is a non-oneway call. Instead inform the system server with callback" - metadata { - purpose: PURPOSE_BUGFIX - } - bug: "368114370" -} - -flag { name: "kill_instead_of_exit" namespace: "bluetooth" description: "There is no value in pretending we are exiting properly. This is a kill and we should express it this way when finishing the process" @@ -42,18 +12,18 @@ flag { } flag { - name: "remove_one_time_get_name_and_address" + name: "system_server_messenger" namespace: "bluetooth" - description: "We don't need to start bluetooth the first time to get name & address. We can wait for a proper start" - metadata { - purpose: PURPOSE_BUGFIX - } - bug: "368120237" + description: "Replace binder call to the system server with a Messenger to enforce thread safety" + bug: "321804999" } flag { - name: "system_server_messenger" + name: "system_server_remove_extra_thread_jump" namespace: "bluetooth" - description: "Replace binder call to the system server with a Messenger to enforce thread safety" - bug: "321804999" + description: "Methods are unnecessarily re-posting on the system server thread" + bug: "402209603" + metadata { + purpose: PURPOSE_BUGFIX + } } diff --git a/framework/Android.bp b/framework/Android.bp index 36cd93670c..e40f1af6f4 100644 --- a/framework/Android.bp +++ b/framework/Android.bp @@ -100,7 +100,6 @@ java_sdk_library { "ExtraTranslation", "FlaggedApi", "GestureBackNavigation", - "GetterSetterNullability", "GuardedLogInvocation", "HandlerLeak", "InflateParams", diff --git a/framework/api/system-current.txt b/framework/api/system-current.txt index 10bdab4b5c..cdb9bf0670 100644 --- a/framework/api/system-current.txt +++ b/framework/api/system-current.txt @@ -247,7 +247,7 @@ package android.bluetooth { method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public boolean cancelBondProcess(); method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED, android.Manifest.permission.MODIFY_PHONE_STATE}) public int connect(); method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public boolean createBond(int); - method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public boolean createBondOutOfBand(int, @Nullable android.bluetooth.OobData, @Nullable android.bluetooth.OobData); + method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public boolean createBondOutOfBand(int, @Nullable android.bluetooth.OobData, @Nullable android.bluetooth.OobData); method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public int disconnect(); method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}, conditional=true) public boolean fetchUuidsWithSdp(int); method @RequiresPermission(allOf={android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_PRIVILEGED}) public int getActiveAudioDevicePolicy(); diff --git a/framework/java/android/bluetooth/AudioInputControl.java b/framework/java/android/bluetooth/AudioInputControl.java index b39458b15f..eb89a4cab3 100644 --- a/framework/java/android/bluetooth/AudioInputControl.java +++ b/framework/java/android/bluetooth/AudioInputControl.java @@ -333,7 +333,7 @@ public class AudioInputControl { /** see {@link #setDescription(String)} */ default void onDescriptionChanged(@NonNull String description) {} - /** see {@link #getStatus()} */ + /** see {@link #getAudioInputStatus()} */ default void onAudioInputStatusChanged(@AudioInputStatus int status) {} /** see {@link #setGainSetting(int)} */ @@ -564,8 +564,8 @@ public class AudioInputControl { /** * Sets the gain setting as defined in AICS 1.0 - 3.5.2.1. * - * <p>The operation will fail if the current gain mode is {@link #AUTOMATIC} or {@link - * #AUTOMATIC_ONLY}. + * <p>The operation will fail if the current gain mode is {@link #GAIN_MODE_AUTOMATIC} or {@link + * #GAIN_MODE_AUTOMATIC_ONLY}. * * <p>Register an {@link AudioInputControl.AudioInputCallback} to be notified via * @@ -585,8 +585,8 @@ public class AudioInputControl { * #getGainSettingUnit()} to knows how much decibel this represents. * @return true if the operation is successfully initiated, false otherwise. The callback {@link * AudioInputCallback#onSetGainSettingFailed()} will not be call if false is returned - * @throws IllegalStateException if the gain mode is {@link #AUTOMATIC} or {@link - * #AUTOMATIC_ONLY} + * @throws IllegalStateException if the gain mode is {@link #GAIN_MODE_AUTOMATIC} or {@link + * #GAIN_MODE_AUTOMATIC_ONLY} * @throws IllegalArgumentException if the gain setting is not in range */ @RequiresBluetoothConnectPermission @@ -614,14 +614,14 @@ public class AudioInputControl { return callService( mService, s -> s.getAudioInputGainMode(mAttributionSource, mDevice, mInstanceId), - (int) bluetooth.constants.aics.GainMode.AUTOMATIC_ONLY); + GAIN_MODE_AUTOMATIC_ONLY); } /** * Sets the gain mode as defined in AICS 1.0 - 3.5.2.4/5. * - * <p>The operation will fail if the current gain mode is {@link #MANUAL_ONLY} or {@link - * #AUTOMATIC_ONLY}. + * <p>The operation will fail if the current gain mode is {@link #GAIN_MODE_MANUAL_ONLY} or + * {@link #GAIN_MODE_AUTOMATIC_ONLY}. * * <p>Register an {@link AudioInputControl.AudioInputCallback} to be notified via * @@ -634,8 +634,8 @@ public class AudioInputControl { * @param gainMode The desired gain mode * @return true if the operation is successfully initiated, false otherwise. The callback {@link * AudioInputCallback#onSetGainModeFailed()} will not be call if false is returned - * @throws IllegalStateException if the gain mode is {@link #MANUAL_ONLY} or {@link - * #AUTOMATIC_ONLY} + * @throws IllegalStateException if the gain mode is {@link #GAIN_MODE_MANUAL_ONLY} or {@link + * #GAIN_MODE_AUTOMATIC_ONLY} * @throws IllegalArgumentException if the gain mode value is invalid. */ @RequiresBluetoothConnectPermission diff --git a/framework/java/android/bluetooth/BluetoothActivityEnergyInfo.java b/framework/java/android/bluetooth/BluetoothActivityEnergyInfo.java index 1dc5c3bf92..52bb0fd0dd 100644 --- a/framework/java/android/bluetooth/BluetoothActivityEnergyInfo.java +++ b/framework/java/android/bluetooth/BluetoothActivityEnergyInfo.java @@ -139,12 +139,9 @@ public final class BluetoothActivityEnergyInfo implements Parcelable { } /** - * Get the Bluetooth stack state associated with the energy info. - * - * @return one of {@link #BluetoothStackState} states + * @return the Bluetooth stack state associated with the energy info. */ - @BluetoothStackState - public int getBluetoothStackState() { + public @BluetoothStackState int getBluetoothStackState() { return mBluetoothStackState; } diff --git a/framework/java/android/bluetooth/BluetoothAdapter.java b/framework/java/android/bluetooth/BluetoothAdapter.java index 8f2edc546d..40d1153581 100644 --- a/framework/java/android/bluetooth/BluetoothAdapter.java +++ b/framework/java/android/bluetooth/BluetoothAdapter.java @@ -506,8 +506,8 @@ public final class BluetoothAdapter { @SystemApi public static final int BT_SNOOP_LOG_MODE_FILTERED = 1; /** - * Used as parameter for {@link #setSnoopLogMode}, indicates that the Bluetooth HCI snoop - * logging should be enabled. + * Used as parameter for {@link #setBluetoothHciSnoopLoggingMode}, indicates that the Bluetooth + * HCI snoop logging should be enabled. * * <p>See {@link #BT_SNOOP_LOG_MODE_FILTERED} to enable logging with filtered information. * @@ -913,11 +913,7 @@ public final class BluetoothAdapter { Log.d(TAG, getProfileName(mProfile) + " connected"); mConnected = true; proxy.onServiceConnected(binder); - if (Flags.getProfileUseLock()) { - executeFromBinder(mExecutor, () -> mListener.onServiceConnected(mProfile, proxy)); - } else { - mListener.onServiceConnected(mProfile, proxy); - } + executeFromBinder(mExecutor, () -> mListener.onServiceConnected(mProfile, proxy)); } @GuardedBy("BluetoothAdapter.sProfileLock") @@ -925,11 +921,7 @@ public final class BluetoothAdapter { Log.d(TAG, getProfileName(mProfile) + " disconnected"); mConnected = false; proxy.onServiceDisconnected(); - if (Flags.getProfileUseLock()) { - executeFromBinder(mExecutor, () -> mListener.onServiceDisconnected(mProfile)); - } else { - mListener.onServiceDisconnected(mProfile); - } + executeFromBinder(mExecutor, () -> mListener.onServiceDisconnected(mProfile)); } } @@ -1435,25 +1427,6 @@ public final class BluetoothAdapter { IpcDataCache.invalidateCache(IpcDataCache.MODULE_BLUETOOTH, api); } - private static final IpcDataCache.QueryHandler<IBluetooth, Integer> sBluetoothGetStateQuery = - new IpcDataCache.QueryHandler<>() { - @RequiresLegacyBluetoothPermission - @RequiresNoPermission - @Override - public @InternalAdapterState Integer apply(IBluetooth serviceQuery) { - try { - return serviceQuery.getState(); - } catch (RemoteException e) { - throw e.rethrowAsRuntimeException(); - } - } - @RequiresNoPermission - @Override - public boolean shouldBypassCache(IBluetooth serviceQuery) { - return false; - } - }; - private static final IpcDataCache.QueryHandler<Void, Integer> sBluetoothGetSystemStateQuery = new IpcDataCache.QueryHandler<>() { @RequiresNoPermission @@ -1478,14 +1451,9 @@ public final class BluetoothAdapter { } }; - private static final String GET_STATE_API = "BluetoothAdapter_getState"; - /** @hide */ public static final String GET_SYSTEM_STATE_API = IBluetoothManager.GET_SYSTEM_STATE_API; - private static final IpcDataCache<IBluetooth, Integer> sBluetoothGetStateCache = - new BluetoothCache<>(GET_STATE_API, sBluetoothGetStateQuery); - private static final IpcDataCache<Void, Integer> sBluetoothGetSystemStateCache = new IpcDataCache<>( 1, @@ -1494,44 +1462,6 @@ public final class BluetoothAdapter { GET_SYSTEM_STATE_API, sBluetoothGetSystemStateQuery); - /** @hide */ - @RequiresNoPermission - public void disableBluetoothGetStateCache() { - if (Flags.getStateFromSystemServer()) { - throw new IllegalStateException("getStateFromSystemServer is enabled"); - } - sBluetoothGetStateCache.disableForCurrentProcess(); - } - - /** @hide */ - public static void invalidateBluetoothGetStateCache() { - if (Flags.getStateFromSystemServer()) { - throw new IllegalStateException("getStateFromSystemServer is enabled"); - } - invalidateCache(GET_STATE_API); - } - - /** Fetch the current bluetooth state. If the service is down, return OFF. */ - private @InternalAdapterState int getStateInternal() { - if (Flags.getStateFromSystemServer()) { - return sBluetoothGetSystemStateCache.query(null); - } - mServiceLock.readLock().lock(); - try { - if (mService != null) { - return sBluetoothGetStateCache.query(mService); - } - } catch (RuntimeException e) { - if (!(e.getCause() instanceof RemoteException)) { - throw e; - } - Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable())); - } finally { - mServiceLock.readLock().unlock(); - } - return STATE_OFF; - } - /** * Get the current state of the local Bluetooth adapter. * @@ -1543,7 +1473,7 @@ public final class BluetoothAdapter { @RequiresLegacyBluetoothPermission @RequiresNoPermission public @AdapterState int getState() { - int state = getStateInternal(); + int state = sBluetoothGetSystemStateCache.query(null); // Consider all internal states as OFF if (state == BluetoothAdapter.STATE_BLE_ON @@ -1584,7 +1514,7 @@ public final class BluetoothAdapter { "Use {@link #getState()} instead to determine " + "whether you can use BLE & BT classic.") public @InternalAdapterState int getLeState() { - int state = getStateInternal(); + int state = sBluetoothGetSystemStateCache.query(null); if (VDBG) { Log.d(TAG, "getLeState() returning " + BluetoothAdapter.nameForState(state)); @@ -3538,24 +3468,16 @@ public final class BluetoothAdapter { return false; } - Runnable connectAction = - () -> { - synchronized (sProfileLock) { - // Synchronize with the binder callback to prevent performing the - // ProfileConnection.connect concurrently - mProfileConnections.put(profileProxy, connection); + synchronized (sProfileLock) { + // Synchronize with the binder callback to prevent performing the + // ProfileConnection.connect concurrently + mProfileConnections.put(profileProxy, connection); - IBinder binder = getProfile(profile); - if (binder != null) { - connection.connect(profileProxy, binder); - } - } - }; - if (Flags.getProfileUseLock()) { - connectAction.run(); - return true; + IBinder binder = getProfile(profile); + if (binder != null) { + connection.connect(profileProxy, binder); + } } - executor.execute(connectAction); return true; } @@ -3623,7 +3545,12 @@ public final class BluetoothAdapter { private static final IBluetoothManagerCallback sManagerCallback = new IBluetoothManagerCallback.Stub() { - private void onBluetoothServiceUpFlagged(IBinder bluetoothService) { + @RequiresNoPermission + public void onBluetoothServiceUp(IBinder bluetoothService) { + if (DBG) { + Log.d(TAG, "onBluetoothServiceUp: " + bluetoothService); + } + sServiceLock.writeLock().lock(); try { sService = IBluetooth.Stub.asInterface(bluetoothService); @@ -3640,32 +3567,11 @@ public final class BluetoothAdapter { } @RequiresNoPermission - public void onBluetoothServiceUp(IBinder bluetoothService) { + public void onBluetoothServiceDown() { if (DBG) { - Log.d(TAG, "onBluetoothServiceUp: " + bluetoothService); - } - - if (Flags.getProfileUseLock()) { - onBluetoothServiceUpFlagged(bluetoothService); - return; - } - synchronized (sServiceLock) { - sService = IBluetooth.Stub.asInterface(bluetoothService); - for (IBluetoothManagerCallback cb : sProxyServiceStateCallbacks.keySet()) { - try { - if (cb != null) { - cb.onBluetoothServiceUp(bluetoothService); - } else { - Log.d(TAG, "onBluetoothServiceUp: cb is null!"); - } - } catch (Exception e) { - Log.e(TAG, "", e); - } - } + Log.d(TAG, "onBluetoothServiceDown"); } - } - private void onBluetoothServiceDownFlagged() { sServiceLock.writeLock().lock(); try { sService = null; @@ -3682,33 +3588,11 @@ public final class BluetoothAdapter { } @RequiresNoPermission - public void onBluetoothServiceDown() { + public void onBluetoothOn() { if (DBG) { - Log.d(TAG, "onBluetoothServiceDown"); - } - - if (Flags.getProfileUseLock()) { - onBluetoothServiceDownFlagged(); - return; - } - - synchronized (sServiceLock) { - sService = null; - for (IBluetoothManagerCallback cb : sProxyServiceStateCallbacks.keySet()) { - try { - if (cb != null) { - cb.onBluetoothServiceDown(); - } else { - Log.d(TAG, "onBluetoothServiceDown: cb is null!"); - } - } catch (Exception e) { - Log.e(TAG, "", e); - } - } + Log.d(TAG, "onBluetoothOn"); } - } - private void onBluetoothOnFlagged() { sServiceLock.readLock().lock(); try { for (IBluetoothManagerCallback cb : sProxyServiceStateCallbacks.keySet()) { @@ -3724,31 +3608,11 @@ public final class BluetoothAdapter { } @RequiresNoPermission - public void onBluetoothOn() { + public void onBluetoothOff() { if (DBG) { - Log.d(TAG, "onBluetoothOn"); - } - - if (Flags.getProfileUseLock()) { - onBluetoothOnFlagged(); - return; - } - synchronized (sServiceLock) { - for (IBluetoothManagerCallback cb : sProxyServiceStateCallbacks.keySet()) { - try { - if (cb != null) { - cb.onBluetoothOn(); - } else { - Log.d(TAG, "onBluetoothOn: cb is null!"); - } - } catch (Exception e) { - Log.e(TAG, "", e); - } - } + Log.d(TAG, "onBluetoothOff"); } - } - private void onBluetoothOffFlagged() { sServiceLock.readLock().lock(); try { for (IBluetoothManagerCallback cb : sProxyServiceStateCallbacks.keySet()) { @@ -3762,31 +3626,6 @@ public final class BluetoothAdapter { sServiceLock.readLock().unlock(); } } - - @RequiresNoPermission - public void onBluetoothOff() { - if (DBG) { - Log.d(TAG, "onBluetoothOff"); - } - - if (Flags.getProfileUseLock()) { - onBluetoothOffFlagged(); - return; - } - synchronized (sServiceLock) { - for (IBluetoothManagerCallback cb : sProxyServiceStateCallbacks.keySet()) { - try { - if (cb != null) { - cb.onBluetoothOff(); - } else { - Log.d(TAG, "onBluetoothOff: cb is null!"); - } - } catch (Exception e) { - Log.e(TAG, "", e); - } - } - } - } }; private final IBluetoothManagerCallback mManagerCallback = @@ -3874,37 +3713,21 @@ public final class BluetoothAdapter { @RequiresNoPermission public void onBluetoothOn() { - Runnable btOnAction = - () -> { - synchronized (sProfileLock) { - connectAllProfileProxyLocked(); - } - }; - if (Flags.getProfileUseLock()) { - btOnAction.run(); - return; + synchronized (sProfileLock) { + connectAllProfileProxyLocked(); } - mMainHandler.post(btOnAction); } @RequiresNoPermission public void onBluetoothOff() { - Runnable btOffAction = - () -> { - synchronized (sProfileLock) { - mProfileConnections.forEach( - (proxy, connection) -> { - if (connection.mConnected) { - connection.disconnect(proxy); - } - }); - } - }; - if (Flags.getProfileUseLock()) { - btOffAction.run(); - return; + synchronized (sProfileLock) { + mProfileConnections.forEach( + (proxy, connection) -> { + if (connection.mConnected) { + connection.disconnect(proxy); + } + }); } - mMainHandler.post(btOffAction); } }; @@ -4134,36 +3957,24 @@ public final class BluetoothAdapter { new WeakHashMap<>(); /*package*/ IBluetooth getBluetoothService() { - if (Flags.getProfileUseLock()) { - sServiceLock.readLock().lock(); - try { - return sService; - } finally { - sServiceLock.readLock().unlock(); - } - } - synchronized (sServiceLock) { + sServiceLock.readLock().lock(); + try { return sService; + } finally { + sServiceLock.readLock().unlock(); } } /** Registers a IBluetoothManagerCallback and returns the cached service proxy object. */ IBluetooth registerBluetoothManagerCallback(IBluetoothManagerCallback cb) { requireNonNull(cb); - if (Flags.getProfileUseLock()) { - sServiceLock.writeLock().lock(); - try { - sProxyServiceStateCallbacks.put(cb, null); - registerOrUnregisterAdapterLocked(); - return sService; - } finally { - sServiceLock.writeLock().unlock(); - } - } - synchronized (sServiceLock) { + sServiceLock.writeLock().lock(); + try { sProxyServiceStateCallbacks.put(cb, null); registerOrUnregisterAdapterLocked(); return sService; + } finally { + sServiceLock.writeLock().unlock(); } } @@ -4264,19 +4075,12 @@ public final class BluetoothAdapter { void removeServiceStateCallback(IBluetoothManagerCallback cb) { requireNonNull(cb); - if (Flags.getProfileUseLock()) { - sServiceLock.writeLock().lock(); - try { - sProxyServiceStateCallbacks.remove(cb); - registerOrUnregisterAdapterLocked(); - } finally { - sServiceLock.writeLock().unlock(); - } - return; - } - synchronized (sServiceLock) { + sServiceLock.writeLock().lock(); + try { sProxyServiceStateCallbacks.remove(cb); registerOrUnregisterAdapterLocked(); + } finally { + sServiceLock.writeLock().unlock(); } } @@ -4714,21 +4518,20 @@ public final class BluetoothAdapter { } /** - * Register a {@link #OnMetadataChangedListener} to receive update about metadata changes for + * Register a {@link OnMetadataChangedListener} to receive update about metadata changes for * this {@link BluetoothDevice}. Registration must be done when Bluetooth is ON and will last - * until {@link #removeOnMetadataChangedListener(BluetoothDevice)} is called, even when - * Bluetooth restarted in the middle. All input parameters should not be null or {@link - * NullPointerException} will be triggered. The same {@link BluetoothDevice} and {@link - * #OnMetadataChangedListener} pair can only be registered once, double registration would cause - * {@link IllegalArgumentException}. + * until {@link #removeOnMetadataChangedListener} is called, even when Bluetooth restarted in + * the middle. All input parameters should not be null or {@link NullPointerException} will be + * triggered. The same {@link BluetoothDevice} and {@link OnMetadataChangedListener} pair can + * only be registered once, double registration would cause {@link IllegalArgumentException}. * * @param device {@link BluetoothDevice} that will be registered * @param executor the executor for listener callback - * @param listener {@link #OnMetadataChangedListener} that will receive asynchronous callbacks + * @param listener {@link OnMetadataChangedListener} that will receive asynchronous callbacks * @return true on success, false on error * @throws NullPointerException If one of {@code listener}, {@code device} or {@code executor} * is null. - * @throws IllegalArgumentException The same {@link #OnMetadataChangedListener} and {@link + * @throws IllegalArgumentException The same {@link OnMetadataChangedListener} and {@link * BluetoothDevice} are registered twice. * @hide */ @@ -4795,10 +4598,9 @@ public final class BluetoothAdapter { } /** - * Unregister a {@link #OnMetadataChangedListener} from a registered {@link BluetoothDevice}. + * Unregister a {@link OnMetadataChangedListener} from a registered {@link BluetoothDevice}. * Unregistration can be done when Bluetooth is either ON or OFF. {@link - * #addOnMetadataChangedListener(OnMetadataChangedListener, BluetoothDevice, Executor)} must be - * called before unregistration. + * #addOnMetadataChangedListener} must be called before unregistration. * * @param device {@link BluetoothDevice} that will be unregistered. It should not be null or * {@link NullPointerException} will be triggered. @@ -5539,7 +5341,7 @@ public final class BluetoothAdapter { * the report supports five event types: Quality monitor event, Approaching LSTO event, A2DP * choppy event, SCO choppy event and Connect fail event. To know which kind of event is * wrapped in this {@link BluetoothQualityReport} object, you need to call {@link - * #getQualityReportId}. + * BluetoothQualityReport#getQualityReportId}. * * @param device is the BluetoothDevice which connection quality is being reported * @param bluetoothQualityReport a Parcel that contains info about Bluetooth Quality diff --git a/framework/java/android/bluetooth/BluetoothCsipSetCoordinator.java b/framework/java/android/bluetooth/BluetoothCsipSetCoordinator.java index 9ec499d002..db03b15ad7 100644 --- a/framework/java/android/bluetooth/BluetoothCsipSetCoordinator.java +++ b/framework/java/android/bluetooth/BluetoothCsipSetCoordinator.java @@ -86,7 +86,7 @@ public final class BluetoothCsipSetCoordinator implements BluetoothProfile, Auto @interface Status {} /** - * Callback is invoked as a result on {@link #groupLock()}. + * Callback is invoked as a result on {@link BluetoothCsipSetCoordinator#lockGroup()}. * * @param groupId group identifier * @param opStatus status of lock operation @@ -115,7 +115,6 @@ public final class BluetoothCsipSetCoordinator implements BluetoothProfile, Auto mExecutor, () -> mCallback.onGroupLockSet(groupId, opStatus, isLocked)); } } - ; /** * Intent used to broadcast the change in connection state of the CSIS Client. diff --git a/framework/java/android/bluetooth/BluetoothDevice.java b/framework/java/android/bluetooth/BluetoothDevice.java index 8c053201e9..d5ec86546c 100644 --- a/framework/java/android/bluetooth/BluetoothDevice.java +++ b/framework/java/android/bluetooth/BluetoothDevice.java @@ -375,14 +375,6 @@ public final class BluetoothDevice implements Parcelable, Attributable { public static final String EXTRA_NAME = "android.bluetooth.device.extra.NAME"; /** - * Used as a Parcelable {@link BluetoothQualityReport} extra field in {@link - * #ACTION_REMOTE_ISSUE_OCCURRED} intent. It contains the {@link BluetoothQualityReport}. - * - * @hide - */ - public static final String EXTRA_BQR = "android.bluetooth.qti.extra.EXTRA_BQR"; - - /** * Used as an optional short extra field in {@link #ACTION_FOUND} intents. Contains the RSSI * value of the remote device as reported by the Bluetooth hardware. */ @@ -1958,7 +1950,21 @@ public final class BluetoothDevice implements Parcelable, Attributable { @RequiresBluetoothConnectPermission @RequiresPermission(BLUETOOTH_CONNECT) public boolean createBond(int transport) { - return createBondInternal(transport, null, null); + if (DBG) log("createBond()"); + final IBluetooth service = getService(); + if (service == null || !isBluetoothEnabled()) { + Log.w(TAG, "BT not enabled, createBond failed"); + if (DBG) log(Log.getStackTraceString(new Throwable())); + } else if (NULL_MAC_ADDRESS.equals(mAddress)) { + Log.e(TAG, "Unable to create bond, invalid address " + mAddress); + } else { + try { + return service.createBond(this, transport, mAttributionSource); + } catch (RemoteException e) { + Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable())); + } + } + return false; } /** @@ -1982,30 +1988,25 @@ public final class BluetoothDevice implements Parcelable, Attributable { * @hide */ @SystemApi - @RequiresPermission(BLUETOOTH_CONNECT) + @RequiresPermission(allOf = {BLUETOOTH_CONNECT, BLUETOOTH_PRIVILEGED}) public boolean createBondOutOfBand( int transport, @Nullable OobData remoteP192Data, @Nullable OobData remoteP256Data) { + if (DBG) log("createBondOutOfBand()"); + final IBluetooth service = getService(); + if (remoteP192Data == null && remoteP256Data == null) { throw new IllegalArgumentException( "One or both arguments for the OOB data types are required to not be null. " + " Please use createBond() instead if you do not have OOB data to pass."); } - return createBondInternal(transport, remoteP192Data, remoteP256Data); - } - - @RequiresPermission(BLUETOOTH_CONNECT) - private boolean createBondInternal( - int transport, @Nullable OobData remoteP192Data, @Nullable OobData remoteP256Data) { - if (DBG) log("createBondInternal()"); - final IBluetooth service = getService(); if (service == null || !isBluetoothEnabled()) { - Log.w(TAG, "BT not enabled, createBondInternal failed"); + Log.w(TAG, "BT not enabled, createBondOutOfBand failed"); if (DBG) log(Log.getStackTraceString(new Throwable())); } else if (NULL_MAC_ADDRESS.equals(mAddress)) { - Log.e(TAG, "Unable to create bond, invalid address " + mAddress); + Log.e(TAG, "Unable to create bond Out of Band, invalid address " + mAddress); } else { try { - return service.createBond( + return service.createBondOutOfBand( this, transport, remoteP192Data, remoteP256Data, mAttributionSource); } catch (RemoteException e) { Log.e(TAG, e.toString() + "\n" + Log.getStackTraceString(new Throwable())); @@ -3359,7 +3360,7 @@ public final class BluetoothDevice implements Parcelable, Attributable { int psm = settings.getL2capPsm(); if (settings.getSocketType() == BluetoothSocket.TYPE_RFCOMM) { if (settings.getRfcommUuid() == null) { - throw new IllegalArgumentException("null uuid: " + settings.getRfcommUuid()); + throw new IllegalArgumentException("null uuid"); } uuid = new ParcelUuid(settings.getRfcommUuid()); } else if (settings.getSocketType() == BluetoothSocket.TYPE_LE) { diff --git a/framework/java/android/bluetooth/BluetoothHearingAid.java b/framework/java/android/bluetooth/BluetoothHearingAid.java index 7e14057546..991efc3dc6 100644 --- a/framework/java/android/bluetooth/BluetoothHearingAid.java +++ b/framework/java/android/bluetooth/BluetoothHearingAid.java @@ -1,5 +1,5 @@ /* - * Copyright 2018 The Android Open Source Project + * Copyright (C) 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. diff --git a/framework/java/android/bluetooth/BluetoothLeBroadcast.java b/framework/java/android/bluetooth/BluetoothLeBroadcast.java index 85c895fa54..75aec6f996 100644 --- a/framework/java/android/bluetooth/BluetoothLeBroadcast.java +++ b/framework/java/android/bluetooth/BluetoothLeBroadcast.java @@ -1,5 +1,5 @@ /* - * Copyright 2021 The Android Open Source Project + * Copyright (C) 2021 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. @@ -459,7 +459,7 @@ public final class BluetoothLeBroadcast implements AutoCloseable, BluetoothProfi * Callback#onBroadcastStartFailed(int)} will be invoked with reason code. * * <p>In particular, when the number of Broadcast Sources reaches {@link - * #getMaximumNumberOfBroadcast()}, this method will fail with {@link + * #getMaximumNumberOfBroadcasts()}, this method will fail with {@link * BluetoothStatusCodes#ERROR_LOCAL_NOT_ENOUGH_RESOURCES} * * <p>After broadcast is started, {@link Callback#onBroadcastMetadataChanged(int, diff --git a/framework/java/android/bluetooth/BluetoothLeBroadcastAssistant.java b/framework/java/android/bluetooth/BluetoothLeBroadcastAssistant.java index d72fc1a50f..3c6cbed382 100644 --- a/framework/java/android/bluetooth/BluetoothLeBroadcastAssistant.java +++ b/framework/java/android/bluetooth/BluetoothLeBroadcastAssistant.java @@ -1,5 +1,5 @@ /* - * Copyright 2021 The Android Open Source Project + * Copyright (C) 2021 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. diff --git a/framework/java/android/bluetooth/BluetoothLeBroadcastChannel.java b/framework/java/android/bluetooth/BluetoothLeBroadcastChannel.java index 5149b19211..873edac288 100644 --- a/framework/java/android/bluetooth/BluetoothLeBroadcastChannel.java +++ b/framework/java/android/bluetooth/BluetoothLeBroadcastChannel.java @@ -1,5 +1,5 @@ /* - * Copyright 2022 The Android Open Source Project + * Copyright (C) 2022 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. diff --git a/framework/java/android/bluetooth/BluetoothLeBroadcastMetadata.java b/framework/java/android/bluetooth/BluetoothLeBroadcastMetadata.java index 562e0b7835..f40f4d7397 100644 --- a/framework/java/android/bluetooth/BluetoothLeBroadcastMetadata.java +++ b/framework/java/android/bluetooth/BluetoothLeBroadcastMetadata.java @@ -1,5 +1,5 @@ /* - * Copyright 2022 The Android Open Source Project + * Copyright (C) 2022 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. diff --git a/framework/java/android/bluetooth/BluetoothLeBroadcastReceiveState.java b/framework/java/android/bluetooth/BluetoothLeBroadcastReceiveState.java index 3fa4dcc7a3..a0ae67799c 100644 --- a/framework/java/android/bluetooth/BluetoothLeBroadcastReceiveState.java +++ b/framework/java/android/bluetooth/BluetoothLeBroadcastReceiveState.java @@ -1,5 +1,5 @@ /* - * Copyright 2022 The Android Open Source Project + * Copyright (C) 2022 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. diff --git a/framework/java/android/bluetooth/BluetoothLeBroadcastSettings.java b/framework/java/android/bluetooth/BluetoothLeBroadcastSettings.java index 48d53c4cb3..182780e6b9 100644 --- a/framework/java/android/bluetooth/BluetoothLeBroadcastSettings.java +++ b/framework/java/android/bluetooth/BluetoothLeBroadcastSettings.java @@ -1,5 +1,5 @@ /* - * Copyright 2023 The Android Open Source Project + * Copyright (C) 2023 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/framework/java/android/bluetooth/BluetoothLeBroadcastSubgroup.java b/framework/java/android/bluetooth/BluetoothLeBroadcastSubgroup.java index 5d150ed78c..cc87421e50 100644 --- a/framework/java/android/bluetooth/BluetoothLeBroadcastSubgroup.java +++ b/framework/java/android/bluetooth/BluetoothLeBroadcastSubgroup.java @@ -1,5 +1,5 @@ /* - * Copyright 2022 The Android Open Source Project + * Copyright (C) 2022 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. diff --git a/framework/java/android/bluetooth/BluetoothLeBroadcastSubgroupSettings.java b/framework/java/android/bluetooth/BluetoothLeBroadcastSubgroupSettings.java index d903435974..b355f43473 100644 --- a/framework/java/android/bluetooth/BluetoothLeBroadcastSubgroupSettings.java +++ b/framework/java/android/bluetooth/BluetoothLeBroadcastSubgroupSettings.java @@ -1,5 +1,5 @@ /* - * Copyright 2023 The Android Open Source Project + * Copyright (C) 2023 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/framework/java/android/bluetooth/BluetoothSinkAudioPolicy.java b/framework/java/android/bluetooth/BluetoothSinkAudioPolicy.java index 5a11a7fbe5..5ebffbd430 100644 --- a/framework/java/android/bluetooth/BluetoothSinkAudioPolicy.java +++ b/framework/java/android/bluetooth/BluetoothSinkAudioPolicy.java @@ -1,5 +1,5 @@ /* - * Copyright 2022 The Android Open Source Project + * Copyright (C) 2022 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. diff --git a/framework/java/android/bluetooth/BluetoothSocketSettings.java b/framework/java/android/bluetooth/BluetoothSocketSettings.java index 3f222d4717..04151ef3e6 100644 --- a/framework/java/android/bluetooth/BluetoothSocketSettings.java +++ b/framework/java/android/bluetooth/BluetoothSocketSettings.java @@ -1,5 +1,5 @@ /* - * Copyright 2024 The Android Open Source Project + * Copyright (C) 2024 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. diff --git a/framework/java/android/bluetooth/BluetoothUtils.java b/framework/java/android/bluetooth/BluetoothUtils.java index 2665af1bac..f944a6c57c 100644 --- a/framework/java/android/bluetooth/BluetoothUtils.java +++ b/framework/java/android/bluetooth/BluetoothUtils.java @@ -290,7 +290,7 @@ public final class BluetoothUtils { repl = Integer.toHexString(Byte.toUnsignedInt((byte) arg)); } else { throw new IllegalArgumentException( - "Unsupported hex type " + arg.getClass()); + "Unsupported hex type " + arg.getClass().getSimpleName()); } } case '%' -> { @@ -346,6 +346,22 @@ public final class BluetoothUtils { } } + /** A {@link Runnable} that automatically logs {@link RemoteException} @hide */ + @FunctionalInterface + public interface RemoteExceptionIgnoringRunnable { + /** Called by {@code accept}. */ + void runOrThrow() throws RemoteException; + + @RequiresNoPermission + default void run() { + try { + runOrThrow(); + } catch (RemoteException ex) { + logRemoteException(TAG, ex); + } + } + } + /** A {@link Consumer} that automatically logs {@link RemoteException} @hide */ @FunctionalInterface public interface RemoteExceptionIgnoringConsumer<T> { diff --git a/framework/java/android/bluetooth/le/BluetoothLeUtils.java b/framework/java/android/bluetooth/le/BluetoothLeUtils.java index b1821291fa..8e249394e4 100644 --- a/framework/java/android/bluetooth/le/BluetoothLeUtils.java +++ b/framework/java/android/bluetooth/le/BluetoothLeUtils.java @@ -152,9 +152,6 @@ public class BluetoothLeUtils { /** * Compares two UUIDs with a UUID mask. * - * @param data first {@link #UUID} to compare. - * @param uuid second {@link #UUID} to compare. - * @param mask mask {@link #UUID}. * @return true if both UUIDs are equals when masked, false otherwise. */ static boolean maskedEquals(UUID data, UUID uuid, UUID mask) { diff --git a/framework/java/android/bluetooth/le/ChannelSoundingParams.java b/framework/java/android/bluetooth/le/ChannelSoundingParams.java index cbaa01d0fb..aa0202a3be 100644 --- a/framework/java/android/bluetooth/le/ChannelSoundingParams.java +++ b/framework/java/android/bluetooth/le/ChannelSoundingParams.java @@ -1,5 +1,5 @@ /* - * Copyright 2024 The Android Open Source Project + * Copyright (C) 2024 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. diff --git a/framework/java/android/bluetooth/le/DistanceMeasurementManager.java b/framework/java/android/bluetooth/le/DistanceMeasurementManager.java index 6209e31946..3b3c1126ff 100644 --- a/framework/java/android/bluetooth/le/DistanceMeasurementManager.java +++ b/framework/java/android/bluetooth/le/DistanceMeasurementManager.java @@ -1,5 +1,5 @@ /* - * Copyright 2022 The Android Open Source Project + * Copyright (C) 2022 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. diff --git a/framework/java/android/bluetooth/le/DistanceMeasurementMethod.java b/framework/java/android/bluetooth/le/DistanceMeasurementMethod.java index 0d9f187889..a677f0e810 100644 --- a/framework/java/android/bluetooth/le/DistanceMeasurementMethod.java +++ b/framework/java/android/bluetooth/le/DistanceMeasurementMethod.java @@ -1,5 +1,5 @@ /* - * Copyright 2022 The Android Open Source Project + * Copyright (C) 2022 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. diff --git a/framework/java/android/bluetooth/le/DistanceMeasurementParams.java b/framework/java/android/bluetooth/le/DistanceMeasurementParams.java index 51a4a595a9..eadcd3078c 100644 --- a/framework/java/android/bluetooth/le/DistanceMeasurementParams.java +++ b/framework/java/android/bluetooth/le/DistanceMeasurementParams.java @@ -1,5 +1,5 @@ /* - * Copyright 2022 The Android Open Source Project + * Copyright (C) 2022 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. diff --git a/framework/java/android/bluetooth/le/DistanceMeasurementResult.java b/framework/java/android/bluetooth/le/DistanceMeasurementResult.java index 2292371e56..c757daa710 100644 --- a/framework/java/android/bluetooth/le/DistanceMeasurementResult.java +++ b/framework/java/android/bluetooth/le/DistanceMeasurementResult.java @@ -1,5 +1,5 @@ /* - * Copyright 2022 The Android Open Source Project + * Copyright (C) 2022 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. diff --git a/framework/java/android/bluetooth/le/DistanceMeasurementSession.java b/framework/java/android/bluetooth/le/DistanceMeasurementSession.java index 3241e68b59..e2dd181810 100644 --- a/framework/java/android/bluetooth/le/DistanceMeasurementSession.java +++ b/framework/java/android/bluetooth/le/DistanceMeasurementSession.java @@ -1,5 +1,5 @@ /* - * Copyright 2022 The Android Open Source Project + * Copyright (C) 2022 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. diff --git a/framework/java/android/bluetooth/le/TransportBlockFilter.java b/framework/java/android/bluetooth/le/TransportBlockFilter.java index 5da9bf658f..1a8418c691 100644 --- a/framework/java/android/bluetooth/le/TransportBlockFilter.java +++ b/framework/java/android/bluetooth/le/TransportBlockFilter.java @@ -1,5 +1,5 @@ /* - * Copyright 2023 The Android Open Source Project + * Copyright (C) 2023 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/framework/tests/bumble/src/android/bluetooth/GattClientTest.java b/framework/tests/bumble/src/android/bluetooth/GattClientTest.java index fa52d8c607..9b631dce91 100644 --- a/framework/tests/bumble/src/android/bluetooth/GattClientTest.java +++ b/framework/tests/bumble/src/android/bluetooth/GattClientTest.java @@ -510,6 +510,51 @@ public class GattClientTest { assertThat(resp.getStatus()).isEqualTo(AttStatusCode.SUCCESS); } + @Test + public void multipleGattClientsSeparateInteractions() throws Exception { + advertiseWithBumble(); + + BluetoothDevice device = + mAdapter.getRemoteLeDevice( + Utils.BUMBLE_RANDOM_ADDRESS, BluetoothDevice.ADDRESS_TYPE_RANDOM); + + BluetoothGattCallback gattCallbackA = mock(BluetoothGattCallback.class); + BluetoothGattCallback gattCallbackB = mock(BluetoothGattCallback.class); + InOrder inOrder = inOrder(gattCallbackA, gattCallbackB); + + BluetoothGatt gattA = device.connectGatt(mContext, false, gattCallbackA); + inOrder.verify(gattCallbackA, timeout(1000)) + .onConnectionStateChange(any(), anyInt(), eq(BluetoothProfile.STATE_CONNECTED)); + + BluetoothGatt gattB = device.connectGatt(mContext, false, gattCallbackB); + inOrder.verify(gattCallbackB, timeout(1000)) + .onConnectionStateChange(any(), anyInt(), eq(BluetoothProfile.STATE_CONNECTED)); + + gattA.disconnect(); + inOrder.verify(gattCallbackA, timeout(1000)) + .onConnectionStateChange(any(), anyInt(), eq(BluetoothProfile.STATE_DISCONNECTED)); + + gattA.connect(); + inOrder.verify(gattCallbackA, timeout(1000)) + .onConnectionStateChange(any(), anyInt(), eq(BluetoothProfile.STATE_CONNECTED)); + + gattB.disconnect(); + inOrder.verify(gattCallbackB, timeout(1000)) + .onConnectionStateChange(any(), anyInt(), eq(BluetoothProfile.STATE_DISCONNECTED)); + + gattB.close(); + + gattA.disconnect(); + inOrder.verify(gattCallbackA, timeout(1000)) + .onConnectionStateChange(any(), anyInt(), eq(BluetoothProfile.STATE_DISCONNECTED)); + + gattA.connect(); + inOrder.verify(gattCallbackA, timeout(1000)) + .onConnectionStateChange(any(), anyInt(), eq(BluetoothProfile.STATE_CONNECTED)); + + gattA.close(); + } + private void advertiseWithBumble() { AdvertiseRequest request = AdvertiseRequest.newBuilder() diff --git a/framework/tests/bumble/src/android/bluetooth/pairing/PairingWithDiscoveryTest.java b/framework/tests/bumble/src/android/bluetooth/pairing/PairingWithDiscoveryTest.java new file mode 100644 index 0000000000..ed5dfd0561 --- /dev/null +++ b/framework/tests/bumble/src/android/bluetooth/pairing/PairingWithDiscoveryTest.java @@ -0,0 +1,506 @@ +/* + * Copyright (C) 2025 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.bluetooth.pairing; + +import static com.google.common.truth.Truth.assertThat; + +import static org.mockito.Mockito.inOrder; +import static org.mockito.Mockito.timeout; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.doAnswer; + +import android.annotation.SuppressLint; +import android.bluetooth.BluetoothAdapter; +import android.bluetooth.BluetoothDevice; +import android.bluetooth.BluetoothManager; +import android.bluetooth.PandoraDevice; +import android.bluetooth.BluetoothDevice; +import android.bluetooth.Utils; +import android.bluetooth.StreamObserverSpliterator; +import com.android.bluetooth.flags.Flags; +import android.platform.test.annotations.RequiresFlagsEnabled; +import android.platform.test.flag.junit.CheckFlagsRule; +import android.platform.test.flag.junit.DeviceFlagsValueProvider; + +import static androidx.test.espresso.intent.matcher.IntentMatchers.hasAction; +import static androidx.test.espresso.intent.matcher.IntentMatchers.hasExtra; + +import android.content.BroadcastReceiver; +import android.content.Context; +import android.content.Intent; +import android.content.IntentFilter; +import android.util.Log; + +import androidx.test.core.app.ApplicationProvider; +import androidx.test.ext.junit.runners.AndroidJUnit4; + +import com.android.compatibility.common.util.AdoptShellPermissionsRule; + +import io.grpc.stub.StreamObserver; + +import org.hamcrest.Matcher; +import org.hamcrest.Matchers; +import org.hamcrest.core.AllOf; +import org.mockito.MockitoAnnotations; +import org.mockito.InOrder; +import org.mockito.hamcrest.MockitoHamcrest; +import org.mockito.Mock; +import org.mockito.stubbing.Answer; +import org.junit.After; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.runner.RunWith; + +import pandora.HostProto; +import pandora.HostProto.DiscoverabilityMode; +import pandora.HostProto.SetDiscoverabilityModeRequest; +import pandora.HostProto.ConnectabilityMode; +import pandora.HostProto.SetConnectabilityModeRequest; +import pandora.HostProto.AdvertiseRequest; +import pandora.HostProto.AdvertiseResponse; +import pandora.HostProto.OwnAddressType; +import pandora.SecurityProto.PairingEvent; +import pandora.SecurityProto.PairingEventAnswer; + +import java.util.HashMap; +import java.util.Map; +import java.util.Arrays; +import java.util.ArrayList; +import java.time.Duration; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.CompletableFuture; +import java.util.Set; + +/** Test cases for {@link PairingWithDiscoveryTest}. */ +@RunWith(AndroidJUnit4.class) +public class PairingWithDiscoveryTest { + private static final String TAG = PairingWithDiscoveryTest.class.getSimpleName(); + private static final String BUMBLE_DEVICE_NAME = "Bumble"; + private static final Duration BOND_INTENT_TIMEOUT = Duration.ofSeconds(10); + private static final int DISCOVERY_TIMEOUT = 2000; // 2 seconds + private static final int LE_GENERAL_DISCOVERABLE = 2; + + private final Context mContext = ApplicationProvider.getApplicationContext(); + private final BluetoothManager mManager = mContext.getSystemService(BluetoothManager.class); + private final BluetoothAdapter mAdapter = mManager.getAdapter(); + + private final Map<String, Integer> mActionRegistrationCounts = new HashMap<>(); + private final StreamObserverSpliterator<PairingEvent> mPairingEventStreamObserver = + new StreamObserverSpliterator<>(); + + @Rule(order = 0) + public final CheckFlagsRule mCheckFlagsRule = DeviceFlagsValueProvider.createCheckFlagsRule(); + + @Rule(order = 1) + public final AdoptShellPermissionsRule mPermissionRule = new AdoptShellPermissionsRule(); + + @Rule(order = 2) + public final PandoraDevice mBumble = new PandoraDevice(); + + private BluetoothDevice mBumbleDevice; + private InOrder mInOrder = null; + private CompletableFuture<BluetoothDevice> mDeviceFound; + @Mock private BroadcastReceiver mReceiver; + + @SuppressLint("MissingPermission") + private final Answer<Void> mIntentHandler = + inv -> { + Log.i(TAG, "onReceive(): intent=" + Arrays.toString(inv.getArguments())); + Intent intent = inv.getArgument(1); + String action = intent.getAction(); + switch (action) { + case BluetoothDevice.ACTION_FOUND: + BluetoothDevice device = + intent.getParcelableExtra( + BluetoothDevice.EXTRA_DEVICE, + BluetoothDevice.class); + String deviceName = + String.valueOf( + intent.getStringExtra(BluetoothDevice.EXTRA_NAME)); + Log.i( + TAG, + "Discovered device: " + + device + + " with name: " + + deviceName); + if (deviceName != null && BUMBLE_DEVICE_NAME.equals(deviceName) && + mDeviceFound != null) { + mDeviceFound.complete(device); + } + break; + default: + Log.i(TAG, "onReceive(): unknown intent action " + action); + break; + } + return null; + }; + + @Before + public void setUp() throws Exception { + MockitoAnnotations.initMocks(this); + doAnswer(mIntentHandler).when(mReceiver).onReceive(any(), any()); + + mInOrder = inOrder(mReceiver); + + mBumbleDevice = mBumble.getRemoteDevice(); + + for (BluetoothDevice device : mAdapter.getBondedDevices()) { + removeBond(device); + } + } + + @After + public void tearDown() throws Exception { + for (BluetoothDevice device : mAdapter.getBondedDevices()) { + removeBond(device); + } + mBumbleDevice = null; + if (getTotalActionRegistrationCounts() > 0) { + mContext.unregisterReceiver(mReceiver); + mActionRegistrationCounts.clear(); + } + } + + /** + * Test LE pairing flow with Auto transport + * + * <p>Prerequisites: + * + * <ol> + * <li>Bumble and Android are not bonded + * </ol> + * + * <p>Steps: + * + * <ol> + * <li>Bumble is non discoverable over BR/EDR and discoverable over LE + * <li>Bumble LE AD Flags in advertisement support dual mode + * <li>Android starts discovery of remote devices + * <li>Android initiates pairing with Bumble using Auto transport + * </ol> + * + * <p>Expectation: Pairing succeeds over LE Transport + */ + @Test + @RequiresFlagsEnabled({Flags.FLAG_AUTO_TRANSPORT_PAIRING}) + public void testBondLe_AutoTransport() throws Exception { + registerIntentActions( + BluetoothDevice.ACTION_BOND_STATE_CHANGED, + BluetoothDevice.ACTION_ACL_CONNECTED, + BluetoothDevice.ACTION_PAIRING_REQUEST); + + // Make Bumble Non discoverable over BR/EDR + mBumble.hostBlocking() + .setDiscoverabilityMode( + SetDiscoverabilityModeRequest.newBuilder() + .setMode(DiscoverabilityMode.NOT_DISCOVERABLE) + .build()); + + // Make Bumble Non connectable over BR/EDR + SetConnectabilityModeRequest request = + SetConnectabilityModeRequest.newBuilder() + .setMode(ConnectabilityMode.NOT_CONNECTABLE) + .build(); + mBumble.hostBlocking().setConnectabilityMode(request); + + // Start LE advertisement from Bumble + AdvertiseRequest.Builder requestBuilder = + AdvertiseRequest.newBuilder().setLegacy(true) + .setConnectable(true) + .setOwnAddressType(OwnAddressType.PUBLIC); + + HostProto.DataTypes.Builder dataTypeBuilder = HostProto.DataTypes.newBuilder(); + dataTypeBuilder.setCompleteLocalName(BUMBLE_DEVICE_NAME); + dataTypeBuilder.setIncludeCompleteLocalName(true); + //Set LE AD Flags to be LE General discoverable, also supports dual mode + dataTypeBuilder.setLeDiscoverabilityModeValue(LE_GENERAL_DISCOVERABLE); + requestBuilder.setData(dataTypeBuilder.build()); + + StreamObserverSpliterator<AdvertiseResponse> responseObserver = + new StreamObserverSpliterator<>(); + mBumble.host().advertise(requestBuilder.build(), responseObserver); + + // Start Device Discovery from Android + testStepStartDiscovery(); + + StreamObserver<PairingEventAnswer> pairingEventAnswerObserver = + mBumble.security() + .withDeadlineAfter(BOND_INTENT_TIMEOUT.toMillis(), + TimeUnit.MILLISECONDS) + .onPairing(mPairingEventStreamObserver); + + // Start pairing from Android with Auto transport + assertThat(mBumbleDevice.createBond(BluetoothDevice.TRANSPORT_AUTO)).isTrue(); + + verifyIntentReceived( + hasAction(BluetoothDevice.ACTION_BOND_STATE_CHANGED), + hasExtra(BluetoothDevice.EXTRA_DEVICE, mBumbleDevice), + hasExtra(BluetoothDevice.EXTRA_BOND_STATE, BluetoothDevice.BOND_BONDING)); + verifyIntentReceived( + hasAction(BluetoothDevice.ACTION_ACL_CONNECTED), + hasExtra(BluetoothDevice.EXTRA_DEVICE, mBumbleDevice), + hasExtra(BluetoothDevice.EXTRA_TRANSPORT, BluetoothDevice.TRANSPORT_LE)); + verifyIntentReceived( + hasAction(BluetoothDevice.ACTION_PAIRING_REQUEST), + hasExtra(BluetoothDevice.EXTRA_DEVICE, mBumbleDevice), + hasExtra( + BluetoothDevice.EXTRA_PAIRING_VARIANT, + BluetoothDevice.PAIRING_VARIANT_CONSENT)); + + // Approve pairing from Android + assertThat(mBumbleDevice.setPairingConfirmation(true)).isTrue(); + + PairingEvent pairingEvent = mPairingEventStreamObserver.iterator().next(); + assertThat(pairingEvent.hasJustWorks()).isTrue(); + pairingEventAnswerObserver.onNext( + PairingEventAnswer.newBuilder().setEvent(pairingEvent) + .setConfirm(true).build()); + + // Ensure that pairing succeeds + verifyIntentReceived( + hasAction(BluetoothDevice.ACTION_BOND_STATE_CHANGED), + hasExtra(BluetoothDevice.EXTRA_DEVICE, mBumbleDevice), + hasExtra(BluetoothDevice.EXTRA_BOND_STATE, BluetoothDevice.BOND_BONDED)); + + unregisterIntentActions( + BluetoothDevice.ACTION_BOND_STATE_CHANGED, + BluetoothDevice.ACTION_ACL_CONNECTED, + BluetoothDevice.ACTION_PAIRING_REQUEST); + } + + /** + * Test BR/EDR pairing flow with Auto transport + * + * <p>Prerequisites: + * + * <ol> + * <li>Bumble and Android are not bonded + * </ol> + * + * <p>Steps: + * + * <ol> + * <li>Bumble is discoverable over BR/EDR and non discoverable over LE + * <li>Android starts discovery of remote devices + * <li>Android initiates pairing with Bumble using Auto transport + * </ol> + * + * <p>Expectation: Pairing succeeds over BR/EDR Transport + */ + @Test + @RequiresFlagsEnabled({Flags.FLAG_AUTO_TRANSPORT_PAIRING}) + public void testBondBrEdr_AutoTransport() throws Exception { + registerIntentActions( + BluetoothDevice.ACTION_BOND_STATE_CHANGED, + BluetoothDevice.ACTION_ACL_CONNECTED, + BluetoothDevice.ACTION_PAIRING_REQUEST); + + // Make Bumble discoverable over BR/EDR + mBumble.hostBlocking() + .setDiscoverabilityMode( + SetDiscoverabilityModeRequest.newBuilder() + .setMode(DiscoverabilityMode.DISCOVERABLE_GENERAL) + .build()); + + SetConnectabilityModeRequest request = + SetConnectabilityModeRequest.newBuilder() + .setMode(ConnectabilityMode.CONNECTABLE) + .build(); + mBumble.hostBlocking().setConnectabilityMode(request); + + // Start Device Discovery from Android + testStepStartDiscovery(); + + StreamObserver<PairingEventAnswer> pairingEventAnswerObserver = + mBumble.security() + .withDeadlineAfter(BOND_INTENT_TIMEOUT.toMillis(), + TimeUnit.MILLISECONDS) + .onPairing(mPairingEventStreamObserver); + + // Start pairing from Android with Auto transport + assertThat(mBumbleDevice.createBond(BluetoothDevice.TRANSPORT_AUTO)).isTrue(); + + verifyIntentReceived( + hasAction(BluetoothDevice.ACTION_BOND_STATE_CHANGED), + hasExtra(BluetoothDevice.EXTRA_DEVICE, mBumbleDevice), + hasExtra(BluetoothDevice.EXTRA_BOND_STATE, BluetoothDevice.BOND_BONDING)); + verifyIntentReceived( + hasAction(BluetoothDevice.ACTION_ACL_CONNECTED), + hasExtra(BluetoothDevice.EXTRA_DEVICE, mBumbleDevice), + hasExtra(BluetoothDevice.EXTRA_TRANSPORT, BluetoothDevice.TRANSPORT_BREDR)); + verifyIntentReceived( + hasAction(BluetoothDevice.ACTION_PAIRING_REQUEST), + hasExtra(BluetoothDevice.EXTRA_DEVICE, mBumbleDevice), + hasExtra( + BluetoothDevice.EXTRA_PAIRING_VARIANT, + BluetoothDevice.PAIRING_VARIANT_CONSENT)); + + // Approve pairing from Android + assertThat(mBumbleDevice.setPairingConfirmation(true)).isTrue(); + + PairingEvent pairingEvent = mPairingEventStreamObserver.iterator().next(); + assertThat(pairingEvent.hasJustWorks()).isTrue(); + pairingEventAnswerObserver.onNext( + PairingEventAnswer.newBuilder().setEvent(pairingEvent).setConfirm(true).build()); + + // Ensure that pairing succeeds + verifyIntentReceived( + hasAction(BluetoothDevice.ACTION_BOND_STATE_CHANGED), + hasExtra(BluetoothDevice.EXTRA_DEVICE, mBumbleDevice), + hasExtra(BluetoothDevice.EXTRA_BOND_STATE, BluetoothDevice.BOND_BONDED)); + + unregisterIntentActions( + BluetoothDevice.ACTION_BOND_STATE_CHANGED, + BluetoothDevice.ACTION_ACL_CONNECTED, + BluetoothDevice.ACTION_PAIRING_REQUEST); + } + + /** Helper/testStep functions go here */ + /** + * Helper function to start device discovery + * + * <p>Steps: + * + * <ol> + * <li>Android starts discovery of remote devices + * </ol> + * + * <p>Expectation: + * + * <ol> + * <li>Android receives discovery started intent + * <li>Android receives discovery finished intent + * <li>Checks whether Bumble device was found + * </ol> + */ + private void testStepStartDiscovery() throws Exception { + registerIntentActions(BluetoothDevice.ACTION_FOUND); + mBumbleDevice = null; + + // Start device discovery from Android + mDeviceFound = new CompletableFuture<>(); + assertThat(mAdapter.startDiscovery()).isTrue(); + mBumbleDevice = + mDeviceFound + .completeOnTimeout(null, DISCOVERY_TIMEOUT, TimeUnit.MILLISECONDS) + .join(); + assertThat(mBumbleDevice).isNotNull(); + assertThat(mAdapter.cancelDiscovery()).isTrue(); + + unregisterIntentActions(BluetoothDevice.ACTION_FOUND); + } + + @SafeVarargs + private void verifyIntentReceived(Matcher<Intent>... matchers) { + mInOrder.verify(mReceiver, timeout(BOND_INTENT_TIMEOUT.toMillis())) + .onReceive(any(Context.class), MockitoHamcrest.argThat(AllOf.allOf(matchers))); + } + + private void removeBond(BluetoothDevice device) { + IntentFilter filter = new IntentFilter(BluetoothDevice.ACTION_BOND_STATE_CHANGED); + mContext.registerReceiver(mReceiver, filter); + + assertThat(device.removeBond()).isTrue(); + verifyIntentReceived( + hasAction(BluetoothDevice.ACTION_BOND_STATE_CHANGED), + hasExtra(BluetoothDevice.EXTRA_DEVICE, device), + hasExtra(BluetoothDevice.EXTRA_BOND_STATE, BluetoothDevice.BOND_NONE)); + + mContext.unregisterReceiver(mReceiver); + } + + /** + * Helper function to add reference count to registered intent actions + * + * @param actions new intent actions to add. If the array is empty, it is a no-op. + */ + private void registerIntentActions(String... actions) { + if (actions.length == 0) { + return; + } + if (getTotalActionRegistrationCounts() > 0) { + Log.d(TAG, "registerIntentActions(): unregister ALL intents"); + mContext.unregisterReceiver(mReceiver); + } + for (String action : actions) { + mActionRegistrationCounts.merge(action, 1, Integer::sum); + } + IntentFilter filter = new IntentFilter(); + mActionRegistrationCounts.entrySet().stream() + .filter(entry -> entry.getValue() > 0) + .forEach( + entry -> { + Log.d( + TAG, + "registerIntentActions(): Registering action = " + + entry.getKey()); + filter.addAction(entry.getKey()); + }); + mContext.registerReceiver(mReceiver, filter); + } + + /** + * Helper function to reduce reference count to registered intent actions If total reference + * count is zero after removal, no broadcast receiver will be registered. + * + * @param actions intent actions to be removed. If some action is not registered, it is no-op + * for that action. If the actions array is empty, it is also a no-op. + */ + private void unregisterIntentActions(String... actions) { + if (actions.length == 0) { + return; + } + if (getTotalActionRegistrationCounts() <= 0) { + return; + } + Log.d(TAG, "unregisterIntentActions(): unregister ALL intents"); + mContext.unregisterReceiver(mReceiver); + for (String action : actions) { + if (!mActionRegistrationCounts.containsKey(action)) { + continue; + } + mActionRegistrationCounts.put(action, mActionRegistrationCounts.get(action) - 1); + if (mActionRegistrationCounts.get(action) <= 0) { + mActionRegistrationCounts.remove(action); + } + } + if (getTotalActionRegistrationCounts() > 0) { + IntentFilter filter = new IntentFilter(); + mActionRegistrationCounts.entrySet().stream() + .filter(entry -> entry.getValue() > 0) + .forEach( + entry -> { + Log.d( + TAG, + "unregisterIntentActions(): Registering action = " + + entry.getKey()); + filter.addAction(entry.getKey()); + }); + mContext.registerReceiver(mReceiver, filter); + } + } + + /** + * Get sum of reference count from all registered actions + * + * @return sum of reference count from all registered actions + */ + private int getTotalActionRegistrationCounts() { + return mActionRegistrationCounts.values().stream().reduce(0, Integer::sum); + } +}
\ No newline at end of file diff --git a/framework/tests/bumble/src/android/bluetooth/sockets/lecoc/DckL2capTest.kt b/framework/tests/bumble/src/android/bluetooth/sockets/lecoc/DckL2capTest.kt index 145993ec1a..5caa19bf40 100644 --- a/framework/tests/bumble/src/android/bluetooth/sockets/lecoc/DckL2capTest.kt +++ b/framework/tests/bumble/src/android/bluetooth/sockets/lecoc/DckL2capTest.kt @@ -190,6 +190,28 @@ public class DckL2capTest() : Closeable { @VirtualOnly /** * Test: + * - Create L2CAP server on Bumble (DCK L2cap Server) + * - create insecure Client Bluetooth Socket & initiate connection on phone + * - Ensure socket is connected + * - Initiate disconnection from Bumble side + */ + fun testConnectInsecureClientRemoteDisconnect() { + Log.d(TAG, "testConnectInsecureClientRemoteDisconnect") + val (bluetoothSocket, channel) = clientSocketConnectUtil(false) + + assertThat((bluetoothSocket).isConnected()).isTrue() + Log.d(TAG, "testConnectInsecureClientRemoteDisconnect: close/disconnect") + disconnectSocketAndWaitForDisconnectUtil(bluetoothSocket, channel, true) + + // Todo: b/401106684 + // assertThat((bluetoothSocket).isConnected()).isFalse() + Log.d(TAG, "testConnectInsecureClientRemoteDisconnect: done") + } + + @Test + @VirtualOnly + /** + * Test: * - Create insecure L2CAP Socket server on Phone * - Use Bumble as client and trigger connection to L2cap server on Phone * - Ensure connection is established @@ -229,6 +251,30 @@ public class DckL2capTest() : Closeable { @VirtualOnly /** * Test: + * - Create insecure L2CAP Socket server on Phone + * - Use Bumble as client nd trigger connection to L2cap server on Phone + * - Ensure connection is established + * - trigger disconnection by closing the socket handle from Bumble/Remote side + * - Ensure L2cap connection is disconnected + */ + fun testAcceptInsecureRemoteDisconnect() { + Log.d(TAG, "testAcceptInsecureRemoteDisconnect: Connect L2CAP") + val (l2capServer, bluetoothSocket, channel) = + l2capServerOnPhoneAndConnectionFromBumbleUtil(false) + Log.d(TAG, "testAcceptInsecureRemoteDisconnect: close/disconnect from remote") + disconnectSocketAndWaitForDisconnectUtil(bluetoothSocket, channel, true) + + // Todo: b/401106684 + // assertThat((bluetoothSocket)?.isConnected()).isFalse() + + l2capServer.close() + Log.d(TAG, "testAcceptInsecureRemoteDisconnect: done") + } + + @Test + @VirtualOnly + /** + * Test: * - Create L2CAP Socket server on Bumble (DCK server) * - create insecure l2cap client and connect to l2cap on Bumble server * - Ensure connection is established @@ -419,6 +465,44 @@ public class DckL2capTest() : Closeable { Log.d(TAG, "testSendOverEncryptedOnlySocket: done") } + @Test + @RequiresFlagsEnabled(Flags.FLAG_SOCKET_SETTINGS_API) + /** + * Test: + * - Create Bond between Phone and Bumble (Just works) + * - Create L2cap Server on Bumble side (DCK server) and wait for connection + * - Create Encrypt Only socket using BluetoothSocketSettings interface + * - trigger connection from client socket on phone to l2cap server on Bumble + * - Ensure connection is established + * - Send sample data from Bumble to phone & ensure It is received on bumble side as expected + * - close the connection + * - Ensure L2cap connection is disconnected and Socket state is disconnected + * - remote bonding + */ + fun testReceiveOverEncryptedOnlySocketAsClient() { + Log.d(TAG, "testReceiveOverEncryptedOnlySocketAsClient") + val remoteDevice = + bluetoothAdapter.getRemoteLeDevice( + Utils.BUMBLE_RANDOM_ADDRESS, + BluetoothDevice.ADDRESS_TYPE_RANDOM, + ) + + host.createBondAndVerify(remoteDevice) + + Log.d(TAG, "testReceiveOverEncryptedOnlySocketAsClient: Connect L2CAP") + val (bluetoothSocket, channel) = clientSocketConnectUtilUsingSocketSettings(false, true) + + Log.d(TAG, "testReceiveOverEncryptedOnlySocketAsClient: send data from phone to bumble") + sendDataFromBumbleToPhoneAndVerifyUtil(bluetoothSocket, channel) + + // disconnect from local + disconnectSocketAndWaitForDisconnectUtil(bluetoothSocket, channel) + assertThat((bluetoothSocket).isConnected()).isFalse() + + host.removeBondAndVerify(remoteDevice) + Log.d(TAG, "testReceiveOverEncryptedOnlySocketAsClient: done") + } + // Utility functions private fun clientSocketConnectUtil(isSecure: Boolean = false): Pair<BluetoothSocket, Channel> { val remoteDevice = diff --git a/framework/tests/bumble/src/android/bluetooth/RfcommTest.kt b/framework/tests/bumble/src/android/bluetooth/sockets/rfcomm/RfcommTest.kt index bf382ba159..acbd097b25 100644 --- a/framework/tests/bumble/src/android/bluetooth/RfcommTest.kt +++ b/framework/tests/bumble/src/android/bluetooth/sockets/rfcomm/RfcommTest.kt @@ -13,11 +13,23 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package android.bluetooth +package android.bluetooth.sockets.rfcomm import android.Manifest import android.annotation.SuppressLint +import android.bluetooth.BluetoothA2dp +import android.bluetooth.BluetoothAdapter +import android.bluetooth.BluetoothDevice +import android.bluetooth.BluetoothHeadset +import android.bluetooth.BluetoothHidHost +import android.bluetooth.BluetoothManager +import android.bluetooth.BluetoothProfile import android.bluetooth.BluetoothProfile.CONNECTION_POLICY_FORBIDDEN +import android.bluetooth.BluetoothServerSocket +import android.bluetooth.BluetoothSocket +import android.bluetooth.BluetoothSocketSettings +import android.bluetooth.Host +import android.bluetooth.PandoraDevice import android.bluetooth.test_utils.EnableBluetoothRule import android.content.BroadcastReceiver import android.content.Context @@ -119,13 +131,13 @@ class RfcommTest { mFlow = intentFlow(mContext, intentFilter, mScope).shareIn(mScope, SharingStarted.Eagerly) } - /* - Setup: - 1. Initialize host and mRemoteDevice - 2. Override pairing config to enable insecure tests - 3. Disable A2DP, HFP, and HID profiles - 4. Disconnect devices, if they are connected - */ + /** + * Setup: + * - Initialize host and mRemoteDevice + * - Override pairing config (allows insecure tests to run) + * - Disable A2DP, HFP, and HID profiles + * - Disconnect devices, if they are connected + */ @Before fun setUp() { mRemoteDevice = mBumble.remoteDevice @@ -143,11 +155,11 @@ class RfcommTest { } } - /* - TearDown: - 1. remove bond - 2. shutdown host - */ + /** + * TearDown: + * - Remove Bond + * - Shutdown host + */ @After fun tearDown() { if (Settings.Global.getInt(mContext.contentResolver, BLE_SCAN_ALWAYS_AVAILABLE, 0) == 1) { @@ -160,38 +172,38 @@ class RfcommTest { mHost.close() } - /* - Test Steps: - 1. Create an insecure socket - 2. Connect to the socket - 3. Verify that devices are connected. - */ + /** + * Test Steps: + * - Create an insecure socket + * - Connect to the socket + * - Verify that devices are connected. + */ @Test fun clientConnectToOpenServerSocketInsecure() { updateSecurityConfig() startServer { serverId -> createConnectAcceptSocket(isSecure = false, serverId) } } - /* - Test Steps: - 1. Create an secure socket - 2. Connect to the socket - 3. Verify that devices are connected. - */ + /** + * Test Steps: + * - Create an secure socket + * - Connect to the socket + * - Verify that devices are connected. + */ @Test fun clientConnectToOpenServerSocketSecure() { updateSecurityConfig() startServer { serverId -> createConnectAcceptSocket(isSecure = true, serverId) } } - /* - Test Steps: - 1. Create an insecure socket - 2. Connect to the socket - 3. Verify that devices are connected - 4. Write data to socket output stream - 5. Verify bumble received that data - */ + /** + * Test Steps: + * - Create an insecure socket + * - Connect to the socket + * - Verify that devices are connected + * - Write data to socket output stream + * - Verify bumble received that data + */ @Test fun clientSendDataOverInsecureSocket() { updateSecurityConfig() @@ -210,14 +222,14 @@ class RfcommTest { } } - /* - Test Steps: - 1. Create a secure socket - 2. Connect to the socket - 3. Verify that devices are connected - 4. Write data to socket output stream - 5. Verify remote device received that data - */ + /** + * Test Steps: + * - Create a secure socket + * - Connect to the socket + * - Verify that devices are connected + * - Write data to socket output stream + * - Verify remote device received that data + */ @Test fun clientSendDataOverSecureSocket() { updateSecurityConfig() @@ -236,14 +248,14 @@ class RfcommTest { } } - /* - Test Steps: - 1. Create an insecure socket - 2. Connect to the socket - 3. Verify that devices are connected - 4. Send data from remote device - 5. Read and verify data from socket input stream - */ + /** + * Test Steps: + * - Create an insecure socket + * - Connect to the socket + * - Verify that devices are connected + * - Send data from remote device + * - Read and verify data from socket input stream + */ @Test fun clientReceiveDataOverInsecureSocket() { updateSecurityConfig() @@ -263,14 +275,14 @@ class RfcommTest { } } - /* - Test Steps: - 1. Create a secure socket - 2. Connect to the socket - 3. Verify that devices are connected - 4. Send data from remote device - 5. Read and verify data from socket input stream - */ + /** + * Test Steps: + * - Create a secure socket + * - Connect to the socket + * - Verify that devices are connected + * - Send data from remote device + * - Read and verify data from socket input stream + */ @Test fun clientReceiveDataOverSecureSocket() { updateSecurityConfig() @@ -290,15 +302,15 @@ class RfcommTest { } } - /* - Test Steps: - 1. Create insecure socket 1 - 2. Create insecure socket 2 - 3. Remote device initiates connection to socket 1 - 4. Remote device initiates connection to socket 2 - 5. Accept socket 1 and verify connection - 6. Accept socket 2 and verify connection - */ + /** + * Test Steps: + * - Create insecure socket 1 + * - Create insecure socket 2 + * - Remote device initiates connection to socket 1 + * - Remote device initiates connection to socket 2 + * - Accept socket 1 and verify connection + * - Accept socket 2 and verify connection + */ @Test fun connectTwoInsecureClientsSimultaneously() { updateSecurityConfig() @@ -316,13 +328,13 @@ class RfcommTest { } } - /* - Test Steps: - 1. Create insecure socket 1 - 2. Remote device initiates connection to socket 1 - 3. Accept socket 1 and verify connection - 4. Repeat for socket 2 - */ + /** + * Test Steps: + * - Create insecure socket 1 + * - Remote device initiates connection to socket 1 + * - Accept socket 1 and verify connection + * - Repeat for socket 2 + */ @Test fun connectTwoInsecureClientsSequentially() { updateSecurityConfig() @@ -339,15 +351,15 @@ class RfcommTest { } } - /* - Test Steps: - 1. Create secure socket 1 - 2. Create secure socket 2 - 3. Remote device initiates connection to socket 1 - 4. Remote device initiates connection to socket 2 - 5. Accept socket 1 and verify connection - 6. Accept socket 2 and verify connection - */ + /** + * Test Steps: + * - Create secure socket 1 + * - Create secure socket 2 + * - Remote device initiates connection to socket 1 + * - Remote device initiates connection to socket 2 + * - Accept socket 1 and verify connection + * - Accept socket 2 and verify connection + */ @Test fun connectTwoSecureClientsSimultaneously() { updateSecurityConfig() @@ -365,13 +377,13 @@ class RfcommTest { } } - /* - Test Steps: - 1. Create insecure socket 1 - 2. Remote device initiates connection to socket 1 - 3. Accept socket 1 and verify connection - 4. Repeat for socket 2 - */ + /** + * Test Steps: + * - Create insecure socket 1 + * - Remote device initiates connection to socket 1 + * - Accept socket 1 and verify connection + * - Repeat for socket 2 + */ @Test fun connectTwoSecureClientsSequentially() { updateSecurityConfig() @@ -388,13 +400,13 @@ class RfcommTest { } } - /* - Test Steps: - 1. Create insecure socket 1 - 2. Remote device initiates connection to socket 1 - 3. Accept socket 1 and verify connection - 4. Repeat for secure socket 2 - */ + /** + * Test Steps: + * - Create insecure socket 1 + * - Remote device initiates connection to socket 1 + * - Accept socket 1 and verify connection + * - Repeat for secure socket 2 + */ @Test @Ignore("b/380091558") fun connectTwoMixedClientsInsecureThenSecure() { @@ -412,13 +424,13 @@ class RfcommTest { } } - /* - Test Steps: - 1. Create secure socket 2 - 2. Remote device initiates connection to socket 2 - 3. Accept socket 2 and verify connection - 4. Repeat for insecure socket 1 - */ + /** + * Test Steps: + * - Create secure socket 2 + * - Remote device initiates connection to socket 2 + * - Accept socket 2 and verify connection + * - Repeat for insecure socket 1 + */ @Test fun connectTwoMixedClientsSecureThenInsecure() { updateSecurityConfig() @@ -435,11 +447,11 @@ class RfcommTest { } } - /* - Test Steps: - 1. Create listening socket and connect - 2. Disconnect RFCOMM from remote device - */ + /** + * Test Steps: + * - Create listening socket and connect + * - Disconnect RFCOMM from remote device + */ @RequiresFlagsEnabled(Flags.FLAG_TRIGGER_SEC_PROC_ON_INC_ACCESS_REQ) @Test fun serverSecureConnectThenRemoteDisconnect() { @@ -453,11 +465,11 @@ class RfcommTest { Truth.assertThat(serverSock.channel).isEqualTo(-1) // ensure disconnected at RFCOMM Layer } - /* - Test Steps: - 1. Create listening socket and connect - 2. Disconnect RFCOMM from local device - */ + /** + * Test Steps: + * - Create listening socket and connect + * - Disconnect RFCOMM from local device + */ @RequiresFlagsEnabled(Flags.FLAG_TRIGGER_SEC_PROC_ON_INC_ACCESS_REQ) @Test fun serverSecureConnectThenLocalDisconnect() { @@ -469,16 +481,16 @@ class RfcommTest { Truth.assertThat(serverSock.channel).isEqualTo(-1) // ensure disconnected at RFCOMM Layer } - /* - Test Steps: - 1. Disable inquiry and page scan - 2. Create RFCOMM socket - 3. Attempt to connect to socket: expect not connected - 4. Wait 3 seconds - 5. Before page timeout of 5 seconds, close the socket - 6. Enable page scan - 7. Create and connect to an RFCOMM socket - verify proper connection - */ + /** + * Test Steps: + * - Disable inquiry and page scan + * - Create RFCOMM socket + * - Attempt to connect to socket: expect not connected + * - Wait 3 seconds + * - Before page timeout of 5 seconds, close the socket + * - Enable page scan + * - Create and connect to an RFCOMM socket - verify proper connection + */ @RequiresFlagsEnabled(Flags.FLAG_RFCOMM_CANCEL_ONGOING_SDP_ON_CLOSE) @Test fun clientConnectToOpenServerSocketAfterPageTimeout() { @@ -531,14 +543,14 @@ class RfcommTest { startServer { serverId -> createConnectAcceptSocket(isSecure = false, serverId) } } - /* - Test Steps: - 1. Create an insecure socket - 2. Connect to the socket - 3. Verify that devices are connected - 4. Write data to socket output stream - 5. Verify bumble received that data - */ + /** + * Test Steps: + * - Create an insecure socket + * - Connect to the socket + * - Verify that devices are connected + * - Write data to socket output stream + * - Verify bumble received that data + */ @Test @RequiresFlagsEnabled(Flags.FLAG_SOCKET_SETTINGS_API) fun clientSendDataOverInsecureSocketUsingSocketSettings() { @@ -559,14 +571,14 @@ class RfcommTest { } } - /* - Test Steps: - 1. Create an encrypt only socket - 2. Connect to the socket - 3. Verify that devices are connected - 4. Write data to socket output stream - 5. Verify bumble received that data - */ + /** + * Test Steps: + * - Create an encrypt only socket + * - Connect to the socket + * - Verify that devices are connected + * - Write data to socket output stream + * - Verify bumble received that data + */ @Test @RequiresFlagsEnabled(Flags.FLAG_SOCKET_SETTINGS_API) fun clientSendDataOverEncryptedOnlySocketUsingSocketSettings() { @@ -590,14 +602,14 @@ class RfcommTest { } } - /* - Test Steps: - 1. Create an secure socket - 2. Connect to the socket - 3. Verify that devices are connected - 4. Write data to socket output stream - 5. Verify bumble received that data - */ + /** + * Test Steps: + * - Create an secure socket + * - Connect to the socket + * - Verify that devices are connected + * - Write data to socket output stream + * - Verify bumble received that data + */ @Test @RequiresFlagsEnabled(Flags.FLAG_SOCKET_SETTINGS_API) fun clientSendDataOverSecureSocketUsingSocketSettings() { @@ -619,13 +631,13 @@ class RfcommTest { } } - /* - Test Steps: - 1. Create an Rfcomm insecure socket - 2. Verify that Rfcomm socket is connected - 3. Disable Bluetooth to BLE_ON mode - 4. Verify remote devices disconnected based on successful data transmission - */ + /** + * Test Steps: + * - Create an Rfcomm insecure socket + * - Verify that Rfcomm socket is connected + * - Disable Bluetooth to BLE_ON mode + * - Verify remote devices disconnected based on successful data transmission + */ @Test @RequiresFlagsEnabled(Flags.FLAG_DISCONNECT_ACLS_BY_BREDR_DISABLED) fun clientRfcommDeviceDisconnectedOnBleOnMode() { @@ -719,18 +731,6 @@ class RfcommTest { return Pair(socket, connection) } - private fun createConnectAcceptSocket( - isSecure: Boolean, - server: ServerId, - uuid: String = TEST_UUID, - ): Pair<BluetoothSocket, RfcommProto.RfcommConnection> { - val socket = createSocket(mRemoteDevice, isSecure, uuid) - val connection = acceptSocket(server) - Truth.assertThat(socket.isConnected).isTrue() - - return Pair(socket, connection) - } - private fun createClientSocketUsingSocketSettings( uuid: String, remoteDevice: BluetoothDevice, @@ -818,6 +818,18 @@ class RfcommTest { return connectionResponse.connection } + private fun createConnectAcceptSocket( + isSecure: Boolean, + server: ServerId, + uuid: String = TEST_UUID, + ): Pair<BluetoothSocket, RfcommProto.RfcommConnection> { + val socket = createSocket(mRemoteDevice, isSecure, uuid) + val connection = acceptSocket(server) + Truth.assertThat(socket.isConnected).isTrue() + + return Pair(socket, connection) + } + private fun startServer( name: String = TEST_SERVER_NAME, uuid: String = TEST_UUID, diff --git a/framework/tests/unit/src/android/bluetooth/BluetoothActivityEnergyInfoTest.java b/framework/tests/unit/src/android/bluetooth/BluetoothActivityEnergyInfoTest.java index eb8e074953..fdb8bd9f25 100644 --- a/framework/tests/unit/src/android/bluetooth/BluetoothActivityEnergyInfoTest.java +++ b/framework/tests/unit/src/android/bluetooth/BluetoothActivityEnergyInfoTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2022 The Android Open Source Project + * Copyright (C) 2022 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. diff --git a/framework/tests/unit/src/android/bluetooth/BluetoothAudioConfigTest.java b/framework/tests/unit/src/android/bluetooth/BluetoothAudioConfigTest.java index 2360dcad14..49f0f745b6 100644 --- a/framework/tests/unit/src/android/bluetooth/BluetoothAudioConfigTest.java +++ b/framework/tests/unit/src/android/bluetooth/BluetoothAudioConfigTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2022 The Android Open Source Project + * Copyright (C) 2022 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. diff --git a/framework/tests/unit/src/android/bluetooth/BluetoothCodecConfigTest.java b/framework/tests/unit/src/android/bluetooth/BluetoothCodecConfigTest.java index 316ef1f109..d2ca867f01 100644 --- a/framework/tests/unit/src/android/bluetooth/BluetoothCodecConfigTest.java +++ b/framework/tests/unit/src/android/bluetooth/BluetoothCodecConfigTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2018 The Android Open Source Project + * Copyright (C) 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. diff --git a/framework/tests/unit/src/android/bluetooth/BluetoothCodecStatusTest.java b/framework/tests/unit/src/android/bluetooth/BluetoothCodecStatusTest.java index 85422f568a..25b1812bf5 100644 --- a/framework/tests/unit/src/android/bluetooth/BluetoothCodecStatusTest.java +++ b/framework/tests/unit/src/android/bluetooth/BluetoothCodecStatusTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2018 The Android Open Source Project + * Copyright (C) 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. diff --git a/framework/tests/unit/src/android/bluetooth/BluetoothDeviceTest.java b/framework/tests/unit/src/android/bluetooth/BluetoothDeviceTest.java index 55263c4400..d173645914 100644 --- a/framework/tests/unit/src/android/bluetooth/BluetoothDeviceTest.java +++ b/framework/tests/unit/src/android/bluetooth/BluetoothDeviceTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2024 The Android Open Source Project + * Copyright (C) 2024 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. diff --git a/framework/tests/unit/src/android/bluetooth/CallbackWrapperTest.java b/framework/tests/unit/src/android/bluetooth/CallbackWrapperTest.java index 0721ead366..15dad9ca3b 100644 --- a/framework/tests/unit/src/android/bluetooth/CallbackWrapperTest.java +++ b/framework/tests/unit/src/android/bluetooth/CallbackWrapperTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2024 The Android Open Source Project + * Copyright (C) 2024 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. diff --git a/framework/tests/unit/src/android/bluetooth/SdpDipRecordTest.java b/framework/tests/unit/src/android/bluetooth/SdpDipRecordTest.java index b8a0d48f66..380ef9d34f 100644 --- a/framework/tests/unit/src/android/bluetooth/SdpDipRecordTest.java +++ b/framework/tests/unit/src/android/bluetooth/SdpDipRecordTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2022 The Android Open Source Project + * Copyright (C) 2022 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. diff --git a/framework/tests/unit/src/android/bluetooth/SdpMnsRecordTest.java b/framework/tests/unit/src/android/bluetooth/SdpMnsRecordTest.java index 5e686d1bfc..d314a959c3 100644 --- a/framework/tests/unit/src/android/bluetooth/SdpMnsRecordTest.java +++ b/framework/tests/unit/src/android/bluetooth/SdpMnsRecordTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2022 The Android Open Source Project + * Copyright (C) 2022 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. diff --git a/framework/tests/unit/src/android/bluetooth/SdpOppOpsRecordTest.java b/framework/tests/unit/src/android/bluetooth/SdpOppOpsRecordTest.java index dcff94073d..8ab38cbb19 100644 --- a/framework/tests/unit/src/android/bluetooth/SdpOppOpsRecordTest.java +++ b/framework/tests/unit/src/android/bluetooth/SdpOppOpsRecordTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2022 The Android Open Source Project + * Copyright (C) 2022 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. diff --git a/framework/tests/unit/src/android/bluetooth/SdpPseRecordTest.java b/framework/tests/unit/src/android/bluetooth/SdpPseRecordTest.java index c9eeaa2940..1f1ce64540 100644 --- a/framework/tests/unit/src/android/bluetooth/SdpPseRecordTest.java +++ b/framework/tests/unit/src/android/bluetooth/SdpPseRecordTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2022 The Android Open Source Project + * Copyright (C) 2022 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. diff --git a/framework/tests/unit/src/android/bluetooth/SdpRecordTest.java b/framework/tests/unit/src/android/bluetooth/SdpRecordTest.java index f7afe42688..74fc82bef4 100644 --- a/framework/tests/unit/src/android/bluetooth/SdpRecordTest.java +++ b/framework/tests/unit/src/android/bluetooth/SdpRecordTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2022 The Android Open Source Project + * Copyright (C) 2022 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. diff --git a/framework/tests/unit/src/android/bluetooth/SdpSapsRecordTest.java b/framework/tests/unit/src/android/bluetooth/SdpSapsRecordTest.java index eedfb9ac64..5316bc915f 100644 --- a/framework/tests/unit/src/android/bluetooth/SdpSapsRecordTest.java +++ b/framework/tests/unit/src/android/bluetooth/SdpSapsRecordTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2022 The Android Open Source Project + * Copyright (C) 2022 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. diff --git a/service/Android.bp b/service/Android.bp index 1532b89d3c..4b608dd4b3 100644 --- a/service/Android.bp +++ b/service/Android.bp @@ -72,7 +72,6 @@ java_library { static_libs: [ "androidx.annotation_annotation", "androidx.appcompat_appcompat", - "bluetooth-manager-service-proto-java-gen", "bluetooth-nano-protos", "bluetooth-proto-enums-java-gen", "bluetooth_flags_java_lib", @@ -121,21 +120,6 @@ java_library { } java_library { - name: "bluetooth-manager-service-proto-java-gen", - srcs: [":srcs_bluetooth_manager_service_proto"], - installable: false, - - proto: { - type: "stream", - include_dirs: ["external/protobuf/src"], - }, - - sdk_version: "system_server_current", - min_sdk_version: "Tiramisu", - apex_available: ["com.android.bt"], -} - -java_library { name: "bluetooth-nano-protos", srcs: [":system-messages-proto-src"], installable: false, @@ -183,7 +167,6 @@ android_robolectric_test { static_libs: [ "androidx.test.core", "androidx.test.ext.truth", - "bluetooth-manager-service-proto-java-gen", "bluetooth-nano-protos", "bluetooth-proto-enums-java-gen", "bluetooth_flags_java_lib", diff --git a/service/kls-classpath b/service/kls-classpath index 94c74875ad..3ea610246d 100755 --- a/service/kls-classpath +++ b/service/kls-classpath @@ -16,7 +16,6 @@ CLASSPATH+=":$ROOT/out/soong/.intermediates/packages/modules/Bluetooth/service/c CLASSPATH+=":$ROOT/out/soong/.intermediates/packages/modules/Bluetooth/framework/framework-bluetooth.impl/android_common/turbine-jarjar/framework-bluetooth.impl.jar" CLASSPATH+=":$ROOT/out/soong/.intermediates/prebuilts/sdk/current/androidx/m2repository/androidx/annotation/annotation-jvm/1.8.0-alpha01/androidx.annotation_annotation/android_common_apex33/turbine-combined/androidx.annotation_annotation.jar" -CLASSPATH+=":$ROOT/out/soong/.intermediates/packages/modules/Bluetooth/service/bluetooth-manager-service-proto-java-gen/android_common_apex33/turbine-combined/bluetooth-manager-service-proto-java-gen.jar" CLASSPATH+=":$ROOT/out/soong/.intermediates/packages/modules/Bluetooth/service/bluetooth-nano-protos/android_common_apex33/turbine-combined/bluetooth-nano-protos.jar" CLASSPATH+=":$ROOT/out/soong/.intermediates/packages/modules/Bluetooth/android/app/bluetooth-proto-enums-java-gen/android_common_apex33/turbine-combined/bluetooth-proto-enums-java-gen.jar" CLASSPATH+=":$ROOT/out/soong/.intermediates/packages/modules/Bluetooth/flags/bluetooth_flags_java_lib/android_common_apex33/turbine-combined/bluetooth_flags_java_lib.jar" diff --git a/service/src/ActiveLog.kt b/service/src/ActiveLog.kt index 46e3a5570d..ac49031f90 100644 --- a/service/src/ActiveLog.kt +++ b/service/src/ActiveLog.kt @@ -30,14 +30,12 @@ import android.bluetooth.BluetoothProtoEnums.ENABLE_DISABLE_REASON_START_ERROR import android.bluetooth.BluetoothProtoEnums.ENABLE_DISABLE_REASON_SYSTEM_BOOT import android.bluetooth.BluetoothProtoEnums.ENABLE_DISABLE_REASON_USER_SWITCH import android.os.Binder -import android.util.proto.ProtoOutputStream import androidx.annotation.VisibleForTesting import com.android.bluetooth.BluetoothStatsLog import com.android.bluetooth.BluetoothStatsLog.BLUETOOTH_ENABLED_STATE_CHANGED import com.android.bluetooth.BluetoothStatsLog.BLUETOOTH_ENABLED_STATE_CHANGED__STATE__DISABLED import com.android.bluetooth.BluetoothStatsLog.BLUETOOTH_ENABLED_STATE_CHANGED__STATE__ENABLED import com.android.bluetooth.BluetoothStatsLog.BLUETOOTH_ENABLED_STATE_CHANGED__STATE__UNKNOWN -import com.android.server.BluetoothManagerServiceDumpProto as BtProto import java.io.PrintWriter private const val TAG = "ActiveLogs" @@ -58,13 +56,6 @@ object ActiveLogs { } @JvmStatic - fun dumpProto(proto: ProtoOutputStream) { - val token = proto.start(BtProto.ACTIVE_LOGS) - activeLogs.forEach { it.dump(proto) } - proto.end(token) - } - - @JvmStatic fun add(reason: Int, enable: Boolean) { add(reason, enable, "BluetoothSystemServer", false) } @@ -124,13 +115,6 @@ internal class ActiveLog( (if (isBle) "Ble" else "") + "]. \tReason is " + getEnableDisableReasonString(reason) - - fun dump(proto: ProtoOutputStream) { - proto.write(BtProto.ActiveLog.TIMESTAMP_MS, timestamp) - proto.write(BtProto.ActiveLog.ENABLE, enable) - proto.write(BtProto.ActiveLog.PACKAGE_NAME, packageName) - proto.write(BtProto.ActiveLog.REASON, reason) - } } private fun getEnableDisableReasonString(reason: Int): String { diff --git a/service/src/ActiveLogTest.kt b/service/src/ActiveLogTest.kt index ccd86a375e..baa5076626 100644 --- a/service/src/ActiveLogTest.kt +++ b/service/src/ActiveLogTest.kt @@ -26,7 +26,6 @@ import android.bluetooth.BluetoothProtoEnums.ENABLE_DISABLE_REASON_SATELLITE_MOD import android.bluetooth.BluetoothProtoEnums.ENABLE_DISABLE_REASON_START_ERROR import android.bluetooth.BluetoothProtoEnums.ENABLE_DISABLE_REASON_SYSTEM_BOOT import android.bluetooth.BluetoothProtoEnums.ENABLE_DISABLE_REASON_USER_SWITCH -import android.util.proto.ProtoOutputStream import com.android.server.bluetooth.ActiveLogs import com.android.server.bluetooth.Log import com.google.common.truth.Truth.assertThat @@ -137,14 +136,4 @@ class ActiveLogTest { ".*UNKNOWN\\[\\d+\\]\n" ) } - - @Test - fun protoDump() { - ActiveLogs.add(ENABLE_DISABLE_REASON_APPLICATION_REQUEST, false) - - val proto = ProtoOutputStream() - ActiveLogs.dumpProto(proto) - - assertThat(proto.getRawSize()).isEqualTo(48) - } } diff --git a/service/src/AdapterState.kt b/service/src/AdapterState.kt index ac52185c89..ef6900975e 100644 --- a/service/src/AdapterState.kt +++ b/service/src/AdapterState.kt @@ -20,7 +20,6 @@ import android.bluetooth.BluetoothAdapter.STATE_OFF import android.bluetooth.IBluetoothManager.GET_SYSTEM_STATE_API import android.bluetooth.IBluetoothManager.IPC_CACHE_MODULE_SYSTEM import android.os.IpcDataCache -import com.android.bluetooth.flags.Flags import kotlin.time.Duration import kotlin.time.toKotlinDuration import kotlinx.coroutines.flow.MutableSharedFlow @@ -40,9 +39,7 @@ class BluetoothAdapterState { fun set(s: Int) = runBlocking { _uiState.emit(s) - if (Flags.getStateFromSystemServer()) { - IpcDataCache.invalidateCache(IPC_CACHE_MODULE_SYSTEM, GET_SYSTEM_STATE_API) - } + IpcDataCache.invalidateCache(IPC_CACHE_MODULE_SYSTEM, GET_SYSTEM_STATE_API) } fun get(): Int = _uiState.replayCache.get(0) diff --git a/service/src/airplane/ModeListenerTest.kt b/service/src/airplane/ModeListenerTest.kt index b455b1122d..50f7f06a5c 100644 --- a/service/src/airplane/ModeListenerTest.kt +++ b/service/src/airplane/ModeListenerTest.kt @@ -26,7 +26,6 @@ import android.platform.test.flag.junit.FlagsParameterization import android.platform.test.flag.junit.SetFlagsRule import android.provider.Settings import androidx.test.core.app.ApplicationProvider -import com.android.bluetooth.flags.Flags import com.android.server.bluetooth.BluetoothAdapterState import com.android.server.bluetooth.Log import com.android.server.bluetooth.airplane.APM_BT_ENABLED_NOTIFICATION @@ -63,14 +62,13 @@ class ModeListenerTest(flags: FlagsParameterization) { companion object { @JvmStatic @Parameters(name = "{0}") - fun getParams() = - FlagsParameterization.allCombinationsOf(Flags.FLAG_GET_STATE_FROM_SYSTEM_SERVER) + fun getParams() = FlagsParameterization.allCombinationsOf() internal fun setupAirplaneModeToOn( resolver: ContentResolver, looper: Looper, user: () -> Context, - enableEnhancedMode: Boolean + enableEnhancedMode: Boolean, ) { enableSensitive(resolver, looper, Settings.Global.AIRPLANE_MODE_RADIOS) enableMode(resolver, looper, Settings.Global.AIRPLANE_MODE_ON) diff --git a/service/src/com/android/server/bluetooth/BluetoothManagerService.java b/service/src/com/android/server/bluetooth/BluetoothManagerService.java index fe63ff1c21..08a949d81a 100644 --- a/service/src/com/android/server/bluetooth/BluetoothManagerService.java +++ b/service/src/com/android/server/bluetooth/BluetoothManagerService.java @@ -61,7 +61,6 @@ import android.content.ServiceConnection; import android.content.pm.ApplicationInfo; import android.content.pm.PackageInfo; import android.content.pm.PackageManager; -import android.content.pm.ResolveInfo; import android.os.Binder; import android.os.Build; import android.os.Bundle; @@ -87,7 +86,6 @@ import com.android.bluetooth.flags.Flags; import com.android.internal.annotations.VisibleForTesting; import com.android.modules.expresslog.Counter; import com.android.modules.expresslog.Histogram; -import com.android.server.BluetoothManagerServiceDumpProto; import com.android.server.bluetooth.airplane.AirplaneModeListener; import com.android.server.bluetooth.satellite.SatelliteModeListener; @@ -151,8 +149,6 @@ class BluetoothManagerService { @VisibleForTesting static final int MESSAGE_RESTART_BLUETOOTH_SERVICE = 42; @VisibleForTesting static final int MESSAGE_BLUETOOTH_STATE_CHANGE = 60; @VisibleForTesting static final int MESSAGE_TIMEOUT_BIND = 100; - // TODO: b/368120237 delete MESSAGE_GET_NAME_AND_ADDRESS - @VisibleForTesting static final int MESSAGE_GET_NAME_AND_ADDRESS = 200; @VisibleForTesting static final int MESSAGE_USER_SWITCHED = 300; @VisibleForTesting static final int MESSAGE_USER_UNLOCKED = 301; @VisibleForTesting static final int MESSAGE_RESTORE_USER_SETTING_OFF = 501; @@ -513,24 +509,7 @@ class BluetoothManagerService { @Override public void onReceive(Context context, Intent intent) { String action = intent.getAction(); - if (!Flags.getNameAndAddressAsCallback() - && BluetoothAdapter.ACTION_LOCAL_NAME_CHANGED.equals(action)) { - String newName = intent.getStringExtra(BluetoothAdapter.EXTRA_LOCAL_NAME); - if (newName != null) { - Log.d(TAG, "Local name changed to: " + newName); - storeNameAndAddress(newName, null); - } - } else if (!Flags.getNameAndAddressAsCallback() - && BluetoothAdapter.ACTION_BLUETOOTH_ADDRESS_CHANGED.equals(action)) { - String newAddress = - intent.getStringExtra(BluetoothAdapter.EXTRA_BLUETOOTH_ADDRESS); - if (newAddress != null) { - Log.d(TAG, "Local address changed to: " + logAddress(newAddress)); - storeNameAndAddress(null, newAddress); - } else { - Log.e(TAG, "No Bluetooth Adapter address parameter found"); - } - } else if (Intent.ACTION_SETTING_RESTORED.equals(action)) { + if (Intent.ACTION_SETTING_RESTORED.equals(action)) { final String name = intent.getStringExtra(Intent.EXTRA_SETTING_NAME); if (Settings.Global.BLUETOOTH_ON.equals(name)) { // The Bluetooth On state may be changed during system restore. @@ -605,10 +584,6 @@ class BluetoothManagerService { } IntentFilter filter = new IntentFilter(); - if (!Flags.getNameAndAddressAsCallback()) { - filter.addAction(BluetoothAdapter.ACTION_LOCAL_NAME_CHANGED); - filter.addAction(BluetoothAdapter.ACTION_BLUETOOTH_ADDRESS_CHANGED); - } filter.addAction(Intent.ACTION_SETTING_RESTORED); filter.addAction(Intent.ACTION_SHUTDOWN); filter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY); @@ -643,20 +618,15 @@ class BluetoothManagerService { null, mHandler); - if (Flags.getNameAndAddressAsCallback()) { - mName = - BluetoothServerProxy.getInstance() - .settingsSecureGetString( - mContentResolver, Settings.Secure.BLUETOOTH_NAME); - mAddress = - BluetoothServerProxy.getInstance() - .settingsSecureGetString( - mContentResolver, Settings.Secure.BLUETOOTH_ADDRESS); - - Log.d(TAG, "Local adapter: Name=" + mName + ", Address=" + logAddress(mAddress)); - } else { - loadStoredNameAndAddress(); - } + mName = + BluetoothServerProxy.getInstance() + .settingsSecureGetString(mContentResolver, Settings.Secure.BLUETOOTH_NAME); + mAddress = + BluetoothServerProxy.getInstance() + .settingsSecureGetString( + mContentResolver, Settings.Secure.BLUETOOTH_ADDRESS); + + Log.d(TAG, "Local adapter: Name=" + mName + ", Address=" + logAddress(mAddress)); if (isBluetoothPersistedStateOn()) { Log.i(TAG, "Startup: Bluetooth persisted state is ON."); @@ -726,30 +696,6 @@ class BluetoothManagerService { BluetoothServerProxy.getInstance().setBluetoothPersistedState(mContentResolver, state); } - /** Returns true if the Bluetooth Adapter's name and address is locally cached */ - private boolean isNameAndAddressSet() { - return mName != null && mAddress != null && mName.length() > 0 && mAddress.length() > 0; - } - - private void loadStoredNameAndAddress() { - if (BluetoothProperties.isAdapterAddressValidationEnabled().orElse(false) - && Settings.Secure.getInt(mContentResolver, Settings.Secure.BLUETOOTH_ADDR_VALID, 0) - == 0) { - // if the valid flag is not set, don't load the address and name - Log.w(TAG, "There is no valid bluetooth name and address stored"); - return; - } - mName = - BluetoothServerProxy.getInstance() - .settingsSecureGetString(mContentResolver, Settings.Secure.BLUETOOTH_NAME); - mAddress = - BluetoothServerProxy.getInstance() - .settingsSecureGetString( - mContentResolver, Settings.Secure.BLUETOOTH_ADDRESS); - - Log.d(TAG, "loadStoredNameAndAddress: Name=" + mName + ", Address=" + logAddress(mAddress)); - } - private static String logAddress(String address) { if (address == null) { return "[address is null]"; @@ -760,35 +706,6 @@ class BluetoothManagerService { return "XX:XX:XX:XX:" + address.substring(address.length() - 5); } - /** - * Save the Bluetooth name and address in the persistent store. Only non-null values will be - * saved. - */ - private void storeNameAndAddress(String name, String address) { - final String logHeader = "storeNameAndAddress(" + name + ", " + logAddress(address) + "): "; - if (name != null) { - if (Settings.Secure.putString(mContentResolver, Settings.Secure.BLUETOOTH_NAME, name)) { - mName = name; - } else { - Log.e(TAG, logHeader + "Failed. Name is still " + mName); - } - } - - if (address != null) { - if (Settings.Secure.putString( - mContentResolver, Settings.Secure.BLUETOOTH_ADDRESS, address)) { - mAddress = address; - } else { - Log.e(TAG, logHeader + "Failed. Address is still " + logAddress(mAddress)); - } - } - - if ((mName != null) && (mAddress != null)) { - Settings.Secure.putInt(mContentResolver, Settings.Secure.BLUETOOTH_ADDR_VALID, 1); - } - Log.d(TAG, logHeader + "Completed successfully"); - } - // Called from unsafe binder thread IBluetooth registerAdapter(IBluetoothManagerCallback callback) { mCallbacks.register(callback); @@ -1223,9 +1140,6 @@ class BluetoothManagerService { if (mEnableExternal && isBluetoothPersistedStateOnBluetooth() && !isSafeMode) { Log.i(TAG, "internalHandleOnBootPhase: Auto-enabling Bluetooth."); sendEnableMsg(mQuietEnableExternal, ENABLE_DISABLE_REASON_SYSTEM_BOOT); - } else if (!Flags.removeOneTimeGetNameAndAddress() && !isNameAndAddressSet()) { - Log.i(TAG, "internalHandleOnBootPhase: Getting adapter name and address"); - mHandler.sendEmptyMessage(MESSAGE_GET_NAME_AND_ADDRESS); } else { autoOnSetupTimer(); } @@ -1284,43 +1198,11 @@ class BluetoothManagerService { // Called from unsafe binder thread String getAddress() { - if (Flags.getNameAndAddressAsCallback()) { - return mAddress; - } - // Copy to local variable to avoid race condition when checking for null - AdapterBinder adapter = mAdapter; - if (adapter != null) { - try { - return adapter.getAddress(mContext.getAttributionSource()); - } catch (RemoteException e) { - Log.e(TAG, "getAddress(): Returning cached address", e); - } - } - - // mAddress is accessed from outside. - // It is alright without a lock. Here, bluetooth is off, no other thread is - // changing mAddress return mAddress; } // Called from unsafe binder thread String getName() { - if (Flags.getNameAndAddressAsCallback()) { - return mName; - } - // Copy to local variable to avoid race condition when checking for null - AdapterBinder adapter = mAdapter; - if (adapter != null) { - try { - return adapter.getName(mContext.getAttributionSource()); - } catch (RemoteException e) { - Log.e(TAG, "getName(): Returning cached name", e); - } - } - - // mName is accessed from outside. - // It alright without a lock. Here, bluetooth is off, no other thread is - // changing mName return mName; } @@ -1362,9 +1244,6 @@ class BluetoothManagerService { @VisibleForTesting class BluetoothHandler extends Handler { - // TODO: b/368120237 delete mGetNameAddressOnly - boolean mGetNameAddressOnly = false; - BluetoothHandler(Looper looper) { super(looper); } @@ -1372,33 +1251,6 @@ class BluetoothManagerService { @Override public void handleMessage(Message msg) { switch (msg.what) { - case MESSAGE_GET_NAME_AND_ADDRESS: - if (Flags.removeOneTimeGetNameAndAddress()) { - Log.e(TAG, "MESSAGE_GET_NAME_AND_ADDRESS is not supported anymore"); - break; - } - Log.d(TAG, "MESSAGE_GET_NAME_AND_ADDRESS"); - if (mAdapter == null && !isBinding()) { - Log.d(TAG, "Binding to service to get name and address"); - mGetNameAddressOnly = true; - bindToAdapter(); - } else if (mAdapter != null) { - if (!Flags.getNameAndAddressAsCallback()) { - try { - storeNameAndAddress( - mAdapter.getName(mContext.getAttributionSource()), - mAdapter.getAddress(mContext.getAttributionSource())); - } catch (RemoteException e) { - Log.e(TAG, "Unable to grab name or address", e); - } - } - if (mGetNameAddressOnly && !mEnable) { - unbindAndFinish(); - } - mGetNameAddressOnly = false; - } - break; - case MESSAGE_ENABLE: int quietEnable = msg.arg1; int isBle = msg.arg2; @@ -1419,68 +1271,20 @@ class BluetoothManagerService { break; case MESSAGE_HANDLE_ENABLE_DELAYED: - // The Bluetooth is turning off, wait for STATE_OFF - if (!mState.oneOf(STATE_OFF)) { - if (mWaitForEnableRetry < MAX_WAIT_FOR_ENABLE_DISABLE_RETRIES) { - mWaitForEnableRetry++; - mHandler.sendEmptyMessageDelayed( - MESSAGE_HANDLE_ENABLE_DELAYED, ENABLE_DISABLE_DELAY_MS); - break; - } else { - Log.e(TAG, "Wait for STATE_OFF timeout"); - } - } - // Either state is changed to STATE_OFF or reaches the maximum retry, we - // should move forward to the next step. - mWaitForEnableRetry = 0; - mHandler.sendEmptyMessageDelayed( - MESSAGE_RESTART_BLUETOOTH_SERVICE, getServiceRestartMs()); - Log.d(TAG, "Handle enable is finished"); + Log.d(TAG, "MESSAGE_HANDLE_ENABLE_DELAYED: mAdapter=" + mAdapter); + + handleEnableDelayed(); break; case MESSAGE_HANDLE_DISABLE_DELAYED: boolean disabling = (msg.arg1 == 1); - Log.d(TAG, "MESSAGE_HANDLE_DISABLE_DELAYED: disabling:" + disabling); - if (!disabling) { - // The Bluetooth is turning on, wait for STATE_ON - if (!mState.oneOf(STATE_ON)) { - if (mWaitForDisableRetry < MAX_WAIT_FOR_ENABLE_DISABLE_RETRIES) { - mWaitForDisableRetry++; - mHandler.sendEmptyMessageDelayed( - MESSAGE_HANDLE_DISABLE_DELAYED, ENABLE_DISABLE_DELAY_MS); - break; - } else { - Log.e(TAG, "Wait for STATE_ON timeout"); - } - } - // Either state is changed to STATE_ON or reaches the maximum retry, we - // should move forward to the next step. - mWaitForDisableRetry = 0; - mEnable = false; - onToBleOn(); - // Wait for state exiting STATE_ON - Message disableDelayedMsg = - mHandler.obtainMessage(MESSAGE_HANDLE_DISABLE_DELAYED, 1, 0); - mHandler.sendMessageDelayed(disableDelayedMsg, ENABLE_DISABLE_DELAY_MS); - } else { - // The Bluetooth is turning off, wait for exiting STATE_ON - if (mState.oneOf(STATE_ON)) { - if (mWaitForDisableRetry < MAX_WAIT_FOR_ENABLE_DISABLE_RETRIES) { - mWaitForDisableRetry++; - Message disableDelayedMsg = - mHandler.obtainMessage( - MESSAGE_HANDLE_DISABLE_DELAYED, 1, 0); - mHandler.sendMessageDelayed( - disableDelayedMsg, ENABLE_DISABLE_DELAY_MS); - break; - } else { - Log.e(TAG, "Wait for exiting STATE_ON timeout"); - } - } - // Either state is exited from STATE_ON or reaches the maximum retry, we - // should move forward to the next step. - Log.d(TAG, "Handle disable is finished"); - } + + Log.d( + TAG, + ("MESSAGE_HANDLE_DISABLE_DELAYED(disabling=" + disabling + ")") + + (": mAdapter=" + mAdapter)); + + handleDisableDelayed(disabling); break; case MESSAGE_RESTORE_USER_SETTING_OFF: @@ -1516,15 +1320,6 @@ class BluetoothManagerService { propagateForegroundUserId(ActivityManager.getCurrentUser()); - if (!Flags.removeOneTimeGetNameAndAddress()) { - if (!isNameAndAddressSet()) { - mHandler.sendEmptyMessage(MESSAGE_GET_NAME_AND_ADDRESS); - if (mGetNameAddressOnly) { - return; - } - } - } - try { mAdapter.registerCallback( mBluetoothCallback, mContext.getAttributionSource()); @@ -1815,12 +1610,7 @@ class BluetoothManagerService { UserHandle user = UserHandle.CURRENT; int flags = Context.BIND_AUTO_CREATE | Context.BIND_IMPORTANT; Intent intent = new Intent(IBluetooth.class.getName()); - ComponentName comp = resolveSystemService(intent); - if (comp == null && !Flags.enforceResolveSystemServiceBehavior()) { - Log.e(TAG, "No ComponentName found for intent=" + intent); - return; - } - intent.setComponent(comp); + intent.setComponent(resolveSystemService(intent)); mHandler.sendEmptyMessageDelayed(MESSAGE_TIMEOUT_BIND, TIMEOUT_BIND_MS); Log.d(TAG, "Start binding to the Bluetooth service with intent=" + intent); @@ -1846,6 +1636,66 @@ class BluetoothManagerService { } } + private void handleEnableDelayed() { + // The Bluetooth is turning off, wait for STATE_OFF + if (!mState.oneOf(STATE_OFF)) { + if (mWaitForEnableRetry < MAX_WAIT_FOR_ENABLE_DISABLE_RETRIES) { + mWaitForEnableRetry++; + mHandler.sendEmptyMessageDelayed( + MESSAGE_HANDLE_ENABLE_DELAYED, ENABLE_DISABLE_DELAY_MS); + return; + } else { + Log.e(TAG, "Wait for STATE_OFF timeout"); + } + } + // Either state is changed to STATE_OFF or reaches the maximum retry, we + // should move forward to the next step. + mWaitForEnableRetry = 0; + mHandler.sendEmptyMessageDelayed(MESSAGE_RESTART_BLUETOOTH_SERVICE, getServiceRestartMs()); + Log.d(TAG, "Handle enable is finished"); + } + + private void handleDisableDelayed(boolean disabling) { + if (!disabling) { + // The Bluetooth is turning on, wait for STATE_ON + if (!mState.oneOf(STATE_ON)) { + if (mWaitForDisableRetry < MAX_WAIT_FOR_ENABLE_DISABLE_RETRIES) { + mWaitForDisableRetry++; + mHandler.sendEmptyMessageDelayed( + MESSAGE_HANDLE_DISABLE_DELAYED, ENABLE_DISABLE_DELAY_MS); + return; + } else { + Log.e(TAG, "Wait for STATE_ON timeout"); + } + } + // Either state is changed to STATE_ON or reaches the maximum retry, we + // should move forward to the next step. + mWaitForDisableRetry = 0; + mEnable = false; + onToBleOn(); + // Wait for state exiting STATE_ON + Message disableDelayedMsg = + mHandler.obtainMessage(MESSAGE_HANDLE_DISABLE_DELAYED, 1, 0); + mHandler.sendMessageDelayed(disableDelayedMsg, ENABLE_DISABLE_DELAY_MS); + } else { + // The Bluetooth is turning off, wait for exiting STATE_ON + if (mState.oneOf(STATE_ON)) { + if (mWaitForDisableRetry < MAX_WAIT_FOR_ENABLE_DISABLE_RETRIES) { + mWaitForDisableRetry++; + Message disableDelayedMsg = + mHandler.obtainMessage(MESSAGE_HANDLE_DISABLE_DELAYED, 1, 0); + mHandler.sendMessageDelayed(disableDelayedMsg, ENABLE_DISABLE_DELAY_MS); + return; + } else { + Log.e(TAG, "Wait for exiting STATE_ON timeout"); + } + } + // Either state is exited from STATE_ON or reaches the maximum retry, we + // should move forward to the next step. + Log.d(TAG, "Handle disable is finished"); + } + } + private void offToBleOn() { if (!mState.oneOf(STATE_OFF)) { Log.e(TAG, "offToBleOn: Impossible transition from " + mState); @@ -2158,10 +2008,6 @@ class BluetoothManagerService { } void dump(FileDescriptor fd, PrintWriter writer, String[] args) { - if ((args.length > 0) && args[0].startsWith("--proto")) { - dumpProto(fd); - return; - } String errorMsg = null; writer.println("Bluetooth Status"); @@ -2251,33 +2097,6 @@ class BluetoothManagerService { }); } - private void dumpProto(FileDescriptor fd) { - final ProtoOutputStream proto = new ProtoOutputStream(new FileOutputStream(fd)); - proto.write(BluetoothManagerServiceDumpProto.ENABLED, isEnabled()); - proto.write(BluetoothManagerServiceDumpProto.STATE, mState.get()); - proto.write(BluetoothManagerServiceDumpProto.STATE_NAME, nameForState(mState.get())); - proto.write(BluetoothManagerServiceDumpProto.ADDRESS, logAddress(mAddress)); - proto.write(BluetoothManagerServiceDumpProto.NAME, mName); - if (mEnable) { - proto.write(BluetoothManagerServiceDumpProto.LAST_ENABLED_TIME_MS, mLastEnabledTime); - } - proto.write( - BluetoothManagerServiceDumpProto.CURR_TIMESTAMP_MS, SystemClock.elapsedRealtime()); - ActiveLogs.dumpProto(proto); - proto.write(BluetoothManagerServiceDumpProto.NUM_CRASHES, mCrashes); - proto.write( - BluetoothManagerServiceDumpProto.CRASH_LOG_MAXED, mCrashes == CRASH_LOG_MAX_SIZE); - for (Long time : mCrashTimestamps) { - proto.write(BluetoothManagerServiceDumpProto.CRASH_TIMESTAMPS_MS, time); - } - proto.write(BluetoothManagerServiceDumpProto.NUM_BLE_APPS, mBleApps.size()); - for (ClientDeathRecipient app : mBleApps.values()) { - proto.write( - BluetoothManagerServiceDumpProto.BLE_APP_PACKAGE_NAMES, app.getPackageName()); - } - proto.flush(); - } - static @NonNull Bundle getTempAllowlistBroadcastOptions() { final long duration = 10_000; final BroadcastOptions bOptions = BroadcastOptions.makeBasic(); @@ -2289,38 +2108,7 @@ class BluetoothManagerService { return bOptions.toBundle(); } - private ComponentName legacyresolveSystemService(@NonNull Intent intent) { - List<ResolveInfo> results = mContext.getPackageManager().queryIntentServices(intent, 0); - if (results == null) { - return null; - } - ComponentName comp = null; - for (int i = 0; i < results.size(); i++) { - ResolveInfo ri = results.get(i); - if ((ri.serviceInfo.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) == 0) { - continue; - } - ComponentName foundComp = - new ComponentName( - ri.serviceInfo.applicationInfo.packageName, ri.serviceInfo.name); - if (comp != null) { - throw new IllegalStateException( - "Multiple system services handle " - + intent - + ": " - + comp - + ", " - + foundComp); - } - comp = foundComp; - } - return comp; - } - private ComponentName resolveSystemService(@NonNull Intent intent) { - if (!Flags.enforceResolveSystemServiceBehavior()) { - return legacyresolveSystemService(intent); - } List<ComponentName> results = mContext.getPackageManager().queryIntentServices(intent, 0).stream() .filter( diff --git a/service/src/com/android/server/bluetooth/BluetoothServiceBinder.java b/service/src/com/android/server/bluetooth/BluetoothServiceBinder.java index bb0e951d96..99759d764d 100644 --- a/service/src/com/android/server/bluetooth/BluetoothServiceBinder.java +++ b/service/src/com/android/server/bluetooth/BluetoothServiceBinder.java @@ -44,8 +44,6 @@ import android.permission.PermissionManager; import androidx.annotation.RequiresApi; -import com.android.bluetooth.flags.Flags; - import java.io.FileDescriptor; import java.io.PrintWriter; @@ -170,15 +168,6 @@ class BluetoothServiceBinder extends IBluetoothManager.Stub { @Override public int getState() { - if (Flags.getStateFromSystemServer()) { - return mBluetoothManagerService.getState(); - } - if (!isCallerSystem(getCallingAppId()) - && !mPermissionUtils.checkIfCallerIsForegroundUser(mUserManager)) { - Log.w(TAG, "getState(): UNAUTHORIZED. Report OFF for non-active and non system user"); - return BluetoothAdapter.STATE_OFF; - } - return mBluetoothManagerService.getState(); } diff --git a/service/tests/src/com/android/server/bluetooth/BluetoothManagerServiceTest.java b/service/tests/src/com/android/server/bluetooth/BluetoothManagerServiceTest.java index b2042b5e79..480af98329 100644 --- a/service/tests/src/com/android/server/bluetooth/BluetoothManagerServiceTest.java +++ b/service/tests/src/com/android/server/bluetooth/BluetoothManagerServiceTest.java @@ -69,8 +69,6 @@ import android.provider.Settings; import androidx.test.platform.app.InstrumentationRegistry; -import com.android.bluetooth.flags.Flags; - import org.junit.After; import org.junit.Before; import org.junit.Rule; @@ -95,10 +93,7 @@ public class BluetoothManagerServiceTest { @Parameters(name = "{0}") public static List<FlagsParameterization> getParams() { - return FlagsParameterization.allCombinationsOf( - Flags.FLAG_GET_NAME_AND_ADDRESS_AS_CALLBACK, - Flags.FLAG_ENFORCE_RESOLVE_SYSTEM_SERVICE_BEHAVIOR, - Flags.FLAG_REMOVE_ONE_TIME_GET_NAME_AND_ADDRESS); + return FlagsParameterization.allCombinationsOf(); } public BluetoothManagerServiceTest(FlagsParameterization flags) { diff --git a/service/tests/src/com/android/server/bluetooth/BluetoothServiceBinderTest.java b/service/tests/src/com/android/server/bluetooth/BluetoothServiceBinderTest.java index ec4abca34f..7ef4ec8887 100644 --- a/service/tests/src/com/android/server/bluetooth/BluetoothServiceBinderTest.java +++ b/service/tests/src/com/android/server/bluetooth/BluetoothServiceBinderTest.java @@ -49,16 +49,12 @@ import android.content.ContextWrapper; import android.os.IBinder; import android.os.Process; import android.os.UserManager; -import android.platform.test.annotations.DisableFlags; -import android.platform.test.annotations.EnableFlags; import android.platform.test.flag.junit.SetFlagsRule; import androidx.test.filters.SmallTest; import androidx.test.platform.app.InstrumentationRegistry; import androidx.test.runner.AndroidJUnit4; -import com.android.bluetooth.flags.Flags; - import libcore.junit.util.compat.CoreCompatChangeRule.DisableCompatChanges; import libcore.junit.util.compat.CoreCompatChangeRule.EnableCompatChanges; @@ -226,19 +222,6 @@ public class BluetoothServiceBinderTest { } @Test - @DisableFlags(Flags.FLAG_GET_STATE_FROM_SYSTEM_SERVER) - public void getState() { - // TODO(b/280518177): add more test from not System / ... - // TODO(b/280518177): add more test when caller is not in foreground - - mBinder.getState(); - verify(mManagerService).getState(); - verify(mUserManager).getProfileParent(any()); - verifyMock(); - } - - @Test - @EnableFlags(Flags.FLAG_GET_STATE_FROM_SYSTEM_SERVER) public void getStateFromSystemServer() { mBinder.getState(); verify(mManagerService).getState(); 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/aidl/le_audio_software_aidl.cc b/system/audio_hal_interface/aidl/le_audio_software_aidl.cc index be7cf3a6b2..e0b96475d3 100644 --- a/system/audio_hal_interface/aidl/le_audio_software_aidl.cc +++ b/system/audio_hal_interface/aidl/le_audio_software_aidl.cc @@ -30,6 +30,7 @@ #include "common/strings.h" #include "hal_version_manager.h" #include "le_audio_utils.h" +#include "osi/include/properties.h" namespace bluetooth { namespace audio { @@ -694,6 +695,14 @@ bluetooth::audio::le_audio::OffloadCapabilities get_offload_capabilities() { return {offload_capabilities, broadcast_offload_capabilities}; } +static bool IsUsingCodecExtensibility() { + auto codec_ext_status = + osi_property_get_bool("bluetooth.core.le_audio.codec_extension_aidl.enabled", false); + + log::debug("Using codec extensibility AIDL: {}", codec_ext_status); + return codec_ext_status; +} + AudioConfiguration stream_config_to_hal_audio_config( const ::bluetooth::le_audio::stream_config& offload_config) { LeAudioConfiguration ucast_config = { @@ -726,6 +735,7 @@ AudioConfiguration stream_config_to_hal_audio_config( .blocksPerSdu = static_cast<int8_t>(offload_config.codec_frames_blocks_per_sdu), }; ucast_config.leAudioCodecConfig = LeAudioCodecConfiguration(lc3_config); + ucast_config.codecType = CodecType::LC3; lc3_codec_config_found = true; } @@ -741,14 +751,20 @@ AudioConfiguration stream_config_to_hal_audio_config( BLE_ADDRESS_RANDOM; } - ucast_config.streamMap.push_back({ + LeAudioConfiguration::StreamMap map_entry = { .streamHandle = info.stream_handle, .audioChannelAllocation = static_cast<int32_t>(info.audio_channel_allocation), .isStreamActive = info.is_stream_active, - .aseConfiguration = GetAidlLeAudioAseConfigurationFromStackFormat( - info.codec_config, info.target_latency, info.target_phy, info.metadata), - .bluetoothDeviceAddress = aidl_device_address, - }); + }; + + // Add the additional codec extensibility data fields + if (IsUsingCodecExtensibility()) { + map_entry.aseConfiguration = GetAidlLeAudioAseConfigurationFromStackFormat( + info.codec_config, info.target_latency, info.target_phy, info.metadata); + map_entry.bluetoothDeviceAddress = aidl_device_address; + } + + ucast_config.streamMap.push_back(map_entry); } if (!lc3_codec_config_found) { 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/bta/ag/bta_ag_sco.cc b/system/bta/ag/bta_ag_sco.cc index cdb960b716..a5cc30f41b 100644 --- a/system/bta/ag/bta_ag_sco.cc +++ b/system/bta/ag/bta_ag_sco.cc @@ -47,6 +47,8 @@ #include "internal/btm_api.h" #include "internal_include/bt_target.h" #include "main/shim/entry.h" +#include "main/shim/helpers.h" +#include "main/shim/metrics_api.h" #include "osi/include/alarm.h" #include "osi/include/properties.h" #include "stack/btm/btm_int_types.h" @@ -61,6 +63,7 @@ extern tBTM_CB btm_cb; using HfpInterface = bluetooth::audio::hfp::HfpClientInterface; using namespace bluetooth; +using namespace bluetooth::shim; /* Codec negotiation timeout */ #ifndef BTA_AG_CODEC_NEGOTIATION_TIMEOUT_MS @@ -329,6 +332,7 @@ static bool bta_ag_remove_sco(tBTA_AG_SCB* p_scb, bool only_active) { if (p_scb->sco_idx != BTM_INVALID_SCO_INDEX) { if (!only_active || p_scb->sco_idx == bta_ag_cb.sco.cur_idx) { tBTM_STATUS status = get_btm_client_interface().sco.BTM_RemoveSco(p_scb->sco_idx); + LogMetricScoLinkRemoved(ToGdAddress(p_scb->peer_addr)); log::debug("Removed SCO index:0x{:04x} status:{}", p_scb->sco_idx, btm_status_text(status)); if (status == tBTM_STATUS::BTM_CMD_STARTED) { /* SCO is connected; set current control block */ @@ -563,6 +567,8 @@ void bta_ag_create_sco(tBTA_AG_SCB* p_scb, bool is_orig) { bta_ag_cb.sco.cur_idx = p_scb->sco_idx; /* Configure input/output data. */ hfp_hal_interface::set_codec_datapath(esco_codec); + LogMetricScoLinkCreated(ToGdAddress(p_scb->peer_addr)); + LogMetricScoCodec(ToGdAddress(p_scb->peer_addr), p_scb->sco_codec); log::verbose("initiated SCO connection"); } diff --git a/system/bta/gatt/bta_gattc_act.cc b/system/bta/gatt/bta_gattc_act.cc index 4825da22b7..3b6069b1a1 100644 --- a/system/bta/gatt/bta_gattc_act.cc +++ b/system/bta/gatt/bta_gattc_act.cc @@ -1580,6 +1580,25 @@ static bool bta_gattc_process_srvc_chg_ind(tCONN_ID conn_id, tBTA_GATTC_RCB* p_c } } } + // Use a busy CLCB to start discovery if no CLCB is available, this will be queued. + if (com::android::bluetooth::flags::start_discover_service_changed() && p_clcb == NULL) { + if (com::android::bluetooth::flags::gatt_client_dynamic_allocation()) { + for (auto& p_clcb_i : bta_gattc_cb.clcb_set) { + if (p_clcb_i->in_use && p_clcb_i->p_srcb == p_srcb) { + p_clcb = p_clcb_i.get(); + break; + } + } + } else { + for (size_t i = 0; i < BTA_GATTC_CLCB_MAX; i++) { + if (bta_gattc_cb.clcb[i].in_use && bta_gattc_cb.clcb[i].p_srcb == p_srcb) { + p_clcb = &bta_gattc_cb.clcb[i]; + break; + } + } + } + } + /* send confirmation here if this is an indication, it should always be */ if (GATTC_SendHandleValueConfirm(conn_id, p_notify->cid) != GATT_SUCCESS) { log::warn("Unable to send GATT client handle value confirmation conn_id:{} cid:{}", conn_id, @@ -1591,6 +1610,8 @@ static bool bta_gattc_process_srvc_chg_ind(tCONN_ID conn_id, tBTA_GATTC_RCB* p_c /* request read db hash first */ p_srcb->srvc_hdl_db_hash = true; bta_gattc_sm_execute(p_clcb, BTA_GATTC_INT_DISCOVER_EVT, NULL); + } else { + log::warn("No clcb is available to handle service change indication"); } } diff --git a/system/bta/le_audio/codec_manager.cc b/system/bta/le_audio/codec_manager.cc index 9452218c5d..104d397833 100644 --- a/system/bta/le_audio/codec_manager.cc +++ b/system/bta/le_audio/codec_manager.cc @@ -733,11 +733,11 @@ public: bool AppendStreamMapExtension(const std::vector<struct types::cis>& cises, const stream_parameters& stream_params, uint8_t direction) { - // In the legacy mode we are already done - if (!IsUsingCodecExtensibility()) { - log::verbose("Codec Extensibility is disabled"); - return true; - } + /* Without the codec extensibility enabled, we still need the BT stack structure to + * have the valid extended codec configuration entries, as these are used for codec type + * matching. The extended data fields of the AIDL API data structures are filed + * right before the AIDL call, only if the codec extensibility is enabled + */ const std::string tag = types::BidirectionalPair<std::string>({.sink = "Sink", .source = "Source"}) diff --git a/system/bta/le_audio/codec_manager_test.cc b/system/bta/le_audio/codec_manager_test.cc index b8f79a609b..9ac1fde07d 100644 --- a/system/bta/le_audio/codec_manager_test.cc +++ b/system/bta/le_audio/codec_manager_test.cc @@ -559,15 +559,16 @@ TEST_F(CodecManagerTestAdsp, testStreamConfigurationMono) { }; // Stream parameters + auto stream_map_entry_mono_bidir = + stream_map_info(97, codec_spec_conf::kLeAudioLocationMonoAudio, true); + stream_map_entry_mono_bidir.codec_config.id = kLeAudioCodecIdLc3; types::BidirectionalPair<stream_parameters> stream_params{ .sink = { .audio_channel_allocation = codec_spec_conf::kLeAudioLocationMonoAudio, .stream_config = { - .stream_map = {stream_map_info( - 97, codec_spec_conf::kLeAudioLocationMonoAudio, - true)}, + .stream_map = {stream_map_entry_mono_bidir}, .bits_per_sample = 16, .sampling_frequency_hz = 16000, .frame_duration_us = 10000, @@ -583,9 +584,7 @@ TEST_F(CodecManagerTestAdsp, testStreamConfigurationMono) { .audio_channel_allocation = codec_spec_conf::kLeAudioLocationMonoAudio, .stream_config = { - .stream_map = {stream_map_info( - 97, codec_spec_conf::kLeAudioLocationMonoAudio, - true)}, + .stream_map = {stream_map_entry_mono_bidir}, .bits_per_sample = 16, .sampling_frequency_hz = 16000, .frame_duration_us = 10000, @@ -628,6 +627,7 @@ TEST_F(CodecManagerTestAdsp, testStreamConfigurationMono) { ASSERT_EQ(codec_spec_conf::kLeAudioLocationMonoAudio, info.audio_channel_allocation); // The connected should be active ASSERT_TRUE(info.is_stream_active); + ASSERT_EQ(info.codec_config.id.coding_format, kLeAudioCodecIdLc3.coding_format); } else { ASSERT_EQ(97, info.stream_handle); diff --git a/system/btcore/Android.bp b/system/btcore/Android.bp index 7b95bd95ca..6a0350afcb 100644 --- a/system/btcore/Android.bp +++ b/system/btcore/Android.bp @@ -8,8 +8,11 @@ package { default_applicable_licenses: ["system_bt_license"], } -cc_defaults { - name: "libbtcore_defaults", +cc_library_static { + name: "libbtcore", + visibility: [ + "//packages/modules/Bluetooth:__subpackages__", + ], defaults: ["fluoride_defaults"], local_include_dirs: ["include"], include_dirs: [ @@ -23,26 +26,17 @@ cc_defaults { "src/property.cc", ], header_libs: ["libbluetooth_headers"], - host_supported: true, - apex_available: ["com.android.bt"], + static_libs: [ + "libbluetooth_log", + ], target: { host_linux: { cflags: ["-D_GNU_SOURCE"], }, }, -} - -cc_library_static { - name: "libbtcore", - visibility: [ - "//packages/apps/Test/connectivity/sl4n", - "//packages/modules/Bluetooth:__subpackages__", - ], - defaults: ["libbtcore_defaults"], + host_supported: true, + apex_available: ["com.android.bt"], min_sdk_version: "Tiramisu", - static_libs: [ - "libbluetooth_log", - ], } cc_library_headers { 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/avrcp/avrcp_service.h b/system/btif/avrcp/avrcp_service.h index 581852194e..84f2d0149d 100644 --- a/system/btif/avrcp/avrcp_service.h +++ b/system/btif/avrcp/avrcp_service.h @@ -108,7 +108,6 @@ private: uint16_t target_sdp_request_id_ = UNASSIGNED_REQUEST_ID; uint16_t control_sdp_request_id_ = UNASSIGNED_REQUEST_ID; uint32_t sdp_record_handle = -1; - uint32_t ct_sdp_record_handle = -1; uint16_t profile_version = -1; MediaInterface* media_interface_ = nullptr; diff --git a/system/btif/include/btif_metrics_logging.h b/system/btif/include/btif_metrics_logging.h index d68eddce5e..94f7a66b79 100644 --- a/system/btif/include/btif_metrics_logging.h +++ b/system/btif/include/btif_metrics_logging.h @@ -52,7 +52,10 @@ void log_counter_metrics_btif(android::bluetooth::CodePathCounterKeyEnum key, in void log_socket_connection_state(const RawAddress& address, int port, int type, android::bluetooth::SocketConnectionstateEnum connection_state, int64_t tx_bytes, int64_t rx_bytes, int uid, int server_port, - android::bluetooth::SocketRoleEnum socket_role); + android::bluetooth::SocketRoleEnum socket_role, + uint64_t connection_duration_ms, + android::bluetooth::SocketErrorEnum error_code, + bool is_hardware_offload); bool init_metric_id_allocator(const std::unordered_map<RawAddress, int>& paired_device_map, bluetooth::shim::CallbackLegacy save_id_callback, diff --git a/system/btif/include/btif_sock_logging.h b/system/btif/include/btif_sock_logging.h index 7cd30f6396..38dfe3e302 100644 --- a/system/btif/include/btif_sock_logging.h +++ b/system/btif/include/btif_sock_logging.h @@ -16,9 +16,11 @@ #pragma once +#include "hardware/bt_sock.h" #include "types/raw_address.h" void btif_sock_connection_logger(const RawAddress& address, int port, int type, int state, int role, int uid, int server_port, int64_t tx_bytes, int64_t rx_bytes, - const char* server_name); + const char* server_name, uint64_t connection_start_time_ms, + btsock_error_code_t error_code, btsock_data_path_t data_path); void btif_sock_dump(int fd); 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..bf4c00c0d5 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; @@ -255,8 +253,6 @@ static bool btif_a2dp_source_startup(void); static void btif_a2dp_source_startup_delayed(void); static void btif_a2dp_source_start_session_delayed(const RawAddress& peer_address, std::promise<void> start_session_promise); -static void btif_a2dp_source_end_session_delayed(const RawAddress& peer_address); -static void btif_a2dp_source_shutdown_delayed(std::promise<void>); static void btif_a2dp_source_audio_tx_start_event(void); static void btif_a2dp_source_audio_tx_stop_event(void); static void btif_a2dp_source_audio_tx_flush_event(void); @@ -264,7 +260,6 @@ static void btif_a2dp_source_audio_tx_flush_event(void); // The peer address is |peer_addr|. // This function should be called prior to starting A2DP streaming. static void btif_a2dp_source_setup_codec(const RawAddress& peer_addr); -static void btif_a2dp_source_cleanup_codec(); static void btif_a2dp_source_cleanup_codec_delayed(); static void btif_a2dp_source_encoder_user_config_update_event( const RawAddress& peer_address, @@ -331,19 +326,13 @@ static void btif_a2dp_source_accumulate_stats(BtifMediaStats* src, BtifMediaStat src->Reset(); } -/// Select the thread to run a2dp source actions on (a2dp encoder excluded). -static bluetooth::common::MessageLoopThread* local_thread() { - return com::android::bluetooth::flags::a2dp_source_threading_fix() ? get_main_thread() - : &btif_a2dp_source_thread; -} - bool btif_a2dp_source_init(void) { log::info(""); // Start A2DP Source media task btif_a2dp_source_thread.StartUp(); - local_thread()->DoInThread(base::BindOnce(&btif_a2dp_source_init_delayed)); + do_in_main_thread(base::BindOnce(&btif_a2dp_source_init_delayed)); return true; } @@ -424,7 +413,7 @@ static void btif_a2dp_source_init_delayed(void) { // the provider needs to be initialized earlier in order to ensure // get_a2dp_configuration and parse_a2dp_configuration can be // invoked before the stream is started. - bluetooth::audio::a2dp::init(local_thread(), &a2dp_stream_callbacks, + bluetooth::audio::a2dp::init(get_main_thread(), &a2dp_stream_callbacks, btif_av_is_a2dp_offload_enabled()); } @@ -441,7 +430,7 @@ static bool btif_a2dp_source_startup(void) { btif_a2dp_source_cb.tx_audio_queue = fixed_queue_new(SIZE_MAX); // Schedule the rest of the operations - local_thread()->DoInThread(base::BindOnce(&btif_a2dp_source_startup_delayed)); + do_in_main_thread(base::BindOnce(&btif_a2dp_source_startup_delayed)); return true; } @@ -453,7 +442,7 @@ static void btif_a2dp_source_startup_delayed() { log::fatal("unable to enable real time scheduling"); #endif } - if (!bluetooth::audio::a2dp::init(local_thread(), &a2dp_stream_callbacks, + if (!bluetooth::audio::a2dp::init(get_main_thread(), &a2dp_stream_callbacks, btif_av_is_a2dp_offload_enabled())) { log::warn("Failed to setup the bluetooth audio HAL"); } @@ -466,15 +455,14 @@ bool btif_a2dp_source_start_session(const RawAddress& peer_address, btif_a2dp_source_audio_tx_flush_req(); - if (local_thread()->DoInThread(base::BindOnce(&btif_a2dp_source_start_session_delayed, - peer_address, std::move(peer_ready_promise)))) { - return true; - } else { - // cannot set promise but triggers crash + if (do_in_main_thread(base::BindOnce(&btif_a2dp_source_start_session_delayed, peer_address, + std::move(peer_ready_promise))) != BT_STATUS_SUCCESS) { log::fatal("peer_address={} state={} fails to context switch", peer_address, btif_a2dp_source_cb.StateStr()); return false; } + + return true; } static void btif_a2dp_source_start_session_delayed(const RawAddress& peer_address, @@ -492,11 +480,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(); @@ -510,7 +493,7 @@ bool btif_a2dp_source_restart_session(const RawAddress& old_peer_address, log::assert_that(!new_peer_address.IsEmpty(), "assert failed: !new_peer_address.IsEmpty()"); - // Must stop first the audio streaming + // Must stop first the audio streaming. btif_a2dp_source_stop_audio_req(); // If the old active peer was valid, end the old session. @@ -530,38 +513,30 @@ bool btif_a2dp_source_restart_session(const RawAddress& old_peer_address, bool btif_a2dp_source_end_session(const RawAddress& peer_address) { log::info("peer_address={} state={}", peer_address, btif_a2dp_source_cb.StateStr()); - if (com::android::bluetooth::flags::a2dp_source_threading_fix()) { - btif_a2dp_source_cleanup_codec(); - btif_a2dp_source_end_session_delayed(peer_address); - } else { - local_thread()->DoInThread(base::BindOnce(&btif_a2dp_source_end_session_delayed, peer_address)); - btif_a2dp_source_cleanup_codec(); - } - return true; -} -static void btif_a2dp_source_end_session_delayed(const RawAddress& peer_address) { - log::info("peer_address={} state={}", peer_address, btif_a2dp_source_cb.StateStr()); + // Must stop first the audio streaming. + btif_a2dp_source_stop_audio_req(); + + do_in_main_thread(base::BindOnce(&btif_a2dp_source_cleanup_codec_delayed)); + if ((btif_a2dp_source_cb.State() == BtifA2dpSource::kStateRunning) || (btif_a2dp_source_cb.State() == BtifA2dpSource::kStateShuttingDown)) { btif_av_stream_stop(peer_address); } else { log::error("A2DP Source media task is not running"); } + 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); } + + return true; } void btif_a2dp_source_allow_low_latency_audio(bool allowed) { log::info("allowed={}", allowed); - local_thread()->DoInThread( + do_in_main_thread( base::BindOnce(bluetooth::audio::a2dp::set_audio_low_latency_mode_allowed, allowed)); } @@ -573,22 +548,10 @@ void btif_a2dp_source_shutdown(std::promise<void> shutdown_complete_promise) { return; } - /* Make sure no channels are restarted while shutting down */ + // Make sure no channels are restarted while shutting down. btif_a2dp_source_cb.SetState(BtifA2dpSource::kStateShuttingDown); - // TODO(b/374166531) Remove the check for get_main_thread. - if (local_thread() != get_main_thread()) { - local_thread()->DoInThread(base::BindOnce(&btif_a2dp_source_shutdown_delayed, - std::move(shutdown_complete_promise))); - } else { - btif_a2dp_source_shutdown_delayed(std::move(shutdown_complete_promise)); - } -} - -static void btif_a2dp_source_shutdown_delayed(std::promise<void> shutdown_complete_promise) { - log::info("state={}", btif_a2dp_source_cb.StateStr()); - - // Stop the timer + // Stop the timer. btif_a2dp_source_cb.media_alarm.CancelAndWait(); wakelock_release(); @@ -688,13 +651,6 @@ static void btif_a2dp_source_setup_codec(const RawAddress& peer_address) { } } -static void btif_a2dp_source_cleanup_codec() { - log::info("state={}", btif_a2dp_source_cb.StateStr()); - // Must stop media task first before cleaning up the encoder - btif_a2dp_source_stop_audio_req(); - local_thread()->DoInThread(base::BindOnce(&btif_a2dp_source_cleanup_codec_delayed)); -} - static void btif_a2dp_source_cleanup_codec_delayed() { log::info("state={}", btif_a2dp_source_cb.StateStr()); if (btif_a2dp_source_cb.encoder_interface != nullptr) { @@ -706,13 +662,13 @@ static void btif_a2dp_source_cleanup_codec_delayed() { void btif_a2dp_source_start_audio_req(void) { log::info("state={}", btif_a2dp_source_cb.StateStr()); - local_thread()->DoInThread(base::BindOnce(&btif_a2dp_source_audio_tx_start_event)); + do_in_main_thread(base::BindOnce(&btif_a2dp_source_audio_tx_start_event)); } void btif_a2dp_source_stop_audio_req(void) { log::info("state={}", btif_a2dp_source_cb.StateStr()); - local_thread()->DoInThread(base::BindOnce(&btif_a2dp_source_audio_tx_stop_event)); + do_in_main_thread(base::BindOnce(&btif_a2dp_source_audio_tx_stop_event)); } void btif_a2dp_source_encoder_user_config_update_req( @@ -722,9 +678,9 @@ void btif_a2dp_source_encoder_user_config_update_req( log::info("peer_address={} state={} {} codec_preference(s)", peer_address, btif_a2dp_source_cb.StateStr(), codec_user_preferences.size()); - if (!local_thread()->DoInThread( - base::BindOnce(&btif_a2dp_source_encoder_user_config_update_event, peer_address, - codec_user_preferences, std::move(peer_ready_promise)))) { + if (do_in_main_thread(base::BindOnce(&btif_a2dp_source_encoder_user_config_update_event, + peer_address, codec_user_preferences, + std::move(peer_ready_promise))) != BT_STATUS_SUCCESS) { // cannot set promise but triggers crash log::fatal("peer_address={} state={} fails to context switch", peer_address, btif_a2dp_source_cb.StateStr()); @@ -767,7 +723,7 @@ static void btif_a2dp_source_encoder_user_config_update_event( void btif_a2dp_source_feeding_update_req(const btav_a2dp_codec_config_t& codec_audio_config) { log::info("state={}", btif_a2dp_source_cb.StateStr()); - local_thread()->DoInThread( + do_in_main_thread( base::BindOnce(&btif_a2dp_source_audio_feeding_update_event, codec_audio_config)); } @@ -1081,7 +1037,7 @@ static void btif_a2dp_source_audio_tx_flush_event(void) { static bool btif_a2dp_source_audio_tx_flush_req(void) { log::info("state={}", btif_a2dp_source_cb.StateStr()); - local_thread()->DoInThread(base::BindOnce(&btif_a2dp_source_audio_tx_flush_event)); + do_in_main_thread(base::BindOnce(&btif_a2dp_source_audio_tx_flush_event)); return true; } @@ -1267,9 +1223,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 +1274,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_av.cc b/system/btif/src/btif_av.cc index e4f784a39c..101ebcc4a0 100644 --- a/system/btif/src/btif_av.cc +++ b/system/btif/src/btif_av.cc @@ -2400,12 +2400,10 @@ bool BtifAvStateMachine::StateOpened::ProcessEvent(uint32_t event, void* p_data) std::promise<void> peer_ready_promise; std::future<void> peer_ready_future = peer_ready_promise.get_future(); - if (com::android::bluetooth::flags::a2dp_clear_pending_start_on_session_restart()) { - // The stream may not be restarted without an explicit request from the - // Bluetooth Audio HAL. Any start request that was pending before the - // reconfiguration is invalidated when the session is ended. - peer_.ClearFlags(BtifAvPeer::kFlagPendingStart); - } + // The stream may not be restarted without an explicit request from the + // Bluetooth Audio HAL. Any start request that was pending before the + // reconfiguration is invalidated when the session is ended. + peer_.ClearFlags(BtifAvPeer::kFlagPendingStart); btif_a2dp_source_start_session(peer_.PeerAddress(), std::move(peer_ready_promise)); } 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 808d9333aa..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" @@ -572,7 +571,11 @@ static void bond_state_changed(bt_status_t status, const RawAddress& bd_addr, if (pairing_cb.bond_type == BOND_TYPE_TEMPORARY) { state = BT_BOND_STATE_NONE; + } else if (com::android::bluetooth::flags::reset_security_flags_on_pairing_failure() && + state == BT_BOND_STATE_NONE) { + get_security_client_interface().BTM_SecClearSecurityFlags(bd_addr); } + log::info( "Bond state changed to state={}[0:none, 1:bonding, " "2:bonded],prev_state={}, sdp_attempts={}", @@ -3869,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_gatt_client.cc b/system/btif/src/btif_gatt_client.cc index c77af0e13d..cdd099d582 100644 --- a/system/btif/src/btif_gatt_client.cc +++ b/system/btif/src/btif_gatt_client.cc @@ -150,8 +150,18 @@ static void btif_gattc_upstreams_evt(uint16_t event, char* p_param) { } case BTA_GATTC_SEARCH_CMPL_EVT: { - HAL_CBACK(callbacks, client->search_complete_cb, - static_cast<int>(p_data->search_cmpl.conn_id), p_data->search_cmpl.status); + int conn_id = p_data->search_cmpl.conn_id; + tGATT_STATUS status = p_data->search_cmpl.status; + + log::debug("BTA_GATTC_SEARCH_CMPL_EVT GATT db ready conn_id={}, status={}", conn_id, status); + + btgatt_db_element_t* db = NULL; + int count = 0; + BTA_GATTC_GetGattDb(static_cast<tCONN_ID>(conn_id), 0x0000, 0xFFFF, &db, &count); + + auto callbacks = bt_gatt_callbacks; + HAL_CBACK(callbacks, client->get_gatt_db_cb, conn_id, db, count); + osi_free(db); break; } @@ -417,21 +427,6 @@ static void btif_gattc_discover_service_by_uuid(int conn_id, const Uuid& uuid) { do_in_jni_thread(Bind(&BTA_GATTC_DiscoverServiceByUuid, static_cast<tCONN_ID>(conn_id), uuid)); } -void btif_gattc_get_gatt_db_impl(int conn_id) { - btgatt_db_element_t* db = NULL; - int count = 0; - BTA_GATTC_GetGattDb(static_cast<tCONN_ID>(conn_id), 0x0000, 0xFFFF, &db, &count); - - auto callbacks = bt_gatt_callbacks; - HAL_CBACK(callbacks, client->get_gatt_db_cb, conn_id, db, count); - osi_free(db); -} - -static bt_status_t btif_gattc_get_gatt_db(int conn_id) { - CHECK_BTGATT_INIT(); - return do_in_jni_thread(Bind(&btif_gattc_get_gatt_db_impl, conn_id)); -} - void read_char_cb(uint16_t conn_id, tGATT_STATUS status, uint16_t handle, uint16_t len, uint8_t* value, void* /* data */) { btgatt_read_params_t params = { @@ -886,6 +881,5 @@ const btgatt_client_interface_t btgattClientInterface = { btif_gattc_set_preferred_phy, btif_gattc_read_phy, btif_gattc_test_command, - btif_gattc_get_gatt_db, btif_gattc_subrate_request, }; 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/btif/src/btif_metrics_logging.cc b/system/btif/src/btif_metrics_logging.cc index e116cebe28..40f2fed315 100644 --- a/system/btif/src/btif_metrics_logging.cc +++ b/system/btif/src/btif_metrics_logging.cc @@ -72,9 +72,13 @@ void log_read_tx_power_level_result(const RawAddress& address, uint16_t handle, void log_socket_connection_state(const RawAddress& address, int port, int type, android::bluetooth::SocketConnectionstateEnum connection_state, int64_t tx_bytes, int64_t rx_bytes, int uid, int server_port, - android::bluetooth::SocketRoleEnum socket_role) { - bluetooth::shim::LogMetricSocketConnectionState(address, port, type, connection_state, tx_bytes, - rx_bytes, uid, server_port, socket_role); + android::bluetooth::SocketRoleEnum socket_role, + uint64_t connection_duration_ms, + android::bluetooth::SocketErrorEnum error_code, + bool is_hardware_offload) { + bluetooth::shim::LogMetricSocketConnectionState( + address, port, type, connection_state, tx_bytes, rx_bytes, uid, server_port, socket_role, + connection_duration_ms, error_code, is_hardware_offload); } void log_counter_metrics_btif(android::bluetooth::CodePathCounterKeyEnum key, int64_t value) { diff --git a/system/btif/src/btif_sock.cc b/system/btif/src/btif_sock.cc index d58326e571..dae8f745c2 100644 --- a/system/btif/src/btif_sock.cc +++ b/system/btif/src/btif_sock.cc @@ -177,7 +177,8 @@ static bt_status_t btsock_listen(btsock_type_t type, const char* service_name, RawAddress::kEmpty, type, channel, app_uid, data_path, hub_id, endpoint_id, max_rx_packet_size); btif_sock_connection_logger(RawAddress::kEmpty, 0, type, SOCKET_CONNECTION_STATE_LISTENING, - SOCKET_ROLE_LISTEN, app_uid, channel, 0, 0, service_name); + SOCKET_ROLE_LISTEN, app_uid, channel, 0, 0, service_name, 0, + BTSOCK_ERROR_NONE, data_path); switch (type) { case BTSOCK_RFCOMM: status = btsock_rfc_listen(service_name, service_uuid, channel, sock_fd, flags, app_uid, @@ -207,7 +208,8 @@ static bt_status_t btsock_listen(btsock_type_t type, const char* service_name, "channel: {}, app_uid: {}", RawAddress::kEmpty, type, channel, app_uid); btif_sock_connection_logger(RawAddress::kEmpty, 0, type, SOCKET_CONNECTION_STATE_DISCONNECTED, - SOCKET_ROLE_LISTEN, app_uid, channel, 0, 0, service_name); + SOCKET_ROLE_LISTEN, app_uid, channel, 0, 0, service_name, 0, + BTSOCK_ERROR_LISTEN_FAILURE, data_path); } return status; } @@ -227,9 +229,9 @@ static bt_status_t btsock_connect(const RawAddress* bd_addr, btsock_type_t type, *sock_fd = INVALID_FD; bt_status_t status = BT_STATUS_SOCKET_ERROR; - btif_sock_connection_logger(*bd_addr, 0, type, SOCKET_CONNECTION_STATE_CONNECTING, - SOCKET_ROLE_CONNECTION, app_uid, channel, 0, 0, - uuid ? uuid->ToString().c_str() : ""); + btif_sock_connection_logger( + *bd_addr, 0, type, SOCKET_CONNECTION_STATE_CONNECTING, SOCKET_ROLE_CONNECTION, app_uid, + channel, 0, 0, uuid ? uuid->ToString().c_str() : "", 0, BTSOCK_ERROR_NONE, data_path); switch (type) { case BTSOCK_RFCOMM: status = btsock_rfc_connect(bd_addr, uuid, channel, sock_fd, flags, app_uid, data_path, @@ -261,7 +263,8 @@ static bt_status_t btsock_connect(const RawAddress* bd_addr, btsock_type_t type, *bd_addr, type, channel, app_uid); btif_sock_connection_logger(*bd_addr, 0, type, SOCKET_CONNECTION_STATE_DISCONNECTED, SOCKET_ROLE_CONNECTION, app_uid, channel, 0, 0, - uuid ? uuid->ToString().c_str() : ""); + uuid ? uuid->ToString().c_str() : "", 0, + BTSOCK_ERROR_CONNECTION_FAILURE, data_path); } return status; } diff --git a/system/btif/src/btif_sock_l2cap.cc b/system/btif/src/btif_sock_l2cap.cc index ac1099fec4..3867727cdb 100644 --- a/system/btif/src/btif_sock_l2cap.cc +++ b/system/btif/src/btif_sock_l2cap.cc @@ -35,6 +35,7 @@ #include "btif/include/btif_sock_thread.h" #include "btif/include/btif_sock_util.h" #include "btif/include/btif_uid.h" +#include "common/time_util.h" #include "gd/os/rand.h" #include "include/hardware/bluetooth.h" #include "internal_include/bt_target.h" @@ -92,6 +93,7 @@ typedef struct l2cap_socket { uint64_t hub_id; // ID of the hub to which the end point belongs uint64_t endpoint_id; // ID of the hub end point bool is_accepting; // is app accepting on server socket? + uint64_t connection_start_time_ms; // Timestamp when the connection state started } l2cap_socket; static void btsock_l2cap_server_listen(l2cap_socket* sock); @@ -238,7 +240,7 @@ static l2cap_socket* btsock_l2cap_find_by_conn_uuid_l(Uuid& conn_uuid) { return nullptr; } -static void btsock_l2cap_free_l(l2cap_socket* sock) { +static void btsock_l2cap_free_l(l2cap_socket* sock, btsock_error_code_t error_code) { uint8_t* buf; l2cap_socket* t = socks; @@ -258,7 +260,8 @@ static void btsock_l2cap_free_l(l2cap_socket* sock) { sock->addr, sock->id, sock->is_le_coc ? BTSOCK_L2CAP_LE : BTSOCK_L2CAP, SOCKET_CONNECTION_STATE_DISCONNECTED, sock->server ? SOCKET_ROLE_LISTEN : SOCKET_ROLE_CONNECTION, sock->app_uid, sock->channel, - sock->tx_bytes, sock->rx_bytes, sock->name); + sock->tx_bytes, sock->rx_bytes, sock->name, sock->connection_start_time_ms, error_code, + sock->data_path); if (com::android::bluetooth::flags::socket_settings_api()) { if (sock->data_path == BTSOCK_DATA_PATH_HARDWARE_OFFLOAD && !sock->server && sock->socket_id != 0) { @@ -359,6 +362,7 @@ static l2cap_socket* btsock_l2cap_alloc_l(const char* name, const RawAddress* ad sock->hub_id = 0; sock->endpoint_id = 0; sock->is_accepting = false; + sock->connection_start_time_ms = 0; if (name) { strncpy(sock->name, name, sizeof(sock->name) - 1); @@ -418,7 +422,7 @@ bt_status_t btsock_l2cap_cleanup() { std::unique_lock<std::mutex> lock(state_lock); pth = -1; while (socks) { - btsock_l2cap_free_l(socks); + btsock_l2cap_free_l(socks, BTSOCK_ERROR_NONE); } return BT_STATUS_SUCCESS; } @@ -500,7 +504,7 @@ static void on_srv_l2cap_listen_started(tBTA_JV_L2CAP_START* p_start, uint32_t i if (p_start->status != tBTA_JV_STATUS::SUCCESS) { log::error("Unable to start l2cap server socket_id:{}", sock->id); - btsock_l2cap_free_l(sock); + btsock_l2cap_free_l(sock, BTSOCK_ERROR_SERVER_START_FAILURE); return; } @@ -510,17 +514,17 @@ static void on_srv_l2cap_listen_started(tBTA_JV_L2CAP_START* p_start, uint32_t i "Listening for L2CAP connection for device: {}, channel: {}, app_uid: " "{}, id: {}, is_le: {}", sock->addr, sock->channel, sock->app_uid, sock->id, sock->is_le_coc); - btif_sock_connection_logger(sock->addr, sock->id, - sock->is_le_coc ? BTSOCK_L2CAP_LE : BTSOCK_L2CAP, - SOCKET_CONNECTION_STATE_LISTENING, - sock->server ? SOCKET_ROLE_LISTEN : SOCKET_ROLE_CONNECTION, - sock->app_uid, sock->channel, 0, 0, sock->name); + btif_sock_connection_logger( + sock->addr, sock->id, sock->is_le_coc ? BTSOCK_L2CAP_LE : BTSOCK_L2CAP, + SOCKET_CONNECTION_STATE_LISTENING, + sock->server ? SOCKET_ROLE_LISTEN : SOCKET_ROLE_CONNECTION, sock->app_uid, sock->channel, + 0, 0, sock->name, 0, BTSOCK_ERROR_NONE, sock->data_path); if (!sock->server_psm_sent) { if (!send_app_psm_or_chan_l(sock)) { // closed log::info("Unable to send socket to application socket_id:{}", sock->id); - btsock_l2cap_free_l(sock); + btsock_l2cap_free_l(sock, BTSOCK_ERROR_SEND_TO_APP_FAILURE); } else { sock->server_psm_sent = true; } @@ -539,7 +543,7 @@ static void on_cl_l2cap_init(tBTA_JV_L2CAP_CL_INIT* p_init, uint32_t id) { if (p_init->status != tBTA_JV_STATUS::SUCCESS) { log::error("Initialization status failed socket_id:{}", id); - btsock_l2cap_free_l(sock); + btsock_l2cap_free_l(sock, BTSOCK_ERROR_CLIENT_INIT_FAILURE); return; } @@ -587,13 +591,14 @@ static void on_srv_l2cap_psm_connect_l(tBTA_JV_L2CAP_OPEN* p_open, l2cap_socket* log::info( "Connected to L2CAP connection for device: {}, channel: {}, app_uid: {}, " "id: {}, is_le: {}, socket_id: {}, rx_mtu: {}", - sock->addr, sock->channel, sock->app_uid, sock->id, sock->is_le_coc, accept_rs->socket_id, - accept_rs->rx_mtu); - btif_sock_connection_logger(accept_rs->addr, accept_rs->id, - accept_rs->is_le_coc ? BTSOCK_L2CAP_LE : BTSOCK_L2CAP, - SOCKET_CONNECTION_STATE_CONNECTED, - accept_rs->server ? SOCKET_ROLE_LISTEN : SOCKET_ROLE_CONNECTION, - accept_rs->app_uid, accept_rs->channel, 0, 0, accept_rs->name); + accept_rs->addr, accept_rs->channel, accept_rs->app_uid, accept_rs->id, + accept_rs->is_le_coc, accept_rs->socket_id, accept_rs->rx_mtu); + btif_sock_connection_logger( + accept_rs->addr, accept_rs->id, accept_rs->is_le_coc ? BTSOCK_L2CAP_LE : BTSOCK_L2CAP, + SOCKET_CONNECTION_STATE_CONNECTED, + accept_rs->server ? SOCKET_ROLE_LISTEN : SOCKET_ROLE_CONNECTION, accept_rs->app_uid, + accept_rs->channel, 0, 0, accept_rs->name, 0, BTSOCK_ERROR_NONE, accept_rs->data_path); + accept_rs->connection_start_time_ms = common::time_gettimeofday_us() / 1000; // start monitor the socket btsock_thread_add_fd(pth, sock->our_fd, BTSOCK_L2CAP, SOCK_THREAD_FD_EXCEPTION, sock->id); @@ -638,11 +643,12 @@ static void on_cl_l2cap_psm_connect_l(tBTA_JV_L2CAP_OPEN* p_open, l2cap_socket* "id: {}, is_le: {}, socket_id: {}, rx_mtu: {}", sock->addr, sock->channel, sock->app_uid, sock->id, sock->is_le_coc, sock->socket_id, sock->rx_mtu); - btif_sock_connection_logger(sock->addr, sock->id, - sock->is_le_coc ? BTSOCK_L2CAP_LE : BTSOCK_L2CAP, - SOCKET_CONNECTION_STATE_CONNECTED, - sock->server ? SOCKET_ROLE_LISTEN : SOCKET_ROLE_CONNECTION, - sock->app_uid, sock->channel, 0, 0, sock->name); + btif_sock_connection_logger( + sock->addr, sock->id, sock->is_le_coc ? BTSOCK_L2CAP_LE : BTSOCK_L2CAP, + SOCKET_CONNECTION_STATE_CONNECTED, + sock->server ? SOCKET_ROLE_LISTEN : SOCKET_ROLE_CONNECTION, sock->app_uid, sock->channel, + 0, 0, sock->name, 0, BTSOCK_ERROR_NONE, sock->data_path); + sock->connection_start_time_ms = common::time_gettimeofday_us() / 1000; // start monitoring the socketpair to get call back when app writing data btsock_thread_add_fd(pth, sock->our_fd, BTSOCK_L2CAP, SOCK_THREAD_FD_RD, sock->id); @@ -679,7 +685,7 @@ static void on_l2cap_connect(tBTA_JV* p_data, uint32_t id) { } } else { log::error("Unable to open socket after receiving connection socket_id:{}", sock->id); - btsock_l2cap_free_l(sock); + btsock_l2cap_free_l(sock, BTSOCK_ERROR_OPEN_FAILURE); } } @@ -697,11 +703,11 @@ static void on_l2cap_close(tBTA_JV_L2CAP_CLOSE* p_close, uint32_t id) { "Disconnecting from L2CAP connection for device: {}, channel: {}, " "app_uid: {}, id: {}, is_le: {}", sock->addr, sock->channel, sock->app_uid, sock->id, sock->is_le_coc); - btif_sock_connection_logger(sock->addr, sock->id, - sock->is_le_coc ? BTSOCK_L2CAP_LE : BTSOCK_L2CAP, - SOCKET_CONNECTION_STATE_DISCONNECTING, - sock->server ? SOCKET_ROLE_LISTEN : SOCKET_ROLE_CONNECTION, - sock->app_uid, sock->channel, 0, 0, sock->name); + btif_sock_connection_logger( + sock->addr, sock->id, sock->is_le_coc ? BTSOCK_L2CAP_LE : BTSOCK_L2CAP, + SOCKET_CONNECTION_STATE_DISCONNECTING, + sock->server ? SOCKET_ROLE_LISTEN : SOCKET_ROLE_CONNECTION, sock->app_uid, sock->channel, + 0, 0, sock->name, 0, BTSOCK_ERROR_NONE, sock->data_path); if (com::android::bluetooth::flags::donot_push_error_code_to_app_when_connected()) { if (!sock->connected) { if (!send_app_err_code(sock, p_close->reason)) { @@ -720,7 +726,7 @@ static void on_l2cap_close(tBTA_JV_L2CAP_CLOSE* p_close, uint32_t id) { if (sock->server) { BTA_JvFreeChannel(sock->channel, tBTA_JV_CONN_TYPE::L2CAP); } - btsock_l2cap_free_l(sock); + btsock_l2cap_free_l(sock, BTSOCK_ERROR_NONE); } static void on_l2cap_outgoing_congest(tBTA_JV_L2CAP_CONG* p, uint32_t id) { @@ -786,7 +792,7 @@ static void on_l2cap_data_ind(tBTA_JV* /* evt */, uint32_t id) { } else { // connection must be dropped log::warn("Closing socket as unable to push data to socket socket_id:{}", sock->id); BTA_JvL2capClose(sock->handle); - btsock_l2cap_free_l(sock); + btsock_l2cap_free_l(sock, BTSOCK_ERROR_RECEIVE_DATA_FAILURE); return; } } @@ -1151,6 +1157,7 @@ static bool btsock_l2cap_read_signaled_on_listen_socket(int fd, int /* flags */, static void btsock_l2cap_signaled_flagged(int fd, int flags, uint32_t user_id) { char drop_it = false; + btsock_error_code_t error_code = BTSOCK_ERROR_NONE; /* We use MSG_DONTWAIT when sending data to JAVA, hence it can be accepted to * hold the lock. */ @@ -1163,11 +1170,13 @@ static void btsock_l2cap_signaled_flagged(int fd, int flags, uint32_t user_id) { if (!sock->server) { // app sending data on connection socket if (!btsock_l2cap_read_signaled_on_connected_socket(fd, flags, user_id, sock)) { + error_code = BTSOCK_ERROR_READ_SIGNALED_FAILURE; drop_it = true; } } else { // app sending signal on listen socket if (!btsock_l2cap_read_signaled_on_listen_socket(fd, flags, user_id, sock)) { + error_code = BTSOCK_ERROR_READ_SIGNALED_FAILURE; drop_it = true; } } @@ -1181,7 +1190,7 @@ static void btsock_l2cap_signaled_flagged(int fd, int flags, uint32_t user_id) { if (drop_it || (flags & SOCK_THREAD_FD_EXCEPTION)) { int size = 0; if (drop_it || ioctl(sock->our_fd, FIONREAD, &size) != 0 || size == 0) { - btsock_l2cap_free_l(sock); + btsock_l2cap_free_l(sock, error_code); } } } @@ -1192,6 +1201,7 @@ void btsock_l2cap_signaled(int fd, int flags, uint32_t user_id) { return; } char drop_it = false; + btsock_error_code_t error_code = BTSOCK_ERROR_NONE; /* We use MSG_DONTWAIT when sending data to JAVA, hence it can be accepted to * hold the lock. */ @@ -1238,6 +1248,7 @@ void btsock_l2cap_signaled(int fd, int flags, uint32_t user_id) { BTA_JvL2capWrite(sock->handle, PTR_TO_UINT(buffer), buffer, user_id); } } else { + error_code = BTSOCK_ERROR_READ_SIGNALED_FAILURE; drop_it = true; } } @@ -1250,7 +1261,7 @@ void btsock_l2cap_signaled(int fd, int flags, uint32_t user_id) { if (drop_it || (flags & SOCK_THREAD_FD_EXCEPTION)) { int size = 0; if (drop_it || ioctl(sock->our_fd, FIONREAD, &size) != 0 || size == 0) { - btsock_l2cap_free_l(sock); + btsock_l2cap_free_l(sock, error_code); } } } @@ -1269,7 +1280,7 @@ bt_status_t btsock_l2cap_disconnect(const RawAddress* bd_addr) { while (sock) { l2cap_socket* next = sock->next; if (sock->addr == *bd_addr) { - btsock_l2cap_free_l(sock); + btsock_l2cap_free_l(sock, BTSOCK_ERROR_NONE); } sock = next; } @@ -1343,7 +1354,7 @@ void on_btsocket_l2cap_opened_complete(uint64_t socket_id, bool success) { } if (!success) { log::error("L2CAP opened complete failed with socket_id:{}", socket_id); - btsock_l2cap_free_l(sock); + btsock_l2cap_free_l(sock, BTSOCK_ERROR_OPEN_FAILURE); return; } // If the socket was accepted from listen socket, use listen_fd. @@ -1368,11 +1379,12 @@ void on_btsocket_l2cap_opened_complete(uint64_t socket_id, bool success) { "is_le: {}, socket_id: {}, rx_mtu: {}", sock->addr, sock->channel, sock->app_uid, sock->id, sock->is_le_coc, sock->socket_id, sock->rx_mtu); - btif_sock_connection_logger(sock->addr, sock->id, - sock->is_le_coc ? BTSOCK_L2CAP_LE : BTSOCK_L2CAP, - SOCKET_CONNECTION_STATE_CONNECTED, - sock->server ? SOCKET_ROLE_LISTEN : SOCKET_ROLE_CONNECTION, - sock->app_uid, sock->channel, 0, 0, sock->name); + btif_sock_connection_logger( + sock->addr, sock->id, sock->is_le_coc ? BTSOCK_L2CAP_LE : BTSOCK_L2CAP, + SOCKET_CONNECTION_STATE_CONNECTED, + sock->server ? SOCKET_ROLE_LISTEN : SOCKET_ROLE_CONNECTION, sock->app_uid, + sock->channel, 0, 0, sock->name, 0, BTSOCK_ERROR_NONE, sock->data_path); + sock->connection_start_time_ms = common::time_gettimeofday_us() / 1000; log::info("Connected l2cap socket socket_id:{}", sock->id); sock->connected = true; @@ -1389,7 +1401,7 @@ void on_btsocket_l2cap_close(uint64_t socket_id) { return; } log::info("L2CAP close request for socket_id:{}", socket_id); - btsock_l2cap_free_l(sock); + btsock_l2cap_free_l(sock, BTSOCK_ERROR_NONE); } static void on_cl_l2cap_psm_connect_offload_l(tBTA_JV_L2CAP_OPEN* p_open, l2cap_socket* sock) { @@ -1407,11 +1419,12 @@ static void on_cl_l2cap_psm_connect_offload_l(tBTA_JV_L2CAP_OPEN* p_open, l2cap_ "id: {}, is_le: {}, socket_id: {}, rx_mtu: {}", sock->addr, sock->channel, sock->app_uid, sock->id, sock->is_le_coc, sock->socket_id, sock->rx_mtu); - btif_sock_connection_logger(sock->addr, sock->id, - sock->is_le_coc ? BTSOCK_L2CAP_LE : BTSOCK_L2CAP, - SOCKET_CONNECTION_STATE_CONNECTED, - sock->server ? SOCKET_ROLE_LISTEN : SOCKET_ROLE_CONNECTION, - sock->app_uid, sock->channel, 0, 0, sock->name); + btif_sock_connection_logger( + sock->addr, sock->id, sock->is_le_coc ? BTSOCK_L2CAP_LE : BTSOCK_L2CAP, + SOCKET_CONNECTION_STATE_CONNECTED, + sock->server ? SOCKET_ROLE_LISTEN : SOCKET_ROLE_CONNECTION, sock->app_uid, sock->channel, + 0, 0, sock->name, 0, BTSOCK_ERROR_NONE, sock->data_path); + sock->connection_start_time_ms = common::time_gettimeofday_us() / 1000; bluetooth::hal::SocketContext socket_context = { .socket_id = sock->socket_id, @@ -1426,7 +1439,7 @@ static void on_cl_l2cap_psm_connect_offload_l(tBTA_JV_L2CAP_OPEN* p_open, l2cap_ }; if (!bluetooth::shim::GetLppOffloadManager()->SocketOpened(socket_context)) { log::warn("L2CAP socket opened failed. Disconnect the incoming connection."); - btsock_l2cap_free_l(sock); + btsock_l2cap_free_l(sock, BTSOCK_ERROR_OFFLOAD_HAL_OPEN_FAILURE); } else { log::info( "L2CAP socket opened successful. Will send connect signal in " @@ -1468,13 +1481,14 @@ static void on_srv_l2cap_psm_connect_offload_l(tBTA_JV_L2CAP_OPEN* p_open, l2cap log::info( "Connected to L2CAP connection for device: {}, channel: {}, app_uid: {}, " "id: {}, is_le: {}, socket_id: {}, rx_mtu: {}", - sock->addr, sock->channel, sock->app_uid, sock->id, sock->is_le_coc, accept_rs->socket_id, - accept_rs->rx_mtu); - btif_sock_connection_logger(accept_rs->addr, accept_rs->id, - accept_rs->is_le_coc ? BTSOCK_L2CAP_LE : BTSOCK_L2CAP, - SOCKET_CONNECTION_STATE_CONNECTED, - accept_rs->server ? SOCKET_ROLE_LISTEN : SOCKET_ROLE_CONNECTION, - accept_rs->app_uid, accept_rs->channel, 0, 0, accept_rs->name); + accept_rs->addr, accept_rs->channel, accept_rs->app_uid, accept_rs->id, + accept_rs->is_le_coc, accept_rs->socket_id, accept_rs->rx_mtu); + btif_sock_connection_logger( + accept_rs->addr, accept_rs->id, accept_rs->is_le_coc ? BTSOCK_L2CAP_LE : BTSOCK_L2CAP, + SOCKET_CONNECTION_STATE_CONNECTED, + accept_rs->server ? SOCKET_ROLE_LISTEN : SOCKET_ROLE_CONNECTION, accept_rs->app_uid, + accept_rs->channel, 0, 0, accept_rs->name, 0, BTSOCK_ERROR_NONE, accept_rs->data_path); + accept_rs->connection_start_time_ms = common::time_gettimeofday_us() / 1000; bluetooth::hal::SocketContext socket_context = { .socket_id = accept_rs->socket_id, @@ -1489,10 +1503,10 @@ static void on_srv_l2cap_psm_connect_offload_l(tBTA_JV_L2CAP_OPEN* p_open, l2cap }; if (!sock->is_accepting) { log::warn("Server socket is not accepting. Disconnect the incoming connection."); - btsock_l2cap_free_l(accept_rs); + btsock_l2cap_free_l(accept_rs, BTSOCK_ERROR_OFFLOAD_SERVER_NOT_ACCEPTING); } else if (!bluetooth::shim::GetLppOffloadManager()->SocketOpened(socket_context)) { log::warn("L2CAP socket opened failed. Disconnect the incoming connection."); - btsock_l2cap_free_l(accept_rs); + btsock_l2cap_free_l(accept_rs, BTSOCK_ERROR_OFFLOAD_HAL_OPEN_FAILURE); } else { log::info("L2CAP socket opened successful. Will send connect signal in async callback."); } diff --git a/system/btif/src/btif_sock_logging.cc b/system/btif/src/btif_sock_logging.cc index acb38f7de5..111e52002b 100644 --- a/system/btif/src/btif_sock_logging.cc +++ b/system/btif/src/btif_sock_logging.cc @@ -25,6 +25,7 @@ #include "btif/include/btif_metrics_logging.h" #include "btif/include/btif_sock.h" +#include "common/time_util.h" #include "types/raw_address.h" #define SOCK_LOGGER_SIZE_MAX 16 @@ -50,11 +51,15 @@ static SockConnectionEvent connection_logger[SOCK_LOGGER_SIZE_MAX]; static android::bluetooth::SocketConnectionstateEnum toConnectionStateEnum(int state); static android::bluetooth::SocketRoleEnum toSocketRoleEnum(int role); +static android::bluetooth::SocketErrorEnum toSocketErrorEnum(btsock_error_code_t error_code); +static uint64_t getConnectionDuration(uint64_t start_time_ms); void btif_sock_connection_logger(const RawAddress& address, int port, int type, int state, int role, int uid, int server_port, int64_t tx_bytes, int64_t rx_bytes, - const char* server_name) { - log::verbose("bd_addr: {}, port: {}, role: {}, state: {}", address, port, role, state); + const char* server_name, uint64_t connection_start_time_ms, + btsock_error_code_t error_code, btsock_data_path_t data_path) { + log::verbose("bd_addr: {}, port: {}, role: {}, state: {}, data_path: {}", address, port, role, + state, data_path); uint8_t index = logger_index++ % SOCK_LOGGER_SIZE_MAX; @@ -74,8 +79,10 @@ void btif_sock_connection_logger(const RawAddress& address, int port, int type, } clock_gettime(CLOCK_REALTIME, &connection_logger[index].timestamp); - log_socket_connection_state(address, port, type, toConnectionStateEnum(state), tx_bytes, rx_bytes, - uid, server_port, toSocketRoleEnum(role)); + log_socket_connection_state( + address, port, type, toConnectionStateEnum(state), tx_bytes, rx_bytes, uid, server_port, + toSocketRoleEnum(role), getConnectionDuration(connection_start_time_ms), + toSocketErrorEnum(error_code), data_path == BTSOCK_DATA_PATH_HARDWARE_OFFLOAD); } void btif_sock_dump(int fd) { @@ -192,3 +199,54 @@ static android::bluetooth::SocketRoleEnum toSocketRoleEnum(int role) { } return android::bluetooth::SOCKET_ROLE_UNKNOWN; } + +static android::bluetooth::SocketErrorEnum toSocketErrorEnum(btsock_error_code_t error_code) { + switch (error_code) { + case BTSOCK_ERROR_NONE: + return android::bluetooth::SocketErrorEnum::SOCKET_ERROR_NONE; + case BTSOCK_ERROR_SERVER_START_FAILURE: + return android::bluetooth::SocketErrorEnum::SOCKET_ERROR_SERVER_START_FAILURE; + case BTSOCK_ERROR_CLIENT_INIT_FAILURE: + return android::bluetooth::SocketErrorEnum::SOCKET_ERROR_CLIENT_INIT_FAILURE; + case BTSOCK_ERROR_LISTEN_FAILURE: + return android::bluetooth::SocketErrorEnum::SOCKET_ERROR_LISTEN_FAILURE; + case BTSOCK_ERROR_CONNECTION_FAILURE: + return android::bluetooth::SocketErrorEnum::SOCKET_ERROR_CONNECTION_FAILURE; + case BTSOCK_ERROR_OPEN_FAILURE: + return android::bluetooth::SocketErrorEnum::SOCKET_ERROR_OPEN_FAILURE; + case BTSOCK_ERROR_OFFLOAD_SERVER_NOT_ACCEPTING: + return android::bluetooth::SocketErrorEnum::SOCKET_ERROR_OFFLOAD_SERVER_NOT_ACCEPTING; + case BTSOCK_ERROR_OFFLOAD_HAL_OPEN_FAILURE: + return android::bluetooth::SocketErrorEnum::SOCKET_ERROR_OFFLOAD_HAL_OPEN_FAILURE; + case BTSOCK_ERROR_SEND_TO_APP_FAILURE: + return android::bluetooth::SocketErrorEnum::SOCKET_ERROR_SEND_TO_APP_FAILURE; + case BTSOCK_ERROR_RECEIVE_DATA_FAILURE: + return android::bluetooth::SocketErrorEnum::SOCKET_ERROR_RECEIVE_DATA_FAILURE; + case BTSOCK_ERROR_READ_SIGNALED_FAILURE: + return android::bluetooth::SocketErrorEnum::SOCKET_ERROR_READ_SIGNALED_FAILURE; + case BTSOCK_ERROR_WRITE_SIGNALED_FAILURE: + return android::bluetooth::SocketErrorEnum::SOCKET_ERROR_WRITE_SIGNALED_FAILURE; + case BTSOCK_ERROR_SEND_SCN_FAILURE: + return android::bluetooth::SocketErrorEnum::SOCKET_ERROR_SEND_SCN_FAILURE; + case BTSOCK_ERROR_SCN_ALLOCATION_FAILURE: + return android::bluetooth::SocketErrorEnum::SOCKET_ERROR_SCN_ALLOCATION_FAILURE; + case BTSOCK_ERROR_ADD_SDP_FAILURE: + return android::bluetooth::SocketErrorEnum::SOCKET_ERROR_ADD_SDP_FAILURE; + case BTSOCK_ERROR_SDP_DISCOVERY_FAILURE: + return android::bluetooth::SocketErrorEnum::SOCKET_ERROR_SDP_DISCOVERY_FAILURE; + } + return android::bluetooth::SocketErrorEnum::SOCKET_ERROR_NONE; +} + +static uint64_t getConnectionDuration(uint64_t start_time_ms) { + // start time is 0 before the connection state, use 0 for duration + if (start_time_ms == 0) { + return 0; + } + uint64_t current_time_ms = common::time_gettimeofday_us() / 1000; + if (current_time_ms <= start_time_ms) { + log::warn("Socket connection end time is not greater than start time, logging 0 ms instead"); + return 0; + } + return current_time_ms - start_time_ms; +} diff --git a/system/btif/src/btif_sock_rfc.cc b/system/btif/src/btif_sock_rfc.cc index 8af6a1bcf6..4c75b0f355 100644 --- a/system/btif/src/btif_sock_rfc.cc +++ b/system/btif/src/btif_sock_rfc.cc @@ -106,6 +106,7 @@ typedef struct { uint64_t hub_id; // ID of the hub to which the end point belongs uint64_t endpoint_id; // ID of the hub end point bool is_accepting; // is app accepting on server socket? + uint64_t connection_start_time_ms; // Timestamp when the connection state started } rfc_slot_t; static rfc_slot_t rfc_slots[MAX_RFC_CHANNEL]; @@ -115,7 +116,7 @@ static std::recursive_mutex slot_lock; static uid_set_t* uid_set = NULL; static rfc_slot_t* find_free_slot(void); -static void cleanup_rfc_slot(rfc_slot_t* rs); +static void cleanup_rfc_slot(rfc_slot_t* rs, btsock_error_code_t error_code); static void jv_dm_cback(tBTA_JV_EVT event, tBTA_JV* p_data, uint32_t id); static uint32_t rfcomm_cback(tBTA_JV_EVT event, tBTA_JV* p_data, uint32_t rfcomm_slot_id); static bool send_app_scn(rfc_slot_t* rs); @@ -152,7 +153,7 @@ void btsock_rfc_cleanup(void) { std::unique_lock<std::recursive_mutex> lock(slot_lock); for (size_t i = 0; i < ARRAY_SIZE(rfc_slots); ++i) { if (rfc_slots[i].id) { - cleanup_rfc_slot(&rfc_slots[i]); + cleanup_rfc_slot(&rfc_slots[i], BTSOCK_ERROR_NONE); } list_free(rfc_slots[i].incoming_queue); rfc_slots[i].incoming_queue = NULL; @@ -251,6 +252,7 @@ static rfc_slot_t* alloc_rfc_slot(const RawAddress* addr, const char* name, cons slot->hub_id = 0; slot->endpoint_id = 0; slot->is_accepting = false; + slot->connection_start_time_ms = 0; slot->is_service_uuid_valid = !uuid.IsEmpty(); slot->service_uuid = uuid; @@ -466,13 +468,13 @@ bt_status_t btsock_rfc_connect(const RawAddress* bd_addr, const Uuid* service_uu if (ret != tBTA_JV_STATUS::SUCCESS) { log::error("unable to initiate RFCOMM connection. status:{}, scn:{}, bd_addr:{}", bta_jv_status_text(ret), slot->scn, slot->addr); - cleanup_rfc_slot(slot); + cleanup_rfc_slot(slot, BTSOCK_ERROR_CONNECTION_FAILURE); return BT_STATUS_SOCKET_ERROR; } if (!send_app_scn(slot)) { log::error("send_app_scn() failed, closing slot_id:{}", slot->id); - cleanup_rfc_slot(slot); + cleanup_rfc_slot(slot, BTSOCK_ERROR_SEND_SCN_FAILURE); return BT_STATUS_SOCKET_ERROR; } } else { @@ -535,7 +537,7 @@ static void free_rfc_slot_scn(rfc_slot_t* slot) { slot->scn = 0; } -static void cleanup_rfc_slot(rfc_slot_t* slot) { +static void cleanup_rfc_slot(rfc_slot_t* slot, btsock_error_code_t error_code) { if (slot->fd != INVALID_FD) { shutdown(slot->fd, SHUT_RDWR); close(slot->fd); @@ -547,7 +549,8 @@ static void cleanup_rfc_slot(rfc_slot_t* slot) { slot->addr, slot->id, BTSOCK_RFCOMM, SOCKET_CONNECTION_STATE_DISCONNECTED, slot->f.server ? SOCKET_ROLE_LISTEN : SOCKET_ROLE_CONNECTION, slot->app_uid, slot->scn, slot->tx_bytes, slot->rx_bytes, - slot->role ? slot->service_name : slot->service_uuid.ToString().c_str()); + slot->role ? slot->service_name : slot->service_uuid.ToString().c_str(), + slot->connection_start_time_ms, error_code, slot->data_path); slot->fd = INVALID_FD; @@ -625,7 +628,7 @@ static void on_cl_rfc_init(tBTA_JV_RFCOMM_CL_INIT* p_init, uint32_t id) { } else if (p_init->status != tBTA_JV_STATUS::SUCCESS) { log::warn("INIT unsuccessful, status {}. Cleaning up slot_id {}", bta_jv_status_text(p_init->status), slot->id); - cleanup_rfc_slot(slot); + cleanup_rfc_slot(slot, BTSOCK_ERROR_CLIENT_INIT_FAILURE); } else { slot->rfc_handle = p_init->handle; } @@ -640,7 +643,7 @@ static void on_srv_rfc_listen_started(tBTA_JV_RFCOMM_START* p_start, uint32_t id } else if (p_start->status != tBTA_JV_STATUS::SUCCESS) { log::warn("START unsuccessful, status {}. Cleaning up slot_id {}", bta_jv_status_text(p_start->status), slot->id); - cleanup_rfc_slot(slot); + cleanup_rfc_slot(slot, BTSOCK_ERROR_SERVER_START_FAILURE); return; } @@ -649,14 +652,13 @@ static void on_srv_rfc_listen_started(tBTA_JV_RFCOMM_START* p_start, uint32_t id "listening for RFCOMM socket connections for device: {}, scn: {}, " "app_uid: {}, id: {}", slot->addr, slot->scn, slot->app_uid, id); - btif_sock_connection_logger(slot->addr, slot->id, BTSOCK_RFCOMM, - SOCKET_CONNECTION_STATE_LISTENING, - slot->f.server ? SOCKET_ROLE_LISTEN : SOCKET_ROLE_CONNECTION, - slot->app_uid, slot->scn, 0, 0, slot->service_name); + btif_sock_connection_logger( + slot->addr, slot->id, BTSOCK_RFCOMM, SOCKET_CONNECTION_STATE_LISTENING, + slot->f.server ? SOCKET_ROLE_LISTEN : SOCKET_ROLE_CONNECTION, slot->app_uid, slot->scn, 0, + 0, slot->service_name, 0, BTSOCK_ERROR_NONE, slot->data_path); } -static uint32_t on_srv_rfc_connect_offload(tBTA_JV_RFCOMM_SRV_OPEN* p_open, uint32_t id, - rfc_slot_t* srv_rs) { +static uint32_t on_srv_rfc_connect_offload(tBTA_JV_RFCOMM_SRV_OPEN* p_open, rfc_slot_t* srv_rs) { rfc_slot_t* accept_rs; accept_rs = create_srv_accept_rfc_slot(srv_rs, &p_open->rem_bda, p_open->handle, p_open->new_listen_handle); @@ -667,11 +669,13 @@ static uint32_t on_srv_rfc_connect_offload(tBTA_JV_RFCOMM_SRV_OPEN* p_open, uint log::info( "connected to RFCOMM socket connections for device: {}, scn: {}, " "app_uid: {}, id: {}, socket_id: {}", - accept_rs->addr, accept_rs->scn, accept_rs->app_uid, id, accept_rs->socket_id); + accept_rs->addr, accept_rs->scn, accept_rs->app_uid, accept_rs->id, accept_rs->socket_id); btif_sock_connection_logger(accept_rs->addr, accept_rs->id, BTSOCK_RFCOMM, SOCKET_CONNECTION_STATE_CONNECTED, accept_rs->f.server ? SOCKET_ROLE_LISTEN : SOCKET_ROLE_CONNECTION, - accept_rs->app_uid, accept_rs->scn, 0, 0, accept_rs->service_name); + accept_rs->app_uid, accept_rs->scn, 0, 0, accept_rs->service_name, 0, + BTSOCK_ERROR_NONE, accept_rs->data_path); + accept_rs->connection_start_time_ms = common::time_gettimeofday_us() / 1000; bluetooth::hal::SocketContext socket_context = { .socket_id = accept_rs->socket_id, @@ -686,10 +690,10 @@ static uint32_t on_srv_rfc_connect_offload(tBTA_JV_RFCOMM_SRV_OPEN* p_open, uint }; if (!srv_rs->is_accepting) { log::warn("Server socket is not accepting. Disconnect the incoming connection."); - cleanup_rfc_slot(accept_rs); + cleanup_rfc_slot(accept_rs, BTSOCK_ERROR_OFFLOAD_SERVER_NOT_ACCEPTING); } else if (!bluetooth::shim::GetLppOffloadManager()->SocketOpened(socket_context)) { log::warn("RFCOMM socket opened failed. Disconnect the incoming connection."); - cleanup_rfc_slot(accept_rs); + cleanup_rfc_slot(accept_rs, BTSOCK_ERROR_OFFLOAD_HAL_OPEN_FAILURE); } else { log::info("RFCOMM socket opened successful. Will send connect signal in async callback."); } @@ -713,7 +717,7 @@ static uint32_t on_srv_rfc_connect(tBTA_JV_RFCOMM_SRV_OPEN* p_open, uint32_t id) if (com::android::bluetooth::flags::socket_settings_api() && srv_rs->data_path == BTSOCK_DATA_PATH_HARDWARE_OFFLOAD) { - return on_srv_rfc_connect_offload(p_open, id, srv_rs); + return on_srv_rfc_connect_offload(p_open, srv_rs); } accept_rs = create_srv_accept_rfc_slot(srv_rs, &p_open->rem_bda, p_open->handle, @@ -725,11 +729,13 @@ static uint32_t on_srv_rfc_connect(tBTA_JV_RFCOMM_SRV_OPEN* p_open, uint32_t id) log::info( "connected to RFCOMM socket connections for device: {}, scn: {}, " "app_uid: {}, slot_id: {}, socket_id: {}", - accept_rs->addr, accept_rs->scn, accept_rs->app_uid, id, accept_rs->socket_id); + accept_rs->addr, accept_rs->scn, accept_rs->app_uid, accept_rs->id, accept_rs->socket_id); btif_sock_connection_logger(accept_rs->addr, accept_rs->id, BTSOCK_RFCOMM, SOCKET_CONNECTION_STATE_CONNECTED, accept_rs->f.server ? SOCKET_ROLE_LISTEN : SOCKET_ROLE_CONNECTION, - accept_rs->app_uid, accept_rs->scn, 0, 0, accept_rs->service_name); + accept_rs->app_uid, accept_rs->scn, 0, 0, accept_rs->service_name, 0, + BTSOCK_ERROR_NONE, accept_rs->data_path); + accept_rs->connection_start_time_ms = common::time_gettimeofday_us() / 1000; // Start monitoring the socket. btsock_thread_add_fd(pth, srv_rs->fd, BTSOCK_RFCOMM, SOCK_THREAD_FD_EXCEPTION, srv_rs->id); @@ -744,7 +750,7 @@ static uint32_t on_srv_rfc_connect(tBTA_JV_RFCOMM_SRV_OPEN* p_open, uint32_t id) return srv_rs->id; } -static void on_cli_rfc_connect_offload(tBTA_JV_RFCOMM_OPEN* p_open, uint32_t id, rfc_slot_t* slot) { +static void on_cli_rfc_connect_offload(tBTA_JV_RFCOMM_OPEN* p_open, rfc_slot_t* slot) { slot->rfc_port_handle = BTA_JvRfcommGetPortHdl(p_open->handle); slot->addr = p_open->rem_bda; slot->socket_id = btif_rfc_sock_generate_socket_id(); @@ -752,11 +758,12 @@ static void on_cli_rfc_connect_offload(tBTA_JV_RFCOMM_OPEN* p_open, uint32_t id, log::info( "connected to RFCOMM socket connections for device: {}, scn: {}, " "app_uid: {}, id: {}, socket_id: {}", - slot->addr, slot->scn, slot->app_uid, id, slot->socket_id); + slot->addr, slot->scn, slot->app_uid, slot->id, slot->socket_id); btif_sock_connection_logger( slot->addr, slot->id, BTSOCK_RFCOMM, SOCKET_CONNECTION_STATE_CONNECTED, slot->f.server ? SOCKET_ROLE_LISTEN : SOCKET_ROLE_CONNECTION, slot->app_uid, slot->scn, 0, - 0, slot->service_uuid.ToString().c_str()); + 0, slot->service_uuid.ToString().c_str(), 0, BTSOCK_ERROR_NONE, slot->data_path); + slot->connection_start_time_ms = common::time_gettimeofday_us() / 1000; bluetooth::hal::SocketContext socket_context = { .socket_id = slot->socket_id, @@ -771,7 +778,7 @@ static void on_cli_rfc_connect_offload(tBTA_JV_RFCOMM_OPEN* p_open, uint32_t id, }; if (!bluetooth::shim::GetLppOffloadManager()->SocketOpened(socket_context)) { log::warn("RFCOMM socket opened failed. Disconnect the incoming connection."); - cleanup_rfc_slot(slot); + cleanup_rfc_slot(slot, BTSOCK_ERROR_OFFLOAD_HAL_OPEN_FAILURE); } else { log::info( "RFCOMM socket opened successful. Will send connect signal in " @@ -791,13 +798,13 @@ static void on_cli_rfc_connect(tBTA_JV_RFCOMM_OPEN* p_open, uint32_t id) { if (p_open->status != tBTA_JV_STATUS::SUCCESS) { log::warn("CONNECT unsuccessful, status {}. Cleaning up slot_id {}", bta_jv_status_text(p_open->status), slot->id); - cleanup_rfc_slot(slot); + cleanup_rfc_slot(slot, BTSOCK_ERROR_CONNECTION_FAILURE); return; } if (com::android::bluetooth::flags::socket_settings_api() && slot->data_path == BTSOCK_DATA_PATH_HARDWARE_OFFLOAD) { - on_cli_rfc_connect_offload(p_open, id, slot); + on_cli_rfc_connect_offload(p_open, slot); return; } @@ -808,11 +815,12 @@ static void on_cli_rfc_connect(tBTA_JV_RFCOMM_OPEN* p_open, uint32_t id) { log::info( "connected to RFCOMM socket connections for device: {}, scn: {}, " "app_uid: {}, id: {}, socket_id: {}", - slot->addr, slot->scn, slot->app_uid, id, slot->socket_id); + slot->addr, slot->scn, slot->app_uid, slot->id, slot->socket_id); btif_sock_connection_logger( slot->addr, slot->id, BTSOCK_RFCOMM, SOCKET_CONNECTION_STATE_CONNECTED, slot->f.server ? SOCKET_ROLE_LISTEN : SOCKET_ROLE_CONNECTION, slot->app_uid, slot->scn, 0, - 0, slot->service_uuid.ToString().c_str()); + 0, slot->service_uuid.ToString().c_str(), 0, BTSOCK_ERROR_NONE, slot->data_path); + slot->connection_start_time_ms = common::time_gettimeofday_us() / 1000; if (send_app_connect_signal(slot->fd, &slot->addr, slot->scn, 0, -1, slot->socket_id)) { slot->f.connected = true; @@ -848,7 +856,7 @@ void on_btsocket_rfc_opened_complete(uint64_t socket_id, bool success) { } if (!success) { log::error("RFCOMM opened complete failed with socket_id: {}", socket_id); - cleanup_rfc_slot(slot); + cleanup_rfc_slot(slot, BTSOCK_ERROR_OPEN_FAILURE); return; } // If the socket was accepted from listen socket, use listen_fd. @@ -878,7 +886,7 @@ void on_btsocket_rfc_close(uint64_t socket_id) { return; } log::info("RFCOMM close request for socket_id: {}", socket_id); - cleanup_rfc_slot(slot); + cleanup_rfc_slot(slot, BTSOCK_ERROR_NONE); } // TODO(b/380189525): Replace the randomized socket ID with static counter when we don't have @@ -905,8 +913,9 @@ static void on_rfc_close(tBTA_JV_RFCOMM_CLOSE* /* p_close */, uint32_t id) { android::bluetooth::SOCKET_CONNECTION_STATE_DISCONNECTING, 0, 0, slot->app_uid, slot->scn, slot->f.server ? android::bluetooth::SOCKET_ROLE_LISTEN - : android::bluetooth::SOCKET_ROLE_CONNECTION); - cleanup_rfc_slot(slot); + : android::bluetooth::SOCKET_ROLE_CONNECTION, + 0, android::bluetooth::SOCKET_ERROR_NONE, slot->data_path); + cleanup_rfc_slot(slot, BTSOCK_ERROR_NONE); } static void on_rfc_write_done(tBTA_JV_RFCOMM_WRITE* p, uint32_t id) { @@ -1011,7 +1020,7 @@ static void jv_dm_cback(tBTA_JV_EVT event, tBTA_JV* p_data, uint32_t id) { if (p_data->scn == 0) { log::error("Unable to allocate scn: all resources exhausted. slot found: {}", std::format_ptr(rs)); - cleanup_rfc_slot(rs); + cleanup_rfc_slot(rs, BTSOCK_ERROR_SCN_ALLOCATION_FAILURE); break; } @@ -1019,7 +1028,7 @@ static void jv_dm_cback(tBTA_JV_EVT event, tBTA_JV* p_data, uint32_t id) { // Send channel ID to java layer if (!send_app_scn(rs)) { log::warn("send_app_scn() failed, closing rs->id:{}", rs->id); - cleanup_rfc_slot(rs); + cleanup_rfc_slot(rs, BTSOCK_ERROR_SEND_SCN_FAILURE); break; } @@ -1072,7 +1081,7 @@ static void jv_dm_cback(tBTA_JV_EVT event, tBTA_JV* p_data, uint32_t id) { if (!create_server_sdp_record(slot)) { log::error("cannot start server, slot found: {}", std::format_ptr(slot)); - cleanup_rfc_slot(slot); + cleanup_rfc_slot(slot, BTSOCK_ERROR_ADD_SDP_FAILURE); break; } @@ -1138,7 +1147,7 @@ static void handle_discovery_comp(tBTA_JV_STATUS status, int scn, uint32_t id) { id, bta_jv_status_text(status), scn); bta_collect_rfc_metrics_after_sdp_fail(status, slot->addr, slot->app_uid, slot->security, static_cast<bool>(slot->f.server), sdp_duration_ms); - cleanup_rfc_slot(slot); + cleanup_rfc_slot(slot, BTSOCK_ERROR_SDP_DISCOVERY_FAILURE); return; } @@ -1160,7 +1169,7 @@ static void handle_discovery_comp(tBTA_JV_STATUS status, int scn, uint32_t id) { if (BTA_JvRfcommConnect(slot->security, scn, slot->addr, rfcomm_cback, slot->id, cfg, slot->app_uid, sdp_duration_ms) != tBTA_JV_STATUS::SUCCESS) { log::warn("BTA_JvRfcommConnect() returned BTA_JV_FAILURE for RFCOMM slot_id:{}", id); - cleanup_rfc_slot(slot); + cleanup_rfc_slot(slot, BTSOCK_ERROR_CONNECTION_FAILURE); return; } // Establish connection if successfully found channel number to connect. @@ -1169,7 +1178,7 @@ static void handle_discovery_comp(tBTA_JV_STATUS status, int scn, uint32_t id) { if (!send_app_scn(slot)) { log::warn("send_app_scn() failed, closing slot_id {}", slot->id); - cleanup_rfc_slot(slot); + cleanup_rfc_slot(slot, BTSOCK_ERROR_SEND_SCN_FAILURE); return; } } @@ -1277,6 +1286,7 @@ static bool btsock_rfc_read_signaled_on_listen_socket(int fd, int /* flags */, u static void btsock_rfc_signaled_flagged(int fd, int flags, uint32_t id) { bool need_close = false; + btsock_error_code_t error_code = BTSOCK_ERROR_NONE; std::unique_lock<std::recursive_mutex> lock(slot_lock); rfc_slot_t* slot = find_rfc_slot_by_id(id); if (!slot) { @@ -1290,11 +1300,13 @@ static void btsock_rfc_signaled_flagged(int fd, int flags, uint32_t id) { // app sending data on connection socket if (!btsock_rfc_read_signaled_on_connected_socket(fd, flags, id, slot)) { need_close = true; + error_code = BTSOCK_ERROR_READ_SIGNALED_FAILURE; } } else { // app sending signal on listen socket if (!btsock_rfc_read_signaled_on_listen_socket(fd, flags, id, slot)) { need_close = true; + error_code = BTSOCK_ERROR_READ_SIGNALED_FAILURE; } } } @@ -1307,6 +1319,7 @@ static void btsock_rfc_signaled_flagged(int fd, int flags, uint32_t id) { "slot_id: {}, channel: {}", slot->id, slot->scn); need_close = true; + error_code = BTSOCK_ERROR_WRITE_SIGNALED_FAILURE; } } @@ -1318,7 +1331,7 @@ static void btsock_rfc_signaled_flagged(int fd, int flags, uint32_t id) { slot->f.doing_sdp_request) { BTA_JvCancelDiscovery(slot->id); } - cleanup_rfc_slot(slot); + cleanup_rfc_slot(slot, error_code); } } } @@ -1329,6 +1342,7 @@ void btsock_rfc_signaled(int fd, int flags, uint32_t id) { return; } bool need_close = false; + btsock_error_code_t error_code = BTSOCK_ERROR_NONE; std::unique_lock<std::recursive_mutex> lock(slot_lock); rfc_slot_t* slot = find_rfc_slot_by_id(id); if (!slot) { @@ -1347,6 +1361,7 @@ void btsock_rfc_signaled(int fd, int flags, uint32_t id) { } else { log::error("socket signaled for read while disconnected, slot_id: {}, channel: {}", slot->id, slot->scn); + error_code = BTSOCK_ERROR_READ_SIGNALED_FAILURE; need_close = true; } } @@ -1358,6 +1373,7 @@ void btsock_rfc_signaled(int fd, int flags, uint32_t id) { "socket signaled for write while disconnected (or write failure), " "slot_id: {}, channel: {}", slot->id, slot->scn); + error_code = BTSOCK_ERROR_WRITE_SIGNALED_FAILURE; need_close = true; } } @@ -1370,7 +1386,7 @@ void btsock_rfc_signaled(int fd, int flags, uint32_t id) { slot->f.doing_sdp_request) { BTA_JvCancelDiscovery(slot->id); } - cleanup_rfc_slot(slot); + cleanup_rfc_slot(slot, error_code); } } } @@ -1404,7 +1420,7 @@ int bta_co_rfc_data_incoming(uint32_t id, BT_HDR* p_buf) { case SENT_FAILED: osi_free(p_buf); - cleanup_rfc_slot(slot); + cleanup_rfc_slot(slot, BTSOCK_ERROR_SEND_TO_APP_FAILURE); break; } } else { @@ -1429,7 +1445,7 @@ int bta_co_rfc_data_outgoing_size(uint32_t id, int* size) { if (ioctl(slot->fd, FIONREAD, size) != 0) { log::error("unable to determine bytes remaining to be read on fd {}: {}", slot->fd, strerror(errno)); - cleanup_rfc_slot(slot); + cleanup_rfc_slot(slot, BTSOCK_ERROR_RECEIVE_DATA_FAILURE); return false; } @@ -1449,7 +1465,7 @@ int bta_co_rfc_data_outgoing(uint32_t id, uint8_t* buf, uint16_t size) { if (received != size) { log::error("error receiving RFCOMM data from app: {}", strerror(errno)); - cleanup_rfc_slot(slot); + cleanup_rfc_slot(slot, BTSOCK_ERROR_RECEIVE_DATA_FAILURE); return false; } @@ -1466,7 +1482,7 @@ bt_status_t btsock_rfc_disconnect(const RawAddress* bd_addr) { std::unique_lock<std::recursive_mutex> lock(slot_lock); for (size_t i = 0; i < ARRAY_SIZE(rfc_slots); ++i) { if (rfc_slots[i].id && rfc_slots[i].addr == *bd_addr) { - cleanup_rfc_slot(&rfc_slots[i]); + cleanup_rfc_slot(&rfc_slots[i], BTSOCK_ERROR_NONE); } } diff --git a/system/common/Android.bp b/system/common/Android.bp index e4efd7156e..c192613dbc 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"], @@ -79,18 +77,14 @@ cc_test { srcs: [ "address_obfuscator_unittest.cc", "base_bind_unittest.cc", - "id_generator_unittest.cc", "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/id_generator.h b/system/common/id_generator.h deleted file mode 100644 index 7c6425aeef..0000000000 --- a/system/common/id_generator.h +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright 2019 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. - */ - -#pragma once - -#include <array> - -/* Helper class generating N unique ids, from 0 to N-1 */ -template <std::size_t N> -class IdGenerator { -public: - static int ALL_USED; - - IdGenerator() : in_use_{} {} - - /* Returns next free id, or ALL_USED if no ids left */ - int GetNext() { - for (std::size_t i = 0; i < N; i++) { - if (!in_use_[i]) { - in_use_[i] = true; - return i; - } - } - return ALL_USED; - } - - /* Release given ID */ - void Release(int id) { in_use_[id] = false; } - -private: - std::array<bool, N> in_use_; -}; - -template <std::size_t N> -int IdGenerator<N>::ALL_USED = -1; diff --git a/system/common/id_generator_unittest.cc b/system/common/id_generator_unittest.cc deleted file mode 100644 index 7b090cf365..0000000000 --- a/system/common/id_generator_unittest.cc +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright 2019 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. - */ - -#include "common/id_generator.h" - -#include <gtest/gtest.h> - -TEST(IdGeneratorTest, sanity_test) { - IdGenerator<5> generator; - ASSERT_EQ(0, generator.GetNext()); - ASSERT_EQ(1, generator.GetNext()); - ASSERT_EQ(2, generator.GetNext()); - ASSERT_EQ(3, generator.GetNext()); - ASSERT_EQ(4, generator.GetNext()); - ASSERT_EQ(generator.ALL_USED, generator.GetNext()); - - generator.Release(3); - ASSERT_EQ(3, generator.GetNext()); - - generator.Release(0); - generator.Release(2); - ASSERT_EQ(0, generator.GetNext()); - ASSERT_EQ(2, generator.GetNext()); -} diff --git a/system/common/lru.h b/system/common/lru.h deleted file mode 100644 index ca0a5a1c35..0000000000 --- a/system/common/lru.h +++ /dev/null @@ -1,187 +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 <bluetooth/log.h> - -#include <functional> -#include <iterator> -#include <list> -#include <mutex> -#include <optional> -#include <thread> -#include <unordered_map> - -namespace bluetooth { - -namespace common { - -template <typename K, typename V> -class LegacyLruCache { -public: - using Node = std::pair<K, V>; - /** - * Constructor of the cache - * - * @param capacity maximum size of the cache - * @param log_tag, keyword to put at the head of log. - */ - LegacyLruCache(const size_t& capacity, const std::string& log_tag) : capacity_(capacity) { - if (capacity_ == 0) { - // don't allow invalid capacity - log::fatal("{} unable to have 0 LRU Cache capacity", log_tag); - } - } - - // delete copy constructor - LegacyLruCache(LegacyLruCache const&) = delete; - LegacyLruCache& operator=(LegacyLruCache const&) = delete; - - ~LegacyLruCache() { Clear(); } - - /** - * Clear the cache - */ - void Clear() { - std::lock_guard<std::recursive_mutex> lock(lru_mutex_); - lru_map_.clear(); - node_list_.clear(); - } - - /** - * Same as Get, but return an iterator to the accessed element - * - * Modifying the returned iterator does not warm up the cache - * - * @param key - * @return pointer to the underlying value to allow in-place modification - * nullptr when not found, will be invalidated when the key is evicted - */ - V* Find(const K& key) { - std::lock_guard<std::recursive_mutex> lock(lru_mutex_); - auto map_iterator = lru_map_.find(key); - if (map_iterator == lru_map_.end()) { - return nullptr; - } - node_list_.splice(node_list_.begin(), node_list_, map_iterator->second); - return &(map_iterator->second->second); - } - - /** - * Get the value of a key, and move the key to the head of cache, if there is - * one - * - * @param key - * @param value, output parameter of value of the key - * @return true if the cache has the key - */ - bool Get(const K& key, V* value) { - log::assert_that(value != nullptr, "assert failed: value != nullptr"); - std::lock_guard<std::recursive_mutex> lock(lru_mutex_); - auto value_ptr = Find(key); - if (value_ptr == nullptr) { - return false; - } - *value = *value_ptr; - return true; - } - - /** - * Check if the cache has the input key, move the key to the head - * if there is one - * - * @param key - * @return true if the cache has the key - */ - bool HasKey(const K& key) { - std::lock_guard<std::recursive_mutex> lock(lru_mutex_); - return Find(key) != nullptr; - } - - /** - * Put a key-value pair to the head of cache - * - * @param key - * @param value - * @return evicted node if tail value is popped, std::nullopt if no value - * is popped. std::optional can be treated as a boolean as well - */ - std::optional<Node> Put(const K& key, V value) { - std::lock_guard<std::recursive_mutex> lock(lru_mutex_); - auto value_ptr = Find(key); - if (value_ptr != nullptr) { - // hasKey() calls get(), therefore already move the node to the head - *value_ptr = std::move(value); - return std::nullopt; - } - - // remove tail - std::optional<Node> ret = std::nullopt; - if (lru_map_.size() == capacity_) { - lru_map_.erase(node_list_.back().first); - ret = std::move(node_list_.back()); - node_list_.pop_back(); - } - // insert to dummy next; - node_list_.emplace_front(key, std::move(value)); - lru_map_.emplace(key, node_list_.begin()); - return ret; - } - - /** - * Delete a key from cache - * - * @param key - * @return true if deleted successfully - */ - bool Remove(const K& key) { - std::lock_guard<std::recursive_mutex> lock(lru_mutex_); - auto map_iterator = lru_map_.find(key); - if (map_iterator == lru_map_.end()) { - return false; - } - - // remove from the list - node_list_.erase(map_iterator->second); - - // delete key from map - lru_map_.erase(map_iterator); - - return true; - } - - /** - * Return size of the cache - * - * @return size of the cache - */ - int Size() const { - std::lock_guard<std::recursive_mutex> lock(lru_mutex_); - return lru_map_.size(); - } - -private: - std::list<Node> node_list_; - size_t capacity_; - std::unordered_map<K, typename std::list<Node>::iterator> lru_map_; - mutable std::recursive_mutex lru_mutex_; -}; - -} // namespace common -} // namespace bluetooth diff --git a/system/common/lru_unittest.cc b/system/common/lru_unittest.cc deleted file mode 100644 index 7b41143ec5..0000000000 --- a/system/common/lru_unittest.cc +++ /dev/null @@ -1,250 +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/lru.h" - -#include <gmock/gmock.h> -#include <gtest/gtest.h> - -#include <chrono> -#include <limits> - -namespace testing { - -using bluetooth::common::LegacyLruCache; - -TEST(BluetoothLegacyLruCacheTest, LegacyLruCacheMainTest1) { - int* value = new int(0); - LegacyLruCache<int, int> cache(3, "testing"); // capacity = 3; - cache.Put(1, 10); - EXPECT_EQ(cache.Size(), 1); - EXPECT_FALSE(cache.Put(2, 20)); - EXPECT_FALSE(cache.Put(3, 30)); - EXPECT_EQ(cache.Size(), 3); - - // 1, 2, 3 should be in cache - EXPECT_TRUE(cache.Get(1, value)); - EXPECT_EQ(*value, 10); - EXPECT_TRUE(cache.Get(2, value)); - EXPECT_EQ(*value, 20); - EXPECT_TRUE(cache.Get(3, value)); - EXPECT_EQ(*value, 30); - EXPECT_EQ(cache.Size(), 3); - - EXPECT_THAT(cache.Put(4, 40), Optional(Pair(1, 10))); - // 2, 3, 4 should be in cache, 1 is evicted - EXPECT_FALSE(cache.Get(1, value)); - EXPECT_TRUE(cache.Get(4, value)); - EXPECT_EQ(*value, 40); - EXPECT_TRUE(cache.Get(2, value)); - EXPECT_EQ(*value, 20); - EXPECT_TRUE(cache.Get(3, value)); - EXPECT_EQ(*value, 30); - - EXPECT_THAT(cache.Put(5, 50), Optional(Pair(4, 40))); - EXPECT_EQ(cache.Size(), 3); - // 2, 3, 5 should be in cache, 4 is evicted - - EXPECT_TRUE(cache.Remove(3)); - EXPECT_FALSE(cache.Put(6, 60)); - // 2, 5, 6 should be in cache - - EXPECT_FALSE(cache.Get(3, value)); - EXPECT_FALSE(cache.Get(4, value)); - EXPECT_TRUE(cache.Get(2, value)); - EXPECT_EQ(*value, 20); - EXPECT_TRUE(cache.Get(5, value)); - EXPECT_EQ(*value, 50); - EXPECT_TRUE(cache.Get(6, value)); - EXPECT_EQ(*value, 60); -} - -TEST(BluetoothLegacyLruCacheTest, LegacyLruCacheMainTest2) { - int* value = new int(0); - LegacyLruCache<int, int> cache(2, "testing"); // size = 2; - EXPECT_FALSE(cache.Put(1, 10)); - EXPECT_FALSE(cache.Put(2, 20)); - EXPECT_THAT(cache.Put(3, 30), Optional(Pair(1, 10))); - EXPECT_FALSE(cache.Put(2, 200)); - EXPECT_EQ(cache.Size(), 2); - // 3, 2 should be in cache - - EXPECT_FALSE(cache.HasKey(1)); - EXPECT_TRUE(cache.Get(2, value)); - EXPECT_EQ(*value, 200); - EXPECT_TRUE(cache.Get(3, value)); - EXPECT_EQ(*value, 30); - - EXPECT_THAT(cache.Put(4, 40), Optional(Pair(2, 200))); - // 3, 4 should be in cache - - EXPECT_FALSE(cache.HasKey(2)); - EXPECT_TRUE(cache.Get(3, value)); - EXPECT_EQ(*value, 30); - EXPECT_TRUE(cache.Get(4, value)); - EXPECT_EQ(*value, 40); - - EXPECT_TRUE(cache.Remove(4)); - EXPECT_EQ(cache.Size(), 1); - cache.Put(2, 2000); - // 3, 2 should be in cache - - EXPECT_FALSE(cache.HasKey(4)); - EXPECT_TRUE(cache.Get(3, value)); - EXPECT_EQ(*value, 30); - EXPECT_TRUE(cache.Get(2, value)); - EXPECT_EQ(*value, 2000); - - EXPECT_TRUE(cache.Remove(2)); - EXPECT_TRUE(cache.Remove(3)); - cache.Put(5, 50); - cache.Put(1, 100); - cache.Put(1, 1000); - EXPECT_EQ(cache.Size(), 2); - // 1, 5 should be in cache - - EXPECT_FALSE(cache.HasKey(2)); - EXPECT_FALSE(cache.HasKey(3)); - EXPECT_TRUE(cache.Get(1, value)); - EXPECT_EQ(*value, 1000); - EXPECT_TRUE(cache.Get(5, value)); - EXPECT_EQ(*value, 50); -} - -TEST(BluetoothLegacyLruCacheTest, LegacyLruCacheFindTest) { - LegacyLruCache<int, int> cache(10, "testing"); - cache.Put(1, 10); - cache.Put(2, 20); - int value = 0; - EXPECT_TRUE(cache.Get(1, &value)); - EXPECT_EQ(value, 10); - auto value_ptr = cache.Find(1); - EXPECT_NE(value_ptr, nullptr); - *value_ptr = 20; - EXPECT_TRUE(cache.Get(1, &value)); - EXPECT_EQ(value, 20); - cache.Put(1, 40); - EXPECT_EQ(*value_ptr, 40); - EXPECT_EQ(cache.Find(10), nullptr); -} - -TEST(BluetoothLegacyLruCacheTest, LegacyLruCacheGetTest) { - LegacyLruCache<int, int> cache(10, "testing"); - cache.Put(1, 10); - cache.Put(2, 20); - int value = 0; - EXPECT_TRUE(cache.Get(1, &value)); - EXPECT_EQ(value, 10); - EXPECT_TRUE(cache.HasKey(1)); - EXPECT_TRUE(cache.HasKey(2)); - EXPECT_FALSE(cache.HasKey(3)); - EXPECT_FALSE(cache.Get(3, &value)); - EXPECT_EQ(value, 10); -} - -TEST(BluetoothLegacyLruCacheTest, LegacyLruCacheRemoveTest) { - LegacyLruCache<int, int> cache(10, "testing"); - for (int key = 0; key <= 30; key++) { - cache.Put(key, key * 100); - } - for (int key = 0; key <= 20; key++) { - EXPECT_FALSE(cache.HasKey(key)); - } - for (int key = 21; key <= 30; key++) { - EXPECT_TRUE(cache.HasKey(key)); - } - for (int key = 21; key <= 30; key++) { - EXPECT_TRUE(cache.Remove(key)); - } - for (int key = 21; key <= 30; key++) { - EXPECT_FALSE(cache.HasKey(key)); - } -} - -TEST(BluetoothLegacyLruCacheTest, LegacyLruCacheClearTest) { - LegacyLruCache<int, int> cache(10, "testing"); - for (int key = 0; key < 10; key++) { - cache.Put(key, key * 100); - } - for (int key = 0; key < 10; key++) { - EXPECT_TRUE(cache.HasKey(key)); - } - cache.Clear(); - for (int key = 0; key < 10; key++) { - EXPECT_FALSE(cache.HasKey(key)); - } - - for (int key = 0; key < 10; key++) { - cache.Put(key, key * 1000); - } - for (int key = 0; key < 10; key++) { - EXPECT_TRUE(cache.HasKey(key)); - } -} - -TEST(BluetoothLegacyLruCacheTest, LegacyLruCachePressureTest) { - int max_size = 0xFFFFF; // 2^20 = 1M - LegacyLruCache<int, int> cache(static_cast<size_t>(max_size), "testing"); - - // fill the cache - for (int key = 0; key < max_size; key++) { - cache.Put(key, key); - } - - // make sure the cache is full - for (int key = 0; key < max_size; key++) { - EXPECT_TRUE(cache.HasKey(key)); - } - - // refresh the entire cache - for (int key = 0; key < max_size; key++) { - int new_key = key + max_size; - cache.Put(new_key, new_key); - EXPECT_FALSE(cache.HasKey(key)); - EXPECT_TRUE(cache.HasKey(new_key)); - } - - // clear the entire cache - int* value = new int(0); - for (int key = max_size; key < 2 * max_size; key++) { - EXPECT_TRUE(cache.Get(key, value)); - EXPECT_EQ(*value, key); - EXPECT_TRUE(cache.Remove(key)); - } - EXPECT_EQ(cache.Size(), 0); -} - -TEST(BluetoothLegacyLruCacheTest, BluetoothLruMultiThreadPressureTest) { - LegacyLruCache<int, int> cache(100, "testing"); - auto pointer = &cache; - // make sure no deadlock - std::vector<std::thread> workers; - for (int key = 0; key < 100; key++) { - workers.push_back(std::thread([key, pointer]() { - pointer->Put(key, key); - EXPECT_TRUE(pointer->HasKey(key)); - EXPECT_TRUE(pointer->Remove(key)); - })); - } - for (auto& worker : workers) { - worker.join(); - } - EXPECT_EQ(cache.Size(), 0); -} - -} // namespace testing 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 49b73a01c3..a3b3eea450 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" @@ -58,486 +57,15 @@ struct formatter<android::bluetooth::AddressTypeEnum> template <> struct formatter<android::bluetooth::DeviceInfoSrcEnum> : enum_formatter<android::bluetooth::DeviceInfoSrcEnum> {}; +template <> +struct formatter<android::bluetooth::SocketErrorEnum> + : enum_formatter<android::bluetooth::SocketErrorEnum> {}; } // namespace std 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, @@ -778,7 +306,10 @@ void LogSdpAttribute(const RawAddress& address, uint16_t protocol_uuid, uint16_t void LogSocketConnectionState(const RawAddress& address, int port, int type, android::bluetooth::SocketConnectionstateEnum connection_state, int64_t tx_bytes, int64_t rx_bytes, int uid, int server_port, - android::bluetooth::SocketRoleEnum socket_role) { + android::bluetooth::SocketRoleEnum socket_role, + uint64_t connection_duration_ms, + android::bluetooth::SocketErrorEnum error_code, + bool is_hardware_offload) { std::string obfuscated_id; int metric_id = 0; if (!address.IsEmpty()) { @@ -790,13 +321,16 @@ void LogSocketConnectionState(const RawAddress& address, int port, int type, address.IsEmpty() ? 0 : obfuscated_id.size()); int ret = stats_write(BLUETOOTH_SOCKET_CONNECTION_STATE_CHANGED, obfuscated_id_field, port, type, connection_state, tx_bytes, rx_bytes, uid, server_port, socket_role, - metric_id); + metric_id, static_cast<int64_t>(connection_duration_ms), error_code, + is_hardware_offload); if (ret < 0) { log::warn( "failed for {}, port {}, type {}, state {}, tx_bytes {}, rx_bytes {}, " - "uid {}, server_port {}, socket_role {}, error {}", + "uid {}, server_port {}, socket_role {}, error {}, connection_duration_ms {}, " + "socket_error_code {}, " + "is_hardware_offload {}", address, port, type, connection_state, tx_bytes, rx_bytes, uid, server_port, - socket_role, ret); + socket_role, ret, connection_duration_ms, error_code, is_hardware_offload); } } diff --git a/system/common/metrics.h b/system/common/metrics.h index 8cd41bd6db..4ccb47f64c 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 */ @@ -459,11 +213,17 @@ void LogSdpAttribute(const RawAddress& address, uint16_t protocol_uuid, uint16_t * by |server_port| * @param socket_role role of this socket, server or connection * @param uid socket owner's uid + * @param connection_duration_ms duration of socket connection in milliseconds + * @param error_code error code of socket failures + * @param is_hardware_offload whether this is a offload socket */ void LogSocketConnectionState(const RawAddress& address, int port, int type, android::bluetooth::SocketConnectionstateEnum connection_state, int64_t tx_bytes, int64_t rx_bytes, int uid, int server_port, - android::bluetooth::SocketRoleEnum socket_role); + android::bluetooth::SocketRoleEnum socket_role, + uint64_t connection_duration_ms, + android::bluetooth::SocketErrorEnum error_code, + bool is_hardware_offload); /** * Logs when a Bluetooth device's manufacturer information is learnt diff --git a/system/common/metrics_linux.cc b/system/common/metrics_linux.cc index 009d16878e..3283619415 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 */, @@ -92,7 +34,10 @@ void LogSocketConnectionState(const RawAddress& /* address */, int /* port */, i android::bluetooth::SocketConnectionstateEnum /* connection_state */, int64_t /* tx_bytes */, int64_t /* rx_bytes */, int /* uid */, int /* server_port */, - android::bluetooth::SocketRoleEnum /* socket_role */) {} + android::bluetooth::SocketRoleEnum /* socket_role */, + uint64_t /* connection_duration_ms */, + android::bluetooth::SocketErrorEnum /* error_code */, + bool /* is_hardware_offload */) {} void LogHciTimeoutEvent(uint32_t /* hci_cmd */) {} 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 a57b83073d..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", @@ -390,6 +389,7 @@ cc_test { "hci/class_of_device_unittest.cc", "hci/controller_test.cc", "hci/controller_unittest.cc", + "hci/distance_measurement_manager_test.cc", "hci/hci_layer_fake.cc", "hci/hci_layer_test.cc", "hci/hci_layer_unittest.cc", @@ -417,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", @@ -509,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/AndroidTestTemplate.xml b/system/gd/AndroidTestTemplate.xml index 4083baac14..92e0a83ae1 100644 --- a/system/gd/AndroidTestTemplate.xml +++ b/system/gd/AndroidTestTemplate.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="utf-8"?> -<!-- Copyright 2018 The Android Open Source Project +<!-- Copyright (C) 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. diff --git a/system/gd/benchmark.cc b/system/gd/benchmark.cc index 2b11c898d5..923b0c76e7 100644 --- a/system/gd/benchmark.cc +++ b/system/gd/benchmark.cc @@ -1,5 +1,5 @@ /* - * Copyright 2019 The Android Open Source Project + * Copyright (C) 2019 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. diff --git a/system/gd/common/audit_log.cc b/system/gd/common/audit_log.cc index 36cee3c801..e83c2894f8 100644 --- a/system/gd/common/audit_log.cc +++ b/system/gd/common/audit_log.cc @@ -1,5 +1,5 @@ /* - * Copyright 2022 The Android Open Source Project + * Copyright (C) 2022 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. diff --git a/system/gd/common/audit_log.h b/system/gd/common/audit_log.h index b129bc7411..70a160870e 100644 --- a/system/gd/common/audit_log.h +++ b/system/gd/common/audit_log.h @@ -1,5 +1,5 @@ /* - * Copyright 2022 The Android Open Source Project + * Copyright (C) 2022 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. diff --git a/system/gd/common/bidi_queue.h b/system/gd/common/bidi_queue.h index 98271887eb..4dad186562 100644 --- a/system/gd/common/bidi_queue.h +++ b/system/gd/common/bidi_queue.h @@ -1,6 +1,6 @@ /****************************************************************************** * - * Copyright 2019 The Android Open Source Project + * Copyright (C) 2019 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. diff --git a/system/gd/common/bidi_queue_unittest.cc b/system/gd/common/bidi_queue_unittest.cc index 3505d16cdb..2235c3cc71 100644 --- a/system/gd/common/bidi_queue_unittest.cc +++ b/system/gd/common/bidi_queue_unittest.cc @@ -1,5 +1,5 @@ /* - * Copyright 2019 The Android Open Source Project + * Copyright (C) 2019 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. diff --git a/system/gd/common/bind.h b/system/gd/common/bind.h index 9385c79dc5..fc1c9cdb80 100644 --- a/system/gd/common/bind.h +++ b/system/gd/common/bind.h @@ -1,5 +1,5 @@ /* - * Copyright 2019 The Android Open Source Project + * Copyright (C) 2019 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. diff --git a/system/gd/common/blocking_queue.h b/system/gd/common/blocking_queue.h index 4b68e514ab..25b46163d7 100644 --- a/system/gd/common/blocking_queue.h +++ b/system/gd/common/blocking_queue.h @@ -1,5 +1,5 @@ /* - * Copyright 2019 The Android Open Source Project + * Copyright (C) 2019 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. diff --git a/system/gd/common/blocking_queue_unittest.cc b/system/gd/common/blocking_queue_unittest.cc index 2b109ffe5f..623dc026bd 100644 --- a/system/gd/common/blocking_queue_unittest.cc +++ b/system/gd/common/blocking_queue_unittest.cc @@ -1,5 +1,5 @@ /* - * Copyright 2019 The Android Open Source Project + * Copyright (C) 2019 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. diff --git a/system/gd/common/byte_array.h b/system/gd/common/byte_array.h index b7183c4d2d..daff291385 100644 --- a/system/gd/common/byte_array.h +++ b/system/gd/common/byte_array.h @@ -1,5 +1,5 @@ /* - * Copyright 2020 The Android Open Source Project + * Copyright (C) 2020 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. diff --git a/system/gd/common/byte_array_test.cc b/system/gd/common/byte_array_test.cc index b9a64b3882..29ae26494b 100644 --- a/system/gd/common/byte_array_test.cc +++ b/system/gd/common/byte_array_test.cc @@ -1,5 +1,5 @@ /* - * Copyright 2020 The Android Open Source Project + * Copyright (C) 2020 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. diff --git a/system/gd/common/callback.h b/system/gd/common/callback.h index 7bf6f3a4ef..5fa3ee991c 100644 --- a/system/gd/common/callback.h +++ b/system/gd/common/callback.h @@ -1,5 +1,5 @@ /* - * Copyright 2019 The Android Open Source Project + * Copyright (C) 2019 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. diff --git a/system/gd/common/circular_buffer.h b/system/gd/common/circular_buffer.h index 6132f2e51c..bfb4b4252a 100644 --- a/system/gd/common/circular_buffer.h +++ b/system/gd/common/circular_buffer.h @@ -1,5 +1,5 @@ /* - * Copyright 2020 The Android Open Source Project + * Copyright (C) 2020 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. diff --git a/system/gd/common/circular_buffer_test.cc b/system/gd/common/circular_buffer_test.cc index 618388858b..5b465de723 100644 --- a/system/gd/common/circular_buffer_test.cc +++ b/system/gd/common/circular_buffer_test.cc @@ -1,5 +1,5 @@ /* - * Copyright 2020 The Android Open Source Project + * Copyright (C) 2020 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. diff --git a/system/gd/common/contextual_callback.h b/system/gd/common/contextual_callback.h index 548936d68b..6a6602e217 100644 --- a/system/gd/common/contextual_callback.h +++ b/system/gd/common/contextual_callback.h @@ -1,5 +1,5 @@ /* - * Copyright 2019 The Android Open Source Project + * Copyright (C) 2019 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. diff --git a/system/gd/common/i_postable_context.h b/system/gd/common/i_postable_context.h index b421579ca8..13ec14db29 100644 --- a/system/gd/common/i_postable_context.h +++ b/system/gd/common/i_postable_context.h @@ -1,5 +1,5 @@ /* - * Copyright 2019 The Android Open Source Project + * Copyright (C) 2019 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. diff --git a/system/gd/common/list_map.h b/system/gd/common/list_map.h index 1b63302806..8c1b014753 100644 --- a/system/gd/common/list_map.h +++ b/system/gd/common/list_map.h @@ -1,5 +1,5 @@ /* - * Copyright 2020 The Android Open Source Project + * Copyright (C) 2020 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. diff --git a/system/gd/common/list_map_test.cc b/system/gd/common/list_map_test.cc index 991fd25c58..d9a6c149b3 100644 --- a/system/gd/common/list_map_test.cc +++ b/system/gd/common/list_map_test.cc @@ -1,5 +1,5 @@ /* - * Copyright 2020 The Android Open Source Project + * Copyright (C) 2020 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. diff --git a/system/gd/common/lru_cache.h b/system/gd/common/lru_cache.h index 303688d55f..6f5c2340f5 100644 --- a/system/gd/common/lru_cache.h +++ b/system/gd/common/lru_cache.h @@ -1,5 +1,5 @@ /* - * Copyright 2020 The Android Open Source Project + * Copyright (C) 2020 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. diff --git a/system/gd/common/lru_cache_test.cc b/system/gd/common/lru_cache_test.cc index 555a04edd2..166eb94561 100644 --- a/system/gd/common/lru_cache_test.cc +++ b/system/gd/common/lru_cache_test.cc @@ -1,5 +1,5 @@ /* - * Copyright 2020 The Android Open Source Project + * Copyright (C) 2020 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. diff --git a/system/gd/common/multi_priority_queue.h b/system/gd/common/multi_priority_queue.h index d48f0bffb0..9dcc751c8e 100644 --- a/system/gd/common/multi_priority_queue.h +++ b/system/gd/common/multi_priority_queue.h @@ -1,6 +1,6 @@ /****************************************************************************** * - * Copyright 2021 The Android Open Source Project + * Copyright (C) 2021 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. diff --git a/system/gd/common/multi_priority_queue_test.cc b/system/gd/common/multi_priority_queue_test.cc index 435e1ad3cd..5691a7ca7a 100644 --- a/system/gd/common/multi_priority_queue_test.cc +++ b/system/gd/common/multi_priority_queue_test.cc @@ -1,6 +1,6 @@ /****************************************************************************** * - * Copyright 2021 The Android Open Source Project + * Copyright (C) 2021 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. diff --git a/system/gd/common/numbers.h b/system/gd/common/numbers.h index e31bebbee3..5256093fa5 100644 --- a/system/gd/common/numbers.h +++ b/system/gd/common/numbers.h @@ -1,5 +1,5 @@ /* - * Copyright 2020 The Android Open Source Project + * Copyright (C) 2020 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. diff --git a/system/gd/common/numbers_test.cc b/system/gd/common/numbers_test.cc index bf4159f934..c5afad5cdc 100644 --- a/system/gd/common/numbers_test.cc +++ b/system/gd/common/numbers_test.cc @@ -1,5 +1,5 @@ /* - * Copyright 2020 The Android Open Source Project + * Copyright (C) 2020 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. diff --git a/system/gd/common/postable_context.h b/system/gd/common/postable_context.h index 4a9514870f..332952df31 100644 --- a/system/gd/common/postable_context.h +++ b/system/gd/common/postable_context.h @@ -1,5 +1,5 @@ /* - * Copyright 2024 The Android Open Source Project + * Copyright (C) 2024 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. diff --git a/system/gd/common/stop_watch.cc b/system/gd/common/stop_watch.cc index b9f95bbcbe..5425ab7ed7 100644 --- a/system/gd/common/stop_watch.cc +++ b/system/gd/common/stop_watch.cc @@ -1,5 +1,5 @@ /* - * Copyright 2020 The Android Open Source Project + * Copyright (C) 2020 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. diff --git a/system/gd/common/stop_watch.h b/system/gd/common/stop_watch.h index 792229172e..1a33d10770 100644 --- a/system/gd/common/stop_watch.h +++ b/system/gd/common/stop_watch.h @@ -1,5 +1,5 @@ /* - * Copyright 2020 The Android Open Source Project + * Copyright (C) 2020 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. diff --git a/system/gd/common/strings.cc b/system/gd/common/strings.cc index db42acfcf4..ba450acf65 100644 --- a/system/gd/common/strings.cc +++ b/system/gd/common/strings.cc @@ -1,5 +1,5 @@ /* - * Copyright 2020 The Android Open Source Project + * Copyright (C) 2020 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. diff --git a/system/gd/common/strings.h b/system/gd/common/strings.h index 5593715eb2..ab8756e08e 100644 --- a/system/gd/common/strings.h +++ b/system/gd/common/strings.h @@ -1,5 +1,5 @@ /* - * Copyright 2020 The Android Open Source Project + * Copyright (C) 2020 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. diff --git a/system/gd/common/strings_test.cc b/system/gd/common/strings_test.cc index 9188eae528..24b4adedc6 100644 --- a/system/gd/common/strings_test.cc +++ b/system/gd/common/strings_test.cc @@ -1,5 +1,5 @@ /* - * Copyright 2020 The Android Open Source Project + * Copyright (C) 2020 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. diff --git a/system/gd/common/sync_map_count.h b/system/gd/common/sync_map_count.h index b9cfab3049..10e63cdd08 100644 --- a/system/gd/common/sync_map_count.h +++ b/system/gd/common/sync_map_count.h @@ -1,5 +1,5 @@ /* - * Copyright 2021 The Android Open Source Project + * Copyright (C) 2021 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. diff --git a/system/gd/common/sync_map_count_test.cc b/system/gd/common/sync_map_count_test.cc index 0e29c32467..04911b87bc 100644 --- a/system/gd/common/sync_map_count_test.cc +++ b/system/gd/common/sync_map_count_test.cc @@ -1,5 +1,5 @@ /* - * Copyright 2021 The Android Open Source Project + * Copyright (C) 2021 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. diff --git a/system/gd/common/testing/bind_test_util.h b/system/gd/common/testing/bind_test_util.h index 7db92045f7..d3f8996265 100644 --- a/system/gd/common/testing/bind_test_util.h +++ b/system/gd/common/testing/bind_test_util.h @@ -1,5 +1,5 @@ /* - * Copyright 2019 The Android Open Source Project + * Copyright (C) 2019 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. diff --git a/system/gd/common/testing/wired_pair_of_bidi_queues.h b/system/gd/common/testing/wired_pair_of_bidi_queues.h index ca401cb9e0..663727f1df 100644 --- a/system/gd/common/testing/wired_pair_of_bidi_queues.h +++ b/system/gd/common/testing/wired_pair_of_bidi_queues.h @@ -1,6 +1,6 @@ /****************************************************************************** * - * Copyright 2019 The Android Open Source Project + * Copyright (C) 2019 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. diff --git a/system/gd/common/type_helper.h b/system/gd/common/type_helper.h index 2f4a9d74fe..7ffd9b7363 100644 --- a/system/gd/common/type_helper.h +++ b/system/gd/common/type_helper.h @@ -1,5 +1,5 @@ /* - * Copyright 2020 The Android Open Source Project + * Copyright (C) 2020 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. diff --git a/system/gd/crypto_toolbox/crypto_toolbox_test.cc b/system/gd/crypto_toolbox/crypto_toolbox_test.cc index 35ab082d89..382d7035d4 100644 --- a/system/gd/crypto_toolbox/crypto_toolbox_test.cc +++ b/system/gd/crypto_toolbox/crypto_toolbox_test.cc @@ -1,6 +1,6 @@ /****************************************************************************** * - * Copyright 2018 The Android Open Source Project + * Copyright (C) 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. diff --git a/system/gd/fuzz/helpers.cc b/system/gd/fuzz/helpers.cc index a03f04aab8..1efe175dda 100644 --- a/system/gd/fuzz/helpers.cc +++ b/system/gd/fuzz/helpers.cc @@ -1,5 +1,5 @@ /* - * Copyright 2020 The Android Open Source Project + * Copyright (C) 2020 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. diff --git a/system/gd/fuzz/helpers.h b/system/gd/fuzz/helpers.h index 7b90ff82bc..ed7f3ee852 100644 --- a/system/gd/fuzz/helpers.h +++ b/system/gd/fuzz/helpers.h @@ -1,5 +1,5 @@ /* - * Copyright 2020 The Android Open Source Project + * Copyright (C) 2020 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. diff --git a/system/gd/fuzz_test.cc b/system/gd/fuzz_test.cc index bdb007b295..73ad2fd65e 100644 --- a/system/gd/fuzz_test.cc +++ b/system/gd/fuzz_test.cc @@ -1,5 +1,5 @@ /* - * Copyright 2019 The Android Open Source Project + * Copyright (C) 2019 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. diff --git a/system/gd/hal/fuzz/fuzz_hci_hal.cc b/system/gd/hal/fuzz/fuzz_hci_hal.cc index a0db9f01d9..3d9afec3a8 100644 --- a/system/gd/hal/fuzz/fuzz_hci_hal.cc +++ b/system/gd/hal/fuzz/fuzz_hci_hal.cc @@ -1,5 +1,5 @@ /* - * Copyright 2020 The Android Open Source Project + * Copyright (C) 2020 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. diff --git a/system/gd/hal/fuzz/fuzz_hci_hal.h b/system/gd/hal/fuzz/fuzz_hci_hal.h index 07a3593e7c..ab9fc7ee64 100644 --- a/system/gd/hal/fuzz/fuzz_hci_hal.h +++ b/system/gd/hal/fuzz/fuzz_hci_hal.h @@ -1,5 +1,5 @@ /* - * Copyright 2020 The Android Open Source Project + * Copyright (C) 2020 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. diff --git a/system/gd/hal/hci_backend.h b/system/gd/hal/hci_backend.h index 5c107ef8a1..657d771bbc 100644 --- a/system/gd/hal/hci_backend.h +++ b/system/gd/hal/hci_backend.h @@ -1,5 +1,5 @@ /* - * Copyright 2024 The Android Open Source Project + * Copyright (C) 2024 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. diff --git a/system/gd/hal/hci_backend_aidl.cc b/system/gd/hal/hci_backend_aidl.cc index 04bd67f992..93994c374d 100644 --- a/system/gd/hal/hci_backend_aidl.cc +++ b/system/gd/hal/hci_backend_aidl.cc @@ -1,5 +1,5 @@ /* - * Copyright 2024 The Android Open Source Project + * Copyright (C) 2024 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. diff --git a/system/gd/hal/hci_backend_hidl.cc b/system/gd/hal/hci_backend_hidl.cc index 0fb2729307..79f69a44f0 100644 --- a/system/gd/hal/hci_backend_hidl.cc +++ b/system/gd/hal/hci_backend_hidl.cc @@ -1,5 +1,5 @@ /* - * Copyright 2024 The Android Open Source Project + * Copyright (C) 2024 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. diff --git a/system/gd/hal/hci_hal.h b/system/gd/hal/hci_hal.h index d016d354f2..2c028c3b6f 100644 --- a/system/gd/hal/hci_hal.h +++ b/system/gd/hal/hci_hal.h @@ -1,5 +1,5 @@ /* - * Copyright 2019 The Android Open Source Project + * Copyright (C) 2019 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. @@ -51,6 +51,10 @@ public: // Send an ISO data packet from the controller to the host // @param data the ISO HCI packet to be passed to the host stack virtual void isoDataReceived(HciPacket data) = 0; + + // This function is invoked when the controller encounters an error requiring + // the Bluetooth stack to initiate a reset. + virtual void controllerNeedsReset() {} }; // Mirrors hardware/interfaces/bluetooth/1.0/IBluetoothHci.hal in Android @@ -101,9 +105,6 @@ public: // Get the MSFT opcode (as specified in Microsoft-defined Bluetooth HCI // extensions) virtual uint16_t getMsftOpcode() { return 0; } - - // Mark the controller as broken to prevent further read / write operation. - virtual void markControllerBroken() { return; } }; // LINT.ThenChange(fuzz/fuzz_hci_hal.h) diff --git a/system/gd/hal/hci_hal_android.cc b/system/gd/hal/hci_hal_android.cc index 8f1246d064..f548080d83 100644 --- a/system/gd/hal/hci_hal_android.cc +++ b/system/gd/hal/hci_hal_android.cc @@ -1,5 +1,5 @@ /* - * Copyright 2024 The Android Open Source Project + * Copyright (C) 2024 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. diff --git a/system/gd/hal/hci_hal_android_test.cc b/system/gd/hal/hci_hal_android_test.cc index 28ce145379..247f15745f 100644 --- a/system/gd/hal/hci_hal_android_test.cc +++ b/system/gd/hal/hci_hal_android_test.cc @@ -1,5 +1,5 @@ /* - * Copyright 2024 The Android Open Source Project + * Copyright (C) 2024 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. @@ -74,12 +74,15 @@ class HciHalAndroidTest : public ::testing::Test { protected: void SetUp() override { thread_ = new Thread("test_thread", Thread::Priority::NORMAL); - hal = fake_registry_.Start<HciHal>(thread_); + handler_ = new os::Handler(thread_); + hal = fake_registry_.Start<HciHal>(thread_, handler_); } void TearDown() override { fake_registry_.StopAll(); + handler_->Clear(); delete thread_; + delete handler_; } HciHal* hal; @@ -87,6 +90,7 @@ protected: private: ModuleRegistry fake_registry_; Thread* thread_; + os::Handler* handler_; }; TEST_F(HciHalAndroidTest, init) { diff --git a/system/gd/hal/hci_hal_fake.cc b/system/gd/hal/hci_hal_fake.cc index 7d396dd571..781dde6749 100644 --- a/system/gd/hal/hci_hal_fake.cc +++ b/system/gd/hal/hci_hal_fake.cc @@ -1,5 +1,5 @@ /* - * Copyright 2023 The Android Open Source Project + * Copyright (C) 2023 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/system/gd/hal/hci_hal_fake.h b/system/gd/hal/hci_hal_fake.h index 1d94f768ce..9d58064297 100644 --- a/system/gd/hal/hci_hal_fake.h +++ b/system/gd/hal/hci_hal_fake.h @@ -1,5 +1,5 @@ /* - * Copyright 2023 The Android Open Source Project + * Copyright (C) 2023 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/system/gd/hal/hci_hal_host.cc b/system/gd/hal/hci_hal_host.cc index 970a2ae48c..bf020a2e02 100644 --- a/system/gd/hal/hci_hal_host.cc +++ b/system/gd/hal/hci_hal_host.cc @@ -1,5 +1,5 @@ /* - * Copyright 2019 The Android Open Source Project + * Copyright (C) 2019 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. @@ -262,9 +262,6 @@ public: void sendHciCommand(HciPacket command) override { std::lock_guard<std::mutex> lock(api_mutex_); - if (controller_broken_) { - return; - } log::assert_that(sock_fd_ != INVALID_FD, "assert failed: sock_fd_ != INVALID_FD"); std::vector<uint8_t> packet = std::move(command); btsnoop_logger_->Capture(packet, SnoopLogger::Direction::OUTGOING, @@ -275,9 +272,6 @@ public: void sendAclData(HciPacket data) override { std::lock_guard<std::mutex> lock(api_mutex_); - if (controller_broken_) { - return; - } log::assert_that(sock_fd_ != INVALID_FD, "assert failed: sock_fd_ != INVALID_FD"); std::vector<uint8_t> packet = std::move(data); btsnoop_logger_->Capture(packet, SnoopLogger::Direction::OUTGOING, @@ -288,10 +282,6 @@ public: void sendScoData(HciPacket data) override { std::lock_guard<std::mutex> lock(api_mutex_); - if (controller_broken_) { - return; - } - log::assert_that(sock_fd_ != INVALID_FD, "assert failed: sock_fd_ != INVALID_FD"); std::vector<uint8_t> packet = std::move(data); btsnoop_logger_->Capture(packet, SnoopLogger::Direction::OUTGOING, @@ -302,9 +292,6 @@ public: void sendIsoData(HciPacket data) override { std::lock_guard<std::mutex> lock(api_mutex_); - if (controller_broken_) { - return; - } log::assert_that(sock_fd_ != INVALID_FD, "assert failed: sock_fd_ != INVALID_FD"); std::vector<uint8_t> packet = std::move(data); btsnoop_logger_->Capture(packet, SnoopLogger::Direction::OUTGOING, @@ -317,15 +304,6 @@ public: return os::Management::getInstance().getVendorSpecificCode(MGMT_VS_OPCODE_MSFT); } - void markControllerBroken() override { - std::lock_guard<std::mutex> lock(api_mutex_); - if (controller_broken_) { - log::error("Controller already marked as broken!"); - return; - } - controller_broken_ = true; - } - protected: void ListDependencies(ModuleList* list) const { list->add<LinkClocker>(); } @@ -337,8 +315,7 @@ protected: // We don't want to crash when the chipset is broken. if (sock_fd_ == INVALID_FD) { log::error("Failed to connect to HCI socket. Aborting HAL initialization process."); - controller_broken_ = true; - kill(getpid(), SIGTERM); + incoming_packet_callback_->controllerNeedsReset(); return; } @@ -392,7 +369,6 @@ private: std::queue<std::vector<uint8_t>> hci_outgoing_queue_; SnoopLogger* btsnoop_logger_ = nullptr; LinkClocker* link_clocker_ = nullptr; - bool controller_broken_ = false; void write_to_fd(HciPacket packet) { // TODO(chromeos-bt-team@): replace this with new queue when it's ready @@ -414,8 +390,8 @@ private: hci_outgoing_queue_.pop(); if (bytes_written == -1) { log::error("Can't write to socket: {}", strerror(errno)); - markControllerBroken(); - kill(getpid(), SIGTERM); + incoming_packet_callback_->controllerNeedsReset(); + return; } if (hci_outgoing_queue_.empty()) { hci_incoming_thread_.GetReactor()->ModifyRegistration(reactable_, @@ -439,15 +415,13 @@ private: // we don't want crash when the chipset is broken. if (received_size == -1) { log::error("Can't receive from socket: {}", strerror(errno)); - markControllerBroken(); - kill(getpid(), SIGTERM); + incoming_packet_callback_->controllerNeedsReset(); return; } if (received_size == 0) { log::warn("Can't read H4 header. EOF received"); - markControllerBroken(); - kill(getpid(), SIGTERM); + incoming_packet_callback_->controllerNeedsReset(); return; } diff --git a/system/gd/hal/hci_hal_host.h b/system/gd/hal/hci_hal_host.h index 9f1350b265..42712d791a 100644 --- a/system/gd/hal/hci_hal_host.h +++ b/system/gd/hal/hci_hal_host.h @@ -1,5 +1,5 @@ /* - * Copyright 2019 The Android Open Source Project + * Copyright (C) 2019 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. diff --git a/system/gd/hal/hci_hal_host_rootcanal.cc b/system/gd/hal/hci_hal_host_rootcanal.cc index 612372a962..065711059a 100644 --- a/system/gd/hal/hci_hal_host_rootcanal.cc +++ b/system/gd/hal/hci_hal_host_rootcanal.cc @@ -1,5 +1,5 @@ /* - * Copyright 2019 The Android Open Source Project + * Copyright (C) 2019 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. diff --git a/system/gd/hal/hci_hal_host_test.cc b/system/gd/hal/hci_hal_host_test.cc index ab0ccef8f6..4f4c6bc6d0 100644 --- a/system/gd/hal/hci_hal_host_test.cc +++ b/system/gd/hal/hci_hal_host_test.cc @@ -1,5 +1,5 @@ /* - * Copyright 2019 The Android Open Source Project + * Copyright (C) 2019 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. @@ -141,10 +141,11 @@ class HciHalRootcanalTest : public ::testing::Test { protected: void SetUp() override { thread_ = new Thread("test_thread", Thread::Priority::NORMAL); + handler_ = new os::Handler(thread_); HciHalHostRootcanalConfig::Get()->SetPort(kTestPort); fake_server_ = new FakeRootcanalDesktopHciServer; - hal_ = fake_registry_.Start<HciHal>(thread_); + hal_ = fake_registry_.Start<HciHal>(thread_, handler_); hal_->registerIncomingPacketCallback(&callbacks_); fake_server_socket_ = fake_server_->Accept(); // accept() after client is connected to avoid blocking @@ -156,8 +157,10 @@ protected: hal_->unregisterIncomingPacketCallback(); fake_registry_.StopAll(); close(fake_server_socket_); + handler_->Clear(); delete fake_server_; delete thread_; + delete handler_; } void SetFakeServerSocketToBlocking() { @@ -172,6 +175,7 @@ protected: TestHciHalCallbacks callbacks_; int fake_server_socket_ = -1; Thread* thread_; + os::Handler* handler_; }; void check_packet_equal(std::pair<uint8_t, HciPacket> hci_packet1_type_data_pair, diff --git a/system/gd/hal/link_clocker.cc b/system/gd/hal/link_clocker.cc index f491e9ee1b..0a7ee8366a 100644 --- a/system/gd/hal/link_clocker.cc +++ b/system/gd/hal/link_clocker.cc @@ -1,5 +1,5 @@ /* - * Copyright 2023 The Android Open Source Project + * Copyright (C) 2023 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/system/gd/hal/link_clocker.h b/system/gd/hal/link_clocker.h index acabf0787b..34286bfd96 100644 --- a/system/gd/hal/link_clocker.h +++ b/system/gd/hal/link_clocker.h @@ -1,5 +1,5 @@ /* - * Copyright 2023 The Android Open Source Project + * Copyright (C) 2023 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/system/gd/hal/ranging_hal.h b/system/gd/hal/ranging_hal.h index b22378970e..6966aedb0a 100644 --- a/system/gd/hal/ranging_hal.h +++ b/system/gd/hal/ranging_hal.h @@ -1,5 +1,5 @@ /* - * Copyright 2024 The Android Open Source Project + * Copyright (C) 2024 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. diff --git a/system/gd/hal/ranging_hal_android.cc b/system/gd/hal/ranging_hal_android.cc index 033ed789f0..086e651da2 100644 --- a/system/gd/hal/ranging_hal_android.cc +++ b/system/gd/hal/ranging_hal_android.cc @@ -1,5 +1,5 @@ /* - * Copyright 2024 The Android Open Source Project + * Copyright (C) 2024 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. diff --git a/system/gd/hal/ranging_hal_host.cc b/system/gd/hal/ranging_hal_host.cc index 59282dc422..78ce007068 100644 --- a/system/gd/hal/ranging_hal_host.cc +++ b/system/gd/hal/ranging_hal_host.cc @@ -1,5 +1,5 @@ /* - * Copyright 2024 The Android Open Source Project + * Copyright (C) 2024 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. diff --git a/system/gd/hal/ranging_hal_mock.h b/system/gd/hal/ranging_hal_mock.h new file mode 100644 index 0000000000..84696d3f64 --- /dev/null +++ b/system/gd/hal/ranging_hal_mock.h @@ -0,0 +1,67 @@ +/* + * Copyright (C) 2025 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include <gmock/gmock.h> +#include <string> + +#include "hal/ranging_hal.h" + +namespace bluetooth { +namespace hal { +namespace testing { +class MockRangingHal : public RangingHal { +public: + MOCK_METHOD(bool, IsBound, ()); + MOCK_METHOD(RangingHalVersion, GetRangingHalVersion, ()); + MOCK_METHOD(std::vector<VendorSpecificCharacteristic>, GetVendorSpecificCharacteristics, ()); + MOCK_METHOD(void, OpenSession, + (uint16_t connection_handle, uint16_t att_handle, + const std::vector<hal::VendorSpecificCharacteristic>& vendor_specific_data)); + MOCK_METHOD(void, HandleVendorSpecificReply, + (uint16_t connection_handle, + const std::vector<hal::VendorSpecificCharacteristic>& vendor_specific_reply)); + MOCK_METHOD(void, WriteRawData, + (uint16_t connection_handle, const ChannelSoundingRawData& raw_data)); + MOCK_METHOD(void, UpdateChannelSoundingConfig, + (uint16_t connection_handle, + const hci::LeCsConfigCompleteView& leCsConfigCompleteView, + uint8_t local_supported_sw_time, uint8_t remote_supported_sw_time, + uint16_t conn_interval)); + MOCK_METHOD(void, UpdateConnInterval, (uint16_t connection_handle, uint16_t conn_interval)); + MOCK_METHOD(void, UpdateProcedureEnableConfig, + (uint16_t connection_handle, + const hci::LeCsProcedureEnableCompleteView& leCsProcedureEnableCompleteView)); + MOCK_METHOD(void, WriteProcedureData, + (uint16_t connection_handle, hci::CsRole local_cs_role, + const ProcedureDataV2& procedure_data, uint16_t procedure_counter)); + MOCK_METHOD(bool, IsAbortedProcedureRequired, (uint16_t connection_handle)); + + void RegisterCallback(RangingHalCallback* callback) override { ranging_hal_callback_ = callback; } + RangingHalCallback* GetRangingHalCallback() { return ranging_hal_callback_; } + + void Start() override {} + void Stop() override {} + void ListDependencies(ModuleList* /*list*/) const override {} + std::string ToString() const override { return std::string("mock ranging hal"); } + +private: + RangingHalCallback* ranging_hal_callback_ = nullptr; +}; +} // namespace testing +} // namespace hal +} // namespace bluetooth diff --git a/system/gd/hal/serialize_packet.h b/system/gd/hal/serialize_packet.h index 70466fc164..9c13f4b671 100644 --- a/system/gd/hal/serialize_packet.h +++ b/system/gd/hal/serialize_packet.h @@ -1,5 +1,5 @@ /* - * Copyright 2019 The Android Open Source Project + * Copyright (C) 2019 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. diff --git a/system/gd/hal/snoop_logger.cc b/system/gd/hal/snoop_logger.cc index f5e0242dfd..538d13ec3e 100644 --- a/system/gd/hal/snoop_logger.cc +++ b/system/gd/hal/snoop_logger.cc @@ -1,5 +1,5 @@ /* - * Copyright 2019 The Android Open Source Project + * Copyright (C) 2019 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. @@ -1196,7 +1196,7 @@ void SnoopLogger::Capture(const HciPacket& immutable_packet, Direction direction .count(); #ifdef __ANDROID__ if (com::android::bluetooth::flags::snoop_logger_tracing()) { - LogTracePoint(timestamp_us, packet, direction, type); + LogTracePoint(packet, direction, type); } #endif // __ANDROID__ @@ -1436,8 +1436,7 @@ bool SnoopLogger::IsQualcommDebugLogEnabled() { } #ifdef __ANDROID__ -void SnoopLogger::LogTracePoint(uint64_t timestamp_us, const HciPacket& packet, Direction direction, - PacketType type) { +void SnoopLogger::LogTracePoint(const HciPacket& packet, Direction direction, PacketType type) { switch (type) { case PacketType::EVT: { uint8_t evt_code = packet[0]; @@ -1484,7 +1483,7 @@ void SnoopLogger::LogTracePoint(uint64_t timestamp_us, const HciPacket& packet, } break; } - SnoopLoggerTracing::TracePacket(timestamp_us, packet, direction, type); + SnoopLoggerTracing::TracePacket(packet, direction, type); } #endif // __ANDROID__ diff --git a/system/gd/hal/snoop_logger.h b/system/gd/hal/snoop_logger.h index d13113c9af..b009add89c 100644 --- a/system/gd/hal/snoop_logger.h +++ b/system/gd/hal/snoop_logger.h @@ -1,5 +1,5 @@ /* - * Copyright 2019 The Android Open Source Project + * Copyright (C) 2019 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. @@ -327,8 +327,7 @@ protected: std::unique_ptr<SnoopLoggerSocketThread> snoop_logger_socket_thread_; #ifdef __ANDROID__ - void LogTracePoint(uint64_t timestamp_us, const HciPacket& packet, Direction direction, - PacketType type); + void LogTracePoint(const HciPacket& packet, Direction direction, PacketType type); #endif // __ANDROID__ private: diff --git a/system/gd/hal/snoop_logger_socket_test.cc b/system/gd/hal/snoop_logger_socket_test.cc index 85642e37ed..b40f6f5bf3 100644 --- a/system/gd/hal/snoop_logger_socket_test.cc +++ b/system/gd/hal/snoop_logger_socket_test.cc @@ -1,5 +1,5 @@ /* - * Copyright 2020 The Android Open Source Project + * Copyright (C) 2020 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. diff --git a/system/gd/hal/snoop_logger_socket_thread_test.cc b/system/gd/hal/snoop_logger_socket_thread_test.cc index a967a8d2a2..726f7ab245 100644 --- a/system/gd/hal/snoop_logger_socket_thread_test.cc +++ b/system/gd/hal/snoop_logger_socket_thread_test.cc @@ -1,5 +1,5 @@ /* - * Copyright 2020 The Android Open Source Project + * Copyright (C) 2020 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. diff --git a/system/gd/hal/snoop_logger_test.cc b/system/gd/hal/snoop_logger_test.cc index de42db5c06..78d9bb54e4 100644 --- a/system/gd/hal/snoop_logger_test.cc +++ b/system/gd/hal/snoop_logger_test.cc @@ -1,5 +1,5 @@ /* - * Copyright 2020 The Android Open Source Project + * Copyright (C) 2020 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. diff --git a/system/gd/hal/snoop_logger_tracing.cc b/system/gd/hal/snoop_logger_tracing.cc index bb676136de..38ce3dec33 100644 --- a/system/gd/hal/snoop_logger_tracing.cc +++ b/system/gd/hal/snoop_logger_tracing.cc @@ -1,5 +1,5 @@ /* - * Copyright 2025 The Android Open Source Project + * Copyright (C) 2025 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -32,8 +32,8 @@ namespace bluetooth { namespace hal { namespace { -// The Perfetto trace flush interval in microseconds. -constexpr uint64_t TRACE_FLUSH_INTERVAL_MICROS = 100000; +// The Perfetto trace flush interval in nanoseconds. +constexpr uint64_t TRACE_FLUSH_INTERVAL_NANOS = 100 * 1000 * 1000; static bool SkipTracePoint(const HciPacket& packet, SnoopLogger::PacketType type) { if (type == SnoopLogger::PacketType::EVT) { @@ -139,8 +139,7 @@ BluetoothTracePacketType SnoopLoggerTracing::HciToTracePacketType( return trace_packet_type; } -void SnoopLoggerTracing::TracePacket(uint64_t timestamp_us, const HciPacket& packet, - SnoopLogger::Direction direction, +void SnoopLoggerTracing::TracePacket(const HciPacket& packet, SnoopLogger::Direction direction, SnoopLogger::PacketType type) { if (SkipTracePoint(packet, type)) { return; @@ -149,40 +148,44 @@ void SnoopLoggerTracing::TracePacket(uint64_t timestamp_us, const HciPacket& pac SnoopLoggerTracing::Trace([&](SnoopLoggerTracing::TraceContext ctx) { perfetto::LockedHandle<SnoopLoggerTracing> handle = ctx.GetDataSourceLocked(); if (handle.valid()) { - handle->Record(ctx, timestamp_us, packet, direction, type); + handle->Record(ctx, packet, direction, type); } }); } -void SnoopLoggerTracing::Record(TraceContext& ctx, uint64_t timestamp_us, const HciPacket& packet, +void SnoopLoggerTracing::Record(TraceContext& ctx, const HciPacket& packet, SnoopLogger::Direction direction, SnoopLogger::PacketType type) { - BundleKey key(packet, direction, type); - - BundleDetails& bundle = bttrace_bundles_[key]; - bundle.count++; - bundle.total_length += packet.size(); - bundle.start_ts = std::min(bundle.start_ts, timestamp_us); - bundle.end_ts = std::max(bundle.end_ts, timestamp_us); - - if (last_flush_us_ + TRACE_FLUSH_INTERVAL_MICROS < timestamp_us) { + // Write pending events before saving the new one to the bundle. Not doing this + // includes the new event after a potentially long gap, leading to a bundle with + // a very long duration. + uint64_t timestamp_ns = perfetto::base::GetBootTimeNs().count(); + if (last_flush_ns_ + TRACE_FLUSH_INTERVAL_NANOS < timestamp_ns) { for (const auto& [key, details] : bttrace_bundles_) { Write(ctx, key, details); } bttrace_bundles_.clear(); - last_flush_us_ = timestamp_us; + last_flush_ns_ = timestamp_ns; } + + BundleKey key(packet, direction, type); + + BundleDetails& bundle = bttrace_bundles_[key]; + bundle.count++; + bundle.total_length += packet.size(); + bundle.start_ts = std::min(bundle.start_ts, timestamp_ns); + bundle.end_ts = std::max(bundle.end_ts, timestamp_ns); } void SnoopLoggerTracing::Write(TraceContext& ctx, const BundleKey& key, const BundleDetails& details) { auto trace_pkt = ctx.NewTracePacket(); - trace_pkt->set_timestamp(perfetto::base::GetBootTimeNs().count()); + trace_pkt->set_timestamp(details.start_ts); auto* bt_event = trace_pkt->set_bluetooth_trace_event(); bt_event->set_packet_type(HciToTracePacketType(key.packet_type, key.direction)); bt_event->set_count(details.count); bt_event->set_length(details.total_length); - bt_event->set_duration((details.end_ts - details.start_ts) / 1000); + bt_event->set_duration(details.end_ts - details.start_ts); if (key.op_code.has_value()) { bt_event->set_op_code(*key.op_code); } diff --git a/system/gd/hal/snoop_logger_tracing.h b/system/gd/hal/snoop_logger_tracing.h index 234ac2f123..ccf2a60605 100644 --- a/system/gd/hal/snoop_logger_tracing.h +++ b/system/gd/hal/snoop_logger_tracing.h @@ -1,5 +1,5 @@ /* - * Copyright 2025 The Android Open Source Project + * Copyright (C) 2025 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -57,8 +57,8 @@ struct BundleDetails { class SnoopLoggerTracing : public perfetto::DataSource<SnoopLoggerTracing> { public: static void InitializePerfetto(); - static void TracePacket(uint64_t timestamp_us, const HciPacket& packet, - SnoopLogger::Direction direction, SnoopLogger::PacketType type); + static void TracePacket(const HciPacket& packet, SnoopLogger::Direction direction, + SnoopLogger::PacketType type); void OnSetup(const SetupArgs&) override; void OnStart(const StartArgs&) override; @@ -70,13 +70,13 @@ private: SnoopLogger::PacketType hci_packet_type, SnoopLogger::Direction direction); // Records the packet into the internal buffers. - void Record(TraceContext& ctx, uint64_t timestamp_us, const HciPacket& packet, - SnoopLogger::Direction direction, SnoopLogger::PacketType type); + void Record(TraceContext& ctx, const HciPacket& packet, SnoopLogger::Direction direction, + SnoopLogger::PacketType type); // Writes all pending data from the internal buffer as a new trace packet. void Write(TraceContext& ctx, const BundleKey& key, const BundleDetails& details); - uint64_t last_flush_us_ = 0; + uint64_t last_flush_ns_ = 0; std::unordered_map<BundleKey, BundleDetails, BundleHash> bttrace_bundles_; }; } // namespace hal diff --git a/system/gd/hal/socket_hal.h b/system/gd/hal/socket_hal.h index 3922e29da0..3a6fba43b9 100644 --- a/system/gd/hal/socket_hal.h +++ b/system/gd/hal/socket_hal.h @@ -1,5 +1,5 @@ /* - * Copyright 2024 The Android Open Source Project + * Copyright (C) 2024 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. diff --git a/system/gd/hal/socket_hal_android.cc b/system/gd/hal/socket_hal_android.cc index bdbf0a8663..4e206e3d35 100644 --- a/system/gd/hal/socket_hal_android.cc +++ b/system/gd/hal/socket_hal_android.cc @@ -1,5 +1,5 @@ /* - * Copyright 2024 The Android Open Source Project + * Copyright (C) 2024 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. diff --git a/system/gd/hal/socket_hal_host.cc b/system/gd/hal/socket_hal_host.cc index 292428a821..7ee57731cc 100644 --- a/system/gd/hal/socket_hal_host.cc +++ b/system/gd/hal/socket_hal_host.cc @@ -1,5 +1,5 @@ /* - * Copyright 2024 The Android Open Source Project + * Copyright (C) 2024 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. diff --git a/system/gd/hci/acl_builder_test.cc b/system/gd/hci/acl_builder_test.cc index b23581e36f..6c78f0b1e9 100644 --- a/system/gd/hci/acl_builder_test.cc +++ b/system/gd/hci/acl_builder_test.cc @@ -1,5 +1,5 @@ /* - * Copyright 2018 The Android Open Source Project + * Copyright (C) 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. diff --git a/system/gd/hci/acl_connection_interface.h b/system/gd/hci/acl_connection_interface.h index f90b9909d1..ba700aca0b 100644 --- a/system/gd/hci/acl_connection_interface.h +++ b/system/gd/hci/acl_connection_interface.h @@ -1,5 +1,5 @@ /* - * Copyright 2020 The Android Open Source Project + * Copyright (C) 2020 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. diff --git a/system/gd/hci/acl_manager.cc b/system/gd/hci/acl_manager.cc index 6da8b37a6d..73f455f168 100644 --- a/system/gd/hci/acl_manager.cc +++ b/system/gd/hci/acl_manager.cc @@ -1,5 +1,5 @@ /* - * Copyright 2019 The Android Open Source Project + * Copyright (C) 2019 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. diff --git a/system/gd/hci/acl_manager.h b/system/gd/hci/acl_manager.h index 8326d479ab..b6932eee52 100644 --- a/system/gd/hci/acl_manager.h +++ b/system/gd/hci/acl_manager.h @@ -1,5 +1,5 @@ /* - * Copyright 2019 The Android Open Source Project + * Copyright (C) 2019 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. diff --git a/system/gd/hci/acl_manager/acl_connection.cc b/system/gd/hci/acl_manager/acl_connection.cc index e616416f63..28605cc033 100644 --- a/system/gd/hci/acl_manager/acl_connection.cc +++ b/system/gd/hci/acl_manager/acl_connection.cc @@ -1,5 +1,5 @@ /* - * Copyright 2020 The Android Open Source Project + * Copyright (C) 2020 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. diff --git a/system/gd/hci/acl_manager/acl_connection.h b/system/gd/hci/acl_manager/acl_connection.h index 0a7e7d1f07..03fe48755d 100644 --- a/system/gd/hci/acl_manager/acl_connection.h +++ b/system/gd/hci/acl_manager/acl_connection.h @@ -1,5 +1,5 @@ /* - * Copyright 2020 The Android Open Source Project + * Copyright (C) 2020 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. diff --git a/system/gd/hci/acl_manager/acl_fragmenter.cc b/system/gd/hci/acl_manager/acl_fragmenter.cc index 3264ded78d..af0ced547e 100644 --- a/system/gd/hci/acl_manager/acl_fragmenter.cc +++ b/system/gd/hci/acl_manager/acl_fragmenter.cc @@ -1,5 +1,5 @@ /* - * Copyright 2019 The Android Open Source Project + * Copyright (C) 2019 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. diff --git a/system/gd/hci/acl_manager/acl_fragmenter.h b/system/gd/hci/acl_manager/acl_fragmenter.h index 28d14c1a3a..26fd7ea482 100644 --- a/system/gd/hci/acl_manager/acl_fragmenter.h +++ b/system/gd/hci/acl_manager/acl_fragmenter.h @@ -1,5 +1,5 @@ /* - * Copyright 2019 The Android Open Source Project + * Copyright (C) 2019 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. diff --git a/system/gd/hci/acl_manager/acl_scheduler.cc b/system/gd/hci/acl_manager/acl_scheduler.cc index f7c47505af..65981d9c23 100644 --- a/system/gd/hci/acl_manager/acl_scheduler.cc +++ b/system/gd/hci/acl_manager/acl_scheduler.cc @@ -1,5 +1,5 @@ /* - * Copyright 2022 The Android Open Source Project + * Copyright (C) 2022 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. diff --git a/system/gd/hci/acl_manager/acl_scheduler.h b/system/gd/hci/acl_manager/acl_scheduler.h index c90ab11983..4c61461be1 100644 --- a/system/gd/hci/acl_manager/acl_scheduler.h +++ b/system/gd/hci/acl_manager/acl_scheduler.h @@ -1,5 +1,5 @@ /* - * Copyright 2022 The Android Open Source Project + * Copyright (C) 2022 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. diff --git a/system/gd/hci/acl_manager/acl_scheduler_test.cc b/system/gd/hci/acl_manager/acl_scheduler_test.cc index afdddcd3a7..21414c5925 100644 --- a/system/gd/hci/acl_manager/acl_scheduler_test.cc +++ b/system/gd/hci/acl_manager/acl_scheduler_test.cc @@ -1,5 +1,5 @@ /* - * Copyright 2022 The Android Open Source Project + * Copyright (C) 2022 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. @@ -52,7 +52,7 @@ MATCHER(IsSet, "Future is set") { class AclSchedulerTest : public ::testing::Test { protected: void SetUp() override { - fake_registry_.Start<AclScheduler>(&thread_); + fake_registry_.Start<AclScheduler>(&thread_, fake_registry_.GetTestHandler()); ASSERT_TRUE(fake_registry_.IsStarted<AclScheduler>()); client_handler_ = fake_registry_.GetTestModuleHandler(&AclScheduler::Factory); diff --git a/system/gd/hci/acl_manager/assembler.h b/system/gd/hci/acl_manager/assembler.h index d126a980a2..00e63e1e38 100644 --- a/system/gd/hci/acl_manager/assembler.h +++ b/system/gd/hci/acl_manager/assembler.h @@ -1,5 +1,5 @@ /* - * Copyright 2020 The Android Open Source Project + * Copyright (C) 2020 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. diff --git a/system/gd/hci/acl_manager/classic_acl_connection.cc b/system/gd/hci/acl_manager/classic_acl_connection.cc index 301211c345..4a13a1335a 100644 --- a/system/gd/hci/acl_manager/classic_acl_connection.cc +++ b/system/gd/hci/acl_manager/classic_acl_connection.cc @@ -1,5 +1,5 @@ /* - * Copyright 2020 The Android Open Source Project + * Copyright (C) 2020 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. diff --git a/system/gd/hci/acl_manager/classic_acl_connection.h b/system/gd/hci/acl_manager/classic_acl_connection.h index 75dacf52d1..62c11b3196 100644 --- a/system/gd/hci/acl_manager/classic_acl_connection.h +++ b/system/gd/hci/acl_manager/classic_acl_connection.h @@ -1,5 +1,5 @@ /* - * Copyright 2020 The Android Open Source Project + * Copyright (C) 2020 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. diff --git a/system/gd/hci/acl_manager/classic_acl_connection_test.cc b/system/gd/hci/acl_manager/classic_acl_connection_test.cc index 32949927e7..e6167285c8 100644 --- a/system/gd/hci/acl_manager/classic_acl_connection_test.cc +++ b/system/gd/hci/acl_manager/classic_acl_connection_test.cc @@ -1,5 +1,5 @@ /* - * Copyright 2022 The Android Open Source Project + * Copyright (C) 2022 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. diff --git a/system/gd/hci/acl_manager/classic_impl.h b/system/gd/hci/acl_manager/classic_impl.h index ecef1f9414..586b64549c 100644 --- a/system/gd/hci/acl_manager/classic_impl.h +++ b/system/gd/hci/acl_manager/classic_impl.h @@ -1,5 +1,5 @@ /* - * Copyright 2020 The Android Open Source Project + * Copyright (C) 2020 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. diff --git a/system/gd/hci/acl_manager/classic_impl_test.cc b/system/gd/hci/acl_manager/classic_impl_test.cc index 6b57eac662..11e89bb633 100644 --- a/system/gd/hci/acl_manager/classic_impl_test.cc +++ b/system/gd/hci/acl_manager/classic_impl_test.cc @@ -1,5 +1,5 @@ /* - * Copyright 2023 The Android Open Source Project + * Copyright (C) 2023 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/system/gd/hci/acl_manager/connection_callbacks.h b/system/gd/hci/acl_manager/connection_callbacks.h index 8804b5ad9d..2998f20724 100644 --- a/system/gd/hci/acl_manager/connection_callbacks.h +++ b/system/gd/hci/acl_manager/connection_callbacks.h @@ -1,5 +1,5 @@ /* - * Copyright 2020 The Android Open Source Project + * Copyright (C) 2020 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. diff --git a/system/gd/hci/acl_manager/connection_callbacks_mock.h b/system/gd/hci/acl_manager/connection_callbacks_mock.h index 64bd067db2..5018331c42 100644 --- a/system/gd/hci/acl_manager/connection_callbacks_mock.h +++ b/system/gd/hci/acl_manager/connection_callbacks_mock.h @@ -1,5 +1,5 @@ /* - * Copyright 2023 The Android Open Source Project + * Copyright (C) 2023 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/system/gd/hci/acl_manager/connection_management_callbacks.h b/system/gd/hci/acl_manager/connection_management_callbacks.h index 55d0062c0a..b4546a3a2d 100644 --- a/system/gd/hci/acl_manager/connection_management_callbacks.h +++ b/system/gd/hci/acl_manager/connection_management_callbacks.h @@ -1,5 +1,5 @@ /* - * Copyright 2020 The Android Open Source Project + * Copyright (C) 2020 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. diff --git a/system/gd/hci/acl_manager/connection_management_callbacks_mock.h b/system/gd/hci/acl_manager/connection_management_callbacks_mock.h index e453ac99fc..eab69fcd39 100644 --- a/system/gd/hci/acl_manager/connection_management_callbacks_mock.h +++ b/system/gd/hci/acl_manager/connection_management_callbacks_mock.h @@ -1,5 +1,5 @@ /* - * Copyright 2023 The Android Open Source Project + * Copyright (C) 2023 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/system/gd/hci/acl_manager/le_acceptlist_callbacks.h b/system/gd/hci/acl_manager/le_acceptlist_callbacks.h index a7b7dd5f5e..d547a79c3c 100644 --- a/system/gd/hci/acl_manager/le_acceptlist_callbacks.h +++ b/system/gd/hci/acl_manager/le_acceptlist_callbacks.h @@ -1,5 +1,5 @@ /* - * Copyright 2020 The Android Open Source Project + * Copyright (C) 2020 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. diff --git a/system/gd/hci/acl_manager/le_acl_connection.cc b/system/gd/hci/acl_manager/le_acl_connection.cc index 8e6f93be08..3b40ddc52c 100644 --- a/system/gd/hci/acl_manager/le_acl_connection.cc +++ b/system/gd/hci/acl_manager/le_acl_connection.cc @@ -1,5 +1,5 @@ /* - * Copyright 2020 The Android Open Source Project + * Copyright (C) 2020 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. diff --git a/system/gd/hci/acl_manager/le_acl_connection.h b/system/gd/hci/acl_manager/le_acl_connection.h index 5052be51a7..35ef292708 100644 --- a/system/gd/hci/acl_manager/le_acl_connection.h +++ b/system/gd/hci/acl_manager/le_acl_connection.h @@ -1,5 +1,5 @@ /* - * Copyright 2020 The Android Open Source Project + * Copyright (C) 2020 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. diff --git a/system/gd/hci/acl_manager/le_acl_connection_test.cc b/system/gd/hci/acl_manager/le_acl_connection_test.cc index 5153fa4d3b..403f3fd9c4 100644 --- a/system/gd/hci/acl_manager/le_acl_connection_test.cc +++ b/system/gd/hci/acl_manager/le_acl_connection_test.cc @@ -1,5 +1,5 @@ /* - * Copyright 2022 The Android Open Source Project + * Copyright (C) 2022 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. diff --git a/system/gd/hci/acl_manager/le_connection_callbacks.h b/system/gd/hci/acl_manager/le_connection_callbacks.h index 2359c5ac32..c33dbbbe33 100644 --- a/system/gd/hci/acl_manager/le_connection_callbacks.h +++ b/system/gd/hci/acl_manager/le_connection_callbacks.h @@ -1,5 +1,5 @@ /* - * Copyright 2020 The Android Open Source Project + * Copyright (C) 2020 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. diff --git a/system/gd/hci/acl_manager/le_connection_callbacks_mock.h b/system/gd/hci/acl_manager/le_connection_callbacks_mock.h index fca3e93b89..4866ed8e29 100644 --- a/system/gd/hci/acl_manager/le_connection_callbacks_mock.h +++ b/system/gd/hci/acl_manager/le_connection_callbacks_mock.h @@ -1,5 +1,5 @@ /* - * Copyright 2023 The Android Open Source Project + * Copyright (C) 2023 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/system/gd/hci/acl_manager/le_connection_management_callbacks.h b/system/gd/hci/acl_manager/le_connection_management_callbacks.h index 6ac56af029..d7b33c64b7 100644 --- a/system/gd/hci/acl_manager/le_connection_management_callbacks.h +++ b/system/gd/hci/acl_manager/le_connection_management_callbacks.h @@ -1,5 +1,5 @@ /* - * Copyright 2020 The Android Open Source Project + * Copyright (C) 2020 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. diff --git a/system/gd/hci/acl_manager/le_connection_management_callbacks_mock.h b/system/gd/hci/acl_manager/le_connection_management_callbacks_mock.h index bfbd214779..280dd7a860 100644 --- a/system/gd/hci/acl_manager/le_connection_management_callbacks_mock.h +++ b/system/gd/hci/acl_manager/le_connection_management_callbacks_mock.h @@ -1,5 +1,5 @@ /* - * Copyright 2023 The Android Open Source Project + * Copyright (C) 2023 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/system/gd/hci/acl_manager/le_impl.h b/system/gd/hci/acl_manager/le_impl.h index ac3e7171f9..a6761e38b7 100644 --- a/system/gd/hci/acl_manager/le_impl.h +++ b/system/gd/hci/acl_manager/le_impl.h @@ -1,5 +1,5 @@ /* - * Copyright 2020 The Android Open Source Project + * Copyright (C) 2020 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. diff --git a/system/gd/hci/acl_manager/le_impl_test.cc b/system/gd/hci/acl_manager/le_impl_test.cc index d43d2faca1..66bc16bbd8 100644 --- a/system/gd/hci/acl_manager/le_impl_test.cc +++ b/system/gd/hci/acl_manager/le_impl_test.cc @@ -1,5 +1,5 @@ /* - * Copyright 2022 The Android Open Source Project + * Copyright (C) 2022 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. diff --git a/system/gd/hci/acl_manager/round_robin_scheduler.cc b/system/gd/hci/acl_manager/round_robin_scheduler.cc index 6abf838728..ad0e6dc621 100644 --- a/system/gd/hci/acl_manager/round_robin_scheduler.cc +++ b/system/gd/hci/acl_manager/round_robin_scheduler.cc @@ -1,5 +1,5 @@ /* - * Copyright 2020 The Android Open Source Project + * Copyright (C) 2020 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. diff --git a/system/gd/hci/acl_manager/round_robin_scheduler.h b/system/gd/hci/acl_manager/round_robin_scheduler.h index 61be5f1147..080ce0988f 100644 --- a/system/gd/hci/acl_manager/round_robin_scheduler.h +++ b/system/gd/hci/acl_manager/round_robin_scheduler.h @@ -1,5 +1,5 @@ /* - * Copyright 2020 The Android Open Source Project + * Copyright (C) 2020 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. diff --git a/system/gd/hci/acl_manager/round_robin_scheduler_test.cc b/system/gd/hci/acl_manager/round_robin_scheduler_test.cc index f2c9b5528b..25bd2aff80 100644 --- a/system/gd/hci/acl_manager/round_robin_scheduler_test.cc +++ b/system/gd/hci/acl_manager/round_robin_scheduler_test.cc @@ -1,5 +1,5 @@ /* - * Copyright 2020 The Android Open Source Project + * Copyright (C) 2020 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. diff --git a/system/gd/hci/acl_manager_mock.h b/system/gd/hci/acl_manager_mock.h index 330b82bdac..75af214e5b 100644 --- a/system/gd/hci/acl_manager_mock.h +++ b/system/gd/hci/acl_manager_mock.h @@ -1,5 +1,5 @@ /* - * Copyright 2019 The Android Open Source Project + * Copyright (C) 2019 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. diff --git a/system/gd/hci/acl_manager_test.cc b/system/gd/hci/acl_manager_test.cc index c4f7deb89e..8b33dc723e 100644 --- a/system/gd/hci/acl_manager_test.cc +++ b/system/gd/hci/acl_manager_test.cc @@ -1,5 +1,5 @@ /* - * Copyright 2019 The Android Open Source Project + * Copyright (C) 2019 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. @@ -119,7 +119,7 @@ protected: ASSERT_NE(client_handler_, nullptr); bluetooth::hci::testing::mock_storage_ = new storage::StorageModule(new os::Handler(&thread_)); bluetooth::hci::testing::mock_storage_->Start(); - fake_registry_.Start<AclManager>(&thread_); + fake_registry_.Start<AclManager>(&thread_, handler_); acl_manager_ = static_cast<AclManager*>(fake_registry_.GetModuleUnderTest(&AclManager::Factory)); Address::FromString("A1:A2:A3:A4:A5:A6", remote); @@ -173,6 +173,7 @@ protected: HciLayerFake* test_hci_layer_ = nullptr; TestController* test_controller_ = nullptr; os::Thread& thread_ = fake_registry_.GetTestThread(); + os::Handler* handler_ = fake_registry_.GetTestHandler(); AclManager* acl_manager_ = nullptr; os::Handler* client_handler_ = nullptr; Address remote; @@ -1146,7 +1147,7 @@ protected: ASSERT_NE(client_handler_, nullptr); bluetooth::hci::testing::mock_storage_ = new storage::StorageModule(new os::Handler(&thread_)); bluetooth::hci::testing::mock_storage_->Start(); - fake_registry_.Start<AclManager>(&thread_); + fake_registry_.Start<AclManager>(&thread_, handler_); acl_manager_ = static_cast<AclManager*>(fake_registry_.GetModuleUnderTest(&AclManager::Factory)); Address::FromString("A1:A2:A3:A4:A5:A6", remote); diff --git a/system/gd/hci/acl_manager_unittest.cc b/system/gd/hci/acl_manager_unittest.cc index 797b5aed26..848141da0b 100644 --- a/system/gd/hci/acl_manager_unittest.cc +++ b/system/gd/hci/acl_manager_unittest.cc @@ -1,5 +1,5 @@ /* - * Copyright 2022 The Android Open Source Project + * Copyright (C) 2022 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. @@ -155,7 +155,7 @@ protected: fake_registry_.InjectTestModule(&Controller::Factory, test_controller_); client_handler_ = fake_registry_.GetTestModuleHandler(&HciLayer::Factory); ASSERT_NE(client_handler_, nullptr); - fake_registry_.Start<AclManager>(&thread_); + fake_registry_.Start<AclManager>(&thread_, fake_registry_.GetTestHandler()); } void TearDown() override { @@ -440,7 +440,7 @@ protected: fake_registry_.InjectTestModule(&Controller::Factory, test_controller_); client_handler_ = fake_registry_.GetTestModuleHandler(&HciLayer::Factory); ASSERT_NE(client_handler_, nullptr); - fake_registry_.Start<AclManager>(&thread_); + fake_registry_.Start<AclManager>(&thread_, fake_registry_.GetTestHandler()); acl_manager_ = static_cast<AclManager*>(fake_registry_.GetModuleUnderTest(&AclManager::Factory)); hci::Address address; diff --git a/system/gd/hci/address_unittest.cc b/system/gd/hci/address_unittest.cc index 0254545631..ee81f975f6 100644 --- a/system/gd/hci/address_unittest.cc +++ b/system/gd/hci/address_unittest.cc @@ -1,6 +1,6 @@ /****************************************************************************** * - * Copyright 2019 The Android Open Source Project + * Copyright (C) 2019 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. diff --git a/system/gd/hci/address_with_type.h b/system/gd/hci/address_with_type.h index 26c35e814d..b2a662bcae 100644 --- a/system/gd/hci/address_with_type.h +++ b/system/gd/hci/address_with_type.h @@ -1,6 +1,6 @@ /****************************************************************************** * - * Copyright 2019 The Android Open Source Project + * Copyright (C) 2019 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. diff --git a/system/gd/hci/address_with_type_test.cc b/system/gd/hci/address_with_type_test.cc index c3b8bb0db9..9128bf1f57 100644 --- a/system/gd/hci/address_with_type_test.cc +++ b/system/gd/hci/address_with_type_test.cc @@ -1,6 +1,6 @@ /****************************************************************************** * - * Copyright 2019 The Android Open Source Project + * Copyright (C) 2019 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. diff --git a/system/gd/hci/class_of_device_unittest.cc b/system/gd/hci/class_of_device_unittest.cc index 1d3f4f8f3a..4bcedfd84d 100644 --- a/system/gd/hci/class_of_device_unittest.cc +++ b/system/gd/hci/class_of_device_unittest.cc @@ -1,6 +1,6 @@ /****************************************************************************** * - * Copyright 2019 The Android Open Source Project + * Copyright (C) 2019 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. diff --git a/system/gd/hci/command_interface.h b/system/gd/hci/command_interface.h index a6781ef7c5..56b6b5f63f 100644 --- a/system/gd/hci/command_interface.h +++ b/system/gd/hci/command_interface.h @@ -1,5 +1,5 @@ /* - * Copyright 2020 The Android Open Source Project + * Copyright (C) 2020 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. diff --git a/system/gd/hci/controller.cc b/system/gd/hci/controller.cc index eaba7da848..b14e434781 100644 --- a/system/gd/hci/controller.cc +++ b/system/gd/hci/controller.cc @@ -1,5 +1,5 @@ /* - * Copyright 2019 The Android Open Source Project + * Copyright (C) 2019 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. diff --git a/system/gd/hci/controller.h b/system/gd/hci/controller.h index 70609950da..6a35bb691f 100644 --- a/system/gd/hci/controller.h +++ b/system/gd/hci/controller.h @@ -1,5 +1,5 @@ /* - * Copyright 2019 The Android Open Source Project + * Copyright (C) 2019 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. diff --git a/system/gd/hci/controller_interface.h b/system/gd/hci/controller_interface.h index a9ebecd32a..a2a7b64c18 100644 --- a/system/gd/hci/controller_interface.h +++ b/system/gd/hci/controller_interface.h @@ -1,5 +1,5 @@ /* - * Copyright 2023 The Android Open Source Project + * Copyright (C) 2023 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/system/gd/hci/controller_interface_mock.h b/system/gd/hci/controller_interface_mock.h index 36bc50a423..8b21585009 100644 --- a/system/gd/hci/controller_interface_mock.h +++ b/system/gd/hci/controller_interface_mock.h @@ -1,5 +1,5 @@ /* - * Copyright 2021 The Android Open Source Project + * Copyright (C) 2021 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. diff --git a/system/gd/hci/controller_mock.h b/system/gd/hci/controller_mock.h index fd3a7058d1..e39d721126 100644 --- a/system/gd/hci/controller_mock.h +++ b/system/gd/hci/controller_mock.h @@ -1,5 +1,5 @@ /* - * Copyright 2021 The Android Open Source Project + * Copyright (C) 2021 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. diff --git a/system/gd/hci/controller_test.cc b/system/gd/hci/controller_test.cc index 0743204ffd..e680a8598e 100644 --- a/system/gd/hci/controller_test.cc +++ b/system/gd/hci/controller_test.cc @@ -1,5 +1,5 @@ /* - * Copyright 2019 The Android Open Source Project + * Copyright (C) 2019 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. @@ -291,7 +291,7 @@ protected: vendor_capabilities_.reset(); fake_registry_.InjectTestModule(&HciLayer::Factory, test_hci_layer_); client_handler_ = fake_registry_.GetTestModuleHandler(&HciLayer::Factory); - fake_registry_.Start<Controller>(&thread_); + fake_registry_.Start<Controller>(&thread_, fake_registry_.GetTestHandler()); controller_ = static_cast<Controller*>(fake_registry_.GetModuleUnderTest(&Controller::Factory)); } diff --git a/system/gd/hci/controller_unittest.cc b/system/gd/hci/controller_unittest.cc index 6ab8d4d68b..cb90589637 100644 --- a/system/gd/hci/controller_unittest.cc +++ b/system/gd/hci/controller_unittest.cc @@ -1,5 +1,5 @@ /* - * Copyright 2022 The Android Open Source Project + * Copyright (C) 2022 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. diff --git a/system/gd/hci/distance_measurement_interface.h b/system/gd/hci/distance_measurement_interface.h index 9b6e7727c3..055d9e875c 100644 --- a/system/gd/hci/distance_measurement_interface.h +++ b/system/gd/hci/distance_measurement_interface.h @@ -1,5 +1,5 @@ /* - * Copyright 2023 The Android Open Source Project + * Copyright (C) 2023 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/system/gd/hci/distance_measurement_manager.cc b/system/gd/hci/distance_measurement_manager.cc index d9b9200552..6bdfde00b9 100644 --- a/system/gd/hci/distance_measurement_manager.cc +++ b/system/gd/hci/distance_measurement_manager.cc @@ -1,5 +1,5 @@ /* - * Copyright 2022 The Android Open Source Project + * Copyright (C) 2022 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. @@ -337,7 +337,11 @@ struct DistanceMeasurementManager::impl : bluetooth::hal::RangingHalCallback { } } - void stop() { hci_layer_->UnregisterLeEventHandler(hci::SubeventCode::TRANSMIT_POWER_REPORTING); } + void stop() { + hci_layer_->UnregisterLeEventHandler(hci::SubeventCode::TRANSMIT_POWER_REPORTING); + cs_requester_trackers_.clear(); + cs_responder_trackers_.clear(); + } void register_distance_measurement_callbacks(DistanceMeasurementCallbacks* callbacks) { distance_measurement_callbacks_ = callbacks; @@ -1097,10 +1101,6 @@ struct DistanceMeasurementManager::impl : bluetooth::hal::RangingHalCallback { if (!live_tracker->local_start) { // reset the responder state, as no other event to set the state. live_tracker->state = CsTrackerState::WAIT_FOR_CONFIG_COMPLETE; - } else { - live_tracker->setup_complete = true; - log::info("connection_handle: {}, address: {}, config_id: {}", connection_handle, - live_tracker->address, config_id); } live_tracker->used_config_id = config_id; @@ -1175,6 +1175,8 @@ struct DistanceMeasurementManager::impl : bluetooth::hal::RangingHalCallback { } if (it->second.measurement_ongoing) { + log::debug("cs set up succeed"); + it->second.setup_complete = true; send_le_cs_procedure_enable(connection_handle, Enable::ENABLED); } } @@ -2620,17 +2622,17 @@ struct DistanceMeasurementManager::impl : bluetooth::hal::RangingHalCallback { v1.insert(v1.end(), v2.begin(), v2.end()); } - os::Handler* handler_; - hal::RangingHal* ranging_hal_; - hci::Controller* controller_; - hci::HciLayer* hci_layer_; - hci::AclManager* acl_manager_; - hci::DistanceMeasurementInterface* distance_measurement_interface_; + os::Handler* handler_ = nullptr; + hal::RangingHal* ranging_hal_ = nullptr; + hci::Controller* controller_ = nullptr; + hci::HciLayer* hci_layer_ = nullptr; + hci::AclManager* acl_manager_ = nullptr; + hci::DistanceMeasurementInterface* distance_measurement_interface_ = nullptr; std::unordered_map<Address, RSSITracker> rssi_trackers; std::unordered_map<uint16_t, CsTracker> cs_requester_trackers_; std::unordered_map<uint16_t, CsTracker> cs_responder_trackers_; std::unordered_map<uint16_t, uint16_t> gatt_mtus_; - DistanceMeasurementCallbacks* distance_measurement_callbacks_; + DistanceMeasurementCallbacks* distance_measurement_callbacks_ = nullptr; CsOptionalSubfeaturesSupported cs_subfeature_supported_; uint8_t num_antennas_supported_ = 0x01; bool local_support_phase_based_ranging_ = false; diff --git a/system/gd/hci/distance_measurement_manager.h b/system/gd/hci/distance_measurement_manager.h index c0f3cae654..9d13e50cd1 100644 --- a/system/gd/hci/distance_measurement_manager.h +++ b/system/gd/hci/distance_measurement_manager.h @@ -1,5 +1,5 @@ /* - * Copyright 2022 The Android Open Source Project + * Copyright (C) 2022 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. diff --git a/system/gd/hci/distance_measurement_manager_mock.h b/system/gd/hci/distance_measurement_manager_mock.h index 827c096670..ba9919af9e 100644 --- a/system/gd/hci/distance_measurement_manager_mock.h +++ b/system/gd/hci/distance_measurement_manager_mock.h @@ -1,5 +1,5 @@ /* - * Copyright 2022 The Android Open Source Project + * Copyright (C) 2022 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. @@ -31,12 +31,22 @@ struct DistanceMeasurementManager::impl : public bluetooth::hci::LeAddressManage namespace testing { class MockDistanceMeasurementCallbacks : public DistanceMeasurementCallbacks { +public: MOCK_METHOD(void, OnDistanceMeasurementStarted, (Address, DistanceMeasurementMethod)); MOCK_METHOD(void, OnDistanceMeasurementStopped, (Address, DistanceMeasurementErrorCode, DistanceMeasurementMethod)); MOCK_METHOD(void, OnDistanceMeasurementResult, (Address, uint32_t, uint32_t, int, int, int, int, uint64_t, int8_t, double, DistanceMeasurementDetectedAttackLevel, double, DistanceMeasurementMethod)); + MOCK_METHOD(void, OnRasFragmentReady, + (Address address, uint16_t procedure_counter, bool is_last, + std::vector<uint8_t> raw_data)); + MOCK_METHOD(void, OnVendorSpecificCharacteristics, + (std::vector<hal::VendorSpecificCharacteristic> vendor_specific_characteristics)); + MOCK_METHOD(void, OnVendorSpecificReply, + (Address address, std::vector<bluetooth::hal::VendorSpecificCharacteristic> + vendor_specific_characteristics)); + MOCK_METHOD(void, OnHandleVendorSpecificReplyComplete, (Address address, bool success)); }; class MockDistanceMeasurementManager : public DistanceMeasurementManager { diff --git a/system/gd/hci/distance_measurement_manager_test.cc b/system/gd/hci/distance_measurement_manager_test.cc new file mode 100644 index 0000000000..d3b7706ad0 --- /dev/null +++ b/system/gd/hci/distance_measurement_manager_test.cc @@ -0,0 +1,345 @@ +/* + * Copyright (C) 2025 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "hci/distance_measurement_manager.h" + +#include <bluetooth/log.h> +#include <flag_macros.h> +#include <gmock/gmock.h> +#include <gtest/gtest.h> + +#include "hal/ranging_hal.h" +#include "hal/ranging_hal_mock.h" +#include "hci/acl_manager_mock.h" +#include "hci/address.h" +#include "hci/controller.h" +#include "hci/controller_mock.h" +#include "hci/distance_measurement_manager_mock.h" +#include "hci/hci_layer.h" +#include "hci/hci_layer_fake.h" +#include "module.h" +#include "packet/packet_view.h" +#include "ras/ras_packets.h" + +using testing::_; +using testing::AtLeast; +using testing::Return; + +namespace { +constexpr auto kTimeout = std::chrono::seconds(1); +} + +namespace bluetooth { +namespace hci { +namespace { +class TestController : public testing::MockController { +protected: + void Start() override {} + void Stop() override {} + void ListDependencies(ModuleList* /* list */) const override {} +}; + +class TestAclManager : public testing::MockAclManager { +public: + void AddDeviceToRelaxedConnectionIntervalList(const Address /*address*/) override {} + +protected: + void Start() override {} + void Stop() override {} + void ListDependencies(ModuleList* /* list */) const override {} +}; + +struct CsReadCapabilitiesCompleteEvent { + ErrorCode error_code = ErrorCode::SUCCESS; + uint8_t num_config_supported = 4; + uint16_t max_consecutive_procedures_supported = 0; + uint8_t num_antennas_supported = 2; + uint8_t max_antenna_paths_supported = 4; + CsRoleSupported roles_supported = {/*initiator=*/1, /*reflector=*/1}; + unsigned char modes_supported = {/*mode_3=*/1}; + CsRttCapability rtt_capability = {/*rtt_aa_only_n=*/1, /*rtt_sounding_n=*/1, + /*rtt_random_payload_n=*/1}; + uint8_t rtt_aa_only_n = 1; + uint8_t rtt_sounding_n = 1; + uint8_t rtt_random_payload_n = 1; + CsOptionalNadmSoundingCapability nadm_sounding_capability = { + /*normalized_attack_detector_metric=*/1}; + CsOptionalNadmRandomCapability nadm_random_capability = {/*normalized_attack_detector_metric=*/1}; + CsOptionalCsSyncPhysSupported cs_sync_phys_supported = {/*le_2m_phy=*/1}; + CsOptionalSubfeaturesSupported subfeatures_supported = {/*no_frequency_actuation_error=*/1, + /*channel_selection_algorithm=*/1, + /*phase_based_ranging=*/1}; + CsOptionalTIp1TimesSupported t_ip1_times_supported = { + /*support_10_microsecond=*/1, /*support_20_microsecond=*/1, + /*support_30_microsecond=*/1, /*support_40_microsecond=*/1, + /*support_50_microsecond=*/1, /*support_60_microsecond=*/1, + /*support_80_microsecond=*/1}; + CsOptionalTIp2TimesSupported t_ip2_times_supported = { + /*support_10_microsecond=*/1, /*support_20_microsecond=*/1, + /*support_30_microsecond=*/1, + /*support_40_microsecond=*/1, /*support_50_microsecond=*/1, + /*support_60_microsecond=*/1, /*support_80_microsecond=*/1}; + CsOptionalTFcsTimesSupported t_fcs_times_supported = { + /*support_15_microsecond=*/1, /*support_20_microsecond=*/1, + /*support_30_microsecond=*/1, /*support_40_microsecond=*/1, + /*support_50_microsecond=*/1, + /*support_60_microsecond=*/1, /*support_80_microsecond=*/1, + /*support_100_microsecond=*/1, + /*support_120_microsecond=*/1}; + CsOptionalTPmTimesSupported t_pm_times_supported = {/*support_10_microsecond=*/1, + /*support_20_microsecond=*/1}; + uint8_t t_sw_time_supported = 1; + uint8_t tx_snr_capability = 1; +}; + +struct StartMeasurementParameters { + Address remote_address = Address::FromString("12:34:56:78:9a:bc").value(); + uint16_t connection_handle = 64; + Role local_hci_role = Role::CENTRAL; + uint16_t interval = 200; // 200ms + DistanceMeasurementMethod method = DistanceMeasurementMethod::METHOD_CS; +}; + +class DistanceMeasurementManagerTest : public ::testing::Test { +protected: + void SetUp() override { + test_hci_layer_ = new HciLayerFake; // Ownership is transferred to registry + mock_controller_ = new TestController; // Ownership is transferred to registry + mock_ranging_hal_ = new hal::testing::MockRangingHal; // Ownership is transferred to registry + mock_acl_manager_ = new TestAclManager; // Ownership is transferred to registry + fake_registry_.InjectTestModule(&hal::RangingHal::Factory, mock_ranging_hal_); + fake_registry_.InjectTestModule(&Controller::Factory, mock_controller_); + fake_registry_.InjectTestModule(&HciLayer::Factory, test_hci_layer_); + fake_registry_.InjectTestModule(&AclManager::Factory, mock_acl_manager_); + + client_handler_ = fake_registry_.GetTestModuleHandler(&HciLayer::Factory); + ASSERT_NE(client_handler_, nullptr); + + EXPECT_CALL(*mock_controller_, SupportsBleChannelSounding()).WillOnce(Return(true)); + EXPECT_CALL(*mock_ranging_hal_, IsBound()).Times(AtLeast(1)).WillRepeatedly(Return(true)); + + handler_ = fake_registry_.GetTestHandler(); + dm_manager_ = fake_registry_.Start<DistanceMeasurementManager>(&thread_, handler_); + + dm_manager_->RegisterDistanceMeasurementCallbacks(&mock_dm_callbacks_); + } + + void TearDown() override { + fake_registry_.SynchronizeModuleHandler(&DistanceMeasurementManager::Factory, + std::chrono::milliseconds(20)); + fake_registry_.StopAll(); + } + + std::future<void> GetDmSessionFuture() { + log::assert_that(dm_session_promise_ == nullptr, "Promises promises ... Only one at a time"); + dm_session_promise_ = std::make_unique<std::promise<void>>(); + return dm_session_promise_->get_future(); + } + + void sync_client_handler() { + log::assert_that(thread_.GetReactor()->WaitForIdle(kTimeout), + "assert failed: thread_.GetReactor()->WaitForIdle(kTimeout)"); + } + + static std::unique_ptr<LeCsReadLocalSupportedCapabilitiesCompleteBuilder> + GetLocalSupportedCapabilitiesCompleteEvent( + const CsReadCapabilitiesCompleteEvent& cs_cap_complete_event) { + return LeCsReadLocalSupportedCapabilitiesCompleteBuilder::Create( + /*num_hci_command_packets=*/0xFF, cs_cap_complete_event.error_code, + cs_cap_complete_event.num_config_supported, + cs_cap_complete_event.max_consecutive_procedures_supported, + cs_cap_complete_event.num_antennas_supported, + cs_cap_complete_event.max_antenna_paths_supported, + cs_cap_complete_event.roles_supported, cs_cap_complete_event.modes_supported, + cs_cap_complete_event.rtt_capability, cs_cap_complete_event.rtt_aa_only_n, + cs_cap_complete_event.rtt_sounding_n, cs_cap_complete_event.rtt_random_payload_n, + cs_cap_complete_event.nadm_sounding_capability, + cs_cap_complete_event.nadm_random_capability, + cs_cap_complete_event.cs_sync_phys_supported, + cs_cap_complete_event.subfeatures_supported, + cs_cap_complete_event.t_ip1_times_supported, + cs_cap_complete_event.t_ip2_times_supported, + cs_cap_complete_event.t_fcs_times_supported, cs_cap_complete_event.t_pm_times_supported, + cs_cap_complete_event.t_sw_time_supported, cs_cap_complete_event.tx_snr_capability); + } + + static std::unique_ptr<LeCsReadRemoteSupportedCapabilitiesCompleteBuilder> + GetRemoteSupportedCapabilitiesCompleteEvent( + uint16_t connection_handle, + const CsReadCapabilitiesCompleteEvent& cs_cap_complete_event) { + return LeCsReadRemoteSupportedCapabilitiesCompleteBuilder::Create( + cs_cap_complete_event.error_code, connection_handle, + cs_cap_complete_event.num_config_supported, + cs_cap_complete_event.max_consecutive_procedures_supported, + cs_cap_complete_event.num_antennas_supported, + cs_cap_complete_event.max_antenna_paths_supported, + cs_cap_complete_event.roles_supported, cs_cap_complete_event.modes_supported, + cs_cap_complete_event.rtt_capability, cs_cap_complete_event.rtt_aa_only_n, + cs_cap_complete_event.rtt_sounding_n, cs_cap_complete_event.rtt_random_payload_n, + cs_cap_complete_event.nadm_sounding_capability, + cs_cap_complete_event.nadm_random_capability, + cs_cap_complete_event.cs_sync_phys_supported, + cs_cap_complete_event.subfeatures_supported, + cs_cap_complete_event.t_ip1_times_supported, + cs_cap_complete_event.t_ip2_times_supported, + cs_cap_complete_event.t_fcs_times_supported, cs_cap_complete_event.t_pm_times_supported, + cs_cap_complete_event.t_sw_time_supported, cs_cap_complete_event.tx_snr_capability); + } + + void StartMeasurement(const StartMeasurementParameters& params) { + dm_manager_->StartDistanceMeasurement(params.remote_address, params.connection_handle, + params.local_hci_role, params.interval, params.method); + } + + void ReceivedReadLocalCapabilitiesComplete() { + CsReadCapabilitiesCompleteEvent read_cs_complete_event; + test_hci_layer_->IncomingEvent( + GetLocalSupportedCapabilitiesCompleteEvent(read_cs_complete_event)); + } + + void StartMeasurementTillRasConnectedEvent(const StartMeasurementParameters& params) { + ReceivedReadLocalCapabilitiesComplete(); + EXPECT_CALL(*mock_ranging_hal_, OpenSession(_, _, _)) + .WillOnce([this](uint16_t connection_handle, uint16_t /*att_handle*/, + const std::vector<hal::VendorSpecificCharacteristic>& + vendor_specific_data) { + mock_ranging_hal_->GetRangingHalCallback()->OnOpened(connection_handle, + vendor_specific_data); + }); + StartMeasurement(params); + dm_manager_->HandleRasClientConnectedEvent( + params.remote_address, params.connection_handle, + /*att_handle=*/0, + /*vendor_specific_data=*/std::vector<hal::VendorSpecificCharacteristic>(), + /*conn_interval=*/24); + } + +protected: + TestModuleRegistry fake_registry_; + HciLayerFake* test_hci_layer_ = nullptr; + TestController* mock_controller_ = nullptr; + TestAclManager* mock_acl_manager_ = nullptr; + hal::testing::MockRangingHal* mock_ranging_hal_ = nullptr; + os::Thread& thread_ = fake_registry_.GetTestThread(); + os::Handler* client_handler_ = nullptr; + os::Handler* handler_ = nullptr; + + DistanceMeasurementManager* dm_manager_ = nullptr; + testing::MockDistanceMeasurementCallbacks mock_dm_callbacks_; + std::unique_ptr<std::promise<void>> dm_session_promise_; +}; + +TEST_F(DistanceMeasurementManagerTest, setup_teardown) { + EXPECT_NE(mock_ranging_hal_->GetRangingHalCallback(), nullptr); +} + +TEST_F(DistanceMeasurementManagerTest, fail_read_local_cs_capabilities) { + StartMeasurementParameters params; + auto dm_session_future = GetDmSessionFuture(); + EXPECT_CALL(mock_dm_callbacks_, + OnDistanceMeasurementStopped(params.remote_address, + DistanceMeasurementErrorCode::REASON_INTERNAL_ERROR, + DistanceMeasurementMethod::METHOD_CS)) + .WillOnce([this](const Address& /*address*/, DistanceMeasurementErrorCode /*error_code*/, + DistanceMeasurementMethod /*method*/) { + ASSERT_NE(dm_session_promise_, nullptr); + dm_session_promise_->set_value(); + dm_session_promise_.reset(); + }); + + CsReadCapabilitiesCompleteEvent read_cs_complete_event; + read_cs_complete_event.error_code = ErrorCode::COMMAND_DISALLOWED; + test_hci_layer_->IncomingEvent( + GetLocalSupportedCapabilitiesCompleteEvent(read_cs_complete_event)); + + StartMeasurement(params); + + dm_session_future.wait_for(kTimeout); + sync_client_handler(); +} + +TEST_F(DistanceMeasurementManagerTest, ras_remote_not_support) { + ReceivedReadLocalCapabilitiesComplete(); + StartMeasurementParameters params; + auto dm_session_future = GetDmSessionFuture(); + EXPECT_CALL(mock_dm_callbacks_, + OnDistanceMeasurementStopped( + params.remote_address, + DistanceMeasurementErrorCode::REASON_FEATURE_NOT_SUPPORTED_REMOTE, + DistanceMeasurementMethod::METHOD_CS)) + .WillOnce([this](const Address& /*address*/, DistanceMeasurementErrorCode /*error_code*/, + DistanceMeasurementMethod /*method*/) { + ASSERT_NE(dm_session_promise_, nullptr); + dm_session_promise_->set_value(); + dm_session_promise_.reset(); + }); + + StartMeasurement(params); + dm_manager_->HandleRasClientDisconnectedEvent(params.remote_address, + ras::RasDisconnectReason::SERVER_NOT_AVAILABLE); + + dm_session_future.wait_for(kTimeout); + sync_client_handler(); +} + +TEST_F(DistanceMeasurementManagerTest, error_read_remote_cs_caps_command) { + auto dm_session_future = GetDmSessionFuture(); + StartMeasurementParameters params; + StartMeasurementTillRasConnectedEvent(params); + + EXPECT_CALL(mock_dm_callbacks_, + OnDistanceMeasurementStopped(params.remote_address, + DistanceMeasurementErrorCode::REASON_INTERNAL_ERROR, + DistanceMeasurementMethod::METHOD_CS)) + .WillOnce([this](const Address& /*address*/, DistanceMeasurementErrorCode /*error_code*/, + DistanceMeasurementMethod /*method*/) { + ASSERT_NE(dm_session_promise_, nullptr); + dm_session_promise_->set_value(); + dm_session_promise_.reset(); + }); + + test_hci_layer_->GetCommand(OpCode::LE_CS_READ_REMOTE_SUPPORTED_CAPABILITIES); + test_hci_layer_->IncomingEvent(LeCsReadRemoteSupportedCapabilitiesStatusBuilder::Create( + /*status=*/ErrorCode::COMMAND_DISALLOWED, + /*num_hci_command_packets=*/0xff)); +} + +TEST_F(DistanceMeasurementManagerTest, fail_read_remote_cs_caps_complete) { + auto dm_session_future = GetDmSessionFuture(); + StartMeasurementParameters params; + StartMeasurementTillRasConnectedEvent(params); + + EXPECT_CALL(mock_dm_callbacks_, + OnDistanceMeasurementStopped(params.remote_address, + DistanceMeasurementErrorCode::REASON_INTERNAL_ERROR, + DistanceMeasurementMethod::METHOD_CS)) + .WillOnce([this](const Address& /*address*/, DistanceMeasurementErrorCode /*error_code*/, + DistanceMeasurementMethod /*method*/) { + ASSERT_NE(dm_session_promise_, nullptr); + dm_session_promise_->set_value(); + dm_session_promise_.reset(); + }); + + test_hci_layer_->GetCommand(OpCode::LE_CS_READ_REMOTE_SUPPORTED_CAPABILITIES); + CsReadCapabilitiesCompleteEvent read_cs_complete_event; + read_cs_complete_event.error_code = ErrorCode::COMMAND_DISALLOWED; + test_hci_layer_->IncomingLeMetaEvent(GetRemoteSupportedCapabilitiesCompleteEvent( + params.connection_handle, read_cs_complete_event)); +} + +} // namespace +} // namespace hci +} // namespace bluetooth diff --git a/system/gd/hci/enum_helper.h b/system/gd/hci/enum_helper.h index 43ac2f92a1..ad97c318e5 100644 --- a/system/gd/hci/enum_helper.h +++ b/system/gd/hci/enum_helper.h @@ -1,5 +1,5 @@ /* - * Copyright 2020 The Android Open Source Project + * Copyright (C) 2020 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. diff --git a/system/gd/hci/event_checkers.h b/system/gd/hci/event_checkers.h index a484f5752e..8263f238df 100644 --- a/system/gd/hci/event_checkers.h +++ b/system/gd/hci/event_checkers.h @@ -1,5 +1,5 @@ /* - * Copyright 2020 The Android Open Source Project + * Copyright (C) 2020 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. diff --git a/system/gd/hci/fuzz/acl_manager_fuzz_test.cc b/system/gd/hci/fuzz/acl_manager_fuzz_test.cc index d9c039415c..6c98e82168 100644 --- a/system/gd/hci/fuzz/acl_manager_fuzz_test.cc +++ b/system/gd/hci/fuzz/acl_manager_fuzz_test.cc @@ -1,5 +1,5 @@ /* - * Copyright 2019 The Android Open Source Project + * Copyright (C) 2019 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. diff --git a/system/gd/hci/fuzz/fuzz_hci_layer.cc b/system/gd/hci/fuzz/fuzz_hci_layer.cc index 64115ec253..d665655bd3 100644 --- a/system/gd/hci/fuzz/fuzz_hci_layer.cc +++ b/system/gd/hci/fuzz/fuzz_hci_layer.cc @@ -1,5 +1,5 @@ /* - * Copyright 2020 The Android Open Source Project + * Copyright (C) 2020 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. diff --git a/system/gd/hci/fuzz/fuzz_hci_layer.h b/system/gd/hci/fuzz/fuzz_hci_layer.h index d4a69c114e..59a09acfe2 100644 --- a/system/gd/hci/fuzz/fuzz_hci_layer.h +++ b/system/gd/hci/fuzz/fuzz_hci_layer.h @@ -1,5 +1,5 @@ /* - * Copyright 2020 The Android Open Source Project + * Copyright (C) 2020 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. diff --git a/system/gd/hci/fuzz/hci_layer_fuzz_client.cc b/system/gd/hci/fuzz/hci_layer_fuzz_client.cc index 6ca1b15f99..a76770dd70 100644 --- a/system/gd/hci/fuzz/hci_layer_fuzz_client.cc +++ b/system/gd/hci/fuzz/hci_layer_fuzz_client.cc @@ -1,5 +1,5 @@ /* - * Copyright 2019 The Android Open Source Project + * Copyright (C) 2019 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. diff --git a/system/gd/hci/fuzz/hci_layer_fuzz_client.h b/system/gd/hci/fuzz/hci_layer_fuzz_client.h index 3f9942c48a..3a62de2890 100644 --- a/system/gd/hci/fuzz/hci_layer_fuzz_client.h +++ b/system/gd/hci/fuzz/hci_layer_fuzz_client.h @@ -1,5 +1,5 @@ /* - * Copyright 2019 The Android Open Source Project + * Copyright (C) 2019 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. diff --git a/system/gd/hci/fuzz/hci_layer_fuzz_test.cc b/system/gd/hci/fuzz/hci_layer_fuzz_test.cc index 1fed31e882..3f362879f5 100644 --- a/system/gd/hci/fuzz/hci_layer_fuzz_test.cc +++ b/system/gd/hci/fuzz/hci_layer_fuzz_test.cc @@ -1,5 +1,5 @@ /* - * Copyright 2019 The Android Open Source Project + * Copyright (C) 2019 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. diff --git a/system/gd/hci/fuzz/status_vs_complete_commands.cc b/system/gd/hci/fuzz/status_vs_complete_commands.cc index c4cc72ca73..8c21cdeeec 100644 --- a/system/gd/hci/fuzz/status_vs_complete_commands.cc +++ b/system/gd/hci/fuzz/status_vs_complete_commands.cc @@ -1,5 +1,5 @@ /* - * Copyright 2019 The Android Open Source Project + * Copyright (C) 2019 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. diff --git a/system/gd/hci/fuzz/status_vs_complete_commands.h b/system/gd/hci/fuzz/status_vs_complete_commands.h index 57cb9c1174..c2831f2819 100644 --- a/system/gd/hci/fuzz/status_vs_complete_commands.h +++ b/system/gd/hci/fuzz/status_vs_complete_commands.h @@ -1,5 +1,5 @@ /* - * Copyright 2019 The Android Open Source Project + * Copyright (C) 2019 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. diff --git a/system/gd/hci/hci_interface.h b/system/gd/hci/hci_interface.h index 46c5f400bd..677dead98e 100644 --- a/system/gd/hci/hci_interface.h +++ b/system/gd/hci/hci_interface.h @@ -1,5 +1,5 @@ /* - * Copyright 2024 The Android Open Source Project + * Copyright (C) 2024 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. diff --git a/system/gd/hci/hci_layer.cc b/system/gd/hci/hci_layer.cc index fd3d4ff278..da370a7564 100644 --- a/system/gd/hci/hci_layer.cc +++ b/system/gd/hci/hci_layer.cc @@ -1,5 +1,5 @@ /* - * Copyright 2019 The Android Open Source Project + * Copyright (C) 2019 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. @@ -64,6 +64,11 @@ using std::unique_ptr; static std::recursive_mutex life_cycle_guard; static bool life_cycle_stopped = true; +#ifdef TARGET_FLOSS +// Signal to indicate the controller needs to be reset. +const int SIG_RESET_CTRL = SIGUSR1; +#endif + static std::chrono::milliseconds getHciTimeoutMs() { static auto sHciTimeoutMs = std::chrono::milliseconds(bluetooth::os::GetSystemPropertyUint32Base( "bluetooth.hci.timeout_milliseconds", HciLayer::kHciTimeoutMs.count())); @@ -296,12 +301,18 @@ struct HciLayer::impl { void on_hci_timeout(OpCode op_code) { #ifdef TARGET_FLOSS + std::unique_lock<std::recursive_mutex> lock(life_cycle_guard); + if (life_cycle_stopped) { + return; + } + log::warn("Ignoring the timeouted HCI command {}.", OpCodeText(op_code)); - // Terminate the process to trigger controller reset, also mark the controller - // is broken to prevent further error while terminating. - auto hal = module_.GetDependency<hal::HciHal>(); - hal->markControllerBroken(); - kill(getpid(), SIGTERM); + + // Terminate the process to trigger controller reset, also stop sending and + // processing any incoming packet immediately to prevent further error + // while terminating. + module_.LifeCycleStop(); + kill(getpid(), SIG_RESET_CTRL); return; #endif @@ -507,12 +518,11 @@ struct HciLayer::impl { log::assert_that(event_view.IsValid(), "assert failed: event_view.IsValid()"); #ifdef TARGET_FLOSS log::warn("Hardware Error Event with code 0x{:02x}", event_view.GetHardwareCode()); - // Sending SIGTERM to process the exception from BT controller. + // Sending signal to indicate BT controller needs to reset. // The Floss daemon will be restarted. HCI reset during restart will clear the // error state of the BT controller. - auto hal = module_.GetDependency<hal::HciHal>(); - hal->markControllerBroken(); - kill(getpid(), SIGTERM); + module_.LifeCycleStop(); + kill(getpid(), SIG_RESET_CTRL); #else log::fatal("Hardware Error Event with code 0x{:02x}", event_view.GetHardwareCode()); #endif @@ -619,6 +629,14 @@ struct HciLayer::hal_callbacks : public hal::HciHalCallbacks { module_.impl_->incoming_iso_buffer_.Enqueue(std::move(iso), module_.GetHandler()); } +#ifdef TARGET_FLOSS + void controllerNeedsReset() override { + log::info("Controller needs reset!"); + module_.LifeCycleStop(); + kill(getpid(), SIG_RESET_CTRL); + } +#endif + HciLayer& module_; }; @@ -958,6 +976,7 @@ void HciLayer::StartWithNoHalDependencies(Handler* handler) { void HciLayer::Stop() { std::unique_lock<std::recursive_mutex> lock(life_cycle_guard); + life_cycle_stopped = true; auto hal = GetDependency<hal::HciHal>(); hal->unregisterIncomingPacketCallback(); delete hal_callbacks_; @@ -966,7 +985,11 @@ void HciLayer::Stop() { impl_->sco_queue_.GetDownEnd()->UnregisterDequeue(); impl_->iso_queue_.GetDownEnd()->UnregisterDequeue(); delete impl_; +} +// Function to stop sending and handling incoming packets +void HciLayer::LifeCycleStop() { + std::unique_lock<std::recursive_mutex> lock(life_cycle_guard); life_cycle_stopped = true; } diff --git a/system/gd/hci/hci_layer.h b/system/gd/hci/hci_layer.h index d30884a625..94f706cf6b 100644 --- a/system/gd/hci/hci_layer.h +++ b/system/gd/hci/hci_layer.h @@ -1,5 +1,5 @@ /* - * Copyright 2019 The Android Open Source Project + * Copyright (C) 2019 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. @@ -149,6 +149,8 @@ protected: void Stop() override; + void LifeCycleStop(); + virtual void Disconnect(uint16_t handle, ErrorCode reason); virtual void ReadRemoteVersion(hci::ErrorCode hci_status, uint16_t handle, uint8_t version, uint16_t manufacturer_name, uint16_t sub_version); diff --git a/system/gd/hci/hci_layer_fake.cc b/system/gd/hci/hci_layer_fake.cc index b09bb5feeb..ffad279ac5 100644 --- a/system/gd/hci/hci_layer_fake.cc +++ b/system/gd/hci/hci_layer_fake.cc @@ -1,5 +1,5 @@ /* - * Copyright 2022 The Android Open Source Project + * Copyright (C) 2022 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. diff --git a/system/gd/hci/hci_layer_fake.h b/system/gd/hci/hci_layer_fake.h index 4743c0c0ff..d5d024ae77 100644 --- a/system/gd/hci/hci_layer_fake.h +++ b/system/gd/hci/hci_layer_fake.h @@ -1,5 +1,5 @@ /* - * Copyright 2022 The Android Open Source Project + * Copyright (C) 2022 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. diff --git a/system/gd/hci/hci_layer_mock.h b/system/gd/hci/hci_layer_mock.h index f207203251..e272071a4b 100644 --- a/system/gd/hci/hci_layer_mock.h +++ b/system/gd/hci/hci_layer_mock.h @@ -1,5 +1,5 @@ /* - * Copyright 2021 The Android Open Source Project + * Copyright (C) 2021 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. diff --git a/system/gd/hci/hci_layer_test.cc b/system/gd/hci/hci_layer_test.cc index 1f677d518b..8ac7f846d9 100644 --- a/system/gd/hci/hci_layer_test.cc +++ b/system/gd/hci/hci_layer_test.cc @@ -1,5 +1,5 @@ /* - * Copyright 2019 The Android Open Source Project + * Copyright (C) 2019 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. @@ -210,7 +210,8 @@ public: hal = new hal::TestHciHal(); fake_registry_.InjectTestModule(&hal::HciHal::Factory, hal); - fake_registry_.Start<DependsOnHci>(&fake_registry_.GetTestThread()); + fake_registry_.Start<DependsOnHci>(&fake_registry_.GetTestThread(), + fake_registry_.GetTestHandler()); hci = static_cast<HciLayer*>(fake_registry_.GetModuleUnderTest(&HciLayer::Factory)); upper = static_cast<DependsOnHci*>(fake_registry_.GetModuleUnderTest(&DependsOnHci::Factory)); ASSERT_TRUE(fake_registry_.IsStarted<HciLayer>()); diff --git a/system/gd/hci/hci_layer_unittest.cc b/system/gd/hci/hci_layer_unittest.cc index 5abc0c74fc..286f9ced19 100644 --- a/system/gd/hci/hci_layer_unittest.cc +++ b/system/gd/hci/hci_layer_unittest.cc @@ -1,5 +1,5 @@ /* - * Copyright 2022 The Android Open Source Project + * Copyright (C) 2022 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. @@ -87,7 +87,8 @@ protected: void SetUp() override { hal_ = new hal::TestHciHal(); fake_registry_.InjectTestModule(&hal::HciHal::Factory, hal_); - fake_registry_.Start<HciLayer>(&fake_registry_.GetTestThread()); + fake_registry_.Start<HciLayer>(&fake_registry_.GetTestThread(), + fake_registry_.GetTestHandler()); hci_ = static_cast<HciLayer*>(fake_registry_.GetModuleUnderTest(&HciLayer::Factory)); hci_handler_ = fake_registry_.GetTestModuleHandler(&HciLayer::Factory); ASSERT_TRUE(fake_registry_.IsStarted<HciLayer>()); diff --git a/system/gd/hci/hci_metrics_logging.cc b/system/gd/hci/hci_metrics_logging.cc index 21f66ee3ba..914f2b637a 100644 --- a/system/gd/hci/hci_metrics_logging.cc +++ b/system/gd/hci/hci_metrics_logging.cc @@ -1,5 +1,5 @@ /* - * Copyright 2021 The Android Open Source Project + * Copyright (C) 2021 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. diff --git a/system/gd/hci/hci_metrics_logging.h b/system/gd/hci/hci_metrics_logging.h index 4e1d9b72f4..d9c67ee771 100644 --- a/system/gd/hci/hci_metrics_logging.h +++ b/system/gd/hci/hci_metrics_logging.h @@ -1,5 +1,5 @@ /* - * Copyright 2021 The Android Open Source Project + * Copyright (C) 2021 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. diff --git a/system/gd/hci/hci_packets_fuzz_test.cc b/system/gd/hci/hci_packets_fuzz_test.cc index 00a053273c..72a0fc9ebf 100644 --- a/system/gd/hci/hci_packets_fuzz_test.cc +++ b/system/gd/hci/hci_packets_fuzz_test.cc @@ -1,5 +1,5 @@ /* - * Copyright 2019 The Android Open Source Project + * Copyright (C) 2019 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. diff --git a/system/gd/hci/hci_packets_test.cc b/system/gd/hci/hci_packets_test.cc index 017a5dab98..efb7be096b 100644 --- a/system/gd/hci/hci_packets_test.cc +++ b/system/gd/hci/hci_packets_test.cc @@ -1,5 +1,5 @@ /* - * Copyright 2019 The Android Open Source Project + * Copyright (C) 2019 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. diff --git a/system/gd/hci/inquiry_interface.h b/system/gd/hci/inquiry_interface.h index 322e2da30a..74b254a3c1 100644 --- a/system/gd/hci/inquiry_interface.h +++ b/system/gd/hci/inquiry_interface.h @@ -1,5 +1,5 @@ /* - * Copyright 2024 The Android Open Source Project + * Copyright (C) 2024 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. diff --git a/system/gd/hci/le_acl_connection_interface.h b/system/gd/hci/le_acl_connection_interface.h index b3081e30b6..67d1729aec 100644 --- a/system/gd/hci/le_acl_connection_interface.h +++ b/system/gd/hci/le_acl_connection_interface.h @@ -1,5 +1,5 @@ /* - * Copyright 2020 The Android Open Source Project + * Copyright (C) 2020 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. diff --git a/system/gd/hci/le_address_manager.cc b/system/gd/hci/le_address_manager.cc index 034f251b0e..804f88985e 100644 --- a/system/gd/hci/le_address_manager.cc +++ b/system/gd/hci/le_address_manager.cc @@ -1,5 +1,5 @@ /* - * Copyright 2020 The Android Open Source Project + * Copyright (C) 2020 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. @@ -598,10 +598,12 @@ void LeAddressManager::CheckAddressRotationHappenedInExpectedTimeInterval( const std::chrono::time_point<std::chrono::system_clock>& interval_max, const std::chrono::time_point<std::chrono::system_clock>& event_time, const std::string& client_name) { - // Give some tolerance to upper limit since alarms may ring a little bit late. + // Give some tolerance since alarms may ring a little bit early or late. + auto lower_limit_tolerance = std::chrono::seconds(2); auto upper_limit_tolerance = std::chrono::seconds(5); - if (event_time < interval_min || event_time > interval_max + upper_limit_tolerance) { + if (event_time < interval_min - lower_limit_tolerance || + event_time > interval_max + upper_limit_tolerance) { log::warn("RPA rotation happened outside expected time interval. client={}", client_name); auto tt_interval_min = std::chrono::system_clock::to_time_t(interval_min); diff --git a/system/gd/hci/le_address_manager.h b/system/gd/hci/le_address_manager.h index a657d8e55c..b985438d4e 100644 --- a/system/gd/hci/le_address_manager.h +++ b/system/gd/hci/le_address_manager.h @@ -1,5 +1,5 @@ /* - * Copyright 2020 The Android Open Source Project + * Copyright (C) 2020 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. diff --git a/system/gd/hci/le_address_manager_test.cc b/system/gd/hci/le_address_manager_test.cc index 33efcb51a2..1d5961be50 100644 --- a/system/gd/hci/le_address_manager_test.cc +++ b/system/gd/hci/le_address_manager_test.cc @@ -1,5 +1,5 @@ /* - * Copyright 2020 The Android Open Source Project + * Copyright (C) 2020 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. diff --git a/system/gd/hci/le_advertising_interface.h b/system/gd/hci/le_advertising_interface.h index 5fcddc7123..179a70ff4d 100644 --- a/system/gd/hci/le_advertising_interface.h +++ b/system/gd/hci/le_advertising_interface.h @@ -1,5 +1,5 @@ /* - * Copyright 2019 The Android Open Source Project + * Copyright (C) 2019 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. diff --git a/system/gd/hci/le_advertising_manager.cc b/system/gd/hci/le_advertising_manager.cc index afa8fd300b..f9a80f44f8 100644 --- a/system/gd/hci/le_advertising_manager.cc +++ b/system/gd/hci/le_advertising_manager.cc @@ -1,5 +1,5 @@ /* - * Copyright 2019 The Android Open Source Project + * Copyright (C) 2019 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. diff --git a/system/gd/hci/le_advertising_manager.h b/system/gd/hci/le_advertising_manager.h index fe614861e2..b50dd2623c 100644 --- a/system/gd/hci/le_advertising_manager.h +++ b/system/gd/hci/le_advertising_manager.h @@ -1,5 +1,5 @@ /* - * Copyright 2019 The Android Open Source Project + * Copyright (C) 2019 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. diff --git a/system/gd/hci/le_advertising_manager_mock.h b/system/gd/hci/le_advertising_manager_mock.h index baf2e263f1..e54e2ae584 100644 --- a/system/gd/hci/le_advertising_manager_mock.h +++ b/system/gd/hci/le_advertising_manager_mock.h @@ -1,5 +1,5 @@ /* - * Copyright 2019 The Android Open Source Project + * Copyright (C) 2019 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. diff --git a/system/gd/hci/le_advertising_manager_test.cc b/system/gd/hci/le_advertising_manager_test.cc index 0c33ab9e33..efe9462137 100644 --- a/system/gd/hci/le_advertising_manager_test.cc +++ b/system/gd/hci/le_advertising_manager_test.cc @@ -1,5 +1,5 @@ /* - * Copyright 2019 The Android Open Source Project + * Copyright (C) 2019 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. @@ -181,7 +181,8 @@ protected: test_controller_->num_advertisers_ = num_instances_; test_controller_->vendor_capabilities_.max_advt_instances_ = num_instances_; test_controller_->SetBleExtendedAdvertisingSupport(support_ble_extended_advertising_); - le_advertising_manager_ = fake_registry_.Start<LeAdvertisingManager>(&thread_); + le_advertising_manager_ = + fake_registry_.Start<LeAdvertisingManager>(&thread_, fake_registry_.GetTestHandler()); le_advertising_manager_->RegisterAdvertisingCallback(&mock_advertising_callback_); } diff --git a/system/gd/hci/le_iso_interface.h b/system/gd/hci/le_iso_interface.h index 33aa1c4461..ec05320438 100644 --- a/system/gd/hci/le_iso_interface.h +++ b/system/gd/hci/le_iso_interface.h @@ -1,5 +1,5 @@ /* - * Copyright 2020 The Android Open Source Project + * Copyright (C) 2020 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. diff --git a/system/gd/hci/le_periodic_sync_manager.h b/system/gd/hci/le_periodic_sync_manager.h index 09c557549a..d600371480 100644 --- a/system/gd/hci/le_periodic_sync_manager.h +++ b/system/gd/hci/le_periodic_sync_manager.h @@ -1,5 +1,5 @@ /* - * Copyright 2022 The Android Open Source Project + * Copyright (C) 2022 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. diff --git a/system/gd/hci/le_periodic_sync_manager_test.cc b/system/gd/hci/le_periodic_sync_manager_test.cc index 18a76ae18c..cba8905dfd 100644 --- a/system/gd/hci/le_periodic_sync_manager_test.cc +++ b/system/gd/hci/le_periodic_sync_manager_test.cc @@ -1,5 +1,5 @@ /* - * Copyright 2022 The Android Open Source Project + * Copyright (C) 2022 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. diff --git a/system/gd/hci/le_rand_callback.h b/system/gd/hci/le_rand_callback.h index 54db17e4f9..617a7c45a9 100644 --- a/system/gd/hci/le_rand_callback.h +++ b/system/gd/hci/le_rand_callback.h @@ -1,5 +1,5 @@ /* - * Copyright 2022 The Android Open Source Project + * Copyright (C) 2022 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. diff --git a/system/gd/hci/le_scanning_callback.h b/system/gd/hci/le_scanning_callback.h index 4bd75dbbc4..6f086a3673 100644 --- a/system/gd/hci/le_scanning_callback.h +++ b/system/gd/hci/le_scanning_callback.h @@ -1,5 +1,5 @@ /* - * Copyright 2022 The Android Open Source Project + * Copyright (C) 2022 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. diff --git a/system/gd/hci/le_scanning_interface.h b/system/gd/hci/le_scanning_interface.h index d26cf53604..6f0c456c3e 100644 --- a/system/gd/hci/le_scanning_interface.h +++ b/system/gd/hci/le_scanning_interface.h @@ -1,5 +1,5 @@ /* - * Copyright 2019 The Android Open Source Project + * Copyright (C) 2019 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. diff --git a/system/gd/hci/le_scanning_manager.cc b/system/gd/hci/le_scanning_manager.cc index e80caaf23c..439b6241c1 100644 --- a/system/gd/hci/le_scanning_manager.cc +++ b/system/gd/hci/le_scanning_manager.cc @@ -1,5 +1,5 @@ /* - * Copyright 2019 The Android Open Source Project + * Copyright (C) 2019 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. diff --git a/system/gd/hci/le_scanning_manager.h b/system/gd/hci/le_scanning_manager.h index 90043145a9..e09bf304af 100644 --- a/system/gd/hci/le_scanning_manager.h +++ b/system/gd/hci/le_scanning_manager.h @@ -1,5 +1,5 @@ /* - * Copyright 2019 The Android Open Source Project + * Copyright (C) 2019 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. diff --git a/system/gd/hci/le_scanning_manager_mock.h b/system/gd/hci/le_scanning_manager_mock.h index f62012c38c..b72ce45fd2 100644 --- a/system/gd/hci/le_scanning_manager_mock.h +++ b/system/gd/hci/le_scanning_manager_mock.h @@ -1,5 +1,5 @@ /* - * Copyright 2019 The Android Open Source Project + * Copyright (C) 2019 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. diff --git a/system/gd/hci/le_scanning_manager_test.cc b/system/gd/hci/le_scanning_manager_test.cc index 7eab705d0f..f19ac15862 100644 --- a/system/gd/hci/le_scanning_manager_test.cc +++ b/system/gd/hci/le_scanning_manager_test.cc @@ -1,5 +1,5 @@ /* - * Copyright 2019 The Android Open Source Project + * Copyright (C) 2019 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. @@ -288,7 +288,7 @@ protected: } void start_le_scanning_manager() { - fake_registry_.Start<LeScanningManager>(&thread_); + fake_registry_.Start<LeScanningManager>(&thread_, fake_registry_.GetTestHandler()); le_scanning_manager = static_cast<LeScanningManager*>( fake_registry_.GetModuleUnderTest(&LeScanningManager::Factory)); le_scanning_manager->RegisterScanningCallback(&mock_callbacks_); diff --git a/system/gd/hci/le_scanning_reassembler.cc b/system/gd/hci/le_scanning_reassembler.cc index 8f8ad06b00..80e7be28d2 100644 --- a/system/gd/hci/le_scanning_reassembler.cc +++ b/system/gd/hci/le_scanning_reassembler.cc @@ -1,5 +1,5 @@ /* - * Copyright 2023 The Android Open Source Project + * Copyright (C) 2023 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/system/gd/hci/le_scanning_reassembler.h b/system/gd/hci/le_scanning_reassembler.h index afc4b9b303..327d0445f7 100644 --- a/system/gd/hci/le_scanning_reassembler.h +++ b/system/gd/hci/le_scanning_reassembler.h @@ -1,5 +1,5 @@ /* - * Copyright 2019 The Android Open Source Project + * Copyright (C) 2019 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. diff --git a/system/gd/hci/le_scanning_reassembler_test.cc b/system/gd/hci/le_scanning_reassembler_test.cc index d2461391f9..beaa0a375b 100644 --- a/system/gd/hci/le_scanning_reassembler_test.cc +++ b/system/gd/hci/le_scanning_reassembler_test.cc @@ -1,5 +1,5 @@ /* - * Copyright 2023 The Android Open Source Project + * Copyright (C) 2023 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/system/gd/hci/le_security_interface.h b/system/gd/hci/le_security_interface.h index 93a2122d8f..7bdfb590e9 100644 --- a/system/gd/hci/le_security_interface.h +++ b/system/gd/hci/le_security_interface.h @@ -1,5 +1,5 @@ /* - * Copyright 2019 The Android Open Source Project + * Copyright (C) 2019 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. diff --git a/system/gd/hci/link_key.cc b/system/gd/hci/link_key.cc index 78ea1a48ea..6795b904af 100644 --- a/system/gd/hci/link_key.cc +++ b/system/gd/hci/link_key.cc @@ -1,5 +1,5 @@ /* - * Copyright 2020 The Android Open Source Project + * Copyright (C) 2020 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. diff --git a/system/gd/hci/link_key.h b/system/gd/hci/link_key.h index fc55c0cacc..9f1930c1f9 100644 --- a/system/gd/hci/link_key.h +++ b/system/gd/hci/link_key.h @@ -1,5 +1,5 @@ /* - * Copyright 2020 The Android Open Source Project + * Copyright (C) 2020 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. diff --git a/system/gd/hci/msft.cc b/system/gd/hci/msft.cc index 1c5a700030..c542bb950f 100644 --- a/system/gd/hci/msft.cc +++ b/system/gd/hci/msft.cc @@ -1,5 +1,5 @@ /* - * Copyright 2022 The Android Open Source Project + * Copyright (C) 2022 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. diff --git a/system/gd/hci/msft.h b/system/gd/hci/msft.h index 70b41ee8ce..6e9357d834 100644 --- a/system/gd/hci/msft.h +++ b/system/gd/hci/msft.h @@ -1,5 +1,5 @@ /* - * Copyright 2022 The Android Open Source Project + * Copyright (C) 2022 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. diff --git a/system/gd/hci/octets.h b/system/gd/hci/octets.h index 0eba1561c0..159dc9df09 100644 --- a/system/gd/hci/octets.h +++ b/system/gd/hci/octets.h @@ -1,5 +1,5 @@ /* - * Copyright 2023 The Android Open Source Project + * Copyright (C) 2023 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/system/gd/hci/remote_name_request.cc b/system/gd/hci/remote_name_request.cc index 2f703feca9..e2f5433f27 100644 --- a/system/gd/hci/remote_name_request.cc +++ b/system/gd/hci/remote_name_request.cc @@ -1,5 +1,5 @@ /* - * Copyright 2022 The Android Open Source Project + * Copyright (C) 2022 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. diff --git a/system/gd/hci/remote_name_request.h b/system/gd/hci/remote_name_request.h index c8553c7c2f..ce6f2a8337 100644 --- a/system/gd/hci/remote_name_request.h +++ b/system/gd/hci/remote_name_request.h @@ -1,5 +1,5 @@ /* - * Copyright 2022 The Android Open Source Project + * Copyright (C) 2022 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. diff --git a/system/gd/hci/remote_name_request_test.cc b/system/gd/hci/remote_name_request_test.cc index a90ff2eb47..948d82bc89 100644 --- a/system/gd/hci/remote_name_request_test.cc +++ b/system/gd/hci/remote_name_request_test.cc @@ -1,5 +1,5 @@ /* - * Copyright 2022 The Android Open Source Project + * Copyright (C) 2022 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. @@ -67,7 +67,7 @@ protected: test_hci_layer_ = new HciLayerFake; fake_registry_.InjectTestModule(&HciLayer::Factory, test_hci_layer_); - fake_registry_.Start<RemoteNameRequestModule>(&thread_); + fake_registry_.Start<RemoteNameRequestModule>(&thread_, fake_registry_.GetTestHandler()); ASSERT_TRUE(fake_registry_.IsStarted<RemoteNameRequestModule>()); client_handler_ = fake_registry_.GetTestModuleHandler(&RemoteNameRequestModule::Factory); diff --git a/system/gd/hci/security_interface.h b/system/gd/hci/security_interface.h index ad7a628b73..606e2edf01 100644 --- a/system/gd/hci/security_interface.h +++ b/system/gd/hci/security_interface.h @@ -1,5 +1,5 @@ /* - * Copyright 2019 The Android Open Source Project + * Copyright (C) 2019 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. diff --git a/system/gd/hci/uuid_unittest.cc b/system/gd/hci/uuid_unittest.cc index 3656a13ffd..c148c6b39d 100644 --- a/system/gd/hci/uuid_unittest.cc +++ b/system/gd/hci/uuid_unittest.cc @@ -1,5 +1,5 @@ /* - * Copyright 2020 The Android Open Source Project + * Copyright (C) 2020 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. diff --git a/system/gd/lpp/lpp_offload_interface.h b/system/gd/lpp/lpp_offload_interface.h index 388466f2e5..1387423fdb 100644 --- a/system/gd/lpp/lpp_offload_interface.h +++ b/system/gd/lpp/lpp_offload_interface.h @@ -1,5 +1,5 @@ /* - * Copyright 2024 The Android Open Source Project + * Copyright (C) 2024 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. diff --git a/system/gd/lpp/lpp_offload_interface_mock.h b/system/gd/lpp/lpp_offload_interface_mock.h index 03cd5f4f52..6ac1490830 100644 --- a/system/gd/lpp/lpp_offload_interface_mock.h +++ b/system/gd/lpp/lpp_offload_interface_mock.h @@ -1,5 +1,5 @@ /* - * Copyright 2024 The Android Open Source Project + * Copyright (C) 2024 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. diff --git a/system/gd/lpp/lpp_offload_manager.cc b/system/gd/lpp/lpp_offload_manager.cc index c5c1fb247e..4518cc96fe 100644 --- a/system/gd/lpp/lpp_offload_manager.cc +++ b/system/gd/lpp/lpp_offload_manager.cc @@ -1,5 +1,5 @@ /* - * Copyright 2024 The Android Open Source Project + * Copyright (C) 2024 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. diff --git a/system/gd/lpp/lpp_offload_manager.h b/system/gd/lpp/lpp_offload_manager.h index 90097f77bd..c8b90a69df 100644 --- a/system/gd/lpp/lpp_offload_manager.h +++ b/system/gd/lpp/lpp_offload_manager.h @@ -1,5 +1,5 @@ /* - * Copyright 2024 The Android Open Source Project + * Copyright (C) 2024 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. diff --git a/system/gd/metrics/bluetooth_event.cc b/system/gd/metrics/bluetooth_event.cc index 26ce918099..6fa3678bec 100644 --- a/system/gd/metrics/bluetooth_event.cc +++ b/system/gd/metrics/bluetooth_event.cc @@ -1,5 +1,5 @@ /* - * Copyright 2024 The Android Open Source Project + * Copyright (C) 2024 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. @@ -20,6 +20,7 @@ #include "bta/include/bta_hfp_api.h" #include "main/shim/helpers.h" #include "os/metrics.h" +#include "stack/include/btm_api_types.h" namespace bluetooth { namespace metrics { @@ -338,6 +339,27 @@ State MapHfpVersionToState(uint16_t version) { } } +State MapScoCodecToState(uint16_t codec) { + switch (codec) { + case BTM_SCO_CODEC_CVSD: + return State::CODEC_CVSD; + case BTM_SCO_CODEC_MSBC: + return State::CODEC_MSBC; + case BTM_SCO_CODEC_LC3: + return State::CODEC_LC3; + case BTA_AG_SCO_APTX_SWB_SETTINGS_Q0_MASK: + return State::CODEC_APTX_SWB_SETTINGS_Q0_MASK; + case BTA_AG_SCO_APTX_SWB_SETTINGS_Q1_MASK: + return State::CODEC_APTX_SWB_SETTINGS_Q1_MASK; + case BTA_AG_SCO_APTX_SWB_SETTINGS_Q2_MASK: + return State::CODEC_APTX_SWB_SETTINGS_Q2_MASK; + case BTA_AG_SCO_APTX_SWB_SETTINGS_Q3_MASK: + return State::CODEC_APTX_SWB_SETTINGS_Q3_MASK; + default: + return State::CODEC_UNKNOWN; + } +} + void LogIncomingAclStartEvent(const hci::Address& address) { bluetooth::os::LogMetricBluetoothEvent(address, EventType::ACL_CONNECTION_RESPONDER, State::START); diff --git a/system/gd/metrics/bluetooth_event.h b/system/gd/metrics/bluetooth_event.h index 12a122c442..65875bcaa7 100644 --- a/system/gd/metrics/bluetooth_event.h +++ b/system/gd/metrics/bluetooth_event.h @@ -1,5 +1,5 @@ /* - * Copyright 2024 The Android Open Source Project + * Copyright (C) 2024 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. @@ -52,5 +52,7 @@ android::bluetooth::State MapErrorCodeToState(hci::ErrorCode reason); android::bluetooth::State MapHfpVersionToState(uint16_t version); +android::bluetooth::State MapScoCodecToState(uint16_t codec); + } // namespace metrics } // namespace bluetooth diff --git a/system/gd/metrics/chromeos/metrics.cc b/system/gd/metrics/chromeos/metrics.cc index 87966a379c..ee84dd7095 100644 --- a/system/gd/metrics/chromeos/metrics.cc +++ b/system/gd/metrics/chromeos/metrics.cc @@ -1,5 +1,5 @@ /* - * Copyright 2022 The Android Open Source Project + * Copyright (C) 2022 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. diff --git a/system/gd/metrics/chromeos/metrics_allowlist.cc b/system/gd/metrics/chromeos/metrics_allowlist.cc index 33f2bf6dde..67c2e2647b 100644 --- a/system/gd/metrics/chromeos/metrics_allowlist.cc +++ b/system/gd/metrics/chromeos/metrics_allowlist.cc @@ -1,5 +1,5 @@ /* - * Copyright 2022 The Android Open Source Project + * Copyright (C) 2022 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. diff --git a/system/gd/metrics/chromeos/metrics_allowlist.h b/system/gd/metrics/chromeos/metrics_allowlist.h index 6bd1530558..799c81b87f 100644 --- a/system/gd/metrics/chromeos/metrics_allowlist.h +++ b/system/gd/metrics/chromeos/metrics_allowlist.h @@ -1,5 +1,5 @@ /* - * Copyright 2022 The Android Open Source Project + * Copyright (C) 2022 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. diff --git a/system/gd/metrics/chromeos/metrics_event.cc b/system/gd/metrics/chromeos/metrics_event.cc index 80f517da56..d7e0d76bb3 100644 --- a/system/gd/metrics/chromeos/metrics_event.cc +++ b/system/gd/metrics/chromeos/metrics_event.cc @@ -1,5 +1,5 @@ /* - * Copyright 2022 The Android Open Source Project + * Copyright (C) 2022 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. diff --git a/system/gd/metrics/chromeos/metrics_event.h b/system/gd/metrics/chromeos/metrics_event.h index b4ddb403ba..1b685cf358 100644 --- a/system/gd/metrics/chromeos/metrics_event.h +++ b/system/gd/metrics/chromeos/metrics_event.h @@ -1,5 +1,5 @@ /* - * Copyright 2022 The Android Open Source Project + * Copyright (C) 2022 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. diff --git a/system/gd/metrics/counter_metrics.cc b/system/gd/metrics/counter_metrics.cc index 99ba652bf9..5bafd90599 100644 --- a/system/gd/metrics/counter_metrics.cc +++ b/system/gd/metrics/counter_metrics.cc @@ -1,5 +1,5 @@ /* - * Copyright 2021 The Android Open Source Project + * Copyright (C) 2021 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. diff --git a/system/gd/metrics/counter_metrics.h b/system/gd/metrics/counter_metrics.h index e5a63f6394..88c7711f92 100644 --- a/system/gd/metrics/counter_metrics.h +++ b/system/gd/metrics/counter_metrics.h @@ -1,5 +1,5 @@ /* - * Copyright 2021 The Android Open Source Project + * Copyright (C) 2021 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. diff --git a/system/gd/metrics/counter_metrics_unittest.cc b/system/gd/metrics/counter_metrics_unittest.cc index cbaf7f0072..eb5545ca19 100644 --- a/system/gd/metrics/counter_metrics_unittest.cc +++ b/system/gd/metrics/counter_metrics_unittest.cc @@ -1,5 +1,5 @@ /* - * Copyright 2021 The Android Open Source Project + * Copyright (C) 2021 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. diff --git a/system/gd/metrics/linux/metrics.cc b/system/gd/metrics/linux/metrics.cc index 9be10aeec9..f15ebb4695 100644 --- a/system/gd/metrics/linux/metrics.cc +++ b/system/gd/metrics/linux/metrics.cc @@ -1,5 +1,5 @@ /* - * Copyright 2022 The Android Open Source Project + * Copyright (C) 2022 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. diff --git a/system/gd/metrics/metrics.h b/system/gd/metrics/metrics.h index e26ded4e17..36fe66ed06 100644 --- a/system/gd/metrics/metrics.h +++ b/system/gd/metrics/metrics.h @@ -1,5 +1,5 @@ /* - * Copyright 2022 The Android Open Source Project + * Copyright (C) 2022 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. diff --git a/system/gd/metrics/utils.cc b/system/gd/metrics/utils.cc index b059bb7133..b39b27f5b7 100644 --- a/system/gd/metrics/utils.cc +++ b/system/gd/metrics/utils.cc @@ -1,5 +1,5 @@ /* - * Copyright 2022 The Android Open Source Project + * Copyright (C) 2022 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. diff --git a/system/gd/metrics/utils.h b/system/gd/metrics/utils.h index 316ffdc74e..05d8d6044b 100644 --- a/system/gd/metrics/utils.h +++ b/system/gd/metrics/utils.h @@ -1,5 +1,5 @@ /* - * Copyright 2022 The Android Open Source Project + * Copyright (C) 2022 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. diff --git a/system/gd/module.cc b/system/gd/module.cc index ba7695db28..8904f0c559 100644 --- a/system/gd/module.cc +++ b/system/gd/module.cc @@ -1,5 +1,5 @@ /* - * Copyright 2019 The Android Open Source Project + * Copyright (C) 2019 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. @@ -66,18 +66,26 @@ bool ModuleRegistry::IsStarted(const ModuleFactory* module) const { return started_modules_.find(module) != started_modules_.end(); } -void ModuleRegistry::Start(ModuleList* modules, Thread* thread) { +void ModuleRegistry::Start(ModuleList* modules, Thread* thread, Handler* handler) { for (auto it = modules->list_.begin(); it != modules->list_.end(); it++) { - Start(*it, thread); + Start(*it, thread, handler); } } -void ModuleRegistry::set_registry_and_handler(Module* instance, Thread* thread) const { +void ModuleRegistry::set_registry_and_handler(Module* instance, Thread* thread, + Handler* handler) const { instance->registry_ = this; - instance->handler_ = new Handler(thread); + + if (com::android::bluetooth::flags::same_handler_for_all_modules()) { + // Use same handler for all modules initialization. + // TODO: remove the dependency on the `thread` when the flag is removed. + instance->handler_ = handler; + } else { + instance->handler_ = new Handler(thread); + } } -Module* ModuleRegistry::Start(const ModuleFactory* module, Thread* thread) { +Module* ModuleRegistry::Start(const ModuleFactory* module, Thread* thread, Handler* handler) { { std::unique_lock<std::mutex> lock(started_modules_guard_, std::defer_lock); if (com::android::bluetooth::flags::fix_started_module_race()) { @@ -91,11 +99,11 @@ Module* ModuleRegistry::Start(const ModuleFactory* module, Thread* thread) { log::info("Constructing next module"); Module* instance = module->ctor_(); - set_registry_and_handler(instance, thread); + set_registry_and_handler(instance, thread, handler); log::info("Starting dependencies of {}", instance->ToString()); instance->ListDependencies(&instance->dependencies_); - Start(&instance->dependencies_, thread); + Start(&instance->dependencies_, thread, handler); log::info("Finished starting dependencies and calling Start() of {}", instance->ToString()); diff --git a/system/gd/module.h b/system/gd/module.h index 28bebe568b..816d455482 100644 --- a/system/gd/module.h +++ b/system/gd/module.h @@ -1,5 +1,5 @@ /* - * Copyright 2019 The Android Open Source Project + * Copyright (C) 2019 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. @@ -140,14 +140,14 @@ public: // Start all the modules on this list and their dependencies // in dependency order - void Start(ModuleList* modules, ::bluetooth::os::Thread* thread); + void Start(ModuleList* modules, ::bluetooth::os::Thread* thread, os::Handler* handler); template <class T> - T* Start(::bluetooth::os::Thread* thread) { - return static_cast<T*>(Start(&T::Factory, thread)); + T* Start(::bluetooth::os::Thread* thread, os::Handler* handler) { + return static_cast<T*>(Start(&T::Factory, thread, handler)); } - Module* Start(const ModuleFactory* id, ::bluetooth::os::Thread* thread); + Module* Start(const ModuleFactory* id, ::bluetooth::os::Thread* thread, os::Handler* handler); // Stop all running modules in reverse order of start void StopAll(); @@ -155,7 +155,8 @@ public: protected: Module* Get(const ModuleFactory* module) const; - void set_registry_and_handler(Module* instance, ::bluetooth::os::Thread* thread) const; + void set_registry_and_handler(Module* instance, ::bluetooth::os::Thread* thread, + os::Handler* handler) const; os::Handler* GetModuleHandler(const ModuleFactory* module) const; @@ -172,7 +173,7 @@ public: void InjectTestModule(const ModuleFactory* module, Module* instance) { start_order_.push_back(module); started_modules_[module] = instance; - set_registry_and_handler(instance, &test_thread); + set_registry_and_handler(instance, &test_thread, test_handler_); instance->Start(); } @@ -188,6 +189,7 @@ public: } os::Thread& GetTestThread() { return test_thread; } + os::Handler* GetTestHandler() { return test_handler_; } bool SynchronizeModuleHandler(const ModuleFactory* module, std::chrono::milliseconds timeout) const { @@ -203,6 +205,7 @@ public: private: os::Thread test_thread{"test_thread", os::Thread::Priority::NORMAL}; + os::Handler* test_handler_ = new os::Handler(&test_thread); }; class FuzzTestModuleRegistry : public TestModuleRegistry { @@ -216,7 +219,7 @@ public: template <class T> T* Start() { - return ModuleRegistry::Start<T>(&GetTestThread()); + return ModuleRegistry::Start<T>(&GetTestThread(), GetTestHandler()); } void WaitForIdleAndStopAll() { diff --git a/system/gd/module_unittest.cc b/system/gd/module_unittest.cc index 24ccc8b3d2..d1bf59ac73 100644 --- a/system/gd/module_unittest.cc +++ b/system/gd/module_unittest.cc @@ -1,5 +1,5 @@ /* - * Copyright 2019 The Android Open Source Project + * Copyright (C) 2019 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. @@ -35,16 +35,20 @@ class ModuleTest : public ::testing::Test { protected: void SetUp() override { thread_ = new Thread("test_thread", Thread::Priority::NORMAL); + handler_ = new os::Handler(thread_); registry_ = new ModuleRegistry(); } void TearDown() override { + handler_->Clear(); delete registry_; delete thread_; + delete handler_; } ModuleRegistry* registry_; Thread* thread_; + os::Handler* handler_; }; os::Handler* test_module_no_dependency_handler = nullptr; @@ -161,7 +165,7 @@ const ModuleFactory TestModuleTwoDependencies::Factory = TEST_F(ModuleTest, no_dependency) { ModuleList list; list.add<TestModuleNoDependency>(); - registry_->Start(&list, thread_); + registry_->Start(&list, thread_, handler_); EXPECT_TRUE(registry_->IsStarted<TestModuleNoDependency>()); EXPECT_FALSE(registry_->IsStarted<TestModuleOneDependency>()); @@ -179,7 +183,7 @@ TEST_F(ModuleTest, no_dependency) { TEST_F(ModuleTest, one_dependency) { ModuleList list; list.add<TestModuleOneDependency>(); - registry_->Start(&list, thread_); + registry_->Start(&list, thread_, handler_); EXPECT_TRUE(registry_->IsStarted<TestModuleNoDependency>()); EXPECT_TRUE(registry_->IsStarted<TestModuleOneDependency>()); @@ -197,7 +201,7 @@ TEST_F(ModuleTest, one_dependency) { TEST_F(ModuleTest, two_dependencies) { ModuleList list; list.add<TestModuleTwoDependencies>(); - registry_->Start(&list, thread_); + registry_->Start(&list, thread_, handler_); EXPECT_TRUE(registry_->IsStarted<TestModuleNoDependency>()); EXPECT_TRUE(registry_->IsStarted<TestModuleOneDependency>()); @@ -220,7 +224,7 @@ void post_to_module_one_handler() { TEST_F(ModuleTest, shutdown_with_unhandled_callback) { ModuleList list; list.add<TestModuleOneDependency>(); - registry_->Start(&list, thread_); + registry_->Start(&list, thread_, handler_); test_module_no_dependency_handler->Post(common::BindOnce(&post_to_module_one_handler)); registry_->StopAll(); } diff --git a/system/gd/os/alarm.h b/system/gd/os/alarm.h index 2eeea77b1f..5f5f21c9c8 100644 --- a/system/gd/os/alarm.h +++ b/system/gd/os/alarm.h @@ -1,5 +1,5 @@ /* - * Copyright 2019 The Android Open Source Project + * Copyright (C) 2019 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. diff --git a/system/gd/os/alarm_benchmark.cc b/system/gd/os/alarm_benchmark.cc index cfe3c3db80..3839a1695d 100644 --- a/system/gd/os/alarm_benchmark.cc +++ b/system/gd/os/alarm_benchmark.cc @@ -1,5 +1,5 @@ /* - * Copyright 2019 The Android Open Source Project + * Copyright (C) 2019 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. diff --git a/system/gd/os/android/metrics.cc b/system/gd/os/android/metrics.cc index ddb9d826f1..78b12c8d96 100644 --- a/system/gd/os/android/metrics.cc +++ b/system/gd/os/android/metrics.cc @@ -66,6 +66,9 @@ struct formatter<android::bluetooth::rfcomm::SocketConnectionSecurity> : enum_formatter<android::bluetooth::rfcomm::SocketConnectionSecurity> {}; template <> struct formatter<android::bluetooth::BtaStatus> : enum_formatter<android::bluetooth::BtaStatus> {}; +template <> +struct formatter<android::bluetooth::SocketErrorEnum> + : enum_formatter<android::bluetooth::SocketErrorEnum> {}; } // namespace std namespace bluetooth { @@ -332,21 +335,28 @@ void LogMetricSdpAttribute(const Address& address, uint16_t protocol_uuid, uint1 void LogMetricSocketConnectionState(const Address& address, int port, int type, android::bluetooth::SocketConnectionstateEnum connection_state, int64_t tx_bytes, int64_t rx_bytes, int uid, int server_port, - android::bluetooth::SocketRoleEnum socket_role) { + android::bluetooth::SocketRoleEnum socket_role, + uint64_t connection_duration_ms, + android::bluetooth::SocketErrorEnum error_code, + bool is_hardware_offload) { int metric_id = 0; if (!address.IsEmpty()) { metric_id = MetricIdManager::GetInstance().AllocateId(address); } + int ret = stats_write(BLUETOOTH_SOCKET_CONNECTION_STATE_CHANGED, byteField, port, type, connection_state, tx_bytes, rx_bytes, uid, server_port, socket_role, - metric_id); + metric_id, static_cast<int64_t>(connection_duration_ms), error_code, + is_hardware_offload); + if (ret < 0) { log::warn( "Failed for {}, port {}, type {}, state {}, tx_bytes {}, rx_bytes {}, uid {}, " "server_port " - "{}, socket_role {}, error {}", + "{}, socket_role {}, error {}, connection_duration_ms {}, socket_error_code {}, " + "is_hardware_offload {}", address, port, type, connection_state, tx_bytes, rx_bytes, uid, server_port, - socket_role, ret); + socket_role, ret, connection_duration_ms, error_code, is_hardware_offload); } } diff --git a/system/gd/os/android/parameter_provider.cc b/system/gd/os/android/parameter_provider.cc index c8507ddf32..06132e677f 100644 --- a/system/gd/os/android/parameter_provider.cc +++ b/system/gd/os/android/parameter_provider.cc @@ -1,5 +1,5 @@ /* - * Copyright 2019 The Android Open Source Project + * Copyright (C) 2019 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. diff --git a/system/gd/os/android/system_properties.cc b/system/gd/os/android/system_properties.cc index d0f2707173..7b246128b5 100644 --- a/system/gd/os/android/system_properties.cc +++ b/system/gd/os/android/system_properties.cc @@ -1,5 +1,5 @@ /* - * Copyright 2019 The Android Open Source Project + * Copyright (C) 2019 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. diff --git a/system/gd/os/bt_keystore.h b/system/gd/os/bt_keystore.h index 68005acdea..daff5f8217 100644 --- a/system/gd/os/bt_keystore.h +++ b/system/gd/os/bt_keystore.h @@ -1,5 +1,5 @@ /* - * Copyright 2020 The Android Open Source Project + * Copyright (C) 2020 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. diff --git a/system/gd/os/chromeos/metrics.cc b/system/gd/os/chromeos/metrics.cc index 70258d335a..b7921fe308 100644 --- a/system/gd/os/chromeos/metrics.cc +++ b/system/gd/os/chromeos/metrics.cc @@ -35,7 +35,10 @@ void LogMetricClassicPairingEvent(const Address& address, uint16_t handle, uint3 void LogMetricSocketConnectionState(const Address& address, int port, int type, android::bluetooth::SocketConnectionstateEnum connection_state, int64_t tx_bytes, int64_t rx_bytes, int uid, int server_port, - android::bluetooth::SocketRoleEnum socket_role) {} + android::bluetooth::SocketRoleEnum socket_role, + uint64_t /* connection_duration_ms */, + android::bluetooth::SocketErrorEnum /* error_code */, + bool /* is_hardware_offload */) {} void LogMetricHciTimeoutEvent(uint32_t hci_cmd) {} diff --git a/system/gd/os/chromeos/parameter_provider.cc b/system/gd/os/chromeos/parameter_provider.cc index a8ee19c5a6..0cfd60b82a 100644 --- a/system/gd/os/chromeos/parameter_provider.cc +++ b/system/gd/os/chromeos/parameter_provider.cc @@ -1,5 +1,5 @@ /* - * Copyright 2019 The Android Open Source Project + * Copyright (C) 2019 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. diff --git a/system/gd/os/chromeos/system_properties.cc b/system/gd/os/chromeos/system_properties.cc index 16e474c8d2..07645d3390 100644 --- a/system/gd/os/chromeos/system_properties.cc +++ b/system/gd/os/chromeos/system_properties.cc @@ -1,5 +1,5 @@ /* - * Copyright 2019 The Android Open Source Project + * Copyright (C) 2019 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. diff --git a/system/gd/os/fake_timer/fake_timerfd.cc b/system/gd/os/fake_timer/fake_timerfd.cc index 400a92743c..cacd37bd7f 100644 --- a/system/gd/os/fake_timer/fake_timerfd.cc +++ b/system/gd/os/fake_timer/fake_timerfd.cc @@ -1,5 +1,5 @@ /* - * Copyright 2020 The Android Open Source Project + * Copyright (C) 2020 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. diff --git a/system/gd/os/fake_timer/fake_timerfd.h b/system/gd/os/fake_timer/fake_timerfd.h index 31a698aec9..2183edb57c 100644 --- a/system/gd/os/fake_timer/fake_timerfd.h +++ b/system/gd/os/fake_timer/fake_timerfd.h @@ -1,5 +1,5 @@ /* - * Copyright 2020 The Android Open Source Project + * Copyright (C) 2020 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. diff --git a/system/gd/os/files.h b/system/gd/os/files.h index 34a9f2f5b9..4efb0afdd4 100644 --- a/system/gd/os/files.h +++ b/system/gd/os/files.h @@ -1,5 +1,5 @@ /* - * Copyright 2020 The Android Open Source Project + * Copyright (C) 2020 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. diff --git a/system/gd/os/fuzz/dev_null_queue.h b/system/gd/os/fuzz/dev_null_queue.h index 46f88d3fc4..3ffd2adcca 100644 --- a/system/gd/os/fuzz/dev_null_queue.h +++ b/system/gd/os/fuzz/dev_null_queue.h @@ -1,5 +1,5 @@ /* - * Copyright 2020 The Android Open Source Project + * Copyright (C) 2020 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. diff --git a/system/gd/os/fuzz/fuzz_inject_queue.h b/system/gd/os/fuzz/fuzz_inject_queue.h index 322faa0d57..5cd60b1f2b 100644 --- a/system/gd/os/fuzz/fuzz_inject_queue.h +++ b/system/gd/os/fuzz/fuzz_inject_queue.h @@ -1,5 +1,5 @@ /* - * Copyright 2020 The Android Open Source Project + * Copyright (C) 2020 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. diff --git a/system/gd/os/handler.cc b/system/gd/os/handler.cc index 388fcd4c72..919bf0be40 100644 --- a/system/gd/os/handler.cc +++ b/system/gd/os/handler.cc @@ -1,5 +1,5 @@ /* - * Copyright 2019 The Android Open Source Project + * Copyright (C) 2019 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. diff --git a/system/gd/os/handler.h b/system/gd/os/handler.h index 4bb75b86f4..167f475d68 100644 --- a/system/gd/os/handler.h +++ b/system/gd/os/handler.h @@ -1,5 +1,5 @@ /* - * Copyright 2019 The Android Open Source Project + * Copyright (C) 2019 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. diff --git a/system/gd/os/handler_unittest.cc b/system/gd/os/handler_unittest.cc index 7306effd30..cca5b955cc 100644 --- a/system/gd/os/handler_unittest.cc +++ b/system/gd/os/handler_unittest.cc @@ -1,5 +1,5 @@ /* - * Copyright 2019 The Android Open Source Project + * Copyright (C) 2019 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. diff --git a/system/gd/os/host/metrics.cc b/system/gd/os/host/metrics.cc index 61734e6a81..a333113238 100644 --- a/system/gd/os/host/metrics.cc +++ b/system/gd/os/host/metrics.cc @@ -32,7 +32,8 @@ void LogMetricSocketConnectionState( const Address& /* address */, int /* port */, int /* type */, android::bluetooth::SocketConnectionstateEnum /* connection_state */, int64_t /* tx_bytes */, int64_t /* rx_bytes */, int /* uid */, int /* server_port */, - android::bluetooth::SocketRoleEnum /* socket_role */) {} + android::bluetooth::SocketRoleEnum /* socket_role */, uint64_t /* connection_duration_ms */, + android::bluetooth::SocketErrorEnum /* error_code */, bool /* is_hardware_offload */) {} void LogMetricHciTimeoutEvent(uint32_t /* hci_cmd */) {} diff --git a/system/gd/os/host/parameter_provider.cc b/system/gd/os/host/parameter_provider.cc index 7b150da4be..e56f82731f 100644 --- a/system/gd/os/host/parameter_provider.cc +++ b/system/gd/os/host/parameter_provider.cc @@ -1,5 +1,5 @@ /* - * Copyright 2019 The Android Open Source Project + * Copyright (C) 2019 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. diff --git a/system/gd/os/host/system_properties.cc b/system/gd/os/host/system_properties.cc index 5b28659612..2d49810adb 100644 --- a/system/gd/os/host/system_properties.cc +++ b/system/gd/os/host/system_properties.cc @@ -1,5 +1,5 @@ /* - * Copyright 2019 The Android Open Source Project + * Copyright (C) 2019 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. diff --git a/system/gd/os/linux/metrics.cc b/system/gd/os/linux/metrics.cc index 45fca1f4ee..7b727f38f2 100644 --- a/system/gd/os/linux/metrics.cc +++ b/system/gd/os/linux/metrics.cc @@ -30,7 +30,10 @@ void LogMetricClassicPairingEvent(const Address& address, uint16_t handle, uint3 void LogMetricSocketConnectionState(const Address& address, int port, int type, android::bluetooth::SocketConnectionstateEnum connection_state, int64_t tx_bytes, int64_t rx_bytes, int uid, int server_port, - android::bluetooth::SocketRoleEnum socket_role) {} + android::bluetooth::SocketRoleEnum socket_role, + uint64_t /* connection_duration_ms */, + android::bluetooth::SocketErrorEnum /* error_code */, + bool /* is_hardware_offload */) {} void LogMetricHciTimeoutEvent(uint32_t hci_cmd) {} diff --git a/system/gd/os/linux/parameter_provider.cc b/system/gd/os/linux/parameter_provider.cc index a8ee19c5a6..0cfd60b82a 100644 --- a/system/gd/os/linux/parameter_provider.cc +++ b/system/gd/os/linux/parameter_provider.cc @@ -1,5 +1,5 @@ /* - * Copyright 2019 The Android Open Source Project + * Copyright (C) 2019 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. diff --git a/system/gd/os/linux/system_properties.cc b/system/gd/os/linux/system_properties.cc index 16e474c8d2..07645d3390 100644 --- a/system/gd/os/linux/system_properties.cc +++ b/system/gd/os/linux/system_properties.cc @@ -1,5 +1,5 @@ /* - * Copyright 2019 The Android Open Source Project + * Copyright (C) 2019 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. diff --git a/system/gd/os/linux_generic/alarm.cc b/system/gd/os/linux_generic/alarm.cc index 9f85016f0b..8846ede579 100644 --- a/system/gd/os/linux_generic/alarm.cc +++ b/system/gd/os/linux_generic/alarm.cc @@ -1,5 +1,5 @@ /* - * Copyright 2019 The Android Open Source Project + * Copyright (C) 2019 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. diff --git a/system/gd/os/linux_generic/alarm_timerfd_unittest.cc b/system/gd/os/linux_generic/alarm_timerfd_unittest.cc index bcf802b86d..5d0698ce31 100644 --- a/system/gd/os/linux_generic/alarm_timerfd_unittest.cc +++ b/system/gd/os/linux_generic/alarm_timerfd_unittest.cc @@ -1,5 +1,5 @@ /* - * Copyright 2024 The Android Open Source Project + * Copyright (C) 2024 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. diff --git a/system/gd/os/linux_generic/alarm_unittest.cc b/system/gd/os/linux_generic/alarm_unittest.cc index f5c14dc410..14b97022b9 100644 --- a/system/gd/os/linux_generic/alarm_unittest.cc +++ b/system/gd/os/linux_generic/alarm_unittest.cc @@ -1,5 +1,5 @@ /* - * Copyright 2019 The Android Open Source Project + * Copyright (C) 2019 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. diff --git a/system/gd/os/linux_generic/files.cc b/system/gd/os/linux_generic/files.cc index a759e1d631..045c02c471 100644 --- a/system/gd/os/linux_generic/files.cc +++ b/system/gd/os/linux_generic/files.cc @@ -1,5 +1,5 @@ /* - * Copyright 2020 The Android Open Source Project + * Copyright (C) 2020 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. diff --git a/system/gd/os/linux_generic/files_test.cc b/system/gd/os/linux_generic/files_test.cc index 5d85d76fba..5804148c21 100644 --- a/system/gd/os/linux_generic/files_test.cc +++ b/system/gd/os/linux_generic/files_test.cc @@ -1,5 +1,5 @@ /* - * Copyright 2020 The Android Open Source Project + * Copyright (C) 2020 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. diff --git a/system/gd/os/linux_generic/linux.h b/system/gd/os/linux_generic/linux.h index b0571355f9..1ef54967ab 100644 --- a/system/gd/os/linux_generic/linux.h +++ b/system/gd/os/linux_generic/linux.h @@ -1,5 +1,5 @@ /* - * Copyright 2019 The Android Open Source Project + * Copyright (C) 2019 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. diff --git a/system/gd/os/linux_generic/mgmt.cc b/system/gd/os/linux_generic/mgmt.cc index 8f2fbd0a17..ebb04b5ed5 100644 --- a/system/gd/os/linux_generic/mgmt.cc +++ b/system/gd/os/linux_generic/mgmt.cc @@ -1,6 +1,6 @@ /****************************************************************************** * - * Copyright 2022 The Android Open Source Project + * Copyright (C) 2022 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. diff --git a/system/gd/os/linux_generic/queue_unittest.cc b/system/gd/os/linux_generic/queue_unittest.cc index 0e23454c61..f119a8f734 100644 --- a/system/gd/os/linux_generic/queue_unittest.cc +++ b/system/gd/os/linux_generic/queue_unittest.cc @@ -1,5 +1,5 @@ /* - * Copyright 2019 The Android Open Source Project + * Copyright (C) 2019 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. diff --git a/system/gd/os/linux_generic/reactive_semaphore.cc b/system/gd/os/linux_generic/reactive_semaphore.cc index 57fc9d6fe9..76ec29b38b 100644 --- a/system/gd/os/linux_generic/reactive_semaphore.cc +++ b/system/gd/os/linux_generic/reactive_semaphore.cc @@ -1,5 +1,5 @@ /* - * Copyright 2019 The Android Open Source Project + * Copyright (C) 2019 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. diff --git a/system/gd/os/linux_generic/reactive_semaphore.h b/system/gd/os/linux_generic/reactive_semaphore.h index ac10d76143..6b92200274 100644 --- a/system/gd/os/linux_generic/reactive_semaphore.h +++ b/system/gd/os/linux_generic/reactive_semaphore.h @@ -1,5 +1,5 @@ /* - * Copyright 2019 The Android Open Source Project + * Copyright (C) 2019 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. diff --git a/system/gd/os/linux_generic/reactor.cc b/system/gd/os/linux_generic/reactor.cc index 13f14dceb1..e67c1fd388 100644 --- a/system/gd/os/linux_generic/reactor.cc +++ b/system/gd/os/linux_generic/reactor.cc @@ -1,5 +1,5 @@ /* - * Copyright 2019 The Android Open Source Project + * Copyright (C) 2019 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. diff --git a/system/gd/os/linux_generic/reactor_unittest.cc b/system/gd/os/linux_generic/reactor_unittest.cc index d131f5f74d..326ff1dd33 100644 --- a/system/gd/os/linux_generic/reactor_unittest.cc +++ b/system/gd/os/linux_generic/reactor_unittest.cc @@ -1,5 +1,5 @@ /* - * Copyright 2019 The Android Open Source Project + * Copyright (C) 2019 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. diff --git a/system/gd/os/linux_generic/repeating_alarm.cc b/system/gd/os/linux_generic/repeating_alarm.cc index 20542228d4..f2536ba821 100644 --- a/system/gd/os/linux_generic/repeating_alarm.cc +++ b/system/gd/os/linux_generic/repeating_alarm.cc @@ -1,5 +1,5 @@ /* - * Copyright 2019 The Android Open Source Project + * Copyright (C) 2019 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. diff --git a/system/gd/os/linux_generic/repeating_alarm_unittest.cc b/system/gd/os/linux_generic/repeating_alarm_unittest.cc index f101f505c9..1868615c84 100644 --- a/system/gd/os/linux_generic/repeating_alarm_unittest.cc +++ b/system/gd/os/linux_generic/repeating_alarm_unittest.cc @@ -1,5 +1,5 @@ /* - * Copyright 2019 The Android Open Source Project + * Copyright (C) 2019 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. diff --git a/system/gd/os/linux_generic/thread.cc b/system/gd/os/linux_generic/thread.cc index 33dfb2a229..5799ec096c 100644 --- a/system/gd/os/linux_generic/thread.cc +++ b/system/gd/os/linux_generic/thread.cc @@ -1,5 +1,5 @@ /* - * Copyright 2019 The Android Open Source Project + * Copyright (C) 2019 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. diff --git a/system/gd/os/linux_generic/thread_unittest.cc b/system/gd/os/linux_generic/thread_unittest.cc index 9057934845..08160972d4 100644 --- a/system/gd/os/linux_generic/thread_unittest.cc +++ b/system/gd/os/linux_generic/thread_unittest.cc @@ -1,5 +1,5 @@ /* - * Copyright 2019 The Android Open Source Project + * Copyright (C) 2019 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. diff --git a/system/gd/os/metrics.h b/system/gd/os/metrics.h index 9f372b25af..aab82826e6 100644 --- a/system/gd/os/metrics.h +++ b/system/gd/os/metrics.h @@ -260,11 +260,17 @@ void LogMetricSdpAttribute(const hci::Address& address, uint16_t protocol_uuid, * by |server_port| * @param socket_role role of this socket, server or connection * @param uid socket owner's uid + * @param connection_duration_ms duration of socket connection in milliseconds + * @param error_code error code of socket failures + * @param is_hardware_offload whether this is a offload socket */ void LogMetricSocketConnectionState(const hci::Address& address, int port, int type, android::bluetooth::SocketConnectionstateEnum connection_state, int64_t tx_bytes, int64_t rx_bytes, int uid, int server_port, - android::bluetooth::SocketRoleEnum socket_role); + android::bluetooth::SocketRoleEnum socket_role, + uint64_t connection_duration_ms, + android::bluetooth::SocketErrorEnum error_code, + bool is_hardware_offload); /** * Logs when a Bluetooth device's manufacturer information is learnt diff --git a/system/gd/os/mock_queue.h b/system/gd/os/mock_queue.h index 03ede2025b..187911174b 100644 --- a/system/gd/os/mock_queue.h +++ b/system/gd/os/mock_queue.h @@ -1,5 +1,5 @@ /* - * Copyright 2021 The Android Open Source Project + * Copyright (C) 2021 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. diff --git a/system/gd/os/parameter_provider.h b/system/gd/os/parameter_provider.h index df8a8ee900..e943d9ab37 100644 --- a/system/gd/os/parameter_provider.h +++ b/system/gd/os/parameter_provider.h @@ -1,5 +1,5 @@ /* - * Copyright 2020 The Android Open Source Project + * Copyright (C) 2020 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. diff --git a/system/gd/os/queue.h b/system/gd/os/queue.h index fef9073202..1287ad4f39 100644 --- a/system/gd/os/queue.h +++ b/system/gd/os/queue.h @@ -1,5 +1,5 @@ /* - * Copyright 2019 The Android Open Source Project + * Copyright (C) 2019 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. diff --git a/system/gd/os/queue_benchmark.cc b/system/gd/os/queue_benchmark.cc index b4c442e7dd..c6dfdc9ec1 100644 --- a/system/gd/os/queue_benchmark.cc +++ b/system/gd/os/queue_benchmark.cc @@ -1,5 +1,5 @@ /* - * Copyright 2019 The Android Open Source Project + * Copyright (C) 2019 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. diff --git a/system/gd/os/rand.h b/system/gd/os/rand.h index 03f29bc815..d0ab6db36b 100644 --- a/system/gd/os/rand.h +++ b/system/gd/os/rand.h @@ -1,5 +1,5 @@ /* - * Copyright 2020 The Android Open Source Project + * Copyright (C) 2020 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. diff --git a/system/gd/os/reactor.h b/system/gd/os/reactor.h index ef286fbb60..41ad1910a9 100644 --- a/system/gd/os/reactor.h +++ b/system/gd/os/reactor.h @@ -1,5 +1,5 @@ /* - * Copyright 2019 The Android Open Source Project + * Copyright (C) 2019 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. diff --git a/system/gd/os/repeating_alarm.h b/system/gd/os/repeating_alarm.h index d38e5374d0..4ffbc92cd5 100644 --- a/system/gd/os/repeating_alarm.h +++ b/system/gd/os/repeating_alarm.h @@ -1,5 +1,5 @@ /* - * Copyright 2019 The Android Open Source Project + * Copyright (C) 2019 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. diff --git a/system/gd/os/system_properties.h b/system/gd/os/system_properties.h index db31708480..e040119b3e 100644 --- a/system/gd/os/system_properties.h +++ b/system/gd/os/system_properties.h @@ -1,5 +1,5 @@ /* - * Copyright 2020 The Android Open Source Project + * Copyright (C) 2020 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. diff --git a/system/gd/os/system_properties_common.cc b/system/gd/os/system_properties_common.cc index 9dfed10da6..9a491d1a4d 100644 --- a/system/gd/os/system_properties_common.cc +++ b/system/gd/os/system_properties_common.cc @@ -1,5 +1,5 @@ /* - * Copyright 2022 The Android Open Source Project + * Copyright (C) 2022 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. diff --git a/system/gd/os/system_properties_common_test.cc b/system/gd/os/system_properties_common_test.cc index 1550e0ad19..567995336e 100644 --- a/system/gd/os/system_properties_common_test.cc +++ b/system/gd/os/system_properties_common_test.cc @@ -1,5 +1,5 @@ /* - * Copyright 2019 The Android Open Source Project + * Copyright (C) 2019 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. diff --git a/system/gd/os/thread.h b/system/gd/os/thread.h index ccab6113cc..d987195b6c 100644 --- a/system/gd/os/thread.h +++ b/system/gd/os/thread.h @@ -1,5 +1,5 @@ /* - * Copyright 2019 The Android Open Source Project + * Copyright (C) 2019 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. diff --git a/system/gd/os/thread_benchmark.cc b/system/gd/os/thread_benchmark.cc index 529eb8a662..e0dcb008e4 100644 --- a/system/gd/os/thread_benchmark.cc +++ b/system/gd/os/thread_benchmark.cc @@ -1,5 +1,5 @@ /* - * Copyright 2019 The Android Open Source Project + * Copyright (C) 2019 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. diff --git a/system/gd/os/utils.h b/system/gd/os/utils.h index f768a317d7..d0fa4e7b64 100644 --- a/system/gd/os/utils.h +++ b/system/gd/os/utils.h @@ -1,5 +1,5 @@ /* - * Copyright 2019 The Android Open Source Project + * Copyright (C) 2019 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. diff --git a/system/gd/packet/base_packet_builder.h b/system/gd/packet/base_packet_builder.h index 766e896f9d..37f0f0e236 100644 --- a/system/gd/packet/base_packet_builder.h +++ b/system/gd/packet/base_packet_builder.h @@ -1,5 +1,5 @@ /* - * Copyright 2019 The Android Open Source Project + * Copyright (C) 2019 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. diff --git a/system/gd/packet/base_struct.h b/system/gd/packet/base_struct.h index f0461f9ff5..a378a05d22 100644 --- a/system/gd/packet/base_struct.h +++ b/system/gd/packet/base_struct.h @@ -1,5 +1,5 @@ /* - * Copyright 2019 The Android Open Source Project + * Copyright (C) 2019 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. diff --git a/system/gd/packet/bit_inserter.cc b/system/gd/packet/bit_inserter.cc index d02e1deecf..4206c4a9ec 100644 --- a/system/gd/packet/bit_inserter.cc +++ b/system/gd/packet/bit_inserter.cc @@ -1,5 +1,5 @@ /* - * Copyright 2019 The Android Open Source Project + * Copyright (C) 2019 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. diff --git a/system/gd/packet/bit_inserter.h b/system/gd/packet/bit_inserter.h index f7749d62c6..e0fb8faac4 100644 --- a/system/gd/packet/bit_inserter.h +++ b/system/gd/packet/bit_inserter.h @@ -1,5 +1,5 @@ /* - * Copyright 2019 The Android Open Source Project + * Copyright (C) 2019 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. diff --git a/system/gd/packet/bit_inserter_unittest.cc b/system/gd/packet/bit_inserter_unittest.cc index 636fa470bd..19fc09191c 100644 --- a/system/gd/packet/bit_inserter_unittest.cc +++ b/system/gd/packet/bit_inserter_unittest.cc @@ -1,5 +1,5 @@ /* - * Copyright 2019 The Android Open Source Project + * Copyright (C) 2019 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. diff --git a/system/gd/packet/byte_inserter.cc b/system/gd/packet/byte_inserter.cc index a821477a85..cbe04fb172 100644 --- a/system/gd/packet/byte_inserter.cc +++ b/system/gd/packet/byte_inserter.cc @@ -1,5 +1,5 @@ /* - * Copyright 2019 The Android Open Source Project + * Copyright (C) 2019 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. diff --git a/system/gd/packet/byte_inserter.h b/system/gd/packet/byte_inserter.h index 9cb71b2e36..150bc37d27 100644 --- a/system/gd/packet/byte_inserter.h +++ b/system/gd/packet/byte_inserter.h @@ -1,5 +1,5 @@ /* - * Copyright 2019 The Android Open Source Project + * Copyright (C) 2019 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. diff --git a/system/gd/packet/byte_observer.cc b/system/gd/packet/byte_observer.cc index 1b294b4bcc..34920b7ac7 100644 --- a/system/gd/packet/byte_observer.cc +++ b/system/gd/packet/byte_observer.cc @@ -1,5 +1,5 @@ /* - * Copyright 2019 The Android Open Source Project + * Copyright (C) 2019 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. diff --git a/system/gd/packet/byte_observer.h b/system/gd/packet/byte_observer.h index f5c32f3d66..c700aa18ef 100644 --- a/system/gd/packet/byte_observer.h +++ b/system/gd/packet/byte_observer.h @@ -1,5 +1,5 @@ /* - * Copyright 2019 The Android Open Source Project + * Copyright (C) 2019 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. diff --git a/system/gd/packet/checksum_type_checker.h b/system/gd/packet/checksum_type_checker.h index 380c4d3240..9aeb215c68 100644 --- a/system/gd/packet/checksum_type_checker.h +++ b/system/gd/packet/checksum_type_checker.h @@ -1,5 +1,5 @@ /* - * Copyright 2019 The Android Open Source Project + * Copyright (C) 2019 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. diff --git a/system/gd/packet/custom_field_fixed_size_interface.h b/system/gd/packet/custom_field_fixed_size_interface.h index 1bf1335d27..ce27438948 100644 --- a/system/gd/packet/custom_field_fixed_size_interface.h +++ b/system/gd/packet/custom_field_fixed_size_interface.h @@ -1,5 +1,5 @@ /* - * Copyright 2020 The Android Open Source Project + * Copyright (C) 2020 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. diff --git a/system/gd/packet/custom_type_checker.h b/system/gd/packet/custom_type_checker.h index ea1b59f801..0f6a271789 100644 --- a/system/gd/packet/custom_type_checker.h +++ b/system/gd/packet/custom_type_checker.h @@ -1,5 +1,5 @@ /* - * Copyright 2019 The Android Open Source Project + * Copyright (C) 2019 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. diff --git a/system/gd/packet/endian_inserter.h b/system/gd/packet/endian_inserter.h index 6490ed257c..670d13af15 100644 --- a/system/gd/packet/endian_inserter.h +++ b/system/gd/packet/endian_inserter.h @@ -1,5 +1,5 @@ /* - * Copyright 2019 The Android Open Source Project + * Copyright (C) 2019 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. diff --git a/system/gd/packet/fragmenting_inserter.cc b/system/gd/packet/fragmenting_inserter.cc index a0230c5218..1f552b4eac 100644 --- a/system/gd/packet/fragmenting_inserter.cc +++ b/system/gd/packet/fragmenting_inserter.cc @@ -1,5 +1,5 @@ /* - * Copyright 2019 The Android Open Source Project + * Copyright (C) 2019 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. diff --git a/system/gd/packet/fragmenting_inserter.h b/system/gd/packet/fragmenting_inserter.h index 282b6cc228..2073ea967a 100644 --- a/system/gd/packet/fragmenting_inserter.h +++ b/system/gd/packet/fragmenting_inserter.h @@ -1,5 +1,5 @@ /* - * Copyright 2019 The Android Open Source Project + * Copyright (C) 2019 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. diff --git a/system/gd/packet/fragmenting_inserter_unittest.cc b/system/gd/packet/fragmenting_inserter_unittest.cc index 5d90a5a075..b4aa6f573d 100644 --- a/system/gd/packet/fragmenting_inserter_unittest.cc +++ b/system/gd/packet/fragmenting_inserter_unittest.cc @@ -1,5 +1,5 @@ /* - * Copyright 2019 The Android Open Source Project + * Copyright (C) 2019 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. diff --git a/system/gd/packet/iterator.cc b/system/gd/packet/iterator.cc index 3b4d48ea4c..0394641335 100644 --- a/system/gd/packet/iterator.cc +++ b/system/gd/packet/iterator.cc @@ -1,5 +1,5 @@ /* - * Copyright 2019 The Android Open Source Project + * Copyright (C) 2019 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. diff --git a/system/gd/packet/iterator.h b/system/gd/packet/iterator.h index d1ea14b687..bd724dd96c 100644 --- a/system/gd/packet/iterator.h +++ b/system/gd/packet/iterator.h @@ -1,5 +1,5 @@ /* - * Copyright 2019 The Android Open Source Project + * Copyright (C) 2019 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. diff --git a/system/gd/packet/packet_builder.h b/system/gd/packet/packet_builder.h index 19a0be1183..b772770a9d 100644 --- a/system/gd/packet/packet_builder.h +++ b/system/gd/packet/packet_builder.h @@ -1,5 +1,5 @@ /* - * Copyright 2019 The Android Open Source Project + * Copyright (C) 2019 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. diff --git a/system/gd/packet/packet_builder_unittest.cc b/system/gd/packet/packet_builder_unittest.cc index edb978d7de..8626b86d6e 100644 --- a/system/gd/packet/packet_builder_unittest.cc +++ b/system/gd/packet/packet_builder_unittest.cc @@ -1,5 +1,5 @@ /* - * Copyright 2019 The Android Open Source Project + * Copyright (C) 2019 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. diff --git a/system/gd/packet/packet_struct.h b/system/gd/packet/packet_struct.h index 92ab83e4db..cb972f6b1c 100644 --- a/system/gd/packet/packet_struct.h +++ b/system/gd/packet/packet_struct.h @@ -1,5 +1,5 @@ /* - * Copyright 2019 The Android Open Source Project + * Copyright (C) 2019 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. diff --git a/system/gd/packet/packet_view.cc b/system/gd/packet/packet_view.cc index d9d4b86683..e4f44122e5 100644 --- a/system/gd/packet/packet_view.cc +++ b/system/gd/packet/packet_view.cc @@ -1,5 +1,5 @@ /* - * Copyright 2019 The Android Open Source Project + * Copyright (C) 2019 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. diff --git a/system/gd/packet/packet_view.h b/system/gd/packet/packet_view.h index 3c495f3755..c9dafb931b 100644 --- a/system/gd/packet/packet_view.h +++ b/system/gd/packet/packet_view.h @@ -1,5 +1,5 @@ /* - * Copyright 2019 The Android Open Source Project + * Copyright (C) 2019 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. diff --git a/system/gd/packet/packet_view_unittest.cc b/system/gd/packet/packet_view_unittest.cc index 108275f94a..3842107fea 100644 --- a/system/gd/packet/packet_view_unittest.cc +++ b/system/gd/packet/packet_view_unittest.cc @@ -1,5 +1,5 @@ /* - * Copyright 2019 The Android Open Source Project + * Copyright (C) 2019 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. diff --git a/system/gd/packet/parser/checksum_def.cc b/system/gd/packet/parser/checksum_def.cc index 0ad6ec6f90..6d34e5a581 100644 --- a/system/gd/packet/parser/checksum_def.cc +++ b/system/gd/packet/parser/checksum_def.cc @@ -1,5 +1,5 @@ /* - * Copyright 2019 The Android Open Source Project + * Copyright (C) 2019 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. diff --git a/system/gd/packet/parser/checksum_def.h b/system/gd/packet/parser/checksum_def.h index ee8ea1b909..32a57d9eb7 100644 --- a/system/gd/packet/parser/checksum_def.h +++ b/system/gd/packet/parser/checksum_def.h @@ -1,5 +1,5 @@ /* - * Copyright 2019 The Android Open Source Project + * Copyright (C) 2019 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. diff --git a/system/gd/packet/parser/custom_field_def.cc b/system/gd/packet/parser/custom_field_def.cc index 1ffde0522e..22b3ceaf49 100644 --- a/system/gd/packet/parser/custom_field_def.cc +++ b/system/gd/packet/parser/custom_field_def.cc @@ -1,5 +1,5 @@ /* - * Copyright 2019 The Android Open Source Project + * Copyright (C) 2019 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. diff --git a/system/gd/packet/parser/custom_field_def.h b/system/gd/packet/parser/custom_field_def.h index f605fe559b..10eee4af81 100644 --- a/system/gd/packet/parser/custom_field_def.h +++ b/system/gd/packet/parser/custom_field_def.h @@ -1,5 +1,5 @@ /* - * Copyright 2019 The Android Open Source Project + * Copyright (C) 2019 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. diff --git a/system/gd/packet/parser/declarations.h b/system/gd/packet/parser/declarations.h index ff89d8aaf1..e18b47666d 100644 --- a/system/gd/packet/parser/declarations.h +++ b/system/gd/packet/parser/declarations.h @@ -1,5 +1,5 @@ /* - * Copyright 2019 The Android Open Source Project + * Copyright (C) 2019 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. diff --git a/system/gd/packet/parser/enum_def.cc b/system/gd/packet/parser/enum_def.cc index 8b36572b3a..999ce9cedc 100644 --- a/system/gd/packet/parser/enum_def.cc +++ b/system/gd/packet/parser/enum_def.cc @@ -1,5 +1,5 @@ /* - * Copyright 2019 The Android Open Source Project + * Copyright (C) 2019 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. diff --git a/system/gd/packet/parser/enum_def.h b/system/gd/packet/parser/enum_def.h index 1150da86c7..03c0017669 100644 --- a/system/gd/packet/parser/enum_def.h +++ b/system/gd/packet/parser/enum_def.h @@ -1,5 +1,5 @@ /* - * Copyright 2019 The Android Open Source Project + * Copyright (C) 2019 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. diff --git a/system/gd/packet/parser/enum_gen.cc b/system/gd/packet/parser/enum_gen.cc index b7db3d6b29..f70e8ad449 100644 --- a/system/gd/packet/parser/enum_gen.cc +++ b/system/gd/packet/parser/enum_gen.cc @@ -1,5 +1,5 @@ /* - * Copyright 2019 The Android Open Source Project + * Copyright (C) 2019 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. diff --git a/system/gd/packet/parser/enum_gen.h b/system/gd/packet/parser/enum_gen.h index 7dcb7b76a3..d0909f3f4d 100644 --- a/system/gd/packet/parser/enum_gen.h +++ b/system/gd/packet/parser/enum_gen.h @@ -1,5 +1,5 @@ /* - * Copyright 2019 The Android Open Source Project + * Copyright (C) 2019 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. diff --git a/system/gd/packet/parser/field_list.h b/system/gd/packet/parser/field_list.h index 2eaeffa1cb..49cdb23755 100644 --- a/system/gd/packet/parser/field_list.h +++ b/system/gd/packet/parser/field_list.h @@ -1,5 +1,5 @@ /* - * Copyright 2019 The Android Open Source Project + * Copyright (C) 2019 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. diff --git a/system/gd/packet/parser/fields/all_fields.h b/system/gd/packet/parser/fields/all_fields.h index 8c0aeee02f..f750098a1d 100644 --- a/system/gd/packet/parser/fields/all_fields.h +++ b/system/gd/packet/parser/fields/all_fields.h @@ -1,5 +1,5 @@ /* - * Copyright 2019 The Android Open Source Project + * Copyright (C) 2019 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. diff --git a/system/gd/packet/parser/fields/array_field.cc b/system/gd/packet/parser/fields/array_field.cc index b3612a089b..3d6869234e 100644 --- a/system/gd/packet/parser/fields/array_field.cc +++ b/system/gd/packet/parser/fields/array_field.cc @@ -1,5 +1,5 @@ /* - * Copyright 2019 The Android Open Source Project + * Copyright (C) 2019 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. diff --git a/system/gd/packet/parser/fields/array_field.h b/system/gd/packet/parser/fields/array_field.h index 80c08e3b97..144feebb4d 100644 --- a/system/gd/packet/parser/fields/array_field.h +++ b/system/gd/packet/parser/fields/array_field.h @@ -1,5 +1,5 @@ /* - * Copyright 2019 The Android Open Source Project + * Copyright (C) 2019 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. diff --git a/system/gd/packet/parser/fields/body_field.cc b/system/gd/packet/parser/fields/body_field.cc index b0a093d7d4..16608d4496 100644 --- a/system/gd/packet/parser/fields/body_field.cc +++ b/system/gd/packet/parser/fields/body_field.cc @@ -1,5 +1,5 @@ /* - * Copyright 2019 The Android Open Source Project + * Copyright (C) 2019 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. diff --git a/system/gd/packet/parser/fields/body_field.h b/system/gd/packet/parser/fields/body_field.h index 7f44d001e1..0777f80903 100644 --- a/system/gd/packet/parser/fields/body_field.h +++ b/system/gd/packet/parser/fields/body_field.h @@ -1,5 +1,5 @@ /* - * Copyright 2019 The Android Open Source Project + * Copyright (C) 2019 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. diff --git a/system/gd/packet/parser/fields/checksum_field.cc b/system/gd/packet/parser/fields/checksum_field.cc index 729266ae9d..6a64143bb6 100644 --- a/system/gd/packet/parser/fields/checksum_field.cc +++ b/system/gd/packet/parser/fields/checksum_field.cc @@ -1,5 +1,5 @@ /* - * Copyright 2019 The Android Open Source Project + * Copyright (C) 2019 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. diff --git a/system/gd/packet/parser/fields/checksum_field.h b/system/gd/packet/parser/fields/checksum_field.h index c54439b343..c3753382a9 100644 --- a/system/gd/packet/parser/fields/checksum_field.h +++ b/system/gd/packet/parser/fields/checksum_field.h @@ -1,5 +1,5 @@ /* - * Copyright 2019 The Android Open Source Project + * Copyright (C) 2019 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. diff --git a/system/gd/packet/parser/fields/checksum_start_field.cc b/system/gd/packet/parser/fields/checksum_start_field.cc index 3634b45c0f..c5b90f577d 100644 --- a/system/gd/packet/parser/fields/checksum_start_field.cc +++ b/system/gd/packet/parser/fields/checksum_start_field.cc @@ -1,5 +1,5 @@ /* - * Copyright 2019 The Android Open Source Project + * Copyright (C) 2019 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. diff --git a/system/gd/packet/parser/fields/checksum_start_field.h b/system/gd/packet/parser/fields/checksum_start_field.h index d0d29ca517..d873c3e889 100644 --- a/system/gd/packet/parser/fields/checksum_start_field.h +++ b/system/gd/packet/parser/fields/checksum_start_field.h @@ -1,5 +1,5 @@ /* - * Copyright 2019 The Android Open Source Project + * Copyright (C) 2019 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. diff --git a/system/gd/packet/parser/fields/count_field.cc b/system/gd/packet/parser/fields/count_field.cc index 0c5c1ace85..7dd2a6a322 100644 --- a/system/gd/packet/parser/fields/count_field.cc +++ b/system/gd/packet/parser/fields/count_field.cc @@ -1,5 +1,5 @@ /* - * Copyright 2019 The Android Open Source Project + * Copyright (C) 2019 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. diff --git a/system/gd/packet/parser/fields/count_field.h b/system/gd/packet/parser/fields/count_field.h index d5e3927e95..c145c481fb 100644 --- a/system/gd/packet/parser/fields/count_field.h +++ b/system/gd/packet/parser/fields/count_field.h @@ -1,5 +1,5 @@ /* - * Copyright 2019 The Android Open Source Project + * Copyright (C) 2019 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. diff --git a/system/gd/packet/parser/fields/custom_field.cc b/system/gd/packet/parser/fields/custom_field.cc index c01d5a15eb..a33a86c7f5 100644 --- a/system/gd/packet/parser/fields/custom_field.cc +++ b/system/gd/packet/parser/fields/custom_field.cc @@ -1,5 +1,5 @@ /* - * Copyright 2019 The Android Open Source Project + * Copyright (C) 2019 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. diff --git a/system/gd/packet/parser/fields/custom_field.h b/system/gd/packet/parser/fields/custom_field.h index 9a10479e69..e5f547027f 100644 --- a/system/gd/packet/parser/fields/custom_field.h +++ b/system/gd/packet/parser/fields/custom_field.h @@ -1,5 +1,5 @@ /* - * Copyright 2019 The Android Open Source Project + * Copyright (C) 2019 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. diff --git a/system/gd/packet/parser/fields/custom_field_fixed_size.cc b/system/gd/packet/parser/fields/custom_field_fixed_size.cc index 84cffa7986..8419d0b58b 100644 --- a/system/gd/packet/parser/fields/custom_field_fixed_size.cc +++ b/system/gd/packet/parser/fields/custom_field_fixed_size.cc @@ -1,5 +1,5 @@ /* - * Copyright 2019 The Android Open Source Project + * Copyright (C) 2019 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. diff --git a/system/gd/packet/parser/fields/custom_field_fixed_size.h b/system/gd/packet/parser/fields/custom_field_fixed_size.h index a5f728286e..05c16fde68 100644 --- a/system/gd/packet/parser/fields/custom_field_fixed_size.h +++ b/system/gd/packet/parser/fields/custom_field_fixed_size.h @@ -1,5 +1,5 @@ /* - * Copyright 2019 The Android Open Source Project + * Copyright (C) 2019 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. diff --git a/system/gd/packet/parser/fields/enum_field.cc b/system/gd/packet/parser/fields/enum_field.cc index 675232d568..f6a46719b8 100644 --- a/system/gd/packet/parser/fields/enum_field.cc +++ b/system/gd/packet/parser/fields/enum_field.cc @@ -1,5 +1,5 @@ /* - * Copyright 2019 The Android Open Source Project + * Copyright (C) 2019 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. diff --git a/system/gd/packet/parser/fields/enum_field.h b/system/gd/packet/parser/fields/enum_field.h index ea1a48f3ee..d961824e7e 100644 --- a/system/gd/packet/parser/fields/enum_field.h +++ b/system/gd/packet/parser/fields/enum_field.h @@ -1,5 +1,5 @@ /* - * Copyright 2019 The Android Open Source Project + * Copyright (C) 2019 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. diff --git a/system/gd/packet/parser/fields/fixed_enum_field.cc b/system/gd/packet/parser/fields/fixed_enum_field.cc index 642c46fd4a..a3460df65e 100644 --- a/system/gd/packet/parser/fields/fixed_enum_field.cc +++ b/system/gd/packet/parser/fields/fixed_enum_field.cc @@ -1,5 +1,5 @@ /* - * Copyright 2019 The Android Open Source Project + * Copyright (C) 2019 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. diff --git a/system/gd/packet/parser/fields/fixed_enum_field.h b/system/gd/packet/parser/fields/fixed_enum_field.h index 4ea33db12b..31873c6bc3 100644 --- a/system/gd/packet/parser/fields/fixed_enum_field.h +++ b/system/gd/packet/parser/fields/fixed_enum_field.h @@ -1,5 +1,5 @@ /* - * Copyright 2019 The Android Open Source Project + * Copyright (C) 2019 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. diff --git a/system/gd/packet/parser/fields/fixed_field.cc b/system/gd/packet/parser/fields/fixed_field.cc index a5dcd372fa..a15c7e4cac 100644 --- a/system/gd/packet/parser/fields/fixed_field.cc +++ b/system/gd/packet/parser/fields/fixed_field.cc @@ -1,5 +1,5 @@ /* - * Copyright 2019 The Android Open Source Project + * Copyright (C) 2019 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. diff --git a/system/gd/packet/parser/fields/fixed_field.h b/system/gd/packet/parser/fields/fixed_field.h index da67daf4e6..4f6da5e6d6 100644 --- a/system/gd/packet/parser/fields/fixed_field.h +++ b/system/gd/packet/parser/fields/fixed_field.h @@ -1,5 +1,5 @@ /* - * Copyright 2019 The Android Open Source Project + * Copyright (C) 2019 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. diff --git a/system/gd/packet/parser/fields/fixed_scalar_field.cc b/system/gd/packet/parser/fields/fixed_scalar_field.cc index 4f66ddb4b7..1cf4ec7d4d 100644 --- a/system/gd/packet/parser/fields/fixed_scalar_field.cc +++ b/system/gd/packet/parser/fields/fixed_scalar_field.cc @@ -1,5 +1,5 @@ /* - * Copyright 2019 The Android Open Source Project + * Copyright (C) 2019 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. diff --git a/system/gd/packet/parser/fields/fixed_scalar_field.h b/system/gd/packet/parser/fields/fixed_scalar_field.h index fc6603ad37..ac1afdc892 100644 --- a/system/gd/packet/parser/fields/fixed_scalar_field.h +++ b/system/gd/packet/parser/fields/fixed_scalar_field.h @@ -1,5 +1,5 @@ /* - * Copyright 2019 The Android Open Source Project + * Copyright (C) 2019 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. diff --git a/system/gd/packet/parser/fields/group_field.cc b/system/gd/packet/parser/fields/group_field.cc index 1440d23293..c9c4ce5681 100644 --- a/system/gd/packet/parser/fields/group_field.cc +++ b/system/gd/packet/parser/fields/group_field.cc @@ -1,5 +1,5 @@ /* - * Copyright 2019 The Android Open Source Project + * Copyright (C) 2019 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. diff --git a/system/gd/packet/parser/fields/group_field.h b/system/gd/packet/parser/fields/group_field.h index d1f0bee5c5..749a7539c4 100644 --- a/system/gd/packet/parser/fields/group_field.h +++ b/system/gd/packet/parser/fields/group_field.h @@ -1,5 +1,5 @@ /* - * Copyright 2019 The Android Open Source Project + * Copyright (C) 2019 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. diff --git a/system/gd/packet/parser/fields/packet_field.cc b/system/gd/packet/parser/fields/packet_field.cc index 04239ade66..f83c68e4e9 100644 --- a/system/gd/packet/parser/fields/packet_field.cc +++ b/system/gd/packet/parser/fields/packet_field.cc @@ -1,5 +1,5 @@ /* - * Copyright 2019 The Android Open Source Project + * Copyright (C) 2019 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. diff --git a/system/gd/packet/parser/fields/packet_field.h b/system/gd/packet/parser/fields/packet_field.h index 4e25c9017e..22194d7fc1 100644 --- a/system/gd/packet/parser/fields/packet_field.h +++ b/system/gd/packet/parser/fields/packet_field.h @@ -1,5 +1,5 @@ /* - * Copyright 2019 The Android Open Source Project + * Copyright (C) 2019 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. diff --git a/system/gd/packet/parser/fields/padding_field.cc b/system/gd/packet/parser/fields/padding_field.cc index d38148eb92..7f92b6c83a 100644 --- a/system/gd/packet/parser/fields/padding_field.cc +++ b/system/gd/packet/parser/fields/padding_field.cc @@ -1,5 +1,5 @@ /* - * Copyright 2019 The Android Open Source Project + * Copyright (C) 2019 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. diff --git a/system/gd/packet/parser/fields/padding_field.h b/system/gd/packet/parser/fields/padding_field.h index b9c5449a04..75ef037b5c 100644 --- a/system/gd/packet/parser/fields/padding_field.h +++ b/system/gd/packet/parser/fields/padding_field.h @@ -1,5 +1,5 @@ /* - * Copyright 2019 The Android Open Source Project + * Copyright (C) 2019 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. diff --git a/system/gd/packet/parser/fields/payload_field.cc b/system/gd/packet/parser/fields/payload_field.cc index 85d17b81b7..9f5c3c25a7 100644 --- a/system/gd/packet/parser/fields/payload_field.cc +++ b/system/gd/packet/parser/fields/payload_field.cc @@ -1,5 +1,5 @@ /* - * Copyright 2019 The Android Open Source Project + * Copyright (C) 2019 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. diff --git a/system/gd/packet/parser/fields/payload_field.h b/system/gd/packet/parser/fields/payload_field.h index 6ef419d863..17aa1c07ff 100644 --- a/system/gd/packet/parser/fields/payload_field.h +++ b/system/gd/packet/parser/fields/payload_field.h @@ -1,5 +1,5 @@ /* - * Copyright 2019 The Android Open Source Project + * Copyright (C) 2019 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. diff --git a/system/gd/packet/parser/fields/reserved_field.cc b/system/gd/packet/parser/fields/reserved_field.cc index 72b7f25601..a57c9855b7 100644 --- a/system/gd/packet/parser/fields/reserved_field.cc +++ b/system/gd/packet/parser/fields/reserved_field.cc @@ -1,5 +1,5 @@ /* - * Copyright 2019 The Android Open Source Project + * Copyright (C) 2019 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. diff --git a/system/gd/packet/parser/fields/reserved_field.h b/system/gd/packet/parser/fields/reserved_field.h index 258ce234af..a658c2067a 100644 --- a/system/gd/packet/parser/fields/reserved_field.h +++ b/system/gd/packet/parser/fields/reserved_field.h @@ -1,5 +1,5 @@ /* - * Copyright 2019 The Android Open Source Project + * Copyright (C) 2019 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. diff --git a/system/gd/packet/parser/fields/scalar_field.cc b/system/gd/packet/parser/fields/scalar_field.cc index f916329cc1..b65e8bd8f7 100644 --- a/system/gd/packet/parser/fields/scalar_field.cc +++ b/system/gd/packet/parser/fields/scalar_field.cc @@ -1,5 +1,5 @@ /* - * Copyright 2019 The Android Open Source Project + * Copyright (C) 2019 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. diff --git a/system/gd/packet/parser/fields/scalar_field.h b/system/gd/packet/parser/fields/scalar_field.h index a63d46dd21..802e6f4db1 100644 --- a/system/gd/packet/parser/fields/scalar_field.h +++ b/system/gd/packet/parser/fields/scalar_field.h @@ -1,5 +1,5 @@ /* - * Copyright 2019 The Android Open Source Project + * Copyright (C) 2019 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. diff --git a/system/gd/packet/parser/fields/size_field.cc b/system/gd/packet/parser/fields/size_field.cc index 6c0fbb5360..44c3418c55 100644 --- a/system/gd/packet/parser/fields/size_field.cc +++ b/system/gd/packet/parser/fields/size_field.cc @@ -1,5 +1,5 @@ /* - * Copyright 2019 The Android Open Source Project + * Copyright (C) 2019 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. diff --git a/system/gd/packet/parser/fields/size_field.h b/system/gd/packet/parser/fields/size_field.h index 9258a45752..1bd258fee6 100644 --- a/system/gd/packet/parser/fields/size_field.h +++ b/system/gd/packet/parser/fields/size_field.h @@ -1,5 +1,5 @@ /* - * Copyright 2019 The Android Open Source Project + * Copyright (C) 2019 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. diff --git a/system/gd/packet/parser/fields/struct_field.cc b/system/gd/packet/parser/fields/struct_field.cc index 50762045e3..10e3bd26b6 100644 --- a/system/gd/packet/parser/fields/struct_field.cc +++ b/system/gd/packet/parser/fields/struct_field.cc @@ -1,5 +1,5 @@ /* - * Copyright 2019 The Android Open Source Project + * Copyright (C) 2019 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. diff --git a/system/gd/packet/parser/fields/struct_field.h b/system/gd/packet/parser/fields/struct_field.h index cb05169c28..e2dd1e7c8f 100644 --- a/system/gd/packet/parser/fields/struct_field.h +++ b/system/gd/packet/parser/fields/struct_field.h @@ -1,5 +1,5 @@ /* - * Copyright 2019 The Android Open Source Project + * Copyright (C) 2019 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. diff --git a/system/gd/packet/parser/fields/variable_length_struct_field.cc b/system/gd/packet/parser/fields/variable_length_struct_field.cc index 0ba48e8800..f114af50bf 100644 --- a/system/gd/packet/parser/fields/variable_length_struct_field.cc +++ b/system/gd/packet/parser/fields/variable_length_struct_field.cc @@ -1,5 +1,5 @@ /* - * Copyright 2019 The Android Open Source Project + * Copyright (C) 2019 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. diff --git a/system/gd/packet/parser/fields/variable_length_struct_field.h b/system/gd/packet/parser/fields/variable_length_struct_field.h index 361b7fdca8..34cb38380c 100644 --- a/system/gd/packet/parser/fields/variable_length_struct_field.h +++ b/system/gd/packet/parser/fields/variable_length_struct_field.h @@ -1,5 +1,5 @@ /* - * Copyright 2019 The Android Open Source Project + * Copyright (C) 2019 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. diff --git a/system/gd/packet/parser/fields/vector_field.cc b/system/gd/packet/parser/fields/vector_field.cc index 741bcff32f..ca620247da 100644 --- a/system/gd/packet/parser/fields/vector_field.cc +++ b/system/gd/packet/parser/fields/vector_field.cc @@ -1,5 +1,5 @@ /* - * Copyright 2019 The Android Open Source Project + * Copyright (C) 2019 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. diff --git a/system/gd/packet/parser/fields/vector_field.h b/system/gd/packet/parser/fields/vector_field.h index 8ef1155540..c371a731c4 100644 --- a/system/gd/packet/parser/fields/vector_field.h +++ b/system/gd/packet/parser/fields/vector_field.h @@ -1,5 +1,5 @@ /* - * Copyright 2019 The Android Open Source Project + * Copyright (C) 2019 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. diff --git a/system/gd/packet/parser/gen_cpp.cc b/system/gd/packet/parser/gen_cpp.cc index 7dd2deee07..5227c14001 100644 --- a/system/gd/packet/parser/gen_cpp.cc +++ b/system/gd/packet/parser/gen_cpp.cc @@ -1,5 +1,5 @@ /* - * Copyright 2019 The Android Open Source Project + * Copyright (C) 2019 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. diff --git a/system/gd/packet/parser/logging.h b/system/gd/packet/parser/logging.h index 0f1f6f1428..6ccaf7d713 100644 --- a/system/gd/packet/parser/logging.h +++ b/system/gd/packet/parser/logging.h @@ -1,5 +1,5 @@ /* - * Copyright 2019 The Android Open Source Project + * Copyright (C) 2019 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. diff --git a/system/gd/packet/parser/main.cc b/system/gd/packet/parser/main.cc index 4426f748f8..cfe585c402 100644 --- a/system/gd/packet/parser/main.cc +++ b/system/gd/packet/parser/main.cc @@ -1,5 +1,5 @@ /* - * Copyright 2019 The Android Open Source Project + * Copyright (C) 2019 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. diff --git a/system/gd/packet/parser/packet_def.cc b/system/gd/packet/parser/packet_def.cc index 7753d37547..0d067a371b 100644 --- a/system/gd/packet/parser/packet_def.cc +++ b/system/gd/packet/parser/packet_def.cc @@ -1,5 +1,5 @@ /* - * Copyright 2019 The Android Open Source Project + * Copyright (C) 2019 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. diff --git a/system/gd/packet/parser/packet_def.h b/system/gd/packet/parser/packet_def.h index 2ca40975ff..1959c4c267 100644 --- a/system/gd/packet/parser/packet_def.h +++ b/system/gd/packet/parser/packet_def.h @@ -1,5 +1,5 @@ /* - * Copyright 2019 The Android Open Source Project + * Copyright (C) 2019 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. diff --git a/system/gd/packet/parser/packet_dependency.cc b/system/gd/packet/parser/packet_dependency.cc index 01000ea1ae..ae4c690522 100644 --- a/system/gd/packet/parser/packet_dependency.cc +++ b/system/gd/packet/parser/packet_dependency.cc @@ -1,5 +1,5 @@ /* - * Copyright 2022 The Android Open Source Project + * Copyright (C) 2022 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. diff --git a/system/gd/packet/parser/packet_dependency.h b/system/gd/packet/parser/packet_dependency.h index ad2a5aa024..2e275e6242 100644 --- a/system/gd/packet/parser/packet_dependency.h +++ b/system/gd/packet/parser/packet_dependency.h @@ -1,5 +1,5 @@ /* - * Copyright 2022 The Android Open Source Project + * Copyright (C) 2022 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. diff --git a/system/gd/packet/parser/parent_def.cc b/system/gd/packet/parser/parent_def.cc index 18fd9a98ba..416ee76ea1 100644 --- a/system/gd/packet/parser/parent_def.cc +++ b/system/gd/packet/parser/parent_def.cc @@ -1,5 +1,5 @@ /* - * Copyright 2019 The Android Open Source Project + * Copyright (C) 2019 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. diff --git a/system/gd/packet/parser/parent_def.h b/system/gd/packet/parser/parent_def.h index c7816da45b..acaf202d11 100644 --- a/system/gd/packet/parser/parent_def.h +++ b/system/gd/packet/parser/parent_def.h @@ -1,5 +1,5 @@ /* - * Copyright 2019 The Android Open Source Project + * Copyright (C) 2019 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. diff --git a/system/gd/packet/parser/parse_location.h b/system/gd/packet/parser/parse_location.h index ee2b747888..a3283ab71c 100644 --- a/system/gd/packet/parser/parse_location.h +++ b/system/gd/packet/parser/parse_location.h @@ -1,5 +1,5 @@ /* - * Copyright 2019 The Android Open Source Project + * Copyright (C) 2019 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. diff --git a/system/gd/packet/parser/size.h b/system/gd/packet/parser/size.h index f863639e36..493e4ae949 100644 --- a/system/gd/packet/parser/size.h +++ b/system/gd/packet/parser/size.h @@ -1,5 +1,5 @@ /* - * Copyright 2019 The Android Open Source Project + * Copyright (C) 2019 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. diff --git a/system/gd/packet/parser/struct_def.cc b/system/gd/packet/parser/struct_def.cc index b611bc8957..3f13e0537b 100644 --- a/system/gd/packet/parser/struct_def.cc +++ b/system/gd/packet/parser/struct_def.cc @@ -1,5 +1,5 @@ /* - * Copyright 2019 The Android Open Source Project + * Copyright (C) 2019 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. diff --git a/system/gd/packet/parser/struct_def.h b/system/gd/packet/parser/struct_def.h index 82bba3446e..a1a9e275b9 100644 --- a/system/gd/packet/parser/struct_def.h +++ b/system/gd/packet/parser/struct_def.h @@ -1,5 +1,5 @@ /* - * Copyright 2019 The Android Open Source Project + * Copyright (C) 2019 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. diff --git a/system/gd/packet/parser/struct_parser_generator.cc b/system/gd/packet/parser/struct_parser_generator.cc index cd66b31da6..13d894e3c7 100644 --- a/system/gd/packet/parser/struct_parser_generator.cc +++ b/system/gd/packet/parser/struct_parser_generator.cc @@ -1,5 +1,5 @@ /* - * Copyright 2019 The Android Open Source Project + * Copyright (C) 2019 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. diff --git a/system/gd/packet/parser/struct_parser_generator.h b/system/gd/packet/parser/struct_parser_generator.h index 1f5f9b1fcd..8120b187c6 100644 --- a/system/gd/packet/parser/struct_parser_generator.h +++ b/system/gd/packet/parser/struct_parser_generator.h @@ -1,5 +1,5 @@ /* - * Copyright 2019 The Android Open Source Project + * Copyright (C) 2019 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. diff --git a/system/gd/packet/parser/test/generated_packet_test.cc b/system/gd/packet/parser/test/generated_packet_test.cc index e706e15bee..61d7ea1299 100644 --- a/system/gd/packet/parser/test/generated_packet_test.cc +++ b/system/gd/packet/parser/test/generated_packet_test.cc @@ -1,5 +1,5 @@ /* - * Copyright 2019 The Android Open Source Project + * Copyright (C) 2019 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. diff --git a/system/gd/packet/parser/test/simple_sum.h b/system/gd/packet/parser/test/simple_sum.h index aea9448803..6228a3abff 100644 --- a/system/gd/packet/parser/test/simple_sum.h +++ b/system/gd/packet/parser/test/simple_sum.h @@ -1,5 +1,5 @@ /* - * Copyright 2019 The Android Open Source Project + * Copyright (C) 2019 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. diff --git a/system/gd/packet/parser/test/six_bytes.cc b/system/gd/packet/parser/test/six_bytes.cc index 5122868318..bc5a16e42b 100644 --- a/system/gd/packet/parser/test/six_bytes.cc +++ b/system/gd/packet/parser/test/six_bytes.cc @@ -1,6 +1,6 @@ /****************************************************************************** * - * Copyright 2019 The Android Open Source Project + * Copyright (C) 2019 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. diff --git a/system/gd/packet/parser/test/six_bytes.h b/system/gd/packet/parser/test/six_bytes.h index c8b3ea8293..34bd44b1c5 100644 --- a/system/gd/packet/parser/test/six_bytes.h +++ b/system/gd/packet/parser/test/six_bytes.h @@ -1,6 +1,6 @@ /****************************************************************************** * - * Copyright 2019 The Android Open Source Project + * Copyright (C) 2019 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. diff --git a/system/gd/packet/parser/test/variable.cc b/system/gd/packet/parser/test/variable.cc index 727d33a392..ff77914d26 100644 --- a/system/gd/packet/parser/test/variable.cc +++ b/system/gd/packet/parser/test/variable.cc @@ -1,6 +1,6 @@ /****************************************************************************** * - * Copyright 2019 The Android Open Source Project + * Copyright (C) 2019 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. diff --git a/system/gd/packet/parser/test/variable.h b/system/gd/packet/parser/test/variable.h index febd3e63f7..c2d4dfabac 100644 --- a/system/gd/packet/parser/test/variable.h +++ b/system/gd/packet/parser/test/variable.h @@ -1,6 +1,6 @@ /****************************************************************************** * - * Copyright 2019 The Android Open Source Project + * Copyright (C) 2019 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. diff --git a/system/gd/packet/parser/type_def.h b/system/gd/packet/parser/type_def.h index 9aa5c29731..38c9ae4622 100644 --- a/system/gd/packet/parser/type_def.h +++ b/system/gd/packet/parser/type_def.h @@ -1,5 +1,5 @@ /* - * Copyright 2019 The Android Open Source Project + * Copyright (C) 2019 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. diff --git a/system/gd/packet/parser/util.h b/system/gd/packet/parser/util.h index c65a5dc493..cc7f09330d 100644 --- a/system/gd/packet/parser/util.h +++ b/system/gd/packet/parser/util.h @@ -1,5 +1,5 @@ /* - * Copyright 2019 The Android Open Source Project + * Copyright (C) 2019 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. diff --git a/system/gd/packet/raw_builder.cc b/system/gd/packet/raw_builder.cc index 49ebeed351..46ffe27852 100644 --- a/system/gd/packet/raw_builder.cc +++ b/system/gd/packet/raw_builder.cc @@ -1,5 +1,5 @@ /* - * Copyright 2019 The Android Open Source Project + * Copyright (C) 2019 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. diff --git a/system/gd/packet/raw_builder.h b/system/gd/packet/raw_builder.h index 0b17c049d2..28aa291011 100644 --- a/system/gd/packet/raw_builder.h +++ b/system/gd/packet/raw_builder.h @@ -1,5 +1,5 @@ /* - * Copyright 2019 The Android Open Source Project + * Copyright (C) 2019 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. diff --git a/system/gd/packet/raw_builder_unittest.cc b/system/gd/packet/raw_builder_unittest.cc index 07beca80c4..827ad2fc3b 100644 --- a/system/gd/packet/raw_builder_unittest.cc +++ b/system/gd/packet/raw_builder_unittest.cc @@ -1,5 +1,5 @@ /* - * Copyright 2019 The Android Open Source Project + * Copyright (C) 2019 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. diff --git a/system/gd/packet/view.cc b/system/gd/packet/view.cc index 672d2f7769..22b3f5c202 100644 --- a/system/gd/packet/view.cc +++ b/system/gd/packet/view.cc @@ -1,5 +1,5 @@ /* - * Copyright 2019 The Android Open Source Project + * Copyright (C) 2019 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. diff --git a/system/gd/packet/view.h b/system/gd/packet/view.h index 9ec8c4b1b1..372e2fb837 100644 --- a/system/gd/packet/view.h +++ b/system/gd/packet/view.h @@ -1,5 +1,5 @@ /* - * Copyright 2019 The Android Open Source Project + * Copyright (C) 2019 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. 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/gd/proto/bluetooth/metrics/bluetooth.proto b/system/gd/proto/bluetooth/metrics/bluetooth.proto index 64eb0eea21..4acad9fe1e 100644 --- a/system/gd/proto/bluetooth/metrics/bluetooth.proto +++ b/system/gd/proto/bluetooth/metrics/bluetooth.proto @@ -22,286 +22,10 @@ package bluetooth.metrics.BluetoothMetricsProto; option java_package = "com.android.bluetooth"; option java_outer_classname = "BluetoothMetricsProto"; -message BluetoothLog { - // Session information that gets logged for every BT connection. - repeated BluetoothSession session = 1; - - // Session information that gets logged for every Pair event. - repeated PairEvent pair_event = 2; - - // Information for Wake locks. - repeated WakeEvent wake_event = 3; - - // Scan event information. - repeated ScanEvent scan_event = 4; - - // Number of bonded devices. - optional int32 num_bonded_devices = 5; - - // Number of BluetoothSession including discarded ones beyond capacity - optional int64 num_bluetooth_session = 6; - - // Number of PairEvent including discarded ones beyond capacity - optional int64 num_pair_event = 7; - - // Number of WakeEvent including discarded ones beyond capacity - optional int64 num_wake_event = 8; - - // Number of ScanEvent including discarded ones beyond capacity - optional int64 num_scan_event = 9; - - // Statistics about Bluetooth profile connections - repeated ProfileConnectionStats profile_connection_stats = 10; - - // Statistics about Headset profile connections - repeated HeadsetProfileConnectionStats headset_profile_connection_stats = 11; -} - -// The information about the device. -message DeviceInfo { - // Device type. - enum DeviceType { - // Type is unknown. - DEVICE_TYPE_UNKNOWN = 0; - - DEVICE_TYPE_BREDR = 1; - - DEVICE_TYPE_LE = 2; - - DEVICE_TYPE_DUMO = 3; - } - - // Device class - // https://cs.corp.google.com/#android/packages/modules/Bluetooth/system/stack/include/btm_api.h&q=major_computer. - optional int32 device_class = 1; - - // Device type. - optional DeviceType device_type = 2; -} - -// Information that gets logged for every Bluetooth connection. -message BluetoothSession { - // Type of technology used in the connection. - enum ConnectionTechnologyType { - CONNECTION_TECHNOLOGY_TYPE_UNKNOWN = 0; - - CONNECTION_TECHNOLOGY_TYPE_LE = 1; - - CONNECTION_TECHNOLOGY_TYPE_BREDR = 2; - } - - enum DisconnectReasonType { - UNKNOWN = 0; - - // A metrics dump takes a snapshot of current Bluetooth session and thus - // is not a real disconnect, but a discontinuation in metrics logging. - // This enum indicates this situation. - METRICS_DUMP = 1; - - NEXT_START_WITHOUT_END_PREVIOUS = 2; - } - - // Duration of the session. - optional int64 session_duration_sec = 2; - - // Technology type. - optional ConnectionTechnologyType connection_technology_type = 3; - - // Reason for disconnecting. - optional string disconnect_reason = 4 [deprecated = true]; - - // The information about the device which it is connected to. - optional DeviceInfo device_connected_to = 5; - - // The information about the RFComm session. - optional RFCommSession rfcomm_session = 6; - - // The information about the A2DP audio session. - optional A2DPSession a2dp_session = 7; - - // Numeric reason for disconnecting as defined in metrics.h - optional DisconnectReasonType disconnect_reason_type = 8; -} - -message RFCommSession { - // bytes transmitted. - optional int32 rx_bytes = 1; - - // bytes transmitted. - optional int32 tx_bytes = 2; -} - -enum A2dpSourceCodec { - A2DP_SOURCE_CODEC_UNKNOWN = 0; - A2DP_SOURCE_CODEC_SBC = 1; - A2DP_SOURCE_CODEC_AAC = 2; - A2DP_SOURCE_CODEC_APTX = 3; - A2DP_SOURCE_CODEC_APTX_HD = 4; - A2DP_SOURCE_CODEC_LDAC = 5; -} - -// Session information that gets logged for A2DP session. -message A2DPSession { - // Media timer in milliseconds. - optional int32 media_timer_min_millis = 1; - - // Media timer in milliseconds. - optional int32 media_timer_max_millis = 2; - - // Media timer in milliseconds. - optional int32 media_timer_avg_millis = 3; - - // Buffer overruns count. - optional int32 buffer_overruns_max_count = 4; - - // Buffer overruns total. - optional int32 buffer_overruns_total = 5; - - // Buffer underruns average. - optional float buffer_underruns_average = 6; - - // Buffer underruns count. - optional int32 buffer_underruns_count = 7; - - // Total audio time in this A2DP session - optional int64 audio_duration_millis = 8; - - // Audio codec used in this A2DP session in A2DP source role - optional A2dpSourceCodec source_codec = 9; - - // Whether A2DP offload is enabled in this A2DP session - optional bool is_a2dp_offload = 10; -} - -message PairEvent { - // The reason for disconnecting - // See: packages/modules/Bluetooth/system/stack/include/hcidefs.h, HCI_ERR_CONN_FAILED_ESTABLISHMENT - optional int32 disconnect_reason = 1; - - // Pair event time - optional int64 event_time_millis = 2; // [(datapol.semantic_type) = ST_TIMESTAMP]; - - // The information about the device which it is paired to. - optional DeviceInfo device_paired_with = 3; -} - -message WakeEvent { - // Information about the wake event type. - enum WakeEventType { - UNKNOWN = 0; - // WakeLock was acquired. - ACQUIRED = 1; - // WakeLock was released. - RELEASED = 2; - } - - // Information about the wake event type. - optional WakeEventType wake_event_type = 1; - - // Initiator of the scan. Only the first three names will be stored. - // e.g. com.company.app - optional string requestor = 2; - - // Name of the wakelock (e.g. bluedroid_timer). - optional string name = 3; - - // Time of the event. - optional int64 event_time_millis = 4; // [(datapol.semantic_type) = ST_TIMESTAMP]; -} - -message ScanEvent { - // Scan type. - enum ScanTechnologyType { - SCAN_TYPE_UNKNOWN = 0; - - SCAN_TECH_TYPE_LE = 1; - - SCAN_TECH_TYPE_BREDR = 2; - - SCAN_TECH_TYPE_BOTH = 3; - } - - // Scan event type. - enum ScanEventType { - // Scan started. - SCAN_EVENT_START = 0; - // Scan stopped. - SCAN_EVENT_STOP = 1; - } - - // Scan event type. - optional ScanEventType scan_event_type = 1; - - // Initiator of the scan. Only the first three names will be stored. - // e.g. com.company.app - optional string initiator = 2; - - // Technology used for scanning. - optional ScanTechnologyType scan_technology_type = 3; - - // Number of results returned. - optional int32 number_results = 4; - - // Time of the event. - optional int64 event_time_millis = 5; // [(datapol.semantic_type) = ST_TIMESTAMP]; -} - -// Profile IDs defined in BluetoothProfile API class -// Values must match API class values -enum ProfileId { - PROFILE_UNKNOWN = 0; - HEADSET = 1; - A2DP = 2; - HEALTH = 3; - HID_HOST = 4; - PAN = 5; - PBAP = 6; - GATT = 7; - GATT_SERVER = 8; - MAP = 9; - SAP = 10; - A2DP_SINK = 11; - AVRCP_CONTROLLER = 12; - AVRCP = 13; - HEADSET_CLIENT = 16; - PBAP_CLIENT = 17; - MAP_CLIENT = 18; - HID_DEVICE = 19; - OPP = 20; - HEARING_AID = 21; -} - -// Statistics about Bluetooth profile connections -message ProfileConnectionStats { - // Profile id defined in BluetoothProfile.java - optional ProfileId profile_id = 1; - - // Number of times that this profile is connected since last metrics dump - optional int32 num_times_connected = 2; -} - -enum HeadsetProfileType { - HEADSET_PROFILE_UNKNOWN = 0; - HSP = 1; - HFP = 2; -} - -// Statistics about headset profile connections -message HeadsetProfileConnectionStats { - // Type of headset profile connected - optional HeadsetProfileType headset_profile_type = 1; - - // Number of times this type of headset profile is connected - optional int32 num_times_connected = 2; -} - /** * Encapsulates Remote Device Information. Needs to be kept consistent with * BluetoothRemoteDeviceInformation * in frameworks/proto_logging/stats/atoms/bluetooth/bluetooth_extension_atoms.proto -* -* Logged from: -* packages/modules/Bluetooth */ message BluetoothRemoteDeviceInformation { // SHA256 hashed Bluetooth device name. diff --git a/system/gd/rust/linux/service/src/interface_manager.rs b/system/gd/rust/linux/service/src/interface_manager.rs index 116979de0d..62fdbc8638 100644 --- a/system/gd/rust/linux/service/src/interface_manager.rs +++ b/system/gd/rust/linux/service/src/interface_manager.rs @@ -1,27 +1,29 @@ -use dbus::{channel::MatchingReceiver, message::MatchRule, nonblock::SyncConnection}; +use dbus::channel::MatchingReceiver; +use dbus::message::MatchRule; +use dbus::nonblock::SyncConnection; use dbus_crossroads::Crossroads; use dbus_projection::DisconnectWatcher; use std::sync::{Arc, Mutex}; use tokio::sync::mpsc::{channel, Receiver, Sender}; -use btstack::{ - battery_manager::BatteryManager, battery_provider_manager::BatteryProviderManager, - bluetooth::Bluetooth, bluetooth_admin::BluetoothAdmin, bluetooth_gatt::BluetoothGatt, - bluetooth_logging::BluetoothLogging, bluetooth_media::BluetoothMedia, - bluetooth_qa::BluetoothQA, socket_manager::BluetoothSocketManager, suspend::Suspend, - APIMessage, BluetoothAPI, Message, -}; +use btstack::battery_manager::BatteryManager; +use btstack::battery_provider_manager::BatteryProviderManager; +use btstack::bluetooth::{Bluetooth, SigData}; +use btstack::bluetooth_admin::BluetoothAdmin; +use btstack::bluetooth_gatt::BluetoothGatt; +use btstack::bluetooth_logging::BluetoothLogging; +use btstack::bluetooth_media::BluetoothMedia; +use btstack::bluetooth_qa::BluetoothQA; +use btstack::socket_manager::BluetoothSocketManager; +use btstack::suspend::Suspend; +use btstack::{APIMessage, BluetoothAPI}; -use crate::iface_battery_manager; -use crate::iface_battery_provider_manager; -use crate::iface_bluetooth; -use crate::iface_bluetooth_admin; -use crate::iface_bluetooth_gatt; -use crate::iface_bluetooth_media; -use crate::iface_bluetooth_qa; -use crate::iface_bluetooth_telephony; -use crate::iface_logging; +use crate::{ + iface_battery_manager, iface_battery_provider_manager, iface_bluetooth, iface_bluetooth_admin, + iface_bluetooth_gatt, iface_bluetooth_media, iface_bluetooth_qa, iface_bluetooth_telephony, + iface_logging, +}; pub(crate) struct InterfaceManager {} @@ -50,11 +52,11 @@ impl InterfaceManager { #[allow(clippy::too_many_arguments)] pub async fn dispatch( mut rx: Receiver<APIMessage>, - tx: Sender<Message>, virt_index: i32, conn: Arc<SyncConnection>, conn_join_handle: tokio::task::JoinHandle<()>, disconnect_watcher: Arc<Mutex<DisconnectWatcher>>, + sig_notifier: Arc<SigData>, bluetooth: Arc<Mutex<Box<Bluetooth>>>, bluetooth_admin: Arc<Mutex<Box<BluetoothAdmin>>>, bluetooth_gatt: Arc<Mutex<Box<BluetoothGatt>>>, @@ -93,6 +95,9 @@ impl InterfaceManager { }), ); + *sig_notifier.api_enabled.lock().unwrap() = true; + sig_notifier.api_notify.notify_all(); + // Register D-Bus method handlers of IBluetooth. let adapter_iface = iface_bluetooth::export_bluetooth_dbus_intf( conn.clone(), @@ -246,11 +251,8 @@ impl InterfaceManager { // To shut down the connection, call _handle.abort() and drop the connection. conn_join_handle.abort(); drop(conn); - - let tx = tx.clone(); - tokio::spawn(async move { - let _ = tx.send(Message::AdapterShutdown).await; - }); + *sig_notifier.api_enabled.lock().unwrap() = false; + sig_notifier.api_notify.notify_all(); break; } } diff --git a/system/gd/rust/linux/service/src/main.rs b/system/gd/rust/linux/service/src/main.rs index f326bb62ee..4fc43d11f3 100644 --- a/system/gd/rust/linux/service/src/main.rs +++ b/system/gd/rust/linux/service/src/main.rs @@ -9,22 +9,21 @@ use std::time::Duration; use tokio::runtime::Builder; use tokio::sync::mpsc::Sender; -use bt_topshim::{btif::get_btinterface, topstack}; -use btstack::{ - battery_manager::BatteryManager, - battery_provider_manager::BatteryProviderManager, - battery_service::BatteryService, - bluetooth::{Bluetooth, IBluetooth, SigData}, - bluetooth_admin::BluetoothAdmin, - bluetooth_gatt::BluetoothGatt, - bluetooth_logging::BluetoothLogging, - bluetooth_media::BluetoothMedia, - bluetooth_qa::BluetoothQA, - dis::DeviceInformation, - socket_manager::BluetoothSocketManager, - suspend::Suspend, - Message, Stack, -}; +use bt_topshim::btif::get_btinterface; +use bt_topshim::topstack; +use btstack::battery_manager::BatteryManager; +use btstack::battery_provider_manager::BatteryProviderManager; +use btstack::battery_service::BatteryService; +use btstack::bluetooth::{Bluetooth, IBluetooth, SigData}; +use btstack::bluetooth_admin::BluetoothAdmin; +use btstack::bluetooth_gatt::BluetoothGatt; +use btstack::bluetooth_logging::BluetoothLogging; +use btstack::bluetooth_media::BluetoothMedia; +use btstack::bluetooth_qa::BluetoothQA; +use btstack::dis::DeviceInformation; +use btstack::socket_manager::BluetoothSocketManager; +use btstack::suspend::Suspend; +use btstack::{Message, Stack}; mod dbus_arg; mod iface_battery_manager; @@ -40,6 +39,8 @@ mod interface_manager; const DBUS_SERVICE_NAME: &str = "org.chromium.bluetooth"; const ADMIN_SETTINGS_FILE_PATH: &str = "/var/lib/bluetooth/admin_policy.json"; +// Time to wait for API unregistration in DBus +const API_DISABLE_TIMEOUT_MS: Duration = Duration::from_millis(100); // The maximum ACL disconnect timeout is 3.5s defined by BTA_DM_DISABLE_TIMER_MS // and BTA_DM_DISABLE_TIMER_RETRIAL_MS const STACK_TURN_OFF_TIMEOUT_MS: Duration = Duration::from_millis(4000); @@ -115,6 +116,8 @@ fn main() -> Result<(), Box<dyn Error>> { enabled_notify: Condvar::new(), thread_attached: Mutex::new(false), thread_notify: Condvar::new(), + api_enabled: Mutex::new(false), + api_notify: Condvar::new(), }); // This needs to be built before any |topstack::get_runtime()| call! @@ -148,8 +151,14 @@ fn main() -> Result<(), Box<dyn Error>> { signal::SaFlags::empty(), signal::SigSet::empty(), ); + let sig_action_usr1 = signal::SigAction::new( + signal::SigHandler::Handler(handle_sigusr1), + signal::SaFlags::empty(), + signal::SigSet::empty(), + ); unsafe { signal::sigaction(signal::SIGTERM, &sig_action_term).unwrap(); + signal::sigaction(signal::SIGUSR1, &sig_action_usr1).unwrap(); } // Construct btstack profiles. @@ -241,11 +250,11 @@ fn main() -> Result<(), Box<dyn Error>> { tokio::spawn(interface_manager::InterfaceManager::dispatch( api_rx, - tx.clone(), virt_index, conn, conn_join_handle, disconnect_watcher.clone(), + sig_notifier.clone(), bluetooth.clone(), bluetooth_admin.clone(), bluetooth_gatt.clone(), @@ -267,37 +276,63 @@ fn main() -> Result<(), Box<dyn Error>> { /// Data needed for signal handling. static SIG_DATA: Mutex<Option<(Sender<Message>, Arc<SigData>)>> = Mutex::new(None); -extern "C" fn handle_sigterm(_signum: i32) { - let guard = SIG_DATA.lock().unwrap(); - if let Some((tx, notifier)) = guard.as_ref() { - log::debug!("Handling SIGTERM by disabling the adapter!"); - let txl = tx.clone(); - topstack::get_runtime().spawn(async move { - // Send the shutdown message here. - let _ = txl.send(Message::InterfaceShutdown).await; - }); +/// Try to cleanup the whole stack. Returns whether to clean up. +extern "C" fn try_cleanup_stack(abort: bool) -> bool { + let lock = SIG_DATA.try_lock(); + + // If SIG_DATA is locked, it is likely the cleanup procedure is ongoing. No + // need to do anything here. + if lock.is_err() { + return false; + } + + if let Some((tx, notifier)) = lock.unwrap().as_ref() { + log::info!("Cleanup stack: disabling the adapter!"); + + // Remove the API first to prevent clients calling while shutting down. + let guard = notifier.api_enabled.lock().unwrap(); + if *guard { + let txl = tx.clone(); + topstack::get_runtime().spawn(async move { + // Remove the API first to prevent clients calling while shutting down. + let _ = txl.send(Message::InterfaceShutdown).await; + }); + log::info!( + "Cleanup stack: Waiting for API shutdown to complete for {:?}", + API_DISABLE_TIMEOUT_MS + ); + let _ = notifier.api_notify.wait_timeout(guard, API_DISABLE_TIMEOUT_MS); + } let guard = notifier.enabled.lock().unwrap(); if *guard { - log::debug!("Waiting for stack to turn off for {:?}", STACK_TURN_OFF_TIMEOUT_MS); + let txl = tx.clone(); + topstack::get_runtime().spawn(async move { + let _ = txl.send(Message::AdapterShutdown(abort)).await; + }); + log::info!( + "Cleanup stack: Waiting for stack to turn off for {:?}", + STACK_TURN_OFF_TIMEOUT_MS + ); let _ = notifier.enabled_notify.wait_timeout(guard, STACK_TURN_OFF_TIMEOUT_MS); } - log::debug!("SIGTERM cleaning up the stack."); - let txl = tx.clone(); - topstack::get_runtime().spawn(async move { - // Clean up the profiles first as some of them might require main thread to clean up. - let _ = txl.send(Message::CleanupProfiles).await; - // Currently there is no good way to know when the profile is cleaned. - // Simply add a small delay here. - tokio::time::sleep(STACK_CLEANUP_PROFILES_TIMEOUT_MS).await; - // Send the cleanup message to clean up the main thread. - let _ = txl.send(Message::Cleanup).await; - }); - let guard = notifier.thread_attached.lock().unwrap(); if *guard { - log::debug!("Waiting for stack to clean up for {:?}", STACK_CLEANUP_TIMEOUT_MS); + let txl = tx.clone(); + topstack::get_runtime().spawn(async move { + // Clean up the profiles first as some of them might require main thread to clean up. + let _ = txl.send(Message::CleanupProfiles).await; + // Currently there is no good way to know when the profile is cleaned. + // Simply add a small delay here. + tokio::time::sleep(STACK_CLEANUP_PROFILES_TIMEOUT_MS).await; + // Send the cleanup message to clean up the main thread. + let _ = txl.send(Message::Cleanup).await; + }); + log::info!( + "Cleanup stack: Waiting for libbluetooth stack to clean up for {:?}", + STACK_CLEANUP_TIMEOUT_MS + ); let _ = notifier.thread_notify.wait_timeout(guard, STACK_CLEANUP_TIMEOUT_MS); } @@ -305,7 +340,26 @@ extern "C" fn handle_sigterm(_signum: i32) { // finishing btif cleanup. std::thread::sleep(EXTRA_WAIT_BEFORE_KILL_MS); } + return true; +} - log::debug!("Sigterm completed"); +extern "C" fn handle_sigterm(_signum: i32) { + log::info!("SIGTERM received"); + if !try_cleanup_stack(false) { + log::info!("Skipped to handle SIGTERM"); + return; + } + log::info!("SIGTERM completed"); + std::process::exit(0); +} + +/// Used to indicate controller needs reset +extern "C" fn handle_sigusr1(_signum: i32) { + log::info!("SIGUSR1 received"); + if !try_cleanup_stack(true) { + log::info!("Skipped to handle SIGUSR1"); + return; + } + log::info!("SIGUSR1 completed"); std::process::exit(0); } diff --git a/system/gd/rust/linux/stack/src/bluetooth.rs b/system/gd/rust/linux/stack/src/bluetooth.rs index bac9c4a1a9..ade91229c4 100644 --- a/system/gd/rust/linux/stack/src/bluetooth.rs +++ b/system/gd/rust/linux/stack/src/bluetooth.rs @@ -503,6 +503,9 @@ pub struct SigData { pub thread_attached: Mutex<bool>, pub thread_notify: Condvar, + + pub api_enabled: Mutex<bool>, + pub api_notify: Condvar, } /// The interface for adapter callbacks registered through `IBluetooth::register_callback`. @@ -818,6 +821,21 @@ impl Bluetooth { self.connection_callbacks.remove_callback(id); } + pub fn shutdown_adapter(&mut self, abort: bool) -> bool { + self.disabling = true; + + if !abort { + if !self.set_discoverable(BtDiscMode::NonDiscoverable, 0) { + warn!("set_discoverable failed on disabling"); + } + if !self.set_connectable_internal(false) { + warn!("set_connectable_internal failed on disabling"); + } + } + + self.intf.lock().unwrap().disable() == 0 + } + fn get_remote_device_property( &self, device: &BluetoothDevice, @@ -2240,14 +2258,7 @@ impl IBluetooth for Bluetooth { } fn disable(&mut self) -> bool { - self.disabling = true; - if !self.set_discoverable(BtDiscMode::NonDiscoverable, 0) { - warn!("set_discoverable failed on disabling"); - } - if !self.set_connectable_internal(false) { - warn!("set_connectable_internal failed on disabling"); - } - self.intf.lock().unwrap().disable() == 0 + self.shutdown_adapter(false) } fn cleanup(&mut self) { diff --git a/system/gd/rust/linux/stack/src/bluetooth_gatt.rs b/system/gd/rust/linux/stack/src/bluetooth_gatt.rs index 3acc31fcc4..bdd73bd28f 100644 --- a/system/gd/rust/linux/stack/src/bluetooth_gatt.rs +++ b/system/gd/rust/linux/stack/src/bluetooth_gatt.rs @@ -2740,9 +2740,6 @@ pub(crate) trait BtifGattClientCallbacks { #[btif_callback(Disconnect)] fn disconnect_cb(&mut self, conn_id: i32, status: GattStatus, client_id: i32, addr: RawAddress); - #[btif_callback(SearchComplete)] - fn search_complete_cb(&mut self, conn_id: i32, status: GattStatus); - #[btif_callback(RegisterForNotification)] fn register_for_notification_cb( &mut self, @@ -2893,12 +2890,6 @@ impl BtifGattClientCallbacks for BluetoothGatt { } #[log_cb_args] - fn search_complete_cb(&mut self, conn_id: i32, _status: GattStatus) { - // Gatt DB is ready! - self.gatt.lock().unwrap().client.get_gatt_db(conn_id); - } - - #[log_cb_args] fn register_for_notification_cb( &mut self, _conn_id: i32, diff --git a/system/gd/rust/linux/stack/src/lib.rs b/system/gd/rust/linux/stack/src/lib.rs index d9f97bfa32..4f49a186b4 100644 --- a/system/gd/rust/linux/stack/src/lib.rs +++ b/system/gd/rust/linux/stack/src/lib.rs @@ -66,7 +66,9 @@ pub enum Message { /// Remove the DBus API. Call it before other AdapterShutdown. InterfaceShutdown, /// Disable the adapter by calling btif disable. - AdapterShutdown, + /// Param: bool to indicate abort(true) or graceful shutdown(false). + /// Use abort when we believe adapter is already in a bad state. + AdapterShutdown(bool), /// Clean up the adapter by calling btif cleanup. Cleanup, /// Clean up the media by calling profile cleanup. @@ -287,9 +289,9 @@ impl Stack { }); } - Message::AdapterShutdown => { + Message::AdapterShutdown(abort) => { bluetooth_gatt.lock().unwrap().enable(false); - bluetooth.lock().unwrap().disable(); + bluetooth.lock().unwrap().shutdown_adapter(abort); } Message::Cleanup => { diff --git a/system/gd/rust/topshim/controller/controller_shim.cc b/system/gd/rust/topshim/controller/controller_shim.cc index b47065f440..4b587d79b3 100644 --- a/system/gd/rust/topshim/controller/controller_shim.cc +++ b/system/gd/rust/topshim/controller/controller_shim.cc @@ -1,5 +1,5 @@ /* - * Copyright 2021 The Android Open Source Project + * Copyright (C) 2021 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. diff --git a/system/gd/rust/topshim/src/profiles/gatt.rs b/system/gd/rust/topshim/src/profiles/gatt.rs index 5daddbbd55..c4647ea9b6 100644 --- a/system/gd/rust/topshim/src/profiles/gatt.rs +++ b/system/gd/rust/topshim/src/profiles/gatt.rs @@ -576,7 +576,6 @@ pub enum GattClientCallbacks { RegisterClient(GattStatus, i32, Uuid), Connect(i32, GattStatus, i32, RawAddress), Disconnect(i32, GattStatus, i32, RawAddress), - SearchComplete(i32, GattStatus), RegisterForNotification(i32, i32, GattStatus, u16), Notify(i32, BtGattNotifyParams), ReadCharacteristic(i32, GattStatus, BtGattReadParams), @@ -665,12 +664,6 @@ cb_variant!( cb_variant!( GattClientCb, - gc_search_complete_cb -> GattClientCallbacks::SearchComplete, - i32, i32 -> GattStatus, {} -); - -cb_variant!( - GattClientCb, gc_register_for_notification_cb -> GattClientCallbacks::RegisterForNotification, i32, i32, i32 -> GattStatus, u16, {} ); @@ -1419,11 +1412,6 @@ impl GattClient { pub fn test_command(&self, command: i32, params: &BtGattTestParams) -> BtStatus { BtStatus::from(ccall!(self, test_command, command, params)) } - - #[log_args] - pub fn get_gatt_db(&self, conn_id: i32) -> BtStatus { - BtStatus::from(ccall!(self, get_gatt_db, conn_id)) - } } pub struct GattServer { @@ -1973,7 +1961,6 @@ impl Gatt { register_client_cb: Some(gc_register_client_cb), open_cb: Some(gc_open_cb), close_cb: Some(gc_close_cb), - search_complete_cb: Some(gc_search_complete_cb), register_for_notification_cb: Some(gc_register_for_notification_cb), notify_cb: Some(gc_notify_cb), read_characteristic_cb: Some(gc_read_characteristic_cb), diff --git a/system/gd/storage/classic_device.cc b/system/gd/storage/classic_device.cc index f2104a9c07..e49e6b214e 100644 --- a/system/gd/storage/classic_device.cc +++ b/system/gd/storage/classic_device.cc @@ -1,5 +1,5 @@ /* - * Copyright 2020 The Android Open Source Project + * Copyright (C) 2020 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. diff --git a/system/gd/storage/classic_device.h b/system/gd/storage/classic_device.h index 155b44d8d8..dec4ebceda 100644 --- a/system/gd/storage/classic_device.h +++ b/system/gd/storage/classic_device.h @@ -1,5 +1,5 @@ /* - * Copyright 2020 The Android Open Source Project + * Copyright (C) 2020 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. diff --git a/system/gd/storage/classic_device_test.cc b/system/gd/storage/classic_device_test.cc index ae26587d7a..2dbe9df5d6 100644 --- a/system/gd/storage/classic_device_test.cc +++ b/system/gd/storage/classic_device_test.cc @@ -1,5 +1,5 @@ /* - * Copyright 2020 The Android Open Source Project + * Copyright (C) 2020 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. diff --git a/system/gd/storage/config_cache.cc b/system/gd/storage/config_cache.cc index f2517be128..c506c3dcae 100644 --- a/system/gd/storage/config_cache.cc +++ b/system/gd/storage/config_cache.cc @@ -1,5 +1,5 @@ /* - * Copyright 2020 The Android Open Source Project + * Copyright (C) 2020 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. diff --git a/system/gd/storage/config_cache.h b/system/gd/storage/config_cache.h index 238660170c..25a3a1b6c3 100644 --- a/system/gd/storage/config_cache.h +++ b/system/gd/storage/config_cache.h @@ -1,5 +1,5 @@ /* - * Copyright 2020 The Android Open Source Project + * Copyright (C) 2020 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. diff --git a/system/gd/storage/config_cache_helper.cc b/system/gd/storage/config_cache_helper.cc index 485ed61508..7c2eb7d630 100644 --- a/system/gd/storage/config_cache_helper.cc +++ b/system/gd/storage/config_cache_helper.cc @@ -1,5 +1,5 @@ /* - * Copyright 2020 The Android Open Source Project + * Copyright (C) 2020 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. diff --git a/system/gd/storage/config_cache_helper.h b/system/gd/storage/config_cache_helper.h index e4f5c23a57..2f02c0e0e4 100644 --- a/system/gd/storage/config_cache_helper.h +++ b/system/gd/storage/config_cache_helper.h @@ -1,5 +1,5 @@ /* - * Copyright 2020 The Android Open Source Project + * Copyright (C) 2020 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. diff --git a/system/gd/storage/config_cache_helper_test.cc b/system/gd/storage/config_cache_helper_test.cc index e149c3777c..5ad20e6be0 100644 --- a/system/gd/storage/config_cache_helper_test.cc +++ b/system/gd/storage/config_cache_helper_test.cc @@ -1,5 +1,5 @@ /* - * Copyright 2020 The Android Open Source Project + * Copyright (C) 2020 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. diff --git a/system/gd/storage/config_cache_test.cc b/system/gd/storage/config_cache_test.cc index c129e8841b..3aa0bc493d 100644 --- a/system/gd/storage/config_cache_test.cc +++ b/system/gd/storage/config_cache_test.cc @@ -1,5 +1,5 @@ /* - * Copyright 2020 The Android Open Source Project + * Copyright (C) 2020 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. diff --git a/system/gd/storage/device.cc b/system/gd/storage/device.cc index 7210a110fe..b84f360477 100644 --- a/system/gd/storage/device.cc +++ b/system/gd/storage/device.cc @@ -1,5 +1,5 @@ /* - * Copyright 2020 The Android Open Source Project + * Copyright (C) 2020 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. diff --git a/system/gd/storage/device.h b/system/gd/storage/device.h index 03311d1504..40ca990080 100644 --- a/system/gd/storage/device.h +++ b/system/gd/storage/device.h @@ -1,5 +1,5 @@ /* - * Copyright 2020 The Android Open Source Project + * Copyright (C) 2020 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. diff --git a/system/gd/storage/device_test.cc b/system/gd/storage/device_test.cc index 01754cfd7e..ab8d399db0 100644 --- a/system/gd/storage/device_test.cc +++ b/system/gd/storage/device_test.cc @@ -1,5 +1,5 @@ /* - * Copyright 2020 The Android Open Source Project + * Copyright (C) 2020 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. diff --git a/system/gd/storage/le_device.cc b/system/gd/storage/le_device.cc index 3cbbb7839f..bf6475faa8 100644 --- a/system/gd/storage/le_device.cc +++ b/system/gd/storage/le_device.cc @@ -1,5 +1,5 @@ /* - * Copyright 2020 The Android Open Source Project + * Copyright (C) 2020 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. diff --git a/system/gd/storage/le_device.h b/system/gd/storage/le_device.h index 835519929e..aa5c4d8815 100644 --- a/system/gd/storage/le_device.h +++ b/system/gd/storage/le_device.h @@ -1,5 +1,5 @@ /* - * Copyright 2020 The Android Open Source Project + * Copyright (C) 2020 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. diff --git a/system/gd/storage/le_device_test.cc b/system/gd/storage/le_device_test.cc index b18b4e2fb7..c32c94f3d3 100644 --- a/system/gd/storage/le_device_test.cc +++ b/system/gd/storage/le_device_test.cc @@ -1,5 +1,5 @@ /* - * Copyright 2020 The Android Open Source Project + * Copyright (C) 2020 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. diff --git a/system/gd/storage/legacy_config_file.cc b/system/gd/storage/legacy_config_file.cc index 0bee52af03..29f09da9bd 100644 --- a/system/gd/storage/legacy_config_file.cc +++ b/system/gd/storage/legacy_config_file.cc @@ -1,5 +1,5 @@ /* - * Copyright 2020 The Android Open Source Project + * Copyright (C) 2020 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. diff --git a/system/gd/storage/legacy_config_file.h b/system/gd/storage/legacy_config_file.h index 2a5a8bf9b0..0bfa1651b6 100644 --- a/system/gd/storage/legacy_config_file.h +++ b/system/gd/storage/legacy_config_file.h @@ -1,5 +1,5 @@ /* - * Copyright 2020 The Android Open Source Project + * Copyright (C) 2020 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. diff --git a/system/gd/storage/legacy_config_file_test.cc b/system/gd/storage/legacy_config_file_test.cc index b52891793f..1c11ea8ba0 100644 --- a/system/gd/storage/legacy_config_file_test.cc +++ b/system/gd/storage/legacy_config_file_test.cc @@ -1,5 +1,5 @@ /* - * Copyright 2020 The Android Open Source Project + * Copyright (C) 2020 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. diff --git a/system/gd/storage/mutation.cc b/system/gd/storage/mutation.cc index e091344f36..097357a668 100644 --- a/system/gd/storage/mutation.cc +++ b/system/gd/storage/mutation.cc @@ -1,5 +1,5 @@ /* - * Copyright 2020 The Android Open Source Project + * Copyright (C) 2020 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. diff --git a/system/gd/storage/mutation.h b/system/gd/storage/mutation.h index 4f24e7725b..ec801f13ee 100644 --- a/system/gd/storage/mutation.h +++ b/system/gd/storage/mutation.h @@ -1,5 +1,5 @@ /* - * Copyright 2020 The Android Open Source Project + * Copyright (C) 2020 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. diff --git a/system/gd/storage/mutation_entry.cc b/system/gd/storage/mutation_entry.cc index 5d610e70ef..a3b99afd09 100644 --- a/system/gd/storage/mutation_entry.cc +++ b/system/gd/storage/mutation_entry.cc @@ -1,5 +1,5 @@ /* - * Copyright 2020 The Android Open Source Project + * Copyright (C) 2020 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. diff --git a/system/gd/storage/mutation_entry.h b/system/gd/storage/mutation_entry.h index cc1a3d09ed..00ce85bc6c 100644 --- a/system/gd/storage/mutation_entry.h +++ b/system/gd/storage/mutation_entry.h @@ -1,5 +1,5 @@ /* - * Copyright 2020 The Android Open Source Project + * Copyright (C) 2020 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. diff --git a/system/gd/storage/mutation_test.cc b/system/gd/storage/mutation_test.cc index 1a1a3e82ff..c99b3d754f 100644 --- a/system/gd/storage/mutation_test.cc +++ b/system/gd/storage/mutation_test.cc @@ -1,5 +1,5 @@ /* - * Copyright 2020 The Android Open Source Project + * Copyright (C) 2020 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. diff --git a/system/gd/storage/serializable.h b/system/gd/storage/serializable.h index ef26d3a4f4..0b617e0d3d 100644 --- a/system/gd/storage/serializable.h +++ b/system/gd/storage/serializable.h @@ -1,5 +1,5 @@ /* - * Copyright 2020 The Android Open Source Project + * Copyright (C) 2020 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. diff --git a/system/gd/storage/storage_module.cc b/system/gd/storage/storage_module.cc index 9a59caf4f6..5e3459e109 100644 --- a/system/gd/storage/storage_module.cc +++ b/system/gd/storage/storage_module.cc @@ -1,5 +1,5 @@ /* - * Copyright 2020 The Android Open Source Project + * Copyright (C) 2020 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. diff --git a/system/gd/storage/storage_module.h b/system/gd/storage/storage_module.h index 8899423697..de47e71e25 100644 --- a/system/gd/storage/storage_module.h +++ b/system/gd/storage/storage_module.h @@ -1,5 +1,5 @@ /* - * Copyright 2020 The Android Open Source Project + * Copyright (C) 2020 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. diff --git a/system/gd/storage/storage_module_test.cc b/system/gd/storage/storage_module_test.cc index 488eda0a53..7eaf3ae3fa 100644 --- a/system/gd/storage/storage_module_test.cc +++ b/system/gd/storage/storage_module_test.cc @@ -1,5 +1,5 @@ /* - * Copyright 2020 The Android Open Source Project + * Copyright (C) 2020 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. diff --git a/system/gd/sysprops/sysprops_module.cc b/system/gd/sysprops/sysprops_module.cc index 0cdcaa2efa..b994bcf52c 100644 --- a/system/gd/sysprops/sysprops_module.cc +++ b/system/gd/sysprops/sysprops_module.cc @@ -1,5 +1,5 @@ /* - * Copyright 2020 The Android Open Source Project + * Copyright (C) 2020 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. diff --git a/system/gd/sysprops/sysprops_module.h b/system/gd/sysprops/sysprops_module.h index d1050bd660..eaeb648941 100644 --- a/system/gd/sysprops/sysprops_module.h +++ b/system/gd/sysprops/sysprops_module.h @@ -1,5 +1,5 @@ /* - * Copyright 2020 The Android Open Source Project + * Copyright (C) 2020 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. diff --git a/system/gd/sysprops/sysprops_module_test.cc b/system/gd/sysprops/sysprops_module_test.cc index e427db3831..e4f90b9068 100644 --- a/system/gd/sysprops/sysprops_module_test.cc +++ b/system/gd/sysprops/sysprops_module_test.cc @@ -1,5 +1,5 @@ /* - * Copyright 2024 The Android Open Source Project + * Copyright (C) 2024 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. diff --git a/system/include/Android.bp b/system/include/Android.bp index c7cec2e726..5f5283b277 100644 --- a/system/include/Android.bp +++ b/system/include/Android.bp @@ -30,7 +30,6 @@ cc_library_headers { cc_library_headers { name: "libbluetooth_headers", visibility: [ - "//packages/apps/Test/connectivity/sl4n", "//packages/modules/Bluetooth:__subpackages__", ], header_libs: [ 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/include/hardware/bt_gatt_client.h b/system/include/hardware/bt_gatt_client.h index 94bb4c7c24..96f91bafd4 100644 --- a/system/include/hardware/bt_gatt_client.h +++ b/system/include/hardware/bt_gatt_client.h @@ -99,12 +99,6 @@ typedef void (*connect_callback)(int conn_id, int status, int client_if, const R /** Callback invoked in response to close */ typedef void (*disconnect_callback)(int conn_id, int status, int client_if, const RawAddress& bda); -/** - * Invoked in response to search_service when the GATT service search - * has been completed. - */ -typedef void (*search_complete_callback)(int conn_id, int status); - /** Callback invoked in response to (de)register_for_notification */ typedef void (*register_for_notification_callback)(int conn_id, int registered, int status, uint16_t handle); @@ -179,7 +173,6 @@ typedef struct { register_client_callback register_client_cb; connect_callback open_cb; disconnect_callback close_cb; - search_complete_callback search_complete_cb; register_for_notification_callback register_for_notification_cb; notify_callback notify_cb; read_characteristic_callback read_characteristic_cb; @@ -285,9 +278,6 @@ typedef struct { /** Test mode interface */ bt_status_t (*test_command)(int command, const btgatt_test_params_t& params); - /** Get gatt db content */ - bt_status_t (*get_gatt_db)(int conn_id); - /** Request a BLE subrate request procedure */ bt_status_t (*subrate_request)(const RawAddress& bd_addr, int subrate_min, int subrate_max, int max_latency, int cont_num, int timeout); diff --git a/system/include/hardware/bt_sock.h b/system/include/hardware/bt_sock.h index 0436fad9cb..340085998c 100644 --- a/system/include/hardware/bt_sock.h +++ b/system/include/hardware/bt_sock.h @@ -38,6 +38,25 @@ typedef enum { BTSOCK_L2CAP_LE = 4 } btsock_type_t; +typedef enum { + BTSOCK_ERROR_NONE = 0, + BTSOCK_ERROR_SERVER_START_FAILURE = 1, + BTSOCK_ERROR_CLIENT_INIT_FAILURE = 2, + BTSOCK_ERROR_LISTEN_FAILURE = 3, + BTSOCK_ERROR_CONNECTION_FAILURE = 4, + BTSOCK_ERROR_OPEN_FAILURE = 5, + BTSOCK_ERROR_OFFLOAD_SERVER_NOT_ACCEPTING = 6, + BTSOCK_ERROR_OFFLOAD_HAL_OPEN_FAILURE = 7, + BTSOCK_ERROR_SEND_TO_APP_FAILURE = 8, + BTSOCK_ERROR_RECEIVE_DATA_FAILURE = 9, + BTSOCK_ERROR_READ_SIGNALED_FAILURE = 10, + BTSOCK_ERROR_WRITE_SIGNALED_FAILURE = 11, + BTSOCK_ERROR_SEND_SCN_FAILURE = 12, + BTSOCK_ERROR_SCN_ALLOCATION_FAILURE = 13, + BTSOCK_ERROR_ADD_SDP_FAILURE = 14, + BTSOCK_ERROR_SDP_DISCOVERY_FAILURE = 15, +} btsock_error_code_t; + /** * Data path used for Bluetooth socket communication. * diff --git a/system/internal_include/bt_target.h b/system/internal_include/bt_target.h index edb4eb712e..742ae0155f 100644 --- a/system/internal_include/bt_target.h +++ b/system/internal_include/bt_target.h @@ -643,7 +643,7 @@ #endif #ifndef HID_HOST_MAX_DEVICES -#define HID_HOST_MAX_DEVICES 7 +#define HID_HOST_MAX_DEVICES 10 #endif #ifndef HID_HOST_MTU diff --git a/system/main/shim/metrics_api.cc b/system/main/shim/metrics_api.cc index 20c14191a9..2250090901 100644 --- a/system/main/shim/metrics_api.cc +++ b/system/main/shim/metrics_api.cc @@ -135,10 +135,14 @@ void LogMetricSdpAttribute(const RawAddress& raw_address, uint16_t protocol_uuid void LogMetricSocketConnectionState(const RawAddress& raw_address, int port, int type, android::bluetooth::SocketConnectionstateEnum connection_state, int64_t tx_bytes, int64_t rx_bytes, int uid, int server_port, - android::bluetooth::SocketRoleEnum socket_role) { + android::bluetooth::SocketRoleEnum socket_role, + uint64_t connection_duration_ms, + android::bluetooth::SocketErrorEnum error_code, + bool is_hardware_offload) { Address address = bluetooth::ToGdAddress(raw_address); - bluetooth::os::LogMetricSocketConnectionState(address, port, type, connection_state, tx_bytes, - rx_bytes, uid, server_port, socket_role); + bluetooth::os::LogMetricSocketConnectionState( + address, port, type, connection_state, tx_bytes, rx_bytes, uid, server_port, socket_role, + connection_duration_ms, error_code, is_hardware_offload); } void LogMetricManufacturerInfo(const RawAddress& raw_address, @@ -247,5 +251,18 @@ void LogMetricHfpSlcFail(hci::Address address) { State::HFP_SLC_FAIL_CONNECTION); } +void LogMetricScoLinkCreated(hci::Address address) { + bluetooth::os::LogMetricBluetoothEvent(address, EventType::SCO_SESSION, State::SCO_LINK_CREATED); +} + +void LogMetricScoLinkRemoved(hci::Address address) { + bluetooth::os::LogMetricBluetoothEvent(address, EventType::SCO_SESSION, State::SCO_LINK_REMOVED); +} + +void LogMetricScoCodec(hci::Address address, uint16_t codec) { + bluetooth::os::LogMetricBluetoothEvent(address, EventType::SCO_CODEC, + bluetooth::metrics::MapScoCodecToState(codec)); +} + } // namespace shim } // namespace bluetooth diff --git a/system/main/shim/metrics_api.h b/system/main/shim/metrics_api.h index 43d89e5469..143a2f754d 100644 --- a/system/main/shim/metrics_api.h +++ b/system/main/shim/metrics_api.h @@ -225,11 +225,17 @@ void LogMetricSdpAttribute(const RawAddress& address, uint16_t protocol_uuid, ui * by |server_port| * @param socket_role role of this socket, server or connection * @param uid socket owner's uid + * @param connection_duration_ms duration of socket connection in milliseconds + * @param error_code error code of socket failures + * @param is_hardware_offload whether this is a offload socket */ void LogMetricSocketConnectionState(const RawAddress& address, int port, int type, android::bluetooth::SocketConnectionstateEnum connection_state, int64_t tx_bytes, int64_t rx_bytes, int uid, int server_port, - android::bluetooth::SocketRoleEnum socket_role); + android::bluetooth::SocketRoleEnum socket_role, + uint64_t connection_duration_ms, + android::bluetooth::SocketErrorEnum error_code, + bool is_hardware_offload); /** * Logs when a Bluetooth device's manufacturer information is learnt @@ -354,5 +360,24 @@ void LogMetricHfpRfcommAgOpenFail(hci::Address address); */ void LogMetricHfpSlcFail(hci::Address address); +/** + * Logs when a SCO link is created in HFP + * @param address + */ +void LogMetricScoLinkCreated(hci::Address address); + +/** + * Logs when a SCO link is removed in HFP + * @param address + */ +void LogMetricScoLinkRemoved(hci::Address address); + +/** + * Logs what codec the SCO is using + * @param address + * @param codec + */ +void LogMetricScoCodec(hci::Address address, uint16_t codec); + } // namespace shim } // namespace bluetooth diff --git a/system/main/shim/stack.cc b/system/main/shim/stack.cc index c570a5f542..bb8994aee0 100644 --- a/system/main/shim/stack.cc +++ b/system/main/shim/stack.cc @@ -169,8 +169,11 @@ void Stack::Stop() { log::assert_that(is_running_, "Gd stack not running"); is_running_ = false; - stack_handler_->Clear(); - + if (!com::android::bluetooth::flags::same_handler_for_all_modules()) { + // Clear the handler only if the flag is not defined, otherwise it will be cleared by the + // registry + stack_handler_->Clear(); + } WakelockManager::Get().Acquire(); std::promise<void> promise; @@ -192,7 +195,14 @@ void Stack::Stop() { delete management_handler_; delete management_thread_; - delete stack_handler_; + if (!com::android::bluetooth::flags::same_handler_for_all_modules()) { + // delete the handler only if the flag is not defined, otherwise it will be deleted by the + // registry + delete stack_handler_; + } + + // stack_handler_ is already deleted by the registry in handle_shut_down, just set it to nullptr + // to avoid any potential use-after-free stack_handler_ = nullptr; stack_thread_->Stop(); @@ -259,7 +269,7 @@ void Stack::handle_start_up(ModuleList* modules, std::promise<void> promise) { pimpl_->counter_metrics_->Start(); pimpl_->storage_->Start(); pimpl_->snoop_logger_->Start(); - registry_.Start(modules, stack_thread_); + registry_.Start(modules, stack_thread_, stack_handler_); promise.set_value(); } diff --git a/system/osi/Android.bp b/system/osi/Android.bp index 0c008ff771..fdd51a564b 100644 --- a/system/osi/Android.bp +++ b/system/osi/Android.bp @@ -29,7 +29,6 @@ filegroup { cc_library_static { name: "libosi", visibility: [ - "//packages/apps/Test/connectivity/sl4n", "//packages/modules/Bluetooth:__subpackages__", ], export_include_dirs: [ 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/stack/a2dp/a2dp_api.cc b/system/stack/a2dp/a2dp_api.cc index 4374867f15..31119be104 100644 --- a/system/stack/a2dp/a2dp_api.cc +++ b/system/stack/a2dp/a2dp_api.cc @@ -27,6 +27,7 @@ #include "a2dp_api.h" #include <bluetooth/log.h> +#include <com_android_bluetooth_flags.h> #include <string.h> #include <cstdint> @@ -220,7 +221,8 @@ bool A2DP_AddRecord(uint16_t service_uuid, char* p_service_name, char* p_provide /* add profile descriptor list */ result &= get_legacy_stack_sdp_api()->handle.SDP_AddProfileDescriptorList( - sdp_handle, UUID_SERVCLASS_ADV_AUDIO_DISTRIBUTION, A2DP_VERSION); + sdp_handle, UUID_SERVCLASS_ADV_AUDIO_DISTRIBUTION, + com::android::bluetooth::flags::a2dp_version_1_4() ? A2DP_VERSION_V1_4 : A2DP_VERSION_V1_3); /* add supported feature */ if (features != 0) { diff --git a/system/stack/a2dp/a2dp_ext.cc b/system/stack/a2dp/a2dp_ext.cc index b938c93cd9..094a517364 100644 --- a/system/stack/a2dp/a2dp_ext.cc +++ b/system/stack/a2dp/a2dp_ext.cc @@ -86,11 +86,13 @@ tA2DP_STATUS A2dpCodecConfigExt::setCodecConfig(const uint8_t* p_peer_codec_info return A2DP_SUCCESS; } -bool A2dpCodecConfigExt::setPeerCodecCapabilities(const uint8_t* /* p_peer_codec_capabilities */) { - // setPeerCodecCapabilities updates the selectable - // capabilities in the codec config. It can be safely - // ignored as providing a superset of the selectable - // capabilities is safe. +bool A2dpCodecConfigExt::setPeerCodecCapabilities(const uint8_t* p_peer_codec_capabilities) { + // Use the local capabilities for the selectable capabilities: + // the provider AIDL HAL does not provide an interface to parse the + // peer capabilities and the selectable capabilities cannot be + // computed. + codec_selectable_capability_ = codec_local_capability_; + memcpy(ota_codec_peer_capability_, p_peer_codec_capabilities, sizeof(ota_codec_peer_capability_)); return true; } diff --git a/system/stack/a2dp/a2dp_int.h b/system/stack/a2dp/a2dp_int.h index 922ff29be9..69f36c3c7c 100644 --- a/system/stack/a2dp/a2dp_int.h +++ b/system/stack/a2dp/a2dp_int.h @@ -29,7 +29,8 @@ /***************************************************************************** * Constants ****************************************************************************/ -#define A2DP_VERSION 0x0103 +#define A2DP_VERSION_V1_3 0x0103 +#define A2DP_VERSION_V1_4 0x0104 /* Number of attributes in A2DP SDP record. */ #define A2DP_NUM_ATTR 6 diff --git a/system/stack/btm/btm_ble_sec.cc b/system/stack/btm/btm_ble_sec.cc index 05d1c16337..b7db7fa130 100644 --- a/system/stack/btm/btm_ble_sec.cc +++ b/system/stack/btm/btm_ble_sec.cc @@ -744,16 +744,28 @@ tBTM_STATUS btm_ble_start_sec_check(const RawAddress& bd_addr, uint16_t psm, boo bool is_encrypted = BTM_IsEncrypted(bd_addr, BT_TRANSPORT_LE); bool is_link_key_authed = BTM_IsLinkKeyAuthed(bd_addr, BT_TRANSPORT_LE); bool is_authenticated = BTM_IsAuthenticated(bd_addr, BT_TRANSPORT_LE); + bool is_bonded = BTM_IsBonded(bd_addr, BT_TRANSPORT_LE); if (!is_originator) { - if ((p_serv_rec->security_flags & BTM_SEC_IN_ENCRYPT) && !is_encrypted) { - log::error("BTM_NOT_ENCRYPTED. service security_flags=0x{:x}", p_serv_rec->security_flags); - return tBTM_STATUS::BTM_NOT_ENCRYPTED; - } else if ((p_serv_rec->security_flags & BTM_SEC_IN_AUTHENTICATE) && - !(is_link_key_authed || is_authenticated)) { - log::error("tBTM_STATUS::BTM_NOT_AUTHENTICATED. service security_flags=0x{:x}", - p_serv_rec->security_flags); - return tBTM_STATUS::BTM_NOT_AUTHENTICATED; + if (!com::android::bluetooth::flags::donot_mandate_auth_along_with_encryption()) { + if ((p_serv_rec->security_flags & BTM_SEC_IN_ENCRYPT) && !is_encrypted) { + log::error("BTM_NOT_ENCRYPTED. service security_flags=0x{:x}", p_serv_rec->security_flags); + return tBTM_STATUS::BTM_NOT_ENCRYPTED; + } else if ((p_serv_rec->security_flags & BTM_SEC_IN_AUTHENTICATE) && + !(is_link_key_authed || is_authenticated)) { + log::error("tBTM_STATUS::BTM_NOT_AUTHENTICATED. service security_flags=0x{:x}", + p_serv_rec->security_flags); + return tBTM_STATUS::BTM_NOT_AUTHENTICATED; + } + } else { + if ((p_serv_rec->security_flags & BTM_SEC_IN_ENCRYPT) && !is_encrypted) { + log::error("BTM_NOT_ENCRYPTED. service security_flags=0x{:x}", p_serv_rec->security_flags); + return tBTM_STATUS::BTM_NOT_ENCRYPTED; + } else if ((p_serv_rec->security_flags & BTM_SEC_IN_AUTHENTICATE) && !(is_bonded)) { + log::error("tBTM_STATUS::BTM_NOT_AUTHENTICATED. service security_flags=0x{:x}", + p_serv_rec->security_flags); + return tBTM_STATUS::BTM_NOT_AUTHENTICATED; + } } /* TODO: When security is required, then must check that the key size of our service is equal or smaller than the incoming connection key size. */ @@ -1677,7 +1689,6 @@ static void btm_ble_consent_req(const RawAddress& bd_addr, tBTM_LE_EVT_DATA* p_d static void btm_ble_complete_evt(const RawAddress& bd_addr, tBTM_SEC_DEV_REC* p_dev_rec, tBTM_LE_EVT_DATA* p_data) { - if (btm_ble_complete_evt_ignore(p_dev_rec, p_data)) { return; } diff --git a/system/stack/btm/btm_sec.cc b/system/stack/btm/btm_sec.cc index d218c234fa..b00b779eee 100644 --- a/system/stack/btm/btm_sec.cc +++ b/system/stack/btm/btm_sec.cc @@ -241,42 +241,6 @@ static tBTM_SEC_DEV_REC* btm_sec_find_dev_by_sec_state(tSECURITY_STATE state) { /******************************************************************************* * - * Function btm_sec_is_device_sc_downgrade - * - * Description Check for a stored device record matching the candidate - * device, and return true if the stored device has reported - * that it supports Secure Connections mode and the candidate - * device reports that it does not. Otherwise, return false. - * - * Returns bool - * - ******************************************************************************/ -static bool btm_sec_is_device_sc_downgrade(uint16_t hci_handle, bool secure_connections_supported) { - if (secure_connections_supported) { - return false; - } - - tBTM_SEC_DEV_REC* p_dev_rec = btm_find_dev_by_handle(hci_handle); - if (p_dev_rec == nullptr) { - return false; - } - - uint8_t property_val = 0; - bt_property_t property = {.type = BT_PROPERTY_REMOTE_SECURE_CONNECTIONS_SUPPORTED, - .len = sizeof(uint8_t), - .val = &property_val}; - - bt_status_t cached = btif_storage_get_remote_device_property(&p_dev_rec->bd_addr, &property); - - if (cached == BT_STATUS_FAIL) { - return false; - } - - return (bool)property_val; -} - -/******************************************************************************* - * * Function btm_sec_store_device_sc_support * * Description Save Secure Connections support for this device to file @@ -667,6 +631,7 @@ tBTM_STATUS btm_sec_bond_by_transport(const RawAddress& bd_addr, tBLE_ADDR_TYPE /* Finished if connection is active and already paired */ if (((p_dev_rec->hci_handle != HCI_INVALID_HANDLE) && transport == BT_TRANSPORT_BR_EDR && + (btm_get_bond_type_dev(bd_addr) == BOND_TYPE_PERSISTENT) && (p_dev_rec->sec_rec.sec_flags & BTM_SEC_AUTHENTICATED)) || ((p_dev_rec->ble_hci_handle != HCI_INVALID_HANDLE) && transport == BT_TRANSPORT_LE && (p_dev_rec->sec_rec.sec_flags & BTM_SEC_LE_AUTHENTICATED))) { @@ -4009,6 +3974,10 @@ void btm_sec_disconnected(uint16_t handle, tHCI_REASON reason, std::string comme p_dev_rec->sec_rec.classic_link = tSECURITY_STATE::IDLE; p_dev_rec->sec_rec.le_link = tSECURITY_STATE::IDLE; p_dev_rec->sec_rec.security_required = BTM_SEC_NONE; + if (com::android::bluetooth::flags::reset_security_flags_on_pairing_failure() && + !btm_sec_is_a_bonded_dev(p_dev_rec->bd_addr)) { + p_dev_rec->sec_rec.sec_flags = 0; + } if (p_dev_rec->sec_rec.p_callback != nullptr) { tBTM_SEC_CALLBACK* p_callback = p_dev_rec->sec_rec.p_callback; @@ -5172,15 +5141,6 @@ void btm_sec_set_peer_sec_caps(uint16_t hci_handle, bool ssp_supported, bool sc_ return; } - // Drop the connection here if the remote attempts to downgrade from Secure - // Connections mode. - if (btm_sec_is_device_sc_downgrade(hci_handle, sc_supported)) { - acl_set_disconnect_reason(HCI_ERR_HOST_REJECT_SECURITY); - btm_sec_send_hci_disconnect(p_dev_rec, HCI_ERR_AUTH_FAILURE, hci_handle, - "attempted to downgrade from Secure Connections mode"); - return; - } - p_dev_rec->remote_feature_received = true; p_dev_rec->remote_supports_hci_role_switch = hci_role_switch_supported; diff --git a/system/stack/l2cap/l2c_api.cc b/system/stack/l2cap/l2c_api.cc index 38b9dd030c..04f32105e5 100644 --- a/system/stack/l2cap/l2c_api.cc +++ b/system/stack/l2cap/l2c_api.cc @@ -1211,8 +1211,15 @@ bool L2CA_ConnectFixedChnl(uint16_t fixed_cid, const RawAddress& rem_bda) { // Restore the fixed channel if it was suspended l2cu_fixed_channel_restore(p_lcb, fixed_cid); - (*l2cb.fixed_reg[fixed_cid - L2CAP_FIRST_FIXED_CHNL].pL2CA_FixedConn_Cb)( - fixed_cid, p_lcb->remote_bd_addr, true, 0, p_lcb->transport); + if (!com::android::bluetooth::flags::smp_connection_status_handling_when_no_acl()) { + (*l2cb.fixed_reg[fixed_cid - L2CAP_FIRST_FIXED_CHNL].pL2CA_FixedConn_Cb)( + fixed_cid, p_lcb->remote_bd_addr, true, 0, p_lcb->transport); + return true; + } + if (p_lcb->link_state == LST_CONNECTED) { + (*l2cb.fixed_reg[fixed_cid - L2CAP_FIRST_FIXED_CHNL].pL2CA_FixedConn_Cb)( + fixed_cid, p_lcb->remote_bd_addr, true, 0, p_lcb->transport); + } return true; } diff --git a/system/test/mock/mock_main_shim_metrics_api.cc b/system/test/mock/mock_main_shim_metrics_api.cc index 259fa2dcfb..e635979ed8 100644 --- a/system/test/mock/mock_main_shim_metrics_api.cc +++ b/system/test/mock/mock_main_shim_metrics_api.cc @@ -67,6 +67,9 @@ struct LogMetricHfpRfcommChannelFail LogMetricHfpRfcommChannelFail; struct LogMetricHfpRfcommCollisionFail LogMetricHfpRfcommCollisionFail; struct LogMetricHfpRfcommAgOpenFail LogMetricHfpRfcommAgOpenFail; struct LogMetricHfpSlcFail LogMetricHfpSlcFail; +struct LogMetricScoCodec LogMetricScoCodec; +struct LogMetricScoLinkCreated LogMetricScoLinkCreated; +struct LogMetricScoLinkRemoved LogMetricScoLinkRemoved; } // namespace main_shim_metrics_api } // namespace mock @@ -181,12 +184,13 @@ void bluetooth::shim::LogMetricSdpAttribute(const RawAddress& raw_address, uint1 void bluetooth::shim::LogMetricSocketConnectionState( const RawAddress& raw_address, int port, int type, android::bluetooth::SocketConnectionstateEnum connection_state, int64_t tx_bytes, - int64_t rx_bytes, int uid, int server_port, - android::bluetooth::SocketRoleEnum socket_role) { + int64_t rx_bytes, int uid, int server_port, android::bluetooth::SocketRoleEnum socket_role, + uint64_t connection_duration_ms, android::bluetooth::SocketErrorEnum error_code, + bool is_hardware_offload) { inc_func_call_count(__func__); test::mock::main_shim_metrics_api::LogMetricSocketConnectionState( raw_address, port, type, connection_state, tx_bytes, rx_bytes, uid, server_port, - socket_role); + socket_role, connection_duration_ms, error_code, is_hardware_offload); } void bluetooth::shim::LogMetricManufacturerInfo( const RawAddress& raw_address, android::bluetooth::AddressTypeEnum address_type, @@ -271,4 +275,19 @@ void bluetooth::shim::LogMetricHfpSlcFail(bluetooth::hci::Address address) { test::mock::main_shim_metrics_api::LogMetricHfpSlcFail(address); } +void bluetooth::shim::LogMetricScoCodec(bluetooth::hci::Address address, uint16_t codec) { + inc_func_call_count(__func__); + test::mock::main_shim_metrics_api::LogMetricScoCodec(address, codec); +} + +void bluetooth::shim::LogMetricScoLinkCreated(bluetooth::hci::Address address) { + inc_func_call_count(__func__); + test::mock::main_shim_metrics_api::LogMetricScoLinkCreated(address); +} + +void bluetooth::shim::LogMetricScoLinkRemoved(bluetooth::hci::Address address) { + inc_func_call_count(__func__); + test::mock::main_shim_metrics_api::LogMetricScoLinkRemoved(address); +} + // END mockcify generation diff --git a/system/test/mock/mock_main_shim_metrics_api.h b/system/test/mock/mock_main_shim_metrics_api.h index 8a245bbe37..4beaab72c0 100644 --- a/system/test/mock/mock_main_shim_metrics_api.h +++ b/system/test/mock/mock_main_shim_metrics_api.h @@ -274,17 +274,23 @@ struct LogMetricSocketConnectionState { std::function<void(const RawAddress& raw_address, int port, int type, android::bluetooth::SocketConnectionstateEnum connection_state, int64_t tx_bytes, int64_t rx_bytes, int uid, int server_port, - android::bluetooth::SocketRoleEnum socket_role)> + android::bluetooth::SocketRoleEnum socket_role, + uint64_t connection_duration_ms, + android::bluetooth::SocketErrorEnum error_code, bool is_hardware_offload)> body{[](const RawAddress& /* raw_address */, int /* port */, int /* type */, android::bluetooth::SocketConnectionstateEnum /* connection_state */, int64_t /* tx_bytes */, int64_t /* rx_bytes */, int /* uid */, - int /* server_port */, android::bluetooth::SocketRoleEnum /* socket_role */) {}}; + int /* server_port */, android::bluetooth::SocketRoleEnum /* socket_role */, + uint64_t /* connection_duration_ms */, + android::bluetooth::SocketErrorEnum /* error_code */, + bool /* is_hardware_offload */) {}}; void operator()(const RawAddress& raw_address, int port, int type, android::bluetooth::SocketConnectionstateEnum connection_state, int64_t tx_bytes, int64_t rx_bytes, int uid, int server_port, - android::bluetooth::SocketRoleEnum socket_role) { + android::bluetooth::SocketRoleEnum socket_role, uint64_t connection_duration_ms, + android::bluetooth::SocketErrorEnum error_code, bool is_hardware_offload) { body(raw_address, port, type, connection_state, tx_bytes, rx_bytes, uid, server_port, - socket_role); + socket_role, connection_duration_ms, error_code, is_hardware_offload); } }; extern struct LogMetricSocketConnectionState LogMetricSocketConnectionState; @@ -474,6 +480,36 @@ struct LogMetricHfpSlcFail { }; extern struct LogMetricHfpSlcFail LogMetricHfpSlcFail; +// Name: LogMetricScoCodec +// Params: bluetooth::hci::Address, uint16_t codec +// Returns: void +struct LogMetricScoCodec { + std::function<void(bluetooth::hci::Address address, uint16_t codec)> body{ + [](bluetooth::hci::Address /* address */, uint16_t /* codec */) {}}; + void operator()(bluetooth::hci::Address address, uint16_t codec) { body(address, codec); } +}; +extern struct LogMetricScoCodec LogMetricScoCodec; + +// Name: LogMetricScoLinkCreated +// Params: bluetooth::hci::Address +// Returns: void +struct LogMetricScoLinkCreated { + std::function<void(bluetooth::hci::Address address)> body{ + [](bluetooth::hci::Address /* address */) {}}; + void operator()(bluetooth::hci::Address address) { body(address); } +}; +extern struct LogMetricScoLinkCreated LogMetricScoLinkCreated; + +// Name: LogMetricScoLinkRemoved +// Params: bluetooth::hci::Address +// Returns: void +struct LogMetricScoLinkRemoved { + std::function<void(bluetooth::hci::Address address)> body{ + [](bluetooth::hci::Address /* address */) {}}; + void operator()(bluetooth::hci::Address address) { body(address); } +}; +extern struct LogMetricScoLinkRemoved LogMetricScoLinkRemoved; + } // namespace main_shim_metrics_api } // namespace mock } // namespace test 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() |