packages/modules/Bluetooth/service/java/com/android/server/bluetooth/BluetoothNotificationManage...

177 lines
6.3 KiB
Java
Raw Permalink Normal View History

2025-08-25 08:38:42 +08:00
/*
* Copyright 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.
* 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.server.bluetooth;
import android.app.Notification;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.net.Uri;
import android.os.Binder;
import android.os.UserHandle;
import android.service.notification.StatusBarNotification;
import android.util.Log;
import com.android.internal.messages.nano.SystemMessageProto.SystemMessage;
import java.util.ArrayList;
import java.util.List;
/**
* Notification manager for Bluetooth. All notification will be sent to the current user.
*/
public class BluetoothNotificationManager {
private static final String TAG = "BluetoothNotificationManager";
private static final String NOTIFICATION_TAG = "com.android.bluetooth";
public static final String APM_NOTIFICATION_CHANNEL = "apm_notification_channel";
private static final String APM_NOTIFICATION_GROUP = "apm_notification_group";
private static final String HELP_PAGE_URL =
"https://support.google.com/pixelphone/answer/12639358";
private final Context mContext;
private NotificationManager mNotificationManager;
private boolean mInitialized = false;
/**
* Constructor
*
* @param ctx The context to use to obtain access to the Notification Service
*/
BluetoothNotificationManager(Context ctx) {
mContext = ctx;
}
private NotificationManager getNotificationManagerForCurrentUser() {
final long callingIdentity = Binder.clearCallingIdentity();
try {
return mContext.createPackageContextAsUser(mContext.getPackageName(), 0,
UserHandle.CURRENT).getSystemService(NotificationManager.class);
} catch (PackageManager.NameNotFoundException e) {
Log.e(TAG, "Failed to get NotificationManager for current user: " + e.getMessage());
} finally {
Binder.restoreCallingIdentity(callingIdentity);
}
return null;
}
/**
* Update to the notification manager fot current user and create notification channels.
*/
public void createNotificationChannels() {
if (mNotificationManager != null) {
// Cancel all active notification from Bluetooth Stack.
cleanAllBtNotification();
}
mNotificationManager = getNotificationManagerForCurrentUser();
if (mNotificationManager == null) {
return;
}
List<NotificationChannel> channelsList = new ArrayList<>();
final NotificationChannel apmChannel = new NotificationChannel(
APM_NOTIFICATION_CHANNEL,
APM_NOTIFICATION_GROUP,
NotificationManager.IMPORTANCE_HIGH);
channelsList.add(apmChannel);
final long callingIdentity = Binder.clearCallingIdentity();
try {
mNotificationManager.createNotificationChannels(channelsList);
} catch (Exception e) {
Log.e(TAG, "Error Message: " + e.getMessage());
e.printStackTrace();
} finally {
Binder.restoreCallingIdentity(callingIdentity);
}
}
private void cleanAllBtNotification() {
for (StatusBarNotification notification : getActiveNotifications()) {
if (NOTIFICATION_TAG.equals(notification.getTag())) {
cancel(notification.getId());
}
}
}
/**
* Send notification to the current user.
*/
public void notify(int id, Notification notification) {
if (!mInitialized) {
createNotificationChannels();
mInitialized = true;
}
if (mNotificationManager == null) {
return;
}
mNotificationManager.notify(NOTIFICATION_TAG, id, notification);
}
/**
* Build and send the APM notification.
*/
public void sendApmNotification(String title, String message) {
if (!mInitialized) {
createNotificationChannels();
mInitialized = true;
}
Intent openLinkIntent = new Intent(Intent.ACTION_VIEW)
.setData(Uri.parse(HELP_PAGE_URL))
.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
PendingIntent tapPendingIntent = PendingIntent.getActivity(
mContext.createContextAsUser(UserHandle.CURRENT, 0),
PendingIntent.FLAG_UPDATE_CURRENT, openLinkIntent, PendingIntent.FLAG_IMMUTABLE);
Notification notification = new Notification.Builder(mContext, APM_NOTIFICATION_CHANNEL)
.setAutoCancel(true)
.setLocalOnly(true)
.setContentTitle(title)
.setContentText(message)
.setContentIntent(tapPendingIntent)
.setVisibility(Notification.VISIBILITY_PUBLIC)
.setStyle(new Notification.BigTextStyle().bigText(message))
.setSmallIcon(android.R.drawable.stat_sys_data_bluetooth)
.build();
notify(SystemMessage.NOTE_BT_APM_NOTIFICATION, notification);
}
/**
* Cancel the notification fot current user.
*/
public void cancel(int id) {
if (mNotificationManager == null) {
return;
}
mNotificationManager.cancel(NOTIFICATION_TAG, id);
}
/**
* Get active notifications for current user.
*/
public StatusBarNotification[] getActiveNotifications() {
if (mNotificationManager == null) {
return new StatusBarNotification[0];
}
return mNotificationManager.getActiveNotifications();
}
}