summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRiddle Hsu <riddlehsu@google.com>2020-11-26 18:01:46 +0800
committerRiddle Hsu <riddlehsu@google.com>2020-12-07 19:26:40 +0800
commit700bdd58fdb3daec08199e8cd6b1055980b88b5d (patch)
treee511c91b2c0870438fca147bfeb11f8bfbd13d18
parent386bec73e4184820b421f03ce56929a3322cd8fc (diff)
Extract window related perf test base classes
Add WindowPerfTestBase and WindowPerfRunPreconditionBase into apct-perftests-utils. So window manager and input method manager can share the same functions. Bug: 174292015 Test: WmPerfTests ImePerfTests Change-Id: Ie2818536d6611d1ba5f4b6cd725cd2d4a95e1cac
-rw-r--r--apct-tests/perftests/inputmethod/src/android/inputmethod/ImePerfRunPrecondition.java130
-rw-r--r--apct-tests/perftests/inputmethod/src/android/inputmethod/ImePerfTest.java10
-rw-r--r--apct-tests/perftests/inputmethod/src/android/inputmethod/ImePerfTestBase.java122
-rw-r--r--apct-tests/perftests/utils/src/android/perftests/utils/WindowPerfRunPreconditionBase.java155
-rw-r--r--apct-tests/perftests/utils/src/android/perftests/utils/WindowPerfTestBase.java193
-rw-r--r--apct-tests/perftests/windowmanager/src/android/wm/InternalWindowOperationPerfTest.java13
-rw-r--r--apct-tests/perftests/windowmanager/src/android/wm/RecentsAnimationPerfTest.java6
-rw-r--r--apct-tests/perftests/windowmanager/src/android/wm/WindowAddRemovePerfTest.java4
-rw-r--r--apct-tests/perftests/windowmanager/src/android/wm/WindowManagerPerfTestBase.java138
-rw-r--r--apct-tests/perftests/windowmanager/src/android/wm/WmPerfRunListener.java134
10 files changed, 373 insertions, 532 deletions
diff --git a/apct-tests/perftests/inputmethod/src/android/inputmethod/ImePerfRunPrecondition.java b/apct-tests/perftests/inputmethod/src/android/inputmethod/ImePerfRunPrecondition.java
index fc48fd5271a8..4bfcadebc2d9 100644
--- a/apct-tests/perftests/inputmethod/src/android/inputmethod/ImePerfRunPrecondition.java
+++ b/apct-tests/perftests/inputmethod/src/android/inputmethod/ImePerfRunPrecondition.java
@@ -16,134 +16,8 @@
package android.inputmethod;
-import static android.app.WindowConfiguration.ACTIVITY_TYPE_ASSISTANT;
-import static android.app.WindowConfiguration.ACTIVITY_TYPE_RECENTS;
-import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
-import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED;
-import static android.inputmethod.ImePerfTestBase.executeShellCommand;
-import static android.inputmethod.ImePerfTestBase.runWithShellPermissionIdentity;
-
-import android.app.ActivityManager;
-import android.app.ActivityManager.RunningAppProcessInfo;
-import android.app.ActivityTaskManager;
-import android.content.Context;
-import android.inputmethod.ImePerfTestBase.SettingsSession;
-import android.os.BatteryManager;
-import android.os.Bundle;
-import android.os.SystemClock;
-import android.provider.Settings;
-import android.util.Log;
-import android.view.WindowManagerPolicyConstants;
-
-import androidx.test.platform.app.InstrumentationRegistry;
-
-import com.android.internal.policy.PhoneWindow;
-
-import org.junit.runner.Description;
-import org.junit.runner.Result;
-import org.junit.runner.notification.RunListener;
-
-import java.util.List;
+import android.perftests.utils.WindowPerfRunPreconditionBase;
/** Prepare the preconditions before running performance test. */
-public class ImePerfRunPrecondition extends RunListener {
- private static final String TAG = ImePerfRunPrecondition.class.getSimpleName();
-
- private static final String ARGUMENT_LOG_ONLY = "log";
- private static final String ARGUMENT_KILL_BACKGROUND = "kill-bg";
- private static final String ARGUMENT_PROFILING_ITERATIONS = "profiling-iterations";
- private static final String ARGUMENT_PROFILING_SAMPLING = "profiling-sampling";
- private static final String DEFAULT_PROFILING_ITERATIONS = "10";
- private static final String DEFAULT_PROFILING_SAMPLING_US = "10";
- private static final long KILL_BACKGROUND_WAIT_MS = 3000;
-
- /** The requested iterations to run with method profiling. */
- static int sProfilingIterations;
-
- /** The interval of sample profiling in microseconds. */
- static int sSamplingIntervalUs;
-
- private final Context mContext = InstrumentationRegistry.getInstrumentation().getContext();
- private long mWaitPreconditionDoneMs = 500;
-
- private final SettingsSession<Integer> mStayOnWhilePluggedInSetting = new SettingsSession<>(
- Settings.Global.getInt(mContext.getContentResolver(),
- Settings.Global.STAY_ON_WHILE_PLUGGED_IN, 0),
- value -> executeShellCommand(String.format("settings put global %s %d",
- Settings.Global.STAY_ON_WHILE_PLUGGED_IN, value)));
-
- private final SettingsSession<Integer> mNavigationModeSetting = new SettingsSession<>(
- mContext.getResources().getInteger(
- com.android.internal.R.integer.config_navBarInteractionMode),
- value -> {
- final String navOverlay;
- switch (value) {
- case WindowManagerPolicyConstants.NAV_BAR_MODE_GESTURAL:
- default:
- navOverlay = WindowManagerPolicyConstants.NAV_BAR_MODE_GESTURAL_OVERLAY;
- break;
- }
- executeShellCommand("cmd overlay enable-exclusive " + navOverlay);
- });
-
- /** It only executes once before all tests. */
- @Override
- public void testRunStarted(Description description) {
- final Bundle arguments = InstrumentationRegistry.getArguments();
- // If true, it only logs the method names without running.
- final boolean skip = Boolean.parseBoolean(arguments.getString(ARGUMENT_LOG_ONLY, "false"));
- Log.i(TAG, "arguments=" + arguments);
- if (skip) {
- return;
- }
- sProfilingIterations = Integer.parseInt(
- arguments.getString(ARGUMENT_PROFILING_ITERATIONS, DEFAULT_PROFILING_ITERATIONS));
- sSamplingIntervalUs = Integer.parseInt(
- arguments.getString(ARGUMENT_PROFILING_SAMPLING, DEFAULT_PROFILING_SAMPLING_US));
-
- // Use same navigation mode (gesture navigation) across all devices and tests
- // for consistency.
- mNavigationModeSetting.set(WindowManagerPolicyConstants.NAV_BAR_MODE_GESTURAL);
- // Keep the device awake during testing.
- mStayOnWhilePluggedInSetting.set(BatteryManager.BATTERY_PLUGGED_ANY);
-
- runWithShellPermissionIdentity(() -> {
- final ActivityTaskManager atm = mContext.getSystemService(ActivityTaskManager.class);
- atm.removeAllVisibleRecentTasks();
- atm.removeRootTasksWithActivityTypes(new int[] { ACTIVITY_TYPE_STANDARD,
- ACTIVITY_TYPE_ASSISTANT, ACTIVITY_TYPE_RECENTS, ACTIVITY_TYPE_UNDEFINED });
- });
- PhoneWindow.sendCloseSystemWindows(mContext, "ImePerfTests");
-
- if (Boolean.parseBoolean(arguments.getString(ARGUMENT_KILL_BACKGROUND))) {
- runWithShellPermissionIdentity(this::killBackgroundProcesses);
- mWaitPreconditionDoneMs = KILL_BACKGROUND_WAIT_MS;
- }
- // Wait a while for the precondition setup to complete.
- SystemClock.sleep(mWaitPreconditionDoneMs);
- }
-
- private void killBackgroundProcesses() {
- Log.i(TAG, "Killing background processes...");
- final ActivityManager am = mContext.getSystemService(ActivityManager.class);
- final List<RunningAppProcessInfo> processes = am.getRunningAppProcesses();
- if (processes == null) {
- return;
- }
- for (RunningAppProcessInfo processInfo : processes) {
- if (processInfo.importanceReasonCode == RunningAppProcessInfo.REASON_UNKNOWN
- && processInfo.importance > RunningAppProcessInfo.IMPORTANCE_SERVICE) {
- for (String pkg : processInfo.pkgList) {
- am.forceStopPackage(pkg);
- }
- }
- }
- }
-
- /** It only executes once after all tests. */
- @Override
- public void testRunFinished(Result result) {
- mNavigationModeSetting.close();
- mStayOnWhilePluggedInSetting.close();
- }
+public class ImePerfRunPrecondition extends WindowPerfRunPreconditionBase {
}
diff --git a/apct-tests/perftests/inputmethod/src/android/inputmethod/ImePerfTest.java b/apct-tests/perftests/inputmethod/src/android/inputmethod/ImePerfTest.java
index 2b7af2f0a11e..689fb3645daf 100644
--- a/apct-tests/perftests/inputmethod/src/android/inputmethod/ImePerfTest.java
+++ b/apct-tests/perftests/inputmethod/src/android/inputmethod/ImePerfTest.java
@@ -29,7 +29,6 @@ import android.app.Activity;
import android.content.ComponentName;
import android.content.Context;
import android.inputmethodservice.InputMethodService;
-import android.os.ParcelFileDescriptor;
import android.os.Process;
import android.os.SystemClock;
import android.perftests.utils.ManualBenchmarkState;
@@ -420,23 +419,20 @@ public class ImePerfTest extends ImePerfTestBase
});
}
- private void startAsyncAtrace() throws IOException {
+ private void startAsyncAtrace() {
mIsTraceStarted = true;
// IMF uses 'wm' component for trace in InputMethodService, InputMethodManagerService,
// WindowManagerService and 'view' for client window (InsetsController).
// TODO(b/167947940): Consider a separate input_method atrace
- UI_AUTOMATION.executeShellCommand("atrace -b 32768 --async_start wm view");
- // Avoid atrace isn't ready immediately.
- SystemClock.sleep(TimeUnit.NANOSECONDS.toMillis(TIME_1_S_IN_NS));
+ startAsyncAtrace("wm view");
}
private void stopAsyncAtrace() {
if (!mIsTraceStarted) {
return;
}
- final ParcelFileDescriptor pfd = UI_AUTOMATION.executeShellCommand("atrace --async_stop");
mIsTraceStarted = false;
- final InputStream inputStream = new ParcelFileDescriptor.AutoCloseInputStream(pfd);
+ final InputStream inputStream = stopAsyncAtraceWithStream();
try (BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream))) {
String line;
while ((line = reader.readLine()) != null) {
diff --git a/apct-tests/perftests/inputmethod/src/android/inputmethod/ImePerfTestBase.java b/apct-tests/perftests/inputmethod/src/android/inputmethod/ImePerfTestBase.java
index 1a861d7ba87b..f70d79cf9153 100644
--- a/apct-tests/perftests/inputmethod/src/android/inputmethod/ImePerfTestBase.java
+++ b/apct-tests/perftests/inputmethod/src/android/inputmethod/ImePerfTestBase.java
@@ -18,135 +18,21 @@ package android.inputmethod;
import static android.perftests.utils.PerfTestActivity.INTENT_EXTRA_ADD_EDIT_TEXT;
-import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;
-
-import android.app.KeyguardManager;
-import android.app.UiAutomation;
-import android.content.Context;
import android.content.Intent;
-import android.os.ParcelFileDescriptor;
-import android.os.PowerManager;
import android.perftests.utils.PerfTestActivity;
+import android.perftests.utils.WindowPerfTestBase;
-
-import androidx.test.rule.ActivityTestRule;
-
-import org.junit.BeforeClass;
-
-import java.io.ByteArrayOutputStream;
-import java.io.FileInputStream;
-import java.io.IOException;
-import java.util.Objects;
-import java.util.function.Consumer;
-
-public class ImePerfTestBase {
- static final UiAutomation UI_AUTOMATION = getInstrumentation().getUiAutomation();
- static final long NANOS_PER_S = 1000L * 1000 * 1000;
- static final long TIME_1_S_IN_NS = 1 * NANOS_PER_S;
+public class ImePerfTestBase extends WindowPerfTestBase {
static final long TIMEOUT_1_S_IN_MS = 1 * 1000L;
- @BeforeClass
- public static void setUpOnce() {
- final Context context = getInstrumentation().getContext();
-
- if (!context.getSystemService(PowerManager.class).isInteractive()
- || context.getSystemService(KeyguardManager.class).isKeyguardLocked()) {
- executeShellCommand("input keyevent KEYCODE_WAKEUP");
- executeShellCommand("wm dismiss-keyguard");
- }
- context.startActivity(new Intent(Intent.ACTION_MAIN)
- .addCategory(Intent.CATEGORY_HOME).setFlags(Intent.FLAG_ACTIVITY_NEW_TASK));
- }
-
- /**
- * Executes shell command with reading the output. It may also used to block until the current
- * command is completed.
- */
- static ByteArrayOutputStream executeShellCommand(String command) {
- final ParcelFileDescriptor pfd = UI_AUTOMATION.executeShellCommand(command);
- final byte[] buf = new byte[512];
- final ByteArrayOutputStream bytes = new ByteArrayOutputStream();
- int bytesRead;
- try (FileInputStream fis = new ParcelFileDescriptor.AutoCloseInputStream(pfd)) {
- while ((bytesRead = fis.read(buf)) != -1) {
- bytes.write(buf, 0, bytesRead);
- }
- } catch (IOException e) {
- throw new RuntimeException(e);
- }
- return bytes;
- }
-
- /** Returns how many iterations should run with method tracing. */
- static int getProfilingIterations() {
- return ImePerfRunPrecondition.sProfilingIterations;
- }
-
- static void runWithShellPermissionIdentity(Runnable runnable) {
- UI_AUTOMATION.adoptShellPermissionIdentity();
- try {
- runnable.run();
- } finally {
- UI_AUTOMATION.dropShellPermissionIdentity();
- }
- }
-
- static class SettingsSession<T> implements AutoCloseable {
- private final Consumer<T> mSetter;
- private final T mOriginalValue;
- private boolean mChanged;
-
- SettingsSession(T originalValue, Consumer<T> setter) {
- mOriginalValue = originalValue;
- mSetter = setter;
- }
-
- void set(T value) {
- if (Objects.equals(value, mOriginalValue)) {
- mChanged = false;
- return;
- }
- mSetter.accept(value);
- mChanged = true;
- }
-
- @Override
- public void close() {
- if (mChanged) {
- mSetter.accept(mOriginalValue);
- }
- }
- }
-
- /**
- * Provides an activity that keeps screen on and is able to wait for a stable lifecycle stage.
- */
- static class PerfTestActivityRule extends ActivityTestRule<PerfTestActivity> {
- private final Intent mStartIntent =
- new Intent(getInstrumentation().getTargetContext(), PerfTestActivity.class);
-
- PerfTestActivityRule() {
- this(false /* launchActivity */);
- }
-
- PerfTestActivityRule(boolean launchActivity) {
- super(PerfTestActivity.class, false /* initialTouchMode */, launchActivity);
- }
-
- @Override
- protected Intent getActivityIntent() {
- return mStartIntent;
- }
+ /** Provides an activity that contains an edit text view.*/
+ static class PerfTestActivityRule extends PerfTestActivityRuleBase {
@Override
public PerfTestActivity launchActivity(Intent intent) {
intent.putExtra(INTENT_EXTRA_ADD_EDIT_TEXT, true);
return super.launchActivity(intent);
}
-
- PerfTestActivity launchActivity() {
- return launchActivity(mStartIntent);
- }
}
static String[] buildArray(String[]... arrays) {
diff --git a/apct-tests/perftests/utils/src/android/perftests/utils/WindowPerfRunPreconditionBase.java b/apct-tests/perftests/utils/src/android/perftests/utils/WindowPerfRunPreconditionBase.java
new file mode 100644
index 000000000000..8d2ac0276592
--- /dev/null
+++ b/apct-tests/perftests/utils/src/android/perftests/utils/WindowPerfRunPreconditionBase.java
@@ -0,0 +1,155 @@
+/*
+ * Copyright (C) 2020 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.perftests.utils;
+
+import static android.app.WindowConfiguration.ACTIVITY_TYPE_ASSISTANT;
+import static android.app.WindowConfiguration.ACTIVITY_TYPE_RECENTS;
+import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
+import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED;
+import static android.perftests.utils.WindowPerfTestBase.executeShellCommand;
+import static android.perftests.utils.WindowPerfTestBase.runWithShellPermissionIdentity;
+
+import android.app.ActivityManager;
+import android.app.ActivityManager.RunningAppProcessInfo;
+import android.app.ActivityTaskManager;
+import android.content.Context;
+import android.os.BatteryManager;
+import android.os.Bundle;
+import android.os.SystemClock;
+import android.perftests.utils.WindowPerfTestBase.SettingsSession;
+import android.provider.Settings;
+import android.util.Log;
+import android.view.WindowManagerPolicyConstants;
+
+import androidx.test.platform.app.InstrumentationRegistry;
+
+import com.android.internal.policy.PhoneWindow;
+
+import org.junit.runner.Description;
+import org.junit.runner.Result;
+import org.junit.runner.notification.RunListener;
+
+import java.util.List;
+
+/** Prepare the preconditions before running performance test. */
+public class WindowPerfRunPreconditionBase extends RunListener {
+ protected final String mTag = getClass().getSimpleName();
+
+ private static final String ARGUMENT_LOG_ONLY = "log";
+ private static final String ARGUMENT_KILL_BACKGROUND = "kill-bg";
+ private static final String ARGUMENT_PROFILING_ITERATIONS = "profiling-iterations";
+ private static final String ARGUMENT_PROFILING_SAMPLING = "profiling-sampling";
+ private static final String DEFAULT_PROFILING_ITERATIONS = "0";
+ private static final String DEFAULT_PROFILING_SAMPLING_US = "10";
+ private static final long KILL_BACKGROUND_WAIT_MS = 3000;
+
+ /** The requested iterations to run with method profiling. */
+ static int sProfilingIterations;
+
+ /** The interval of sample profiling in microseconds. */
+ static int sSamplingIntervalUs;
+
+ private final Context mContext = InstrumentationRegistry.getInstrumentation().getContext();
+ private long mWaitPreconditionDoneMs = 500;
+
+ private final SettingsSession<Integer> mStayOnWhilePluggedInSetting = new SettingsSession<>(
+ Settings.Global.getInt(mContext.getContentResolver(),
+ Settings.Global.STAY_ON_WHILE_PLUGGED_IN, 0),
+ value -> executeShellCommand(String.format("settings put global %s %d",
+ Settings.Global.STAY_ON_WHILE_PLUGGED_IN, value)));
+
+ private final SettingsSession<Integer> mNavigationModeSetting = new SettingsSession<>(
+ mContext.getResources().getInteger(
+ com.android.internal.R.integer.config_navBarInteractionMode),
+ value -> {
+ final String navOverlay;
+ switch (value) {
+ case WindowManagerPolicyConstants.NAV_BAR_MODE_2BUTTON:
+ navOverlay = WindowManagerPolicyConstants.NAV_BAR_MODE_2BUTTON_OVERLAY;
+ break;
+ case WindowManagerPolicyConstants.NAV_BAR_MODE_3BUTTON:
+ navOverlay = WindowManagerPolicyConstants.NAV_BAR_MODE_3BUTTON_OVERLAY;
+ break;
+ case WindowManagerPolicyConstants.NAV_BAR_MODE_GESTURAL:
+ default:
+ navOverlay = WindowManagerPolicyConstants.NAV_BAR_MODE_GESTURAL_OVERLAY;
+ break;
+ }
+ executeShellCommand("cmd overlay enable-exclusive " + navOverlay);
+ });
+
+ /** It only executes once before all tests. */
+ @Override
+ public void testRunStarted(Description description) {
+ final Bundle arguments = InstrumentationRegistry.getArguments();
+ // If true, it only logs the method names without running.
+ final boolean skip = Boolean.parseBoolean(arguments.getString(ARGUMENT_LOG_ONLY, "false"));
+ Log.i(mTag, "arguments=" + arguments);
+ if (skip) {
+ return;
+ }
+ sProfilingIterations = Integer.parseInt(
+ arguments.getString(ARGUMENT_PROFILING_ITERATIONS, DEFAULT_PROFILING_ITERATIONS));
+ sSamplingIntervalUs = Integer.parseInt(
+ arguments.getString(ARGUMENT_PROFILING_SAMPLING, DEFAULT_PROFILING_SAMPLING_US));
+
+ // Use same navigation mode (gesture navigation) across all devices and tests
+ // for consistency.
+ mNavigationModeSetting.set(WindowManagerPolicyConstants.NAV_BAR_MODE_GESTURAL);
+ // Keep the device awake during testing.
+ mStayOnWhilePluggedInSetting.set(BatteryManager.BATTERY_PLUGGED_ANY);
+
+ runWithShellPermissionIdentity(() -> {
+ final ActivityTaskManager atm = mContext.getSystemService(ActivityTaskManager.class);
+ atm.removeAllVisibleRecentTasks();
+ atm.removeRootTasksWithActivityTypes(new int[] { ACTIVITY_TYPE_STANDARD,
+ ACTIVITY_TYPE_ASSISTANT, ACTIVITY_TYPE_RECENTS, ACTIVITY_TYPE_UNDEFINED });
+ });
+ PhoneWindow.sendCloseSystemWindows(mContext, mTag);
+
+ if (Boolean.parseBoolean(arguments.getString(ARGUMENT_KILL_BACKGROUND))) {
+ runWithShellPermissionIdentity(this::killBackgroundProcesses);
+ mWaitPreconditionDoneMs = KILL_BACKGROUND_WAIT_MS;
+ }
+ // Wait a while for the precondition setup to complete.
+ SystemClock.sleep(mWaitPreconditionDoneMs);
+ }
+
+ private void killBackgroundProcesses() {
+ Log.i(mTag, "Killing background processes...");
+ final ActivityManager am = mContext.getSystemService(ActivityManager.class);
+ final List<RunningAppProcessInfo> processes = am.getRunningAppProcesses();
+ if (processes == null) {
+ return;
+ }
+ for (RunningAppProcessInfo processInfo : processes) {
+ if (processInfo.importanceReasonCode == RunningAppProcessInfo.REASON_UNKNOWN
+ && processInfo.importance > RunningAppProcessInfo.IMPORTANCE_SERVICE) {
+ for (String pkg : processInfo.pkgList) {
+ am.forceStopPackage(pkg);
+ }
+ }
+ }
+ }
+
+ /** It only executes once after all tests. */
+ @Override
+ public void testRunFinished(Result result) {
+ mNavigationModeSetting.close();
+ mStayOnWhilePluggedInSetting.close();
+ }
+}
diff --git a/apct-tests/perftests/utils/src/android/perftests/utils/WindowPerfTestBase.java b/apct-tests/perftests/utils/src/android/perftests/utils/WindowPerfTestBase.java
new file mode 100644
index 000000000000..ca5913701d3b
--- /dev/null
+++ b/apct-tests/perftests/utils/src/android/perftests/utils/WindowPerfTestBase.java
@@ -0,0 +1,193 @@
+/*
+ * Copyright (C) 2020 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.perftests.utils;
+
+import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;
+
+import android.app.KeyguardManager;
+import android.app.UiAutomation;
+import android.content.Context;
+import android.content.Intent;
+import android.os.ParcelFileDescriptor;
+import android.os.PowerManager;
+import android.os.SystemClock;
+
+import androidx.test.rule.ActivityTestRule;
+
+import org.junit.After;
+import org.junit.BeforeClass;
+
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Objects;
+import java.util.concurrent.TimeUnit;
+import java.util.function.Consumer;
+
+/** The base class for window related performance tests. */
+public class WindowPerfTestBase {
+ public static final long NANOS_PER_S = 1000L * 1000 * 1000;
+ public static final long TIME_1_S_IN_NS = 1 * NANOS_PER_S;
+
+ static boolean sIsProfilingMethod;
+
+ @BeforeClass
+ public static void setUpOnce() {
+ final Context context = getInstrumentation().getContext();
+
+ if (!context.getSystemService(PowerManager.class).isInteractive()
+ || context.getSystemService(KeyguardManager.class).isKeyguardLocked()) {
+ executeShellCommand("input keyevent KEYCODE_WAKEUP");
+ executeShellCommand("wm dismiss-keyguard");
+ }
+ context.startActivity(new Intent(Intent.ACTION_MAIN)
+ .addCategory(Intent.CATEGORY_HOME).setFlags(Intent.FLAG_ACTIVITY_NEW_TASK));
+ }
+
+ @After
+ public void tearDown() {
+ // Make sure that profiling is stopped if test fails.
+ if (sIsProfilingMethod) {
+ stopProfiling();
+ }
+ }
+
+ public static UiAutomation getUiAutomation() {
+ return getInstrumentation().getUiAutomation();
+ }
+
+ public static void startAsyncAtrace(String tags) {
+ getUiAutomation().executeShellCommand("atrace -b 32768 --async_start " + tags);
+ // Avoid atrace isn't ready immediately.
+ SystemClock.sleep(TimeUnit.NANOSECONDS.toMillis(TIME_1_S_IN_NS));
+ }
+
+ public static InputStream stopAsyncAtraceWithStream() {
+ return new ParcelFileDescriptor.AutoCloseInputStream(
+ getUiAutomation().executeShellCommand("atrace --async_stop"));
+ }
+
+ /** Starts method tracing on system server. */
+ public static void startProfiling(File basePath, String outFileName) {
+ if (!basePath.exists()) {
+ executeShellCommand("mkdir -p " + basePath);
+ }
+ final String samplingArg = WindowPerfRunPreconditionBase.sSamplingIntervalUs > 0
+ ? ("--sampling " + WindowPerfRunPreconditionBase.sSamplingIntervalUs)
+ : "";
+ executeShellCommand("am profile start " + samplingArg + " system "
+ + new File(basePath, outFileName));
+ sIsProfilingMethod = true;
+ }
+
+ /** Stops method tracing of system server. */
+ public static void stopProfiling() {
+ executeShellCommand("am profile stop system");
+ sIsProfilingMethod = false;
+ }
+
+ public static boolean sIsProfilingMethod() {
+ return sIsProfilingMethod;
+ }
+
+ /** Returns how many iterations should run with method tracing. */
+ public static int getProfilingIterations() {
+ return WindowPerfRunPreconditionBase.sProfilingIterations;
+ }
+
+ /**
+ * Executes shell command with reading the output. It may also used to block until the current
+ * command is completed.
+ */
+ public static ByteArrayOutputStream executeShellCommand(String command) {
+ final ParcelFileDescriptor pfd = getUiAutomation().executeShellCommand(command);
+ final byte[] buf = new byte[512];
+ final ByteArrayOutputStream bytes = new ByteArrayOutputStream();
+ int bytesRead;
+ try (FileInputStream fis = new ParcelFileDescriptor.AutoCloseInputStream(pfd)) {
+ while ((bytesRead = fis.read(buf)) != -1) {
+ bytes.write(buf, 0, bytesRead);
+ }
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ return bytes;
+ }
+
+ public static void runWithShellPermissionIdentity(Runnable runnable) {
+ getUiAutomation().adoptShellPermissionIdentity();
+ try {
+ runnable.run();
+ } finally {
+ getUiAutomation().dropShellPermissionIdentity();
+ }
+ }
+
+ public static class SettingsSession<T> implements AutoCloseable {
+ private final Consumer<T> mSetter;
+ private final T mOriginalValue;
+ private boolean mChanged;
+
+ public SettingsSession(T originalValue, Consumer<T> setter) {
+ mOriginalValue = originalValue;
+ mSetter = setter;
+ }
+
+ public void set(T value) {
+ if (Objects.equals(value, mOriginalValue)) {
+ mChanged = false;
+ return;
+ }
+ mSetter.accept(value);
+ mChanged = true;
+ }
+
+ @Override
+ public void close() {
+ if (mChanged) {
+ mSetter.accept(mOriginalValue);
+ }
+ }
+ }
+
+ /**
+ * Provides the {@link PerfTestActivity} with an associated customizable intent.
+ */
+ public static class PerfTestActivityRuleBase extends ActivityTestRule<PerfTestActivity> {
+ protected final Intent mStartIntent =
+ new Intent(getInstrumentation().getTargetContext(), PerfTestActivity.class);
+
+ public PerfTestActivityRuleBase() {
+ this(false /* launchActivity */);
+ }
+
+ public PerfTestActivityRuleBase(boolean launchActivity) {
+ super(PerfTestActivity.class, false /* initialTouchMode */, launchActivity);
+ }
+
+ @Override
+ public Intent getActivityIntent() {
+ return mStartIntent;
+ }
+
+ public PerfTestActivity launchActivity() {
+ return launchActivity(mStartIntent);
+ }
+ }
+}
diff --git a/apct-tests/perftests/windowmanager/src/android/wm/InternalWindowOperationPerfTest.java b/apct-tests/perftests/windowmanager/src/android/wm/InternalWindowOperationPerfTest.java
index 5c09ec2e760f..bccef533be32 100644
--- a/apct-tests/perftests/windowmanager/src/android/wm/InternalWindowOperationPerfTest.java
+++ b/apct-tests/perftests/windowmanager/src/android/wm/InternalWindowOperationPerfTest.java
@@ -18,7 +18,6 @@ package android.wm;
import static android.perftests.utils.ManualBenchmarkState.StatsReport;
-import android.os.ParcelFileDescriptor;
import android.os.SystemClock;
import android.perftests.utils.ManualBenchmarkState;
import android.perftests.utils.ManualBenchmarkState.ManualBenchmarkTest;
@@ -37,7 +36,6 @@ import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
-import java.util.concurrent.TimeUnit;
/** Measure the performance of internal methods in window manager service by trace tag. */
@LargeTest
@@ -85,7 +83,7 @@ public class InternalWindowOperationPerfTest extends WindowManagerPerfTestBase
while (state.keepRunning(measuredTimeNs)) {
if (!mIsTraceStarted && !mIsProfiling && !state.isWarmingUp()) {
- startAsyncAtrace();
+ startAsyncAtrace("wm");
mIsTraceStarted = true;
}
final long startTime = SystemClock.elapsedRealtimeNanos();
@@ -108,15 +106,8 @@ public class InternalWindowOperationPerfTest extends WindowManagerPerfTestBase
Log.i(TAG, String.valueOf(mTraceMarkParser));
}
- private void startAsyncAtrace() throws IOException {
- sUiAutomation.executeShellCommand("atrace -b 32768 --async_start wm");
- // Avoid atrace isn't ready immediately.
- SystemClock.sleep(TimeUnit.NANOSECONDS.toMillis(TIME_1_S_IN_NS));
- }
-
private void stopAsyncAtrace() {
- final ParcelFileDescriptor pfd = sUiAutomation.executeShellCommand("atrace --async_stop");
- final InputStream inputStream = new ParcelFileDescriptor.AutoCloseInputStream(pfd);
+ final InputStream inputStream = stopAsyncAtraceWithStream();
try (BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream))) {
String line;
while ((line = reader.readLine()) != null) {
diff --git a/apct-tests/perftests/windowmanager/src/android/wm/RecentsAnimationPerfTest.java b/apct-tests/perftests/windowmanager/src/android/wm/RecentsAnimationPerfTest.java
index 833cc0ff37a0..2aea61f4e540 100644
--- a/apct-tests/perftests/windowmanager/src/android/wm/RecentsAnimationPerfTest.java
+++ b/apct-tests/perftests/windowmanager/src/android/wm/RecentsAnimationPerfTest.java
@@ -96,7 +96,7 @@ public class RecentsAnimationPerfTest extends WindowManagerPerfTestBase
@BeforeClass
public static void setUpClass() {
// Get the permission to invoke startRecentsActivity.
- sUiAutomation.adoptShellPermissionIdentity();
+ getUiAutomation().adoptShellPermissionIdentity();
final Context context = getInstrumentation().getContext();
final PackageManager pm = context.getPackageManager();
@@ -129,7 +129,7 @@ public class RecentsAnimationPerfTest extends WindowManagerPerfTestBase
ActivityManager.resumeAppSwitches();
} catch (RemoteException ignored) {
}
- sUiAutomation.dropShellPermissionIdentity();
+ getUiAutomation().dropShellPermissionIdentity();
}
@Before
@@ -233,7 +233,7 @@ public class RecentsAnimationPerfTest extends WindowManagerPerfTestBase
// Ensure the animation callback is done.
Assume.assumeTrue(recentsSemaphore.tryAcquire(
- sIsProfilingMethod ? 10 * TIME_5_S_IN_NS : TIME_5_S_IN_NS,
+ sIsProfilingMethod() ? 10 * TIME_5_S_IN_NS : TIME_5_S_IN_NS,
TimeUnit.NANOSECONDS));
}
}
diff --git a/apct-tests/perftests/windowmanager/src/android/wm/WindowAddRemovePerfTest.java b/apct-tests/perftests/windowmanager/src/android/wm/WindowAddRemovePerfTest.java
index 29606030a041..9403e8b72348 100644
--- a/apct-tests/perftests/windowmanager/src/android/wm/WindowAddRemovePerfTest.java
+++ b/apct-tests/perftests/windowmanager/src/android/wm/WindowAddRemovePerfTest.java
@@ -54,12 +54,12 @@ public class WindowAddRemovePerfTest extends WindowManagerPerfTestBase
@BeforeClass
public static void setUpClass() {
// Get the permission to use most window types.
- sUiAutomation.adoptShellPermissionIdentity();
+ getUiAutomation().adoptShellPermissionIdentity();
}
@AfterClass
public static void tearDownClass() {
- sUiAutomation.dropShellPermissionIdentity();
+ getUiAutomation().dropShellPermissionIdentity();
}
/** The last customized iterations will provide the information of method profiling. */
diff --git a/apct-tests/perftests/windowmanager/src/android/wm/WindowManagerPerfTestBase.java b/apct-tests/perftests/windowmanager/src/android/wm/WindowManagerPerfTestBase.java
index b51a9a8fb0dd..4b1982f60092 100644
--- a/apct-tests/perftests/windowmanager/src/android/wm/WindowManagerPerfTestBase.java
+++ b/apct-tests/perftests/windowmanager/src/android/wm/WindowManagerPerfTestBase.java
@@ -19,36 +19,21 @@ package android.wm;
import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;
import android.app.Activity;
-import android.app.KeyguardManager;
-import android.app.UiAutomation;
-import android.content.Context;
import android.content.Intent;
-import android.os.ParcelFileDescriptor;
-import android.os.PowerManager;
import android.perftests.utils.PerfTestActivity;
+import android.perftests.utils.WindowPerfTestBase;
-import androidx.test.rule.ActivityTestRule;
import androidx.test.runner.lifecycle.ActivityLifecycleCallback;
import androidx.test.runner.lifecycle.ActivityLifecycleMonitorRegistry;
import androidx.test.runner.lifecycle.Stage;
-import org.junit.After;
-import org.junit.BeforeClass;
import org.junit.runner.Description;
import org.junit.runners.model.Statement;
-import java.io.ByteArrayOutputStream;
import java.io.File;
-import java.io.FileInputStream;
-import java.io.IOException;
-import java.util.Objects;
import java.util.concurrent.TimeUnit;
-import java.util.function.Consumer;
-public class WindowManagerPerfTestBase {
- static final UiAutomation sUiAutomation = getInstrumentation().getUiAutomation();
- static final long NANOS_PER_S = 1000L * 1000 * 1000;
- static final long TIME_1_S_IN_NS = 1 * NANOS_PER_S;
+public class WindowManagerPerfTestBase extends WindowPerfTestBase {
static final long TIME_5_S_IN_NS = 5 * NANOS_PER_S;
/**
@@ -58,121 +43,21 @@ public class WindowManagerPerfTestBase {
*/
static final File BASE_OUT_PATH = new File("/data/local/tmp/WmPerfTests");
- static boolean sIsProfilingMethod;
-
- @BeforeClass
- public static void setUpOnce() {
- final Context context = getInstrumentation().getContext();
-
- if (!context.getSystemService(PowerManager.class).isInteractive()
- || context.getSystemService(KeyguardManager.class).isKeyguardLocked()) {
- executeShellCommand("input keyevent KEYCODE_WAKEUP");
- executeShellCommand("wm dismiss-keyguard");
- }
- context.startActivity(new Intent(Intent.ACTION_MAIN)
- .addCategory(Intent.CATEGORY_HOME).setFlags(Intent.FLAG_ACTIVITY_NEW_TASK));
- }
-
- @After
- public void tearDown() {
- // Make sure that profiling is stopped if test fails.
- if (sIsProfilingMethod) {
- stopProfiling();
- }
+ static void startProfiling(String outFileName) {
+ startProfiling(BASE_OUT_PATH, outFileName);
}
/**
- * Executes shell command with reading the output. It may also used to block until the current
- * command is completed.
+ * Provides an activity that is able to wait for a stable lifecycle stage.
*/
- static ByteArrayOutputStream executeShellCommand(String command) {
- final ParcelFileDescriptor pfd = sUiAutomation.executeShellCommand(command);
- final byte[] buf = new byte[512];
- final ByteArrayOutputStream bytes = new ByteArrayOutputStream();
- int bytesRead;
- try (FileInputStream fis = new ParcelFileDescriptor.AutoCloseInputStream(pfd)) {
- while ((bytesRead = fis.read(buf)) != -1) {
- bytes.write(buf, 0, bytesRead);
- }
- } catch (IOException e) {
- throw new RuntimeException(e);
- }
- return bytes;
- }
-
- /** Starts method tracing on system server. */
- static void startProfiling(String subPath) {
- if (!BASE_OUT_PATH.exists()) {
- executeShellCommand("mkdir -p " + BASE_OUT_PATH);
- }
- final String samplingArg = WmPerfRunListener.sSamplingIntervalUs > 0
- ? ("--sampling " + WmPerfRunListener.sSamplingIntervalUs)
- : "";
- executeShellCommand("am profile start " + samplingArg + " system "
- + new File(BASE_OUT_PATH, subPath));
- sIsProfilingMethod = true;
- }
-
- static void stopProfiling() {
- executeShellCommand("am profile stop system");
- sIsProfilingMethod = false;
- }
-
- /** Returns how many iterations should run with method tracing. */
- static int getProfilingIterations() {
- return WmPerfRunListener.sProfilingIterations;
- }
-
- static void runWithShellPermissionIdentity(Runnable runnable) {
- sUiAutomation.adoptShellPermissionIdentity();
- try {
- runnable.run();
- } finally {
- sUiAutomation.dropShellPermissionIdentity();
- }
- }
-
- static class SettingsSession<T> implements AutoCloseable {
- private final Consumer<T> mSetter;
- private final T mOriginalValue;
- private boolean mChanged;
-
- SettingsSession(T originalValue, Consumer<T> setter) {
- mOriginalValue = originalValue;
- mSetter = setter;
- }
-
- void set(T value) {
- if (Objects.equals(value, mOriginalValue)) {
- mChanged = false;
- return;
- }
- mSetter.accept(value);
- mChanged = true;
- }
-
- @Override
- public void close() {
- if (mChanged) {
- mSetter.accept(mOriginalValue);
- }
- }
- }
-
- /**
- * Provides an activity that keeps screen on and is able to wait for a stable lifecycle stage.
- */
- static class PerfTestActivityRule extends ActivityTestRule<PerfTestActivity> {
- private final Intent mStartIntent =
- new Intent(getInstrumentation().getTargetContext(), PerfTestActivity.class);
+ static class PerfTestActivityRule extends PerfTestActivityRuleBase {
private final LifecycleListener mLifecycleListener = new LifecycleListener();
PerfTestActivityRule() {
- this(false /* launchActivity */);
}
PerfTestActivityRule(boolean launchActivity) {
- super(PerfTestActivity.class, false /* initialTouchMode */, launchActivity);
+ super(launchActivity);
}
@Override
@@ -191,21 +76,12 @@ public class WindowManagerPerfTestBase {
}
@Override
- protected Intent getActivityIntent() {
- return mStartIntent;
- }
-
- @Override
public PerfTestActivity launchActivity(Intent intent) {
final PerfTestActivity activity = super.launchActivity(intent);
mLifecycleListener.setTargetActivity(activity);
return activity;
}
- PerfTestActivity launchActivity() {
- return launchActivity(mStartIntent);
- }
-
void waitForIdleSync(Stage state) {
mLifecycleListener.waitForIdleSync(state);
}
diff --git a/apct-tests/perftests/windowmanager/src/android/wm/WmPerfRunListener.java b/apct-tests/perftests/windowmanager/src/android/wm/WmPerfRunListener.java
index a9d57167f6d2..2b0801af12cb 100644
--- a/apct-tests/perftests/windowmanager/src/android/wm/WmPerfRunListener.java
+++ b/apct-tests/perftests/windowmanager/src/android/wm/WmPerfRunListener.java
@@ -16,138 +16,8 @@
package android.wm;
-import static android.app.WindowConfiguration.ACTIVITY_TYPE_ASSISTANT;
-import static android.app.WindowConfiguration.ACTIVITY_TYPE_RECENTS;
-import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
-import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED;
-import static android.wm.WindowManagerPerfTestBase.executeShellCommand;
-import static android.wm.WindowManagerPerfTestBase.runWithShellPermissionIdentity;
-
-import android.app.ActivityManager;
-import android.app.ActivityManager.RunningAppProcessInfo;
-import android.app.ActivityTaskManager;
-import android.content.Context;
-import android.os.BatteryManager;
-import android.os.Bundle;
-import android.os.SystemClock;
-import android.provider.Settings;
-import android.util.Log;
-import android.view.WindowManagerPolicyConstants;
-import android.wm.WindowManagerPerfTestBase.SettingsSession;
-
-import androidx.test.platform.app.InstrumentationRegistry;
-
-import com.android.internal.policy.PhoneWindow;
-
-import org.junit.runner.Description;
-import org.junit.runner.Result;
-import org.junit.runner.notification.RunListener;
-
-import java.util.List;
+import android.perftests.utils.WindowPerfRunPreconditionBase;
/** Prepare the preconditions before running performance test. */
-public class WmPerfRunListener extends RunListener {
- private static final String TAG = WmPerfRunListener.class.getSimpleName();
-
- private static final String ARGUMENT_LOG_ONLY = "log";
- private static final String ARGUMENT_KILL_BACKGROUND = "kill-bg";
- private static final String ARGUMENT_PROFILING_ITERATIONS = "profiling-iterations";
- private static final String ARGUMENT_PROFILING_SAMPLING = "profiling-sampling";
- private static final String DEFAULT_PROFILING_ITERATIONS = "0";
- private static final String DEFAULT_PROFILING_SAMPLING_US = "10";
- private static final long KILL_BACKGROUND_WAIT_MS = 3000;
-
- /** The requested iterations to run with method profiling. */
- static int sProfilingIterations;
-
- /** The interval of sample profiling in microseconds. */
- static int sSamplingIntervalUs;
-
- private final Context mContext = InstrumentationRegistry.getInstrumentation().getContext();
- private long mWaitPreconditionDoneMs = 500;
-
- private final SettingsSession<Integer> mStayOnWhilePluggedInSetting = new SettingsSession<>(
- Settings.Global.getInt(mContext.getContentResolver(),
- Settings.Global.STAY_ON_WHILE_PLUGGED_IN, 0),
- value -> executeShellCommand(String.format("settings put global %s %d",
- Settings.Global.STAY_ON_WHILE_PLUGGED_IN, value)));
-
- private final SettingsSession<Integer> mNavigationModeSetting = new SettingsSession<>(
- mContext.getResources().getInteger(
- com.android.internal.R.integer.config_navBarInteractionMode),
- value -> {
- final String navOverlay;
- switch (value) {
- case WindowManagerPolicyConstants.NAV_BAR_MODE_2BUTTON:
- navOverlay = WindowManagerPolicyConstants.NAV_BAR_MODE_2BUTTON_OVERLAY;
- break;
- case WindowManagerPolicyConstants.NAV_BAR_MODE_3BUTTON:
- navOverlay = WindowManagerPolicyConstants.NAV_BAR_MODE_3BUTTON_OVERLAY;
- break;
- case WindowManagerPolicyConstants.NAV_BAR_MODE_GESTURAL:
- default:
- navOverlay = WindowManagerPolicyConstants.NAV_BAR_MODE_GESTURAL_OVERLAY;
- break;
- }
- executeShellCommand("cmd overlay enable-exclusive " + navOverlay);
- });
-
- /** It only executes once before all tests. */
- @Override
- public void testRunStarted(Description description) {
- final Bundle arguments = InstrumentationRegistry.getArguments();
- // If true, it only logs the method names without running.
- final boolean skip = Boolean.parseBoolean(arguments.getString(ARGUMENT_LOG_ONLY, "false"));
- Log.i(TAG, "arguments=" + arguments);
- if (skip) {
- return;
- }
- sProfilingIterations = Integer.parseInt(
- arguments.getString(ARGUMENT_PROFILING_ITERATIONS, DEFAULT_PROFILING_ITERATIONS));
- sSamplingIntervalUs = Integer.parseInt(
- arguments.getString(ARGUMENT_PROFILING_SAMPLING, DEFAULT_PROFILING_SAMPLING_US));
-
- // Use gesture navigation for consistency.
- mNavigationModeSetting.set(WindowManagerPolicyConstants.NAV_BAR_MODE_GESTURAL);
- // Keep the device awake during testing.
- mStayOnWhilePluggedInSetting.set(BatteryManager.BATTERY_PLUGGED_ANY);
-
- runWithShellPermissionIdentity(() -> {
- final ActivityTaskManager atm = mContext.getSystemService(ActivityTaskManager.class);
- atm.removeAllVisibleRecentTasks();
- atm.removeRootTasksWithActivityTypes(new int[] { ACTIVITY_TYPE_STANDARD,
- ACTIVITY_TYPE_ASSISTANT, ACTIVITY_TYPE_RECENTS, ACTIVITY_TYPE_UNDEFINED });
- });
- PhoneWindow.sendCloseSystemWindows(mContext, "WmPerfTests");
-
- if (Boolean.parseBoolean(arguments.getString(ARGUMENT_KILL_BACKGROUND))) {
- runWithShellPermissionIdentity(this::killBackgroundProcesses);
- mWaitPreconditionDoneMs = KILL_BACKGROUND_WAIT_MS;
- }
- // Wait a while for the precondition setup to complete.
- SystemClock.sleep(mWaitPreconditionDoneMs);
- }
-
- private void killBackgroundProcesses() {
- final ActivityManager am = mContext.getSystemService(ActivityManager.class);
- final List<RunningAppProcessInfo> processes = am.getRunningAppProcesses();
- if (processes == null) {
- return;
- }
- for (RunningAppProcessInfo processInfo : processes) {
- if (processInfo.importanceReasonCode == RunningAppProcessInfo.REASON_UNKNOWN
- && processInfo.importance > RunningAppProcessInfo.IMPORTANCE_SERVICE) {
- for (String pkg : processInfo.pkgList) {
- am.forceStopPackage(pkg);
- }
- }
- }
- }
-
- /** It only executes once after all tests. */
- @Override
- public void testRunFinished(Result result) {
- mNavigationModeSetting.close();
- mStayOnWhilePluggedInSetting.close();
- }
+public class WmPerfRunListener extends WindowPerfRunPreconditionBase {
}