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.Context;
23import android.content.Intent;
24import android.content.res.Resources;
25import android.os.Bundle;
26import android.telephony.SubscriptionManager;
27import android.telephony.TelephonyManager;
28import android.util.Log;
29import com.android.internal.telephony.PhoneConstants;
30import com.android.carrierdefaultapp.R;
31/**
32 * This util class provides common logic for carrier actions
33 */
34public class CarrierActionUtils {
35    private static final String TAG = CarrierActionUtils.class.getSimpleName();
36
37    private static final String PORTAL_NOTIFICATION_TAG = "CarrierDefault.Portal.Notification";
38    private static final String NO_DATA_NOTIFICATION_TAG = "CarrierDefault.NoData.Notification";
39    private static final String NOTIFICATION_CHANNEL_ID_MOBILE_DATA_STATUS = "mobile_data_status";
40    private static final int PORTAL_NOTIFICATION_ID = 0;
41    private static final int NO_DATA_NOTIFICATION_ID = 1;
42    private static boolean ENABLE = true;
43
44    // A list of supported carrier action idx
45    public static final int CARRIER_ACTION_ENABLE_METERED_APNS               = 0;
46    public static final int CARRIER_ACTION_DISABLE_METERED_APNS              = 1;
47    public static final int CARRIER_ACTION_DISABLE_RADIO                     = 2;
48    public static final int CARRIER_ACTION_ENABLE_RADIO                      = 3;
49    public static final int CARRIER_ACTION_SHOW_PORTAL_NOTIFICATION          = 4;
50    public static final int CARRIER_ACTION_SHOW_NO_DATA_SERVICE_NOTIFICATION = 5;
51    public static final int CARRIER_ACTION_CANCEL_ALL_NOTIFICATIONS          = 6;
52
53    public static void applyCarrierAction(int actionIdx, Intent intent, Context context) {
54        switch (actionIdx) {
55            case CARRIER_ACTION_ENABLE_METERED_APNS:
56                onEnableAllMeteredApns(intent, context);
57                break;
58            case CARRIER_ACTION_DISABLE_METERED_APNS:
59                onDisableAllMeteredApns(intent, context);
60                break;
61            case CARRIER_ACTION_DISABLE_RADIO:
62                onDisableRadio(intent, context);
63                break;
64            case CARRIER_ACTION_ENABLE_RADIO:
65                onEnableRadio(intent, context);
66                break;
67            case CARRIER_ACTION_SHOW_PORTAL_NOTIFICATION:
68                onShowCaptivePortalNotification(intent, context);
69                break;
70            case CARRIER_ACTION_SHOW_NO_DATA_SERVICE_NOTIFICATION:
71                onShowNoDataServiceNotification(context);
72                break;
73            case CARRIER_ACTION_CANCEL_ALL_NOTIFICATIONS:
74                onCancelAllNotifications(context);
75                break;
76            default:
77                loge("unsupported carrier action index: " + actionIdx);
78        }
79    }
80
81    private static void onDisableAllMeteredApns(Intent intent, Context context) {
82        int subId = intent.getIntExtra(PhoneConstants.SUBSCRIPTION_KEY,
83                SubscriptionManager.getDefaultVoiceSubscriptionId());
84        logd("onDisableAllMeteredApns subId: " + subId);
85        final TelephonyManager telephonyMgr = context.getSystemService(TelephonyManager.class);
86        telephonyMgr.carrierActionSetMeteredApnsEnabled(subId, !ENABLE);
87    }
88
89    private static void onEnableAllMeteredApns(Intent intent, Context context) {
90        int subId = intent.getIntExtra(PhoneConstants.SUBSCRIPTION_KEY,
91                SubscriptionManager.getDefaultVoiceSubscriptionId());
92        logd("onEnableAllMeteredApns subId: " + subId);
93        final TelephonyManager telephonyMgr = context.getSystemService(TelephonyManager.class);
94        telephonyMgr.carrierActionSetMeteredApnsEnabled(subId, ENABLE);
95    }
96
97    private static void onDisableRadio(Intent intent, Context context) {
98        int subId = intent.getIntExtra(PhoneConstants.SUBSCRIPTION_KEY,
99                SubscriptionManager.getDefaultVoiceSubscriptionId());
100        logd("onDisableRadio subId: " + subId);
101        final TelephonyManager telephonyMgr = context.getSystemService(TelephonyManager.class);
102        telephonyMgr.carrierActionSetRadioEnabled(subId, !ENABLE);
103    }
104
105    private static void onEnableRadio(Intent intent, Context context) {
106        int subId = intent.getIntExtra(PhoneConstants.SUBSCRIPTION_KEY,
107                SubscriptionManager.getDefaultVoiceSubscriptionId());
108        logd("onEnableRadio subId: " + subId);
109        final TelephonyManager telephonyMgr = context.getSystemService(TelephonyManager.class);
110        telephonyMgr.carrierActionSetRadioEnabled(subId, ENABLE);
111    }
112
113    private static void onShowCaptivePortalNotification(Intent intent, Context context) {
114        logd("onShowCaptivePortalNotification");
115        Intent portalIntent = new Intent(context, CaptivePortalLoginActivity.class);
116        portalIntent.putExtras(intent);
117        portalIntent.setFlags(Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT
118                | Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
119        PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, portalIntent,
120                PendingIntent.FLAG_UPDATE_CURRENT);
121        Notification notification = getNotification(context, R.string.portal_notification_id,
122                R.string.portal_notification_detail, pendingIntent);
123        try {
124            context.getSystemService(NotificationManager.class)
125                    .notify(PORTAL_NOTIFICATION_TAG, PORTAL_NOTIFICATION_ID, notification);
126        } catch (NullPointerException npe) {
127            loge("setNotificationVisible: " + npe);
128        }
129    }
130
131    private static void onShowNoDataServiceNotification(Context context) {
132        logd("onShowNoDataServiceNotification");
133        Notification notification = getNotification(context, R.string.no_data_notification_id,
134                R.string.no_data_notification_detail, null);
135        try {
136            context.getSystemService(NotificationManager.class)
137                    .notify(NO_DATA_NOTIFICATION_TAG, NO_DATA_NOTIFICATION_ID, notification);
138        } catch (NullPointerException npe) {
139            loge("setNotificationVisible: " + npe);
140        }
141    }
142
143    private static void onCancelAllNotifications(Context context) {
144        logd("onCancelAllNotifications");
145        context.getSystemService(NotificationManager.class).cancelAll();
146    }
147
148    private static Notification getNotification(Context context, int titleId, int textId,
149                                         PendingIntent pendingIntent) {
150        final TelephonyManager telephonyMgr = context.getSystemService(TelephonyManager.class);
151        final Resources resources = context.getResources();
152        final Bundle extras = Bundle.forPair(Notification.EXTRA_SUBSTITUTE_APP_NAME,
153                resources.getString(R.string.android_system_label));
154        createNotificationChannels(context);
155        Notification.Builder builder = new Notification.Builder(context)
156                .setContentTitle(resources.getString(titleId))
157                .setContentText(String.format(resources.getString(textId),
158                        telephonyMgr.getNetworkOperatorName()))
159                .setSmallIcon(R.drawable.ic_sim_card)
160                .setColor(context.getColor(
161                        com.android.internal.R.color.system_notification_accent_color))
162                .setOngoing(true)
163                .setPriority(Notification.PRIORITY_HIGH)
164                .setDefaults(Notification.DEFAULT_ALL)
165                .setVisibility(Notification.VISIBILITY_PUBLIC)
166                .setLocalOnly(true)
167                .setWhen(System.currentTimeMillis())
168                .setShowWhen(false)
169                .setExtras(extras)
170                .setChannel(NOTIFICATION_CHANNEL_ID_MOBILE_DATA_STATUS);
171
172        if (pendingIntent != null) {
173            builder.setContentIntent(pendingIntent);
174        }
175        return builder.build();
176    }
177
178    /**
179     * Creates the notification channel and registers it with NotificationManager. Also used to
180     * update an existing channel's name.
181     */
182    static void createNotificationChannels(Context context) {
183        context.getSystemService(NotificationManager.class)
184                .createNotificationChannel(new NotificationChannel(
185                NOTIFICATION_CHANNEL_ID_MOBILE_DATA_STATUS,
186                context.getResources().getString(
187                        R.string.mobile_data_status_notification_channel_name),
188                NotificationManager.IMPORTANCE_DEFAULT));
189    }
190
191    private static void logd(String s) {
192        Log.d(TAG, s);
193    }
194
195    private static void loge(String s) {
196        Log.e(TAG, s);
197    }
198}
199