1package com.android.uiautomator.core;
2
3import android.accessibilityservice.AccessibilityServiceInfo;
4import android.app.ActivityManager;
5import android.app.IActivityController;
6import android.app.IActivityManager;
7import android.app.UiAutomation;
8import android.app.UiAutomationConnection;
9import android.content.Intent;
10import android.os.HandlerThread;
11import android.os.RemoteException;
12
13/**
14 * @hide
15 */
16public class UiAutomationShellWrapper {
17
18    private static final String HANDLER_THREAD_NAME = "UiAutomatorHandlerThread";
19
20    private final HandlerThread mHandlerThread = new HandlerThread(HANDLER_THREAD_NAME);
21
22    private UiAutomation mUiAutomation;
23
24    public void connect() {
25        if (mHandlerThread.isAlive()) {
26            throw new IllegalStateException("Already connected!");
27        }
28        mHandlerThread.start();
29        mUiAutomation = new UiAutomation(mHandlerThread.getLooper(),
30                new UiAutomationConnection());
31        mUiAutomation.connect();
32    }
33
34    /**
35     * Enable or disable monkey test mode.
36     *
37     * Setting test as "monkey" indicates to some applications that a test framework is
38     * running as a "monkey" type. Such applications may choose not to perform actions that
39     * do submits so to avoid allowing monkey tests from doing harm or performing annoying
40     * actions such as dialing 911 or posting messages to public forums, etc.
41     *
42     * @param isSet True to set as monkey test. False to set as regular functional test (default).
43     * @see ActivityManager#isUserAMonkey()
44     */
45    public void setRunAsMonkey(boolean isSet) {
46        IActivityManager am = ActivityManager.getService();
47        if (am == null) {
48            throw new RuntimeException("Can't manage monkey status; is the system running?");
49        }
50        try {
51            if (isSet) {
52                am.setActivityController(new DummyActivityController(), true);
53            } else {
54                am.setActivityController(null, true);
55            }
56        } catch (RemoteException e) {
57            throw new RuntimeException(e);
58        }
59    }
60
61    public void disconnect() {
62        if (!mHandlerThread.isAlive()) {
63            throw new IllegalStateException("Already disconnected!");
64        }
65        mUiAutomation.disconnect();
66        mHandlerThread.quit();
67    }
68
69    public UiAutomation getUiAutomation() {
70        return mUiAutomation;
71    }
72
73    public void setCompressedLayoutHierarchy(boolean compressed) {
74        AccessibilityServiceInfo info = mUiAutomation.getServiceInfo();
75        if (compressed)
76            info.flags &= ~AccessibilityServiceInfo.FLAG_INCLUDE_NOT_IMPORTANT_VIEWS;
77        else
78            info.flags |= AccessibilityServiceInfo.FLAG_INCLUDE_NOT_IMPORTANT_VIEWS;
79        mUiAutomation.setServiceInfo(info);
80    }
81
82    /**
83     * Dummy, no interference, activity controller.
84     */
85    private class DummyActivityController extends IActivityController.Stub {
86        @Override
87        public boolean activityStarting(Intent intent, String pkg) throws RemoteException {
88            /* do nothing and let activity proceed normally */
89            return true;
90        }
91
92        @Override
93        public boolean activityResuming(String pkg) throws RemoteException {
94            /* do nothing and let activity proceed normally */
95            return true;
96        }
97
98        @Override
99        public boolean appCrashed(String processName, int pid, String shortMsg, String longMsg,
100                long timeMillis, String stackTrace) throws RemoteException {
101            /* do nothing and let activity proceed normally */
102            return true;
103        }
104
105        @Override
106        public int appEarlyNotResponding(String processName, int pid, String annotation)
107                throws RemoteException {
108            /* do nothing and let activity proceed normally */
109            return 0;
110        }
111
112        @Override
113        public int appNotResponding(String processName, int pid, String processStats)
114                throws RemoteException {
115            /* do nothing and let activity proceed normally */
116            return 0;
117        }
118
119        @Override
120        public int systemNotResponding(String message)
121                throws RemoteException {
122            /* do nothing and let system proceed normally */
123            return 0;
124        }
125    }
126}
127