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 package android.videoencodingquality.cts; 17 18 import com.android.compatibility.common.util.CddTest; 19 import com.android.tradefed.build.IBuildInfo; 20 import com.android.tradefed.config.Option; 21 import com.android.tradefed.config.OptionClass; 22 import com.android.tradefed.device.ITestDevice; 23 import com.android.tradefed.log.LogUtil; 24 import com.android.tradefed.testtype.DeviceJUnit4ClassRunner; 25 import com.android.tradefed.testtype.IAbi; 26 import com.android.tradefed.testtype.IAbiReceiver; 27 import com.android.tradefed.testtype.IBuildReceiver; 28 import com.android.tradefed.testtype.IDeviceTest; 29 30 import org.junit.Assert; 31 import org.junit.Assume; 32 import org.junit.Test; 33 import org.junit.runner.RunWith; 34 35 import java.io.BufferedReader; 36 import java.io.File; 37 import java.io.IOException; 38 import java.io.InputStreamReader; 39 import java.util.concurrent.TimeUnit; 40 41 /** 42 * Run the host-side video encoding quality test (go/pc14-veq) 43 * The body of this test is implemented in a test script, not within the java here. This java 44 * code acquires the testsuite tar file, unpacks it, executes the script (which encodes and 45 * measures) that report either PASS or FAIL. 46 **/ 47 @RunWith(DeviceJUnit4ClassRunner.class) 48 @OptionClass(alias = "pc-veq-test") 49 public class CtsVideoEncodingQualityHostTest implements IAbiReceiver, IBuildReceiver, IDeviceTest { 50 51 static final String BASE_URL = 52 "https://storage.googleapis.com/android_media/cts/hostsidetests/pc14_veq/"; 53 54 @Option(name = "force-to-run", 55 description = "Force to run the test even if the device is not a right performance " 56 + "class device.") 57 private boolean mForceToRun = false; 58 59 @Option(name = "disable-b", description = "Disable b-frame-encoding.") 60 private boolean mDisableB = false; 61 62 @Option(name = "reset", description = "Start with a fresh directory.") 63 private boolean mReset = true; 64 65 @Option(name = "quick-check", description = "Run a quick check.") 66 private boolean mQuickCheck = false; 67 68 // test is not valid before sdk 31, aka Android 12, aka Android S 69 static final int MINIMUM_VALID_SDK = 31; 70 71 // media performance class 14 72 static final int MEDIA_PERFORMANCE_CLASS_14 = 34; 73 74 /** A reference to the build info. */ 75 private IBuildInfo mBuildInfo; 76 77 /** A reference to the device under test. */ 78 private ITestDevice mDevice; 79 80 /** A reference to the ABI under test. */ 81 private IAbi mAbi; 82 83 @Override setAbi(IAbi abi)84 public void setAbi(IAbi abi) { 85 mAbi = abi; 86 } 87 88 @Override setBuild(IBuildInfo buildInfo)89 public void setBuild(IBuildInfo buildInfo) { 90 mBuildInfo = buildInfo; 91 } 92 93 @Override setDevice(ITestDevice device)94 public void setDevice(ITestDevice device) { 95 mDevice = device; 96 } 97 98 @Override getDevice()99 public ITestDevice getDevice() { 100 return mDevice; 101 } 102 getProperty(String prop)103 private String getProperty(String prop) throws Exception { 104 return mDevice.executeShellCommand("getprop " + prop).replace("\n", ""); 105 } 106 107 /** 108 * TODO: Add JavaDoc 109 */ 110 /** 111 * Verify the video encoding quality requirements for the performance class 14 devices. 112 */ 113 @CddTest(requirements = {"2.2.7.1/5.8/H-1-1"}) 114 @Test testEncoding()115 public void testEncoding() throws Exception { 116 String sdkAsString = getProperty("ro.build.version.sdk"); 117 int sdk = Integer.parseInt(sdkAsString); 118 Assume.assumeTrue( 119 "Test requires sdk >= " + MINIMUM_VALID_SDK + " test device has sdk = " + sdk, 120 sdk >= MINIMUM_VALID_SDK); 121 122 String os = System.getProperty("os.name").toLowerCase(); 123 LogUtil.CLog.i("Host OS = " + os); 124 125 String pcAsString = getProperty("ro.odm.build.media_performance_class"); 126 int mpc = 0; 127 try { 128 mpc = Integer.parseInt("0" + pcAsString); 129 } catch (Exception e) { 130 LogUtil.CLog.i("Invalid pcAsString: " + pcAsString + ", exception: " + e); 131 mpc = 0; 132 } 133 134 // Enable early termination on errors on the devices whose mpc's are not valid. 135 // Run the entire test til the end on the devices whose mpc's are valid. 136 boolean earlyTermination = mpc < MEDIA_PERFORMANCE_CLASS_14; 137 if (mForceToRun) { 138 earlyTermination = false; // Force to run the test til the end. 139 } 140 141 String targetSerial = getDevice().getSerialNumber(); 142 LogUtil.CLog.i("serial:\n\n" + targetSerial); 143 144 String tmpBase = System.getProperty("java.io.tmpdir"); 145 String dirName = "CtsVideoEncodingQualityHostTest_" + targetSerial; 146 String tmpDir = tmpBase + "/" + dirName; 147 148 LogUtil.CLog.i("tmpBase= " + tmpBase + " tmpDir =" + tmpDir); 149 150 if (mReset) { 151 // start with a fresh directory 152 File cwd = new File("."); 153 runCommand("rm -fr " + tmpDir, cwd); 154 } 155 156 // set up test directory, make sure it exists 157 File destination = new File(tmpDir); 158 try { 159 if (!destination.isDirectory()) { 160 destination.mkdirs(); 161 } 162 } catch (SecurityException e) { 163 LogUtil.CLog.e("Unable to establish temp directory " + destination.getPath()); 164 } 165 Assert.assertTrue("Failed to create test director: " + tmpDir, destination.isDirectory()); 166 167 // Download the testsuit tar file. 168 downloadFile("veqtests.tar.gz", destination); 169 170 // Unpack the testsuit tar file. 171 int result = runCommand("tar xvzf veqtests.tar.gz", destination); 172 Assert.assertTrue("Failed to untar veqtests.tar.gz", result == 0); 173 174 // Execute the script to run the test. 175 String testCommand = "./testit.sh --serial " + targetSerial; 176 if (mQuickCheck) testCommand += " --enablequickrun YES"; 177 if (mDisableB) testCommand += " --enableb NO"; 178 if (earlyTermination) testCommand += " --exitonerror YES"; 179 result = runCommand(testCommand, destination); 180 181 if (mpc >= MEDIA_PERFORMANCE_CLASS_14 || mForceToRun) { 182 Assert.assertTrue( 183 "test device advertises mpc=" + mpc 184 + ", but failed to pass the video encoding quality test.", 185 result == 0); 186 } else { 187 Assume.assumeTrue( 188 "test device advertises mpc=" + mpc 189 + ", and did not pass the video encoding quality test.", 190 result == 0); 191 } 192 193 LogUtil.CLog.i("Finished executing " + testCommand); 194 } 195 runCommand(String cmd, File dir)196 private int runCommand(String cmd, File dir) throws IOException, InterruptedException { 197 Process process = Runtime.getRuntime().exec(cmd, null, dir); 198 199 BufferedReader stdInput = 200 new BufferedReader(new InputStreamReader(process.getInputStream())); 201 BufferedReader stdError = 202 new BufferedReader(new InputStreamReader(process.getErrorStream())); 203 String line = ""; 204 boolean isOutReady = false; 205 boolean isErrorReady = false; 206 boolean isProcessAlive = false; 207 208 while (process.isAlive()) { 209 do { 210 isOutReady = stdInput.ready(); 211 212 if (isOutReady) { 213 line = stdInput.readLine(); 214 LogUtil.CLog.i("== " + line + "\n"); 215 } 216 217 isErrorReady = stdError.ready(); 218 if (isErrorReady) { 219 line = stdError.readLine(); 220 LogUtil.CLog.i("xx " + line + "\n"); 221 } 222 223 isProcessAlive = process.isAlive(); 224 if (!isProcessAlive) { 225 LogUtil.CLog.i("::Process DIED! " + line + "\n"); 226 line = null; 227 process.waitFor(1000, TimeUnit.MILLISECONDS); 228 } 229 230 } while (line != null); 231 232 process.waitFor(100, TimeUnit.MILLISECONDS); 233 } 234 235 return process.exitValue(); 236 } 237 238 // Download the indicated file (within the base_url folder) to 239 // our desired destination/fileName. 240 // simple caching -- if file exists, we do not redownload downloadFile(String fileName, File destDir)241 private void downloadFile(String fileName, File destDir) { 242 File destination = new File(destDir, fileName); 243 244 // save bandwidth, also allows a user to manually preload files 245 LogUtil.CLog.i("Do we already have a copy of file " + destination.getPath()); 246 if (destination.isFile()) { 247 LogUtil.CLog.i("Skipping re-download of file " + destination.getPath()); 248 return; 249 } 250 251 String url = BASE_URL + fileName; 252 String cmd = "wget -O " + destination.getPath() + " " + url; 253 LogUtil.CLog.i("wget_cmd = " + cmd); 254 255 int result = 0; 256 257 try { 258 result = runCommand(cmd, destDir); 259 } catch (IOException e) { 260 result = -2; 261 } catch (InterruptedException e) { 262 result = -3; 263 } 264 Assert.assertTrue("downloadFile failed.\n", result == 0); 265 } 266 } 267