1/*
2 ** Copyright 2017, The Android Open Source Project
3 **
4 ** Licensed under the Apache License, Version 2.0 (the "License");
5 ** you may not use this file except in compliance with the License.
6 ** You may obtain a copy of the License at
7 **
8 **     http://www.apache.org/licenses/LICENSE-2.0
9 **
10 ** Unless required by applicable law or agreed to in writing, software
11 ** distributed under the License is distributed on an "AS IS" BASIS,
12 ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 ** See the License for the specific language governing permissions and
14 ** limitations under the License.
15 */
16
17package com.android.server.accessibility;
18
19import static org.junit.Assert.assertEquals;
20import static org.junit.Assert.assertFalse;
21import static org.junit.Assert.assertTrue;
22import static org.mockito.ArgumentMatchers.anyInt;
23import static org.mockito.Mockito.mock;
24import static org.mockito.Mockito.verify;
25import static org.mockito.Mockito.when;
26
27import android.accessibilityservice.AccessibilityServiceInfo;
28import android.accessibilityservice.IAccessibilityServiceClient;
29import android.app.UiAutomation;
30import android.content.Context;
31import android.content.pm.ApplicationInfo;
32import android.content.pm.ResolveInfo;
33import android.content.pm.ServiceInfo;
34import android.os.IBinder;
35import android.os.Looper;
36import android.view.accessibility.AccessibilityEvent;
37
38import com.android.server.wm.WindowManagerInternal;
39
40import org.junit.Before;
41import org.junit.BeforeClass;
42import org.junit.Test;
43import org.mockito.ArgumentCaptor;
44import org.mockito.Mock;
45import org.mockito.MockitoAnnotations;
46
47/**
48 * Tests for UiAutomationManager
49 */
50public class UiAutomationManagerTest {
51    static final int SERVICE_ID = 42;
52
53    final UiAutomationManager mUiAutomationManager = new UiAutomationManager();
54
55    MessageCapturingHandler mMessageCapturingHandler;
56
57    @Mock AccessibilityManagerService.UserState mMockUserState;
58    @Mock Context mMockContext;
59    @Mock AccessibilityServiceInfo mMockServiceInfo;
60    @Mock ResolveInfo mMockResolveInfo;
61    @Mock AccessibilityManagerService.SecurityPolicy mMockSecurityPolicy;
62    @Mock AbstractAccessibilityServiceConnection.SystemSupport mMockSystemSupport;
63    @Mock WindowManagerInternal mMockWindowManagerInternal;
64    @Mock GlobalActionPerformer mMockGlobalActionPerformer;
65    @Mock IBinder mMockOwner;
66    @Mock IAccessibilityServiceClient mMockAccessibilityServiceClient;
67    @Mock IBinder mMockServiceAsBinder;
68
69    @BeforeClass
70    public static void oneTimeInitialization() {
71        if (Looper.myLooper() == null) {
72            Looper.prepare();
73        }
74    }
75
76    @Before
77    public void setup() {
78        MockitoAnnotations.initMocks(this);
79
80        when(mMockSystemSupport.getKeyEventDispatcher()).thenReturn(mock(KeyEventDispatcher.class));
81
82        when(mMockServiceInfo.getResolveInfo()).thenReturn(mMockResolveInfo);
83        mMockResolveInfo.serviceInfo = mock(ServiceInfo.class);
84        mMockResolveInfo.serviceInfo.applicationInfo = mock(ApplicationInfo.class);
85
86        when(mMockAccessibilityServiceClient.asBinder()).thenReturn(mMockServiceAsBinder);
87
88        mMessageCapturingHandler = new MessageCapturingHandler(null);
89    }
90
91    @Test
92    public void isRunning_returnsTrueOnlyWhenRunning() {
93        assertFalse(mUiAutomationManager.isUiAutomationRunningLocked());
94        register(0);
95        assertTrue(mUiAutomationManager.isUiAutomationRunningLocked());
96        unregister();
97        assertFalse(mUiAutomationManager.isUiAutomationRunningLocked());
98    }
99
100    @Test
101    public void suppressingAccessibilityServicesLocked_dependsOnFlags() {
102        assertFalse(mUiAutomationManager.suppressingAccessibilityServicesLocked());
103        register(0);
104        assertTrue(mUiAutomationManager.suppressingAccessibilityServicesLocked());
105        unregister();
106        assertFalse(mUiAutomationManager.suppressingAccessibilityServicesLocked());
107        register(UiAutomation.FLAG_DONT_SUPPRESS_ACCESSIBILITY_SERVICES);
108        assertFalse(mUiAutomationManager.suppressingAccessibilityServicesLocked());
109        unregister();
110        assertFalse(mUiAutomationManager.suppressingAccessibilityServicesLocked());
111    }
112
113    @Test
114    public void isTouchExplorationEnabledLocked_dependsOnInfoFlags() {
115        assertFalse(mUiAutomationManager.isTouchExplorationEnabledLocked());
116        register(0);
117        assertFalse(mUiAutomationManager.isTouchExplorationEnabledLocked());
118        unregister();
119        mMockServiceInfo.flags = AccessibilityServiceInfo.FLAG_REQUEST_TOUCH_EXPLORATION_MODE;
120        register(0);
121        assertTrue(mUiAutomationManager.isTouchExplorationEnabledLocked());
122        unregister();
123        assertFalse(mUiAutomationManager.isTouchExplorationEnabledLocked());
124    }
125
126    @Test
127    public void canRetrieveInteractiveWindowsLocked_dependsOnInfoFlags() {
128        assertFalse(mUiAutomationManager.canRetrieveInteractiveWindowsLocked());
129        register(0);
130        assertFalse(mUiAutomationManager.canRetrieveInteractiveWindowsLocked());
131        unregister();
132        mMockServiceInfo.flags = AccessibilityServiceInfo.FLAG_RETRIEVE_INTERACTIVE_WINDOWS;
133        register(0);
134        assertTrue(mUiAutomationManager.canRetrieveInteractiveWindowsLocked());
135        unregister();
136        assertFalse(mUiAutomationManager.canRetrieveInteractiveWindowsLocked());
137    }
138
139    @Test
140    public void getRequestedEventMaskLocked_dependsOnInfoEventTypes() {
141        assertEquals(0, mUiAutomationManager.getRequestedEventMaskLocked());
142        mMockServiceInfo.eventTypes = 0;
143        register(0);
144        assertEquals(mMockServiceInfo.eventTypes,
145                mUiAutomationManager.getRequestedEventMaskLocked());
146        unregister();
147        mMockServiceInfo.eventTypes = AccessibilityEvent.TYPES_ALL_MASK;
148        register(0);
149        assertEquals(mMockServiceInfo.eventTypes,
150                mUiAutomationManager.getRequestedEventMaskLocked());
151        unregister();
152        assertEquals(0, mUiAutomationManager.getRequestedEventMaskLocked());
153    }
154
155    @Test
156    public void uiAutomationBinderDiesBeforeConnecting_notifiesSystem() throws Exception {
157        register(0);
158        ArgumentCaptor<IBinder.DeathRecipient> captor = ArgumentCaptor.forClass(
159                IBinder.DeathRecipient.class);
160        verify(mMockOwner).linkToDeath(captor.capture(), anyInt());
161        captor.getValue().binderDied();
162        mMessageCapturingHandler.sendAllMessages();
163        verify(mMockSystemSupport).onClientChange(false);
164    }
165
166    private void register(int flags) {
167        mUiAutomationManager.registerUiTestAutomationServiceLocked(mMockOwner,
168                mMockAccessibilityServiceClient, mMockContext, mMockServiceInfo, SERVICE_ID,
169                mMessageCapturingHandler, new Object(), mMockSecurityPolicy, mMockSystemSupport,
170                mMockWindowManagerInternal, mMockGlobalActionPerformer, flags);
171    }
172
173    private void unregister() {
174        mUiAutomationManager.unregisterUiTestAutomationServiceLocked(
175                mMockAccessibilityServiceClient);
176    }
177}
178