/* * Copyright (C) 2019 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 com.android.systemui; import android.content.Context; import android.content.Intent; import android.content.pm.ActivityInfo; import android.content.pm.PackageManager; import android.content.pm.ResolveInfo; import java.util.List; /** * Contains useful methods for querying properties of an Activity Intent. */ public class ActivityIntentHelper { private final Context mContext; public ActivityIntentHelper(Context context) { mContext = context; } /** * Determines if sending the given intent would result in starting an Intent resolver activity, * instead of resolving to a specific component. * * @param intent the intent * @param currentUserId the id for the user to resolve as * @return true if the intent would launch a resolver activity */ public boolean wouldLaunchResolverActivity(Intent intent, int currentUserId) { ActivityInfo targetActivityInfo = getTargetActivityInfo(intent, currentUserId, false /* onlyDirectBootAware */); return targetActivityInfo == null; } /** * Returns info about the target Activity of a given intent, or null if the intent does not * resolve to a specific component meeting the requirements. * * @param onlyDirectBootAware a boolean indicating whether the matched activity packages must * be direct boot aware when in direct boot mode if false, all packages are considered * a match even if they are not aware. * @return the target activity info of the intent it resolves to a specific package or * {@code null} if it resolved to the resolver activity */ public ActivityInfo getTargetActivityInfo(Intent intent, int currentUserId, boolean onlyDirectBootAware) { PackageManager packageManager = mContext.getPackageManager(); int flags = PackageManager.MATCH_DEFAULT_ONLY; if (!onlyDirectBootAware) { flags |= PackageManager.MATCH_DIRECT_BOOT_AWARE | PackageManager.MATCH_DIRECT_BOOT_UNAWARE; } final List appList = packageManager.queryIntentActivitiesAsUser( intent, flags, currentUserId); if (appList.size() == 0) { return null; } ResolveInfo resolved = packageManager.resolveActivityAsUser(intent, flags | PackageManager.GET_META_DATA, currentUserId); if (resolved == null || wouldLaunchResolverActivity(resolved, appList)) { return null; } else { return resolved.activityInfo; } } /** * Determines if the given intent resolves to an Activity which is allowed to appear above * the lock screen. * * @param intent the intent to resolve * @return true if the launched Activity would appear above the lock screen */ public boolean wouldShowOverLockscreen(Intent intent, int currentUserId) { ActivityInfo targetActivityInfo = getTargetActivityInfo(intent, currentUserId, false /* onlyDirectBootAware */); return targetActivityInfo != null && (targetActivityInfo.flags & (ActivityInfo.FLAG_SHOW_WHEN_LOCKED | ActivityInfo.FLAG_SHOW_FOR_ALL_USERS)) > 0; } /** * Determines if sending the given intent would result in starting an Intent resolver activity, * instead of resolving to a specific component. * * @param resolved the resolveInfo for the intent as returned by resolveActivityAsUser * @param appList a list of resolveInfo as returned by queryIntentActivitiesAsUser * @return true if the intent would launch a resolver activity */ public boolean wouldLaunchResolverActivity(ResolveInfo resolved, List appList) { // If the list contains the above resolved activity, then it can't be // ResolverActivity itself. for (int i = 0; i < appList.size(); i++) { ResolveInfo tmp = appList.get(i); if (tmp.activityInfo.name.equals(resolved.activityInfo.name) && tmp.activityInfo.packageName.equals(resolved.activityInfo.packageName)) { return false; } } return true; } }