Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 178b57c5 authored by Chris Tate's avatar Chris Tate Committed by Android (Google) Code Review
Browse files

Merge "Only autoVerify at install for new hosts" into oc-mr1-dev

parents 239ab1c9 153de338
Loading
Loading
Loading
Loading
+149 −55
Original line number Diff line number Diff line
@@ -114,6 +114,7 @@ import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.ActivityManager;
import android.app.AppOpsManager;
import android.app.BroadcastOptions;
import android.app.IActivityManager;
import android.app.ResourcesManager;
import android.app.admin.IDevicePolicyManager;
@@ -1103,9 +1104,13 @@ public class PackageManagerService extends IPackageManager.Stub
            verificationIntent.setComponent(mIntentFilterVerifierComponent);
            verificationIntent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
            final long whitelistTimeout = getVerificationTimeout();
            final BroadcastOptions options = BroadcastOptions.makeBasic();
            options.setTemporaryAppWhitelistDuration(whitelistTimeout);
            DeviceIdleController.LocalService idleController = getDeviceIdleController();
            idleController.addPowerSaveTempWhitelistApp(Process.myUid(),
                    mIntentFilterVerifierComponent.getPackageName(), getVerificationTimeout(),
                    mIntentFilterVerifierComponent.getPackageName(), whitelistTimeout,
                    UserHandle.USER_SYSTEM, true, "intent filter verifier");
            mContext.sendBroadcastAsUser(verificationIntent, UserHandle.SYSTEM);
@@ -1146,9 +1151,6 @@ public class PackageManagerService extends IPackageManager.Stub
                        + verificationId + " packageName:" + packageName);
                return;
            }
            if (DEBUG_DOMAIN_VERIFICATION) Slog.d(TAG,
                    "Updating IntentFilterVerificationInfo for package " + packageName
                            +" verificationId:" + verificationId);
            synchronized (mPackages) {
                if (verified) {
@@ -1166,19 +1168,51 @@ public class PackageManagerService extends IPackageManager.Stub
                    int updatedStatus = INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_UNDEFINED;
                    boolean needUpdate = false;
                    // We cannot override the STATUS_ALWAYS / STATUS_NEVER states if they have
                    // already been set by the User thru the Disambiguation dialog
                    // In a success case, we promote from undefined or ASK to ALWAYS.  This
                    // supports a flow where the app fails validation but then ships an updated
                    // APK that passes, and therefore deserves to be in ALWAYS.
                    //
                    // If validation failed, the undefined state winds up in the basic ASK behavior,
                    // but apps that previously passed and became ALWAYS are *demoted* out of
                    // that state, since they would not deserve the ALWAYS behavior in case of a
                    // clean install.
                     switch (userStatus) {
                         case INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ALWAYS:
                             if (!verified) {
                                 // Don't demote if sysconfig says 'always'
                                 SystemConfig systemConfig = SystemConfig.getInstance();
                                 ArraySet<String> packages = systemConfig.getLinkedApps();
                                 if (!packages.contains(packageName)) {
                                     // updatedStatus is already UNDEFINED
                                     needUpdate = true;
                                     if (DEBUG_DOMAIN_VERIFICATION) {
                                         Slog.d(TAG, "Formerly validated but now failing; demoting");
                                     }
                                 } else {
                                     if (DEBUG_DOMAIN_VERIFICATION) {
                                         Slog.d(TAG, "Updating bundled package " + packageName
                                                 + " failed autoVerify, but sysconfig supersedes");
                                     }
                                     // leave needUpdate == false here intentionally
                                 }
                             }
                             break;
                         case INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_UNDEFINED:
                             // Stay in 'undefined' on verification failure
                             if (verified) {
                                 updatedStatus = INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ALWAYS;
                            } else {
                                updatedStatus = INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ASK;
                             }
                             needUpdate = true;
                             if (DEBUG_DOMAIN_VERIFICATION) {
                                 Slog.d(TAG, "Applying update; old=" + userStatus
                                         + " new=" + updatedStatus);
                             }
                             break;
                         case INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ASK:
                             // Keep in 'ask' on failure
                             if (verified) {
                                 updatedStatus = INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ALWAYS;
                                 needUpdate = true;
@@ -1194,6 +1228,8 @@ public class PackageManagerService extends IPackageManager.Stub
                                packageName, updatedStatus, userId);
                        scheduleWritePackageRestrictionsLocked(userId);
                    }
                } else {
                    Slog.i(TAG, "autoVerify ignored when installing for all users");
                }
             }
        }
