From 84c664162f36447d0a28abef870651f4105ea7cf Mon Sep 17 00:00:00 2001 From: Riddle Hsu Date: Fri, 28 Oct 2022 21:16:04 +0800 Subject: [PATCH] Add transition latency test for activity switch in the same task To track the window drawn time and transition start time without task switch. Bug: 256141667 Test: atest WmPerfTests:android.wm.InTaskTransitionTest Change-Id: I940971e04531328f27f8f4d23fbf648ac428c718 --- .../windowmanager/AndroidManifest.xml | 7 + .../src/android/wm/InTaskTransitionTest.java | 140 ++++++++++++++++++ .../android/wm/WindowManagerPerfTestBase.java | 46 ++++++ 3 files changed, 193 insertions(+) create mode 100644 apct-tests/perftests/windowmanager/src/android/wm/InTaskTransitionTest.java diff --git a/apct-tests/perftests/windowmanager/AndroidManifest.xml b/apct-tests/perftests/windowmanager/AndroidManifest.xml index 95ede345fbee0..532a0fcfc92b7 100644 --- a/apct-tests/perftests/windowmanager/AndroidManifest.xml +++ b/apct-tests/perftests/windowmanager/AndroidManifest.xml @@ -17,6 +17,10 @@ package="com.android.perftests.wm"> + + + + @@ -26,6 +30,9 @@ + + 0) { + state.addExtraResult("transitionDelayMs", metrics.mTransitionDelayMs); + } + if (metrics.mWindowsDrawnDelayMs > 0) { + state.addExtraResult("windowsDrawnDelayMs", metrics.mWindowsDrawnDelayMs); + } + } + } + + @Override + public void onResult(Bundle result) { + // The test activity is destroyed. + synchronized (mMetricsReader) { + mMetricsReader.notifyAll(); + } + } + + /** The test activity runs on a different process to trigger metrics logs. */ + public static class TestActivity extends Activity implements Runnable { + static final String CALLBACK = "callback"; + + private RemoteCallback mCallback; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + mCallback = getIntent().getParcelableExtra(CALLBACK, RemoteCallback.class); + if (mCallback != null) { + Looper.myLooper().getQueue().addIdleHandler(() -> { + new Thread(this).start(); + return false; + }); + } + } + + @Override + public void run() { + // Wait until transition animation is finished and then finish self. + try { + WindowManagerGlobal.getWindowManagerService() + .syncInputTransactions(true /* waitForAnimations */); + } catch (RemoteException e) { + e.rethrowFromSystemServer(); + } + finish(); + } + + @Override + protected void onDestroy() { + super.onDestroy(); + if (mCallback != null) { + getMainThreadHandler().post(() -> mCallback.sendResult(null)); + } + } + } +} diff --git a/apct-tests/perftests/windowmanager/src/android/wm/WindowManagerPerfTestBase.java b/apct-tests/perftests/windowmanager/src/android/wm/WindowManagerPerfTestBase.java index 4b1982f600921..aea0326ec9a28 100644 --- a/apct-tests/perftests/windowmanager/src/android/wm/WindowManagerPerfTestBase.java +++ b/apct-tests/perftests/windowmanager/src/android/wm/WindowManagerPerfTestBase.java @@ -18,10 +18,17 @@ package android.wm; import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation; +import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.APP_TRANSITION; +import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.APP_TRANSITION_DELAY_MS; +import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.APP_TRANSITION_WINDOWS_DRAWN_DELAY_MS; + import android.app.Activity; import android.content.Intent; +import android.metrics.LogMaker; +import android.metrics.MetricsReader; import android.perftests.utils.PerfTestActivity; import android.perftests.utils.WindowPerfTestBase; +import android.util.SparseArray; import androidx.test.runner.lifecycle.ActivityLifecycleCallback; import androidx.test.runner.lifecycle.ActivityLifecycleMonitorRegistry; @@ -31,6 +38,7 @@ import org.junit.runner.Description; import org.junit.runners.model.Statement; import java.io.File; +import java.util.ArrayList; import java.util.concurrent.TimeUnit; public class WindowManagerPerfTestBase extends WindowPerfTestBase { @@ -124,4 +132,42 @@ public class WindowManagerPerfTestBase extends WindowPerfTestBase { } } } + + static class TransitionMetricsReader { + final MetricsReader mMetricsReader = new MetricsReader(); + + static class TransitionMetrics { + int mTransitionDelayMs; + int mWindowsDrawnDelayMs; + } + + TransitionMetrics[] getMetrics() { + mMetricsReader.read(0); + final ArrayList logs = new ArrayList<>(); + final LogMaker logTemplate = new LogMaker(APP_TRANSITION); + while (mMetricsReader.hasNext()) { + final LogMaker b = mMetricsReader.next(); + if (logTemplate.isSubsetOf(b)) { + logs.add(b); + } + } + + final TransitionMetrics[] infoArray = new TransitionMetrics[logs.size()]; + for (int i = 0; i < infoArray.length; i++) { + final LogMaker log = logs.get(i); + final SparseArray data = log.getEntries(); + final TransitionMetrics info = new TransitionMetrics(); + infoArray[i] = info; + info.mTransitionDelayMs = + (int) data.get(APP_TRANSITION_DELAY_MS, -1); + info.mWindowsDrawnDelayMs = + (int) data.get(APP_TRANSITION_WINDOWS_DRAWN_DELAY_MS, -1); + } + return infoArray; + } + + void setCheckpoint() { + mMetricsReader.checkpoint(); + } + } }