1 /* 2 * Copyright (C) 2018 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 com.android.dx.mockito.inline.extended.ExtendedMockito.verify; 20 import static com.android.server.wm.SurfaceAnimator.ANIMATION_TYPE_APP_TRANSITION; 21 22 import static com.google.common.truth.Truth.assertThat; 23 24 import static org.mockito.ArgumentMatchers.any; 25 import static org.mockito.ArgumentMatchers.eq; 26 import static org.mockito.ArgumentMatchers.intThat; 27 28 import android.platform.test.annotations.Presubmit; 29 import android.view.SurfaceControl; 30 31 import androidx.test.filters.SmallTest; 32 33 import org.junit.Before; 34 import org.junit.Test; 35 import org.junit.runner.RunWith; 36 import org.mockito.ArgumentCaptor; 37 import org.mockito.Mock; 38 import org.mockito.MockitoAnnotations; 39 40 41 /** 42 * Animation related tests for the {@link ActivityRecord} class. 43 * 44 * Build/Install/Run: 45 * atest AppWindowTokenAnimationTests 46 */ 47 @SmallTest 48 @Presubmit 49 @RunWith(WindowTestRunner.class) 50 public class AppWindowTokenAnimationTests extends WindowTestsBase { 51 52 private ActivityRecord mActivity; 53 54 @Mock 55 private AnimationAdapter mSpec; 56 57 @Before setUp()58 public void setUp() throws Exception { 59 MockitoAnnotations.initMocks(this); 60 61 mActivity = createActivityRecord(mDisplayContent); 62 } 63 64 @Test clipAfterAnim_boundsLayerIsCreated()65 public void clipAfterAnim_boundsLayerIsCreated() { 66 mActivity.mNeedsAnimationBoundsLayer = true; 67 68 mActivity.mSurfaceAnimator.startAnimation(mTransaction, mSpec, true /* hidden */, 69 ANIMATION_TYPE_APP_TRANSITION); 70 verify(mTransaction).reparent(eq(mActivity.getSurfaceControl()), 71 eq(mActivity.mSurfaceAnimator.mLeash)); 72 verify(mTransaction).reparent(eq(mActivity.mSurfaceAnimator.mLeash), 73 eq(mActivity.mAnimationBoundsLayer)); 74 } 75 76 @Test clipAfterAnim_boundsLayerZBoosted()77 public void clipAfterAnim_boundsLayerZBoosted() { 78 final Task task = mActivity.getTask(); 79 final ActivityRecord topActivity = createActivityRecord(task); 80 task.assignChildLayers(mTransaction); 81 82 assertThat(topActivity.getLastLayer()).isGreaterThan(mActivity.getLastLayer()); 83 84 mActivity.mNeedsAnimationBoundsLayer = true; 85 mActivity.mNeedsZBoost = true; 86 mActivity.mSurfaceAnimator.startAnimation(mTransaction, mSpec, true /* hidden */, 87 ANIMATION_TYPE_APP_TRANSITION); 88 89 verify(mTransaction).setLayer(eq(mActivity.mAnimationBoundsLayer), 90 intThat(layer -> layer > topActivity.getLastLayer())); 91 92 // The layer should be restored after the animation leash is removed. 93 mActivity.onAnimationLeashLost(mTransaction); 94 assertThat(mActivity.mNeedsZBoost).isFalse(); 95 assertThat(topActivity.getLastLayer()).isGreaterThan(mActivity.getLastLayer()); 96 } 97 98 @Test clipAfterAnim_boundsLayerIsDestroyed()99 public void clipAfterAnim_boundsLayerIsDestroyed() { 100 mActivity.mNeedsAnimationBoundsLayer = true; 101 mActivity.mSurfaceAnimator.startAnimation(mTransaction, mSpec, true /* hidden */, 102 ANIMATION_TYPE_APP_TRANSITION); 103 final SurfaceControl leash = mActivity.mSurfaceAnimator.mLeash; 104 final SurfaceControl animationBoundsLayer = mActivity.mAnimationBoundsLayer; 105 final ArgumentCaptor<SurfaceAnimator.OnAnimationFinishedCallback> callbackCaptor = 106 ArgumentCaptor.forClass( 107 SurfaceAnimator.OnAnimationFinishedCallback.class); 108 verify(mSpec).startAnimation(any(), any(), eq(ANIMATION_TYPE_APP_TRANSITION), 109 callbackCaptor.capture()); 110 111 callbackCaptor.getValue().onAnimationFinished( 112 ANIMATION_TYPE_APP_TRANSITION, mSpec); 113 verify(mTransaction).remove(eq(leash)); 114 verify(mTransaction).remove(eq(animationBoundsLayer)); 115 assertThat(mActivity.mNeedsAnimationBoundsLayer).isFalse(); 116 } 117 118 @Test clipAfterAnimCancelled_boundsLayerIsDestroyed()119 public void clipAfterAnimCancelled_boundsLayerIsDestroyed() { 120 mActivity.mNeedsAnimationBoundsLayer = true; 121 mActivity.mSurfaceAnimator.startAnimation(mTransaction, mSpec, true /* hidden */, 122 ANIMATION_TYPE_APP_TRANSITION); 123 final SurfaceControl leash = mActivity.mSurfaceAnimator.mLeash; 124 final SurfaceControl animationBoundsLayer = mActivity.mAnimationBoundsLayer; 125 126 mActivity.mSurfaceAnimator.cancelAnimation(); 127 verify(mTransaction).remove(eq(leash)); 128 verify(mTransaction).remove(eq(animationBoundsLayer)); 129 assertThat(mActivity.mNeedsAnimationBoundsLayer).isFalse(); 130 } 131 132 @Test clipNoneAnim_boundsLayerIsNotCreated()133 public void clipNoneAnim_boundsLayerIsNotCreated() { 134 mActivity.mNeedsAnimationBoundsLayer = false; 135 136 mActivity.mSurfaceAnimator.startAnimation(mTransaction, mSpec, true /* hidden */, 137 ANIMATION_TYPE_APP_TRANSITION); 138 verify(mTransaction).reparent(eq(mActivity.getSurfaceControl()), 139 eq(mActivity.mSurfaceAnimator.mLeash)); 140 assertThat(mActivity.mAnimationBoundsLayer).isNull(); 141 } 142 } 143