Home | History | Annotate | Download | only in wm
      1 /*
      2  * Copyright (C) 2017 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 com.android.server.wm;
     18 
     19 import static org.junit.Assert.assertEquals;
     20 import static org.junit.Assert.assertNotNull;
     21 import static org.mockito.ArgumentMatchers.any;
     22 import static org.mockito.ArgumentMatchers.anyBoolean;
     23 import static org.mockito.Mockito.mock;
     24 import static org.mockito.Mockito.never;
     25 import static org.mockito.Mockito.reset;
     26 import static org.mockito.Mockito.spy;
     27 import static org.mockito.Mockito.times;
     28 import static org.mockito.Mockito.verify;
     29 
     30 import android.graphics.Rect;
     31 import android.platform.test.annotations.Presubmit;
     32 import android.support.test.runner.AndroidJUnit4;
     33 import android.view.SurfaceControl;
     34 import android.view.SurfaceSession;
     35 
     36 import org.junit.Before;
     37 import org.junit.Test;
     38 import org.junit.runner.RunWith;
     39 
     40 /**
     41  * Build/Install/Run:
     42  * atest FrameworksServicesTests:com.android.server.wm.DimmerTests;
     43  */
     44 @Presubmit
     45 @RunWith(AndroidJUnit4.class)
     46 public class DimmerTests extends WindowTestsBase {
     47 
     48     private class TestWindowContainer extends WindowContainer<TestWindowContainer> {
     49         final SurfaceControl mControl = mock(SurfaceControl.class);
     50         final SurfaceControl.Transaction mTransaction = mock(SurfaceControl.Transaction.class);
     51 
     52         TestWindowContainer() {
     53             super(sWm);
     54         }
     55 
     56         @Override
     57         public SurfaceControl getSurfaceControl() {
     58             return mControl;
     59         }
     60 
     61         @Override
     62         public SurfaceControl.Transaction getPendingTransaction() {
     63             return mTransaction;
     64         }
     65     }
     66 
     67     private class MockSurfaceBuildingContainer extends WindowContainer<TestWindowContainer> {
     68         final SurfaceSession mSession = new SurfaceSession();
     69         final SurfaceControl mHostControl = mock(SurfaceControl.class);
     70         final SurfaceControl.Transaction mHostTransaction = mock(SurfaceControl.Transaction.class);
     71 
     72         MockSurfaceBuildingContainer() {
     73             super(sWm);
     74         }
     75 
     76         class MockSurfaceBuilder extends SurfaceControl.Builder {
     77             MockSurfaceBuilder(SurfaceSession ss) {
     78                 super(ss);
     79             }
     80 
     81             @Override
     82             public SurfaceControl build() {
     83                 return mock(SurfaceControl.class);
     84             }
     85         }
     86 
     87         @Override
     88         SurfaceControl.Builder makeChildSurface(WindowContainer child) {
     89             return new MockSurfaceBuilder(mSession);
     90         }
     91 
     92         @Override
     93         public SurfaceControl getSurfaceControl() {
     94             return mHostControl;
     95         }
     96 
     97         @Override
     98         public SurfaceControl.Transaction getPendingTransaction() {
     99             return mHostTransaction;
    100         }
    101     }
    102 
    103     private MockSurfaceBuildingContainer mHost;
    104     private Dimmer mDimmer;
    105     private SurfaceControl.Transaction mTransaction;
    106     private Dimmer.SurfaceAnimatorStarter mSurfaceAnimatorStarter;
    107 
    108     private static class SurfaceAnimatorStarterImpl implements Dimmer.SurfaceAnimatorStarter {
    109         @Override
    110         public void startAnimation(SurfaceAnimator surfaceAnimator, SurfaceControl.Transaction t,
    111                 AnimationAdapter anim, boolean hidden) {
    112             surfaceAnimator.mAnimationFinishedCallback.run();
    113         }
    114     }
    115 
    116     @Before
    117     public void setUp() throws Exception {
    118         super.setUp();
    119         mHost = new MockSurfaceBuildingContainer();
    120         mSurfaceAnimatorStarter = spy(new SurfaceAnimatorStarterImpl());
    121         mTransaction = mock(SurfaceControl.Transaction.class);
    122         mDimmer = new Dimmer(mHost, mSurfaceAnimatorStarter);
    123     }
    124 
    125     @Test
    126     public void testDimAboveNoChildCreatesSurface() throws Exception {
    127         final float alpha = 0.8f;
    128         mDimmer.dimAbove(mTransaction, alpha);
    129 
    130         SurfaceControl dimLayer = getDimLayer();
    131 
    132         assertNotNull("Dimmer should have created a surface", dimLayer);
    133 
    134         verify(mTransaction).setAlpha(dimLayer, alpha);
    135         verify(mTransaction).setLayer(dimLayer, Integer.MAX_VALUE);
    136     }
    137 
    138     @Test
    139     public void testDimAboveNoChildRedundantlyUpdatesAlphaOnExistingSurface() throws Exception {
    140         float alpha = 0.8f;
    141         mDimmer.dimAbove(mTransaction, alpha);
    142         final SurfaceControl firstSurface = getDimLayer();
    143 
    144         alpha = 0.9f;
    145         mDimmer.dimAbove(mTransaction, alpha);
    146 
    147         assertEquals(firstSurface, getDimLayer());
    148         verify(mTransaction).setAlpha(firstSurface, 0.9f);
    149     }
    150 
    151     @Test
    152     public void testUpdateDimsAppliesSize() throws Exception {
    153         mDimmer.dimAbove(mTransaction, 0.8f);
    154 
    155         int width = 100;
    156         int height = 300;
    157         Rect bounds = new Rect(0, 0, width, height);
    158         mDimmer.updateDims(mTransaction, bounds);
    159 
    160         verify(mTransaction).setSize(getDimLayer(), width, height);
    161         verify(mTransaction).show(getDimLayer());
    162     }
    163 
    164     @Test
    165     public void testDimAboveNoChildNotReset() throws Exception {
    166         mDimmer.dimAbove(mTransaction, 0.8f);
    167         SurfaceControl dimLayer = getDimLayer();
    168         mDimmer.resetDimStates();
    169 
    170         mDimmer.updateDims(mTransaction, new Rect());
    171         verify(mTransaction).show(getDimLayer());
    172         verify(dimLayer, never()).destroy();
    173     }
    174 
    175     @Test
    176     public void testDimAboveWithChildCreatesSurfaceAboveChild() throws Exception {
    177         TestWindowContainer child = new TestWindowContainer();
    178         mHost.addChild(child, 0);
    179 
    180         final float alpha = 0.8f;
    181         mDimmer.dimAbove(mTransaction, child, alpha);
    182         SurfaceControl dimLayer = getDimLayer();
    183 
    184         assertNotNull("Dimmer should have created a surface", dimLayer);
    185 
    186         verify(mTransaction).setAlpha(dimLayer, alpha);
    187         verify(mTransaction).setRelativeLayer(dimLayer, child.mControl, 1);
    188     }
    189 
    190     @Test
    191     public void testDimBelowWithChildSurfaceCreatesSurfaceBelowChild() throws Exception {
    192         TestWindowContainer child = new TestWindowContainer();
    193         mHost.addChild(child, 0);
    194 
    195         final float alpha = 0.8f;
    196         mDimmer.dimBelow(mTransaction, child, alpha);
    197         SurfaceControl dimLayer = getDimLayer();
    198 
    199         assertNotNull("Dimmer should have created a surface", dimLayer);
    200 
    201         verify(mTransaction).setAlpha(dimLayer, alpha);
    202         verify(mTransaction).setRelativeLayer(dimLayer, child.mControl, -1);
    203     }
    204 
    205     @Test
    206     public void testDimBelowWithChildSurfaceDestroyedWhenReset() throws Exception {
    207         TestWindowContainer child = new TestWindowContainer();
    208         mHost.addChild(child, 0);
    209 
    210         final float alpha = 0.8f;
    211         mDimmer.dimAbove(mTransaction, child, alpha);
    212         SurfaceControl dimLayer = getDimLayer();
    213         mDimmer.resetDimStates();
    214 
    215         mDimmer.updateDims(mTransaction, new Rect());
    216         verify(mSurfaceAnimatorStarter).startAnimation(any(SurfaceAnimator.class), any(
    217                 SurfaceControl.Transaction.class), any(AnimationAdapter.class), anyBoolean());
    218         verify(dimLayer).destroy();
    219     }
    220 
    221     @Test
    222     public void testDimBelowWithChildSurfaceNotDestroyedWhenPersisted() throws Exception {
    223         TestWindowContainer child = new TestWindowContainer();
    224         mHost.addChild(child, 0);
    225 
    226         final float alpha = 0.8f;
    227         mDimmer.dimAbove(mTransaction, child, alpha);
    228         SurfaceControl dimLayer = getDimLayer();
    229         mDimmer.resetDimStates();
    230         mDimmer.dimAbove(mTransaction, child, alpha);
    231 
    232         mDimmer.updateDims(mTransaction, new Rect());
    233         verify(mTransaction).show(dimLayer);
    234         verify(dimLayer, never()).destroy();
    235     }
    236 
    237     @Test
    238     public void testDimUpdateWhileDimming() throws Exception {
    239         Rect bounds = new Rect();
    240         TestWindowContainer child = new TestWindowContainer();
    241         mHost.addChild(child, 0);
    242 
    243         final float alpha = 0.8f;
    244         mDimmer.dimAbove(mTransaction, child, alpha);
    245 
    246         SurfaceControl dimLayer = getDimLayer();
    247         bounds.set(0, 0, 10, 10);
    248         mDimmer.updateDims(mTransaction, bounds);
    249         verify(mTransaction, times(1)).show(dimLayer);
    250         verify(mTransaction).setSize(dimLayer, bounds.width(), bounds.height());
    251         verify(mTransaction).setPosition(dimLayer, 0, 0);
    252 
    253         bounds.set(10, 10, 30, 30);
    254         mDimmer.updateDims(mTransaction, bounds);
    255         verify(mTransaction).setSize(dimLayer, bounds.width(), bounds.height());
    256         verify(mTransaction).setPosition(dimLayer, 10, 10);
    257     }
    258 
    259     @Test
    260     public void testRemoveDimImmediately() throws Exception {
    261         TestWindowContainer child = new TestWindowContainer();
    262         mHost.addChild(child, 0);
    263 
    264         mDimmer.dimAbove(mTransaction, child, 1);
    265         SurfaceControl dimLayer = getDimLayer();
    266         mDimmer.updateDims(mTransaction, new Rect());
    267         verify(mTransaction, times(1)).show(dimLayer);
    268 
    269         reset(mSurfaceAnimatorStarter);
    270         mDimmer.dontAnimateExit();
    271         mDimmer.resetDimStates();
    272         mDimmer.updateDims(mTransaction, new Rect());
    273         verify(mSurfaceAnimatorStarter, never()).startAnimation(any(SurfaceAnimator.class), any(
    274                 SurfaceControl.Transaction.class), any(AnimationAdapter.class), anyBoolean());
    275         verify(mTransaction).destroy(dimLayer);
    276     }
    277 
    278     private SurfaceControl getDimLayer() {
    279         return mDimmer.mDimState.mDimLayer;
    280     }
    281 }
    282