1 /* 2 * Copyright (C) 2019 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.systemui; 18 19 import android.content.Context; 20 import android.content.Intent; 21 import android.content.pm.ActivityInfo; 22 import android.content.pm.PackageManager; 23 import android.content.pm.ResolveInfo; 24 25 import com.android.systemui.dagger.SysUISingleton; 26 27 import java.util.List; 28 29 import javax.inject.Inject; 30 31 /** 32 * Contains useful methods for querying properties of an Activity Intent. 33 */ 34 @SysUISingleton 35 public class ActivityIntentHelper { 36 37 private final Context mContext; 38 39 @Inject ActivityIntentHelper(Context context)40 public ActivityIntentHelper(Context context) { 41 // TODO: inject a package manager, not a context. 42 mContext = context; 43 } 44 45 /** 46 * Determines if sending the given intent would result in starting an Intent resolver activity, 47 * instead of resolving to a specific component. 48 * 49 * @param intent the intent 50 * @param currentUserId the id for the user to resolve as 51 * @return true if the intent would launch a resolver activity 52 */ wouldLaunchResolverActivity(Intent intent, int currentUserId)53 public boolean wouldLaunchResolverActivity(Intent intent, int currentUserId) { 54 ActivityInfo targetActivityInfo = getTargetActivityInfo(intent, currentUserId, 55 false /* onlyDirectBootAware */); 56 return targetActivityInfo == null; 57 } 58 59 /** 60 * Returns info about the target Activity of a given intent, or null if the intent does not 61 * resolve to a specific component meeting the requirements. 62 * 63 * @param onlyDirectBootAware a boolean indicating whether the matched activity packages must 64 * be direct boot aware when in direct boot mode if false, all packages are considered 65 * a match even if they are not aware. 66 * @return the target activity info of the intent it resolves to a specific package or 67 * {@code null} if it resolved to the resolver activity 68 */ getTargetActivityInfo(Intent intent, int currentUserId, boolean onlyDirectBootAware)69 public ActivityInfo getTargetActivityInfo(Intent intent, int currentUserId, 70 boolean onlyDirectBootAware) { 71 PackageManager packageManager = mContext.getPackageManager(); 72 int flags = PackageManager.MATCH_DEFAULT_ONLY; 73 if (!onlyDirectBootAware) { 74 flags |= PackageManager.MATCH_DIRECT_BOOT_AWARE 75 | PackageManager.MATCH_DIRECT_BOOT_UNAWARE; 76 } 77 final List<ResolveInfo> appList = packageManager.queryIntentActivitiesAsUser( 78 intent, flags, currentUserId); 79 if (appList.size() == 0) { 80 return null; 81 } 82 ResolveInfo resolved = packageManager.resolveActivityAsUser(intent, 83 flags | PackageManager.GET_META_DATA, currentUserId); 84 if (resolved == null || wouldLaunchResolverActivity(resolved, appList)) { 85 return null; 86 } else { 87 return resolved.activityInfo; 88 } 89 } 90 91 /** 92 * Determines if the given intent resolves to an Activity which is allowed to appear above 93 * the lock screen. 94 * 95 * @param intent the intent to resolve 96 * @return true if the launched Activity would appear above the lock screen 97 */ wouldShowOverLockscreen(Intent intent, int currentUserId)98 public boolean wouldShowOverLockscreen(Intent intent, int currentUserId) { 99 ActivityInfo targetActivityInfo = getTargetActivityInfo(intent, 100 currentUserId, false /* onlyDirectBootAware */); 101 return targetActivityInfo != null 102 && (targetActivityInfo.flags & (ActivityInfo.FLAG_SHOW_WHEN_LOCKED 103 | ActivityInfo.FLAG_SHOW_FOR_ALL_USERS)) > 0; 104 } 105 106 /** 107 * Determines if sending the given intent would result in starting an Intent resolver activity, 108 * instead of resolving to a specific component. 109 * 110 * @param resolved the resolveInfo for the intent as returned by resolveActivityAsUser 111 * @param appList a list of resolveInfo as returned by queryIntentActivitiesAsUser 112 * @return true if the intent would launch a resolver activity 113 */ wouldLaunchResolverActivity(ResolveInfo resolved, List<ResolveInfo> appList)114 public boolean wouldLaunchResolverActivity(ResolveInfo resolved, List<ResolveInfo> appList) { 115 // If the list contains the above resolved activity, then it can't be 116 // ResolverActivity itself. 117 for (int i = 0; i < appList.size(); i++) { 118 ResolveInfo tmp = appList.get(i); 119 if (tmp.activityInfo.name.equals(resolved.activityInfo.name) 120 && tmp.activityInfo.packageName.equals(resolved.activityInfo.packageName)) { 121 return false; 122 } 123 } 124 return true; 125 } 126 } 127