Home | History | Annotate | Download | only in uicc
      1 /*
      2  * Copyright (C) 2018 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.internal.telephony.uicc;
     18 
     19 import static android.content.Context.ALARM_SERVICE;
     20 
     21 import android.app.AlarmManager;
     22 import android.app.Notification;
     23 import android.app.NotificationManager;
     24 import android.app.PendingIntent;
     25 import android.content.Context;
     26 import android.content.Intent;
     27 import android.content.IntentFilter;
     28 import android.content.res.Resources;
     29 import android.net.Uri;
     30 import android.os.SystemClock;
     31 import android.provider.Settings;
     32 import android.service.notification.StatusBarNotification;
     33 import android.text.TextUtils;
     34 
     35 import com.android.internal.R;
     36 import com.android.internal.annotations.VisibleForTesting;
     37 import com.android.internal.telephony.util.NotificationChannelController;
     38 
     39 import java.util.Arrays;
     40 import java.util.List;
     41 
     42 /**
     43  * Utility methods for installing the carrier app when a SIM is insterted without the carrier app
     44  * for that SIM installed.
     45  */
     46 @VisibleForTesting
     47 public class InstallCarrierAppUtils {
     48     // TODO(b/72714040) centralize notification IDs
     49     private static final int ACTIVATE_CELL_SERVICE_NOTIFICATION_ID = 12;
     50     private static CarrierAppInstallReceiver sCarrierAppInstallReceiver = null;
     51 
     52     static void showNotification(Context context, String pkgName) {
     53         Resources res = Resources.getSystem();
     54         String title = res.getString(
     55                 com.android.internal.R.string.install_carrier_app_notification_title);
     56         String appName = getAppNameFromPackageName(context, pkgName);
     57         String message;
     58         if (TextUtils.isEmpty(appName)) {
     59             message = res.getString(R.string.install_carrier_app_notification_text);
     60         } else {
     61             message = res.getString(R.string.install_carrier_app_notification_text_app_name,
     62                     appName);
     63         }
     64         String downloadButtonText = res.getString(R.string.install_carrier_app_notification_button);
     65 
     66         boolean persistent = Settings.Global.getInt(
     67                 context.getContentResolver(),
     68                 Settings.Global.INSTALL_CARRIER_APP_NOTIFICATION_PERSISTENT, 1) == 1;
     69 
     70         PendingIntent goToStore = PendingIntent.getActivity(context, 0,
     71                 getPlayStoreIntent(pkgName), PendingIntent.FLAG_UPDATE_CURRENT);
     72 
     73         Notification.Action goToStoreAction =
     74                 new Notification.Action.Builder(null, downloadButtonText, goToStore).build();
     75 
     76         Notification notification = new Notification.Builder(context,
     77                 NotificationChannelController.CHANNEL_ID_SIM)
     78                 .setContentTitle(title)
     79                 .setContentText(message)
     80                 .setSmallIcon(R.drawable.ic_signal_cellular_alt_24px)
     81                 .addAction(goToStoreAction)
     82                 .setOngoing(persistent)
     83                 .setVisibility(Notification.VISIBILITY_SECRET) // Should not appear on lock screen
     84                 .build();
     85 
     86         getNotificationManager(context).notify(
     87                 pkgName,
     88                 ACTIVATE_CELL_SERVICE_NOTIFICATION_ID,
     89                 notification);
     90     }
     91 
     92     static void hideAllNotifications(Context context) {
     93         NotificationManager notificationManager = getNotificationManager(context);
     94         StatusBarNotification[] activeNotifications = notificationManager.getActiveNotifications();
     95 
     96         if (activeNotifications == null) {
     97             return;
     98         }
     99 
    100         for (StatusBarNotification notification : activeNotifications) {
    101             if (notification.getId() == ACTIVATE_CELL_SERVICE_NOTIFICATION_ID) {
    102                 notificationManager.cancel(notification.getTag(), notification.getId());
    103             }
    104         }
    105     }
    106 
    107     static void hideNotification(Context context, String pkgName) {
    108         getNotificationManager(context).cancel(pkgName, ACTIVATE_CELL_SERVICE_NOTIFICATION_ID);
    109     }
    110 
    111     static Intent getPlayStoreIntent(String pkgName) {
    112         // Open play store to download package
    113         Intent storeIntent = new Intent(Intent.ACTION_VIEW);
    114         storeIntent.setData(Uri.parse("market://details?id=" + pkgName));
    115         storeIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
    116 
    117         return storeIntent;
    118     }
    119 
    120     static void showNotificationIfNotInstalledDelayed(Context context,
    121             String pkgName, long delayMillis) {
    122         AlarmManager alarmManager = (AlarmManager) context.getSystemService(ALARM_SERVICE);
    123         PendingIntent pendingIntent = PendingIntent.getBroadcast(
    124                 context,
    125                 0,
    126                 ShowInstallAppNotificationReceiver.get(context, pkgName),
    127                 0);
    128         alarmManager.set(AlarmManager.ELAPSED_REALTIME,
    129                 SystemClock.elapsedRealtime() + delayMillis,
    130                 pendingIntent);
    131 
    132     }
    133 
    134     static void registerPackageInstallReceiver(Context context) {
    135         if (sCarrierAppInstallReceiver == null) {
    136             sCarrierAppInstallReceiver = new CarrierAppInstallReceiver();
    137             context = context.getApplicationContext();
    138             IntentFilter intentFilter = new IntentFilter(Intent.ACTION_PACKAGE_ADDED);
    139             intentFilter.addDataScheme("package");
    140             context.registerReceiver(sCarrierAppInstallReceiver, intentFilter);
    141         }
    142     }
    143 
    144     static void unregisterPackageInstallReceiver(Context context) {
    145         if (sCarrierAppInstallReceiver == null) {
    146             return;
    147         }
    148         context = context.getApplicationContext();
    149         context.unregisterReceiver(sCarrierAppInstallReceiver);
    150         sCarrierAppInstallReceiver = null;
    151     }
    152 
    153     static boolean isPackageInstallNotificationActive(Context context) {
    154         StatusBarNotification[] activeNotifications =
    155                 getNotificationManager(context).getActiveNotifications();
    156 
    157         for (StatusBarNotification notification : activeNotifications) {
    158             if (notification.getId() == ACTIVATE_CELL_SERVICE_NOTIFICATION_ID) {
    159                 return true;
    160             }
    161         }
    162         return false;
    163     }
    164 
    165     static String getAppNameFromPackageName(Context context, String packageName) {
    166         String whitelistSetting = Settings.Global.getString(
    167                 context.getContentResolver(),
    168                 Settings.Global.CARRIER_APP_NAMES);
    169         return getAppNameFromPackageName(packageName, whitelistSetting);
    170     }
    171 
    172     /**
    173      * @param packageName the name of the package.  Will be used as a key into the map
    174      * @param mapString map of package name to application name in the format:
    175      *                  packageName1:appName1;packageName2:appName2;
    176      * @return the name of the application for the package name provided.
    177      */
    178     @VisibleForTesting
    179     public static String getAppNameFromPackageName(String packageName, String mapString) {
    180         packageName = packageName.toLowerCase();
    181         final String pairDelim = "\\s*;\\s*";
    182         final String keyValueDelim = "\\s*:\\s*";
    183 
    184         if (TextUtils.isEmpty(mapString)) {
    185             return null;
    186         }
    187 
    188         List<String> keyValuePairList = Arrays.asList(mapString.split(pairDelim));
    189 
    190         if (keyValuePairList.isEmpty()) {
    191             return null;
    192         }
    193 
    194         for (String keyValueString: keyValuePairList) {
    195             String[] keyValue = keyValueString.split(keyValueDelim);
    196 
    197             if (keyValue.length == 2) {
    198                 if (keyValue[0].equals(packageName)) {
    199                     return keyValue[1];
    200                 }
    201             }
    202         }
    203         return null;
    204     }
    205     private static NotificationManager getNotificationManager(Context context) {
    206         return (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
    207     }
    208 }
    209