/*
 * Copyright (C) 2016 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.autofill;

import static android.Manifest.permission.MANAGE_AUTO_FILL;
import static android.content.Context.AUTOFILL_MANAGER_SERVICE;
import static android.view.autofill.AutofillManager.MAX_TEMP_AUGMENTED_SERVICE_DURATION_MS;
import static android.view.autofill.AutofillManager.getSmartSuggestionModeToString;

import static com.android.server.autofill.Helper.sDebug;
import static com.android.server.autofill.Helper.sFullScreenMode;
import static com.android.server.autofill.Helper.sVerbose;

import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.UserIdInt;
import android.app.ActivityManagerInternal;
import android.app.ActivityThread;
import android.content.AutofillOptions;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.PackageManager;
import android.content.pm.UserInfo;
import android.database.ContentObserver;
import android.graphics.Rect;
import android.os.Binder;
import android.os.Build;
import android.os.Bundle;
import android.os.IBinder;
import android.os.Parcelable;
import android.os.RemoteCallback;
import android.os.RemoteException;
import android.os.ResultReceiver;
import android.os.ShellCallback;
import android.os.UserHandle;
import android.os.UserManager;
import android.provider.DeviceConfig;
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.LocalLog;
import android.util.Slog;
import android.util.SparseArray;
import android.util.SparseBooleanArray;
import android.view.autofill.AutofillId;
import android.view.autofill.AutofillManager;
import android.view.autofill.AutofillManager.SmartSuggestionMode;
import android.view.autofill.AutofillManagerInternal;
import android.view.autofill.AutofillValue;
import android.view.autofill.IAutoFillManager;
import android.view.autofill.IAutoFillManagerClient;

import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.infra.AbstractRemoteService;
import com.android.internal.infra.GlobalWhitelistState;
import com.android.internal.infra.WhitelistHelper;
import com.android.internal.os.IResultReceiver;
import com.android.internal.util.DumpUtils;
import com.android.internal.util.Preconditions;
import com.android.internal.util.SyncResultReceiver;
import com.android.server.FgThread;
import com.android.server.LocalServices;
import com.android.server.autofill.ui.AutoFillUI;
import com.android.server.infra.AbstractMasterSystemService;
import com.android.server.infra.FrameworkResourcesServiceNameResolver;
import com.android.server.infra.SecureSettingsServiceNameResolver;

import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;

/**
 * Entry point service for autofill management.
 *
 * <p>This service provides the {@link IAutoFillManager} implementation and keeps a list of
 * {@link AutofillManagerServiceImpl} per user; the real work is done by
 * {@link AutofillManagerServiceImpl} itself.
 */
