blob: e43b2b71532103d3a6299a9e7946a18a030cb990 [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;
Eugene Susla92b88c72019-01-11 13:31:20 -080018import android.app.role.RoleManager;
19import android.app.role.RoleManagerCallback;
Yorke Lee014de022015-04-21 17:15:47 -070020import android.content.Context;
21import android.content.Intent;
22import android.content.pm.ActivityInfo;
23import android.content.pm.PackageManager;
24import android.content.pm.ResolveInfo;
Yorke Lee856a5ac2015-04-28 15:45:42 -070025import android.net.Uri;
Eugene Susla92b88c72019-01-11 13:31:20 -080026import android.os.AsyncTask;
27import android.os.Binder;
Tony Makb401a942016-01-19 19:05:18 +000028import android.os.Process;
Tony Mak39198fa2017-09-15 17:41:43 +010029import android.os.UserHandle;
Yorke Lee014de022015-04-21 17:15:47 -070030import android.text.TextUtils;
Eugene Susla98a872d2019-01-31 18:30:47 -080031import android.util.Slog;
Yorke Lee014de022015-04-21 17:15:47 -070032
Eugene Susla92b88c72019-01-11 13:31:20 -080033import com.android.internal.util.CollectionUtils;
34
Yorke Lee014de022015-04-21 17:15:47 -070035import java.util.ArrayList;
36import java.util.List;
Eugene Susla98a872d2019-01-31 18:30:47 -080037import java.util.concurrent.ExecutionException;
38import java.util.concurrent.TimeUnit;
39import java.util.concurrent.TimeoutException;
Yorke Lee014de022015-04-21 17:15:47 -070040
41/**
42 * Class for managing the default dialer application that will receive incoming calls, and be
43 * allowed to make emergency outgoing calls.
44 *
45 * @hide
46 */
47public class DefaultDialerManager {
48 private static final String TAG = "DefaultDialerManager";
49
50 /**
Yorke Lee6526f672015-05-04 17:07:32 -070051 * Sets the specified package name as the default dialer application for the current user.
52 * The caller of this method needs to have permission to write to secure settings and
53 * manage users on the device.
Yorke Lee014de022015-04-21 17:15:47 -070054 *
Yorke Leedb6da482015-06-02 13:55:25 -070055 * @return {@code true} if the default dialer application was successfully changed,
56 * {@code false} otherwise.
57 *
Yorke Lee014de022015-04-21 17:15:47 -070058 * @hide
59 * */
Yorke Leedb6da482015-06-02 13:55:25 -070060 public static boolean setDefaultDialerApplication(Context context, String packageName) {
61 return setDefaultDialerApplication(context, packageName, ActivityManager.getCurrentUser());
Yorke Lee6526f672015-05-04 17:07:32 -070062 }
63
64 /**
65 * Sets the specified package name as the default dialer application for the specified user.
66 * The caller of this method needs to have permission to write to secure settings and
67 * manage users on the device.
68 *
Yorke Leedb6da482015-06-02 13:55:25 -070069 * @return {@code true} if the default dialer application was successfully changed,
70 * {@code false} otherwise.
71 *
Yorke Lee6526f672015-05-04 17:07:32 -070072 * @hide
73 * */
Yorke Leedb6da482015-06-02 13:55:25 -070074 public static boolean setDefaultDialerApplication(Context context, String packageName,
75 int user) {
Eugene Susla92b88c72019-01-11 13:31:20 -080076 long identity = Binder.clearCallingIdentity();
77 try {
Eugene Susla98a872d2019-01-31 18:30:47 -080078 RoleManagerCallback.Future cb = new RoleManagerCallback.Future();
Eugene Susla92b88c72019-01-11 13:31:20 -080079 context.getSystemService(RoleManager.class).addRoleHolderAsUser(
Hai Zhang71d70362019-02-04 16:17:38 -080080 RoleManager.ROLE_DIALER, packageName, 0, UserHandle.of(user),
Eugene Susla98a872d2019-01-31 18:30:47 -080081 AsyncTask.THREAD_POOL_EXECUTOR, cb);
82 cb.get(5, TimeUnit.SECONDS);
Yorke Leedb6da482015-06-02 13:55:25 -070083 return true;
Eugene Susla98a872d2019-01-31 18:30:47 -080084 } catch (InterruptedException | ExecutionException | TimeoutException e) {
85 Slog.e(TAG, "Failed to set default dialer to " + packageName + " for user " + user, e);
86 return false;
Eugene Susla92b88c72019-01-11 13:31:20 -080087 } finally {
88 Binder.restoreCallingIdentity(identity);
Yorke Lee014de022015-04-21 17:15:47 -070089 }
90 }
91
92 /**
Yorke Lee6526f672015-05-04 17:07:32 -070093 * Returns the installed dialer application for the current user that will be used to receive
94 * incoming calls, and is allowed to make emergency calls.
Yorke Lee014de022015-04-21 17:15:47 -070095 *
96 * The application will be returned in order of preference:
97 * 1) User selected phone application (if still installed)
98 * 2) Pre-installed system dialer (if not disabled)
99 * 3) Null
100 *
Yorke Lee6526f672015-05-04 17:07:32 -0700101 * The caller of this method needs to have permission to manage users on the device.
102 *
Yorke Lee014de022015-04-21 17:15:47 -0700103 * @hide
104 * */
Yorke Lee8e0207b2015-04-28 09:39:20 -0700105 public static String getDefaultDialerApplication(Context context) {
Svet Ganov52153f42015-08-11 08:59:12 -0700106 return getDefaultDialerApplication(context, context.getUserId());
Yorke Lee6526f672015-05-04 17:07:32 -0700107 }
Yorke Lee014de022015-04-21 17:15:47 -0700108
Yorke Lee6526f672015-05-04 17:07:32 -0700109 /**
110 * Returns the installed dialer application for the specified user that will be used to receive
111 * incoming calls, and is allowed to make emergency calls.
112 *
113 * The application will be returned in order of preference:
114 * 1) User selected phone application (if still installed)
115 * 2) Pre-installed system dialer (if not disabled)
116 * 3) Null
117 *
118 * The caller of this method needs to have permission to manage users on the device.
119 *
120 * @hide
121 * */
122 public static String getDefaultDialerApplication(Context context, int user) {
Eugene Susla92b88c72019-01-11 13:31:20 -0800123 long identity = Binder.clearCallingIdentity();
124 try {
125 return CollectionUtils.firstOrNull(context.getSystemService(RoleManager.class)
126 .getRoleHoldersAsUser(RoleManager.ROLE_DIALER, UserHandle.of(user)));
127 } finally {
128 Binder.restoreCallingIdentity(identity);
Yorke Lee8e0207b2015-04-28 09:39:20 -0700129 }
Yorke Lee014de022015-04-21 17:15:47 -0700130 }
131
132 /**
133 * Returns a list of installed and available dialer applications.
134 *
135 * In order to appear in the list, a dialer application must implement an intent-filter with
136 * the DIAL intent for the following schemes:
137 *
138 * 1) Empty scheme
139 * 2) tel Uri scheme
140 *
141 * @hide
142 **/
Tony Makb401a942016-01-19 19:05:18 +0000143 public static List<String> getInstalledDialerApplications(Context context, int userId) {
Yorke Lee014de022015-04-21 17:15:47 -0700144 PackageManager packageManager = context.getPackageManager();
145
146 // Get the list of apps registered for the DIAL intent with empty scheme
147 Intent intent = new Intent(Intent.ACTION_DIAL);
Tony Makb401a942016-01-19 19:05:18 +0000148 List<ResolveInfo> resolveInfoList =
149 packageManager.queryIntentActivitiesAsUser(intent, 0, userId);
Yorke Lee014de022015-04-21 17:15:47 -0700150
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;
Tony Mak39198fa2017-09-15 17:41:43 +0100155 if (activityInfo != null
156 && !packageNames.contains(activityInfo.packageName)
157 // ignore cross profile intent handler
158 && resolveInfo.targetUserId == UserHandle.USER_CURRENT) {
Yorke Lee856a5ac2015-04-28 15:45:42 -0700159 packageNames.add(activityInfo.packageName);
Yorke Lee014de022015-04-21 17:15:47 -0700160 }
Yorke Lee014de022015-04-21 17:15:47 -0700161 }
162
Yorke Lee856a5ac2015-04-28 15:45:42 -0700163 final Intent dialIntentWithTelScheme = new Intent(Intent.ACTION_DIAL);
164 dialIntentWithTelScheme.setData(Uri.fromParts(PhoneAccount.SCHEME_TEL, "", null));
Hai Zhang7c8d2e72019-02-11 19:07:30 +0000165 return filterByIntent(context, packageNames, dialIntentWithTelScheme, userId);
Yorke Lee014de022015-04-21 17:15:47 -0700166 }
167
Tony Makb401a942016-01-19 19:05:18 +0000168 public static List<String> getInstalledDialerApplications(Context context) {
169 return getInstalledDialerApplications(context, Process.myUserHandle().getIdentifier());
170 }
171
Yorke Lee014de022015-04-21 17:15:47 -0700172 /**
Yorke Lee61043822015-04-27 11:18:38 -0700173 * Determines if the package name belongs to the user-selected default dialer or the preloaded
174 * system dialer, and thus should be allowed to perform certain privileged operations.
175 *
176 * @param context A valid context.
177 * @param packageName of the package to check for.
178 *
179 * @return {@code true} if the provided package name corresponds to the user-selected default
180 * dialer or the preloaded system dialer, {@code false} otherwise.
181 *
182 * @hide
183 */
184 public static boolean isDefaultOrSystemDialer(Context context, String packageName) {
185 if (TextUtils.isEmpty(packageName)) {
186 return false;
187 }
188 final TelecomManager tm = getTelecomManager(context);
189 return packageName.equals(tm.getDefaultDialerPackage())
190 || packageName.equals(tm.getSystemDialerPackage());
191 }
192
Yorke Lee856a5ac2015-04-28 15:45:42 -0700193 /**
194 * Filter a given list of package names for those packages that contain an activity that has
195 * an intent filter for a given intent.
196 *
197 * @param context A valid context
198 * @param packageNames List of package names to filter.
Tyler Gunn0907bd62017-09-01 15:17:05 -0700199 * @param userId The UserId
Yorke Lee856a5ac2015-04-28 15:45:42 -0700200 * @return The filtered list.
201 */
202 private static List<String> filterByIntent(Context context, List<String> packageNames,
Tyler Gunn0907bd62017-09-01 15:17:05 -0700203 Intent intent, int userId) {
Yorke Lee856a5ac2015-04-28 15:45:42 -0700204 if (packageNames == null || packageNames.isEmpty()) {
205 return new ArrayList<>();
206 }
207
208 final List<String> result = new ArrayList<>();
Jeff Sharkey2a9e3f82015-12-18 10:57:58 -0700209 final List<ResolveInfo> resolveInfoList = context.getPackageManager()
Tyler Gunn0907bd62017-09-01 15:17:05 -0700210 .queryIntentActivitiesAsUser(intent, 0, userId);
Yorke Lee856a5ac2015-04-28 15:45:42 -0700211 final int length = resolveInfoList.size();
212 for (int i = 0; i < length; i++) {
213 final ActivityInfo info = resolveInfoList.get(i).activityInfo;
214 if (info != null && packageNames.contains(info.packageName)
215 && !result.contains(info.packageName)) {
216 result.add(info.packageName);
217 }
218 }
219
220 return result;
221 }
222
223
Yorke Lee014de022015-04-21 17:15:47 -0700224 private static TelecomManager getTelecomManager(Context context) {
225 return (TelecomManager) context.getSystemService(Context.TELECOM_SERVICE);
226 }
227}