/*
 ** Copyright 2017, 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.accessibilityservice.AccessibilityService.ACCESSIBILITY_TAKE_SCREENSHOT_REQUEST_INTERVAL_TIMES_MS;
import static android.accessibilityservice.AccessibilityService.KEY_ACCESSIBILITY_SCREENSHOT_COLORSPACE;
import static android.accessibilityservice.AccessibilityService.KEY_ACCESSIBILITY_SCREENSHOT_HARDWAREBUFFER;
import static android.accessibilityservice.AccessibilityService.KEY_ACCESSIBILITY_SCREENSHOT_STATUS;
import static android.accessibilityservice.AccessibilityService.KEY_ACCESSIBILITY_SCREENSHOT_TIMESTAMP;
import static android.accessibilityservice.AccessibilityServiceInfo.DEFAULT;
import static android.accessibilityservice.AccessibilityTrace.FLAGS_ACCESSIBILITY_INTERACTION_CONNECTION;
import static android.accessibilityservice.AccessibilityTrace.FLAGS_ACCESSIBILITY_SERVICE_CLIENT;
import static android.accessibilityservice.AccessibilityTrace.FLAGS_ACCESSIBILITY_SERVICE_CONNECTION;
import static android.accessibilityservice.AccessibilityTrace.FLAGS_WINDOW_MANAGER_INTERNAL;
import static android.view.WindowManager.LayoutParams.TYPE_ACCESSIBILITY_OVERLAY;
import static android.view.accessibility.AccessibilityInteractionClient.CALL_STACK;
import static android.view.accessibility.AccessibilityInteractionClient.IGNORE_CALL_STACK;
import static android.view.accessibility.AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS;
import static android.view.accessibility.AccessibilityNodeInfo.ACTION_CLEAR_ACCESSIBILITY_FOCUS;
import static android.view.accessibility.AccessibilityNodeInfo.ACTION_CLICK;
import static android.view.accessibility.AccessibilityNodeInfo.ACTION_LONG_CLICK;

import static com.android.window.flags.Flags.deleteCaptureDisplay;

import android.accessibilityservice.AccessibilityGestureEvent;
import android.accessibilityservice.AccessibilityService;
import android.accessibilityservice.AccessibilityServiceInfo;
import android.accessibilityservice.AccessibilityTrace;
import android.accessibilityservice.IAccessibilityServiceClient;
import android.accessibilityservice.IAccessibilityServiceConnection;
import android.accessibilityservice.MagnificationConfig;
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.PendingIntent;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.content.pm.PackageManager;
import android.content.pm.ParceledListSlice;
import android.graphics.ParcelableColorSpace;
import android.graphics.Region;
import android.hardware.HardwareBuffer;
import android.hardware.display.DisplayManager;
import android.hardware.display.DisplayManagerInternal;
import android.os.Binder;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.os.Looper;
import android.os.Message;
import android.os.PowerManager;
import android.os.RemoteCallback;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.SystemClock;
import android.provider.Settings;
import android.util.Pair;
import android.util.Slog;
import android.util.SparseArray;
import android.view.Display;
import android.view.InputDevice;
import android.view.KeyEvent;
import android.view.MagnificationSpec;
import android.view.MotionEvent;
import android.view.SurfaceControl;
import android.view.View;
import android.view.accessibility.AccessibilityCache;
import android.view.accessibility.AccessibilityEvent;
import android.view.accessibility.AccessibilityNodeInfo;
import android.view.accessibility.AccessibilityWindowInfo;
import android.view.accessibility.IAccessibilityInteractionConnectionCallback;
import android.view.inputmethod.EditorInfo;
import android.window.ScreenCapture;
import android.window.ScreenCapture.ScreenshotHardwareBuffer;

import com.android.internal.annotations.GuardedBy;
import com.android.internal.compat.IPlatformCompat;
import com.android.internal.inputmethod.IAccessibilityInputMethodSession;
import com.android.internal.inputmethod.IRemoteAccessibilityInputConnection;
import com.android.internal.os.SomeArgs;
import com.android.internal.util.DumpUtils;
import com.android.internal.util.function.pooled.PooledLambda;
import com.android.server.LocalServices;
import com.android.server.accessibility.AccessibilityWindowManager.RemoteAccessibilityConnection;
import com.android.server.accessibility.magnification.MagnificationProcessor;
import com.android.server.wm.WindowManagerInternal;

import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.NoSuchElementException;
import java.util.Set;

/**
 * This class represents an accessibility client - either an AccessibilityService or a UiAutomation.
 * It is responsible for behavior common to both types of clients.
 */
