1 /* 2 * Copyright (C) 2014 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.cts.tradefed.testtype; 18 19 import com.android.cts.tradefed.build.CtsBuildHelper; 20 import com.android.cts.tradefed.targetprep.SettingsToggler; 21 import com.android.cts.util.AbiUtils; 22 import com.android.ddmlib.testrunner.IRemoteAndroidTestRunner; 23 import com.android.ddmlib.testrunner.IRemoteAndroidTestRunner.TestSize; 24 import com.android.tradefed.build.IBuildInfo; 25 import com.android.tradefed.device.DeviceNotAvailableException; 26 import com.android.tradefed.device.ITestDevice; 27 import com.android.tradefed.result.ITestInvocationListener; 28 import com.android.tradefed.testtype.IAbi; 29 import com.android.tradefed.testtype.IBuildReceiver; 30 import com.android.tradefed.testtype.IDeviceTest; 31 import com.android.tradefed.testtype.IRemoteTest; 32 import com.android.tradefed.util.StringEscapeUtils; 33 34 import java.io.FileNotFoundException; 35 import java.util.HashMap; 36 import java.util.Map; 37 import java.util.concurrent.TimeUnit; 38 39 /** 40 * Running the print tests requires modification of secure settings. Secure 41 * settings cannot be changed from device CTS tests since system signature 42 * permission is required. Such settings can be modified by the shell user, 43 * so a host side test driver is used for enabling these services, running 44 * the tests, and disabling the services. 45 */ 46 public class PrintTestRunner implements IBuildReceiver, IRemoteTest, IDeviceTest { 47 48 private static final String PRINT_TEST_AND_SERVICES_APP_NAME = 49 "CtsPrintTestCases.apk"; 50 51 private static final String PRINT_TESTS_PACKAGE_NAME = 52 "com.android.cts.print"; 53 54 private static final String FIRST_PRINT_SERVICE_NAME = 55 "android.print.cts.services.FirstPrintService"; 56 57 private static final String SECOND_PRINT_SERVICE_NAME = 58 "android.print.cts.services.SecondPrintService"; 59 60 private static final String SHELL_USER_FOLDER = "data/local/tmp"; 61 62 private static final String PRINT_INSTRUMENT_JAR = "CtsPrintInstrument.jar"; 63 64 private static final String PRINT_INSTRUMENT_SCRIPT = "print-instrument"; 65 66 private ITestDevice mDevice; 67 68 private CtsBuildHelper mCtsBuild; 69 70 private IAbi mAbi; 71 private String mPackageName; 72 private String mRunnerName = "android.test.InstrumentationTestRunner"; 73 private String mTestClassName; 74 private String mTestMethodName; 75 private String mTestPackageName; 76 private int mTestTimeout = 10 * 60 * 1000; // 10 minutes 77 private String mTestSize; 78 private String mRunName = null; 79 private Map<String, String> mInstrArgMap = new HashMap<String, String>(); 80 81 /** 82 * @param abi The ABI to run the test on 83 */ 84 public void setAbi(IAbi abi) { 85 mAbi = abi; 86 } 87 88 @Override 89 public void setBuild(IBuildInfo buildInfo) { 90 mCtsBuild = CtsBuildHelper.createBuildHelper(buildInfo); 91 } 92 93 @Override 94 public void setDevice(ITestDevice device) { 95 mDevice = device; 96 } 97 98 @Override 99 public ITestDevice getDevice() { 100 return mDevice; 101 } 102 103 public void setPackageName(String packageName) { 104 mPackageName = packageName; 105 } 106 107 public void setRunnerName(String runnerName) { 108 mRunnerName = runnerName; 109 } 110 111 public void setClassName(String testClassName) { 112 mTestClassName = testClassName; 113 } 114 115 public void setMethodName(String testMethodName) { 116 mTestMethodName = StringEscapeUtils.escapeShell(testMethodName); 117 } 118 119 public void setTestPackageName(String testPackageName) { 120 mTestPackageName = testPackageName; 121 } 122 123 public void setTestSize(String size) { 124 mTestSize = size; 125 } 126 127 public void setRunName(String runName) { 128 mRunName = runName; 129 } 130 131 @Override 132 public void run(final ITestInvocationListener listener) throws DeviceNotAvailableException { 133 installShellProgramAndScriptFiles(); 134 installTestsAndServicesApk(); 135 enablePrintServices(); 136 doRunTests(listener); 137 disablePrintServices(); 138 uninstallTestsAndServicesApk(); 139 uninstallShellProgramAndScriptFiles(); 140 } 141 142 private void doRunTests(ITestInvocationListener listener) 143 throws DeviceNotAvailableException { 144 if (mPackageName == null) { 145 throw new IllegalArgumentException("package name has not been set"); 146 } 147 if (mDevice == null) { 148 throw new IllegalArgumentException("Device has not been set"); 149 } 150 151 IRemoteAndroidTestRunner runner = new PrintTestRemoteTestRunner(mPackageName, 152 mRunnerName, mDevice.getIDevice()); 153 154 if (mTestClassName != null) { 155 if (mTestMethodName != null) { 156 runner.setMethodName(mTestClassName, mTestMethodName); 157 } else { 158 runner.setClassName(mTestClassName); 159 } 160 } else if (mTestPackageName != null) { 161 runner.setTestPackageName(mTestPackageName); 162 } 163 if (mTestSize != null) { 164 runner.setTestSize(TestSize.getTestSize(mTestSize)); 165 } 166 runner.setMaxTimeToOutputResponse(mTestTimeout, TimeUnit.MILLISECONDS); 167 if (mRunName != null) { 168 runner.setRunName(mRunName); 169 } 170 for (Map.Entry<String, String> argEntry : mInstrArgMap.entrySet()) { 171 runner.addInstrumentationArg(argEntry.getKey(), argEntry.getValue()); 172 } 173 174 mDevice.runInstrumentationTests(runner, listener); 175 } 176 177 private void installShellProgramAndScriptFiles() throws DeviceNotAvailableException { 178 installFile(PRINT_INSTRUMENT_JAR); 179 installFile(PRINT_INSTRUMENT_SCRIPT); 180 } 181 182 private void installFile(String fileName) throws DeviceNotAvailableException { 183 try { 184 final boolean success = getDevice().pushFile(mCtsBuild.getTestApp( 185 fileName), SHELL_USER_FOLDER + "/" + fileName); 186 if (!success) { 187 throw new IllegalArgumentException("Failed to install " 188 + fileName + " on " + getDevice().getSerialNumber()); 189 } 190 } catch (FileNotFoundException fnfe) { 191 throw new IllegalArgumentException("Cannot find file: " + fileName); 192 } 193 } 194 195 private void uninstallShellProgramAndScriptFiles() throws DeviceNotAvailableException { 196 getDevice().executeShellCommand("rm " + SHELL_USER_FOLDER + "/" 197 + PRINT_INSTRUMENT_JAR); 198 getDevice().executeShellCommand("rm " + SHELL_USER_FOLDER + "/" 199 + PRINT_INSTRUMENT_SCRIPT); 200 } 201 202 private void installTestsAndServicesApk() throws DeviceNotAvailableException { 203 try { 204 String[] options = {AbiUtils.createAbiFlag(mAbi.getName())}; 205 String installCode = getDevice().installPackage(mCtsBuild.getTestApp( 206 PRINT_TEST_AND_SERVICES_APP_NAME), true, options); 207 if (installCode != null) { 208 throw new IllegalArgumentException("Failed to install " 209 + PRINT_TEST_AND_SERVICES_APP_NAME + " on " + getDevice().getSerialNumber() 210 + ". Reason: " + installCode); 211 } 212 } catch (FileNotFoundException fnfe) { 213 throw new IllegalArgumentException("Cannot find file: " 214 + PRINT_TEST_AND_SERVICES_APP_NAME); 215 } 216 } 217 218 private void uninstallTestsAndServicesApk() throws DeviceNotAvailableException { 219 getDevice().uninstallPackage(PRINT_TESTS_PACKAGE_NAME); 220 } 221 222 private void enablePrintServices() throws DeviceNotAvailableException { 223 String enabledServicesValue = PRINT_TESTS_PACKAGE_NAME + "/" + FIRST_PRINT_SERVICE_NAME 224 + ":" + PRINT_TESTS_PACKAGE_NAME + "/" + SECOND_PRINT_SERVICE_NAME; 225 SettingsToggler.setSecureString(getDevice(), "enabled_print_services", 226 enabledServicesValue); 227 } 228 229 private void disablePrintServices() throws DeviceNotAvailableException { 230 SettingsToggler.setSecureString(getDevice(), "enabled_print_services", ""); 231 } 232 } 233