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.media.tests; 18 19 import com.android.ddmlib.CollectingOutputReceiver; 20 import com.android.tradefed.device.DeviceNotAvailableException; 21 import com.android.tradefed.device.ITestDevice; 22 import com.android.tradefed.log.LogUtil.CLog; 23 import com.android.tradefed.result.ITestInvocationListener; 24 import com.android.tradefed.result.TestDescription; 25 import com.android.tradefed.testtype.IDeviceTest; 26 import com.android.tradefed.testtype.IRemoteTest; 27 import com.android.tradefed.util.proto.TfMetricProtoUtil; 28 29 import java.util.Collections; 30 import java.util.HashMap; 31 import java.util.Map; 32 import java.util.concurrent.TimeUnit; 33 34 /** 35 * A harness that launches AudioJitter tool and reports result. 36 */ 37 public class AudioJitterTest implements IDeviceTest, IRemoteTest { 38 39 private static final String RUN_KEY = "audiojitter"; 40 private static final long TIMEOUT_MS = 5 * 60 * 1000; // 5 min 41 private static final int MAX_ATTEMPTS = 3; 42 private static final Map<String, String> METRICS_KEY_MAP = createMetricsKeyMap(); 43 44 private ITestDevice mDevice; 45 46 private static final String DEVICE_TEMPORARY_DIR_PATH = "/data/local/tmp/"; 47 private static final String JITTER_BINARY_FILENAME = "sljitter"; 48 private static final String JITTER_BINARY_DEVICE_PATH = 49 DEVICE_TEMPORARY_DIR_PATH + JITTER_BINARY_FILENAME; 50 createMetricsKeyMap()51 private static Map<String, String> createMetricsKeyMap() { 52 Map<String, String> result = new HashMap<String, String>(); 53 result.put("min_jitter_ticks", "min_jitter_ticks"); 54 result.put("min_jitter_ms", "min_jitter_ms"); 55 result.put("min_jitter_period_id", "min_jitter_period_id"); 56 result.put("max_jitter_ticks", "max_jitter_ticks"); 57 result.put("max_jitter_ms", "max_jitter_ms"); 58 result.put("max_jitter_period_id", "max_jitter_period_id"); 59 result.put("mark_jitter_ticks", "mark_jitter_ticks"); 60 result.put("mark_jitter_ms", "mark_jitter_ms"); 61 result.put("max_cb_done_delay_ms", "max_cb_done_delay_ms"); 62 result.put("max_thread_delay_ms", "max_thread_delay_ms"); 63 result.put("max_render_delay_ms", "max_render_delay_ms"); 64 result.put("drift_rate", "drift_rate"); 65 result.put("error_ms", "error_ms"); 66 result.put("min_error_ms", "min_error_ms"); 67 result.put("max_error_ms", "max_error_ms"); 68 return Collections.unmodifiableMap(result); 69 } 70 71 /** 72 * {@inheritDoc} 73 */ 74 @Override setDevice(ITestDevice device)75 public void setDevice(ITestDevice device) { 76 mDevice = device; 77 } 78 79 /** 80 * {@inheritDoc} 81 */ 82 @Override getDevice()83 public ITestDevice getDevice() { 84 return mDevice; 85 } 86 87 /** 88 * {@inheritDoc} 89 */ 90 @Override run(ITestInvocationListener listener)91 public void run(ITestInvocationListener listener) throws DeviceNotAvailableException { 92 TestDescription testId = new TestDescription(getClass().getCanonicalName(), RUN_KEY); 93 ITestDevice device = getDevice(); 94 95 listener.testRunStarted(RUN_KEY, 0); 96 listener.testStarted(testId); 97 98 long testStartTime = System.currentTimeMillis(); 99 Map<String, String> metrics = new HashMap<String, String>(); 100 String errMsg = null; 101 102 // start jitter and wait for process to complete 103 CollectingOutputReceiver receiver = new CollectingOutputReceiver(); 104 device.executeShellCommand(JITTER_BINARY_DEVICE_PATH, receiver, 105 TIMEOUT_MS, TimeUnit.MILLISECONDS, MAX_ATTEMPTS); 106 String resultStr = receiver.getOutput(); 107 108 if (resultStr != null) { 109 // parse result 110 CLog.i("== Jitter result =="); 111 Map<String, String> jitterResult = parseResult(resultStr); 112 if (jitterResult == null) { 113 errMsg = "Failed to parse Jitter result."; 114 } else { 115 metrics = jitterResult; 116 } 117 } else { 118 errMsg = "Jitter result not found."; 119 } 120 121 if (errMsg != null) { 122 CLog.e(errMsg); 123 listener.testFailed(testId, errMsg); 124 listener.testEnded(testId, TfMetricProtoUtil.upgradeConvert(metrics)); 125 listener.testRunFailed(errMsg); 126 } else { 127 long durationMs = System.currentTimeMillis() - testStartTime; 128 listener.testEnded(testId, TfMetricProtoUtil.upgradeConvert(metrics)); 129 listener.testRunEnded(durationMs, TfMetricProtoUtil.upgradeConvert(metrics)); 130 } 131 } 132 133 /** 134 * Parse Jitter result. 135 * 136 * @param result Jitter result output 137 * @return a {@link HashMap} that contains metrics keys and results 138 */ parseResult(String result)139 private Map<String, String> parseResult(String result) { 140 Map<String, String> resultMap = new HashMap<String, String>(); 141 String lines[] = result.split("\\r?\\n"); 142 for (String line: lines) { 143 line = line.trim().replaceAll(" +", " "); 144 String[] tokens = line.split(" "); 145 if (tokens.length >= 2) { 146 String metricName = tokens[0]; 147 String metricValue = tokens[1]; 148 if (METRICS_KEY_MAP.containsKey(metricName)) { 149 CLog.i(String.format("%s: %s", metricName, metricValue)); 150 resultMap.put(METRICS_KEY_MAP.get(metricName), metricValue); 151 } 152 } 153 } 154 return resultMap; 155 } 156 } 157