• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2014 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.provider.Settings.ENABLE_MMS_DATA_REQUEST_REASON_INCOMING_MMS;
20 import static android.provider.Settings.ENABLE_MMS_DATA_REQUEST_REASON_OUTGOING_MMS;
21 import static android.provider.Settings.EXTRA_ENABLE_MMS_DATA_REQUEST_REASON;
22 import static android.provider.Settings.EXTRA_SUB_ID;
23 import static android.telephony.TelephonyManager.EXTRA_DEFAULT_SUBSCRIPTION_SELECT_TYPE;
24 import static android.telephony.TelephonyManager.EXTRA_DEFAULT_SUBSCRIPTION_SELECT_TYPE_ALL;
25 import static android.telephony.TelephonyManager.EXTRA_DEFAULT_SUBSCRIPTION_SELECT_TYPE_DATA;
26 import static android.telephony.TelephonyManager.EXTRA_DEFAULT_SUBSCRIPTION_SELECT_TYPE_DISMISS;
27 import static android.telephony.TelephonyManager.EXTRA_DEFAULT_SUBSCRIPTION_SELECT_TYPE_NONE;
28 import static android.telephony.TelephonyManager.EXTRA_SIM_COMBINATION_NAMES;
29 import static android.telephony.TelephonyManager.EXTRA_SIM_COMBINATION_WARNING_TYPE;
30 import static android.telephony.TelephonyManager.EXTRA_SIM_COMBINATION_WARNING_TYPE_DUAL_CDMA;
31 import static android.telephony.TelephonyManager.EXTRA_SIM_COMBINATION_WARNING_TYPE_NONE;
32 import static android.telephony.TelephonyManager.EXTRA_SUBSCRIPTION_ID;
33 import static android.telephony.data.ApnSetting.TYPE_MMS;
34 
35 import static com.android.settings.Utils.SETTINGS_PACKAGE_NAME;
36 
37 import android.app.Notification;
38 import android.app.NotificationChannel;
39 import android.app.NotificationManager;
40 import android.app.PendingIntent;
41 import android.content.BroadcastReceiver;
42 import android.content.Context;
43 import android.content.Intent;
44 import android.content.res.Resources;
45 import android.os.UserManager;
46 import android.provider.Settings;
47 import android.telephony.SubscriptionInfo;
48 import android.telephony.SubscriptionManager;
49 import android.telephony.TelephonyManager;
50 import android.util.Log;
51 
52 import androidx.annotation.NonNull;
53 import androidx.annotation.WorkerThread;
54 
55 import com.android.internal.annotations.VisibleForTesting;
56 import com.android.settings.HelpTrampoline;
57 import com.android.settings.R;
58 import com.android.settings.network.SatelliteRepository;
59 import com.android.settings.network.SubscriptionUtil;
60 
61 import com.google.common.util.concurrent.ListenableFuture;
62 
63 import java.util.concurrent.ExecutionException;
64 import java.util.concurrent.Executor;
65 import java.util.concurrent.Executors;
66 import java.util.concurrent.TimeUnit;
67 import java.util.concurrent.TimeoutException;
68 
69 public class SimSelectNotification extends BroadcastReceiver {
70     private static final String TAG = "SimSelectNotification";
71 
72     private static final int DEFAULT_TIMEOUT_MS = 1000;
73 
74     @VisibleForTesting
75     public static final int SIM_SELECT_NOTIFICATION_ID = 1;
76     @VisibleForTesting
77     public static final int ENABLE_MMS_NOTIFICATION_ID = 2;
78     @VisibleForTesting
79     public static final int SIM_WARNING_NOTIFICATION_ID = 3;
80 
81     @VisibleForTesting
82     public static final String SIM_SELECT_NOTIFICATION_CHANNEL =
83             "sim_select_notification_channel";
84 
85     @VisibleForTesting
86     public static final String ENABLE_MMS_NOTIFICATION_CHANNEL =
87             "enable_mms_notification_channel";
88 
89     @VisibleForTesting
90     public static final String SIM_WARNING_NOTIFICATION_CHANNEL =
91             "sim_warning_notification_channel";
92 
93     @Override
onReceive(Context context, Intent intent)94     public void onReceive(Context context, Intent intent) {
95         UserManager userManager = context.getSystemService(UserManager.class);
96         if (userManager != null && !userManager.isMainUser()) {
97             Log.d(TAG, "The userId is not the main user");
98             return;
99         }
100         if (!SubscriptionUtil.isSimHardwareVisible(context)) {
101             Log.w(TAG, "Received unexpected intent with null action.");
102             return;
103         }
104         String action = intent.getAction();
105 
106         if (action == null) {
107             Log.w(TAG, "Received unexpected intent with null action.");
108             return;
109         }
110 
111         switch (action) {
112             case TelephonyManager.ACTION_PRIMARY_SUBSCRIPTION_LIST_CHANGED:
113                 PrimarySubscriptionListChangedService.scheduleJob(context, intent);
114                 break;
115             case Settings.ACTION_ENABLE_MMS_DATA_REQUEST:
116                 onEnableMmsDataRequest(context, intent);
117                 break;
118             default:
119                 Log.w(TAG, "Received unexpected intent " + intent.getAction());
120         }
121     }
122 
onEnableMmsDataRequest(Context context, Intent intent)123     private void onEnableMmsDataRequest(Context context, Intent intent) {
124         // Getting subId from extra.
125         int subId = intent.getIntExtra(EXTRA_SUB_ID, SubscriptionManager.INVALID_SUBSCRIPTION_ID);
126         if (subId == SubscriptionManager.DEFAULT_SUBSCRIPTION_ID) {
127             subId = SubscriptionManager.getDefaultSmsSubscriptionId();
128         }
129 
130         SubscriptionManager subscriptionManager = ((SubscriptionManager) context.getSystemService(
131                 Context.TELEPHONY_SUBSCRIPTION_SERVICE));
132         if (!subscriptionManager.isActiveSubscriptionId(subId)) {
133             Log.w(TAG, "onEnableMmsDataRequest invalid sub ID " + subId);
134             return;
135         }
136         final SubscriptionInfo info = subscriptionManager.getActiveSubscriptionInfo(subId);
137         if (info == null) {
138             Log.w(TAG, "onEnableMmsDataRequest null SubscriptionInfo for sub ID " + subId);
139             return;
140         }
141 
142         // Getting request reason from extra, which will determine the notification title.
143         CharSequence notificationTitle = null;
144         int requestReason = intent.getIntExtra(EXTRA_ENABLE_MMS_DATA_REQUEST_REASON, -1);
145         if (requestReason == ENABLE_MMS_DATA_REQUEST_REASON_INCOMING_MMS) {
146             notificationTitle = context.getResources().getText(
147                     R.string.enable_receiving_mms_notification_title);
148         } else if (requestReason == ENABLE_MMS_DATA_REQUEST_REASON_OUTGOING_MMS) {
149             notificationTitle = context.getResources().getText(
150                     R.string.enable_sending_mms_notification_title);
151         } else {
152             Log.w(TAG, "onEnableMmsDataRequest invalid request reason " + requestReason);
153             return;
154         }
155 
156         TelephonyManager tm = ((TelephonyManager) context.getSystemService(
157                 Context.TELEPHONY_SERVICE)).createForSubscriptionId(subId);
158 
159         if (tm.isDataEnabledForApn(TYPE_MMS)) {
160             Log.w(TAG, "onEnableMmsDataRequest MMS data already enabled on sub ID " + subId);
161             return;
162         }
163 
164         CharSequence notificationSummary = context.getResources().getString(
165                 R.string.enable_mms_notification_summary,
166                 SubscriptionUtil.getUniqueSubscriptionDisplayName(info, context));
167 
168         cancelEnableMmsNotification(context);
169 
170         createEnableMmsNotification(context, notificationTitle, notificationSummary, subId);
171     }
172 
173     /**
174      * Handles changes to the primary subscription list, performing actions only
175      * if the device is not currently in a satellite session. This method is
176      * intended to be executed on a worker thread.
177      *
178      * @param context The application context
179      * @param intent  The intent signaling a primary subscription change
180      */
181     @WorkerThread
onPrimarySubscriptionListChanged(@onNull Context context, @NonNull Intent intent)182     public static void onPrimarySubscriptionListChanged(@NonNull Context context,
183             @NonNull Intent intent) {
184         Log.d(TAG, "Checking satellite enabled status");
185         Executor executor = Executors.newSingleThreadExecutor();
186         ListenableFuture<Boolean> isSatelliteSessionStartedFuture =
187                 new SatelliteRepository(context).requestIsSessionStarted(executor);
188         boolean isSatelliteSessionStarted = false;
189         try {
190             isSatelliteSessionStarted =
191                     isSatelliteSessionStartedFuture.get(DEFAULT_TIMEOUT_MS, TimeUnit.MILLISECONDS);
192         } catch (InterruptedException | ExecutionException | TimeoutException e) {
193             Log.w(TAG, "Can't get satellite session status", e);
194         } finally {
195             if (isSatelliteSessionStarted) {
196                 Log.i(TAG, "Device is in a satellite session.g Unable to handle primary"
197                         + " subscription list changes");
198             } else {
199                 Log.i(TAG, "Device is not in a satellite session. Handle primary"
200                         + " subscription list changes");
201                 startSimSelectDialogIfNeeded(context, intent);
202                 sendSimCombinationWarningIfNeeded(context, intent);
203             }
204         }
205     }
206 
startSimSelectDialogIfNeeded(Context context, Intent intent)207     private static void startSimSelectDialogIfNeeded(Context context, Intent intent) {
208         int dialogType = intent.getIntExtra(EXTRA_DEFAULT_SUBSCRIPTION_SELECT_TYPE,
209                 EXTRA_DEFAULT_SUBSCRIPTION_SELECT_TYPE_NONE);
210 
211         if (dialogType == EXTRA_DEFAULT_SUBSCRIPTION_SELECT_TYPE_NONE) {
212             return;
213         }
214 
215         // Cancel any previous notifications
216         cancelSimSelectNotification(context);
217 
218         // If the dialog type is to dismiss.
219         if (dialogType == EXTRA_DEFAULT_SUBSCRIPTION_SELECT_TYPE_DISMISS) {
220             SimDialogProhibitService.dismissDialog(context);
221             return;
222         }
223 
224         // Create a notification to tell the user that some defaults are missing
225         createSimSelectNotification(context);
226 
227         if (dialogType == EXTRA_DEFAULT_SUBSCRIPTION_SELECT_TYPE_ALL) {
228             int subId = intent.getIntExtra(EXTRA_SUBSCRIPTION_ID,
229                     SubscriptionManager.DEFAULT_SUBSCRIPTION_ID);
230             int slotIndex = SubscriptionManager.getSlotIndex(subId);
231             // If there is only one subscription, ask if user wants to use if for everything
232             Intent newIntent = new Intent(context, SimDialogActivity.class);
233             newIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
234             newIntent.putExtra(SimDialogActivity.DIALOG_TYPE_KEY,
235                     SimDialogActivity.PREFERRED_PICK);
236             newIntent.putExtra(SimDialogActivity.PREFERRED_SIM, slotIndex);
237             context.startActivity(newIntent);
238         } else if (dialogType == EXTRA_DEFAULT_SUBSCRIPTION_SELECT_TYPE_DATA) {
239             // If there are multiple, ensure they pick default data
240             Intent newIntent = new Intent(context, SimDialogActivity.class);
241             newIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
242             newIntent.putExtra(SimDialogActivity.DIALOG_TYPE_KEY, SimDialogActivity.DATA_PICK);
243             context.startActivity(newIntent);
244         }
245     }
246 
sendSimCombinationWarningIfNeeded(Context context, Intent intent)247     private static void sendSimCombinationWarningIfNeeded(Context context, Intent intent) {
248         final int warningType = intent.getIntExtra(EXTRA_SIM_COMBINATION_WARNING_TYPE,
249                 EXTRA_SIM_COMBINATION_WARNING_TYPE_NONE);
250 
251         // Cancel any previous notifications
252         cancelSimCombinationWarningNotification(context);
253 
254         if (warningType == EXTRA_SIM_COMBINATION_WARNING_TYPE_DUAL_CDMA) {
255             // Create a notification to tell the user that there's a sim combination warning.
256             createSimCombinationWarningNotification(context, intent);
257         }
258     }
259 
createSimSelectNotification(Context context)260     private static void createSimSelectNotification(Context context) {
261         final Resources resources = context.getResources();
262 
263         NotificationChannel notificationChannel = new NotificationChannel(
264                 SIM_SELECT_NOTIFICATION_CHANNEL,
265                 resources.getText(R.string.sim_selection_channel_title),
266                 NotificationManager.IMPORTANCE_LOW);
267 
268         Notification.Builder builder =
269                 new Notification.Builder(context, SIM_SELECT_NOTIFICATION_CHANNEL)
270                         .setSmallIcon(R.drawable.ic_sim_alert)
271                         .setColor(context.getColor(R.color.sim_noitification))
272                         .setContentTitle(resources.getText(R.string.sim_notification_title))
273                         .setContentText(resources.getText(R.string.sim_notification_summary))
274                         .setAutoCancel(true);
275         Intent resultIntent = new Intent(Settings.ACTION_WIRELESS_SETTINGS);
276         resultIntent.setPackage(SETTINGS_PACKAGE_NAME);
277         resultIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
278         PendingIntent resultPendingIntent = PendingIntent.getActivity(context, 0, resultIntent,
279                 PendingIntent.FLAG_CANCEL_CURRENT | PendingIntent.FLAG_IMMUTABLE);
280         builder.setContentIntent(resultPendingIntent);
281         NotificationManager notificationManager =
282                 (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
283         notificationManager.createNotificationChannel(notificationChannel);
284         notificationManager.notify(SIM_SELECT_NOTIFICATION_ID, builder.build());
285     }
286 
cancelSimSelectNotification(Context context)287     public static void cancelSimSelectNotification(Context context) {
288         NotificationManager notificationManager =
289                 (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
290         notificationManager.cancel(SIM_SELECT_NOTIFICATION_ID);
291     }
292 
createEnableMmsNotification(Context context, CharSequence titleString, CharSequence notificationSummary, int subId)293     private void createEnableMmsNotification(Context context, CharSequence titleString,
294             CharSequence notificationSummary, int subId) {
295         final Resources resources = context.getResources();
296 
297         NotificationChannel notificationChannel = new NotificationChannel(
298                 ENABLE_MMS_NOTIFICATION_CHANNEL,
299                 resources.getText(R.string.enable_mms_notification_channel_title),
300                 NotificationManager.IMPORTANCE_HIGH);
301 
302         Notification.Builder builder =
303                 new Notification.Builder(context, ENABLE_MMS_NOTIFICATION_CHANNEL)
304                         .setSmallIcon(R.drawable.ic_settings_24dp)
305                         .setColor(context.getColor(R.color.sim_noitification))
306                         .setContentTitle(titleString)
307                         .setContentText(notificationSummary)
308                         .setStyle(new Notification.BigTextStyle().bigText(notificationSummary))
309                         .setAutoCancel(true);
310 
311         // Create the pending intent that will lead to the subscription setting page.
312         Intent resultIntent = new Intent(Settings.ACTION_MMS_MESSAGE_SETTING);
313         resultIntent.setPackage(SETTINGS_PACKAGE_NAME);
314         resultIntent.putExtra(Settings.EXTRA_SUB_ID, subId);
315         PendingIntent resultPendingIntent = PendingIntent.getActivity(context, 0, resultIntent,
316                 PendingIntent.FLAG_CANCEL_CURRENT | PendingIntent.FLAG_IMMUTABLE);
317         builder.setContentIntent(resultPendingIntent);
318 
319         // Notify the notification.
320         NotificationManager notificationManager =
321                 (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
322         notificationManager.createNotificationChannel(notificationChannel);
323         notificationManager.notify(ENABLE_MMS_NOTIFICATION_ID, builder.build());
324     }
325 
cancelEnableMmsNotification(Context context)326     private void cancelEnableMmsNotification(Context context) {
327         NotificationManager notificationManager =
328                 (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
329         notificationManager.cancel(ENABLE_MMS_NOTIFICATION_ID);
330     }
331 
createSimCombinationWarningNotification(Context context, Intent intent)332     private static void createSimCombinationWarningNotification(Context context, Intent intent) {
333         final Resources resources = context.getResources();
334         final String simNames = intent.getStringExtra(EXTRA_SIM_COMBINATION_NAMES);
335 
336         if (simNames == null) {
337             return;
338         }
339 
340         CharSequence dualCdmaSimWarningSummary = resources.getString(
341                 R.string.dual_cdma_sim_warning_notification_summary, simNames);
342 
343         NotificationChannel notificationChannel = new NotificationChannel(
344                 SIM_WARNING_NOTIFICATION_CHANNEL,
345                 resources.getText(R.string.dual_cdma_sim_warning_notification_channel_title),
346                 NotificationManager.IMPORTANCE_HIGH);
347 
348         Notification.Builder builder =
349                 new Notification.Builder(context, SIM_WARNING_NOTIFICATION_CHANNEL)
350                         .setSmallIcon(R.drawable.ic_sim_alert)
351                         .setColor(context.getColor(R.color.sim_noitification))
352                         .setContentTitle(resources.getText(
353                                 R.string.sim_combination_warning_notification_title))
354                         .setContentText(dualCdmaSimWarningSummary)
355                         .setStyle(new Notification.BigTextStyle().bigText(
356                                 dualCdmaSimWarningSummary))
357                         .setAutoCancel(true);
358 
359         // Create the pending intent that will lead to the helper page.
360         Intent resultIntent = new Intent(context, HelpTrampoline.class);
361         resultIntent.putExtra(Intent.EXTRA_TEXT, "help_uri_sim_combination_warning");
362 
363         PendingIntent resultPendingIntent = PendingIntent.getActivity(context, 0, resultIntent,
364                 PendingIntent.FLAG_CANCEL_CURRENT | PendingIntent.FLAG_IMMUTABLE);
365         builder.setContentIntent(resultPendingIntent);
366 
367         NotificationManager notificationManager =
368                 context.getSystemService(NotificationManager.class);
369         notificationManager.createNotificationChannel(notificationChannel);
370         notificationManager.notify(SIM_WARNING_NOTIFICATION_ID, builder.build());
371     }
372 
cancelSimCombinationWarningNotification(Context context)373     public static void cancelSimCombinationWarningNotification(Context context) {
374         NotificationManager notificationManager =
375                 context.getSystemService(NotificationManager.class);
376         notificationManager.cancel(SIM_WARNING_NOTIFICATION_ID);
377     }
378 }
379