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