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

import static android.content.Context.DEVICE_ID_DEFAULT;
import static android.content.Context.DEVICE_ID_INVALID;

import static com.android.internal.util.FunctionalUtils.ignoreRemoteException;

import android.accessibilityservice.AccessibilityServiceInfo;
import android.accessibilityservice.AccessibilityTrace;
import android.accessibilityservice.IAccessibilityServiceClient;
import android.annotation.NonNull;
import android.companion.virtual.VirtualDevice;
import android.companion.virtual.VirtualDeviceManager;
import android.content.ComponentName;
import android.content.Context;
import android.hardware.display.DisplayManager;
import android.os.Build;
import android.os.Handler;
import android.os.IBinder;
import android.os.RemoteCallbackList;
import android.os.RemoteException;
import android.util.ArraySet;
import android.util.IntArray;
import android.util.Log;
import android.util.Slog;
import android.util.SparseArray;
import android.util.SparseIntArray;
import android.view.Display;
import android.view.accessibility.AccessibilityEvent;
import android.view.accessibility.AccessibilityManager;
import android.view.accessibility.IAccessibilityManagerClient;

import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.IntPair;
import com.android.server.LocalServices;
import com.android.server.companion.virtual.VirtualDeviceManagerInternal;
import com.android.server.wm.WindowManagerInternal;

import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Set;
import java.util.function.Consumer;

/**
 * Manages proxy connections.
 *
 * Currently this acts similarly to UiAutomationManager as a global manager, though ideally each
 * proxy connection will belong to a separate user state.
 *
 * TODO(241117292): Remove or cut down during simultaneous user refactoring.
 */
public class ProxyManager {
    private static final String LOG_TAG = "ProxyManager";
    private static final boolean DEBUG = Log.isLoggable(LOG_TAG, Log.DEBUG) && Build.IS_DEBUGGABLE;

    // Names used to populate ComponentName and ResolveInfo in connection.mA11yServiceInfo and in
    // the infos of connection.setInstalledAndEnabledServices
    static final String PROXY_COMPONENT_PACKAGE_NAME = "ProxyPackage";
    static final String PROXY_COMPONENT_CLASS_NAME = "ProxyClass";

    // AMS#mLock
    private final Object mLock;

    private final Context mContext;
    private final Handler mMainHandler;

    private final UiAutomationManager mUiAutomationManager;

    // Device Id -> state. Used to determine if we should notify AccessibilityManager clients of
    // updates.
    private final SparseIntArray mLastStates = new SparseIntArray();

    // Each display id entry in a SparseArray represents a proxy a11y user.
    private final SparseArray<ProxyAccessibilityServiceConnection> mProxyA11yServiceConnections =
            new SparseArray<>();

    private final AccessibilityWindowManager mA11yWindowManager;

    private AccessibilityInputFilter mA11yInputFilter;

    private VirtualDeviceManagerInternal mLocalVdm;

    private final SystemSupport mSystemSupport;

    private VirtualDeviceManagerInternal.AppsOnVirtualDeviceListener
            mAppsOnVirtualDeviceListener;

    private VirtualDeviceManager.VirtualDeviceListener mVirtualDeviceListener;

    /**
     * Callbacks into AccessibilityManagerService.
     */
    public interface SystemSupport {
        /**
         * Removes the device id from tracking.
         */
        void removeDeviceIdLocked(int deviceId);

        /**
         * Updates the windows tracking for the current user.
         */
        void updateWindowsForAccessibilityCallbackLocked();

        /**
         * Clears all caches.
         */
        void notifyClearAccessibilityCacheLocked();

        /**
         * Gets the clients for all users.
         */
        @NonNull
        RemoteCallbackList<IAccessibilityManagerClient> getGlobalClientsLocked();

        /**
         * Gets the clients for the current user.
         */
        @NonNull
        RemoteCallbackList<IAccessibilityManagerClient> getCurrentUserClientsLocked();
    }

    public ProxyManager(Object lock, AccessibilityWindowManager awm,
            Context context, Handler mainHandler, UiAutomationManager uiAutomationManager,
            SystemSupport systemSupport) {
        mLock = lock;
        mA11yWindowManager = awm;
        mContext = context;
        mMainHandler = mainHandler;
        mUiAutomationManager = uiAutomationManager;
        mSystemSupport = systemSupport;
        mLocalVdm = LocalServices.getService(VirtualDeviceManagerInternal.class);
    }

