• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /**
2  * Copyright (C) 2016 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
5  * in compliance with the License. You may obtain a copy of the License at
6  *
7  * http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software distributed under the
10  * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
11  * express or implied. See the License for the specific language governing permissions and
12  * limitations under the License.
13  */
14 
15 package android.accessibilityservice.cts;
16 import static android.accessibilityservice.AccessibilityService.SHOW_MODE_AUTO;
17 import static android.accessibilityservice.AccessibilityService.SHOW_MODE_HIDDEN;
18 import static android.accessibilityservice.AccessibilityService.SHOW_MODE_IGNORE_HARD_KEYBOARD;
19 import static android.accessibilityservice.cts.utils.CtsTestUtils.runIfNotNull;
20 
21 import static org.junit.Assert.assertEquals;
22 import static org.junit.Assert.assertTrue;
23 
24 import android.accessibility.cts.common.InstrumentedAccessibilityService;
25 import android.accessibilityservice.AccessibilityService.SoftKeyboardController;
26 import android.accessibilityservice.AccessibilityService.SoftKeyboardController.OnShowModeChangedListener;
27 import android.accessibilityservice.cts.activities.AccessibilityTestActivity;
28 import android.accessibilityservice.cts.utils.AsyncUtils;
29 import android.app.Instrumentation;
30 import android.os.Bundle;
31 import android.os.SystemClock;
32 import android.platform.test.annotations.AppModeFull;
33 
34 import androidx.test.InstrumentationRegistry;
35 import androidx.test.runner.AndroidJUnit4;
36 
37 import org.junit.After;
38 import org.junit.Before;
39 import org.junit.Test;
40 import org.junit.runner.RunWith;
41 
42 /**
43  * Test cases for testing the accessibility APIs for interacting with the soft keyboard show mode.
44  */
45 @RunWith(AndroidJUnit4.class)
46 @AppModeFull
47 public class AccessibilitySoftKeyboardModesTest {
48     private int mLastCallbackValue;
49 
50     private final Instrumentation mInstrumentation = InstrumentationRegistry.getInstrumentation();
51     private InstrumentedAccessibilityService mService;
52     private final Object mLock = new Object();
53     private final OnShowModeChangedListener mListener = (c, showMode) -> {
54         synchronized (mLock) {
55             mLastCallbackValue = showMode;
56             mLock.notifyAll();
57         }
58     };
59 
60 
61 
62     @Before
setUp()63     public void setUp() throws Exception {
64         mService = InstrumentedAccessibilityService.enableService(mInstrumentation,
65                 InstrumentedAccessibilityService.class);
66     }
67 
68     @After
tearDown()69     public void tearDown() throws Exception {
70         runIfNotNull(mService, service -> service.runOnServiceSync(service::disableSelf));
71     }
72 
73     @Test
testApiReturnValues_shouldChangeValueOnRequestAndSendCallback()74     public void testApiReturnValues_shouldChangeValueOnRequestAndSendCallback() throws Exception {
75         final SoftKeyboardController controller = mService.getSoftKeyboardController();
76 
77         // Confirm that we start in the default state
78         assertEquals(SHOW_MODE_AUTO, controller.getShowMode());
79 
80         controller.addOnShowModeChangedListener(mListener);
81         assertCanSetAndGetShowModeAndCallbackHappens(SHOW_MODE_HIDDEN, mService);
82         assertCanSetAndGetShowModeAndCallbackHappens(SHOW_MODE_IGNORE_HARD_KEYBOARD, mService);
83         assertCanSetAndGetShowModeAndCallbackHappens(SHOW_MODE_AUTO, mService);
84 
85         // Make sure we can remove our listener.
86         assertTrue(controller.removeOnShowModeChangedListener(mListener));
87     }
88 
89     @Test
secondServiceChangingTheShowMode_updatesModeAndNotifiesFirstService()90     public void secondServiceChangingTheShowMode_updatesModeAndNotifiesFirstService()
91             throws Exception {
92 
93         final SoftKeyboardController controller = mService.getSoftKeyboardController();
94         // Confirm that we start in the default state
95         assertEquals(SHOW_MODE_AUTO, controller.getShowMode());
96 
97         final InstrumentedAccessibilityService secondService =
98                 StubAccessibilityButtonService.enableSelf(mInstrumentation);
99         try {
100             // Listen on the first service
101             controller.addOnShowModeChangedListener(mListener);
102             assertCanSetAndGetShowModeAndCallbackHappens(SHOW_MODE_HIDDEN, mService);
103 
104             // Change the mode on the second service
105             assertCanSetAndGetShowModeAndCallbackHappens(SHOW_MODE_IGNORE_HARD_KEYBOARD,
106                     secondService);
107         } finally {
108             secondService.runOnServiceSync(() -> secondService.disableSelf());
109         }
110 
111         // Shutting down the second service, which was controlling the mode, should put us back
112         // to the default
113         waitForCallbackValueWithLock(SHOW_MODE_AUTO);
114         final int showMode = mService.getOnService(() -> controller.getShowMode());
115         assertEquals(SHOW_MODE_AUTO, showMode);
116     }
117 
assertCanSetAndGetShowModeAndCallbackHappens( int mode, InstrumentedAccessibilityService service)118     private void assertCanSetAndGetShowModeAndCallbackHappens(
119             int mode, InstrumentedAccessibilityService service)
120             throws Exception  {
121         final SoftKeyboardController controller = service.getSoftKeyboardController();
122         mLastCallbackValue = -1;
123         final boolean setShowModeReturns =
124                 service.getOnService(() -> controller.setShowMode(mode));
125         assertTrue(setShowModeReturns);
126         waitForCallbackValueWithLock(mode);
127         assertEquals(mode, controller.getShowMode());
128     }
129 
waitForCallbackValueWithLock(int expectedValue)130     private void waitForCallbackValueWithLock(int expectedValue) throws Exception {
131         long timeoutTimeMillis = SystemClock.uptimeMillis() + AsyncUtils.DEFAULT_TIMEOUT_MS;
132 
133         while (SystemClock.uptimeMillis() < timeoutTimeMillis) {
134             synchronized(mLock) {
135                 if (mLastCallbackValue == expectedValue) {
136                     return;
137                 }
138                 try {
139                     mLock.wait(timeoutTimeMillis - SystemClock.uptimeMillis());
140                 } catch (InterruptedException e) {
141                     // Wait until timeout.
142                 }
143             }
144         }
145 
146         throw new IllegalStateException("last callback value <" + mLastCallbackValue
147                 + "> does not match expected value < " + expectedValue + ">");
148     }
149 
150     /**
151      * Activity for testing the AccessibilityService API for hiding and showing the soft keyboard.
152      */
153     public static class SoftKeyboardModesActivity extends AccessibilityTestActivity {
SoftKeyboardModesActivity()154         public SoftKeyboardModesActivity() {
155             super();
156         }
157 
158         @Override
onCreate(Bundle savedInstanceState)159         public void onCreate(Bundle savedInstanceState) {
160             super.onCreate(savedInstanceState);
161             setContentView(R.layout.accessibility_soft_keyboard_modes_test);
162         }
163     }
164 }
165