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.accessibilityservice;
1875986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov
19cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganovimport android.content.ComponentName;
20cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganovimport android.content.Context;
21cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganovimport android.content.pm.PackageManager;
22cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganovimport android.content.pm.PackageManager.NameNotFoundException;
23cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganovimport android.content.pm.ResolveInfo;
24cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganovimport android.content.pm.ServiceInfo;
25cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganovimport android.content.res.Resources;
26cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganovimport android.content.res.TypedArray;
27cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganovimport android.content.res.XmlResourceParser;
2875986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganovimport android.os.Parcel;
2975986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganovimport android.os.Parcelable;
30cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganovimport android.util.AttributeSet;
31cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganovimport android.util.Xml;
32cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganovimport android.view.accessibility.AccessibilityEvent;
33cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov
34cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganovimport org.xmlpull.v1.XmlPullParser;
35cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganovimport org.xmlpull.v1.XmlPullParserException;
36cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov
37cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganovimport java.io.IOException;
3875986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov
3975986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov/**
4038e8b4e5bc3c93affdffbc064fd9db5aeccc3e8eSvetoslav Ganov * This class describes an {@link AccessibilityService}. The system notifies an
4138e8b4e5bc3c93affdffbc064fd9db5aeccc3e8eSvetoslav Ganov * {@link AccessibilityService} for {@link android.view.accessibility.AccessibilityEvent}s
4275986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov * according to the information encapsulated in this class.
4375986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov *
4475986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov * @see AccessibilityService
4575986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov * @see android.view.accessibility.AccessibilityEvent
4638e8b4e5bc3c93affdffbc064fd9db5aeccc3e8eSvetoslav Ganov * @see android.view.accessibility.AccessibilityManager
4775986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov */
4875986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganovpublic class AccessibilityServiceInfo implements Parcelable {
4975986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov
50cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov    private static final String TAG_ACCESSIBILITY_SERVICE = "accessibility-service";
51cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov
5275986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov    /**
5375986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov     * Denotes spoken feedback.
5475986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov     */
5575986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov    public static final int FEEDBACK_SPOKEN = 0x0000001;
5675986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov
5775986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov    /**
5875986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov     * Denotes haptic feedback.
5975986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov     */
6075986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov    public static final int FEEDBACK_HAPTIC =  0x0000002;
6175986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov
6275986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov    /**
6375986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov     * Denotes audible (not spoken) feedback.
6475986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov     */
6575986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov    public static final int FEEDBACK_AUDIBLE = 0x0000004;
6675986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov
6775986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov    /**
6875986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov     * Denotes visual feedback.
6975986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov     */
7075986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov    public static final int FEEDBACK_VISUAL = 0x0000008;
7175986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov
7275986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov    /**
7375986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov     * Denotes generic feedback.
7475986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov     */
7575986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov    public static final int FEEDBACK_GENERIC = 0x0000010;
7675986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov
7775986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov    /**
7800aabf7d187bc05408199bd687a538b2e68bdc17Svetoslav Ganov     * Mask for all feedback types.
7900aabf7d187bc05408199bd687a538b2e68bdc17Svetoslav Ganov     *
8000aabf7d187bc05408199bd687a538b2e68bdc17Svetoslav Ganov     * @see #FEEDBACK_SPOKEN
8100aabf7d187bc05408199bd687a538b2e68bdc17Svetoslav Ganov     * @see #FEEDBACK_HAPTIC
8200aabf7d187bc05408199bd687a538b2e68bdc17Svetoslav Ganov     * @see #FEEDBACK_AUDIBLE
8300aabf7d187bc05408199bd687a538b2e68bdc17Svetoslav Ganov     * @see #FEEDBACK_VISUAL
8400aabf7d187bc05408199bd687a538b2e68bdc17Svetoslav Ganov     * @see #FEEDBACK_GENERIC
8500aabf7d187bc05408199bd687a538b2e68bdc17Svetoslav Ganov     */
8600aabf7d187bc05408199bd687a538b2e68bdc17Svetoslav Ganov    public static final int FEEDBACK_ALL_MASK = 0xFFFFFFFF;
8700aabf7d187bc05408199bd687a538b2e68bdc17Svetoslav Ganov
8800aabf7d187bc05408199bd687a538b2e68bdc17Svetoslav Ganov    /**
8975986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov     * If an {@link AccessibilityService} is the default for a given type.
9075986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov     * Default service is invoked only if no package specific one exists. In case of
9175986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov     * more than one package specific service only the earlier registered is notified.
9275986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov     */
9375986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov    public static final int DEFAULT = 0x0000001;
9475986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov
9575986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov    /**
9675986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov     * The event types an {@link AccessibilityService} is interested in.
97cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov     * <p>
98cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov     *   <strong>Can be dynamically set at runtime.</strong>
99cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov     * </p>
10075986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov     * @see android.view.accessibility.AccessibilityEvent#TYPE_VIEW_CLICKED
1019b31779eab896bdcc0922473b183c979cc0b874fSvetoslav Ganov     * @see android.view.accessibility.AccessibilityEvent#TYPE_VIEW_LONG_CLICKED
10275986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov     * @see android.view.accessibility.AccessibilityEvent#TYPE_VIEW_FOCUSED
10375986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov     * @see android.view.accessibility.AccessibilityEvent#TYPE_VIEW_SELECTED
10475986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov     * @see android.view.accessibility.AccessibilityEvent#TYPE_VIEW_TEXT_CHANGED
10575986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov     * @see android.view.accessibility.AccessibilityEvent#TYPE_WINDOW_STATE_CHANGED
10675986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov     * @see android.view.accessibility.AccessibilityEvent#TYPE_NOTIFICATION_STATE_CHANGED
10738e8b4e5bc3c93affdffbc064fd9db5aeccc3e8eSvetoslav Ganov     * @see android.view.accessibility.AccessibilityEvent#TYPE_TOUCH_EXPLORATION_GESTURE_START
10838e8b4e5bc3c93affdffbc064fd9db5aeccc3e8eSvetoslav Ganov     * @see android.view.accessibility.AccessibilityEvent#TYPE_TOUCH_EXPLORATION_GESTURE_END
10938e8b4e5bc3c93affdffbc064fd9db5aeccc3e8eSvetoslav Ganov     * @see android.view.accessibility.AccessibilityEvent#TYPE_VIEW_HOVER_ENTER
11038e8b4e5bc3c93affdffbc064fd9db5aeccc3e8eSvetoslav Ganov     * @see android.view.accessibility.AccessibilityEvent#TYPE_VIEW_HOVER_EXIT
11138e8b4e5bc3c93affdffbc064fd9db5aeccc3e8eSvetoslav Ganov     * @see android.view.accessibility.AccessibilityEvent#TYPE_VIEW_SCROLLED
11238e8b4e5bc3c93affdffbc064fd9db5aeccc3e8eSvetoslav Ganov     * @see android.view.accessibility.AccessibilityEvent#TYPE_VIEW_TEXT_SELECTION_CHANGED
11338e8b4e5bc3c93affdffbc064fd9db5aeccc3e8eSvetoslav Ganov     * @see android.view.accessibility.AccessibilityEvent#TYPE_WINDOW_CONTENT_CHANGED
11475986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov     */
11575986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov    public int eventTypes;
11675986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov
11775986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov    /**
11875986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov     * The package names an {@link AccessibilityService} is interested in. Setting
11938e8b4e5bc3c93affdffbc064fd9db5aeccc3e8eSvetoslav Ganov     * to <code>null</code> is equivalent to all packages.
120cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov     * <p>
121cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov     *   <strong>Can be dynamically set at runtime.</strong>
122cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov     * </p>
12375986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov     */
12475986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov    public String[] packageNames;
12575986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov
12675986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov    /**
12775986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov     * The feedback type an {@link AccessibilityService} provides.
128cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov     * <p>
129cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov     *   <strong>Can be dynamically set at runtime.</strong>
130cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov     * </p>
13175986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov     * @see #FEEDBACK_AUDIBLE
13275986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov     * @see #FEEDBACK_GENERIC
13375986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov     * @see #FEEDBACK_HAPTIC
13475986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov     * @see #FEEDBACK_SPOKEN
13575986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov     * @see #FEEDBACK_VISUAL
13675986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov     */
13775986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov    public int feedbackType;
13875986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov
13975986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov    /**
14075986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov     * The timeout after the most recent event of a given type before an
14175986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov     * {@link AccessibilityService} is notified.
14275986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov     * <p>
143cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov     *   <strong>Can be dynamically set at runtime.</strong>.
144cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov     * </p>
145cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov     * <p>
14638e8b4e5bc3c93affdffbc064fd9db5aeccc3e8eSvetoslav Ganov     * <strong>Note:</strong> The event notification timeout is useful to avoid propagating
14738e8b4e5bc3c93affdffbc064fd9db5aeccc3e8eSvetoslav Ganov     *       events to the client too frequently since this is accomplished via an expensive
14838e8b4e5bc3c93affdffbc064fd9db5aeccc3e8eSvetoslav Ganov     *       interprocess call. One can think of the timeout as a criteria to determine when
14938e8b4e5bc3c93affdffbc064fd9db5aeccc3e8eSvetoslav Ganov     *       event generation has settled down.
15075986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov     */
15175986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov    public long notificationTimeout;
15275986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov
15375986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov    /**
15475986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov     * This field represents a set of flags used for configuring an
15575986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov     * {@link AccessibilityService}.
156cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov     * <p>
157cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov     *   <strong>Can be dynamically set at runtime.</strong>
158cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov     * </p>
15975986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov     * @see #DEFAULT
16075986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov     */
16175986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov    public int flags;
16275986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov
163cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov    /**
164cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov     * The unique string Id to identify the accessibility service.
165cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov     */
166cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov    private String mId;
167cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov
168cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov    /**
169cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov     * The Service that implements this accessibility service component.
170cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov     */
171cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov    private ResolveInfo mResolveInfo;
172cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov
173cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov    /**
174cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov     * The accessibility service setting activity's name, used by the system
175cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov     * settings to launch the setting activity of this accessibility service.
176cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov     */
177cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov    private String mSettingsActivityName;
178cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov
179cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov    /**
18038e8b4e5bc3c93affdffbc064fd9db5aeccc3e8eSvetoslav Ganov     * Flag whether this accessibility service can retrieve window content.
181cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov     */
182cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov    private boolean mCanRetrieveWindowContent;
183cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov
184cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov    /**
18535bfedeaba724aeadc6f6c890269cb6bf7ef42f5Svetoslav Ganov     * Description of the accessibility service.
18635bfedeaba724aeadc6f6c890269cb6bf7ef42f5Svetoslav Ganov     */
18735bfedeaba724aeadc6f6c890269cb6bf7ef42f5Svetoslav Ganov    private String mDescription;
18835bfedeaba724aeadc6f6c890269cb6bf7ef42f5Svetoslav Ganov
18935bfedeaba724aeadc6f6c890269cb6bf7ef42f5Svetoslav Ganov    /**
190cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov     * Creates a new instance.
191cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov     */
192cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov    public AccessibilityServiceInfo() {
193cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov        /* do nothing */
194cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov    }
195cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov
196cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov    /**
197cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov     * Creates a new instance.
198cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov     *
199cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov     * @param resolveInfo The service resolve info.
200cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov     * @param context Context for accessing resources.
201cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov     * @throws XmlPullParserException If a XML parsing error occurs.
202cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov     * @throws IOException If a XML parsing error occurs.
203cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov     *
204cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov     * @hide
205cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov     */
206cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov    public AccessibilityServiceInfo(ResolveInfo resolveInfo, Context context)
207cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov            throws XmlPullParserException, IOException {
208cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov        ServiceInfo serviceInfo = resolveInfo.serviceInfo;
209cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov        mId = new ComponentName(serviceInfo.packageName, serviceInfo.name).flattenToShortString();
210cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov        mResolveInfo = resolveInfo;
211cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov
212cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov        XmlResourceParser parser = null;
213cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov
214cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov        try {
215cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov            PackageManager packageManager = context.getPackageManager();
216cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov            parser = serviceInfo.loadXmlMetaData(packageManager,
217cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov                    AccessibilityService.SERVICE_META_DATA);
218cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov            if (parser == null) {
219cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov                return;
220cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov            }
221cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov
222cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov            int type = 0;
223cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov            while (type != XmlPullParser.END_DOCUMENT && type != XmlPullParser.START_TAG) {
224cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov                type = parser.next();
225cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov            }
226cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov
227cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov            String nodeName = parser.getName();
228cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov            if (!TAG_ACCESSIBILITY_SERVICE.equals(nodeName)) {
229cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov                throw new XmlPullParserException( "Meta-data does not start with"
230cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov                        + TAG_ACCESSIBILITY_SERVICE + " tag");
231cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov            }
232cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov
233cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov            AttributeSet allAttributes = Xml.asAttributeSet(parser);
234cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov            Resources resources = packageManager.getResourcesForApplication(
235cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov                    serviceInfo.applicationInfo);
236cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov            TypedArray asAttributes = resources.obtainAttributes(allAttributes,
237cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov                    com.android.internal.R.styleable.AccessibilityService);
238cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov            eventTypes = asAttributes.getInt(
239cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov                    com.android.internal.R.styleable.AccessibilityService_accessibilityEventTypes,
240cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov                    0);
241cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov            String packageNamez = asAttributes.getString(
242cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov                    com.android.internal.R.styleable.AccessibilityService_packageNames);
243cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov            if (packageNamez != null) {
244cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov                packageNames = packageNamez.split("(\\s)*,(\\s)*");
245cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov            }
246cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov            feedbackType = asAttributes.getInt(
247cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov                    com.android.internal.R.styleable.AccessibilityService_accessibilityFeedbackType,
248cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov                    0);
249cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov            notificationTimeout = asAttributes.getInt(
250cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov                    com.android.internal.R.styleable.AccessibilityService_notificationTimeout,
251cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov                    0);
252cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov            flags = asAttributes.getInt(
253cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov                    com.android.internal.R.styleable.AccessibilityService_accessibilityFlags, 0);
254cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov            mSettingsActivityName = asAttributes.getString(
255cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov                    com.android.internal.R.styleable.AccessibilityService_settingsActivity);
256cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov            mCanRetrieveWindowContent = asAttributes.getBoolean(
257cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov                    com.android.internal.R.styleable.AccessibilityService_canRetrieveWindowContent,
258cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov                    false);
25935bfedeaba724aeadc6f6c890269cb6bf7ef42f5Svetoslav Ganov            mDescription = asAttributes.getString(
26035bfedeaba724aeadc6f6c890269cb6bf7ef42f5Svetoslav Ganov                    com.android.internal.R.styleable.AccessibilityService_description);
261cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov            asAttributes.recycle();
262cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov        } catch (NameNotFoundException e) {
263cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov            throw new XmlPullParserException( "Unable to create context for: "
264cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov                    + serviceInfo.packageName);
265cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov        } finally {
266cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov            if (parser != null) {
267cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov                parser.close();
268cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov            }
269cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov        }
270cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov    }
271cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov
272cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov    /**
273cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov     * Updates the properties that an AccessibilitySerivice can change dynamically.
274cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov     *
275cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov     * @param other The info from which to update the properties.
276cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov     *
277cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov     * @hide
278cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov     */
279cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov    public void updateDynamicallyConfigurableProperties(AccessibilityServiceInfo other) {
280cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov        eventTypes = other.eventTypes;
281cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov        packageNames = other.packageNames;
282cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov        feedbackType = other.feedbackType;
283cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov        notificationTimeout = other.notificationTimeout;
284cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov        flags = other.flags;
285cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov    }
286cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov
287cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov    /**
288cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov     * The accessibility service id.
289cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov     * <p>
290cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov     *   <strong>Generated by the system.</strong>
291cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov     * </p>
292cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov     * @return The id.
293cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov     */
294cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov    public String getId() {
295cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov        return mId;
296cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov    }
297cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov
298cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov    /**
299cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov     * The service {@link ResolveInfo}.
300cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov     * <p>
301cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov     *   <strong>Generated by the system.</strong>
302cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov     * </p>
303cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov     * @return The info.
304cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov     */
305cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov    public ResolveInfo getResolveInfo() {
306cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov        return mResolveInfo;
307cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov    }
308cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov
309cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov    /**
310cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov     * The settings activity name.
311cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov     * <p>
312cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov     *    <strong>Statically set from
313cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov     *    {@link AccessibilityService#SERVICE_META_DATA meta-data}.</strong>
314cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov     * </p>
315cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov     * @return The settings activity name.
316cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov     */
317cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov    public String getSettingsActivityName() {
318cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov        return mSettingsActivityName;
319cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov    }
320cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov
321cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov    /**
32238e8b4e5bc3c93affdffbc064fd9db5aeccc3e8eSvetoslav Ganov     * Whether this service can retrieve the current window's content.
323cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov     * <p>
324cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov     *    <strong>Statically set from
325cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov     *    {@link AccessibilityService#SERVICE_META_DATA meta-data}.</strong>
326cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov     * </p>
32738e8b4e5bc3c93affdffbc064fd9db5aeccc3e8eSvetoslav Ganov     * @return True window content can be retrieved.
328cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov     */
329cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov    public boolean getCanRetrieveWindowContent() {
330cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov        return mCanRetrieveWindowContent;
331cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov    }
332cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov
333cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov    /**
33435bfedeaba724aeadc6f6c890269cb6bf7ef42f5Svetoslav Ganov     * Description of the accessibility service.
33535bfedeaba724aeadc6f6c890269cb6bf7ef42f5Svetoslav Ganov     * <p>
33635bfedeaba724aeadc6f6c890269cb6bf7ef42f5Svetoslav Ganov     *    <strong>Statically set from
33735bfedeaba724aeadc6f6c890269cb6bf7ef42f5Svetoslav Ganov     *    {@link AccessibilityService#SERVICE_META_DATA meta-data}.</strong>
33835bfedeaba724aeadc6f6c890269cb6bf7ef42f5Svetoslav Ganov     * </p>
33935bfedeaba724aeadc6f6c890269cb6bf7ef42f5Svetoslav Ganov     * @return The description.
34035bfedeaba724aeadc6f6c890269cb6bf7ef42f5Svetoslav Ganov     */
34135bfedeaba724aeadc6f6c890269cb6bf7ef42f5Svetoslav Ganov    public String getDescription() {
34235bfedeaba724aeadc6f6c890269cb6bf7ef42f5Svetoslav Ganov        return mDescription;
34335bfedeaba724aeadc6f6c890269cb6bf7ef42f5Svetoslav Ganov    }
34435bfedeaba724aeadc6f6c890269cb6bf7ef42f5Svetoslav Ganov
34535bfedeaba724aeadc6f6c890269cb6bf7ef42f5Svetoslav Ganov    /**
346cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov     * {@inheritDoc}
347cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov     */
34875986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov    public int describeContents() {
34975986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov        return 0;
35075986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov    }
35175986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov
3529b31779eab896bdcc0922473b183c979cc0b874fSvetoslav Ganov    public void writeToParcel(Parcel parcel, int flagz) {
35375986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov        parcel.writeInt(eventTypes);
35475986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov        parcel.writeStringArray(packageNames);
35575986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov        parcel.writeInt(feedbackType);
35675986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov        parcel.writeLong(notificationTimeout);
35775986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov        parcel.writeInt(flags);
358cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov        parcel.writeString(mId);
359cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov        parcel.writeParcelable(mResolveInfo, 0);
360cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov        parcel.writeString(mSettingsActivityName);
361cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov        parcel.writeInt(mCanRetrieveWindowContent ? 1 : 0);
36235bfedeaba724aeadc6f6c890269cb6bf7ef42f5Svetoslav Ganov        parcel.writeString(mDescription);
363cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov    }
364cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov
365cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov    private void initFromParcel(Parcel parcel) {
366cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov        eventTypes = parcel.readInt();
367cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov        packageNames = parcel.readStringArray();
368cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov        feedbackType = parcel.readInt();
369cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov        notificationTimeout = parcel.readLong();
370cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov        flags = parcel.readInt();
371cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov        mId = parcel.readString();
372cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov        mResolveInfo = parcel.readParcelable(null);
373cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov        mSettingsActivityName = parcel.readString();
374cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov        mCanRetrieveWindowContent = (parcel.readInt() == 1);
37535bfedeaba724aeadc6f6c890269cb6bf7ef42f5Svetoslav Ganov        mDescription = parcel.readString();
376cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov    }
377cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov
378cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov    @Override
379cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov    public String toString() {
380cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov        StringBuilder stringBuilder = new StringBuilder();
381cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov        appendEventTypes(stringBuilder, eventTypes);
382cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov        stringBuilder.append(", ");
383cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov        appendPackageNames(stringBuilder, packageNames);
384cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov        stringBuilder.append(", ");
385cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov        appendFeedbackTypes(stringBuilder, feedbackType);
386cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov        stringBuilder.append(", ");
387cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov        stringBuilder.append("notificationTimeout: ").append(notificationTimeout);
388cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov        stringBuilder.append(", ");
389cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov        appendFlags(stringBuilder, flags);
390cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov        stringBuilder.append(", ");
391cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov        stringBuilder.append("id: ").append(mId);
392cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov        stringBuilder.append(", ");
393cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov        stringBuilder.append("resolveInfo: ").append(mResolveInfo);
394cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov        stringBuilder.append(", ");
395cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov        stringBuilder.append("settingsActivityName: ").append(mSettingsActivityName);
396cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov        stringBuilder.append(", ");
397cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov        stringBuilder.append("retrieveScreenContent: ").append(mCanRetrieveWindowContent);
398cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov        return stringBuilder.toString();
399cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov    }
400cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov
401cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov    private static void appendFeedbackTypes(StringBuilder stringBuilder, int feedbackTypes) {
402cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov        stringBuilder.append("feedbackTypes:");
403cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov        stringBuilder.append("[");
404cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov        while (feedbackTypes != 0) {
405cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov            final int feedbackTypeBit = (1 << Integer.numberOfTrailingZeros(feedbackTypes));
406cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov            stringBuilder.append(feedbackTypeToString(feedbackTypeBit));
407cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov            feedbackTypes &= ~feedbackTypeBit;
408cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov            if (feedbackTypes != 0) {
409cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov                stringBuilder.append(", ");
410cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov            }
411cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov        }
412cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov        stringBuilder.append("]");
413cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov    }
414cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov
415cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov    private static void appendPackageNames(StringBuilder stringBuilder, String[] packageNames) {
416cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov        stringBuilder.append("packageNames:");
417cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov        stringBuilder.append("[");
418cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov        if (packageNames != null) {
419cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov            final int packageNameCount = packageNames.length;
420cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov            for (int i = 0; i < packageNameCount; i++) {
421cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov                stringBuilder.append(packageNames[i]);
422cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov                if (i < packageNameCount - 1) {
423cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov                    stringBuilder.append(", ");
424cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov                }
425cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov            }
426cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov        }
427cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov        stringBuilder.append("]");
428cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov    }
429cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov
430cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov    private static void appendEventTypes(StringBuilder stringBuilder, int eventTypes) {
431cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov        stringBuilder.append("eventTypes:");
432cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov        stringBuilder.append("[");
433cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov        while (eventTypes != 0) {
434cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov            final int eventTypeBit = (1 << Integer.numberOfTrailingZeros(eventTypes));
435cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov            stringBuilder.append(AccessibilityEvent.eventTypeToString(eventTypeBit));
436cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov            eventTypes &= ~eventTypeBit;
437cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov            if (eventTypes != 0) {
438cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov                stringBuilder.append(", ");
439cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov            }
440cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov        }
441cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov        stringBuilder.append("]");
442cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov    }
443cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov
444cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov    private static void appendFlags(StringBuilder stringBuilder, int flags) {
445cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov        stringBuilder.append("flags:");
446cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov        stringBuilder.append("[");
447cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov        while (flags != 0) {
448cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov            final int flagBit = (1 << Integer.numberOfTrailingZeros(flags));
449cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov            stringBuilder.append(flagToString(flagBit));
450cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov            flags &= ~flagBit;
451cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov            if (flags != 0) {
452cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov                stringBuilder.append(", ");
453cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov            }
454cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov        }
455cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov        stringBuilder.append("]");
456cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov    }
457cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov
458cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov    /**
459cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov     * Returns the string representation of a feedback type. For example,
460cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov     * {@link #FEEDBACK_SPOKEN} is represented by the string FEEDBACK_SPOKEN.
461cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov     *
462cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov     * @param feedbackType The feedback type.
463cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov     * @return The string representation.
464cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov     */
465cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov    public static String feedbackTypeToString(int feedbackType) {
466bb1b9ea8a488eec833b0be18c45dae8505876042Svetoslav Ganov        StringBuilder builder = new StringBuilder();
467bb1b9ea8a488eec833b0be18c45dae8505876042Svetoslav Ganov        builder.append("[");
468bb1b9ea8a488eec833b0be18c45dae8505876042Svetoslav Ganov        while (feedbackType > 0) {
469bb1b9ea8a488eec833b0be18c45dae8505876042Svetoslav Ganov            final int feedbackTypeFlag = 1 << Integer.numberOfTrailingZeros(feedbackType);
470bb1b9ea8a488eec833b0be18c45dae8505876042Svetoslav Ganov            feedbackType &= ~feedbackTypeFlag;
471bb1b9ea8a488eec833b0be18c45dae8505876042Svetoslav Ganov            if (builder.length() > 1) {
472bb1b9ea8a488eec833b0be18c45dae8505876042Svetoslav Ganov                builder.append(", ");
473bb1b9ea8a488eec833b0be18c45dae8505876042Svetoslav Ganov            }
474bb1b9ea8a488eec833b0be18c45dae8505876042Svetoslav Ganov            switch (feedbackTypeFlag) {
475bb1b9ea8a488eec833b0be18c45dae8505876042Svetoslav Ganov                case FEEDBACK_AUDIBLE:
476bb1b9ea8a488eec833b0be18c45dae8505876042Svetoslav Ganov                    builder.append("FEEDBACK_AUDIBLE");
477bb1b9ea8a488eec833b0be18c45dae8505876042Svetoslav Ganov                    break;
478bb1b9ea8a488eec833b0be18c45dae8505876042Svetoslav Ganov                case FEEDBACK_HAPTIC:
479bb1b9ea8a488eec833b0be18c45dae8505876042Svetoslav Ganov                    builder.append("FEEDBACK_HAPTIC");
480bb1b9ea8a488eec833b0be18c45dae8505876042Svetoslav Ganov                    break;
481bb1b9ea8a488eec833b0be18c45dae8505876042Svetoslav Ganov                case FEEDBACK_GENERIC:
482bb1b9ea8a488eec833b0be18c45dae8505876042Svetoslav Ganov                    builder.append("FEEDBACK_GENERIC");
483bb1b9ea8a488eec833b0be18c45dae8505876042Svetoslav Ganov                    break;
484bb1b9ea8a488eec833b0be18c45dae8505876042Svetoslav Ganov                case FEEDBACK_SPOKEN:
485bb1b9ea8a488eec833b0be18c45dae8505876042Svetoslav Ganov                    builder.append("FEEDBACK_SPOKEN");
486bb1b9ea8a488eec833b0be18c45dae8505876042Svetoslav Ganov                    break;
487bb1b9ea8a488eec833b0be18c45dae8505876042Svetoslav Ganov                case FEEDBACK_VISUAL:
488bb1b9ea8a488eec833b0be18c45dae8505876042Svetoslav Ganov                    builder.append("FEEDBACK_VISUAL");
489bb1b9ea8a488eec833b0be18c45dae8505876042Svetoslav Ganov                    break;
490bb1b9ea8a488eec833b0be18c45dae8505876042Svetoslav Ganov            }
491cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov        }
492bb1b9ea8a488eec833b0be18c45dae8505876042Svetoslav Ganov        builder.append("]");
493bb1b9ea8a488eec833b0be18c45dae8505876042Svetoslav Ganov        return builder.toString();
494cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov    }
495cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov
496cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov    /**
497cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov     * Returns the string representation of a flag. For example,
498cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov     * {@link #DEFAULT} is represented by the string DEFAULT.
499cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov     *
500cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov     * @param flag The flag.
501cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov     * @return The string representation.
502cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov     */
503cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov    public static String flagToString(int flag) {
504cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov        switch (flag) {
505cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov            case DEFAULT:
506cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov                return "DEFAULT";
507cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov            default:
508cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov                return null;
509cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov        }
51075986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov    }
51175986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov
51275986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov    /**
51375986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov     * @see Parcelable.Creator
51475986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov     */
51575986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov    public static final Parcelable.Creator<AccessibilityServiceInfo> CREATOR =
51675986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov            new Parcelable.Creator<AccessibilityServiceInfo>() {
51775986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov        public AccessibilityServiceInfo createFromParcel(Parcel parcel) {
51875986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov            AccessibilityServiceInfo info = new AccessibilityServiceInfo();
519cc4053e031371456fe54d51bbad1db721db4ae38Svetoslav Ganov            info.initFromParcel(parcel);
52075986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov            return info;
52175986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov        }
52275986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov
52375986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov        public AccessibilityServiceInfo[] newArray(int size) {
52475986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov            return new AccessibilityServiceInfo[size];
52575986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov        }
52675986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov    };
52775986cf9bc57ef11ad70f36fb77fbbf5d63af6ecsvetoslavganov}
528