Loading android/ChannelSoundingTestApp/app/src/main/java/com/android/bluetooth/channelsoundingtestapp/DistanceMeasurementInitiator.java +1 −0 Original line number Diff line number Diff line Loading @@ -74,6 +74,7 @@ class DistanceMeasurementInitiator { void setTargetDevice(BluetoothDevice targetDevice) { mTargetDevice = targetDevice; } private void printLog(String log) { mLoggingListener.onLog(log); } Loading android/app/Android.bp +1 −0 Original line number Diff line number Diff line Loading @@ -342,6 +342,7 @@ android_app { "-Xep:InvalidParam:ERROR", "-Xep:LoopOverCharArray:ERROR", "-Xep:MissingCasesInEnumSwitch:ERROR", "-Xep:MixedMutabilityReturnType:ERROR", "-Xep:MockNotUsedInProduction:ERROR", "-Xep:ModifyCollectionInEnhancedForLoop:ERROR", "-Xep:NarrowCalculation:ERROR", Loading android/app/src/com/android/bluetooth/Utils.java +111 −84 Original line number Diff line number Diff line Loading @@ -100,8 +100,7 @@ public final class Utils { private static final int MICROS_PER_UNIT = 625; private static final String PTS_TEST_MODE_PROPERTY = "persist.bluetooth.pts"; private static final String ENABLE_DUAL_MODE_AUDIO = "persist.bluetooth.enable_dual_mode_audio"; private static final String ENABLE_DUAL_MODE_AUDIO = "persist.bluetooth.enable_dual_mode_audio"; private static boolean sDualModeEnabled = SystemProperties.getBoolean(ENABLE_DUAL_MODE_AUDIO, false); Loading Loading @@ -142,17 +141,17 @@ public final class Utils { /** * Check if dual mode audio is enabled. This is set via the system property * persist.bluetooth.enable_dual_mode_audio. * <p> * When set to {@code false}, we will not connect A2DP and HFP on a dual mode (BR/EDR + BLE) * * <p>When set to {@code false}, we will not connect A2DP and HFP on a dual mode (BR/EDR + BLE) * device. We will only attempt to use BLE Audio in this scenario. * <p> * When set to {@code true}, we will connect all the supported audio profiles * (A2DP, HFP, and LE Audio) at the same time. In this state, we will respect calls to * profile-specific APIs (e.g. if a SCO API is invoked, we will route audio over HFP). If no * profile-specific API is invoked to route audio (e.g. Telecom routed phone calls, media, * game audio, etc.), then audio will be routed in accordance with the preferred audio profiles * for the remote device. You can get the preferred audio profiles for a remote device by * calling {@link BluetoothAdapter#getPreferredAudioProfiles(BluetoothDevice)}. * * <p>When set to {@code true}, we will connect all the supported audio profiles (A2DP, HFP, and * LE Audio) at the same time. In this state, we will respect calls to profile-specific APIs * (e.g. if a SCO API is invoked, we will route audio over HFP). If no profile-specific API is * invoked to route audio (e.g. Telecom routed phone calls, media, game audio, etc.), then audio * will be routed in accordance with the preferred audio profiles for the remote device. You can * get the preferred audio profiles for a remote device by calling {@link * BluetoothAdapter#getPreferredAudioProfiles(BluetoothDevice)}. * * @return true if dual mode audio is enabled, false otherwise */ Loading Loading @@ -191,6 +190,7 @@ public final class Utils { /** * Only exposed for testing, do not invoke this method outside of tests. * * @param enabled true if the dual mode state is enabled, false otherwise */ public static void setDualModeAudioStateForTesting(boolean enabled) { Loading Loading @@ -220,8 +220,9 @@ public final class Utils { return null; } return String.format("%02X:%02X:%02X:%02X:%02X:%02X", address[0], address[1], address[2], address[3], address[4], address[5]); return String.format( "%02X:%02X:%02X:%02X:%02X:%02X", address[0], address[1], address[2], address[3], address[4], address[5]); } public static String getRedactedAddressStringFromByte(byte[] address) { Loading Loading @@ -413,7 +414,8 @@ public final class Utils { converter.order(ByteOrder.BIG_ENDIAN); for (int i = 0; i < numUuids; i++) { puuids[i] = new ParcelUuid( puuids[i] = new ParcelUuid( new UUID(converter.getLong(offset), converter.getLong(offset + 8))); offset += BD_UUID_LEN; } Loading Loading @@ -481,6 +483,7 @@ public final class Utils { } static int sSystemUiUid = USER_HANDLE_NULL.getIdentifier(); public static void setSystemUiUid(int uid) { Utils.sSystemUiUid = uid; } Loading Loading @@ -514,8 +517,11 @@ public final class Utils { BluetoothDevice device) { int callingUid = Binder.getCallingUid(); if (!isPackageNameAccurate(context, callingPackage, callingUid)) { throw new SecurityException("hasCdmAssociation: Package name " + callingPackage + " is inaccurate for calling uid " + callingUid); throw new SecurityException( "hasCdmAssociation: Package name " + callingPackage + " is inaccurate for calling uid " + callingUid); } for (AssociationInfo association : cdm.getAllAssociations()) { Loading Loading @@ -559,15 +565,26 @@ public final class Utils { // Verifies the integrity of the calling package name try { int packageUid = context.createContextAsUser(callingUser, 0) .getPackageManager().getPackageUid(callingPackage, 0); int packageUid = context.createContextAsUser(callingUser, 0) .getPackageManager() .getPackageUid(callingPackage, 0); if (packageUid != callingUid) { Log.e(TAG, "isPackageNameAccurate: App with package name " + callingPackage + " is UID " + packageUid + " but caller is " + callingUid); Log.e( TAG, "isPackageNameAccurate: App with package name " + callingPackage + " is UID " + packageUid + " but caller is " + callingUid); return false; } } catch (PackageManager.NameNotFoundException e) { Log.e(TAG, "isPackageNameAccurate: App with package name " + callingPackage Log.e( TAG, "isPackageNameAccurate: App with package name " + callingPackage + " does not exist"); return false; } Loading @@ -591,8 +608,8 @@ public final class Utils { if (pm == null) { return false; } final int result = pm.checkPermissionForPreflight(permission, context.getAttributionSource()); final int result = pm.checkPermissionForPreflight(permission, context.getAttributionSource()); if (result == PERMISSION_GRANTED) { return true; } Loading Loading @@ -625,8 +642,9 @@ public final class Utils { if (pm == null) { return false; } final int result = pm.checkPermissionForDataDeliveryFromDataSource(permission, currentAttribution, message); final int result = pm.checkPermissionForDataDeliveryFromDataSource( permission, currentAttribution, message); if (result == PERMISSION_GRANTED) { return true; } Loading Loading @@ -666,8 +684,8 @@ public final class Utils { @RequiresPermission(BLUETOOTH_CONNECT) public static boolean checkConnectPermissionForDataDelivery( Context context, AttributionSource attributionSource, String message) { return checkPermissionForDataDelivery(context, BLUETOOTH_CONNECT, attributionSource, message); return checkPermissionForDataDelivery( context, BLUETOOTH_CONNECT, attributionSource, message); } /** Loading @@ -693,8 +711,7 @@ public final class Utils { @RequiresPermission(BLUETOOTH_SCAN) public static boolean checkScanPermissionForDataDelivery( Context context, AttributionSource attributionSource, String message) { return checkPermissionForDataDelivery(context, BLUETOOTH_SCAN, attributionSource, message); return checkPermissionForDataDelivery(context, BLUETOOTH_SCAN, attributionSource, message); } /** Loading Loading @@ -764,7 +781,8 @@ public final class Utils { for (int i = 0; i < pkgInfo.requestedPermissions.length; i++) { if (pkgInfo.requestedPermissions[i].equals(BLUETOOTH_SCAN)) { return (pkgInfo.requestedPermissionsFlags[i] & PackageInfo.REQUESTED_PERMISSION_NEVER_FOR_LOCATION) != 0; & PackageInfo.REQUESTED_PERMISSION_NEVER_FOR_LOCATION) != 0; } } } catch (PackageManager.NameNotFoundException e) { Loading Loading @@ -856,14 +874,17 @@ public final class Utils { } final boolean res = checkCallerIsSystemOrActiveOrManagedUser(context); if (!res) { Log.w(TAG, tag + " - Not allowed for" Log.w( TAG, tag + " - Not allowed for" + " non-active user and non-system and non-managed user"); } return res; } public static boolean callerIsSystemOrActiveOrManagedUser(Context context, String tag, String method) { public static boolean callerIsSystemOrActiveOrManagedUser( Context context, String tag, String method) { return checkCallerIsSystemOrActiveOrManagedUser(context, tag + "." + method + "()"); } Loading @@ -879,9 +900,7 @@ public final class Utils { return true; } /** * Checks whether location is off and must be on for us to perform some operation */ /** Checks whether location is off and must be on for us to perform some operation */ public static boolean blockedByLocationOff(Context context, UserHandle userHandle) { return !context.getSystemService(LocationManager.class) .isLocationEnabledForUser(userHandle); Loading @@ -906,12 +925,15 @@ public final class Utils { if (pm == null) { return false; } if (pm.checkPermissionForDataDeliveryFromDataSource(ACCESS_COARSE_LOCATION, currentAttribution, "Bluetooth location check") == PERMISSION_GRANTED) { if (pm.checkPermissionForDataDeliveryFromDataSource( ACCESS_COARSE_LOCATION, currentAttribution, "Bluetooth location check") == PERMISSION_GRANTED) { return true; } Log.e(TAG, "Permission denial: Need ACCESS_COARSE_LOCATION " Log.e( TAG, "Permission denial: Need ACCESS_COARSE_LOCATION " + "permission to get scan results"); return false; } Loading Loading @@ -945,12 +967,15 @@ public final class Utils { return true; } if (pm.checkPermissionForDataDeliveryFromDataSource(ACCESS_COARSE_LOCATION, currentAttribution, "Bluetooth location check") == PERMISSION_GRANTED) { if (pm.checkPermissionForDataDeliveryFromDataSource( ACCESS_COARSE_LOCATION, currentAttribution, "Bluetooth location check") == PERMISSION_GRANTED) { return true; } Log.e(TAG, "Permission denial: Need ACCESS_COARSE_LOCATION or ACCESS_FINE_LOCATION" Log.e( TAG, "Permission denial: Need ACCESS_COARSE_LOCATION or ACCESS_FINE_LOCATION" + "permission to get scan results"); return false; } Loading Loading @@ -981,32 +1006,27 @@ public final class Utils { return true; } Log.e(TAG, "Permission denial: Need ACCESS_FINE_LOCATION " + "permission to get scan results"); Log.e( TAG, "Permission denial: Need ACCESS_FINE_LOCATION " + "permission to get scan results"); return false; } /** * Returns true if the caller holds NETWORK_SETTINGS */ /** Returns true if the caller holds NETWORK_SETTINGS */ // Suppressed since we're not actually enforcing here @SuppressLint("AndroidFrameworkRequiresPermission") public static boolean checkCallerHasNetworkSettingsPermission(Context context) { return context.checkCallingOrSelfPermission(NETWORK_SETTINGS) == PERMISSION_GRANTED; } /** * Returns true if the caller holds NETWORK_SETUP_WIZARD */ /** Returns true if the caller holds NETWORK_SETUP_WIZARD */ // Suppressed since we're not actually enforcing here @SuppressLint("AndroidFrameworkRequiresPermission") public static boolean checkCallerHasNetworkSetupWizardPermission(Context context) { return context.checkCallingOrSelfPermission(NETWORK_SETUP_WIZARD) == PERMISSION_GRANTED; } /** * Returns true if the caller holds RADIO_SCAN_WITHOUT_LOCATION */ /** Returns true if the caller holds RADIO_SCAN_WITHOUT_LOCATION */ // Suppressed since we're not actually enforcing here @SuppressLint("AndroidFrameworkRequiresPermission") public static boolean checkCallerHasScanWithoutLocationPermission(Context context) { Loading Loading @@ -1050,9 +1070,7 @@ public final class Utils { return true; } /** * Converts {@code milliseconds} to unit. Each unit is 0.625 millisecond. */ /** Converts {@code milliseconds} to unit. Each unit is 0.625 millisecond. */ public static int millsToUnit(int milliseconds) { return (int) (TimeUnit.MILLISECONDS.toMicros(milliseconds) / MICROS_PER_UNIT); } Loading @@ -1063,8 +1081,8 @@ public final class Utils { /** * Check if we are running in BluetoothInstrumentationTest context by trying to load * com.android.bluetooth.FileSystemWriteTest. If we are not in Instrumentation test mode, this * class should not be found. Thus, the assumption is that FileSystemWriteTest must exist. * If FileSystemWriteTest is removed in the future, another test class in * class should not be found. Thus, the assumption is that FileSystemWriteTest must exist. If * FileSystemWriteTest is removed in the future, another test class in * BluetoothInstrumentationTest should be used instead * * @return true if in BluetoothInstrumentationTest, false otherwise Loading Loading @@ -1093,8 +1111,8 @@ public final class Utils { } /** * Check if we are running in PTS test mode. To enable/disable PTS test mode, invoke * {@code adb shell setprop persist.bluetooth.pts true/false} * Check if we are running in PTS test mode. To enable/disable PTS test mode, invoke {@code adb * shell setprop persist.bluetooth.pts true/false} * * @return true if in PTS Test mode, false otherwise */ Loading @@ -1118,7 +1136,8 @@ public final class Utils { */ public static String getLocalTimeString() { return DateTimeFormatter.ofPattern("MM-dd HH:mm:ss.SSS") .withZone(ZoneId.systemDefault()).format(Instant.now()); .withZone(ZoneId.systemDefault()) .format(Instant.now()); } public static void skipCurrentTag(XmlPullParser parser) Loading @@ -1126,15 +1145,12 @@ public final class Utils { int outerDepth = parser.getDepth(); int type; while ((type = parser.next()) != XmlPullParser.END_DOCUMENT && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) { } && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {} } /** * Converts pause and tonewait pause characters * to Android representation. * RFC 3601 says pause is 'p' and tonewait is 'w'. * Converts pause and tonewait pause characters to Android representation. RFC 3601 says pause * is 'p' and tonewait is 'w'. */ public static String convertPreDial(String phoneNumber) { if (phoneNumber == null) { Loading Loading @@ -1179,23 +1195,28 @@ public final class Utils { } values.put(Telephony.Sms.ERROR_CODE, 0); return 1 == BluetoothMethodProxy.getInstance().contentResolverUpdate( return 1 == BluetoothMethodProxy.getInstance() .contentResolverUpdate( context.getContentResolver(), uri, values, null, null); } /** * Returns broadcast options. */ /** Returns broadcast options. */ public static @NonNull BroadcastOptions getTempBroadcastOptions() { final BroadcastOptions bOptions = BroadcastOptions.makeBasic(); // Use the Bluetooth process identity to pass permission check when reading DeviceConfig final long ident = Binder.clearCallingIdentity(); try { final long durationMs = DeviceConfig.getLong(DeviceConfig.NAMESPACE_BLUETOOTH, KEY_TEMP_ALLOW_LIST_DURATION_MS, DEFAULT_TEMP_ALLOW_LIST_DURATION_MS); bOptions.setTemporaryAppAllowlist(durationMs, final long durationMs = DeviceConfig.getLong( DeviceConfig.NAMESPACE_BLUETOOTH, KEY_TEMP_ALLOW_LIST_DURATION_MS, DEFAULT_TEMP_ALLOW_LIST_DURATION_MS); bOptions.setTemporaryAppAllowlist( durationMs, TEMPORARY_ALLOW_LIST_TYPE_FOREGROUND_SERVICE_ALLOWED, PowerExemptionManager.REASON_BLUETOOTH_BROADCAST, ""); PowerExemptionManager.REASON_BLUETOOTH_BROADCAST, ""); } finally { Binder.restoreCallingIdentity(ident); } Loading @@ -1204,6 +1225,7 @@ public final class Utils { /** * Checks that value is present as at least one of the elements of the array. * * @param array the array to check in * @param value the value to check for * @return true if the value is present in the array Loading @@ -1218,6 +1240,7 @@ public final class Utils { /** * CCC descriptor short integer value to string. * * @param cccValue the short value of CCC descriptor * @return String value representing CCC state */ Loading @@ -1240,6 +1263,7 @@ public final class Utils { /** * Check if BLE is supported by this platform * * @param context current device context * @return true if BLE is supported, false otherwise */ Loading @@ -1249,6 +1273,7 @@ public final class Utils { /** * Check if this is an automotive device * * @param context current device context * @return true if this Android device is an automotive device, false otherwise */ Loading @@ -1258,6 +1283,7 @@ public final class Utils { /** * Check if this is a watch device * * @param context current device context * @return true if this Android device is a watch device, false otherwise */ Loading @@ -1267,6 +1293,7 @@ public final class Utils { /** * Check if this is a TV device * * @param context current device context * @return true if this Android device is a TV device, false otherwise */ Loading android/app/src/com/android/bluetooth/bass_client/BassClientService.java +4 −8 Original line number Diff line number Diff line Loading @@ -100,6 +100,7 @@ import java.util.Optional; import java.util.PriorityQueue; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; import java.util.stream.Collectors; /** Broadcast Assistant Scan Service */ public class BassClientService extends ProfileService { Loading Loading @@ -3059,14 +3060,9 @@ public class BassClientService extends ProfileService { log("stateMachine is null"); return Collections.emptyList(); } List<BluetoothLeBroadcastReceiveState> recvStates = new ArrayList<BluetoothLeBroadcastReceiveState>(); for (BluetoothLeBroadcastReceiveState rs : stateMachine.getAllSources()) { if (!isEmptyBluetoothDevice(rs.getSourceDevice())) { recvStates.add(rs); } } return recvStates; return stateMachine.getAllSources().stream() .filter(rs -> !isEmptyBluetoothDevice(rs.getSourceDevice())) .collect(Collectors.toList()); } } Loading android/app/src/com/android/bluetooth/btservice/MetricsLogger.java +3 −2 Original line number Diff line number Diff line Loading @@ -28,7 +28,6 @@ import android.util.proto.ProtoOutputStream; import androidx.annotation.RequiresApi; import com.android.bluetooth.bass_client.BassConstants; import com.android.bluetooth.BluetoothMetricsProto.BluetoothLog; import com.android.bluetooth.BluetoothMetricsProto.BluetoothRemoteDeviceInformation; import com.android.bluetooth.BluetoothMetricsProto.ProfileConnectionStats; Loading @@ -36,6 +35,7 @@ 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.modules.utils.build.SdkLevel; import com.google.common.annotations.VisibleForTesting; Loading Loading @@ -411,7 +411,8 @@ public class MetricsLogger { } } return wordBreakdownList; // Prevent returning a mutable list return Collections.unmodifiableList(wordBreakdownList); } @RequiresApi(Build.VERSION_CODES.UPSIDE_DOWN_CAKE) Loading Loading
android/ChannelSoundingTestApp/app/src/main/java/com/android/bluetooth/channelsoundingtestapp/DistanceMeasurementInitiator.java +1 −0 Original line number Diff line number Diff line Loading @@ -74,6 +74,7 @@ class DistanceMeasurementInitiator { void setTargetDevice(BluetoothDevice targetDevice) { mTargetDevice = targetDevice; } private void printLog(String log) { mLoggingListener.onLog(log); } Loading
android/app/Android.bp +1 −0 Original line number Diff line number Diff line Loading @@ -342,6 +342,7 @@ android_app { "-Xep:InvalidParam:ERROR", "-Xep:LoopOverCharArray:ERROR", "-Xep:MissingCasesInEnumSwitch:ERROR", "-Xep:MixedMutabilityReturnType:ERROR", "-Xep:MockNotUsedInProduction:ERROR", "-Xep:ModifyCollectionInEnhancedForLoop:ERROR", "-Xep:NarrowCalculation:ERROR", Loading
android/app/src/com/android/bluetooth/Utils.java +111 −84 Original line number Diff line number Diff line Loading @@ -100,8 +100,7 @@ public final class Utils { private static final int MICROS_PER_UNIT = 625; private static final String PTS_TEST_MODE_PROPERTY = "persist.bluetooth.pts"; private static final String ENABLE_DUAL_MODE_AUDIO = "persist.bluetooth.enable_dual_mode_audio"; private static final String ENABLE_DUAL_MODE_AUDIO = "persist.bluetooth.enable_dual_mode_audio"; private static boolean sDualModeEnabled = SystemProperties.getBoolean(ENABLE_DUAL_MODE_AUDIO, false); Loading Loading @@ -142,17 +141,17 @@ public final class Utils { /** * Check if dual mode audio is enabled. This is set via the system property * persist.bluetooth.enable_dual_mode_audio. * <p> * When set to {@code false}, we will not connect A2DP and HFP on a dual mode (BR/EDR + BLE) * * <p>When set to {@code false}, we will not connect A2DP and HFP on a dual mode (BR/EDR + BLE) * device. We will only attempt to use BLE Audio in this scenario. * <p> * When set to {@code true}, we will connect all the supported audio profiles * (A2DP, HFP, and LE Audio) at the same time. In this state, we will respect calls to * profile-specific APIs (e.g. if a SCO API is invoked, we will route audio over HFP). If no * profile-specific API is invoked to route audio (e.g. Telecom routed phone calls, media, * game audio, etc.), then audio will be routed in accordance with the preferred audio profiles * for the remote device. You can get the preferred audio profiles for a remote device by * calling {@link BluetoothAdapter#getPreferredAudioProfiles(BluetoothDevice)}. * * <p>When set to {@code true}, we will connect all the supported audio profiles (A2DP, HFP, and * LE Audio) at the same time. In this state, we will respect calls to profile-specific APIs * (e.g. if a SCO API is invoked, we will route audio over HFP). If no profile-specific API is * invoked to route audio (e.g. Telecom routed phone calls, media, game audio, etc.), then audio * will be routed in accordance with the preferred audio profiles for the remote device. You can * get the preferred audio profiles for a remote device by calling {@link * BluetoothAdapter#getPreferredAudioProfiles(BluetoothDevice)}. * * @return true if dual mode audio is enabled, false otherwise */ Loading Loading @@ -191,6 +190,7 @@ public final class Utils { /** * Only exposed for testing, do not invoke this method outside of tests. * * @param enabled true if the dual mode state is enabled, false otherwise */ public static void setDualModeAudioStateForTesting(boolean enabled) { Loading Loading @@ -220,8 +220,9 @@ public final class Utils { return null; } return String.format("%02X:%02X:%02X:%02X:%02X:%02X", address[0], address[1], address[2], address[3], address[4], address[5]); return String.format( "%02X:%02X:%02X:%02X:%02X:%02X", address[0], address[1], address[2], address[3], address[4], address[5]); } public static String getRedactedAddressStringFromByte(byte[] address) { Loading Loading @@ -413,7 +414,8 @@ public final class Utils { converter.order(ByteOrder.BIG_ENDIAN); for (int i = 0; i < numUuids; i++) { puuids[i] = new ParcelUuid( puuids[i] = new ParcelUuid( new UUID(converter.getLong(offset), converter.getLong(offset + 8))); offset += BD_UUID_LEN; } Loading Loading @@ -481,6 +483,7 @@ public final class Utils { } static int sSystemUiUid = USER_HANDLE_NULL.getIdentifier(); public static void setSystemUiUid(int uid) { Utils.sSystemUiUid = uid; } Loading Loading @@ -514,8 +517,11 @@ public final class Utils { BluetoothDevice device) { int callingUid = Binder.getCallingUid(); if (!isPackageNameAccurate(context, callingPackage, callingUid)) { throw new SecurityException("hasCdmAssociation: Package name " + callingPackage + " is inaccurate for calling uid " + callingUid); throw new SecurityException( "hasCdmAssociation: Package name " + callingPackage + " is inaccurate for calling uid " + callingUid); } for (AssociationInfo association : cdm.getAllAssociations()) { Loading Loading @@ -559,15 +565,26 @@ public final class Utils { // Verifies the integrity of the calling package name try { int packageUid = context.createContextAsUser(callingUser, 0) .getPackageManager().getPackageUid(callingPackage, 0); int packageUid = context.createContextAsUser(callingUser, 0) .getPackageManager() .getPackageUid(callingPackage, 0); if (packageUid != callingUid) { Log.e(TAG, "isPackageNameAccurate: App with package name " + callingPackage + " is UID " + packageUid + " but caller is " + callingUid); Log.e( TAG, "isPackageNameAccurate: App with package name " + callingPackage + " is UID " + packageUid + " but caller is " + callingUid); return false; } } catch (PackageManager.NameNotFoundException e) { Log.e(TAG, "isPackageNameAccurate: App with package name " + callingPackage Log.e( TAG, "isPackageNameAccurate: App with package name " + callingPackage + " does not exist"); return false; } Loading @@ -591,8 +608,8 @@ public final class Utils { if (pm == null) { return false; } final int result = pm.checkPermissionForPreflight(permission, context.getAttributionSource()); final int result = pm.checkPermissionForPreflight(permission, context.getAttributionSource()); if (result == PERMISSION_GRANTED) { return true; } Loading Loading @@ -625,8 +642,9 @@ public final class Utils { if (pm == null) { return false; } final int result = pm.checkPermissionForDataDeliveryFromDataSource(permission, currentAttribution, message); final int result = pm.checkPermissionForDataDeliveryFromDataSource( permission, currentAttribution, message); if (result == PERMISSION_GRANTED) { return true; } Loading Loading @@ -666,8 +684,8 @@ public final class Utils { @RequiresPermission(BLUETOOTH_CONNECT) public static boolean checkConnectPermissionForDataDelivery( Context context, AttributionSource attributionSource, String message) { return checkPermissionForDataDelivery(context, BLUETOOTH_CONNECT, attributionSource, message); return checkPermissionForDataDelivery( context, BLUETOOTH_CONNECT, attributionSource, message); } /** Loading @@ -693,8 +711,7 @@ public final class Utils { @RequiresPermission(BLUETOOTH_SCAN) public static boolean checkScanPermissionForDataDelivery( Context context, AttributionSource attributionSource, String message) { return checkPermissionForDataDelivery(context, BLUETOOTH_SCAN, attributionSource, message); return checkPermissionForDataDelivery(context, BLUETOOTH_SCAN, attributionSource, message); } /** Loading Loading @@ -764,7 +781,8 @@ public final class Utils { for (int i = 0; i < pkgInfo.requestedPermissions.length; i++) { if (pkgInfo.requestedPermissions[i].equals(BLUETOOTH_SCAN)) { return (pkgInfo.requestedPermissionsFlags[i] & PackageInfo.REQUESTED_PERMISSION_NEVER_FOR_LOCATION) != 0; & PackageInfo.REQUESTED_PERMISSION_NEVER_FOR_LOCATION) != 0; } } } catch (PackageManager.NameNotFoundException e) { Loading Loading @@ -856,14 +874,17 @@ public final class Utils { } final boolean res = checkCallerIsSystemOrActiveOrManagedUser(context); if (!res) { Log.w(TAG, tag + " - Not allowed for" Log.w( TAG, tag + " - Not allowed for" + " non-active user and non-system and non-managed user"); } return res; } public static boolean callerIsSystemOrActiveOrManagedUser(Context context, String tag, String method) { public static boolean callerIsSystemOrActiveOrManagedUser( Context context, String tag, String method) { return checkCallerIsSystemOrActiveOrManagedUser(context, tag + "." + method + "()"); } Loading @@ -879,9 +900,7 @@ public final class Utils { return true; } /** * Checks whether location is off and must be on for us to perform some operation */ /** Checks whether location is off and must be on for us to perform some operation */ public static boolean blockedByLocationOff(Context context, UserHandle userHandle) { return !context.getSystemService(LocationManager.class) .isLocationEnabledForUser(userHandle); Loading @@ -906,12 +925,15 @@ public final class Utils { if (pm == null) { return false; } if (pm.checkPermissionForDataDeliveryFromDataSource(ACCESS_COARSE_LOCATION, currentAttribution, "Bluetooth location check") == PERMISSION_GRANTED) { if (pm.checkPermissionForDataDeliveryFromDataSource( ACCESS_COARSE_LOCATION, currentAttribution, "Bluetooth location check") == PERMISSION_GRANTED) { return true; } Log.e(TAG, "Permission denial: Need ACCESS_COARSE_LOCATION " Log.e( TAG, "Permission denial: Need ACCESS_COARSE_LOCATION " + "permission to get scan results"); return false; } Loading Loading @@ -945,12 +967,15 @@ public final class Utils { return true; } if (pm.checkPermissionForDataDeliveryFromDataSource(ACCESS_COARSE_LOCATION, currentAttribution, "Bluetooth location check") == PERMISSION_GRANTED) { if (pm.checkPermissionForDataDeliveryFromDataSource( ACCESS_COARSE_LOCATION, currentAttribution, "Bluetooth location check") == PERMISSION_GRANTED) { return true; } Log.e(TAG, "Permission denial: Need ACCESS_COARSE_LOCATION or ACCESS_FINE_LOCATION" Log.e( TAG, "Permission denial: Need ACCESS_COARSE_LOCATION or ACCESS_FINE_LOCATION" + "permission to get scan results"); return false; } Loading Loading @@ -981,32 +1006,27 @@ public final class Utils { return true; } Log.e(TAG, "Permission denial: Need ACCESS_FINE_LOCATION " + "permission to get scan results"); Log.e( TAG, "Permission denial: Need ACCESS_FINE_LOCATION " + "permission to get scan results"); return false; } /** * Returns true if the caller holds NETWORK_SETTINGS */ /** Returns true if the caller holds NETWORK_SETTINGS */ // Suppressed since we're not actually enforcing here @SuppressLint("AndroidFrameworkRequiresPermission") public static boolean checkCallerHasNetworkSettingsPermission(Context context) { return context.checkCallingOrSelfPermission(NETWORK_SETTINGS) == PERMISSION_GRANTED; } /** * Returns true if the caller holds NETWORK_SETUP_WIZARD */ /** Returns true if the caller holds NETWORK_SETUP_WIZARD */ // Suppressed since we're not actually enforcing here @SuppressLint("AndroidFrameworkRequiresPermission") public static boolean checkCallerHasNetworkSetupWizardPermission(Context context) { return context.checkCallingOrSelfPermission(NETWORK_SETUP_WIZARD) == PERMISSION_GRANTED; } /** * Returns true if the caller holds RADIO_SCAN_WITHOUT_LOCATION */ /** Returns true if the caller holds RADIO_SCAN_WITHOUT_LOCATION */ // Suppressed since we're not actually enforcing here @SuppressLint("AndroidFrameworkRequiresPermission") public static boolean checkCallerHasScanWithoutLocationPermission(Context context) { Loading Loading @@ -1050,9 +1070,7 @@ public final class Utils { return true; } /** * Converts {@code milliseconds} to unit. Each unit is 0.625 millisecond. */ /** Converts {@code milliseconds} to unit. Each unit is 0.625 millisecond. */ public static int millsToUnit(int milliseconds) { return (int) (TimeUnit.MILLISECONDS.toMicros(milliseconds) / MICROS_PER_UNIT); } Loading @@ -1063,8 +1081,8 @@ public final class Utils { /** * Check if we are running in BluetoothInstrumentationTest context by trying to load * com.android.bluetooth.FileSystemWriteTest. If we are not in Instrumentation test mode, this * class should not be found. Thus, the assumption is that FileSystemWriteTest must exist. * If FileSystemWriteTest is removed in the future, another test class in * class should not be found. Thus, the assumption is that FileSystemWriteTest must exist. If * FileSystemWriteTest is removed in the future, another test class in * BluetoothInstrumentationTest should be used instead * * @return true if in BluetoothInstrumentationTest, false otherwise Loading Loading @@ -1093,8 +1111,8 @@ public final class Utils { } /** * Check if we are running in PTS test mode. To enable/disable PTS test mode, invoke * {@code adb shell setprop persist.bluetooth.pts true/false} * Check if we are running in PTS test mode. To enable/disable PTS test mode, invoke {@code adb * shell setprop persist.bluetooth.pts true/false} * * @return true if in PTS Test mode, false otherwise */ Loading @@ -1118,7 +1136,8 @@ public final class Utils { */ public static String getLocalTimeString() { return DateTimeFormatter.ofPattern("MM-dd HH:mm:ss.SSS") .withZone(ZoneId.systemDefault()).format(Instant.now()); .withZone(ZoneId.systemDefault()) .format(Instant.now()); } public static void skipCurrentTag(XmlPullParser parser) Loading @@ -1126,15 +1145,12 @@ public final class Utils { int outerDepth = parser.getDepth(); int type; while ((type = parser.next()) != XmlPullParser.END_DOCUMENT && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) { } && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {} } /** * Converts pause and tonewait pause characters * to Android representation. * RFC 3601 says pause is 'p' and tonewait is 'w'. * Converts pause and tonewait pause characters to Android representation. RFC 3601 says pause * is 'p' and tonewait is 'w'. */ public static String convertPreDial(String phoneNumber) { if (phoneNumber == null) { Loading Loading @@ -1179,23 +1195,28 @@ public final class Utils { } values.put(Telephony.Sms.ERROR_CODE, 0); return 1 == BluetoothMethodProxy.getInstance().contentResolverUpdate( return 1 == BluetoothMethodProxy.getInstance() .contentResolverUpdate( context.getContentResolver(), uri, values, null, null); } /** * Returns broadcast options. */ /** Returns broadcast options. */ public static @NonNull BroadcastOptions getTempBroadcastOptions() { final BroadcastOptions bOptions = BroadcastOptions.makeBasic(); // Use the Bluetooth process identity to pass permission check when reading DeviceConfig final long ident = Binder.clearCallingIdentity(); try { final long durationMs = DeviceConfig.getLong(DeviceConfig.NAMESPACE_BLUETOOTH, KEY_TEMP_ALLOW_LIST_DURATION_MS, DEFAULT_TEMP_ALLOW_LIST_DURATION_MS); bOptions.setTemporaryAppAllowlist(durationMs, final long durationMs = DeviceConfig.getLong( DeviceConfig.NAMESPACE_BLUETOOTH, KEY_TEMP_ALLOW_LIST_DURATION_MS, DEFAULT_TEMP_ALLOW_LIST_DURATION_MS); bOptions.setTemporaryAppAllowlist( durationMs, TEMPORARY_ALLOW_LIST_TYPE_FOREGROUND_SERVICE_ALLOWED, PowerExemptionManager.REASON_BLUETOOTH_BROADCAST, ""); PowerExemptionManager.REASON_BLUETOOTH_BROADCAST, ""); } finally { Binder.restoreCallingIdentity(ident); } Loading @@ -1204,6 +1225,7 @@ public final class Utils { /** * Checks that value is present as at least one of the elements of the array. * * @param array the array to check in * @param value the value to check for * @return true if the value is present in the array Loading @@ -1218,6 +1240,7 @@ public final class Utils { /** * CCC descriptor short integer value to string. * * @param cccValue the short value of CCC descriptor * @return String value representing CCC state */ Loading @@ -1240,6 +1263,7 @@ public final class Utils { /** * Check if BLE is supported by this platform * * @param context current device context * @return true if BLE is supported, false otherwise */ Loading @@ -1249,6 +1273,7 @@ public final class Utils { /** * Check if this is an automotive device * * @param context current device context * @return true if this Android device is an automotive device, false otherwise */ Loading @@ -1258,6 +1283,7 @@ public final class Utils { /** * Check if this is a watch device * * @param context current device context * @return true if this Android device is a watch device, false otherwise */ Loading @@ -1267,6 +1293,7 @@ public final class Utils { /** * Check if this is a TV device * * @param context current device context * @return true if this Android device is a TV device, false otherwise */ Loading
android/app/src/com/android/bluetooth/bass_client/BassClientService.java +4 −8 Original line number Diff line number Diff line Loading @@ -100,6 +100,7 @@ import java.util.Optional; import java.util.PriorityQueue; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; import java.util.stream.Collectors; /** Broadcast Assistant Scan Service */ public class BassClientService extends ProfileService { Loading Loading @@ -3059,14 +3060,9 @@ public class BassClientService extends ProfileService { log("stateMachine is null"); return Collections.emptyList(); } List<BluetoothLeBroadcastReceiveState> recvStates = new ArrayList<BluetoothLeBroadcastReceiveState>(); for (BluetoothLeBroadcastReceiveState rs : stateMachine.getAllSources()) { if (!isEmptyBluetoothDevice(rs.getSourceDevice())) { recvStates.add(rs); } } return recvStates; return stateMachine.getAllSources().stream() .filter(rs -> !isEmptyBluetoothDevice(rs.getSourceDevice())) .collect(Collectors.toList()); } } Loading
android/app/src/com/android/bluetooth/btservice/MetricsLogger.java +3 −2 Original line number Diff line number Diff line Loading @@ -28,7 +28,6 @@ import android.util.proto.ProtoOutputStream; import androidx.annotation.RequiresApi; import com.android.bluetooth.bass_client.BassConstants; import com.android.bluetooth.BluetoothMetricsProto.BluetoothLog; import com.android.bluetooth.BluetoothMetricsProto.BluetoothRemoteDeviceInformation; import com.android.bluetooth.BluetoothMetricsProto.ProfileConnectionStats; Loading @@ -36,6 +35,7 @@ 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.modules.utils.build.SdkLevel; import com.google.common.annotations.VisibleForTesting; Loading Loading @@ -411,7 +411,8 @@ public class MetricsLogger { } } return wordBreakdownList; // Prevent returning a mutable list return Collections.unmodifiableList(wordBreakdownList); } @RequiresApi(Build.VERSION_CODES.UPSIDE_DOWN_CAKE) Loading