    /**
     * Creates the service connection.
     */
    public void registerProxy(IAccessibilityServiceClient client, int displayId,
            int id, AccessibilitySecurityPolicy securityPolicy,
            AbstractAccessibilityServiceConnection.SystemSupport systemSupport,
            AccessibilityTrace trace,
            WindowManagerInternal windowManagerInternal) throws RemoteException {
        if (DEBUG) {
            Slog.v(LOG_TAG, "Register proxy for display id: " + displayId);
        }

        VirtualDeviceManager vdm = mContext.getSystemService(VirtualDeviceManager.class);
        if (vdm == null) {
            return;
        }
        final int deviceId = vdm.getDeviceIdForDisplayId(displayId);

        // Set a default AccessibilityServiceInfo that is used before the proxy's info is
        // populated. A proxy has the touch exploration and window capabilities.
        AccessibilityServiceInfo info = new AccessibilityServiceInfo();
        info.setCapabilities(AccessibilityServiceInfo.CAPABILITY_CAN_REQUEST_TOUCH_EXPLORATION
                | AccessibilityServiceInfo.CAPABILITY_CAN_RETRIEVE_WINDOW_CONTENT);
        final String componentClassDisplayName = PROXY_COMPONENT_CLASS_NAME + displayId;
        info.setComponentName(new ComponentName(PROXY_COMPONENT_PACKAGE_NAME,
                componentClassDisplayName));
        ProxyAccessibilityServiceConnection connection =
                new ProxyAccessibilityServiceConnection(mContext, info.getComponentName(), info,
                        id, mMainHandler, mLock, securityPolicy, systemSupport, trace,
                        windowManagerInternal,
                        mA11yWindowManager, displayId, deviceId);

        synchronized (mLock) {
            mProxyA11yServiceConnections.put(displayId, connection);
            if (Flags.proxyUseAppsOnVirtualDeviceListener()) {
                if (mAppsOnVirtualDeviceListener == null) {
                    mAppsOnVirtualDeviceListener = allRunningUids ->
                            notifyProxyOfRunningAppsChange(allRunningUids);
                    final VirtualDeviceManagerInternal localVdm = getLocalVdm();
                    if (localVdm != null) {
                        localVdm.registerAppsOnVirtualDeviceListener(mAppsOnVirtualDeviceListener);
                    }
                }
            }
            if (mProxyA11yServiceConnections.size() == 1) {
                registerVirtualDeviceListener();
            }
        }

        // If the client dies, make sure to remove the connection.
        IBinder.DeathRecipient deathRecipient =
                new IBinder.DeathRecipient() {
                    @Override
                    public void binderDied() {
                        client.asBinder().unlinkToDeath(this, 0);
                        clearConnectionAndUpdateState(displayId);
                    }
                };
        client.asBinder().linkToDeath(deathRecipient, 0);

        mMainHandler.post(() -> {
            if (mA11yInputFilter != null) {
                mA11yInputFilter.disableFeaturesForDisplayIfInstalled(displayId);
            }
        });
        connection.initializeServiceInterface(client);
    }

    private void registerVirtualDeviceListener() {
        VirtualDeviceManager vdm = mContext.getSystemService(VirtualDeviceManager.class);
        if (vdm == null || !android.companion.virtual.flags.Flags.vdmPublicApis()) {
            return;
        }
        if (mVirtualDeviceListener == null) {
            mVirtualDeviceListener = new VirtualDeviceManager.VirtualDeviceListener() {
                @Override
                public void onVirtualDeviceClosed(int deviceId) {
                    clearConnections(deviceId);
                }
            };
        }

        vdm.registerVirtualDeviceListener(mContext.getMainExecutor(), mVirtualDeviceListener);
    }

    private void unregisterVirtualDeviceListener() {
        VirtualDeviceManager vdm = mContext.getSystemService(VirtualDeviceManager.class);
        if (vdm == null || !android.companion.virtual.flags.Flags.vdmPublicApis()) {
            return;
        }
        vdm.unregisterVirtualDeviceListener(mVirtualDeviceListener);
    }

    /**
     * Unregister the proxy based on display id.
     */
    public boolean unregisterProxy(int displayId) {
        return clearConnectionAndUpdateState(displayId);
    }

    /**
     * Clears all proxy connections belonging to {@code deviceId}.
     */
    public void clearConnections(int deviceId) {
        final IntArray displaysToClear = new IntArray();
        synchronized (mLock) {
            for (int i = 0; i < mProxyA11yServiceConnections.size(); i++) {
                final ProxyAccessibilityServiceConnection proxy =
                        mProxyA11yServiceConnections.valueAt(i);
                if (proxy != null && proxy.getDeviceId() == deviceId) {
                    displaysToClear.add(proxy.getDisplayId());
                }
            }
        }
        for (int i = 0; i < displaysToClear.size(); i++) {
            clearConnectionAndUpdateState(displaysToClear.get(i));
        }
    }

