blob: 27ee804bebd41140498bb5401b130b55fab414d4 [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 *
Yorke Leedb6da482015-06-02 13:55:25 -070044 * @return {@code true} if the default dialer application was successfully changed,
45 * {@code false} otherwise.
46 *
Yorke Lee014de022015-04-21 17:15:47 -070047 * @hide
48 * */
Yorke Leedb6da482015-06-02 13:55:25 -070049 public static boolean setDefaultDialerApplication(Context context, String packageName) {
50 return setDefaultDialerApplication(context, packageName, ActivityManager.getCurrentUser());
Yorke Lee6526f672015-05-04 17:07:32 -070051 }
52
53 /**
54 * Sets the specified package name as the default dialer application for the specified user.
55 * The caller of this method needs to have permission to write to secure settings and
56 * manage users on the device.
57 *
Yorke Leedb6da482015-06-02 13:55:25 -070058 * @return {@code true} if the default dialer application was successfully changed,
59 * {@code false} otherwise.
60 *
Yorke Lee6526f672015-05-04 17:07:32 -070061 * @hide
62 * */
Yorke Leedb6da482015-06-02 13:55:25 -070063 public static boolean setDefaultDialerApplication(Context context, String packageName,
64 int user) {
Yorke Lee014de022015-04-21 17:15:47 -070065 // Get old package name
Yorke Lee6526f672015-05-04 17:07:32 -070066 String oldPackageName = Settings.Secure.getStringForUser(context.getContentResolver(),
67 Settings.Secure.DIALER_DEFAULT_APPLICATION, user);
Yorke Lee014de022015-04-21 17:15:47 -070068
69 if (packageName != null && oldPackageName != null && packageName.equals(oldPackageName)) {
70 // No change
Yorke Leedb6da482015-06-02 13:55:25 -070071 return false;
Yorke Lee014de022015-04-21 17:15:47 -070072 }
73
74 // Only make the change if the new package belongs to a valid phone application
Yorke Lee8e0207b2015-04-28 09:39:20 -070075 List<String> packageNames = getInstalledDialerApplications(context);
Yorke Lee014de022015-04-21 17:15:47 -070076
Yorke Lee8e0207b2015-04-28 09:39:20 -070077 if (packageNames.contains(packageName)) {
Yorke Lee014de022015-04-21 17:15:47 -070078 // Update the secure setting.
Yorke Lee6526f672015-05-04 17:07:32 -070079 Settings.Secure.putStringForUser(context.getContentResolver(),
80 Settings.Secure.DIALER_DEFAULT_APPLICATION, packageName, user);
Yorke Leedb6da482015-06-02 13:55:25 -070081 return true;
Yorke Lee014de022015-04-21 17:15:47 -070082 }
Yorke Leedb6da482015-06-02 13:55:25 -070083 return false;
Yorke Lee014de022015-04-21 17:15:47 -070084 }
85
86 /**
Yorke Lee6526f672015-05-04 17:07:32 -070087 * Returns the installed dialer application for the current user that will be used to receive
88 * incoming calls, and is allowed to make emergency calls.
Yorke Lee014de022015-04-21 17:15:47 -070089 *
90 * The application will be returned in order of preference:
91 * 1) User selected phone application (if still installed)
92 * 2) Pre-installed system dialer (if not disabled)
93 * 3) Null
94 *
Yorke Lee6526f672015-05-04 17:07:32 -070095 * The caller of this method needs to have permission to manage users on the device.
96 *
Yorke Lee014de022015-04-21 17:15:47 -070097 * @hide
98 * */
Yorke Lee8e0207b2015-04-28 09:39:20 -070099 public static String getDefaultDialerApplication(Context context) {
Svet Ganov52153f42015-08-11 08:59:12 -0700100 return getDefaultDialerApplication(context, context.getUserId());
Yorke Lee6526f672015-05-04 17:07:32 -0700101 }
Yorke Lee014de022015-04-21 17:15:47 -0700102
Yorke Lee6526f672015-05-04 17:07:32 -0700103 /**
104 * Returns the installed dialer application for the specified user that will be used to receive
105 * incoming calls, and is allowed to make emergency calls.
106 *
107 * The application will be returned in order of preference:
108 * 1) User selected phone application (if still installed)
109 * 2) Pre-installed system dialer (if not disabled)
110 * 3) Null
111 *
112 * The caller of this method needs to have permission to manage users on the device.
113 *
114 * @hide
115 * */
116 public static String getDefaultDialerApplication(Context context, int user) {
117 String defaultPackageName = Settings.Secure.getStringForUser(context.getContentResolver(),
118 Settings.Secure.DIALER_DEFAULT_APPLICATION, user);
Yorke Lee8e0207b2015-04-28 09:39:20 -0700119
120 final List<String> packageNames = getInstalledDialerApplications(context);
121
122 // Verify that the default dialer has not been disabled or uninstalled.
123 if (packageNames.contains(defaultPackageName)) {
124 return defaultPackageName;
Yorke Lee014de022015-04-21 17:15:47 -0700125 }
126
127 // No user-set dialer found, fallback to system dialer
Yorke Lee8e0207b2015-04-28 09:39:20 -0700128 String systemDialerPackageName = getTelecomManager(context).getSystemDialerPackage();
Yorke Lee014de022015-04-21 17:15:47 -0700129
Yorke Lee8e0207b2015-04-28 09:39:20 -0700130 if (TextUtils.isEmpty(systemDialerPackageName)) {
Yorke Lee014de022015-04-21 17:15:47 -0700131 // No system dialer configured at build time
132 return null;
133 }
134
Yorke Lee8e0207b2015-04-28 09:39:20 -0700135 if (packageNames.contains(systemDialerPackageName)) {
136 return systemDialerPackageName;
137 } else {
138 return null;
139 }
Yorke Lee014de022015-04-21 17:15:47 -0700140 }
141
142 /**
143 * Returns a list of installed and available dialer applications.
144 *
145 * In order to appear in the list, a dialer application must implement an intent-filter with
146 * the DIAL intent for the following schemes:
147 *
148 * 1) Empty scheme
149 * 2) tel Uri scheme
150 *
151 * @hide
152 **/
Yorke Lee8e0207b2015-04-28 09:39:20 -0700153 public static List<String> getInstalledDialerApplications(Context context) {
Yorke Lee014de022015-04-21 17:15:47 -0700154 PackageManager packageManager = context.getPackageManager();
155
156 // Get the list of apps registered for the DIAL intent with empty scheme
157 Intent intent = new Intent(Intent.ACTION_DIAL);
Jeff Sharkey2a9e3f82015-12-18 10:57:58 -0700158 List<ResolveInfo> resolveInfoList = packageManager.queryIntentActivities(intent,
159 PackageManager.MATCH_ENCRYPTION_DEFAULT);
Yorke Lee014de022015-04-21 17:15:47 -0700160
Yorke Lee8e0207b2015-04-28 09:39:20 -0700161 List<String> packageNames = new ArrayList<>();
Yorke Lee014de022015-04-21 17:15:47 -0700162
163 for (ResolveInfo resolveInfo : resolveInfoList) {
164 final ActivityInfo activityInfo = resolveInfo.activityInfo;
Yorke Lee856a5ac2015-04-28 15:45:42 -0700165 if (activityInfo != null && !packageNames.contains(activityInfo.packageName)) {
166 packageNames.add(activityInfo.packageName);
Yorke Lee014de022015-04-21 17:15:47 -0700167 }
Yorke Lee014de022015-04-21 17:15:47 -0700168 }
169
Yorke Lee856a5ac2015-04-28 15:45:42 -0700170 final Intent dialIntentWithTelScheme = new Intent(Intent.ACTION_DIAL);
171 dialIntentWithTelScheme.setData(Uri.fromParts(PhoneAccount.SCHEME_TEL, "", null));
172 return filterByIntent(context, packageNames, dialIntentWithTelScheme);
Yorke Lee014de022015-04-21 17:15:47 -0700173 }
174
175 /**
Yorke Lee61043822015-04-27 11:18:38 -0700176 * Determines if the package name belongs to the user-selected default dialer or the preloaded
177 * system dialer, and thus should be allowed to perform certain privileged operations.
178 *
179 * @param context A valid context.
180 * @param packageName of the package to check for.
181 *
182 * @return {@code true} if the provided package name corresponds to the user-selected default
183 * dialer or the preloaded system dialer, {@code false} otherwise.
184 *
185 * @hide
186 */
187 public static boolean isDefaultOrSystemDialer(Context context, String packageName) {
188 if (TextUtils.isEmpty(packageName)) {
189 return false;
190 }
191 final TelecomManager tm = getTelecomManager(context);
192 return packageName.equals(tm.getDefaultDialerPackage())
193 || packageName.equals(tm.getSystemDialerPackage());
194 }
195
Yorke Lee856a5ac2015-04-28 15:45:42 -0700196 /**
197 * Filter a given list of package names for those packages that contain an activity that has
198 * an intent filter for a given intent.
199 *
200 * @param context A valid context
201 * @param packageNames List of package names to filter.
202 * @return The filtered list.
203 */
204 private static List<String> filterByIntent(Context context, List<String> packageNames,
205 Intent intent) {
206 if (packageNames == null || packageNames.isEmpty()) {
207 return new ArrayList<>();
208 }
209
210 final List<String> result = new ArrayList<>();
Jeff Sharkey2a9e3f82015-12-18 10:57:58 -0700211 final List<ResolveInfo> resolveInfoList = context.getPackageManager()
212 .queryIntentActivities(intent, PackageManager.MATCH_ENCRYPTION_DEFAULT);
Yorke Lee856a5ac2015-04-28 15:45:42 -0700213 final int length = resolveInfoList.size();
214 for (int i = 0; i < length; i++) {
215 final ActivityInfo info = resolveInfoList.get(i).activityInfo;
216 if (info != null && packageNames.contains(info.packageName)
217 && !result.contains(info.packageName)) {
218 result.add(info.packageName);
219 }
220 }
221
222 return result;
223 }
224
225
Yorke Lee014de022015-04-21 17:15:47 -0700226 private static TelecomManager getTelecomManager(Context context) {
227 return (TelecomManager) context.getSystemService(Context.TELECOM_SERVICE);
228 }
229}