• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2020 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 static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
20 import static android.server.wm.app.Components.TEST_ACTIVITY;
21 import static android.view.Display.DEFAULT_DISPLAY;
22 
23 import static org.junit.Assert.assertTrue;
24 import static org.junit.Assume.assumeFalse;
25 import static org.junit.Assume.assumeTrue;
26 
27 import android.app.Activity;
28 import android.app.ActivityOptions;
29 import android.app.Instrumentation;
30 import android.content.ComponentName;
31 import android.content.Intent;
32 import android.os.Bundle;
33 import android.os.Handler;
34 import android.os.Looper;
35 import android.platform.test.annotations.Presubmit;
36 import android.server.wm.cts.R;
37 import android.util.Range;
38 
39 import androidx.test.platform.app.InstrumentationRegistry;
40 
41 import com.android.compatibility.common.util.SystemUtil;
42 
43 import org.junit.Test;
44 
45 import java.util.concurrent.CountDownLatch;
46 import java.util.concurrent.TimeUnit;
47 
48 /**
49  * <p>Build/Install/Run:
50  * atest CtsWindowManagerDeviceTestCases:ActivityTransitionTests
51  */
52 @Presubmit
53 public class ActivityTransitionTests extends ActivityManagerTestBase {
54     // See WindowManagerService.DISABLE_CUSTOM_TASK_ANIMATION_PROPERTY
55     static final String DISABLE_CUSTOM_TASK_ANIMATION_PROPERTY =
56             "persist.wm.disable_custom_task_animation";
57     static final boolean DISABLE_CUSTOM_TASK_ANIMATION_DEFAULT = true;
58 
59     // Duration of the default wallpaper close animation
60     static final long DEFAULT_ANIMATION_DURATION = 275L;
61     // Duration of the R.anim.alpha animation
62     static final long CUSTOM_ANIMATION_DURATION = 2000L;
63 
customTaskAnimationDisabled()64     private static boolean customTaskAnimationDisabled() {
65         try {
66             return Integer.parseInt(executeShellCommand(
67                     "getprop " + DISABLE_CUSTOM_TASK_ANIMATION_PROPERTY).replace("\n", "")) != 0;
68         } catch (NumberFormatException e) {
69             return DISABLE_CUSTOM_TASK_ANIMATION_DEFAULT;
70         }
71     }
72 
73     @Test
testActivityTransitionDurationNoShortenAsExpected()74     public void testActivityTransitionDurationNoShortenAsExpected() throws Exception {
75         final long expectedDurationMs = CUSTOM_ANIMATION_DURATION - 100L;
76         final long minDurationMs = expectedDurationMs;
77         final long maxDurationMs = expectedDurationMs + 300L;
78         final Range<Long> durationRange = new Range<>(minDurationMs, maxDurationMs);
79 
80         final CountDownLatch latch = new CountDownLatch(1);
81         long[] transitionStartTime = new long[1];
82         long[] transitionEndTime = new long[1];
83 
84         final ActivityOptions.OnAnimationStartedListener startedListener = () -> {
85             transitionStartTime[0] = System.currentTimeMillis();
86         };
87 
88         final ActivityOptions.OnAnimationFinishedListener finishedListener = () -> {
89             transitionEndTime[0] = System.currentTimeMillis();
90             latch.countDown();
91         };
92 
93         final Intent intent = new Intent(mContext, LauncherActivity.class)
94                 .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
95         final Instrumentation instrumentation = InstrumentationRegistry.getInstrumentation();
96         final LauncherActivity launcherActivity =
97                 (LauncherActivity) instrumentation.startActivitySync(intent);
98 
99         final Bundle bundle = ActivityOptions.makeCustomAnimation(mContext,
100                 R.anim.alpha, 0, new Handler(Looper.getMainLooper()), startedListener,
101                 finishedListener).toBundle();
102         launcherActivity.startTransitionActivity(bundle);
103         mWmState.waitForAppTransitionIdleOnDisplay(DEFAULT_DISPLAY);
104         waitAndAssertTopResumedActivity(new ComponentName(mContext, TransitionActivity.class),
105                 DEFAULT_DISPLAY, "Activity must be launched");
106 
107         latch.await(2, TimeUnit.SECONDS);
108         final long totalTime = transitionEndTime[0] - transitionStartTime[0];
109         assertTrue("Actual transition duration should be in the range "
110                 + "<" + minDurationMs + ", " + maxDurationMs + "> ms, "
111                 + "actual=" + totalTime, durationRange.contains(totalTime));
112     }
113 
114     @Test
testTaskTransitionDurationNoShortenAsExpected()115     public void testTaskTransitionDurationNoShortenAsExpected() throws Exception {
116         assumeFalse(customTaskAnimationDisabled());
117 
118         final long expectedDurationMs = CUSTOM_ANIMATION_DURATION - 100L;
119         final long minDurationMs = expectedDurationMs;
120         final long maxDurationMs = expectedDurationMs + 300L;
121         final Range<Long> durationRange = new Range<>(minDurationMs, maxDurationMs);
122 
123         final CountDownLatch latch = new CountDownLatch(1);
124         long[] transitionStartTime = new long[1];
125         long[] transitionEndTime = new long[1];
126 
127         final ActivityOptions.OnAnimationStartedListener startedListener = () -> {
128             transitionStartTime[0] = System.currentTimeMillis();
129         };
130 
131         final ActivityOptions.OnAnimationFinishedListener finishedListener = () -> {
132             transitionEndTime[0] = System.currentTimeMillis();
133             latch.countDown();
134         };
135 
136         final Bundle bundle = ActivityOptions.makeCustomAnimation(mContext,
137                 R.anim.alpha, 0, new Handler(Looper.getMainLooper()), startedListener,
138                 finishedListener).toBundle();
139         final Intent intent = new Intent().setComponent(TEST_ACTIVITY)
140                 .addFlags(FLAG_ACTIVITY_NEW_TASK);
141         mContext.startActivity(intent, bundle);
142         mWmState.waitForAppTransitionIdleOnDisplay(DEFAULT_DISPLAY);
143         waitAndAssertTopResumedActivity(TEST_ACTIVITY, DEFAULT_DISPLAY,
144                 "Activity must be launched");
145 
146         latch.await(2, TimeUnit.SECONDS);
147         final long totalTime = transitionEndTime[0] - transitionStartTime[0];
148         assertTrue("Actual transition duration should be in the range "
149                 + "<" + minDurationMs + ", " + maxDurationMs + "> ms, "
150                 + "actual=" + totalTime, durationRange.contains(totalTime));
151     }
152 
153     @Test
testTaskTransitionOverrideDisabled()154     public void testTaskTransitionOverrideDisabled() throws Exception {
155         assumeTrue(customTaskAnimationDisabled());
156 
157         final long expectedDurationMs = DEFAULT_ANIMATION_DURATION - 100L;
158         final long minDurationMs = expectedDurationMs;
159         final long maxDurationMs = expectedDurationMs + 1000L;
160         final Range<Long> durationRange = new Range<>(minDurationMs, maxDurationMs);
161 
162         final CountDownLatch latch = new CountDownLatch(1);
163         long[] transitionStartTime = new long[1];
164         long[] transitionEndTime = new long[1];
165 
166         final ActivityOptions.OnAnimationStartedListener startedListener = () -> {
167             transitionStartTime[0] = System.currentTimeMillis();
168         };
169 
170         final ActivityOptions.OnAnimationFinishedListener finishedListener = () -> {
171             transitionEndTime[0] = System.currentTimeMillis();
172             latch.countDown();
173         };
174 
175         // Overriding task transit animation is disabled, so default wallpaper close animation
176         // is played.
177         final Bundle bundle = ActivityOptions.makeCustomAnimation(mContext,
178                 R.anim.alpha, 0, new Handler(Looper.getMainLooper()), startedListener,
179                 finishedListener).toBundle();
180         final Intent intent = new Intent().setComponent(TEST_ACTIVITY)
181                 .addFlags(FLAG_ACTIVITY_NEW_TASK);
182         mContext.startActivity(intent, bundle);
183         mWmState.waitForAppTransitionIdleOnDisplay(DEFAULT_DISPLAY);
184         waitAndAssertTopResumedActivity(TEST_ACTIVITY, DEFAULT_DISPLAY,
185                 "Activity must be launched");
186 
187         latch.await(2, TimeUnit.SECONDS);
188         final long totalTime = transitionEndTime[0] - transitionStartTime[0];
189         assertTrue("Actual transition duration should be in the range "
190                 + "<" + minDurationMs + ", " + maxDurationMs + "> ms, "
191                 + "actual=" + totalTime, durationRange.contains(totalTime));
192     }
193 
194     @Test
testTaskTransitionOverride()195     public void testTaskTransitionOverride() throws Exception {
196         assumeTrue(customTaskAnimationDisabled());
197 
198         final long expectedDurationMs = CUSTOM_ANIMATION_DURATION - 100L;
199         final long minDurationMs = expectedDurationMs;
200         final long maxDurationMs = expectedDurationMs + 1000L;
201         final Range<Long> durationRange = new Range<>(minDurationMs, maxDurationMs);
202 
203         final CountDownLatch latch = new CountDownLatch(1);
204         long[] transitionStartTime = new long[1];
205         long[] transitionEndTime = new long[1];
206 
207         final ActivityOptions.OnAnimationStartedListener startedListener = () -> {
208             transitionStartTime[0] = System.currentTimeMillis();
209         };
210 
211         final ActivityOptions.OnAnimationFinishedListener finishedListener = () -> {
212             transitionEndTime[0] = System.currentTimeMillis();
213             latch.countDown();
214         };
215 
216         SystemUtil.runWithShellPermissionIdentity(() -> {
217             // Overriding task transit animation is enabled, so custom animation is played.
218             final Bundle bundle = ActivityOptions.makeCustomTaskAnimation(mContext,
219                     R.anim.alpha, 0, new Handler(Looper.getMainLooper()), startedListener,
220                     finishedListener).toBundle();
221             final Intent intent = new Intent().setComponent(TEST_ACTIVITY)
222                     .addFlags(FLAG_ACTIVITY_NEW_TASK);
223             mContext.startActivity(intent, bundle);
224             mWmState.waitForAppTransitionIdleOnDisplay(DEFAULT_DISPLAY);
225             waitAndAssertTopResumedActivity(TEST_ACTIVITY, DEFAULT_DISPLAY,
226                     "Activity must be launched");
227 
228             latch.await(2, TimeUnit.SECONDS);
229             final long totalTime = transitionEndTime[0] - transitionStartTime[0];
230             assertTrue("Actual transition duration should be in the range "
231                     + "<" + minDurationMs + ", " + maxDurationMs + "> ms, "
232                     + "actual=" + totalTime, durationRange.contains(totalTime));
233         });
234     }
235 
236     public static class LauncherActivity extends Activity {
237 
startTransitionActivity(Bundle bundle)238         public void startTransitionActivity(Bundle bundle) {
239             startActivity(new Intent(this, TransitionActivity.class), bundle);
240         }
241     }
242 
243     public static class TransitionActivity extends Activity {
244     }
245 }
246