diff options
17 files changed, 573 insertions, 213 deletions
diff --git a/core/java/android/content/pm/PackageUserState.java b/core/java/android/content/pm/PackageUserState.java index 99258712030c..5cc74c0a1c8e 100644 --- a/core/java/android/content/pm/PackageUserState.java +++ b/core/java/android/content/pm/PackageUserState.java @@ -77,8 +77,6 @@ public class PackageUserState { public boolean virtualPreload; public int enabled; public String lastDisableAppCaller; - public int domainVerificationStatus; - public int appLinkGeneration; public int categoryHint = ApplicationInfo.CATEGORY_UNDEFINED; public int installReason; public @PackageManager.UninstallReason int uninstallReason; @@ -100,8 +98,6 @@ public class PackageUserState { hidden = false; suspended = false; enabled = COMPONENT_ENABLED_STATE_DEFAULT; - domainVerificationStatus = - PackageManager.INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_UNDEFINED; installReason = PackageManager.INSTALL_REASON_UNKNOWN; uninstallReason = PackageManager.UNINSTALL_REASON_UNKNOWN; } @@ -120,8 +116,6 @@ public class PackageUserState { virtualPreload = o.virtualPreload; enabled = o.enabled; lastDisableAppCaller = o.lastDisableAppCaller; - domainVerificationStatus = o.domainVerificationStatus; - appLinkGeneration = o.appLinkGeneration; categoryHint = o.categoryHint; installReason = o.installReason; uninstallReason = o.uninstallReason; @@ -416,12 +410,6 @@ public class PackageUserState { && !lastDisableAppCaller.equals(oldState.lastDisableAppCaller))) { return false; } - if (domainVerificationStatus != oldState.domainVerificationStatus) { - return false; - } - if (appLinkGeneration != oldState.appLinkGeneration) { - return false; - } if (categoryHint != oldState.categoryHint) { return false; } @@ -481,8 +469,6 @@ public class PackageUserState { hashCode = 31 * hashCode + Boolean.hashCode(virtualPreload); hashCode = 31 * hashCode + enabled; hashCode = 31 * hashCode + Objects.hashCode(lastDisableAppCaller); - hashCode = 31 * hashCode + domainVerificationStatus; - hashCode = 31 * hashCode + appLinkGeneration; hashCode = 31 * hashCode + categoryHint; hashCode = 31 * hashCode + installReason; hashCode = 31 * hashCode + uninstallReason; diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java index 42d900f04060..cbc66ac64436 100644 --- a/services/core/java/com/android/server/pm/PackageManagerService.java +++ b/services/core/java/com/android/server/pm/PackageManagerService.java @@ -238,7 +238,6 @@ import android.content.pm.VersionedPackage; import android.content.pm.dex.ArtManager; import android.content.pm.dex.DexMetadataHelper; import android.content.pm.dex.IArtManager; -import android.content.pm.domain.verify.DomainVerificationManager; import android.content.pm.parsing.ApkLiteParseUtils; import android.content.pm.parsing.PackageLite; import android.content.pm.parsing.ParsingPackageUtils; @@ -386,7 +385,6 @@ import com.android.server.pm.domain.verify.proxy.DomainVerificationProxyV2; import com.android.server.pm.intent.verify.legacy.IntentFilterVerificationManager; import com.android.server.pm.intent.verify.legacy.IntentFilterVerificationParams; import com.android.server.pm.intent.verify.legacy.IntentVerifierProxy; -import com.android.server.pm.intent.verify.legacy.IntentVerifyUtils; import com.android.server.pm.parsing.PackageCacher; import com.android.server.pm.parsing.PackageInfoUtils; import com.android.server.pm.parsing.PackageParser2; @@ -1814,7 +1812,7 @@ public class PackageManagerService extends IPackageManager.Stub @NonNull @Override public WatchedSparseIntArray getNextAppLinkGeneration() { - return mSettings.mNextAppLinkGeneration; + return null; } @NonNull @@ -2753,7 +2751,8 @@ public class PackageManagerService extends IPackageManager.Stub } // Try to get the status from User settings first - long packedStatus = IntentVerifyUtils.getDomainVerificationStatus(ps, userId); + long packedStatus = 0; + //IntentVerifyUtils.getDomainVerificationStatus(ps, userId); int status = (int)(packedStatus >> 32); int linkGeneration = (int)(packedStatus & 0xFFFFFFFF); if (status == INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ALWAYS) { @@ -2980,8 +2979,8 @@ public class PackageManagerService extends IPackageManager.Stub result.wereAnyDomainsVerificationApproved |= mDomainVerificationManager .isApprovedForDomain(ps, intent, riTargetUser.targetUserId); } else { - long verificationState = - IntentVerifyUtils.getDomainVerificationStatus(ps, parentUserId); + long verificationState = 0; + //IntentVerifyUtils.getDomainVerificationStatus(ps, parentUserId); int status = (int) (verificationState >> 32); result.bestDomainVerificationStatus = bestDomainVerificationStatus(status, result.bestDomainVerificationStatus); @@ -3257,8 +3256,8 @@ public class PackageManagerService extends IPackageManager.Stub } } - final long packedStatus = - IntentVerifyUtils.getDomainVerificationStatus(ps, userId); + final long packedStatus = 0; + //IntentVerifyUtils.getDomainVerificationStatus(ps, userId); final int status = (int)(packedStatus >> 32); if (status == INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_NEVER) { // there's a local instant application installed, but, the user has @@ -4202,8 +4201,8 @@ public class PackageManagerService extends IPackageManager.Stub } } else { // Try to get the status from User settings first - final long packedStatus = - IntentVerifyUtils.getDomainVerificationStatus(ps, userId); + final long packedStatus = 0; + //IntentVerifyUtils.getDomainVerificationStatus(ps, userId); final int status = (int) (packedStatus >> 32); if (status == INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ALWAYS || status @@ -9655,8 +9654,8 @@ public class PackageManagerService extends IPackageManager.Stub return ri; } } else { - final long packedStatus = - IntentVerifyUtils.getDomainVerificationStatus(ps, userId); + final long packedStatus = 0; + //IntentVerifyUtils.getDomainVerificationStatus(ps, userId); final int status = (int) (packedStatus >> 32); if (status != INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ALWAYS_ASK) { return ri; @@ -16447,13 +16446,13 @@ public class PackageManagerService extends IPackageManager.Stub @Override public int getIntentVerificationStatus(String packageName, int userId) { - return mIntentFilterVerificationManager.getIntentVerificationStatus(packageName, userId); + return mDomainVerificationManager.getLegacyState(packageName, userId); } @Override public boolean updateIntentVerificationStatus(String packageName, int status, int userId) { - return mIntentFilterVerificationManager.updateIntentVerificationStatus(packageName, status, - userId); + mDomainVerificationManager.setLegacyUserState(packageName, userId, status); + return true; } @Override @@ -21681,8 +21680,6 @@ public class PackageManagerService extends IPackageManager.Stub null /*lastDisableAppCaller*/, null /*enabledComponents*/, null /*disabledComponents*/, - ps.readUserState(nextUserId).domainVerificationStatus, - 0 /*linkGeneration*/, PackageManager.INSTALL_REASON_UNKNOWN, PackageManager.UNINSTALL_REASON_UNKNOWN, null /*harmfulAppWarning*/); diff --git a/services/core/java/com/android/server/pm/PackageSettingBase.java b/services/core/java/com/android/server/pm/PackageSettingBase.java index b69d2b015d6c..d3005184e087 100644 --- a/services/core/java/com/android/server/pm/PackageSettingBase.java +++ b/services/core/java/com/android/server/pm/PackageSettingBase.java @@ -133,8 +133,6 @@ public abstract class PackageSettingBase extends SettingBase { /** Whether or not an update is available. Ostensibly only for instant apps. */ boolean updateAvailable; - IntentFilterVerificationInfo verificationInfo; - boolean forceQueryableOverride; @NonNull @@ -260,7 +258,6 @@ public abstract class PackageSettingBase extends SettingBase { for (int i = 0; i < orig.mUserState.size(); i++) { mUserState.put(orig.mUserState.keyAt(i), orig.mUserState.valueAt(i)); } - verificationInfo = orig.verificationInfo; versionCode = orig.versionCode; volumeUuid = orig.volumeUuid; categoryHint = orig.categoryHint; @@ -354,12 +351,6 @@ public abstract class PackageSettingBase extends SettingBase { /** * Only use for testing. Do NOT use in production code. - * - * Unless you're {@link DomainVerificationService} and you need to migrate legacy state. - * This is done rather than passing in the user IDs to - * {@link DomainVerificationManagerInternal#addPackage(PackageSetting)} to make the v2 APIs - * completely correct, without legacy details, since that method inherently does not care about - * the users on the device. */ @VisibleForTesting @Deprecated @@ -507,8 +498,7 @@ public abstract class PackageSettingBase extends SettingBase { ArrayMap<String, PackageUserState.SuspendParams> suspendParams, boolean instantApp, boolean virtualPreload, String lastDisableAppCaller, ArraySet<String> enabledComponents, ArraySet<String> disabledComponents, - int domainVerifState, int linkGeneration, int installReason, int uninstallReason, - String harmfulAppWarning) { + int installReason, int uninstallReason, String harmfulAppWarning) { PackageUserState state = modifyUserState(userId); state.ceDataInode = ceDataInode; state.enabled = enabled; @@ -522,8 +512,6 @@ public abstract class PackageSettingBase extends SettingBase { state.lastDisableAppCaller = lastDisableAppCaller; state.enabledComponents = enabledComponents; state.disabledComponents = disabledComponents; - state.domainVerificationStatus = domainVerifState; - state.appLinkGeneration = linkGeneration; state.installReason = installReason; state.uninstallReason = uninstallReason; state.instantApp = instantApp; @@ -539,7 +527,6 @@ public abstract class PackageSettingBase extends SettingBase { otherState.instantApp, otherState.virtualPreload, otherState.lastDisableAppCaller, otherState.enabledComponents, otherState.disabledComponents, - otherState.domainVerificationStatus, otherState.appLinkGeneration, otherState.installReason, otherState.uninstallReason, otherState.harmfulAppWarning); } @@ -655,40 +642,6 @@ public abstract class PackageSettingBase extends SettingBase { return excludedUserIds; } - public IntentFilterVerificationInfo getIntentFilterVerificationInfo() { - return verificationInfo; - } - - public void setIntentFilterVerificationInfo(IntentFilterVerificationInfo info) { - verificationInfo = info; - onChanged(); - } - - // Returns a packed value as a long: - // - // high 'int'-sized word: link status: undefined/ask/never/always. - // low 'int'-sized word: relative priority among 'always' results. - public long getDomainVerificationStatusForUser(int userId) { - PackageUserState state = readUserState(userId); - long result = (long) state.appLinkGeneration; - result |= ((long) state.domainVerificationStatus) << 32; - return result; - } - - public void setDomainVerificationStatusForUser(final int status, int generation, int userId) { - PackageUserState state = modifyUserState(userId); - state.domainVerificationStatus = status; - if (status == PackageManager.INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ALWAYS) { - state.appLinkGeneration = generation; - onChanged(); - } - } - - public void clearDomainVerificationStatusForUser(int userId) { - modifyUserState(userId).domainVerificationStatus = - PackageManager.INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_UNDEFINED; - } - protected void writeUsersInfoToProto(ProtoOutputStream proto, long fieldId) { int count = mUserState.size(); for (int i = 0; i < count; i++) { @@ -856,7 +809,6 @@ public abstract class PackageSettingBase extends SettingBase { this.volumeUuid = other.volumeUuid; this.categoryHint = other.categoryHint; this.updateAvailable = other.updateAvailable; - this.verificationInfo = other.verificationInfo; this.forceQueryableOverride = other.forceQueryableOverride; this.incrementalStates = other.incrementalStates; diff --git a/services/core/java/com/android/server/pm/Settings.java b/services/core/java/com/android/server/pm/Settings.java index 689830bd6b98..43617cf9a0c9 100644 --- a/services/core/java/com/android/server/pm/Settings.java +++ b/services/core/java/com/android/server/pm/Settings.java @@ -21,7 +21,6 @@ import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_DISABLED import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_ENABLED; import static android.content.pm.PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE; import static android.content.pm.PackageManager.INSTALL_FAILED_SHARED_USER_INCOMPATIBLE; -import static android.content.pm.PackageManager.INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_UNDEFINED; import static android.content.pm.PackageManager.MATCH_DEFAULT_ONLY; import static android.content.pm.PackageManager.UNINSTALL_REASON_UNKNOWN; import static android.content.pm.PackageManager.UNINSTALL_REASON_USER_TYPE; @@ -106,6 +105,7 @@ import com.android.permission.persistence.RuntimePermissionsState; import com.android.server.LocalServices; import com.android.server.backup.PreferredActivityBackupHelper; import com.android.server.pm.Installer.InstallerException; +import com.android.server.pm.domain.verify.DomainVerificationLegacySettings; import com.android.server.pm.domain.verify.DomainVerificationManagerInternal; import com.android.server.pm.domain.verify.DomainVerificationPersistence; import com.android.server.pm.intent.verify.legacy.IntentFilterVerificationManager; @@ -557,7 +557,6 @@ public final class Settings implements Watchable, Snappable { mOtherAppIds.registerObserver(mObserver); mRenamedPackages.registerObserver(mObserver); mDefaultBrowserApp.registerObserver(mObserver); - mNextAppLinkGeneration.registerObserver(mObserver); Watchable.verifyWatchedAttributes(this, mObserver); } @@ -610,7 +609,6 @@ public final class Settings implements Watchable, Snappable { mOtherAppIds.registerObserver(mObserver); mRenamedPackages.registerObserver(mObserver); mDefaultBrowserApp.registerObserver(mObserver); - mNextAppLinkGeneration.registerObserver(mObserver); Watchable.verifyWatchedAttributes(this, mObserver); } @@ -659,7 +657,6 @@ public final class Settings implements Watchable, Snappable { mKeySetRefs.putAll(r.mKeySetRefs); mRenamedPackages.snapshot(r.mRenamedPackages); mDefaultBrowserApp.snapshot(r.mDefaultBrowserApp); - mNextAppLinkGeneration.snapshot(r.mNextAppLinkGeneration); // mReadMessages mPendingPackages.addAll(r.mPendingPackages); mSystemDir = null; @@ -938,8 +935,6 @@ public final class Settings implements Watchable, Snappable { null /*lastDisableAppCaller*/, null /*enabledComponents*/, null /*disabledComponents*/, - INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_UNDEFINED, - 0 /*linkGeneration*/, PackageManager.INSTALL_REASON_UNKNOWN, PackageManager.UNINSTALL_REASON_UNKNOWN, null /*harmfulAppWarning*/); @@ -1182,12 +1177,6 @@ public final class Settings implements Watchable, Snappable { replaceAppIdLPw(p.appId, sharedUser); } } - - IntentFilterVerificationInfo info = - mIntentFilterVerificationManager.getRestoredIntentFilterVerificationInfo(p.name); - if (info != null) { - p.setIntentFilterVerificationInfo(info); - } } int removePackageLPw(String name) { @@ -1582,8 +1571,6 @@ public final class Settings implements Watchable, Snappable { null /*lastDisableAppCaller*/, null /*enabledComponents*/, null /*disabledComponents*/, - INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_UNDEFINED, - 0 /*linkGeneration*/, PackageManager.INSTALL_REASON_UNKNOWN, PackageManager.UNINSTALL_REASON_UNKNOWN, null /*harmfulAppWarning*/); @@ -1608,8 +1595,6 @@ public final class Settings implements Watchable, Snappable { return; } - int maxAppLinkGeneration = 0; - int outerDepth = parser.getDepth(); PackageSetting ps = null; while ((type=parser.next()) != XmlPullParser.END_DOCUMENT @@ -1672,11 +1657,6 @@ public final class Settings implements Watchable, Snappable { final int verifState = parser.getAttributeInt(null, ATTR_DOMAIN_VERIFICATON_STATE, PackageManager.INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_UNDEFINED); - final int linkGeneration = - parser.getAttributeInt(null, ATTR_APP_LINK_GENERATION, 0); - if (linkGeneration > maxAppLinkGeneration) { - maxAppLinkGeneration = linkGeneration; - } final int installReason = parser.getAttributeInt(null, ATTR_INSTALL_REASON, PackageManager.INSTALL_REASON_UNKNOWN); final int uninstallReason = parser.getAttributeInt(null, ATTR_UNINSTALL_REASON, @@ -1752,9 +1732,10 @@ public final class Settings implements Watchable, Snappable { } ps.setUserState(userId, ceDataInode, enabled, installed, stopped, notLaunched, hidden, distractionFlags, suspended, suspendParamsMap, - instantApp, virtualPreload, - enabledCaller, enabledComponents, disabledComponents, verifState, - linkGeneration, installReason, uninstallReason, harmfulAppWarning); + instantApp, virtualPreload, enabledCaller, enabledComponents, + disabledComponents, installReason, uninstallReason, harmfulAppWarning); + + mDomainVerificationManager.setLegacyUserState(name, userId, verifState); } else if (tagName.equals("preferred-activities")) { readPreferredActivitiesLPw(parser, userId); } else if (tagName.equals(TAG_PERSISTENT_PREFERRED_ACTIVITIES)) { @@ -1773,9 +1754,6 @@ public final class Settings implements Watchable, Snappable { } str.close(); - - mNextAppLinkGeneration.put(userId, maxAppLinkGeneration + 1); - } catch (XmlPullParserException e) { mReadMessages.append("Error reading: " + e.toString()); PackageManagerService.reportSettingsProblem(Log.ERROR, @@ -2002,15 +1980,6 @@ public final class Settings implements Watchable, Snappable { ustate.lastDisableAppCaller); } } - if (ustate.domainVerificationStatus != - PackageManager.INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_UNDEFINED) { - serializer.attributeInt(null, ATTR_DOMAIN_VERIFICATON_STATE, - ustate.domainVerificationStatus); - } - if (ustate.appLinkGeneration != 0) { - serializer.attributeInt(null, ATTR_APP_LINK_GENERATION, - ustate.appLinkGeneration); - } if (ustate.installReason != PackageManager.INSTALL_REASON_UNKNOWN) { serializer.attributeInt(null, ATTR_INSTALL_REASON, ustate.installReason); } @@ -2747,8 +2716,7 @@ public final class Settings implements Watchable, Snappable { writeSigningKeySetLPr(serializer, pkg.keySetData); writeUpgradeKeySetsLPr(serializer, pkg.keySetData); writeKeySetAliasesLPr(serializer, pkg.keySetData); - mIntentFilterVerificationManager.writeDomainVerificationsLPr(serializer, - pkg.verificationInfo); + mDomainVerificationManager.writeLegacySettings(serializer, pkg.name); writeMimeGroupLPr(serializer, pkg.mimeGroups); serializer.endTag(null, "package"); @@ -2924,7 +2892,10 @@ public final class Settings implements Watchable, Snappable { ver.fingerprint = XmlUtils.readStringAttribute(parser, ATTR_FINGERPRINT); } else if (tagName.equals(DomainVerificationPersistence.TAG_DOMAIN_VERIFICATIONS)) { mDomainVerificationManager.readSettings(parser); - }else { + } else if (tagName.equals( + DomainVerificationLegacySettings.TAG_DOMAIN_VERIFICATIONS_LEGACY)) { + mDomainVerificationManager.readLegacySettings(parser); + } else { Slog.w(PackageManagerService.TAG, "Unknown element under <packages>: " + parser.getName()); XmlUtils.skipCurrentTag(parser); @@ -3739,9 +3710,8 @@ public final class Settings implements Watchable, Snappable { packageSetting.installSource = packageSetting.installSource.setInitiatingPackageSignatures(signatures); } else if (tagName.equals(TAG_DOMAIN_VERIFICATION)) { - IntentFilterVerificationInfo ivi = - mIntentFilterVerificationManager.readDomainVerificationLPw(parser); - packageSetting.setIntentFilterVerificationInfo(ivi); + IntentFilterVerificationInfo ivi = new IntentFilterVerificationInfo(parser); + mDomainVerificationManager.addLegacySetting(packageSetting.name, ivi); if (DEBUG_PARSER) { Log.d(TAG, "Read domain verification for package: " + ivi.getPackageName()); } diff --git a/services/core/java/com/android/server/pm/domain/verify/DomainVerificationCollector.java b/services/core/java/com/android/server/pm/domain/verify/DomainVerificationCollector.java index 5aaa37e9dadd..832714f2bfe6 100644 --- a/services/core/java/com/android/server/pm/domain/verify/DomainVerificationCollector.java +++ b/services/core/java/com/android/server/pm/domain/verify/DomainVerificationCollector.java @@ -88,9 +88,8 @@ public class DomainVerificationCollector { @NonNull private ArraySet<String> collectDomains(@NonNull AndroidPackage pkg, boolean checkAutoVerify) { - @SuppressWarnings("ConstantConditions") - boolean restrictDomains = Binder.withCleanCallingIdentity( - () -> mPlatformCompat.isChangeEnabled(RESTRICT_DOMAINS, buildMockAppInfo(pkg))); + boolean restrictDomains = + DomainVerificationUtils.isChangeEnabled(mPlatformCompat, pkg, RESTRICT_DOMAINS); ArraySet<String> domains = new ArraySet<>(); @@ -198,19 +197,4 @@ public class DomainVerificationCollector { } } } - - /** - * Passed to {@link PlatformCompat} because this can be invoked mid-install process, and - * {@link PlatformCompat} will not be able to query the pending {@link ApplicationInfo} from - * {@link PackageManager}. - * - * TODO(b/177613575): Can a different API be used? - */ - @NonNull - private ApplicationInfo buildMockAppInfo(@NonNull AndroidPackage pkg) { - ApplicationInfo appInfo = new ApplicationInfo(); - appInfo.packageName = pkg.getPackageName(); - appInfo.targetSdkVersion = pkg.getTargetSdkVersion(); - return appInfo; - } } diff --git a/services/core/java/com/android/server/pm/domain/verify/DomainVerificationEnforcer.java b/services/core/java/com/android/server/pm/domain/verify/DomainVerificationEnforcer.java index 05b1c47f8b27..cdcc5fcba7b5 100644 --- a/services/core/java/com/android/server/pm/domain/verify/DomainVerificationEnforcer.java +++ b/services/core/java/com/android/server/pm/domain/verify/DomainVerificationEnforcer.java @@ -118,4 +118,11 @@ public class DomainVerificationEnforcer { Binder.getCallingPid(), callingUid, "Caller is not allowed to edit user selections"); } + + public void callerIsLegacyUserSelector(int callingUid) { + mContext.enforcePermission( + android.Manifest.permission.SET_PREFERRED_APPLICATIONS, + Binder.getCallingPid(), callingUid, + "Caller is not allowed to edit user state"); + } } diff --git a/services/core/java/com/android/server/pm/domain/verify/DomainVerificationLegacySettings.java b/services/core/java/com/android/server/pm/domain/verify/DomainVerificationLegacySettings.java new file mode 100644 index 000000000000..09307d2a2db1 --- /dev/null +++ b/services/core/java/com/android/server/pm/domain/verify/DomainVerificationLegacySettings.java @@ -0,0 +1,228 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.server.pm.domain.verify; + +import android.annotation.NonNull; +import android.annotation.Nullable; +import android.annotation.UserIdInt; +import android.content.pm.IntentFilterVerificationInfo; +import android.content.pm.PackageManager; +import android.util.ArrayMap; +import android.util.SparseIntArray; +import android.util.TypedXmlPullParser; +import android.util.TypedXmlSerializer; + +import com.android.internal.annotations.GuardedBy; +import com.android.server.pm.SettingsXml; + +import org.xmlpull.v1.XmlPullParserException; + +import java.io.IOException; +import java.util.Map; + +/** + * Reads and writes the old {@link android.content.pm.IntentFilterVerificationInfo} so that it can + * be migrated in to the new API. Will throw away the state once it's successfully applied so that + * eventually there will be no legacy state on the device. + * + * This attempt is best effort, and if the legacy state is lost that's acceptable. The user setting + * in the legacy API may have been set incorrectly because it was never made obvious to the user + * what it actually toggled, so there's a strong argument to prevent migration anyways. The user + * can just set their preferences again, this time with finer grained control, if the legacy state + * gets dropped. + */ +public class DomainVerificationLegacySettings { + + public static final String TAG_DOMAIN_VERIFICATIONS_LEGACY = "domain-verifications-legacy"; + public static final String TAG_USER_STATES = "user-states"; + public static final String ATTR_PACKAGE_NAME = "packageName"; + public static final String TAG_USER_STATE = "user-state"; + public static final String ATTR_USER_ID = "userId"; + public static final String ATTR_STATE = "state"; + + @NonNull + private final Object mLock = new Object(); + + @NonNull + private final ArrayMap<String, LegacyState> mStates = new ArrayMap<>(); + + public void add(@NonNull String packageName, @NonNull IntentFilterVerificationInfo info) { + synchronized (mLock) { + getOrCreateStateLocked(packageName).setInfo(info); + } + } + + public void add(@NonNull String packageName, @UserIdInt int userId, int state) { + synchronized (mLock) { + getOrCreateStateLocked(packageName).addUserState(userId, state); + } + } + + public int getUserState(@NonNull String packageName, @UserIdInt int userId) { + synchronized (mLock) { + LegacyState state = mStates.get(packageName); + if (state != null) { + return state.getUserState(userId); + } + } + return PackageManager.INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_UNDEFINED; + } + + @Nullable + public SparseIntArray getUserStates(@NonNull String packageName) { + synchronized (mLock) { + LegacyState state = mStates.get(packageName); + if (state != null) { + // Yes, this returns outside of the lock, but we assume that retrieval generally + // only happens after all adding has concluded from reading settings. + return state.getUserStates(); + } + } + return null; + } + + @Nullable + public IntentFilterVerificationInfo remove(@NonNull String packageName) { + synchronized (mLock) { + LegacyState state = mStates.get(packageName); + if (state != null && !state.isAttached()) { + state.markAttached(); + return state.getInfo(); + } + } + return null; + } + + @GuardedBy("mLock") + @NonNull + private LegacyState getOrCreateStateLocked(@NonNull String packageName) { + LegacyState state = mStates.get(packageName); + if (state == null) { + state = new LegacyState(); + mStates.put(packageName, state); + } + + return state; + } + + public void writeSettings(TypedXmlSerializer xmlSerializer) throws IOException { + try (SettingsXml.Serializer serializer = SettingsXml.serializer(xmlSerializer)) { + try (SettingsXml.WriteSection ignored = + serializer.startSection(TAG_DOMAIN_VERIFICATIONS_LEGACY)) { + synchronized (mLock) { + final int statesSize = mStates.size(); + for (int stateIndex = 0; stateIndex < statesSize; stateIndex++) { + final LegacyState state = mStates.valueAt(stateIndex); + final SparseIntArray userStates = state.getUserStates(); + if (userStates == null) { + continue; + } + + final String packageName = mStates.keyAt(stateIndex); + try (SettingsXml.WriteSection userStatesSection = + serializer.startSection(TAG_USER_STATES) + .attribute(ATTR_PACKAGE_NAME, packageName)) { + final int userStatesSize = userStates.size(); + for (int userStateIndex = 0; userStateIndex < userStatesSize; + userStateIndex++) { + final int userId = userStates.keyAt(userStateIndex); + final int userState = userStates.valueAt(userStateIndex); + userStatesSection.startSection(TAG_USER_STATE) + .attribute(ATTR_USER_ID, userId) + .attribute(ATTR_STATE, userState) + .finish(); + } + } + } + } + } + } + } + + public void readSettings(TypedXmlPullParser xmlParser) + throws IOException, XmlPullParserException { + final SettingsXml.ChildSection child = SettingsXml.parser(xmlParser).children(); + while (child.moveToNext()) { + if (TAG_USER_STATES.equals(child.getName())) { + readUserStates(child); + } + } + } + + private void readUserStates(SettingsXml.ReadSection section) { + String packageName = section.getString(ATTR_PACKAGE_NAME); + synchronized (mLock) { + final LegacyState legacyState = getOrCreateStateLocked(packageName); + final SettingsXml.ChildSection child = section.children(); + while (child.moveToNext()) { + if (TAG_USER_STATE.equals(child.getName())) { + readUserState(child, legacyState); + } + } + } + } + + private void readUserState(SettingsXml.ReadSection section, LegacyState legacyState) { + int userId = section.getInt(ATTR_USER_ID); + int state = section.getInt(ATTR_STATE); + legacyState.addUserState(userId, state); + } + + static class LegacyState { + @Nullable + private IntentFilterVerificationInfo mInfo; + + @Nullable + private SparseIntArray mUserStates; + + private boolean attached; + + @Nullable + public IntentFilterVerificationInfo getInfo() { + return mInfo; + } + + public int getUserState(int userId) { + return mUserStates.get(userId, + PackageManager.INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_UNDEFINED); + } + + @Nullable + public SparseIntArray getUserStates() { + return mUserStates; + } + + public void setInfo(@NonNull IntentFilterVerificationInfo info) { + mInfo = info; + } + + public void addUserState(@UserIdInt int userId, int state) { + if (mUserStates == null) { + mUserStates = new SparseIntArray(1); + } + mUserStates.put(userId, state); + } + + public boolean isAttached() { + return attached; + } + + public void markAttached() { + attached = true; + } + } +} diff --git a/services/core/java/com/android/server/pm/domain/verify/DomainVerificationManagerInternal.java b/services/core/java/com/android/server/pm/domain/verify/DomainVerificationManagerInternal.java index 9ef498780393..56994c864870 100644 --- a/services/core/java/com/android/server/pm/domain/verify/DomainVerificationManagerInternal.java +++ b/services/core/java/com/android/server/pm/domain/verify/DomainVerificationManagerInternal.java @@ -21,6 +21,7 @@ import android.annotation.Nullable; import android.annotation.RequiresPermission; import android.annotation.UserIdInt; import android.content.Intent; +import android.content.pm.IntentFilterVerificationInfo; import android.content.pm.PackageManager.NameNotFoundException; import android.content.pm.domain.verify.DomainVerificationManager; import android.content.pm.domain.verify.DomainVerificationSet; @@ -31,6 +32,7 @@ import android.util.TypedXmlSerializer; import com.android.server.pm.PackageSetting; import com.android.server.pm.domain.verify.models.DomainVerificationPkgState; import com.android.server.pm.domain.verify.proxy.DomainVerificationProxy; +import com.android.server.pm.parsing.pkg.AndroidPackage; import org.xmlpull.v1.XmlPullParserException; @@ -103,15 +105,14 @@ public interface DomainVerificationManagerInternal extends DomainVerificationMan /** * Serializes the entire internal state. This is equivalent to a full backup of the existing - * verification state. + * verification state. This write includes legacy state, as a sibling tag the modern state. */ void writeSettings(@NonNull TypedXmlSerializer serializer) throws IOException; /** * Read back a list of {@link DomainVerificationPkgState}s previously written by {@link * #writeSettings(TypedXmlSerializer)}. Assumes that the - * {@link DomainVerificationPersistence#TAG_DOMAIN_VERIFICATIONS} - * tag has already been entered. + * {@link DomainVerificationPersistence#TAG_DOMAIN_VERIFICATIONS} tag has already been entered. * <p> * This is expected to only be used to re-attach states for packages already known to be on the * device. If restoring from a backup, use {@link #restoreSettings(TypedXmlPullParser)}. @@ -120,6 +121,15 @@ public interface DomainVerificationManagerInternal extends DomainVerificationMan throws IOException, XmlPullParserException; /** + * Read back data from + * {@link DomainVerificationLegacySettings#writeSettings(TypedXmlSerializer)}. Assumes that the + * {@link DomainVerificationLegacySettings#TAG_DOMAIN_VERIFICATIONS_LEGACY} tag has already + * been entered. + */ + void readLegacySettings(@NonNull TypedXmlPullParser parser) + throws IOException, XmlPullParserException; + + /** * Remove all state for the given package. */ void clearPackage(@NonNull String packageName); @@ -149,6 +159,32 @@ public interface DomainVerificationManagerInternal extends DomainVerificationMan throws IOException, XmlPullParserException; /** + * Set aside a legacy {@link IntentFilterVerificationInfo} that will be restored to a pending + * {@link DomainVerificationPkgState} once it's added through + * {@link #addPackage(PackageSetting)}. + */ + void addLegacySetting(@NonNull String packageName, @NonNull IntentFilterVerificationInfo info); + + /** + * Set aside a legacy user selection that will be restored to a pending + * {@link DomainVerificationPkgState} once it's added through + * {@link #addPackage(PackageSetting)}. + */ + void setLegacyUserState(@NonNull String packageName, @UserIdInt int userId, int state); + + /** + * Until the legacy APIs are entirely removed, returns the legacy state from the previously + * written info stored in {@link com.android.server.pm.Settings}. + */ + int getLegacyState(@NonNull String packageName, @UserIdInt int userId); + + /** + * Serialize a legacy setting that wasn't attached yet. + * TODO: Does this even matter? Should consider for removal. + */ + void writeLegacySettings(TypedXmlSerializer serializer, String name); + + /** * Print the verification state and user selection state of a package. * * @param packageName the package whose state to change, or all packages if none is specified diff --git a/services/core/java/com/android/server/pm/domain/verify/DomainVerificationService.java b/services/core/java/com/android/server/pm/domain/verify/DomainVerificationService.java index 0a28069017d4..ace72090193a 100644 --- a/services/core/java/com/android/server/pm/domain/verify/DomainVerificationService.java +++ b/services/core/java/com/android/server/pm/domain/verify/DomainVerificationService.java @@ -19,6 +19,8 @@ package com.android.server.pm.domain.verify; import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.UserIdInt; +import android.compat.annotation.ChangeId; +import android.compat.annotation.Disabled; import android.content.Context; import android.content.Intent; import android.content.pm.IntentFilterVerificationInfo; @@ -38,6 +40,7 @@ import android.util.IndentingPrintWriter; import android.util.Singleton; import android.util.Slog; import android.util.SparseArray; +import android.util.SparseIntArray; import android.util.TypedXmlPullParser; import android.util.TypedXmlSerializer; @@ -74,6 +77,19 @@ public class DomainVerificationService extends SystemService public static final boolean DEBUG_APPROVAL = true; /** + * The new user preference API for verifying domains marked autoVerify=true in + * AndroidManifest.xml intent filters is not yet implemented in the current platform preview. + * This is anticipated to ship before S releases. + * + * For now, it is possible to preview the new user preference changes by enabling this + * ChangeId and using the <code>adb shell pm set-app-links-user-selection</code> and similar + * commands. + */ + @ChangeId + @Disabled + private static final long SETTINGS_API_V2 = 178111421; + + /** * States that are currently alive and attached to a package. Entries are exclusive with the * state stored in {@link DomainVerificationSettings}, as any pending/restored state should be * immediately attached once its available. @@ -100,6 +116,9 @@ public class DomainVerificationService extends SystemService private final SystemConfig mSystemConfig; @NonNull + private final PlatformCompat mPlatformCompat; + + @NonNull private final DomainVerificationSettings mSettings; @NonNull @@ -115,6 +134,9 @@ public class DomainVerificationService extends SystemService private final DomainVerificationShell mShell; @NonNull + private final DomainVerificationLegacySettings mLegacySettings; + + @NonNull private final IDomainVerificationManager.Stub mStub = new DomainVerificationManagerStub(this); @NonNull @@ -125,11 +147,13 @@ public class DomainVerificationService extends SystemService super(context); mConnection = connection; mSystemConfig = systemConfig; + mPlatformCompat = platformCompat; mSettings = new DomainVerificationSettings(); mCollector = new DomainVerificationCollector(platformCompat, systemConfig); mEnforcer = new DomainVerificationEnforcer(context); mDebug = new DomainVerificationDebug(mCollector); mShell = new DomainVerificationShell(this); + mLegacySettings = new DomainVerificationLegacySettings(); } @Override @@ -401,6 +425,8 @@ public class DomainVerificationService extends SystemService .setDisallowLinkHandling(!allowed); } } + + mConnection.get().scheduleWriteSettings(); } @Override @@ -473,6 +499,8 @@ public class DomainVerificationService extends SystemService enabled, domains); } } + + mConnection.get().scheduleWriteSettings(); } private void setDomainVerificationUserSelectionInternal(int userId, @@ -500,6 +528,8 @@ public class DomainVerificationService extends SystemService userState.removeHosts(domains); } } + + mConnection.get().scheduleWriteSettings(); } @Nullable @@ -693,12 +723,11 @@ public class DomainVerificationService extends SystemService // and disable them if appropriate. ArraySet<String> webDomains = null; - @SuppressWarnings("deprecation") - SparseArray<PackageUserState> userState = newPkgSetting.getUserState(); - int userStateSize = userState.size(); + SparseIntArray legacyUserStates = mLegacySettings.getUserStates(pkgName); + int userStateSize = legacyUserStates == null ? 0 : legacyUserStates.size(); for (int index = 0; index < userStateSize; index++) { - int userId = userState.keyAt(index); - int legacyStatus = userState.valueAt(index).domainVerificationStatus; + int userId = legacyUserStates.keyAt(index); + int legacyStatus = legacyUserStates.valueAt(index); if (legacyStatus == PackageManager.INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ALWAYS) { if (webDomains == null) { @@ -709,8 +738,7 @@ public class DomainVerificationService extends SystemService } } - IntentFilterVerificationInfo legacyInfo = - newPkgSetting.getIntentFilterVerificationInfo(); + IntentFilterVerificationInfo legacyInfo = mLegacySettings.remove(pkgName); if (legacyInfo != null && legacyInfo.getStatus() == PackageManager.INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ALWAYS) { @@ -772,6 +800,8 @@ public class DomainVerificationService extends SystemService synchronized (mLock) { mSettings.writeSettings(serializer, mAttachedPkgStates); } + + mLegacySettings.writeSettings(serializer); } @Override @@ -783,6 +813,12 @@ public class DomainVerificationService extends SystemService } @Override + public void readLegacySettings(@NonNull TypedXmlPullParser parser) + throws IOException, XmlPullParserException { + mLegacySettings.readSettings(parser); + } + + @Override public void restoreSettings(@NonNull TypedXmlPullParser parser) throws IOException, XmlPullParserException { synchronized (mLock) { @@ -791,6 +827,28 @@ public class DomainVerificationService extends SystemService } @Override + public void addLegacySetting(@NonNull String packageName, + @NonNull IntentFilterVerificationInfo info) { + mLegacySettings.add(packageName, info); + } + + @Override + public void setLegacyUserState(@NonNull String packageName, @UserIdInt int userId, int state) { + mEnforcer.callerIsLegacyUserSelector(mConnection.get().getCallingUid()); + mLegacySettings.add(packageName, userId, state); + } + + @Override + public int getLegacyState(@NonNull String packageName, @UserIdInt int userId) { + return mLegacySettings.getUserState(packageName, userId); + } + + @Override + public void writeLegacySettings(TypedXmlSerializer serializer, String name) { + + } + + @Override public void clearPackage(@NonNull String packageName) { synchronized (mLock) { mAttachedPkgStates.remove(packageName); @@ -1051,13 +1109,36 @@ public class DomainVerificationService extends SystemService return false; } - // To allow an instant app to immediately open domains after being installed by the user, - // auto approve them for any declared autoVerify domains. String host = intent.getData().getHost(); final AndroidPackage pkg = pkgSetting.getPkg(); - if (pkgSetting.getInstantApp(userId) && pkg != null - && mCollector.collectAutoVerifyDomains(pkg).contains(host)) { - return true; + + // Should never be null, but if it is, skip this and assume that v2 is enabled + if (pkg != null) { + // To allow an instant app to immediately open domains after being installed by the + // user, auto approve them for any declared autoVerify domains. + if (pkgSetting.getInstantApp(userId) + && mCollector.collectAutoVerifyDomains(pkg).contains(host)) { + return true; + } + + if (!DomainVerificationUtils.isChangeEnabled(mPlatformCompat, pkg, SETTINGS_API_V2)) { + int legacyState = mLegacySettings.getUserState(packageName, userId); + switch (legacyState) { + case PackageManager.INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_UNDEFINED: + // If nothing specifically set, assume v2 rules + break; + case PackageManager.INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ASK: + case PackageManager.INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ALWAYS: + case PackageManager.INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ALWAYS_ASK: + // With v2 split into 2 lists, always and undefined, the concept of whether + // or not to ask is irrelevant. Assume the user wants this application to + // open the domain. + return true; + case PackageManager.INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_NEVER: + // Never has the same semantics are before + return false; + } + } } synchronized (mLock) { diff --git a/services/core/java/com/android/server/pm/domain/verify/DomainVerificationUtils.java b/services/core/java/com/android/server/pm/domain/verify/DomainVerificationUtils.java index ff030710274e..f704478b92a5 100644 --- a/services/core/java/com/android/server/pm/domain/verify/DomainVerificationUtils.java +++ b/services/core/java/com/android/server/pm/domain/verify/DomainVerificationUtils.java @@ -19,13 +19,20 @@ package com.android.server.pm.domain.verify; import android.annotation.CheckResult; import android.annotation.NonNull; import android.content.Intent; +import android.content.pm.ApplicationInfo; +import android.content.pm.PackageManager; import android.content.pm.PackageManager.NameNotFoundException; +import android.os.Binder; + +import com.android.server.compat.PlatformCompat; +import com.android.server.pm.PackageManagerService; +import com.android.server.pm.parsing.pkg.AndroidPackage; final class DomainVerificationUtils { /** - * Consolidates package exception messages. A generic unavailable message is included since - * the caller doesn't bother to check why the package isn't available. + * Consolidates package exception messages. A generic unavailable message is included since the + * caller doesn't bother to check why the package isn't available. */ @CheckResult static NameNotFoundException throwPackageUnavailable(@NonNull String packageName) @@ -38,4 +45,26 @@ final class DomainVerificationUtils { && intent.hasCategory(Intent.CATEGORY_BROWSABLE) && intent.hasCategory(Intent.CATEGORY_DEFAULT); } + + static boolean isChangeEnabled(PlatformCompat platformCompat, AndroidPackage pkg, + long changeId) { + //noinspection ConstantConditions + return Binder.withCleanCallingIdentity( + () -> platformCompat.isChangeEnabled(changeId, buildMockAppInfo(pkg))); + } + + /** + * Passed to {@link PlatformCompat} because this can be invoked mid-install process or when + * {@link PackageManagerService#mLock} is being held, and {@link PlatformCompat} will not be + * able to query the pending {@link ApplicationInfo} from {@link PackageManager}. + * <p> + * TODO(b/177613575): Can a different API be used? + */ + @NonNull + private static ApplicationInfo buildMockAppInfo(@NonNull AndroidPackage pkg) { + ApplicationInfo appInfo = new ApplicationInfo(); + appInfo.packageName = pkg.getPackageName(); + appInfo.targetSdkVersion = pkg.getTargetSdkVersion(); + return appInfo; + } } diff --git a/services/core/java/com/android/server/pm/intent/verify/legacy/IntentFilterVerificationSettings.java b/services/core/java/com/android/server/pm/intent/verify/legacy/IntentFilterVerificationSettings.java index 2aac51402d10..3ff770d5fb3a 100644 --- a/services/core/java/com/android/server/pm/intent/verify/legacy/IntentFilterVerificationSettings.java +++ b/services/core/java/com/android/server/pm/intent/verify/legacy/IntentFilterVerificationSettings.java @@ -176,10 +176,10 @@ public class IntentFilterVerificationSettings { public IntentFilterVerificationInfo updatePackageSetting(@NonNull PackageSetting pkgSetting, ArraySet<String> domains) { String pkgName = pkgSetting.name; - IntentFilterVerificationInfo ivi = pkgSetting.getIntentFilterVerificationInfo(); + IntentFilterVerificationInfo ivi = null;//pkgSetting.getIntentFilterVerificationInfo(); if (ivi == null) { ivi = new IntentFilterVerificationInfo(pkgName, domains); - pkgSetting.setIntentFilterVerificationInfo(ivi); + // pkgSetting.setIntentFilterVerificationInfo(ivi); mConnection.debugLog("Creating new IntentFilterVerificationInfo for pkg: " + pkgName); } else { ivi.setDomains(domains); @@ -197,7 +197,7 @@ public class IntentFilterVerificationSettings { mConnection.warnLog("No package known: " + packageName); return INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_UNDEFINED; } - return (int) (pkgSetting.getDomainVerificationStatusForUser(userId) >> 32); + return 0;//(int) (pkgSetting.getDomainVerificationStatusForUser(userId) >> 32); } @Nullable @@ -208,7 +208,7 @@ public class IntentFilterVerificationSettings { mConnection.warnLog("No package known: " + packageName); return null; } - return ps.getIntentFilterVerificationInfo(); + return null;//ps.getIntentFilterVerificationInfo(); } boolean updateIntentFilterVerificationStatusLPw(String packageName, final int status, @@ -222,14 +222,14 @@ public class IntentFilterVerificationSettings { final int alwaysGeneration; if (status == INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ALWAYS) { - WatchedSparseIntArray nextAppLinkGeneration = mConnection.getNextAppLinkGeneration(); - alwaysGeneration = nextAppLinkGeneration.get(userId) + 1; - nextAppLinkGeneration.put(userId, alwaysGeneration); +// WatchedSparseIntArray nextAppLinkGeneration = mConnection.getNextAppLinkGeneration(); +// alwaysGeneration = nextAppLinkGeneration.get(userId) + 1; +// nextAppLinkGeneration.put(userId, alwaysGeneration); } else { alwaysGeneration = 0; } - current.setDomainVerificationStatusForUser(status, alwaysGeneration, userId); +// current.setDomainVerificationStatusForUser(status, alwaysGeneration, userId); return true; } @@ -241,9 +241,8 @@ public class IntentFilterVerificationSettings { return false; } if (alsoResetStatus) { - ps.clearDomainVerificationStatusForUser(userId); +// ps.clearDomainVerificationStatusForUser(userId); } - ps.setIntentFilterVerificationInfo(null); return true; } @@ -262,7 +261,7 @@ public class IntentFilterVerificationSettings { } ArrayList<IntentFilterVerificationInfo> result = new ArrayList<>(); for (PackageSetting ps : mConnection.getPackageSettingsLPr().values()) { - IntentFilterVerificationInfo ivi = ps.getIntentFilterVerificationInfo(); + IntentFilterVerificationInfo ivi = null;//ps.getIntentFilterVerificationInfo(); if (ivi == null || TextUtils.isEmpty(ivi.getPackageName()) || !ivi.getPackageName().equalsIgnoreCase(packageName)) { continue; @@ -278,7 +277,7 @@ public class IntentFilterVerificationSettings { throws IllegalArgumentException, IllegalStateException, IOException { serializer.startTag(null, Settings.TAG_ALL_INTENT_FILTER_VERIFICATION); for (PackageSetting value : pkgSettings.values()) { - IntentFilterVerificationInfo ivi = value.getIntentFilterVerificationInfo(); + IntentFilterVerificationInfo ivi = null;//value.getIntentFilterVerificationInfo(); if (ivi != null) { writeDomainVerificationsLPr(serializer, ivi); } @@ -318,7 +317,9 @@ public class IntentFilterVerificationSettings { final PackageSetting ps = mConnection.getPackageSettingLPr(pkgName); if (ps != null) { // known/existing package; update in place - ps.setIntentFilterVerificationInfo(ivi); + // TODO: Removed, commented out to allow compile, awaiting removal of entire + // class + // ps.setIntentFilterVerificationInfo(ivi); mConnection.debugLog("Restored IVI for existing app " + pkgName + " status=" + ivi.getStatusString()); } else { diff --git a/services/core/java/com/android/server/pm/intent/verify/legacy/IntentVerifyUtils.java b/services/core/java/com/android/server/pm/intent/verify/legacy/IntentVerifyUtils.java index 389aa20e9ff0..b64ac94ba07f 100644 --- a/services/core/java/com/android/server/pm/intent/verify/legacy/IntentVerifyUtils.java +++ b/services/core/java/com/android/server/pm/intent/verify/legacy/IntentVerifyUtils.java @@ -31,19 +31,4 @@ public class IntentVerifyUtils { && (filter.hasDataScheme(IntentFilter.SCHEME_HTTP) || filter.hasDataScheme(IntentFilter.SCHEME_HTTPS)); } - - // Returns a packed value as a long: - // - // high 'int'-sized word: link status: undefined/ask/never/always. - // low 'int'-sized word: relative priority among 'always' results. - public static long getDomainVerificationStatus(PackageSetting ps, int userId) { - long result = ps.getDomainVerificationStatusForUser(userId); - // if none available, get the status - if (result >> 32 == INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_UNDEFINED) { - if (ps.getIntentFilterVerificationInfo() != null) { - result = ((long) ps.getIntentFilterVerificationInfo().getStatus()) << 32; - } - } - return result; - } } diff --git a/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/domain/verify/DomainVerificationEnforcerTest.kt b/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/domain/verify/DomainVerificationEnforcerTest.kt index 13a37ffe77d6..c944cff8c04f 100644 --- a/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/domain/verify/DomainVerificationEnforcerTest.kt +++ b/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/domain/verify/DomainVerificationEnforcerTest.kt @@ -149,6 +149,7 @@ class DomainVerificationEnforcerTest { whenever(getPackageSettingLocked(TEST_PKG)) { mockPkgSetting } whenever(getPackageLocked(TEST_PKG)) { mockPkg } whenever(schedule(anyInt(), any())) + whenever(scheduleWriteSettings()) } }) ) diff --git a/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/domain/verify/DomainVerificationLegacySettingsTest.kt b/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/domain/verify/DomainVerificationLegacySettingsTest.kt new file mode 100644 index 000000000000..47601a499d62 --- /dev/null +++ b/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/domain/verify/DomainVerificationLegacySettingsTest.kt @@ -0,0 +1,103 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.server.pm.test.domain.verify + +import android.content.pm.IntentFilterVerificationInfo +import android.content.pm.PackageManager +import android.util.ArraySet +import com.android.server.pm.domain.verify.DomainVerificationLegacySettings +import com.android.server.pm.test.domain.verify.DomainVerificationPersistenceTest.Companion.readXml +import com.android.server.pm.test.domain.verify.DomainVerificationPersistenceTest.Companion.writeXml +import com.google.common.truth.Truth.assertWithMessage +import org.junit.Rule +import org.junit.Test +import org.junit.rules.TemporaryFolder + +class DomainVerificationLegacySettingsTest { + + @Rule + @JvmField + val tempFolder = TemporaryFolder() + + @Test + fun writeAndReadBackNormal() { + val settings = DomainVerificationLegacySettings().apply { + add( + "com.test.one", + IntentFilterVerificationInfo( + "com.test.one", + ArraySet(setOf("example1.com", "example2.com")) + ).apply { + status = PackageManager.INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ALWAYS_ASK + } + ) + add( + "com.test.one", + 0, PackageManager.INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ALWAYS + ) + add( + "com.test.one", + 10, PackageManager.INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_NEVER + ) + + add( + "com.test.two", + IntentFilterVerificationInfo( + "com.test.two", + ArraySet(setOf("example3.com")) + ) + ) + + add( + "com.test.three", + 11, PackageManager.INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ALWAYS + ) + } + + + val file = tempFolder.newFile().writeXml(settings::writeSettings) + val newSettings = file.readXml { + DomainVerificationLegacySettings().apply { + readSettings(it) + } + } + + val xml = file.readText() + + // Legacy migrated settings doesn't bother writing the legacy verification info + assertWithMessage(xml).that(newSettings.remove("com.test.one")).isNull() + assertWithMessage(xml).that(newSettings.getUserState("com.test.one", 0)) + .isEqualTo(PackageManager.INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ALWAYS) + assertWithMessage(xml).that(newSettings.getUserState("com.test.one", 10)) + .isEqualTo(PackageManager.INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_NEVER) + + val firstUserStates = newSettings.getUserStates("com.test.one") + assertWithMessage(xml).that(firstUserStates).isNotNull() + assertWithMessage(xml).that(firstUserStates!!.size()).isEqualTo(2) + assertWithMessage(xml).that(firstUserStates[0]) + .isEqualTo(PackageManager.INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ALWAYS) + assertWithMessage(xml).that(firstUserStates[10]) + .isEqualTo(PackageManager.INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_NEVER) + + assertWithMessage(xml).that(newSettings.remove("com.test.two")).isNull() + assertWithMessage(xml).that(newSettings.getUserStates("com.test.two")).isNull() + + assertWithMessage(xml).that(newSettings.remove("com.test.three")).isNull() + assertWithMessage(xml).that(newSettings.getUserState("com.test.three", 11)) + .isEqualTo(PackageManager.INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ALWAYS) + } +} diff --git a/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/domain/verify/DomainVerificationPersistenceTest.kt b/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/domain/verify/DomainVerificationPersistenceTest.kt index cf331d5ce775..ada5c1b063fa 100644 --- a/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/domain/verify/DomainVerificationPersistenceTest.kt +++ b/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/domain/verify/DomainVerificationPersistenceTest.kt @@ -18,6 +18,7 @@ package com.android.server.pm.test.domain.verify import android.content.pm.domain.verify.DomainVerificationManager import android.util.ArrayMap +import android.util.TypedXmlPullParser import android.util.TypedXmlSerializer import android.util.Xml import com.android.server.pm.domain.verify.DomainVerificationPersistence @@ -29,12 +30,33 @@ import com.google.common.truth.Truth.assertWithMessage import org.junit.Rule import org.junit.Test import org.junit.rules.TemporaryFolder +import java.io.File +import java.nio.charset.StandardCharsets import java.util.UUID class DomainVerificationPersistenceTest { companion object { private val PKG_PREFIX = DomainVerificationPersistenceTest::class.java.`package`!!.name + + internal fun File.writeXml(block: (serializer: TypedXmlSerializer) -> Unit) = apply { + outputStream().use { + // Explicitly use string based XML so it can printed in the test failure output + Xml.newFastSerializer() + .apply { + setOutput(it, StandardCharsets.UTF_8.name()) + startDocument(null, true) + setFeature("http://xmlpull.org/v1/doc/features.html#indent-output", true) + } + .apply(block) + .endDocument() + } + } + + internal fun <T> File.readXml(block: (parser: TypedXmlPullParser) -> T) = + inputStream().use { + block(Xml.resolvePullParser(it)) + } } @Rule @@ -56,17 +78,18 @@ class DomainVerificationPersistenceTest { mockPkgState(5).let { put(it.packageName, it) } } - val file = writeXml { + val file = tempFolder.newFile().writeXml { DomainVerificationPersistence.writeToXml(it, attached, pending, restored) } val xml = file.readText() - val (readActive, readRestored) = file.inputStream() - .use { DomainVerificationPersistence.readFromXml(Xml.resolvePullParser(it)) } + val (readActive, readRestored) = file.readXml { + DomainVerificationPersistence.readFromXml(it) + } assertWithMessage(xml).that(readActive.values) - .containsExactlyElementsIn(attached.values() + pending.values) + .containsExactlyElementsIn(attached.values() + pending.values) assertWithMessage(xml).that(readRestored.values).containsExactlyElementsIn(restored.values) } @@ -172,25 +195,12 @@ class DomainVerificationPersistenceTest { """.trimIndent() val (active, restored) = DomainVerificationPersistence - .readFromXml(Xml.resolvePullParser(xml.byteInputStream())) + .readFromXml(Xml.resolvePullParser(xml.byteInputStream())) assertThat(active.values).containsExactly(stateZero) assertThat(restored.values).containsExactly(stateOne, stateTwo) } - private fun writeXml(block: (TypedXmlSerializer) -> Unit) = tempFolder.newFile() - .apply { - outputStream().use { - Xml.resolveSerializer(it) - .apply { - startDocument(null, true) - setFeature("http://xmlpull.org/v1/doc/features.html#indent-output", true) - } - .apply(block) - .endDocument() - } - } - private fun mockEmptyPkgState( id: Int, hasAutoVerifyDomains: Boolean = true diff --git a/services/tests/servicestests/src/com/android/server/pm/PackageManagerSettingsTests.java b/services/tests/servicestests/src/com/android/server/pm/PackageManagerSettingsTests.java index 850a031d7ad6..beeae7df6956 100644 --- a/services/tests/servicestests/src/com/android/server/pm/PackageManagerSettingsTests.java +++ b/services/tests/servicestests/src/com/android/server/pm/PackageManagerSettingsTests.java @@ -961,8 +961,6 @@ public class PackageManagerSettingsTests { assertNotSame(origPkgSetting.getUserState(), is(testPkgSetting.getUserState())); // No equals() method for SparseArray object // assertThat(origPkgSetting.getUserState(), is(testPkgSetting.getUserState())); - assertSame(origPkgSetting.verificationInfo, testPkgSetting.verificationInfo); - assertThat(origPkgSetting.verificationInfo, is(testPkgSetting.verificationInfo)); assertThat(origPkgSetting.versionCode, is(testPkgSetting.versionCode)); assertSame(origPkgSetting.volumeUuid, testPkgSetting.volumeUuid); assertThat(origPkgSetting.volumeUuid, is(testPkgSetting.volumeUuid)); diff --git a/services/tests/servicestests/src/com/android/server/pm/PackageUserStateTest.java b/services/tests/servicestests/src/com/android/server/pm/PackageUserStateTest.java index 1cfbad93c2e5..938e4cc84e62 100644 --- a/services/tests/servicestests/src/com/android/server/pm/PackageUserStateTest.java +++ b/services/tests/servicestests/src/com/android/server/pm/PackageUserStateTest.java @@ -53,18 +53,10 @@ public class PackageUserStateTest { assertThat(testUserState.equals(oldUserState), is(true)); oldUserState = new PackageUserState(); - oldUserState.appLinkGeneration = 6; - assertThat(testUserState.equals(oldUserState), is(false)); - - oldUserState = new PackageUserState(); oldUserState.ceDataInode = 4000L; assertThat(testUserState.equals(oldUserState), is(false)); oldUserState = new PackageUserState(); - oldUserState.domainVerificationStatus = INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ASK; - assertThat(testUserState.equals(oldUserState), is(false)); - - oldUserState = new PackageUserState(); oldUserState.enabled = COMPONENT_ENABLED_STATE_ENABLED; assertThat(testUserState.equals(oldUserState), is(false)); |