175986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov/*
275986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov * Copyright (C) 2009 The Android Open Source Project
375986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov *
475986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov * Licensed under the Apache License, Version 2.0 (the "License");
575986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov * you may not use this file except in compliance with the License.
675986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov * You may obtain a copy of the License at
775986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov *
875986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov *      http://www.apache.org/licenses/LICENSE-2.0
975986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov *
1075986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov * Unless required by applicable law or agreed to in writing, software
1175986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov * distributed under the License is distributed on an "AS IS" BASIS,
1275986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1375986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov * See the License for the specific language governing permissions and
1475986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov * limitations under the License.
1575986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov */
1675986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov
1775986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganovpackage android.view.accessibility;
1875986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov
19736c2756bf3c14ae9fef7255c119057f7a2be1edSvetoslav Ganovimport android.accessibilityservice.AccessibilityServiceInfo;
2075986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganovimport android.content.Context;
2175986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganovimport android.content.pm.ServiceInfo;
2275986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganovimport android.os.Binder;
2375986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganovimport android.os.Handler;
2475986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganovimport android.os.IBinder;
2575986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganovimport android.os.Looper;
2675986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganovimport android.os.Message;
2775986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganovimport android.os.RemoteException;
2875986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganovimport android.os.ServiceManager;
2975986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganovimport android.os.SystemClock;
3075986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganovimport android.util.Log;
318643aa0179e598e78d938c59035389054535a229Svetoslav Ganovimport android.view.IWindow;
328643aa0179e598e78d938c59035389054535a229Svetoslav Ganovimport android.view.View;
3375986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov
34cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganovimport java.util.ArrayList;
3575986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganovimport java.util.Collections;
3675986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganovimport java.util.List;
378643aa0179e598e78d938c59035389054535a229Svetoslav Ganovimport java.util.concurrent.CopyOnWriteArrayList;
3875986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov
3975986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov/**
4038e8b4e5bc3c93affdffbc064fd9db5aeccc3e8eSvetoslav Ganov * System level service that serves as an event dispatch for {@link AccessibilityEvent}s,
4138e8b4e5bc3c93affdffbc064fd9db5aeccc3e8eSvetoslav Ganov * and provides facilities for querying the accessibility state of the system.
4238e8b4e5bc3c93affdffbc064fd9db5aeccc3e8eSvetoslav Ganov * Accessibility events are generated when something notable happens in the user interface,
4375986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov * for example an {@link android.app.Activity} starts, the focus or selection of a
4475986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov * {@link android.view.View} changes etc. Parties interested in handling accessibility
4575986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov * events implement and register an accessibility service which extends
4675986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov * {@link android.accessibilityservice.AccessibilityService}.
4738e8b4e5bc3c93affdffbc064fd9db5aeccc3e8eSvetoslav Ganov * <p>
4838e8b4e5bc3c93affdffbc064fd9db5aeccc3e8eSvetoslav Ganov * To obtain a handle to the accessibility manager do the following:
4938e8b4e5bc3c93affdffbc064fd9db5aeccc3e8eSvetoslav Ganov * </p>
5038e8b4e5bc3c93affdffbc064fd9db5aeccc3e8eSvetoslav Ganov * <p>
5138e8b4e5bc3c93affdffbc064fd9db5aeccc3e8eSvetoslav Ganov * <code>
52b303d8381d734f48c4e1de4f11bf25950b28adf1Scott Main * <pre>AccessibilityManager accessibilityManager =
53b303d8381d734f48c4e1de4f11bf25950b28adf1Scott Main *        (AccessibilityManager) context.getSystemService(Context.ACCESSIBILITY_SERVICE);</pre>
5438e8b4e5bc3c93affdffbc064fd9db5aeccc3e8eSvetoslav Ganov * </code>
5538e8b4e5bc3c93affdffbc064fd9db5aeccc3e8eSvetoslav Ganov * </p>
5675986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov *
5775986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov * @see AccessibilityEvent
5838e8b4e5bc3c93affdffbc064fd9db5aeccc3e8eSvetoslav Ganov * @see AccessibilityNodeInfo
5975986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov * @see android.accessibilityservice.AccessibilityService
6038e8b4e5bc3c93affdffbc064fd9db5aeccc3e8eSvetoslav Ganov * @see Context#getSystemService
6138e8b4e5bc3c93affdffbc064fd9db5aeccc3e8eSvetoslav Ganov * @see Context#ACCESSIBILITY_SERVICE
6275986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov */
6375986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganovpublic final class AccessibilityManager {
64736c2756bf3c14ae9fef7255c119057f7a2be1edSvetoslav Ganov    private static final boolean DEBUG = false;
65736c2756bf3c14ae9fef7255c119057f7a2be1edSvetoslav Ganov
6675986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov    private static final String LOG_TAG = "AccessibilityManager";
6775986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov
6800aabf7d187bc05408199bd687a538b2e68bdc17Svetoslav Ganov    /** @hide */
6900aabf7d187bc05408199bd687a538b2e68bdc17Svetoslav Ganov    public static final int STATE_FLAG_ACCESSIBILITY_ENABLED = 0x00000001;
7000aabf7d187bc05408199bd687a538b2e68bdc17Svetoslav Ganov
7100aabf7d187bc05408199bd687a538b2e68bdc17Svetoslav Ganov    /** @hide */
7200aabf7d187bc05408199bd687a538b2e68bdc17Svetoslav Ganov    public static final int STATE_FLAG_TOUCH_EXPLORATION_ENABLED = 0x00000002;
7300aabf7d187bc05408199bd687a538b2e68bdc17Svetoslav Ganov
7475986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov    static final Object sInstanceSync = new Object();
7575986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov
7675986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov    private static AccessibilityManager sInstance;
7775986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov
7800aabf7d187bc05408199bd687a538b2e68bdc17Svetoslav Ganov    private static final int DO_SET_STATE = 10;
7975986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov
8075986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov    final IAccessibilityManager mService;
8175986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov
8275986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov    final Handler mHandler;
8375986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov
8475986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov    boolean mIsEnabled;
8575986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov
8635bfedeaba724aeadc6f6c890269cb6bf7ef42f5Svetoslav Ganov    boolean mIsTouchExplorationEnabled;
8735bfedeaba724aeadc6f6c890269cb6bf7ef42f5Svetoslav Ganov
888643aa0179e598e78d938c59035389054535a229Svetoslav Ganov    final CopyOnWriteArrayList<AccessibilityStateChangeListener> mAccessibilityStateChangeListeners =
898643aa0179e598e78d938c59035389054535a229Svetoslav Ganov        new CopyOnWriteArrayList<AccessibilityStateChangeListener>();
908643aa0179e598e78d938c59035389054535a229Svetoslav Ganov
918643aa0179e598e78d938c59035389054535a229Svetoslav Ganov    /**
92b303d8381d734f48c4e1de4f11bf25950b28adf1Scott Main     * Listener for the system accessibility state. To listen for changes to the accessibility
93b303d8381d734f48c4e1de4f11bf25950b28adf1Scott Main     * state on the device, implement this interface and register it with the system by
94b303d8381d734f48c4e1de4f11bf25950b28adf1Scott Main     * calling {@link AccessibilityManager#addAccessibilityStateChangeListener
95b303d8381d734f48c4e1de4f11bf25950b28adf1Scott Main     * addAccessibilityStateChangeListener()}.
968643aa0179e598e78d938c59035389054535a229Svetoslav Ganov     */
978643aa0179e598e78d938c59035389054535a229Svetoslav Ganov    public interface AccessibilityStateChangeListener {
9838e8b4e5bc3c93affdffbc064fd9db5aeccc3e8eSvetoslav Ganov
998643aa0179e598e78d938c59035389054535a229Svetoslav Ganov        /**
1008643aa0179e598e78d938c59035389054535a229Svetoslav Ganov         * Called back on change in the accessibility state.
1018643aa0179e598e78d938c59035389054535a229Svetoslav Ganov         *
10238e8b4e5bc3c93affdffbc064fd9db5aeccc3e8eSvetoslav Ganov         * @param enabled Whether accessibility is enabled.
1038643aa0179e598e78d938c59035389054535a229Svetoslav Ganov         */
1048643aa0179e598e78d938c59035389054535a229Svetoslav Ganov        public void onAccessibilityStateChanged(boolean enabled);
1058643aa0179e598e78d938c59035389054535a229Svetoslav Ganov    }
1068643aa0179e598e78d938c59035389054535a229Svetoslav Ganov
10775986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov    final IAccessibilityManagerClient.Stub mClient = new IAccessibilityManagerClient.Stub() {
10800aabf7d187bc05408199bd687a538b2e68bdc17Svetoslav Ganov        public void setState(int state) {
10900aabf7d187bc05408199bd687a538b2e68bdc17Svetoslav Ganov            mHandler.obtainMessage(DO_SET_STATE, state, 0).sendToTarget();
11075986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov        }
11175986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov    };
11275986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov
11375986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov    class MyHandler extends Handler {
11475986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov
11575986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov        MyHandler(Looper mainLooper) {
11675986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov            super(mainLooper);
11775986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov        }
11875986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov
11975986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov        @Override
12075986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov        public void handleMessage(Message message) {
12175986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov            switch (message.what) {
12200aabf7d187bc05408199bd687a538b2e68bdc17Svetoslav Ganov                case DO_SET_STATE :
12300aabf7d187bc05408199bd687a538b2e68bdc17Svetoslav Ganov                    setState(message.arg1);
12475986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov                    return;
12575986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov                default :
12675986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov                    Log.w(LOG_TAG, "Unknown message type: " + message.what);
12775986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov            }
12875986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov        }
12975986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov    }
13075986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov
13175986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov    /**
13275986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov     * Get an AccessibilityManager instance (create one if necessary).
13375986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov     *
13475986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov     * @hide
13575986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov     */
13675986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov    public static AccessibilityManager getInstance(Context context) {
13775986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov        synchronized (sInstanceSync) {
13875986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov            if (sInstance == null) {
139af7adab3e35863fff24e701039d5d04afbc060c5Svetoslav Ganov                IBinder iBinder = ServiceManager.getService(Context.ACCESSIBILITY_SERVICE);
140af7adab3e35863fff24e701039d5d04afbc060c5Svetoslav Ganov                IAccessibilityManager service = IAccessibilityManager.Stub.asInterface(iBinder);
141af7adab3e35863fff24e701039d5d04afbc060c5Svetoslav Ganov                sInstance = new AccessibilityManager(context, service);
14275986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov            }
14375986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov        }
14475986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov        return sInstance;
14575986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov    }
14675986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov
14775986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov    /**
14875986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov     * Create an instance.
14975986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov     *
15075986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov     * @param context A {@link Context}.
151af7adab3e35863fff24e701039d5d04afbc060c5Svetoslav Ganov     * @param service An interface to the backing service.
152af7adab3e35863fff24e701039d5d04afbc060c5Svetoslav Ganov     *
153af7adab3e35863fff24e701039d5d04afbc060c5Svetoslav Ganov     * @hide
15475986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov     */
155af7adab3e35863fff24e701039d5d04afbc060c5Svetoslav Ganov    public AccessibilityManager(Context context, IAccessibilityManager service) {
15675986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov        mHandler = new MyHandler(context.getMainLooper());
157af7adab3e35863fff24e701039d5d04afbc060c5Svetoslav Ganov        mService = service;
158af7adab3e35863fff24e701039d5d04afbc060c5Svetoslav Ganov
15975986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov        try {
16000aabf7d187bc05408199bd687a538b2e68bdc17Svetoslav Ganov            final int stateFlags = mService.addClient(mClient);
16100aabf7d187bc05408199bd687a538b2e68bdc17Svetoslav Ganov            setState(stateFlags);
16275986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov        } catch (RemoteException re) {
16375986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov            Log.e(LOG_TAG, "AccessibilityManagerService is dead", re);
16475986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov        }
16575986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov    }
16675986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov
16775986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov    /**
16838e8b4e5bc3c93affdffbc064fd9db5aeccc3e8eSvetoslav Ganov     * Returns if the accessibility in the system is enabled.
16975986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov     *
17038e8b4e5bc3c93affdffbc064fd9db5aeccc3e8eSvetoslav Ganov     * @return True if accessibility is enabled, false otherwise.
17175986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov     */
17275986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov    public boolean isEnabled() {
17375986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov        synchronized (mHandler) {
17475986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov            return mIsEnabled;
17575986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov        }
17675986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov    }
17775986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov
17875986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov    /**
17935bfedeaba724aeadc6f6c890269cb6bf7ef42f5Svetoslav Ganov     * Returns if the touch exploration in the system is enabled.
18035bfedeaba724aeadc6f6c890269cb6bf7ef42f5Svetoslav Ganov     *
18135bfedeaba724aeadc6f6c890269cb6bf7ef42f5Svetoslav Ganov     * @return True if touch exploration is enabled, false otherwise.
18235bfedeaba724aeadc6f6c890269cb6bf7ef42f5Svetoslav Ganov     */
18335bfedeaba724aeadc6f6c890269cb6bf7ef42f5Svetoslav Ganov    public boolean isTouchExplorationEnabled() {
18435bfedeaba724aeadc6f6c890269cb6bf7ef42f5Svetoslav Ganov        synchronized (mHandler) {
18535bfedeaba724aeadc6f6c890269cb6bf7ef42f5Svetoslav Ganov            return mIsTouchExplorationEnabled;
18635bfedeaba724aeadc6f6c890269cb6bf7ef42f5Svetoslav Ganov        }
18735bfedeaba724aeadc6f6c890269cb6bf7ef42f5Svetoslav Ganov    }
18835bfedeaba724aeadc6f6c890269cb6bf7ef42f5Svetoslav Ganov
18935bfedeaba724aeadc6f6c890269cb6bf7ef42f5Svetoslav Ganov    /**
190af7adab3e35863fff24e701039d5d04afbc060c5Svetoslav Ganov     * Returns the client interface this instance registers in
191af7adab3e35863fff24e701039d5d04afbc060c5Svetoslav Ganov     * the centralized accessibility manager service.
192af7adab3e35863fff24e701039d5d04afbc060c5Svetoslav Ganov     *
193af7adab3e35863fff24e701039d5d04afbc060c5Svetoslav Ganov     * @return The client.
194af7adab3e35863fff24e701039d5d04afbc060c5Svetoslav Ganov     *
195af7adab3e35863fff24e701039d5d04afbc060c5Svetoslav Ganov     * @hide
196af7adab3e35863fff24e701039d5d04afbc060c5Svetoslav Ganov     */
197af7adab3e35863fff24e701039d5d04afbc060c5Svetoslav Ganov    public IAccessibilityManagerClient getClient() {
1984dfecf55c1afcc7ffe0cef931df67c4934a13e34Jim Miller       return (IAccessibilityManagerClient) mClient.asBinder();
199af7adab3e35863fff24e701039d5d04afbc060c5Svetoslav Ganov    }
200af7adab3e35863fff24e701039d5d04afbc060c5Svetoslav Ganov
201af7adab3e35863fff24e701039d5d04afbc060c5Svetoslav Ganov    /**
20238e8b4e5bc3c93affdffbc064fd9db5aeccc3e8eSvetoslav Ganov     * Sends an {@link AccessibilityEvent}.
20375986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov     *
20438e8b4e5bc3c93affdffbc064fd9db5aeccc3e8eSvetoslav Ganov     * @param event The event to send.
20575986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov     *
20638e8b4e5bc3c93affdffbc064fd9db5aeccc3e8eSvetoslav Ganov     * @throws IllegalStateException if accessibility is not enabled.
20775986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov     */
20875986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov    public void sendAccessibilityEvent(AccessibilityEvent event) {
20975986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov        if (!mIsEnabled) {
21075986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov            throw new IllegalStateException("Accessibility off. Did you forget to check that?");
21175986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov        }
21275986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov        boolean doRecycle = false;
21375986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov        try {
21475986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov            event.setEventTime(SystemClock.uptimeMillis());
21575986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov            // it is possible that this manager is in the same process as the service but
21675986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov            // client using it is called through Binder from another process. Example: MMS
21775986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov            // app adds a SMS notification and the NotificationManagerService calls this method
21875986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov            long identityToken = Binder.clearCallingIdentity();
21975986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov            doRecycle = mService.sendAccessibilityEvent(event);
22075986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov            Binder.restoreCallingIdentity(identityToken);
221736c2756bf3c14ae9fef7255c119057f7a2be1edSvetoslav Ganov            if (DEBUG) {
22275986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov                Log.i(LOG_TAG, event + " sent");
22375986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov            }
22475986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov        } catch (RemoteException re) {
22575986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov            Log.e(LOG_TAG, "Error during sending " + event + " ", re);
22675986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov        } finally {
22775986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov            if (doRecycle) {
22875986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov                event.recycle();
22975986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov            }
23075986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov        }
23175986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov    }
23275986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov
23375986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov    /**
23438e8b4e5bc3c93affdffbc064fd9db5aeccc3e8eSvetoslav Ganov     * Requests feedback interruption from all accessibility services.
23575986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov     */
23675986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov    public void interrupt() {
23775986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov        if (!mIsEnabled) {
23875986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov            throw new IllegalStateException("Accessibility off. Did you forget to check that?");
23975986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov        }
24075986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov        try {
24175986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov            mService.interrupt();
242736c2756bf3c14ae9fef7255c119057f7a2be1edSvetoslav Ganov            if (DEBUG) {
24375986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov                Log.i(LOG_TAG, "Requested interrupt from all services");
24475986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov            }
24575986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov        } catch (RemoteException re) {
24675986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov            Log.e(LOG_TAG, "Error while requesting interrupt from all services. ", re);
24775986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov        }
24875986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov    }
24975986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov
25075986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov    /**
25175986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov     * Returns the {@link ServiceInfo}s of the installed accessibility services.
25275986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov     *
25375986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov     * @return An unmodifiable list with {@link ServiceInfo}s.
254cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov     *
255cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov     * @deprecated Use {@link #getInstalledAccessibilityServiceList()}
25675986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov     */
257cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov    @Deprecated
25875986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov    public List<ServiceInfo> getAccessibilityServiceList() {
259cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov        List<AccessibilityServiceInfo> infos = getInstalledAccessibilityServiceList();
260cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov        List<ServiceInfo> services = new ArrayList<ServiceInfo>();
261cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov        final int infoCount = infos.size();
262cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov        for (int i = 0; i < infoCount; i++) {
263cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov            AccessibilityServiceInfo info = infos.get(i);
264cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov            services.add(info.getResolveInfo().serviceInfo);
265cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov        }
266cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov        return Collections.unmodifiableList(services);
267cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov    }
268cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov
269cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov    /**
270cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov     * Returns the {@link AccessibilityServiceInfo}s of the installed accessibility services.
271cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov     *
272cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov     * @return An unmodifiable list with {@link AccessibilityServiceInfo}s.
273cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov     */
274cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov    public List<AccessibilityServiceInfo> getInstalledAccessibilityServiceList() {
275cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov        List<AccessibilityServiceInfo> services = null;
27675986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov        try {
277cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov            services = mService.getInstalledAccessibilityServiceList();
278736c2756bf3c14ae9fef7255c119057f7a2be1edSvetoslav Ganov            if (DEBUG) {
279736c2756bf3c14ae9fef7255c119057f7a2be1edSvetoslav Ganov                Log.i(LOG_TAG, "Installed AccessibilityServices " + services);
280736c2756bf3c14ae9fef7255c119057f7a2be1edSvetoslav Ganov            }
281736c2756bf3c14ae9fef7255c119057f7a2be1edSvetoslav Ganov        } catch (RemoteException re) {
282736c2756bf3c14ae9fef7255c119057f7a2be1edSvetoslav Ganov            Log.e(LOG_TAG, "Error while obtaining the installed AccessibilityServices. ", re);
283736c2756bf3c14ae9fef7255c119057f7a2be1edSvetoslav Ganov        }
284736c2756bf3c14ae9fef7255c119057f7a2be1edSvetoslav Ganov        return Collections.unmodifiableList(services);
285736c2756bf3c14ae9fef7255c119057f7a2be1edSvetoslav Ganov    }
286736c2756bf3c14ae9fef7255c119057f7a2be1edSvetoslav Ganov
287736c2756bf3c14ae9fef7255c119057f7a2be1edSvetoslav Ganov    /**
288cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov     * Returns the {@link AccessibilityServiceInfo}s of the enabled accessibility services
289736c2756bf3c14ae9fef7255c119057f7a2be1edSvetoslav Ganov     * for a given feedback type.
290736c2756bf3c14ae9fef7255c119057f7a2be1edSvetoslav Ganov     *
29138e8b4e5bc3c93affdffbc064fd9db5aeccc3e8eSvetoslav Ganov     * @param feedbackTypeFlags The feedback type flags.
292cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov     * @return An unmodifiable list with {@link AccessibilityServiceInfo}s.
29338e8b4e5bc3c93affdffbc064fd9db5aeccc3e8eSvetoslav Ganov     *
29438e8b4e5bc3c93affdffbc064fd9db5aeccc3e8eSvetoslav Ganov     * @see AccessibilityServiceInfo#FEEDBACK_AUDIBLE
29538e8b4e5bc3c93affdffbc064fd9db5aeccc3e8eSvetoslav Ganov     * @see AccessibilityServiceInfo#FEEDBACK_GENERIC
29638e8b4e5bc3c93affdffbc064fd9db5aeccc3e8eSvetoslav Ganov     * @see AccessibilityServiceInfo#FEEDBACK_HAPTIC
29738e8b4e5bc3c93affdffbc064fd9db5aeccc3e8eSvetoslav Ganov     * @see AccessibilityServiceInfo#FEEDBACK_SPOKEN
29838e8b4e5bc3c93affdffbc064fd9db5aeccc3e8eSvetoslav Ganov     * @see AccessibilityServiceInfo#FEEDBACK_VISUAL
299736c2756bf3c14ae9fef7255c119057f7a2be1edSvetoslav Ganov     */
30038e8b4e5bc3c93affdffbc064fd9db5aeccc3e8eSvetoslav Ganov    public List<AccessibilityServiceInfo> getEnabledAccessibilityServiceList(
30138e8b4e5bc3c93affdffbc064fd9db5aeccc3e8eSvetoslav Ganov            int feedbackTypeFlags) {
302cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov        List<AccessibilityServiceInfo> services = null;
303736c2756bf3c14ae9fef7255c119057f7a2be1edSvetoslav Ganov        try {
30438e8b4e5bc3c93affdffbc064fd9db5aeccc3e8eSvetoslav Ganov            services = mService.getEnabledAccessibilityServiceList(feedbackTypeFlags);
305736c2756bf3c14ae9fef7255c119057f7a2be1edSvetoslav Ganov            if (DEBUG) {
30675986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov                Log.i(LOG_TAG, "Installed AccessibilityServices " + services);
30775986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov            }
30875986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov        } catch (RemoteException re) {
30975986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov            Log.e(LOG_TAG, "Error while obtaining the installed AccessibilityServices. ", re);
31075986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov        }
31175986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov        return Collections.unmodifiableList(services);
31275986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov    }
3138643aa0179e598e78d938c59035389054535a229Svetoslav Ganov
3148643aa0179e598e78d938c59035389054535a229Svetoslav Ganov    /**
31538e8b4e5bc3c93affdffbc064fd9db5aeccc3e8eSvetoslav Ganov     * Registers an {@link AccessibilityStateChangeListener} for changes in
31638e8b4e5bc3c93affdffbc064fd9db5aeccc3e8eSvetoslav Ganov     * the global accessibility state of the system.
3178643aa0179e598e78d938c59035389054535a229Svetoslav Ganov     *
3188643aa0179e598e78d938c59035389054535a229Svetoslav Ganov     * @param listener The listener.
3198643aa0179e598e78d938c59035389054535a229Svetoslav Ganov     * @return True if successfully registered.
3208643aa0179e598e78d938c59035389054535a229Svetoslav Ganov     */
3218643aa0179e598e78d938c59035389054535a229Svetoslav Ganov    public boolean addAccessibilityStateChangeListener(
3228643aa0179e598e78d938c59035389054535a229Svetoslav Ganov            AccessibilityStateChangeListener listener) {
3238643aa0179e598e78d938c59035389054535a229Svetoslav Ganov        return mAccessibilityStateChangeListeners.add(listener);
3248643aa0179e598e78d938c59035389054535a229Svetoslav Ganov    }
3258643aa0179e598e78d938c59035389054535a229Svetoslav Ganov
3268643aa0179e598e78d938c59035389054535a229Svetoslav Ganov    /**
3278643aa0179e598e78d938c59035389054535a229Svetoslav Ganov     * Unregisters an {@link AccessibilityStateChangeListener}.
3288643aa0179e598e78d938c59035389054535a229Svetoslav Ganov     *
3298643aa0179e598e78d938c59035389054535a229Svetoslav Ganov     * @param listener The listener.
3308643aa0179e598e78d938c59035389054535a229Svetoslav Ganov     * @return True if successfully unregistered.
3318643aa0179e598e78d938c59035389054535a229Svetoslav Ganov     */
3328643aa0179e598e78d938c59035389054535a229Svetoslav Ganov    public boolean removeAccessibilityStateChangeListener(
3338643aa0179e598e78d938c59035389054535a229Svetoslav Ganov            AccessibilityStateChangeListener listener) {
3348643aa0179e598e78d938c59035389054535a229Svetoslav Ganov        return mAccessibilityStateChangeListeners.remove(listener);
3358643aa0179e598e78d938c59035389054535a229Svetoslav Ganov    }
3368643aa0179e598e78d938c59035389054535a229Svetoslav Ganov
3378643aa0179e598e78d938c59035389054535a229Svetoslav Ganov    /**
33800aabf7d187bc05408199bd687a538b2e68bdc17Svetoslav Ganov     * Sets the current state.
33900aabf7d187bc05408199bd687a538b2e68bdc17Svetoslav Ganov     *
34000aabf7d187bc05408199bd687a538b2e68bdc17Svetoslav Ganov     * @param stateFlags The state flags.
34100aabf7d187bc05408199bd687a538b2e68bdc17Svetoslav Ganov     */
34200aabf7d187bc05408199bd687a538b2e68bdc17Svetoslav Ganov    private void setState(int stateFlags) {
34300aabf7d187bc05408199bd687a538b2e68bdc17Svetoslav Ganov        final boolean accessibilityEnabled = (stateFlags & STATE_FLAG_ACCESSIBILITY_ENABLED) != 0;
34400aabf7d187bc05408199bd687a538b2e68bdc17Svetoslav Ganov        setAccessibilityState(accessibilityEnabled);
34500aabf7d187bc05408199bd687a538b2e68bdc17Svetoslav Ganov        mIsTouchExplorationEnabled = (stateFlags & STATE_FLAG_TOUCH_EXPLORATION_ENABLED) != 0;
34600aabf7d187bc05408199bd687a538b2e68bdc17Svetoslav Ganov    }
34700aabf7d187bc05408199bd687a538b2e68bdc17Svetoslav Ganov
34800aabf7d187bc05408199bd687a538b2e68bdc17Svetoslav Ganov    /**
3498643aa0179e598e78d938c59035389054535a229Svetoslav Ganov     * Sets the enabled state.
3508643aa0179e598e78d938c59035389054535a229Svetoslav Ganov     *
3518643aa0179e598e78d938c59035389054535a229Svetoslav Ganov     * @param isEnabled The accessibility state.
3528643aa0179e598e78d938c59035389054535a229Svetoslav Ganov     */
3538643aa0179e598e78d938c59035389054535a229Svetoslav Ganov    private void setAccessibilityState(boolean isEnabled) {
3548643aa0179e598e78d938c59035389054535a229Svetoslav Ganov        synchronized (mHandler) {
3558643aa0179e598e78d938c59035389054535a229Svetoslav Ganov            if (isEnabled != mIsEnabled) {
3568643aa0179e598e78d938c59035389054535a229Svetoslav Ganov                mIsEnabled = isEnabled;
3578643aa0179e598e78d938c59035389054535a229Svetoslav Ganov                notifyAccessibilityStateChanged();
3588643aa0179e598e78d938c59035389054535a229Svetoslav Ganov            }
3598643aa0179e598e78d938c59035389054535a229Svetoslav Ganov        }
3608643aa0179e598e78d938c59035389054535a229Svetoslav Ganov    }
3618643aa0179e598e78d938c59035389054535a229Svetoslav Ganov
3628643aa0179e598e78d938c59035389054535a229Svetoslav Ganov    /**
3638643aa0179e598e78d938c59035389054535a229Svetoslav Ganov     * Notifies the registered {@link AccessibilityStateChangeListener}s.
3648643aa0179e598e78d938c59035389054535a229Svetoslav Ganov     */
3658643aa0179e598e78d938c59035389054535a229Svetoslav Ganov    private void notifyAccessibilityStateChanged() {
3668643aa0179e598e78d938c59035389054535a229Svetoslav Ganov        final int listenerCount = mAccessibilityStateChangeListeners.size();
3678643aa0179e598e78d938c59035389054535a229Svetoslav Ganov        for (int i = 0; i < listenerCount; i++) {
3688643aa0179e598e78d938c59035389054535a229Svetoslav Ganov            mAccessibilityStateChangeListeners.get(i).onAccessibilityStateChanged(mIsEnabled);
3698643aa0179e598e78d938c59035389054535a229Svetoslav Ganov        }
3708643aa0179e598e78d938c59035389054535a229Svetoslav Ganov    }
3718643aa0179e598e78d938c59035389054535a229Svetoslav Ganov
3728643aa0179e598e78d938c59035389054535a229Svetoslav Ganov    /**
3738643aa0179e598e78d938c59035389054535a229Svetoslav Ganov     * Adds an accessibility interaction connection interface for a given window.
3748643aa0179e598e78d938c59035389054535a229Svetoslav Ganov     * @param windowToken The window token to which a connection is added.
3758643aa0179e598e78d938c59035389054535a229Svetoslav Ganov     * @param connection The connection.
3768643aa0179e598e78d938c59035389054535a229Svetoslav Ganov     *
3778643aa0179e598e78d938c59035389054535a229Svetoslav Ganov     * @hide
3788643aa0179e598e78d938c59035389054535a229Svetoslav Ganov     */
3798643aa0179e598e78d938c59035389054535a229Svetoslav Ganov    public int addAccessibilityInteractionConnection(IWindow windowToken,
3808643aa0179e598e78d938c59035389054535a229Svetoslav Ganov            IAccessibilityInteractionConnection connection) {
3818643aa0179e598e78d938c59035389054535a229Svetoslav Ganov        try {
3828643aa0179e598e78d938c59035389054535a229Svetoslav Ganov            return mService.addAccessibilityInteractionConnection(windowToken, connection);
3838643aa0179e598e78d938c59035389054535a229Svetoslav Ganov        } catch (RemoteException re) {
3848643aa0179e598e78d938c59035389054535a229Svetoslav Ganov            Log.e(LOG_TAG, "Error while adding an accessibility interaction connection. ", re);
3858643aa0179e598e78d938c59035389054535a229Svetoslav Ganov        }
3868643aa0179e598e78d938c59035389054535a229Svetoslav Ganov        return View.NO_ID;
3878643aa0179e598e78d938c59035389054535a229Svetoslav Ganov    }
3888643aa0179e598e78d938c59035389054535a229Svetoslav Ganov
3898643aa0179e598e78d938c59035389054535a229Svetoslav Ganov    /**
3908643aa0179e598e78d938c59035389054535a229Svetoslav Ganov     * Removed an accessibility interaction connection interface for a given window.
3918643aa0179e598e78d938c59035389054535a229Svetoslav Ganov     * @param windowToken The window token to which a connection is removed.
3928643aa0179e598e78d938c59035389054535a229Svetoslav Ganov     *
3938643aa0179e598e78d938c59035389054535a229Svetoslav Ganov     * @hide
3948643aa0179e598e78d938c59035389054535a229Svetoslav Ganov     */
3958643aa0179e598e78d938c59035389054535a229Svetoslav Ganov    public void removeAccessibilityInteractionConnection(IWindow windowToken) {
3968643aa0179e598e78d938c59035389054535a229Svetoslav Ganov        try {
3978643aa0179e598e78d938c59035389054535a229Svetoslav Ganov            mService.removeAccessibilityInteractionConnection(windowToken);
3988643aa0179e598e78d938c59035389054535a229Svetoslav Ganov        } catch (RemoteException re) {
3998643aa0179e598e78d938c59035389054535a229Svetoslav Ganov            Log.e(LOG_TAG, "Error while removing an accessibility interaction connection. ", re);
4008643aa0179e598e78d938c59035389054535a229Svetoslav Ganov        }
4018643aa0179e598e78d938c59035389054535a229Svetoslav Ganov    }
40275986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov}
403