    /**
     * Removes the system connection of an AccessibilityDisplayProxy.
     *
     * This will:
     * <ul>
     * <li> Reset Clients to belong to the default device if appropriate.
     * <li> Stop identifying the display's a11y windows as belonging to a proxy.
     * <li> Re-enable any input filters for the display.
     * <li> Notify AMS that a proxy has been removed.
     * </ul>
     *
     * @param displayId the display id of the connection to be cleared.
     * @return whether the proxy was removed.
     */
    private boolean clearConnectionAndUpdateState(int displayId) {
        boolean removedFromConnections = false;
        int deviceId = DEVICE_ID_INVALID;
        synchronized (mLock) {
            if (mProxyA11yServiceConnections.contains(displayId)) {
                deviceId = mProxyA11yServiceConnections.get(displayId).getDeviceId();
                mProxyA11yServiceConnections.remove(displayId);
                removedFromConnections = true;
                if (mProxyA11yServiceConnections.size() == 0) {
                    unregisterVirtualDeviceListener();
                }
            }
        }

        if (removedFromConnections) {
            updateStateForRemovedDisplay(displayId, deviceId);
        }

        if (DEBUG) {
            Slog.v(LOG_TAG, "Unregistered proxy for display id " + displayId + ": "
                    + removedFromConnections);
        }
        return removedFromConnections;
    }

    /**
     * When the connection is removed from tracking in ProxyManager, propagate changes to other a11y
     * system components like the input filter and IAccessibilityManagerClients.
     */
    private void updateStateForRemovedDisplay(int displayId, int deviceId) {
        mA11yWindowManager.stopTrackingDisplayProxy(displayId);
        // A11yInputFilter isn't thread-safe, so post on the system thread.
        mMainHandler.post(
                () -> {
                    if (mA11yInputFilter != null) {
                        final DisplayManager displayManager = (DisplayManager)
                                mContext.getSystemService(Context.DISPLAY_SERVICE);
                        final Display proxyDisplay = displayManager.getDisplay(displayId);
                        if (proxyDisplay != null) {
                            // A11yInputFilter isn't thread-safe, so post on the system thread.
                            mA11yInputFilter.enableFeaturesForDisplayIfInstalled(proxyDisplay);
                        }
                    }
                });
        // If there isn't an existing proxy for the device id, reset app clients. Resetting
        // will usually happen, since in most cases there will only be one proxy for a
        // device.
        if (!isProxyedDeviceId(deviceId)) {
            synchronized (mLock) {
                if (Flags.proxyUseAppsOnVirtualDeviceListener()) {
                    if (mProxyA11yServiceConnections.size() == 0) {
                        final VirtualDeviceManagerInternal localVdm = getLocalVdm();
                        if (localVdm != null && mAppsOnVirtualDeviceListener != null) {
                            localVdm.unregisterAppsOnVirtualDeviceListener(
                                    mAppsOnVirtualDeviceListener);
                            mAppsOnVirtualDeviceListener = null;
                        }
                    }
                }
                mSystemSupport.removeDeviceIdLocked(deviceId);
                mLastStates.delete(deviceId);
            }
        } else {
            // Update with the states of the remaining proxies.
            onProxyChanged(deviceId);
        }
    }

    /**
     * Returns {@code true} if {@code displayId} is being proxy-ed.
     */
    public boolean isProxyedDisplay(int displayId) {
        synchronized (mLock) {
            final boolean tracked = mProxyA11yServiceConnections.contains(displayId);
            if (DEBUG) {
                Slog.v(LOG_TAG, "Tracking proxy display " + displayId + " : " + tracked);
            }
            return tracked;
        }
    }

    /**
     * Returns {@code true} if {@code deviceId} is being proxy-ed.
     */
    public boolean isProxyedDeviceId(int deviceId) {
        if (deviceId == DEVICE_ID_DEFAULT || deviceId == DEVICE_ID_INVALID) {
            return false;
        }
        boolean isTrackingDeviceId;
        synchronized (mLock) {
            isTrackingDeviceId = getFirstProxyForDeviceIdLocked(deviceId) != null;
        }
        if (DEBUG) {
            Slog.v(LOG_TAG, "Tracking device " + deviceId + " : " + isTrackingDeviceId);
        }
        return isTrackingDeviceId;
    }

    /** Returns true if the display belongs to one of the caller's virtual devices. */
    public boolean displayBelongsToCaller(int callingUid, int proxyDisplayId) {
        final VirtualDeviceManager vdm = mContext.getSystemService(VirtualDeviceManager.class);
        final VirtualDeviceManagerInternal localVdm = getLocalVdm();
        if (vdm == null || localVdm == null) {
            return false;
        }
        final List<VirtualDevice> virtualDevices = vdm.getVirtualDevices();
        for (VirtualDevice device : virtualDevices) {
            if (localVdm.getDisplayIdsForDevice(device.getDeviceId()).contains(proxyDisplayId)) {
                final int ownerUid = localVdm.getDeviceOwnerUid(device.getDeviceId());
                if (callingUid == ownerUid) {
                    return true;
                }
            }
        }
        return false;
    }

    /**
     * Sends AccessibilityEvents to a proxy given the event's displayId.
     */
    public void sendAccessibilityEventLocked(AccessibilityEvent event) {
        final ProxyAccessibilityServiceConnection proxy =
                mProxyA11yServiceConnections.get(event.getDisplayId());
        if (proxy != null) {
            if (DEBUG) {
                Slog.v(LOG_TAG, "Send proxy event " + event + " for display id "
                        + event.getDisplayId());
            }
            proxy.notifyAccessibilityEvent(event);
        }
    }

