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