1 /* 2 * Copyright 2019 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.google.sample.oboe.manualtest; 18 19 import android.os.Bundle; 20 21 import java.io.IOException; 22 23 public class BaseAutoGlitchActivity extends GlitchActivity { 24 25 private static final int SETUP_TIME_SECONDS = 4; // Time for the stream to settle. 26 protected static final int DEFAULT_DURATION_SECONDS = 8; // Run time for each test. 27 private static final int DEFAULT_GAP_MILLIS = 400; // Idle time between each test. 28 private static final String TEXT_SKIP = "SKIP"; 29 public static final String TEXT_PASS = "PASS"; 30 public static final String TEXT_FAIL = "FAIL !!!!"; 31 32 protected int mDurationSeconds = DEFAULT_DURATION_SECONDS; 33 protected int mGapMillis = DEFAULT_GAP_MILLIS; 34 35 protected AutomatedTestRunner mAutomatedTestRunner; 36 37 @Override onCreate(Bundle savedInstanceState)38 protected void onCreate(Bundle savedInstanceState) { 39 super.onCreate(savedInstanceState); 40 41 mAutomatedTestRunner = findViewById(R.id.auto_test_runner); 42 mAutomatedTestRunner.setActivity(this); 43 } 44 log(String text)45 protected void log(String text) { 46 mAutomatedTestRunner.log(text); 47 } 48 appendFailedSummary(String text)49 protected void appendFailedSummary(String text) { 50 mAutomatedTestRunner.appendFailedSummary(text); 51 } 52 appendSummary(String text)53 protected void appendSummary(String text) { 54 mAutomatedTestRunner.appendSummary(text); 55 } 56 57 @Override onStopTest()58 public void onStopTest() { 59 mAutomatedTestRunner.stopTest(); 60 } 61 getConfigText(StreamConfiguration config)62 protected String getConfigText(StreamConfiguration config) { 63 int channel = (config.getDirection() == StreamConfiguration.DIRECTION_OUTPUT) 64 ? getOutputChannel() : getInputChannel(); 65 return ((config.getDirection() == StreamConfiguration.DIRECTION_OUTPUT) ? "OUT" : "INP") 66 + (config.isMMap() ? "-M" : "-L") 67 + ", ID = " + String.format("%2d", config.getDeviceId()) 68 + ", SR = " + String.format("%5d", config.getSampleRate()) 69 + ", Perf = " + StreamConfiguration.convertPerformanceModeToText( 70 config.getPerformanceMode()) 71 + ", " + StreamConfiguration.convertSharingModeToText(config.getSharingMode()) 72 + ", ch = " + config.getChannelCount() + "[" + channel + "]"; 73 } 74 75 public final static int TEST_RESULT_FAILED = -2; 76 public final static int TEST_RESULT_WARNING = -1; 77 public final static int TEST_RESULT_SKIPPED = 0; 78 public final static int TEST_RESULT_PASSED = 1; 79 80 // Run test based on the requested input/output configurations. testConfigurations()81 protected int testConfigurations() throws InterruptedException { 82 int result = TEST_RESULT_SKIPPED; 83 mAutomatedTestRunner.incrementTestCount(); 84 if ((getSingleTestIndex() >= 0) && (mAutomatedTestRunner.getTestCount() != getSingleTestIndex())) { 85 return result; 86 } 87 88 log("========================== #" + mAutomatedTestRunner.getTestCount()); 89 90 StreamConfiguration requestedInConfig = mAudioInputTester.requestedConfiguration; 91 StreamConfiguration requestedOutConfig = mAudioOutTester.requestedConfiguration; 92 93 StreamConfiguration actualInConfig = mAudioInputTester.actualConfiguration; 94 StreamConfiguration actualOutConfig = mAudioOutTester.actualConfiguration; 95 96 log("Requested:"); 97 log(" " + getConfigText(requestedInConfig)); 98 log(" " + getConfigText(requestedOutConfig)); 99 100 String reason = ""; 101 boolean openFailed = false; 102 try { 103 openAudio(); // this will fill in actualConfig 104 log("Actual:"); 105 log(" " + getConfigText(actualInConfig)); 106 log(" " + getConfigText(actualOutConfig)); 107 // Set output size to a level that will avoid glitches. 108 AudioStreamBase stream = mAudioOutTester.getCurrentAudioStream(); 109 int sizeFrames = stream.getBufferCapacityInFrames() / 2; 110 stream.setBufferSizeInFrames(sizeFrames); 111 } catch (Exception e) { 112 openFailed = true; 113 log(e.getMessage()); 114 reason = e.getMessage(); 115 } 116 117 // The test would only be worth running if we got the configuration we requested on input or output. 118 String skipReason = shouldTestBeSkipped(); 119 boolean skipped = skipReason.length() > 0; 120 boolean valid = !openFailed && !skipped; 121 boolean startFailed = false; 122 if (valid) { 123 try { 124 startAudioTest(); 125 } catch (IOException e) { 126 e.printStackTrace(); 127 valid = false; 128 startFailed = true; 129 log(e.getMessage()); 130 reason = e.getMessage(); 131 } 132 } 133 mAutomatedTestRunner.flushLog(); 134 135 if (valid) { 136 // Check for early return until we reach full duration. 137 long now = System.currentTimeMillis(); 138 long startedAt = now; 139 long endTime = System.currentTimeMillis() + (mDurationSeconds * 1000); 140 boolean finishedEarly = false; 141 while (now < endTime && !finishedEarly) { 142 Thread.sleep(100); // Let test run. 143 now = System.currentTimeMillis(); 144 finishedEarly = isFinishedEarly(); 145 if (finishedEarly) { 146 log("Finished early after " + (now - startedAt) + " msec."); 147 } 148 } 149 } 150 int inXRuns = 0; 151 int outXRuns = 0; 152 153 if (!openFailed) { 154 // get xRuns before closing the streams. 155 inXRuns = mAudioInputTester.getCurrentAudioStream().getXRunCount(); 156 outXRuns = mAudioOutTester.getCurrentAudioStream().getXRunCount(); 157 158 super.stopAudioTest(); 159 } 160 161 if (openFailed || startFailed) { 162 appendFailedSummary("------ #" + mAutomatedTestRunner.getTestCount() + "\n"); 163 appendFailedSummary(getConfigText(requestedInConfig) + "\n"); 164 appendFailedSummary(getConfigText(requestedOutConfig) + "\n"); 165 appendFailedSummary(reason + "\n"); 166 mAutomatedTestRunner.incrementFailCount(); 167 } else if (skipped) { 168 log(TEXT_SKIP + " - " + skipReason); 169 } else { 170 log("Result:"); 171 reason += didTestFail(); 172 boolean passed = reason.length() == 0; 173 174 String resultText = getShortReport(); 175 resultText += ", xruns = " + inXRuns + "/" + outXRuns; 176 resultText += ", " + (passed ? TEXT_PASS : TEXT_FAIL); 177 resultText += reason; 178 log(" " + resultText); 179 if (!passed) { 180 appendFailedSummary("------ #" + mAutomatedTestRunner.getTestCount() + "\n"); 181 appendFailedSummary(" " + getConfigText(actualInConfig) + "\n"); 182 appendFailedSummary(" " + getConfigText(actualOutConfig) + "\n"); 183 appendFailedSummary(" " + resultText + "\n"); 184 mAutomatedTestRunner.incrementFailCount(); 185 result = TEST_RESULT_FAILED; 186 } else { 187 mAutomatedTestRunner.incrementPassCount(); 188 result = TEST_RESULT_PASSED; 189 } 190 } 191 mAutomatedTestRunner.flushLog(); 192 193 // Give hardware time to settle between tests. 194 Thread.sleep(mGapMillis); 195 return result; 196 } 197 isFinishedEarly()198 protected boolean isFinishedEarly() { 199 return false; 200 } 201 shouldTestBeSkipped()202 protected String shouldTestBeSkipped() { 203 String why = ""; 204 StreamConfiguration requestedInConfig = mAudioInputTester.requestedConfiguration; 205 StreamConfiguration requestedOutConfig = mAudioOutTester.requestedConfiguration; 206 StreamConfiguration actualInConfig = mAudioInputTester.actualConfiguration; 207 StreamConfiguration actualOutConfig = mAudioOutTester.actualConfiguration; 208 // No point running the test if we don't get the sharing mode we requested. 209 if (actualInConfig.getSharingMode() != requestedInConfig.getSharingMode() 210 || actualOutConfig.getSharingMode() != requestedOutConfig.getSharingMode()) { 211 log("Did not get requested sharing mode."); 212 why += "share"; 213 } 214 // We don't skip based on performance mode because if you request LOW_LATENCY you might 215 // get a smaller burst than if you request NONE. 216 return why; 217 } 218 didTestFail()219 public String didTestFail() { 220 String why = ""; 221 if (getMaxSecondsWithNoGlitch() <= (mDurationSeconds - SETUP_TIME_SECONDS)) { 222 why += ", glitch"; 223 } 224 return why; 225 } 226 227 } 228