@SuppressWarnings("MissingPermissionAnnotation")
abstract class AbstractAccessibilityServiceConnection extends IAccessibilityServiceConnection.Stub
        implements ServiceConnection, IBinder.DeathRecipient, KeyEventDispatcher.KeyEventFilter,
        FingerprintGestureDispatcher.FingerprintGestureClient {
    private static final boolean DEBUG = false;
    private static final String LOG_TAG = "AbstractAccessibilityServiceConnection";
    private static final String TRACE_SVC_CONN = LOG_TAG + ".IAccessibilityServiceConnection";
    private static final String TRACE_SVC_CLIENT = LOG_TAG + ".IAccessibilityServiceClient";
    private static final String TRACE_WM = "WindowManagerInternal";
    private static final int WAIT_WINDOWS_TIMEOUT_MILLIS = 5000;

    /** Display type for displays associated with the default user of the device. */
    public static final int DISPLAY_TYPE_DEFAULT = 1 << 0;
    /** Display type for displays associated with an AccessibilityDisplayProxy user. */
    public static final int DISPLAY_TYPE_PROXY = 1 << 1;

    protected static final String TAKE_SCREENSHOT = "takeScreenshot";
    protected final Context mContext;
    protected final SystemSupport mSystemSupport;
    protected final WindowManagerInternal mWindowManagerService;
    private final SystemActionPerformer mSystemActionPerformer;
    final AccessibilityWindowManager mA11yWindowManager;
    private final DisplayManager mDisplayManager;
    private final PowerManager mPowerManager;
    private final IPlatformCompat mIPlatformCompat;

    private final Handler mMainHandler;

    // Handler for scheduling method invocations on the main thread.
    public final InvocationHandler mInvocationHandler;

    final int mId;

    protected final AccessibilityServiceInfo mAccessibilityServiceInfo;

    // Lock must match the one used by AccessibilityManagerService
    protected final Object mLock;

    protected final AccessibilitySecurityPolicy mSecurityPolicy;
    protected final AccessibilityTrace mTrace;

    // The attribution tag set by the service that is bound to this instance
    protected String mAttributionTag;

    protected int mDisplayTypes = DISPLAY_TYPE_DEFAULT;

    // The service that's bound to this instance. Whenever this value is non-null, this
    // object is registered as a death recipient
    IBinder mService;

    IAccessibilityServiceClient mServiceInterface;

    int mEventTypes;

    int mFeedbackType;

    Set<String> mPackageNames = new HashSet<>();

    boolean mIsDefault;

    boolean mRequestTouchExplorationMode;

    private boolean mServiceHandlesDoubleTap;

    private boolean mRequestMultiFingerGestures;

    private boolean mRequestTwoFingerPassthrough;

    private boolean mSendMotionEvents;

    private SparseArray<Boolean> mServiceDetectsGestures = new SparseArray<>(0);
    boolean mRequestFilterKeyEvents;

    boolean mRetrieveInteractiveWindows;

    boolean mCaptureFingerprintGestures;

    boolean mRequestAccessibilityButton;

    boolean mReceivedAccessibilityButtonCallbackSinceBind;

    boolean mLastAccessibilityButtonCallbackState;

    boolean mRequestImeApis;

    int mFetchFlags;

    long mNotificationTimeout;

    final ComponentName mComponentName;

    int mGenericMotionEventSources;
    int mObservedMotionEventSources;

    // the events pending events to be dispatched to this service
    final SparseArray<AccessibilityEvent> mPendingEvents = new SparseArray<>();

    /** Whether this service relies on its {@link AccessibilityCache} being up to date */
    boolean mUsesAccessibilityCache = false;

    // Handler only for dispatching accessibility events since we use event
    // types as message types allowing us to remove messages per event type.
    public Handler mEventDispatchHandler;

    final SparseArray<IBinder> mOverlayWindowTokens = new SparseArray();

    // All the embedded accessibility overlays that have been added by this service.
    private List<SurfaceControl> mOverlays = new ArrayList<>();

    /** The timestamp of requesting to take screenshot in milliseconds */
    private long mRequestTakeScreenshotTimestampMs;
    /**
     * The timestamps of requesting to take a window screenshot in milliseconds,
     * mapping from accessibility window id -> timestamp.
     */
    private SparseArray<Long> mRequestTakeScreenshotOfWindowTimestampMs = new SparseArray<>();

    /** @hide */
    @Retention(RetentionPolicy.SOURCE)
    @IntDef(flag = true, prefix = { "DISPLAY_TYPE_" }, value = {
            DISPLAY_TYPE_DEFAULT,
            DISPLAY_TYPE_PROXY
    })
    public @interface DisplayTypes {}

    public interface SystemSupport {
        /**
         * @return The current dispatcher for key events
         */
        @NonNull KeyEventDispatcher getKeyEventDispatcher();

        /**
         * @param displayId The display id.
         * @return The current injector of motion events used on the display, if one exists.
         */
        @Nullable MotionEventInjector getMotionEventInjectorForDisplayLocked(int displayId);

        /**
         * @return The current dispatcher for fingerprint gestures, if one exists
         */
        @Nullable FingerprintGestureDispatcher getFingerprintGestureDispatcher();

        /**
         * @return The magnification processor
         */
        @NonNull
        MagnificationProcessor getMagnificationProcessor();

        /**
         * Called back to notify system that the client has changed
         * @param serviceInfoChanged True if the service's AccessibilityServiceInfo changed.
         */
        void onClientChangeLocked(boolean serviceInfoChanged);

        /**
         * Called back to notify the system the proxy client for a device has changed.
         *
         * Changes include if the proxy is unregistered, if its service info list has changed, or if
         * its focus appearance has changed.
         */
        void onProxyChanged(int deviceId);

        int getCurrentUserIdLocked();

        Pair<float[], MagnificationSpec> getWindowTransformationMatrixAndMagnificationSpec(
                int windowId);

        boolean isAccessibilityButtonShown();

        /**
         * Persists the component names in the specified setting in a
         * colon separated fashion.
         *
         * @param settingName The setting name.
         * @param componentNames The component names.
         * @param userId The user id to persist the setting for.
         */
        void persistComponentNamesToSettingLocked(String settingName,
                Set<ComponentName> componentNames, int userId);

        /* This is exactly PendingIntent.getActivity, separated out for testability */
        PendingIntent getPendingIntentActivity(Context context, int requestCode, Intent intent,
                int flags);

        void setGestureDetectionPassthroughRegion(int displayId, Region region);

        void setTouchExplorationPassthroughRegion(int displayId, Region region);

        void setServiceDetectsGesturesEnabled(int displayId, boolean mode);

        void requestTouchExploration(int displayId);

        void requestDragging(int displayId, int pointerId);

        void requestDelegating(int displayId);

        void onDoubleTap(int displayId);

        void onDoubleTapAndHold(int displayId);

        void requestImeLocked(AbstractAccessibilityServiceConnection connection);

        void unbindImeLocked(AbstractAccessibilityServiceConnection connection);

        void attachAccessibilityOverlayToDisplay(
                int interactionId,
                int displayId,
                SurfaceControl sc,
                IAccessibilityInteractionConnectionCallback callback);

    }

    public AbstractAccessibilityServiceConnection(Context context, ComponentName componentName,
            AccessibilityServiceInfo accessibilityServiceInfo, int id, Handler mainHandler,
            Object lock, AccessibilitySecurityPolicy securityPolicy, SystemSupport systemSupport,
            AccessibilityTrace trace, WindowManagerInternal windowManagerInternal,
            SystemActionPerformer systemActionPerfomer,
            AccessibilityWindowManager a11yWindowManager) {
        mContext = context;
        mWindowManagerService = windowManagerInternal;
        mId = id;
        mComponentName = componentName;
        mAccessibilityServiceInfo = accessibilityServiceInfo;
        mLock = lock;
        mSecurityPolicy = securityPolicy;
        mSystemActionPerformer = systemActionPerfomer;
        mSystemSupport = systemSupport;
        mTrace = trace;
        mMainHandler = mainHandler;
        mInvocationHandler = new InvocationHandler(mainHandler.getLooper());
        mA11yWindowManager = a11yWindowManager;
        mDisplayManager = (DisplayManager) context.getSystemService(Context.DISPLAY_SERVICE);
        mPowerManager = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
        mIPlatformCompat = IPlatformCompat.Stub.asInterface(
                ServiceManager.getService(Context.PLATFORM_COMPAT_SERVICE));
        mEventDispatchHandler = new Handler(mainHandler.getLooper()) {
            @Override
            public void handleMessage(Message message) {
                final int eventType =  message.what;
                AccessibilityEvent event = (AccessibilityEvent) message.obj;
                boolean serviceWantsEvent = message.arg1 != 0;
                notifyAccessibilityEventInternal(eventType, event, serviceWantsEvent);
            }
        };
        setDynamicallyConfigurableProperties(accessibilityServiceInfo);
    }

    @Override
    public boolean onKeyEvent(KeyEvent keyEvent, int sequenceNumber) {
        if (!mRequestFilterKeyEvents || (mServiceInterface == null)) {
            return false;
        }
        if((mAccessibilityServiceInfo.getCapabilities()
                & AccessibilityServiceInfo.CAPABILITY_CAN_REQUEST_FILTER_KEY_EVENTS) == 0) {
            return false;
        }
        if (!mSecurityPolicy.checkAccessibilityAccess(this)) {
            return false;
        }
        try {
            if (svcClientTracingEnabled()) {
                logTraceSvcClient("onKeyEvent", keyEvent + ", " + sequenceNumber);
            }
            mServiceInterface.onKeyEvent(keyEvent, sequenceNumber);
        } catch (RemoteException e) {
            return false;
        }
        return true;
    }

    public void setDynamicallyConfigurableProperties(AccessibilityServiceInfo info) {
        mEventTypes = info.eventTypes;
        mFeedbackType = info.feedbackType;
        String[] packageNames = info.packageNames;
        mPackageNames.clear();
        if (packageNames != null) {
            mPackageNames.addAll(Arrays.asList(packageNames));
        }
        mNotificationTimeout = info.notificationTimeout;
        mIsDefault = (info.flags & DEFAULT) != 0;
        mGenericMotionEventSources = info.getMotionEventSources();
        if (android.view.accessibility.Flags.motionEventObserving()) {
            if (mContext.checkCallingOrSelfPermission(
                            android.Manifest.permission.ACCESSIBILITY_MOTION_EVENT_OBSERVING)
                    == PackageManager.PERMISSION_GRANTED) {
                mObservedMotionEventSources = info.getObservedMotionEventSources();
            } else {
                Slog.e(
                        LOG_TAG,
                        "Observing motion events requires"
                            + " android.Manifest.permission.ACCESSIBILITY_MOTION_EVENT_OBSERVING.");
                mObservedMotionEventSources = 0;
            }
        }

        if (supportsFlagForNotImportantViews(info)) {
            if ((info.flags & AccessibilityServiceInfo.FLAG_INCLUDE_NOT_IMPORTANT_VIEWS) != 0) {
                mFetchFlags |=
                        AccessibilityNodeInfo.FLAG_SERVICE_REQUESTS_INCLUDE_NOT_IMPORTANT_VIEWS;
            } else {
                mFetchFlags &=
                        ~AccessibilityNodeInfo.FLAG_SERVICE_REQUESTS_INCLUDE_NOT_IMPORTANT_VIEWS;
            }
        }

        if ((info.flags & AccessibilityServiceInfo.FLAG_REPORT_VIEW_IDS) != 0) {
            mFetchFlags |= AccessibilityNodeInfo.FLAG_SERVICE_REQUESTS_REPORT_VIEW_IDS;
        } else {
            mFetchFlags &= ~AccessibilityNodeInfo.FLAG_SERVICE_REQUESTS_REPORT_VIEW_IDS;
        }

        if (mAccessibilityServiceInfo.isAccessibilityTool()) {
            mFetchFlags |= AccessibilityNodeInfo.FLAG_SERVICE_IS_ACCESSIBILITY_TOOL;
        } else {
            mFetchFlags &= ~AccessibilityNodeInfo.FLAG_SERVICE_IS_ACCESSIBILITY_TOOL;
        }

        mRequestTouchExplorationMode = (info.flags
                & AccessibilityServiceInfo.FLAG_REQUEST_TOUCH_EXPLORATION_MODE) != 0;
        mServiceHandlesDoubleTap = (info.flags
                & AccessibilityServiceInfo.FLAG_SERVICE_HANDLES_DOUBLE_TAP) != 0;
        mRequestMultiFingerGestures = (info.flags
                & AccessibilityServiceInfo.FLAG_REQUEST_MULTI_FINGER_GESTURES) != 0;
        mRequestTwoFingerPassthrough =
                (info.flags & AccessibilityServiceInfo.FLAG_REQUEST_2_FINGER_PASSTHROUGH) != 0;
        mSendMotionEvents =
                (info.flags & AccessibilityServiceInfo.FLAG_SEND_MOTION_EVENTS) != 0;
        mRequestFilterKeyEvents =
                (info.flags & AccessibilityServiceInfo.FLAG_REQUEST_FILTER_KEY_EVENTS) != 0;
        mRetrieveInteractiveWindows = (info.flags
                & AccessibilityServiceInfo.FLAG_RETRIEVE_INTERACTIVE_WINDOWS) != 0;
        mCaptureFingerprintGestures = (info.flags
                & AccessibilityServiceInfo.FLAG_REQUEST_FINGERPRINT_GESTURES) != 0;
        mRequestAccessibilityButton = (info.flags
                & AccessibilityServiceInfo.FLAG_REQUEST_ACCESSIBILITY_BUTTON) != 0;
        mRequestImeApis = (info.flags
                & AccessibilityServiceInfo.FLAG_INPUT_METHOD_EDITOR) != 0;
    }

    protected boolean supportsFlagForNotImportantViews(AccessibilityServiceInfo info) {
        return info.getResolveInfo().serviceInfo.applicationInfo.targetSdkVersion
                >= Build.VERSION_CODES.JELLY_BEAN;
    }

    public boolean canReceiveEventsLocked() {
        return (mEventTypes != 0 && mService != null);
    }

    @Override
    public void setOnKeyEventResult(boolean handled, int sequence) {
        if (svcConnTracingEnabled()) {
            logTraceSvcConn("setOnKeyEventResult", "handled=" + handled + ";sequence=" + sequence);
        }
        final long identity = Binder.clearCallingIdentity();
        try {
            mSystemSupport.getKeyEventDispatcher().setOnKeyEventResult(this, handled, sequence);
        } finally {
            Binder.restoreCallingIdentity(identity);
        }
    }

    @Override
    public AccessibilityServiceInfo getServiceInfo() {
        if (svcConnTracingEnabled()) {
            logTraceSvcConn("getServiceInfo", "");
        }
        synchronized (mLock) {
            return mAccessibilityServiceInfo;
        }
    }

    public int getCapabilities() {
        return mAccessibilityServiceInfo.getCapabilities();
    }

    int getRelevantEventTypes() {
        return (mUsesAccessibilityCache ? AccessibilityCache.CACHE_CRITICAL_EVENTS_MASK
                : AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED) | mEventTypes;
    }

    @Override
    public void setServiceInfo(AccessibilityServiceInfo info) {
        if (svcConnTracingEnabled()) {
            logTraceSvcConn("setServiceInfo", "info=" + info);
        }
        if (!info.isWithinParcelableSize()) {
            throw new IllegalStateException(
                    "Cannot update service info: size is larger than safe parcelable limits.");
        }
        final long identity = Binder.clearCallingIdentity();
        try {
            synchronized (mLock) {
                // If the XML manifest had data to configure the service its info
                // should be already set. In such a case update only the dynamically
                // configurable properties.
                boolean oldRequestIme = mRequestImeApis;
                AccessibilityServiceInfo oldInfo = mAccessibilityServiceInfo;
                if (oldInfo != null) {
                    oldInfo.updateDynamicallyConfigurableProperties(mIPlatformCompat, info);
                    setDynamicallyConfigurableProperties(oldInfo);
                } else {
                    setDynamicallyConfigurableProperties(info);
                }
                mSystemSupport.onClientChangeLocked(true);
                if (!oldRequestIme && mRequestImeApis) {
                    mSystemSupport.requestImeLocked(this);
                } else if (oldRequestIme && !mRequestImeApis) {
                    mSystemSupport.unbindImeLocked(this);
                }
            }
        } finally {
            Binder.restoreCallingIdentity(identity);
        }
    }

    @Override
    public void setInstalledAndEnabledServices(List<AccessibilityServiceInfo> infos) {
        return;
    }

    @Override
    public List<AccessibilityServiceInfo> getInstalledAndEnabledServices() {
        return null;
    }

    @Override
    public void setAttributionTag(String attributionTag) {
        mAttributionTag = attributionTag;
    }

    String getAttributionTag() {
        return mAttributionTag;
    }

    protected abstract boolean hasRightsToCurrentUserLocked();

    @Nullable
    @Override
    public AccessibilityWindowInfo.WindowListSparseArray getWindows() {
        if (svcConnTracingEnabled()) {
            logTraceSvcConn("getWindows", "");
        }
        synchronized (mLock) {
            if (!hasRightsToCurrentUserLocked()) {
                return null;
            }
            final boolean permissionGranted =
                    mSecurityPolicy.canRetrieveWindowsLocked(this);
            if (!permissionGranted) {
                return null;
            }
            if (!mSecurityPolicy.checkAccessibilityAccess(this)) {
                return null;
            }

            final long identity = Binder.clearCallingIdentity();
            try {
                final AccessibilityWindowInfo.WindowListSparseArray allWindows =
                        new AccessibilityWindowInfo.WindowListSparseArray();
                final ArrayList<Integer> displayList = mA11yWindowManager.getDisplayListLocked(
                        mDisplayTypes);
                final int displayListCounts = displayList.size();
                if (displayListCounts > 0) {
                    for (int i = 0; i < displayListCounts; i++) {
                        final int displayId = displayList.get(i);
                        ensureWindowsAvailableTimedLocked(displayId);

                        final List<AccessibilityWindowInfo> windowList = getWindowsByDisplayLocked(
                                displayId);
                        if (windowList != null) {
                            allWindows.put(displayId, windowList);
                        }
                    }
                }
                return allWindows;
            } finally {
                Binder.restoreCallingIdentity(identity);
            }
        }
    }

    protected void setDisplayTypes(@DisplayTypes int displayTypes) {
        mDisplayTypes = displayTypes;
    }

    @Override
    public AccessibilityWindowInfo getWindow(int windowId) {
        if (svcConnTracingEnabled()) {
            logTraceSvcConn("getWindow", "windowId=" + windowId);
        }
        synchronized (mLock) {
            int displayId = Display.INVALID_DISPLAY;
            if (windowId != AccessibilityWindowInfo.UNDEFINED_WINDOW_ID) {
                displayId = mA11yWindowManager.getDisplayIdByUserIdAndWindowIdLocked(
                        mSystemSupport.getCurrentUserIdLocked(), windowId);
            }
            ensureWindowsAvailableTimedLocked(displayId);

            if (!hasRightsToCurrentUserLocked()) {
                return null;
            }
            final boolean permissionGranted =
                    mSecurityPolicy.canRetrieveWindowsLocked(this);
            if (!permissionGranted) {
                return null;
            }
            if (!mSecurityPolicy.checkAccessibilityAccess(this)) {
                return null;
            }
            final long identity = Binder.clearCallingIdentity();
            try {
                AccessibilityWindowInfo window =
                        mA11yWindowManager.findA11yWindowInfoByIdLocked(windowId);
                if (window != null) {
                    AccessibilityWindowInfo windowClone = AccessibilityWindowInfo.obtain(window);
                    windowClone.setConnectionId(mId);
                    return windowClone;
                }
                return null;
            } finally {
                Binder.restoreCallingIdentity(identity);
            }
        }
    }

    @Override
    public String[] findAccessibilityNodeInfosByViewId(int accessibilityWindowId,
            long accessibilityNodeId, String viewIdResName, int interactionId,
            IAccessibilityInteractionConnectionCallback callback, long interrogatingTid)
            throws RemoteException {
        if (svcConnTracingEnabled()) {
            logTraceSvcConn("findAccessibilityNodeInfosByViewId",
                    "accessibilityWindowId=" + accessibilityWindowId + ";accessibilityNodeId="
                    + accessibilityNodeId + ";viewIdResName=" + viewIdResName + ";interactionId="
                    + interactionId + ";callback=" + callback + ";interrogatingTid="
                    + interrogatingTid);
        }
        final int resolvedWindowId;
        RemoteAccessibilityConnection connection;
        Region partialInteractiveRegion = Region.obtain();
        synchronized (mLock) {
            mUsesAccessibilityCache = true;
            if (!hasRightsToCurrentUserLocked()) {
                return null;
            }
            resolvedWindowId = resolveAccessibilityWindowIdLocked(accessibilityWindowId);
            final boolean permissionGranted =
                    mSecurityPolicy.canGetAccessibilityNodeInfoLocked(
                            mSystemSupport.getCurrentUserIdLocked(), this, resolvedWindowId);
            if (!permissionGranted) {
                return null;
            } else {
                connection = mA11yWindowManager.getConnectionLocked(
                        mSystemSupport.getCurrentUserIdLocked(), resolvedWindowId);
                if (connection == null) {
                    return null;
                }
            }
            if (!mA11yWindowManager.computePartialInteractiveRegionForWindowLocked(
                    resolvedWindowId, partialInteractiveRegion)) {
                partialInteractiveRegion.recycle();
                partialInteractiveRegion = null;
            }
        }
        final Pair<float[], MagnificationSpec> transformMatrixAndSpec =
                getWindowTransformationMatrixAndMagnificationSpec(resolvedWindowId);
        final float[] transformMatrix = transformMatrixAndSpec.first;
        final MagnificationSpec spec = transformMatrixAndSpec.second;
        if (!mSecurityPolicy.checkAccessibilityAccess(this)) {
            return null;
        }
        final int interrogatingPid = Binder.getCallingPid();
        callback = replaceCallbackIfNeeded(callback, resolvedWindowId, interactionId,
                interrogatingPid, interrogatingTid);
        final long identityToken = Binder.clearCallingIdentity();
        if (intConnTracingEnabled()) {
            logTraceIntConn("findAccessibilityNodeInfosByViewId",
                    accessibilityNodeId + ";" + viewIdResName + ";" + partialInteractiveRegion + ";"
                    + interactionId + ";" + callback + ";" + mFetchFlags + ";" + interrogatingPid
                    + ";" + interrogatingTid + ";" + spec + ";" + Arrays.toString(transformMatrix));
        }
        try {
            connection.getRemote().findAccessibilityNodeInfosByViewId(accessibilityNodeId,
                    viewIdResName, partialInteractiveRegion, interactionId, callback, mFetchFlags,
                    interrogatingPid, interrogatingTid, spec, transformMatrix);
            return mSecurityPolicy.computeValidReportedPackages(
                    connection.getPackageName(), connection.getUid());
        } catch (RemoteException re) {
            if (DEBUG) {
                Slog.e(LOG_TAG, "Error findAccessibilityNodeInfoByViewId().");
            }
        } finally {
            Binder.restoreCallingIdentity(identityToken);
            // Recycle if passed to another process.
            if (partialInteractiveRegion != null && Binder.isProxy(connection.getRemote())) {
                partialInteractiveRegion.recycle();
            }
        }
        return null;
    }

    @Override
    public String[] findAccessibilityNodeInfosByText(int accessibilityWindowId,
            long accessibilityNodeId, String text, int interactionId,
            IAccessibilityInteractionConnectionCallback callback, long interrogatingTid)
            throws RemoteException {
        if (svcConnTracingEnabled()) {
            logTraceSvcConn("findAccessibilityNodeInfosByText",
                    "accessibilityWindowId=" + accessibilityWindowId + ";accessibilityNodeId="
                    + accessibilityNodeId + ";text=" + text + ";interactionId=" + interactionId
                    + ";callback=" + callback + ";interrogatingTid=" + interrogatingTid);
        }
        final int resolvedWindowId;
        RemoteAccessibilityConnection connection;
        Region partialInteractiveRegion = Region.obtain();
        synchronized (mLock) {
            mUsesAccessibilityCache = true;
            if (!hasRightsToCurrentUserLocked()) {
                return null;
            }
            resolvedWindowId = resolveAccessibilityWindowIdLocked(accessibilityWindowId);
            final boolean permissionGranted =
                    mSecurityPolicy.canGetAccessibilityNodeInfoLocked(
                            mSystemSupport.getCurrentUserIdLocked(), this, resolvedWindowId);
            if (!permissionGranted) {
                return null;
            } else {
                connection = mA11yWindowManager.getConnectionLocked(
                        mSystemSupport.getCurrentUserIdLocked(), resolvedWindowId);
                if (connection == null) {
                    return null;
                }
            }
            if (!mA11yWindowManager.computePartialInteractiveRegionForWindowLocked(
                    resolvedWindowId, partialInteractiveRegion)) {
                partialInteractiveRegion.recycle();
                partialInteractiveRegion = null;
            }
        }
        final Pair<float[], MagnificationSpec> transformMatrixAndSpec =
                getWindowTransformationMatrixAndMagnificationSpec(resolvedWindowId);
        final float[] transformMatrix = transformMatrixAndSpec.first;
        final MagnificationSpec spec = transformMatrixAndSpec.second;
        if (!mSecurityPolicy.checkAccessibilityAccess(this)) {
            return null;
        }
        final int interrogatingPid = Binder.getCallingPid();
        callback = replaceCallbackIfNeeded(callback, resolvedWindowId, interactionId,
                interrogatingPid, interrogatingTid);
        final long identityToken = Binder.clearCallingIdentity();
        if (intConnTracingEnabled()) {
            logTraceIntConn("findAccessibilityNodeInfosByText",
                    accessibilityNodeId + ";" + text + ";" + partialInteractiveRegion + ";"
                    + interactionId + ";" + callback + ";" + mFetchFlags + ";" + interrogatingPid
                    + ";" + interrogatingTid + ";" + spec + ";" + Arrays.toString(transformMatrix));
        }
        try {
            connection.getRemote().findAccessibilityNodeInfosByText(accessibilityNodeId,
                    text, partialInteractiveRegion, interactionId, callback, mFetchFlags,
                    interrogatingPid, interrogatingTid, spec, transformMatrix);
            return mSecurityPolicy.computeValidReportedPackages(
                    connection.getPackageName(), connection.getUid());
        } catch (RemoteException re) {
            if (DEBUG) {
                Slog.e(LOG_TAG, "Error calling findAccessibilityNodeInfosByText()");
            }
        } finally {
            Binder.restoreCallingIdentity(identityToken);
            // Recycle if passed to another process.
            if (partialInteractiveRegion != null && Binder.isProxy(connection.getRemote())) {
                partialInteractiveRegion.recycle();
            }
        }
        return null;
    }

    @Override
    public String[] findAccessibilityNodeInfoByAccessibilityId(
            int accessibilityWindowId, long accessibilityNodeId, int interactionId,
            IAccessibilityInteractionConnectionCallback callback, int flags,
            long interrogatingTid, Bundle arguments) throws RemoteException {
        if (svcConnTracingEnabled()) {
            logTraceSvcConn("findAccessibilityNodeInfoByAccessibilityId",
                    "accessibilityWindowId=" + accessibilityWindowId + ";accessibilityNodeId="
                    + accessibilityNodeId + ";interactionId=" + interactionId + ";callback="
                    + callback + ";flags=" + flags + ";interrogatingTid=" + interrogatingTid
                    + ";arguments=" + arguments);
        }
        final int resolvedWindowId;
        RemoteAccessibilityConnection connection;
        Region partialInteractiveRegion = Region.obtain();
        synchronized (mLock) {
            mUsesAccessibilityCache = true;
            if (!hasRightsToCurrentUserLocked()) {
                return null;
            }
            resolvedWindowId = resolveAccessibilityWindowIdLocked(accessibilityWindowId);
            final boolean permissionGranted =
                    mSecurityPolicy.canGetAccessibilityNodeInfoLocked(
                            mSystemSupport.getCurrentUserIdLocked(), this, resolvedWindowId);
            if (!permissionGranted) {
                return null;
            } else {
                connection = mA11yWindowManager.getConnectionLocked(
                        mSystemSupport.getCurrentUserIdLocked(), resolvedWindowId);
                if (connection == null) {
                    return null;
                }
            }
            if (!mA11yWindowManager.computePartialInteractiveRegionForWindowLocked(
                    resolvedWindowId, partialInteractiveRegion)) {
                partialInteractiveRegion.recycle();
                partialInteractiveRegion = null;
            }
        }
        final Pair<float[], MagnificationSpec> transformMatrixAndSpec =
                getWindowTransformationMatrixAndMagnificationSpec(resolvedWindowId);
        final float[] transformMatrix = transformMatrixAndSpec.first;
        final MagnificationSpec spec = transformMatrixAndSpec.second;
        if (!mSecurityPolicy.checkAccessibilityAccess(this)) {
            return null;
        }
        final int interrogatingPid = Binder.getCallingPid();
        callback = replaceCallbackIfNeeded(callback, resolvedWindowId, interactionId,
                interrogatingPid, interrogatingTid);
        final long identityToken = Binder.clearCallingIdentity();
        if (intConnTracingEnabled()) {
            logTraceIntConn("findAccessibilityNodeInfoByAccessibilityId",
                    accessibilityNodeId + ";" + partialInteractiveRegion + ";" + interactionId + ";"
                    + callback + ";" + (mFetchFlags | flags) + ";" + interrogatingPid + ";"
                            + interrogatingTid + ";" + spec + ";" + Arrays.toString(transformMatrix)
                            + ";" + arguments);
        }
        try {
            connection.getRemote().findAccessibilityNodeInfoByAccessibilityId(
                    accessibilityNodeId, partialInteractiveRegion, interactionId, callback,
                    mFetchFlags | flags, interrogatingPid, interrogatingTid, spec, transformMatrix,
                    arguments);
            return mSecurityPolicy.computeValidReportedPackages(
                    connection.getPackageName(), connection.getUid());
        } catch (RemoteException re) {
            if (DEBUG) {
                Slog.e(LOG_TAG, "Error calling findAccessibilityNodeInfoByAccessibilityId()");
            }
        } finally {
            Binder.restoreCallingIdentity(identityToken);
            // Recycle if passed to another process.
            if (partialInteractiveRegion != null && Binder.isProxy(connection.getRemote())) {
                partialInteractiveRegion.recycle();
            }
        }
        return null;
    }

    @Override
    public String[] findFocus(int accessibilityWindowId, long accessibilityNodeId,
            int focusType, int interactionId,
            IAccessibilityInteractionConnectionCallback callback, long interrogatingTid)
            throws RemoteException {
        if (svcConnTracingEnabled()) {
            logTraceSvcConn("findFocus",
                    "accessibilityWindowId=" + accessibilityWindowId + ";accessibilityNodeId="
                    + accessibilityNodeId + ";focusType=" + focusType + ";interactionId="
                    + interactionId + ";callback=" + callback + ";interrogatingTid="
                    + interrogatingTid);
        }
        final int resolvedWindowId;
        RemoteAccessibilityConnection connection;
        Region partialInteractiveRegion = Region.obtain();
        synchronized (mLock) {
            if (!hasRightsToCurrentUserLocked()) {
                return null;
            }
            resolvedWindowId = resolveAccessibilityWindowIdForFindFocusLocked(
                    accessibilityWindowId, focusType);
            final boolean permissionGranted =
                    mSecurityPolicy.canGetAccessibilityNodeInfoLocked(
                            mSystemSupport.getCurrentUserIdLocked(), this, resolvedWindowId);
            if (!permissionGranted) {
                return null;
            } else {
                connection = mA11yWindowManager.getConnectionLocked(
                        mSystemSupport.getCurrentUserIdLocked(), resolvedWindowId);
                if (connection == null) {
                    return null;
                }
            }
            if (!mA11yWindowManager.computePartialInteractiveRegionForWindowLocked(
                    resolvedWindowId, partialInteractiveRegion)) {
                partialInteractiveRegion.recycle();
                partialInteractiveRegion = null;
            }
        }
        final Pair<float[], MagnificationSpec> transformMatrixAndSpec =
                getWindowTransformationMatrixAndMagnificationSpec(resolvedWindowId);
        final float[] transformMatrix = transformMatrixAndSpec.first;
        final MagnificationSpec spec = transformMatrixAndSpec.second;
        if (!mSecurityPolicy.checkAccessibilityAccess(this)) {
            return null;
        }
        final int interrogatingPid = Binder.getCallingPid();
        callback = replaceCallbackIfNeeded(callback, resolvedWindowId, interactionId,
                interrogatingPid, interrogatingTid);
        final long identityToken = Binder.clearCallingIdentity();
        if (intConnTracingEnabled()) {
            logTraceIntConn("findFocus",
                    accessibilityNodeId + ";" + focusType + ";" + partialInteractiveRegion + ";"
                    + interactionId + ";" + callback + ";" + mFetchFlags + ";" + interrogatingPid
                            + ";" + interrogatingTid + ";" + spec + ";"
                            + Arrays.toString(transformMatrix));
        }
        try {
            connection.getRemote().findFocus(accessibilityNodeId, focusType,
                    partialInteractiveRegion, interactionId, callback, mFetchFlags,
                    interrogatingPid, interrogatingTid, spec, transformMatrix);
            return mSecurityPolicy.computeValidReportedPackages(
                    connection.getPackageName(), connection.getUid());
        } catch (RemoteException re) {
            if (DEBUG) {
                Slog.e(LOG_TAG, "Error calling findFocus()");
            }
        } finally {
            Binder.restoreCallingIdentity(identityToken);
            // Recycle if passed to another process.
            if (partialInteractiveRegion != null && Binder.isProxy(connection.getRemote())) {
                partialInteractiveRegion.recycle();
            }
        }
        return null;
    }

    @Override
    public String[] focusSearch(int accessibilityWindowId, long accessibilityNodeId,
            int direction, int interactionId,
            IAccessibilityInteractionConnectionCallback callback, long interrogatingTid)
            throws RemoteException {
        if (svcConnTracingEnabled()) {
            logTraceSvcConn("focusSearch",
                    "accessibilityWindowId=" + accessibilityWindowId + ";accessibilityNodeId="
                    + accessibilityNodeId + ";direction=" + direction + ";interactionId="
                    + interactionId + ";callback=" + callback + ";interrogatingTid="
                    + interrogatingTid);
        }
        final int resolvedWindowId;
        RemoteAccessibilityConnection connection;
        Region partialInteractiveRegion = Region.obtain();
        synchronized (mLock) {
            if (!hasRightsToCurrentUserLocked()) {
                return null;
            }
            resolvedWindowId = resolveAccessibilityWindowIdLocked(accessibilityWindowId);
            final boolean permissionGranted =
                    mSecurityPolicy.canGetAccessibilityNodeInfoLocked(
                            mSystemSupport.getCurrentUserIdLocked(), this, resolvedWindowId);
            if (!permissionGranted) {
                return null;
            } else {
                connection = mA11yWindowManager.getConnectionLocked(
                        mSystemSupport.getCurrentUserIdLocked(), resolvedWindowId);
                if (connection == null) {
                    return null;
                }
            }
            if (!mA11yWindowManager.computePartialInteractiveRegionForWindowLocked(
                    resolvedWindowId, partialInteractiveRegion)) {
                partialInteractiveRegion.recycle();
                partialInteractiveRegion = null;
            }
        }
        final Pair<float[], MagnificationSpec> transformMatrixAndSpec =
                getWindowTransformationMatrixAndMagnificationSpec(resolvedWindowId);
        final float[] transformMatrix = transformMatrixAndSpec.first;
        final MagnificationSpec spec = transformMatrixAndSpec.second;
        if (!mSecurityPolicy.checkAccessibilityAccess(this)) {
            return null;
        }
        final int interrogatingPid = Binder.getCallingPid();
        callback = replaceCallbackIfNeeded(callback, resolvedWindowId, interactionId,
                interrogatingPid, interrogatingTid);
        final long identityToken = Binder.clearCallingIdentity();
        if (intConnTracingEnabled()) {
            logTraceIntConn("focusSearch",
                    accessibilityNodeId + ";" + direction + ";" + partialInteractiveRegion
                    + ";" + interactionId + ";" + callback + ";" + mFetchFlags + ";"
                            + interrogatingPid + ";" + interrogatingTid + ";" + spec + ";"
                             + Arrays.toString(transformMatrix));
        }
        try {
            connection.getRemote().focusSearch(accessibilityNodeId, direction,
                    partialInteractiveRegion, interactionId, callback, mFetchFlags,
                    interrogatingPid, interrogatingTid, spec, transformMatrix);
            return mSecurityPolicy.computeValidReportedPackages(
                    connection.getPackageName(), connection.getUid());
        } catch (RemoteException re) {
            if (DEBUG) {
                Slog.e(LOG_TAG, "Error calling accessibilityFocusSearch()");
            }
        } finally {
            Binder.restoreCallingIdentity(identityToken);
            // Recycle if passed to another process.
            if (partialInteractiveRegion != null && Binder.isProxy(connection.getRemote())) {
                partialInteractiveRegion.recycle();
            }
        }
        return null;
    }

    @Override
    public void sendGesture(int sequence, ParceledListSlice gestureSteps) {
        if (svcConnTracingEnabled()) {
            logTraceSvcConn(
                    "sendGesture", "sequence=" + sequence + ";gestureSteps=" + gestureSteps);
        }
    }

    @Override
    public void dispatchGesture(int sequence, ParceledListSlice gestureSteps, int displayId) {
        if (svcConnTracingEnabled()) {
            logTraceSvcConn("dispatchGesture", "sequence=" + sequence + ";gestureSteps="
                    + gestureSteps + ";displayId=" + displayId);
        }
    }

    @Override
    public boolean performAccessibilityAction(int accessibilityWindowId,
            long accessibilityNodeId, int action, Bundle arguments, int interactionId,
            IAccessibilityInteractionConnectionCallback callback, long interrogatingTid)
            throws RemoteException {
        if (svcConnTracingEnabled()) {
            logTraceSvcConn("performAccessibilityAction",
                    "accessibilityWindowId=" + accessibilityWindowId + ";accessibilityNodeId="
                    + accessibilityNodeId + ";action=" + action + ";arguments=" + arguments
                    + ";interactionId=" + interactionId + ";callback=" + callback
                    + ";interrogatingTid=" + interrogatingTid);
        }
        final int resolvedWindowId;
        synchronized (mLock) {
            if (!hasRightsToCurrentUserLocked()) {
                return false;
            }
            resolvedWindowId = resolveAccessibilityWindowIdLocked(accessibilityWindowId);
            if (!mSecurityPolicy.canGetAccessibilityNodeInfoLocked(
                    mSystemSupport.getCurrentUserIdLocked(), this, resolvedWindowId)) {
                return false;
            }
        }
        if (!mSecurityPolicy.checkAccessibilityAccess(this)) {
            return false;
        }
        return performAccessibilityActionInternal(
                mSystemSupport.getCurrentUserIdLocked(), resolvedWindowId, accessibilityNodeId,
                action, arguments, interactionId, callback, mFetchFlags, interrogatingTid);
    }

    @Override
    public boolean performGlobalAction(int action) {
        if (svcConnTracingEnabled()) {
            logTraceSvcConn("performGlobalAction", "action=" + action);
        }
        synchronized (mLock) {
            if (!hasRightsToCurrentUserLocked()) {
                return false;
            }
        }
        final long identity = Binder.clearCallingIdentity();
        try {
            return mSystemActionPerformer.performSystemAction(action);
        } finally {
            Binder.restoreCallingIdentity(identity);
        }
    }

    @Override
    public @NonNull List<AccessibilityNodeInfo.AccessibilityAction> getSystemActions() {
        if (svcConnTracingEnabled()) {
            logTraceSvcConn("getSystemActions", "");
        }
        synchronized (mLock) {
            if (!hasRightsToCurrentUserLocked()) {
                return Collections.emptyList();
            }
        }
        final long identity = Binder.clearCallingIdentity();
        try {
            return mSystemActionPerformer.getSystemActions();
        } finally {
            Binder.restoreCallingIdentity(identity);
        }
    }

    @Override
    public boolean isFingerprintGestureDetectionAvailable() {
        if (svcConnTracingEnabled()) {
            logTraceSvcConn("isFingerprintGestureDetectionAvailable", "");
        }
        if (!mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_FINGERPRINT)) {
            return false;
        }
        final long identity = Binder.clearCallingIdentity();
        try {
            if (isCapturingFingerprintGestures()) {
                FingerprintGestureDispatcher dispatcher =
                        mSystemSupport.getFingerprintGestureDispatcher();
                return (dispatcher != null) && dispatcher.isFingerprintGestureDetectionAvailable();
            }
            return false;
        } finally {
            Binder.restoreCallingIdentity(identity);
        }
    }

    @Nullable
    @Override
    public MagnificationConfig getMagnificationConfig(int displayId) {
        if (svcConnTracingEnabled()) {
            logTraceSvcConn("getMagnificationConfig", "displayId=" + displayId);
        }
        synchronized (mLock) {
            if (!hasRightsToCurrentUserLocked()) {
                return null;
            }
        }
        final long identity = Binder.clearCallingIdentity();
        try {
            return mSystemSupport.getMagnificationProcessor().getMagnificationConfig(displayId);
        } finally {
            Binder.restoreCallingIdentity(identity);
        }
    }

    @Override
    public float getMagnificationScale(int displayId) {
        if (svcConnTracingEnabled()) {
            logTraceSvcConn("getMagnificationScale", "displayId=" + displayId);
        }
        synchronized (mLock) {
            if (!hasRightsToCurrentUserLocked()) {
                return 1.0f;
            }
        }
        final long identity = Binder.clearCallingIdentity();
        try {
            return mSystemSupport.getMagnificationProcessor().getScale(displayId);
        } finally {
            Binder.restoreCallingIdentity(identity);
        }
    }

    @Override
    public Region getMagnificationRegion(int displayId) {
        if (svcConnTracingEnabled()) {
            logTraceSvcConn("getMagnificationRegion", "displayId=" + displayId);
        }
        synchronized (mLock) {
            final Region region = Region.obtain();
            if (!hasRightsToCurrentUserLocked()) {
                return region;
            }
            MagnificationProcessor magnificationProcessor =
                    mSystemSupport.getMagnificationProcessor();
            final long identity = Binder.clearCallingIdentity();
            try {
                magnificationProcessor.getFullscreenMagnificationRegion(displayId,
                        region, mSecurityPolicy.canControlMagnification(this));
                return region;
            } finally {
                Binder.restoreCallingIdentity(identity);
            }
        }
    }


    @Override
    public Region getCurrentMagnificationRegion(int displayId) {
        if (svcConnTracingEnabled()) {
            logTraceSvcConn("getCurrentMagnificationRegion", "displayId=" + displayId);
        }
        synchronized (mLock) {
            final Region region = Region.obtain();
            if (!hasRightsToCurrentUserLocked()) {
                return region;
            }
            MagnificationProcessor magnificationProcessor =
                    mSystemSupport.getMagnificationProcessor();
            final long identity = Binder.clearCallingIdentity();
            try {
                magnificationProcessor.getCurrentMagnificationRegion(displayId,
                        region, mSecurityPolicy.canControlMagnification(this));
                return region;
            } finally {
                Binder.restoreCallingIdentity(identity);
            }
        }
    }

    @Override
    public float getMagnificationCenterX(int displayId) {
        if (svcConnTracingEnabled()) {
            logTraceSvcConn("getMagnificationCenterX", "displayId=" + displayId);
        }
        synchronized (mLock) {
            if (!hasRightsToCurrentUserLocked()) {
                return 0.0f;
            }
            MagnificationProcessor magnificationProcessor =
                    mSystemSupport.getMagnificationProcessor();
            final long identity = Binder.clearCallingIdentity();
            try {
                return magnificationProcessor.getCenterX(displayId,
                        mSecurityPolicy.canControlMagnification(this));
            } finally {
                Binder.restoreCallingIdentity(identity);
            }
        }
    }

    @Override
    public float getMagnificationCenterY(int displayId) {
        if (svcConnTracingEnabled()) {
            logTraceSvcConn("getMagnificationCenterY", "displayId=" + displayId);
        }
        synchronized (mLock) {
            if (!hasRightsToCurrentUserLocked()) {
                return 0.0f;
            }
            MagnificationProcessor magnificationProcessor =
                    mSystemSupport.getMagnificationProcessor();
            final long identity = Binder.clearCallingIdentity();
            try {
                return magnificationProcessor.getCenterY(displayId,
                        mSecurityPolicy.canControlMagnification(this));
            } finally {
                Binder.restoreCallingIdentity(identity);
            }
        }
    }

    @Override
    public boolean resetMagnification(int displayId, boolean animate) {
        if (svcConnTracingEnabled()) {
            logTraceSvcConn("resetMagnification", "displayId=" + displayId + ";animate=" + animate);
        }
        synchronized (mLock) {
            if (!hasRightsToCurrentUserLocked()) {
                return false;
            }
            if (!mSecurityPolicy.canControlMagnification(this)) {
                return false;
            }
        }
        final long identity = Binder.clearCallingIdentity();
        try {
            MagnificationProcessor magnificationProcessor =
                    mSystemSupport.getMagnificationProcessor();
            return (magnificationProcessor.resetFullscreenMagnification(displayId, animate)
                    || !magnificationProcessor.isMagnifying(displayId));
        } finally {
            Binder.restoreCallingIdentity(identity);
        }
    }

    @Override
    public boolean resetCurrentMagnification(int displayId, boolean animate) {
        if (svcConnTracingEnabled()) {
            logTraceSvcConn("resetCurrentMagnification",
                    "displayId=" + displayId + ";animate=" + animate);
        }
        synchronized (mLock) {
            if (!hasRightsToCurrentUserLocked()) {
                return false;
            }
            if (!mSecurityPolicy.canControlMagnification(this)) {
                return false;
            }
        }
        final long identity = Binder.clearCallingIdentity();
        try {
            MagnificationProcessor magnificationProcessor =
                    mSystemSupport.getMagnificationProcessor();
            return (magnificationProcessor.resetCurrentMagnification(displayId, animate)
                    || !magnificationProcessor.isMagnifying(displayId));
        } finally {
            Binder.restoreCallingIdentity(identity);
        }
    }

    @Override
    public boolean setMagnificationConfig(int displayId,
            @NonNull MagnificationConfig config, boolean animate) {
        if (svcConnTracingEnabled()) {
            logTraceSvcConn("setMagnificationSpec",
                    "displayId=" + displayId + ", config=" + config.toString());
        }
        synchronized (mLock) {
            if (!hasRightsToCurrentUserLocked()) {
                return false;
            }
            if (!mSecurityPolicy.canControlMagnification(this)) {
                return false;
            }
            final long identity = Binder.clearCallingIdentity();
            try {
                MagnificationProcessor magnificationProcessor =
                        mSystemSupport.getMagnificationProcessor();
                return magnificationProcessor.setMagnificationConfig(displayId, config, animate,
                        mId);
            } finally {
                Binder.restoreCallingIdentity(identity);
            }
        }
    }

    @Override
    public void setMagnificationCallbackEnabled(int displayId, boolean enabled) {
        if (svcConnTracingEnabled()) {
            logTraceSvcConn("setMagnificationCallbackEnabled",
                    "displayId=" + displayId + ";enabled=" + enabled);
        }
        final long identity = Binder.clearCallingIdentity();
        try {
            mInvocationHandler.setMagnificationCallbackEnabled(displayId, enabled);
        } finally {
            Binder.restoreCallingIdentity(identity);
        }
    }

    public boolean isMagnificationCallbackEnabled(int displayId) {
        return mInvocationHandler.isMagnificationCallbackEnabled(displayId);
    }

    @Override
    public void setSoftKeyboardCallbackEnabled(boolean enabled) {
        if (svcConnTracingEnabled()) {
            logTraceSvcConn("setSoftKeyboardCallbackEnabled", "enabled=" + enabled);
        }
        final long identity = Binder.clearCallingIdentity();
        try {
            mInvocationHandler.setSoftKeyboardCallbackEnabled(enabled);
        } finally {
            Binder.restoreCallingIdentity(identity);
        }
    }

    @Override
    public void takeScreenshotOfWindow(int accessibilityWindowId, int interactionId,
            ScreenCapture.ScreenCaptureListener listener,
            IAccessibilityInteractionConnectionCallback callback) throws RemoteException {
        final long currentTimestamp = SystemClock.uptimeMillis();
        if ((currentTimestamp
                - mRequestTakeScreenshotOfWindowTimestampMs.get(accessibilityWindowId, 0L))
                <= ACCESSIBILITY_TAKE_SCREENSHOT_REQUEST_INTERVAL_TIMES_MS) {
            callback.sendTakeScreenshotOfWindowError(
                    AccessibilityService.ERROR_TAKE_SCREENSHOT_INTERVAL_TIME_SHORT, interactionId);
            return;
        }
        mRequestTakeScreenshotOfWindowTimestampMs.put(accessibilityWindowId, currentTimestamp);

        synchronized (mLock) {
            if (!hasRightsToCurrentUserLocked()) {
                callback.sendTakeScreenshotOfWindowError(
                        AccessibilityService.ERROR_TAKE_SCREENSHOT_INTERNAL_ERROR, interactionId);
                return;
            }
            if (!mSecurityPolicy.canTakeScreenshotLocked(this)) {
                callback.sendTakeScreenshotOfWindowError(
                        AccessibilityService.ERROR_TAKE_SCREENSHOT_NO_ACCESSIBILITY_ACCESS,
                        interactionId);
                return;
            }
        }
        if (!mSecurityPolicy.checkAccessibilityAccess(this)) {
            callback.sendTakeScreenshotOfWindowError(
                    AccessibilityService.ERROR_TAKE_SCREENSHOT_NO_ACCESSIBILITY_ACCESS,
                    interactionId);
            return;
        }

        final long identity = Binder.clearCallingIdentity();
        try {
            RemoteAccessibilityConnection connection = mA11yWindowManager.getConnectionLocked(
                    mSystemSupport.getCurrentUserIdLocked(),
                    resolveAccessibilityWindowIdLocked(accessibilityWindowId));
            if (connection == null) {
                callback.sendTakeScreenshotOfWindowError(
                        AccessibilityService.ERROR_TAKE_SCREENSHOT_INVALID_WINDOW, interactionId);
                return;
            }
            connection.getRemote().takeScreenshotOfWindow(interactionId, listener, callback);
        } finally {
            Binder.restoreCallingIdentity(identity);
        }
    }

    @Override
    public void takeScreenshot(int displayId, RemoteCallback callback) {
        if (svcConnTracingEnabled()) {
            logTraceSvcConn("takeScreenshot", "displayId=" + displayId + ";callback=" + callback);
        }
        final long currentTimestamp = SystemClock.uptimeMillis();
        if (mRequestTakeScreenshotTimestampMs != 0
                && (currentTimestamp - mRequestTakeScreenshotTimestampMs)
                <= AccessibilityService.ACCESSIBILITY_TAKE_SCREENSHOT_REQUEST_INTERVAL_TIMES_MS) {
            sendScreenshotFailure(AccessibilityService.ERROR_TAKE_SCREENSHOT_INTERVAL_TIME_SHORT,
                    callback);
            return;
        }
        mRequestTakeScreenshotTimestampMs = currentTimestamp;

        synchronized (mLock) {
            if (!hasRightsToCurrentUserLocked()) {
                sendScreenshotFailure(AccessibilityService.ERROR_TAKE_SCREENSHOT_INTERNAL_ERROR,
                        callback);
                return;
            }

            if (!mSecurityPolicy.canTakeScreenshotLocked(this)) {
                throw new SecurityException("Services don't have the capability of taking"
                        + " the screenshot.");
            }
        }

        if (!mSecurityPolicy.checkAccessibilityAccess(this)) {
            sendScreenshotFailure(
                    AccessibilityService.ERROR_TAKE_SCREENSHOT_NO_ACCESSIBILITY_ACCESS,
                    callback);
            return;
        }

        // Private virtual displays are created by the ap and is not allowed to access by other
        // aps.  We assume the contents on this display should not be captured.
        final DisplayManager displayManager =
                (DisplayManager) mContext.getSystemService(Context.DISPLAY_SERVICE);
        final Display display = displayManager.getDisplay(displayId);
        if ((display == null) || (display.getType() == Display.TYPE_VIRTUAL
                && (display.getFlags() & Display.FLAG_PRIVATE) != 0)) {
            sendScreenshotFailure(
                    AccessibilityService.ERROR_TAKE_SCREENSHOT_INVALID_DISPLAY, callback);
            return;
        }
        final long identity = Binder.clearCallingIdentity();
        if (deleteCaptureDisplay()) {
            try {
                ScreenCapture.ScreenCaptureListener screenCaptureListener = new
                        ScreenCapture.ScreenCaptureListener(
                        (screenshotBuffer, result) -> {
                            if (screenshotBuffer != null && result == 0) {
                                sendScreenshotSuccess(screenshotBuffer, callback);
                            } else {
                                sendScreenshotFailure(
                                        AccessibilityService.ERROR_TAKE_SCREENSHOT_INVALID_DISPLAY,
                                        callback);
                            }
                        }
                );
                mWindowManagerService.captureDisplay(displayId, null, screenCaptureListener);
            } catch (Exception e) {
                sendScreenshotFailure(AccessibilityService.ERROR_TAKE_SCREENSHOT_INVALID_DISPLAY,
                        callback);
            } finally {
                Binder.restoreCallingIdentity(identity);
            }
        } else {
            try {
                mMainHandler.post(PooledLambda.obtainRunnable((nonArg) -> {
                    final ScreenshotHardwareBuffer screenshotBuffer = LocalServices
                            .getService(DisplayManagerInternal.class).userScreenshot(displayId);
                    if (screenshotBuffer != null) {
                        sendScreenshotSuccess(screenshotBuffer, callback);
                    } else {
                        sendScreenshotFailure(
                                AccessibilityService.ERROR_TAKE_SCREENSHOT_INVALID_DISPLAY,
                                callback);
                    }
                }, null).recycleOnUse());
            } finally {
                Binder.restoreCallingIdentity(identity);
            }
        }
    }

    private void sendScreenshotSuccess(ScreenshotHardwareBuffer screenshotBuffer,
            RemoteCallback callback) {
        if (deleteCaptureDisplay()) {
            mMainHandler.post(PooledLambda.obtainRunnable((nonArg) -> {
                final HardwareBuffer hardwareBuffer = screenshotBuffer.getHardwareBuffer();
                final ParcelableColorSpace colorSpace =
                        new ParcelableColorSpace(screenshotBuffer.getColorSpace());

                final Bundle payload = new Bundle();
                payload.putInt(KEY_ACCESSIBILITY_SCREENSHOT_STATUS,
                        AccessibilityService.TAKE_SCREENSHOT_SUCCESS);
                payload.putParcelable(KEY_ACCESSIBILITY_SCREENSHOT_HARDWAREBUFFER,
                        hardwareBuffer);
                payload.putParcelable(KEY_ACCESSIBILITY_SCREENSHOT_COLORSPACE, colorSpace);
                payload.putLong(KEY_ACCESSIBILITY_SCREENSHOT_TIMESTAMP,
                        SystemClock.uptimeMillis());

                // Send back the result.
                callback.sendResult(payload);
                hardwareBuffer.close();
            }, null).recycleOnUse());
        } else {
            final HardwareBuffer hardwareBuffer = screenshotBuffer.getHardwareBuffer();
            final ParcelableColorSpace colorSpace =
                    new ParcelableColorSpace(screenshotBuffer.getColorSpace());

            final Bundle payload = new Bundle();
            payload.putInt(KEY_ACCESSIBILITY_SCREENSHOT_STATUS,
                    AccessibilityService.TAKE_SCREENSHOT_SUCCESS);
            payload.putParcelable(KEY_ACCESSIBILITY_SCREENSHOT_HARDWAREBUFFER,
                    hardwareBuffer);
            payload.putParcelable(KEY_ACCESSIBILITY_SCREENSHOT_COLORSPACE, colorSpace);
            payload.putLong(KEY_ACCESSIBILITY_SCREENSHOT_TIMESTAMP,
                    SystemClock.uptimeMillis());

            // Send back the result.
            callback.sendResult(payload);
            hardwareBuffer.close();
        }
    }

    private void sendScreenshotFailure(@AccessibilityService.ScreenshotErrorCode int errorCode,
            RemoteCallback callback) {
        mMainHandler.post(PooledLambda.obtainRunnable((nonArg) -> {
            final Bundle payload = new Bundle();
            payload.putInt(KEY_ACCESSIBILITY_SCREENSHOT_STATUS, errorCode);
            // Send back the result.
            callback.sendResult(payload);
        }, null).recycleOnUse());
    }

    @Override
    public void dump(FileDescriptor fd, final PrintWriter pw, String[] args) {
        if (!DumpUtils.checkDumpPermission(mContext, LOG_TAG, pw)) return;
        synchronized (mLock) {
            pw.append("Service[label=" + mAccessibilityServiceInfo.getResolveInfo()
                    .loadLabel(mContext.getPackageManager()));
            pw.append(", feedbackType"
                    + AccessibilityServiceInfo.feedbackTypeToString(mFeedbackType));
            pw.append(", capabilities=" + mAccessibilityServiceInfo.getCapabilities());
            pw.append(", eventTypes="
                    + AccessibilityEvent.eventTypeToString(mEventTypes));
            pw.append(", notificationTimeout=" + mNotificationTimeout);
            pw.append(", requestA11yBtn=" + mRequestAccessibilityButton);
            pw.append("]");
        }
    }

    /**
     * Called when the connection is first created. Add a window token for all known displays.
     * <p>
     * <strong>Note:</strong> Should not be called while holding the AccessibilityManagerService
     * lock because this calls out to WindowManagerService.
     */
    void addWindowTokensForAllDisplays() {
        final Display[] displays = mDisplayManager.getDisplays();
        for (int i = 0; i < displays.length; i++) {
            final int displayId = displays[i].getDisplayId();
            addWindowTokenForDisplay(displayId);
        }
    }

    /**
     * Called whenever a logical display has been added to the system. Add a window token for adding
     * an accessibility overlay.
     *
     * <p>
     * <strong>Note:</strong> Should not be called while holding the AccessibilityManagerService
     * lock because this calls out to WindowManagerService.
     *
     * @param displayId The id of the logical display that was added.
     */
    void addWindowTokenForDisplay(int displayId) {
        final long identity = Binder.clearCallingIdentity();
        try {
            final IBinder overlayWindowToken = new Binder();
            if (wmTracingEnabled()) {
                logTraceWM("addWindowToken",
                        overlayWindowToken + ";TYPE_ACCESSIBILITY_OVERLAY;" + displayId + ";null");
            }
            mWindowManagerService.addWindowToken(overlayWindowToken, TYPE_ACCESSIBILITY_OVERLAY,
                    displayId, null /* options */);
            synchronized (mLock) {
                mOverlayWindowTokens.put(displayId, overlayWindowToken);
            }
        } finally {
            Binder.restoreCallingIdentity(identity);
        }
    }

    public void onRemoved() {
        final Display[] displays = mDisplayManager.getDisplays();
        for (int i = 0; i < displays.length; i++) {
            final int displayId = displays[i].getDisplayId();
            onDisplayRemoved(displayId);
        }
        if (com.android.server.accessibility.Flags.cleanupA11yOverlays()) {
            detachAllOverlays();
        }
    }

    /**
     * Called whenever a logical display has been removed from the system. Remove a window token for
     * removing an accessibility overlay.
     *
     * @param displayId The id of the logical display that was added.
     */
    public void onDisplayRemoved(int displayId) {
        final long identity = Binder.clearCallingIdentity();
        if (wmTracingEnabled()) {
            logTraceWM(
                    "addWindowToken", mOverlayWindowTokens.get(displayId) + ";true;" + displayId);
        }
        try {
            mWindowManagerService.removeWindowToken(mOverlayWindowTokens.get(displayId), true,
                    displayId);
            synchronized (mLock) {
                mOverlayWindowTokens.remove(displayId);
            }
        } finally {
            Binder.restoreCallingIdentity(identity);
        }
    }

    /**
     * Gets overlay window token by the display Id.
     *
     * @param displayId The id of the logical display that was added.
     * @return window token.
     */
    @Override
    public IBinder getOverlayWindowToken(int displayId) {
        if (svcConnTracingEnabled()) {
            logTraceSvcConn("getOverlayWindowToken", "displayId=" + displayId);
        }
        synchronized (mLock) {
            final long identity = Binder.clearCallingIdentity();
            try {
                return mOverlayWindowTokens.get(displayId);
            } finally {
                Binder.restoreCallingIdentity(identity);
            }
        }
    }

    /**
     * Gets windowId of given token.
     *
     * @param token The token
     * @return window id
     */
    @Override
    public int getWindowIdForLeashToken(@NonNull IBinder token) {
        if (svcConnTracingEnabled()) {
            logTraceSvcConn("getWindowIdForLeashToken", "token=" + token);
        }
        synchronized (mLock) {
            final long identity = Binder.clearCallingIdentity();
            try {
                return mA11yWindowManager.getWindowIdLocked(token);
            } finally {
                Binder.restoreCallingIdentity(identity);
            }
        }
    }

    public void resetLocked() {
        mSystemSupport.getKeyEventDispatcher().flush(this);
        try {
            // Clear the proxy in the other process so this
            // IAccessibilityServiceConnection can be garbage collected.
            if (mServiceInterface != null) {
                if (svcClientTracingEnabled()) {
                    logTraceSvcClient("init", "null, " + mId + ", null");
                }
                mServiceInterface.init(null, mId, null);
            }
        } catch (RemoteException re) {
                /* ignore */
        }
        if (mService != null) {
            try {
                mService.unlinkToDeath(this, 0);
            } catch (NoSuchElementException e) {
                Slog.e(LOG_TAG, "Failed unregistering death link");
            }
            mService = null;
        }

        mServiceInterface = null;
        mReceivedAccessibilityButtonCallbackSinceBind = false;
    }

    public boolean isConnectedLocked() {
        return (mService != null);
    }

    public void notifyAccessibilityEvent(AccessibilityEvent event) {
        synchronized (mLock) {
            final int eventType = event.getEventType();

            final boolean serviceWantsEvent = wantsEventLocked(event);
            final boolean requiredForCacheConsistency = mUsesAccessibilityCache
                    && ((AccessibilityCache.CACHE_CRITICAL_EVENTS_MASK & eventType) != 0);
            if (!serviceWantsEvent && !requiredForCacheConsistency) {
                return;
            }

            if (!mSecurityPolicy.checkAccessibilityAccess(this)) {
                return;
            }
            // Make a copy since during dispatch it is possible the event to
            // be modified to remove its source if the receiving service does
            // not have permission to access the window content.
            AccessibilityEvent newEvent = AccessibilityEvent.obtain(event);
            Message message;
            if ((mNotificationTimeout > 0)
                    && (eventType != AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED)) {
                // Allow at most one pending event
                final AccessibilityEvent oldEvent = mPendingEvents.get(eventType);
                mPendingEvents.put(eventType, newEvent);
                if (oldEvent != null) {
                    mEventDispatchHandler.removeMessages(eventType);
                    oldEvent.recycle();
                }
                message = mEventDispatchHandler.obtainMessage(eventType);
            } else {
                // Send all messages, bypassing mPendingEvents
                message = mEventDispatchHandler.obtainMessage(eventType, newEvent);
            }
            message.arg1 = serviceWantsEvent ? 1 : 0;

            mEventDispatchHandler.sendMessageDelayed(message, mNotificationTimeout);
        }
    }

    /**
     * Determines if given event can be dispatched to a service based on the package of the
     * event source. Specifically, a service is notified if it is interested in events from the
     * package.
     *
     * @param event The event.
     * @return True if the listener should be notified, false otherwise.
     */
    private boolean wantsEventLocked(AccessibilityEvent event) {

        if (!canReceiveEventsLocked()) {
            return false;
        }

        final boolean includeNotImportantViews = (mFetchFlags
                & AccessibilityNodeInfo.FLAG_SERVICE_REQUESTS_INCLUDE_NOT_IMPORTANT_VIEWS) != 0;
        if ((event.getWindowId() != AccessibilityWindowInfo.UNDEFINED_WINDOW_ID)
                && !event.isImportantForAccessibility()
                && !includeNotImportantViews) {
            return false;
        }

        if (event.isAccessibilityDataSensitive()
                && (mFetchFlags & AccessibilityNodeInfo.FLAG_SERVICE_IS_ACCESSIBILITY_TOOL) == 0) {
            return false;
        }

        int eventType = event.getEventType();
        if ((mEventTypes & eventType) != eventType) {
            return false;
        }

        Set<String> packageNames = mPackageNames;
        String packageName = (event.getPackageName() != null)
                ? event.getPackageName().toString() : null;

        return (packageNames.isEmpty() || packageNames.contains(packageName));
    }

    /**
     * Notifies an accessibility service client for a scheduled event given the event type.
     *
     * @param eventType The type of the event to dispatch.
     */
    private void notifyAccessibilityEventInternal(
            int eventType,
            AccessibilityEvent event,
            boolean serviceWantsEvent) {
        IAccessibilityServiceClient listener;

        synchronized (mLock) {
            listener = mServiceInterface;

            // If the service died/was disabled while the message for dispatching
            // the accessibility event was propagating the listener may be null.
            if (listener == null) {
                return;
            }

            // There are two ways we notify for events, throttled AND non-throttled. If we
            // are not throttling, then messages come with events, which we handle with
            // minimal fuss.
            if (event == null) {
                // We are throttling events, so we'll send the event for this type in
                // mPendingEvents as long as it it's null. It can only null due to a race
                // condition:
                //
                //   1) A binder thread calls notifyAccessibilityServiceDelayedLocked
                //      which posts a message for dispatching an event and stores the event
                //      in mPendingEvents.
                //   2) The message is pulled from the queue by the handler on the service
                //      thread and this method is just about to acquire the lock.
                //   3) Another binder thread acquires the lock in notifyAccessibilityEvent
                //   4) notifyAccessibilityEvent recycles the event that this method was about
                //      to process, replaces it with a new one, and posts a second message
                //   5) This method grabs the new event, processes it, and removes it from
                //      mPendingEvents
                //   6) The second message dispatched in (4) arrives, but the event has been
                //      remvoved in (5).
                event = mPendingEvents.get(eventType);
                if (event == null) {
                    return;
                }
                mPendingEvents.remove(eventType);
            }
            if (mSecurityPolicy.canRetrieveWindowContentLocked(this)) {
                event.setConnectionId(mId);
            } else {
                event.setSource((View) null);
            }
            event.setSealed(true);
        }

        try {
            if (svcClientTracingEnabled()) {
                logTraceSvcClient("onAccessibilityEvent", event + ";" + serviceWantsEvent);
            }
            listener.onAccessibilityEvent(event, serviceWantsEvent);
            if (DEBUG) {
                Slog.i(LOG_TAG, "Event " + event + " sent to " + listener);
            }
        } catch (RemoteException re) {
            Slog.e(LOG_TAG, "Error during sending " + event + " to " + listener, re);
        } finally {
            event.recycle();
        }
    }

    public void notifyGesture(AccessibilityGestureEvent gestureEvent) {
        if (android.view.accessibility.Flags.copyEventsForGestureDetection()) {
            // We will use this event async, so copy it because it contains MotionEvents.
            mInvocationHandler.obtainMessage(InvocationHandler.MSG_ON_GESTURE,
                    gestureEvent.copyForAsync()).sendToTarget();
        } else {
            mInvocationHandler.obtainMessage(InvocationHandler.MSG_ON_GESTURE,
                    gestureEvent).sendToTarget();
        }
    }

    public void notifySystemActionsChangedLocked() {
        mInvocationHandler.sendEmptyMessage(
                InvocationHandler.MSG_ON_SYSTEM_ACTIONS_CHANGED);
    }

    public void notifyClearAccessibilityNodeInfoCache() {
        mInvocationHandler.sendEmptyMessage(
                InvocationHandler.MSG_CLEAR_ACCESSIBILITY_CACHE);
    }

    public void notifyMagnificationChangedLocked(int displayId, @NonNull Region region,
            @NonNull MagnificationConfig config) {
        mInvocationHandler
                .notifyMagnificationChangedLocked(displayId, region, config);
    }

    public void notifySoftKeyboardShowModeChangedLocked(int showState) {
        mInvocationHandler.notifySoftKeyboardShowModeChangedLocked(showState);
    }

    public void notifyAccessibilityButtonClickedLocked(int displayId) {
        mInvocationHandler.notifyAccessibilityButtonClickedLocked(displayId);
    }

    public void notifyAccessibilityButtonAvailabilityChangedLocked(boolean available) {
        mInvocationHandler.notifyAccessibilityButtonAvailabilityChangedLocked(available);
    }

    public void createImeSessionLocked() {
        mInvocationHandler.createImeSessionLocked();
    }

    public void setImeSessionEnabledLocked(IAccessibilityInputMethodSession session,
            boolean enabled) {
        mInvocationHandler.setImeSessionEnabledLocked(session, enabled);
    }

    public void bindInputLocked() {
        mInvocationHandler.bindInputLocked();
    }

    public  void unbindInputLocked() {
        mInvocationHandler.unbindInputLocked();
    }

    public void startInputLocked(IRemoteAccessibilityInputConnection connection,
            EditorInfo editorInfo, boolean restarting) {
        mInvocationHandler.startInputLocked(connection, editorInfo, restarting);
    }

    @Nullable
    private Pair<float[], MagnificationSpec> getWindowTransformationMatrixAndMagnificationSpec(
            int resolvedWindowId) {
        return mSystemSupport.getWindowTransformationMatrixAndMagnificationSpec(resolvedWindowId);
    }

    public boolean wantsGenericMotionEvent(MotionEvent event) {
        final int eventSourceWithoutClass = event.getSource() & ~InputDevice.SOURCE_CLASS_MASK;
        return (mGenericMotionEventSources & eventSourceWithoutClass) != 0;
    }


    /**
     * Called by the invocation handler to notify the service that the
     * state of magnification has changed.
     */
    private void notifyMagnificationChangedInternal(int displayId, @NonNull Region region,
            @NonNull MagnificationConfig config) {
        final IAccessibilityServiceClient listener = getServiceInterfaceSafely();
        if (listener != null) {
            try {
                if (svcClientTracingEnabled()) {
                    logTraceSvcClient("onMagnificationChanged", displayId + ", " + region + ", "
                            + config.toString());
                }
                listener.onMagnificationChanged(displayId, region, config);
            } catch (RemoteException re) {
                Slog.e(LOG_TAG, "Error sending magnification changes to " + mService, re);
            }
        }
    }

    /**
     * Called by the invocation handler to notify the service that the state of the soft
     * keyboard show mode has changed.
     */
    private void notifySoftKeyboardShowModeChangedInternal(int showState) {
        final IAccessibilityServiceClient listener = getServiceInterfaceSafely();
        if (listener != null) {
            try {
                if (svcClientTracingEnabled()) {
                    logTraceSvcClient("onSoftKeyboardShowModeChanged", String.valueOf(showState));
                }
                listener.onSoftKeyboardShowModeChanged(showState);
            } catch (RemoteException re) {
                Slog.e(LOG_TAG, "Error sending soft keyboard show mode changes to " + mService,
                        re);
            }
        }
    }

    private void notifyAccessibilityButtonClickedInternal(int displayId) {
        final IAccessibilityServiceClient listener = getServiceInterfaceSafely();
        if (listener != null) {
            try {
                if (svcClientTracingEnabled()) {
                    logTraceSvcClient("onAccessibilityButtonClicked", String.valueOf(displayId));
                }
                listener.onAccessibilityButtonClicked(displayId);
            } catch (RemoteException re) {
                Slog.e(LOG_TAG, "Error sending accessibility button click to " + mService, re);
            }
        }
    }

    private void notifyAccessibilityButtonAvailabilityChangedInternal(boolean available) {
        // Only notify the service if it's not been notified or the state has changed
        if (mReceivedAccessibilityButtonCallbackSinceBind
                && (mLastAccessibilityButtonCallbackState == available)) {
            return;
        }
        mReceivedAccessibilityButtonCallbackSinceBind = true;
        mLastAccessibilityButtonCallbackState = available;
        final IAccessibilityServiceClient listener = getServiceInterfaceSafely();
        if (listener != null) {
            try {
                if (svcClientTracingEnabled()) {
                    logTraceSvcClient("onAccessibilityButtonAvailabilityChanged",
                            String.valueOf(available));
                }
                listener.onAccessibilityButtonAvailabilityChanged(available);
            } catch (RemoteException re) {
                Slog.e(LOG_TAG,
                        "Error sending accessibility button availability change to " + mService,
                        re);
            }
        }
    }

    private void notifyGestureInternal(AccessibilityGestureEvent gestureInfo) {
        final IAccessibilityServiceClient listener = getServiceInterfaceSafely();
        if (listener != null) {
            try {
                if (svcClientTracingEnabled()) {
                    logTraceSvcClient("onGesture", gestureInfo.toString());
                }
                listener.onGesture(gestureInfo);
            } catch (RemoteException re) {
                Slog.e(LOG_TAG, "Error during sending gesture " + gestureInfo
                        + " to " + mService, re);
            }
        }
    }

    private void notifySystemActionsChangedInternal() {
        final IAccessibilityServiceClient listener = getServiceInterfaceSafely();
        if (listener != null) {
            try {
                if (svcClientTracingEnabled()) {
                    logTraceSvcClient("onSystemActionsChanged", "");
                }
                listener.onSystemActionsChanged();
            } catch (RemoteException re) {
                Slog.e(LOG_TAG, "Error sending system actions change to " + mService,
                        re);
            }
        }
    }

    private void notifyClearAccessibilityCacheInternal() {
        final IAccessibilityServiceClient listener = getServiceInterfaceSafely();
        if (listener != null) {
            try {
                if (svcClientTracingEnabled()) {
                    logTraceSvcClient("clearAccessibilityCache", "");
                }
                listener.clearAccessibilityCache();
            } catch (RemoteException re) {
                Slog.e(LOG_TAG, "Error during requesting accessibility info cache"
                        + " to be cleared.", re);
            }
        }
    }

    protected void createImeSessionInternal() {
    }

    private void setImeSessionEnabledInternal(IAccessibilityInputMethodSession session,
            boolean enabled) {
        final IAccessibilityServiceClient listener = getServiceInterfaceSafely();
        if (listener != null && session != null) {
            try {
                if (svcClientTracingEnabled()) {
                    logTraceSvcClient("createImeSession", "");
                }
                listener.setImeSessionEnabled(session, enabled);
            } catch (RemoteException re) {
                Slog.e(LOG_TAG,
                        "Error requesting IME session from " + mService, re);
            }
        }
    }

    private void bindInputInternal() {
        final IAccessibilityServiceClient listener = getServiceInterfaceSafely();
        if (listener != null) {
            try {
                if (svcClientTracingEnabled()) {
                    logTraceSvcClient("bindInput", "");
                }
                listener.bindInput();
            } catch (RemoteException re) {
                Slog.e(LOG_TAG,
                        "Error binding input to " + mService, re);
            }
        }
    }

    private void unbindInputInternal() {
        final IAccessibilityServiceClient listener = getServiceInterfaceSafely();
        if (listener != null) {
            try {
                if (svcClientTracingEnabled()) {
                    logTraceSvcClient("unbindInput", "");
                }
                listener.unbindInput();
            } catch (RemoteException re) {
                Slog.e(LOG_TAG,
                        "Error unbinding input to " + mService, re);
            }
        }
    }

    private void startInputInternal(IRemoteAccessibilityInputConnection connection,
            EditorInfo editorInfo, boolean restarting) {
        final IAccessibilityServiceClient listener = getServiceInterfaceSafely();
        if (listener != null) {
            try {
                if (svcClientTracingEnabled()) {
                    logTraceSvcClient("startInput", "editorInfo=" + editorInfo
                            + " restarting=" + restarting);
                }
                listener.startInput(connection, editorInfo, restarting);
            } catch (RemoteException re) {
                Slog.e(LOG_TAG,
                        "Error starting input to " + mService, re);
            }
        }
    }

    protected IAccessibilityServiceClient getServiceInterfaceSafely() {
        synchronized (mLock) {
            return mServiceInterface;
        }
    }

    private int resolveAccessibilityWindowIdLocked(int accessibilityWindowId) {
        if (accessibilityWindowId == AccessibilityWindowInfo.ACTIVE_WINDOW_ID) {
            final int focusedWindowId =
                    mA11yWindowManager.getActiveWindowId(mSystemSupport.getCurrentUserIdLocked());
            if (!mA11yWindowManager.windowIdBelongsToDisplayType(focusedWindowId, mDisplayTypes)) {
                return AccessibilityWindowInfo.UNDEFINED_WINDOW_ID;
            }
            return focusedWindowId;
        }
        return accessibilityWindowId;
    }

    int resolveAccessibilityWindowIdForFindFocusLocked(int windowId, int focusType) {
        if (windowId == AccessibilityWindowInfo.ANY_WINDOW_ID) {
            final int focusedWindowId = mA11yWindowManager.getFocusedWindowId(focusType);
            // If the caller is a proxy and the found window doesn't belong to a proxy display
            // (or vice versa), then return null. This doesn't work if there are multiple active
            // proxys, but in the future this code shouldn't be needed if input focus are
            // properly split. (so we will deal with the issues if we see them).
            //TODO(254545943): Remove this when there is user and proxy separation of input focus
            if (!mA11yWindowManager.windowIdBelongsToDisplayType(focusedWindowId, mDisplayTypes)) {
                return AccessibilityWindowInfo.UNDEFINED_WINDOW_ID;
            }
            return focusedWindowId;
        }
        return windowId;
    }

    /**
     * Request that the system make sure windows are available to interrogate.
     *
     * @param displayId The logical display id.
     */
    private void ensureWindowsAvailableTimedLocked(int displayId) {
        if (displayId == Display.INVALID_DISPLAY) {
            return;
        }

        if (mA11yWindowManager.getWindowListLocked(displayId) != null) {
            return;
        }
        // If we have no registered callback, update the state we
        // we may have to register one but it didn't happen yet.
        if (!mA11yWindowManager.isTrackingWindowsLocked(displayId)) {
            // Invokes client change to make sure tracking window enabled.
            mSystemSupport.onClientChangeLocked(false);
        }
        // We have no windows but do not care about them, done.
        if (!mA11yWindowManager.isTrackingWindowsLocked(displayId)) {
            return;
        }

        // Wait for the windows with a timeout.
        final long startMillis = SystemClock.uptimeMillis();
        while (mA11yWindowManager.getWindowListLocked(displayId) == null) {
            final long elapsedMillis = SystemClock.uptimeMillis() - startMillis;
            final long remainMillis = WAIT_WINDOWS_TIMEOUT_MILLIS - elapsedMillis;
            if (remainMillis <= 0) {
                return;
            }
            try {
                mLock.wait(remainMillis);
            } catch (InterruptedException ie) {
                /* ignore */
            }
        }
    }

    /**
     * Perform the specified accessibility action
     *
     * @param resolvedWindowId The window ID
     * [Other parameters match the method on IAccessibilityServiceConnection]
     *
     * @return Whether or not the action could be sent to the app process
     */
    private boolean performAccessibilityActionInternal(int userId, int resolvedWindowId,
            long accessibilityNodeId, int action, Bundle arguments, int interactionId,
            IAccessibilityInteractionConnectionCallback callback, int fetchFlags,
            long interrogatingTid) {
        RemoteAccessibilityConnection connection;
        IBinder windowToken = null;
        synchronized (mLock) {
            connection = mA11yWindowManager.getConnectionLocked(userId, resolvedWindowId);
            if (connection == null)  {
                return false;
            }
            final boolean isA11yFocusAction = (action == ACTION_ACCESSIBILITY_FOCUS)
                    || (action == ACTION_CLEAR_ACCESSIBILITY_FOCUS);
            if (!isA11yFocusAction) {
                windowToken = mA11yWindowManager.getWindowTokenForUserAndWindowIdLocked(
                        userId, resolvedWindowId);
            }
            final AccessibilityWindowInfo a11yWindowInfo =
                    mA11yWindowManager.findA11yWindowInfoByIdLocked(resolvedWindowId);
            if (a11yWindowInfo != null && a11yWindowInfo.isInPictureInPictureMode()
                    && mA11yWindowManager.getPictureInPictureActionReplacingConnection() != null
                    && !isA11yFocusAction) {
                connection = mA11yWindowManager.getPictureInPictureActionReplacingConnection();
            }
        }
        final int interrogatingPid = Binder.getCallingPid();
        final long identityToken = Binder.clearCallingIdentity();
        try {
            // Regardless of whether or not the action succeeds, it was generated by an
            // accessibility service that is driven by user actions, so note user activity.
            mPowerManager.userActivity(SystemClock.uptimeMillis(),
                    PowerManager.USER_ACTIVITY_EVENT_ACCESSIBILITY, 0);

            if (action == ACTION_CLICK || action == ACTION_LONG_CLICK) {
                mA11yWindowManager.notifyOutsideTouch(userId, resolvedWindowId);
            }
            if (windowToken != null) {
                mWindowManagerService.requestWindowFocus(windowToken);
            }
            if (intConnTracingEnabled()) {
                logTraceIntConn("performAccessibilityAction",
                        accessibilityNodeId + ";" + action + ";" + arguments + ";" + interactionId
                        + ";" + callback + ";" + mFetchFlags + ";" + interrogatingPid + ";"
                        + interrogatingTid);
            }
            connection.getRemote().performAccessibilityAction(accessibilityNodeId, action,
                    arguments, interactionId, callback, fetchFlags, interrogatingPid,
                    interrogatingTid);
        } catch (RemoteException re) {
            if (DEBUG) {
                Slog.e(LOG_TAG, "Error calling performAccessibilityAction: " + re);
            }
            return false;
        } finally {
            Binder.restoreCallingIdentity(identityToken);
        }
        return true;
    }

    /**
     * Replace the interaction callback if needed, for example if the window is in picture-
     * in-picture mode and needs its nodes replaced.
     *
     * @param originalCallback The callback we were planning to use
     * @param resolvedWindowId The ID of the window we're calling
     * @param interactionId The id for the original callback
     * @param interrogatingPid Process ID of requester
     * @param interrogatingTid Thread ID of requester
     *
     * @return The callback to use, which may be the original one.
     */
    private IAccessibilityInteractionConnectionCallback replaceCallbackIfNeeded(
            IAccessibilityInteractionConnectionCallback originalCallback, int resolvedWindowId,
            int interactionId, int interrogatingPid, long interrogatingTid) {
        final RemoteAccessibilityConnection pipActionReplacingConnection =
                mA11yWindowManager.getPictureInPictureActionReplacingConnection();
        synchronized (mLock) {
            final AccessibilityWindowInfo windowInfo =
                    mA11yWindowManager.findA11yWindowInfoByIdLocked(resolvedWindowId);
            if ((windowInfo == null) || !windowInfo.isInPictureInPictureMode()
                || (pipActionReplacingConnection == null)) {
                return originalCallback;
            }
        }
        return new ActionReplacingCallback(originalCallback,
                pipActionReplacingConnection.getRemote(), interactionId,
                interrogatingPid, interrogatingTid);
    }

    private List<AccessibilityWindowInfo> getWindowsByDisplayLocked(int displayId) {
        final List<AccessibilityWindowInfo> internalWindowList =
                mA11yWindowManager.getWindowListLocked(displayId);
        if (internalWindowList == null) {
            return null;
        }
        final List<AccessibilityWindowInfo> returnedWindowList = new ArrayList<>();
        final int windowCount = internalWindowList.size();
        for (int i = 0; i < windowCount; i++) {
            AccessibilityWindowInfo window = internalWindowList.get(i);
            AccessibilityWindowInfo windowClone =
                    AccessibilityWindowInfo.obtain(window);
            windowClone.setConnectionId(mId);
            returnedWindowList.add(windowClone);
        }
        return returnedWindowList;
    }

    public ComponentName getComponentName() {
        return mComponentName;
    }

    private final class InvocationHandler extends Handler {
        public static final int MSG_ON_GESTURE = 1;
        public static final int MSG_CLEAR_ACCESSIBILITY_CACHE = 2;

        private static final int MSG_ON_MAGNIFICATION_CHANGED = 5;
        private static final int MSG_ON_SOFT_KEYBOARD_STATE_CHANGED = 6;
        private static final int MSG_ON_ACCESSIBILITY_BUTTON_CLICKED = 7;
        private static final int MSG_ON_ACCESSIBILITY_BUTTON_AVAILABILITY_CHANGED = 8;
        private static final int MSG_ON_SYSTEM_ACTIONS_CHANGED = 9;
        private static final int MSG_CREATE_IME_SESSION = 10;
        private static final int MSG_SET_IME_SESSION_ENABLED = 11;
        private static final int MSG_BIND_INPUT = 12;
        private static final int MSG_UNBIND_INPUT = 13;
        private static final int MSG_START_INPUT = 14;

        /** List of magnification callback states, mapping from displayId -> Boolean */
        @GuardedBy("mlock")
        private final SparseArray<Boolean> mMagnificationCallbackState = new SparseArray<>(0);
        private boolean mIsSoftKeyboardCallbackEnabled = false;

        public InvocationHandler(Looper looper) {
            super(looper, null, true);
        }

        @Override
        public void handleMessage(Message message) {
            final int type = message.what;
            switch (type) {
                case MSG_ON_GESTURE: {
                    if (message.obj instanceof AccessibilityGestureEvent gesture) {
                        notifyGestureInternal(gesture);
                        if (android.view.accessibility.Flags.copyEventsForGestureDetection()) {
                            gesture.recycle();
                        }
                    }
                } break;
                case MSG_CLEAR_ACCESSIBILITY_CACHE: {
                    notifyClearAccessibilityCacheInternal();
                } break;

                case MSG_ON_MAGNIFICATION_CHANGED: {
                    final SomeArgs args = (SomeArgs) message.obj;
                    final Region region = (Region) args.arg1;
                    final MagnificationConfig config = (MagnificationConfig) args.arg2;
                    final int displayId = args.argi1;
                    notifyMagnificationChangedInternal(displayId, region, config);
                    args.recycle();
                } break;

                case MSG_ON_SOFT_KEYBOARD_STATE_CHANGED: {
                    final int showState = (int) message.arg1;
                    notifySoftKeyboardShowModeChangedInternal(showState);
                } break;

                case MSG_ON_ACCESSIBILITY_BUTTON_CLICKED: {
                    final int displayId = (int) message.arg1;
                    notifyAccessibilityButtonClickedInternal(displayId);
                } break;

                case MSG_ON_ACCESSIBILITY_BUTTON_AVAILABILITY_CHANGED: {
                    final boolean available = (message.arg1 != 0);
                    notifyAccessibilityButtonAvailabilityChangedInternal(available);
                } break;
                case MSG_ON_SYSTEM_ACTIONS_CHANGED: {
                    notifySystemActionsChangedInternal();
                    break;
                }
                case MSG_CREATE_IME_SESSION:
                    createImeSessionInternal();
                    break;
                case MSG_SET_IME_SESSION_ENABLED:
                    final boolean enabled = (message.arg1 != 0);
                    final IAccessibilityInputMethodSession session =
                            (IAccessibilityInputMethodSession) message.obj;
                    setImeSessionEnabledInternal(session, enabled);
                    break;
                case MSG_BIND_INPUT:
                    bindInputInternal();
                    break;
                case MSG_UNBIND_INPUT:
                    unbindInputInternal();
                    break;
                case MSG_START_INPUT:
                    final boolean restarting = (message.arg1 != 0);
                    final SomeArgs args = (SomeArgs) message.obj;
                    final IRemoteAccessibilityInputConnection connection =
                            (IRemoteAccessibilityInputConnection) args.arg1;
                    final EditorInfo editorInfo = (EditorInfo) args.arg2;
                    startInputInternal(connection, editorInfo, restarting);
                    args.recycle();
                    break;
                default: {
                    throw new IllegalArgumentException("Unknown message: " + type);
                }
            }
        }

        public void notifyMagnificationChangedLocked(int displayId, @NonNull Region region,
                @NonNull MagnificationConfig config) {
            synchronized (mLock) {
                if (mMagnificationCallbackState.get(displayId) == null) {
                    return;
                }
            }

            final SomeArgs args = SomeArgs.obtain();
            args.arg1 = region;
            args.arg2 = config;
            args.argi1 = displayId;

            final Message msg = obtainMessage(MSG_ON_MAGNIFICATION_CHANGED, args);
            msg.sendToTarget();
        }

        public void setMagnificationCallbackEnabled(int displayId, boolean enabled) {
            synchronized (mLock) {
                if (enabled) {
                    mMagnificationCallbackState.put(displayId, true);
                } else {
                    mMagnificationCallbackState.remove(displayId);
                }
            }
        }

        public boolean isMagnificationCallbackEnabled(int displayId) {
            synchronized (mLock) {
                return mMagnificationCallbackState.get(displayId) != null;
            }
        }

        public void notifySoftKeyboardShowModeChangedLocked(int showState) {
            if (!mIsSoftKeyboardCallbackEnabled) {
                return;
            }

            final Message msg = obtainMessage(MSG_ON_SOFT_KEYBOARD_STATE_CHANGED, showState, 0);
            msg.sendToTarget();
        }

        public void setSoftKeyboardCallbackEnabled(boolean enabled) {
            mIsSoftKeyboardCallbackEnabled = enabled;
        }

        public void notifyAccessibilityButtonClickedLocked(int displayId) {
            final Message msg = obtainMessage(MSG_ON_ACCESSIBILITY_BUTTON_CLICKED, displayId, 0);
            msg.sendToTarget();
        }

        public void notifyAccessibilityButtonAvailabilityChangedLocked(boolean available) {
            final Message msg = obtainMessage(MSG_ON_ACCESSIBILITY_BUTTON_AVAILABILITY_CHANGED,
                    (available ? 1 : 0), 0);
            msg.sendToTarget();
        }

        public void createImeSessionLocked() {
            final Message msg = obtainMessage(MSG_CREATE_IME_SESSION);
            msg.sendToTarget();
        }

        public void setImeSessionEnabledLocked(IAccessibilityInputMethodSession session,
                boolean enabled) {
            final Message msg = obtainMessage(MSG_SET_IME_SESSION_ENABLED, (enabled ? 1 : 0),
                    0, session);
            msg.sendToTarget();
        }

        public void bindInputLocked() {
            final Message msg = obtainMessage(MSG_BIND_INPUT);
            msg.sendToTarget();
        }

        public void unbindInputLocked() {
            final Message msg = obtainMessage(MSG_UNBIND_INPUT);
            msg.sendToTarget();
        }

        public void startInputLocked(
                IRemoteAccessibilityInputConnection connection,
                EditorInfo editorInfo, boolean restarting) {
            final SomeArgs args = SomeArgs.obtain();
            args.arg1 = connection;
            args.arg2 = editorInfo;
            final Message msg = obtainMessage(MSG_START_INPUT, restarting ? 1 : 0, 0, args);
            msg.sendToTarget();
        }
    }

    public boolean isServiceHandlesDoubleTapEnabled() {
        return mServiceHandlesDoubleTap;
    }

    public boolean isMultiFingerGesturesEnabled() {
        return mRequestMultiFingerGestures;
    }

    public boolean isTwoFingerPassthroughEnabled() {
        return mRequestTwoFingerPassthrough;
    }

    public boolean isSendMotionEventsEnabled() {
        return mSendMotionEvents;
    }

    @Override
    public void setGestureDetectionPassthroughRegion(int displayId, Region region) {
        if (svcConnTracingEnabled()) {
            logTraceSvcConn("setGestureDetectionPassthroughRegion",
                    "displayId=" + displayId + ";region=" + region);
        }
        final long identity = Binder.clearCallingIdentity();
        try {
            mSystemSupport.setGestureDetectionPassthroughRegion(displayId, region);
        } finally {
            Binder.restoreCallingIdentity(identity);
        }
    }

    @Override
    public void setTouchExplorationPassthroughRegion(int displayId, Region region) {
        if (svcConnTracingEnabled()) {
            logTraceSvcConn("setTouchExplorationPassthroughRegion",
                    "displayId=" + displayId + ";region=" + region);
        }
        final long identity = Binder.clearCallingIdentity();
        try {
            mSystemSupport.setTouchExplorationPassthroughRegion(displayId, region);
        } finally {
            Binder.restoreCallingIdentity(identity);
        }
    }

    @Override
    public void setFocusAppearance(int strokeWidth, int color) {
        if (svcConnTracingEnabled()) {
            logTraceSvcConn("setFocusAppearance", "strokeWidth=" + strokeWidth + ";color=" + color);
        }
    }

    @Override
    public void setCacheEnabled(boolean enabled) {
        if (svcConnTracingEnabled()) {
            logTraceSvcConn("setCacheEnabled", "enabled=" + enabled);
        }
        final long identity = Binder.clearCallingIdentity();
        try {
            synchronized (mLock) {
                mUsesAccessibilityCache = enabled;
                mSystemSupport.onClientChangeLocked(true);
            }
        } finally {
            Binder.restoreCallingIdentity(identity);
        }
    }

    @Override
    public void logTrace(long timestamp, String where, long loggingTypes, String callingParams,
            int processId, long threadId, int callingUid, Bundle callingStack) {
        final long identity = Binder.clearCallingIdentity();
        try {
            if (mTrace.isA11yTracingEnabledForTypes(loggingTypes)) {
                ArrayList<StackTraceElement> list =
                        (ArrayList<StackTraceElement>) callingStack.getSerializable(CALL_STACK,
                                java.util.ArrayList.class);
                HashSet<String> ignoreList =
                        (HashSet<String>) callingStack.getSerializable(IGNORE_CALL_STACK,
                                java.util.HashSet.class);
                mTrace.logTrace(timestamp, where, loggingTypes, callingParams, processId, threadId,
                        callingUid, list.toArray(new StackTraceElement[list.size()]), ignoreList);
            }
        } finally {
            Binder.restoreCallingIdentity(identity);
        }
    }

    protected boolean svcClientTracingEnabled() {
        return mTrace.isA11yTracingEnabledForTypes(FLAGS_ACCESSIBILITY_SERVICE_CLIENT);
    }

    protected void logTraceSvcClient(String methodName, String params) {
        mTrace.logTrace(TRACE_SVC_CLIENT + "." + methodName,
                    FLAGS_ACCESSIBILITY_SERVICE_CLIENT, params);
    }

    protected boolean svcConnTracingEnabled() {
        return mTrace.isA11yTracingEnabledForTypes(FLAGS_ACCESSIBILITY_SERVICE_CONNECTION);
    }

    protected void logTraceSvcConn(String methodName, String params) {
        mTrace.logTrace(TRACE_SVC_CONN + "." + methodName,
                FLAGS_ACCESSIBILITY_SERVICE_CONNECTION, params);
    }

    protected boolean intConnTracingEnabled() {
        return mTrace.isA11yTracingEnabledForTypes(FLAGS_ACCESSIBILITY_INTERACTION_CONNECTION);
    }

    protected void logTraceIntConn(String methodName, String params) {
        mTrace.logTrace(LOG_TAG + "." + methodName,
                FLAGS_ACCESSIBILITY_INTERACTION_CONNECTION, params);
    }

    protected boolean wmTracingEnabled() {
        return mTrace.isA11yTracingEnabledForTypes(FLAGS_WINDOW_MANAGER_INTERNAL);
    }

    protected void logTraceWM(String methodName, String params) {
        mTrace.logTrace(TRACE_WM + "." + methodName, FLAGS_WINDOW_MANAGER_INTERNAL, params);
    }

    @Override
    public void setServiceDetectsGesturesEnabled(int displayId, boolean mode) {
        final long identity = Binder.clearCallingIdentity();
        try {
            mServiceDetectsGestures.put(displayId, mode);
            mSystemSupport.setServiceDetectsGesturesEnabled(displayId, mode);
        } finally {
            Binder.restoreCallingIdentity(identity);
        }
    }

    public boolean isServiceDetectsGesturesEnabled(int displayId) {
        if (mServiceDetectsGestures.contains(displayId)) {
            return mServiceDetectsGestures.get(displayId);
        }
        return false;
    }

    @Override
    public void requestTouchExploration(int displayId) {
        final long identity = Binder.clearCallingIdentity();
        try {
            mSystemSupport.requestTouchExploration(displayId);
        } finally {
            Binder.restoreCallingIdentity(identity);
        }
    }

    @Override
    public void requestDragging(int displayId, int pointerId) {
        final long identity = Binder.clearCallingIdentity();
        try {
            mSystemSupport.requestDragging(displayId, pointerId);
        } finally {
            Binder.restoreCallingIdentity(identity);
        }
    }

    @Override
    public void requestDelegating(int displayId) {
        final long identity = Binder.clearCallingIdentity();
        try {
            mSystemSupport.requestDelegating(displayId);
        } finally {
            Binder.restoreCallingIdentity(identity);
        }
    }

    @Override
    public void onDoubleTap(int displayId) {
        final long identity = Binder.clearCallingIdentity();
        try {
            mSystemSupport.onDoubleTap(displayId);
        } finally {
            Binder.restoreCallingIdentity(identity);
        }
    }

    @Override
    public void onDoubleTapAndHold(int displayId) {
        final long identity = Binder.clearCallingIdentity();
        try {
            mSystemSupport.onDoubleTapAndHold(displayId);
        } finally {
            Binder.restoreCallingIdentity(identity);
        }
    }

    /**
     * Sets the scaling factor for animations.
     */
    @Override
    public void setAnimationScale(float scale) {
        final long identity = Binder.clearCallingIdentity();
        try {
            Settings.Global.putFloat(
                    mContext.getContentResolver(), Settings.Global.WINDOW_ANIMATION_SCALE, scale);
            Settings.Global.putFloat(
                    mContext.getContentResolver(),
                    Settings.Global.TRANSITION_ANIMATION_SCALE,
                    scale);
            Settings.Global.putFloat(
                    mContext.getContentResolver(), Settings.Global.ANIMATOR_DURATION_SCALE, scale);
        } finally {
            Binder.restoreCallingIdentity(identity);
        }
    }

    @Override
    public void attachAccessibilityOverlayToDisplay(
            int interactionId,
            int displayId,
            SurfaceControl sc,
            IAccessibilityInteractionConnectionCallback callback) {
        final long identity = Binder.clearCallingIdentity();
        try {
            mSystemSupport.attachAccessibilityOverlayToDisplay(
                    interactionId, displayId, sc, callback);
            mOverlays.add(sc);
        } finally {
            Binder.restoreCallingIdentity(identity);
        }
    }

    @Override
    public void attachAccessibilityOverlayToWindow(
            int interactionId,
            int accessibilityWindowId,
            SurfaceControl sc,
            IAccessibilityInteractionConnectionCallback callback)
            throws RemoteException {
        final long identity = Binder.clearCallingIdentity();
        try {
            SurfaceControl.Transaction t = new SurfaceControl.Transaction();
            t.setTrustedOverlay(sc, true).apply();
            t.close();
            synchronized (mLock) {
                RemoteAccessibilityConnection connection =
                        mA11yWindowManager.getConnectionLocked(
                                mSystemSupport.getCurrentUserIdLocked(),
                                resolveAccessibilityWindowIdLocked(accessibilityWindowId));
                if (connection == null) {
                    callback.sendAttachOverlayResult(
                            AccessibilityService.OVERLAY_RESULT_INVALID, interactionId);
                    return;
                }
                connection
                        .getRemote()
                        .attachAccessibilityOverlayToWindow(sc, interactionId, callback);
                mOverlays.add(sc);
            }

        } finally {
            Binder.restoreCallingIdentity(identity);
        }
    }

    protected void detachAllOverlays() {
        SurfaceControl.Transaction t = new SurfaceControl.Transaction();
        for (SurfaceControl sc : mOverlays) {
            if (sc.isValid()) {
                t.reparent(sc, null);
            }
        }
        t.apply();
        t.close();
        mOverlays.clear();
    }
}
