| /* | |
| * Copyright (C) 2020 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.settings.sim; | |
| import static android.content.Context.MODE_PRIVATE; | |
| import android.annotation.IntDef; | |
| 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.SharedPreferences; | |
| import android.telephony.CarrierConfigManager; | |
| import android.telephony.SubscriptionInfo; | |
| import android.telephony.SubscriptionManager; | |
| import android.telephony.TelephonyManager; | |
| import android.text.TextUtils; | |
| import android.util.Log; | |
| import androidx.core.app.TaskStackBuilder; | |
| import com.android.settings.R; | |
| import com.android.settings.Settings; | |
| import com.android.settings.network.SubscriptionUtil; | |
| import java.lang.annotation.Retention; | |
| import java.lang.annotation.RetentionPolicy; | |
| import javax.annotation.Nullable; | |
| /** | |
| * This class manages the notification of SIM activation notification including creating and | |
| * canceling the notifications. | |
| */ | |
| public class SimActivationNotifier { | |
| private static final String TAG = "SimActivationNotifier"; | |
| private static final String SIM_SETUP_CHANNEL_ID = "sim_setup"; | |
| private static final String SWITCH_SLOT_CHANNEL_ID = "carrier_switching"; | |
| private static final String SIM_PREFS = "sim_prefs"; | |
| private static final String KEY_SHOW_SIM_SETTINGS_NOTIFICATION = | |
| "show_sim_settings_notification"; | |
| public static final int SIM_ACTIVATION_NOTIFICATION_ID = 1; | |
| public static final int SWITCH_TO_REMOVABLE_SLOT_NOTIFICATION_ID = 2; | |
| /** Notification types */ | |
| @Retention(RetentionPolicy.SOURCE) | |
| @IntDef( | |
| value = { | |
| NotificationType.NETWORK_CONFIG, | |
| NotificationType.SWITCH_TO_REMOVABLE_SLOT, | |
| NotificationType.ENABLE_DSDS, | |
| }) | |
| public @interface NotificationType { | |
| // The notification to remind users to config network Settings. | |
| int NETWORK_CONFIG = 1; | |
| // The notification to notify users that the device is switched to the removable slot. | |
| int SWITCH_TO_REMOVABLE_SLOT = 2; | |
| // The notification to notify users that the device is capable of DSDS. | |
| int ENABLE_DSDS = 3; | |
| } | |
| private final Context mContext; | |
| private final NotificationManager mNotificationManager; | |
| public SimActivationNotifier(Context context) { | |
| mContext = context; | |
| mNotificationManager = context.getSystemService(NotificationManager.class); | |
| mNotificationManager.createNotificationChannel( | |
| new NotificationChannel( | |
| SIM_SETUP_CHANNEL_ID, | |
| mContext.getString(R.string.sim_setup_channel_id), | |
| NotificationManager.IMPORTANCE_HIGH)); | |
| mNotificationManager.createNotificationChannel( | |
| new NotificationChannel( | |
| SWITCH_SLOT_CHANNEL_ID, | |
| mContext.getString(R.string.sim_switch_channel_id), | |
| NotificationManager.IMPORTANCE_HIGH)); | |
| } | |
| /** | |
| * Sets whether Settings should send a push notification for the SIM activation. | |
| * | |
| * @param context | |
| * @param showNotification whether Settings should send a push notification for the SIM | |
| * activation. | |
| */ | |
| public static void setShowSimSettingsNotification(Context context, boolean showNotification) { | |
| final SharedPreferences prefs = context.getSharedPreferences(SIM_PREFS, MODE_PRIVATE); | |
| prefs.edit().putBoolean(KEY_SHOW_SIM_SETTINGS_NOTIFICATION, showNotification).apply(); | |
| } | |
| /** | |
| * Gets whether Settings should send a push notification for the SIM activation. | |
| * | |
| * @param context | |
| * @return true if Settings should send a push notification for SIM activation. Otherwise, | |
| * return false. | |
| */ | |
| public static boolean getShowSimSettingsNotification(Context context) { | |
| final SharedPreferences prefs = context.getSharedPreferences(SIM_PREFS, MODE_PRIVATE); | |
| return prefs.getBoolean(KEY_SHOW_SIM_SETTINGS_NOTIFICATION, false); | |
| } | |
| /** Sends a push notification for the SIM activation. It should be called after DSDS reboot. */ | |
| public void sendNetworkConfigNotification() { | |
| SubscriptionInfo activeRemovableSub = getActiveRemovableSub(); | |
| if (activeRemovableSub == null) { | |
| Log.e(TAG, "No removable subscriptions found. Do not show notification."); | |
| return; | |
| } | |
| CharSequence displayName = | |
| SubscriptionUtil.getUniqueSubscriptionDisplayName(activeRemovableSub, mContext); | |
| String carrierName = | |
| TextUtils.isEmpty(displayName) | |
| ? mContext.getString(R.string.sim_card_label) | |
| : displayName.toString(); | |
| String title = | |
| mContext.getString( | |
| R.string.post_dsds_reboot_notification_title_with_carrier, carrierName); | |
| String text = mContext.getString(R.string.post_dsds_reboot_notification_text); | |
| Intent clickIntent = new Intent(mContext, Settings.MobileNetworkListActivity.class); | |
| TaskStackBuilder stackBuilder = | |
| TaskStackBuilder.create(mContext).addNextIntent(clickIntent); | |
| PendingIntent contentIntent = | |
| stackBuilder.getPendingIntent( | |
| 0 /* requestCode */, | |
| PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE); | |
| Notification.Builder builder = | |
| new Notification.Builder(mContext, SIM_SETUP_CHANNEL_ID) | |
| .setContentTitle(title) | |
| .setContentText(text) | |
| .setContentIntent(contentIntent) | |
| .setSmallIcon(R.drawable.ic_sim_alert) | |
| .setAutoCancel(true); | |
| mNotificationManager.notify(SIM_ACTIVATION_NOTIFICATION_ID, builder.build()); | |
| } | |
| /** Sends a push notification for switching to the removable slot. */ | |
| public void sendSwitchedToRemovableSlotNotification() { | |
| String carrierName = getActiveCarrierName(); | |
| Intent clickIntent = new Intent(mContext, Settings.MobileNetworkListActivity.class); | |
| TaskStackBuilder stackBuilder = | |
| TaskStackBuilder.create(mContext).addNextIntent(clickIntent); | |
| PendingIntent contentIntent = | |
| stackBuilder.getPendingIntent( | |
| 0 /* requestCode */, | |
| PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE); | |
| String titleText = | |
| TextUtils.isEmpty(carrierName) | |
| ? mContext.getString( | |
| R.string.switch_to_removable_notification_no_carrier_name) | |
| : mContext.getString( | |
| R.string.switch_to_removable_notification, carrierName); | |
| Notification.Builder builder = | |
| new Notification.Builder(mContext, SWITCH_SLOT_CHANNEL_ID) | |
| .setContentTitle(titleText) | |
| .setContentText( | |
| mContext.getString(R.string.network_changed_notification_text)) | |
| .setContentIntent(contentIntent) | |
| .setSmallIcon(R.drawable.ic_sim_alert) | |
| .setColor( | |
| mContext.getResources() | |
| .getColor( | |
| R.color.homepage_generic_icon_background, | |
| null /* theme */)) | |
| .setAutoCancel(true); | |
| mNotificationManager.notify(SWITCH_TO_REMOVABLE_SLOT_NOTIFICATION_ID, builder.build()); | |
| } | |
| /** Sends a push notification for enabling DSDS. */ | |
| public void sendEnableDsdsNotification() { | |
| Intent parentIntent = new Intent(mContext, Settings.MobileNetworkListActivity.class); | |
| Intent clickIntent = new Intent(mContext, DsdsDialogActivity.class); | |
| TaskStackBuilder stackBuilder = | |
| TaskStackBuilder.create(mContext) | |
| .addNextIntentWithParentStack(parentIntent) | |
| .addNextIntent(clickIntent); | |
| PendingIntent contentIntent = | |
| stackBuilder.getPendingIntent( | |
| 0 /* requestCode */, | |
| PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE); | |
| Notification.Builder builder = | |
| new Notification.Builder(mContext, SIM_SETUP_CHANNEL_ID) | |
| .setContentTitle( | |
| mContext.getString(R.string.dsds_notification_after_suw_title)) | |
| .setContentText( | |
| mContext.getString(R.string.dsds_notification_after_suw_text)) | |
| .setContentIntent(contentIntent) | |
| .setSmallIcon(R.drawable.ic_sim_alert) | |
| .setAutoCancel(true); | |
| mNotificationManager.notify(SIM_ACTIVATION_NOTIFICATION_ID, builder.build()); | |
| } | |
| @Nullable | |
| private SubscriptionInfo getActiveRemovableSub() { | |
| SubscriptionManager subscriptionManager = | |
| mContext.getSystemService(SubscriptionManager.class); | |
| return SubscriptionUtil.getActiveSubscriptions(subscriptionManager).stream() | |
| .filter(sub -> !sub.isEmbedded()) | |
| .findFirst() | |
| .orElse(null); | |
| } | |
| @Nullable | |
| private String getActiveCarrierName() { | |
| CarrierConfigManager configManager = mContext.getSystemService(CarrierConfigManager.class); | |
| TelephonyManager telManager = mContext.getSystemService(TelephonyManager.class); | |
| String telName = telManager.getSimOperatorName(); | |
| if (configManager != null && configManager.getConfig() != null) { | |
| boolean override = | |
| configManager | |
| .getConfig() | |
| .getBoolean(CarrierConfigManager.KEY_CARRIER_NAME_OVERRIDE_BOOL); | |
| String configName = | |
| configManager | |
| .getConfig() | |
| .getString(CarrierConfigManager.KEY_CARRIER_NAME_STRING); | |
| return override || TextUtils.isEmpty(telName) ? configName : telName; | |
| } | |
| return telName; | |
| } | |
| } |