Home | History | Annotate | Download | only in telecom
      1 /*
      2  * Copyright (C) 2015 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
      5  * in compliance with the License. You may obtain a copy of the License at
      6  *
      7  * http://www.apache.org/licenses/LICENSE-2.0
      8  *
      9  * Unless required by applicable law or agreed to in writing, software distributed under the License
     10  * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
     11  * or implied. See the License for the specific language governing permissions and limitations under
     12  * the License.
     13  */
     14 
     15 package android.telecom;
     16 
     17 import android.app.ActivityManager;
     18 import android.content.Context;
     19 import android.content.Intent;
     20 import android.content.pm.ActivityInfo;
     21 import android.content.pm.PackageManager;
     22 import android.content.pm.ResolveInfo;
     23 import android.net.Uri;
     24 import android.provider.Settings;
     25 import android.text.TextUtils;
     26 
     27 import java.util.ArrayList;
     28 import java.util.List;
     29 
     30 /**
     31  * Class for managing the default dialer application that will receive incoming calls, and be
     32  * allowed to make emergency outgoing calls.
     33  *
     34  * @hide
     35  */
     36 public class DefaultDialerManager {
     37     private static final String TAG = "DefaultDialerManager";
     38 
     39     /**
     40      * Sets the specified package name as the default dialer application for the current user.
     41      * The caller of this method needs to have permission to write to secure settings and
     42      * manage users on the device.
     43      *
     44      * @return {@code true} if the default dialer application was successfully changed,
     45      *         {@code false} otherwise.
     46      *
     47      * @hide
     48      * */
     49     public static boolean setDefaultDialerApplication(Context context, String packageName) {
     50         return setDefaultDialerApplication(context, packageName, ActivityManager.getCurrentUser());
     51     }
     52 
     53     /**
     54      * Sets the specified package name as the default dialer application for the specified user.
     55      * The caller of this method needs to have permission to write to secure settings and
     56      * manage users on the device.
     57      *
     58      * @return {@code true} if the default dialer application was successfully changed,
     59      *         {@code false} otherwise.
     60      *
     61      * @hide
     62      * */
     63     public static boolean setDefaultDialerApplication(Context context, String packageName,
     64             int user) {
     65         // Get old package name
     66         String oldPackageName = Settings.Secure.getStringForUser(context.getContentResolver(),
     67                 Settings.Secure.DIALER_DEFAULT_APPLICATION, user);
     68 
     69         if (packageName != null && oldPackageName != null && packageName.equals(oldPackageName)) {
     70             // No change
     71             return false;
     72         }
     73 
     74         // Only make the change if the new package belongs to a valid phone application
     75         List<String> packageNames = getInstalledDialerApplications(context);
     76 
     77         if (packageNames.contains(packageName)) {
     78             // Update the secure setting.
     79             Settings.Secure.putStringForUser(context.getContentResolver(),
     80                     Settings.Secure.DIALER_DEFAULT_APPLICATION, packageName, user);
     81             return true;
     82         }
     83         return false;
     84     }
     85 
     86     /**
     87      * Returns the installed dialer application for the current user that will be used to receive
     88      * incoming calls, and is allowed to make emergency calls.
     89      *
     90      * The application will be returned in order of preference:
     91      * 1) User selected phone application (if still installed)
     92      * 2) Pre-installed system dialer (if not disabled)
     93      * 3) Null
     94      *
     95      * The caller of this method needs to have permission to manage users on the device.
     96      *
     97      * @hide
     98      * */
     99     public static String getDefaultDialerApplication(Context context) {
    100         return getDefaultDialerApplication(context, context.getUserId());
    101     }
    102 
    103     /**
    104      * Returns the installed dialer application for the specified user that will be used to receive
    105      * incoming calls, and is allowed to make emergency calls.
    106      *
    107      * The application will be returned in order of preference:
    108      * 1) User selected phone application (if still installed)
    109      * 2) Pre-installed system dialer (if not disabled)
    110      * 3) Null
    111      *
    112      * The caller of this method needs to have permission to manage users on the device.
    113      *
    114      * @hide
    115      * */
    116     public static String getDefaultDialerApplication(Context context, int user) {
    117         String defaultPackageName = Settings.Secure.getStringForUser(context.getContentResolver(),
    118                 Settings.Secure.DIALER_DEFAULT_APPLICATION, user);
    119 
    120         final List<String> packageNames = getInstalledDialerApplications(context);
    121 
    122         // Verify that the default dialer has not been disabled or uninstalled.
    123         if (packageNames.contains(defaultPackageName)) {
    124             return defaultPackageName;
    125         }
    126 
    127         // No user-set dialer found, fallback to system dialer
    128         String systemDialerPackageName = getTelecomManager(context).getSystemDialerPackage();
    129 
    130         if (TextUtils.isEmpty(systemDialerPackageName)) {
    131             // No system dialer configured at build time
    132             return null;
    133         }
    134 
    135         if (packageNames.contains(systemDialerPackageName)) {
    136             return systemDialerPackageName;
    137         } else {
    138             return null;
    139         }
    140     }
    141 
    142     /**
    143      * Returns a list of installed and available dialer applications.
    144      *
    145      * In order to appear in the list, a dialer application must implement an intent-filter with
    146      * the DIAL intent for the following schemes:
    147      *
    148      * 1) Empty scheme
    149      * 2) tel Uri scheme
    150      *
    151      * @hide
    152      **/
    153     public static List<String> getInstalledDialerApplications(Context context) {
    154         PackageManager packageManager = context.getPackageManager();
    155 
    156         // Get the list of apps registered for the DIAL intent with empty scheme
    157         Intent intent = new Intent(Intent.ACTION_DIAL);
    158         List<ResolveInfo> resolveInfoList = packageManager.queryIntentActivities(intent, 0);
    159 
    160         List<String> packageNames = new ArrayList<>();
    161 
    162         for (ResolveInfo resolveInfo : resolveInfoList) {
    163             final ActivityInfo activityInfo = resolveInfo.activityInfo;
    164             if (activityInfo != null && !packageNames.contains(activityInfo.packageName)) {
    165                 packageNames.add(activityInfo.packageName);
    166             }
    167         }
    168 
    169         final Intent dialIntentWithTelScheme = new Intent(Intent.ACTION_DIAL);
    170         dialIntentWithTelScheme.setData(Uri.fromParts(PhoneAccount.SCHEME_TEL, "", null));
    171         return filterByIntent(context, packageNames, dialIntentWithTelScheme);
    172     }
    173 
    174     /**
    175      * Determines if the package name belongs to the user-selected default dialer or the preloaded
    176      * system dialer, and thus should be allowed to perform certain privileged operations.
    177      *
    178      * @param context A valid context.
    179      * @param packageName of the package to check for.
    180      *
    181      * @return {@code true} if the provided package name corresponds to the user-selected default
    182      *         dialer or the preloaded system dialer, {@code false} otherwise.
    183      *
    184      * @hide
    185      */
    186     public static boolean isDefaultOrSystemDialer(Context context, String packageName) {
    187         if (TextUtils.isEmpty(packageName)) {
    188             return false;
    189         }
    190         final TelecomManager tm = getTelecomManager(context);
    191         return packageName.equals(tm.getDefaultDialerPackage())
    192                 || packageName.equals(tm.getSystemDialerPackage());
    193     }
    194 
    195     /**
    196      * Filter a given list of package names for those packages that contain an activity that has
    197      * an intent filter for a given intent.
    198      *
    199      * @param context A valid context
    200      * @param packageNames List of package names to filter.
    201      * @return The filtered list.
    202      */
    203     private static List<String> filterByIntent(Context context, List<String> packageNames,
    204             Intent intent) {
    205         if (packageNames == null || packageNames.isEmpty()) {
    206             return new ArrayList<>();
    207         }
    208 
    209         final List<String> result = new ArrayList<>();
    210         final List<ResolveInfo> resolveInfoList =
    211                 context.getPackageManager().queryIntentActivities(intent, 0);
    212         final int length = resolveInfoList.size();
    213         for (int i = 0; i < length; i++) {
    214             final ActivityInfo info = resolveInfoList.get(i).activityInfo;
    215             if (info != null && packageNames.contains(info.packageName)
    216                     && !result.contains(info.packageName)) {
    217                 result.add(info.packageName);
    218             }
    219         }
    220 
    221         return result;
    222     }
    223 
    224 
    225     private static TelecomManager getTelecomManager(Context context) {
    226         return (TelecomManager) context.getSystemService(Context.TELECOM_SERVICE);
    227     }
    228 }
    229