1e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu/*
2e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * Copyright (C) 2012 The Android Open Source Project
3e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu *
4e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * Licensed under the Apache License, Version 2.0 (the "License");
5e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * you may not use this file except in compliance with the License.
6e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * You may obtain a copy of the License at
7e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu *
8e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu *      http://www.apache.org/licenses/LICENSE-2.0
9e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu *
10e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * Unless required by applicable law or agreed to in writing, software
11e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * distributed under the License is distributed on an "AS IS" BASIS,
12e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * See the License for the specific language governing permissions and
14e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * limitations under the License.
15e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu */
16e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu
17e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhupackage com.android.uiautomator.core;
18e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu
19e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhuimport android.util.SparseArray;
20e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhuimport android.view.accessibility.AccessibilityNodeInfo;
21e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu
224f72d8d757b71a767999703016ba4d6db7333457Adam Momtazimport java.util.regex.Pattern;
234f72d8d757b71a767999703016ba4d6db7333457Adam Momtaz
24e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu/**
25445e82ee022c484166ce7175973827f591ff2ea7quddusc * Specifies the elements in the layout hierarchy for tests to target, filtered
26445e82ee022c484166ce7175973827f591ff2ea7quddusc * by properties such as text value, content-description, class name, and state
27445e82ee022c484166ce7175973827f591ff2ea7quddusc * information. You can also target an element by its location in a layout
28445e82ee022c484166ce7175973827f591ff2ea7quddusc * hierarchy.
29dbba713661688a285e701a006ce2d199296ac328Guang Zhu * @since API Level 16
30e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu */
314ab790eccf6d5c27f542056b87d26d38f7caeeb3Adam Momtazpublic class UiSelector {
32e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu    static final int SELECTOR_NIL = 0;
33e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu    static final int SELECTOR_TEXT = 1;
34e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu    static final int SELECTOR_START_TEXT = 2;
35e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu    static final int SELECTOR_CONTAINS_TEXT = 3;
36e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu    static final int SELECTOR_CLASS = 4;
37e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu    static final int SELECTOR_DESCRIPTION = 5;
38e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu    static final int SELECTOR_START_DESCRIPTION = 6;
39e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu    static final int SELECTOR_CONTAINS_DESCRIPTION = 7;
40e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu    static final int SELECTOR_INDEX = 8;
41e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu    static final int SELECTOR_INSTANCE = 9;
42e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu    static final int SELECTOR_ENABLED = 10;
43e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu    static final int SELECTOR_FOCUSED = 11;
44e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu    static final int SELECTOR_FOCUSABLE = 12;
45e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu    static final int SELECTOR_SCROLLABLE = 13;
46e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu    static final int SELECTOR_CLICKABLE = 14;
47e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu    static final int SELECTOR_CHECKED = 15;
48e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu    static final int SELECTOR_SELECTED = 16;
49e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu    static final int SELECTOR_ID = 17;
50e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu    static final int SELECTOR_PACKAGE_NAME = 18;
51e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu    static final int SELECTOR_CHILD = 19;
52e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu    static final int SELECTOR_CONTAINER = 20;
53e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu    static final int SELECTOR_PATTERN = 21;
54e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu    static final int SELECTOR_PARENT = 22;
55e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu    static final int SELECTOR_COUNT = 23;
56336d1a84909be8ec12af8bc27c65825b13ad9909Adam Momtaz    static final int SELECTOR_LONG_CLICKABLE = 24;
57ee4b48cd50f6e4e24ba7f538b8a77c839c1087f5Adam Momtaz    static final int SELECTOR_TEXT_REGEX = 25;
58ee4b48cd50f6e4e24ba7f538b8a77c839c1087f5Adam Momtaz    static final int SELECTOR_CLASS_REGEX = 26;
59ee4b48cd50f6e4e24ba7f538b8a77c839c1087f5Adam Momtaz    static final int SELECTOR_DESCRIPTION_REGEX = 27;
60ee4b48cd50f6e4e24ba7f538b8a77c839c1087f5Adam Momtaz    static final int SELECTOR_PACKAGE_NAME_REGEX = 28;
61946d553eb162ee5ac4eeef2c91c40f36f3db791dAdam Momtaz    static final int SELECTOR_RESOURCE_ID = 29;
6297835f3a7c80b147136c44c175eb9e6a4261fd92Adam Momtaz    static final int SELECTOR_CHECKABLE = 30;
634f72d8d757b71a767999703016ba4d6db7333457Adam Momtaz    static final int SELECTOR_RESOURCE_ID_REGEX = 31;
64e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu
65e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu    private SparseArray<Object> mSelectorAttributes = new SparseArray<Object>();
66e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu
67dbba713661688a285e701a006ce2d199296ac328Guang Zhu    /**
68dbba713661688a285e701a006ce2d199296ac328Guang Zhu     * @since API Level 16
69dbba713661688a285e701a006ce2d199296ac328Guang Zhu     */
704ab790eccf6d5c27f542056b87d26d38f7caeeb3Adam Momtaz    public UiSelector() {
71e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu    }
72e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu
733d50587be8ff021369c90554d814839335b445b0Adam Momtaz    UiSelector(UiSelector selector) {
743d50587be8ff021369c90554d814839335b445b0Adam Momtaz        mSelectorAttributes = selector.cloneSelector().mSelectorAttributes;
75e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu    }
76e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu
77dbba713661688a285e701a006ce2d199296ac328Guang Zhu    /**
7879693ede92636fe6f3a6ec4dc049a438fd9504ffGuang Zhu     * @since API Level 17
79dbba713661688a285e701a006ce2d199296ac328Guang Zhu     */
803d50587be8ff021369c90554d814839335b445b0Adam Momtaz    protected UiSelector cloneSelector() {
814ab790eccf6d5c27f542056b87d26d38f7caeeb3Adam Momtaz        UiSelector ret = new UiSelector();
82e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu        ret.mSelectorAttributes = mSelectorAttributes.clone();
834f72d8d757b71a767999703016ba4d6db7333457Adam Momtaz        if (hasChildSelector())
843d50587be8ff021369c90554d814839335b445b0Adam Momtaz            ret.mSelectorAttributes.put(SELECTOR_CHILD, new UiSelector(getChildSelector()));
854f72d8d757b71a767999703016ba4d6db7333457Adam Momtaz        if (hasParentSelector())
863d50587be8ff021369c90554d814839335b445b0Adam Momtaz            ret.mSelectorAttributes.put(SELECTOR_PARENT, new UiSelector(getParentSelector()));
874f72d8d757b71a767999703016ba4d6db7333457Adam Momtaz        if (hasPatternSelector())
883d50587be8ff021369c90554d814839335b445b0Adam Momtaz            ret.mSelectorAttributes.put(SELECTOR_PATTERN, new UiSelector(getPatternSelector()));
89e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu        return ret;
90e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu    }
91e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu
924ab790eccf6d5c27f542056b87d26d38f7caeeb3Adam Momtaz    static UiSelector patternBuilder(UiSelector selector) {
934f72d8d757b71a767999703016ba4d6db7333457Adam Momtaz        if (!selector.hasPatternSelector()) {
944ab790eccf6d5c27f542056b87d26d38f7caeeb3Adam Momtaz            return new UiSelector().patternSelector(selector);
95e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu        }
96e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu        return selector;
97e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu    }
98e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu
994ab790eccf6d5c27f542056b87d26d38f7caeeb3Adam Momtaz    static UiSelector patternBuilder(UiSelector container, UiSelector pattern) {
1004ab790eccf6d5c27f542056b87d26d38f7caeeb3Adam Momtaz        return new UiSelector(
1014ab790eccf6d5c27f542056b87d26d38f7caeeb3Adam Momtaz                new UiSelector().containerSelector(container).patternSelector(pattern));
102e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu    }
103e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu
104a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz    /**
105a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     * Set the search criteria to match the visible text displayed
106445e82ee022c484166ce7175973827f591ff2ea7quddusc     * in a widget (for example, the text label to launch an app).
107a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     *
108445e82ee022c484166ce7175973827f591ff2ea7quddusc     * The text for the element must match exactly with the string in your input
109445e82ee022c484166ce7175973827f591ff2ea7quddusc     * argument. Matching is case-sensitive.
110a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     *
111a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     * @param text Value to match
112a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     * @return UiSelector with the specified search criteria
113dbba713661688a285e701a006ce2d199296ac328Guang Zhu     * @since API Level 16
114a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     */
1154ab790eccf6d5c27f542056b87d26d38f7caeeb3Adam Momtaz    public UiSelector text(String text) {
116e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu        return buildSelector(SELECTOR_TEXT, text);
117e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu    }
118e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu
119a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz    /**
120445e82ee022c484166ce7175973827f591ff2ea7quddusc     * Set the search criteria to match the visible text displayed in a layout
121445e82ee022c484166ce7175973827f591ff2ea7quddusc     * element, using a regular expression.
122ee4b48cd50f6e4e24ba7f538b8a77c839c1087f5Adam Momtaz     *
123445e82ee022c484166ce7175973827f591ff2ea7quddusc     * The text in the widget must match exactly with the string in your
124445e82ee022c484166ce7175973827f591ff2ea7quddusc     * input argument.
125ee4b48cd50f6e4e24ba7f538b8a77c839c1087f5Adam Momtaz     *
1261893caed0ad4e73b0676f206282d490c2d345316Thanh Le     * @param regex a regular expression
127ee4b48cd50f6e4e24ba7f538b8a77c839c1087f5Adam Momtaz     * @return UiSelector with the specified search criteria
128dbba713661688a285e701a006ce2d199296ac328Guang Zhu     * @since API Level 17
129ee4b48cd50f6e4e24ba7f538b8a77c839c1087f5Adam Momtaz     */
130ee4b48cd50f6e4e24ba7f538b8a77c839c1087f5Adam Momtaz    public UiSelector textMatches(String regex) {
1314f72d8d757b71a767999703016ba4d6db7333457Adam Momtaz        return buildSelector(SELECTOR_TEXT_REGEX, Pattern.compile(regex));
132ee4b48cd50f6e4e24ba7f538b8a77c839c1087f5Adam Momtaz    }
133ee4b48cd50f6e4e24ba7f538b8a77c839c1087f5Adam Momtaz
134ee4b48cd50f6e4e24ba7f538b8a77c839c1087f5Adam Momtaz    /**
135445e82ee022c484166ce7175973827f591ff2ea7quddusc     * Set the search criteria to match visible text in a widget that is
136445e82ee022c484166ce7175973827f591ff2ea7quddusc     * prefixed by the text parameter.
137a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     *
138445e82ee022c484166ce7175973827f591ff2ea7quddusc     * The matching is case-insensitive.
139a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     *
140445e82ee022c484166ce7175973827f591ff2ea7quddusc     * @param text Value to match
141445e82ee022c484166ce7175973827f591ff2ea7quddusc     * @return UiSelector with the specified search criteria
142dbba713661688a285e701a006ce2d199296ac328Guang Zhu     * @since API Level 16
143a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     */
1444ab790eccf6d5c27f542056b87d26d38f7caeeb3Adam Momtaz    public UiSelector textStartsWith(String text) {
145e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu        return buildSelector(SELECTOR_START_TEXT, text);
146e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu    }
147e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu
148a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz    /**
149445e82ee022c484166ce7175973827f591ff2ea7quddusc     * Set the search criteria to match the visible text in a widget
150445e82ee022c484166ce7175973827f591ff2ea7quddusc     * where the visible text must contain the string in your input argument.
151a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     *
152445e82ee022c484166ce7175973827f591ff2ea7quddusc     * The matching is case-sensitive.
153a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     *
154a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     * @param text Value to match
155a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     * @return UiSelector with the specified search criteria
156dbba713661688a285e701a006ce2d199296ac328Guang Zhu     * @since API Level 16
157a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     */
1584ab790eccf6d5c27f542056b87d26d38f7caeeb3Adam Momtaz    public UiSelector textContains(String text) {
159e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu        return buildSelector(SELECTOR_CONTAINS_TEXT, text);
160e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu    }
161e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu
162a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz    /**
163a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     * Set the search criteria to match the class property
164a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     * for a widget (for example, "android.widget.Button").
165a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     *
166a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     * @param className Value to match
167a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     * @return UiSelector with the specified search criteria
168dbba713661688a285e701a006ce2d199296ac328Guang Zhu     * @since API Level 16
169a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     */
1704ab790eccf6d5c27f542056b87d26d38f7caeeb3Adam Momtaz    public UiSelector className(String className) {
171e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu        return buildSelector(SELECTOR_CLASS, className);
172e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu    }
173e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu
174a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz    /**
175ee4b48cd50f6e4e24ba7f538b8a77c839c1087f5Adam Momtaz     * Set the search criteria to match the class property
176445e82ee022c484166ce7175973827f591ff2ea7quddusc     * for a widget, using a regular expression.
177ee4b48cd50f6e4e24ba7f538b8a77c839c1087f5Adam Momtaz     *
1781893caed0ad4e73b0676f206282d490c2d345316Thanh Le     * @param regex a regular expression
179ee4b48cd50f6e4e24ba7f538b8a77c839c1087f5Adam Momtaz     * @return UiSelector with the specified search criteria
180dbba713661688a285e701a006ce2d199296ac328Guang Zhu     * @since API Level 17
181ee4b48cd50f6e4e24ba7f538b8a77c839c1087f5Adam Momtaz     */
182ee4b48cd50f6e4e24ba7f538b8a77c839c1087f5Adam Momtaz    public UiSelector classNameMatches(String regex) {
1834f72d8d757b71a767999703016ba4d6db7333457Adam Momtaz        return buildSelector(SELECTOR_CLASS_REGEX, Pattern.compile(regex));
184ee4b48cd50f6e4e24ba7f538b8a77c839c1087f5Adam Momtaz    }
185ee4b48cd50f6e4e24ba7f538b8a77c839c1087f5Adam Momtaz
186ee4b48cd50f6e4e24ba7f538b8a77c839c1087f5Adam Momtaz    /**
187ee4b48cd50f6e4e24ba7f538b8a77c839c1087f5Adam Momtaz     * Set the search criteria to match the class property
188ee4b48cd50f6e4e24ba7f538b8a77c839c1087f5Adam Momtaz     * for a widget (for example, "android.widget.Button").
189ee4b48cd50f6e4e24ba7f538b8a77c839c1087f5Adam Momtaz     *
1901893caed0ad4e73b0676f206282d490c2d345316Thanh Le     * @param type type
191ee4b48cd50f6e4e24ba7f538b8a77c839c1087f5Adam Momtaz     * @return UiSelector with the specified search criteria
192dbba713661688a285e701a006ce2d199296ac328Guang Zhu     * @since API Level 17
193ee4b48cd50f6e4e24ba7f538b8a77c839c1087f5Adam Momtaz     */
194ee4b48cd50f6e4e24ba7f538b8a77c839c1087f5Adam Momtaz    public <T> UiSelector className(Class<T> type) {
195ee4b48cd50f6e4e24ba7f538b8a77c839c1087f5Adam Momtaz        return buildSelector(SELECTOR_CLASS, type.getName());
196ee4b48cd50f6e4e24ba7f538b8a77c839c1087f5Adam Momtaz    }
197ee4b48cd50f6e4e24ba7f538b8a77c839c1087f5Adam Momtaz
198ee4b48cd50f6e4e24ba7f538b8a77c839c1087f5Adam Momtaz    /**
199a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     * Set the search criteria to match the content-description
200a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     * property for a widget.
201a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     *
202a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     * The content-description is typically used
203a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     * by the Android Accessibility framework to
204a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     * provide an audio prompt for the widget when
205a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     * the widget is selected. The content-description
206a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     * for the widget must match exactly
207a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     * with the string in your input argument.
208a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     *
209a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     * Matching is case-sensitive.
210a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     *
211a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     * @param desc Value to match
212a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     * @return UiSelector with the specified search criteria
213dbba713661688a285e701a006ce2d199296ac328Guang Zhu     * @since API Level 16
214a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     */
2154ab790eccf6d5c27f542056b87d26d38f7caeeb3Adam Momtaz    public UiSelector description(String desc) {
216e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu        return buildSelector(SELECTOR_DESCRIPTION, desc);
217e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu    }
218e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu
219a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz    /**
220a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     * Set the search criteria to match the content-description
221a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     * property for a widget.
222a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     *
223a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     * The content-description is typically used
224a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     * by the Android Accessibility framework to
225a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     * provide an audio prompt for the widget when
226a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     * the widget is selected. The content-description
227ee4b48cd50f6e4e24ba7f538b8a77c839c1087f5Adam Momtaz     * for the widget must match exactly
228ee4b48cd50f6e4e24ba7f538b8a77c839c1087f5Adam Momtaz     * with the string in your input argument.
229ee4b48cd50f6e4e24ba7f538b8a77c839c1087f5Adam Momtaz     *
2301893caed0ad4e73b0676f206282d490c2d345316Thanh Le     * @param regex a regular expression
231ee4b48cd50f6e4e24ba7f538b8a77c839c1087f5Adam Momtaz     * @return UiSelector with the specified search criteria
232dbba713661688a285e701a006ce2d199296ac328Guang Zhu     * @since API Level 17
233ee4b48cd50f6e4e24ba7f538b8a77c839c1087f5Adam Momtaz     */
234ee4b48cd50f6e4e24ba7f538b8a77c839c1087f5Adam Momtaz    public UiSelector descriptionMatches(String regex) {
2354f72d8d757b71a767999703016ba4d6db7333457Adam Momtaz        return buildSelector(SELECTOR_DESCRIPTION_REGEX, Pattern.compile(regex));
236ee4b48cd50f6e4e24ba7f538b8a77c839c1087f5Adam Momtaz    }
237ee4b48cd50f6e4e24ba7f538b8a77c839c1087f5Adam Momtaz
238ee4b48cd50f6e4e24ba7f538b8a77c839c1087f5Adam Momtaz    /**
239ee4b48cd50f6e4e24ba7f538b8a77c839c1087f5Adam Momtaz     * Set the search criteria to match the content-description
240ee4b48cd50f6e4e24ba7f538b8a77c839c1087f5Adam Momtaz     * property for a widget.
241ee4b48cd50f6e4e24ba7f538b8a77c839c1087f5Adam Momtaz     *
242ee4b48cd50f6e4e24ba7f538b8a77c839c1087f5Adam Momtaz     * The content-description is typically used
243ee4b48cd50f6e4e24ba7f538b8a77c839c1087f5Adam Momtaz     * by the Android Accessibility framework to
244ee4b48cd50f6e4e24ba7f538b8a77c839c1087f5Adam Momtaz     * provide an audio prompt for the widget when
245ee4b48cd50f6e4e24ba7f538b8a77c839c1087f5Adam Momtaz     * the widget is selected. The content-description
246a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     * for the widget must start
247a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     * with the string in your input argument.
248a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     *
249a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     * Matching is case-insensitive.
250a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     *
251a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     * @param desc Value to match
252a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     * @return UiSelector with the specified search criteria
253dbba713661688a285e701a006ce2d199296ac328Guang Zhu     * @since API Level 16
254a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     */
2554ab790eccf6d5c27f542056b87d26d38f7caeeb3Adam Momtaz    public UiSelector descriptionStartsWith(String desc) {
256e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu        return buildSelector(SELECTOR_START_DESCRIPTION, desc);
257e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu    }
258e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu
259a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz    /**
260a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     * Set the search criteria to match the content-description
261a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     * property for a widget.
262a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     *
263a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     * The content-description is typically used
264a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     * by the Android Accessibility framework to
265a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     * provide an audio prompt for the widget when
266a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     * the widget is selected. The content-description
267a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     * for the widget must contain
268a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     * the string in your input argument.
269a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     *
270a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     * Matching is case-insensitive.
271a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     *
272a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     * @param desc Value to match
273a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     * @return UiSelector with the specified search criteria
274dbba713661688a285e701a006ce2d199296ac328Guang Zhu     * @since API Level 16
275a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     */
2764ab790eccf6d5c27f542056b87d26d38f7caeeb3Adam Momtaz    public UiSelector descriptionContains(String desc) {
277e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu        return buildSelector(SELECTOR_CONTAINS_DESCRIPTION, desc);
278e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu    }
279e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu
280a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz    /**
281445e82ee022c484166ce7175973827f591ff2ea7quddusc     * Set the search criteria to match the given resource ID.
28289f6117cb1fbeab3770106cf54e05af1f597be81Svetoslav Ganov     *
283445e82ee022c484166ce7175973827f591ff2ea7quddusc     * @param id Value to match
28489f6117cb1fbeab3770106cf54e05af1f597be81Svetoslav Ganov     * @return UiSelector with the specified search criteria
28589f6117cb1fbeab3770106cf54e05af1f597be81Svetoslav Ganov     * @since API Level 18
28689f6117cb1fbeab3770106cf54e05af1f597be81Svetoslav Ganov     */
287946d553eb162ee5ac4eeef2c91c40f36f3db791dAdam Momtaz    public UiSelector resourceId(String id) {
288946d553eb162ee5ac4eeef2c91c40f36f3db791dAdam Momtaz        return buildSelector(SELECTOR_RESOURCE_ID, id);
28989f6117cb1fbeab3770106cf54e05af1f597be81Svetoslav Ganov    }
29089f6117cb1fbeab3770106cf54e05af1f597be81Svetoslav Ganov
29189f6117cb1fbeab3770106cf54e05af1f597be81Svetoslav Ganov    /**
292445e82ee022c484166ce7175973827f591ff2ea7quddusc     * Set the search criteria to match the resource ID
293445e82ee022c484166ce7175973827f591ff2ea7quddusc     * of the widget, using a regular expression.http://blog.bettersoftwaretesting.com/
2944f72d8d757b71a767999703016ba4d6db7333457Adam Momtaz     *
2954f72d8d757b71a767999703016ba4d6db7333457Adam Momtaz     * @param regex a regular expression
2964f72d8d757b71a767999703016ba4d6db7333457Adam Momtaz     * @return UiSelector with the specified search criteria
2974f72d8d757b71a767999703016ba4d6db7333457Adam Momtaz     * @since API Level 18
2984f72d8d757b71a767999703016ba4d6db7333457Adam Momtaz     */
2994f72d8d757b71a767999703016ba4d6db7333457Adam Momtaz    public UiSelector resourceIdMatches(String regex) {
3004f72d8d757b71a767999703016ba4d6db7333457Adam Momtaz        return buildSelector(SELECTOR_RESOURCE_ID_REGEX, Pattern.compile(regex));
3014f72d8d757b71a767999703016ba4d6db7333457Adam Momtaz    }
3024f72d8d757b71a767999703016ba4d6db7333457Adam Momtaz
3034f72d8d757b71a767999703016ba4d6db7333457Adam Momtaz    /**
304a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     * Set the search criteria to match the widget by its node
305a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     * index in the layout hierarchy.
306a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     *
307a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     * The index value must be 0 or greater.
308a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     *
309a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     * Using the index can be unreliable and should only
310a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     * be used as a last resort for matching. Instead,
311a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     * consider using the {@link #instance(int)} method.
312a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     *
313a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     * @param index Value to match
314a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     * @return UiSelector with the specified search criteria
315dbba713661688a285e701a006ce2d199296ac328Guang Zhu     * @since API Level 16
316a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     */
3174ab790eccf6d5c27f542056b87d26d38f7caeeb3Adam Momtaz    public UiSelector index(final int index) {
318e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu        return buildSelector(SELECTOR_INDEX, index);
319e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu    }
320e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu
321a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz    /**
322a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     * Set the search criteria to match the
323a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     * widget by its instance number.
324a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     *
325a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     * The instance value must be 0 or greater, where
326a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     * the first instance is 0.
327a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     *
328a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     * For example, to simulate a user click on
329a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     * the third image that is enabled in a UI screen, you
330a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     * could specify a a search criteria where the instance is
331a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     * 2, the {@link #className(String)} matches the image
332a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     * widget class, and {@link #enabled(boolean)} is true.
333a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     * The code would look like this:
334a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     * <code>
335a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     * new UiSelector().className("android.widget.ImageView")
336a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     *    .enabled(true).instance(2);
337a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     * </code>
338a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     *
339a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     * @param instance Value to match
340a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     * @return UiSelector with the specified search criteria
341dbba713661688a285e701a006ce2d199296ac328Guang Zhu     * @since API Level 16
342a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     */
3434ab790eccf6d5c27f542056b87d26d38f7caeeb3Adam Momtaz    public UiSelector instance(final int instance) {
344e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu        return buildSelector(SELECTOR_INSTANCE, instance);
345e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu    }
346e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu
347a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz    /**
348a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     * Set the search criteria to match widgets that are enabled.
349a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     *
350a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     * Typically, using this search criteria alone is not useful.
351a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     * You should also include additional criteria, such as text,
352a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     * content-description, or the class name for a widget.
353a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     *
354a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     * If no other search criteria is specified, and there is more
355a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     * than one matching widget, the first widget in the tree
356a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     * is selected.
357a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     *
358a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     * @param val Value to match
359a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     * @return UiSelector with the specified search criteria
360dbba713661688a285e701a006ce2d199296ac328Guang Zhu     * @since API Level 16
361a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     */
3624ab790eccf6d5c27f542056b87d26d38f7caeeb3Adam Momtaz    public UiSelector enabled(boolean val) {
363e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu        return buildSelector(SELECTOR_ENABLED, val);
364e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu    }
365e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu
366a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz    /**
367a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     * Set the search criteria to match widgets that have focus.
368a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     *
369a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     * Typically, using this search criteria alone is not useful.
370a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     * You should also include additional criteria, such as text,
371a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     * content-description, or the class name for a widget.
372a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     *
373a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     * If no other search criteria is specified, and there is more
374a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     * than one matching widget, the first widget in the tree
375a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     * is selected.
376a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     *
377a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     * @param val Value to match
378a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     * @return UiSelector with the specified search criteria
379dbba713661688a285e701a006ce2d199296ac328Guang Zhu     * @since API Level 16
380a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     */
3814ab790eccf6d5c27f542056b87d26d38f7caeeb3Adam Momtaz    public UiSelector focused(boolean val) {
382e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu        return buildSelector(SELECTOR_FOCUSED, val);
383e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu    }
384e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu
385a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz    /**
386a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     * Set the search criteria to match widgets that are focusable.
387a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     *
388a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     * Typically, using this search criteria alone is not useful.
389a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     * You should also include additional criteria, such as text,
390a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     * content-description, or the class name for a widget.
391a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     *
392a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     * If no other search criteria is specified, and there is more
393a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     * than one matching widget, the first widget in the tree
394a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     * is selected.
395a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     *
396a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     * @param val Value to match
397a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     * @return UiSelector with the specified search criteria
398dbba713661688a285e701a006ce2d199296ac328Guang Zhu     * @since API Level 16
399a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     */
4004ab790eccf6d5c27f542056b87d26d38f7caeeb3Adam Momtaz    public UiSelector focusable(boolean val) {
401e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu        return buildSelector(SELECTOR_FOCUSABLE, val);
402e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu    }
403e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu
404a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz    /**
405a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     * Set the search criteria to match widgets that are scrollable.
406a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     *
407a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     * Typically, using this search criteria alone is not useful.
408a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     * You should also include additional criteria, such as text,
409a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     * content-description, or the class name for a widget.
410a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     *
411a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     * If no other search criteria is specified, and there is more
412a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     * than one matching widget, the first widget in the tree
413a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     * is selected.
414a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     *
415a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     * @param val Value to match
416a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     * @return UiSelector with the specified search criteria
417dbba713661688a285e701a006ce2d199296ac328Guang Zhu     * @since API Level 16
418a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     */
4194ab790eccf6d5c27f542056b87d26d38f7caeeb3Adam Momtaz    public UiSelector scrollable(boolean val) {
420e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu        return buildSelector(SELECTOR_SCROLLABLE, val);
421e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu    }
422e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu
423a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz    /**
424a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     * Set the search criteria to match widgets that
425a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     * are currently selected.
426a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     *
427a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     * Typically, using this search criteria alone is not useful.
428a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     * You should also include additional criteria, such as text,
429a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     * content-description, or the class name for a widget.
430a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     *
431a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     * If no other search criteria is specified, and there is more
432a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     * than one matching widget, the first widget in the tree
433a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     * is selected.
434a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     *
435a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     * @param val Value to match
436a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     * @return UiSelector with the specified search criteria
437dbba713661688a285e701a006ce2d199296ac328Guang Zhu     * @since API Level 16
438a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     */
4394ab790eccf6d5c27f542056b87d26d38f7caeeb3Adam Momtaz    public UiSelector selected(boolean val) {
440e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu        return buildSelector(SELECTOR_SELECTED, val);
441e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu    }
442e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu
443a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz    /**
444a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     * Set the search criteria to match widgets that
445a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     * are currently checked (usually for checkboxes).
446a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     *
447a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     * Typically, using this search criteria alone is not useful.
448a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     * You should also include additional criteria, such as text,
449a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     * content-description, or the class name for a widget.
450a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     *
451a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     * If no other search criteria is specified, and there is more
452a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     * than one matching widget, the first widget in the tree
453a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     * is selected.
454a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     *
455a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     * @param val Value to match
456a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     * @return UiSelector with the specified search criteria
457dbba713661688a285e701a006ce2d199296ac328Guang Zhu     * @since API Level 16
458a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     */
4594ab790eccf6d5c27f542056b87d26d38f7caeeb3Adam Momtaz    public UiSelector checked(boolean val) {
460e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu        return buildSelector(SELECTOR_CHECKED, val);
461e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu    }
462e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu
463a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz    /**
464a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     * Set the search criteria to match widgets that are clickable.
465a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     *
466a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     * Typically, using this search criteria alone is not useful.
467a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     * You should also include additional criteria, such as text,
468a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     * content-description, or the class name for a widget.
469a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     *
470a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     * If no other search criteria is specified, and there is more
471a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     * than one matching widget, the first widget in the tree
472a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     * is selected.
473a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     *
474a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     * @param val Value to match
475a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     * @return UiSelector with the specified search criteria
476dbba713661688a285e701a006ce2d199296ac328Guang Zhu     * @since API Level 16
477a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     */
4784ab790eccf6d5c27f542056b87d26d38f7caeeb3Adam Momtaz    public UiSelector clickable(boolean val) {
479e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu        return buildSelector(SELECTOR_CLICKABLE, val);
480e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu    }
481e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu
482a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz    /**
48397835f3a7c80b147136c44c175eb9e6a4261fd92Adam Momtaz     * Set the search criteria to match widgets that are checkable.
48497835f3a7c80b147136c44c175eb9e6a4261fd92Adam Momtaz     *
48597835f3a7c80b147136c44c175eb9e6a4261fd92Adam Momtaz     * Typically, using this search criteria alone is not useful.
48697835f3a7c80b147136c44c175eb9e6a4261fd92Adam Momtaz     * You should also include additional criteria, such as text,
48797835f3a7c80b147136c44c175eb9e6a4261fd92Adam Momtaz     * content-description, or the class name for a widget.
48897835f3a7c80b147136c44c175eb9e6a4261fd92Adam Momtaz     *
48997835f3a7c80b147136c44c175eb9e6a4261fd92Adam Momtaz     * If no other search criteria is specified, and there is more
49097835f3a7c80b147136c44c175eb9e6a4261fd92Adam Momtaz     * than one matching widget, the first widget in the tree
49197835f3a7c80b147136c44c175eb9e6a4261fd92Adam Momtaz     * is selected.
49297835f3a7c80b147136c44c175eb9e6a4261fd92Adam Momtaz     *
49397835f3a7c80b147136c44c175eb9e6a4261fd92Adam Momtaz     * @param val Value to match
49497835f3a7c80b147136c44c175eb9e6a4261fd92Adam Momtaz     * @return UiSelector with the specified search criteria
49597835f3a7c80b147136c44c175eb9e6a4261fd92Adam Momtaz     * @since API Level 18
49697835f3a7c80b147136c44c175eb9e6a4261fd92Adam Momtaz     */
49797835f3a7c80b147136c44c175eb9e6a4261fd92Adam Momtaz    public UiSelector checkable(boolean val) {
49897835f3a7c80b147136c44c175eb9e6a4261fd92Adam Momtaz        return buildSelector(SELECTOR_CHECKABLE, val);
49997835f3a7c80b147136c44c175eb9e6a4261fd92Adam Momtaz    }
50097835f3a7c80b147136c44c175eb9e6a4261fd92Adam Momtaz
50197835f3a7c80b147136c44c175eb9e6a4261fd92Adam Momtaz    /**
502336d1a84909be8ec12af8bc27c65825b13ad9909Adam Momtaz     * Set the search criteria to match widgets that are long-clickable.
503336d1a84909be8ec12af8bc27c65825b13ad9909Adam Momtaz     *
504336d1a84909be8ec12af8bc27c65825b13ad9909Adam Momtaz     * Typically, using this search criteria alone is not useful.
505336d1a84909be8ec12af8bc27c65825b13ad9909Adam Momtaz     * You should also include additional criteria, such as text,
506336d1a84909be8ec12af8bc27c65825b13ad9909Adam Momtaz     * content-description, or the class name for a widget.
507336d1a84909be8ec12af8bc27c65825b13ad9909Adam Momtaz     *
508336d1a84909be8ec12af8bc27c65825b13ad9909Adam Momtaz     * If no other search criteria is specified, and there is more
509336d1a84909be8ec12af8bc27c65825b13ad9909Adam Momtaz     * than one matching widget, the first widget in the tree
510336d1a84909be8ec12af8bc27c65825b13ad9909Adam Momtaz     * is selected.
511336d1a84909be8ec12af8bc27c65825b13ad9909Adam Momtaz     *
512336d1a84909be8ec12af8bc27c65825b13ad9909Adam Momtaz     * @param val Value to match
513336d1a84909be8ec12af8bc27c65825b13ad9909Adam Momtaz     * @return UiSelector with the specified search criteria
514dbba713661688a285e701a006ce2d199296ac328Guang Zhu     * @since API Level 17
515336d1a84909be8ec12af8bc27c65825b13ad9909Adam Momtaz     */
516336d1a84909be8ec12af8bc27c65825b13ad9909Adam Momtaz    public UiSelector longClickable(boolean val) {
517336d1a84909be8ec12af8bc27c65825b13ad9909Adam Momtaz        return buildSelector(SELECTOR_LONG_CLICKABLE, val);
518336d1a84909be8ec12af8bc27c65825b13ad9909Adam Momtaz    }
519336d1a84909be8ec12af8bc27c65825b13ad9909Adam Momtaz
520336d1a84909be8ec12af8bc27c65825b13ad9909Adam Momtaz    /**
521a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     * Adds a child UiSelector criteria to this selector.
522a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     *
523a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     * Use this selector to narrow the search scope to
524a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     * child widgets under a specific parent widget.
525a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     *
526a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     * @param selector
527a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     * @return UiSelector with this added search criterion
528dbba713661688a285e701a006ce2d199296ac328Guang Zhu     * @since API Level 16
529a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     */
5303d50587be8ff021369c90554d814839335b445b0Adam Momtaz    public UiSelector childSelector(UiSelector selector) {
5313d50587be8ff021369c90554d814839335b445b0Adam Momtaz        return buildSelector(SELECTOR_CHILD, selector);
532e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu    }
533e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu
5343d50587be8ff021369c90554d814839335b445b0Adam Momtaz    private UiSelector patternSelector(UiSelector selector) {
5353d50587be8ff021369c90554d814839335b445b0Adam Momtaz        return buildSelector(SELECTOR_PATTERN, selector);
536e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu    }
537e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu
5383d50587be8ff021369c90554d814839335b445b0Adam Momtaz    private UiSelector containerSelector(UiSelector selector) {
5393d50587be8ff021369c90554d814839335b445b0Adam Momtaz        return buildSelector(SELECTOR_CONTAINER, selector);
540e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu    }
541e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu
542a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz    /**
543a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     * Adds a child UiSelector criteria to this selector which is used to
544a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     * start search from the parent widget.
545a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     *
546a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     * Use this selector to narrow the search scope to
547a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     * sibling widgets as well all child widgets under a parent.
548a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     *
549a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     * @param selector
550a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     * @return UiSelector with this added search criterion
551dbba713661688a285e701a006ce2d199296ac328Guang Zhu     * @since API Level 16
552a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     */
5533d50587be8ff021369c90554d814839335b445b0Adam Momtaz    public UiSelector fromParent(UiSelector selector) {
5543d50587be8ff021369c90554d814839335b445b0Adam Momtaz        return buildSelector(SELECTOR_PARENT, selector);
555e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu    }
556e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu
557a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz    /**
558a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     * Set the search criteria to match the package name
559a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     * of the application that contains the widget.
560a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     *
561a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     * @param name Value to match
562a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     * @return UiSelector with the specified search criteria
563dbba713661688a285e701a006ce2d199296ac328Guang Zhu     * @since API Level 16
564a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     */
5654ab790eccf6d5c27f542056b87d26d38f7caeeb3Adam Momtaz    public UiSelector packageName(String name) {
566e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu        return buildSelector(SELECTOR_PACKAGE_NAME, name);
567e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu    }
568e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu
569e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu    /**
570ee4b48cd50f6e4e24ba7f538b8a77c839c1087f5Adam Momtaz     * Set the search criteria to match the package name
571ee4b48cd50f6e4e24ba7f538b8a77c839c1087f5Adam Momtaz     * of the application that contains the widget.
572ee4b48cd50f6e4e24ba7f538b8a77c839c1087f5Adam Momtaz     *
5731893caed0ad4e73b0676f206282d490c2d345316Thanh Le     * @param regex a regular expression
574ee4b48cd50f6e4e24ba7f538b8a77c839c1087f5Adam Momtaz     * @return UiSelector with the specified search criteria
575dbba713661688a285e701a006ce2d199296ac328Guang Zhu     * @since API Level 17
576ee4b48cd50f6e4e24ba7f538b8a77c839c1087f5Adam Momtaz     */
577ee4b48cd50f6e4e24ba7f538b8a77c839c1087f5Adam Momtaz    public UiSelector packageNameMatches(String regex) {
5784f72d8d757b71a767999703016ba4d6db7333457Adam Momtaz        return buildSelector(SELECTOR_PACKAGE_NAME_REGEX, Pattern.compile(regex));
579ee4b48cd50f6e4e24ba7f538b8a77c839c1087f5Adam Momtaz    }
580ee4b48cd50f6e4e24ba7f538b8a77c839c1087f5Adam Momtaz
581ee4b48cd50f6e4e24ba7f538b8a77c839c1087f5Adam Momtaz    /**
5823d50587be8ff021369c90554d814839335b445b0Adam Momtaz     * Building a UiSelector always returns a new UiSelector and never modifies the
5833d50587be8ff021369c90554d814839335b445b0Adam Momtaz     * existing UiSelector being used.
584e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu     */
5854ab790eccf6d5c27f542056b87d26d38f7caeeb3Adam Momtaz    private UiSelector buildSelector(int selectorId, Object selectorValue) {
5863d50587be8ff021369c90554d814839335b445b0Adam Momtaz        UiSelector selector = new UiSelector(this);
5874f72d8d757b71a767999703016ba4d6db7333457Adam Momtaz        if (selectorId == SELECTOR_CHILD || selectorId == SELECTOR_PARENT)
5883d50587be8ff021369c90554d814839335b445b0Adam Momtaz            selector.getLastSubSelector().mSelectorAttributes.put(selectorId, selectorValue);
589e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu        else
5903d50587be8ff021369c90554d814839335b445b0Adam Momtaz            selector.mSelectorAttributes.put(selectorId, selectorValue);
5913d50587be8ff021369c90554d814839335b445b0Adam Momtaz        return selector;
592e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu    }
593e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu
594e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu    /**
595e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu     * Selectors may have a hierarchy defined by specifying child nodes to be matched.
596e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu     * It is not necessary that every selector have more than one level. A selector
597e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu     * can also be a single level referencing only one node. In such cases the return
598e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu     * it null.
599a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz     *
600e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu     * @return a child selector if one exists. Else null if this selector does not
601e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu     * reference child node.
602e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu     */
6034ab790eccf6d5c27f542056b87d26d38f7caeeb3Adam Momtaz    UiSelector getChildSelector() {
6043d50587be8ff021369c90554d814839335b445b0Adam Momtaz        UiSelector selector = (UiSelector)mSelectorAttributes.get(UiSelector.SELECTOR_CHILD, null);
6054f72d8d757b71a767999703016ba4d6db7333457Adam Momtaz        if (selector != null)
6063d50587be8ff021369c90554d814839335b445b0Adam Momtaz            return new UiSelector(selector);
607e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu        return null;
608e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu    }
609e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu
6104ab790eccf6d5c27f542056b87d26d38f7caeeb3Adam Momtaz    UiSelector getPatternSelector() {
6113d50587be8ff021369c90554d814839335b445b0Adam Momtaz        UiSelector selector =
6123d50587be8ff021369c90554d814839335b445b0Adam Momtaz                (UiSelector)mSelectorAttributes.get(UiSelector.SELECTOR_PATTERN, null);
6134f72d8d757b71a767999703016ba4d6db7333457Adam Momtaz        if (selector != null)
6143d50587be8ff021369c90554d814839335b445b0Adam Momtaz            return new UiSelector(selector);
615e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu        return null;
616e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu    }
617e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu
6184ab790eccf6d5c27f542056b87d26d38f7caeeb3Adam Momtaz    UiSelector getContainerSelector() {
6193d50587be8ff021369c90554d814839335b445b0Adam Momtaz        UiSelector selector =
6203d50587be8ff021369c90554d814839335b445b0Adam Momtaz                (UiSelector)mSelectorAttributes.get(UiSelector.SELECTOR_CONTAINER, null);
6214f72d8d757b71a767999703016ba4d6db7333457Adam Momtaz        if (selector != null)
6223d50587be8ff021369c90554d814839335b445b0Adam Momtaz            return new UiSelector(selector);
623e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu        return null;
624e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu    }
625e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu
6264ab790eccf6d5c27f542056b87d26d38f7caeeb3Adam Momtaz    UiSelector getParentSelector() {
6273d50587be8ff021369c90554d814839335b445b0Adam Momtaz        UiSelector selector =
6283d50587be8ff021369c90554d814839335b445b0Adam Momtaz                (UiSelector) mSelectorAttributes.get(UiSelector.SELECTOR_PARENT, null);
6294f72d8d757b71a767999703016ba4d6db7333457Adam Momtaz        if (selector != null)
6303d50587be8ff021369c90554d814839335b445b0Adam Momtaz            return new UiSelector(selector);
631e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu        return null;
632e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu    }
633e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu
634e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu    int getInstance() {
6354ab790eccf6d5c27f542056b87d26d38f7caeeb3Adam Momtaz        return getInt(UiSelector.SELECTOR_INSTANCE);
636e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu    }
637e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu
638e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu    String getString(int criterion) {
639e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu        return (String) mSelectorAttributes.get(criterion, null);
640e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu    }
641e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu
642e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu    boolean getBoolean(int criterion) {
643e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu        return (Boolean) mSelectorAttributes.get(criterion, false);
644e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu    }
645e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu
646e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu    int getInt(int criterion) {
647e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu        return (Integer) mSelectorAttributes.get(criterion, 0);
648e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu    }
649e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu
6504f72d8d757b71a767999703016ba4d6db7333457Adam Momtaz    Pattern getPattern(int criterion) {
6514f72d8d757b71a767999703016ba4d6db7333457Adam Momtaz        return (Pattern) mSelectorAttributes.get(criterion, null);
6524f72d8d757b71a767999703016ba4d6db7333457Adam Momtaz    }
6534f72d8d757b71a767999703016ba4d6db7333457Adam Momtaz
654e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu    boolean isMatchFor(AccessibilityNodeInfo node, int index) {
655e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu        int size = mSelectorAttributes.size();
656e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu        for(int x = 0; x < size; x++) {
657e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu            CharSequence s = null;
658e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu            int criterion = mSelectorAttributes.keyAt(x);
659e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu            switch(criterion) {
6604ab790eccf6d5c27f542056b87d26d38f7caeeb3Adam Momtaz            case UiSelector.SELECTOR_INDEX:
6614f72d8d757b71a767999703016ba4d6db7333457Adam Momtaz                if (index != this.getInt(criterion))
662e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu                    return false;
663e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu                break;
6644ab790eccf6d5c27f542056b87d26d38f7caeeb3Adam Momtaz            case UiSelector.SELECTOR_CHECKED:
665e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu                if (node.isChecked() != getBoolean(criterion)) {
666e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu                    return false;
667e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu                }
668e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu                break;
6694ab790eccf6d5c27f542056b87d26d38f7caeeb3Adam Momtaz            case UiSelector.SELECTOR_CLASS:
670e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu                s = node.getClassName();
671e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu                if (s == null || !s.toString().contentEquals(getString(criterion))) {
672e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu                    return false;
673e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu                }
674e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu                break;
675ee4b48cd50f6e4e24ba7f538b8a77c839c1087f5Adam Momtaz            case UiSelector.SELECTOR_CLASS_REGEX:
676ee4b48cd50f6e4e24ba7f538b8a77c839c1087f5Adam Momtaz                s = node.getClassName();
6774f72d8d757b71a767999703016ba4d6db7333457Adam Momtaz                if (s == null || !getPattern(criterion).matcher(s).matches()) {
678ee4b48cd50f6e4e24ba7f538b8a77c839c1087f5Adam Momtaz                    return false;
679ee4b48cd50f6e4e24ba7f538b8a77c839c1087f5Adam Momtaz                }
680ee4b48cd50f6e4e24ba7f538b8a77c839c1087f5Adam Momtaz                break;
6814ab790eccf6d5c27f542056b87d26d38f7caeeb3Adam Momtaz            case UiSelector.SELECTOR_CLICKABLE:
682e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu                if (node.isClickable() != getBoolean(criterion)) {
683e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu                    return false;
684e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu                }
685e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu                break;
68697835f3a7c80b147136c44c175eb9e6a4261fd92Adam Momtaz            case UiSelector.SELECTOR_CHECKABLE:
68797835f3a7c80b147136c44c175eb9e6a4261fd92Adam Momtaz                if (node.isCheckable() != getBoolean(criterion)) {
68897835f3a7c80b147136c44c175eb9e6a4261fd92Adam Momtaz                    return false;
68997835f3a7c80b147136c44c175eb9e6a4261fd92Adam Momtaz                }
69097835f3a7c80b147136c44c175eb9e6a4261fd92Adam Momtaz                break;
691336d1a84909be8ec12af8bc27c65825b13ad9909Adam Momtaz            case UiSelector.SELECTOR_LONG_CLICKABLE:
692336d1a84909be8ec12af8bc27c65825b13ad9909Adam Momtaz                if (node.isLongClickable() != getBoolean(criterion)) {
693336d1a84909be8ec12af8bc27c65825b13ad9909Adam Momtaz                    return false;
694336d1a84909be8ec12af8bc27c65825b13ad9909Adam Momtaz                }
695336d1a84909be8ec12af8bc27c65825b13ad9909Adam Momtaz                break;
6964ab790eccf6d5c27f542056b87d26d38f7caeeb3Adam Momtaz            case UiSelector.SELECTOR_CONTAINS_DESCRIPTION:
697e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu                s = node.getContentDescription();
6984f72d8d757b71a767999703016ba4d6db7333457Adam Momtaz                if (s == null || !s.toString().toLowerCase()
699e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu                        .contains(getString(criterion).toLowerCase())) {
700e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu                    return false;
701e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu                }
702e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu                break;
7034ab790eccf6d5c27f542056b87d26d38f7caeeb3Adam Momtaz            case UiSelector.SELECTOR_START_DESCRIPTION:
704e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu                s = node.getContentDescription();
7054f72d8d757b71a767999703016ba4d6db7333457Adam Momtaz                if (s == null || !s.toString().toLowerCase()
706e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu                        .startsWith(getString(criterion).toLowerCase())) {
707e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu                    return false;
708e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu                }
709e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu                break;
7104ab790eccf6d5c27f542056b87d26d38f7caeeb3Adam Momtaz            case UiSelector.SELECTOR_DESCRIPTION:
711e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu                s = node.getContentDescription();
7124f72d8d757b71a767999703016ba4d6db7333457Adam Momtaz                if (s == null || !s.toString().contentEquals(getString(criterion))) {
713e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu                    return false;
714e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu                }
715e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu                break;
716ee4b48cd50f6e4e24ba7f538b8a77c839c1087f5Adam Momtaz            case UiSelector.SELECTOR_DESCRIPTION_REGEX:
717ee4b48cd50f6e4e24ba7f538b8a77c839c1087f5Adam Momtaz                s = node.getContentDescription();
7184f72d8d757b71a767999703016ba4d6db7333457Adam Momtaz                if (s == null || !getPattern(criterion).matcher(s).matches()) {
719ee4b48cd50f6e4e24ba7f538b8a77c839c1087f5Adam Momtaz                    return false;
720ee4b48cd50f6e4e24ba7f538b8a77c839c1087f5Adam Momtaz                }
721ee4b48cd50f6e4e24ba7f538b8a77c839c1087f5Adam Momtaz                break;
7224ab790eccf6d5c27f542056b87d26d38f7caeeb3Adam Momtaz            case UiSelector.SELECTOR_CONTAINS_TEXT:
723e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu                s = node.getText();
7244f72d8d757b71a767999703016ba4d6db7333457Adam Momtaz                if (s == null || !s.toString().toLowerCase()
725e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu                        .contains(getString(criterion).toLowerCase())) {
726e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu                    return false;
727e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu                }
728e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu                break;
7294ab790eccf6d5c27f542056b87d26d38f7caeeb3Adam Momtaz            case UiSelector.SELECTOR_START_TEXT:
730e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu                s = node.getText();
7314f72d8d757b71a767999703016ba4d6db7333457Adam Momtaz                if (s == null || !s.toString().toLowerCase()
732e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu                        .startsWith(getString(criterion).toLowerCase())) {
733e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu                    return false;
734e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu                }
735e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu                break;
7364ab790eccf6d5c27f542056b87d26d38f7caeeb3Adam Momtaz            case UiSelector.SELECTOR_TEXT:
737e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu                s = node.getText();
7384f72d8d757b71a767999703016ba4d6db7333457Adam Momtaz                if (s == null || !s.toString().contentEquals(getString(criterion))) {
739e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu                    return false;
740e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu                }
741e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu                break;
742ee4b48cd50f6e4e24ba7f538b8a77c839c1087f5Adam Momtaz            case UiSelector.SELECTOR_TEXT_REGEX:
743ee4b48cd50f6e4e24ba7f538b8a77c839c1087f5Adam Momtaz                s = node.getText();
7444f72d8d757b71a767999703016ba4d6db7333457Adam Momtaz                if (s == null || !getPattern(criterion).matcher(s).matches()) {
745ee4b48cd50f6e4e24ba7f538b8a77c839c1087f5Adam Momtaz                    return false;
746ee4b48cd50f6e4e24ba7f538b8a77c839c1087f5Adam Momtaz                }
747ee4b48cd50f6e4e24ba7f538b8a77c839c1087f5Adam Momtaz                break;
7484ab790eccf6d5c27f542056b87d26d38f7caeeb3Adam Momtaz            case UiSelector.SELECTOR_ENABLED:
7494f72d8d757b71a767999703016ba4d6db7333457Adam Momtaz                if (node.isEnabled() != getBoolean(criterion)) {
750e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu                    return false;
751e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu                }
752e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu                break;
7534ab790eccf6d5c27f542056b87d26d38f7caeeb3Adam Momtaz            case UiSelector.SELECTOR_FOCUSABLE:
7544f72d8d757b71a767999703016ba4d6db7333457Adam Momtaz                if (node.isFocusable() != getBoolean(criterion)) {
755e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu                    return false;
756e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu                }
757e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu                break;
7584ab790eccf6d5c27f542056b87d26d38f7caeeb3Adam Momtaz            case UiSelector.SELECTOR_FOCUSED:
7594f72d8d757b71a767999703016ba4d6db7333457Adam Momtaz                if (node.isFocused() != getBoolean(criterion)) {
760e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu                    return false;
761e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu                }
762e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu                break;
7634ab790eccf6d5c27f542056b87d26d38f7caeeb3Adam Momtaz            case UiSelector.SELECTOR_ID:
764e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu                break; //TODO: do we need this for AccessibilityNodeInfo.id?
7654ab790eccf6d5c27f542056b87d26d38f7caeeb3Adam Momtaz            case UiSelector.SELECTOR_PACKAGE_NAME:
766e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu                s = node.getPackageName();
7674f72d8d757b71a767999703016ba4d6db7333457Adam Momtaz                if (s == null || !s.toString().contentEquals(getString(criterion))) {
768e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu                    return false;
769e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu                }
770e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu                break;
771ee4b48cd50f6e4e24ba7f538b8a77c839c1087f5Adam Momtaz            case UiSelector.SELECTOR_PACKAGE_NAME_REGEX:
772ee4b48cd50f6e4e24ba7f538b8a77c839c1087f5Adam Momtaz                s = node.getPackageName();
7734f72d8d757b71a767999703016ba4d6db7333457Adam Momtaz                if (s == null || !getPattern(criterion).matcher(s).matches()) {
774ee4b48cd50f6e4e24ba7f538b8a77c839c1087f5Adam Momtaz                    return false;
775ee4b48cd50f6e4e24ba7f538b8a77c839c1087f5Adam Momtaz                }
776ee4b48cd50f6e4e24ba7f538b8a77c839c1087f5Adam Momtaz                break;
7774ab790eccf6d5c27f542056b87d26d38f7caeeb3Adam Momtaz            case UiSelector.SELECTOR_SCROLLABLE:
7784f72d8d757b71a767999703016ba4d6db7333457Adam Momtaz                if (node.isScrollable() != getBoolean(criterion)) {
779e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu                    return false;
780e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu                }
781e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu                break;
7824ab790eccf6d5c27f542056b87d26d38f7caeeb3Adam Momtaz            case UiSelector.SELECTOR_SELECTED:
7834f72d8d757b71a767999703016ba4d6db7333457Adam Momtaz                if (node.isSelected() != getBoolean(criterion)) {
784e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu                    return false;
785e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu                }
786e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu                break;
787946d553eb162ee5ac4eeef2c91c40f36f3db791dAdam Momtaz            case UiSelector.SELECTOR_RESOURCE_ID:
7886b8d14ca5b3c2cbc066133da2e66658fb81f206eAdam Momtaz                s = node.getViewIdResourceName();
7896b8d14ca5b3c2cbc066133da2e66658fb81f206eAdam Momtaz                if (s == null || !s.toString().contentEquals(getString(criterion))) {
79089f6117cb1fbeab3770106cf54e05af1f597be81Svetoslav Ganov                    return false;
79189f6117cb1fbeab3770106cf54e05af1f597be81Svetoslav Ganov                }
79289f6117cb1fbeab3770106cf54e05af1f597be81Svetoslav Ganov                break;
7934f72d8d757b71a767999703016ba4d6db7333457Adam Momtaz            case UiSelector.SELECTOR_RESOURCE_ID_REGEX:
7944f72d8d757b71a767999703016ba4d6db7333457Adam Momtaz                s = node.getViewIdResourceName();
7954f72d8d757b71a767999703016ba4d6db7333457Adam Momtaz                if (s == null || !getPattern(criterion).matcher(s).matches()) {
7964f72d8d757b71a767999703016ba4d6db7333457Adam Momtaz                    return false;
7974f72d8d757b71a767999703016ba4d6db7333457Adam Momtaz                }
7984f72d8d757b71a767999703016ba4d6db7333457Adam Momtaz                break;
799e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu            }
800e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu        }
801e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu        return matchOrUpdateInstance();
802e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu    }
803e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu
804e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu    private boolean matchOrUpdateInstance() {
805e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu        int currentSelectorCounter = 0;
806e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu        int currentSelectorInstance = 0;
807e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu
808e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu        // matched attributes - now check for matching instance number
8094f72d8d757b71a767999703016ba4d6db7333457Adam Momtaz        if (mSelectorAttributes.indexOfKey(UiSelector.SELECTOR_INSTANCE) >= 0) {
8104ab790eccf6d5c27f542056b87d26d38f7caeeb3Adam Momtaz            currentSelectorInstance =
8114ab790eccf6d5c27f542056b87d26d38f7caeeb3Adam Momtaz                    (Integer)mSelectorAttributes.get(UiSelector.SELECTOR_INSTANCE);
812e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu        }
813e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu
814e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu        // instance is required. Add count if not already counting
8154f72d8d757b71a767999703016ba4d6db7333457Adam Momtaz        if (mSelectorAttributes.indexOfKey(UiSelector.SELECTOR_COUNT) >= 0) {
8164ab790eccf6d5c27f542056b87d26d38f7caeeb3Adam Momtaz            currentSelectorCounter = (Integer)mSelectorAttributes.get(UiSelector.SELECTOR_COUNT);
817e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu        }
818e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu
819e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu        // Verify
820e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu        if (currentSelectorInstance == currentSelectorCounter) {
821e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu            return true;
822e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu        }
823e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu        // Update count
824e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu        if (currentSelectorInstance > currentSelectorCounter) {
8254ab790eccf6d5c27f542056b87d26d38f7caeeb3Adam Momtaz            mSelectorAttributes.put(UiSelector.SELECTOR_COUNT, ++currentSelectorCounter);
826e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu        }
827e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu        return false;
828e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu    }
829e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu
830e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu    /**
831e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu     * Leaf selector indicates no more child or parent selectors
832e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu     * are declared in the this selector.
833e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu     * @return true if is leaf.
834e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu     */
835e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu    boolean isLeaf() {
8364f72d8d757b71a767999703016ba4d6db7333457Adam Momtaz        if (mSelectorAttributes.indexOfKey(UiSelector.SELECTOR_CHILD) < 0 &&
8374ab790eccf6d5c27f542056b87d26d38f7caeeb3Adam Momtaz                mSelectorAttributes.indexOfKey(UiSelector.SELECTOR_PARENT) < 0) {
838e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu            return true;
839e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu        }
840e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu        return false;
841e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu    }
842e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu
843e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu    boolean hasChildSelector() {
8444f72d8d757b71a767999703016ba4d6db7333457Adam Momtaz        if (mSelectorAttributes.indexOfKey(UiSelector.SELECTOR_CHILD) < 0) {
845e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu            return false;
846e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu        }
847e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu        return true;
848e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu    }
849e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu
850e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu    boolean hasPatternSelector() {
8514f72d8d757b71a767999703016ba4d6db7333457Adam Momtaz        if (mSelectorAttributes.indexOfKey(UiSelector.SELECTOR_PATTERN) < 0) {
852e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu            return false;
853e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu        }
854e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu        return true;
855e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu    }
856e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu
857e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu    boolean hasContainerSelector() {
8584f72d8d757b71a767999703016ba4d6db7333457Adam Momtaz        if (mSelectorAttributes.indexOfKey(UiSelector.SELECTOR_CONTAINER) < 0) {
859e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu            return false;
860e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu        }
861e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu        return true;
862e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu    }
863e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu
864e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu    boolean hasParentSelector() {
8654f72d8d757b71a767999703016ba4d6db7333457Adam Momtaz        if (mSelectorAttributes.indexOfKey(UiSelector.SELECTOR_PARENT) < 0) {
866e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu            return false;
867e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu        }
868e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu        return true;
869e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu    }
870e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu
871e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu    /**
872e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu     * Returns the deepest selector in the chain of possible sub selectors.
8734ab790eccf6d5c27f542056b87d26d38f7caeeb3Adam Momtaz     * A chain of selector is created when either of {@link UiSelector#childSelector(UiSelector)}
8744ab790eccf6d5c27f542056b87d26d38f7caeeb3Adam Momtaz     * or {@link UiSelector#fromParent(UiSelector)} are used once or more in the construction of
875e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu     * a selector.
8763d50587be8ff021369c90554d814839335b445b0Adam Momtaz     * @return last UiSelector in chain
877e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu     */
8784ab790eccf6d5c27f542056b87d26d38f7caeeb3Adam Momtaz    private UiSelector getLastSubSelector() {
8794f72d8d757b71a767999703016ba4d6db7333457Adam Momtaz        if (mSelectorAttributes.indexOfKey(UiSelector.SELECTOR_CHILD) >= 0) {
8804ab790eccf6d5c27f542056b87d26d38f7caeeb3Adam Momtaz            UiSelector child = (UiSelector)mSelectorAttributes.get(UiSelector.SELECTOR_CHILD);
8814f72d8d757b71a767999703016ba4d6db7333457Adam Momtaz            if (child.getLastSubSelector() == null) {
882e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu                return child;
883e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu            }
884e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu            return child.getLastSubSelector();
8854f72d8d757b71a767999703016ba4d6db7333457Adam Momtaz        } else if (mSelectorAttributes.indexOfKey(UiSelector.SELECTOR_PARENT) >= 0) {
8864ab790eccf6d5c27f542056b87d26d38f7caeeb3Adam Momtaz            UiSelector parent = (UiSelector)mSelectorAttributes.get(UiSelector.SELECTOR_PARENT);
8874f72d8d757b71a767999703016ba4d6db7333457Adam Momtaz            if (parent.getLastSubSelector() == null) {
888e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu                return parent;
889e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu            }
890e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu            return parent.getLastSubSelector();
891e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu        }
892e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu        return this;
893e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu    }
894e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu
895e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu    @Override
896e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu    public String toString() {
897e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu        return dumpToString(true);
898e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu    }
899e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu
900e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu    String dumpToString(boolean all) {
901e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu        StringBuilder builder = new StringBuilder();
9023d50587be8ff021369c90554d814839335b445b0Adam Momtaz        builder.append(UiSelector.class.getSimpleName() + "[");
903e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu        final int criterionCount = mSelectorAttributes.size();
904e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu        for (int i = 0; i < criterionCount; i++) {
905e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu            if (i > 0) {
906e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu                builder.append(", ");
907e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu            }
908e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu            final int criterion = mSelectorAttributes.keyAt(i);
909e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu            switch (criterion) {
910e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu            case SELECTOR_TEXT:
911e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu                builder.append("TEXT=").append(mSelectorAttributes.valueAt(i));
912e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu                break;
913ee4b48cd50f6e4e24ba7f538b8a77c839c1087f5Adam Momtaz            case SELECTOR_TEXT_REGEX:
914ee4b48cd50f6e4e24ba7f538b8a77c839c1087f5Adam Momtaz                builder.append("TEXT_REGEX=").append(mSelectorAttributes.valueAt(i));
915ee4b48cd50f6e4e24ba7f538b8a77c839c1087f5Adam Momtaz                break;
916e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu            case SELECTOR_START_TEXT:
917e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu                builder.append("START_TEXT=").append(mSelectorAttributes.valueAt(i));
918e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu                break;
919e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu            case SELECTOR_CONTAINS_TEXT:
920e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu                builder.append("CONTAINS_TEXT=").append(mSelectorAttributes.valueAt(i));
921e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu                break;
922e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu            case SELECTOR_CLASS:
923e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu                builder.append("CLASS=").append(mSelectorAttributes.valueAt(i));
924e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu                break;
925ee4b48cd50f6e4e24ba7f538b8a77c839c1087f5Adam Momtaz            case SELECTOR_CLASS_REGEX:
926ee4b48cd50f6e4e24ba7f538b8a77c839c1087f5Adam Momtaz                builder.append("CLASS_REGEX=").append(mSelectorAttributes.valueAt(i));
927ee4b48cd50f6e4e24ba7f538b8a77c839c1087f5Adam Momtaz                break;
928e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu            case SELECTOR_DESCRIPTION:
929e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu                builder.append("DESCRIPTION=").append(mSelectorAttributes.valueAt(i));
930e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu                break;
931ee4b48cd50f6e4e24ba7f538b8a77c839c1087f5Adam Momtaz            case SELECTOR_DESCRIPTION_REGEX:
932ee4b48cd50f6e4e24ba7f538b8a77c839c1087f5Adam Momtaz                builder.append("DESCRIPTION_REGEX=").append(mSelectorAttributes.valueAt(i));
933ee4b48cd50f6e4e24ba7f538b8a77c839c1087f5Adam Momtaz                break;
934e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu            case SELECTOR_START_DESCRIPTION:
935e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu                builder.append("START_DESCRIPTION=").append(mSelectorAttributes.valueAt(i));
936e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu                break;
937e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu            case SELECTOR_CONTAINS_DESCRIPTION:
938e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu                builder.append("CONTAINS_DESCRIPTION=").append(mSelectorAttributes.valueAt(i));
939e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu                break;
940e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu            case SELECTOR_INDEX:
941e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu                builder.append("INDEX=").append(mSelectorAttributes.valueAt(i));
942e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu                break;
943e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu            case SELECTOR_INSTANCE:
944e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu                builder.append("INSTANCE=").append(mSelectorAttributes.valueAt(i));
945e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu                break;
946e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu            case SELECTOR_ENABLED:
947e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu                builder.append("ENABLED=").append(mSelectorAttributes.valueAt(i));
948e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu                break;
949e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu            case SELECTOR_FOCUSED:
950e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu                builder.append("FOCUSED=").append(mSelectorAttributes.valueAt(i));
951e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu                break;
952e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu            case SELECTOR_FOCUSABLE:
953e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu                builder.append("FOCUSABLE=").append(mSelectorAttributes.valueAt(i));
954e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu                break;
955e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu            case SELECTOR_SCROLLABLE:
956e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu                builder.append("SCROLLABLE=").append(mSelectorAttributes.valueAt(i));
957e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu                break;
958e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu            case SELECTOR_CLICKABLE:
959e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu                builder.append("CLICKABLE=").append(mSelectorAttributes.valueAt(i));
960e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu                break;
96197835f3a7c80b147136c44c175eb9e6a4261fd92Adam Momtaz            case SELECTOR_CHECKABLE:
96297835f3a7c80b147136c44c175eb9e6a4261fd92Adam Momtaz                builder.append("CHECKABLE=").append(mSelectorAttributes.valueAt(i));
96397835f3a7c80b147136c44c175eb9e6a4261fd92Adam Momtaz                break;
964336d1a84909be8ec12af8bc27c65825b13ad9909Adam Momtaz            case SELECTOR_LONG_CLICKABLE:
965336d1a84909be8ec12af8bc27c65825b13ad9909Adam Momtaz                builder.append("LONG_CLICKABLE=").append(mSelectorAttributes.valueAt(i));
966336d1a84909be8ec12af8bc27c65825b13ad9909Adam Momtaz                break;
967e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu            case SELECTOR_CHECKED:
968e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu                builder.append("CHECKED=").append(mSelectorAttributes.valueAt(i));
969e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu                break;
970e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu            case SELECTOR_SELECTED:
971e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu                builder.append("SELECTED=").append(mSelectorAttributes.valueAt(i));
972e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu                break;
973e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu            case SELECTOR_ID:
974e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu                builder.append("ID=").append(mSelectorAttributes.valueAt(i));
975e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu                break;
976e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu            case SELECTOR_CHILD:
9774f72d8d757b71a767999703016ba4d6db7333457Adam Momtaz                if (all)
978e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu                    builder.append("CHILD=").append(mSelectorAttributes.valueAt(i));
979e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu                else
980e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu                    builder.append("CHILD[..]");
981e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu                break;
982e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu            case SELECTOR_PATTERN:
9834f72d8d757b71a767999703016ba4d6db7333457Adam Momtaz                if (all)
984e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu                    builder.append("PATTERN=").append(mSelectorAttributes.valueAt(i));
985e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu                else
986e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu                    builder.append("PATTERN[..]");
987e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu                break;
988e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu            case SELECTOR_CONTAINER:
9894f72d8d757b71a767999703016ba4d6db7333457Adam Momtaz                if (all)
990e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu                    builder.append("CONTAINER=").append(mSelectorAttributes.valueAt(i));
991e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu                else
992e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu                    builder.append("CONTAINER[..]");
993e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu                break;
994e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu            case SELECTOR_PARENT:
9954f72d8d757b71a767999703016ba4d6db7333457Adam Momtaz                if (all)
996e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu                    builder.append("PARENT=").append(mSelectorAttributes.valueAt(i));
997e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu                else
998e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu                    builder.append("PARENT[..]");
999e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu                break;
1000e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu            case SELECTOR_COUNT:
1001e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu                builder.append("COUNT=").append(mSelectorAttributes.valueAt(i));
1002e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu                break;
1003e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu            case SELECTOR_PACKAGE_NAME:
1004e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu                builder.append("PACKAGE NAME=").append(mSelectorAttributes.valueAt(i));
1005e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu                break;
1006ee4b48cd50f6e4e24ba7f538b8a77c839c1087f5Adam Momtaz            case SELECTOR_PACKAGE_NAME_REGEX:
1007ee4b48cd50f6e4e24ba7f538b8a77c839c1087f5Adam Momtaz                builder.append("PACKAGE_NAME_REGEX=").append(mSelectorAttributes.valueAt(i));
1008ee4b48cd50f6e4e24ba7f538b8a77c839c1087f5Adam Momtaz                break;
1009946d553eb162ee5ac4eeef2c91c40f36f3db791dAdam Momtaz            case SELECTOR_RESOURCE_ID:
1010946d553eb162ee5ac4eeef2c91c40f36f3db791dAdam Momtaz                builder.append("RESOURCE_ID=").append(mSelectorAttributes.valueAt(i));
101189f6117cb1fbeab3770106cf54e05af1f597be81Svetoslav Ganov                break;
10124f72d8d757b71a767999703016ba4d6db7333457Adam Momtaz            case SELECTOR_RESOURCE_ID_REGEX:
10134f72d8d757b71a767999703016ba4d6db7333457Adam Momtaz                builder.append("RESOURCE_ID_REGEX=").append(mSelectorAttributes.valueAt(i));
10144f72d8d757b71a767999703016ba4d6db7333457Adam Momtaz                break;
1015e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu            default:
1016e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu                builder.append("UNDEFINED="+criterion+" ").append(mSelectorAttributes.valueAt(i));
1017e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu            }
1018e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu        }
1019e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu        builder.append("]");
1020e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu        return builder.toString();
1021e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu    }
10229ebf91aa923d2424298cb908a79dd03aefbf0a8fGuang Zhu}
1023