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