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