blob: d3df1510c406d96bf9876a0be937e2a10ade32b3 [file] [log] [blame]
Yorke Lee014de022015-04-21 17:15:47 -07001/*
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
15package android.telecom;
16
Yorke Lee6526f672015-05-04 17:07:32 -070017import android.app.ActivityManager;
Yorke Lee014de022015-04-21 17:15:47 -070018import android.content.Context;
19import android.content.Intent;
20import android.content.pm.ActivityInfo;
21import android.content.pm.PackageManager;
22import android.content.pm.ResolveInfo;
Yorke Lee856a5ac2015-04-28 15:45:42 -070023import android.net.Uri;
Yorke Lee014de022015-04-21 17:15:47 -070024import android.provider.Settings;
25import android.text.TextUtils;
26
27import java.util.ArrayList;
28import 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 */
36public class DefaultDialerManager {
37 private static final String TAG = "DefaultDialerManager";
38
39 /**
Yorke Lee6526f672015-05-04 17:07:32 -070040 * 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.
Yorke Lee014de022015-04-21 17:15:47 -070043 *
44 * @hide
45 * */
Yorke Leea162f022015-04-27 15:17:50 -070046 public static void setDefaultDialerApplication(Context context, String packageName) {
Yorke Lee6526f672015-05-04 17:07:32 -070047 setDefaultDialerApplication(context, packageName, ActivityManager.getCurrentUser());
48 }
49
50 /**
51 * Sets the specified package name as the default dialer application for the specified user.
52 * The caller of this method needs to have permission to write to secure settings and
53 * manage users on the device.
54 *
55 * @hide
56 * */
57 public static void setDefaultDialerApplication(Context context, String packageName, int user) {
Yorke Lee014de022015-04-21 17:15:47 -070058 // Get old package name
Yorke Lee6526f672015-05-04 17:07:32 -070059 String oldPackageName = Settings.Secure.getStringForUser(context.getContentResolver(),
60 Settings.Secure.DIALER_DEFAULT_APPLICATION, user);
Yorke Lee014de022015-04-21 17:15:47 -070061
62 if (packageName != null && oldPackageName != null && packageName.equals(oldPackageName)) {
63 // No change
64 return;
65 }
66
67 // Only make the change if the new package belongs to a valid phone application
Yorke Lee8e0207b2015-04-28 09:39:20 -070068 List<String> packageNames = getInstalledDialerApplications(context);
Yorke Lee014de022015-04-21 17:15:47 -070069
Yorke Lee8e0207b2015-04-28 09:39:20 -070070 if (packageNames.contains(packageName)) {
Yorke Lee014de022015-04-21 17:15:47 -070071 // Update the secure setting.
Yorke Lee6526f672015-05-04 17:07:32 -070072 Settings.Secure.putStringForUser(context.getContentResolver(),
73 Settings.Secure.DIALER_DEFAULT_APPLICATION, packageName, user);
Yorke Lee014de022015-04-21 17:15:47 -070074 }
75 }
76
77 /**
Yorke Lee6526f672015-05-04 17:07:32 -070078 * Returns the installed dialer application for the current user that will be used to receive
79 * incoming calls, and is allowed to make emergency calls.
Yorke Lee014de022015-04-21 17:15:47 -070080 *
81 * The application will be returned in order of preference:
82 * 1) User selected phone application (if still installed)
83 * 2) Pre-installed system dialer (if not disabled)
84 * 3) Null
85 *
Yorke Lee6526f672015-05-04 17:07:32 -070086 * The caller of this method needs to have permission to manage users on the device.
87 *
Yorke Lee014de022015-04-21 17:15:47 -070088 * @hide
89 * */
Yorke Lee8e0207b2015-04-28 09:39:20 -070090 public static String getDefaultDialerApplication(Context context) {
Yorke Lee6526f672015-05-04 17:07:32 -070091 return getDefaultDialerApplication(context, ActivityManager.getCurrentUser());
92 }
Yorke Lee014de022015-04-21 17:15:47 -070093
Yorke Lee6526f672015-05-04 17:07:32 -070094 /**
95 * Returns the installed dialer application for the specified user that will be used to receive
96 * incoming calls, and is allowed to make emergency calls.
97 *
98 * The application will be returned in order of preference:
99 * 1) User selected phone application (if still installed)
100 * 2) Pre-installed system dialer (if not disabled)
101 * 3) Null
102 *
103 * The caller of this method needs to have permission to manage users on the device.
104 *
105 * @hide
106 * */
107 public static String getDefaultDialerApplication(Context context, int user) {
108 String defaultPackageName = Settings.Secure.getStringForUser(context.getContentResolver(),
109 Settings.Secure.DIALER_DEFAULT_APPLICATION, user);
Yorke Lee8e0207b2015-04-28 09:39:20 -0700110
111 final List<String> packageNames = getInstalledDialerApplications(context);
112
113 // Verify that the default dialer has not been disabled or uninstalled.
114 if (packageNames.contains(defaultPackageName)) {
115 return defaultPackageName;
Yorke Lee014de022015-04-21 17:15:47 -0700116 }
117
118 // No user-set dialer found, fallback to system dialer
Yorke Lee8e0207b2015-04-28 09:39:20 -0700119 String systemDialerPackageName = getTelecomManager(context).getSystemDialerPackage();
Yorke Lee014de022015-04-21 17:15:47 -0700120
Yorke Lee8e0207b2015-04-28 09:39:20 -0700121 if (TextUtils.isEmpty(systemDialerPackageName)) {
Yorke Lee014de022015-04-21 17:15:47 -0700122 // No system dialer configured at build time
123 return null;
124 }
125
Yorke Lee8e0207b2015-04-28 09:39:20 -0700126 if (packageNames.contains(systemDialerPackageName)) {
127 return systemDialerPackageName;
128 } else {
129 return null;
130 }
Yorke Lee014de022015-04-21 17:15:47 -0700131 }
132
133 /**
134 * Returns a list of installed and available dialer applications.
135 *
136 * In order to appear in the list, a dialer application must implement an intent-filter with
137 * the DIAL intent for the following schemes:
138 *
139 * 1) Empty scheme
140 * 2) tel Uri scheme
141 *
142 * @hide
143 **/
Yorke Lee8e0207b2015-04-28 09:39:20 -0700144 public static List<String> getInstalledDialerApplications(Context context) {
Yorke Lee014de022015-04-21 17:15:47 -0700145 PackageManager packageManager = context.getPackageManager();
146
147 // Get the list of apps registered for the DIAL intent with empty scheme
148 Intent intent = new Intent(Intent.ACTION_DIAL);
149 List<ResolveInfo> resolveInfoList = packageManager.queryIntentActivities(intent, 0);
150
Yorke Lee8e0207b2015-04-28 09:39:20 -0700151 List<String> packageNames = new ArrayList<>();
Yorke Lee014de022015-04-21 17:15:47 -0700152
153 for (ResolveInfo resolveInfo : resolveInfoList) {
154 final ActivityInfo activityInfo = resolveInfo.activityInfo;
Yorke Lee856a5ac2015-04-28 15:45:42 -0700155 if (activityInfo != null && !packageNames.contains(activityInfo.packageName)) {
156 packageNames.add(activityInfo.packageName);
Yorke Lee014de022015-04-21 17:15:47 -0700157 }
Yorke Lee014de022015-04-21 17:15:47 -0700158 }
159
Yorke Lee856a5ac2015-04-28 15:45:42 -0700160 final Intent dialIntentWithTelScheme = new Intent(Intent.ACTION_DIAL);
161 dialIntentWithTelScheme.setData(Uri.fromParts(PhoneAccount.SCHEME_TEL, "", null));
162 return filterByIntent(context, packageNames, dialIntentWithTelScheme);
Yorke Lee014de022015-04-21 17:15:47 -0700163 }
164
165 /**
Yorke Lee61043822015-04-27 11:18:38 -0700166 * Determines if the package name belongs to the user-selected default dialer or the preloaded
167 * system dialer, and thus should be allowed to perform certain privileged operations.
168 *
169 * @param context A valid context.
170 * @param packageName of the package to check for.
171 *
172 * @return {@code true} if the provided package name corresponds to the user-selected default
173 * dialer or the preloaded system dialer, {@code false} otherwise.
174 *
175 * @hide
176 */
177 public static boolean isDefaultOrSystemDialer(Context context, String packageName) {
178 if (TextUtils.isEmpty(packageName)) {
179 return false;
180 }
181 final TelecomManager tm = getTelecomManager(context);
182 return packageName.equals(tm.getDefaultDialerPackage())
183 || packageName.equals(tm.getSystemDialerPackage());
184 }
185
Yorke Lee856a5ac2015-04-28 15:45:42 -0700186 /**
187 * Filter a given list of package names for those packages that contain an activity that has
188 * an intent filter for a given intent.
189 *
190 * @param context A valid context
191 * @param packageNames List of package names to filter.
192 * @return The filtered list.
193 */
194 private static List<String> filterByIntent(Context context, List<String> packageNames,
195 Intent intent) {
196 if (packageNames == null || packageNames.isEmpty()) {
197 return new ArrayList<>();
198 }
199
200 final List<String> result = new ArrayList<>();
201 final List<ResolveInfo> resolveInfoList =
202 context.getPackageManager().queryIntentActivities(intent, 0);
203 final int length = resolveInfoList.size();
204 for (int i = 0; i < length; i++) {
205 final ActivityInfo info = resolveInfoList.get(i).activityInfo;
206 if (info != null && packageNames.contains(info.packageName)
207 && !result.contains(info.packageName)) {
208 result.add(info.packageName);
209 }
210 }
211
212 return result;
213 }
214
215
Yorke Lee014de022015-04-21 17:15:47 -0700216 private static TelecomManager getTelecomManager(Context context) {
217 return (TelecomManager) context.getSystemService(Context.TELECOM_SERVICE);
218 }
219}