• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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