1 /* 2 * Copyright (C) 2024 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.settings.connecteddevice.audiosharing; 18 19 import android.app.Notification; 20 import android.app.NotificationChannel; 21 import android.app.NotificationManager; 22 import android.app.PendingIntent; 23 import android.app.settings.SettingsEnums; 24 import android.content.BroadcastReceiver; 25 import android.content.Context; 26 import android.content.Intent; 27 import android.os.Bundle; 28 import android.util.Log; 29 30 import androidx.core.app.NotificationCompat; 31 32 import com.android.settings.R; 33 import com.android.settings.bluetooth.Utils; 34 import com.android.settings.overlay.FeatureFactory; 35 import com.android.settingslib.bluetooth.LocalBluetoothLeBroadcast; 36 import com.android.settingslib.bluetooth.LocalBluetoothManager; 37 import com.android.settingslib.core.instrumentation.MetricsFeatureProvider; 38 39 public class AudioSharingReceiver extends BroadcastReceiver { 40 private static final String TAG = "AudioSharingNotification"; 41 private static final String ACTION_LE_AUDIO_SHARING_SETTINGS = 42 "com.android.settings.BLUETOOTH_AUDIO_SHARING_SETTINGS"; 43 private static final String ACTION_LE_AUDIO_SHARING_STOP = 44 "com.android.settings.action.BLUETOOTH_LE_AUDIO_SHARING_STOP"; 45 private static final String CHANNEL_ID = "bluetooth_notification_channel"; 46 private static final int NOTIFICATION_ID = 47 com.android.settingslib.R.drawable.ic_bt_le_audio_sharing; 48 49 @Override onReceive(Context context, Intent intent)50 public void onReceive(Context context, Intent intent) { 51 if (!AudioSharingUtils.isFeatureEnabled()) { 52 Log.w(TAG, "Skip handling received intent, flag is off."); 53 return; 54 } 55 String action = intent.getAction(); 56 if (action == null) { 57 Log.w(TAG, "Received unexpected intent with null action."); 58 return; 59 } 60 MetricsFeatureProvider metricsFeatureProvider = 61 FeatureFactory.getFeatureFactory().getMetricsFeatureProvider(); 62 switch (action) { 63 case LocalBluetoothLeBroadcast.ACTION_LE_AUDIO_SHARING_STATE_CHANGE: 64 int state = 65 intent.getIntExtra( 66 LocalBluetoothLeBroadcast.EXTRA_LE_AUDIO_SHARING_STATE, -1); 67 if (state == LocalBluetoothLeBroadcast.BROADCAST_STATE_ON) { 68 showSharingNotification(context); 69 metricsFeatureProvider.action( 70 context, SettingsEnums.ACTION_SHOW_AUDIO_SHARING_NOTIFICATION); 71 } else if (state == LocalBluetoothLeBroadcast.BROADCAST_STATE_OFF) { 72 cancelSharingNotification(context); 73 metricsFeatureProvider.action( 74 context, SettingsEnums.ACTION_CANCEL_AUDIO_SHARING_NOTIFICATION); 75 } else { 76 Log.w( 77 TAG, 78 "Skip handling ACTION_LE_AUDIO_SHARING_STATE_CHANGE, invalid extras."); 79 } 80 break; 81 case ACTION_LE_AUDIO_SHARING_STOP: 82 LocalBluetoothManager manager = Utils.getLocalBtManager(context); 83 AudioSharingUtils.stopBroadcasting(manager); 84 metricsFeatureProvider.action( 85 context, SettingsEnums.ACTION_STOP_AUDIO_SHARING_FROM_NOTIFICATION); 86 break; 87 default: 88 Log.w(TAG, "Received unexpected intent " + intent.getAction()); 89 } 90 } 91 showSharingNotification(Context context)92 private void showSharingNotification(Context context) { 93 NotificationManager nm = context.getSystemService(NotificationManager.class); 94 if (nm.getNotificationChannel(CHANNEL_ID) == null) { 95 Log.d(TAG, "Create bluetooth notification channel"); 96 NotificationChannel notificationChannel = 97 new NotificationChannel( 98 CHANNEL_ID, 99 context.getString(com.android.settings.R.string.bluetooth), 100 NotificationManager.IMPORTANCE_HIGH); 101 nm.createNotificationChannel(notificationChannel); 102 } 103 Intent stopIntent = 104 new Intent(ACTION_LE_AUDIO_SHARING_STOP).setPackage(context.getPackageName()); 105 PendingIntent stopPendingIntent = 106 PendingIntent.getBroadcast( 107 context, 108 R.string.audio_sharing_stop_button_label, 109 stopIntent, 110 PendingIntent.FLAG_IMMUTABLE); 111 Intent settingsIntent = 112 new Intent(ACTION_LE_AUDIO_SHARING_SETTINGS) 113 .setPackage(context.getPackageName()) 114 .putExtra( 115 MetricsFeatureProvider.EXTRA_SOURCE_METRICS_CATEGORY, 116 SettingsEnums.NOTIFICATION_AUDIO_SHARING); 117 PendingIntent settingsPendingIntent = 118 PendingIntent.getActivity( 119 context, 120 R.string.audio_sharing_settings_button_label, 121 settingsIntent, 122 PendingIntent.FLAG_IMMUTABLE); 123 NotificationCompat.Action stopAction = 124 new NotificationCompat.Action.Builder( 125 0, 126 context.getString(R.string.audio_sharing_stop_button_label), 127 stopPendingIntent) 128 .build(); 129 NotificationCompat.Action settingsAction = 130 new NotificationCompat.Action.Builder( 131 0, 132 context.getString(R.string.audio_sharing_settings_button_label), 133 settingsPendingIntent) 134 .build(); 135 final Bundle extras = new Bundle(); 136 extras.putString( 137 Notification.EXTRA_SUBSTITUTE_APP_NAME, 138 context.getString(R.string.audio_sharing_title)); 139 NotificationCompat.Builder builder = 140 new NotificationCompat.Builder(context, CHANNEL_ID) 141 .setSmallIcon(com.android.settingslib.R.drawable.ic_bt_le_audio_sharing) 142 .setLocalOnly(true) 143 .setContentTitle( 144 context.getString(R.string.audio_sharing_notification_title)) 145 .setContentText( 146 context.getString(R.string.audio_sharing_notification_content)) 147 .setOngoing(true) 148 .setSilent(true) 149 .setColor( 150 context.getColor( 151 com.android.internal.R.color 152 .system_notification_accent_color)) 153 .setContentIntent(settingsPendingIntent) 154 .addAction(stopAction) 155 .addAction(settingsAction) 156 .addExtras(extras); 157 nm.notify(NOTIFICATION_ID, builder.build()); 158 } 159 cancelSharingNotification(Context context)160 private void cancelSharingNotification(Context context) { 161 NotificationManager nm = context.getSystemService(NotificationManager.class); 162 nm.cancel(NOTIFICATION_ID); 163 } 164 } 165