    /**
     * Returns {@code true} if any proxy can retrieve windows.
     * TODO(b/250929565): Retrieve per connection/user state.
     */
    public boolean canRetrieveInteractiveWindowsLocked() {
        boolean observingWindows = false;
        for (int i = 0; i < mProxyA11yServiceConnections.size(); i++) {
            final ProxyAccessibilityServiceConnection proxy =
                    mProxyA11yServiceConnections.valueAt(i);
            if (proxy.mRetrieveInteractiveWindows) {
                observingWindows = true;
                break;
            }
        }
        if (DEBUG) {
            Slog.v(LOG_TAG, "At least one proxy can retrieve windows: " + observingWindows);
        }
        return observingWindows;
    }

    /**
     * If there is at least one proxy, accessibility is enabled.
     */
    public int getStateLocked(int deviceId) {
        int clientState = 0;
        final boolean uiAutomationCanIntrospect = mUiAutomationManager.canIntrospect();
        if (uiAutomationCanIntrospect) {
            clientState |= AccessibilityManager.STATE_FLAG_ACCESSIBILITY_ENABLED;
        }
        for (int i = 0; i < mProxyA11yServiceConnections.size(); i++) {
            final ProxyAccessibilityServiceConnection proxy =
                    mProxyA11yServiceConnections.valueAt(i);
            if (proxy != null && proxy.getDeviceId() == deviceId) {
                // Combine proxy states.
                clientState |= getStateForDisplayIdLocked(proxy);
            }
        }

        if (DEBUG) {
            Slog.v(LOG_TAG, "For device id " + deviceId + " a11y is enabled: "
                    + ((clientState & AccessibilityManager.STATE_FLAG_ACCESSIBILITY_ENABLED) != 0));
            Slog.v(LOG_TAG, "For device id " + deviceId + " touch exploration is enabled: "
                    + ((clientState & AccessibilityManager.STATE_FLAG_TOUCH_EXPLORATION_ENABLED)
                            != 0));
        }
        return clientState;
    }

    /**
     * If there is at least one proxy, accessibility is enabled.
     */
    private int getStateForDisplayIdLocked(ProxyAccessibilityServiceConnection proxy) {
        int clientState = 0;
        if (proxy != null) {
            clientState |= AccessibilityManager.STATE_FLAG_ACCESSIBILITY_ENABLED;
            if (proxy.mRequestTouchExplorationMode) {
                clientState |= AccessibilityManager.STATE_FLAG_TOUCH_EXPLORATION_ENABLED;
            }
        }

        if (DEBUG) {
            Slog.v(LOG_TAG, "Accessibility is enabled for all proxies: "
                    + ((clientState & AccessibilityManager.STATE_FLAG_ACCESSIBILITY_ENABLED) != 0));
            Slog.v(LOG_TAG, "Touch exploration is enabled for all proxies: "
                    + ((clientState & AccessibilityManager.STATE_FLAG_TOUCH_EXPLORATION_ENABLED)
                            != 0));
        }
        return clientState;
    }

    /**
     * Gets the last state for a device.
     */
    private int getLastSentStateLocked(int deviceId) {
        return mLastStates.get(deviceId, 0);
    }

    /**
     * Sets the last state for a device.
     */
    private void setLastStateLocked(int deviceId, int proxyState) {
        mLastStates.put(deviceId, proxyState);
    }

    /**
     * Updates the relevant event types of the app clients that are shown on a display owned by the
     * specified device.
     *
     * A client belongs to a device id, so event types (and other state) is determined by the device
     * id. In most cases, a device owns a single display. But if multiple displays may belong to one
     * Virtual Device, the app clients will get the aggregated event types for all proxy-ed displays
     * belonging to a VirtualDevice.
     */
    private void updateRelevantEventTypesLocked(int deviceId) {
        if (!isProxyedDeviceId(deviceId)) {
            return;
        }
        mMainHandler.post(() -> {
            synchronized (mLock) {
                broadcastToClientsLocked(ignoreRemoteException(client -> {
                    int relevantEventTypes;
                    if (client.mDeviceId == deviceId) {
                        relevantEventTypes = computeRelevantEventTypesLocked(client);
                        if (client.mLastSentRelevantEventTypes != relevantEventTypes) {
                            client.mLastSentRelevantEventTypes = relevantEventTypes;
                            client.mCallback.setRelevantEventTypes(relevantEventTypes);
                        }
                    }
                }));
            }
        });
    }

