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 * */ setDefaultDialerApplication(Context context, String packageName)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 * */ setDefaultDialerApplication(Context context, String packageName, int user)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 * */ getDefaultDialerApplication(Context context)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 * */ getDefaultDialerApplication(Context context, int user)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 **/ getInstalledDialerApplications(Context context, int userId)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 getInstalledDialerApplications(Context context)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 */ isDefaultOrSystemDialer(Context context, String packageName)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 */ filterByIntent(Context context, List<String> packageNames, Intent intent)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 getTelecomManager(Context context)231 private static TelecomManager getTelecomManager(Context context) { 232 return (TelecomManager) context.getSystemService(Context.TELECOM_SERVICE); 233 } 234 } 235