@@ -19066,70 +19102,125 @@ public class PackageManagerService extends IPackageManager.Stub
        int count = 0;
        final String packageName = pkg.packageName;
        boolean handlesWebUris = false;
        ArraySet<String> domains = new ArraySet<>();
        final boolean previouslyVerified;
        boolean hostSetExpanded = false;
        boolean needToRunVerify = false;
        synchronized (mPackages) {
            // If this is a new install and we see that we've already run verification for this
            // package, we have nothing to do: it means the state was restored from backup.
            if (!replacing) {
            IntentFilterVerificationInfo ivi =
                    mSettings.getIntentFilterVerificationLPr(packageName);
                if (ivi != null) {
            previouslyVerified = (ivi != null);
            if (!replacing && previouslyVerified) {
                if (DEBUG_DOMAIN_VERIFICATION) {
                    Slog.i(TAG, "Package " + packageName + " already verified: status="
                            + ivi.getStatusString());
                }
                return;
            }
            if (DEBUG_DOMAIN_VERIFICATION) {
                Slog.i(TAG, "    Previous verified hosts: "
                        + (ivi == null ? "[none]" : ivi.getDomainsString()));
            }
            // If any filters need to be verified, then all need to be.
            boolean needToVerify = false;
            // If any filters need to be verified, then all need to be.  In addition, we need to
            // know whether an updating app has any web navigation intent filters, to re-
            // examine handling policy even if not re-verifying.
            final boolean needsVerification = needsNetworkVerificationLPr(packageName);
            for (PackageParser.Activity a : pkg.activities) {
                for (ActivityIntentInfo filter : a.intents) {
                    if (filter.needsVerification() && needsNetworkVerificationLPr(filter)) {
                    if (filter.handlesWebUris(true)) {
                        handlesWebUris = true;
                    }
                    if (needsVerification && filter.needsVerification()) {
                        if (DEBUG_DOMAIN_VERIFICATION) {
                            Slog.d(TAG, "Intent filter needs verification, so processing all filters");
                            Slog.d(TAG, "autoVerify requested, processing all filters");
                        }
                        needToVerify = true;
                        needToRunVerify = true;
                        // It's safe to break out here because filter.needsVerification()
                        // can only be true if filter.handlesWebUris(true) returned true, so
                        // we've already noted that.
                        break;
                    }
                }
            }
            if (needToVerify) {
            // Compare the new set of recognized hosts if the app is either requesting
            // autoVerify or has previously used autoVerify but no longer does.
            if (needToRunVerify || previouslyVerified) {
                final int verificationId = mIntentFilterVerificationToken++;
                for (PackageParser.Activity a : pkg.activities) {
                    for (ActivityIntentInfo filter : a.intents) {
                        // Run verification against hosts mentioned in any web-nav intent filter,
                        // even if the filter matches non-web schemes as well
                        if (filter.handlesWebUris(false) && needsNetworkVerificationLPr(filter)) {
                        if (filter.handlesWebUris(false /*onlyWebSchemes*/)) {
                            if (DEBUG_DOMAIN_VERIFICATION) Slog.d(TAG,
                                    "Verification needed for IntentFilter:" + filter.toString());
                            mIntentFilterVerifier.addOneIntentFilterVerification(
                                    verifierUid, userId, verificationId, filter, packageName);
                            domains.addAll(filter.getHostsList());
                            count++;
                        }
                    }
                }
            }
            if (DEBUG_DOMAIN_VERIFICATION) {
                Slog.i(TAG, "    Update published hosts: " + domains.toString());
            }
        if (count > 0) {
            // If we've previously verified this same host set (or a subset), we can trust that
            // a current ALWAYS policy is still applicable.  If this is the case, we're done.
            // (If we aren't in ALWAYS, we want to reverify to allow for apps that had failing
            // hosts in their intent filters, then pushed a new apk that removed them and now
            // passes.)
            //
            // Cases:
            //   + still autoVerify (needToRunVerify):
            //      - preserve current state if all of: unexpanded, in always
            //      - otherwise rerun as usual (fall through)
            //   + no longer autoVerify (alreadyVerified && !needToRunVerify)
            //      - wipe verification history always
            //      - preserve current state if all of: unexpanded, in always
            hostSetExpanded = !previouslyVerified
                    || (ivi != null && !ivi.getDomains().containsAll(domains));
            final int currentPolicy =
                    mSettings.getIntentFilterVerificationStatusLPr(packageName, userId);
            final boolean keepCurState = !hostSetExpanded
                    && currentPolicy == INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ALWAYS;
            if (needToRunVerify && keepCurState) {
                if (DEBUG_DOMAIN_VERIFICATION) {
                    Slog.i(TAG, "Host set not expanding + ALWAYS -> no need to reverify");
                }
                ivi.setDomains(domains);
                scheduleWriteSettingsLocked();
                return;
            } else if (previouslyVerified && !needToRunVerify) {
                // Prior autoVerify state but not requesting it now.  Clear autoVerify history,
                // and preserve the always policy iff the host set is not expanding.
                clearIntentFilterVerificationsLPw(packageName, userId, !keepCurState);
                return;
            }
        }
        if (needToRunVerify && count > 0) {
            // app requested autoVerify and has at least one matching intent filter
            if (DEBUG_DOMAIN_VERIFICATION) Slog.d(TAG, "Starting " + count
                    + " IntentFilter verification" + (count > 1 ? "s" : "")
                    +  " for userId:" + userId);
            mIntentFilterVerifier.startVerifications(userId);
        } else {
            if (DEBUG_DOMAIN_VERIFICATION) {
                Slog.d(TAG, "No filters or not all autoVerify for " + packageName);
                Slog.d(TAG, "No web filters or no new host policy for " + packageName);
            }
        }
     }
    private boolean needsNetworkVerificationLPr(ActivityIntentInfo filter) {
        final ComponentName cn  = filter.activity.getComponentName();
        final String packageName = cn.getPackageName();
    private boolean needsNetworkVerificationLPr(String packageName) {
        IntentFilterVerificationInfo ivi = mSettings.getIntentFilterVerificationLPr(
                packageName);
        if (ivi == null) {
@@ -19138,6 +19229,7 @@ public class PackageManagerService extends IPackageManager.Stub
        int status = ivi.getStatus();
        switch (status) {
            case INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_UNDEFINED:
            case INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ALWAYS:
            case INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ASK:
                return true;
@@ -19847,7 +19939,7 @@ public class PackageManagerService extends IPackageManager.Stub
            boolean installedStateChanged = false;
            if (deletedPs != null) {
                if ((flags&PackageManager.DELETE_KEEP_DATA) == 0) {
                    clearIntentFilterVerificationsLPw(deletedPs.name, UserHandle.USER_ALL);
                    clearIntentFilterVerificationsLPw(deletedPs.name, UserHandle.USER_ALL, true);
                    clearDefaultBrowserIfNeeded(packageName);
                    mSettings.mKeySetManagerService.removeAppKeySetDataLPw(packageName);
                    removedAppId = mSettings.removePackageLPw(packageName);
@@ -21153,12 +21245,13 @@ public class PackageManagerService extends IPackageManager.Stub
        final int packageCount = mPackages.size();
        for (int i = 0; i < packageCount; i++) {
            PackageParser.Package pkg = mPackages.valueAt(i);
            clearIntentFilterVerificationsLPw(pkg.packageName, userId);
            clearIntentFilterVerificationsLPw(pkg.packageName, userId, true);
        }
    }
    /** This method takes a specific user id as well as UserHandle.USER_ALL. */
    void clearIntentFilterVerificationsLPw(String packageName, int userId) {
    void clearIntentFilterVerificationsLPw(String packageName, int userId,
            boolean alsoResetStatus) {
        if (userId == UserHandle.USER_ALL) {
            if (mSettings.removeIntentFilterVerificationLPw(packageName,
                    sUserManager.getUserIds())) {
@@ -21167,7 +21260,8 @@ public class PackageManagerService extends IPackageManager.Stub
                }
            }
        } else {
            if (mSettings.removeIntentFilterVerificationLPw(packageName, userId)) {
            if (mSettings.removeIntentFilterVerificationLPw(packageName, userId,
                    alsoResetStatus)) {
                scheduleWritePackageRestrictionsLocked(userId);
            }
        }
+7 −3
Original line number Diff line number Diff line
@@ -1371,7 +1371,8 @@ final class Settings {
        return result;
    }

    boolean removeIntentFilterVerificationLPw(String packageName, int userId) {
    boolean removeIntentFilterVerificationLPw(String packageName, int userId,
            boolean alsoResetStatus) {
        PackageSetting ps = mPackages.get(packageName);
        if (ps == null) {
            if (DEBUG_DOMAIN_VERIFICATION) {
@@ -1379,14 +1380,17 @@ final class Settings {
            }
            return false;
        }
        if (alsoResetStatus) {
            ps.clearDomainVerificationStatusForUser(userId);
        }
        ps.setIntentFilterVerificationInfo(null);
        return true;
    }

    boolean removeIntentFilterVerificationLPw(String packageName, int[] userIds) {
        boolean result = false;
        for (int userId : userIds) {
            result |= removeIntentFilterVerificationLPw(packageName, userId);
            result |= removeIntentFilterVerificationLPw(packageName, userId, true);
        }
        return result;
    }