Create all notification channels on boot
Previously, channels would only be created when the first notification
was sent to that user.
Bug: 265277413
Test: Manually, checking both personal and work profile
Change-Id: I7fe5e2e0c86bad3a9501a71bd869b2909a4eab1d
diff --git a/service/java/com/android/safetycenter/SafetyCenterNotificationChannels.java b/service/java/com/android/safetycenter/SafetyCenterNotificationChannels.java
index 024b2cd..59a9cc9 100644
--- a/service/java/com/android/safetycenter/SafetyCenterNotificationChannels.java
+++ b/service/java/com/android/safetycenter/SafetyCenterNotificationChannels.java
@@ -22,15 +22,20 @@
import android.app.NotificationChannel;
import android.app.NotificationChannelGroup;
import android.app.NotificationManager;
+import android.content.Context;
import android.os.Binder;
+import android.os.UserHandle;
import android.safetycenter.SafetySourceData;
import android.safetycenter.SafetySourceIssue;
import android.util.Log;
import androidx.annotation.RequiresApi;
+import com.android.permission.util.UserUtils;
import com.android.safetycenter.resources.SafetyCenterResourcesContext;
+import java.util.List;
+
/** Class responsible for creating and updating Safety Center's notification channels. */
@RequiresApi(TIRAMISU)
final class SafetyCenterNotificationChannels {
@@ -48,6 +53,14 @@
mResourcesContext = safetyCenterResourceContext;
}
+ /** Returns a {@link NotificationManager} which will send notifications to the given user. */
+ @Nullable
+ static NotificationManager getNotificationManagerForUser(
+ Context baseContext, UserHandle userHandle) {
+ Context contextAsUser = baseContext.createContextAsUser(userHandle, 0);
+ return contextAsUser.getSystemService(NotificationManager.class);
+ }
+
/**
* Returns the ID of the appropriate {@link NotificationChannel} for a notification about the
* given {@code issue} after ensuring that channel has been created.
@@ -63,6 +76,23 @@
return getChannelIdForIssue(issue);
}
+ /**
+ * Creates all Safety Center {@link NotificationChannel}s instances and their group, for all
+ * current users, dropping any calling identity so those channels can be unblockable. Throws a
+ * {@link RuntimeException} if any channel is malformed and could not be created.
+ */
+ void createAllChannelsForAllUsers(Context context) {
+ List<UserHandle> users = UserUtils.getUserHandles(context);
+ for (int i = 0; i < users.size(); i++) {
+ try {
+ createAllChannelsWithoutCallingIdentity(
+ getNotificationManagerForUser(context, users.get(i)));
+ } catch (RuntimeException e) {
+ Log.w(TAG, "Unable to create notification channels", e);
+ }
+ }
+ }
+
@Nullable
private String getChannelIdForIssue(SafetySourceIssue issue) {
switch (issue.getSeverityLevel()) {
diff --git a/service/java/com/android/safetycenter/SafetyCenterNotificationSender.java b/service/java/com/android/safetycenter/SafetyCenterNotificationSender.java
index debc108..24eb304 100644
--- a/service/java/com/android/safetycenter/SafetyCenterNotificationSender.java
+++ b/service/java/com/android/safetycenter/SafetyCenterNotificationSender.java
@@ -311,9 +311,9 @@
/** Returns a {@link NotificationManager} which will send notifications to the given user. */
@Nullable
- private NotificationManager getNotificationManagerForUser(@UserIdInt int recipientUserId) {
- Context contextAsUser = mContext.createContextAsUser(UserHandle.of(recipientUserId), 0);
- return contextAsUser.getSystemService(NotificationManager.class);
+ private NotificationManager getNotificationManagerForUser(@UserIdInt int userId) {
+ return SafetyCenterNotificationChannels.getNotificationManagerForUser(
+ mContext, UserHandle.of(userId));
}
/**
diff --git a/service/java/com/android/safetycenter/SafetyCenterService.java b/service/java/com/android/safetycenter/SafetyCenterService.java
index 414383e..d2d62d3 100644
--- a/service/java/com/android/safetycenter/SafetyCenterService.java
+++ b/service/java/com/android/safetycenter/SafetyCenterService.java
@@ -110,6 +110,8 @@
private final SafetyCenterResourcesContext mSafetyCenterResourcesContext;
+ private final SafetyCenterNotificationChannels mNotificationChannels;
+
@GuardedBy("mApiLock")
private final SafetyCenterConfigReader mSafetyCenterConfigReader;
@@ -156,13 +158,12 @@
new PendingIntentFactory(context, mSafetyCenterResourcesContext),
mSafetyCenterDataManager);
mSafetyCenterListeners = new SafetyCenterListeners(mSafetyCenterDataFactory);
+ mNotificationChannels = new SafetyCenterNotificationChannels(mSafetyCenterResourcesContext);
mNotificationSender =
new SafetyCenterNotificationSender(
context,
new SafetyCenterNotificationFactory(
- context,
- new SafetyCenterNotificationChannels(mSafetyCenterResourcesContext),
- mSafetyCenterResourcesContext),
+ context, mNotificationChannels, mSafetyCenterResourcesContext),
mSafetyCenterDataManager);
mSafetyCenterBroadcastDispatcher =
new SafetyCenterBroadcastDispatcher(
@@ -216,6 +217,7 @@
if (phase == SystemService.PHASE_BOOT_COMPLETED && canUseSafetyCenter()) {
registerSafetyCenterEnabledListener();
registerSafetyCenterPullAtomCallback();
+ mNotificationChannels.createAllChannelsForAllUsers(getContext());
}
}