    /**
     * Returns the relevant event types for a Client.
     */
    public int computeRelevantEventTypesLocked(AccessibilityManagerService.Client client) {
        int relevantEventTypes = 0;
        for (int i = 0; i < mProxyA11yServiceConnections.size(); i++) {
            final ProxyAccessibilityServiceConnection proxy =
                    mProxyA11yServiceConnections.valueAt(i);
            if (proxy != null && proxy.getDeviceId() == client.mDeviceId) {
                relevantEventTypes |= proxy.getRelevantEventTypes();
                relevantEventTypes |= AccessibilityManagerService.isClientInPackageAllowlist(
                        mUiAutomationManager.getServiceInfo(), client)
                        ? mUiAutomationManager.getRelevantEventTypes()
                        : 0;
            }
        }
        if (DEBUG) {
            Slog.v(LOG_TAG, "Relevant event types for device id " + client.mDeviceId
                    + ": " + AccessibilityEvent.eventTypeToString(relevantEventTypes));
        }
        return relevantEventTypes;
    }

    /**
     * Adds the service interfaces to a list.
     * @param interfaces the list to add to.
     * @param deviceId the device id of the interested app client.
     */
    public void addServiceInterfacesLocked(@NonNull List<IAccessibilityServiceClient> interfaces,
            int deviceId) {
        for (int i = 0; i < mProxyA11yServiceConnections.size(); i++) {
            final ProxyAccessibilityServiceConnection proxy =
                    mProxyA11yServiceConnections.valueAt(i);
            if (proxy != null && proxy.getDeviceId() == deviceId) {
                final IBinder proxyBinder = proxy.mService;
                final IAccessibilityServiceClient proxyInterface = proxy.mServiceInterface;
                if ((proxyBinder != null) && (proxyInterface != null)) {
                    interfaces.add(proxyInterface);
                }
            }
        }
    }

    /**
     * Gets the list of installed and enabled services for a device id.
     *
     * Note: Multiple display proxies may belong to the same device.
     */
    public List<AccessibilityServiceInfo> getInstalledAndEnabledServiceInfosLocked(int feedbackType,
            int deviceId) {
        List<AccessibilityServiceInfo> serviceInfos = new ArrayList<>();
        for (int i = 0; i < mProxyA11yServiceConnections.size(); i++) {
            final ProxyAccessibilityServiceConnection proxy =
                    mProxyA11yServiceConnections.valueAt(i);
            if (proxy != null && proxy.getDeviceId() == deviceId) {
                // Return all proxy infos for ALL mask.
                if (feedbackType == AccessibilityServiceInfo.FEEDBACK_ALL_MASK) {
                    serviceInfos.addAll(proxy.getInstalledAndEnabledServices());
                } else if ((proxy.mFeedbackType & feedbackType) != 0) {
                    List<AccessibilityServiceInfo> proxyInfos =
                            proxy.getInstalledAndEnabledServices();
                    // Iterate through each info in the proxy.
                    for (AccessibilityServiceInfo info : proxyInfos) {
                        if ((info.feedbackType & feedbackType) != 0) {
                            serviceInfos.add(info);
                        }
                    }
                }
            }
        }
        return serviceInfos;
    }

    /**
     * Handles proxy changes.
     *
     * <p>
     * Changes include if the proxy is unregistered, its service info list has
     * changed, or its focus appearance has changed.
     * <p>
     * Some responses may include updating app clients. A client belongs to a device id, so state is
     * determined by the device id. In most cases, a device owns a single display. But if multiple
     * displays belong to one Virtual Device, the app clients will get a difference in
     * behavior depending on what is being updated.
     *
     * The following state methods are updated for AccessibilityManager clients belonging to a
     * proxied device:
     * <ul>
     * <li> A11yManager#setRelevantEventTypes - The combined event types of all proxies belonging to
     * a device id.
     * <li> A11yManager#setState - The combined states of all proxies belonging to a device id.
     * <li> A11yManager#notifyServicesStateChanged(timeout) - The highest of all proxies belonging
     * to a device id.
     * <li> A11yManager#setFocusAppearance - The appearance of the most recently updated display id
     * belonging to the device.
     * </ul>
     * This is similar to onUserStateChangeLocked and onClientChangeLocked, but does not require an
     * A11yUserState and only checks proxy-relevant settings.
     */
    private void onProxyChanged(int deviceId, boolean forceUpdate) {
        if (DEBUG) {
            Slog.v(LOG_TAG, "onProxyChanged called for deviceId: " + deviceId);
        }
        //The following state updates are excluded:
        //  - Input-related state
        //  - Primary-device / hardware-specific state
        synchronized (mLock) {
            // A proxy may be registered after the client has been initialized in #addClient.
            // For example, a user does not turn on accessibility until after the app has launched.
            // Or the process was started with a default id context and should shift to a device.
            // Update device ids of the clients if necessary.
            updateDeviceIdsIfNeededLocked(deviceId);
            // Start tracking of all displays if necessary.
            mSystemSupport.updateWindowsForAccessibilityCallbackLocked();
            // Calls A11yManager#setRelevantEventTypes (test these)
            updateRelevantEventTypesLocked(deviceId);
            // Calls A11yManager#setState
            scheduleUpdateProxyClientsIfNeededLocked(deviceId, forceUpdate);
            //Calls A11yManager#notifyServicesStateChanged(timeout)
            scheduleNotifyProxyClientsOfServicesStateChangeLocked(deviceId);
            // Calls A11yManager#setFocusAppearance
            updateFocusAppearanceLocked(deviceId);
            mSystemSupport.notifyClearAccessibilityCacheLocked();
        }
    }

