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 Original line Diff line number Diff line
@@ -11354,7 +11354,8 @@ public final class Settings {
                "chained_battery_attribution_enabled";
                "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
         * @hide
         */
         */
+6 −14
Original line number Original line Diff line number Diff line
@@ -45,7 +45,6 @@ import org.xmlpull.v1.XmlPullParserException;


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


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


    @Nullable
    @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)
    public AutofillServiceInfo(Context context, ComponentName comp, int userHandle)
            throws PackageManager.NameNotFoundException {
            throws PackageManager.NameNotFoundException {
@@ -118,7 +117,7 @@ public final class AutofillServiceInfo {
        }
        }


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


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


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


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


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


    /**
    /**
+112 −8
Original line number Original line 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.sPartitionMaxCount;
import static com.android.server.autofill.Helper.sVerbose;
import static com.android.server.autofill.Helper.sVerbose;


import android.annotation.IntRange;
import android.annotation.NonNull;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.Nullable;
import android.annotation.UserIdInt;
import android.annotation.UserIdInt;
@@ -56,7 +55,12 @@ import android.os.UserManagerInternal;
import android.provider.Settings;
import android.provider.Settings;
import android.service.autofill.FillEventHistory;
import android.service.autofill.FillEventHistory;
import android.service.autofill.UserData;
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.LocalLog;
import android.util.Pair;
import android.util.Slog;
import android.util.Slog;
import android.util.SparseArray;
import android.util.SparseArray;
import android.util.SparseBooleanArray;
import android.util.SparseBooleanArray;
@@ -84,6 +88,7 @@ import java.util.ArrayList;
import java.util.Arrays;
import java.util.Arrays;
import java.util.List;
import java.util.List;
import java.util.Objects;
import java.util.Objects;
import java.util.Set;


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


    static final String RECEIVER_BUNDLE_EXTRA_SESSIONS = "sessions";
    static final String RECEIVER_BUNDLE_EXTRA_SESSIONS = "sessions";


    private static final char COMPAT_PACKAGE_DELIMITER = ':';

    private final Context mContext;
    private final Context mContext;
    private final AutoFillUI mUi;
    private final AutoFillUI mUi;


@@ -123,6 +130,9 @@ public final class AutofillManagerService extends SystemService {
    private final LocalLog mUiLatencyHistory = new LocalLog(20);
    private final LocalLog mUiLatencyHistory = new LocalLog(20);
    private final LocalLog mWtfHistory = new LocalLog(50);
    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() {
    private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
        @Override
        @Override
        public void onReceive(Context context, Intent intent) {
        public void onReceive(Context context, Intent intent) {
@@ -271,7 +281,7 @@ public final class AutofillManagerService extends SystemService {
    @Override
    @Override
    public void onStart() {
    public void onStart() {
        publishBinderService(AUTOFILL_MANAGER_SERVICE, new AutoFillManagerServiceStub());
        publishBinderService(AUTOFILL_MANAGER_SERVICE, new AutoFillManagerServiceStub());
        publishLocalService(AutofillManagerInternal.class, new LocalService());
        publishLocalService(AutofillManagerInternal.class, mLocalService);
    }
    }


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


@@ -498,18 +514,60 @@ public final class AutofillManagerService extends SystemService {
     */
     */
    @GuardedBy("mLock")
    @GuardedBy("mLock")
    private void updateCachedServiceLocked(int userId, boolean disabled) {
    private void updateCachedServiceLocked(int userId, boolean disabled) {
        AutofillManagerServiceImpl service = getServiceForUserLocked(userId);
        AutofillManagerServiceImpl service = peekServiceForUserLocked(userId);
        if (service != null) {
        if (service != null) {
            service.destroySessionsLocked();
            service.destroySessionsLocked();
            service.updateLocked(disabled);
            service.updateLocked(disabled);
            if (!service.isEnabledLocked()) {
            if (!service.isEnabledLocked()) {
                removeCachedServiceLocked(userId);
                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
        @Override
        public void onBackKeyPressed() {
        public void onBackKeyPressed() {
            if (sDebug) Slog.d(TAG, "onBackKeyPressed()");
            if (sDebug) Slog.d(TAG, "onBackKeyPressed()");
@@ -519,14 +577,60 @@ public final class AutofillManagerService extends SystemService {
        @Override
        @Override
        public boolean isCompatibilityModeRequested(@NonNull String packageName,
        public boolean isCompatibilityModeRequested(@NonNull String packageName,
                long versionCode, @UserIdInt int userId) {
                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) {
            synchronized (mLock) {
                final AutofillManagerServiceImpl service = getServiceForUserLocked(userId);
                if (mUserSpecs == null) {
                if (service != null) {
                    return false;
                    return service.isCompatibilityModeRequestedLocked(packageName, versionCode);
                }
                }
                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 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 {
    final class AutoFillManagerServiceStub extends IAutoFillManager.Stub {
+9 −17
Original line number Original line Diff line number Diff line
@@ -64,6 +64,7 @@ import android.util.ArrayMap;
import android.util.ArraySet;
import android.util.ArraySet;
import android.util.DebugUtils;
import android.util.DebugUtils;
import android.util.LocalLog;
import android.util.LocalLog;
import android.util.Pair;
import android.util.Slog;
import android.util.Slog;
import android.util.SparseArray;
import android.util.SparseArray;
import android.util.TimeUtils;
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("Disabled: "); pw.println(mDisabled);
        pw.print(prefix); pw.print("Field classification enabled: ");
        pw.print(prefix); pw.print("Field classification enabled: ");
            pw.println(isFieldClassificationEnabledLocked());
            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("Setup complete: "); pw.println(mSetupComplete);
        pw.print(prefix); pw.print("Last prune: "); pw.println(mLastPrune);
        pw.print(prefix); pw.print("Last prune: "); pw.println(mLastPrune);


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


    @GuardedBy("mLock")
    @GuardedBy("mLock")
    boolean isCompatibilityModeRequestedLocked(@NonNull String packageName,
    @Nullable ArrayMap<String, Pair<Long, String>> getCompatibilityPackagesLocked() {
            long versionCode) {
        if (mInfo != null) {
        if (mInfo == null || !mInfo.isCompatibilityModeRequested(packageName, versionCode)) {
            return mInfo.getCompatibilityPackages();
            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;
        }
        }

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


    private void sendStateToClients(boolean resetClient) {
    private void sendStateToClients(boolean resetClient) {