/* * 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; } }