    /**
     * Handles proxy changes, but does not force an update of app clients.
     */
    public void onProxyChanged(int deviceId) {
        onProxyChanged(deviceId, false);
    }

    /**
     * Updates the states of the app AccessibilityManagers.
     */
    private void scheduleUpdateProxyClientsIfNeededLocked(int deviceId, boolean forceUpdate) {
        final int proxyState = getStateLocked(deviceId);
        if (DEBUG) {
            Slog.v(LOG_TAG, "State for device id " + deviceId + " is " + proxyState);
            Slog.v(LOG_TAG, "Last state for device id " + deviceId + " is "
                    + getLastSentStateLocked(deviceId));
            Slog.v(LOG_TAG, "force update: " + forceUpdate);
        }
        if ((getLastSentStateLocked(deviceId)) != proxyState
                || (Flags.proxyUseAppsOnVirtualDeviceListener() && forceUpdate)) {
            setLastStateLocked(deviceId, proxyState);
            mMainHandler.post(() -> {
                synchronized (mLock) {
                    broadcastToClientsLocked(ignoreRemoteException(client -> {
                        if (client.mDeviceId == deviceId) {
                            client.mCallback.setState(proxyState);
                        }
                    }));
                }
            });
        }
    }

    /**
     * Notifies AccessibilityManager of services state changes, which includes changes to the
     * list of service infos and timeouts.
     *
     * @see AccessibilityManager.AccessibilityServicesStateChangeListener
     */
    private void scheduleNotifyProxyClientsOfServicesStateChangeLocked(int deviceId) {
        if (DEBUG) {
            Slog.v(LOG_TAG, "Notify services state change at device id " + deviceId);
        }
        mMainHandler.post(()-> {
            broadcastToClientsLocked(ignoreRemoteException(client -> {
                if (client.mDeviceId == deviceId) {
                    synchronized (mLock) {
                        client.mCallback.notifyServicesStateChanged(
                                getRecommendedTimeoutMillisLocked(deviceId));
                    }
                }
            }));
        });
    }

    /**
     * Updates the focus appearance of AccessibilityManagerClients.
     */
    private void updateFocusAppearanceLocked(int deviceId) {
        if (DEBUG) {
            Slog.v(LOG_TAG, "Update proxy focus appearance at device id " + deviceId);
        }
        // Reasonably assume that all proxies belonging to a virtual device should have the
        // same focus appearance, and if they should be different these should belong to different
        // virtual devices.
        final ProxyAccessibilityServiceConnection proxy = getFirstProxyForDeviceIdLocked(deviceId);
        if (proxy != null) {
            mMainHandler.post(()-> {
                broadcastToClientsLocked(ignoreRemoteException(client -> {
                    if (client.mDeviceId == proxy.getDeviceId()) {
                        client.mCallback.setFocusAppearance(
                                proxy.getFocusStrokeWidthLocked(),
                                proxy.getFocusColorLocked());
                    }
                }));
            });
        }
    }

    private ProxyAccessibilityServiceConnection getFirstProxyForDeviceIdLocked(int deviceId) {
        for (int i = 0; i < mProxyA11yServiceConnections.size(); i++) {
            final ProxyAccessibilityServiceConnection proxy =
                    mProxyA11yServiceConnections.valueAt(i);
            if (proxy != null && proxy.getDeviceId() == deviceId) {
                return proxy;
            }
        }
        return null;
    }

    private void broadcastToClientsLocked(
            @NonNull Consumer<AccessibilityManagerService.Client> clientAction) {
        final RemoteCallbackList<IAccessibilityManagerClient> userClients =
                mSystemSupport.getCurrentUserClientsLocked();
        final RemoteCallbackList<IAccessibilityManagerClient> globalClients =
                mSystemSupport.getGlobalClientsLocked();
        userClients.broadcastForEachCookie(clientAction);
        globalClients.broadcastForEachCookie(clientAction);
    }

    /**
     * Updates the timeout and notifies app clients.
     *
     * For real users, timeouts are tracked in A11yUserState. For proxies, timeouts are in the
     * service connection. The value in user state is preferred, but if this value is 0 the service
     * info value is used.
     *
     * This follows the pattern in readUserRecommendedUiTimeoutSettingsLocked.
     *
     * TODO(b/250929565): ProxyUserState or similar should hold the timeouts
     */
    public void updateTimeoutsIfNeeded(int nonInteractiveUiTimeout, int interactiveUiTimeout) {
        synchronized (mLock) {
            for (int i = 0; i < mProxyA11yServiceConnections.size(); i++) {
                final ProxyAccessibilityServiceConnection proxy =
                        mProxyA11yServiceConnections.valueAt(i);
                if (proxy != null) {
                    if (proxy.updateTimeouts(nonInteractiveUiTimeout, interactiveUiTimeout)) {
                        scheduleNotifyProxyClientsOfServicesStateChangeLocked(proxy.getDeviceId());
                    }
                }
            }
        }
    }

