Home | History | Annotate | Download | only in cts
      1 /*
      2  * Copyright (C) 2014 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.app.uiautomation.cts;
     18 
     19 import static org.junit.Assert.assertEquals;
     20 import static org.junit.Assert.assertFalse;
     21 import static org.junit.Assert.assertNotNull;
     22 import static org.junit.Assert.assertSame;
     23 import static org.junit.Assert.assertTrue;
     24 import static org.junit.Assert.fail;
     25 
     26 import android.Manifest;
     27 import android.accessibilityservice.AccessibilityServiceInfo;
     28 import android.app.Activity;
     29 import android.app.ActivityManager;
     30 import android.app.Instrumentation;
     31 import android.app.UiAutomation;
     32 import android.content.ContentResolver;
     33 import android.content.Context;
     34 import android.content.Intent;
     35 import android.content.pm.PackageManager;
     36 import android.os.Process;
     37 import android.os.SystemClock;
     38 import android.platform.test.annotations.AppModeFull;
     39 import android.platform.test.annotations.Presubmit;
     40 import android.provider.Settings;
     41 import android.view.FrameStats;
     42 import android.view.WindowAnimationFrameStats;
     43 import android.view.WindowContentFrameStats;
     44 import android.view.accessibility.AccessibilityEvent;
     45 import android.view.accessibility.AccessibilityManager;
     46 import android.view.accessibility.AccessibilityWindowInfo;
     47 import android.widget.ListView;
     48 
     49 import androidx.test.InstrumentationRegistry;
     50 import androidx.test.runner.AndroidJUnit4;
     51 
     52 import org.junit.Before;
     53 import org.junit.Rule;
     54 import org.junit.Test;
     55 import org.junit.runner.RunWith;
     56 
     57 import java.util.List;
     58 import java.util.concurrent.TimeoutException;
     59 
     60 /**
     61  * Tests for the UiAutomation APIs.
     62  */
     63 @RunWith(AndroidJUnit4.class)
     64 public class UiAutomationTest {
     65     private static final long QUIET_TIME_TO_BE_CONSIDERED_IDLE_STATE = 1000;//ms
     66 
     67     private static final long TOTAL_TIME_TO_WAIT_FOR_IDLE_STATE = 1000 * 10;//ms
     68 
     69     // Used to enable/disable accessibility services
     70     private static final String COMPONENT_NAME_SEPARATOR = ":";
     71     private static final int TIMEOUT_FOR_SERVICE_ENABLE = 10000; // millis; 10s
     72 
     73     @Rule
     74     public final UiAutomationLogRule mLogRule = new UiAutomationLogRule(
     75             UiAutomationTest.class.getSimpleName());
     76 
     77     @Before
     78     public void setUp() throws Exception {
     79         UiAutomation uiAutomation = getInstrumentation().getUiAutomation();
     80         AccessibilityServiceInfo info = uiAutomation.getServiceInfo();
     81         info.flags |= AccessibilityServiceInfo.FLAG_RETRIEVE_INTERACTIVE_WINDOWS;
     82         uiAutomation.setServiceInfo(info);
     83         grantWriteSecureSettingsPermission(uiAutomation);
     84     }
     85 
     86     @AppModeFull
     87     @Test
     88     public void testAdoptAllShellPermissions() {
     89         final Context context = getInstrumentation().getContext();
     90         final ActivityManager activityManager = context.getSystemService(ActivityManager.class);
     91         final PackageManager packageManager = context.getPackageManager();
     92 
     93         // Try to access APIs guarded by a platform defined signature permissions
     94         try {
     95             activityManager.getPackageImportance("foo.bar.baz");
     96             fail("Should not be able to access APIs protected by a permission apps cannot get");
     97         } catch (SecurityException e) {
     98             /* expected */
     99         }
    100         try {
    101             packageManager.grantRuntimePermission(context.getPackageName(),
    102                     Manifest.permission.CAMERA, Process.myUserHandle());
    103             fail("Should not be able to access APIs protected by a permission apps cannot get");
    104         } catch (SecurityException e) {
    105             /* expected */
    106         }
    107 
    108         // Access APIs guarded by a platform defined signature permissions
    109         try {
    110             getInstrumentation().getUiAutomation().adoptShellPermissionIdentity();
    111 
    112             // Access APIs guarded by a platform defined signature permission
    113             activityManager.getPackageImportance("foo.bar.baz");
    114 
    115             // Grant ourselves a runtime permission (was granted at install)
    116             assertSame(packageManager.checkPermission(Manifest.permission.CAMERA,
    117                     context.getPackageName()), PackageManager.PERMISSION_DENIED);
    118             packageManager.grantRuntimePermission(context.getPackageName(),
    119                     Manifest.permission.CAMERA, Process.myUserHandle());
    120         } catch (SecurityException e) {
    121             fail("Should be able to access APIs protected by a permission apps cannot get");
    122         } finally {
    123             getInstrumentation().getUiAutomation().dropShellPermissionIdentity();
    124         }
    125         // Make sure the grant worked
    126         assertSame(packageManager.checkPermission(Manifest.permission.CAMERA,
    127                 context.getPackageName()), PackageManager.PERMISSION_GRANTED);
    128 
    129 
    130         // Try to access APIs guarded by a platform defined signature permissions
    131         try {
    132             activityManager.getPackageImportance("foo.bar.baz");
    133             fail("Should not be able to access APIs protected by a permission apps cannot get");
    134         } catch (SecurityException e) {
    135             /* expected */
    136         }
    137         try {
    138             packageManager.revokeRuntimePermission(context.getPackageName(),
    139                     Manifest.permission.CAMERA, Process.myUserHandle());
    140             fail("Should not be able to access APIs protected by a permission apps cannot get");
    141         } catch (SecurityException e) {
    142             /* expected */
    143         }
    144     }
    145 
    146     @AppModeFull
    147     @Test
    148     public void testAdoptSomeShellPermissions() {
    149         final Context context = getInstrumentation().getContext();
    150 
    151         // Make sure we don't have any of the permissions
    152         assertSame(PackageManager.PERMISSION_DENIED, context.checkSelfPermission(
    153                 Manifest.permission.BATTERY_STATS));
    154         assertSame(PackageManager.PERMISSION_DENIED, context.checkSelfPermission(
    155                 Manifest.permission.PACKAGE_USAGE_STATS));
    156 
    157         try {
    158             // Adopt a permission
    159             getInstrumentation().getUiAutomation().adoptShellPermissionIdentity(
    160                     Manifest.permission.BATTERY_STATS);
    161             // Check one is granted and the other not
    162             assertSame(PackageManager.PERMISSION_GRANTED, context.checkSelfPermission(
    163                     Manifest.permission.BATTERY_STATS));
    164             assertSame(PackageManager.PERMISSION_DENIED, context.checkSelfPermission(
    165                     Manifest.permission.PACKAGE_USAGE_STATS));
    166 
    167             // Adopt all permissions
    168             getInstrumentation().getUiAutomation().adoptShellPermissionIdentity();
    169             // Check both permissions are granted
    170             assertSame(PackageManager.PERMISSION_GRANTED, context.checkSelfPermission(
    171                     Manifest.permission.BATTERY_STATS));
    172             assertSame(PackageManager.PERMISSION_GRANTED, context.checkSelfPermission(
    173                     Manifest.permission.PACKAGE_USAGE_STATS));
    174 
    175             // Adopt a permission
    176             getInstrumentation().getUiAutomation().adoptShellPermissionIdentity(
    177                     Manifest.permission.PACKAGE_USAGE_STATS);
    178             // Check one is granted and the other not
    179             assertSame(PackageManager.PERMISSION_DENIED, context.checkSelfPermission(
    180                     Manifest.permission.BATTERY_STATS));
    181             assertSame(PackageManager.PERMISSION_GRANTED, context.checkSelfPermission(
    182                     Manifest.permission.PACKAGE_USAGE_STATS));
    183         } finally {
    184             getInstrumentation().getUiAutomation().dropShellPermissionIdentity();
    185         }
    186     }
    187 
    188     @Test
    189     public void testWindowContentFrameStats() throws Exception {
    190         Activity activity = null;
    191         try {
    192             UiAutomation uiAutomation = getInstrumentation().getUiAutomation();
    193 
    194             // Start an activity.
    195             Intent intent = new Intent(getInstrumentation().getContext(),
    196                     UiAutomationTestFirstActivity.class);
    197             intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
    198             activity = getInstrumentation().startActivitySync(intent);
    199 
    200             // Wait for things to settle.
    201             uiAutomation.waitForIdle(
    202                     QUIET_TIME_TO_BE_CONSIDERED_IDLE_STATE, TOTAL_TIME_TO_WAIT_FOR_IDLE_STATE);
    203 
    204             // Wait for Activity draw finish
    205             getInstrumentation().waitForIdleSync();
    206 
    207             // Find the application window.
    208             final int windowId = findAppWindowId(uiAutomation.getWindows());
    209             assertTrue(windowId >= 0);
    210 
    211             // Clear stats to be with a clean slate.
    212             assertTrue(uiAutomation.clearWindowContentFrameStats(windowId));
    213 
    214             // Find the list to scroll around.
    215             final ListView listView = (ListView) activity.findViewById(R.id.list_view);
    216 
    217             // Scroll a bit.
    218             scrollListView(uiAutomation, listView, listView.getAdapter().getCount() - 1);
    219             scrollListView(uiAutomation, listView, 0);
    220 
    221             // Get the frame stats.
    222             WindowContentFrameStats stats = uiAutomation.getWindowContentFrameStats(windowId);
    223 
    224             // Check the frame stats...
    225 
    226             // We should have something.
    227             assertNotNull(stats);
    228 
    229             // The refresh period is always positive.
    230             assertTrue(stats.getRefreshPeriodNano() > 0);
    231 
    232             // There is some frame data.
    233             final int frameCount = stats.getFrameCount();
    234             assertTrue(frameCount > 0);
    235 
    236             // The frames are ordered in ascending order.
    237             assertWindowContentTimestampsInAscendingOrder(stats);
    238 
    239             // The start and end times are based on first and last frame.
    240             assertEquals(stats.getStartTimeNano(), stats.getFramePresentedTimeNano(0));
    241             assertEquals(stats.getEndTimeNano(), stats.getFramePresentedTimeNano(frameCount - 1));
    242         } finally {
    243             // Clean up.
    244             if (activity != null) {
    245                 activity.finish();
    246             }
    247         }
    248     }
    249 
    250     @Test
    251     public void testWindowContentFrameStatsNoAnimation() throws Exception {
    252         Activity activity = null;
    253         try {
    254             UiAutomation uiAutomation = getInstrumentation().getUiAutomation();
    255 
    256             // Start an activity.
    257             Intent intent = new Intent(getInstrumentation().getContext(),
    258                     UiAutomationTestFirstActivity.class);
    259             intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
    260             activity = getInstrumentation().startActivitySync(intent);
    261 
    262             // Wait for things to settle.
    263             uiAutomation.waitForIdle(
    264                     QUIET_TIME_TO_BE_CONSIDERED_IDLE_STATE, TOTAL_TIME_TO_WAIT_FOR_IDLE_STATE);
    265 
    266             // Wait for Activity draw finish
    267             getInstrumentation().waitForIdleSync();
    268 
    269             // Find the application window.
    270             final int windowId = findAppWindowId(uiAutomation.getWindows());
    271             assertTrue(windowId >= 0);
    272 
    273             // Clear stats to be with a clean slate.
    274             assertTrue(uiAutomation.clearWindowContentFrameStats(windowId));
    275 
    276             // Get the frame stats.
    277             WindowContentFrameStats stats = uiAutomation.getWindowContentFrameStats(windowId);
    278 
    279             // Check the frame stats...
    280 
    281             // We should have something.
    282             assertNotNull(stats);
    283 
    284             // The refresh period is always positive.
    285             assertTrue(stats.getRefreshPeriodNano() > 0);
    286 
    287             // There is no data.
    288             assertTrue(stats.getFrameCount() == 0);
    289 
    290             // The start and end times are undefibed as we have no data.
    291             assertEquals(stats.getStartTimeNano(), FrameStats.UNDEFINED_TIME_NANO);
    292             assertEquals(stats.getEndTimeNano(), FrameStats.UNDEFINED_TIME_NANO);
    293         } finally {
    294             // Clean up.
    295             if (activity != null) {
    296                 activity.finish();
    297             }
    298         }
    299     }
    300 
    301     @Presubmit
    302     @Test
    303     public void testWindowAnimationFrameStats() throws Exception {
    304         Activity firstActivity = null;
    305         Activity secondActivity = null;
    306         try {
    307             UiAutomation uiAutomation = getInstrumentation().getUiAutomation();
    308 
    309             // Start the frist activity.
    310             Intent firstIntent = new Intent(getInstrumentation().getContext(),
    311                     UiAutomationTestFirstActivity.class);
    312             firstIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
    313             firstActivity = getInstrumentation().startActivitySync(firstIntent);
    314 
    315             // Wait for things to settle.
    316             uiAutomation.waitForIdle(
    317                     QUIET_TIME_TO_BE_CONSIDERED_IDLE_STATE, TOTAL_TIME_TO_WAIT_FOR_IDLE_STATE);
    318 
    319             // Wait for Activity draw finish
    320             getInstrumentation().waitForIdleSync();
    321 
    322             // Clear the window animation stats to be with a clean slate.
    323             uiAutomation.clearWindowAnimationFrameStats();
    324 
    325             // Start the second activity
    326             Intent secondIntent = new Intent(getInstrumentation().getContext(),
    327                     UiAutomationTestSecondActivity.class);
    328             secondIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
    329             secondActivity = getInstrumentation().startActivitySync(secondIntent);
    330 
    331             // Wait for things to settle.
    332             uiAutomation.waitForIdle(
    333                     QUIET_TIME_TO_BE_CONSIDERED_IDLE_STATE, TOTAL_TIME_TO_WAIT_FOR_IDLE_STATE);
    334 
    335             // Wait for Activity draw finish
    336             getInstrumentation().waitForIdleSync();
    337 
    338             // Get the frame stats.
    339             WindowAnimationFrameStats stats = uiAutomation.getWindowAnimationFrameStats();
    340 
    341             // Check the frame stats...
    342 
    343             // We should have something.
    344             assertNotNull(stats);
    345 
    346             // The refresh presiod is always positive.
    347             assertTrue(stats.getRefreshPeriodNano() > 0);
    348 
    349             // There is some frame data.
    350             final int frameCount = stats.getFrameCount();
    351             assertTrue(frameCount > 0);
    352 
    353             // The frames are ordered in ascending order.
    354             assertWindowAnimationTimestampsInAscendingOrder(stats);
    355 
    356             // The start and end times are based on first and last frame.
    357             assertEquals(stats.getStartTimeNano(), stats.getFramePresentedTimeNano(0));
    358             assertEquals(stats.getEndTimeNano(), stats.getFramePresentedTimeNano(frameCount - 1));
    359         } finally {
    360             // Clean up.
    361             if (firstActivity != null) {
    362                 firstActivity.finish();
    363             }
    364             if (secondActivity != null) {
    365                 secondActivity.finish();
    366             }
    367         }
    368     }
    369 
    370     @Test
    371     public void testWindowAnimationFrameStatsNoAnimation() throws Exception {
    372         UiAutomation uiAutomation = getInstrumentation().getUiAutomation();
    373 
    374         // Wait for things to settle.
    375         uiAutomation.waitForIdle(
    376                 QUIET_TIME_TO_BE_CONSIDERED_IDLE_STATE, TOTAL_TIME_TO_WAIT_FOR_IDLE_STATE);
    377 
    378         // Clear the window animation stats to be with a clean slate.
    379         uiAutomation.clearWindowAnimationFrameStats();
    380 
    381         // Get the frame stats.
    382         WindowAnimationFrameStats stats = uiAutomation.getWindowAnimationFrameStats();
    383 
    384         // Check the frame stats...
    385 
    386         // We should have something.
    387         assertNotNull(stats);
    388 
    389         // The refresh presiod is always positive.
    390         assertTrue(stats.getRefreshPeriodNano() > 0);
    391 
    392         // There is no data.
    393         assertTrue(stats.getFrameCount() == 0);
    394 
    395         // The start and end times are undefibed as we have no data.
    396         assertEquals(stats.getStartTimeNano(), FrameStats.UNDEFINED_TIME_NANO);
    397         assertEquals(stats.getEndTimeNano(), FrameStats.UNDEFINED_TIME_NANO);
    398     }
    399 
    400     @Presubmit
    401     @Test
    402     public void testUsingUiAutomationAfterDestroy_shouldThrowException() {
    403         UiAutomation uiAutomation = getInstrumentation().getUiAutomation();
    404         uiAutomation.destroy();
    405         try {
    406             uiAutomation.getServiceInfo();
    407             fail("Expected exception when using destroyed UiAutomation");
    408         } catch (RuntimeException e) {
    409         }
    410     }
    411 
    412     @AppModeFull
    413     @Test
    414     public void testDontSuppressAccessibility_canStartA11yService() throws Exception {
    415         turnAccessibilityOff();
    416         try {
    417             getInstrumentation()
    418                     .getUiAutomation(UiAutomation.FLAG_DONT_SUPPRESS_ACCESSIBILITY_SERVICES);
    419             enableAccessibilityService();
    420             assertTrue(UiAutomationTestA11yService.sConnectedInstance.isConnected());
    421         } finally {
    422             turnAccessibilityOff();
    423         }
    424     }
    425 
    426     @AppModeFull
    427     @Test
    428     public void testServiceWithNoFlags_shutsDownA11yService() throws Exception {
    429         turnAccessibilityOff();
    430         try {
    431             UiAutomation uiAutomation = getInstrumentation()
    432                     .getUiAutomation(UiAutomation.FLAG_DONT_SUPPRESS_ACCESSIBILITY_SERVICES);
    433             enableAccessibilityService();
    434             assertTrue(UiAutomationTestA11yService.sConnectedInstance.isConnected());
    435             uiAutomation.destroy();
    436             assertTrue(UiAutomationTestA11yService.sConnectedInstance.isConnected());
    437             getInstrumentation().getUiAutomation(); // Should suppress
    438             waitForAccessibilityServiceToUnbind();
    439         } finally {
    440             turnAccessibilityOff();
    441         }
    442     }
    443 
    444     @AppModeFull
    445     @Test
    446     public void testServiceSupressingA11yServices_a11yServiceStartsWhenDestroyed()
    447             throws Exception {
    448         turnAccessibilityOff();
    449         try {
    450             UiAutomation uiAutomation = getInstrumentation()
    451                     .getUiAutomation(UiAutomation.FLAG_DONT_SUPPRESS_ACCESSIBILITY_SERVICES);
    452             enableAccessibilityService();
    453             uiAutomation.destroy();
    454             UiAutomation suppressingUiAutomation = getInstrumentation().getUiAutomation();
    455             // We verify above that the connection is broken here. Make sure we see a new one
    456             // after we destroy it
    457             waitForAccessibilityServiceToUnbind();
    458             suppressingUiAutomation.destroy();
    459             waitForAccessibilityServiceToStart();
    460         } finally {
    461             turnAccessibilityOff();
    462         }
    463     }
    464 
    465     @AppModeFull
    466     @Test
    467     public void testServiceSupressingA11yServices_a11yServiceStartsWhenFlagsChange()
    468             throws Exception {
    469         turnAccessibilityOff();
    470         try {
    471             getInstrumentation()
    472                     .getUiAutomation(UiAutomation.FLAG_DONT_SUPPRESS_ACCESSIBILITY_SERVICES);
    473             enableAccessibilityService();
    474             getInstrumentation().getUiAutomation();
    475             // We verify above that the connection is broken here. Make sure we see a new one
    476             // after we change the flags
    477             waitForAccessibilityServiceToUnbind();
    478             getInstrumentation()
    479                     .getUiAutomation(UiAutomation.FLAG_DONT_SUPPRESS_ACCESSIBILITY_SERVICES);
    480             waitForAccessibilityServiceToStart();
    481         } finally {
    482             turnAccessibilityOff();
    483         }
    484     }
    485 
    486     private void scrollListView(UiAutomation uiAutomation, final ListView listView,
    487             final int position) throws TimeoutException {
    488         getInstrumentation().runOnMainSync(new Runnable() {
    489             @Override
    490             public void run() {
    491                 listView.smoothScrollToPosition(position);
    492             }
    493         });
    494         Runnable emptyRunnable = new Runnable() {
    495             @Override
    496             public void run() {
    497             }
    498         };
    499         UiAutomation.AccessibilityEventFilter scrollFilter =
    500                 new UiAutomation.AccessibilityEventFilter() {
    501                     @Override
    502                     public boolean accept(AccessibilityEvent accessibilityEvent) {
    503                         return accessibilityEvent.getEventType()
    504                                 == AccessibilityEvent.TYPE_VIEW_SCROLLED;
    505                     }
    506                 };
    507         uiAutomation.executeAndWaitForEvent(emptyRunnable, scrollFilter,
    508                 TOTAL_TIME_TO_WAIT_FOR_IDLE_STATE);
    509         uiAutomation.waitForIdle(
    510                 QUIET_TIME_TO_BE_CONSIDERED_IDLE_STATE, TOTAL_TIME_TO_WAIT_FOR_IDLE_STATE);
    511     }
    512 
    513     private void grantWriteSecureSettingsPermission(UiAutomation uiAutomation) {
    514         uiAutomation.grantRuntimePermission(getInstrumentation().getContext().getPackageName(),
    515                 android.Manifest.permission.WRITE_SECURE_SETTINGS);
    516     }
    517 
    518     private void enableAccessibilityService() {
    519         Context context = getInstrumentation().getContext();
    520         AccessibilityManager manager =
    521                 (AccessibilityManager) context.getSystemService(Context.ACCESSIBILITY_SERVICE);
    522         List<AccessibilityServiceInfo> serviceInfos =
    523                 manager.getInstalledAccessibilityServiceList();
    524         for (int i = 0; i < serviceInfos.size(); i++) {
    525             AccessibilityServiceInfo serviceInfo = serviceInfos.get(i);
    526             if (context.getString(R.string.uiautomation_a11y_service_description)
    527                     .equals(serviceInfo.getDescription())) {
    528                 ContentResolver cr = context.getContentResolver();
    529                 String enabledServices = Settings.Secure.getString(cr,
    530                         Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES);
    531                 Settings.Secure.putString(cr, Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES,
    532                         enabledServices + COMPONENT_NAME_SEPARATOR + serviceInfo.getId());
    533                 Settings.Secure.putInt(cr, Settings.Secure.ACCESSIBILITY_ENABLED, 1);
    534                 waitForAccessibilityServiceToStart();
    535                 return;
    536             }
    537         }
    538         throw new RuntimeException("Test accessibility service not found");
    539     }
    540 
    541     private void waitForAccessibilityServiceToStart() {
    542         long timeoutTimeMillis = SystemClock.uptimeMillis() + TIMEOUT_FOR_SERVICE_ENABLE;
    543         while (SystemClock.uptimeMillis() < timeoutTimeMillis) {
    544             synchronized(UiAutomationTestA11yService.sWaitObjectForConnectOrUnbind) {
    545                 if (UiAutomationTestA11yService.sConnectedInstance != null) {
    546                     return;
    547                 }
    548                 try {
    549                     UiAutomationTestA11yService.sWaitObjectForConnectOrUnbind.wait(
    550                             timeoutTimeMillis - SystemClock.uptimeMillis());
    551                 } catch (InterruptedException e) {
    552                     // Ignored; loop again
    553                 }
    554             }
    555         }
    556         throw new RuntimeException("Test accessibility service not starting");
    557     }
    558 
    559     private void waitForAccessibilityServiceToUnbind() {
    560         long timeoutTimeMillis = SystemClock.uptimeMillis() + TIMEOUT_FOR_SERVICE_ENABLE;
    561         while (SystemClock.uptimeMillis() < timeoutTimeMillis) {
    562             synchronized(UiAutomationTestA11yService.sWaitObjectForConnectOrUnbind) {
    563                 if (UiAutomationTestA11yService.sConnectedInstance == null) {
    564                     return;
    565                 }
    566                 try {
    567                     UiAutomationTestA11yService.sWaitObjectForConnectOrUnbind.wait(
    568                             timeoutTimeMillis - SystemClock.uptimeMillis());
    569                 } catch (InterruptedException e) {
    570                     // Ignored; loop again
    571                 }
    572             }
    573         }
    574         throw new RuntimeException("Test accessibility service doesn't unbind");
    575     }
    576 
    577     private void turnAccessibilityOff() {
    578         getInstrumentation().getUiAutomation().destroy();
    579         final Object waitLockForA11yOff = new Object();
    580         Context context = getInstrumentation().getContext();
    581         AccessibilityManager manager =
    582                 (AccessibilityManager) context.getSystemService(Context.ACCESSIBILITY_SERVICE);
    583         manager.addAccessibilityStateChangeListener(
    584                 new AccessibilityManager.AccessibilityStateChangeListener() {
    585                     @Override
    586                     public void onAccessibilityStateChanged(boolean b) {
    587                         synchronized (waitLockForA11yOff) {
    588                             waitLockForA11yOff.notifyAll();
    589                         }
    590                     }
    591                 });
    592         ContentResolver cr = context.getContentResolver();
    593         Settings.Secure.putString(
    594                 cr, Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES, null);
    595         long timeoutTimeMillis = SystemClock.uptimeMillis() + TIMEOUT_FOR_SERVICE_ENABLE;
    596         while (SystemClock.uptimeMillis() < timeoutTimeMillis) {
    597             synchronized (waitLockForA11yOff) {
    598                 if (!manager.isEnabled()) {
    599                     return;
    600                 }
    601                 try {
    602                     waitLockForA11yOff.wait(timeoutTimeMillis - SystemClock.uptimeMillis());
    603                 } catch (InterruptedException e) {
    604                     // Ignored; loop again
    605                 }
    606             }
    607         }
    608         throw new RuntimeException("Unable to turn accessibility off");
    609     }
    610 
    611     private void assertWindowContentTimestampsInAscendingOrder(WindowContentFrameStats stats) {
    612         long lastExpectedTimeNano = 0;
    613         long lastPresentedTimeNano = 0;
    614         long lastPreparedTimeNano = 0;
    615 
    616         final int frameCount = stats.getFrameCount();
    617         for (int i = 0; i < frameCount; i++) {
    618             final long expectedTimeNano = stats.getFramePostedTimeNano(i);
    619             assertTrue(expectedTimeNano >= lastExpectedTimeNano);
    620             lastExpectedTimeNano = expectedTimeNano;
    621 
    622             final long presentedTimeNano = stats.getFramePresentedTimeNano(i);
    623             if (lastPresentedTimeNano == FrameStats.UNDEFINED_TIME_NANO) {
    624                 assertTrue(presentedTimeNano == FrameStats.UNDEFINED_TIME_NANO);
    625             } else if (presentedTimeNano != FrameStats.UNDEFINED_TIME_NANO) {
    626                 assertTrue(presentedTimeNano >= lastPresentedTimeNano);
    627             }
    628             lastPresentedTimeNano = presentedTimeNano;
    629 
    630             final long preparedTimeNano = stats.getFrameReadyTimeNano(i);
    631             if (lastPreparedTimeNano == FrameStats.UNDEFINED_TIME_NANO) {
    632                 assertTrue(preparedTimeNano == FrameStats.UNDEFINED_TIME_NANO);
    633             } else if (preparedTimeNano != FrameStats.UNDEFINED_TIME_NANO) {
    634                 assertTrue(preparedTimeNano >= lastPreparedTimeNano);
    635             }
    636             lastPreparedTimeNano = preparedTimeNano;
    637         }
    638     }
    639 
    640     private void assertWindowAnimationTimestampsInAscendingOrder(WindowAnimationFrameStats stats) {
    641         long lastPresentedTimeNano = 0;
    642 
    643         final int frameCount = stats.getFrameCount();
    644         for (int i = 0; i < frameCount; i++) {
    645             final long presentedTimeNano = stats.getFramePresentedTimeNano(i);
    646             if (lastPresentedTimeNano == FrameStats.UNDEFINED_TIME_NANO) {
    647                 assertTrue(presentedTimeNano == FrameStats.UNDEFINED_TIME_NANO);
    648             } else if (presentedTimeNano != FrameStats.UNDEFINED_TIME_NANO) {
    649                 assertTrue(presentedTimeNano >= lastPresentedTimeNano);
    650             }
    651             lastPresentedTimeNano = presentedTimeNano;
    652         }
    653     }
    654 
    655     private int findAppWindowId(List<AccessibilityWindowInfo> windows) {
    656         final int windowCount = windows.size();
    657         for (int i = 0; i < windowCount; i++) {
    658             AccessibilityWindowInfo window = windows.get(i);
    659             if (window.getType() == AccessibilityWindowInfo.TYPE_APPLICATION) {
    660                 return window.getId();
    661             }
    662         }
    663         return -1;
    664     }
    665 
    666     private Instrumentation getInstrumentation() {
    667         return InstrumentationRegistry.getInstrumentation();
    668     }
    669 }
    670