| /* |
| * Copyright (C) 2016 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.carrierdefaultapp; |
| |
| import android.app.Notification; |
| import android.app.NotificationChannel; |
| import android.app.NotificationManager; |
| import android.app.PendingIntent; |
| import android.content.ComponentName; |
| import android.content.Context; |
| import android.content.Intent; |
| import android.content.pm.PackageManager; |
| import android.content.res.Resources; |
| import android.os.Bundle; |
| import android.telephony.SubscriptionManager; |
| import android.telephony.TelephonyManager; |
| import android.text.TextUtils; |
| import android.util.Log; |
| |
| import com.android.internal.telephony.PhoneConstants; |
| |
| /** |
| * This util class provides common logic for carrier actions |
| */ |
| public class CarrierActionUtils { |
| private static final String TAG = CarrierActionUtils.class.getSimpleName(); |
| |
| private static final String PORTAL_NOTIFICATION_TAG = "CarrierDefault.Portal.Notification"; |
| private static final String NO_DATA_NOTIFICATION_TAG = "CarrierDefault.NoData.Notification"; |
| private static final String NOTIFICATION_CHANNEL_ID_MOBILE_DATA_STATUS = "mobile_data_status"; |
| private static final int PORTAL_NOTIFICATION_ID = 0; |
| private static final int NO_DATA_NOTIFICATION_ID = 1; |
| private static boolean ENABLE = true; |
| |
| // A list of supported carrier action idx |
| public static final int CARRIER_ACTION_ENABLE_METERED_APNS = 0; |
| public static final int CARRIER_ACTION_DISABLE_METERED_APNS = 1; |
| public static final int CARRIER_ACTION_DISABLE_RADIO = 2; |
| public static final int CARRIER_ACTION_ENABLE_RADIO = 3; |
| public static final int CARRIER_ACTION_SHOW_PORTAL_NOTIFICATION = 4; |
| public static final int CARRIER_ACTION_SHOW_NO_DATA_SERVICE_NOTIFICATION = 5; |
| public static final int CARRIER_ACTION_CANCEL_ALL_NOTIFICATIONS = 6; |
| public static final int CARRIER_ACTION_ENABLE_DEFAULT_URL_HANDLER = 7; |
| public static final int CARRIER_ACTION_DISABLE_DEFAULT_URL_HANDLER = 8; |
| public static final int CARRIER_ACTION_REGISTER_DEFAULT_NETWORK_AVAIL = 9; |
| public static final int CARRIER_ACTION_DEREGISTER_DEFAULT_NETWORK_AVAIL = 10; |
| public static final int CARRIER_ACTION_RESET_ALL = 11; |
| |
| public static void applyCarrierAction(int actionIdx, Intent intent, Context context) { |
| switch (actionIdx) { |
| case CARRIER_ACTION_ENABLE_METERED_APNS: |
| onEnableAllMeteredApns(intent, context); |
| break; |
| case CARRIER_ACTION_DISABLE_METERED_APNS: |
| onDisableAllMeteredApns(intent, context); |
| break; |
| case CARRIER_ACTION_DISABLE_RADIO: |
| onDisableRadio(intent, context); |
| break; |
| case CARRIER_ACTION_ENABLE_RADIO: |
| onEnableRadio(intent, context); |
| break; |
| case CARRIER_ACTION_SHOW_PORTAL_NOTIFICATION: |
| onShowCaptivePortalNotification(intent, context); |
| break; |
| case CARRIER_ACTION_SHOW_NO_DATA_SERVICE_NOTIFICATION: |
| onShowNoDataServiceNotification(context); |
| break; |
| case CARRIER_ACTION_CANCEL_ALL_NOTIFICATIONS: |
| onCancelAllNotifications(context); |
| break; |
| case CARRIER_ACTION_ENABLE_DEFAULT_URL_HANDLER: |
| onEnableDefaultURLHandler(context); |
| break; |
| case CARRIER_ACTION_DISABLE_DEFAULT_URL_HANDLER: |
| onDisableDefaultURLHandler(context); |
| break; |
| case CARRIER_ACTION_REGISTER_DEFAULT_NETWORK_AVAIL: |
| onRegisterDefaultNetworkAvail(intent, context); |
| break; |
| case CARRIER_ACTION_DEREGISTER_DEFAULT_NETWORK_AVAIL: |
| onDeregisterDefaultNetworkAvail(intent, context); |
| break; |
| case CARRIER_ACTION_RESET_ALL: |
| onResetAllCarrierActions(intent, context); |
| break; |
| default: |
| loge("unsupported carrier action index: " + actionIdx); |
| } |
| } |
| |
| private static void onDisableAllMeteredApns(Intent intent, Context context) { |
| int subId = intent.getIntExtra(PhoneConstants.SUBSCRIPTION_KEY, |
| SubscriptionManager.getDefaultVoiceSubscriptionId()); |
| logd("onDisableAllMeteredApns subId: " + subId); |
| final TelephonyManager telephonyMgr = context.getSystemService(TelephonyManager.class); |
| telephonyMgr.createForSubscriptionId(subId).setCarrierDataEnabled(!ENABLE); |
| } |
| |
| private static void onEnableAllMeteredApns(Intent intent, Context context) { |
| int subId = intent.getIntExtra(PhoneConstants.SUBSCRIPTION_KEY, |
| SubscriptionManager.getDefaultVoiceSubscriptionId()); |
| logd("onEnableAllMeteredApns subId: " + subId); |
| final TelephonyManager telephonyMgr = context.getSystemService(TelephonyManager.class); |
| telephonyMgr.createForSubscriptionId(subId).setCarrierDataEnabled(ENABLE); |
| } |
| |
| private static void onEnableDefaultURLHandler(Context context) { |
| logd("onEnableDefaultURLHandler"); |
| final PackageManager pm = context.getPackageManager(); |
| pm.setComponentEnabledSetting( |
| new ComponentName(context, CaptivePortalLoginActivity.getAlias(context)), |
| PackageManager.COMPONENT_ENABLED_STATE_ENABLED, PackageManager.DONT_KILL_APP); |
| } |
| |
| private static void onDisableDefaultURLHandler(Context context) { |
| logd("onDisableDefaultURLHandler"); |
| final PackageManager pm = context.getPackageManager(); |
| pm.setComponentEnabledSetting( |
| new ComponentName(context, CaptivePortalLoginActivity.getAlias(context)), |
| PackageManager.COMPONENT_ENABLED_STATE_DISABLED, PackageManager.DONT_KILL_APP); |
| } |
| |
| private static void onRegisterDefaultNetworkAvail(Intent intent, Context context) { |
| int subId = intent.getIntExtra(PhoneConstants.SUBSCRIPTION_KEY, |
| SubscriptionManager.getDefaultVoiceSubscriptionId()); |
| logd("onRegisterDefaultNetworkAvail subId: " + subId); |
| final TelephonyManager telephonyMgr = context.getSystemService(TelephonyManager.class); |
| telephonyMgr.createForSubscriptionId(subId).reportDefaultNetworkStatus(true); |
| } |
| |
| private static void onDeregisterDefaultNetworkAvail(Intent intent, Context context) { |
| int subId = intent.getIntExtra(PhoneConstants.SUBSCRIPTION_KEY, |
| SubscriptionManager.getDefaultVoiceSubscriptionId()); |
| logd("onDeregisterDefaultNetworkAvail subId: " + subId); |
| final TelephonyManager telephonyMgr = context.getSystemService(TelephonyManager.class); |
| telephonyMgr.createForSubscriptionId(subId).reportDefaultNetworkStatus(false); |
| } |
| |
| private static void onDisableRadio(Intent intent, Context context) { |
| int subId = intent.getIntExtra(PhoneConstants.SUBSCRIPTION_KEY, |
| SubscriptionManager.getDefaultVoiceSubscriptionId()); |
| logd("onDisableRadio subId: " + subId); |
| final TelephonyManager telephonyMgr = context.getSystemService(TelephonyManager.class); |
| telephonyMgr.createForSubscriptionId(subId).setRadioEnabled(!ENABLE); |
| } |
| |
| private static void onEnableRadio(Intent intent, Context context) { |
| int subId = intent.getIntExtra(PhoneConstants.SUBSCRIPTION_KEY, |
| SubscriptionManager.getDefaultVoiceSubscriptionId()); |
| logd("onEnableRadio subId: " + subId); |
| final TelephonyManager telephonyMgr = context.getSystemService(TelephonyManager.class); |
| telephonyMgr.createForSubscriptionId(subId).setRadioEnabled(ENABLE); |
| } |
| |
| private static void onShowCaptivePortalNotification(Intent intent, Context context) { |
| logd("onShowCaptivePortalNotification"); |
| Intent portalIntent = new Intent(context, CaptivePortalLoginActivity.class); |
| portalIntent.putExtras(intent); |
| portalIntent.setFlags(Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT |
| | Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK); |
| PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, portalIntent, |
| PendingIntent.FLAG_UPDATE_CURRENT); |
| Notification notification = getNotification(context, R.string.portal_notification_id, |
| R.string.portal_notification_detail, pendingIntent); |
| try { |
| context.getSystemService(NotificationManager.class) |
| .notify(PORTAL_NOTIFICATION_TAG, PORTAL_NOTIFICATION_ID, notification); |
| } catch (NullPointerException npe) { |
| loge("setNotificationVisible: " + npe); |
| } |
| } |
| |
| private static void onShowNoDataServiceNotification(Context context) { |
| logd("onShowNoDataServiceNotification"); |
| Notification notification = getNotification(context, R.string.no_data_notification_id, |
| R.string.no_data_notification_detail, null); |
| try { |
| context.getSystemService(NotificationManager.class) |
| .notify(NO_DATA_NOTIFICATION_TAG, NO_DATA_NOTIFICATION_ID, notification); |
| } catch (NullPointerException npe) { |
| loge("setNotificationVisible: " + npe); |
| } |
| } |
| |
| private static void onCancelAllNotifications(Context context) { |
| logd("onCancelAllNotifications"); |
| context.getSystemService(NotificationManager.class).cancelAll(); |
| } |
| |
| private static void onResetAllCarrierActions(Intent intent, Context context) { |
| int subId = intent.getIntExtra(PhoneConstants.SUBSCRIPTION_KEY, |
| SubscriptionManager.getDefaultVoiceSubscriptionId()); |
| logd("onResetAllCarrierActions subId: " + subId); |
| final TelephonyManager telephonyMgr = context.getSystemService(TelephonyManager.class); |
| telephonyMgr.createForSubscriptionId(subId).resetAllCarrierActions(); |
| } |
| |
| private static Notification getNotification(Context context, int titleId, int textId, |
| PendingIntent pendingIntent) { |
| final TelephonyManager telephonyMgr = context.getSystemService(TelephonyManager.class); |
| final Resources resources = context.getResources(); |
| String spn = telephonyMgr.getSimOperatorName(); |
| if (TextUtils.isEmpty(spn)) { |
| // There is no consistent way to get the current carrier name as MNOs didn't |
| // bother to set EF_SPN. in the long term, we should display a generic wording if |
| // spn from subscription is not set. |
| spn = telephonyMgr.getNetworkOperatorName(); |
| } |
| final Bundle extras = Bundle.forPair(Notification.EXTRA_SUBSTITUTE_APP_NAME, |
| resources.getString(R.string.android_system_label)); |
| createNotificationChannels(context); |
| Notification.Builder builder = new Notification.Builder(context) |
| .setContentTitle(resources.getString(titleId)) |
| .setContentText(String.format(resources.getString(textId), spn)) |
| .setSmallIcon(R.drawable.ic_sim_card) |
| .setColor(context.getColor( |
| com.android.internal.R.color.system_notification_accent_color)) |
| .setOngoing(true) |
| .setPriority(Notification.PRIORITY_HIGH) |
| .setDefaults(Notification.DEFAULT_ALL) |
| .setVisibility(Notification.VISIBILITY_PUBLIC) |
| .setLocalOnly(true) |
| .setWhen(System.currentTimeMillis()) |
| .setShowWhen(false) |
| .setExtras(extras) |
| .setChannel(NOTIFICATION_CHANNEL_ID_MOBILE_DATA_STATUS); |
| |
| if (pendingIntent != null) { |
| builder.setContentIntent(pendingIntent); |
| } |
| return builder.build(); |
| } |
| |
| /** |
| * Creates the notification channel and registers it with NotificationManager. Also used to |
| * update an existing channel's name. |
| */ |
| static void createNotificationChannels(Context context) { |
| context.getSystemService(NotificationManager.class) |
| .createNotificationChannel(new NotificationChannel( |
| NOTIFICATION_CHANNEL_ID_MOBILE_DATA_STATUS, |
| context.getResources().getString( |
| R.string.mobile_data_status_notification_channel_name), |
| NotificationManager.IMPORTANCE_DEFAULT)); |
| } |
| |
| private static void logd(String s) { |
| Log.d(TAG, s); |
| } |
| |
| private static void loge(String s) { |
| Log.e(TAG, s); |
| } |
| } |