summaryrefslogtreecommitdiffstats
path: root/java/com/android/dialer/notification/NotificationChannelManager.java
diff options
context:
space:
mode:
Diffstat (limited to 'java/com/android/dialer/notification/NotificationChannelManager.java')
-rw-r--r--java/com/android/dialer/notification/NotificationChannelManager.java141
1 files changed, 135 insertions, 6 deletions
diff --git a/java/com/android/dialer/notification/NotificationChannelManager.java b/java/com/android/dialer/notification/NotificationChannelManager.java
index db7ded781..ef0f5f17a 100644
--- a/java/com/android/dialer/notification/NotificationChannelManager.java
+++ b/java/com/android/dialer/notification/NotificationChannelManager.java
@@ -16,15 +16,21 @@
package com.android.dialer.notification;
+import android.annotation.TargetApi;
import android.app.Notification;
import android.app.NotificationChannel;
import android.app.NotificationChannelGroup;
import android.app.NotificationManager;
import android.content.Context;
+import android.content.Intent;
+import android.content.SharedPreferences;
import android.media.AudioAttributes;
import android.net.Uri;
+import android.os.Build.VERSION_CODES;
+import android.provider.Settings;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
+import android.support.annotation.RequiresApi;
import android.support.annotation.StringDef;
import android.support.v4.os.BuildCompat;
import android.telecom.PhoneAccount;
@@ -34,12 +40,18 @@ import android.telephony.TelephonyManager;
import com.android.contacts.common.compat.TelephonyManagerCompat;
import com.android.dialer.buildtype.BuildType;
import com.android.dialer.common.LogUtil;
+import com.android.dialer.common.concurrent.DialerExecutors;
+import com.android.dialer.telecom.TelecomUtil;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
+import java.util.List;
+import java.util.Objects;
/** Contains info on how to create {@link NotificationChannel NotificationChannels} */
public class NotificationChannelManager {
+ private static final String PREFS_FILENAME = "NotificationChannelManager";
+ private static final String PREF_NEED_FIRST_INIT = "needFirstInit";
private static NotificationChannelManager instance;
public static NotificationChannelManager getInstance() {
@@ -53,9 +65,10 @@ public class NotificationChannelManager {
* Set the channel of notification appropriately. Will create the channel if it does not already
* exist. Safe to call pre-O (will no-op).
*
- * <p>phoneAccount should only be null if channelName is {@link Channel#MISC} or {@link
+ * <p>phoneAccount should only be null if channelName is {@link Channel#DEFAULT} or {@link
* Channel#MISSED_CALL} since these do not have account-specific settings.
*/
+ @TargetApi(26)
public static void applyChannel(
@NonNull Notification.Builder notification,
@NonNull Context context,
@@ -89,7 +102,7 @@ public class NotificationChannelManager {
private static boolean channelAllowsNullPhoneAccountHandle(@Channel String channelName) {
switch (channelName) {
- case Channel.MISC:
+ case Channel.DEFAULT:
case Channel.MISSED_CALL:
return true;
default:
@@ -102,22 +115,122 @@ public class NotificationChannelManager {
@StringDef({
Channel.INCOMING_CALL,
Channel.ONGOING_CALL,
+ Channel.ONGOING_CALL_OLD,
Channel.MISSED_CALL,
Channel.VOICEMAIL,
Channel.EXTERNAL_CALL,
- Channel.MISC
+ Channel.DEFAULT
})
public @interface Channel {
+ @Deprecated String ONGOING_CALL_OLD = "ongoingCall";
String INCOMING_CALL = "incomingCall";
- String ONGOING_CALL = "ongoingCall";
+ String ONGOING_CALL = "ongoingCall2";
String MISSED_CALL = "missedCall";
String VOICEMAIL = "voicemail";
String EXTERNAL_CALL = "externalCall";
- String MISC = "miscellaneous";
+ String DEFAULT = "default";
}
+ @Channel
+ private static final String[] prepopulatedAccountChannels =
+ new String[] {Channel.INCOMING_CALL, Channel.ONGOING_CALL, Channel.VOICEMAIL};
+
+ @Channel
+ private static final String[] prepopulatedGlobalChannels =
+ new String[] {Channel.MISSED_CALL, Channel.DEFAULT};
+
private NotificationChannelManager() {}
+ public void firstInitIfNeeded(@NonNull Context context) {
+ if (BuildCompat.isAtLeastO()) {
+ DialerExecutors.createNonUiTaskBuilder(this::firstInitIfNeededSync)
+ .build()
+ .executeSerial(context);
+ }
+ }
+
+ private boolean firstInitIfNeededSync(@NonNull Context context) {
+ if (needsFirstInit(context)) {
+ initChannels(context);
+ return true;
+ }
+ return false;
+ }
+
+ public boolean needsFirstInit(@NonNull Context context) {
+ return (BuildCompat.isAtLeastO()
+ && getSharedPreferences(context).getBoolean(PREF_NEED_FIRST_INIT, true));
+ }
+
+ @RequiresApi(VERSION_CODES.N)
+ private SharedPreferences getSharedPreferences(@NonNull Context context) {
+ // Use device protected storage since in some cases this will need to be accessed while device
+ // is locked
+ context = context.createDeviceProtectedStorageContext();
+ return context.getSharedPreferences(PREFS_FILENAME, Context.MODE_PRIVATE);
+ }
+
+ @RequiresApi(26)
+ public Intent getSettingsIntentForChannel(
+ @NonNull Context context, @Channel String channelName, PhoneAccountHandle accountHandle) {
+ checkNullity(channelName, accountHandle);
+ Intent intent = new Intent(Settings.ACTION_CHANNEL_NOTIFICATION_SETTINGS);
+ intent.putExtra(
+ Settings.EXTRA_CHANNEL_ID, getChannel(context, channelName, accountHandle).getId());
+ intent.putExtra(Settings.EXTRA_APP_PACKAGE, context.getPackageName());
+ return intent;
+ }
+
+ @TargetApi(26)
+ @SuppressWarnings("AndroidApiChecker")
+ public void initChannels(@NonNull Context context) {
+ if (!BuildCompat.isAtLeastO()) {
+ return;
+ }
+ LogUtil.enterBlock("NotificationChannelManager.initChannels");
+ List<PhoneAccountHandle> phoneAccounts = TelecomUtil.getCallCapablePhoneAccounts(context);
+
+ // Remove notification channels for PhoneAccounts that don't exist anymore
+ NotificationManager notificationManager = context.getSystemService(NotificationManager.class);
+ List<NotificationChannelGroup> notificationChannelGroups =
+ notificationManager.getNotificationChannelGroups();
+ notificationChannelGroups
+ .stream()
+ .filter(group -> !idExists(group.getId(), phoneAccounts))
+ .forEach(group -> deleteGroup(notificationManager, group));
+
+ for (PhoneAccountHandle phoneAccountHandle : phoneAccounts) {
+ for (@Channel String channel : prepopulatedAccountChannels) {
+ getChannel(context, channel, phoneAccountHandle);
+ }
+ }
+
+ for (@Channel String channel : prepopulatedGlobalChannels) {
+ getChannel(context, channel, null);
+ }
+ getSharedPreferences(context).edit().putBoolean(PREF_NEED_FIRST_INIT, false).apply();
+ }
+
+ @TargetApi(26)
+ private void deleteGroup(
+ @NonNull NotificationManager notificationManager, @NonNull NotificationChannelGroup group) {
+ for (NotificationChannel channel : group.getChannels()) {
+ notificationManager.deleteNotificationChannel(channel.getId());
+ }
+ notificationManager.deleteNotificationChannelGroup(group.getId());
+ }
+
+ private boolean idExists(String id, List<PhoneAccountHandle> phoneAccountHandles) {
+ for (PhoneAccountHandle handle : phoneAccountHandles) {
+ if (Objects.equals(handle.getId(), id)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ @NonNull
+ @RequiresApi(26)
private NotificationChannel getChannel(
@NonNull Context context,
@Channel String channelName,
@@ -139,6 +252,7 @@ public class NotificationChannelManager {
}
}
+ @RequiresApi(26)
private NotificationChannel createChannel(
Context context,
@Channel String channelName,
@@ -191,6 +305,7 @@ public class NotificationChannelManager {
lights = false;
vibration = false;
sound = silentRingtone;
+ deleteOldOngoingCallChannelIfNeeded(context, phoneAccountHandle);
break;
case Channel.VOICEMAIL:
name = context.getText(R.string.notification_channel_voicemail);
@@ -210,7 +325,7 @@ public class NotificationChannelManager {
vibration = true;
sound = null;
break;
- case Channel.MISC:
+ case Channel.DEFAULT:
name = context.getText(R.string.notification_channel_misc);
importance = NotificationManager.IMPORTANCE_DEFAULT;
canShowBadge = false;
@@ -235,6 +350,20 @@ public class NotificationChannelManager {
return channel;
}
+ @RequiresApi(26)
+ private void deleteOldOngoingCallChannelIfNeeded(
+ @NonNull Context context, PhoneAccountHandle phoneAccountHandle) {
+ String channelId = channelNameToId(Channel.ONGOING_CALL_OLD, phoneAccountHandle);
+ NotificationManager notificationManager = getNotificationManager(context);
+ NotificationChannel channel = notificationManager.getNotificationChannel(channelId);
+ if (channel != null) {
+ LogUtil.i(
+ "NotificationManager.deleteOldOngoingCallChannelIfNeeded",
+ "Old ongoing channel found. Deleting to create new channel");
+ notificationManager.deleteNotificationChannel(channel.getId());
+ }
+ }
+
private static NotificationManager getNotificationManager(@NonNull Context context) {
return context.getSystemService(NotificationManager.class);
}