public final class AutofillManagerService
        extends AbstractMasterSystemService<AutofillManagerService, AutofillManagerServiceImpl> {

    private static final String TAG = "AutofillManagerService";

    private static final Object sLock = AutofillManagerService.class;

    static final String RECEIVER_BUNDLE_EXTRA_SESSIONS = "sessions";

    private static final char COMPAT_PACKAGE_DELIMITER = ':';
    private static final char COMPAT_PACKAGE_URL_IDS_DELIMITER = ',';
    private static final char COMPAT_PACKAGE_URL_IDS_BLOCK_BEGIN = '[';
    private static final char COMPAT_PACKAGE_URL_IDS_BLOCK_END = ']';

    private static final int DEFAULT_AUGMENTED_AUTOFILL_REQUEST_TIMEOUT_MILLIS = 5_000;

    /**
     * Maximum number of partitions that can be allowed in a session.
     *
     * <p>Can be modified using {@code cmd autofill set max_partitions} or through
     * {@link android.provider.Settings.Global#AUTOFILL_MAX_PARTITIONS_SIZE}.
     */
    @GuardedBy("sLock")
    private static int sPartitionMaxCount = AutofillManager.DEFAULT_MAX_PARTITIONS_SIZE;

    /**
     * Maximum number of visible datasets in the dataset picker UI, or {@code 0} to use default
     * value from resources.
     *
     * <p>Can be modified using {@code cmd autofill set max_visible_datasets} or through
     * {@link android.provider.Settings.Global#AUTOFILL_MAX_VISIBLE_DATASETS}.
     */
    @GuardedBy("sLock")
    private static int sVisibleDatasetsMaxCount = 0;

    /**
     * Object used to set the name of the augmented autofill service.
     */
    @NonNull
    final FrameworkResourcesServiceNameResolver mAugmentedAutofillResolver;

    private final AutoFillUI mUi;

    private final LocalLog mRequestsHistory = new LocalLog(20);
    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 ActivityManagerInternal mAm;

    private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            if (Intent.ACTION_CLOSE_SYSTEM_DIALOGS.equals(intent.getAction())) {
                if (sDebug) Slog.d(TAG, "Close system dialogs");

                // TODO(b/64940307): we need to destroy all sessions that are finished but showing
                // Save UI because there is no way to show the Save UI back when the activity
                // beneath it is brought back to top. Ideally, we should just hide the UI and
                // bring it back when the activity resumes.
                synchronized (mLock) {
                    visitServicesLocked((s) -> s.destroyFinishedSessionsLocked());
                }
                mUi.hideAll(null);
            }
        }
    };

    /**
     * Supported modes for Augmented Autofill Smart Suggestions.
     */
    @GuardedBy("mLock")
    private int mSupportedSmartSuggestionModes;

    @GuardedBy("mLock")
    int mAugmentedServiceIdleUnbindTimeoutMs;
    @GuardedBy("mLock")
    int mAugmentedServiceRequestTimeoutMs;

    final AugmentedAutofillState mAugmentedAutofillState = new AugmentedAutofillState();

    public AutofillManagerService(Context context) {
        super(context,
                new SecureSettingsServiceNameResolver(context, Settings.Secure.AUTOFILL_SERVICE),
                UserManager.DISALLOW_AUTOFILL);
        mUi = new AutoFillUI(ActivityThread.currentActivityThread().getSystemUiContext());
        mAm = LocalServices.getService(ActivityManagerInternal.class);

        DeviceConfig.addOnPropertiesChangedListener(DeviceConfig.NAMESPACE_AUTOFILL,
                ActivityThread.currentApplication().getMainExecutor(),
                (properties) -> onDeviceConfigChange(properties.getKeyset()));

        setLogLevelFromSettings();
        setMaxPartitionsFromSettings();
        setMaxVisibleDatasetsFromSettings();
        setDeviceConfigProperties();

        final IntentFilter filter = new IntentFilter();
        filter.addAction(Intent.ACTION_CLOSE_SYSTEM_DIALOGS);
        context.registerReceiver(mBroadcastReceiver, filter, null, FgThread.getHandler());

        mAugmentedAutofillResolver = new FrameworkResourcesServiceNameResolver(getContext(),
                com.android.internal.R.string.config_defaultAugmentedAutofillService);
        mAugmentedAutofillResolver.setOnTemporaryServiceNameChangedCallback(
                (u, s, t) -> onAugmentedServiceNameChanged(u, s, t));

        if (mSupportedSmartSuggestionModes != AutofillManager.FLAG_SMART_SUGGESTION_OFF) {
            final UserManager um = getContext().getSystemService(UserManager.class);
            final List<UserInfo> users = um.getUsers();
            for (int i = 0; i < users.size(); i++) {
                final int userId = users.get(i).id;
                // Must eager load the services so they bind to the augmented autofill service
                getServiceForUserLocked(userId);

                // And also set the global state
                mAugmentedAutofillState.setServiceInfo(userId,
                        mAugmentedAutofillResolver.getServiceName(userId),
                        mAugmentedAutofillResolver.isTemporary(userId));
            }
        }
    }

    @Override // from AbstractMasterSystemService
    protected String getServiceSettingsProperty() {
        return Settings.Secure.AUTOFILL_SERVICE;
    }

    @Override // from AbstractMasterSystemService
    protected void registerForExtraSettingsChanges(@NonNull ContentResolver resolver,
            @NonNull ContentObserver observer) {
        resolver.registerContentObserver(Settings.Global.getUriFor(
                Settings.Global.AUTOFILL_COMPAT_MODE_ALLOWED_PACKAGES), false, observer,
                UserHandle.USER_ALL);
        resolver.registerContentObserver(Settings.Global.getUriFor(
                Settings.Global.AUTOFILL_LOGGING_LEVEL), false, observer,
                UserHandle.USER_ALL);
        resolver.registerContentObserver(Settings.Global.getUriFor(
                Settings.Global.AUTOFILL_MAX_PARTITIONS_SIZE), false, observer,
                UserHandle.USER_ALL);
        resolver.registerContentObserver(Settings.Global.getUriFor(
                Settings.Global.AUTOFILL_MAX_VISIBLE_DATASETS), false, observer,
                UserHandle.USER_ALL);
    }

    @Override // from AbstractMasterSystemService
    protected void onSettingsChanged(int userId, @NonNull String property) {
        switch (property) {
            case Settings.Global.AUTOFILL_LOGGING_LEVEL:
                setLogLevelFromSettings();
                break;
            case Settings.Global.AUTOFILL_MAX_PARTITIONS_SIZE:
                setMaxPartitionsFromSettings();
                break;
            case Settings.Global.AUTOFILL_MAX_VISIBLE_DATASETS:
                setMaxVisibleDatasetsFromSettings();
                break;
            default:
                Slog.w(TAG, "Unexpected property (" + property + "); updating cache instead");
                // fall through
            case Settings.Global.AUTOFILL_COMPAT_MODE_ALLOWED_PACKAGES:
                synchronized (mLock) {
                    updateCachedServiceLocked(userId);
                }
        }
    }

    private void onDeviceConfigChange(@NonNull Set<String> keys) {
        for (String key : keys) {
            switch (key) {
                case AutofillManager.DEVICE_CONFIG_AUTOFILL_SMART_SUGGESTION_SUPPORTED_MODES:
                case AutofillManager.DEVICE_CONFIG_AUGMENTED_SERVICE_IDLE_UNBIND_TIMEOUT:
                case AutofillManager.DEVICE_CONFIG_AUGMENTED_SERVICE_REQUEST_TIMEOUT:
                    setDeviceConfigProperties();
                    break;
                default:
                    Slog.i(mTag, "Ignoring change on " + key);
            }
        }
    }

    private void onAugmentedServiceNameChanged(@UserIdInt int userId, @Nullable String serviceName,
            boolean isTemporary) {
        mAugmentedAutofillState.setServiceInfo(userId, serviceName, isTemporary);
        synchronized (mLock) {
            getServiceForUserLocked(userId).updateRemoteAugmentedAutofillService();
        }
    }

    @Override // from AbstractMasterSystemService
    protected AutofillManagerServiceImpl newServiceLocked(@UserIdInt int resolvedUserId,
            boolean disabled) {
        return new AutofillManagerServiceImpl(this, mLock, mUiLatencyHistory,
                mWtfHistory, resolvedUserId, mUi, mAutofillCompatState, disabled);
    }

    @Override // AbstractMasterSystemService
    protected void onServiceRemoved(@NonNull AutofillManagerServiceImpl service,
            @UserIdInt int userId) {
        service.destroyLocked();
        mAutofillCompatState.removeCompatibilityModeRequests(userId);
    }

    @Override // from AbstractMasterSystemService
    protected void onServiceEnabledLocked(@NonNull AutofillManagerServiceImpl service,
            @UserIdInt int userId) {
        addCompatibilityModeRequestsLocked(service, userId);
    }

    @Override // from AbstractMasterSystemService
    protected void enforceCallingPermissionForManagement() {
        getContext().enforceCallingPermission(MANAGE_AUTO_FILL, TAG);
    }

    @Override // from SystemService
    public void onStart() {
        publishBinderService(AUTOFILL_MANAGER_SERVICE, new AutoFillManagerServiceStub());
        publishLocalService(AutofillManagerInternal.class, mLocalService);
    }

    @Override // from SystemService
    public void onSwitchUser(int userHandle) {
        if (sDebug) Slog.d(TAG, "Hiding UI when user switched");
        mUi.hideAll(null);
    }

    @SmartSuggestionMode int getSupportedSmartSuggestionModesLocked() {
        return mSupportedSmartSuggestionModes;
    }

    /**
     * Logs a request so it's dumped later...
     */
    void logRequestLocked(@NonNull String historyItem) {
        mRequestsHistory.log(historyItem);
    }

    // Called by AutofillManagerServiceImpl, doesn't need to check permission
    boolean isInstantServiceAllowed() {
        return mAllowInstantService;
    }

    // Called by Shell command.
    void destroySessions(@UserIdInt int userId, IResultReceiver receiver) {
        Slog.i(TAG, "destroySessions() for userId " + userId);
        enforceCallingPermissionForManagement();

        synchronized (mLock) {
            if (userId != UserHandle.USER_ALL) {
                AutofillManagerServiceImpl service = peekServiceForUserLocked(userId);
                if (service != null) {
                    service.destroySessionsLocked();
                }
            } else {
                visitServicesLocked((s) -> s.destroySessionsLocked());
            }
        }

        try {
            receiver.send(0, new Bundle());
        } catch (RemoteException e) {
            // Just ignore it...
        }
    }

    // Called by Shell command.
    void listSessions(int userId, IResultReceiver receiver) {
        Slog.i(TAG, "listSessions() for userId " + userId);
        enforceCallingPermissionForManagement();

        final Bundle resultData = new Bundle();
        final ArrayList<String> sessions = new ArrayList<>();

        synchronized (mLock) {
            if (userId != UserHandle.USER_ALL) {
                AutofillManagerServiceImpl service = peekServiceForUserLocked(userId);
                if (service != null) {
                    service.listSessionsLocked(sessions);
                }
            } else {
                visitServicesLocked((s) -> s.listSessionsLocked(sessions));
            }
        }

        resultData.putStringArrayList(RECEIVER_BUNDLE_EXTRA_SESSIONS, sessions);
        try {
            receiver.send(0, resultData);
        } catch (RemoteException e) {
            // Just ignore it...
        }
    }

    // Called by Shell command.
    void reset() {
        Slog.i(TAG, "reset()");
        enforceCallingPermissionForManagement();

        synchronized (mLock) {
            visitServicesLocked((s) -> s.destroyLocked());
            clearCacheLocked();
        }
    }

    // Called by Shell command.
    void setLogLevel(int level) {
        Slog.i(TAG, "setLogLevel(): " + level);
        enforceCallingPermissionForManagement();

        final long token = Binder.clearCallingIdentity();
        try {
            Settings.Global.putInt(getContext().getContentResolver(),
                    Settings.Global.AUTOFILL_LOGGING_LEVEL, level);
        } finally {
            Binder.restoreCallingIdentity(token);
        }
    }

    private void setLogLevelFromSettings() {
        final int level = Settings.Global.getInt(
                getContext().getContentResolver(),
                Settings.Global.AUTOFILL_LOGGING_LEVEL, AutofillManager.DEFAULT_LOGGING_LEVEL);
        boolean debug = false;
        boolean verbose = false;
        if (level != AutofillManager.NO_LOGGING) {
            if (level == AutofillManager.FLAG_ADD_CLIENT_VERBOSE) {
                debug = verbose = true;
            } else if (level == AutofillManager.FLAG_ADD_CLIENT_DEBUG) {
                debug = true;
            } else {
                Slog.w(TAG,  "setLogLevelFromSettings(): invalid level: " + level);
            }
        }
        if (debug || sDebug) {
            Slog.d(TAG, "setLogLevelFromSettings(): level=" + level + ", debug=" + debug
                    + ", verbose=" + verbose);
        }
        synchronized (mLock) {
            setLoggingLevelsLocked(debug, verbose);
        }
    }

    // Called by Shell command.
    int getLogLevel() {
        enforceCallingPermissionForManagement();

        synchronized (mLock) {
            if (sVerbose) return AutofillManager.FLAG_ADD_CLIENT_VERBOSE;
            if (sDebug) return AutofillManager.FLAG_ADD_CLIENT_DEBUG;
            return 0;
        }
    }

    // Called by Shell command.
    int getMaxPartitions() {
        enforceCallingPermissionForManagement();

        synchronized (mLock) {
            return sPartitionMaxCount;
        }
    }

    // Called by Shell command.
    void setMaxPartitions(int max) {
        Slog.i(TAG, "setMaxPartitions(): " + max);
        enforceCallingPermissionForManagement();

        final long token = Binder.clearCallingIdentity();
        try {
            Settings.Global.putInt(getContext().getContentResolver(),
                    Settings.Global.AUTOFILL_MAX_PARTITIONS_SIZE, max);
        } finally {
            Binder.restoreCallingIdentity(token);
        }
    }

    private void setMaxPartitionsFromSettings() {
        final int max = Settings.Global.getInt(getContext().getContentResolver(),
                Settings.Global.AUTOFILL_MAX_PARTITIONS_SIZE,
                AutofillManager.DEFAULT_MAX_PARTITIONS_SIZE);
        if (sDebug) Slog.d(TAG, "setMaxPartitionsFromSettings(): " + max);

        synchronized (sLock) {
            sPartitionMaxCount = max;
        }
    }

    // Called by Shell command.
    int getMaxVisibleDatasets() {
        enforceCallingPermissionForManagement();

        synchronized (sLock) {
            return sVisibleDatasetsMaxCount;
        }
    }

    // Called by Shell command.
    void setMaxVisibleDatasets(int max) {
        Slog.i(TAG, "setMaxVisibleDatasets(): " + max);
        enforceCallingPermissionForManagement();

        final long token = Binder.clearCallingIdentity();
        try {
            Settings.Global.putInt(getContext().getContentResolver(),
                    Settings.Global.AUTOFILL_MAX_VISIBLE_DATASETS, max);
        } finally {
            Binder.restoreCallingIdentity(token);
        }
    }

    private void setMaxVisibleDatasetsFromSettings() {
        final int max = Settings.Global.getInt(getContext().getContentResolver(),
                Settings.Global.AUTOFILL_MAX_VISIBLE_DATASETS, 0);

        if (sDebug) Slog.d(TAG, "setMaxVisibleDatasetsFromSettings(): " + max);
        synchronized (sLock) {
            sVisibleDatasetsMaxCount = max;
        }
    }

    private void setDeviceConfigProperties() {
        synchronized (mLock) {
            mAugmentedServiceIdleUnbindTimeoutMs = DeviceConfig.getInt(
                    DeviceConfig.NAMESPACE_AUTOFILL,
                    AutofillManager.DEVICE_CONFIG_AUGMENTED_SERVICE_IDLE_UNBIND_TIMEOUT,
                    (int) AbstractRemoteService.PERMANENT_BOUND_TIMEOUT_MS);
            mAugmentedServiceRequestTimeoutMs = DeviceConfig.getInt(
                    DeviceConfig.NAMESPACE_AUTOFILL,
                    AutofillManager.DEVICE_CONFIG_AUGMENTED_SERVICE_REQUEST_TIMEOUT,
                    DEFAULT_AUGMENTED_AUTOFILL_REQUEST_TIMEOUT_MILLIS);
            mSupportedSmartSuggestionModes = DeviceConfig.getInt(
                    DeviceConfig.NAMESPACE_AUTOFILL,
                    AutofillManager.DEVICE_CONFIG_AUTOFILL_SMART_SUGGESTION_SUPPORTED_MODES,
                    AutofillManager.FLAG_SMART_SUGGESTION_SYSTEM);
            if (verbose) {
                Slog.v(mTag, "setDeviceConfigProperties(): "
                        + "augmentedIdleTimeout=" + mAugmentedServiceIdleUnbindTimeoutMs
                        + ", augmentedRequestTimeout=" + mAugmentedServiceRequestTimeoutMs
                        + ", smartSuggestionMode="
                        + getSmartSuggestionModeToString(mSupportedSmartSuggestionModes));
            }
        }
    }

    // Called by Shell command.
    void calculateScore(@Nullable String algorithmName, @NonNull String value1,
            @NonNull String value2, @NonNull RemoteCallback callback) {
        enforceCallingPermissionForManagement();

        final FieldClassificationStrategy strategy =
                new FieldClassificationStrategy(getContext(), UserHandle.USER_CURRENT);

        strategy.calculateScores(callback, Arrays.asList(AutofillValue.forText(value1)),
                new String[] { value2 }, new String[] { null }, algorithmName, null, null, null);
    }

    // Called by Shell command.
    Boolean getFullScreenMode() {
        enforceCallingPermissionForManagement();
        return sFullScreenMode;
    }

    // Called by Shell command.
    void setFullScreenMode(@Nullable Boolean mode) {
        enforceCallingPermissionForManagement();
        sFullScreenMode = mode;
    }

    // Called by Shell command.
    void setTemporaryAugmentedAutofillService(@UserIdInt int userId, @NonNull String serviceName,
            int durationMs) {
        Slog.i(mTag, "setTemporaryAugmentedAutofillService(" + userId + ") to " + serviceName
                + " for " + durationMs + "ms");
        enforceCallingPermissionForManagement();

        Preconditions.checkNotNull(serviceName);
        if (durationMs > MAX_TEMP_AUGMENTED_SERVICE_DURATION_MS) {
            throw new IllegalArgumentException("Max duration is "
                    + MAX_TEMP_AUGMENTED_SERVICE_DURATION_MS + " (called with " + durationMs + ")");
        }

        mAugmentedAutofillResolver.setTemporaryService(userId, serviceName, durationMs);
    }

    // Called by Shell command
    void resetTemporaryAugmentedAutofillService(@UserIdInt int userId) {
        enforceCallingPermissionForManagement();
        mAugmentedAutofillResolver.resetTemporaryService(userId);
    }

    // Called by Shell command
    boolean isDefaultAugmentedServiceEnabled(@UserIdInt int userId) {
        enforceCallingPermissionForManagement();
        return mAugmentedAutofillResolver.isDefaultServiceEnabled(userId);
    }

    // Called by Shell command
    boolean setDefaultAugmentedServiceEnabled(@UserIdInt int userId, boolean enabled) {
        Slog.i(mTag, "setDefaultAugmentedServiceEnabled() for userId " + userId + ": " + enabled);
        enforceCallingPermissionForManagement();

        synchronized (mLock) {
            final AutofillManagerServiceImpl service = getServiceForUserLocked(userId);
            if (service != null) {
                final boolean changed = mAugmentedAutofillResolver
                        .setDefaultServiceEnabled(userId, enabled);
                if (changed) {
                    service.updateRemoteAugmentedAutofillService();
                    return true;
                } else {
                    if (debug) {
                        Slog.d(TAG, "setDefaultAugmentedServiceEnabled(): already " + enabled);
                    }
                }
            }
        }
        return false;
    }

    private void setLoggingLevelsLocked(boolean debug, boolean verbose) {
        com.android.server.autofill.Helper.sDebug = debug;
        android.view.autofill.Helper.sDebug = debug;
        this.debug = debug;

        com.android.server.autofill.Helper.sVerbose = verbose;
        android.view.autofill.Helper.sVerbose = verbose;
        this.verbose = verbose;
    }

    private void addCompatibilityModeRequestsLocked(@NonNull AutofillManagerServiceImpl service
            , int userId) {
        mAutofillCompatState.reset(userId);
        final ArrayMap<String, Long> compatPackages =
                service.getCompatibilityPackagesLocked();
        if (compatPackages == null || compatPackages.isEmpty()) {
            return;
        }

        final Map<String, String[]> whiteListedPackages = getWhitelistedCompatModePackages();
        final int compatPackageCount = compatPackages.size();
        for (int i = 0; i < compatPackageCount; i++) {
            final String packageName = compatPackages.keyAt(i);
            if (whiteListedPackages == null || !whiteListedPackages.containsKey(packageName)) {
                Slog.w(TAG, "Ignoring not whitelisted compat package " + packageName);
                continue;
            }
            final Long maxVersionCode = compatPackages.valueAt(i);
            if (maxVersionCode != null) {
                mAutofillCompatState.addCompatibilityModeRequest(packageName,
                        maxVersionCode, whiteListedPackages.get(packageName), userId);
            }
        }
    }

    private String getWhitelistedCompatModePackagesFromSettings() {
        return Settings.Global.getString(
                getContext().getContentResolver(),
                Settings.Global.AUTOFILL_COMPAT_MODE_ALLOWED_PACKAGES);
    }

    @Nullable
    private Map<String, String[]> getWhitelistedCompatModePackages() {
        return getWhitelistedCompatModePackages(getWhitelistedCompatModePackagesFromSettings());
    }

    private void send(@NonNull IResultReceiver receiver, int value) {
        try {
            receiver.send(value, null);
        } catch (RemoteException e) {
            Slog.w(TAG, "Error async reporting result to client: " + e);
        }
    }

    private void send(@NonNull IResultReceiver receiver, @NonNull Bundle value) {
        try {
            receiver.send(0, value);
        } catch (RemoteException e) {
            Slog.w(TAG, "Error async reporting result to client: " + e);
        }
    }

    private void send(@NonNull IResultReceiver receiver, @Nullable String value) {
        send(receiver, SyncResultReceiver.bundleFor(value));
    }

    private void send(@NonNull IResultReceiver receiver, @Nullable String[] value) {
        send(receiver, SyncResultReceiver.bundleFor(value));
    }

    private void send(@NonNull IResultReceiver receiver, @Nullable Parcelable value) {
        send(receiver, SyncResultReceiver.bundleFor(value));
    }

    private void send(@NonNull IResultReceiver receiver, boolean value) {
        send(receiver, value ? 1 : 0);
    }

    private void send(@NonNull IResultReceiver receiver, int value1, int value2) {
        try {
            receiver.send(value1, SyncResultReceiver.bundleFor(value2));
        } catch (RemoteException e) {
            Slog.w(TAG, "Error async reporting result to client: " + e);
        }
    }

    @Nullable
    @VisibleForTesting
    static Map<String, String[]> getWhitelistedCompatModePackages(String setting) {
        if (TextUtils.isEmpty(setting)) {
            return null;
        }

        final ArrayMap<String, String[]> compatPackages = new ArrayMap<>();
        final SimpleStringSplitter splitter = new SimpleStringSplitter(COMPAT_PACKAGE_DELIMITER);
        splitter.setString(setting);
        while (splitter.hasNext()) {
            final String packageBlock = splitter.next();
            final int urlBlockIndex = packageBlock.indexOf(COMPAT_PACKAGE_URL_IDS_BLOCK_BEGIN);
            final String packageName;
            final List<String> urlBarIds;
            if (urlBlockIndex == -1) {
                packageName = packageBlock;
                urlBarIds = null;
            } else {
                if (packageBlock.charAt(packageBlock.length() - 1)
                        != COMPAT_PACKAGE_URL_IDS_BLOCK_END) {
                    Slog.w(TAG, "Ignoring entry '" + packageBlock + "' on '" + setting
                            + "'because it does not end on '" + COMPAT_PACKAGE_URL_IDS_BLOCK_END +
                            "'");
                    continue;
                }
                packageName = packageBlock.substring(0, urlBlockIndex);
                urlBarIds = new ArrayList<>();
                final String urlBarIdsBlock =
                        packageBlock.substring(urlBlockIndex + 1, packageBlock.length() - 1);
                if (sVerbose) {
                    Slog.v(TAG, "pkg:" + packageName + ": block:" + packageBlock + ": urls:"
                            + urlBarIds + ": block:" + urlBarIdsBlock + ":");
                }
                final SimpleStringSplitter splitter2 =
                        new SimpleStringSplitter(COMPAT_PACKAGE_URL_IDS_DELIMITER);
                splitter2.setString(urlBarIdsBlock);
                while (splitter2.hasNext()) {
                    final String urlBarId = splitter2.next();
                    urlBarIds.add(urlBarId);
                }
            }
            if (urlBarIds == null) {
                compatPackages.put(packageName, null);
            } else {
                final String[] urlBarIdsArray = new String[urlBarIds.size()];
                urlBarIds.toArray(urlBarIdsArray);
                compatPackages.put(packageName, urlBarIdsArray);
            }
        }
        return compatPackages;
    }

    /**
     * Gets the maximum number of partitions / fill requests.
     */
    public static int getPartitionMaxCount() {
        synchronized (sLock) {
            return sPartitionMaxCount;
        }
    }

    /**
     * Gets the maxium number of datasets visible in the UI.
     */
    public static int getVisibleDatasetsMaxCount() {
        synchronized (sLock) {
            return sVisibleDatasetsMaxCount;
        }
    }

    private final class LocalService extends AutofillManagerInternal {
        @Override
        public void onBackKeyPressed() {
            if (sDebug) Slog.d(TAG, "onBackKeyPressed()");
            mUi.hideAll(null);
            synchronized (mLock) {
                final AutofillManagerServiceImpl service =
                        getServiceForUserLocked(UserHandle.getCallingUserId());
                service.onBackKeyPressed();
            }
        }

        @Override
        public AutofillOptions getAutofillOptions(@NonNull String packageName,
                long versionCode, @UserIdInt int userId) {
            final int loggingLevel;
            if (verbose) {
                loggingLevel = AutofillManager.FLAG_ADD_CLIENT_VERBOSE
                        | AutofillManager.FLAG_ADD_CLIENT_DEBUG;
            } else if (debug) {
                loggingLevel = AutofillManager.FLAG_ADD_CLIENT_DEBUG;
            } else {
                loggingLevel = AutofillManager.NO_LOGGING;
            }
            final boolean compatModeEnabled = mAutofillCompatState.isCompatibilityModeRequested(
                    packageName, versionCode, userId);
            final AutofillOptions options = new AutofillOptions(loggingLevel, compatModeEnabled);
            mAugmentedAutofillState.injectAugmentedAutofillInfo(options, userId, packageName);
            return options;
        }

        @Override
        public boolean isAugmentedAutofillServiceForUser(int callingUid, int userId) {
            synchronized (mLock) {
                final AutofillManagerServiceImpl service = peekServiceForUserLocked(userId);
                if (service != null) {
                    return service.isAugmentedAutofillServiceForUserLocked(callingUid);
                }
            }
            return false;
        }
    }

    /**
     * Compatibility mode metadata per package.
     */
    static final class PackageCompatState {
        private final long maxVersionCode;
        private final String[] urlBarResourceIds;

        PackageCompatState(long maxVersionCode, String[] urlBarResourceIds) {
            this.maxVersionCode = maxVersionCode;
            this.urlBarResourceIds = urlBarResourceIds;
        }

        @Override
        public String toString() {
            return "maxVersionCode=" + maxVersionCode
                    + ", urlBarResourceIds=" + Arrays.toString(urlBarResourceIds);
        }
    }

    /**
     * Compatibility mode metadata associated with all services.
     *
     * <p>This object is defined here instead of on each {@link AutofillManagerServiceImpl} because
     * it cannot hold a lock on the main lock when
     * {@link AutofillCompatState#isCompatibilityModeRequested(String, long, int)} is called by
     * external services.
     */
    static final class AutofillCompatState {
        private final Object mLock = new Object();

        /**
         * Map of app->compat_state per user.
         */
        @GuardedBy("mLock")
        private SparseArray<ArrayMap<String, PackageCompatState>> mUserSpecs;

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

        @Nullable
        String[] getUrlBarResourceIds(@NonNull String packageName, @UserIdInt int userId) {
            synchronized (mLock) {
                if (mUserSpecs == null) {
                    return null;
                }
                final ArrayMap<String, PackageCompatState> userSpec = mUserSpecs.get(userId);
                if (userSpec == null) {
                    return null;
                }
                final PackageCompatState metadata = userSpec.get(packageName);
                if (metadata == null) {
                    return null;
                }
                return metadata.urlBarResourceIds;
            }
        }

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

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

        void reset(int userId) {
            synchronized (mLock) {
                if (mUserSpecs != null) {
                    mUserSpecs.delete(userId);
                    final int newSize = mUserSpecs.size();
                    if (newSize == 0) {
                        if (sVerbose) Slog.v(TAG, "reseting mUserSpecs");
                        mUserSpecs = null;
                    } else {
                        if (sVerbose) Slog.v(TAG, "mUserSpecs down to " + newSize);
                    }
                }
            }
        }

        private void dump(String prefix, PrintWriter pw) {
            synchronized (mLock) {
                if (mUserSpecs == null) {
                    pw.println("N/A");
                    return;
                }
                pw.println();
                final String prefix2 = prefix + "  ";
                for (int i = 0; i < mUserSpecs.size(); i++) {
                    final int user = mUserSpecs.keyAt(i);
                    pw.print(prefix);
                    pw.print("User: ");
                    pw.println(user);
                    final ArrayMap<String, PackageCompatState> perUser = mUserSpecs.valueAt(i);
                    for (int j = 0; j < perUser.size(); j++) {
                        final String packageName = perUser.keyAt(j);
                        final PackageCompatState state = perUser.valueAt(j);
                        pw.print(prefix2); pw.print(packageName); pw.print(": "); pw.println(state);
                    }
                }
            }
        }
    }

    /**
     * Augmented autofill metadata associated with all services.
     *
     * <p>This object is defined here instead of on each {@link AutofillManagerServiceImpl} because
     * it cannot hold a lock on the main lock when
     * {@link AugmentedAutofillState#injectAugmentedAutofillInfo(AutofillOptions, int, String)}
     * is called by external services.
     */
    static final class AugmentedAutofillState extends GlobalWhitelistState {

        @GuardedBy("mGlobalWhitelistStateLock")
        private final SparseArray<String> mServicePackages = new SparseArray<>();
        @GuardedBy("mGlobalWhitelistStateLock")
        private final SparseBooleanArray mTemporaryServices = new SparseBooleanArray();

        private void setServiceInfo(@UserIdInt int userId, @Nullable String serviceName,
                boolean isTemporary) {
            synchronized (mGlobalWhitelistStateLock) {
                if (isTemporary) {
                    mTemporaryServices.put(userId, true);
                } else {
                    mTemporaryServices.delete(userId);
                }
                if (serviceName != null) {
                    final ComponentName componentName =
                            ComponentName.unflattenFromString(serviceName);
                    if (componentName == null) {
                        Slog.w(TAG, "setServiceInfo(): invalid name: " + serviceName);
                        mServicePackages.remove(userId);
                    } else {
                        mServicePackages.put(userId, componentName.getPackageName());
                    }
                } else {
                    mServicePackages.remove(userId);
                }
            }
        }

        public void injectAugmentedAutofillInfo(@NonNull AutofillOptions options,
                @UserIdInt int userId, @NonNull String packageName) {
            synchronized (mGlobalWhitelistStateLock) {
                if (mWhitelisterHelpers == null) return;
                final WhitelistHelper helper = mWhitelisterHelpers.get(userId);
                if (helper != null) {
                    options.augmentedAutofillEnabled = helper.isWhitelisted(packageName);
                    options.whitelistedActivitiesForAugmentedAutofill = helper
                            .getWhitelistedComponents(packageName);
                }
            }
        }

        @Override
        public boolean isWhitelisted(@UserIdInt int userId, @NonNull ComponentName componentName) {
            synchronized (mGlobalWhitelistStateLock) {
                if (!super.isWhitelisted(userId, componentName)) return false;

                if (Build.IS_USER && mTemporaryServices.get(userId)) {
                    final String packageName = componentName.getPackageName();
                    if (!packageName.equals(mServicePackages.get(userId))) {
                        Slog.w(TAG, "Ignoring package " + packageName + " for augmented autofill "
                                + "while using temporary service " + mServicePackages.get(userId));
                        return false;
                    }
                }
            }
            return true;
        }

        @Override
        public void dump(@NonNull String prefix, @NonNull PrintWriter pw) {
            super.dump(prefix, pw);

            synchronized (mGlobalWhitelistStateLock) {
                if (mServicePackages.size() > 0) {
                    pw.print(prefix); pw.print("Service packages: "); pw.println(mServicePackages);
                }
                if (mTemporaryServices.size() > 0) {
                    pw.print(prefix); pw.print("Temp services: "); pw.println(mTemporaryServices);
                }
            }
        }
    }

    final class AutoFillManagerServiceStub extends IAutoFillManager.Stub {
        @Override
        public void addClient(IAutoFillManagerClient client, ComponentName componentName,
                int userId, IResultReceiver receiver) {
            int flags = 0;
            synchronized (mLock) {
                final int enabledFlags = getServiceForUserLocked(userId).addClientLocked(client,
                        componentName);
                if (enabledFlags != 0) {
                    flags |= enabledFlags;
                }
                if (sDebug) {
                    flags |= AutofillManager.FLAG_ADD_CLIENT_DEBUG;
                }
                if (sVerbose) {
                    flags |= AutofillManager.FLAG_ADD_CLIENT_VERBOSE;
                }
            }
            send(receiver, flags);
        }

        @Override
        public void removeClient(IAutoFillManagerClient client, int userId) {
            synchronized (mLock) {
                final AutofillManagerServiceImpl service = peekServiceForUserLocked(userId);
                if (service != null) {
                    service.removeClientLocked(client);
                } else if (sVerbose) {
                    Slog.v(TAG, "removeClient(): no service for " + userId);
                }
            }
        }

        @Override
        public void setAuthenticationResult(Bundle data, int sessionId, int authenticationId,
                int userId) {
            synchronized (mLock) {
                final AutofillManagerServiceImpl service = getServiceForUserLocked(userId);
                service.setAuthenticationResultLocked(data, sessionId, authenticationId,
                        getCallingUid());
            }
        }

        @Override
        public void setHasCallback(int sessionId, int userId, boolean hasIt) {
            synchronized (mLock) {
                final AutofillManagerServiceImpl service = getServiceForUserLocked(userId);
                service.setHasCallback(sessionId, getCallingUid(), hasIt);
            }
        }

        @Override
        public void startSession(IBinder activityToken, IBinder appCallback, AutofillId autofillId,
                Rect bounds, AutofillValue value, int userId, boolean hasCallback, int flags,
                ComponentName componentName, boolean compatMode, IResultReceiver receiver) {

            activityToken = Preconditions.checkNotNull(activityToken, "activityToken");
            appCallback = Preconditions.checkNotNull(appCallback, "appCallback");
            autofillId = Preconditions.checkNotNull(autofillId, "autoFillId");
            componentName = Preconditions.checkNotNull(componentName, "componentName");
            final String packageName = Preconditions.checkNotNull(componentName.getPackageName());

            Preconditions.checkArgument(userId == UserHandle.getUserId(getCallingUid()), "userId");

            try {
                getContext().getPackageManager().getPackageInfoAsUser(packageName, 0, userId);
            } catch (PackageManager.NameNotFoundException e) {
                throw new IllegalArgumentException(packageName + " is not a valid package", e);
            }

            // TODO(b/113281366): add a callback method on AM to be notified when a task is finished
            // so we can clean up sessions kept alive
            final int taskId = mAm.getTaskIdForActivity(activityToken, false);
            final long result;
            synchronized (mLock) {
                final AutofillManagerServiceImpl service = getServiceForUserLocked(userId);
                result = service.startSessionLocked(activityToken, taskId, getCallingUid(),
                        appCallback, autofillId, bounds, value, hasCallback, componentName,
                        compatMode, mAllowInstantService, flags);
            }
            final int sessionId = (int) result;
            final int resultFlags = (int) (result >> 32);
            if (resultFlags != 0) {
                send(receiver, sessionId, resultFlags);
            } else {
                send(receiver, sessionId);
            }
        }

        @Override
        public void getFillEventHistory(@NonNull IResultReceiver receiver) throws RemoteException {
            final int userId = UserHandle.getCallingUserId();

            FillEventHistory fillEventHistory = null;
            synchronized (mLock) {
                final AutofillManagerServiceImpl service = peekServiceForUserLocked(userId);
                if (service != null) {
                    fillEventHistory = service.getFillEventHistory(getCallingUid());
                } else if (sVerbose) {
                    Slog.v(TAG, "getFillEventHistory(): no service for " + userId);
                }
            }
            send(receiver, fillEventHistory);
        }

        @Override
        public void getUserData(@NonNull IResultReceiver receiver) throws RemoteException {
            final int userId = UserHandle.getCallingUserId();

            UserData userData = null;
            synchronized (mLock) {
                final AutofillManagerServiceImpl service = peekServiceForUserLocked(userId);
                if (service != null) {
                    userData = service.getUserData(getCallingUid());
                } else if (sVerbose) {
                    Slog.v(TAG, "getUserData(): no service for " + userId);
                }
            }
            send(receiver, userData);
        }

        @Override
        public void getUserDataId(@NonNull IResultReceiver receiver) throws RemoteException {
            final int userId = UserHandle.getCallingUserId();
            UserData userData = null;

            synchronized (mLock) {
                final AutofillManagerServiceImpl service = peekServiceForUserLocked(userId);
                if (service != null) {
                    userData = service.getUserData(getCallingUid());
                } else if (sVerbose) {
                    Slog.v(TAG, "getUserDataId(): no service for " + userId);
                }
            }
            final String userDataId = userData == null ? null : userData.getId();
            send(receiver, userDataId);
        }

        @Override
        public void setUserData(UserData userData) throws RemoteException {
            final int userId = UserHandle.getCallingUserId();

            synchronized (mLock) {
                final AutofillManagerServiceImpl service = peekServiceForUserLocked(userId);
                if (service != null) {
                    service.setUserData(getCallingUid(), userData);
                } else if (sVerbose) {
                    Slog.v(TAG, "setUserData(): no service for " + userId);
                }
            }
        }

        @Override
        public void isFieldClassificationEnabled(@NonNull IResultReceiver receiver)
                throws RemoteException {
            final int userId = UserHandle.getCallingUserId();
            boolean enabled = false;

            synchronized (mLock) {
                final AutofillManagerServiceImpl service = peekServiceForUserLocked(userId);
                if (service != null) {
                    enabled = service.isFieldClassificationEnabled(getCallingUid());
                } else if (sVerbose) {
                    Slog.v(TAG, "isFieldClassificationEnabled(): no service for " + userId);
                }
            }
            send(receiver, enabled);
        }

        @Override
        public void getDefaultFieldClassificationAlgorithm(@NonNull IResultReceiver receiver)
                throws RemoteException {
            final int userId = UserHandle.getCallingUserId();
            String algorithm = null;

            synchronized (mLock) {
                final AutofillManagerServiceImpl service = peekServiceForUserLocked(userId);
                if (service != null) {
                    algorithm = service.getDefaultFieldClassificationAlgorithm(getCallingUid());
                } else {
                    if (sVerbose) {
                        Slog.v(TAG, "getDefaultFcAlgorithm(): no service for " + userId);
                    }
               }
            }
            send(receiver, algorithm);
        }

        @Override
        public void setAugmentedAutofillWhitelist(@Nullable List<String> packages,
                @Nullable List<ComponentName> activities, @NonNull IResultReceiver receiver)
                throws RemoteException {
            final int userId = UserHandle.getCallingUserId();

            boolean ok;
            synchronized (mLock) {
                final AutofillManagerServiceImpl service = peekServiceForUserLocked(userId);
                if (service != null) {
                    ok = service.setAugmentedAutofillWhitelistLocked(packages, activities,
                            getCallingUid());
                } else {
                    if (sVerbose) {
                        Slog.v(TAG, "setAugmentedAutofillWhitelist(): no service for " + userId);
                    }
                    ok = false;
                }
            }
            send(receiver,
                    ok ? AutofillManager.RESULT_OK : AutofillManager.RESULT_CODE_NOT_SERVICE);
        }

        @Override
        public void getAvailableFieldClassificationAlgorithms(@NonNull IResultReceiver receiver)
                throws RemoteException {
            final int userId = UserHandle.getCallingUserId();
            String[] algorithms = null;

            synchronized (mLock) {
                final AutofillManagerServiceImpl service = peekServiceForUserLocked(userId);
                if (service != null) {
                    algorithms = service.getAvailableFieldClassificationAlgorithms(getCallingUid());
                } else {
                    if (sVerbose) {
                        Slog.v(TAG, "getAvailableFcAlgorithms(): no service for " + userId);
                    }
                }
            }
            send(receiver, algorithms);
        }

        @Override
        public void getAutofillServiceComponentName(@NonNull IResultReceiver receiver)
                throws RemoteException {
            final int userId = UserHandle.getCallingUserId();

            ComponentName componentName = null;
            synchronized (mLock) {
                final AutofillManagerServiceImpl service = peekServiceForUserLocked(userId);
                if (service != null) {
                    componentName = service.getServiceComponentName();
                } else if (sVerbose) {
                    Slog.v(TAG, "getAutofillServiceComponentName(): no service for " + userId);
                }
            }
            send(receiver, componentName);
        }

        @Override
        public void restoreSession(int sessionId, @NonNull IBinder activityToken,
                @NonNull IBinder appCallback, @NonNull IResultReceiver receiver)
                throws RemoteException {
            final int userId = UserHandle.getCallingUserId();
            activityToken = Preconditions.checkNotNull(activityToken, "activityToken");
            appCallback = Preconditions.checkNotNull(appCallback, "appCallback");

            boolean restored = false;
            synchronized (mLock) {
                final AutofillManagerServiceImpl service = peekServiceForUserLocked(userId);
                if (service != null) {
                    restored = service.restoreSession(sessionId, getCallingUid(), activityToken,
                            appCallback);
                } else if (sVerbose) {
                    Slog.v(TAG, "restoreSession(): no service for " + userId);
                }
            }
            send(receiver, restored);
        }

        @Override
        public void updateSession(int sessionId, AutofillId autoFillId, Rect bounds,
                AutofillValue value, int action, int flags, int userId) {
            synchronized (mLock) {
                final AutofillManagerServiceImpl service = peekServiceForUserLocked(userId);
                if (service != null) {
                    service.updateSessionLocked(sessionId, getCallingUid(), autoFillId, bounds,
                            value, action, flags);
                } else if (sVerbose) {
                    Slog.v(TAG, "updateSession(): no service for " + userId);
                }
            }
        }

        @Override
        public void setAutofillFailure(int sessionId, @NonNull List<AutofillId> ids, int userId) {
            synchronized (mLock) {
                final AutofillManagerServiceImpl service = peekServiceForUserLocked(userId);
                if (service != null) {
                    service.setAutofillFailureLocked(sessionId, getCallingUid(), ids);
                } else if (sVerbose) {
                    Slog.v(TAG, "setAutofillFailure(): no service for " + userId);
                }
            }
        }

        @Override
        public void finishSession(int sessionId, int userId) {
            synchronized (mLock) {
                final AutofillManagerServiceImpl service = peekServiceForUserLocked(userId);
                if (service != null) {
                    service.finishSessionLocked(sessionId, getCallingUid());
                } else if (sVerbose) {
                    Slog.v(TAG, "finishSession(): no service for " + userId);
                }
            }
        }

        @Override
        public void cancelSession(int sessionId, int userId) {
            synchronized (mLock) {
                final AutofillManagerServiceImpl service = peekServiceForUserLocked(userId);
                if (service != null) {
                    service.cancelSessionLocked(sessionId, getCallingUid());
                } else if (sVerbose) {
                    Slog.v(TAG, "cancelSession(): no service for " + userId);
                }
            }
        }

        @Override
        public void disableOwnedAutofillServices(int userId) {
            synchronized (mLock) {
                final AutofillManagerServiceImpl service = peekServiceForUserLocked(userId);
                if (service != null) {
                    service.disableOwnedAutofillServicesLocked(Binder.getCallingUid());
                } else if (sVerbose) {
                    Slog.v(TAG, "cancelSession(): no service for " + userId);
                }
            }
        }

        @Override
        public void isServiceSupported(int userId, @NonNull IResultReceiver receiver) {
            boolean supported = false;
            synchronized (mLock) {
                supported = !isDisabledLocked(userId);
            }
            send(receiver, supported);
        }

        @Override
        public void isServiceEnabled(int userId, @NonNull String packageName,
                @NonNull IResultReceiver receiver) {
            boolean enabled = false;
            synchronized (mLock) {
                final AutofillManagerServiceImpl service = peekServiceForUserLocked(userId);
                if (service != null) {
                    enabled = Objects.equals(packageName, service.getServicePackageName());
                } else if (sVerbose) {
                    Slog.v(TAG, "isServiceEnabled(): no service for " + userId);
                }
            }
            send(receiver, enabled);
        }

        @Override
        public void onPendingSaveUi(int operation, IBinder token) {
            Preconditions.checkNotNull(token, "token");
            Preconditions.checkArgument(operation == AutofillManager.PENDING_UI_OPERATION_CANCEL
                    || operation == AutofillManager.PENDING_UI_OPERATION_RESTORE,
                    "invalid operation: %d", operation);
            synchronized (mLock) {
                final AutofillManagerServiceImpl service = peekServiceForUserLocked(
                        UserHandle.getCallingUserId());
                if (service != null) {
                    service.onPendingSaveUi(operation, token);
                }
            }
        }

        @Override
        public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
            if (!DumpUtils.checkDumpPermission(getContext(), TAG, pw)) return;

            boolean showHistory = true;
            boolean uiOnly = false;
            if (args != null) {
                for (String arg : args) {
                    switch(arg) {
                        case "--no-history":
                            showHistory = false;
                            break;
                        case "--ui-only":
                            uiOnly = true;
                            break;
                        case "--help":
                            pw.println("Usage: dumpsys autofill [--ui-only|--no-history]");
                            return;
                        default:
                            Slog.w(TAG, "Ignoring invalid dump arg: " + arg);
                    }
                }
            }

            if (uiOnly) {
                mUi.dump(pw);
                return;
            }

            final String prefix = "  ";
            boolean realDebug = sDebug;
            boolean realVerbose = sVerbose;
            try {
                sDebug = sVerbose = true;
                synchronized (mLock) {
                    pw.print("sDebug: "); pw.print(realDebug);
                    pw.print(" sVerbose: "); pw.println(realVerbose);
                    // Dump per-user services
                    dumpLocked("", pw);
                    mAugmentedAutofillResolver.dumpShort(pw); pw.println();
                    pw.print("Max partitions per session: "); pw.println(sPartitionMaxCount);
                    pw.print("Max visible datasets: "); pw.println(sVisibleDatasetsMaxCount);
                    if (sFullScreenMode != null) {
                        pw.print("Overridden full-screen mode: "); pw.println(sFullScreenMode);
                    }
                    pw.println("User data constraints: "); UserData.dumpConstraints(prefix, pw);
                    mUi.dump(pw);
                    pw.print("Autofill Compat State: ");
                    mAutofillCompatState.dump(prefix, pw);
                    pw.print("from settings: ");
                    pw.println(getWhitelistedCompatModePackagesFromSettings());
                    if (mSupportedSmartSuggestionModes != 0) {
                        pw.print("Smart Suggestion modes: ");
                        pw.println(getSmartSuggestionModeToString(mSupportedSmartSuggestionModes));
                    }
                    pw.print("Augmented Service Idle Unbind Timeout: ");
                    pw.println(mAugmentedServiceIdleUnbindTimeoutMs);
                    pw.print("Augmented Service Request Timeout: ");
                    pw.println(mAugmentedServiceRequestTimeoutMs);
                    if (showHistory) {
                        pw.println(); pw.println("Requests history:"); pw.println();
                        mRequestsHistory.reverseDump(fd, pw, args);
                        pw.println(); pw.println("UI latency history:"); pw.println();
                        mUiLatencyHistory.reverseDump(fd, pw, args);
                        pw.println(); pw.println("WTF history:"); pw.println();
                        mWtfHistory.reverseDump(fd, pw, args);
                    }
                    pw.println("Augmented Autofill State: ");
                    mAugmentedAutofillState.dump(prefix, pw);
                }
            } finally {
                sDebug = realDebug;
                sVerbose = realVerbose;
            }
        }

        @Override
        public void onShellCommand(FileDescriptor in, FileDescriptor out, FileDescriptor err,
                String[] args, ShellCallback callback, ResultReceiver resultReceiver) {
            new AutofillManagerServiceShellCommand(AutofillManagerService.this).exec(
                    this, in, out, err, args, callback, resultReceiver);
        }
    }
}
