1 /* 2 * Copyright (C) 2023 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.server.wm; 18 19 import android.app.Activity; 20 import android.graphics.Color; 21 import android.graphics.Rect; 22 import android.os.Bundle; 23 import android.os.Handler; 24 import android.provider.Settings; 25 import android.server.wm.settings.SettingsSession; 26 import android.view.Display; 27 import android.view.Gravity; 28 import android.view.View; 29 import android.view.ViewGroup; 30 import android.view.Window; 31 import android.view.WindowManager; 32 33 import org.junit.ClassRule; 34 import org.junit.Test; 35 import org.junit.rules.TestRule; 36 37 import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation; 38 39 import static org.junit.Assert.assertEquals; 40 import static org.junit.Assert.assertFalse; 41 import static org.junit.Assert.assertTrue; 42 43 /** 44 * Test the following APIs for controlling FLAG_NO_MOVE_ANIMATION: 45 * <ul> 46 * <li>{@code WindowManager.LayoutParams.setCanPlayMoveAnimation(boolean)} 47 * <li>{@code WindowManager.LayoutParams.canPlayMoveAnimation()} 48 * <li>{@code android:style/windowNoMoveAnimation} 49 * </ul> 50 * 51 * Build/Install/Run: 52 * atest CtsWindowManagerDeviceTestCases:MoveAnimationTests 53 */ 54 public class MoveAnimationTests extends WindowManagerTestBase { 55 56 /** 57 * All tests in this class run with window animation scaling set to 20.0f 58 */ 59 @ClassRule 60 public static final TestRule sWindowAnimationRule = SettingsSession.overrideForTest( 61 Settings.Global.getUriFor(Settings.Global.WINDOW_ANIMATION_SCALE), 62 Settings.Global::getFloat, 63 Settings.Global::putFloat, 64 20.0f); 65 66 /** 67 * Activity with a theme setting {@code windowIsFloating} as {@code true} to get the default 68 * behavior of floating window move animations. 69 */ 70 public static class FloatingActivity extends FocusableActivity { 71 72 protected View mContentView; 73 74 /** 75 * Instance of {@link FloatingActivity} with a theme setting {@code windowNoMoveAnimation} 76 * as {@code true}. 77 */ 78 public static class NoMove extends FloatingActivity { 79 @Override onCreate(Bundle savedInstanceState)80 protected void onCreate(Bundle savedInstanceState) { 81 super.onCreate(savedInstanceState); 82 } 83 } 84 85 @Override onCreate(Bundle savedInstanceState)86 protected void onCreate(Bundle savedInstanceState) { 87 super.onCreate(savedInstanceState); 88 89 mContentView = new View(this); 90 mContentView.setBackgroundColor(Color.BLUE); 91 92 setContentSquare(40); 93 } 94 setContentSquare(int size)95 public void setContentSquare(int size) { 96 getWindow().setContentView(mContentView, new ViewGroup.LayoutParams(size, size)); 97 98 WindowManager.LayoutParams attrs = getWindow().getAttributes(); 99 attrs.gravity = Gravity.RIGHT | Gravity.BOTTOM; 100 getWindow().setAttributes(attrs); 101 } 102 } 103 104 @Test testCanPlayMoveAnimationByDefault()105 public void testCanPlayMoveAnimationByDefault() { 106 final FloatingActivity activity = 107 startActivityInWindowingModeFullScreen(FloatingActivity.class); 108 final Window window = activity.getWindow(); 109 110 // Default state should be TRUE because the activity has done nothing to override it. 111 assertTrue("Floating windows should play move animations by default", 112 window.getAttributes().canPlayMoveAnimation()); 113 assertPlaysMoveAnimation(activity, true); 114 } 115 116 @Test testCanOverrideTheme()117 public void testCanOverrideTheme() { 118 final FloatingActivity.NoMove activity = 119 startActivityInWindowingModeFullScreen(FloatingActivity.NoMove.class); 120 final Window window = activity.getWindow(); 121 122 // Default state should be FALSE because this Activity uses a theme with no move animation. 123 assertFalse("Themes should be able to prevent move animations via windowNoMoveAnimation", 124 window.getAttributes().canPlayMoveAnimation()); 125 126 // Window API should be able to override theme defaults from FALSE to TRUE. 127 getInstrumentation().runOnMainSync(() -> { 128 WindowManager.LayoutParams attrs = window.getAttributes(); 129 attrs.setCanPlayMoveAnimation(true); 130 window.setAttributes(attrs); 131 }); 132 133 assertTrue("Window should know that it can play a move animation", 134 window.getAttributes().canPlayMoveAnimation()); 135 assertPlaysMoveAnimation(activity, true); 136 } 137 138 @Test testThemeCanDisable()139 public void testThemeCanDisable() { 140 final FloatingActivity.NoMove activity = 141 startActivityInWindowingModeFullScreen(FloatingActivity.NoMove.class); 142 final Window window = activity.getWindow(); 143 144 // Window API should be able to override theme defaults from TRUE to FALSE. 145 getInstrumentation().runOnMainSync(() -> { 146 WindowManager.LayoutParams attrs = window.getAttributes(); 147 attrs.setCanPlayMoveAnimation(false); 148 window.setAttributes(attrs); 149 }); 150 151 assertFalse("Window should know that it can NOT play a move animation", 152 window.getAttributes().canPlayMoveAnimation()); 153 assertPlaysMoveAnimation(activity, false); 154 } 155 assertPlaysMoveAnimation(final FloatingActivity activity, final boolean isPlayed)156 private void assertPlaysMoveAnimation(final FloatingActivity activity, final boolean isPlayed) { 157 mWmState.waitForAppTransitionIdleOnDisplay(Display.DEFAULT_DISPLAY); 158 159 activity.mContentView.post(() -> activity.setContentSquare(200)); 160 161 Condition isAnimating = new Condition("Window is animating", 162 () -> { 163 mWmState.computeState(); 164 WindowManagerState.Activity ar = 165 mWmState.getActivity(activity.getComponentName()); 166 return ar != null && ar.isAnimating(); 167 }) 168 .setRetryIntervalMs(16) 169 .setRetryLimit(50); 170 assertEquals(isPlayed, Condition.waitFor(isAnimating)); 171 } 172 } 173