1 /*
2  * Copyright (C) 2016 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 package com.android.carrierdefaultapp;
17 
18 import android.app.Notification;
19 import android.app.NotificationChannel;
20 import android.app.NotificationManager;
21 import android.app.PendingIntent;
22 import android.content.ComponentName;
23 import android.content.Context;
24 import android.content.Intent;
25 import android.content.pm.PackageManager;
26 import android.content.res.Resources;
27 import android.os.Bundle;
28 import android.telephony.SubscriptionManager;
29 import android.telephony.TelephonyManager;
30 import android.text.TextUtils;
31 import android.util.Log;
32 
33 /**
34  * This util class provides common logic for carrier actions
35  */
36 public class CarrierActionUtils {
37     private static final String TAG = CarrierActionUtils.class.getSimpleName();
38 
39     private static final String PORTAL_NOTIFICATION_TAG = "CarrierDefault.Portal.Notification";
40     private static final String NO_DATA_NOTIFICATION_TAG = "CarrierDefault.NoData.Notification";
41     private static final String NOTIFICATION_CHANNEL_ID_MOBILE_DATA_STATUS = "mobile_data_status";
42     private static final int PORTAL_NOTIFICATION_ID = 0;
43     private static final int NO_DATA_NOTIFICATION_ID = 1;
44     private static boolean ENABLE = true;
45 
46     // A list of supported carrier action idx
47     public static final int CARRIER_ACTION_ENABLE_METERED_APNS               = 0;
48     public static final int CARRIER_ACTION_DISABLE_METERED_APNS              = 1;
49     public static final int CARRIER_ACTION_DISABLE_RADIO                     = 2;
50     public static final int CARRIER_ACTION_ENABLE_RADIO                      = 3;
51     public static final int CARRIER_ACTION_SHOW_PORTAL_NOTIFICATION          = 4;
52     public static final int CARRIER_ACTION_SHOW_NO_DATA_SERVICE_NOTIFICATION = 5;
53     public static final int CARRIER_ACTION_CANCEL_ALL_NOTIFICATIONS          = 6;
54     public static final int CARRIER_ACTION_ENABLE_DEFAULT_URL_HANDLER        = 7;
55     public static final int CARRIER_ACTION_DISABLE_DEFAULT_URL_HANDLER       = 8;
56     public static final int CARRIER_ACTION_REGISTER_DEFAULT_NETWORK_AVAIL    = 9;
57     public static final int CARRIER_ACTION_DEREGISTER_DEFAULT_NETWORK_AVAIL  = 10;
58     public static final int CARRIER_ACTION_RESET_ALL                         = 11;
59 
applyCarrierAction(int actionIdx, Intent intent, Context context)60     public static void applyCarrierAction(int actionIdx, Intent intent, Context context) {
61         switch (actionIdx) {
62             case CARRIER_ACTION_ENABLE_METERED_APNS:
63                 onEnableAllMeteredApns(intent, context);
64                 break;
65             case CARRIER_ACTION_DISABLE_METERED_APNS:
66                 onDisableAllMeteredApns(intent, context);
67                 break;
68             case CARRIER_ACTION_DISABLE_RADIO:
69                 onDisableRadio(intent, context);
70                 break;
71             case CARRIER_ACTION_ENABLE_RADIO:
72                 onEnableRadio(intent, context);
73                 break;
74             case CARRIER_ACTION_SHOW_PORTAL_NOTIFICATION:
75                 onShowCaptivePortalNotification(intent, context);
76                 break;
77             case CARRIER_ACTION_SHOW_NO_DATA_SERVICE_NOTIFICATION:
78                 onShowNoDataServiceNotification(context);
79                 break;
80             case CARRIER_ACTION_CANCEL_ALL_NOTIFICATIONS:
81                 onCancelAllNotifications(context);
82                 break;
83             case CARRIER_ACTION_ENABLE_DEFAULT_URL_HANDLER:
84                 onEnableDefaultURLHandler(context);
85                 break;
86             case CARRIER_ACTION_DISABLE_DEFAULT_URL_HANDLER:
87                 onDisableDefaultURLHandler(context);
88                 break;
89             case CARRIER_ACTION_REGISTER_DEFAULT_NETWORK_AVAIL:
90                 onRegisterDefaultNetworkAvail(intent, context);
91                 break;
92             case CARRIER_ACTION_DEREGISTER_DEFAULT_NETWORK_AVAIL:
93                 onDeregisterDefaultNetworkAvail(intent, context);
94                 break;
95             case CARRIER_ACTION_RESET_ALL:
96                 onResetAllCarrierActions(intent, context);
97                 break;
98             default:
99                 loge("unsupported carrier action index: " + actionIdx);
100         }
101     }
102 
onDisableAllMeteredApns(Intent intent, Context context)103     private static void onDisableAllMeteredApns(Intent intent, Context context) {
104         int subId = intent.getIntExtra(SubscriptionManager.EXTRA_SUBSCRIPTION_INDEX,
105                 SubscriptionManager.getDefaultVoiceSubscriptionId());
106         logd("onDisableAllMeteredApns subId: " + subId);
107         final TelephonyManager telephonyMgr = context.getSystemService(TelephonyManager.class);
108         telephonyMgr.createForSubscriptionId(subId).setCarrierDataEnabled(!ENABLE);
109     }
110 
onEnableAllMeteredApns(Intent intent, Context context)111     private static void onEnableAllMeteredApns(Intent intent, Context context) {
112         int subId = intent.getIntExtra(SubscriptionManager.EXTRA_SUBSCRIPTION_INDEX,
113                 SubscriptionManager.getDefaultVoiceSubscriptionId());
114         logd("onEnableAllMeteredApns subId: " + subId);
115         final TelephonyManager telephonyMgr = context.getSystemService(TelephonyManager.class);
116         telephonyMgr.createForSubscriptionId(subId).setCarrierDataEnabled(ENABLE);
117     }
118 
onEnableDefaultURLHandler(Context context)119     private static void onEnableDefaultURLHandler(Context context) {
120         logd("onEnableDefaultURLHandler");
121         final PackageManager pm = context.getPackageManager();
122         pm.setComponentEnabledSetting(
123                 new ComponentName(context, CaptivePortalLoginActivity.getAlias(context)),
124                 PackageManager.COMPONENT_ENABLED_STATE_ENABLED, PackageManager.DONT_KILL_APP);
125     }
126 
onDisableDefaultURLHandler(Context context)127     private static void onDisableDefaultURLHandler(Context context) {
128         logd("onDisableDefaultURLHandler");
129         final PackageManager pm = context.getPackageManager();
130         pm.setComponentEnabledSetting(
131                 new ComponentName(context, CaptivePortalLoginActivity.getAlias(context)),
132                 PackageManager.COMPONENT_ENABLED_STATE_DISABLED, PackageManager.DONT_KILL_APP);
133     }
134 
onRegisterDefaultNetworkAvail(Intent intent, Context context)135     private static void onRegisterDefaultNetworkAvail(Intent intent, Context context) {
136         int subId = intent.getIntExtra(SubscriptionManager.EXTRA_SUBSCRIPTION_INDEX,
137                 SubscriptionManager.getDefaultVoiceSubscriptionId());
138         logd("onRegisterDefaultNetworkAvail subId: " + subId);
139         final TelephonyManager telephonyMgr = context.getSystemService(TelephonyManager.class);
140         telephonyMgr.createForSubscriptionId(subId).reportDefaultNetworkStatus(true);
141     }
142 
onDeregisterDefaultNetworkAvail(Intent intent, Context context)143     private static void onDeregisterDefaultNetworkAvail(Intent intent, Context context) {
144         int subId = intent.getIntExtra(SubscriptionManager.EXTRA_SUBSCRIPTION_INDEX,
145                 SubscriptionManager.getDefaultVoiceSubscriptionId());
146         logd("onDeregisterDefaultNetworkAvail subId: " + subId);
147         final TelephonyManager telephonyMgr = context.getSystemService(TelephonyManager.class);
148         telephonyMgr.createForSubscriptionId(subId).reportDefaultNetworkStatus(false);
149     }
150 
onDisableRadio(Intent intent, Context context)151     private static void onDisableRadio(Intent intent, Context context) {
152         int subId = intent.getIntExtra(SubscriptionManager.EXTRA_SUBSCRIPTION_INDEX,
153                 SubscriptionManager.getDefaultVoiceSubscriptionId());
154         logd("onDisableRadio subId: " + subId);
155         final TelephonyManager telephonyMgr = context.getSystemService(TelephonyManager.class);
156         telephonyMgr.createForSubscriptionId(subId).setRadioEnabled(!ENABLE);
157     }
158 
onEnableRadio(Intent intent, Context context)159     private static void onEnableRadio(Intent intent, Context context) {
160         int subId = intent.getIntExtra(SubscriptionManager.EXTRA_SUBSCRIPTION_INDEX,
161                 SubscriptionManager.getDefaultVoiceSubscriptionId());
162         logd("onEnableRadio subId: " + subId);
163         final TelephonyManager telephonyMgr = context.getSystemService(TelephonyManager.class);
164         telephonyMgr.createForSubscriptionId(subId).setRadioEnabled(ENABLE);
165     }
166 
onShowCaptivePortalNotification(Intent intent, Context context)167     private static void onShowCaptivePortalNotification(Intent intent, Context context) {
168         logd("onShowCaptivePortalNotification");
169         Intent portalIntent = new Intent(context, CaptivePortalLoginActivity.class);
170         portalIntent.putExtras(intent);
171         portalIntent.setFlags(Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT
172                 | Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
173         PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, portalIntent,
174                 PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_MUTABLE_UNAUDITED);
175         Notification notification = getNotification(context, R.string.portal_notification_id,
176                 R.string.portal_notification_detail, pendingIntent);
177         try {
178             context.getSystemService(NotificationManager.class)
179                     .notify(PORTAL_NOTIFICATION_TAG, PORTAL_NOTIFICATION_ID, notification);
180         } catch (NullPointerException npe) {
181             loge("setNotificationVisible: " + npe);
182         }
183     }
184 
onShowNoDataServiceNotification(Context context)185     private static void onShowNoDataServiceNotification(Context context) {
186         logd("onShowNoDataServiceNotification");
187         Notification notification = getNotification(context, R.string.no_data_notification_id,
188                 R.string.no_data_notification_detail, null);
189         try {
190             context.getSystemService(NotificationManager.class)
191                     .notify(NO_DATA_NOTIFICATION_TAG, NO_DATA_NOTIFICATION_ID, notification);
192         } catch (NullPointerException npe) {
193             loge("setNotificationVisible: " + npe);
194         }
195     }
196 
onCancelAllNotifications(Context context)197     private static void onCancelAllNotifications(Context context) {
198         logd("onCancelAllNotifications");
199         context.getSystemService(NotificationManager.class).cancelAll();
200     }
201 
onResetAllCarrierActions(Intent intent, Context context)202     private static void onResetAllCarrierActions(Intent intent, Context context) {
203         int subId = intent.getIntExtra(SubscriptionManager.EXTRA_SUBSCRIPTION_INDEX,
204                 SubscriptionManager.getDefaultVoiceSubscriptionId());
205         logd("onResetAllCarrierActions subId: " + subId);
206         final TelephonyManager telephonyMgr = context.getSystemService(TelephonyManager.class);
207         telephonyMgr.createForSubscriptionId(subId).resetAllCarrierActions();
208     }
209 
getNotification(Context context, int titleId, int textId, PendingIntent pendingIntent)210     private static Notification getNotification(Context context, int titleId, int textId,
211                                          PendingIntent pendingIntent) {
212         final TelephonyManager telephonyMgr = context.getSystemService(TelephonyManager.class);
213         final Resources resources = context.getResources();
214         String spn = telephonyMgr.getSimOperatorName();
215         if (TextUtils.isEmpty(spn)) {
216             // There is no consistent way to get the current carrier name as MNOs didn't
217             // bother to set EF_SPN. in the long term, we should display a generic wording if
218             // spn from subscription is not set.
219             spn = telephonyMgr.getNetworkOperatorName();
220         }
221         final Bundle extras = Bundle.forPair(Notification.EXTRA_SUBSTITUTE_APP_NAME,
222                 resources.getString(R.string.android_system_label));
223         createNotificationChannels(context);
224         Notification.Builder builder = new Notification.Builder(context)
225                 .setContentTitle(resources.getString(titleId))
226                 .setContentText(String.format(resources.getString(textId), spn))
227                 .setSmallIcon(R.drawable.ic_sim_card)
228                 .setColor(context.getColor(
229                         com.android.internal.R.color.system_notification_accent_color))
230                 .setOngoing(true)
231                 .setPriority(Notification.PRIORITY_HIGH)
232                 .setDefaults(Notification.DEFAULT_ALL)
233                 .setVisibility(Notification.VISIBILITY_PUBLIC)
234                 .setLocalOnly(true)
235                 .setWhen(System.currentTimeMillis())
236                 .setShowWhen(false)
237                 .setExtras(extras)
238                 .setChannel(NOTIFICATION_CHANNEL_ID_MOBILE_DATA_STATUS);
239 
240         if (pendingIntent != null) {
241             builder.setContentIntent(pendingIntent);
242         }
243         return builder.build();
244     }
245 
246     /**
247      * Creates the notification channel and registers it with NotificationManager. Also used to
248      * update an existing channel's name.
249      */
createNotificationChannels(Context context)250     static void createNotificationChannels(Context context) {
251         context.getSystemService(NotificationManager.class)
252                 .createNotificationChannel(new NotificationChannel(
253                 NOTIFICATION_CHANNEL_ID_MOBILE_DATA_STATUS,
254                 context.getResources().getString(
255                         R.string.mobile_data_status_notification_channel_name),
256                 NotificationManager.IMPORTANCE_DEFAULT));
257     }
258 
logd(String s)259     private static void logd(String s) {
260         Log.d(TAG, s);
261     }
262 
loge(String s)263     private static void loge(String s) {
264         Log.e(TAG, s);
265     }
266 }
267