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