236 lines
		
	
	
		
			9.1 KiB
		
	
	
	
		
			Java
		
	
	
	
			
		
		
	
	
			236 lines
		
	
	
		
			9.1 KiB
		
	
	
	
		
			Java
		
	
	
	
| /*
 | |
|  * Copyright (C) 2015 The Android Open Source Project
 | |
|  *
 | |
|  * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
 | |
|  * in compliance with the License. You may obtain a copy of the License at
 | |
|  *
 | |
|  * http://www.apache.org/licenses/LICENSE-2.0
 | |
|  *
 | |
|  * Unless required by applicable law or agreed to in writing, software distributed under the License
 | |
|  * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
 | |
|  * or implied. See the License for the specific language governing permissions and limitations under
 | |
|  * the License.
 | |
|  */
 | |
| 
 | |
| package android.telecom;
 | |
| 
 | |
| import android.app.ActivityManager;
 | |
| import android.app.role.RoleManager;
 | |
| import android.content.Context;
 | |
| import android.content.Intent;
 | |
| import android.content.pm.ActivityInfo;
 | |
| import android.content.pm.PackageManager;
 | |
| import android.content.pm.ResolveInfo;
 | |
| import android.net.Uri;
 | |
| import android.os.AsyncTask;
 | |
| import android.os.Binder;
 | |
| import android.os.Process;
 | |
| import android.os.UserHandle;
 | |
| import android.text.TextUtils;
 | |
| import android.util.Slog;
 | |
| 
 | |
| import com.android.internal.util.CollectionUtils;
 | |
| 
 | |
| import java.util.ArrayList;
 | |
| import java.util.List;
 | |
| import java.util.concurrent.CompletableFuture;
 | |
| import java.util.concurrent.ExecutionException;
 | |
| import java.util.concurrent.TimeUnit;
 | |
| import java.util.concurrent.TimeoutException;
 | |
| import java.util.function.Consumer;
 | |
| 
 | |
| /**
 | |
|  * Class for managing the default dialer application that will receive incoming calls, and be
 | |
|  * allowed to make emergency outgoing calls.
 | |
|  *
 | |
|  * @hide
 | |
|  */
 | |
| public class DefaultDialerManager {
 | |
|     private static final String TAG = "DefaultDialerManager";
 | |
| 
 | |
|     /**
 | |
|      * Sets the specified package name as the default dialer application for the current user.
 | |
|      * The caller of this method needs to have permission to write to secure settings and
 | |
|      * manage users on the device.
 | |
|      *
 | |
|      * @return {@code true} if the default dialer application was successfully changed,
 | |
|      *         {@code false} otherwise.
 | |
|      *
 | |
|      * @hide
 | |
|      * */
 | |
|     public static boolean setDefaultDialerApplication(Context context, String packageName) {
 | |
|         return setDefaultDialerApplication(context, packageName, ActivityManager.getCurrentUser());
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Sets the specified package name as the default dialer application for the specified user.
 | |
|      * The caller of this method needs to have permission to write to secure settings and
 | |
|      * manage users on the device.
 | |
|      *
 | |
|      * @return {@code true} if the default dialer application was successfully changed,
 | |
|      *         {@code false} otherwise.
 | |
|      *
 | |
|      * @hide
 | |
|      * */
 | |
|     public static boolean setDefaultDialerApplication(Context context, String packageName,
 | |
|             int user) {
 | |
|         final long identity = Binder.clearCallingIdentity();
 | |
|         try {
 | |
|             CompletableFuture<Void> future = new CompletableFuture<>();
 | |
|             Consumer<Boolean> callback = successful -> {
 | |
|                 if (successful) {
 | |
|                     future.complete(null);
 | |
|                 } else {
 | |
|                     future.completeExceptionally(new RuntimeException());
 | |
|                 }
 | |
|             };
 | |
|             context.getSystemService(RoleManager.class).addRoleHolderAsUser(
 | |
|                     RoleManager.ROLE_DIALER, packageName, 0, UserHandle.of(user),
 | |
|                     AsyncTask.THREAD_POOL_EXECUTOR, callback);
 | |
|             future.get(5, TimeUnit.SECONDS);
 | |
|             return true;
 | |
|         } catch (InterruptedException | ExecutionException | TimeoutException e) {
 | |
|             Slog.e(TAG, "Failed to set default dialer to " + packageName + " for user " + user, e);
 | |
|             return false;
 | |
|         } finally {
 | |
|             Binder.restoreCallingIdentity(identity);
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Returns the installed dialer application for the current user that will be used to receive
 | |
|      * incoming calls, and is allowed to make emergency calls.
 | |
|      *
 | |
|      * The application will be returned in order of preference:
 | |
|      * 1) User selected phone application (if still installed)
 | |
|      * 2) Pre-installed system dialer (if not disabled)
 | |
|      * 3) Null
 | |
|      *
 | |
|      * The caller of this method needs to have permission to manage users on the device.
 | |
|      *
 | |
|      * @hide
 | |
|      * */
 | |
|     public static String getDefaultDialerApplication(Context context) {
 | |
|         return getDefaultDialerApplication(context, context.getUserId());
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Returns the installed dialer application for the specified user that will be used to receive
 | |
|      * incoming calls, and is allowed to make emergency calls.
 | |
|      *
 | |
|      * The application will be returned in order of preference:
 | |
|      * 1) User selected phone application (if still installed)
 | |
|      * 2) Pre-installed system dialer (if not disabled)
 | |
