blob: a5e8fe1c9168515858f7d0d25fe35936d92a28b8 [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;
Yorke Lee014de022015-04-21 17:15:47 -070025import android.provider.Settings;
26import android.text.TextUtils;
27
28import java.util.ArrayList;
29import 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 */
37public class DefaultDialerManager {
38 private static final String TAG = "DefaultDialerManager";
39
40 /**
Yorke Lee6526f672015-05-04 17:07:32 -070041 * 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.
Yorke Lee014de022015-04-21 17:15:47 -070044 *
Yorke Leedb6da482015-06-02 13:55:25 -070045 * @return {@code true} if the default dialer application was successfully changed,
46 * {@code false} otherwise.
47 *
Yorke Lee014de022015-04-21 17:15:47 -070048 * @hide
49 * */
Yorke Leedb6da482015-06-02 13:55:25 -070050 public static boolean setDefaultDialerApplication(Context context, String packageName) {
51 return setDefaultDialerApplication(context, packageName, ActivityManager.getCurrentUser());
Yorke Lee6526f672015-05-04 17:07:32 -070052 }
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 *
Yorke Leedb6da482015-06-02 13:55:25 -070059 * @return {@code true} if the default dialer application was successfully changed,
60 * {@code false} otherwise.
61 *
Yorke Lee6526f672015-05-04 17:07:32 -070062 * @hide
63 * */
Yorke Leedb6da482015-06-02 13:55:25 -070064 public static boolean setDefaultDialerApplication(Context context, String packageName,
65 int user) {
Yorke Lee014de022015-04-21 17:15:47 -070066 // Get old package name
Yorke Lee6526f672015-05-04 17:07:32 -070067 String oldPackageName = Settings.Secure.getStringForUser(context.getContentResolver(),
68 Settings.Secure.DIALER_DEFAULT_APPLICATION, user);
Yorke Lee014de022015-04-21 17:15:47 -070069
70 if (packageName != null && oldPackageName != null && packageName.equals(oldPackageName)) {
71 // No change
Yorke Leedb6da482015-06-02 13:55:25 -070072 return false;
Yorke Lee014de022015-04-21 17:15:47 -070073 }
74
75 // Only make the change if the new package belongs to a valid phone application
Yorke Lee8e0207b2015-04-28 09:39:20 -070076 List<String> packageNames = getInstalledDialerApplications(context);
Yorke Lee014de022015-04-21 17:15:47 -070077
Yorke Lee8e0207b2015-04-28 09:39:20 -070078 if (packageNames.contains(packageName)) {
Yorke Lee014de022015-04-21 17:15:47 -070079 // Update the secure setting.
Yorke Lee6526f672015-05-04 17:07:32 -070080 Settings.Secure.putStringForUser(context.getContentResolver(),
81 Settings.Secure.DIALER_DEFAULT_APPLICATION, packageName, user);
Yorke Leedb6da482015-06-02 13:55:25 -070082 return true;
Yorke Lee014de022015-04-21 17:15:47 -070083 }
Yorke Leedb6da482015-06-02 13:55:25 -070084 return false;
Yorke Lee014de022015-04-21 17:15:47 -070085 }
86
87 /**
Yorke Lee6526f672015-05-04 17:07:32 -070088 * 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.
Yorke Lee014de022015-04-21 17:15:47 -070090 *
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 *
Yorke Lee6526f672015-05-04 17:07:32 -070096 * The caller of this method needs to have permission to manage users on the device.
97 *
Yorke Lee014de022015-04-21 17:15:47 -070098 * @hide
99 * */
Yorke Lee8e0207b2015-04-28 09:39:20 -0700100 public static String getDefaultDialerApplication(Context context) {
Svet Ganov52153f42015-08-11 08:59:12 -0700101 return getDefaultDialerApplication(context, context.getUserId());
Yorke Lee6526f672015-05-04 17:07:32 -0700102 }
Yorke Lee014de022015-04-21 17:15:47 -0700103
Yorke Lee6526f672015-05-04 17:07:32 -0700104 /**
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 * */
117 public static String getDefaultDialerApplication(Context context, int user) {
118 String defaultPackageName = Settings.Secure.getStringForUser(context.getContentResolver(),
119 Settings.Secure.DIALER_DEFAULT_APPLICATION, user);
Yorke Lee8e0207b2015-04-28 09:39:20 -0700120
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;
Yorke Lee014de022015-04-21 17:15:47 -0700126 }
127
128 // No user-set dialer found, fallback to system dialer
Yorke Lee8e0207b2015-04-28 09:39:20 -0700129 String systemDialerPackageName = getTelecomManager(context).getSystemDialerPackage();
Yorke Lee014de022015-04-21 17:15:47 -0700130
Yorke Lee8e0207b2015-04-28 09:39:20 -0700131 if (TextUtils.isEmpty(systemDialerPackageName)) {
Yorke Lee014de022015-04-21 17:15:47 -0700132 // No system dialer configured at build time
133 return null;
134 }
135
Yorke Lee8e0207b2015-04-28 09:39:20 -0700136 if (packageNames.contains(systemDialerPackageName)) {
137 return systemDialerPackageName;
138 } else {
139 return null;
140 }
Yorke Lee014de022015-04-21 17:15:47 -0700141 }
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 **/
Tony Makb401a942016-01-19 19:05:18 +0000154 public static List<String> getInstalledDialerApplications(Context context, int userId) {
Yorke Lee014de022015-04-21 17:15:47 -0700155 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);
Tony Makb401a942016-01-19 19:05:18 +0000159 List<ResolveInfo> resolveInfoList =
160 packageManager.queryIntentActivitiesAsUser(intent, 0, userId);
Yorke Lee014de022015-04-21 17:15:47 -0700161
Yorke Lee8e0207b2015-04-28 09:39:20 -0700162 List<String> packageNames = new ArrayList<>();
Yorke Lee014de022015-04-21 17:15:47 -0700163
164 for (ResolveInfo resolveInfo : resolveInfoList) {
165 final ActivityInfo activityInfo = resolveInfo.activityInfo;
Yorke Lee856a5ac2015-04-28 15:45:42 -0700166 if (activityInfo != null && !packageNames.contains(activityInfo.packageName)) {
167 packageNames.add(activityInfo.packageName);
Yorke Lee014de022015-04-21 17:15:47 -0700168 }
Yorke Lee014de022015-04-21 17:15:47 -0700169 }
170
Yorke Lee856a5ac2015-04-28 15:45:42 -0700171 final Intent dialIntentWithTelScheme = new Intent(Intent.ACTION_DIAL);
172 dialIntentWithTelScheme.setData(Uri.fromParts(PhoneAccount.SCHEME_TEL, "", null));
173 return filterByIntent(context, packageNames, dialIntentWithTelScheme);
Yorke Lee014de022015-04-21 17:15:47 -0700174 }
175
Tony Makb401a942016-01-19 19:05:18 +0000176 public static List<String> getInstalledDialerApplications(Context context) {
177 return getInstalledDialerApplications(context, Process.myUserHandle().getIdentifier());
178 }
179
Yorke Lee014de022015-04-21 17:15:47 -0700180 /**
Yorke Lee61043822015-04-27 11:18:38 -0700181 * 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 */
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
Yorke Lee856a5ac2015-04-28 15:45:42 -0700201 /**
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 */
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<>();
Jeff Sharkey2a9e3f82015-12-18 10:57:58 -0700216 final List<ResolveInfo> resolveInfoList = context.getPackageManager()
Jeff Sharkey2f3e3532015-12-21 14:16:43 -0700217 .queryIntentActivities(intent, 0);
Yorke Lee856a5ac2015-04-28 15:45:42 -0700218 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
Yorke Lee014de022015-04-21 17:15:47 -0700231 private static TelecomManager getTelecomManager(Context context) {
232 return (TelecomManager) context.getSystemService(Context.TELECOM_SERVICE);
233 }
234}