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