frameworks/base
Revision | 3afe56629d45a6931c0bea64dc0a9a6e82413a3b (tree) |
---|---|
Zeit | 2020-09-11 19:04:55 |
Autor | Christopher Tate <ctate@goog...> |
Commiter | Vasyl Gello |
DO NOT MERGE - Only autoVerify at install for new hosts
Re-run app link verification at update time only when the set of hosts
has expanded. Intentionally revoke verify history when an app stops
using autoVerify, as a one-time measure to place it back into the
non-autoverify model for tracking the user's launch preferences. If the
app starts using autoVerify again later, it behaves identically to an
app that has never done so before.
Bug: 151475497
Bug: 146204120
Test: described on master CL
Merged-In: I200d85085ce79842a3ed39377d1f75ec381c8991
Merged-In: Ibaf087946966ad82d60c7b255e3ee75990716b63
(cherry picked from commit 90b716a442802154208c86c31545b6f1f3ee53db)
[basilgello: Backport to 14.1:
Signed-off-by: Vasyl Gello <vasek.gello@gmail.com>
Change-Id: Ibaf087946966ad82d60c7b255e3ee75990716b63
@@ -107,6 +107,7 @@ import android.app.ActivityManager; | ||
107 | 107 | import android.app.ActivityManagerNative; |
108 | 108 | import android.app.AlarmManager; |
109 | 109 | import android.app.AppOpsManager; |
110 | +import android.app.BroadcastOptions; | |
110 | 111 | import android.app.IActivityManager; |
111 | 112 | import android.app.ResourcesManager; |
112 | 113 | import android.app.admin.IDevicePolicyManager; |
@@ -862,6 +863,10 @@ public class PackageManagerService extends IPackageManager.Stub { | ||
862 | 863 | verificationIntent.setComponent(mIntentFilterVerifierComponent); |
863 | 864 | verificationIntent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND); |
864 | 865 | |
866 | + final long whitelistTimeout = getVerificationTimeout(); | |
867 | + final BroadcastOptions options = BroadcastOptions.makeBasic(); | |
868 | + options.setTemporaryAppWhitelistDuration(whitelistTimeout); | |
869 | + | |
865 | 870 | UserHandle user = new UserHandle(userId); |
866 | 871 | mContext.sendBroadcastAsUser(verificationIntent, user); |
867 | 872 | if (DEBUG_DOMAIN_VERIFICATION) Slog.d(TAG, |
@@ -901,9 +906,6 @@ public class PackageManagerService extends IPackageManager.Stub { | ||
901 | 906 | + verificationId + " packageName:" + packageName); |
902 | 907 | return; |
903 | 908 | } |
904 | - if (DEBUG_DOMAIN_VERIFICATION) Slog.d(TAG, | |
905 | - "Updating IntentFilterVerificationInfo for package " + packageName | |
906 | - +" verificationId:" + verificationId); | |
907 | 909 | |
908 | 910 | synchronized (mPackages) { |
909 | 911 | if (verified) { |
@@ -921,19 +923,51 @@ public class PackageManagerService extends IPackageManager.Stub { | ||
921 | 923 | int updatedStatus = INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_UNDEFINED; |
922 | 924 | boolean needUpdate = false; |
923 | 925 | |
924 | - // We cannot override the STATUS_ALWAYS / STATUS_NEVER states if they have | |
925 | - // already been set by the User thru the Disambiguation dialog | |
926 | + // In a success case, we promote from undefined or ASK to ALWAYS. This | |
927 | + // supports a flow where the app fails validation but then ships an updated | |
928 | + // APK that passes, and therefore deserves to be in ALWAYS. | |
929 | + // | |
930 | + // If validation failed, the undefined state winds up in the basic ASK behavior, | |
931 | + // but apps that previously passed and became ALWAYS are *demoted* out of | |
932 | + // that state, since they would not deserve the ALWAYS behavior in case of a | |
933 | + // clean install. | |
926 | 934 | switch (userStatus) { |
935 | + case INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ALWAYS: | |
936 | + if (!verified) { | |
937 | + // Don't demote if sysconfig says 'always' | |
938 | + SystemConfig systemConfig = SystemConfig.getInstance(); | |
939 | + ArraySet<String> packages = systemConfig.getLinkedApps(); | |
940 | + if (!packages.contains(packageName)) { | |
941 | + // updatedStatus is already UNDEFINED | |
942 | + needUpdate = true; | |
943 | + | |
944 | + if (DEBUG_DOMAIN_VERIFICATION) { | |
945 | + Slog.d(TAG, "Formerly validated but now failing; demoting"); | |
946 | + } | |
947 | + } else { | |
948 | + if (DEBUG_DOMAIN_VERIFICATION) { | |
949 | + Slog.d(TAG, "Updating bundled package " + packageName | |
950 | + + " failed autoVerify, but sysconfig supersedes"); | |
951 | + } | |
952 | + // leave needUpdate == false here intentionally | |
953 | + } | |
954 | + } | |
955 | + break; | |
956 | + | |
927 | 957 | case INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_UNDEFINED: |
958 | + // Stay in 'undefined' on verification failure | |
928 | 959 | if (verified) { |
929 | 960 | updatedStatus = INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ALWAYS; |
930 | - } else { | |
931 | - updatedStatus = INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ASK; | |
932 | 961 | } |
933 | 962 | needUpdate = true; |
963 | + if (DEBUG_DOMAIN_VERIFICATION) { | |
964 | + Slog.d(TAG, "Applying update; old=" + userStatus | |
965 | + + " new=" + updatedStatus); | |
966 | + } | |
934 | 967 | break; |
935 | 968 | |
936 | 969 | case INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ASK: |
970 | + // Keep in 'ask' on failure | |
937 | 971 | if (verified) { |
938 | 972 | updatedStatus = INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ALWAYS; |
939 | 973 | needUpdate = true; |
@@ -949,6 +983,8 @@ public class PackageManagerService extends IPackageManager.Stub { | ||
949 | 983 | packageName, updatedStatus, userId); |
950 | 984 | scheduleWritePackageRestrictionsLocked(userId); |
951 | 985 | } |
986 | + } else { | |
987 | + Slog.i(TAG, "autoVerify ignored when installing for all users"); | |
952 | 988 | } |
953 | 989 | } |
954 | 990 | } |
@@ -15571,69 +15607,127 @@ public class PackageManagerService extends IPackageManager.Stub { | ||
15571 | 15607 | int count = 0; |
15572 | 15608 | final String packageName = pkg.packageName; |
15573 | 15609 | |
15610 | + boolean handlesWebUris = false; | |
15611 | + ArraySet<String> domains = new ArraySet<>(); | |
15612 | + final boolean previouslyVerified; | |
15613 | + boolean hostSetExpanded = false; | |
15614 | + boolean needToRunVerify = false; | |
15574 | 15615 | synchronized (mPackages) { |
15575 | 15616 | // If this is a new install and we see that we've already run verification for this |
15576 | 15617 | // package, we have nothing to do: it means the state was restored from backup. |
15577 | - if (!replacing) { | |
15578 | - IntentFilterVerificationInfo ivi = | |
15579 | - mSettings.getIntentFilterVerificationLPr(packageName); | |
15580 | - if (ivi != null) { | |
15581 | - if (DEBUG_DOMAIN_VERIFICATION) { | |
15582 | - Slog.i(TAG, "Package " + packageName+ " already verified: status=" | |
15583 | - + ivi.getStatusString()); | |
15584 | - } | |
15585 | - return; | |
15618 | + IntentFilterVerificationInfo ivi = | |
15619 | + mSettings.getIntentFilterVerificationLPr(packageName); | |
15620 | + previouslyVerified = (ivi != null); | |
15621 | + if (!replacing && previouslyVerified) { | |
15622 | + if (DEBUG_DOMAIN_VERIFICATION) { | |
15623 | + Slog.i(TAG, "Package " + packageName + " already verified: status=" | |
15624 | + + ivi.getStatusString()); | |
15586 | 15625 | } |
15626 | + return; | |
15587 | 15627 | } |
15588 | 15628 | |
15589 | - // If any filters need to be verified, then all need to be. | |
15590 | - boolean needToVerify = false; | |
15629 | + if (DEBUG_DOMAIN_VERIFICATION) { | |
15630 | + Slog.i(TAG, " Previous verified hosts: " | |
15631 | + + (ivi == null ? "[none]" : ivi.getDomainsString())); | |
15632 | + } | |
15633 | + | |
15634 | + // If any filters need to be verified, then all need to be. In addition, we need to | |
15635 | + // know whether an updating app has any web navigation intent filters, to re- | |
15636 | + // examine handling policy even if not re-verifying. | |
15637 | + final boolean needsVerification = needsNetworkVerificationLPr(packageName); | |
15591 | 15638 | for (PackageParser.Activity a : pkg.activities) { |
15592 | 15639 | for (ActivityIntentInfo filter : a.intents) { |
15593 | - if (filter.needsVerification() && needsNetworkVerificationLPr(filter)) { | |
15640 | + if (filter.handlesWebUris(true)) { | |
15641 | + handlesWebUris = true; | |
15642 | + } | |
15643 | + if (needsVerification && filter.needsVerification()) { | |
15594 | 15644 | if (DEBUG_DOMAIN_VERIFICATION) { |
15595 | - Slog.d(TAG, "Intent filter needs verification, so processing all filters"); | |
15645 | + Slog.d(TAG, "autoVerify requested, processing all filters"); | |
15596 | 15646 | } |
15597 | - needToVerify = true; | |
15647 | + needToRunVerify = true; | |
15648 | + // It's safe to break out here because filter.needsVerification() | |
15649 | + // can only be true if filter.handlesWebUris(true) returned true, so | |
15650 | + // we've already noted that. | |
15598 | 15651 | break; |
15599 | 15652 | } |
15600 | 15653 | } |
15601 | 15654 | } |
15602 | 15655 | |
15603 | - if (needToVerify) { | |
15656 | + // Compare the new set of recognized hosts if the app is either requesting | |
15657 | + // autoVerify or has previously used autoVerify but no longer does. | |
15658 | + if (needToRunVerify || previouslyVerified) { | |
15604 | 15659 | final int verificationId = mIntentFilterVerificationToken++; |
15605 | 15660 | for (PackageParser.Activity a : pkg.activities) { |
15606 | 15661 | for (ActivityIntentInfo filter : a.intents) { |
15607 | 15662 | // Run verification against hosts mentioned in any web-nav intent filter, |
15608 | 15663 | // even if the filter matches non-web schemes as well |
15609 | - if (filter.handlesWebUris(false) && needsNetworkVerificationLPr(filter)) { | |
15664 | + if (filter.handlesWebUris(false /*onlyWebSchemes*/)) { | |
15610 | 15665 | if (DEBUG_DOMAIN_VERIFICATION) Slog.d(TAG, |
15611 | 15666 | "Verification needed for IntentFilter:" + filter.toString()); |
15612 | 15667 | mIntentFilterVerifier.addOneIntentFilterVerification( |
15613 | 15668 | verifierUid, userId, verificationId, filter, packageName); |
15669 | + domains.addAll(filter.getHostsList()); | |
15614 | 15670 | count++; |
15615 | 15671 | } |
15616 | 15672 | } |
15617 | 15673 | } |
15618 | 15674 | } |
15675 | + | |
15676 | + if (DEBUG_DOMAIN_VERIFICATION) { | |
15677 | + Slog.i(TAG, " Update published hosts: " + domains.toString()); | |
15678 | + } | |
15679 | + | |
15680 | + // If we've previously verified this same host set (or a subset), we can trust that | |
15681 | + // a current ALWAYS policy is still applicable. If this is the case, we're done. | |
15682 | + // (If we aren't in ALWAYS, we want to reverify to allow for apps that had failing | |
15683 | + // hosts in their intent filters, then pushed a new apk that removed them and now | |
15684 | + // passes.) | |
15685 | + // | |
15686 | + // Cases: | |
15687 | + // + still autoVerify (needToRunVerify): | |
15688 | + // - preserve current state if all of: unexpanded, in always | |
15689 | + // - otherwise rerun as usual (fall through) | |
15690 | + // + no longer autoVerify (alreadyVerified && !needToRunVerify) | |
15691 | + // - wipe verification history always | |
15692 | + // - preserve current state if all of: unexpanded, in always | |
15693 | + hostSetExpanded = !previouslyVerified | |
15694 | + || (ivi != null && !ivi.getDomains().containsAll(domains)); | |
15695 | + final int currentPolicy = | |
15696 | + mSettings.getIntentFilterVerificationStatusLPr(packageName, userId); | |
15697 | + final boolean keepCurState = !hostSetExpanded | |
15698 | + && currentPolicy == INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ALWAYS; | |
15699 | + | |
15700 | + if (needToRunVerify && keepCurState) { | |
15701 | + if (DEBUG_DOMAIN_VERIFICATION) { | |
15702 | + Slog.i(TAG, "Host set not expanding + ALWAYS -> no need to reverify"); | |
15703 | + } | |
15704 | + ArrayList<String> domainsList = new ArrayList<String>(); | |
15705 | + domainsList.addAll(domains); | |
15706 | + ivi.setDomains(domainsList); | |
15707 | + scheduleWriteSettingsLocked(); | |
15708 | + return; | |
15709 | + } else if (previouslyVerified && !needToRunVerify) { | |
15710 | + // Prior autoVerify state but not requesting it now. Clear autoVerify history, | |
15711 | + // and preserve the always policy iff the host set is not expanding. | |
15712 | + clearIntentFilterVerificationsLPw(packageName, userId, !keepCurState); | |
15713 | + return; | |
15714 | + } | |
15619 | 15715 | } |
15620 | 15716 | |
15621 | - if (count > 0) { | |
15717 | + if (needToRunVerify && count > 0) { | |
15718 | + // app requested autoVerify and has at least one matching intent filter | |
15622 | 15719 | if (DEBUG_DOMAIN_VERIFICATION) Slog.d(TAG, "Starting " + count |
15623 | 15720 | + " IntentFilter verification" + (count > 1 ? "s" : "") |
15624 | 15721 | + " for userId:" + userId); |
15625 | 15722 | mIntentFilterVerifier.startVerifications(userId); |
15626 | 15723 | } else { |
15627 | 15724 | if (DEBUG_DOMAIN_VERIFICATION) { |
15628 | - Slog.d(TAG, "No filters or not all autoVerify for " + packageName); | |
15725 | + Slog.d(TAG, "No web filters or no new host policy for " + packageName); | |
15629 | 15726 | } |
15630 | 15727 | } |
15631 | 15728 | } |
15632 | 15729 | |
15633 | - private boolean needsNetworkVerificationLPr(ActivityIntentInfo filter) { | |
15634 | - final ComponentName cn = filter.activity.getComponentName(); | |
15635 | - final String packageName = cn.getPackageName(); | |
15636 | - | |
15730 | + private boolean needsNetworkVerificationLPr(String packageName) { | |
15637 | 15731 | IntentFilterVerificationInfo ivi = mSettings.getIntentFilterVerificationLPr( |
15638 | 15732 | packageName); |
15639 | 15733 | if (ivi == null) { |
@@ -15642,6 +15736,7 @@ public class PackageManagerService extends IPackageManager.Stub { | ||
15642 | 15736 | int status = ivi.getStatus(); |
15643 | 15737 | switch (status) { |
15644 | 15738 | case INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_UNDEFINED: |
15739 | + case INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ALWAYS: | |
15645 | 15740 | case INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ASK: |
15646 | 15741 | return true; |
15647 | 15742 |
@@ -16147,7 +16242,7 @@ public class PackageManagerService extends IPackageManager.Stub { | ||
16147 | 16242 | synchronized (mPackages) { |
16148 | 16243 | if (deletedPs != null) { |
16149 | 16244 | if ((flags&PackageManager.DELETE_KEEP_DATA) == 0) { |
16150 | - clearIntentFilterVerificationsLPw(deletedPs.name, UserHandle.USER_ALL); | |
16245 | + clearIntentFilterVerificationsLPw(deletedPs.name, UserHandle.USER_ALL, true); | |
16151 | 16246 | clearDefaultBrowserIfNeeded(packageName); |
16152 | 16247 | if (outInfo != null) { |
16153 | 16248 | mSettings.mKeySetManagerService.removeAppKeySetDataLPw(packageName); |
@@ -17382,12 +17477,13 @@ public class PackageManagerService extends IPackageManager.Stub { | ||
17382 | 17477 | final int packageCount = mPackages.size(); |
17383 | 17478 | for (int i = 0; i < packageCount; i++) { |
17384 | 17479 | PackageParser.Package pkg = mPackages.valueAt(i); |
17385 | - clearIntentFilterVerificationsLPw(pkg.packageName, userId); | |
17480 | + clearIntentFilterVerificationsLPw(pkg.packageName, userId, true); | |
17386 | 17481 | } |
17387 | 17482 | } |
17388 | 17483 | |
17389 | 17484 | /** This method takes a specific user id as well as UserHandle.USER_ALL. */ |
17390 | - void clearIntentFilterVerificationsLPw(String packageName, int userId) { | |
17485 | + void clearIntentFilterVerificationsLPw(String packageName, int userId, | |
17486 | + boolean alsoResetStatus) { | |
17391 | 17487 | if (userId == UserHandle.USER_ALL) { |
17392 | 17488 | if (mSettings.removeIntentFilterVerificationLPw(packageName, |
17393 | 17489 | sUserManager.getUserIds())) { |
@@ -17396,7 +17492,8 @@ public class PackageManagerService extends IPackageManager.Stub { | ||
17396 | 17492 | } |
17397 | 17493 | } |
17398 | 17494 | } else { |
17399 | - if (mSettings.removeIntentFilterVerificationLPw(packageName, userId)) { | |
17495 | + if (mSettings.removeIntentFilterVerificationLPw(packageName, userId, | |
17496 | + alsoResetStatus)) { | |
17400 | 17497 | scheduleWritePackageRestrictionsLocked(userId); |
17401 | 17498 | } |
17402 | 17499 | } |
@@ -1322,7 +1322,8 @@ final class Settings { | ||
1322 | 1322 | return result; |
1323 | 1323 | } |
1324 | 1324 | |
1325 | - boolean removeIntentFilterVerificationLPw(String packageName, int userId) { | |
1325 | + boolean removeIntentFilterVerificationLPw(String packageName, int userId, | |
1326 | + boolean alsoResetStatus) { | |
1326 | 1327 | PackageSetting ps = mPackages.get(packageName); |
1327 | 1328 | if (ps == null) { |
1328 | 1329 | if (DEBUG_DOMAIN_VERIFICATION) { |
@@ -1330,14 +1331,17 @@ final class Settings { | ||
1330 | 1331 | } |
1331 | 1332 | return false; |
1332 | 1333 | } |
1333 | - ps.clearDomainVerificationStatusForUser(userId); | |
1334 | + if (alsoResetStatus) { | |
1335 | + ps.clearDomainVerificationStatusForUser(userId); | |
1336 | + } | |
1337 | + ps.setIntentFilterVerificationInfo(null); | |
1334 | 1338 | return true; |
1335 | 1339 | } |
1336 | 1340 | |
1337 | 1341 | boolean removeIntentFilterVerificationLPw(String packageName, int[] userIds) { |
1338 | 1342 | boolean result = false; |
1339 | 1343 | for (int userId : userIds) { |
1340 | - result |= removeIntentFilterVerificationLPw(packageName, userId); | |
1344 | + result |= removeIntentFilterVerificationLPw(packageName, userId, true); | |
1341 | 1345 | } |
1342 | 1346 | return result; |
1343 | 1347 | } |