1 /* 2 * Copyright (C) 2012 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 17 package android.view.accessibility.cts; 18 19 import static android.accessibility.cts.common.InstrumentedAccessibilityService.TIMEOUT_SERVICE_ENABLE; 20 import static android.view.accessibility.cts.ServiceControlUtils.getEnabledServices; 21 import static android.view.accessibility.cts.ServiceControlUtils.waitForConditionWithServiceStateChange; 22 23 import static com.android.compatibility.common.util.SystemUtil.runWithShellPermissionIdentity; 24 25 import static org.junit.Assert.assertEquals; 26 import static org.junit.Assert.assertFalse; 27 import static org.junit.Assert.assertSame; 28 import static org.junit.Assert.assertTrue; 29 import static org.junit.Assert.fail; 30 31 import android.accessibility.cts.common.InstrumentedAccessibilityService; 32 import android.accessibilityservice.AccessibilityServiceInfo; 33 import android.app.Instrumentation; 34 import android.app.Service; 35 import android.app.UiAutomation; 36 import android.content.Context; 37 import android.content.pm.ServiceInfo; 38 import android.os.Handler; 39 import android.platform.test.annotations.AppModeFull; 40 import android.provider.Settings; 41 import android.text.TextUtils; 42 import android.view.accessibility.AccessibilityEvent; 43 import android.view.accessibility.AccessibilityManager; 44 import android.view.accessibility.AccessibilityManager.AccessibilityStateChangeListener; 45 import android.view.accessibility.AccessibilityManager.TouchExplorationStateChangeListener; 46 47 import androidx.test.InstrumentationRegistry; 48 import androidx.test.runner.AndroidJUnit4; 49 50 import com.android.compatibility.common.util.PollingCheck; 51 import com.android.compatibility.common.util.SystemUtil; 52 53 import org.junit.After; 54 import org.junit.Before; 55 import org.junit.Test; 56 import org.junit.runner.RunWith; 57 58 import java.io.IOException; 59 import java.util.List; 60 import java.util.concurrent.atomic.AtomicBoolean; 61 62 /** 63 * Class for testing {@link AccessibilityManager}. 64 */ 65 @RunWith(AndroidJUnit4.class) 66 public class AccessibilityManagerTest { 67 68 private static final Instrumentation sInstrumentation = 69 InstrumentationRegistry.getInstrumentation(); 70 71 private static final String SPEAKING_ACCESSIBLITY_SERVICE_NAME = 72 "android.view.accessibility.cts.SpeakingAccessibilityService"; 73 74 private static final String VIBRATING_ACCESSIBLITY_SERVICE_NAME = 75 "android.view.accessibility.cts.VibratingAccessibilityService"; 76 77 private static final String MULTIPLE_FEEDBACK_TYPES_ACCESSIBILITY_SERVICE_NAME = 78 "android.view.accessibility.cts.SpeakingAndVibratingAccessibilityService"; 79 80 public static final String ACCESSIBILITY_NON_INTERACTIVE_UI_TIMEOUT_MS = 81 "accessibility_non_interactive_ui_timeout_ms"; 82 83 public static final String ACCESSIBILITY_INTERACTIVE_UI_TIMEOUT_MS = 84 "accessibility_interactive_ui_timeout_ms"; 85 86 private AccessibilityManager mAccessibilityManager; 87 88 private Context mTargetContext; 89 90 private Handler mHandler; 91 92 @Before 93 public void setUp() throws Exception { 94 mAccessibilityManager = (AccessibilityManager) 95 sInstrumentation.getContext().getSystemService(Service.ACCESSIBILITY_SERVICE); 96 mTargetContext = sInstrumentation.getTargetContext(); 97 mHandler = new Handler(mTargetContext.getMainLooper()); 98 // In case the test runner started a UiAutomation, destroy it to start with a clean slate. 99 sInstrumentation.getUiAutomation().destroy(); 100 InstrumentedAccessibilityService.disableAllServices(sInstrumentation); 101 } 102 103 @After 104 public void tearDown() throws Exception { 105 InstrumentedAccessibilityService.disableAllServices(sInstrumentation); 106 } 107 108 @Test 109 public void testAddAndRemoveAccessibilityStateChangeListener() throws Exception { 110 AccessibilityStateChangeListener listener = (state) -> { 111 /* do nothing */ 112 }; 113 assertTrue(mAccessibilityManager.addAccessibilityStateChangeListener(listener)); 114 assertTrue(mAccessibilityManager.removeAccessibilityStateChangeListener(listener)); 115 assertFalse(mAccessibilityManager.removeAccessibilityStateChangeListener(listener)); 116 } 117 118 @Test 119 public void testAddAndRemoveTouchExplorationStateChangeListener() throws Exception { 120 TouchExplorationStateChangeListener listener = (boolean enabled) -> { 121 // Do nothing. 122 }; 123 assertTrue(mAccessibilityManager.addTouchExplorationStateChangeListener(listener)); 124 assertTrue(mAccessibilityManager.removeTouchExplorationStateChangeListener(listener)); 125 assertFalse(mAccessibilityManager.removeTouchExplorationStateChangeListener(listener)); 126 } 127 128 @Test 129 public void testIsTouchExplorationEnabled() throws Exception { 130 SpeakingAccessibilityService.enableSelf(sInstrumentation); 131 VibratingAccessibilityService.enableSelf(sInstrumentation); 132 new PollingCheck() { 133 @Override 134 protected boolean check() { 135 return mAccessibilityManager.isTouchExplorationEnabled(); 136 } 137 }.run(); 138 } 139 140 @Test 141 public void testGetInstalledAccessibilityServicesList() throws Exception { 142 List<AccessibilityServiceInfo> installedServices = 143 mAccessibilityManager.getInstalledAccessibilityServiceList(); 144 assertFalse("There must be at least one installed service.", installedServices.isEmpty()); 145 boolean speakingServiceInstalled = false; 146 boolean vibratingServiceInstalled = false; 147 final int serviceCount = installedServices.size(); 148 for (int i = 0; i < serviceCount; i++) { 149 AccessibilityServiceInfo installedService = installedServices.get(i); 150 ServiceInfo serviceInfo = installedService.getResolveInfo().serviceInfo; 151 if (mTargetContext.getPackageName().equals(serviceInfo.packageName) 152 && SPEAKING_ACCESSIBLITY_SERVICE_NAME.equals(serviceInfo.name)) { 153 speakingServiceInstalled = true; 154 } 155 if (mTargetContext.getPackageName().equals(serviceInfo.packageName) 156 && VIBRATING_ACCESSIBLITY_SERVICE_NAME.equals(serviceInfo.name)) { 157 vibratingServiceInstalled = true; 158 } 159 } 160 assertTrue("The speaking service should be installed.", speakingServiceInstalled); 161 assertTrue("The vibrating service should be installed.", vibratingServiceInstalled); 162 } 163 164 @Test 165 public void testGetEnabledAccessibilityServiceList() throws Exception { 166 SpeakingAccessibilityService.enableSelf(sInstrumentation); 167 VibratingAccessibilityService.enableSelf(sInstrumentation); 168 List<AccessibilityServiceInfo> enabledServices = 169 mAccessibilityManager.getEnabledAccessibilityServiceList( 170 AccessibilityServiceInfo.FEEDBACK_ALL_MASK); 171 boolean speakingServiceEnabled = false; 172 boolean vibratingServiceEnabled = false; 173 final int serviceCount = enabledServices.size(); 174 for (int i = 0; i < serviceCount; i++) { 175 AccessibilityServiceInfo enabledService = enabledServices.get(i); 176 ServiceInfo serviceInfo = enabledService.getResolveInfo().serviceInfo; 177 if (mTargetContext.getPackageName().equals(serviceInfo.packageName) 178 && SPEAKING_ACCESSIBLITY_SERVICE_NAME.equals(serviceInfo.name)) { 179 speakingServiceEnabled = true; 180 } 181 if (mTargetContext.getPackageName().equals(serviceInfo.packageName) 182 && VIBRATING_ACCESSIBLITY_SERVICE_NAME.equals(serviceInfo.name)) { 183 vibratingServiceEnabled = true; 184 } 185 } 186 assertTrue("The speaking service should be enabled.", speakingServiceEnabled); 187 assertTrue("The vibrating service should be enabled.", vibratingServiceEnabled); 188 } 189 190 @Test 191 public void testGetEnabledAccessibilityServiceListForType() throws Exception { 192 SpeakingAccessibilityService.enableSelf(sInstrumentation); 193 VibratingAccessibilityService.enableSelf(sInstrumentation); 194 List<AccessibilityServiceInfo> enabledServices = 195 mAccessibilityManager.getEnabledAccessibilityServiceList( 196 AccessibilityServiceInfo.FEEDBACK_SPOKEN); 197 assertSame("There should be only one enabled speaking service.", 1, enabledServices.size()); 198 final int serviceCount = enabledServices.size(); 199 for (int i = 0; i < serviceCount; i++) { 200 AccessibilityServiceInfo enabledService = enabledServices.get(i); 201 ServiceInfo serviceInfo = enabledService.getResolveInfo().serviceInfo; 202 if (mTargetContext.getPackageName().equals(serviceInfo.packageName) 203 && SPEAKING_ACCESSIBLITY_SERVICE_NAME.equals(serviceInfo.name)) { 204 return; 205 } 206 } 207 fail("The speaking service is not enabled."); 208 } 209 210 @Test 211 public void testGetEnabledAccessibilityServiceListForTypes() throws Exception { 212 SpeakingAccessibilityService.enableSelf(sInstrumentation); 213 VibratingAccessibilityService.enableSelf(sInstrumentation); 214 // For this test, also enable a service with multiple feedback types 215 SpeakingAndVibratingAccessibilityService.enableSelf(sInstrumentation); 216 217 List<AccessibilityServiceInfo> enabledServices = 218 mAccessibilityManager.getEnabledAccessibilityServiceList( 219 AccessibilityServiceInfo.FEEDBACK_SPOKEN 220 | AccessibilityServiceInfo.FEEDBACK_HAPTIC); 221 assertSame("There should be 3 enabled accessibility services.", 3, enabledServices.size()); 222 boolean speakingServiceEnabled = false; 223 boolean vibratingServiceEnabled = false; 224 boolean multipleFeedbackTypesServiceEnabled = false; 225 final int serviceCount = enabledServices.size(); 226 for (int i = 0; i < serviceCount; i++) { 227 AccessibilityServiceInfo enabledService = enabledServices.get(i); 228 ServiceInfo serviceInfo = enabledService.getResolveInfo().serviceInfo; 229 if (mTargetContext.getPackageName().equals(serviceInfo.packageName) 230 && SPEAKING_ACCESSIBLITY_SERVICE_NAME.equals(serviceInfo.name)) { 231 speakingServiceEnabled = true; 232 } 233 if (mTargetContext.getPackageName().equals(serviceInfo.packageName) 234 && VIBRATING_ACCESSIBLITY_SERVICE_NAME.equals(serviceInfo.name)) { 235 vibratingServiceEnabled = true; 236 } 237 if (mTargetContext.getPackageName().equals(serviceInfo.packageName) 238 && MULTIPLE_FEEDBACK_TYPES_ACCESSIBILITY_SERVICE_NAME.equals( 239 serviceInfo.name)) { 240 multipleFeedbackTypesServiceEnabled = true; 241 } 242 } 243 assertTrue("The speaking service should be enabled.", speakingServiceEnabled); 244 assertTrue("The vibrating service should be enabled.", vibratingServiceEnabled); 245 assertTrue("The multiple feedback types service should be enabled.", 246 multipleFeedbackTypesServiceEnabled); 247 } 248 249 @SuppressWarnings("deprecation") 250 @Test 251 public void testGetAccessibilityServiceList() throws Exception { 252 List<ServiceInfo> services = mAccessibilityManager.getAccessibilityServiceList(); 253 boolean speakingServiceInstalled = false; 254 boolean vibratingServiceInstalled = false; 255 final int serviceCount = services.size(); 256 for (int i = 0; i < serviceCount; i++) { 257 ServiceInfo serviceInfo = services.get(i); 258 if (mTargetContext.getPackageName().equals(serviceInfo.packageName) 259 && SPEAKING_ACCESSIBLITY_SERVICE_NAME.equals(serviceInfo.name)) { 260 speakingServiceInstalled = true; 261 } 262 if (mTargetContext.getPackageName().equals(serviceInfo.packageName) 263 && VIBRATING_ACCESSIBLITY_SERVICE_NAME.equals(serviceInfo.name)) { 264 vibratingServiceInstalled = true; 265 } 266 } 267 assertTrue("The speaking service should be installed.", speakingServiceInstalled); 268 assertTrue("The vibrating service should be installed.", vibratingServiceInstalled); 269 } 270 271 @Test 272 public void testInterrupt() throws Exception { 273 // The APIs are heavily tested in the android.accessibilityservice package. 274 // This just makes sure the call does not throw an exception. 275 SpeakingAccessibilityService.enableSelf(sInstrumentation); 276 VibratingAccessibilityService.enableSelf(sInstrumentation); 277 waitForAccessibilityEnabled(); 278 mAccessibilityManager.interrupt(); 279 } 280 281 @Test 282 public void testSendAccessibilityEvent() throws Exception { 283 // The APIs are heavily tested in the android.accessibilityservice package. 284 // This just makes sure the call does not throw an exception. 285 SpeakingAccessibilityService.enableSelf(sInstrumentation); 286 VibratingAccessibilityService.enableSelf(sInstrumentation); 287 waitForAccessibilityEnabled(); 288 mAccessibilityManager.sendAccessibilityEvent(AccessibilityEvent.obtain( 289 AccessibilityEvent.TYPE_VIEW_CLICKED)); 290 } 291 292 @Test 293 public void testTouchExplorationListenerNoHandler() throws Exception { 294 final Object waitObject = new Object(); 295 final AtomicBoolean atomicBoolean = new AtomicBoolean(false); 296 297 TouchExplorationStateChangeListener listener = (boolean b) -> { 298 synchronized (waitObject) { 299 atomicBoolean.set(b); 300 waitObject.notifyAll(); 301 } 302 }; 303 mAccessibilityManager.addTouchExplorationStateChangeListener(listener); 304 SpeakingAccessibilityService.enableSelf(sInstrumentation); 305 VibratingAccessibilityService.enableSelf(sInstrumentation); 306 assertAtomicBooleanBecomes(atomicBoolean, true, waitObject, 307 "Touch exploration state listener not called when services enabled"); 308 assertTrue("Listener told that touch exploration is enabled, but manager says disabled", 309 mAccessibilityManager.isTouchExplorationEnabled()); 310 InstrumentedAccessibilityService.disableAllServices(sInstrumentation); 311 assertAtomicBooleanBecomes(atomicBoolean, false, waitObject, 312 "Touch exploration state listener not called when services disabled"); 313 assertFalse("Listener told that touch exploration is disabled, but manager says it enabled", 314 mAccessibilityManager.isTouchExplorationEnabled()); 315 mAccessibilityManager.removeTouchExplorationStateChangeListener(listener); 316 } 317 318 @Test 319 public void testTouchExplorationListenerWithHandler() throws Exception { 320 final Object waitObject = new Object(); 321 final AtomicBoolean atomicBoolean = new AtomicBoolean(false); 322 323 TouchExplorationStateChangeListener listener = (boolean b) -> { 324 synchronized (waitObject) { 325 atomicBoolean.set(b); 326 waitObject.notifyAll(); 327 } 328 }; 329 mAccessibilityManager.addTouchExplorationStateChangeListener(listener, mHandler); 330 SpeakingAccessibilityService.enableSelf(sInstrumentation); 331 VibratingAccessibilityService.enableSelf(sInstrumentation); 332 assertAtomicBooleanBecomes(atomicBoolean, true, waitObject, 333 "Touch exploration state listener not called when services enabled"); 334 assertTrue("Listener told that touch exploration is enabled, but manager says disabled", 335 mAccessibilityManager.isTouchExplorationEnabled()); 336 InstrumentedAccessibilityService.disableAllServices(sInstrumentation); 337 assertAtomicBooleanBecomes(atomicBoolean, false, waitObject, 338 "Touch exploration state listener not called when services disabled"); 339 assertFalse("Listener told that touch exploration is disabled, but manager says it enabled", 340 mAccessibilityManager.isTouchExplorationEnabled()); 341 mAccessibilityManager.removeTouchExplorationStateChangeListener(listener); 342 } 343 344 @Test 345 public void testAccessibilityStateListenerNoHandler() throws Exception { 346 final Object waitObject = new Object(); 347 final AtomicBoolean atomicBoolean = new AtomicBoolean(false); 348 349 AccessibilityStateChangeListener listener = (boolean b) -> { 350 synchronized (waitObject) { 351 atomicBoolean.set(b); 352 waitObject.notifyAll(); 353 } 354 }; 355 mAccessibilityManager.addAccessibilityStateChangeListener(listener); 356 SpeakingAndVibratingAccessibilityService.enableSelf(sInstrumentation); 357 assertAtomicBooleanBecomes(atomicBoolean, true, waitObject, 358 "Accessibility state listener not called when services enabled"); 359 assertTrue("Listener told that accessibility is enabled, but manager says disabled", 360 mAccessibilityManager.isEnabled()); 361 InstrumentedAccessibilityService.disableAllServices(sInstrumentation); 362 assertAtomicBooleanBecomes(atomicBoolean, false, waitObject, 363 "Accessibility state listener not called when services disabled"); 364 assertFalse("Listener told that accessibility is disabled, but manager says enabled", 365 mAccessibilityManager.isEnabled()); 366 mAccessibilityManager.removeAccessibilityStateChangeListener(listener); 367 } 368 369 @Test 370 public void testAccessibilityStateListenerWithHandler() throws Exception { 371 final Object waitObject = new Object(); 372 final AtomicBoolean atomicBoolean = new AtomicBoolean(false); 373 374 AccessibilityStateChangeListener listener = (boolean b) -> { 375 synchronized (waitObject) { 376 atomicBoolean.set(b); 377 waitObject.notifyAll(); 378 } 379 }; 380 mAccessibilityManager.addAccessibilityStateChangeListener(listener, mHandler); 381 SpeakingAndVibratingAccessibilityService.enableSelf(sInstrumentation); 382 assertAtomicBooleanBecomes(atomicBoolean, true, waitObject, 383 "Accessibility state listener not called when services enabled"); 384 assertTrue("Listener told that accessibility is enabled, but manager says disabled", 385 mAccessibilityManager.isEnabled()); 386 InstrumentedAccessibilityService.disableAllServices(sInstrumentation); 387 assertAtomicBooleanBecomes(atomicBoolean, false, waitObject, 388 "Accessibility state listener not called when services disabled"); 389 assertFalse("Listener told that accessibility is disabled, but manager says enabled", 390 mAccessibilityManager.isEnabled()); 391 mAccessibilityManager.removeAccessibilityStateChangeListener(listener); 392 } 393 394 @Test 395 public void testGetRecommendedTimeoutMillis() throws Exception { 396 SpeakingAccessibilityService.enableSelf(sInstrumentation); 397 VibratingAccessibilityService.enableSelf(sInstrumentation); 398 waitForAccessibilityEnabled(); 399 UiAutomation automan = sInstrumentation.getUiAutomation( 400 UiAutomation.FLAG_DONT_SUPPRESS_ACCESSIBILITY_SERVICES); 401 try { 402 // SpeakingA11yService interactive/nonInteractive timeout is 6000/1000 403 // vibratingA11yService interactive/nonInteractive timeout is 5000/2000 404 turnOffRecommendedUiTimoutSettings(automan); 405 PollingCheck.waitFor(() -> sameRecommendedTimeout(6000, 2000)); 406 turnOnRecommendedUiTimoutSettings(automan, 7000, 0); 407 PollingCheck.waitFor(() -> sameRecommendedTimeout(7000, 2000)); 408 turnOnRecommendedUiTimoutSettings(automan, 0, 4000); 409 PollingCheck.waitFor(() -> sameRecommendedTimeout(6000, 4000)); 410 turnOnRecommendedUiTimoutSettings(automan, 9000, 8000); 411 PollingCheck.waitFor(() -> sameRecommendedTimeout(9000, 8000)); 412 turnOffRecommendedUiTimoutSettings(automan); 413 PollingCheck.waitFor(() -> sameRecommendedTimeout(6000, 2000)); 414 assertEquals("Should return original timeout", 3000, 415 mAccessibilityManager.getRecommendedTimeoutMillis(3000, 416 AccessibilityManager.FLAG_CONTENT_ICONS)); 417 assertEquals("Should return original timeout", 7000, 418 mAccessibilityManager.getRecommendedTimeoutMillis(7000, 419 AccessibilityManager.FLAG_CONTENT_CONTROLS)); 420 } finally { 421 automan.destroy(); 422 } 423 } 424 425 @AppModeFull 426 @Test 427 public void performShortcut_withoutPermission_fails() { 428 UiAutomation uiAutomation = sInstrumentation.getUiAutomation( 429 UiAutomation.FLAG_DONT_SUPPRESS_ACCESSIBILITY_SERVICES); 430 431 String originalShortcut = configureShortcut( 432 uiAutomation, SpeakingAccessibilityService.COMPONENT_NAME.flattenToString()); 433 try { 434 mAccessibilityManager.performAccessibilityShortcut(); 435 fail("No security exception thrown when performing shortcut without permission"); 436 } catch (SecurityException e) { 437 // Expected 438 } finally { 439 configureShortcut(uiAutomation, originalShortcut); 440 uiAutomation.destroy(); 441 } 442 assertTrue(TextUtils.isEmpty(getEnabledServices(mTargetContext.getContentResolver()))); 443 } 444 445 @AppModeFull 446 @Test 447 public void performShortcut_withPermission_succeeds() { 448 UiAutomation uiAutomation = sInstrumentation.getUiAutomation( 449 UiAutomation.FLAG_DONT_SUPPRESS_ACCESSIBILITY_SERVICES); 450 451 String originalShortcut = configureShortcut( 452 uiAutomation, SpeakingAccessibilityService.COMPONENT_NAME.flattenToString()); 453 try { 454 runWithShellPermissionIdentity(uiAutomation, 455 () -> mAccessibilityManager.performAccessibilityShortcut()); 456 // Make sure the service starts up 457 final SpeakingAccessibilityService service = 458 SpeakingAccessibilityService.getInstanceForClass( 459 SpeakingAccessibilityService.class, TIMEOUT_SERVICE_ENABLE); 460 assertTrue("Speaking accessibility service starts up", service != null); 461 } finally { 462 configureShortcut(uiAutomation, originalShortcut); 463 uiAutomation.destroy(); 464 } 465 } 466 467 private String configureShortcut(UiAutomation uiAutomation, String shortcutService) { 468 String currentService = Settings.Secure.getString(mTargetContext.getContentResolver(), 469 Settings.Secure.ACCESSIBILITY_SHORTCUT_TARGET_SERVICE); 470 putSecureSetting(uiAutomation, Settings.Secure.ACCESSIBILITY_SHORTCUT_TARGET_SERVICE, 471 shortcutService); 472 if (shortcutService != null) { 473 runWithShellPermissionIdentity(uiAutomation, () -> 474 waitForConditionWithServiceStateChange(mTargetContext, () -> TextUtils.equals( 475 mAccessibilityManager.getAccessibilityShortcutService(), 476 shortcutService), 477 TIMEOUT_SERVICE_ENABLE, 478 "accessibility shortcut set to test service")); 479 } 480 return currentService; 481 } 482 483 private void assertAtomicBooleanBecomes(AtomicBoolean atomicBoolean, 484 boolean expectedValue, Object waitObject, String message) 485 throws Exception { 486 long timeoutTime = 487 System.currentTimeMillis() + TIMEOUT_SERVICE_ENABLE; 488 synchronized (waitObject) { 489 while ((atomicBoolean.get() != expectedValue) 490 && (System.currentTimeMillis() < timeoutTime)) { 491 waitObject.wait(timeoutTime - System.currentTimeMillis()); 492 } 493 } 494 assertTrue(message, atomicBoolean.get() == expectedValue); 495 } 496 497 private void waitForAccessibilityEnabled() throws InterruptedException { 498 final Object waitObject = new Object(); 499 500 AccessibilityStateChangeListener listener = (boolean b) -> { 501 synchronized (waitObject) { 502 waitObject.notifyAll(); 503 } 504 }; 505 mAccessibilityManager.addAccessibilityStateChangeListener(listener); 506 long timeoutTime = 507 System.currentTimeMillis() + TIMEOUT_SERVICE_ENABLE; 508 synchronized (waitObject) { 509 while (!mAccessibilityManager.isEnabled() 510 && (System.currentTimeMillis() < timeoutTime)) { 511 waitObject.wait(timeoutTime - System.currentTimeMillis()); 512 } 513 } 514 mAccessibilityManager.removeAccessibilityStateChangeListener(listener); 515 assertTrue("Timed out enabling accessibility", mAccessibilityManager.isEnabled()); 516 } 517 518 private void turnOffRecommendedUiTimoutSettings(UiAutomation automan) { 519 putSecureSetting(automan, ACCESSIBILITY_INTERACTIVE_UI_TIMEOUT_MS, null); 520 putSecureSetting(automan, ACCESSIBILITY_NON_INTERACTIVE_UI_TIMEOUT_MS, null); 521 } 522 523 private void turnOnRecommendedUiTimoutSettings(UiAutomation automan, 524 int interactiveUiTimeout, int nonInteractiveUiTimeout) { 525 putSecureSetting(automan, ACCESSIBILITY_INTERACTIVE_UI_TIMEOUT_MS, 526 Integer.toString(interactiveUiTimeout)); 527 putSecureSetting(automan, ACCESSIBILITY_NON_INTERACTIVE_UI_TIMEOUT_MS, 528 Integer.toString(nonInteractiveUiTimeout)); 529 } 530 531 private boolean sameRecommendedTimeout(int interactiveUiTimeout, 532 int nonInteractiveUiTimeout) { 533 final int currentInteractiveUiTimeout = mAccessibilityManager 534 .getRecommendedTimeoutMillis(0, AccessibilityManager.FLAG_CONTENT_CONTROLS); 535 final int currentNonInteractiveUiTimeout = mAccessibilityManager 536 .getRecommendedTimeoutMillis(0, AccessibilityManager.FLAG_CONTENT_ICONS); 537 return (currentInteractiveUiTimeout == interactiveUiTimeout 538 && currentNonInteractiveUiTimeout == nonInteractiveUiTimeout); 539 } 540 541 private void putSecureSetting(UiAutomation automan, String name, String value) { 542 final StringBuilder cmd = new StringBuilder("settings put secure ") 543 .append(name).append(" ") 544 .append(value); 545 try { 546 SystemUtil.runShellCommand(automan, cmd.toString()); 547 } catch (IOException e) { 548 fail("Fail to run shell command"); 549 } 550 } 551 } 552