1 /* 2 * Copyright (C) 2020 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package android.perftests.utils; 18 19 import static android.app.WindowConfiguration.ACTIVITY_TYPE_ASSISTANT; 20 import static android.app.WindowConfiguration.ACTIVITY_TYPE_RECENTS; 21 import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD; 22 import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED; 23 import static android.perftests.utils.WindowPerfTestBase.executeShellCommand; 24 import static android.perftests.utils.WindowPerfTestBase.runWithShellPermissionIdentity; 25 26 import android.app.ActivityManager; 27 import android.app.ActivityManager.RunningAppProcessInfo; 28 import android.app.ActivityTaskManager; 29 import android.content.Context; 30 import android.os.BatteryManager; 31 import android.os.Bundle; 32 import android.os.SystemClock; 33 import android.perftests.utils.WindowPerfTestBase.SettingsSession; 34 import android.provider.Settings; 35 import android.util.Log; 36 import android.view.WindowManagerPolicyConstants; 37 38 import androidx.test.platform.app.InstrumentationRegistry; 39 40 import com.android.internal.policy.PhoneWindow; 41 42 import org.junit.runner.Description; 43 import org.junit.runner.Result; 44 import org.junit.runner.notification.RunListener; 45 46 import java.util.List; 47 48 /** Prepare the preconditions before running performance test. */ 49 public class WindowPerfRunPreconditionBase extends RunListener { 50 protected final String mTag = getClass().getSimpleName(); 51 52 private static final String ARGUMENT_LOG_ONLY = "log"; 53 private static final String ARGUMENT_KILL_BACKGROUND = "kill-bg"; 54 private static final String ARGUMENT_PROFILING_ITERATIONS = "profiling-iterations"; 55 private static final String ARGUMENT_PROFILING_SAMPLING = "profiling-sampling"; 56 private static final String DEFAULT_PROFILING_ITERATIONS = "0"; 57 private static final String DEFAULT_PROFILING_SAMPLING_US = "10"; 58 private static final long KILL_BACKGROUND_WAIT_MS = 3000; 59 60 /** The requested iterations to run with method profiling. */ 61 static int sProfilingIterations; 62 63 /** The interval of sample profiling in microseconds. */ 64 static int sSamplingIntervalUs; 65 66 private final Context mContext = InstrumentationRegistry.getInstrumentation().getContext(); 67 private long mWaitPreconditionDoneMs = 500; 68 69 private final SettingsSession<Integer> mStayOnWhilePluggedInSetting = new SettingsSession<>( 70 Settings.Global.getInt(mContext.getContentResolver(), 71 Settings.Global.STAY_ON_WHILE_PLUGGED_IN, 0), 72 value -> executeShellCommand(String.format("settings put global %s %d", 73 Settings.Global.STAY_ON_WHILE_PLUGGED_IN, value))); 74 75 private final SettingsSession<Integer> mNavigationModeSetting = new SettingsSession<>( 76 mContext.getResources().getInteger( 77 com.android.internal.R.integer.config_navBarInteractionMode), 78 value -> { 79 final String navOverlay; 80 switch (value) { 81 case WindowManagerPolicyConstants.NAV_BAR_MODE_2BUTTON: 82 navOverlay = WindowManagerPolicyConstants.NAV_BAR_MODE_2BUTTON_OVERLAY; 83 break; 84 case WindowManagerPolicyConstants.NAV_BAR_MODE_3BUTTON: 85 navOverlay = WindowManagerPolicyConstants.NAV_BAR_MODE_3BUTTON_OVERLAY; 86 break; 87 case WindowManagerPolicyConstants.NAV_BAR_MODE_GESTURAL: 88 default: 89 navOverlay = WindowManagerPolicyConstants.NAV_BAR_MODE_GESTURAL_OVERLAY; 90 break; 91 } 92 executeShellCommand("cmd overlay enable-exclusive --category " + navOverlay); 93 }); 94 95 /** It only executes once before all tests. */ 96 @Override testRunStarted(Description description)97 public void testRunStarted(Description description) { 98 final Bundle arguments = InstrumentationRegistry.getArguments(); 99 // If true, it only logs the method names without running. 100 final boolean skip = Boolean.parseBoolean(arguments.getString(ARGUMENT_LOG_ONLY, "false")); 101 Log.i(mTag, "arguments=" + arguments); 102 if (skip) { 103 return; 104 } 105 sProfilingIterations = Integer.parseInt( 106 arguments.getString(ARGUMENT_PROFILING_ITERATIONS, DEFAULT_PROFILING_ITERATIONS)); 107 sSamplingIntervalUs = Integer.parseInt( 108 arguments.getString(ARGUMENT_PROFILING_SAMPLING, DEFAULT_PROFILING_SAMPLING_US)); 109 110 // Use same navigation mode (gesture navigation) across all devices and tests 111 // for consistency. 112 mNavigationModeSetting.set(WindowManagerPolicyConstants.NAV_BAR_MODE_GESTURAL); 113 // Keep the device awake during testing. 114 mStayOnWhilePluggedInSetting.set(BatteryManager.BATTERY_PLUGGED_ANY); 115 116 runWithShellPermissionIdentity(() -> { 117 final ActivityTaskManager atm = mContext.getSystemService(ActivityTaskManager.class); 118 atm.removeAllVisibleRecentTasks(); 119 atm.removeRootTasksWithActivityTypes(new int[] { ACTIVITY_TYPE_STANDARD, 120 ACTIVITY_TYPE_ASSISTANT, ACTIVITY_TYPE_RECENTS, ACTIVITY_TYPE_UNDEFINED }); 121 }); 122 PhoneWindow.sendCloseSystemWindows(mContext, mTag); 123 124 if (Boolean.parseBoolean(arguments.getString(ARGUMENT_KILL_BACKGROUND))) { 125 runWithShellPermissionIdentity(this::killBackgroundProcesses); 126 mWaitPreconditionDoneMs = KILL_BACKGROUND_WAIT_MS; 127 } 128 // Wait a while for the precondition setup to complete. 129 SystemClock.sleep(mWaitPreconditionDoneMs); 130 } 131 killBackgroundProcesses()132 private void killBackgroundProcesses() { 133 Log.i(mTag, "Killing background processes..."); 134 final ActivityManager am = mContext.getSystemService(ActivityManager.class); 135 final List<RunningAppProcessInfo> processes = am.getRunningAppProcesses(); 136 if (processes == null) { 137 return; 138 } 139 for (RunningAppProcessInfo processInfo : processes) { 140 if (processInfo.importanceReasonCode == RunningAppProcessInfo.REASON_UNKNOWN 141 && processInfo.importance > RunningAppProcessInfo.IMPORTANCE_SERVICE) { 142 for (String pkg : processInfo.pkgList) { 143 am.forceStopPackage(pkg); 144 } 145 } 146 } 147 } 148 149 /** It only executes once after all tests. */ 150 @Override testRunFinished(Result result)151 public void testRunFinished(Result result) { 152 mNavigationModeSetting.close(); 153 mStayOnWhilePluggedInSetting.close(); 154 } 155 } 156