diff options
author | Riddle Hsu <riddlehsu@google.com> | 2020-05-04 21:58:50 +0800 |
---|---|---|
committer | Riddle Hsu <riddlehsu@google.com> | 2020-05-06 00:52:51 +0800 |
commit | b078bc1b9c08ebfebf4114b8b13972784a059e6c (patch) | |
tree | 2e776f38aa976324881e8d7ac8a8b9b8a1757e24 /apct-tests/perftests/windowmanager/src/android/wm/RecentsAnimationPerfTest.java | |
parent | cb7f8e7280df971b67fa094a8f6eef60d34bdf5f (diff) |
Move window manager perf test to a new package
To isolate the test environment.
Bug: 155404627
Test: atest WmPerfTests
Change-Id: I1d9eda840056efc6c2d0696952ece55fd22b1547
Diffstat (limited to 'apct-tests/perftests/windowmanager/src/android/wm/RecentsAnimationPerfTest.java')
-rw-r--r-- | apct-tests/perftests/windowmanager/src/android/wm/RecentsAnimationPerfTest.java | 229 |
1 files changed, 229 insertions, 0 deletions
diff --git a/apct-tests/perftests/windowmanager/src/android/wm/RecentsAnimationPerfTest.java b/apct-tests/perftests/windowmanager/src/android/wm/RecentsAnimationPerfTest.java new file mode 100644 index 000000000000..1667c1658a07 --- /dev/null +++ b/apct-tests/perftests/windowmanager/src/android/wm/RecentsAnimationPerfTest.java @@ -0,0 +1,229 @@ +/* + * Copyright (C) 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.wm; + +import static android.perftests.utils.ManualBenchmarkState.StatsReport; + +import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation; + +import static org.hamcrest.core.AnyOf.anyOf; +import static org.hamcrest.core.Is.is; + +import android.app.ActivityManager.TaskSnapshot; +import android.app.ActivityTaskManager; +import android.app.IActivityTaskManager; +import android.content.ComponentName; +import android.content.Context; +import android.content.Intent; +import android.content.pm.PackageManager; +import android.graphics.Rect; +import android.os.RemoteException; +import android.os.SystemClock; +import android.perftests.utils.ManualBenchmarkState; +import android.perftests.utils.ManualBenchmarkState.ManualBenchmarkTest; +import android.perftests.utils.PerfManualStatusReporter; +import android.util.Pair; +import android.view.IRecentsAnimationController; +import android.view.IRecentsAnimationRunner; +import android.view.RemoteAnimationTarget; + +import androidx.test.filters.LargeTest; +import androidx.test.runner.lifecycle.Stage; + +import org.junit.AfterClass; +import org.junit.Assume; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Rule; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.concurrent.Semaphore; +import java.util.concurrent.TimeUnit; + +@RunWith(Parameterized.class) +@LargeTest +public class RecentsAnimationPerfTest extends WindowManagerPerfTestBase { + private static Intent sRecentsIntent; + + @Rule + public final PerfManualStatusReporter mPerfStatusReporter = new PerfManualStatusReporter(); + + @Rule + public final PerfTestActivityRule mActivityRule = + new PerfTestActivityRule(true /* launchActivity */); + + private long mMeasuredTimeNs; + + /** + * Used to skip each test method if there is error. It cannot be raised in static setup because + * that will break the amount of target method count. + */ + private static Exception sSetUpClassException; + + @Parameterized.Parameter(0) + public int intervalBetweenOperations; + + @Parameterized.Parameters(name = "interval{0}ms") + public static Collection<Object[]> getParameters() { + return Arrays.asList(new Object[][] { + { 0 }, + { 100 }, + { 300 }, + }); + } + + @BeforeClass + public static void setUpClass() { + // Get the permission to invoke startRecentsActivity. + sUiAutomation.adoptShellPermissionIdentity(); + + final Context context = getInstrumentation().getContext(); + final PackageManager pm = context.getPackageManager(); + final ComponentName defaultHome = pm.getHomeActivities(new ArrayList<>()); + + try { + final ComponentName recentsComponent = + ComponentName.unflattenFromString(context.getResources().getString( + com.android.internal.R.string.config_recentsComponentName)); + final int enabledState = pm.getComponentEnabledSetting(recentsComponent); + Assume.assumeThat(enabledState, anyOf( + is(PackageManager.COMPONENT_ENABLED_STATE_DEFAULT), + is(PackageManager.COMPONENT_ENABLED_STATE_ENABLED))); + + final boolean homeIsRecents = + recentsComponent.getPackageName().equals(defaultHome.getPackageName()); + sRecentsIntent = + new Intent().setComponent(homeIsRecents ? defaultHome : recentsComponent); + } catch (Exception e) { + sSetUpClassException = e; + } + } + + @AfterClass + public static void tearDownClass() { + sSetUpClassException = null; + sUiAutomation.dropShellPermissionIdentity(); + } + + @Before + public void setUp() { + Assume.assumeNoException(sSetUpClassException); + } + + /** Simulate the timing of touch. */ + private void makeInterval() { + SystemClock.sleep(intervalBetweenOperations); + } + + /** + * <pre> + * Steps: + * (1) Start recents activity (only make it visible). + * (2) Finish animation, take turns to execute (a), (b). + * (a) Move recents activity to top. + * ({@link com.android.server.wm.RecentsAnimationController#REORDER_MOVE_TO_TOP}) + * Move test app to top by startActivityFromRecents. + * (b) Cancel (it is similar to swipe a little distance and give up to enter recents). + * ({@link com.android.server.wm.RecentsAnimationController#REORDER_MOVE_TO_ORIGINAL_POSITION}) + * (3) Loop (1). + * </pre> + */ + @Test + @ManualBenchmarkTest( + warmupDurationNs = TIME_1_S_IN_NS, + targetTestDurationNs = TIME_5_S_IN_NS, + statsReport = @StatsReport(flags = StatsReport.FLAG_ITERATION | StatsReport.FLAG_MEAN + | StatsReport.FLAG_COEFFICIENT_VAR)) + public void testRecentsAnimation() throws Throwable { + final ManualBenchmarkState state = mPerfStatusReporter.getBenchmarkState(); + final IActivityTaskManager atm = ActivityTaskManager.getService(); + + final ArrayList<Pair<String, Boolean>> finishCases = new ArrayList<>(); + // Real launch the recents activity. + finishCases.add(new Pair<>("finishMoveToTop", true)); + // Return to the original top. + finishCases.add(new Pair<>("finishCancel", false)); + + // Ensure startRecentsActivity won't be called before finishing the animation. + final Semaphore recentsSemaphore = new Semaphore(1); + + final int testActivityTaskId = mActivityRule.getActivity().getTaskId(); + final IRecentsAnimationRunner.Stub anim = new IRecentsAnimationRunner.Stub() { + int mIteration; + + @Override + public void onAnimationStart(IRecentsAnimationController controller, + RemoteAnimationTarget[] apps, RemoteAnimationTarget[] wallpapers, + Rect homeContentInsets, Rect minimizedHomeBounds) throws RemoteException { + final Pair<String, Boolean> finishCase = finishCases.get(mIteration++ % 2); + final boolean moveRecentsToTop = finishCase.second; + makeInterval(); + + long startTime = SystemClock.elapsedRealtimeNanos(); + controller.finish(moveRecentsToTop, false /* sendUserLeaveHint */); + final long elapsedTimeNsOfFinish = SystemClock.elapsedRealtimeNanos() - startTime; + mMeasuredTimeNs += elapsedTimeNsOfFinish; + state.addExtraResult(finishCase.first, elapsedTimeNsOfFinish); + + if (moveRecentsToTop) { + mActivityRule.waitForIdleSync(Stage.STOPPED); + + startTime = SystemClock.elapsedRealtimeNanos(); + atm.startActivityFromRecents(testActivityTaskId, null /* options */); + final long elapsedTimeNs = SystemClock.elapsedRealtimeNanos() - startTime; + mMeasuredTimeNs += elapsedTimeNs; + state.addExtraResult("startFromRecents", elapsedTimeNs); + + mActivityRule.waitForIdleSync(Stage.RESUMED); + } + + makeInterval(); + recentsSemaphore.release(); + } + + @Override + public void onAnimationCanceled(TaskSnapshot taskSnapshot) throws RemoteException { + Assume.assumeNoException( + new AssertionError("onAnimationCanceled should not be called")); + } + + @Override + public void onTaskAppeared(RemoteAnimationTarget app) throws RemoteException { + /* no-op */ + } + }; + + recentsSemaphore.tryAcquire(); + while (state.keepRunning(mMeasuredTimeNs)) { + mMeasuredTimeNs = 0; + + final long startTime = SystemClock.elapsedRealtimeNanos(); + atm.startRecentsActivity(sRecentsIntent, null /* unused */, anim); + final long elapsedTimeNsOfStart = SystemClock.elapsedRealtimeNanos() - startTime; + mMeasuredTimeNs += elapsedTimeNsOfStart; + state.addExtraResult("start", elapsedTimeNsOfStart); + + // Ensure the animation callback is done. + Assume.assumeTrue(recentsSemaphore.tryAcquire(TIME_5_S_IN_NS, TimeUnit.NANOSECONDS)); + } + } +} |