blob: 1806aee27e31f9d877ea03a475019c8be1808b42 [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;
Tony Makb401a942016-01-19 19:05:18 +000024import android.os.Process;
Tony Mak39198fa2017-09-15 17:41:43 +010025import android.os.UserHandle;
Yorke Lee014de022015-04-21 17:15:47 -070026import android.provider.Settings;
27import android.text.TextUtils;
28
29import java.util.ArrayList;
30import java.util.List;
31
32/**
33 * Class for managing the default dialer application that will receive incoming calls, and be
34 * allowed to make emergency outgoing calls.
35 *
36 * @hide
37 */
38public class DefaultDialerManager {
39 private static final String TAG = "DefaultDialerManager";
40
41 /**
Yorke Lee6526f672015-05-04 17:07:32 -070042 * Sets the specified package name as the default dialer application for the current user.
43 * The caller of this method needs to have permission to write to secure settings and
44 * manage users on the device.
Yorke Lee014de022015-04-21 17:15:47 -070045 *
Yorke Leedb6da482015-06-02 13:55:25 -070046 * @return {@code true} if the default dialer application was successfully changed,
47 * {@code false} otherwise.
48 *
Yorke Lee014de022015-04-21 17:15:47 -070049 * @hide
50 * */
Yorke Leedb6da482015-06-02 13:55:25 -070051 public static boolean setDefaultDialerApplication(Context context, String packageName) {
52 return setDefaultDialerApplication(context, packageName, ActivityManager.getCurrentUser());
Yorke Lee6526f672015-05-04 17:07:32 -070053 }
54
55 /**
56 * Sets the specified package name as the default dialer application for the specified user.
57 * The caller of this method needs to have permission to write to secure settings and
58 * manage users on the device.
59 *
Yorke Leedb6da482015-06-02 13:55:25 -070060 * @return {@code true} if the default dialer application was successfully changed,
61 * {@code false} otherwise.
62 *
Yorke Lee6526f672015-05-04 17:07:32 -070063 * @hide
64 * */
Yorke Leedb6da482015-06-02 13:55:25 -070065 public static boolean setDefaultDialerApplication(Context context, String packageName,
66 int user) {
Yorke Lee014de022015-04-21 17:15:47 -070067 // Get old package name
Yorke Lee6526f672015-05-04 17:07:32 -070068 String oldPackageName = Settings.Secure.getStringForUser(context.getContentResolver(),
69 Settings.Secure.DIALER_DEFAULT_APPLICATION, user);
Yorke Lee014de022015-04-21 17:15:47 -070070
71 if (packageName != null && oldPackageName != null && packageName.equals(oldPackageName)) {
72 // No change
Yorke Leedb6da482015-06-02 13:55:25 -070073 return false;
Yorke Lee014de022015-04-21 17:15:47 -070074 }
75
76 // Only make the change if the new package belongs to a valid phone application
Yorke Lee8e0207b2015-04-28 09:39:20 -070077 List<String> packageNames = getInstalledDialerApplications(context);
Yorke Lee014de022015-04-21 17:15:47 -070078
Yorke Lee8e0207b2015-04-28 09:39:20 -070079 if (packageNames.contains(packageName)) {
Yorke Lee014de022015-04-21 17:15:47 -070080 // Update the secure setting.
Yorke Lee6526f672015-05-04 17:07:32 -070081 Settings.Secure.putStringForUser(context.getContentResolver(),
82 Settings.Secure.DIALER_DEFAULT_APPLICATION, packageName, user);
Yorke Leedb6da482015-06-02 13:55:25 -070083 return true;
Yorke Lee014de022015-04-21 17:15:47 -070084 }
Yorke Leedb6da482015-06-02 13:55:25 -070085 return false;
Yorke Lee014de022015-04-21 17:15:47 -070086 }
87
88 /**
Yorke Lee6526f672015-05-04 17:07:32 -070089 * Returns the installed dialer application for the current user that will be used to receive
90 * incoming calls, and is allowed to make emergency calls.
Yorke Lee014de022015-04-21 17:15:47 -070091 *
92 * The application will be returned in order of preference:
93 * 1) User selected phone application (if still installed)
94 * 2) Pre-installed system dialer (if not disabled)
95 * 3) Null
96 *
Yorke Lee6526f672015-05-04 17:07:32 -070097 * The caller of this method needs to have permission to manage users on the device.
98 *
Yorke Lee014de022015-04-21 17:15:47 -070099 * @hide
100 * */
Yorke Lee8e0207b2015-04-28 09:39:20 -0700101 public static String getDefaultDialerApplication(Context context) {
Svet Ganov52153f42015-08-11 08:59:12 -0700102 return getDefaultDialerApplication(context, context.getUserId());
Yorke Lee6526f672015-05-04 17:07:32 -0700103 }
Yorke Lee014de022015-04-21 17:15:47 -0700104
Yorke Lee6526f672015-05-04 17:07:32 -0700105 /**
106 * Returns the installed dialer application for the specified user that will be used to receive
107 * incoming calls, and is allowed to make emergency calls.
108 *
109 * The application will be returned in order of preference:
110 * 1) User selected phone application (if still installed)
111 * 2) Pre-installed system dialer (if not disabled)
112 * 3) Null
113 *
114 * The caller of this method needs to have permission to manage users on the device.
115 *
116 * @hide
117 * */
118 public static String getDefaultDialerApplication(Context context, int user) {
119 String defaultPackageName = Settings.Secure.getStringForUser(context.getContentResolver(),
120 Settings.Secure.DIALER_DEFAULT_APPLICATION, user);
Yorke Lee8e0207b2015-04-28 09:39:20 -0700121
Hall Liu15dbf2b2016-12-07 18:06:46 -0800122 final List<String> packageNames = getInstalledDialerApplications(context, user);
Yorke Lee8e0207b2015-04-28 09:39:20 -0700123
124 // Verify that the default dialer has not been disabled or uninstalled.
125 if (packageNames.contains(defaultPackageName)) {
126 return defaultPackageName;
Yorke Lee014de022015-04-21 17:15:47 -0700127 }
128
129 // No user-set dialer found, fallback to system dialer
Yorke Lee8e0207b2015-04-28 09:39:20 -0700130 String systemDialerPackageName = getTelecomManager(context).getSystemDialerPackage();
Yorke Lee014de022015-04-21 17:15:47 -0700131
Yorke Lee8e0207b2015-04-28 09:39:20 -0700132 if (TextUtils.isEmpty(systemDialerPackageName)) {
Yorke Lee014de022015-04-21 17:15:47 -0700133 // No system dialer configured at build time
134 return null;
135 }
136
Yorke Lee8e0207b2015-04-28 09:39:20 -0700137 if (packageNames.contains(systemDialerPackageName)) {
138 return systemDialerPackageName;
139 } else {
140 return null;
141 }
Yorke Lee014de022015-04-21 17:15:47 -0700142 }
143
144 /**
145 * Returns a list of installed and available dialer applications.
146 *
147 * In order to appear in the list, a dialer application must implement an intent-filter with
148 * the DIAL intent for the following schemes:
149 *
150 * 1) Empty scheme
151 * 2) tel Uri scheme
152 *
153 * @hide
154 **/
Tony Makb401a942016-01-19 19:05:18 +0000155 public static List<String> getInstalledDialerApplications(Context context, int userId) {
Yorke Lee014de022015-04-21 17:15:47 -0700156 PackageManager packageManager = context.getPackageManager();
157
158 // Get the list of apps registered for the DIAL intent with empty scheme
159 Intent intent = new Intent(Intent.ACTION_DIAL);
Tony Makb401a942016-01-19 19:05:18 +0000160 List<ResolveInfo> resolveInfoList =
161 packageManager.queryIntentActivitiesAsUser(intent, 0, userId);
Yorke Lee014de022015-04-21 17:15:47 -0700162
Yorke Lee8e0207b2015-04-28 09:39:20 -0700163 List<String> packageNames = new ArrayList<>();
Yorke Lee014de022015-04-21 17:15:47 -0700164
165 for (ResolveInfo resolveInfo : resolveInfoList) {
166 final ActivityInfo activityInfo = resolveInfo.activityInfo;
Tony Mak39198fa2017-09-15 17:41:43 +0100167 if (activityInfo != null
168 && !packageNames.contains(activityInfo.packageName)
169 // ignore cross profile intent handler
170 && resolveInfo.targetUserId == UserHandle.USER_CURRENT) {
Yorke Lee856a5ac2015-04-28 15:45:42 -0700171 packageNames.add(activityInfo.packageName);
Yorke Lee014de022015-04-21 17:15:47 -0700172 }
Yorke Lee014de022015-04-21 17:15:47 -0700173 }
174
Yorke Lee856a5ac2015-04-28 15:45:42 -0700175 final Intent dialIntentWithTelScheme = new Intent(Intent.ACTION_DIAL);
176 dialIntentWithTelScheme.setData(Uri.fromParts(PhoneAccount.SCHEME_TEL, "", null));
Tyler Gunn0907bd62017-09-01 15:17:05 -0700177 return filterByIntent(context, packageNames, dialIntentWithTelScheme, userId);
Yorke Lee014de022015-04-21 17:15:47 -0700178 }
179
Tony Makb401a942016-01-19 19:05:18 +0000180 public static List<String> getInstalledDialerApplications(Context context) {
181 return getInstalledDialerApplications(context, Process.myUserHandle().getIdentifier());
182 }
183
Yorke Lee014de022015-04-21 17:15:47 -0700184 /**
Yorke Lee61043822015-04-27 11:18:38 -0700185 * Determines if the package name belongs to the user-selected default dialer or the preloaded
186 * system dialer, and thus should be allowed to perform certain privileged operations.
187 *
188 * @param context A valid context.
189 * @param packageName of the package to check for.
190 *
191 * @return {@code true} if the provided package name corresponds to the user-selected default
192 * dialer or the preloaded system dialer, {@code false} otherwise.
193 *
194 * @hide
195 */
196 public static boolean isDefaultOrSystemDialer(Context context, String packageName) {
197 if (TextUtils.isEmpty(packageName)) {
198 return false;
199 }
200 final TelecomManager tm = getTelecomManager(context);
201 return packageName.equals(tm.getDefaultDialerPackage())
202 || packageName.equals(tm.getSystemDialerPackage());
203 }
204
Yorke Lee856a5ac2015-04-28 15:45:42 -0700205 /**
206 * Filter a given list of package names for those packages that contain an activity that has
207 * an intent filter for a given intent.
208 *
209 * @param context A valid context
210 * @param packageNames List of package names to filter.
Tyler Gunn0907bd62017-09-01 15:17:05 -0700211 * @param userId The UserId
Yorke Lee856a5ac2015-04-28 15:45:42 -0700212 * @return The filtered list.
213 */
214 private static List<String> filterByIntent(Context context, List<String> packageNames,
Tyler Gunn0907bd62017-09-01 15:17:05 -0700215 Intent intent, int userId) {
Yorke Lee856a5ac2015-04-28 15:45:42 -0700216 if (packageNames == null || packageNames.isEmpty()) {
217 return new ArrayList<>();
218 }
219
220 final List<String> result = new ArrayList<>();
Jeff Sharkey2a9e3f82015-12-18 10:57:58 -0700221 final List<ResolveInfo> resolveInfoList = context.getPackageManager()
Tyler Gunn0907bd62017-09-01 15:17:05 -0700222 .queryIntentActivitiesAsUser(intent, 0, userId);
Yorke Lee856a5ac2015-04-28 15:45:42 -0700223 final int length = resolveInfoList.size();
224 for (int i = 0; i < length; i++) {
225 final ActivityInfo info = resolveInfoList.get(i).activityInfo;
226 if (info != null && packageNames.contains(info.packageName)
227 && !result.contains(info.packageName)) {
228 result.add(info.packageName);
229 }
230 }
231
232 return result;
233 }
234
235
Yorke Lee014de022015-04-21 17:15:47 -0700236 private static TelecomManager getTelecomManager(Context context) {
237 return (TelecomManager) context.getSystemService(Context.TELECOM_SERVICE);
238 }
239}