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 java.util.List;
26 
27 /**
28  * Contains useful methods for querying properties of an Activity Intent.
29  */
30 public class ActivityIntentHelper {
31 
32     private final Context mContext;
33 
ActivityIntentHelper(Context context)34     public ActivityIntentHelper(Context context) {
35         mContext = context;
36     }
37 
38     /**
39      * Determines if sending the given intent would result in starting an Intent resolver activity,
40      * instead of resolving to a specific component.
41      *
42      * @param intent the intent
43      * @param currentUserId the id for the user to resolve as
44      * @return true if the intent would launch a resolver activity
45      */
wouldLaunchResolverActivity(Intent intent, int currentUserId)46     public boolean wouldLaunchResolverActivity(Intent intent, int currentUserId) {
47         ActivityInfo targetActivityInfo = getTargetActivityInfo(intent, currentUserId,
48                 false /* onlyDirectBootAware */);
49         return targetActivityInfo == null;
50     }
51 
52     /**
53      * Returns info about the target Activity of a given intent, or null if the intent does not
54      * resolve to a specific component meeting the requirements.
55      *
56      * @param onlyDirectBootAware a boolean indicating whether the matched activity packages must
57      *         be direct boot aware when in direct boot mode if false, all packages are considered
58      *         a match even if they are not aware.
59      * @return the target activity info of the intent it resolves to a specific package or
60      *         {@code null} if it resolved to the resolver activity
61      */
getTargetActivityInfo(Intent intent, int currentUserId, boolean onlyDirectBootAware)62     public ActivityInfo getTargetActivityInfo(Intent intent, int currentUserId,
63             boolean onlyDirectBootAware) {
64         PackageManager packageManager = mContext.getPackageManager();
65         int flags = PackageManager.MATCH_DEFAULT_ONLY;
66         if (!onlyDirectBootAware) {
67             flags |= PackageManager.MATCH_DIRECT_BOOT_AWARE
68                     | PackageManager.MATCH_DIRECT_BOOT_UNAWARE;
69         }
70         final List<ResolveInfo> appList = packageManager.queryIntentActivitiesAsUser(
71                 intent, flags, currentUserId);
72         if (appList.size() == 0) {
73             return null;
74         }
75         ResolveInfo resolved = packageManager.resolveActivityAsUser(intent,
76                 flags | PackageManager.GET_META_DATA, currentUserId);
77         if (resolved == null || wouldLaunchResolverActivity(resolved, appList)) {
78             return null;
79         } else {
80             return resolved.activityInfo;
81         }
82     }
83 
84     /**
85      * Determines if the given intent resolves to an Activity which is allowed to appear above
86      * the lock screen.
87      *
88      * @param intent the intent to resolve
89      * @return true if the launched Activity would appear above the lock screen
90      */
wouldShowOverLockscreen(Intent intent, int currentUserId)91     public boolean wouldShowOverLockscreen(Intent intent, int currentUserId) {
92         ActivityInfo targetActivityInfo = getTargetActivityInfo(intent,
93                 currentUserId, false /* onlyDirectBootAware */);
94         return targetActivityInfo != null
95                 && (targetActivityInfo.flags & (ActivityInfo.FLAG_SHOW_WHEN_LOCKED
96                 | ActivityInfo.FLAG_SHOW_FOR_ALL_USERS)) > 0;
97     }
98 
99     /**
100      * Determines if sending the given intent would result in starting an Intent resolver activity,
101      * instead of resolving to a specific component.
102      *
103      * @param resolved the resolveInfo for the intent as returned by resolveActivityAsUser
104      * @param appList a list of resolveInfo as returned by queryIntentActivitiesAsUser
105      * @return true if the intent would launch a resolver activity
106      */
wouldLaunchResolverActivity(ResolveInfo resolved, List<ResolveInfo> appList)107     public boolean wouldLaunchResolverActivity(ResolveInfo resolved, List<ResolveInfo> appList) {
108         // If the list contains the above resolved activity, then it can't be
109         // ResolverActivity itself.
110         for (int i = 0; i < appList.size(); i++) {
111             ResolveInfo tmp = appList.get(i);
112             if (tmp.activityInfo.name.equals(resolved.activityInfo.name)
113                     && tmp.activityInfo.packageName.equals(resolved.activityInfo.packageName)) {
114                 return false;
115             }
116         }
117         return true;
118     }
119 }
120