summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Alexus Allen <alexuseallen@google.com> 2022-07-07 00:23:16 +0000
committer Vishnu Nair <vishnun@google.com> 2022-08-31 23:07:49 +0000
commit1177f3cfc2040c0da62e752ea3de4ddec977398d (patch)
tree0600461927f413112f8fadbe65e4d95d7d3224ea
parent1f8fded51211d8c41f79ba4c54454f2093df5434 (diff)
DO NOT MERGE: Add SurfaceFlingerPerfTests
cherry-pick following change ids from U so we can get a performance baseline in t-qpr I4577987a8c06243b58f3982b379540104ca19a10 Ic8f07222c8307223c030dab08f4acd3eb18e18aa Ic2b49ddbba9d27a8f9ac8015870a1c4aa86014f6 I28e280b8df2d7140fb51fb05fd4e897e23478143 I89c75c956d6aa644367a834453e80c550d351fc2 I3c273a71ed29d5011848517b2bff81c1f3b5b80d Test: atest SurfaceFlingerPerfTests Bug: b/230039226 Ignore-AOSP-First: New folder that does not exist within AOSP. Change-Id: If31b1b573faeed269cf2cc8c7e483e4c5a351dba
-rw-r--r--apct-tests/perftests/surfaceflinger/Android.bp40
-rw-r--r--apct-tests/perftests/surfaceflinger/AndroidManifest.xml37
-rw-r--r--apct-tests/perftests/surfaceflinger/AndroidTest.xml79
-rw-r--r--apct-tests/perftests/surfaceflinger/OWNERS1
-rw-r--r--apct-tests/perftests/surfaceflinger/README.md34
-rw-r--r--apct-tests/perftests/surfaceflinger/src/android/surfaceflinger/BufferFlinger.java79
-rw-r--r--apct-tests/perftests/surfaceflinger/src/android/surfaceflinger/SurfaceFlingerPerfTest.java228
-rw-r--r--apct-tests/perftests/surfaceflinger/src/android/surfaceflinger/SurfaceFlingerTestActivity.java82
8 files changed, 580 insertions, 0 deletions
diff --git a/apct-tests/perftests/surfaceflinger/Android.bp b/apct-tests/perftests/surfaceflinger/Android.bp
new file mode 100644
index 000000000000..0c28bcef469c
--- /dev/null
+++ b/apct-tests/perftests/surfaceflinger/Android.bp
@@ -0,0 +1,40 @@
+// Copyright (C) 2022 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 {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_base_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_base_license"],
+}
+
+android_test {
+ name: "SurfaceFlingerPerfTests",
+ srcs: ["src/**/*.java"],
+ libs: ["android.test.runner.stubs"],
+ static_libs: [
+ "androidx.test.rules",
+ "androidx.test.ext.junit",
+ "androidx.annotation_annotation",
+ "apct-perftests-utils",
+ "collector-device-lib",
+ "platform-test-annotations",
+ ],
+ test_suites: ["device-tests"],
+ data: [":perfetto_artifacts"],
+ platform_apis: true,
+ certificate: "platform",
+}
diff --git a/apct-tests/perftests/surfaceflinger/AndroidManifest.xml b/apct-tests/perftests/surfaceflinger/AndroidManifest.xml
new file mode 100644
index 000000000000..26f25863f055
--- /dev/null
+++ b/apct-tests/perftests/surfaceflinger/AndroidManifest.xml
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2022 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.
+-->
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="android.perftests.surfaceflinger">
+
+ <!-- permission needed to write perfetto trace and read/write simpleperf report -->
+ <uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE" />
+ <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
+
+ <application android:label="SurfaceFlingerPerfTests">
+ <uses-library android:name="android.test.runner" />
+ <activity android:name="android.surfaceflinger.SurfaceFlingerTestActivity"
+ android:exported="true">
+
+ <intent-filter>
+ <action android:name="com.android.perftests.core.PERFTEST" />
+ </intent-filter>
+ </activity>
+ </application>
+
+ <instrumentation android:name="androidx.test.runner.AndroidJUnitRunner"
+ android:targetPackage="android.perftests.surfaceflinger">
+ </instrumentation>
+</manifest>
diff --git a/apct-tests/perftests/surfaceflinger/AndroidTest.xml b/apct-tests/perftests/surfaceflinger/AndroidTest.xml
new file mode 100644
index 000000000000..53e5d99409e2
--- /dev/null
+++ b/apct-tests/perftests/surfaceflinger/AndroidTest.xml
@@ -0,0 +1,79 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2022 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.
+-->
+<configuration description="Runs SurfaceFlingerPerfTests metric instrumentation.">
+ <option name="test-suite-tag" value="apct" />
+ <option name="test-suite-tag" value="apct-metric-instrumentation" />
+ <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
+ <option name="cleanup-apks" value="true" />
+ <option name="install-arg" value="-t" />
+ <option name="test-file-name" value="SurfaceFlingerPerfTests.apk" />
+ </target_preparer>
+
+ <target_preparer class="com.android.tradefed.targetprep.DeviceSetup">
+ <option name="force-skip-system-props" value="true" />
+ <option name="run-command" value="input keyevent KEYCODE_WAKEUP" />
+ <option name="run-command" value="cmd window dismiss-keyguard" />
+ <option name="run-command" value="cmd package compile -m speed android.perftests.surfaceflinger" />
+ </target_preparer>
+
+ <!-- Needed for pushing the trace config file -->
+ <target_preparer class="com.android.tradefed.targetprep.RootTargetPreparer"/>
+ <target_preparer class="com.android.tradefed.targetprep.PushFilePreparer">
+ <option name="push-file" key="trace_config_detailed.textproto" value="/data/misc/perfetto-traces/trace_config.textproto" />
+ </target_preparer>
+
+ <!-- Needed for storing the perfetto trace files in the sdcard/test_results-->
+ <option name="isolated-storage" value="false" />
+
+ <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
+ <option name="runner" value="androidx.test.runner.AndroidJUnitRunner" />
+ <option name="package" value="android.perftests.surfaceflinger" />
+ <option name="hidden-api-checks" value="false"/>
+
+ <!-- Listener related args for collecting the traces and waiting for the device to stabilize. -->
+ <option name="device-listeners" value="android.device.collectors.ProcLoadListener,android.device.collectors.PerfettoListener,android.device.collectors.SimpleperfListener" />
+
+ <!-- Guarantee that user defined RunListeners will be running before any of the default listeners defined in this runner. -->
+ <option name="instrumentation-arg" key="newRunListenerMode" value="true" />
+
+ <!-- PerfettoListener related arguments -->
+ <option name="instrumentation-arg" key="perfetto_config_text_proto" value="true" />
+ <option name="instrumentation-arg" key="perfetto_config_file" value="trace_config.textproto" />
+
+ <!-- SimpleperfListener related arguments -->
+ <option name="instrumentation-arg" key="report" value="true" />
+ <option name="instrumentation-arg" key="arguments" value="&quot;&quot;" />
+ <option name="instrumentation-arg" key="events_to_record" value="instructions,cpu-cycles,raw-l3d-cache-refill,sched:sched_waking" />
+ <option name="instrumentation-arg" key="processes_to_record" value="surfaceflinger" />
+ <option name="instrumentation-arg" key="symbols_to_report" value="&quot;android::SurfaceFlinger::commit(;android::SurfaceFlinger::composite(&quot;" />
+
+ <!-- ProcLoadListener related arguments -->
+ <!-- Wait for device last minute threshold to reach 3 with 2 minute timeout before starting the test run -->
+ <option name="instrumentation-arg" key="procload-collector:per_run" value="true" />
+ <option name="instrumentation-arg" key="proc-loadavg-threshold" value="3" />
+ <option name="instrumentation-arg" key="proc-loadavg-timeout" value="120000" />
+ <option name="instrumentation-arg" key="proc-loadavg-interval" value="10000" />
+
+ </test>
+
+ <metrics_collector class="com.android.tradefed.device.metric.FilePullerLogCollector">
+ <option name="directory-keys" value="/data/local/tmp/SurfaceFlingerPerfTests" />
+ <!-- Needed for pulling the collected trace config on to the host -->
+ <option name="pull-pattern-keys" value="perfetto_file_path" />
+ <option name="pull-pattern-keys" value="simpleperf_file_path" />
+ </metrics_collector>
+
+</configuration>
diff --git a/apct-tests/perftests/surfaceflinger/OWNERS b/apct-tests/perftests/surfaceflinger/OWNERS
new file mode 100644
index 000000000000..0862c05e0ee4
--- /dev/null
+++ b/apct-tests/perftests/surfaceflinger/OWNERS
@@ -0,0 +1 @@
+include /services/core/java/com/android/server/wm/OWNERS
diff --git a/apct-tests/perftests/surfaceflinger/README.md b/apct-tests/perftests/surfaceflinger/README.md
new file mode 100644
index 000000000000..0dec70f3cf18
--- /dev/null
+++ b/apct-tests/perftests/surfaceflinger/README.md
@@ -0,0 +1,34 @@
+## SurfaceFlinger performance tests
+
+### Precondition
+To reduce the variance of the test, if `perf-setup.sh` (platform_testing/scripts/perf-setup)
+is available, it is better to use the following instructions to lock CPU and GPU frequencies.
+```
+m perf-setup
+PERF_SETUP_PATH=/data/local/tmp/perf-setup.sh
+adb push $OUT/$PERF_SETUP_PATH $PERF_SETUP_PATH
+adb shell chmod +x $PERF_SETUP_PATH
+adb shell $PERF_SETUP_PATH
+```
+
+### Example to run
+Use `atest`
+```
+atest SurfaceFlingerPerfTests:SurfaceFlingerPerfTest -- \
+ --module-arg SurfaceFlingerPerfTests:instrumentation-arg:kill-bg:=true
+```
+Use `am instrument`
+```
+adb shell am instrument -w -r -e class android.surfaceflinger.SurfaceFlingerPerfTest \
+ -e kill-bg true \
+ com.android.perftests.surfaceflinger/androidx.test.runner.AndroidJUnitRunner
+```
+* `kill-bg` is optional.
+
+Test arguments
+- kill-bg
+ * boolean: Kill background process before running test.
+- profiling-iterations
+ * int: Run the extra iterations with enabling method profiling.
+- profiling-sampling
+ * int: The interval (0=trace each method, default is 10) of sample profiling in microseconds.
diff --git a/apct-tests/perftests/surfaceflinger/src/android/surfaceflinger/BufferFlinger.java b/apct-tests/perftests/surfaceflinger/src/android/surfaceflinger/BufferFlinger.java
new file mode 100644
index 000000000000..52fb8a6023f1
--- /dev/null
+++ b/apct-tests/perftests/surfaceflinger/src/android/surfaceflinger/BufferFlinger.java
@@ -0,0 +1,79 @@
+/*
+ * Copyright (C) 2022 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.surfaceflinger;
+
+import android.annotation.ColorInt;
+import android.graphics.Canvas;
+import android.graphics.GraphicBuffer;
+import android.graphics.PixelFormat;
+import android.hardware.HardwareBuffer;
+import android.hardware.SyncFence;
+import android.view.SurfaceControl;
+
+import java.util.concurrent.ArrayBlockingQueue;
+
+/**
+ * Allocates n amount of buffers to a SurfaceControl using a Queue implementation. Executes a
+ * releaseCallback so a buffer can be safely re-used.
+ *
+ * @hide
+ */
+public class BufferFlinger {
+ ArrayBlockingQueue<GraphicBuffer> mBufferQ;
+
+ public BufferFlinger(int numOfBuffers, @ColorInt int color) {
+ mBufferQ = new ArrayBlockingQueue<>(numOfBuffers);
+
+ while (numOfBuffers > 0) {
+ GraphicBuffer buffer = GraphicBuffer.create(500, 500,
+ PixelFormat.RGBA_8888,
+ GraphicBuffer.USAGE_HW_TEXTURE | GraphicBuffer.USAGE_HW_COMPOSER
+ | GraphicBuffer.USAGE_SW_WRITE_RARELY);
+
+ Canvas canvas = buffer.lockCanvas();
+ canvas.drawColor(color);
+ buffer.unlockCanvasAndPost(canvas);
+
+ mBufferQ.add(buffer);
+ numOfBuffers--;
+ }
+ }
+
+ public void addBuffer(SurfaceControl.Transaction t, SurfaceControl surfaceControl)
+ throws InterruptedException {
+ GraphicBuffer buffer = mBufferQ.take();
+ t.setBuffer(surfaceControl,
+ HardwareBuffer.createFromGraphicBuffer(buffer),
+ null,
+ (SyncFence fence) -> {
+ releaseCallback(fence, buffer);
+ });
+ }
+
+ public void releaseCallback(SyncFence fence, GraphicBuffer buffer) {
+ if (fence != null) {
+ fence.awaitForever();
+ }
+ mBufferQ.add(buffer);
+ }
+
+ public void freeBuffers() {
+ for (GraphicBuffer buffer : mBufferQ) {
+ buffer.destroy();
+ }
+ }
+}
diff --git a/apct-tests/perftests/surfaceflinger/src/android/surfaceflinger/SurfaceFlingerPerfTest.java b/apct-tests/perftests/surfaceflinger/src/android/surfaceflinger/SurfaceFlingerPerfTest.java
new file mode 100644
index 000000000000..45d164c96cd8
--- /dev/null
+++ b/apct-tests/perftests/surfaceflinger/src/android/surfaceflinger/SurfaceFlingerPerfTest.java
@@ -0,0 +1,228 @@
+/*
+ * Copyright (C) 2022 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.surfaceflinger;
+
+import android.graphics.Bitmap;
+import android.graphics.Color;
+import android.perftests.utils.BenchmarkState;
+import android.perftests.utils.PerfStatusReporter;
+import android.view.SurfaceControl;
+
+import androidx.test.ext.junit.rules.ActivityScenarioRule;
+import androidx.test.filters.LargeTest;
+import androidx.test.platform.app.InstrumentationRegistry;
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.RuleChain;
+import org.junit.runner.RunWith;
+
+import java.util.ArrayList;
+import java.util.Random;
+
+@LargeTest
+@RunWith(AndroidJUnit4.class)
+public class SurfaceFlingerPerfTest {
+ protected ActivityScenarioRule<SurfaceFlingerTestActivity> mActivityRule =
+ new ActivityScenarioRule<>(SurfaceFlingerTestActivity.class);
+ protected PerfStatusReporter mPerfStatusReporter = new PerfStatusReporter();
+ private SurfaceFlingerTestActivity mActivity;
+ static final int BUFFER_COUNT = 2;
+
+ @Rule
+ public final RuleChain mAllRules = RuleChain
+ .outerRule(mPerfStatusReporter)
+ .around(mActivityRule);
+ @Before
+ public void setup() {
+ mActivityRule.getScenario().onActivity(activity -> mActivity = activity);
+ }
+
+ @After
+ public void teardown() {
+ mSurfaceControls.forEach(SurfaceControl::release);
+ mByfferTrackers.forEach(BufferFlinger::freeBuffers);
+ }
+
+
+ private ArrayList<BufferFlinger> mByfferTrackers = new ArrayList<>();
+ private BufferFlinger createBufferTracker(int color) {
+ BufferFlinger bufferTracker = new BufferFlinger(BUFFER_COUNT, color);
+ mByfferTrackers.add(bufferTracker);
+ return bufferTracker;
+ }
+
+ private ArrayList<SurfaceControl> mSurfaceControls = new ArrayList<>();
+ private SurfaceControl createSurfaceControl() throws InterruptedException {
+ SurfaceControl sc = mActivity.createChildSurfaceControl();
+ mSurfaceControls.add(sc);
+ return sc;
+ }
+
+ @Test
+ public void singleBuffer() throws Exception {
+ SurfaceControl sc = createSurfaceControl();
+ BufferFlinger bufferTracker = createBufferTracker(Color.GREEN);
+ SurfaceControl.Transaction t = new SurfaceControl.Transaction();
+ bufferTracker.addBuffer(t, sc);
+ t.show(sc);
+
+ BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+ while (state.keepRunning()) {
+ bufferTracker.addBuffer(t, sc);
+ t.apply();
+ }
+ }
+
+ static int getRandomColorComponent() {
+ return new Random().nextInt(155) + 100;
+ }
+
+ @Test
+ public void multipleBuffers() throws Exception {
+ final int MAX_BUFFERS = 10;
+
+ SurfaceControl.Transaction t = new SurfaceControl.Transaction();
+ for (int i = 0; i < MAX_BUFFERS; i++) {
+ SurfaceControl sc = createSurfaceControl();
+ BufferFlinger bufferTracker = createBufferTracker(Color.argb(getRandomColorComponent(),
+ getRandomColorComponent(), getRandomColorComponent(),
+ getRandomColorComponent()));
+ bufferTracker.addBuffer(t, sc);
+ t.setPosition(sc, i * 10, i * 10);
+ t.show(sc);
+ }
+ t.apply(true);
+ BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+ while (state.keepRunning()) {
+ for (int i = 0; i < MAX_BUFFERS; i++) {
+ mByfferTrackers.get(i).addBuffer(t, mSurfaceControls.get(i));
+ }
+ t.apply();
+ }
+ }
+
+ @Test
+ public void multipleOpaqueBuffers() throws Exception {
+ final int MAX_BUFFERS = 10;
+
+ SurfaceControl.Transaction t = new SurfaceControl.Transaction();
+ for (int i = 0; i < MAX_BUFFERS; i++) {
+ SurfaceControl sc = createSurfaceControl();
+ BufferFlinger bufferTracker = createBufferTracker(Color.rgb(getRandomColorComponent(),
+ getRandomColorComponent(), getRandomColorComponent()));
+ bufferTracker.addBuffer(t, sc);
+ t.setOpaque(sc, true);
+ t.setPosition(sc, i * 10, i * 10);
+ t.show(sc);
+ }
+ t.apply(true);
+ BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+ while (state.keepRunning()) {
+ for (int i = 0; i < MAX_BUFFERS; i++) {
+ mByfferTrackers.get(i).addBuffer(t, mSurfaceControls.get(i));
+ }
+ t.apply();
+ }
+ }
+
+ @Test
+ public void geometryChanges() throws Exception {
+ final int MAX_POSITION = 10;
+ final float MAX_SCALE = 2.0f;
+
+ SurfaceControl sc = createSurfaceControl();
+ BufferFlinger bufferTracker = createBufferTracker(Color.GREEN);
+ SurfaceControl.Transaction t = new SurfaceControl.Transaction();
+ bufferTracker.addBuffer(t, sc);
+ t.show(sc).apply(true);
+
+ int step = 0;
+ BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+ while (state.keepRunning()) {
+ step = ++step % MAX_POSITION;
+ t.setPosition(sc, step, step);
+ float scale = ((step * MAX_SCALE) / MAX_POSITION) + 0.5f;
+ t.setScale(sc, scale, scale);
+ t.apply();
+ }
+ }
+
+ @Test
+ public void geometryWithBufferChanges() throws Exception {
+ final int MAX_POSITION = 10;
+
+ SurfaceControl sc = createSurfaceControl();
+ BufferFlinger bufferTracker = createBufferTracker(Color.GREEN);
+ SurfaceControl.Transaction t = new SurfaceControl.Transaction();
+ bufferTracker.addBuffer(t, sc);
+ t.show(sc).apply(true);
+
+ int step = 0;
+ BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+ while (state.keepRunning()) {
+ step = ++step % MAX_POSITION;
+ t.setPosition(sc, step, step);
+ float scale = ((step * 2.0f) / MAX_POSITION) + 0.5f;
+ t.setScale(sc, scale, scale);
+ bufferTracker.addBuffer(t, sc);
+ t.apply();
+ }
+ }
+
+ @Test
+ public void addRemoveLayers() throws Exception {
+ SurfaceControl sc = createSurfaceControl();
+ BufferFlinger bufferTracker = createBufferTracker(Color.GREEN);
+ SurfaceControl.Transaction t = new SurfaceControl.Transaction();
+
+ BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+ while (state.keepRunning()) {
+ SurfaceControl childSurfaceControl = new SurfaceControl.Builder()
+ .setName("childLayer").setBLASTLayer().build();
+ bufferTracker.addBuffer(t, childSurfaceControl);
+ t.reparent(childSurfaceControl, sc);
+ t.apply();
+ t.remove(childSurfaceControl).apply();
+ }
+ }
+
+ @Test
+ public void displayScreenshot() throws Exception {
+ BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+ while (state.keepRunning()) {
+ Bitmap screenshot =
+ InstrumentationRegistry.getInstrumentation().getUiAutomation().takeScreenshot();
+ screenshot.recycle();
+ }
+ }
+
+ @Test
+ public void layerScreenshot() throws Exception {
+ BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+ while (state.keepRunning()) {
+ Bitmap screenshot =
+ InstrumentationRegistry.getInstrumentation().getUiAutomation().takeScreenshot(
+ mActivity.getWindow());
+ screenshot.recycle();
+ }
+ }
+
+}
diff --git a/apct-tests/perftests/surfaceflinger/src/android/surfaceflinger/SurfaceFlingerTestActivity.java b/apct-tests/perftests/surfaceflinger/src/android/surfaceflinger/SurfaceFlingerTestActivity.java
new file mode 100644
index 000000000000..832a0cd1e917
--- /dev/null
+++ b/apct-tests/perftests/surfaceflinger/src/android/surfaceflinger/SurfaceFlingerTestActivity.java
@@ -0,0 +1,82 @@
+/*
+ * Copyright (C) 2022 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.surfaceflinger;
+
+import android.app.Activity;
+import android.content.Context;
+import android.os.Bundle;
+import android.view.SurfaceControl;
+import android.view.SurfaceHolder;
+import android.view.SurfaceView;
+import android.view.WindowManager;
+
+import java.util.concurrent.CountDownLatch;
+
+/**
+ * A simple activity used for testing, e.g. performance of activity switching, or as a base
+ * container of testing view.
+ */
+public class SurfaceFlingerTestActivity extends Activity {
+ public TestSurfaceView mTestSurfaceView;
+ SurfaceControl mSurfaceControl;
+ CountDownLatch mIsReady = new CountDownLatch(1);
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
+ mTestSurfaceView = new TestSurfaceView(this);
+ setContentView(mTestSurfaceView);
+ }
+
+ public SurfaceControl createChildSurfaceControl() throws InterruptedException {
+ return mTestSurfaceView.getChildSurfaceControlHelper();
+ }
+
+ public class TestSurfaceView extends SurfaceView {
+ public TestSurfaceView(Context context) {
+ super(context);
+ SurfaceHolder holder = getHolder();
+ holder.addCallback(new SurfaceHolder.Callback() {
+ @Override
+ public void surfaceCreated(SurfaceHolder holder) {
+ mIsReady.countDown();
+ }
+ @Override
+ public void surfaceChanged(SurfaceHolder holder, int format, int width,
+ int height) {}
+ @Override
+ public void surfaceDestroyed(SurfaceHolder holder) {
+ }
+ });
+ }
+
+ public SurfaceControl getChildSurfaceControlHelper() throws InterruptedException {
+ mIsReady.await();
+ SurfaceHolder holder = getHolder();
+
+ // check to see if surface is valid
+ if (holder.getSurface().isValid()) {
+ mSurfaceControl = getSurfaceControl();
+ }
+ return new SurfaceControl.Builder()
+ .setName("ChildSurfaceControl")
+ .setParent(mSurfaceControl)
+ .build();
+ }
+ }
+}