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