1 /* 2 * Copyright (C) 2021 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 com.android.performance.tests; 18 19 import com.android.tradefed.config.GlobalConfiguration; 20 import com.android.tradefed.config.IConfiguration; 21 import com.android.tradefed.config.IConfigurationReceiver; 22 import com.android.tradefed.config.Option; 23 import com.android.tradefed.device.DeviceNotAvailableException; 24 import com.android.tradefed.device.TestDeviceState; 25 import com.android.tradefed.invoker.TestInformation; 26 import com.android.tradefed.log.LogUtil; 27 import com.android.tradefed.result.ITestInvocationListener; 28 import com.android.tradefed.targetprep.BaseEmulatorPreparer; 29 import com.android.tradefed.testtype.AndroidJUnitTest; 30 import com.android.tradefed.testtype.IRemoteTest; 31 import com.android.tradefed.util.AaptParser; 32 33 import com.google.common.base.Preconditions; 34 35 import java.io.File; 36 import java.nio.file.Files; 37 import java.nio.file.Path; 38 import java.util.HashMap; 39 import java.util.Map; 40 41 /** 42 * A base call for emulator performance tests that does repeated emulator launches, and runs 43 * instrumentation tests 44 */ 45 public abstract class BaseEmulatorPerfTest implements IRemoteTest, IConfigurationReceiver { 46 @Option(name = "iterations", description = "number of launch iterations to perform") 47 private int mIterations = 1; 48 49 @Option(name = "test-apk-name", description = "File name of test apk install", mandatory = true) 50 private String mInstallApkName; 51 52 @Option(name = "test-dir-path", description = "File system path to test apks") 53 private File mTestDirPath; 54 55 @Option( 56 name = "emulator-metrics-key", 57 description = "The test run name to use to report metrics", 58 mandatory = true) 59 private String mRunName; 60 61 private IConfiguration mConfig; 62 63 @Override setConfiguration(IConfiguration configuration)64 public void setConfiguration(IConfiguration configuration) { 65 mConfig = configuration; 66 } 67 68 @Override run(TestInformation testInfo, ITestInvocationListener listener)69 public void run(TestInformation testInfo, ITestInvocationListener listener) 70 throws DeviceNotAvailableException { 71 Preconditions.checkArgument(testInfo.getDevice().getIDevice().isEmulator()); 72 Preconditions.checkArgument( 73 testInfo.getDevice().getDeviceState() == TestDeviceState.NOT_AVAILABLE); 74 Preconditions.checkNotNull(mTestDirPath, "--test-dir-path was not set"); 75 Path apkPath = mTestDirPath.toPath().resolve(mInstallApkName); 76 Preconditions.checkArgument(Files.exists(apkPath), apkPath.toString() + " does not exist"); 77 78 // Pull the objects to perform the emulator launch amd run tests 79 // They are stored in config in order to support receiving Options. 80 BaseEmulatorPreparer emulatorLauncher = 81 (BaseEmulatorPreparer) mConfig.getConfigurationObject("emulator_launcher"); 82 83 AndroidJUnitTest delegateTest = 84 (AndroidJUnitTest) mConfig.getConfigurationObject("delegate_test"); 85 delegateTest.setDevice(testInfo.getDevice()); 86 // auto find package name of test apk 87 AaptParser parser = AaptParser.parse(apkPath.toFile()); 88 delegateTest.setPackageName(parser.getPackageName()); 89 90 DataRecorder dataRecorder = new DataRecorder(mRunName); 91 92 try { 93 for (int i = 1; i <= mIterations; i++) { 94 LogUtil.CLog.i("Performing %d iteration of %d", i, mIterations); 95 96 performIteration( 97 testInfo, emulatorLauncher, delegateTest, apkPath, dataRecorder, listener); 98 99 // let tradefed kill emulator for last iteration 100 if (i < mIterations) { 101 GlobalConfiguration.getDeviceManagerInstance() 102 .killEmulator(testInfo.getDevice()); 103 } 104 } 105 106 Map<String, String> buildMetrics = getBuildMetrics(testInfo); 107 dataRecorder.reportMetrics(listener, buildMetrics); 108 109 } catch (Exception e) { 110 LogUtil.CLog.e(e); 111 listener.invocationFailed(e); 112 } 113 } 114 getBuildMetrics(TestInformation testInfo)115 private Map<String, String> getBuildMetrics(TestInformation testInfo) { 116 Map<String, String> metrics = new HashMap<>(); 117 // add 'emulator_build_id' to data to report if it exists 118 String emuBuildId = testInfo.getBuildInfo().getBuildAttributes().get("emulator-build-id"); 119 if (emuBuildId != null) { 120 metrics.put("emulator_build_id", emuBuildId); 121 } 122 return metrics; 123 } 124 performIteration( TestInformation device, BaseEmulatorPreparer emulatorLauncher, AndroidJUnitTest delegateTest, Path apkPath, DataRecorder dataRecorder, ITestInvocationListener listener)125 protected abstract void performIteration( 126 TestInformation device, 127 BaseEmulatorPreparer emulatorLauncher, 128 AndroidJUnitTest delegateTest, 129 Path apkPath, 130 DataRecorder dataRecorder, 131 ITestInvocationListener listener) 132 throws Exception; 133 } 134