Home | History | Annotate | Download | only in cts
      1 /*
      2  * Copyright (C) 2016 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.accessibilityservice.cts;
     18 
     19 import android.accessibilityservice.AccessibilityService.MagnificationController;
     20 import android.accessibilityservice.AccessibilityService.MagnificationController.OnMagnificationChangedListener;
     21 import android.accessibilityservice.AccessibilityServiceInfo;
     22 import android.content.res.Resources;
     23 import android.graphics.Region;
     24 import android.provider.Settings;
     25 import android.test.InstrumentationTestCase;
     26 import android.util.DisplayMetrics;
     27 
     28 import java.util.concurrent.atomic.AtomicBoolean;
     29 
     30 import static org.mockito.Mockito.*;
     31 
     32 /**
     33  * Class for testing {@link AccessibilityServiceInfo}.
     34  */
     35 public class AccessibilityMagnificationTest extends InstrumentationTestCase {
     36 
     37     /** Maximum timeout when waiting for a magnification callback. */
     38     public static final int LISTENER_TIMEOUT_MILLIS = 500;
     39     public static final String ACCESSIBILITY_DISPLAY_MAGNIFICATION_ENABLED =
     40             "accessibility_display_magnification_enabled";
     41     private StubMagnificationAccessibilityService mService;
     42 
     43     @Override
     44     public void setUp() throws Exception {
     45         super.setUp();
     46         ShellCommandBuilder.create(this)
     47                 .deleteSecureSetting(ACCESSIBILITY_DISPLAY_MAGNIFICATION_ENABLED)
     48                 .run();
     49         // Starting the service will force the accessibility subsystem to examine its settings, so
     50         // it will update magnification in the process to disable it.
     51         mService = StubMagnificationAccessibilityService.enableSelf(this);
     52     }
     53 
     54     @Override
     55     protected void tearDown() throws Exception {
     56         if (mService != null) {
     57             mService.runOnServiceSync(() -> mService.disableSelfAndRemove());
     58             mService = null;
     59         }
     60 
     61         super.tearDown();
     62     }
     63 
     64     public void testSetScale() {
     65         final MagnificationController controller = mService.getMagnificationController();
     66         final float scale = 2.0f;
     67         final AtomicBoolean result = new AtomicBoolean();
     68 
     69         mService.runOnServiceSync(() -> result.set(controller.setScale(scale, false)));
     70 
     71         assertTrue("Failed to set scale", result.get());
     72         assertEquals("Failed to apply scale", scale, controller.getScale());
     73 
     74         mService.runOnServiceSync(() -> result.set(controller.reset(false)));
     75 
     76         assertTrue("Failed to reset", result.get());
     77         assertEquals("Failed to apply reset", 1.0f, controller.getScale());
     78     }
     79 
     80     public void testSetScaleAndCenter() {
     81         final MagnificationController controller = mService.getMagnificationController();
     82         final Resources res = getInstrumentation().getTargetContext().getResources();
     83         final DisplayMetrics metrics = res.getDisplayMetrics();
     84         final float scale = 2.0f;
     85         final float x = metrics.widthPixels / 4.0f;
     86         final float y = metrics.heightPixels / 4.0f;
     87         final AtomicBoolean setScale = new AtomicBoolean();
     88         final AtomicBoolean setCenter = new AtomicBoolean();
     89         final AtomicBoolean result = new AtomicBoolean();
     90 
     91         mService.runOnServiceSync(() -> {
     92             setScale.set(controller.setScale(scale, false));
     93             setCenter.set(controller.setCenter(x, y, false));
     94         });
     95 
     96         assertTrue("Failed to set scale", setScale.get());
     97         assertEquals("Failed to apply scale", scale, controller.getScale());
     98 
     99         assertTrue("Failed to set center", setCenter.get());
    100         assertEquals("Failed to apply center X", x, controller.getCenterX(), 5.0f);
    101         assertEquals("Failed to apply center Y", y, controller.getCenterY(), 5.0f);
    102 
    103         mService.runOnServiceSync(() -> result.set(controller.reset(false)));
    104 
    105         assertTrue("Failed to reset", result.get());
    106         assertEquals("Failed to apply reset", 1.0f, controller.getScale());
    107     }
    108 
    109     public void testListener() {
    110         final MagnificationController controller = mService.getMagnificationController();
    111         final OnMagnificationChangedListener listener = mock(OnMagnificationChangedListener.class);
    112         controller.addListener(listener);
    113 
    114         try {
    115             final float scale = 2.0f;
    116             final AtomicBoolean result = new AtomicBoolean();
    117 
    118             mService.runOnServiceSync(() -> result.set(controller.setScale(scale, false)));
    119 
    120             assertTrue("Failed to set scale", result.get());
    121             verify(listener, timeout(LISTENER_TIMEOUT_MILLIS).atLeastOnce()).onMagnificationChanged(
    122                     eq(controller), any(Region.class), eq(scale), anyFloat(), anyFloat());
    123 
    124             mService.runOnServiceSync(() -> result.set(controller.reset(false)));
    125 
    126             assertTrue("Failed to reset", result.get());
    127             verify(listener, timeout(LISTENER_TIMEOUT_MILLIS).atLeastOnce()).onMagnificationChanged(
    128                     eq(controller), any(Region.class), eq(1.0f), anyFloat(), anyFloat());
    129         } finally {
    130             controller.removeListener(listener);
    131         }
    132     }
    133 
    134     public void testMagnificationServiceShutsDownWhileMagnifying_shouldReturnTo1x() {
    135         final MagnificationController controller = mService.getMagnificationController();
    136         mService.runOnServiceSync(() -> controller.setScale(2.0f, false));
    137 
    138         mService.runOnServiceSync(() -> mService.disableSelf());
    139         mService = null;
    140         InstrumentedAccessibilityService service = InstrumentedAccessibilityService.enableService(
    141                 this, InstrumentedAccessibilityService.class);
    142         final MagnificationController controller2 = service.getMagnificationController();
    143         try {
    144             assertEquals("Magnification must reset when a service dies",
    145                     1.0f, controller2.getScale());
    146         } finally {
    147             service.runOnServiceSync(() -> service.disableSelf());
    148         }
    149     }
    150 
    151     public void testGetMagnificationRegion_whenCanControlMagnification_shouldNotBeEmpty() {
    152         final MagnificationController controller = mService.getMagnificationController();
    153         Region magnificationRegion = controller.getMagnificationRegion();
    154         assertFalse("Magnification region should not be empty when "
    155                  + "magnification is being actively controlled", magnificationRegion.isEmpty());
    156     }
    157 
    158     public void testGetMagnificationRegion_whenCantControlMagnification_shouldBeEmpty() {
    159         mService.runOnServiceSync(() -> mService.disableSelf());
    160         mService = null;
    161         InstrumentedAccessibilityService service = InstrumentedAccessibilityService.enableService(
    162                 this, InstrumentedAccessibilityService.class);
    163         try {
    164             final MagnificationController controller = service.getMagnificationController();
    165             Region magnificationRegion = controller.getMagnificationRegion();
    166             assertTrue("Magnification region should be empty when magnification "
    167                     + "is not being actively controlled", magnificationRegion.isEmpty());
    168         } finally {
    169             service.runOnServiceSync(() -> service.disableSelf());
    170         }
    171     }
    172 
    173     public void testGetMagnificationRegion_whenMagnificationGesturesEnabled_shouldNotBeEmpty() {
    174         ShellCommandBuilder.create(this)
    175                 .putSecureSetting(ACCESSIBILITY_DISPLAY_MAGNIFICATION_ENABLED, "1")
    176                 .run();
    177         mService.runOnServiceSync(() -> mService.disableSelf());
    178         mService = null;
    179         InstrumentedAccessibilityService service = InstrumentedAccessibilityService.enableService(
    180                 this, InstrumentedAccessibilityService.class);
    181         try {
    182             final MagnificationController controller = service.getMagnificationController();
    183             Region magnificationRegion = controller.getMagnificationRegion();
    184             assertFalse("Magnification region should not be empty when magnification "
    185                     + "gestures are active", magnificationRegion.isEmpty());
    186         } finally {
    187             service.runOnServiceSync(() -> service.disableSelf());
    188             ShellCommandBuilder.create(this)
    189                     .deleteSecureSetting(ACCESSIBILITY_DISPLAY_MAGNIFICATION_ENABLED)
    190                     .run();
    191         }
    192     }
    193 
    194     public void testAnimatingMagnification() throws InterruptedException {
    195         final MagnificationController controller = mService.getMagnificationController();
    196         final int timeBetweenAnimationChanges = 100;
    197 
    198         final float scale1 = 5.0f;
    199         final float x1 = 500;
    200         final float y1 = 1000;
    201 
    202         final float scale2 = 4.0f;
    203         final float x2 = 500;
    204         final float y2 = 1500;
    205 
    206         final float scale3 = 2.1f;
    207         final float x3 = 700;
    208         final float y3 = 700;
    209 
    210         for (int i = 0; i < 5; i++) {
    211             mService.runOnServiceSync(() -> {
    212                 controller.setScale(scale1, true);
    213                 controller.setCenter(x1, y1, true);
    214             });
    215 
    216             Thread.sleep(timeBetweenAnimationChanges);
    217 
    218             mService.runOnServiceSync(() -> {
    219                 controller.setScale(scale2, true);
    220                 controller.setCenter(x2, y2, true);
    221             });
    222 
    223             Thread.sleep(timeBetweenAnimationChanges);
    224 
    225             mService.runOnServiceSync(() -> {
    226                 controller.setScale(scale3, true);
    227                 controller.setCenter(x3, y3, true);
    228             });
    229 
    230             Thread.sleep(timeBetweenAnimationChanges);
    231         }
    232     }
    233 }
    234