/* * 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.view.WindowManager.LayoutParams.FLAG_LAYOUT_INSET_DECOR; import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN; 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.view.Display; import android.view.IWindowSession; import android.view.InputChannel; import android.view.InsetsSourceControl; import android.view.InsetsState; import android.view.View; import android.view.WindowInsets; import android.view.WindowManager; import android.view.WindowManagerGlobal; import androidx.test.filters.LargeTest; import com.android.internal.view.BaseIWindow; import org.junit.AfterClass; import org.junit.BeforeClass; import org.junit.Rule; import org.junit.Test; @LargeTest public class WindowAddRemovePerfTest extends WindowManagerPerfTestBase implements ManualBenchmarkState.CustomizedIterationListener { @Rule public final PerfManualStatusReporter mPerfStatusReporter = new PerfManualStatusReporter(); @BeforeClass public static void setUpClass() { // Get the permission to use most window types. getUiAutomation().adoptShellPermissionIdentity(); } @AfterClass public static void tearDownClass() { getUiAutomation().dropShellPermissionIdentity(); } /** The last customized iterations will provide the information of method profiling. */ @Override public void onStart(int iteration) { startProfiling(WindowAddRemovePerfTest.class.getSimpleName() + "_MethodTracing_" + iteration + ".trace"); } @Override public void onFinished(int iteration) { stopProfiling(); } @Test @ManualBenchmarkTest(warmupDurationNs = TIME_1_S_IN_NS, targetTestDurationNs = TIME_5_S_IN_NS) public void testAddRemoveWindow() throws Throwable { final ManualBenchmarkState state = mPerfStatusReporter.getBenchmarkState(); state.setCustomizedIterations(getProfilingIterations(), this); new TestWindow().runBenchmark(state); } private static class TestWindow extends BaseIWindow { final WindowManager.LayoutParams mLayoutParams = new WindowManager.LayoutParams(); final int mRequestedVisibleTypes = WindowInsets.Type.defaultVisible(); final InsetsState mOutInsetsState = new InsetsState(); final InsetsSourceControl.Array mOutControls = new InsetsSourceControl.Array(); final Rect mOutAttachedFrame = new Rect(); final float[] mOutSizeCompatScale = { 1f }; TestWindow() { mLayoutParams.setTitle(TestWindow.class.getName()); mLayoutParams.type = WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY; // Simulate as common phone window. mLayoutParams.flags = FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR; } void runBenchmark(ManualBenchmarkState state) throws RemoteException { final IWindowSession session = WindowManagerGlobal.getWindowSession(); long elapsedTimeNs = 0; while (state.keepRunning(elapsedTimeNs)) { // InputChannel cannot be reused. final InputChannel inputChannel = new InputChannel(); long startTime = SystemClock.elapsedRealtimeNanos(); session.addToDisplay(this, mLayoutParams, View.VISIBLE, Display.DEFAULT_DISPLAY, mRequestedVisibleTypes, inputChannel, mOutInsetsState, mOutControls, mOutAttachedFrame, mOutSizeCompatScale); final long elapsedTimeNsOfAdd = SystemClock.elapsedRealtimeNanos() - startTime; state.addExtraResult("add", elapsedTimeNsOfAdd); startTime = SystemClock.elapsedRealtimeNanos(); session.remove(this); final long elapsedTimeNsOfRemove = SystemClock.elapsedRealtimeNanos() - startTime; state.addExtraResult("remove", elapsedTimeNsOfRemove); elapsedTimeNs = elapsedTimeNsOfAdd + elapsedTimeNsOfRemove; inputChannel.dispose(); } } } }