    /**
     * Gets the recommended timeout belonging to a Virtual Device.
     *
     * This is the highest of all display proxies belonging to the virtual device.
     */
    public long getRecommendedTimeoutMillisLocked(int deviceId) {
        int combinedInteractiveTimeout = 0;
        int combinedNonInteractiveTimeout = 0;
        for (int i = 0; i < mProxyA11yServiceConnections.size(); i++) {
            final ProxyAccessibilityServiceConnection proxy =
                    mProxyA11yServiceConnections.valueAt(i);
            if (proxy != null && proxy.getDeviceId() == deviceId) {
                final int proxyInteractiveUiTimeout =
                        (proxy != null) ? proxy.getInteractiveTimeout() : 0;
                final int nonInteractiveUiTimeout =
                        (proxy != null) ? proxy.getNonInteractiveTimeout() : 0;
                combinedInteractiveTimeout = Math.max(proxyInteractiveUiTimeout,
                        combinedInteractiveTimeout);
                combinedNonInteractiveTimeout = Math.max(nonInteractiveUiTimeout,
                        combinedNonInteractiveTimeout);
            }
        }
        return IntPair.of(combinedInteractiveTimeout, combinedNonInteractiveTimeout);
    }

    /**
     * Gets the first focus stroke width belonging to the device.
     */
    public int getFocusStrokeWidthLocked(int deviceId) {
        final ProxyAccessibilityServiceConnection proxy = getFirstProxyForDeviceIdLocked(deviceId);
        if (proxy != null) {
            return proxy.getFocusStrokeWidthLocked();
        }
        return 0;

    }

    /**
     * Gets the first focus color belonging to the device.
     */
    public int getFocusColorLocked(int deviceId) {
        final ProxyAccessibilityServiceConnection proxy = getFirstProxyForDeviceIdLocked(deviceId);
        if (proxy != null) {
            return proxy.getFocusColorLocked();
        }
        return 0;
    }

    /**
     * Returns the first device id given a UID.
     * @param callingUid the UID to check.
     * @return the first matching device id, or DEVICE_ID_INVALID.
     */
    public int getFirstDeviceIdForUidLocked(int callingUid) {
        int firstDeviceId = DEVICE_ID_INVALID;
        final VirtualDeviceManagerInternal localVdm = getLocalVdm();
        if (localVdm == null) {
            return firstDeviceId;
        }
        final Set<Integer> deviceIds = localVdm.getDeviceIdsForUid(callingUid);
        for (Integer uidDeviceId : deviceIds) {
            if (uidDeviceId != DEVICE_ID_DEFAULT && uidDeviceId != DEVICE_ID_INVALID) {
                firstDeviceId = uidDeviceId;
                break;
            }
        }
        return firstDeviceId;
    }

    /**
     * Sets a Client device id if the app uid belongs to the virtual device.
     */
    private void updateDeviceIdsIfNeededLocked(int deviceId) {
        final RemoteCallbackList<IAccessibilityManagerClient> userClients =
                mSystemSupport.getCurrentUserClientsLocked();
        final RemoteCallbackList<IAccessibilityManagerClient> globalClients =
                mSystemSupport.getGlobalClientsLocked();

        updateDeviceIdsIfNeededLocked(deviceId, userClients);
        updateDeviceIdsIfNeededLocked(deviceId, globalClients);
    }

    /**
     * Updates the device ids of IAccessibilityManagerClients if needed after a proxy change.
     */
    private void updateDeviceIdsIfNeededLocked(int deviceId,
            @NonNull RemoteCallbackList<IAccessibilityManagerClient> clients) {
        final VirtualDeviceManagerInternal localVdm = getLocalVdm();
        if (localVdm == null) {
            return;
        }

        for (int i = 0; i < clients.getRegisteredCallbackCount(); i++) {
            final AccessibilityManagerService.Client client =
                    ((AccessibilityManagerService.Client) clients.getRegisteredCallbackCookie(i));
            if (Flags.proxyUseAppsOnVirtualDeviceListener()) {
                if (deviceId == DEVICE_ID_DEFAULT || deviceId == DEVICE_ID_INVALID) {
                    continue;
                }
                boolean uidBelongsToDevice =
                        localVdm.getDeviceIdsForUid(client.mUid).contains(deviceId);
                if (client.mDeviceId != deviceId && uidBelongsToDevice) {
                    if (DEBUG) {
                        Slog.v(LOG_TAG, "Packages moved to device id " + deviceId + " are "
                                + Arrays.toString(client.mPackageNames));
                    }
                    client.mDeviceId = deviceId;
                } else if (client.mDeviceId == deviceId && !uidBelongsToDevice) {
                    client.mDeviceId = DEVICE_ID_DEFAULT;
                    if (DEBUG) {
                        Slog.v(LOG_TAG, "Packages moved to the default device from device id "
                                + deviceId + " are " + Arrays.toString(client.mPackageNames));
                    }
                }
            } else {
                if (deviceId != DEVICE_ID_DEFAULT && deviceId != DEVICE_ID_INVALID
                    && localVdm.getDeviceIdsForUid(client.mUid).contains(deviceId)) {
                    if (DEBUG) {
                        Slog.v(LOG_TAG, "Packages moved to device id " + deviceId + " are "
                                + Arrays.toString(client.mPackageNames));
                    }
                    client.mDeviceId = deviceId;
                }
            }
        }
    }

