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.assertFalse;
     21 import static org.junit.Assert.assertNotNull;
     22 import static org.junit.Assert.assertNull;
     23 import static org.junit.Assert.assertTrue;
     24 import static org.mockito.ArgumentMatchers.eq;
     25 import static org.mockito.Mockito.any;
     26 import static org.mockito.Mockito.never;
     27 import static org.mockito.Mockito.verify;
     28 import static org.mockito.Mockito.verifyZeroInteractions;
     29 
     30 import android.platform.test.annotations.Presubmit;
     31 import android.support.test.filters.FlakyTest;
     32 import android.support.test.filters.SmallTest;
     33 import android.support.test.runner.AndroidJUnit4;
     34 import android.view.SurfaceControl;
     35 import android.view.SurfaceControl.Builder;
     36 import android.view.SurfaceControl.Transaction;
     37 import android.view.SurfaceSession;
     38 
     39 import com.android.server.wm.SurfaceAnimator.Animatable;
     40 import com.android.server.wm.SurfaceAnimator.OnAnimationFinishedCallback;
     41 
     42 import org.junit.Before;
     43 import org.junit.Test;
     44 import org.junit.runner.RunWith;
     45 import org.mockito.ArgumentCaptor;
     46 import org.mockito.Mock;
     47 import org.mockito.MockitoAnnotations;
     48 
     49 import java.util.ArrayList;
     50 
     51 /**
     52  * Test class for {@link SurfaceAnimatorTest}.
     53  *
     54  * atest FrameworksServicesTests:com.android.server.wm.SurfaceAnimatorTest
     55  */
     56 @SmallTest
     57 @Presubmit
     58 @RunWith(AndroidJUnit4.class)
     59 public class SurfaceAnimatorTest extends WindowTestsBase {
     60 
     61     @Mock AnimationAdapter mSpec;
     62     @Mock AnimationAdapter mSpec2;
     63     @Mock Transaction mTransaction;
     64 
     65     private SurfaceSession mSession = new SurfaceSession();
     66     private MyAnimatable mAnimatable;
     67     private MyAnimatable mAnimatable2;
     68     private DeferFinishAnimatable mDeferFinishAnimatable;
     69 
     70     @Before
     71     public void setUp() throws Exception {
     72         super.setUp();
     73         MockitoAnnotations.initMocks(this);
     74         mAnimatable = new MyAnimatable();
     75         mAnimatable2 = new MyAnimatable();
     76         mDeferFinishAnimatable = new DeferFinishAnimatable();
     77     }
     78 
     79     @Test
     80     public void testRunAnimation() throws Exception {
     81         mAnimatable.mSurfaceAnimator.startAnimation(mTransaction, mSpec, true /* hidden */);
     82         final ArgumentCaptor<OnAnimationFinishedCallback> callbackCaptor = ArgumentCaptor.forClass(
     83                 OnAnimationFinishedCallback.class);
     84         assertAnimating(mAnimatable);
     85         verify(mTransaction).reparent(eq(mAnimatable.mSurface), eq(mAnimatable.mLeash.getHandle()));
     86         verify(mSpec).startAnimation(any(), any(), callbackCaptor.capture());
     87 
     88         callbackCaptor.getValue().onAnimationFinished(mSpec);
     89         assertNotAnimating(mAnimatable);
     90         assertTrue(mAnimatable.mFinishedCallbackCalled);
     91         verify(mTransaction).destroy(eq(mAnimatable.mLeash));
     92         // TODO: Verify reparenting once we use mPendingTransaction to reparent it back
     93     }
     94 
     95     @Test
     96     public void testOverrideAnimation() throws Exception {
     97         mAnimatable.mSurfaceAnimator.startAnimation(mTransaction, mSpec, true /* hidden */);
     98         final SurfaceControl firstLeash = mAnimatable.mLeash;
     99         mAnimatable.mSurfaceAnimator.startAnimation(mTransaction, mSpec2, true /* hidden */);
    100 
    101         verify(mTransaction).destroy(eq(firstLeash));
    102         assertFalse(mAnimatable.mFinishedCallbackCalled);
    103 
    104         final ArgumentCaptor<OnAnimationFinishedCallback> callbackCaptor = ArgumentCaptor.forClass(
    105                 OnAnimationFinishedCallback.class);
    106         assertAnimating(mAnimatable);
    107         verify(mSpec).startAnimation(any(), any(), callbackCaptor.capture());
    108 
    109         // First animation was finished, but this shouldn't cancel the second animation
    110         callbackCaptor.getValue().onAnimationFinished(mSpec);
    111         assertTrue(mAnimatable.mSurfaceAnimator.isAnimating());
    112 
    113         // Second animation was finished
    114         verify(mSpec2).startAnimation(any(), any(), callbackCaptor.capture());
    115         callbackCaptor.getValue().onAnimationFinished(mSpec2);
    116         assertNotAnimating(mAnimatable);
    117         assertTrue(mAnimatable.mFinishedCallbackCalled);
    118     }
    119 
    120     @Test
    121     public void testCancelAnimation() throws Exception {
    122         mAnimatable.mSurfaceAnimator.startAnimation(mTransaction, mSpec, true /* hidden */);
    123         assertAnimating(mAnimatable);
    124         mAnimatable.mSurfaceAnimator.cancelAnimation();
    125         assertNotAnimating(mAnimatable);
    126         verify(mSpec).onAnimationCancelled(any());
    127         assertTrue(mAnimatable.mFinishedCallbackCalled);
    128         verify(mTransaction).destroy(eq(mAnimatable.mLeash));
    129     }
    130 
    131     @Test
    132     public void testDelayingAnimationStart() throws Exception {
    133         mAnimatable.mSurfaceAnimator.startDelayingAnimationStart();
    134         mAnimatable.mSurfaceAnimator.startAnimation(mTransaction, mSpec, true /* hidden */);
    135         verifyZeroInteractions(mSpec);
    136         assertAnimating(mAnimatable);
    137         assertTrue(mAnimatable.mSurfaceAnimator.isAnimationStartDelayed());
    138         mAnimatable.mSurfaceAnimator.endDelayingAnimationStart();
    139         verify(mSpec).startAnimation(any(), any(), any());
    140     }
    141 
    142     @Test
    143     public void testDelayingAnimationStartAndCancelled() throws Exception {
    144         mAnimatable.mSurfaceAnimator.startDelayingAnimationStart();
    145         mAnimatable.mSurfaceAnimator.startAnimation(mTransaction, mSpec, true /* hidden */);
    146         mAnimatable.mSurfaceAnimator.cancelAnimation();
    147         verifyZeroInteractions(mSpec);
    148         assertNotAnimating(mAnimatable);
    149         assertTrue(mAnimatable.mFinishedCallbackCalled);
    150         verify(mTransaction).destroy(eq(mAnimatable.mLeash));
    151     }
    152 
    153     @Test
    154     public void testTransferAnimation() throws Exception {
    155         mAnimatable.mSurfaceAnimator.startAnimation(mTransaction, mSpec, true /* hidden */);
    156 
    157         final ArgumentCaptor<OnAnimationFinishedCallback> callbackCaptor = ArgumentCaptor.forClass(
    158                 OnAnimationFinishedCallback.class);
    159         verify(mSpec).startAnimation(any(), any(), callbackCaptor.capture());
    160         final SurfaceControl leash = mAnimatable.mLeash;
    161 
    162         mAnimatable2.mSurfaceAnimator.transferAnimation(mAnimatable.mSurfaceAnimator);
    163         assertNotAnimating(mAnimatable);
    164         assertAnimating(mAnimatable2);
    165         assertEquals(leash, mAnimatable2.mSurfaceAnimator.mLeash);
    166         verify(mTransaction, never()).destroy(eq(leash));
    167         callbackCaptor.getValue().onAnimationFinished(mSpec);
    168         assertNotAnimating(mAnimatable2);
    169         assertTrue(mAnimatable2.mFinishedCallbackCalled);
    170         verify(mTransaction).destroy(eq(leash));
    171     }
    172 
    173     @Test
    174     @FlakyTest(detail = "Promote once confirmed non-flaky")
    175     public void testDeferFinish() throws Exception {
    176 
    177         // Start animation
    178         mDeferFinishAnimatable.mSurfaceAnimator.startAnimation(mTransaction, mSpec,
    179                 true /* hidden */);
    180         final ArgumentCaptor<OnAnimationFinishedCallback> callbackCaptor = ArgumentCaptor.forClass(
    181                 OnAnimationFinishedCallback.class);
    182         assertAnimating(mDeferFinishAnimatable);
    183         verify(mSpec).startAnimation(any(), any(), callbackCaptor.capture());
    184 
    185         // Finish the animation but then make sure we are deferring.
    186         callbackCaptor.getValue().onAnimationFinished(mSpec);
    187         assertAnimating(mDeferFinishAnimatable);
    188 
    189         // Now end defer finishing.
    190         mDeferFinishAnimatable.endDeferFinishCallback.run();
    191         assertNotAnimating(mAnimatable2);
    192         assertTrue(mDeferFinishAnimatable.mFinishedCallbackCalled);
    193         verify(mTransaction).destroy(eq(mDeferFinishAnimatable.mLeash));
    194     }
    195 
    196     private void assertAnimating(MyAnimatable animatable) {
    197         assertTrue(animatable.mSurfaceAnimator.isAnimating());
    198         assertNotNull(animatable.mSurfaceAnimator.getAnimation());
    199     }
    200 
    201     private void assertNotAnimating(MyAnimatable animatable) {
    202         assertFalse(animatable.mSurfaceAnimator.isAnimating());
    203         assertNull(animatable.mSurfaceAnimator.getAnimation());
    204     }
    205 
    206     private class MyAnimatable implements Animatable {
    207 
    208         final SurfaceControl mParent;
    209         final SurfaceControl mSurface;
    210         final SurfaceAnimator mSurfaceAnimator;
    211         SurfaceControl mLeash;
    212         boolean mFinishedCallbackCalled;
    213 
    214         MyAnimatable() {
    215             mParent = sWm.makeSurfaceBuilder(mSession)
    216                     .setName("test surface parent")
    217                     .setSize(3000, 3000)
    218                     .build();
    219             mSurface = sWm.makeSurfaceBuilder(mSession)
    220                     .setName("test surface")
    221                     .setSize(1, 1)
    222                     .build();
    223             mFinishedCallbackCalled = false;
    224             mLeash = null;
    225             mSurfaceAnimator = new SurfaceAnimator(this, mFinishedCallback, sWm);
    226         }
    227 
    228         @Override
    229         public Transaction getPendingTransaction() {
    230             return mTransaction;
    231         }
    232 
    233         @Override
    234         public void commitPendingTransaction() {
    235         }
    236 
    237         @Override
    238         public void onAnimationLeashCreated(Transaction t, SurfaceControl leash) {
    239         }
    240 
    241         @Override
    242         public void onAnimationLeashDestroyed(Transaction t) {
    243         }
    244 
    245         @Override
    246         public Builder makeAnimationLeash() {
    247             return new SurfaceControl.Builder(mSession) {
    248 
    249                 @Override
    250                 public SurfaceControl build() {
    251                     mLeash = super.build();
    252                     return mLeash;
    253                 }
    254             }.setParent(mParent);
    255         }
    256 
    257         @Override
    258         public SurfaceControl getAnimationLeashParent() {
    259             return mParent;
    260         }
    261 
    262         @Override
    263         public SurfaceControl getSurfaceControl() {
    264             return mSurface;
    265         }
    266 
    267         @Override
    268         public SurfaceControl getParentSurfaceControl() {
    269             return mParent;
    270         }
    271 
    272         @Override
    273         public int getSurfaceWidth() {
    274             return 1;
    275         }
    276 
    277         @Override
    278         public int getSurfaceHeight() {
    279             return 1;
    280         }
    281 
    282         private final Runnable mFinishedCallback = () -> mFinishedCallbackCalled = true;
    283     }
    284 
    285     private class DeferFinishAnimatable extends MyAnimatable {
    286 
    287         Runnable endDeferFinishCallback;
    288 
    289         @Override
    290         public boolean shouldDeferAnimationFinish(Runnable endDeferFinishCallback) {
    291             this.endDeferFinishCallback = endDeferFinishCallback;
    292             return true;
    293         }
    294     }
    295 }
    296