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 junit.framework.Assert.assertFalse;
20import static junit.framework.Assert.assertTrue;
21
22import static org.mockito.ArgumentMatchers.any;
23import static org.mockito.ArgumentMatchers.anyInt;
24import static org.mockito.ArgumentMatchers.eq;
25import static org.mockito.Mockito.mock;
26import static org.mockito.Mockito.verify;
27import static org.mockito.Mockito.when;
28
29import android.accessibilityservice.AccessibilityServiceInfo;
30import android.content.ComponentName;
31import android.content.Context;
32import android.content.Intent;
33import android.content.pm.ApplicationInfo;
34import android.content.pm.ResolveInfo;
35import android.content.pm.ServiceInfo;
36import android.os.Handler;
37import android.os.IBinder;
38import android.os.Looper;
39import android.os.RemoteException;
40import android.os.UserHandle;
41
42import com.android.server.wm.WindowManagerInternal;
43
44import org.junit.Before;
45import org.junit.BeforeClass;
46import org.junit.Test;
47import org.mockito.Mock;
48import org.mockito.MockitoAnnotations;
49
50import java.util.Arrays;
51import java.util.HashSet;
52
53
54/**
55 * Tests for AccessibilityServiceConnection
56 */
57public class AccessibilityServiceConnectionTest {
58    static final ComponentName COMPONENT_NAME = new ComponentName(
59            "com.android.server.accessibility", "AccessibilityServiceConnectionTest");
60    static final int SERVICE_ID = 42;
61
62    AccessibilityServiceConnection mConnection;
63
64    @Mock AccessibilityManagerService.UserState mMockUserState;
65    @Mock Context mMockContext;
66    @Mock AccessibilityServiceInfo mMockServiceInfo;
67    @Mock ResolveInfo mMockResolveInfo;
68    @Mock AccessibilityManagerService.SecurityPolicy mMockSecurityPolicy;
69    @Mock AbstractAccessibilityServiceConnection.SystemSupport mMockSystemSupport;
70    @Mock WindowManagerInternal mMockWindowManagerInternal;
71    @Mock GlobalActionPerformer mMockGlobalActionPerformer;
72    @Mock KeyEventDispatcher mMockKeyEventDispatcher;
73    @Mock MagnificationController mMockMagnificationController;
74
75    MessageCapturingHandler mHandler = new MessageCapturingHandler(null);
76
77    @BeforeClass
78    public static void oneTimeInitialization() {
79        if (Looper.myLooper() == null) {
80            Looper.prepare();
81        }
82    }
83
84    @Before
85    public void setup() {
86        MockitoAnnotations.initMocks(this);
87        when(mMockSystemSupport.getKeyEventDispatcher()).thenReturn(mMockKeyEventDispatcher);
88        when(mMockSystemSupport.getMagnificationController())
89                .thenReturn(mMockMagnificationController);
90
91        when(mMockServiceInfo.getResolveInfo()).thenReturn(mMockResolveInfo);
92        mMockResolveInfo.serviceInfo = mock(ServiceInfo.class);
93        mMockResolveInfo.serviceInfo.applicationInfo = mock(ApplicationInfo.class);
94
95        mConnection = new AccessibilityServiceConnection(mMockUserState, mMockContext,
96                COMPONENT_NAME, mMockServiceInfo, SERVICE_ID, mHandler, new Object(),
97                mMockSecurityPolicy, mMockSystemSupport, mMockWindowManagerInternal,
98                mMockGlobalActionPerformer);
99    }
100
101    @Test
102    public void bind_requestsContextToBindService() {
103        mConnection.bindLocked();
104        verify(mMockContext).bindServiceAsUser(any(Intent.class), eq(mConnection),
105                eq(Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE_WHILE_AWAKE),
106                any(UserHandle.class));
107    }
108
109    @Test
110    public void unbind_requestsContextToUnbindService() {
111        mConnection.unbindLocked();
112        verify(mMockContext).unbindService(mConnection);
113    }
114
115    @Test
116    public void bindConnectUnbind_linksAndUnlinksToServiceDeath() throws RemoteException {
117        IBinder mockBinder = mock(IBinder.class);
118        setServiceBinding(COMPONENT_NAME);
119        mConnection.bindLocked();
120        mConnection.onServiceConnected(COMPONENT_NAME, mockBinder);
121        verify(mockBinder).linkToDeath(eq(mConnection), anyInt());
122        mConnection.unbindLocked();
123        verify(mockBinder).unlinkToDeath(eq(mConnection), anyInt());
124    }
125
126    @Test
127    public void connectedServiceCrashedAndRestarted_crashReportedInServiceInfo() {
128        IBinder mockBinder = mock(IBinder.class);
129        setServiceBinding(COMPONENT_NAME);
130        mConnection.bindLocked();
131        mConnection.onServiceConnected(COMPONENT_NAME, mockBinder);
132        assertFalse(mConnection.getServiceInfo().crashed);
133        mConnection.binderDied();
134        assertTrue(mConnection.getServiceInfo().crashed);
135        mConnection.onServiceConnected(COMPONENT_NAME, mockBinder);
136        mHandler.sendAllMessages();
137        assertFalse(mConnection.getServiceInfo().crashed);
138    }
139
140    private void setServiceBinding(ComponentName componentName) {
141        when(mMockUserState.getBindingServicesLocked())
142                .thenReturn(new HashSet<>(Arrays.asList(componentName)));
143    }
144}
145