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