1 /* 2 * Copyright (C) 2020 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.sim; 18 19 import static android.content.Context.MODE_PRIVATE; 20 21 import android.annotation.IntDef; 22 import android.app.Notification; 23 import android.app.NotificationChannel; 24 import android.app.NotificationManager; 25 import android.app.PendingIntent; 26 import android.content.Context; 27 import android.content.Intent; 28 import android.content.SharedPreferences; 29 import android.telephony.CarrierConfigManager; 30 import android.telephony.SubscriptionInfo; 31 import android.telephony.SubscriptionManager; 32 import android.telephony.TelephonyManager; 33 import android.text.TextUtils; 34 import android.util.Log; 35 36 import androidx.core.app.TaskStackBuilder; 37 38 import com.android.settings.R; 39 import com.android.settings.Settings; 40 import com.android.settings.network.SubscriptionUtil; 41 42 import java.lang.annotation.Retention; 43 import java.lang.annotation.RetentionPolicy; 44 45 import javax.annotation.Nullable; 46 47 /** 48 * This class manages the notification of SIM activation notification including creating and 49 * canceling the notifications. 50 */ 51 public class SimActivationNotifier { 52 53 private static final String TAG = "SimActivationNotifier"; 54 private static final String SIM_SETUP_CHANNEL_ID = "sim_setup"; 55 private static final String SWITCH_SLOT_CHANNEL_ID = "carrier_switching"; 56 private static final String SIM_PREFS = "sim_prefs"; 57 private static final String KEY_SHOW_SIM_SETTINGS_NOTIFICATION = 58 "show_sim_settings_notification"; 59 60 public static final int SIM_ACTIVATION_NOTIFICATION_ID = 1; 61 public static final int SWITCH_TO_REMOVABLE_SLOT_NOTIFICATION_ID = 2; 62 63 /** Notification types */ 64 @Retention(RetentionPolicy.SOURCE) 65 @IntDef( 66 value = { 67 NotificationType.NETWORK_CONFIG, 68 NotificationType.SWITCH_TO_REMOVABLE_SLOT, 69 NotificationType.ENABLE_DSDS, 70 }) 71 public @interface NotificationType { 72 // The notification to remind users to config network Settings. 73 int NETWORK_CONFIG = 1; 74 // The notification to notify users that the device is switched to the removable slot. 75 int SWITCH_TO_REMOVABLE_SLOT = 2; 76 // The notification to notify users that the device is capable of DSDS. 77 int ENABLE_DSDS = 3; 78 } 79 80 private final Context mContext; 81 private final NotificationManager mNotificationManager; 82 SimActivationNotifier(Context context)83 public SimActivationNotifier(Context context) { 84 mContext = context; 85 mNotificationManager = context.getSystemService(NotificationManager.class); 86 mNotificationManager.createNotificationChannel( 87 new NotificationChannel( 88 SIM_SETUP_CHANNEL_ID, 89 mContext.getString(R.string.sim_setup_channel_id), 90 NotificationManager.IMPORTANCE_HIGH)); 91 mNotificationManager.createNotificationChannel( 92 new NotificationChannel( 93 SWITCH_SLOT_CHANNEL_ID, 94 mContext.getString(R.string.sim_switch_channel_id), 95 NotificationManager.IMPORTANCE_HIGH)); 96 } 97 98 /** 99 * Sets whether Settings should send a push notification for the SIM activation. 100 * 101 * @param context 102 * @param showNotification whether Settings should send a push notification for the SIM 103 * activation. 104 */ setShowSimSettingsNotification(Context context, boolean showNotification)105 public static void setShowSimSettingsNotification(Context context, boolean showNotification) { 106 final SharedPreferences prefs = context.getSharedPreferences(SIM_PREFS, MODE_PRIVATE); 107 prefs.edit().putBoolean(KEY_SHOW_SIM_SETTINGS_NOTIFICATION, showNotification).apply(); 108 } 109 110 /** 111 * Gets whether Settings should send a push notification for the SIM activation. 112 * 113 * @param context 114 * @return true if Settings should send a push notification for SIM activation. Otherwise, 115 * return false. 116 */ getShowSimSettingsNotification(Context context)117 public static boolean getShowSimSettingsNotification(Context context) { 118 final SharedPreferences prefs = context.getSharedPreferences(SIM_PREFS, MODE_PRIVATE); 119 return prefs.getBoolean(KEY_SHOW_SIM_SETTINGS_NOTIFICATION, false); 120 } 121 122 /** Sends a push notification for the SIM activation. It should be called after DSDS reboot. */ sendNetworkConfigNotification()123 public void sendNetworkConfigNotification() { 124 SubscriptionInfo activeRemovableSub = getActiveRemovableSub(); 125 126 if (activeRemovableSub == null) { 127 Log.e(TAG, "No removable subscriptions found. Do not show notification."); 128 return; 129 } 130 131 CharSequence displayName = 132 SubscriptionUtil.getUniqueSubscriptionDisplayName(activeRemovableSub, mContext); 133 String carrierName = 134 TextUtils.isEmpty(displayName) 135 ? mContext.getString(R.string.sim_card_label) 136 : displayName.toString(); 137 String title = 138 mContext.getString( 139 R.string.post_dsds_reboot_notification_title_with_carrier, carrierName); 140 String text = mContext.getString(R.string.post_dsds_reboot_notification_text); 141 Intent clickIntent = new Intent(mContext, Settings.MobileNetworkListActivity.class); 142 TaskStackBuilder stackBuilder = 143 TaskStackBuilder.create(mContext).addNextIntent(clickIntent); 144 PendingIntent contentIntent = 145 stackBuilder.getPendingIntent( 146 0 /* requestCode */, 147 PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE); 148 149 Notification.Builder builder = 150 new Notification.Builder(mContext, SIM_SETUP_CHANNEL_ID) 151 .setContentTitle(title) 152 .setContentText(text) 153 .setContentIntent(contentIntent) 154 .setSmallIcon(R.drawable.ic_sim_alert) 155 .setAutoCancel(true); 156 mNotificationManager.notify(SIM_ACTIVATION_NOTIFICATION_ID, builder.build()); 157 } 158 159 /** Sends a push notification for switching to the removable slot. */ sendSwitchedToRemovableSlotNotification()160 public void sendSwitchedToRemovableSlotNotification() { 161 String carrierName = getActiveCarrierName(); 162 Intent clickIntent = new Intent(mContext, Settings.MobileNetworkListActivity.class); 163 TaskStackBuilder stackBuilder = 164 TaskStackBuilder.create(mContext).addNextIntent(clickIntent); 165 PendingIntent contentIntent = 166 stackBuilder.getPendingIntent( 167 0 /* requestCode */, 168 PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE); 169 String titleText = 170 TextUtils.isEmpty(carrierName) 171 ? mContext.getString( 172 R.string.switch_to_removable_notification_no_carrier_name) 173 : mContext.getString( 174 R.string.switch_to_removable_notification, carrierName); 175 Notification.Builder builder = 176 new Notification.Builder(mContext, SWITCH_SLOT_CHANNEL_ID) 177 .setContentTitle(titleText) 178 .setContentText( 179 mContext.getString(R.string.network_changed_notification_text)) 180 .setContentIntent(contentIntent) 181 .setSmallIcon(R.drawable.ic_sim_alert) 182 .setColor( 183 mContext.getResources() 184 .getColor( 185 R.color.homepage_generic_icon_background, 186 null /* theme */)) 187 .setAutoCancel(true); 188 mNotificationManager.notify(SWITCH_TO_REMOVABLE_SLOT_NOTIFICATION_ID, builder.build()); 189 } 190 191 /** Sends a push notification for enabling DSDS. */ sendEnableDsdsNotification()192 public void sendEnableDsdsNotification() { 193 Intent parentIntent = new Intent(mContext, Settings.MobileNetworkListActivity.class); 194 195 Intent clickIntent = new Intent(mContext, DsdsDialogActivity.class); 196 197 TaskStackBuilder stackBuilder = 198 TaskStackBuilder.create(mContext) 199 .addNextIntentWithParentStack(parentIntent) 200 .addNextIntent(clickIntent); 201 PendingIntent contentIntent = 202 stackBuilder.getPendingIntent( 203 0 /* requestCode */, 204 PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE); 205 206 Notification.Builder builder = 207 new Notification.Builder(mContext, SIM_SETUP_CHANNEL_ID) 208 .setContentTitle( 209 mContext.getString(R.string.dsds_notification_after_suw_title)) 210 .setContentText( 211 mContext.getString(R.string.dsds_notification_after_suw_text)) 212 .setContentIntent(contentIntent) 213 .setSmallIcon(R.drawable.ic_sim_alert) 214 .setAutoCancel(true); 215 mNotificationManager.notify(SIM_ACTIVATION_NOTIFICATION_ID, builder.build()); 216 } 217 218 @Nullable getActiveRemovableSub()219 private SubscriptionInfo getActiveRemovableSub() { 220 SubscriptionManager subscriptionManager = 221 mContext.getSystemService(SubscriptionManager.class); 222 return SubscriptionUtil.getActiveSubscriptions(subscriptionManager).stream() 223 .filter(sub -> !sub.isEmbedded()) 224 .findFirst() 225 .orElse(null); 226 } 227 228 @Nullable getActiveCarrierName()229 private String getActiveCarrierName() { 230 CarrierConfigManager configManager = mContext.getSystemService(CarrierConfigManager.class); 231 TelephonyManager telManager = mContext.getSystemService(TelephonyManager.class); 232 String telName = telManager.getSimOperatorName(); 233 if (configManager != null && configManager.getConfig() != null) { 234 boolean override = 235 configManager 236 .getConfig() 237 .getBoolean(CarrierConfigManager.KEY_CARRIER_NAME_OVERRIDE_BOOL); 238 String configName = 239 configManager 240 .getConfig() 241 .getString(CarrierConfigManager.KEY_CARRIER_NAME_STRING); 242 243 return override || TextUtils.isEmpty(telName) ? configName : telName; 244 } 245 return telName; 246 } 247 } 248