1 /*
2  * Copyright (C) 2012 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 android.content.pm;
18 
19 import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_DEFAULT;
20 import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_DISABLED;
21 import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED;
22 import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_DISABLED_USER;
23 import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_ENABLED;
24 import static android.content.pm.PackageManager.MATCH_DIRECT_BOOT_AWARE;
25 import static android.content.pm.PackageManager.MATCH_DIRECT_BOOT_UNAWARE;
26 import static android.content.pm.PackageManager.MATCH_DISABLED_COMPONENTS;
27 import static android.content.pm.PackageManager.MATCH_DISABLED_UNTIL_USED_COMPONENTS;
28 import static android.content.pm.PackageManager.MATCH_SYSTEM_ONLY;
29 
30 import android.compat.annotation.UnsupportedAppUsage;
31 import android.os.BaseBundle;
32 import android.os.Debug;
33 import android.os.PersistableBundle;
34 import android.util.ArraySet;
35 import android.util.DebugUtils;
36 import android.util.Slog;
37 
38 import com.android.internal.annotations.VisibleForTesting;
39 import com.android.internal.util.ArrayUtils;
40 
41 import java.util.Arrays;
42 import java.util.Objects;
43 
44 /**
45  * Per-user state information about a package.
46  * @hide
47  */
48 public class PackageUserState {
49     private static final boolean DEBUG = false;
50     private static final String LOG_TAG = "PackageUserState";
51 
52     public long ceDataInode;
53     public boolean installed;
54     public boolean stopped;
55     public boolean notLaunched;
56     public boolean hidden; // Is the app restricted by owner / admin
57     public int distractionFlags;
58     public boolean suspended;
59     public String suspendingPackage;
60     public SuspendDialogInfo dialogInfo;
61     public PersistableBundle suspendedAppExtras;
62     public PersistableBundle suspendedLauncherExtras;
63     public boolean instantApp;
64     public boolean virtualPreload;
65     public int enabled;
66     public String lastDisableAppCaller;
67     public int domainVerificationStatus;
68     public int appLinkGeneration;
69     public int categoryHint = ApplicationInfo.CATEGORY_UNDEFINED;
70     public int installReason;
71     public String harmfulAppWarning;
72 
73     public ArraySet<String> disabledComponents;
74     public ArraySet<String> enabledComponents;
75 
76     public String[] overlayPaths;
77 
78     @UnsupportedAppUsage
PackageUserState()79     public PackageUserState() {
80         installed = true;
81         hidden = false;
82         suspended = false;
83         enabled = COMPONENT_ENABLED_STATE_DEFAULT;
84         domainVerificationStatus =
85                 PackageManager.INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_UNDEFINED;
86         installReason = PackageManager.INSTALL_REASON_UNKNOWN;
87     }
88 
89     @VisibleForTesting
PackageUserState(PackageUserState o)90     public PackageUserState(PackageUserState o) {
91         ceDataInode = o.ceDataInode;
92         installed = o.installed;
93         stopped = o.stopped;
94         notLaunched = o.notLaunched;
95         hidden = o.hidden;
96         distractionFlags = o.distractionFlags;
97         suspended = o.suspended;
98         suspendingPackage = o.suspendingPackage;
99         dialogInfo = o.dialogInfo;
100         suspendedAppExtras = o.suspendedAppExtras;
101         suspendedLauncherExtras = o.suspendedLauncherExtras;
102         instantApp = o.instantApp;
103         virtualPreload = o.virtualPreload;
104         enabled = o.enabled;
105         lastDisableAppCaller = o.lastDisableAppCaller;
106         domainVerificationStatus = o.domainVerificationStatus;
107         appLinkGeneration = o.appLinkGeneration;
108         categoryHint = o.categoryHint;
109         installReason = o.installReason;
110         disabledComponents = ArrayUtils.cloneOrNull(o.disabledComponents);
111         enabledComponents = ArrayUtils.cloneOrNull(o.enabledComponents);
112         overlayPaths =
113             o.overlayPaths == null ? null : Arrays.copyOf(o.overlayPaths, o.overlayPaths.length);
114         harmfulAppWarning = o.harmfulAppWarning;
115     }
116 
117     /**
118      * Test if this package is installed.
119      */
isAvailable(int flags)120     public boolean isAvailable(int flags) {
121         // True if it is installed for this user and it is not hidden. If it is hidden,
122         // still return true if the caller requested MATCH_UNINSTALLED_PACKAGES
123         final boolean matchAnyUser = (flags & PackageManager.MATCH_ANY_USER) != 0;
124         final boolean matchUninstalled = (flags & PackageManager.MATCH_UNINSTALLED_PACKAGES) != 0;
125         return matchAnyUser
126                 || (this.installed
127                         && (!this.hidden || matchUninstalled));
128     }
129 
130     /**
131      * Test if the given component is considered installed, enabled and a match
132      * for the given flags.
133      *
134      * <p>
135      * Expects at least one of {@link PackageManager#MATCH_DIRECT_BOOT_AWARE} and
136      * {@link PackageManager#MATCH_DIRECT_BOOT_UNAWARE} are specified in {@code flags}.
137      * </p>
138      */
isMatch(ComponentInfo componentInfo, int flags)139     public boolean isMatch(ComponentInfo componentInfo, int flags) {
140         final boolean isSystemApp = componentInfo.applicationInfo.isSystemApp();
141         final boolean matchUninstalled = (flags & PackageManager.MATCH_KNOWN_PACKAGES) != 0;
142         if (!isAvailable(flags)
143                 && !(isSystemApp && matchUninstalled)) return reportIfDebug(false, flags);
144         if (!isEnabled(componentInfo, flags)) return reportIfDebug(false, flags);
145 
146         if ((flags & MATCH_SYSTEM_ONLY) != 0) {
147             if (!isSystemApp) {
148                 return reportIfDebug(false, flags);
149             }
150         }
151 
152         final boolean matchesUnaware = ((flags & MATCH_DIRECT_BOOT_UNAWARE) != 0)
153                 && !componentInfo.directBootAware;
154         final boolean matchesAware = ((flags & MATCH_DIRECT_BOOT_AWARE) != 0)
155                 && componentInfo.directBootAware;
156         return reportIfDebug(matchesUnaware || matchesAware, flags);
157     }
158 
reportIfDebug(boolean result, int flags)159     private boolean reportIfDebug(boolean result, int flags) {
160         if (DEBUG && !result) {
161             Slog.i(LOG_TAG, "No match!; flags: "
162                     + DebugUtils.flagsToString(PackageManager.class, "MATCH_", flags) + " "
163                     + Debug.getCaller());
164         }
165         return result;
166     }
167 
168     /**
169      * Test if the given component is considered enabled.
170      */
isEnabled(ComponentInfo componentInfo, int flags)171     public boolean isEnabled(ComponentInfo componentInfo, int flags) {
172         if ((flags & MATCH_DISABLED_COMPONENTS) != 0) {
173             return true;
174         }
175 
176         // First check if the overall package is disabled; if the package is
177         // enabled then fall through to check specific component
178         switch (this.enabled) {
179             case COMPONENT_ENABLED_STATE_DISABLED:
180             case COMPONENT_ENABLED_STATE_DISABLED_USER:
181                 return false;
182             case COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED:
183                 if ((flags & MATCH_DISABLED_UNTIL_USED_COMPONENTS) == 0) {
184                     return false;
185                 }
186             case COMPONENT_ENABLED_STATE_DEFAULT:
187                 if (!componentInfo.applicationInfo.enabled) {
188                     return false;
189                 }
190             case COMPONENT_ENABLED_STATE_ENABLED:
191                 break;
192         }
193 
194         // Check if component has explicit state before falling through to
195         // the manifest default
196         if (ArrayUtils.contains(this.enabledComponents, componentInfo.name)) {
197             return true;
198         }
199         if (ArrayUtils.contains(this.disabledComponents, componentInfo.name)) {
200             return false;
201         }
202 
203         return componentInfo.enabled;
204     }
205 
206     @Override
equals(Object obj)207     final public boolean equals(Object obj) {
208         if (!(obj instanceof PackageUserState)) {
209             return false;
210         }
211         final PackageUserState oldState = (PackageUserState) obj;
212         if (ceDataInode != oldState.ceDataInode) {
213             return false;
214         }
215         if (installed != oldState.installed) {
216             return false;
217         }
218         if (stopped != oldState.stopped) {
219             return false;
220         }
221         if (notLaunched != oldState.notLaunched) {
222             return false;
223         }
224         if (hidden != oldState.hidden) {
225             return false;
226         }
227         if (distractionFlags != oldState.distractionFlags) {
228             return false;
229         }
230         if (suspended != oldState.suspended) {
231             return false;
232         }
233         if (suspended) {
234             if (suspendingPackage == null
235                     || !suspendingPackage.equals(oldState.suspendingPackage)) {
236                 return false;
237             }
238             if (!Objects.equals(dialogInfo, oldState.dialogInfo)) {
239                 return false;
240             }
241             if (!BaseBundle.kindofEquals(suspendedAppExtras,
242                     oldState.suspendedAppExtras)) {
243                 return false;
244             }
245             if (!BaseBundle.kindofEquals(suspendedLauncherExtras,
246                     oldState.suspendedLauncherExtras)) {
247                 return false;
248             }
249         }
250         if (instantApp != oldState.instantApp) {
251             return false;
252         }
253         if (virtualPreload != oldState.virtualPreload) {
254             return false;
255         }
256         if (enabled != oldState.enabled) {
257             return false;
258         }
259         if ((lastDisableAppCaller == null && oldState.lastDisableAppCaller != null)
260                 || (lastDisableAppCaller != null
261                         && !lastDisableAppCaller.equals(oldState.lastDisableAppCaller))) {
262             return false;
263         }
264         if (domainVerificationStatus != oldState.domainVerificationStatus) {
265             return false;
266         }
267         if (appLinkGeneration != oldState.appLinkGeneration) {
268             return false;
269         }
270         if (categoryHint != oldState.categoryHint) {
271             return false;
272         }
273         if (installReason != oldState.installReason) {
274             return false;
275         }
276         if ((disabledComponents == null && oldState.disabledComponents != null)
277                 || (disabledComponents != null && oldState.disabledComponents == null)) {
278             return false;
279         }
280         if (disabledComponents != null) {
281             if (disabledComponents.size() != oldState.disabledComponents.size()) {
282                 return false;
283             }
284             for (int i = disabledComponents.size() - 1; i >=0; --i) {
285                 if (!oldState.disabledComponents.contains(disabledComponents.valueAt(i))) {
286                     return false;
287                 }
288             }
289         }
290         if ((enabledComponents == null && oldState.enabledComponents != null)
291                 || (enabledComponents != null && oldState.enabledComponents == null)) {
292             return false;
293         }
294         if (enabledComponents != null) {
295             if (enabledComponents.size() != oldState.enabledComponents.size()) {
296                 return false;
297             }
298             for (int i = enabledComponents.size() - 1; i >=0; --i) {
299                 if (!oldState.enabledComponents.contains(enabledComponents.valueAt(i))) {
300                     return false;
301                 }
302             }
303         }
304         if (harmfulAppWarning == null && oldState.harmfulAppWarning != null
305                 || (harmfulAppWarning != null
306                         && !harmfulAppWarning.equals(oldState.harmfulAppWarning))) {
307             return false;
308         }
309         return true;
310     }
311 }
312