|      * 3) Null
 | |
|      *
 | |
|      * The caller of this method needs to have permission to manage users on the device.
 | |
|      *
 | |
|      * @hide
 | |
|      * */
 | |
|     public static String getDefaultDialerApplication(Context context, int user) {
 | |
|         final long identity = Binder.clearCallingIdentity();
 | |
|         try {
 | |
|             return CollectionUtils.firstOrNull(context.getSystemService(RoleManager.class)
 | |
|                     .getRoleHoldersAsUser(RoleManager.ROLE_DIALER, UserHandle.of(user)));
 | |
|         } finally {
 | |
|             Binder.restoreCallingIdentity(identity);
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Returns a list of installed and available dialer applications.
 | |
|      *
 | |
|      * In order to appear in the list, a dialer application must implement an intent-filter with
 | |
|      * the DIAL intent for the following schemes:
 | |
|      *
 | |
|      * 1) Empty scheme
 | |
|      * 2) tel Uri scheme
 | |
|      *
 | |
|      * @hide
 | |
|      **/
 | |
|     public static List<String> getInstalledDialerApplications(Context context, int userId) {
 | |
|         PackageManager packageManager = context.getPackageManager();
 | |
| 
 | |
|         // Get the list of apps registered for the DIAL intent with empty scheme
 | |
|         Intent intent = new Intent(Intent.ACTION_DIAL);
 | |
|         List<ResolveInfo> resolveInfoList =
 | |
|                 packageManager.queryIntentActivitiesAsUser(intent, 0, userId);
 | |
| 
 | |
|         List<String> packageNames = new ArrayList<>();
 | |
| 
 | |
|         for (ResolveInfo resolveInfo : resolveInfoList) {
 | |
|             final ActivityInfo activityInfo = resolveInfo.activityInfo;
 | |
|             if (activityInfo != null
 | |
|                     && !packageNames.contains(activityInfo.packageName)
 | |
|                     // ignore cross profile intent handler
 | |
|                     && resolveInfo.targetUserId == UserHandle.USER_CURRENT) {
 | |
|                 packageNames.add(activityInfo.packageName);
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         final Intent dialIntentWithTelScheme = new Intent(Intent.ACTION_DIAL);
 | |
|         dialIntentWithTelScheme.setData(Uri.fromParts(PhoneAccount.SCHEME_TEL, "", null));
 | |
|         return filterByIntent(context, packageNames, dialIntentWithTelScheme, userId);
 | |
|     }
 | |
| 
 | |
|     public static List<String> getInstalledDialerApplications(Context context) {
 | |
|         return getInstalledDialerApplications(context, Process.myUserHandle().getIdentifier());
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Determines if the package name belongs to the user-selected default dialer or the preloaded
 | |
|      * system dialer, and thus should be allowed to perform certain privileged operations.
 | |
|      *
 | |
|      * @param context A valid context.
 | |
|      * @param packageName of the package to check for.
 | |
|      *
 | |
|      * @return {@code true} if the provided package name corresponds to the user-selected default
 | |
|      *         dialer or the preloaded system dialer, {@code false} otherwise.
 | |
|      *
 | |
|      * @hide
 | |
|      */
 | |
|     public static boolean isDefaultOrSystemDialer(Context context, String packageName) {
 | |
|         if (TextUtils.isEmpty(packageName)) {
 | |
|             return false;
 | |
|         }
 | |
|         final TelecomManager tm = getTelecomManager(context);
 | |
|         return packageName.equals(tm.getDefaultDialerPackage())
 | |
|                 || packageName.equals(tm.getSystemDialerPackage());
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Filter a given list of package names for those packages that contain an activity that has
 | |
|      * an intent filter for a given intent.
 | |
|      *
 | |
|      * @param context A valid context
 | |
|      * @param packageNames List of package names to filter.
 | |
|      * @param userId The UserId
 | |
|      * @return The filtered list.
 | |
|      */
 | |
|     private static List<String> filterByIntent(Context context, List<String> packageNames,
 | |
|             Intent intent, int userId) {
 | |
|         if (packageNames == null || packageNames.isEmpty()) {
 | |
|             return new ArrayList<>();
 | |
|         }
 | |
| 
 | |
|         final List<String> result = new ArrayList<>();
 | |
|         final List<ResolveInfo> resolveInfoList = context.getPackageManager()
 | |
|                 .queryIntentActivitiesAsUser(intent, 0, userId);
 | |
|         final int length = resolveInfoList.size();
 | |
|         for (int i = 0; i < length; i++) {
 | |
|             final ActivityInfo info = resolveInfoList.get(i).activityInfo;
 | |
|             if (info != null && packageNames.contains(info.packageName)
 | |
|                     && !result.contains(info.packageName)) {
 | |
|                 result.add(info.packageName);
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         return result;
 | |
|     }
 | |
| 
 | |
| 
 | |
|     private static TelecomManager getTelecomManager(Context context) {
 | |
|         return (TelecomManager) context.getSystemService(Context.TELECOM_SERVICE);
 | |
|     }
 | |
| }
 |