/*
 ** 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.AccessibilityServiceInfo.DEFAULT;
import static android.view.Display.DEFAULT_DISPLAY;
import static android.view.WindowManager.LayoutParams.TYPE_ACCESSIBILITY_OVERLAY;

import android.accessibilityservice.AccessibilityServiceInfo;
import android.accessibilityservice.IAccessibilityServiceClient;
import android.accessibilityservice.IAccessibilityServiceConnection;
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.Region;
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.RemoteException;
import android.util.Slog;
import android.util.SparseArray;
import android.view.KeyEvent;
import android.view.MagnificationSpec;
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.IAccessibilityInteractionConnection;
import android.view.accessibility.IAccessibilityInteractionConnectionCallback;

import com.android.internal.annotations.GuardedBy;
import com.android.internal.os.SomeArgs;
import com.android.internal.util.DumpUtils;
import com.android.server.accessibility.AccessibilityManagerService.RemoteAccessibilityConnection;
import com.android.server.accessibility.AccessibilityManagerService.SecurityPolicy;
import com.android.server.wm.WindowManagerInternal;

import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
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.
 */
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";

    protected final Context mContext;
    protected final SystemSupport mSystemSupport;
    private final WindowManagerInternal mWindowManagerService;
    private final GlobalActionPerformer mGlobalActionPerformer;

    // 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 SecurityPolicy mSecurityPolicy;

    // 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;

    boolean mRequestFilterKeyEvents;

    boolean mRetrieveInteractiveWindows;

    boolean mCaptureFingerprintGestures;

    boolean mRequestAccessibilityButton;

    boolean mReceivedAccessibilityButtonCallbackSinceBind;

    boolean mLastAccessibilityButtonCallbackState;

    int mFetchFlags;

    long mNotificationTimeout;

    final ComponentName mComponentName;

    // 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 IBinder mOverlayWindowToken = new Binder();


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

        /**
         * @param windowId The id of the window of interest
         * @return The magnification spec for the window, or {@code null} if none is available
         */
        @Nullable MagnificationSpec getCompatibleMagnificationSpecLocked(int windowId);

        /**
         * @return The current injector of motion events, if one exists
         */
        @Nullable MotionEventInjector getMotionEventInjectorLocked();

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

        /**
         * @return The magnification controller
         */
        @NonNull MagnificationController getMagnificationController();

        /**
         * Resolve a connection wrapper for a window id
         *
         * @param windowId The id of the window of interest
         *
         * @return a connection to the window
         */
        RemoteAccessibilityConnection getConnectionLocked(int windowId);

        /**
         * 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
         */
        boolean performAccessibilityAction(int resolvedWindowId,
                long accessibilityNodeId, int action, Bundle arguments, int interactionId,
                IAccessibilityInteractionConnectionCallback callback, int fetchFlags,
                long interrogatingTid);

        /**
         * 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.
         */
        @NonNull IAccessibilityInteractionConnectionCallback replaceCallbackIfNeeded(
                IAccessibilityInteractionConnectionCallback originalCallback,
                int resolvedWindowId, int interactionId, int interrogatingPid,
                long interrogatingTid);

        /**
         * Request that the system make sure windows are available to interrogate
         */
        void ensureWindowsAvailableTimed();

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

        int getCurrentUserIdLocked();

        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);
    }

    public AbstractAccessibilityServiceConnection(Context context, ComponentName componentName,
            AccessibilityServiceInfo accessibilityServiceInfo, int id, Handler mainHandler,
            Object lock, SecurityPolicy securityPolicy, SystemSupport systemSupport,
            WindowManagerInternal windowManagerInternal,
            GlobalActionPerformer globalActionPerfomer) {
        mContext = context;
        mWindowManagerService = windowManagerInternal;
        mId = id;
        mComponentName = componentName;
        mAccessibilityServiceInfo = accessibilityServiceInfo;
        mLock = lock;
        mSecurityPolicy = securityPolicy;
        mGlobalActionPerformer = globalActionPerfomer;
        mSystemSupport = systemSupport;
        mInvocationHandler = new InvocationHandler(mainHandler.getLooper());
        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 {
            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;
        if (packageNames != null) {
            mPackageNames.addAll(Arrays.asList(packageNames));
        }
        mNotificationTimeout = info.notificationTimeout;
        mIsDefault = (info.flags & DEFAULT) != 0;

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

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

        mRequestTouchExplorationMode = (info.flags
                & AccessibilityServiceInfo.FLAG_REQUEST_TOUCH_EXPLORATION_MODE) != 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;
    }

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

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

    @Override
    public void setOnKeyEventResult(boolean handled, int sequence) {
        mSystemSupport.getKeyEventDispatcher().setOnKeyEventResult(this, handled, sequence);
    }

    @Override
    public AccessibilityServiceInfo 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) {
        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.
                AccessibilityServiceInfo oldInfo = mAccessibilityServiceInfo;
                if (oldInfo != null) {
                    oldInfo.updateDynamicallyConfigurableProperties(info);
                    setDynamicallyConfigurableProperties(oldInfo);
                } else {
                    setDynamicallyConfigurableProperties(info);
                }
                mSystemSupport.onClientChangeLocked(true);
            }
        } finally {
            Binder.restoreCallingIdentity(identity);
        }
    }

    protected abstract boolean isCalledForCurrentUserLocked();

    @Override
    public List<AccessibilityWindowInfo> getWindows() {
        mSystemSupport.ensureWindowsAvailableTimed();
        synchronized (mLock) {
            if (!isCalledForCurrentUserLocked()) {
                return null;
            }
            final boolean permissionGranted =
                    mSecurityPolicy.canRetrieveWindowsLocked(this);
            if (!permissionGranted) {
                return null;
            }
            if (mSecurityPolicy.mWindows == null) {
                return null;
            }
            if (!mSecurityPolicy.checkAccessibilityAccess(this)) {
                return null;
            }
            List<AccessibilityWindowInfo> windows = new ArrayList<>();
            final int windowCount = mSecurityPolicy.mWindows.size();
            for (int i = 0; i < windowCount; i++) {
                AccessibilityWindowInfo window = mSecurityPolicy.mWindows.get(i);
                AccessibilityWindowInfo windowClone =
                        AccessibilityWindowInfo.obtain(window);
                windowClone.setConnectionId(mId);
                windows.add(windowClone);
            }
            return windows;
        }
    }

    @Override
    public AccessibilityWindowInfo getWindow(int windowId) {
        mSystemSupport.ensureWindowsAvailableTimed();
        synchronized (mLock) {
            if (!isCalledForCurrentUserLocked()) {
                return null;
            }
            final boolean permissionGranted =
                    mSecurityPolicy.canRetrieveWindowsLocked(this);
            if (!permissionGranted) {
                return null;
            }
            if (!mSecurityPolicy.checkAccessibilityAccess(this)) {
                return null;
            }
            AccessibilityWindowInfo window = mSecurityPolicy.findA11yWindowInfoById(windowId);
            if (window != null) {
                AccessibilityWindowInfo windowClone = AccessibilityWindowInfo.obtain(window);
                windowClone.setConnectionId(mId);
                return windowClone;
            }
            return null;
        }
    }

    @Override
    public String[] findAccessibilityNodeInfosByViewId(int accessibilityWindowId,
            long accessibilityNodeId, String viewIdResName, int interactionId,
            IAccessibilityInteractionConnectionCallback callback, long interrogatingTid)
            throws RemoteException {
        final int resolvedWindowId;
        RemoteAccessibilityConnection connection;
        Region partialInteractiveRegion = Region.obtain();
        MagnificationSpec spec;
        synchronized (mLock) {
            mUsesAccessibilityCache = true;
            if (!isCalledForCurrentUserLocked()) {
                return null;
            }
            resolvedWindowId = resolveAccessibilityWindowIdLocked(accessibilityWindowId);
            final boolean permissionGranted =
                    mSecurityPolicy.canGetAccessibilityNodeInfoLocked(this, resolvedWindowId);
            if (!permissionGranted) {
                return null;
            } else {
                connection = mSystemSupport.getConnectionLocked(resolvedWindowId);
                if (connection == null) {
                    return null;
                }
            }
            if (!mSecurityPolicy.computePartialInteractiveRegionForWindowLocked(
                    resolvedWindowId, partialInteractiveRegion)) {
                partialInteractiveRegion.recycle();
                partialInteractiveRegion = null;
            }
            spec = mSystemSupport.getCompatibleMagnificationSpecLocked(resolvedWindowId);
        }
        if (!mSecurityPolicy.checkAccessibilityAccess(this)) {
            return null;
        }
        final int interrogatingPid = Binder.getCallingPid();
        callback = mSystemSupport.replaceCallbackIfNeeded(callback, resolvedWindowId, interactionId,
                interrogatingPid, interrogatingTid);
        final long identityToken = Binder.clearCallingIdentity();
        try {
            connection.getRemote().findAccessibilityNodeInfosByViewId(accessibilityNodeId,
                    viewIdResName, partialInteractiveRegion, interactionId, callback, mFetchFlags,
                    interrogatingPid, interrogatingTid, spec);
            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 {
        final int resolvedWindowId;
        RemoteAccessibilityConnection connection;
        Region partialInteractiveRegion = Region.obtain();
        MagnificationSpec spec;
        synchronized (mLock) {
            mUsesAccessibilityCache = true;
            if (!isCalledForCurrentUserLocked()) {
                return null;
            }
            resolvedWindowId = resolveAccessibilityWindowIdLocked(accessibilityWindowId);
            final boolean permissionGranted =
                    mSecurityPolicy.canGetAccessibilityNodeInfoLocked(this, resolvedWindowId);
            if (!permissionGranted) {
                return null;
            } else {
                connection = mSystemSupport.getConnectionLocked(resolvedWindowId);
                if (connection == null) {
                    return null;
                }
            }
            if (!mSecurityPolicy.computePartialInteractiveRegionForWindowLocked(
                    resolvedWindowId, partialInteractiveRegion)) {
                partialInteractiveRegion.recycle();
                partialInteractiveRegion = null;
            }
            spec = mSystemSupport.getCompatibleMagnificationSpecLocked(resolvedWindowId);
        }
        if (!mSecurityPolicy.checkAccessibilityAccess(this)) {
            return null;
        }
        final int interrogatingPid = Binder.getCallingPid();
        callback = mSystemSupport.replaceCallbackIfNeeded(callback, resolvedWindowId, interactionId,
                interrogatingPid, interrogatingTid);
        final long identityToken = Binder.clearCallingIdentity();
        try {
            connection.getRemote().findAccessibilityNodeInfosByText(accessibilityNodeId,
                    text, partialInteractiveRegion, interactionId, callback, mFetchFlags,
                    interrogatingPid, interrogatingTid, spec);
            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 {
        final int resolvedWindowId;
        RemoteAccessibilityConnection connection;
        Region partialInteractiveRegion = Region.obtain();
        MagnificationSpec spec;
        synchronized (mLock) {
            mUsesAccessibilityCache = true;
            if (!isCalledForCurrentUserLocked()) {
                return null;
            }
            resolvedWindowId = resolveAccessibilityWindowIdLocked(accessibilityWindowId);
            final boolean permissionGranted =
                    mSecurityPolicy.canGetAccessibilityNodeInfoLocked(this, resolvedWindowId);
            if (!permissionGranted) {
                return null;
            } else {
                connection = mSystemSupport.getConnectionLocked(resolvedWindowId);
                if (connection == null) {
                    return null;
                }
            }
            if (!mSecurityPolicy.computePartialInteractiveRegionForWindowLocked(
                    resolvedWindowId, partialInteractiveRegion)) {
                partialInteractiveRegion.recycle();
                partialInteractiveRegion = null;
            }
            spec = mSystemSupport.getCompatibleMagnificationSpecLocked(resolvedWindowId);
        }
        if (!mSecurityPolicy.checkAccessibilityAccess(this)) {
            return null;
        }
        final int interrogatingPid = Binder.getCallingPid();
        callback = mSystemSupport.replaceCallbackIfNeeded(callback, resolvedWindowId, interactionId,
                interrogatingPid, interrogatingTid);
        final long identityToken = Binder.clearCallingIdentity();
        try {
            connection.getRemote().findAccessibilityNodeInfoByAccessibilityId(
                    accessibilityNodeId, partialInteractiveRegion, interactionId, callback,
                    mFetchFlags | flags, interrogatingPid, interrogatingTid, spec, 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 {
        final int resolvedWindowId;
        RemoteAccessibilityConnection connection;
        Region partialInteractiveRegion = Region.obtain();
        MagnificationSpec spec;
        synchronized (mLock) {
            if (!isCalledForCurrentUserLocked()) {
                return null;
            }
            resolvedWindowId = resolveAccessibilityWindowIdForFindFocusLocked(
                    accessibilityWindowId, focusType);
            final boolean permissionGranted =
                    mSecurityPolicy.canGetAccessibilityNodeInfoLocked(this, resolvedWindowId);
            if (!permissionGranted) {
                return null;
            } else {
                connection = mSystemSupport.getConnectionLocked(resolvedWindowId);
                if (connection == null) {
                    return null;
                }
            }
            if (!mSecurityPolicy.computePartialInteractiveRegionForWindowLocked(
                    resolvedWindowId, partialInteractiveRegion)) {
                partialInteractiveRegion.recycle();
                partialInteractiveRegion = null;
            }
            spec = mSystemSupport.getCompatibleMagnificationSpecLocked(resolvedWindowId);
        }
        if (!mSecurityPolicy.checkAccessibilityAccess(this)) {
            return null;
        }
        final int interrogatingPid = Binder.getCallingPid();
        callback = mSystemSupport.replaceCallbackIfNeeded(callback, resolvedWindowId, interactionId,
                interrogatingPid, interrogatingTid);
        final long identityToken = Binder.clearCallingIdentity();
        try {
            connection.getRemote().findFocus(accessibilityNodeId, focusType,
                    partialInteractiveRegion, interactionId, callback, mFetchFlags,
                    interrogatingPid, interrogatingTid, spec);
            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 {
        final int resolvedWindowId;
        RemoteAccessibilityConnection connection;
        Region partialInteractiveRegion = Region.obtain();
        MagnificationSpec spec;
        synchronized (mLock) {
            if (!isCalledForCurrentUserLocked()) {
                return null;
            }
            resolvedWindowId = resolveAccessibilityWindowIdLocked(accessibilityWindowId);
            final boolean permissionGranted =
                    mSecurityPolicy.canGetAccessibilityNodeInfoLocked(this, resolvedWindowId);
            if (!permissionGranted) {
                return null;
            } else {
                connection = mSystemSupport.getConnectionLocked(resolvedWindowId);
                if (connection == null) {
                    return null;
                }
            }
            if (!mSecurityPolicy.computePartialInteractiveRegionForWindowLocked(
                    resolvedWindowId, partialInteractiveRegion)) {
                partialInteractiveRegion.recycle();
                partialInteractiveRegion = null;
            }
            spec = mSystemSupport.getCompatibleMagnificationSpecLocked(resolvedWindowId);
        }
        if (!mSecurityPolicy.checkAccessibilityAccess(this)) {
            return null;
        }
        final int interrogatingPid = Binder.getCallingPid();
        callback = mSystemSupport.replaceCallbackIfNeeded(callback, resolvedWindowId, interactionId,
                interrogatingPid, interrogatingTid);
        final long identityToken = Binder.clearCallingIdentity();
        try {
            connection.getRemote().focusSearch(accessibilityNodeId, direction,
                    partialInteractiveRegion, interactionId, callback, mFetchFlags,
                    interrogatingPid, interrogatingTid, spec);
            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) {
    }

    @Override
    public boolean performAccessibilityAction(int accessibilityWindowId,
            long accessibilityNodeId, int action, Bundle arguments, int interactionId,
            IAccessibilityInteractionConnectionCallback callback, long interrogatingTid)
            throws RemoteException {
        final int resolvedWindowId;
        IAccessibilityInteractionConnection connection = null;
        synchronized (mLock) {
            if (!isCalledForCurrentUserLocked()) {
                return false;
            }
            resolvedWindowId = resolveAccessibilityWindowIdLocked(accessibilityWindowId);
            if (!mSecurityPolicy.canGetAccessibilityNodeInfoLocked(this, resolvedWindowId)) {
                return false;
            }
        }
        if (!mSecurityPolicy.checkAccessibilityAccess(this)) {
            return false;
        }
        boolean returnValue =
                mSystemSupport.performAccessibilityAction(resolvedWindowId, accessibilityNodeId,
                action, arguments, interactionId, callback, mFetchFlags, interrogatingTid);
        return returnValue;
    }

    @Override
    public boolean performGlobalAction(int action) {
        synchronized (mLock) {
            if (!isCalledForCurrentUserLocked()) {
                return false;
            }
        }
        return mGlobalActionPerformer.performGlobalAction(action);
    }

    @Override
    public boolean isFingerprintGestureDetectionAvailable() {
        if (!mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_FINGERPRINT)) {
            return false;
        }
        if (isCapturingFingerprintGestures()) {
            FingerprintGestureDispatcher dispatcher =
                    mSystemSupport.getFingerprintGestureDispatcher();
            return (dispatcher != null) && dispatcher.isFingerprintGestureDetectionAvailable();
        }
        return false;
    }

    @Override
    public float getMagnificationScale(int displayId) {
        synchronized (mLock) {
            if (!isCalledForCurrentUserLocked()) {
                return 1.0f;
            }
        }
        final long identity = Binder.clearCallingIdentity();
        try {
            return mSystemSupport.getMagnificationController().getScale(displayId);
        } finally {
            Binder.restoreCallingIdentity(identity);
        }
    }

    @Override
    public Region getMagnificationRegion(int displayId) {
        synchronized (mLock) {
            final Region region = Region.obtain();
            if (!isCalledForCurrentUserLocked()) {
                return region;
            }
            MagnificationController magnificationController =
                    mSystemSupport.getMagnificationController();
            boolean registeredJustForThisCall =
                    registerMagnificationIfNeeded(displayId, magnificationController);
            final long identity = Binder.clearCallingIdentity();
            try {
                magnificationController.getMagnificationRegion(displayId, region);
                return region;
            } finally {
                Binder.restoreCallingIdentity(identity);
                if (registeredJustForThisCall) {
                    magnificationController.unregister(displayId);
                }
            }
        }
    }

    @Override
    public float getMagnificationCenterX(int displayId) {
        synchronized (mLock) {
            if (!isCalledForCurrentUserLocked()) {
                return 0.0f;
            }
            MagnificationController magnificationController =
                    mSystemSupport.getMagnificationController();
            boolean registeredJustForThisCall =
                    registerMagnificationIfNeeded(displayId, magnificationController);
            final long identity = Binder.clearCallingIdentity();
            try {
                return magnificationController.getCenterX(displayId);
            } finally {
                Binder.restoreCallingIdentity(identity);
                if (registeredJustForThisCall) {
                    magnificationController.unregister(displayId);
                }
            }
        }
    }

    @Override
    public float getMagnificationCenterY(int displayId) {
        synchronized (mLock) {
            if (!isCalledForCurrentUserLocked()) {
                return 0.0f;
            }
            MagnificationController magnificationController =
                    mSystemSupport.getMagnificationController();
            boolean registeredJustForThisCall =
                    registerMagnificationIfNeeded(displayId, magnificationController);
            final long identity = Binder.clearCallingIdentity();
            try {
                return magnificationController.getCenterY(displayId);
            } finally {
                Binder.restoreCallingIdentity(identity);
                if (registeredJustForThisCall) {
                    magnificationController.unregister(displayId);
                }
            }
        }
    }

    private boolean registerMagnificationIfNeeded(int displayId,
            MagnificationController magnificationController) {
        if (!magnificationController.isRegistered(displayId)
                && mSecurityPolicy.canControlMagnification(this)) {
            magnificationController.register(displayId);
            return true;
        }
        return false;
    }

    @Override
    public boolean resetMagnification(int displayId, boolean animate) {
        synchronized (mLock) {
            if (!isCalledForCurrentUserLocked()) {
                return false;
            }
            if (!mSecurityPolicy.canControlMagnification(this)) {
                return false;
            }
        }
        final long identity = Binder.clearCallingIdentity();
        try {
            MagnificationController magnificationController =
                    mSystemSupport.getMagnificationController();
            return (magnificationController.reset(displayId, animate)
                    || !magnificationController.isMagnifying(displayId));
        } finally {
            Binder.restoreCallingIdentity(identity);
        }
    }

    @Override
    public boolean setMagnificationScaleAndCenter(int displayId, float scale, float centerX,
            float centerY, boolean animate) {
        synchronized (mLock) {
            if (!isCalledForCurrentUserLocked()) {
                return false;
            }
            if (!mSecurityPolicy.canControlMagnification(this)) {
                return false;
            }
            final long identity = Binder.clearCallingIdentity();
            try {
                MagnificationController magnificationController =
                        mSystemSupport.getMagnificationController();
                if (!magnificationController.isRegistered(displayId)) {
                    magnificationController.register(displayId);
                }
                return magnificationController
                        .setScaleAndCenter(displayId, scale, centerX, centerY, animate, mId);
            } finally {
                Binder.restoreCallingIdentity(identity);
            }
        }
    }

    @Override
    public void setMagnificationCallbackEnabled(int displayId, boolean enabled) {
        mInvocationHandler.setMagnificationCallbackEnabled(displayId, enabled);
    }

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

    @Override
    public void setSoftKeyboardCallbackEnabled(boolean enabled) {
        mInvocationHandler.setSoftKeyboardCallbackEnabled(enabled);
    }

    @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("]");
        }
    }

    public void onAdded() {
        final long identity = Binder.clearCallingIdentity();
        try {
            mWindowManagerService.addWindowToken(mOverlayWindowToken,
                    TYPE_ACCESSIBILITY_OVERLAY, DEFAULT_DISPLAY);
        } finally {
            Binder.restoreCallingIdentity(identity);
        }
    }

    public void onRemoved() {
        final long identity = Binder.clearCallingIdentity();
        try {
            mWindowManagerService.removeWindowToken(mOverlayWindowToken, true, DEFAULT_DISPLAY);
        } 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) {
                mServiceInterface.init(null, mId, null);
            }
        } catch (RemoteException re) {
                /* ignore */
        }
        if (mService != null) {
            mService.unlinkToDeath(this, 0);
            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;
        }

        if ((event.getWindowId() != AccessibilityWindowInfo.UNDEFINED_WINDOW_ID)
                && !event.isImportantForAccessibility()
                && (mFetchFlags & AccessibilityNodeInfo.FLAG_INCLUDE_NOT_IMPORTANT_VIEWS) == 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 {
            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(int gestureId) {
        mInvocationHandler.obtainMessage(InvocationHandler.MSG_ON_GESTURE,
                gestureId, 0).sendToTarget();
    }

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

    public void notifyMagnificationChangedLocked(int displayId, @NonNull Region region,
            float scale, float centerX, float centerY) {
        mInvocationHandler
                .notifyMagnificationChangedLocked(displayId, region, scale, centerX, centerY);
    }

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

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

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

    /**
     * Called by the invocation handler to notify the service that the
     * state of magnification has changed.
     */
    private void notifyMagnificationChangedInternal(int displayId, @NonNull Region region,
            float scale, float centerX, float centerY) {
        final IAccessibilityServiceClient listener = getServiceInterfaceSafely();
        if (listener != null) {
            try {
                listener.onMagnificationChanged(displayId, region, scale, centerX, centerY);
            } 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 {
                listener.onSoftKeyboardShowModeChanged(showState);
            } catch (RemoteException re) {
                Slog.e(LOG_TAG, "Error sending soft keyboard show mode changes to " + mService,
                        re);
            }
        }
    }

    private void notifyAccessibilityButtonClickedInternal() {
        final IAccessibilityServiceClient listener = getServiceInterfaceSafely();
        if (listener != null) {
            try {
                listener.onAccessibilityButtonClicked();
            } 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 {
                listener.onAccessibilityButtonAvailabilityChanged(available);
            } catch (RemoteException re) {
                Slog.e(LOG_TAG,
                        "Error sending accessibility button availability change to " + mService,
                        re);
            }
        }
    }

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

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

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

    private int resolveAccessibilityWindowIdLocked(int accessibilityWindowId) {
        if (accessibilityWindowId == AccessibilityWindowInfo.ACTIVE_WINDOW_ID) {
            return mSecurityPolicy.getActiveWindowId();
        }
        return accessibilityWindowId;
    }

    private int resolveAccessibilityWindowIdForFindFocusLocked(int windowId, int focusType) {
        if (windowId == AccessibilityWindowInfo.ACTIVE_WINDOW_ID) {
            return mSecurityPolicy.mActiveWindowId;
        }
        if (windowId == AccessibilityWindowInfo.ANY_WINDOW_ID) {
            if (focusType == AccessibilityNodeInfo.FOCUS_INPUT) {
                return mSecurityPolicy.mFocusedWindowId;
            } else if (focusType == AccessibilityNodeInfo.FOCUS_ACCESSIBILITY) {
                return mSecurityPolicy.mAccessibilityFocusedWindowId;
            }
        }
        return windowId;
    }

    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;

        /** 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: {
                    final int gestureId = message.arg1;
                    notifyGestureInternal(gestureId);
                } 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 float scale = (float) args.arg2;
                    final float centerX = (float) args.arg3;
                    final float centerY = (float) args.arg4;
                    final int displayId = args.argi1;
                    notifyMagnificationChangedInternal(displayId, region, scale, centerX, centerY);
                    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: {
                    notifyAccessibilityButtonClickedInternal();
                } break;

                case MSG_ON_ACCESSIBILITY_BUTTON_AVAILABILITY_CHANGED: {
                    final boolean available = (message.arg1 != 0);
                    notifyAccessibilityButtonAvailabilityChangedInternal(available);
                } break;

                default: {
                    throw new IllegalArgumentException("Unknown message: " + type);
                }
            }
        }

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

            final SomeArgs args = SomeArgs.obtain();
            args.arg1 = region;
            args.arg2 = scale;
            args.arg3 = centerX;
            args.arg4 = centerY;
            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() {
            final Message msg = obtainMessage(MSG_ON_ACCESSIBILITY_BUTTON_CLICKED);
            msg.sendToTarget();
        }

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