1 /* 2 * Copyright (C) 2017 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 package com.android.internal.telephony.util; 17 18 import android.annotation.NonNull; 19 import android.app.NotificationChannel; 20 import android.app.NotificationManager; 21 import android.content.BroadcastReceiver; 22 import android.content.Context; 23 import android.content.Intent; 24 import android.content.IntentFilter; 25 import android.media.AudioAttributes; 26 import android.net.Uri; 27 import android.provider.Settings; 28 import android.telephony.SubscriptionManager; 29 30 import com.android.internal.R; 31 32 import java.util.Arrays; 33 34 35 public class NotificationChannelController { 36 37 /** 38 * list of {@link android.app.NotificationChannel} for telephony service. 39 */ 40 public static final String CHANNEL_ID_ALERT = "alert"; 41 public static final String CHANNEL_ID_CALL_FORWARD = "callForwardNew"; 42 public static final String CHANNEL_ID_MOBILE_DATA_STATUS = "mobileDataAlertNew"; 43 public static final String CHANNEL_ID_SIM = "sim"; 44 public static final String CHANNEL_ID_SMS = "sms"; 45 public static final String CHANNEL_ID_VOICE_MAIL = "voiceMail"; 46 public static final String CHANNEL_ID_WFC = "wfc"; 47 /** 48 * This channel is for sim related notifications similar as CHANNEL_ID_SIM except that this is 49 * high priority while CHANNEL_ID_SIM is low priority. 50 */ 51 public static final String CHANNEL_ID_SIM_HIGH_PRIORITY = "simHighPriority"; 52 53 /** deprecated channel, replaced with @see #CHANNEL_ID_MOBILE_DATA_STATUS */ 54 private static final String CHANNEL_ID_MOBILE_DATA_ALERT_DEPRECATED = "mobileDataAlert"; 55 /** 56 * deprecated channel, replaced with @see #CHANNEL_ID_CALL_FORWARD 57 * change the importance to default to make sure notification icon shown in the status bar. 58 */ 59 private static final String CHANNEL_ID_CALL_FORWARD_DEPRECATED = "callForward"; 60 61 /** 62 * Creates all notification channels and registers with NotificationManager. If a channel 63 * with the same ID is already registered, NotificationManager will ignore this call. 64 */ createAll(Context context)65 private static void createAll(Context context) { 66 final NotificationChannel alertChannel = new NotificationChannel( 67 CHANNEL_ID_ALERT, 68 context.getText(R.string.notification_channel_network_alert), 69 NotificationManager.IMPORTANCE_DEFAULT); 70 alertChannel.setSound(Settings.System.DEFAULT_NOTIFICATION_URI, 71 new AudioAttributes.Builder().setUsage(AudioAttributes.USAGE_NOTIFICATION).build()); 72 // allow users to block notifications from system 73 alertChannel.setBlockableSystem(true); 74 75 final NotificationChannel mobileDataStatusChannel = new NotificationChannel( 76 CHANNEL_ID_MOBILE_DATA_STATUS, 77 context.getText(R.string.notification_channel_mobile_data_status), 78 NotificationManager.IMPORTANCE_LOW); 79 // allow users to block notifications from system 80 mobileDataStatusChannel.setBlockableSystem(true); 81 82 final NotificationChannel simChannel = new NotificationChannel( 83 CHANNEL_ID_SIM, 84 context.getText(R.string.notification_channel_sim), 85 NotificationManager.IMPORTANCE_LOW 86 ); 87 simChannel.setSound(null, null); 88 89 final NotificationChannel callforwardChannel = new NotificationChannel( 90 CHANNEL_ID_CALL_FORWARD, 91 context.getText(R.string.notification_channel_call_forward), 92 NotificationManager.IMPORTANCE_DEFAULT); 93 migrateCallFowardNotificationChannel(context, callforwardChannel); 94 95 context.getSystemService(NotificationManager.class) 96 .createNotificationChannels(Arrays.asList( 97 new NotificationChannel(CHANNEL_ID_SMS, 98 context.getText(R.string.notification_channel_sms), 99 NotificationManager.IMPORTANCE_HIGH), 100 new NotificationChannel(CHANNEL_ID_WFC, 101 context.getText(R.string.notification_channel_wfc), 102 NotificationManager.IMPORTANCE_LOW), 103 new NotificationChannel(CHANNEL_ID_SIM_HIGH_PRIORITY, 104 context.getText(R.string.notification_channel_sim_high_prio), 105 NotificationManager.IMPORTANCE_HIGH), 106 alertChannel, mobileDataStatusChannel, 107 simChannel, callforwardChannel)); 108 109 // only for update 110 if (getChannel(CHANNEL_ID_VOICE_MAIL, context) != null) { 111 migrateVoicemailNotificationSettings(context); 112 } 113 114 // after channel has been created there is no way to change the channel setting 115 // programmatically. delete the old channel and create a new one with a new ID. 116 if (getChannel(CHANNEL_ID_MOBILE_DATA_ALERT_DEPRECATED, context) != null) { 117 context.getSystemService(NotificationManager.class) 118 .deleteNotificationChannel(CHANNEL_ID_MOBILE_DATA_ALERT_DEPRECATED); 119 } 120 if (getChannel(CHANNEL_ID_CALL_FORWARD_DEPRECATED, context) != null) { 121 context.getSystemService(NotificationManager.class) 122 .deleteNotificationChannel(CHANNEL_ID_CALL_FORWARD_DEPRECATED); 123 } 124 } 125 NotificationChannelController(Context context)126 public NotificationChannelController(Context context) { 127 IntentFilter intentFilter = new IntentFilter(); 128 intentFilter.addAction(Intent.ACTION_LOCALE_CHANGED); 129 intentFilter.addAction(Intent.ACTION_SIM_STATE_CHANGED); 130 context.registerReceiver(mBroadcastReceiver, intentFilter); 131 createAll(context); 132 } 133 getChannel(String channelId, Context context)134 public static NotificationChannel getChannel(String channelId, Context context) { 135 return context.getSystemService(NotificationManager.class) 136 .getNotificationChannel(channelId); 137 } 138 139 /** 140 * migrate deprecated voicemail notification settings to initial notification channel settings 141 * {@link VoicemailNotificationSettingsUtil#getRingTonePreference(Context)}} 142 * {@link VoicemailNotificationSettingsUtil#getVibrationPreference(Context)} 143 * notification settings are based on subId, only migrate if sub id matches. 144 * otherwise fallback to predefined voicemail channel settings. 145 * @param context 146 */ migrateVoicemailNotificationSettings(Context context)147 private static void migrateVoicemailNotificationSettings(Context context) { 148 final NotificationChannel voiceMailChannel = new NotificationChannel( 149 CHANNEL_ID_VOICE_MAIL, 150 context.getText(R.string.notification_channel_voice_mail), 151 NotificationManager.IMPORTANCE_DEFAULT); 152 voiceMailChannel.enableVibration( 153 VoicemailNotificationSettingsUtil.getVibrationPreference(context)); 154 Uri sound = VoicemailNotificationSettingsUtil.getRingTonePreference(context); 155 voiceMailChannel.setSound( 156 (sound == null) ? Settings.System.DEFAULT_NOTIFICATION_URI : sound, 157 new AudioAttributes.Builder().setUsage(AudioAttributes.USAGE_NOTIFICATION).build()); 158 context.getSystemService(NotificationManager.class) 159 .createNotificationChannel(voiceMailChannel); 160 } 161 162 /** 163 * migrate deprecated call forward notification channel. 164 * @param context 165 */ migrateCallFowardNotificationChannel( Context context, @NonNull NotificationChannel callforwardChannel)166 private static void migrateCallFowardNotificationChannel( 167 Context context, @NonNull NotificationChannel callforwardChannel) { 168 final NotificationChannel deprecatedChannel = 169 getChannel(CHANNEL_ID_CALL_FORWARD_DEPRECATED, context); 170 if (deprecatedChannel != null) { 171 callforwardChannel.setSound(deprecatedChannel.getSound(), 172 deprecatedChannel.getAudioAttributes()); 173 callforwardChannel.setVibrationPattern(deprecatedChannel.getVibrationPattern()); 174 callforwardChannel.enableVibration(deprecatedChannel.shouldVibrate()); 175 } 176 } 177 178 private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() { 179 @Override 180 public void onReceive(Context context, Intent intent) { 181 if (Intent.ACTION_LOCALE_CHANGED.equals(intent.getAction())) { 182 // rename all notification channels on locale change 183 createAll(context); 184 } else if (Intent.ACTION_SIM_STATE_CHANGED.equals(intent.getAction())) { 185 // migrate voicemail notification settings on sim load 186 if (SubscriptionManager.INVALID_SUBSCRIPTION_ID != 187 SubscriptionManager.getDefaultSubscriptionId()) { 188 migrateVoicemailNotificationSettings(context); 189 } 190 } 191 } 192 }; 193 } 194