Loading src/com/android/settings/connecteddevice/audiosharing/AudioSharingDialogHandler.java +54 −40 Original line number Diff line number Diff line Loading @@ -164,7 +164,8 @@ public class AudioSharingDialogHandler { : null; mAudioManager = context.getSystemService(AudioManager.class); mMetricsFeatureProvider = FeatureFactory.getFeatureFactory().getMetricsFeatureProvider(); mHostMetricsCategory = mHostFragment instanceof DashboardFragment mHostMetricsCategory = mHostFragment instanceof DashboardFragment ? ((DashboardFragment) mHostFragment).getMetricsCategory() : SettingsEnums.PAGE_UNKNOWN; } Loading @@ -185,6 +186,7 @@ public class AudioSharingDialogHandler { /** * Handle dialog pop-up logic when device is connected. * * @param cachedDevice The target {@link CachedBluetoothDevice} to handle for * @param userTriggered If the device is connected by user * @return If a dialog is popped up Loading Loading @@ -236,8 +238,10 @@ public class AudioSharingDialogHandler { mLocalBtManager, groupedDevices, /* filterByInSharing= */ true); AudioSharingStopDialogFragment.DialogEventListener listener = () -> { if (mLocalBtManager != null && (Flags.adoptPrimaryGroupManagementApi() || ( mContext != null && Flags.audioSharingDeveloperOption() if (mLocalBtManager != null && (Flags.adoptPrimaryGroupManagementApi() || (mContext != null && Flags.audioSharingDeveloperOption() && BluetoothUtils.getAudioSharingPreviewValue( mContext.getContentResolver())))) { LeAudioProfile profile = Loading @@ -260,11 +264,7 @@ public class AudioSharingDialogHandler { /* candidateDeviceCount= */ 0); closeOpeningDialogsOtherThan(AudioSharingStopDialogFragment.tag()); return AudioSharingStopDialogFragment.show( mHostFragment, deviceItemsInSharingSession, cachedDevice, listener, eventData); mHostFragment, deviceItemsInSharingSession, cachedDevice, listener, eventData); } else { if (userTriggered) { cachedDevice.setActive(); Loading Loading @@ -298,7 +298,8 @@ public class AudioSharingDialogHandler { device, mLocalBtManager))) { Log.d(TAG, "Auto add sink with the same group to the sharing: " + deviceAddress); if (mAssistant != null && mBroadcast != null) { mMetricsFeatureProvider.action(mContext, mMetricsFeatureProvider.action( mContext, SettingsEnums.ACTION_AUDIO_SHARING_ADD_SOURCE, AudioSharingUtils.buildAddSourceEventData( mHostMetricsCategory, /* userTriggered= */ false)); Loading @@ -323,7 +324,9 @@ public class AudioSharingDialogHandler { // Remove all sources from the device user clicked removeSourceForGroup(item.getGroupId(), groupedDevices); // Add current broadcast to the latest connected device addSourceForGroup(groupId, groupedDevices, addSourceForGroup( groupId, groupedDevices, AudioSharingUtils.buildAddSourceEventData( SettingsEnums.DIALOG_AUDIO_SHARING_SWITCH_DEVICE, userTriggered)); Loading @@ -335,8 +338,7 @@ public class AudioSharingDialogHandler { userTriggered, deviceItemsInSharingSession.size(), /* candidateDeviceCount= */ 1); closeOpeningDialogsOtherThan( AudioSharingDisconnectDialogFragment.tag()); closeOpeningDialogsOtherThan(AudioSharingDisconnectDialogFragment.tag()); Log.d(TAG, "Show disconnect dialog, device = " + deviceAddress); return AudioSharingDisconnectDialogFragment.show( mHostFragment, Loading @@ -351,7 +353,9 @@ public class AudioSharingDialogHandler { new AudioSharingJoinDialogFragment.DialogEventListener() { @Override public void onShareClick() { addSourceForGroup(groupId, groupedDevices, addSourceForGroup( groupId, groupedDevices, AudioSharingUtils.buildAddSourceEventData( SettingsEnums.DIALOG_AUDIO_SHARING_ADD_DEVICE, userTriggered)); Loading Loading @@ -448,7 +452,11 @@ public class AudioSharingDialogHandler { try { fragments = mHostFragment.getChildFragmentManager().getFragments(); } catch (IllegalStateException e) { Log.d(TAG, "Fail to closeOpeningDialogsOtherThan " + tag + ": " Log.d( TAG, "Fail to closeOpeningDialogsOtherThan " + tag + ": " + e.getMessage()); return; } Loading Loading @@ -507,8 +515,9 @@ public class AudioSharingDialogHandler { } for (Fragment fragment : fragments) { CachedBluetoothDevice device = getCachedBluetoothDeviceFromDialog(fragment); if (device != null && address != null && address.equals( device.getAddress())) { if (device != null && address != null && address.equals(device.getAddress())) { Log.d( TAG, "Remove staled opening dialog for device " Loading Loading @@ -544,26 +553,31 @@ public class AudioSharingDialogHandler { return; } List<BluetoothDevice> devices = groupedDevices.get(groupId); devices.stream().forEach( devices.stream() .forEach( device -> { for (BluetoothLeBroadcastReceiveState source : mAssistant.getAllSources(device)) { mAssistant.removeSource(device, source.getSourceId()); } }); boolean isPrimary = groupId == BluetoothUtils.getPrimaryGroupIdForBroadcast( boolean isPrimary = groupId == BluetoothUtils.getPrimaryGroupIdForBroadcast( mContext.getContentResolver(), mLocalBtManager); boolean isTempBond = devices.stream().anyMatch(BluetoothUtils::isTemporaryBondDevice); Pair<Integer, Object>[] eventData = new Pair[]{ Pair<Integer, Object>[] eventData = new Pair[] { Pair.create(METRIC_KEY_DEVICE_IS_PRIMARY.getId(), isPrimary ? 1 : 0), Pair.create(METRIC_KEY_DEVICE_IS_TEMP_BOND.getId(), isTempBond ? 1 : 0) }; mMetricsFeatureProvider.action(mContext, SettingsEnums.ACTION_AUDIO_SHARING_REMOVE_SOURCE, eventData); mMetricsFeatureProvider.action( mContext, SettingsEnums.ACTION_AUDIO_SHARING_REMOVE_SOURCE, eventData); } private void addSourceForGroup( int groupId, Map<Integer, List<BluetoothDevice>> groupedDevices, int groupId, Map<Integer, List<BluetoothDevice>> groupedDevices, Pair<Integer, Object>[] eventData) { if (mBroadcast == null || mAssistant == null) { Log.d(TAG, "Fail to add source due to null profiles, group = " + groupId); Loading @@ -580,8 +594,8 @@ public class AudioSharingDialogHandler { device, mBroadcast.getLatestBluetoothLeBroadcastMetadata(), /* isGroupOp= */ false)); mMetricsFeatureProvider.action(mContext, SettingsEnums.ACTION_AUDIO_SHARING_ADD_SOURCE, eventData); mMetricsFeatureProvider.action( mContext, SettingsEnums.ACTION_AUDIO_SHARING_ADD_SOURCE, eventData); } private boolean isBroadcasting() { Loading src/com/android/settings/connecteddevice/audiosharing/AudioSharingReceiver.java +60 −48 Original line number Diff line number Diff line Loading @@ -102,7 +102,8 @@ public class AudioSharingReceiver extends BroadcastReceiver { cancelSharingNotification(context, AUDIO_SHARING_NOTIFICATION_ID); cancelSharingNotification(context, ADD_SOURCE_NOTIFICATION_ID); metricsFeatureProvider.action( context, SettingsEnums.ACTION_CANCEL_AUDIO_SHARING_NOTIFICATION, context, SettingsEnums.ACTION_CANCEL_AUDIO_SHARING_NOTIFICATION, LocalBluetoothLeBroadcast.ACTION_LE_AUDIO_SHARING_STATE_CHANGE); } else { Log.w( Loading @@ -127,7 +128,8 @@ public class AudioSharingReceiver extends BroadcastReceiver { // or FEATURE_NOT_SUPPORTED when BT and BLE off cancelSharingNotification(context, AUDIO_SHARING_NOTIFICATION_ID); metricsFeatureProvider.action( context, SettingsEnums.ACTION_CANCEL_AUDIO_SHARING_NOTIFICATION, context, SettingsEnums.ACTION_CANCEL_AUDIO_SHARING_NOTIFICATION, ACTION_LE_AUDIO_SHARING_STOP); cancelSharingNotification(context, ADD_SOURCE_NOTIFICATION_ID); break; Loading @@ -137,8 +139,8 @@ public class AudioSharingReceiver extends BroadcastReceiver { Log.d(TAG, "Skip ACTION_LE_AUDIO_SHARING_DEVICE_CONNECTED, flag/feature off"); return; } BluetoothDevice device = intent.getParcelableExtra(EXTRA_BLUETOOTH_DEVICE, BluetoothDevice.class); BluetoothDevice device = intent.getParcelableExtra(EXTRA_BLUETOOTH_DEVICE, BluetoothDevice.class); if (device == null) { Log.d(TAG, "Skip ACTION_LE_AUDIO_SHARING_DEVICE_CONNECTED, null device"); return; Loading Loading @@ -167,14 +169,15 @@ public class AudioSharingReceiver extends BroadcastReceiver { cancelSharingNotification(context, ADD_SOURCE_NOTIFICATION_ID); return; } BluetoothDevice sink = intent.getParcelableExtra(EXTRA_BLUETOOTH_DEVICE, BluetoothDevice.class); BluetoothDevice sink = intent.getParcelableExtra(EXTRA_BLUETOOTH_DEVICE, BluetoothDevice.class); LocalBluetoothManager manager = Utils.getLocalBtManager(context); ImmutableList<BluetoothDevice> sinksToAdd = validToAddSource(sink, action, manager); AudioSharingUtils.addSourceToTargetSinks(sinksToAdd, manager); cancelSharingNotification(context, ADD_SOURCE_NOTIFICATION_ID); if (!sinksToAdd.isEmpty()) { metricsFeatureProvider.action(context, metricsFeatureProvider.action( context, SettingsEnums.ACTION_AUDIO_SHARING_ADD_SOURCE, AudioSharingUtils.buildAddSourceEventData( SettingsEnums.ACTION_SHOW_ADD_SOURCE_NOTIFICATION, Loading @@ -196,8 +199,10 @@ public class AudioSharingReceiver extends BroadcastReceiver { } } private ImmutableList<BluetoothDevice> validToAddSource(@Nullable BluetoothDevice sink, @NonNull String action, @Nullable LocalBluetoothManager btManager) { private ImmutableList<BluetoothDevice> validToAddSource( @Nullable BluetoothDevice sink, @NonNull String action, @Nullable LocalBluetoothManager btManager) { if (sink == null) { Log.d(TAG, "Skip " + action + ", null device"); return ImmutableList.of(); Loading @@ -209,17 +214,23 @@ public class AudioSharingReceiver extends BroadcastReceiver { } Map<Integer, List<BluetoothDevice>> groupedDevices = AudioSharingUtils.fetchConnectedDevicesByGroupId(btManager); int groupId = groupedDevices.entrySet().stream().filter( entry -> entry.getValue().contains(sink)).findFirst().map( Map.Entry::getKey).orElse(BluetoothCsipSetCoordinator.GROUP_ID_INVALID); int groupId = groupedDevices.entrySet().stream() .filter(entry -> entry.getValue().contains(sink)) .findFirst() .map(Map.Entry::getKey) .orElse(BluetoothCsipSetCoordinator.GROUP_ID_INVALID); if (groupId == BluetoothCsipSetCoordinator.GROUP_ID_INVALID) { Log.d(TAG, "Skip " + action + ", no valid group id"); return ImmutableList.of(); } List<BluetoothDevice> sinksToAdd = groupedDevices.getOrDefault(groupId, ImmutableList.of()).stream().filter( d -> !BluetoothUtils.hasConnectedBroadcastSourceForBtDevice(d, btManager)).toList(); List<BluetoothDevice> sinksToAdd = groupedDevices.getOrDefault(groupId, ImmutableList.of()).stream() .filter( d -> !BluetoothUtils.hasConnectedBroadcastSourceForBtDevice( d, btManager)) .toList(); if (sinksToAdd.isEmpty()) { Log.d(TAG, "Skip " + action + ", already has source"); return ImmutableList.of(); Loading Loading @@ -294,13 +305,14 @@ public class AudioSharingReceiver extends BroadcastReceiver { nm.notify(AUDIO_SHARING_NOTIFICATION_ID, builder.build()); } private void showAddSourceNotification(@NonNull Context context, @NonNull BluetoothDevice device) { private void showAddSourceNotification( @NonNull Context context, @NonNull BluetoothDevice device) { NotificationManager nm = context.getSystemService(NotificationManager.class); if (nm == null) return; createNotificationChannelIfNeeded(nm, context); Intent addSourceIntent = new Intent(ACTION_LE_AUDIO_SHARING_ADD_SOURCE).setPackage(context.getPackageName()) new Intent(ACTION_LE_AUDIO_SHARING_ADD_SOURCE) .setPackage(context.getPackageName()) .putExtra(EXTRA_BLUETOOTH_DEVICE, device); // Use PendingIntent.FLAG_UPDATE_CURRENT here because intent extra (device) could be updated PendingIntent addSourcePendingIntent = Loading @@ -308,7 +320,8 @@ public class AudioSharingReceiver extends BroadcastReceiver { context, R.string.audio_sharing_share_button_label, addSourceIntent, PendingIntent.FLAG_ONE_SHOT | PendingIntent.FLAG_UPDATE_CURRENT PendingIntent.FLAG_ONE_SHOT | PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE); NotificationCompat.Action addSourceAction = new NotificationCompat.Action.Builder( Loading @@ -316,20 +329,16 @@ public class AudioSharingReceiver extends BroadcastReceiver { context.getString(R.string.audio_sharing_share_button_label), addSourcePendingIntent) .build(); Intent cancelIntent = new Intent(ACTION_LE_AUDIO_SHARING_CANCEL_NOTIF).setPackage( context.getPackageName()) Intent cancelIntent = new Intent(ACTION_LE_AUDIO_SHARING_CANCEL_NOTIF) .setPackage(context.getPackageName()) .putExtra(EXTRA_NOTIF_ID, ADD_SOURCE_NOTIFICATION_ID); PendingIntent cancelPendingIntent = PendingIntent.getBroadcast( context, R.string.cancel, cancelIntent, PendingIntent.FLAG_IMMUTABLE); context, R.string.cancel, cancelIntent, PendingIntent.FLAG_IMMUTABLE); NotificationCompat.Action cancelAction = new NotificationCompat.Action.Builder( 0, context.getString(R.string.cancel), cancelPendingIntent) 0, context.getString(R.string.cancel), cancelPendingIntent) .build(); final Bundle extras = new Bundle(); extras.putString( Loading @@ -343,8 +352,9 @@ public class AudioSharingReceiver extends BroadcastReceiver { new NotificationCompat.Builder(context, CHANNEL_ID) .setSmallIcon(com.android.settingslib.R.drawable.ic_bt_le_audio_sharing) .setLocalOnly(true) .setContentTitle(context.getString(R.string.share_audio_notification_title, deviceName)) .setContentTitle( context.getString( R.string.share_audio_notification_title, deviceName)) .setContentText( context.getString(R.string.audio_sharing_notification_content)) .setOngoing(true) Loading @@ -367,8 +377,8 @@ public class AudioSharingReceiver extends BroadcastReceiver { } } private void createNotificationChannelIfNeeded(@NonNull NotificationManager nm, @NonNull Context context) { private void createNotificationChannelIfNeeded( @NonNull NotificationManager nm, @NonNull Context context) { if (nm.getNotificationChannel(CHANNEL_ID) == null) { Log.d(TAG, "Create bluetooth notification channel"); NotificationChannel notificationChannel = Loading @@ -384,12 +394,14 @@ public class AudioSharingReceiver extends BroadcastReceiver { try { ActivityManager activityManager = context.getSystemService(ActivityManager.class); String packageName = context.getPackageName(); if (context.getPackageManager().checkPermission(Manifest.permission.PACKAGE_USAGE_STATS, packageName) != PackageManager.PERMISSION_GRANTED) { if (context.getPackageManager() .checkPermission(Manifest.permission.PACKAGE_USAGE_STATS, packageName) != PackageManager.PERMISSION_GRANTED) { Log.d(TAG, "check isAppInForeground, returns false due to no permission"); return false; } if (packageName != null && activityManager.getPackageImportance(packageName) if (packageName != null && activityManager.getPackageImportance(packageName) == ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND) { Log.d(TAG, "check isAppInForeground, returns true"); return true; Loading Loading
src/com/android/settings/connecteddevice/audiosharing/AudioSharingDialogHandler.java +54 −40 Original line number Diff line number Diff line Loading @@ -164,7 +164,8 @@ public class AudioSharingDialogHandler { : null; mAudioManager = context.getSystemService(AudioManager.class); mMetricsFeatureProvider = FeatureFactory.getFeatureFactory().getMetricsFeatureProvider(); mHostMetricsCategory = mHostFragment instanceof DashboardFragment mHostMetricsCategory = mHostFragment instanceof DashboardFragment ? ((DashboardFragment) mHostFragment).getMetricsCategory() : SettingsEnums.PAGE_UNKNOWN; } Loading @@ -185,6 +186,7 @@ public class AudioSharingDialogHandler { /** * Handle dialog pop-up logic when device is connected. * * @param cachedDevice The target {@link CachedBluetoothDevice} to handle for * @param userTriggered If the device is connected by user * @return If a dialog is popped up Loading Loading @@ -236,8 +238,10 @@ public class AudioSharingDialogHandler { mLocalBtManager, groupedDevices, /* filterByInSharing= */ true); AudioSharingStopDialogFragment.DialogEventListener listener = () -> { if (mLocalBtManager != null && (Flags.adoptPrimaryGroupManagementApi() || ( mContext != null && Flags.audioSharingDeveloperOption() if (mLocalBtManager != null && (Flags.adoptPrimaryGroupManagementApi() || (mContext != null && Flags.audioSharingDeveloperOption() && BluetoothUtils.getAudioSharingPreviewValue( mContext.getContentResolver())))) { LeAudioProfile profile = Loading @@ -260,11 +264,7 @@ public class AudioSharingDialogHandler { /* candidateDeviceCount= */ 0); closeOpeningDialogsOtherThan(AudioSharingStopDialogFragment.tag()); return AudioSharingStopDialogFragment.show( mHostFragment, deviceItemsInSharingSession, cachedDevice, listener, eventData); mHostFragment, deviceItemsInSharingSession, cachedDevice, listener, eventData); } else { if (userTriggered) { cachedDevice.setActive(); Loading Loading @@ -298,7 +298,8 @@ public class AudioSharingDialogHandler { device, mLocalBtManager))) { Log.d(TAG, "Auto add sink with the same group to the sharing: " + deviceAddress); if (mAssistant != null && mBroadcast != null) { mMetricsFeatureProvider.action(mContext, mMetricsFeatureProvider.action( mContext, SettingsEnums.ACTION_AUDIO_SHARING_ADD_SOURCE, AudioSharingUtils.buildAddSourceEventData( mHostMetricsCategory, /* userTriggered= */ false)); Loading @@ -323,7 +324,9 @@ public class AudioSharingDialogHandler { // Remove all sources from the device user clicked removeSourceForGroup(item.getGroupId(), groupedDevices); // Add current broadcast to the latest connected device addSourceForGroup(groupId, groupedDevices, addSourceForGroup( groupId, groupedDevices, AudioSharingUtils.buildAddSourceEventData( SettingsEnums.DIALOG_AUDIO_SHARING_SWITCH_DEVICE, userTriggered)); Loading @@ -335,8 +338,7 @@ public class AudioSharingDialogHandler { userTriggered, deviceItemsInSharingSession.size(), /* candidateDeviceCount= */ 1); closeOpeningDialogsOtherThan( AudioSharingDisconnectDialogFragment.tag()); closeOpeningDialogsOtherThan(AudioSharingDisconnectDialogFragment.tag()); Log.d(TAG, "Show disconnect dialog, device = " + deviceAddress); return AudioSharingDisconnectDialogFragment.show( mHostFragment, Loading @@ -351,7 +353,9 @@ public class AudioSharingDialogHandler { new AudioSharingJoinDialogFragment.DialogEventListener() { @Override public void onShareClick() { addSourceForGroup(groupId, groupedDevices, addSourceForGroup( groupId, groupedDevices, AudioSharingUtils.buildAddSourceEventData( SettingsEnums.DIALOG_AUDIO_SHARING_ADD_DEVICE, userTriggered)); Loading Loading @@ -448,7 +452,11 @@ public class AudioSharingDialogHandler { try { fragments = mHostFragment.getChildFragmentManager().getFragments(); } catch (IllegalStateException e) { Log.d(TAG, "Fail to closeOpeningDialogsOtherThan " + tag + ": " Log.d( TAG, "Fail to closeOpeningDialogsOtherThan " + tag + ": " + e.getMessage()); return; } Loading Loading @@ -507,8 +515,9 @@ public class AudioSharingDialogHandler { } for (Fragment fragment : fragments) { CachedBluetoothDevice device = getCachedBluetoothDeviceFromDialog(fragment); if (device != null && address != null && address.equals( device.getAddress())) { if (device != null && address != null && address.equals(device.getAddress())) { Log.d( TAG, "Remove staled opening dialog for device " Loading Loading @@ -544,26 +553,31 @@ public class AudioSharingDialogHandler { return; } List<BluetoothDevice> devices = groupedDevices.get(groupId); devices.stream().forEach( devices.stream() .forEach( device -> { for (BluetoothLeBroadcastReceiveState source : mAssistant.getAllSources(device)) { mAssistant.removeSource(device, source.getSourceId()); } }); boolean isPrimary = groupId == BluetoothUtils.getPrimaryGroupIdForBroadcast( boolean isPrimary = groupId == BluetoothUtils.getPrimaryGroupIdForBroadcast( mContext.getContentResolver(), mLocalBtManager); boolean isTempBond = devices.stream().anyMatch(BluetoothUtils::isTemporaryBondDevice); Pair<Integer, Object>[] eventData = new Pair[]{ Pair<Integer, Object>[] eventData = new Pair[] { Pair.create(METRIC_KEY_DEVICE_IS_PRIMARY.getId(), isPrimary ? 1 : 0), Pair.create(METRIC_KEY_DEVICE_IS_TEMP_BOND.getId(), isTempBond ? 1 : 0) }; mMetricsFeatureProvider.action(mContext, SettingsEnums.ACTION_AUDIO_SHARING_REMOVE_SOURCE, eventData); mMetricsFeatureProvider.action( mContext, SettingsEnums.ACTION_AUDIO_SHARING_REMOVE_SOURCE, eventData); } private void addSourceForGroup( int groupId, Map<Integer, List<BluetoothDevice>> groupedDevices, int groupId, Map<Integer, List<BluetoothDevice>> groupedDevices, Pair<Integer, Object>[] eventData) { if (mBroadcast == null || mAssistant == null) { Log.d(TAG, "Fail to add source due to null profiles, group = " + groupId); Loading @@ -580,8 +594,8 @@ public class AudioSharingDialogHandler { device, mBroadcast.getLatestBluetoothLeBroadcastMetadata(), /* isGroupOp= */ false)); mMetricsFeatureProvider.action(mContext, SettingsEnums.ACTION_AUDIO_SHARING_ADD_SOURCE, eventData); mMetricsFeatureProvider.action( mContext, SettingsEnums.ACTION_AUDIO_SHARING_ADD_SOURCE, eventData); } private boolean isBroadcasting() { Loading
src/com/android/settings/connecteddevice/audiosharing/AudioSharingReceiver.java +60 −48 Original line number Diff line number Diff line Loading @@ -102,7 +102,8 @@ public class AudioSharingReceiver extends BroadcastReceiver { cancelSharingNotification(context, AUDIO_SHARING_NOTIFICATION_ID); cancelSharingNotification(context, ADD_SOURCE_NOTIFICATION_ID); metricsFeatureProvider.action( context, SettingsEnums.ACTION_CANCEL_AUDIO_SHARING_NOTIFICATION, context, SettingsEnums.ACTION_CANCEL_AUDIO_SHARING_NOTIFICATION, LocalBluetoothLeBroadcast.ACTION_LE_AUDIO_SHARING_STATE_CHANGE); } else { Log.w( Loading @@ -127,7 +128,8 @@ public class AudioSharingReceiver extends BroadcastReceiver { // or FEATURE_NOT_SUPPORTED when BT and BLE off cancelSharingNotification(context, AUDIO_SHARING_NOTIFICATION_ID); metricsFeatureProvider.action( context, SettingsEnums.ACTION_CANCEL_AUDIO_SHARING_NOTIFICATION, context, SettingsEnums.ACTION_CANCEL_AUDIO_SHARING_NOTIFICATION, ACTION_LE_AUDIO_SHARING_STOP); cancelSharingNotification(context, ADD_SOURCE_NOTIFICATION_ID); break; Loading @@ -137,8 +139,8 @@ public class AudioSharingReceiver extends BroadcastReceiver { Log.d(TAG, "Skip ACTION_LE_AUDIO_SHARING_DEVICE_CONNECTED, flag/feature off"); return; } BluetoothDevice device = intent.getParcelableExtra(EXTRA_BLUETOOTH_DEVICE, BluetoothDevice.class); BluetoothDevice device = intent.getParcelableExtra(EXTRA_BLUETOOTH_DEVICE, BluetoothDevice.class); if (device == null) { Log.d(TAG, "Skip ACTION_LE_AUDIO_SHARING_DEVICE_CONNECTED, null device"); return; Loading Loading @@ -167,14 +169,15 @@ public class AudioSharingReceiver extends BroadcastReceiver { cancelSharingNotification(context, ADD_SOURCE_NOTIFICATION_ID); return; } BluetoothDevice sink = intent.getParcelableExtra(EXTRA_BLUETOOTH_DEVICE, BluetoothDevice.class); BluetoothDevice sink = intent.getParcelableExtra(EXTRA_BLUETOOTH_DEVICE, BluetoothDevice.class); LocalBluetoothManager manager = Utils.getLocalBtManager(context); ImmutableList<BluetoothDevice> sinksToAdd = validToAddSource(sink, action, manager); AudioSharingUtils.addSourceToTargetSinks(sinksToAdd, manager); cancelSharingNotification(context, ADD_SOURCE_NOTIFICATION_ID); if (!sinksToAdd.isEmpty()) { metricsFeatureProvider.action(context, metricsFeatureProvider.action( context, SettingsEnums.ACTION_AUDIO_SHARING_ADD_SOURCE, AudioSharingUtils.buildAddSourceEventData( SettingsEnums.ACTION_SHOW_ADD_SOURCE_NOTIFICATION, Loading @@ -196,8 +199,10 @@ public class AudioSharingReceiver extends BroadcastReceiver { } } private ImmutableList<BluetoothDevice> validToAddSource(@Nullable BluetoothDevice sink, @NonNull String action, @Nullable LocalBluetoothManager btManager) { private ImmutableList<BluetoothDevice> validToAddSource( @Nullable BluetoothDevice sink, @NonNull String action, @Nullable LocalBluetoothManager btManager) { if (sink == null) { Log.d(TAG, "Skip " + action + ", null device"); return ImmutableList.of(); Loading @@ -209,17 +214,23 @@ public class AudioSharingReceiver extends BroadcastReceiver { } Map<Integer, List<BluetoothDevice>> groupedDevices = AudioSharingUtils.fetchConnectedDevicesByGroupId(btManager); int groupId = groupedDevices.entrySet().stream().filter( entry -> entry.getValue().contains(sink)).findFirst().map( Map.Entry::getKey).orElse(BluetoothCsipSetCoordinator.GROUP_ID_INVALID); int groupId = groupedDevices.entrySet().stream() .filter(entry -> entry.getValue().contains(sink)) .findFirst() .map(Map.Entry::getKey) .orElse(BluetoothCsipSetCoordinator.GROUP_ID_INVALID); if (groupId == BluetoothCsipSetCoordinator.GROUP_ID_INVALID) { Log.d(TAG, "Skip " + action + ", no valid group id"); return ImmutableList.of(); } List<BluetoothDevice> sinksToAdd = groupedDevices.getOrDefault(groupId, ImmutableList.of()).stream().filter( d -> !BluetoothUtils.hasConnectedBroadcastSourceForBtDevice(d, btManager)).toList(); List<BluetoothDevice> sinksToAdd = groupedDevices.getOrDefault(groupId, ImmutableList.of()).stream() .filter( d -> !BluetoothUtils.hasConnectedBroadcastSourceForBtDevice( d, btManager)) .toList(); if (sinksToAdd.isEmpty()) { Log.d(TAG, "Skip " + action + ", already has source"); return ImmutableList.of(); Loading Loading @@ -294,13 +305,14 @@ public class AudioSharingReceiver extends BroadcastReceiver { nm.notify(AUDIO_SHARING_NOTIFICATION_ID, builder.build()); } private void showAddSourceNotification(@NonNull Context context, @NonNull BluetoothDevice device) { private void showAddSourceNotification( @NonNull Context context, @NonNull BluetoothDevice device) { NotificationManager nm = context.getSystemService(NotificationManager.class); if (nm == null) return; createNotificationChannelIfNeeded(nm, context); Intent addSourceIntent = new Intent(ACTION_LE_AUDIO_SHARING_ADD_SOURCE).setPackage(context.getPackageName()) new Intent(ACTION_LE_AUDIO_SHARING_ADD_SOURCE) .setPackage(context.getPackageName()) .putExtra(EXTRA_BLUETOOTH_DEVICE, device); // Use PendingIntent.FLAG_UPDATE_CURRENT here because intent extra (device) could be updated PendingIntent addSourcePendingIntent = Loading @@ -308,7 +320,8 @@ public class AudioSharingReceiver extends BroadcastReceiver { context, R.string.audio_sharing_share_button_label, addSourceIntent, PendingIntent.FLAG_ONE_SHOT | PendingIntent.FLAG_UPDATE_CURRENT PendingIntent.FLAG_ONE_SHOT | PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE); NotificationCompat.Action addSourceAction = new NotificationCompat.Action.Builder( Loading @@ -316,20 +329,16 @@ public class AudioSharingReceiver extends BroadcastReceiver { context.getString(R.string.audio_sharing_share_button_label), addSourcePendingIntent) .build(); Intent cancelIntent = new Intent(ACTION_LE_AUDIO_SHARING_CANCEL_NOTIF).setPackage( context.getPackageName()) Intent cancelIntent = new Intent(ACTION_LE_AUDIO_SHARING_CANCEL_NOTIF) .setPackage(context.getPackageName()) .putExtra(EXTRA_NOTIF_ID, ADD_SOURCE_NOTIFICATION_ID); PendingIntent cancelPendingIntent = PendingIntent.getBroadcast( context, R.string.cancel, cancelIntent, PendingIntent.FLAG_IMMUTABLE); context, R.string.cancel, cancelIntent, PendingIntent.FLAG_IMMUTABLE); NotificationCompat.Action cancelAction = new NotificationCompat.Action.Builder( 0, context.getString(R.string.cancel), cancelPendingIntent) 0, context.getString(R.string.cancel), cancelPendingIntent) .build(); final Bundle extras = new Bundle(); extras.putString( Loading @@ -343,8 +352,9 @@ public class AudioSharingReceiver extends BroadcastReceiver { new NotificationCompat.Builder(context, CHANNEL_ID) .setSmallIcon(com.android.settingslib.R.drawable.ic_bt_le_audio_sharing) .setLocalOnly(true) .setContentTitle(context.getString(R.string.share_audio_notification_title, deviceName)) .setContentTitle( context.getString( R.string.share_audio_notification_title, deviceName)) .setContentText( context.getString(R.string.audio_sharing_notification_content)) .setOngoing(true) Loading @@ -367,8 +377,8 @@ public class AudioSharingReceiver extends BroadcastReceiver { } } private void createNotificationChannelIfNeeded(@NonNull NotificationManager nm, @NonNull Context context) { private void createNotificationChannelIfNeeded( @NonNull NotificationManager nm, @NonNull Context context) { if (nm.getNotificationChannel(CHANNEL_ID) == null) { Log.d(TAG, "Create bluetooth notification channel"); NotificationChannel notificationChannel = Loading @@ -384,12 +394,14 @@ public class AudioSharingReceiver extends BroadcastReceiver { try { ActivityManager activityManager = context.getSystemService(ActivityManager.class); String packageName = context.getPackageName(); if (context.getPackageManager().checkPermission(Manifest.permission.PACKAGE_USAGE_STATS, packageName) != PackageManager.PERMISSION_GRANTED) { if (context.getPackageManager() .checkPermission(Manifest.permission.PACKAGE_USAGE_STATS, packageName) != PackageManager.PERMISSION_GRANTED) { Log.d(TAG, "check isAppInForeground, returns false due to no permission"); return false; } if (packageName != null && activityManager.getPackageImportance(packageName) if (packageName != null && activityManager.getPackageImportance(packageName) == ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND) { Log.d(TAG, "check isAppInForeground, returns true"); return true; Loading