1b36bed5899431bc495f3046ca380f318963eb700Michael Wright/*
2b36bed5899431bc495f3046ca380f318963eb700Michael Wright * Copyright 2011, The Android Open Source Project
3b36bed5899431bc495f3046ca380f318963eb700Michael Wright *
4b36bed5899431bc495f3046ca380f318963eb700Michael Wright * Licensed under the Apache License, Version 2.0 (the "License");
5b36bed5899431bc495f3046ca380f318963eb700Michael Wright * you may not use this file except in compliance with the License.
6b36bed5899431bc495f3046ca380f318963eb700Michael Wright * You may obtain a copy of the License at
7b36bed5899431bc495f3046ca380f318963eb700Michael Wright *
8b36bed5899431bc495f3046ca380f318963eb700Michael Wright *     http://www.apache.org/licenses/LICENSE-2.0
9b36bed5899431bc495f3046ca380f318963eb700Michael Wright *
10b36bed5899431bc495f3046ca380f318963eb700Michael Wright * Unless required by applicable law or agreed to in writing, software
11b36bed5899431bc495f3046ca380f318963eb700Michael Wright * distributed under the License is distributed on an "AS IS" BASIS,
12b36bed5899431bc495f3046ca380f318963eb700Michael Wright * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13b36bed5899431bc495f3046ca380f318963eb700Michael Wright * See the License for the specific language governing permissions and
14b36bed5899431bc495f3046ca380f318963eb700Michael Wright * limitations under the License.
15b36bed5899431bc495f3046ca380f318963eb700Michael Wright */
16b36bed5899431bc495f3046ca380f318963eb700Michael Wright
17b36bed5899431bc495f3046ca380f318963eb700Michael Wrightpackage com.android.commands.monkey;
18b36bed5899431bc495f3046ca380f318963eb700Michael Wright
19b36bed5899431bc495f3046ca380f318963eb700Michael Wrightimport static com.android.commands.monkey.MonkeySourceNetwork.EARG;
20b36bed5899431bc495f3046ca380f318963eb700Michael Wright
2100fc93c6fe7fa6d086a308e5f4647fb311947c12Svetoslav Ganovimport android.app.UiAutomation;
2200fc93c6fe7fa6d086a308e5f4647fb311947c12Svetoslav Ganovimport android.app.UiAutomationConnection;
23b36bed5899431bc495f3046ca380f318963eb700Michael Wrightimport android.content.pm.ApplicationInfo;
244ce026b4b196e24ee125247843697680fb8e207eSvetoslav Ganovimport android.content.pm.IPackageManager;
25b36bed5899431bc495f3046ca380f318963eb700Michael Wrightimport android.graphics.Rect;
2600fc93c6fe7fa6d086a308e5f4647fb311947c12Svetoslav Ganovimport android.os.HandlerThread;
27b36bed5899431bc495f3046ca380f318963eb700Michael Wrightimport android.os.RemoteException;
284ce026b4b196e24ee125247843697680fb8e207eSvetoslav Ganovimport android.os.ServiceManager;
2977201b54149ff8d531eb15ac5bd8386b325974beDianne Hackbornimport android.os.UserHandle;
3000fc93c6fe7fa6d086a308e5f4647fb311947c12Svetoslav Ganovimport android.view.accessibility.AccessibilityInteractionClient;
314ce026b4b196e24ee125247843697680fb8e207eSvetoslav Ganovimport android.view.accessibility.AccessibilityNodeInfo;
32b36bed5899431bc495f3046ca380f318963eb700Michael Wright
33b36bed5899431bc495f3046ca380f318963eb700Michael Wrightimport com.android.commands.monkey.MonkeySourceNetwork.CommandQueue;
34b36bed5899431bc495f3046ca380f318963eb700Michael Wrightimport com.android.commands.monkey.MonkeySourceNetwork.MonkeyCommand;
35b36bed5899431bc495f3046ca380f318963eb700Michael Wrightimport com.android.commands.monkey.MonkeySourceNetwork.MonkeyCommandReturn;
36b36bed5899431bc495f3046ca380f318963eb700Michael Wright
374ce026b4b196e24ee125247843697680fb8e207eSvetoslav Ganovimport dalvik.system.DexClassLoader;
384ce026b4b196e24ee125247843697680fb8e207eSvetoslav Ganov
39b36bed5899431bc495f3046ca380f318963eb700Michael Wrightimport java.lang.reflect.Field;
404ce026b4b196e24ee125247843697680fb8e207eSvetoslav Ganovimport java.util.ArrayList;
41b36bed5899431bc495f3046ca380f318963eb700Michael Wrightimport java.util.HashMap;
42b36bed5899431bc495f3046ca380f318963eb700Michael Wrightimport java.util.List;
434ce026b4b196e24ee125247843697680fb8e207eSvetoslav Ganovimport java.util.Map;
44b36bed5899431bc495f3046ca380f318963eb700Michael Wright
45b36bed5899431bc495f3046ca380f318963eb700Michael Wright/**
46b36bed5899431bc495f3046ca380f318963eb700Michael Wright * Utility class that enables Monkey to perform view introspection when issued Monkey Network
47b36bed5899431bc495f3046ca380f318963eb700Michael Wright * Script commands over the network.
48b36bed5899431bc495f3046ca380f318963eb700Michael Wright */
49b36bed5899431bc495f3046ca380f318963eb700Michael Wrightpublic class MonkeySourceNetworkViews {
5000fc93c6fe7fa6d086a308e5f4647fb311947c12Svetoslav Ganov
5100fc93c6fe7fa6d086a308e5f4647fb311947c12Svetoslav Ganov    protected static android.app.UiAutomation sUiTestAutomationBridge;
5200fc93c6fe7fa6d086a308e5f4647fb311947c12Svetoslav Ganov
53b36bed5899431bc495f3046ca380f318963eb700Michael Wright    private static IPackageManager sPm =
54b36bed5899431bc495f3046ca380f318963eb700Michael Wright            IPackageManager.Stub.asInterface(ServiceManager.getService("package"));
55b36bed5899431bc495f3046ca380f318963eb700Michael Wright    private static Map<String, Class<?>> sClassMap = new HashMap<String, Class<?>>();
56b36bed5899431bc495f3046ca380f318963eb700Michael Wright
5700fc93c6fe7fa6d086a308e5f4647fb311947c12Svetoslav Ganov    private static final String HANDLER_THREAD_NAME = "UiAutomationHandlerThread";
5800fc93c6fe7fa6d086a308e5f4647fb311947c12Svetoslav Ganov
59b36bed5899431bc495f3046ca380f318963eb700Michael Wright    private static final String REMOTE_ERROR =
60b36bed5899431bc495f3046ca380f318963eb700Michael Wright            "Unable to retrieve application info from PackageManager";
61b36bed5899431bc495f3046ca380f318963eb700Michael Wright    private static final String CLASS_NOT_FOUND = "Error retrieving class information";
62b36bed5899431bc495f3046ca380f318963eb700Michael Wright    private static final String NO_ACCESSIBILITY_EVENT = "No accessibility event has occured yet";
63b36bed5899431bc495f3046ca380f318963eb700Michael Wright    private static final String NO_NODE = "Node with given ID does not exist";
64b36bed5899431bc495f3046ca380f318963eb700Michael Wright    private static final String NO_CONNECTION = "Failed to connect to AccessibilityService, "
65b36bed5899431bc495f3046ca380f318963eb700Michael Wright                                                + "try restarting Monkey";
66b36bed5899431bc495f3046ca380f318963eb700Michael Wright
67b36bed5899431bc495f3046ca380f318963eb700Michael Wright    private static final Map<String, ViewIntrospectionCommand> COMMAND_MAP =
68b36bed5899431bc495f3046ca380f318963eb700Michael Wright            new HashMap<String, ViewIntrospectionCommand>();
69b36bed5899431bc495f3046ca380f318963eb700Michael Wright
70b36bed5899431bc495f3046ca380f318963eb700Michael Wright    /* Interface for view queries */
71b36bed5899431bc495f3046ca380f318963eb700Michael Wright    private static interface ViewIntrospectionCommand {
72b36bed5899431bc495f3046ca380f318963eb700Michael Wright        /**
73b36bed5899431bc495f3046ca380f318963eb700Michael Wright         * Get the response to the query
74b36bed5899431bc495f3046ca380f318963eb700Michael Wright         * @return the response to the query
75b36bed5899431bc495f3046ca380f318963eb700Michael Wright         */
76b36bed5899431bc495f3046ca380f318963eb700Michael Wright        public MonkeyCommandReturn query(AccessibilityNodeInfo node, List<String> args);
77b36bed5899431bc495f3046ca380f318963eb700Michael Wright    }
78b36bed5899431bc495f3046ca380f318963eb700Michael Wright
79b36bed5899431bc495f3046ca380f318963eb700Michael Wright    static {
80b36bed5899431bc495f3046ca380f318963eb700Michael Wright        COMMAND_MAP.put("getlocation", new GetLocation());
81b36bed5899431bc495f3046ca380f318963eb700Michael Wright        COMMAND_MAP.put("gettext", new GetText());
82b36bed5899431bc495f3046ca380f318963eb700Michael Wright        COMMAND_MAP.put("getclass", new GetClass());
83b36bed5899431bc495f3046ca380f318963eb700Michael Wright        COMMAND_MAP.put("getchecked", new GetChecked());
84b36bed5899431bc495f3046ca380f318963eb700Michael Wright        COMMAND_MAP.put("getenabled", new GetEnabled());
85b36bed5899431bc495f3046ca380f318963eb700Michael Wright        COMMAND_MAP.put("getselected", new GetSelected());
86b36bed5899431bc495f3046ca380f318963eb700Michael Wright        COMMAND_MAP.put("setselected", new SetSelected());
87b36bed5899431bc495f3046ca380f318963eb700Michael Wright        COMMAND_MAP.put("getfocused", new GetFocused());
88b36bed5899431bc495f3046ca380f318963eb700Michael Wright        COMMAND_MAP.put("setfocused", new SetFocused());
89b36bed5899431bc495f3046ca380f318963eb700Michael Wright        COMMAND_MAP.put("getparent", new GetParent());
90b36bed5899431bc495f3046ca380f318963eb700Michael Wright        COMMAND_MAP.put("getchildren", new GetChildren());
91b36bed5899431bc495f3046ca380f318963eb700Michael Wright        COMMAND_MAP.put("getaccessibilityids", new GetAccessibilityIds());
92b36bed5899431bc495f3046ca380f318963eb700Michael Wright    }
93b36bed5899431bc495f3046ca380f318963eb700Michael Wright
9400fc93c6fe7fa6d086a308e5f4647fb311947c12Svetoslav Ganov    private static final HandlerThread sHandlerThread = new HandlerThread(HANDLER_THREAD_NAME);
9500fc93c6fe7fa6d086a308e5f4647fb311947c12Svetoslav Ganov
96b36bed5899431bc495f3046ca380f318963eb700Michael Wright    /**
97b36bed5899431bc495f3046ca380f318963eb700Michael Wright     * Registers the event listener for AccessibilityEvents.
98b36bed5899431bc495f3046ca380f318963eb700Michael Wright     * Also sets up a communication connection so we can query the
99b36bed5899431bc495f3046ca380f318963eb700Michael Wright     * accessibility service.
100b36bed5899431bc495f3046ca380f318963eb700Michael Wright     */
101b36bed5899431bc495f3046ca380f318963eb700Michael Wright    public static void setup() {
10200fc93c6fe7fa6d086a308e5f4647fb311947c12Svetoslav Ganov        sHandlerThread.setDaemon(true);
10300fc93c6fe7fa6d086a308e5f4647fb311947c12Svetoslav Ganov        sHandlerThread.start();
10400fc93c6fe7fa6d086a308e5f4647fb311947c12Svetoslav Ganov        sUiTestAutomationBridge = new UiAutomation(sHandlerThread.getLooper(),
10500fc93c6fe7fa6d086a308e5f4647fb311947c12Svetoslav Ganov                new UiAutomationConnection());
1064ce026b4b196e24ee125247843697680fb8e207eSvetoslav Ganov        sUiTestAutomationBridge.connect();
107b36bed5899431bc495f3046ca380f318963eb700Michael Wright    }
108b36bed5899431bc495f3046ca380f318963eb700Michael Wright
10900fc93c6fe7fa6d086a308e5f4647fb311947c12Svetoslav Ganov    public static void teardown() {
11000fc93c6fe7fa6d086a308e5f4647fb311947c12Svetoslav Ganov        sHandlerThread.quit();
11100fc93c6fe7fa6d086a308e5f4647fb311947c12Svetoslav Ganov    }
11200fc93c6fe7fa6d086a308e5f4647fb311947c12Svetoslav Ganov
113b36bed5899431bc495f3046ca380f318963eb700Michael Wright    /**
114b36bed5899431bc495f3046ca380f318963eb700Michael Wright     * Get the ID class for the given package.
115b36bed5899431bc495f3046ca380f318963eb700Michael Wright     * This will cause issues if people reload a package with different
116b36bed5899431bc495f3046ca380f318963eb700Michael Wright     * resource identifiers, but don't restart the Monkey server.
117b36bed5899431bc495f3046ca380f318963eb700Michael Wright     *
118b36bed5899431bc495f3046ca380f318963eb700Michael Wright     * @param packageName The package that we want to retrieve the ID class for
119b36bed5899431bc495f3046ca380f318963eb700Michael Wright     * @return The ID class for the given package
120b36bed5899431bc495f3046ca380f318963eb700Michael Wright     */
121b36bed5899431bc495f3046ca380f318963eb700Michael Wright    private static Class<?> getIdClass(String packageName, String sourceDir)
1224ce026b4b196e24ee125247843697680fb8e207eSvetoslav Ganov            throws ClassNotFoundException {
123b36bed5899431bc495f3046ca380f318963eb700Michael Wright        // This kind of reflection is expensive, so let's only do it
124b36bed5899431bc495f3046ca380f318963eb700Michael Wright        // if we need to
125b36bed5899431bc495f3046ca380f318963eb700Michael Wright        Class<?> klass = sClassMap.get(packageName);
126b36bed5899431bc495f3046ca380f318963eb700Michael Wright        if (klass == null) {
127b36bed5899431bc495f3046ca380f318963eb700Michael Wright            DexClassLoader classLoader = new DexClassLoader(
128b36bed5899431bc495f3046ca380f318963eb700Michael Wright                    sourceDir, "/data/local/tmp",
129b36bed5899431bc495f3046ca380f318963eb700Michael Wright                    null, ClassLoader.getSystemClassLoader());
130b36bed5899431bc495f3046ca380f318963eb700Michael Wright            klass = classLoader.loadClass(packageName + ".R$id");
131b36bed5899431bc495f3046ca380f318963eb700Michael Wright            sClassMap.put(packageName, klass);
132b36bed5899431bc495f3046ca380f318963eb700Michael Wright        }
133b36bed5899431bc495f3046ca380f318963eb700Michael Wright        return klass;
134b36bed5899431bc495f3046ca380f318963eb700Michael Wright    }
135b36bed5899431bc495f3046ca380f318963eb700Michael Wright
136b36bed5899431bc495f3046ca380f318963eb700Michael Wright    private static AccessibilityNodeInfo getNodeByAccessibilityIds(
13733a93ebfe34ca53e7dc6d446f49f647d87732aeeSvetoslav Ganov            String windowString, String viewString) {
138b36bed5899431bc495f3046ca380f318963eb700Michael Wright        int windowId = Integer.parseInt(windowString);
139b36bed5899431bc495f3046ca380f318963eb700Michael Wright        int viewId = Integer.parseInt(viewString);
14000fc93c6fe7fa6d086a308e5f4647fb311947c12Svetoslav Ganov        int connectionId = sUiTestAutomationBridge.getConnectionId();
14100fc93c6fe7fa6d086a308e5f4647fb311947c12Svetoslav Ganov        AccessibilityInteractionClient client = AccessibilityInteractionClient.getInstance();
142e37f81e5a44cde4f5a6551889953d1b8a8ca0038Svetoslav        return client.findAccessibilityNodeInfoByAccessibilityId(connectionId, windowId, viewId,
143e37f81e5a44cde4f5a6551889953d1b8a8ca0038Svetoslav                false, 0);
144b36bed5899431bc495f3046ca380f318963eb700Michael Wright    }
145b36bed5899431bc495f3046ca380f318963eb700Michael Wright
14600fc93c6fe7fa6d086a308e5f4647fb311947c12Svetoslav Ganov    private static AccessibilityNodeInfo getNodeByViewId(String viewId) throws MonkeyViewException {
14700fc93c6fe7fa6d086a308e5f4647fb311947c12Svetoslav Ganov        int connectionId = sUiTestAutomationBridge.getConnectionId();
14800fc93c6fe7fa6d086a308e5f4647fb311947c12Svetoslav Ganov        AccessibilityInteractionClient client = AccessibilityInteractionClient.getInstance();
14900fc93c6fe7fa6d086a308e5f4647fb311947c12Svetoslav Ganov        List<AccessibilityNodeInfo> infos = client.findAccessibilityNodeInfosByViewId(
15000fc93c6fe7fa6d086a308e5f4647fb311947c12Svetoslav Ganov                connectionId, AccessibilityNodeInfo.ACTIVE_WINDOW_ID,
15100fc93c6fe7fa6d086a308e5f4647fb311947c12Svetoslav Ganov                AccessibilityNodeInfo.ROOT_NODE_ID, viewId);
15200fc93c6fe7fa6d086a308e5f4647fb311947c12Svetoslav Ganov        return (!infos.isEmpty()) ? infos.get(0) : null;
153b36bed5899431bc495f3046ca380f318963eb700Michael Wright    }
154b36bed5899431bc495f3046ca380f318963eb700Michael Wright
155b36bed5899431bc495f3046ca380f318963eb700Michael Wright    /**
156b36bed5899431bc495f3046ca380f318963eb700Michael Wright     * Command to list all possible view ids for the given application.
157b36bed5899431bc495f3046ca380f318963eb700Michael Wright     * This lists all view ids regardless if they are on screen or not.
158b36bed5899431bc495f3046ca380f318963eb700Michael Wright     */
159b36bed5899431bc495f3046ca380f318963eb700Michael Wright    public static class ListViewsCommand implements MonkeyCommand {
160b36bed5899431bc495f3046ca380f318963eb700Michael Wright        //listviews
161b36bed5899431bc495f3046ca380f318963eb700Michael Wright        public MonkeyCommandReturn translateCommand(List<String> command,
162b36bed5899431bc495f3046ca380f318963eb700Michael Wright                                                    CommandQueue queue) {
16300fc93c6fe7fa6d086a308e5f4647fb311947c12Svetoslav Ganov            AccessibilityNodeInfo node = sUiTestAutomationBridge.getRootInActiveWindow();
164b36bed5899431bc495f3046ca380f318963eb700Michael Wright            /* Occasionally the API will generate an event with no source, which is essentially the
165b36bed5899431bc495f3046ca380f318963eb700Michael Wright             * same as it generating no event at all */
166b36bed5899431bc495f3046ca380f318963eb700Michael Wright            if (node == null) {
167b36bed5899431bc495f3046ca380f318963eb700Michael Wright                return new MonkeyCommandReturn(false, NO_ACCESSIBILITY_EVENT);
168b36bed5899431bc495f3046ca380f318963eb700Michael Wright            }
169b36bed5899431bc495f3046ca380f318963eb700Michael Wright            String packageName = node.getPackageName().toString();
170b36bed5899431bc495f3046ca380f318963eb700Michael Wright            try{
171b36bed5899431bc495f3046ca380f318963eb700Michael Wright                Class<?> klass;
17200fc93c6fe7fa6d086a308e5f4647fb311947c12Svetoslav Ganov                ApplicationInfo appInfo = sPm.getApplicationInfo(packageName, 0,
17300fc93c6fe7fa6d086a308e5f4647fb311947c12Svetoslav Ganov                        UserHandle.myUserId());
174b36bed5899431bc495f3046ca380f318963eb700Michael Wright                klass = getIdClass(packageName, appInfo.sourceDir);
175b36bed5899431bc495f3046ca380f318963eb700Michael Wright                StringBuilder fieldBuilder = new StringBuilder();
176b36bed5899431bc495f3046ca380f318963eb700Michael Wright                Field[] fields = klass.getFields();
177b36bed5899431bc495f3046ca380f318963eb700Michael Wright                for (Field field : fields) {
178b36bed5899431bc495f3046ca380f318963eb700Michael Wright                    fieldBuilder.append(field.getName() + " ");
179b36bed5899431bc495f3046ca380f318963eb700Michael Wright                }
180b36bed5899431bc495f3046ca380f318963eb700Michael Wright                return new MonkeyCommandReturn(true, fieldBuilder.toString());
181b36bed5899431bc495f3046ca380f318963eb700Michael Wright            } catch (RemoteException e){
182b36bed5899431bc495f3046ca380f318963eb700Michael Wright                return new MonkeyCommandReturn(false, REMOTE_ERROR);
183b36bed5899431bc495f3046ca380f318963eb700Michael Wright            } catch (ClassNotFoundException e){
184b36bed5899431bc495f3046ca380f318963eb700Michael Wright                return new MonkeyCommandReturn(false, CLASS_NOT_FOUND);
185b36bed5899431bc495f3046ca380f318963eb700Michael Wright            }
186b36bed5899431bc495f3046ca380f318963eb700Michael Wright        }
187b36bed5899431bc495f3046ca380f318963eb700Michael Wright    }
188b36bed5899431bc495f3046ca380f318963eb700Michael Wright
189b36bed5899431bc495f3046ca380f318963eb700Michael Wright    /**
190b36bed5899431bc495f3046ca380f318963eb700Michael Wright     * A command that allows for querying of views. It takes an id type, the requisite ids,
191b36bed5899431bc495f3046ca380f318963eb700Michael Wright     * and the command for querying the view.
192b36bed5899431bc495f3046ca380f318963eb700Michael Wright     */
193b36bed5899431bc495f3046ca380f318963eb700Michael Wright    public static class QueryViewCommand implements MonkeyCommand {
194b36bed5899431bc495f3046ca380f318963eb700Michael Wright        //queryview [id type] [id(s)] [command]
195b36bed5899431bc495f3046ca380f318963eb700Michael Wright        //queryview viewid button1 gettext
196b36bed5899431bc495f3046ca380f318963eb700Michael Wright        //queryview accessibilityids 12 5 getparent
197b36bed5899431bc495f3046ca380f318963eb700Michael Wright        public MonkeyCommandReturn translateCommand(List<String> command,
198b36bed5899431bc495f3046ca380f318963eb700Michael Wright                                                    CommandQueue queue) {
199b36bed5899431bc495f3046ca380f318963eb700Michael Wright            if (command.size() > 2) {
200b36bed5899431bc495f3046ca380f318963eb700Michael Wright                String idType = command.get(1);
201b36bed5899431bc495f3046ca380f318963eb700Michael Wright                AccessibilityNodeInfo node;
202b36bed5899431bc495f3046ca380f318963eb700Michael Wright                String viewQuery;
203b36bed5899431bc495f3046ca380f318963eb700Michael Wright                List<String> args;
204b36bed5899431bc495f3046ca380f318963eb700Michael Wright                if ("viewid".equals(idType)) {
205b36bed5899431bc495f3046ca380f318963eb700Michael Wright                    try {
20600fc93c6fe7fa6d086a308e5f4647fb311947c12Svetoslav Ganov                        node = getNodeByViewId(command.get(2));
207b36bed5899431bc495f3046ca380f318963eb700Michael Wright                        viewQuery = command.get(3);
208b36bed5899431bc495f3046ca380f318963eb700Michael Wright                        args = command.subList(4, command.size());
209b36bed5899431bc495f3046ca380f318963eb700Michael Wright                    } catch (MonkeyViewException e) {
210b36bed5899431bc495f3046ca380f318963eb700Michael Wright                        return new MonkeyCommandReturn(false, e.getMessage());
211b36bed5899431bc495f3046ca380f318963eb700Michael Wright                    }
212b36bed5899431bc495f3046ca380f318963eb700Michael Wright                } else if (idType.equals("accessibilityids")) {
213b36bed5899431bc495f3046ca380f318963eb700Michael Wright                    try {
214b36bed5899431bc495f3046ca380f318963eb700Michael Wright                        node = getNodeByAccessibilityIds(command.get(2), command.get(3));
215b36bed5899431bc495f3046ca380f318963eb700Michael Wright                        viewQuery = command.get(4);
216b36bed5899431bc495f3046ca380f318963eb700Michael Wright                        args = command.subList(5, command.size());
217b36bed5899431bc495f3046ca380f318963eb700Michael Wright                    } catch (NumberFormatException e) {
218b36bed5899431bc495f3046ca380f318963eb700Michael Wright                        return EARG;
219b36bed5899431bc495f3046ca380f318963eb700Michael Wright                    }
220b36bed5899431bc495f3046ca380f318963eb700Michael Wright                } else {
221b36bed5899431bc495f3046ca380f318963eb700Michael Wright                    return EARG;
222b36bed5899431bc495f3046ca380f318963eb700Michael Wright                }
223b36bed5899431bc495f3046ca380f318963eb700Michael Wright                if (node == null) {
224b36bed5899431bc495f3046ca380f318963eb700Michael Wright                    return new MonkeyCommandReturn(false, NO_NODE);
225b36bed5899431bc495f3046ca380f318963eb700Michael Wright                }
226b36bed5899431bc495f3046ca380f318963eb700Michael Wright                ViewIntrospectionCommand getter = COMMAND_MAP.get(viewQuery);
227b36bed5899431bc495f3046ca380f318963eb700Michael Wright                if (getter != null) {
228b36bed5899431bc495f3046ca380f318963eb700Michael Wright                    return getter.query(node, args);
229b36bed5899431bc495f3046ca380f318963eb700Michael Wright                } else {
230b36bed5899431bc495f3046ca380f318963eb700Michael Wright                    return EARG;
231b36bed5899431bc495f3046ca380f318963eb700Michael Wright                }
232b36bed5899431bc495f3046ca380f318963eb700Michael Wright            }
233b36bed5899431bc495f3046ca380f318963eb700Michael Wright            return EARG;
234b36bed5899431bc495f3046ca380f318963eb700Michael Wright        }
235b36bed5899431bc495f3046ca380f318963eb700Michael Wright    }
236b36bed5899431bc495f3046ca380f318963eb700Michael Wright
237b36bed5899431bc495f3046ca380f318963eb700Michael Wright    /**
238b36bed5899431bc495f3046ca380f318963eb700Michael Wright     * A command that returns the accessibility ids of the root view.
239b36bed5899431bc495f3046ca380f318963eb700Michael Wright     */
240b36bed5899431bc495f3046ca380f318963eb700Michael Wright    public static class GetRootViewCommand implements MonkeyCommand {
241b36bed5899431bc495f3046ca380f318963eb700Michael Wright        // getrootview
242b36bed5899431bc495f3046ca380f318963eb700Michael Wright        public MonkeyCommandReturn translateCommand(List<String> command,
243b36bed5899431bc495f3046ca380f318963eb700Michael Wright                                                    CommandQueue queue) {
24400fc93c6fe7fa6d086a308e5f4647fb311947c12Svetoslav Ganov            AccessibilityNodeInfo node = sUiTestAutomationBridge.getRootInActiveWindow();
245b36bed5899431bc495f3046ca380f318963eb700Michael Wright            return (new GetAccessibilityIds()).query(node, new ArrayList<String>());
246b36bed5899431bc495f3046ca380f318963eb700Michael Wright        }
247b36bed5899431bc495f3046ca380f318963eb700Michael Wright    }
248b36bed5899431bc495f3046ca380f318963eb700Michael Wright
249b36bed5899431bc495f3046ca380f318963eb700Michael Wright    /**
250b36bed5899431bc495f3046ca380f318963eb700Michael Wright     * A command that returns the accessibility ids of the views that contain the given text.
251b36bed5899431bc495f3046ca380f318963eb700Michael Wright     * It takes a string of text and returns the accessibility ids of the nodes that contain the
252b36bed5899431bc495f3046ca380f318963eb700Michael Wright     * text as a list of integers separated by spaces.
253b36bed5899431bc495f3046ca380f318963eb700Michael Wright     */
254b36bed5899431bc495f3046ca380f318963eb700Michael Wright    public static class GetViewsWithTextCommand implements MonkeyCommand {
255b36bed5899431bc495f3046ca380f318963eb700Michael Wright        // getviewswithtext [text]
256b36bed5899431bc495f3046ca380f318963eb700Michael Wright        // getviewswithtext "some text here"
257b36bed5899431bc495f3046ca380f318963eb700Michael Wright        public MonkeyCommandReturn translateCommand(List<String> command,
258b36bed5899431bc495f3046ca380f318963eb700Michael Wright                                                    CommandQueue queue) {
259b36bed5899431bc495f3046ca380f318963eb700Michael Wright            if (command.size() == 2) {
260b36bed5899431bc495f3046ca380f318963eb700Michael Wright                String text = command.get(1);
26100fc93c6fe7fa6d086a308e5f4647fb311947c12Svetoslav Ganov                int connectionId = sUiTestAutomationBridge.getConnectionId();
26200fc93c6fe7fa6d086a308e5f4647fb311947c12Svetoslav Ganov                List<AccessibilityNodeInfo> nodes = AccessibilityInteractionClient.getInstance()
26300fc93c6fe7fa6d086a308e5f4647fb311947c12Svetoslav Ganov                    .findAccessibilityNodeInfosByText(connectionId,
26400fc93c6fe7fa6d086a308e5f4647fb311947c12Svetoslav Ganov                            AccessibilityNodeInfo.ACTIVE_WINDOW_ID,
26500fc93c6fe7fa6d086a308e5f4647fb311947c12Svetoslav Ganov                            AccessibilityNodeInfo.ROOT_NODE_ID, text);
266b36bed5899431bc495f3046ca380f318963eb700Michael Wright                ViewIntrospectionCommand idGetter = new GetAccessibilityIds();
267b36bed5899431bc495f3046ca380f318963eb700Michael Wright                List<String> emptyArgs = new ArrayList<String>();
268b36bed5899431bc495f3046ca380f318963eb700Michael Wright                StringBuilder ids = new StringBuilder();
269b36bed5899431bc495f3046ca380f318963eb700Michael Wright                for (AccessibilityNodeInfo node : nodes) {
270b36bed5899431bc495f3046ca380f318963eb700Michael Wright                    MonkeyCommandReturn result = idGetter.query(node, emptyArgs);
271b36bed5899431bc495f3046ca380f318963eb700Michael Wright                    if (!result.wasSuccessful()){
272b36bed5899431bc495f3046ca380f318963eb700Michael Wright                        return result;
273b36bed5899431bc495f3046ca380f318963eb700Michael Wright                    }
274b36bed5899431bc495f3046ca380f318963eb700Michael Wright                    ids.append(result.getMessage()).append(" ");
275b36bed5899431bc495f3046ca380f318963eb700Michael Wright                }
276b36bed5899431bc495f3046ca380f318963eb700Michael Wright                return new MonkeyCommandReturn(true, ids.toString());
277b36bed5899431bc495f3046ca380f318963eb700Michael Wright            }
278b36bed5899431bc495f3046ca380f318963eb700Michael Wright            return EARG;
279b36bed5899431bc495f3046ca380f318963eb700Michael Wright        }
280b36bed5899431bc495f3046ca380f318963eb700Michael Wright    }
281b36bed5899431bc495f3046ca380f318963eb700Michael Wright
282b36bed5899431bc495f3046ca380f318963eb700Michael Wright    /**
283b36bed5899431bc495f3046ca380f318963eb700Michael Wright     * Command to retrieve the location of the given node.
284b36bed5899431bc495f3046ca380f318963eb700Michael Wright     * Returns the x, y, width and height of the view, separated by spaces.
285b36bed5899431bc495f3046ca380f318963eb700Michael Wright     */
286b36bed5899431bc495f3046ca380f318963eb700Michael Wright    public static class GetLocation implements ViewIntrospectionCommand {
287b36bed5899431bc495f3046ca380f318963eb700Michael Wright        //queryview [id type] [id] getlocation
288b36bed5899431bc495f3046ca380f318963eb700Michael Wright        //queryview viewid button1 getlocation
289b36bed5899431bc495f3046ca380f318963eb700Michael Wright        public MonkeyCommandReturn query(AccessibilityNodeInfo node,
290b36bed5899431bc495f3046ca380f318963eb700Michael Wright                                         List<String> args) {
291b36bed5899431bc495f3046ca380f318963eb700Michael Wright            if (args.size() == 0) {
292b36bed5899431bc495f3046ca380f318963eb700Michael Wright                Rect nodePosition = new Rect();
293b36bed5899431bc495f3046ca380f318963eb700Michael Wright                node.getBoundsInScreen(nodePosition);
294b36bed5899431bc495f3046ca380f318963eb700Michael Wright                StringBuilder positions = new StringBuilder();
295b36bed5899431bc495f3046ca380f318963eb700Michael Wright                positions.append(nodePosition.left).append(" ").append(nodePosition.top);
296b36bed5899431bc495f3046ca380f318963eb700Michael Wright                positions.append(" ").append(nodePosition.right-nodePosition.left).append(" ");
297b36bed5899431bc495f3046ca380f318963eb700Michael Wright                positions.append(nodePosition.bottom-nodePosition.top);
298b36bed5899431bc495f3046ca380f318963eb700Michael Wright                return new MonkeyCommandReturn(true, positions.toString());
299b36bed5899431bc495f3046ca380f318963eb700Michael Wright            }
300b36bed5899431bc495f3046ca380f318963eb700Michael Wright            return EARG;
301b36bed5899431bc495f3046ca380f318963eb700Michael Wright        }
302b36bed5899431bc495f3046ca380f318963eb700Michael Wright    }
303b36bed5899431bc495f3046ca380f318963eb700Michael Wright
304b36bed5899431bc495f3046ca380f318963eb700Michael Wright
305b36bed5899431bc495f3046ca380f318963eb700Michael Wright    /**
306b36bed5899431bc495f3046ca380f318963eb700Michael Wright     * Command to retrieve the text of the given node
307b36bed5899431bc495f3046ca380f318963eb700Michael Wright     */
308b36bed5899431bc495f3046ca380f318963eb700Michael Wright    public static class GetText implements ViewIntrospectionCommand {
309b36bed5899431bc495f3046ca380f318963eb700Michael Wright        //queryview [id type] [id] gettext
310b36bed5899431bc495f3046ca380f318963eb700Michael Wright        //queryview viewid button1 gettext
311b36bed5899431bc495f3046ca380f318963eb700Michael Wright        public MonkeyCommandReturn query(AccessibilityNodeInfo node,
312b36bed5899431bc495f3046ca380f318963eb700Michael Wright                                         List<String> args) {
313b36bed5899431bc495f3046ca380f318963eb700Michael Wright            if (args.size() == 0) {
314b36bed5899431bc495f3046ca380f318963eb700Michael Wright                if (node.isPassword()){
315b36bed5899431bc495f3046ca380f318963eb700Michael Wright                    return new MonkeyCommandReturn(false, "Node contains a password");
316b36bed5899431bc495f3046ca380f318963eb700Michael Wright                }
317c6c89b994e89b9e4cd1cd6e0463a42c6526130b0Michael Wright                /* Occasionally we get a null from the accessibility API, rather than an empty
318c6c89b994e89b9e4cd1cd6e0463a42c6526130b0Michael Wright                 * string */
319c6c89b994e89b9e4cd1cd6e0463a42c6526130b0Michael Wright                if (node.getText() == null) {
320c6c89b994e89b9e4cd1cd6e0463a42c6526130b0Michael Wright                    return new MonkeyCommandReturn(true, "");
321c6c89b994e89b9e4cd1cd6e0463a42c6526130b0Michael Wright                }
322b36bed5899431bc495f3046ca380f318963eb700Michael Wright                return new MonkeyCommandReturn(true, node.getText().toString());
323b36bed5899431bc495f3046ca380f318963eb700Michael Wright            }
324b36bed5899431bc495f3046ca380f318963eb700Michael Wright            return EARG;
325b36bed5899431bc495f3046ca380f318963eb700Michael Wright        }
326b36bed5899431bc495f3046ca380f318963eb700Michael Wright    }
327b36bed5899431bc495f3046ca380f318963eb700Michael Wright
328b36bed5899431bc495f3046ca380f318963eb700Michael Wright
329b36bed5899431bc495f3046ca380f318963eb700Michael Wright    /**
330b36bed5899431bc495f3046ca380f318963eb700Michael Wright     * Command to retrieve the class name of the given node
331b36bed5899431bc495f3046ca380f318963eb700Michael Wright     */
332b36bed5899431bc495f3046ca380f318963eb700Michael Wright    public static class GetClass implements ViewIntrospectionCommand {
333b36bed5899431bc495f3046ca380f318963eb700Michael Wright        //queryview [id type] [id] getclass
334b36bed5899431bc495f3046ca380f318963eb700Michael Wright        //queryview viewid button1 getclass
335b36bed5899431bc495f3046ca380f318963eb700Michael Wright        public MonkeyCommandReturn query(AccessibilityNodeInfo node,
336b36bed5899431bc495f3046ca380f318963eb700Michael Wright                                         List<String> args) {
337b36bed5899431bc495f3046ca380f318963eb700Michael Wright            if (args.size() == 0) {
338b36bed5899431bc495f3046ca380f318963eb700Michael Wright                return new MonkeyCommandReturn(true, node.getClassName().toString());
339b36bed5899431bc495f3046ca380f318963eb700Michael Wright            }
340b36bed5899431bc495f3046ca380f318963eb700Michael Wright            return EARG;
341b36bed5899431bc495f3046ca380f318963eb700Michael Wright        }
342b36bed5899431bc495f3046ca380f318963eb700Michael Wright    }
343b36bed5899431bc495f3046ca380f318963eb700Michael Wright    /**
344b36bed5899431bc495f3046ca380f318963eb700Michael Wright     * Command to retrieve the checked status of the given node
345b36bed5899431bc495f3046ca380f318963eb700Michael Wright     */
346b36bed5899431bc495f3046ca380f318963eb700Michael Wright    public static class GetChecked implements ViewIntrospectionCommand {
347b36bed5899431bc495f3046ca380f318963eb700Michael Wright        //queryview [id type] [id] getchecked
348b36bed5899431bc495f3046ca380f318963eb700Michael Wright        //queryview viewid button1 getchecked
349b36bed5899431bc495f3046ca380f318963eb700Michael Wright        public MonkeyCommandReturn query(AccessibilityNodeInfo node,
350b36bed5899431bc495f3046ca380f318963eb700Michael Wright                                         List<String> args) {
351b36bed5899431bc495f3046ca380f318963eb700Michael Wright            if (args.size() == 0) {
352b36bed5899431bc495f3046ca380f318963eb700Michael Wright                return new MonkeyCommandReturn(true, Boolean.toString(node.isChecked()));
353b36bed5899431bc495f3046ca380f318963eb700Michael Wright            }
354b36bed5899431bc495f3046ca380f318963eb700Michael Wright            return EARG;
355b36bed5899431bc495f3046ca380f318963eb700Michael Wright        }
356b36bed5899431bc495f3046ca380f318963eb700Michael Wright    }
357b36bed5899431bc495f3046ca380f318963eb700Michael Wright
358b36bed5899431bc495f3046ca380f318963eb700Michael Wright    /**
359b36bed5899431bc495f3046ca380f318963eb700Michael Wright     * Command to retrieve whether the given node is enabled
360b36bed5899431bc495f3046ca380f318963eb700Michael Wright     */
361b36bed5899431bc495f3046ca380f318963eb700Michael Wright    public static class GetEnabled implements ViewIntrospectionCommand {
362b36bed5899431bc495f3046ca380f318963eb700Michael Wright        //queryview [id type] [id] getenabled
363b36bed5899431bc495f3046ca380f318963eb700Michael Wright        //queryview viewid button1 getenabled
364b36bed5899431bc495f3046ca380f318963eb700Michael Wright        public MonkeyCommandReturn query(AccessibilityNodeInfo node,
365b36bed5899431bc495f3046ca380f318963eb700Michael Wright                                         List<String> args) {
366b36bed5899431bc495f3046ca380f318963eb700Michael Wright            if (args.size() == 0) {
367b36bed5899431bc495f3046ca380f318963eb700Michael Wright                return new MonkeyCommandReturn(true, Boolean.toString(node.isEnabled()));
368b36bed5899431bc495f3046ca380f318963eb700Michael Wright            }
369b36bed5899431bc495f3046ca380f318963eb700Michael Wright            return EARG;
370b36bed5899431bc495f3046ca380f318963eb700Michael Wright        }
371b36bed5899431bc495f3046ca380f318963eb700Michael Wright    }
372b36bed5899431bc495f3046ca380f318963eb700Michael Wright
373b36bed5899431bc495f3046ca380f318963eb700Michael Wright    /**
374b36bed5899431bc495f3046ca380f318963eb700Michael Wright     * Command to retrieve whether the given node is selected
375b36bed5899431bc495f3046ca380f318963eb700Michael Wright     */
376b36bed5899431bc495f3046ca380f318963eb700Michael Wright    public static class GetSelected implements ViewIntrospectionCommand {
377b36bed5899431bc495f3046ca380f318963eb700Michael Wright        //queryview [id type] [id] getselected
378b36bed5899431bc495f3046ca380f318963eb700Michael Wright        //queryview viewid button1 getselected
379b36bed5899431bc495f3046ca380f318963eb700Michael Wright        public MonkeyCommandReturn query(AccessibilityNodeInfo node,
380b36bed5899431bc495f3046ca380f318963eb700Michael Wright                                         List<String> args) {
381b36bed5899431bc495f3046ca380f318963eb700Michael Wright            if (args.size() == 0) {
382b36bed5899431bc495f3046ca380f318963eb700Michael Wright                return new MonkeyCommandReturn(true, Boolean.toString(node.isSelected()));
383b36bed5899431bc495f3046ca380f318963eb700Michael Wright            }
384b36bed5899431bc495f3046ca380f318963eb700Michael Wright            return EARG;
385b36bed5899431bc495f3046ca380f318963eb700Michael Wright        }
386b36bed5899431bc495f3046ca380f318963eb700Michael Wright    }
387b36bed5899431bc495f3046ca380f318963eb700Michael Wright
388b36bed5899431bc495f3046ca380f318963eb700Michael Wright    /**
389b36bed5899431bc495f3046ca380f318963eb700Michael Wright     * Command to set the selected status of the given node. Takes a boolean value as its only
390b36bed5899431bc495f3046ca380f318963eb700Michael Wright     * argument.
391b36bed5899431bc495f3046ca380f318963eb700Michael Wright     */
392b36bed5899431bc495f3046ca380f318963eb700Michael Wright    public static class SetSelected implements ViewIntrospectionCommand {
393b36bed5899431bc495f3046ca380f318963eb700Michael Wright        //queryview [id type] [id] setselected [boolean]
394b36bed5899431bc495f3046ca380f318963eb700Michael Wright        //queryview viewid button1 setselected true
395b36bed5899431bc495f3046ca380f318963eb700Michael Wright        public MonkeyCommandReturn query(AccessibilityNodeInfo node,
396b36bed5899431bc495f3046ca380f318963eb700Michael Wright                                         List<String> args) {
397b36bed5899431bc495f3046ca380f318963eb700Michael Wright            if (args.size() == 1) {
398b36bed5899431bc495f3046ca380f318963eb700Michael Wright                boolean actionPerformed;
399b36bed5899431bc495f3046ca380f318963eb700Michael Wright                if (Boolean.valueOf(args.get(0))) {
400b36bed5899431bc495f3046ca380f318963eb700Michael Wright                    actionPerformed = node.performAction(AccessibilityNodeInfo.ACTION_SELECT);
401b36bed5899431bc495f3046ca380f318963eb700Michael Wright                } else if (!Boolean.valueOf(args.get(0))) {
402b36bed5899431bc495f3046ca380f318963eb700Michael Wright                    actionPerformed =
403b36bed5899431bc495f3046ca380f318963eb700Michael Wright                            node.performAction(AccessibilityNodeInfo.ACTION_CLEAR_SELECTION);
404b36bed5899431bc495f3046ca380f318963eb700Michael Wright                } else {
405b36bed5899431bc495f3046ca380f318963eb700Michael Wright                    return EARG;
406b36bed5899431bc495f3046ca380f318963eb700Michael Wright                }
407b36bed5899431bc495f3046ca380f318963eb700Michael Wright                return new MonkeyCommandReturn(actionPerformed);
408b36bed5899431bc495f3046ca380f318963eb700Michael Wright            }
409b36bed5899431bc495f3046ca380f318963eb700Michael Wright            return EARG;
410b36bed5899431bc495f3046ca380f318963eb700Michael Wright        }
411b36bed5899431bc495f3046ca380f318963eb700Michael Wright    }
412b36bed5899431bc495f3046ca380f318963eb700Michael Wright
413b36bed5899431bc495f3046ca380f318963eb700Michael Wright    /**
414b36bed5899431bc495f3046ca380f318963eb700Michael Wright     * Command to get whether the given node is focused.
415b36bed5899431bc495f3046ca380f318963eb700Michael Wright     */
416b36bed5899431bc495f3046ca380f318963eb700Michael Wright    public static class GetFocused implements ViewIntrospectionCommand {
417b36bed5899431bc495f3046ca380f318963eb700Michael Wright        //queryview [id type] [id] getfocused
418b36bed5899431bc495f3046ca380f318963eb700Michael Wright        //queryview viewid button1 getfocused
419b36bed5899431bc495f3046ca380f318963eb700Michael Wright        public MonkeyCommandReturn query(AccessibilityNodeInfo node,
420b36bed5899431bc495f3046ca380f318963eb700Michael Wright                                         List<String> args) {
421b36bed5899431bc495f3046ca380f318963eb700Michael Wright            if (args.size() == 0) {
422b36bed5899431bc495f3046ca380f318963eb700Michael Wright                return new MonkeyCommandReturn(true, Boolean.toString(node.isFocused()));
423b36bed5899431bc495f3046ca380f318963eb700Michael Wright            }
424b36bed5899431bc495f3046ca380f318963eb700Michael Wright            return EARG;
425b36bed5899431bc495f3046ca380f318963eb700Michael Wright        }
426b36bed5899431bc495f3046ca380f318963eb700Michael Wright    }
427b36bed5899431bc495f3046ca380f318963eb700Michael Wright
428b36bed5899431bc495f3046ca380f318963eb700Michael Wright    /**
429b36bed5899431bc495f3046ca380f318963eb700Michael Wright     * Command to set the focus status of the given node. Takes a boolean value
430b36bed5899431bc495f3046ca380f318963eb700Michael Wright     * as its only argument.
431b36bed5899431bc495f3046ca380f318963eb700Michael Wright     */
432b36bed5899431bc495f3046ca380f318963eb700Michael Wright    public static class SetFocused implements ViewIntrospectionCommand {
433b36bed5899431bc495f3046ca380f318963eb700Michael Wright        //queryview [id type] [id] setfocused [boolean]
434b36bed5899431bc495f3046ca380f318963eb700Michael Wright        //queryview viewid button1 setfocused false
435b36bed5899431bc495f3046ca380f318963eb700Michael Wright        public MonkeyCommandReturn query(AccessibilityNodeInfo node,
436b36bed5899431bc495f3046ca380f318963eb700Michael Wright                                         List<String> args) {
437b36bed5899431bc495f3046ca380f318963eb700Michael Wright            if (args.size() == 1) {
438b36bed5899431bc495f3046ca380f318963eb700Michael Wright                boolean actionPerformed;
439b36bed5899431bc495f3046ca380f318963eb700Michael Wright                if (Boolean.valueOf(args.get(0))) {
440b36bed5899431bc495f3046ca380f318963eb700Michael Wright                    actionPerformed = node.performAction(AccessibilityNodeInfo.ACTION_FOCUS);
441b36bed5899431bc495f3046ca380f318963eb700Michael Wright                } else if (!Boolean.valueOf(args.get(0))) {
442b36bed5899431bc495f3046ca380f318963eb700Michael Wright                    actionPerformed = node.performAction(AccessibilityNodeInfo.ACTION_CLEAR_FOCUS);
443b36bed5899431bc495f3046ca380f318963eb700Michael Wright                } else {
444b36bed5899431bc495f3046ca380f318963eb700Michael Wright                    return EARG;
445b36bed5899431bc495f3046ca380f318963eb700Michael Wright                }
446b36bed5899431bc495f3046ca380f318963eb700Michael Wright                return new MonkeyCommandReturn(actionPerformed);
447b36bed5899431bc495f3046ca380f318963eb700Michael Wright            }
448b36bed5899431bc495f3046ca380f318963eb700Michael Wright            return EARG;
449b36bed5899431bc495f3046ca380f318963eb700Michael Wright        }
450b36bed5899431bc495f3046ca380f318963eb700Michael Wright    }
451b36bed5899431bc495f3046ca380f318963eb700Michael Wright
452b36bed5899431bc495f3046ca380f318963eb700Michael Wright    /**
453b36bed5899431bc495f3046ca380f318963eb700Michael Wright     * Command to get the accessibility ids of the given node. Returns the accessibility ids as a
454b36bed5899431bc495f3046ca380f318963eb700Michael Wright     * space separated pair of integers with window id coming first, followed by the accessibility
455b36bed5899431bc495f3046ca380f318963eb700Michael Wright     * view id.
456b36bed5899431bc495f3046ca380f318963eb700Michael Wright     */
457b36bed5899431bc495f3046ca380f318963eb700Michael Wright    public static class GetAccessibilityIds implements ViewIntrospectionCommand {
458b36bed5899431bc495f3046ca380f318963eb700Michael Wright        //queryview [id type] [id] getaccessibilityids
459b36bed5899431bc495f3046ca380f318963eb700Michael Wright        //queryview viewid button1 getaccessibilityids
460b36bed5899431bc495f3046ca380f318963eb700Michael Wright        public MonkeyCommandReturn query(AccessibilityNodeInfo node,
461b36bed5899431bc495f3046ca380f318963eb700Michael Wright                                         List<String> args) {
462b36bed5899431bc495f3046ca380f318963eb700Michael Wright            if (args.size() == 0) {
463b36bed5899431bc495f3046ca380f318963eb700Michael Wright                int viewId;
464b36bed5899431bc495f3046ca380f318963eb700Michael Wright                try {
4654ce026b4b196e24ee125247843697680fb8e207eSvetoslav Ganov                    Class<?> klass = node.getClass();
466b36bed5899431bc495f3046ca380f318963eb700Michael Wright                    Field field = klass.getDeclaredField("mAccessibilityViewId");
467b36bed5899431bc495f3046ca380f318963eb700Michael Wright                    field.setAccessible(true);
468b36bed5899431bc495f3046ca380f318963eb700Michael Wright                    viewId = ((Integer) field.get(node)).intValue();
469b36bed5899431bc495f3046ca380f318963eb700Michael Wright                } catch (NoSuchFieldException e) {
470b36bed5899431bc495f3046ca380f318963eb700Michael Wright                    return new MonkeyCommandReturn(false, NO_NODE);
471b36bed5899431bc495f3046ca380f318963eb700Michael Wright                } catch (IllegalAccessException e) {
472b36bed5899431bc495f3046ca380f318963eb700Michael Wright                    return new MonkeyCommandReturn(false, "Access exception");
473b36bed5899431bc495f3046ca380f318963eb700Michael Wright                }
474b36bed5899431bc495f3046ca380f318963eb700Michael Wright                String ids = node.getWindowId() + " " + viewId;
475b36bed5899431bc495f3046ca380f318963eb700Michael Wright                return new MonkeyCommandReturn(true, ids);
476b36bed5899431bc495f3046ca380f318963eb700Michael Wright            }
477b36bed5899431bc495f3046ca380f318963eb700Michael Wright            return EARG;
478b36bed5899431bc495f3046ca380f318963eb700Michael Wright        }
479b36bed5899431bc495f3046ca380f318963eb700Michael Wright    }
480b36bed5899431bc495f3046ca380f318963eb700Michael Wright
481b36bed5899431bc495f3046ca380f318963eb700Michael Wright    /**
482b36bed5899431bc495f3046ca380f318963eb700Michael Wright     * Command to get the accessibility ids of the parent of the given node. Returns the
483b36bed5899431bc495f3046ca380f318963eb700Michael Wright     * accessibility ids as a space separated pair of integers with window id coming first followed
484b36bed5899431bc495f3046ca380f318963eb700Michael Wright     * by the accessibility view id.
485b36bed5899431bc495f3046ca380f318963eb700Michael Wright     */
486b36bed5899431bc495f3046ca380f318963eb700Michael Wright    public static class GetParent implements ViewIntrospectionCommand {
487b36bed5899431bc495f3046ca380f318963eb700Michael Wright        //queryview [id type] [id] getparent
488b36bed5899431bc495f3046ca380f318963eb700Michael Wright        //queryview viewid button1 getparent
489b36bed5899431bc495f3046ca380f318963eb700Michael Wright        public MonkeyCommandReturn query(AccessibilityNodeInfo node,
490b36bed5899431bc495f3046ca380f318963eb700Michael Wright                                         List<String> args) {
491b36bed5899431bc495f3046ca380f318963eb700Michael Wright            if (args.size() == 0) {
492b36bed5899431bc495f3046ca380f318963eb700Michael Wright                AccessibilityNodeInfo parent = node.getParent();
493b36bed5899431bc495f3046ca380f318963eb700Michael Wright                if (parent == null) {
494b36bed5899431bc495f3046ca380f318963eb700Michael Wright                  return new MonkeyCommandReturn(false, "Given node has no parent");
495b36bed5899431bc495f3046ca380f318963eb700Michael Wright                }
496b36bed5899431bc495f3046ca380f318963eb700Michael Wright                return (new GetAccessibilityIds()).query(parent, new ArrayList<String>());
497b36bed5899431bc495f3046ca380f318963eb700Michael Wright            }
498b36bed5899431bc495f3046ca380f318963eb700Michael Wright            return EARG;
499b36bed5899431bc495f3046ca380f318963eb700Michael Wright        }
500b36bed5899431bc495f3046ca380f318963eb700Michael Wright    }
501b36bed5899431bc495f3046ca380f318963eb700Michael Wright
502b36bed5899431bc495f3046ca380f318963eb700Michael Wright    /**
503b36bed5899431bc495f3046ca380f318963eb700Michael Wright     * Command to get the accessibility ids of the children of the given node. Returns the
504b36bed5899431bc495f3046ca380f318963eb700Michael Wright     * children's ids as a space separated list of integer pairs. Each of the pairs consists of the
505b36bed5899431bc495f3046ca380f318963eb700Michael Wright     * window id, followed by the accessibility id.
506b36bed5899431bc495f3046ca380f318963eb700Michael Wright     */
507b36bed5899431bc495f3046ca380f318963eb700Michael Wright    public static class GetChildren implements ViewIntrospectionCommand {
508b36bed5899431bc495f3046ca380f318963eb700Michael Wright        //queryview [id type] [id] getchildren
509b36bed5899431bc495f3046ca380f318963eb700Michael Wright        //queryview viewid button1 getchildren
510b36bed5899431bc495f3046ca380f318963eb700Michael Wright        public MonkeyCommandReturn query(AccessibilityNodeInfo node,
511b36bed5899431bc495f3046ca380f318963eb700Michael Wright                                         List<String> args) {
512b36bed5899431bc495f3046ca380f318963eb700Michael Wright            if (args.size() == 0) {
513b36bed5899431bc495f3046ca380f318963eb700Michael Wright                ViewIntrospectionCommand idGetter = new GetAccessibilityIds();
514b36bed5899431bc495f3046ca380f318963eb700Michael Wright                List<String> emptyArgs = new ArrayList<String>();
515b36bed5899431bc495f3046ca380f318963eb700Michael Wright                StringBuilder ids = new StringBuilder();
516b36bed5899431bc495f3046ca380f318963eb700Michael Wright                int totalChildren = node.getChildCount();
517b36bed5899431bc495f3046ca380f318963eb700Michael Wright                for (int i = 0; i < totalChildren; i++) {
518b36bed5899431bc495f3046ca380f318963eb700Michael Wright                    MonkeyCommandReturn result = idGetter.query(node.getChild(i), emptyArgs);
519b36bed5899431bc495f3046ca380f318963eb700Michael Wright                    if (!result.wasSuccessful()) {
520b36bed5899431bc495f3046ca380f318963eb700Michael Wright                        return result;
521b36bed5899431bc495f3046ca380f318963eb700Michael Wright                    } else {
522b36bed5899431bc495f3046ca380f318963eb700Michael Wright                        ids.append(result.getMessage()).append(" ");
523b36bed5899431bc495f3046ca380f318963eb700Michael Wright                    }
524b36bed5899431bc495f3046ca380f318963eb700Michael Wright                }
525b36bed5899431bc495f3046ca380f318963eb700Michael Wright                return new MonkeyCommandReturn(true, ids.toString());
526b36bed5899431bc495f3046ca380f318963eb700Michael Wright            }
527b36bed5899431bc495f3046ca380f318963eb700Michael Wright            return EARG;
528b36bed5899431bc495f3046ca380f318963eb700Michael Wright        }
529b36bed5899431bc495f3046ca380f318963eb700Michael Wright    }
530b36bed5899431bc495f3046ca380f318963eb700Michael Wright}
531