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

Commit 08aba3cc authored by Svetoslav Ganov's avatar Svetoslav Ganov Committed by Android (Google) Code Review
Browse files

Merge "Don't hold the autofill lock when looking up fill compat packages"

parents 9ec308d2 a6ebff0f
Loading
Loading
Loading
Loading
+2 −1
Original line number Diff line number Diff line
@@ -11354,7 +11354,8 @@ public final class Settings {
                "chained_battery_attribution_enabled";

        /**
         * The packages whitelisted to be run in autofill compatibility mode.
         * The packages whitelisted to be run in autofill compatibility mode. The list
         * of packages is ":" colon delimited.
         *
         * @hide
         */
+6 −14
Original line number Diff line number Diff line
@@ -45,7 +45,6 @@ import org.xmlpull.v1.XmlPullParserException;

import java.io.IOException;
import java.io.PrintWriter;
import java.util.Map;

/**
 * {@link ServiceInfo} and meta-data about an {@link AutofillService}.
@@ -80,7 +79,7 @@ public final class AutofillServiceInfo {
    private final String mSettingsActivity;

    @Nullable
    private final Map<String, Pair<Long, String>> mCompatibilityPackages;
    private final ArrayMap<String, Pair<Long, String>> mCompatibilityPackages;

    public AutofillServiceInfo(Context context, ComponentName comp, int userHandle)
            throws PackageManager.NameNotFoundException {
@@ -118,7 +117,7 @@ public final class AutofillServiceInfo {
        }

        String settingsActivity = null;
        Map<String, Pair<Long, String>> compatibilityPackages = null;
        ArrayMap<String, Pair<Long, String>> compatibilityPackages = null;

        try {
            final Resources resources = context.getPackageManager().getResourcesForApplication(
@@ -154,10 +153,10 @@ public final class AutofillServiceInfo {
        mCompatibilityPackages = compatibilityPackages;
    }

    private Map<String, Pair<Long, String>> parseCompatibilityPackages(XmlPullParser parser,
    private ArrayMap<String, Pair<Long, String>> parseCompatibilityPackages(XmlPullParser parser,
            Resources resources)
            throws IOException, XmlPullParserException {
        Map<String, Pair<Long, String>> compatibilityPackages = null;
        ArrayMap<String, Pair<Long, String>> compatibilityPackages = null;

        final int outerDepth = parser.getDepth();
        int type;
@@ -229,15 +228,8 @@ public final class AutofillServiceInfo {
        return mSettingsActivity;
    }

    public boolean isCompatibilityModeRequested(String packageName, long versionCode) {
        if (mCompatibilityPackages == null) {
            return false;
        }
        final Pair<Long, String> pair = mCompatibilityPackages.get(packageName);
        if (pair == null) {
            return false;
        }
        return versionCode <= pair.first;
    public ArrayMap<String, Pair<Long, String>> getCompatibilityPackages() {
        return mCompatibilityPackages;
    }

    /**
+112 −8
Original line number Diff line number Diff line
@@ -24,7 +24,6 @@ import static com.android.server.autofill.Helper.sDebug;
import static com.android.server.autofill.Helper.sPartitionMaxCount;
import static com.android.server.autofill.Helper.sVerbose;

import android.annotation.IntRange;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.UserIdInt;
@@ -56,7 +55,12 @@ import android.os.UserManagerInternal;
import android.provider.Settings;
import android.service.autofill.FillEventHistory;
import android.service.autofill.UserData;
import android.text.TextUtils;
import android.text.TextUtils.SimpleStringSplitter;
import android.util.ArrayMap;
import android.util.ArraySet;
import android.util.LocalLog;
import android.util.Pair;
import android.util.Slog;
import android.util.SparseArray;
import android.util.SparseBooleanArray;
@@ -84,6 +88,7 @@ import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
import java.util.Set;

/**
 * Entry point service for autofill management.
@@ -98,6 +103,8 @@ public final class AutofillManagerService extends SystemService {

    static final String RECEIVER_BUNDLE_EXTRA_SESSIONS = "sessions";

    private static final char COMPAT_PACKAGE_DELIMITER = ':';

    private final Context mContext;
    private final AutoFillUI mUi;

@@ -123,6 +130,9 @@ public final class AutofillManagerService extends SystemService {
    private final LocalLog mUiLatencyHistory = new LocalLog(20);
    private final LocalLog mWtfHistory = new LocalLog(50);

    private final AutofillCompatState mAutofillCompatState = new AutofillCompatState();
    private final LocalService mLocalService = new LocalService();

    private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
@@ -271,7 +281,7 @@ public final class AutofillManagerService extends SystemService {
    @Override
    public void onStart() {
        publishBinderService(AUTOFILL_MANAGER_SERVICE, new AutoFillManagerServiceStub());
        publishLocalService(AutofillManagerInternal.class, new LocalService());
        publishLocalService(AutofillManagerInternal.class, mLocalService);
    }

    @Override
@@ -317,6 +327,11 @@ public final class AutofillManagerService extends SystemService {
                    mUiLatencyHistory, mWtfHistory, resolvedUserId, mUi,
                    mDisabledUsers.get(resolvedUserId));
            mServicesCache.put(userId, service);
            final ArrayMap<String, Pair<Long, String>> compatPackages =
                    service.getCompatibilityPackagesLocked();
            if (compatPackages != null) {
                addCompatibilityModeRequests(compatPackages, userId);
            }
        }
        return service;
    }
@@ -482,6 +497,7 @@ public final class AutofillManagerService extends SystemService {
        if (service != null) {
            mServicesCache.delete(userId);
            service.destroyLocked();
            mAutofillCompatState.removeCompatibilityModeRequests(userId);
        }
    }

@@ -498,18 +514,60 @@ public final class AutofillManagerService extends SystemService {
     */
    @GuardedBy("mLock")
    private void updateCachedServiceLocked(int userId, boolean disabled) {
        AutofillManagerServiceImpl service = getServiceForUserLocked(userId);
        AutofillManagerServiceImpl service = peekServiceForUserLocked(userId);
        if (service != null) {
            service.destroySessionsLocked();
            service.updateLocked(disabled);
            if (!service.isEnabledLocked()) {
                removeCachedServiceLocked(userId);
            } else {
                final ArrayMap<String, Pair<Long, String>> compatPackages =
                        service.getCompatibilityPackagesLocked();
                if (compatPackages != null) {
                    addCompatibilityModeRequests(compatPackages, userId);
                }
            }
        }
    }

    private final class LocalService extends AutofillManagerInternal {
    private void addCompatibilityModeRequests(
            @NonNull ArrayMap<String, Pair<Long, String>> compatPackages, int userId) {
        final Set<String> whiteListedPackages = Build.IS_ENG ? null
                : getWhitelistedCompatModePackages();
        final int compatPackageCount = compatPackages.size();
        for (int i = 0; i < compatPackageCount; i++) {
            final String packageName = compatPackages.keyAt(i);
            if (!Build.IS_ENG && (whiteListedPackages == null
                    || !whiteListedPackages.contains(packageName))) {
                Slog.w(TAG, "Ignoring not whitelisted compat package " + packageName);
                continue;
            }
            final Long maxVersionCode = compatPackages.valueAt(i).first;
            if (maxVersionCode != null) {
                mAutofillCompatState.addCompatibilityModeRequest(packageName,
                        maxVersionCode, userId);
            }
        }
    }

    private @Nullable Set<String> getWhitelistedCompatModePackages() {
        final String compatPackagesSetting = Settings.Global.getString(
                mContext.getContentResolver(),
                Settings.Global.AUTOFILL_COMPAT_ALLOWED_PACKAGES);
        if (TextUtils.isEmpty(compatPackagesSetting)) {
            return null;
        }
        final Set<String> compatPackages = new ArraySet<>();
        final SimpleStringSplitter splitter = new SimpleStringSplitter(
                COMPAT_PACKAGE_DELIMITER);
        splitter.setString(compatPackagesSetting);
        while (splitter.hasNext()) {
            compatPackages.add(splitter.next());
        }
        return compatPackages;
    }

    private final class LocalService extends AutofillManagerInternal {
        @Override
        public void onBackKeyPressed() {
            if (sDebug) Slog.d(TAG, "onBackKeyPressed()");
@@ -519,14 +577,60 @@ public final class AutofillManagerService extends SystemService {
        @Override
        public boolean isCompatibilityModeRequested(@NonNull String packageName,
                long versionCode, @UserIdInt int userId) {
            return mAutofillCompatState.isCompatibilityModeRequested(
                    packageName, versionCode, userId);
        }
    }

    private static class AutofillCompatState {
        private final Object mLock = new Object();

        @GuardedBy("mLock")
        private SparseArray<ArrayMap<String, Long>> mUserSpecs;

        boolean isCompatibilityModeRequested(@NonNull String packageName,
                long versionCode, @UserIdInt int userId) {
            synchronized (mLock) {
                final AutofillManagerServiceImpl service = getServiceForUserLocked(userId);
                if (service != null) {
                    return service.isCompatibilityModeRequestedLocked(packageName, versionCode);
                if (mUserSpecs == null) {
                    return false;
                }
                final ArrayMap<String, Long> userSpec = mUserSpecs.get(userId);
                if (userSpec == null) {
                    return false;
                }
                final Long maxVersionCode = userSpec.get(packageName);
                if (maxVersionCode == null) {
                    return false;
                }
                return versionCode <= maxVersionCode;
            }
        }

        void addCompatibilityModeRequest(@NonNull String packageName,
                long versionCode, @UserIdInt int userId) {
            synchronized (mLock) {
                if (mUserSpecs == null) {
                    mUserSpecs = new SparseArray<>();
                }
                ArrayMap<String, Long> userSpec = mUserSpecs.get(userId);
                if (userSpec == null) {
                    userSpec = new ArrayMap<>();
                    mUserSpecs.put(userId, userSpec);
                }
                userSpec.put(packageName, versionCode);
            }
        }

        void removeCompatibilityModeRequests(@UserIdInt int userId) {
            synchronized (mLock) {
                if (mUserSpecs != null) {
                    mUserSpecs.remove(userId);
                    if (mUserSpecs.size() <= 0) {
                        mUserSpecs = null;
                    }
                }
            }
        }
    }

    final class AutoFillManagerServiceStub extends IAutoFillManager.Stub {
+9 −17
Original line number Diff line number Diff line
@@ -64,6 +64,7 @@ import android.util.ArrayMap;
import android.util.ArraySet;
import android.util.DebugUtils;
import android.util.LocalLog;
import android.util.Pair;
import android.util.Slog;
import android.util.SparseArray;
import android.util.TimeUtils;
@@ -906,7 +907,10 @@ final class AutofillManagerServiceImpl {
        pw.print(prefix); pw.print("Disabled: "); pw.println(mDisabled);
        pw.print(prefix); pw.print("Field classification enabled: ");
            pw.println(isFieldClassificationEnabledLocked());
        pw.print(prefix); pw.print("Compat pkgs: "); pw.println(getWhitelistedCompatModePackages());
        final ArrayMap<String, Pair<Long, String>> compatPkgs = getCompatibilityPackagesLocked();
        if (compatPkgs != null) {
            pw.print(prefix); pw.print("Compat pkgs: "); pw.println(compatPkgs.keySet());
        }
        pw.print(prefix); pw.print("Setup complete: "); pw.println(mSetupComplete);
        pw.print(prefix); pw.print("Last prune: "); pw.println(mLastPrune);

@@ -1030,23 +1034,11 @@ final class AutofillManagerServiceImpl {
    }

    @GuardedBy("mLock")
    boolean isCompatibilityModeRequestedLocked(@NonNull String packageName,
            long versionCode) {
        if (mInfo == null || !mInfo.isCompatibilityModeRequested(packageName, versionCode)) {
            return false;
        }
        if (!Build.IS_ENG) {
            // TODO: Build a map and watch for settings changes (this is called on app start)
            final String whiteListedPackages = getWhitelistedCompatModePackages();
            return whiteListedPackages != null && whiteListedPackages.contains(packageName);
        }
        return true;
    @Nullable ArrayMap<String, Pair<Long, String>> getCompatibilityPackagesLocked() {
        if (mInfo != null) {
            return mInfo.getCompatibilityPackages();
        }

    private String getWhitelistedCompatModePackages() {
        return Settings.Global.getString(
                mContext.getContentResolver(),
                Settings.Global.AUTOFILL_COMPAT_ALLOWED_PACKAGES);
        return null;
    }

    private void sendStateToClients(boolean resetClient) {