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