From 7629de08dd50ec363932f0be9b8194d9810fbe4b Mon Sep 17 00:00:00 2001 From: Jiashen Wang Date: Tue, 24 Nov 2020 19:03:33 -0800 Subject: [PATCH] [SIM Dialog Migration] Sending push notification after DSDS reboot After DSDS reboot, send a push notification to users for SIM configration. Design: https://docs.google.com/document/d/1wb5_hoBkZVbkXGNWHbx4Jf61swjfxsJzkytiTzJosYo/edit?usp=sharing Bug: 160819390 Test: Manually tested eSIM profile enabling. Change-Id: Ic0bf2e356bf208d16e2c5a9a380e542fcb8f2b1e --- AndroidManifest.xml | 11 ++ res/values/integers.xml | 1 + res/values/strings.xml | 11 ++ .../ToggleSubscriptionDialogActivity.java | 4 +- .../settings/sim/SimActivationNotifier.java | 144 ++++++++++++++++++ .../settings/sim/SimNotificationService.java | 81 ++++++++++ .../receivers/SimCompleteBootReceiver.java | 42 +++++ 7 files changed, 292 insertions(+), 2 deletions(-) create mode 100644 src/com/android/settings/sim/SimActivationNotifier.java create mode 100644 src/com/android/settings/sim/SimNotificationService.java create mode 100644 src/com/android/settings/sim/receivers/SimCompleteBootReceiver.java diff --git a/AndroidManifest.xml b/AndroidManifest.xml index 3cf759470b8..9b8327c30f2 100644 --- a/AndroidManifest.xml +++ b/AndroidManifest.xml @@ -3652,6 +3652,17 @@ + + + + + + + + diff --git a/res/values/integers.xml b/res/values/integers.xml index 7a6e0aa6d31..3d73f64fabe 100644 --- a/res/values/integers.xml +++ b/res/values/integers.xml @@ -20,4 +20,5 @@ 101 102 103 + 104 diff --git a/res/values/strings.xml b/res/values/strings.xml index 041dbdd771b..ee5b87f5b80 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -12083,6 +12083,17 @@ Try turning on the SIM again. If the problem continues, restart your device. + + + Network activation + + %1$s is active + + Tap to update SIM settings + + + SIM card + Erase this downloaded SIM? diff --git a/src/com/android/settings/network/telephony/ToggleSubscriptionDialogActivity.java b/src/com/android/settings/network/telephony/ToggleSubscriptionDialogActivity.java index 919415b53e0..1dc843a0c6e 100644 --- a/src/com/android/settings/network/telephony/ToggleSubscriptionDialogActivity.java +++ b/src/com/android/settings/network/telephony/ToggleSubscriptionDialogActivity.java @@ -34,6 +34,7 @@ import com.android.settings.network.SubscriptionUtil; import com.android.settings.network.SwitchToEuiccSubscriptionSidecar; import com.android.settings.network.SwitchToRemovableSlotSidecar; import com.android.settings.network.UiccSlotUtil; +import com.android.settings.sim.SimActivationNotifier; import com.google.common.collect.ImmutableList; @@ -189,9 +190,8 @@ public class ToggleSubscriptionDialogActivity extends SubscriptionActionDialogAc return; } Log.i(TAG, "User confirmed reboot to enable DSDS."); + SimActivationNotifier.setShowSimSettingsNotification(this, true); mTelMgr.switchMultiSimConfig(NUM_OF_SIMS_FOR_DSDS); - // TODO(b/170507290): Store a bit in preferences for displaying the notification - // after the reboot. break; case DIALOG_TAG_ENABLE_SIM_CONFIRMATION: Log.i(TAG, "User confirmed to enable the subscription."); diff --git a/src/com/android/settings/sim/SimActivationNotifier.java b/src/com/android/settings/sim/SimActivationNotifier.java new file mode 100644 index 00000000000..85d3da2cd35 --- /dev/null +++ b/src/com/android/settings/sim/SimActivationNotifier.java @@ -0,0 +1,144 @@ +/* + * 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.SubscriptionInfo; +import android.telephony.SubscriptionManager; +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; + +/** + * 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 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; + + /** Notification types */ + @Retention(RetentionPolicy.SOURCE) + @IntDef( + value = { + NotificationType.NETWORK_CONFIG, + }) + public @interface NotificationType { + // The notification to remind users to config network Settings. + int NETWORK_CONFIG = 1; + } + + 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)); + } + + /** + * 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() { + SubscriptionManager subscriptionManager = + mContext.getSystemService(SubscriptionManager.class); + SubscriptionInfo activeRemovableSub = + SubscriptionUtil.getActiveSubscriptions(subscriptionManager).stream() + .filter(sub -> !sub.isEmbedded()) + .findFirst() + .orElse(null); + + if (activeRemovableSub == null) { + Log.e(TAG, "No removable subscriptions found. Do not show notification."); + return; + } + + String carrierName = + TextUtils.isEmpty(activeRemovableSub.getDisplayName()) + ? mContext.getString(R.string.sim_card_label) + : activeRemovableSub.getDisplayName().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); + + 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()); + } +} diff --git a/src/com/android/settings/sim/SimNotificationService.java b/src/com/android/settings/sim/SimNotificationService.java new file mode 100644 index 00000000000..303c21d02c8 --- /dev/null +++ b/src/com/android/settings/sim/SimNotificationService.java @@ -0,0 +1,81 @@ +/* + * 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 android.app.job.JobInfo; +import android.app.job.JobParameters; +import android.app.job.JobScheduler; +import android.app.job.JobService; +import android.content.ComponentName; +import android.content.Context; +import android.os.PersistableBundle; +import android.util.Log; + +import com.android.settings.R; + +/** A JobService sends SIM notifications. */ +public class SimNotificationService extends JobService { + + private static final String TAG = "SimNotificationService"; + private static final String EXTRA_NOTIFICATION_TYPE = "notification_type"; + + /** + * Schedules a service to send SIM push notifications. + * @param context + * @param notificationType indicates which SIM notification to send. + */ + public static void scheduleSimNotification( + Context context, @SimActivationNotifier.NotificationType int notificationType) { + final JobScheduler jobScheduler = + context.getApplicationContext().getSystemService(JobScheduler.class); + final ComponentName component = + new ComponentName(context.getApplicationContext(), SimNotificationService.class); + PersistableBundle extra = new PersistableBundle(); + extra.putInt(EXTRA_NOTIFICATION_TYPE, notificationType); + + jobScheduler.schedule( + new JobInfo.Builder(R.integer.sim_notification_send, component) + .setExtras(extra) + .build()); + } + + @Override + public boolean onStartJob(JobParameters params) { + PersistableBundle extra = params.getExtras(); + if (extra == null) { + Log.e(TAG, "Failed to get notification type."); + return false; + } + int notificationType = extra.getInt(EXTRA_NOTIFICATION_TYPE); + switch (notificationType) { + case SimActivationNotifier.NotificationType.NETWORK_CONFIG: + Log.i(TAG, "Sending SIM config notification."); + SimActivationNotifier.setShowSimSettingsNotification(this, false); + new SimActivationNotifier(this).sendNetworkConfigNotification(); + break; + default: + Log.e(TAG, "Invalid notification type: " + notificationType); + break; + } + return false; + } + + @Override + public boolean onStopJob(JobParameters params) { + return false; + } +} diff --git a/src/com/android/settings/sim/receivers/SimCompleteBootReceiver.java b/src/com/android/settings/sim/receivers/SimCompleteBootReceiver.java new file mode 100644 index 00000000000..e9acf94976e --- /dev/null +++ b/src/com/android/settings/sim/receivers/SimCompleteBootReceiver.java @@ -0,0 +1,42 @@ +/* + * 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.receivers; + +import android.content.BroadcastReceiver; +import android.content.Context; +import android.content.Intent; +import android.util.Log; + +import com.android.settings.sim.SimActivationNotifier; +import com.android.settings.sim.SimNotificationService; + +/** This class manage all SIM operations after device boot up. */ +public class SimCompleteBootReceiver extends BroadcastReceiver { + private static final String TAG = "SimCompleteBootReceiver"; + + @Override + public void onReceive(Context context, Intent intent) { + if (!Intent.ACTION_BOOT_COMPLETED.equals(intent.getAction())) { + Log.e(TAG, "Invalid broadcast received."); + return; + } + if (SimActivationNotifier.getShowSimSettingsNotification(context)) { + SimNotificationService.scheduleSimNotification( + context, SimActivationNotifier.NotificationType.NETWORK_CONFIG); + } + } +}