    @VisibleForTesting
    void notifyProxyOfRunningAppsChange(Set<Integer> allRunningUids) {
        if (DEBUG) {
            Slog.v(LOG_TAG, "notifyProxyOfRunningAppsChange: " + allRunningUids);
        }
        synchronized (mLock) {
            if (mProxyA11yServiceConnections.size() == 0) {
                return;
            }
            final VirtualDeviceManagerInternal localVdm = getLocalVdm();
            if  (localVdm == null) {
                return;
            }
            final ArraySet<Integer> deviceIdsToUpdate = new ArraySet<>();
            for (int i = 0; i < mProxyA11yServiceConnections.size(); i++) {
                final ProxyAccessibilityServiceConnection proxy =
                        mProxyA11yServiceConnections.valueAt(i);
                if (proxy != null) {
                    final int proxyDeviceId = proxy.getDeviceId();
                    for (Integer uid : allRunningUids) {
                        if (localVdm.getDeviceIdsForUid(uid).contains(proxyDeviceId)) {
                            deviceIdsToUpdate.add(proxyDeviceId);
                        }
                    }
                }
            }
            for (Integer proxyDeviceId : deviceIdsToUpdate) {
                onProxyChanged(proxyDeviceId, true);
            }
        }
    }

    /**
     * Clears all proxy caches.
     */
    public void clearCacheLocked() {
        for (int i = 0; i < mProxyA11yServiceConnections.size(); i++) {
            final ProxyAccessibilityServiceConnection proxy =
                    mProxyA11yServiceConnections.valueAt(i);
            proxy.notifyClearAccessibilityNodeInfoCache();
        }
    }

    /**
     * Sets the input filter for enabling and disabling features for proxy displays.
     */
    public void setAccessibilityInputFilter(AccessibilityInputFilter filter) {
        if (DEBUG) {
            Slog.v(LOG_TAG, "Set proxy input filter to " + filter);
        }
        mA11yInputFilter = filter;
    }

    private VirtualDeviceManagerInternal getLocalVdm() {
        if (mLocalVdm == null) {
            mLocalVdm =  LocalServices.getService(VirtualDeviceManagerInternal.class);
        }
        return mLocalVdm;
    }

    @VisibleForTesting
    void setLocalVirtualDeviceManager(VirtualDeviceManagerInternal localVdm) {
        mLocalVdm = localVdm;
    }

    /**
     * Prints information belonging to each display that is controlled by an
     * AccessibilityDisplayProxy.
     */
    void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
        synchronized (mLock) {
            pw.println();
            pw.println("Proxy manager state:");
            pw.println("    Number of proxy connections: " + mProxyA11yServiceConnections.size());
            pw.println("    Registered proxy connections:");
            final RemoteCallbackList<IAccessibilityManagerClient> userClients =
                    mSystemSupport.getCurrentUserClientsLocked();
            final RemoteCallbackList<IAccessibilityManagerClient> globalClients =
                    mSystemSupport.getGlobalClientsLocked();
            for (int i = 0; i < mProxyA11yServiceConnections.size(); i++) {
                final ProxyAccessibilityServiceConnection proxy =
                        mProxyA11yServiceConnections.valueAt(i);
                if (proxy != null) {
                    proxy.dump(fd, pw, args);
                }
                pw.println();
                pw.println("        User clients for proxy's virtual device id");
                printClientsForDeviceId(pw, userClients, proxy.getDeviceId());
                pw.println();
                pw.println("        Global clients for proxy's virtual device id");
                printClientsForDeviceId(pw, globalClients, proxy.getDeviceId());

            }
        }
    }

    private void printClientsForDeviceId(PrintWriter pw,
            RemoteCallbackList<IAccessibilityManagerClient> clients, int deviceId) {
        if (clients != null) {
            for (int j = 0; j < clients.getRegisteredCallbackCount(); j++) {
                final AccessibilityManagerService.Client client =
                        (AccessibilityManagerService.Client)
                                clients.getRegisteredCallbackCookie(j);
                if (client.mDeviceId == deviceId) {
                    pw.println("            " + Arrays.toString(client.mPackageNames) + "\n");
                }
            }
        }
    }
}
