Revert "Merge prod-tests/src/com/android/media/tests/ from platform/tools/tradefederation to src/com/android/media/tests/ BUG:63819116"
Causing tests failure (go/tf-tests)
This reverts commit 8d9e993516f8177bc46f3bd1a177b6cdfe698540.
Change-Id: I429b8d67544c1b4c46ebc85829d1069b965b584c
diff --git a/src/com/android/media/tests/AdbScreenrecordTest.java b/src/com/android/media/tests/AdbScreenrecordTest.java
deleted file mode 100644
index eb50f50..0000000
--- a/src/com/android/media/tests/AdbScreenrecordTest.java
+++ /dev/null
@@ -1,433 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.android.media.tests;
-
-import com.android.ddmlib.CollectingOutputReceiver;
-import com.android.ddmlib.testrunner.TestIdentifier;
-import com.android.tradefed.config.Option;
-import com.android.tradefed.device.DeviceNotAvailableException;
-import com.android.tradefed.device.IFileEntry;
-import com.android.tradefed.device.ITestDevice;
-import com.android.tradefed.log.LogUtil.CLog;
-import com.android.tradefed.result.ITestInvocationListener;
-import com.android.tradefed.testtype.IDeviceTest;
-import com.android.tradefed.testtype.IRemoteTest;
-import com.android.tradefed.util.CommandResult;
-import com.android.tradefed.util.CommandStatus;
-import com.android.tradefed.util.FileUtil;
-import com.android.tradefed.util.RunUtil;
-
-import java.io.File;
-import java.text.ParseException;
-import java.text.SimpleDateFormat;
-import java.util.Arrays;
-import java.util.Date;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.TimeZone;
-import java.util.concurrent.TimeUnit;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-
-/**
- * Tests adb command "screenrecord", i.e. "adb screenrecord [--size] [--bit-rate] [--time-limit]"
- *
- * <p>The test use the above command to record a video of DUT's screen. It then tries to verify that
- * a video was actually recorded and that the video is a valid video file. It currently uses
- * 'avprobe' to do the video analysis along with extracting parameters from the adb command's
- * output.
- */
-public class AdbScreenrecordTest implements IDeviceTest, IRemoteTest {
-
- //===================================================================
- // TEST OPTIONS
- //===================================================================
- @Option(name = "run-key", description = "Run key for the test")
- private String mRunKey = "AdbScreenRecord";
-
- @Option(name = "time-limit", description = "Recording time in seconds", isTimeVal = true)
- private long mRecordTimeInSeconds = -1;
-
- @Option(name = "size", description = "Video Size: 'widthxheight', e.g. '1280x720'")
- private String mVideoSize = null;
-
- @Option(name = "bit-rate", description = "Video bit rate in megabits per second, e.g. 4000000")
- private long mBitRate = -1;
-
- //===================================================================
- // CLASS VARIABLES
- //===================================================================
- private ITestDevice mDevice;
- private TestRunHelper mTestRunHelper;
-
- //===================================================================
- // CONSTANTS
- //===================================================================
- private static final long TEST_TIMEOUT_MS = 5 * 60 * 1000; // 5 min
- private static final long DEVICE_SYNC_MS = 5 * 60 * 1000; // 5 min
- private static final long POLLING_INTERVAL_MS = 5 * 1000; // 5 sec
- private static final long CMD_TIMEOUT_MS = 5 * 1000; // 5 sec
- private static final String ERR_OPTION_MALFORMED = "Test option %1$s is not correct [%2$s]";
- private static final String OPTION_TIME_LIMIT = "--time-limit";
- private static final String OPTION_SIZE = "--size";
- private static final String OPTION_BITRATE = "--bit-rate";
- private static final String RESULT_KEY_RECORDED_FRAMES = "recorded_frames";
- private static final String RESULT_KEY_RECORDED_LENGTH = "recorded_length";
- private static final String RESULT_KEY_VERIFIED_DURATION = "verified_duration";
- private static final String RESULT_KEY_VERIFIED_BITRATE = "verified_bitrate";
- private static final String TEST_FILE = "/sdcard/screenrecord_test.mp4";
- private static final String AVPROBE_NOT_INSTALLED =
- "Program 'avprobe' is not installed on host '%1$s'";
- private static final String REGEX_IS_VIDEO_OK =
- "Duration: (\\d\\d:\\d\\d:\\d\\d.\\d\\d).+bitrate: (\\d+ .b\\/s)";
- private static final String AVPROBE_STR = "avprobe";
-
- //===================================================================
- // ENUMS
- //===================================================================
- enum HOST_SOFTWARE {
- AVPROBE
- }
-
- @Override
- public void setDevice(ITestDevice device) {
- mDevice = device;
- }
-
- @Override
- public ITestDevice getDevice() {
- return mDevice;
- }
-
- /** Main test function invoked by test harness */
- @Override
- public void run(ITestInvocationListener listener) throws DeviceNotAvailableException {
- initializeTest(listener);
-
- CLog.i("Verify required software is installed on host");
- verifyRequiredSoftwareIsInstalled(HOST_SOFTWARE.AVPROBE);
-
- mTestRunHelper.startTest(1);
-
- Map<String, String> resultsDictionary = new HashMap<String, String>();
- try {
- CLog.i("Verify that test options are valid");
- if (!verifyTestParameters()) {
- return;
- }
-
- // "resultDictionary" can be used to post results to dashboards like BlackBox
- resultsDictionary = runTest(resultsDictionary, TEST_TIMEOUT_MS);
- } finally {
- final String metricsStr = Arrays.toString(resultsDictionary.entrySet().toArray());
- CLog.i("Uploading metrics values:\n" + metricsStr);
- mTestRunHelper.endTest(resultsDictionary);
- }
- }
-
- /**
- * Test code that calls "adb screenrecord" and checks for pass/fail criterias
- *
- * <p>
- *
- * <ul>
- * <li>1. Run adb screenrecord command
- * <li>2. Wait until there is a video file; fail if none appears
- * <li>3. Analyze adb output and extract recorded number of frames and video length
- * <li>4. Pull recorded video file off device
- * <li>5. Using avprobe, analyze video file and extract duration and bitrate
- * <li>6. Return extracted results
- * </ul>
- *
- * @throws DeviceNotAvailableException
- */
- private Map<String, String> runTest(Map<String, String> results, final long timeout)
- throws DeviceNotAvailableException {
- final CollectingOutputReceiver receiver = new CollectingOutputReceiver();
- final String cmd = generateAdbScreenRecordCommand();
- final String deviceFileName = getAbsoluteFilename();
-
- CLog.i("START Execute device shell command: '" + cmd + "'");
- getDevice().executeShellCommand(cmd, receiver, timeout, TimeUnit.MILLISECONDS, 3);
- String adbOutput = receiver.getOutput();
- CLog.i(adbOutput);
- CLog.i("END Execute device shell command");
-
- CLog.i("Wait for recorded file: " + deviceFileName);
- if (!waitForFile(getDevice(), timeout, deviceFileName)) {
- mTestRunHelper.reportFailure("Recorded test file not found");
- // Since we don't have a file, no need to delete it; we can return here
- return results;
- }
-
- CLog.i("Get number of recorded frames and recorded length from adb output");
- if (!extractVideoDataFromAdbOutput(adbOutput, results)) {
- deleteFileFromDevice(deviceFileName);
- return results;
- }
-
- CLog.i("Get duration and bitrate info from video file using '" + AVPROBE_STR + "'");
- try {
- extractDurationAndBitrateFromVideoFileUsingAvprobe(deviceFileName, results);
- } catch (ParseException e) {
- throw new RuntimeException(e);
- }
- deleteFileFromDevice(deviceFileName);
- return results;
- }
-
- /** Convert a string on form HH:mm:ss.SS to nearest number of seconds */
- private long convertBitrateToKilobits(String bitrate) {
- Matcher m = Pattern.compile("(\\d+) (.)b\\/s").matcher(bitrate);
- if (!m.matches()) {
- return -1;
- }
-
- final String unit = m.group(2).toUpperCase();
- long factor = 1;
- switch (unit) {
- case "K":
- factor = 1;
- break;
- case "M":
- factor = 1000;
- break;
- case "G":
- factor = 1000000;
- break;
- }
-
- long rate = Long.parseLong(m.group(1));
-
- return rate * factor;
- }
-
- /**
- * Convert a string on form HH:mm:ss.SS to nearest number of seconds
- *
- * @throws ParseException
- */
- private long convertDurationToMilliseconds(String duration) throws ParseException {
- SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SS");
- sdf.setTimeZone(TimeZone.getTimeZone("UTC"));
- Date convertedDate = sdf.parse("1970-01-01 " + duration);
- return convertedDate.getTime();
- }
-
- /**
- * Deletes a file off a device
- *
- * @param deviceFileName - path and filename to file to be deleted
- * @throws DeviceNotAvailableException
- */
- private void deleteFileFromDevice(String deviceFileName) throws DeviceNotAvailableException {
- CLog.i("Delete file from device: " + deviceFileName);
- getDevice().executeShellCommand("rm -f " + deviceFileName);
- }
-
- /**
- * Extracts duration and bitrate data from a video file
- *
- * @throws DeviceNotAvailableException
- * @throws ParseException
- */
- private boolean extractDurationAndBitrateFromVideoFileUsingAvprobe(
- String deviceFileName, Map<String, String> results)
- throws DeviceNotAvailableException, ParseException {
- CLog.i("Check if the recorded file has some data in it: " + deviceFileName);
- IFileEntry video = getDevice().getFileEntry(deviceFileName);
- if (video == null || video.getFileEntry().getSizeValue() < 1) {
- mTestRunHelper.reportFailure("Video Entry info failed");
- return false;
- }
-
- final File recordedVideo = getDevice().pullFile(deviceFileName);
- CLog.i("Recorded video file: " + recordedVideo.getAbsolutePath());
-
- CommandResult result =
- RunUtil.getDefault()
- .runTimedCmd(
- CMD_TIMEOUT_MS,
- AVPROBE_STR,
- "-loglevel",
- "info",
- recordedVideo.getAbsolutePath());
-
- // Remove file from host machine
- FileUtil.deleteFile(recordedVideo);
-
- if (result.getStatus() != CommandStatus.SUCCESS) {
- mTestRunHelper.reportFailure(AVPROBE_STR + " command failed");
- return false;
- }
-
- String data = result.getStderr();
- CLog.i("data: " + data);
- if (data == null || data.isEmpty()) {
- mTestRunHelper.reportFailure(AVPROBE_STR + " output data is empty");
- return false;
- }
-
- Matcher m = Pattern.compile(REGEX_IS_VIDEO_OK).matcher(data);
- if (!m.find()) {
- final String errMsg =
- "Video verification failed; no matching verification pattern found";
- mTestRunHelper.reportFailure(errMsg);
- return false;
- }
-
- String duration = m.group(1);
- long durationInMilliseconds = convertDurationToMilliseconds(duration);
- String bitrate = m.group(2);
- long bitrateInKilobits = convertBitrateToKilobits(bitrate);
-
- results.put(RESULT_KEY_VERIFIED_DURATION, Long.toString(durationInMilliseconds / 1000));
- results.put(RESULT_KEY_VERIFIED_BITRATE, Long.toString(bitrateInKilobits));
- return true;
- }
-
- /** Extracts recorded number of frames and recorded video length from adb output */
- private boolean extractVideoDataFromAdbOutput(String adbOutput, Map<String, String> results) {
- final String regEx = "recorded (\\d+) frames in (\\d+) second";
- Matcher m = Pattern.compile(regEx).matcher(adbOutput);
- if (!m.find()) {
- mTestRunHelper.reportFailure("Regular Expression did not find recorded frames");
- return false;
- }
-
- int recordedFrames = Integer.parseInt(m.group(1));
- int recordedLength = Integer.parseInt(m.group(2));
- CLog.i("Recorded frames: " + recordedFrames);
- CLog.i("Recorded length: " + recordedLength);
- if (recordedFrames <= 0) {
- mTestRunHelper.reportFailure("No recorded frames detected");
- return false;
- }
-
- results.put(RESULT_KEY_RECORDED_FRAMES, Integer.toString(recordedFrames));
- results.put(RESULT_KEY_RECORDED_LENGTH, Integer.toString(recordedLength));
- return true;
- }
-
- /** Generates an adb command from passed in test options */
- private String generateAdbScreenRecordCommand() {
- final String SPACE = " ";
- StringBuilder sb = new StringBuilder(128);
- sb.append("screenrecord --verbose ").append(getAbsoluteFilename());
-
- // Add test options if they have been passed in to the test
- if (mRecordTimeInSeconds != -1) {
- final long timeLimit = TimeUnit.MILLISECONDS.toSeconds(mRecordTimeInSeconds);
- sb.append(SPACE).append(OPTION_TIME_LIMIT).append(SPACE).append(timeLimit);
- }
-
- if (mVideoSize != null) {
- sb.append(SPACE).append(OPTION_SIZE).append(SPACE).append(mVideoSize);
- }
-
- if (mBitRate != -1) {
- sb.append(SPACE).append(OPTION_BITRATE).append(SPACE).append(mBitRate);
- }
-
- return sb.toString();
- }
-
- /** Returns absolute path to device recorded video file */
- private String getAbsoluteFilename() {
- return TEST_FILE;
- }
-
- /** Performs test initialization steps */
- private void initializeTest(ITestInvocationListener listener)
- throws UnsupportedOperationException, DeviceNotAvailableException {
- TestIdentifier testId = new TestIdentifier(getClass().getCanonicalName(), mRunKey);
-
- // Allocate helpers
- mTestRunHelper = new TestRunHelper(listener, testId);
-
- getDevice().disableKeyguard();
- getDevice().waitForDeviceAvailable(DEVICE_SYNC_MS);
-
- CLog.i("Sync device time to host time");
- getDevice().setDate(new Date());
- }
-
- /** Verifies that required software is installed on host machine */
- private void verifyRequiredSoftwareIsInstalled(HOST_SOFTWARE software) {
- String swName = "";
- switch (software) {
- case AVPROBE:
- swName = AVPROBE_STR;
- CommandResult result =
- RunUtil.getDefault().runTimedCmd(CMD_TIMEOUT_MS, swName, "-version");
- String output = result.getStdout();
- if (result.getStatus() == CommandStatus.SUCCESS && output.startsWith(swName)) {
- return;
- }
- break;
- }
-
- CLog.i("Program '" + swName + "' not found, report test failure");
- String hostname = RunUtil.getDefault().runTimedCmd(CMD_TIMEOUT_MS, "hostname").getStdout();
-
- String err = String.format(AVPROBE_NOT_INSTALLED, (hostname == null) ? "" : hostname);
- throw new RuntimeException(err);
- }
-
- /** Verifies that passed in test parameters are legitimate */
- private boolean verifyTestParameters() {
- if (mRecordTimeInSeconds != -1 && mRecordTimeInSeconds < 1) {
- final String error =
- String.format(ERR_OPTION_MALFORMED, OPTION_TIME_LIMIT, mRecordTimeInSeconds);
- mTestRunHelper.reportFailure(error);
- return false;
- }
-
- if (mVideoSize != null) {
- final String videoSizeRegEx = "\\d+x\\d+";
- Matcher m = Pattern.compile(videoSizeRegEx).matcher(mVideoSize);
- if (!m.matches()) {
- final String error = String.format(ERR_OPTION_MALFORMED, OPTION_SIZE, mVideoSize);
- mTestRunHelper.reportFailure(error);
- return false;
- }
- }
-
- if (mBitRate != -1 && mBitRate < 1) {
- final String error = String.format(ERR_OPTION_MALFORMED, OPTION_BITRATE, mBitRate);
- mTestRunHelper.reportFailure(error);
- return false;
- }
-
- return true;
- }
-
- /** Checks for existence of a file on the device */
- private static boolean waitForFile(
- ITestDevice device, final long timeout, final String absoluteFilename)
- throws DeviceNotAvailableException {
- final long checkFileStartTime = System.currentTimeMillis();
-
- do {
- RunUtil.getDefault().sleep(POLLING_INTERVAL_MS);
- if (device.doesFileExist(absoluteFilename)) {
- return true;
- }
- } while (System.currentTimeMillis() - checkFileStartTime < timeout);
-
- return false;
- }
-}
diff --git a/src/com/android/media/tests/AudioJitterTest.java b/src/com/android/media/tests/AudioJitterTest.java
deleted file mode 100644
index 7058cc7..0000000
--- a/src/com/android/media/tests/AudioJitterTest.java
+++ /dev/null
@@ -1,155 +0,0 @@
-/*
- * Copyright (C) 2014 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.media.tests;
-
-import com.android.ddmlib.CollectingOutputReceiver;
-import com.android.ddmlib.testrunner.TestIdentifier;
-import com.android.tradefed.device.DeviceNotAvailableException;
-import com.android.tradefed.device.ITestDevice;
-import com.android.tradefed.log.LogUtil.CLog;
-import com.android.tradefed.result.ITestInvocationListener;
-import com.android.tradefed.testtype.IDeviceTest;
-import com.android.tradefed.testtype.IRemoteTest;
-
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.concurrent.TimeUnit;
-
-/**
- * A harness that launches AudioJitter tool and reports result.
- */
-public class AudioJitterTest implements IDeviceTest, IRemoteTest {
-
- private static final String RUN_KEY = "audiojitter";
- private static final long TIMEOUT_MS = 5 * 60 * 1000; // 5 min
- private static final int MAX_ATTEMPTS = 3;
- private static final Map<String, String> METRICS_KEY_MAP = createMetricsKeyMap();
-
- private ITestDevice mDevice;
-
- private static final String DEVICE_TEMPORARY_DIR_PATH = "/data/local/tmp/";
- private static final String JITTER_BINARY_FILENAME = "sljitter";
- private static final String JITTER_BINARY_DEVICE_PATH =
- DEVICE_TEMPORARY_DIR_PATH + JITTER_BINARY_FILENAME;
-
- private static Map<String, String> createMetricsKeyMap() {
- Map<String, String> result = new HashMap<String, String>();
- result.put("min_jitter_ticks", "min_jitter_ticks");
- result.put("min_jitter_ms", "min_jitter_ms");
- result.put("min_jitter_period_id", "min_jitter_period_id");
- result.put("max_jitter_ticks", "max_jitter_ticks");
- result.put("max_jitter_ms", "max_jitter_ms");
- result.put("max_jitter_period_id", "max_jitter_period_id");
- result.put("mark_jitter_ticks", "mark_jitter_ticks");
- result.put("mark_jitter_ms", "mark_jitter_ms");
- result.put("max_cb_done_delay_ms", "max_cb_done_delay_ms");
- result.put("max_thread_delay_ms", "max_thread_delay_ms");
- result.put("max_render_delay_ms", "max_render_delay_ms");
- result.put("drift_rate", "drift_rate");
- result.put("error_ms", "error_ms");
- result.put("min_error_ms", "min_error_ms");
- result.put("max_error_ms", "max_error_ms");
- return Collections.unmodifiableMap(result);
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public void setDevice(ITestDevice device) {
- mDevice = device;
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public ITestDevice getDevice() {
- return mDevice;
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public void run(ITestInvocationListener listener) throws DeviceNotAvailableException {
- TestIdentifier testId = new TestIdentifier(getClass().getCanonicalName(), RUN_KEY);
- ITestDevice device = getDevice();
-
- listener.testRunStarted(RUN_KEY, 0);
- listener.testStarted(testId);
-
- long testStartTime = System.currentTimeMillis();
- Map<String, String> metrics = new HashMap<String, String>();
- String errMsg = null;
-
- // start jitter and wait for process to complete
- CollectingOutputReceiver receiver = new CollectingOutputReceiver();
- device.executeShellCommand(JITTER_BINARY_DEVICE_PATH, receiver,
- TIMEOUT_MS, TimeUnit.MILLISECONDS, MAX_ATTEMPTS);
- String resultStr = receiver.getOutput();
-
- if (resultStr != null) {
- // parse result
- CLog.i("== Jitter result ==");
- Map<String, String> jitterResult = parseResult(resultStr);
- if (jitterResult == null) {
- errMsg = "Failed to parse Jitter result.";
- } else {
- metrics = jitterResult;
- }
- } else {
- errMsg = "Jitter result not found.";
- }
-
- if (errMsg != null) {
- CLog.e(errMsg);
- listener.testFailed(testId, errMsg);
- listener.testEnded(testId, metrics);
- listener.testRunFailed(errMsg);
- } else {
- long durationMs = System.currentTimeMillis() - testStartTime;
- listener.testEnded(testId, metrics);
- listener.testRunEnded(durationMs, metrics);
- }
- }
-
- /**
- * Parse Jitter result.
- *
- * @param result Jitter result output
- * @return a {@link HashMap} that contains metrics keys and results
- */
- private Map<String, String> parseResult(String result) {
- Map<String, String> resultMap = new HashMap<String, String>();
- String lines[] = result.split("\\r?\\n");
- for (String line: lines) {
- line = line.trim().replaceAll(" +", " ");
- String[] tokens = line.split(" ");
- if (tokens.length >= 2) {
- String metricName = tokens[0];
- String metricValue = tokens[1];
- if (METRICS_KEY_MAP.containsKey(metricName)) {
- CLog.i(String.format("%s: %s", metricName, metricValue));
- resultMap.put(METRICS_KEY_MAP.get(metricName), metricValue);
- }
- }
- }
- return resultMap;
- }
-}
diff --git a/src/com/android/media/tests/AudioLevelUtility.java b/src/com/android/media/tests/AudioLevelUtility.java
deleted file mode 100644
index 3aee1fb..0000000
--- a/src/com/android/media/tests/AudioLevelUtility.java
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.android.media.tests;
-
-import com.android.ddmlib.CollectingOutputReceiver;
-import com.android.tradefed.device.DeviceNotAvailableException;
-import com.android.tradefed.device.ITestDevice;
-import com.android.tradefed.log.LogUtil.CLog;
-
-import java.util.concurrent.TimeUnit;
-
-/** Class to provide audio level utility functions for a test device */
-public class AudioLevelUtility {
-
- public static int extractDeviceAudioLevelFromAdbShell(ITestDevice device)
- throws DeviceNotAvailableException {
-
- final String ADB_SHELL_DUMPSYS_AUDIO = "dumpsys audio";
- final String STREAM_MUSIC = "- STREAM_MUSIC:";
- final String HEADSET = "(headset): ";
-
- final CollectingOutputReceiver receiver = new CollectingOutputReceiver();
-
- device.executeShellCommand(
- ADB_SHELL_DUMPSYS_AUDIO, receiver, 300, TimeUnit.MILLISECONDS, 1);
- final String shellOutput = receiver.getOutput();
- if (shellOutput == null || shellOutput.isEmpty()) {
- return -1;
- }
-
- int audioLevel = -1;
- int pos = shellOutput.indexOf(STREAM_MUSIC);
- if (pos != -1) {
- pos = shellOutput.indexOf(HEADSET, pos);
- if (pos != -1) {
- final int start = pos + HEADSET.length();
- final int stop = shellOutput.indexOf(",", start);
- if (stop != -1) {
- final String audioLevelStr = shellOutput.substring(start, stop);
- try {
- audioLevel = Integer.parseInt(audioLevelStr);
- } catch (final NumberFormatException e) {
- CLog.e(e.getMessage());
- audioLevel = 1;
- }
- }
- }
- }
-
- return audioLevel;
- }
-}
diff --git a/src/com/android/media/tests/AudioLoopbackImageAnalyzer.java b/src/com/android/media/tests/AudioLoopbackImageAnalyzer.java
deleted file mode 100644
index 3b6d767..0000000
--- a/src/com/android/media/tests/AudioLoopbackImageAnalyzer.java
+++ /dev/null
@@ -1,475 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.android.media.tests;
-
-import com.android.tradefed.log.LogUtil.CLog;
-import com.android.tradefed.util.Pair;
-
-import java.awt.image.BufferedImage;
-import java.io.File;
-import java.io.IOException;
-import java.util.ArrayList;
-
-import javax.imageio.ImageIO;
-
-/**
- * Class that analyzes a screenshot captured from AudioLoopback test. There is a wave form in the
- * screenshot that has specific colors (TARGET_COLOR). This class extracts those colors and analyzes
- * wave amplitude, duration and form and make a decision if it's a legitimate wave form or not.
- */
-public class AudioLoopbackImageAnalyzer {
-
- // General
- private static final int HORIZONTAL_THRESHOLD = 10;
- private static final int VERTICAL_THRESHOLD = 0;
- private static final int PRIMARY_WAVE_COLOR = 0xFF1E4A99;
- private static final int SECONDARY_WAVE_COLOR = 0xFF1D4998;
- private static final int[] TARGET_COLORS_TABLET =
- new int[] {PRIMARY_WAVE_COLOR, SECONDARY_WAVE_COLOR};
- private static final int[] TARGET_COLORS_PHONE = new int[] {PRIMARY_WAVE_COLOR};
-
- private static final float EXPERIMENTAL_WAVE_MAX_TABLET = 69.0f; // In percent of image height
- private static final float EXPERIMENTAL_WAVE_MAX_PHONE = 32.0f; // In percent of image height
-
- // Image
- private static final int TABLET_SCREEN_MIN_WIDTH = 1700;
- private static final int TABLET_SCREEN_MIN_HEIGHT = 2300;
-
- // Duration parameters
- // Max duration should not span more than 2 of the 11 sections in the graph
- // Min duration should not be less than 1/4 of a section
- private static final float SECTION_WIDTH_IN_PERCENT = 100 * 1 / 11; // In percent of image width
- private static final float DURATION_MIN = SECTION_WIDTH_IN_PERCENT / 4;
-
- // Amplitude
- // Required numbers of column for a response
- private static final int MIN_NUMBER_OF_COLUMNS = 4;
- // The difference between two amplitude columns should not be more than this
- private static final float MAX_ALLOWED_COLUMN_DECREASE = 0.50f;
- // Only check MAX_ALLOWED_COLUMN_DECREASE up to this number
- private static final float MIN_NUMBER_OF_DECREASING_COLUMNS = 8;
-
- enum Result {
- PASS,
- FAIL,
- UNKNOWN
- }
-
- private static class Amplitude {
- public int maxHeight = -1;
- public int zeroCounter = 0;
- }
-
- public static Pair<Result, String> analyzeImage(String imgFile) {
- final String FN_TAG = "AudioLoopbackImageAnalyzer.analyzeImage";
-
- BufferedImage img = null;
- try {
- final File f = new File(imgFile);
- img = ImageIO.read(f);
- } catch (final IOException e) {
- CLog.e(e);
- throw new RuntimeException("Error loading image file '" + imgFile + "'");
- }
-
- final int width = img.getWidth();
- final int height = img.getHeight();
-
- CLog.i("image width=" + width + ", height=" + height);
-
- // Compute thresholds and min/max values based on image witdh, height
- final float waveMax;
- final int[] targetColors;
- final int amplitudeCenterMaxDiff;
- final float maxDuration;
- final int minNrOfZeroesBetweenAmplitudes;
-
- if (width >= TABLET_SCREEN_MIN_WIDTH && height >= TABLET_SCREEN_MIN_HEIGHT) {
- CLog.i("Apply TABLET config values");
- waveMax = EXPERIMENTAL_WAVE_MAX_TABLET;
- amplitudeCenterMaxDiff = 40;
- minNrOfZeroesBetweenAmplitudes = 8;
- maxDuration = 3 * SECTION_WIDTH_IN_PERCENT;
- targetColors = TARGET_COLORS_TABLET;
- } else {
- waveMax = EXPERIMENTAL_WAVE_MAX_PHONE;
- amplitudeCenterMaxDiff = 20;
- minNrOfZeroesBetweenAmplitudes = 5;
- maxDuration = 2.5f * SECTION_WIDTH_IN_PERCENT;
- targetColors = TARGET_COLORS_PHONE;
- }
-
- // Amplitude
- // Max height should be about 80% of wave max.
- // Min height should be about 40% of wave max.
- final float AMPLITUDE_MAX_VALUE = waveMax * 0.8f;
- final float AMPLITUDE_MIN_VALUE = waveMax * 0.4f;
-
- final int[] vertical = new int[height];
- final int[] horizontal = new int[width];
-
- projectPixelsToXAxis(img, targetColors, horizontal, width, height);
- filter(horizontal, HORIZONTAL_THRESHOLD);
- final Pair<Integer, Integer> durationBounds = getBounds(horizontal);
- if (!boundsWithinRange(durationBounds, 0, width)) {
- final String fmt = "%1$s Upper/Lower bound along horizontal axis not found";
- final String err = String.format(fmt, FN_TAG);
- CLog.w(err);
- return new Pair<Result, String>(Result.FAIL, err);
- }
-
- projectPixelsToYAxis(img, targetColors, vertical, height, durationBounds);
- filter(vertical, VERTICAL_THRESHOLD);
- final Pair<Integer, Integer> amplitudeBounds = getBounds(vertical);
- if (!boundsWithinRange(durationBounds, 0, height)) {
- final String fmt = "%1$s: Upper/Lower bound along vertical axis not found";
- final String err = String.format(fmt, FN_TAG);
- CLog.w(err);
- return new Pair<Result, String>(Result.FAIL, err);
- }
-
- final int durationLeft = durationBounds.first.intValue();
- final int durationRight = durationBounds.second.intValue();
- final int amplitudeTop = amplitudeBounds.first.intValue();
- final int amplitudeBottom = amplitudeBounds.second.intValue();
-
- final float amplitude = (amplitudeBottom - amplitudeTop) * 100.0f / height;
- final float duration = (durationRight - durationLeft) * 100.0f / width;
-
- CLog.i("AudioLoopbackImageAnalyzer: Amplitude=" + amplitude + ", Duration=" + duration);
-
- Pair<Result, String> amplResult =
- analyzeAmplitude(
- vertical,
- amplitude,
- amplitudeTop,
- amplitudeBottom,
- AMPLITUDE_MIN_VALUE,
- AMPLITUDE_MAX_VALUE,
- amplitudeCenterMaxDiff);
- if (amplResult.first != Result.PASS) {
- return amplResult;
- }
-
- amplResult =
- analyzeDuration(
- horizontal,
- duration,
- durationLeft,
- durationRight,
- DURATION_MIN,
- maxDuration,
- MIN_NUMBER_OF_COLUMNS,
- minNrOfZeroesBetweenAmplitudes);
- if (amplResult.first != Result.PASS) {
- return amplResult;
- }
-
- return new Pair<Result, String>(Result.PASS, "");
- }
-
- /**
- * Function to analyze the waveforms duration (how wide it stretches along x-axis) and to make
- * sure the waveform degrades nicely, i.e. the amplitude columns becomes smaller and smaller
- * over time.
- *
- * @param horizontal - int array with waveforms amplitude values
- * @param duration - calculated length of duration in percent of screen width
- * @param durationLeft - index for "horizontal" where waveform starts
- * @param durationRight - index for "horizontal" where waveform ends
- * @param durationMin - if duration is below this value, return FAIL and failure reason
- * @param durationMax - if duration exceed this value, return FAIL and failure reason
- * @param minNumberOfAmplitudes - min number of amplitudes (columns) in waveform to pass test
- * @param minNrOfZeroesBetweenAmplitudes - min number of required zeroes between amplitudes
- * @return - returns result status and failure reason, if any
- */
- private static Pair<Result, String> analyzeDuration(
- int[] horizontal,
- float duration,
- int durationLeft,
- int durationRight,
- final float durationMin,
- final float durationMax,
- final int minNumberOfAmplitudes,
- final int minNrOfZeroesBetweenAmplitudes) {
- // This is the tricky one; basically, there should be "columns" that starts
- // at "durationLeft", with the tallest column to the left and then column
- // height will drop until it fades completely after "durationRight".
- final String FN_TAG = "AudioLoopbackImageAnalyzer.analyzeDuration";
-
- if (duration < durationMin || duration > durationMax) {
- final String fmt = "%1$s: Duration outside range, value=%2$f, range=(%3$f,%4$f)";
- return handleError(fmt, FN_TAG, duration, durationMin, durationMax);
- }
-
- final ArrayList<Amplitude> amplitudes = new ArrayList<Amplitude>();
- Amplitude currentAmplitude = null;
- int zeroCounter = 0;
-
- for (int i = durationLeft; i < durationRight; i++) {
- final int v = horizontal[i];
- if (v == 0) {
- zeroCounter++;
- } else {
- CLog.i("index=" + i + ", v=" + v);
-
- if (zeroCounter > minNrOfZeroesBetweenAmplitudes) {
- // Found a new amplitude; update old amplitude
- // with the "gap" count - i.e. nr of zeroes between the amplitudes
- if (currentAmplitude != null) {
- currentAmplitude.zeroCounter = zeroCounter;
- }
-
- // Create new Amplitude object
- currentAmplitude = new Amplitude();
- amplitudes.add(currentAmplitude);
- }
-
- // Reset counter
- zeroCounter = 0;
-
- if (currentAmplitude != null && v > currentAmplitude.maxHeight) {
- currentAmplitude.maxHeight = horizontal[i];
- }
- }
- }
-
- StringBuilder sb = new StringBuilder(128);
- int counter = 0;
- for (final Amplitude a : amplitudes) {
- CLog.i(
- sb.append("Amplitude=")
- .append(counter)
- .append(", MaxHeight=")
- .append(a.maxHeight)
- .append(", ZeroesToNextColumn=")
- .append(a.zeroCounter)
- .toString());
- counter++;
- sb.setLength(0);
- }
-
- if (amplitudes.size() < minNumberOfAmplitudes) {
- final String fmt = "%1$s: Not enough amplitude columns, value=%2$d";
- return handleError(fmt, FN_TAG, amplitudes.size());
- }
-
- int currentColumnHeight = -1;
- int oldColumnHeight = -1;
- for (int i = 0; i < amplitudes.size(); i++) {
- if (i == 0) {
- oldColumnHeight = amplitudes.get(i).maxHeight;
- continue;
- }
-
- currentColumnHeight = amplitudes.get(i).maxHeight;
- if (oldColumnHeight > currentColumnHeight) {
- // We want at least a good number of columns that declines nicely.
- // After MIN_NUMBER_OF_DECREASING_COLUMNS, we don't really care that much
- if (i < MIN_NUMBER_OF_DECREASING_COLUMNS
- && currentColumnHeight < (oldColumnHeight * MAX_ALLOWED_COLUMN_DECREASE)) {
- final String fmt =
- "%1$s: Amplitude column heights declined too much, "
- + "old=%2$d, new=%3$d, column=%4$d";
- return handleError(fmt, FN_TAG, oldColumnHeight, currentColumnHeight, i);
- }
- oldColumnHeight = currentColumnHeight;
- } else if (oldColumnHeight == currentColumnHeight) {
- if (i < MIN_NUMBER_OF_DECREASING_COLUMNS) {
- final String fmt =
- "%1$s: Amplitude column heights are same, "
- + "old=%2$d, new=%3$d, column=%4$d";
- return handleError(fmt, FN_TAG, oldColumnHeight, currentColumnHeight, i);
- }
- } else {
- final String fmt =
- "%1$s: Amplitude column heights don't decline, "
- + "old=%2$d, new=%3$d, column=%4$d";
- return handleError(fmt, FN_TAG, oldColumnHeight, currentColumnHeight, i);
- }
- }
-
- return new Pair<Result, String>(Result.PASS, "");
- }
-
- /**
- * Function to analyze the waveforms duration (how wide it stretches along x-axis) and to make
- * sure the waveform degrades nicely, i.e. the amplitude columns becomes smaller and smaller
- * over time.
- *
- * @param vertical - integer array with waveforms amplitude accumulated values
- * @param amplitude - calculated height of amplitude in percent of screen height
- * @param amplitudeTop - index in "vertical" array where waveform starts
- * @param amplitudeBottom - index in "vertical" array where waveform ends
- * @param amplitudeMin - if amplitude is below this value, return FAIL and failure reason
- * @param amplitudeMax - if amplitude exceed this value, return FAIL and failure reason
- * @param amplitudeCenterDiffThreshold - threshold to check that waveform is centered
- * @return - returns result status and failure reason, if any
- */
- private static Pair<Result, String> analyzeAmplitude(
- int[] vertical,
- float amplitude,
- int amplitudeTop,
- int amplitudeBottom,
- final float amplitudeMin,
- final float amplitudeMax,
- final int amplitudeCenterDiffThreshold) {
- final String FN_TAG = "AudioLoopbackImageAnalyzer.analyzeAmplitude";
-
- if (amplitude < amplitudeMin || amplitude > amplitudeMax) {
- final String fmt = "%1$s: Amplitude outside range, value=%2$f, range=(%3$f,%4$f)";
- final String err = String.format(fmt, FN_TAG, amplitude, amplitudeMin, amplitudeMax);
- CLog.w(err);
- return new Pair<Result, String>(Result.FAIL, err);
- }
-
- // Are the amplitude top/bottom centered around the centerline?
- final int amplitudeCenter = getAmplitudeCenter(vertical, amplitudeTop, amplitudeBottom);
- final int topDiff = amplitudeCenter - amplitudeTop;
- final int bottomDiff = amplitudeBottom - amplitudeCenter;
- final int diff = Math.abs(topDiff - bottomDiff);
-
- if (diff < amplitudeCenterDiffThreshold) {
- return new Pair<Result, String>(Result.PASS, "");
- }
-
- final String fmt =
- "%1$s: Amplitude not centered topDiff=%2$d, bottomDiff=%3$d, "
- + "center=%4$d, diff=%5$d";
- final String err = String.format(fmt, FN_TAG, topDiff, bottomDiff, amplitudeCenter, diff);
- CLog.w(err);
- return new Pair<Result, String>(Result.FAIL, err);
- }
-
- private static int getAmplitudeCenter(int[] vertical, int amplitudeTop, int amplitudeBottom) {
- int max = -1;
- int center = -1;
- for (int i = amplitudeTop; i < amplitudeBottom; i++) {
- if (vertical[i] > max) {
- max = vertical[i];
- center = i;
- }
- }
-
- return center;
- }
-
- private static void projectPixelsToXAxis(
- BufferedImage img,
- final int[] targetColors,
- int[] horizontal,
- final int width,
- final int height) {
- // "Flatten image" by projecting target colors horizontally,
- // counting number of found pixels in each column
- for (int y = 0; y < height; y++) {
- for (int x = 0; x < width; x++) {
- final int color = img.getRGB(x, y);
- for (final int targetColor : targetColors) {
- if (color == targetColor) {
- horizontal[x]++;
- break;
- }
- }
- }
- }
- }
-
- private static void projectPixelsToYAxis(
- BufferedImage img,
- final int[] targetColors,
- int[] vertical,
- int height,
- Pair<Integer, Integer> horizontalMinMax) {
-
- final int min = horizontalMinMax.first.intValue();
- final int max = horizontalMinMax.second.intValue();
-
- // "Flatten image" by projecting target colors (between min/max) vertically,
- // counting number of found pixels in each row
-
- // Pass over y-axis, restricted to horizontalMin, horizontalMax
- for (int y = 0; y < height; y++) {
- for (int x = min; x <= max; x++) {
- final int color = img.getRGB(x, y);
- for (final int targetColor : targetColors) {
- if (color == targetColor) {
- vertical[y]++;
- break;
- }
- }
- }
- }
- }
-
- private static Pair<Integer, Integer> getBounds(int[] array) {
- // Determine min, max
- int min = -1;
- for (int i = 0; i < array.length; i++) {
- if (array[i] > 0) {
- min = i;
- break;
- }
- }
-
- int max = -1;
- for (int i = array.length - 1; i >= 0; i--) {
- if (array[i] > 0) {
- max = i;
- break;
- }
- }
-
- return new Pair<Integer, Integer>(Integer.valueOf(min), Integer.valueOf(max));
- }
-
- private static void filter(int[] array, final int threshold) {
- // Filter horizontal array; set all values < threshold to 0
- for (int i = 0; i < array.length; i++) {
- final int v = array[i];
- if (v != 0 && v <= threshold) {
- array[i] = 0;
- }
- }
- }
-
- private static boolean boundsWithinRange(Pair<Integer, Integer> bounds, int low, int high) {
- return low <= bounds.first.intValue()
- && bounds.first.intValue() < high
- && low <= bounds.second.intValue()
- && bounds.second.intValue() < high;
- }
-
- private static Pair<Result, String> handleError(String fmt, String tag, int arg1) {
- final String err = String.format(fmt, tag, arg1);
- CLog.w(err);
- return new Pair<Result, String>(Result.FAIL, err);
- }
-
- private static Pair<Result, String> handleError(
- String fmt, String tag, int arg1, int arg2, int arg3) {
- final String err = String.format(fmt, tag, arg1, arg2, arg3);
- CLog.w(err);
- return new Pair<Result, String>(Result.FAIL, err);
- }
-
- private static Pair<Result, String> handleError(
- String fmt, String tag, float arg1, float arg2, float arg3) {
- final String err = String.format(fmt, tag, arg1, arg2, arg3);
- CLog.w(err);
- return new Pair<Result, String>(Result.FAIL, err);
- }
-}
diff --git a/src/com/android/media/tests/AudioLoopbackTest.java b/src/com/android/media/tests/AudioLoopbackTest.java
deleted file mode 100644
index 1d9bab5..0000000
--- a/src/com/android/media/tests/AudioLoopbackTest.java
+++ /dev/null
@@ -1,749 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.android.media.tests;
-
-import static java.nio.file.StandardCopyOption.REPLACE_EXISTING;
-
-import com.android.ddmlib.NullOutputReceiver;
-import com.android.ddmlib.testrunner.TestIdentifier;
-import com.android.media.tests.AudioLoopbackTestHelper.LogFileType;
-import com.android.media.tests.AudioLoopbackTestHelper.ResultData;
-import com.android.tradefed.config.Option;
-import com.android.tradefed.device.DeviceNotAvailableException;
-import com.android.tradefed.device.ITestDevice;
-import com.android.tradefed.log.LogUtil.CLog;
-import com.android.tradefed.result.FileInputStreamSource;
-import com.android.tradefed.result.ITestInvocationListener;
-import com.android.tradefed.result.InputStreamSource;
-import com.android.tradefed.result.LogDataType;
-import com.android.tradefed.testtype.IDeviceTest;
-import com.android.tradefed.testtype.IRemoteTest;
-import com.android.tradefed.util.FileUtil;
-import com.android.tradefed.util.RunUtil;
-
-import java.io.File;
-import java.io.IOException;
-import java.nio.file.Files;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.Date;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.concurrent.TimeUnit;
-
-/**
- * Runs Audio Latency and Audio Glitch test and reports result.
- *
- * <p>Strategy for Audio Latency Stress test: RUN test 1000 times. In each iteration, collect result
- * files from device, parse and collect data in a ResultData object that also keeps track of
- * location to test files for a particular iteration.
- *
- * <p>ANALYZE test results to produce statistics for 1. Latency and Confidence (Min, Max, Mean,
- * Median) 2. Create CSV file with test run data 3. Print bad test data to host log file 4. Get
- * number of test runs with valid data to send to dashboard 5. Produce histogram in host log file;
- * count number of test results that fall into 1 ms wide buckets.
- *
- * <p>UPLOAD test results + log files from “bad” runs; i.e. runs that is missing some or all result
- * data.
- */
-public class AudioLoopbackTest implements IDeviceTest, IRemoteTest {
-
- //===================================================================
- // TEST OPTIONS
- //===================================================================
- @Option(name = "run-key", description = "Run key for the test")
- private String mRunKey = "AudioLoopback";
-
- @Option(name = "sampling-freq", description = "Sampling Frequency for Loopback app")
- private String mSamplingFreq = "48000";
-
- @Option(name = "mic-source", description = "Mic Source for Loopback app")
- private String mMicSource = "3";
-
- @Option(name = "audio-thread", description = "Audio Thread for Loopback app")
- private String mAudioThread = "1";
-
- @Option(
- name = "audio-level",
- description =
- "Audio Level for Loopback app. A device specific"
- + "param which makes waveform in loopback test hit 60% to 80% range"
- )
- private String mAudioLevel = "-1";
-
- @Option(name = "test-type", description = "Test type to be executed")
- private String mTestType = TESTTYPE_LATENCY_STR;
-
- @Option(name = "buffer-test-duration", description = "Buffer test duration in seconds")
- private String mBufferTestDuration = "10";
-
- @Option(name = "key-prefix", description = "Key Prefix for reporting")
- private String mKeyPrefix = "48000_Mic3_";
-
- @Option(name = "iterations", description = "Number of test iterations")
- private int mIterations = 1;
-
- @Option(name = "baseline_latency", description = "")
- private float mBaselineLatency = 0f;
-
- //===================================================================
- // CLASS VARIABLES
- //===================================================================
- private static final Map<String, String> METRICS_KEY_MAP = createMetricsKeyMap();
- private Map<LogFileType, LogFileData> mFileDataKeyMap;
- private ITestDevice mDevice;
- private TestRunHelper mTestRunHelper;
- private AudioLoopbackTestHelper mLoopbackTestHelper;
-
- //===================================================================
- // CONSTANTS
- //===================================================================
- private static final String TESTTYPE_LATENCY_STR = "222";
- private static final String TESTTYPE_GLITCH_STR = "223";
- private static final long TIMEOUT_MS = 5 * 60 * 1000; // 5 min
- private static final long DEVICE_SYNC_MS = 5 * 60 * 1000; // 5 min
- private static final long POLLING_INTERVAL_MS = 5 * 1000;
- private static final int MAX_ATTEMPTS = 3;
- private static final int MAX_NR_OF_LOG_UPLOADS = 100;
-
- private static final int LATENCY_ITERATIONS_LOWER_BOUND = 1;
- private static final int LATENCY_ITERATIONS_UPPER_BOUND = 10000;
- private static final int GLITCH_ITERATIONS_LOWER_BOUND = 1;
- private static final int GLITCH_ITERATIONS_UPPER_BOUND = 1;
-
- private static final String DEVICE_TEMP_DIR_PATH = "/sdcard/";
- private static final String FMT_OUTPUT_PREFIX = "output_%1$d_" + System.currentTimeMillis();
- private static final String FMT_DEVICE_FILENAME = FMT_OUTPUT_PREFIX + "%2$s";
- private static final String FMT_DEVICE_PATH = DEVICE_TEMP_DIR_PATH + FMT_DEVICE_FILENAME;
-
- private static final String AM_CMD =
- "am start -n org.drrickorang.loopback/.LoopbackActivity"
- + " --ei SF %s --es FileName %s --ei MicSource %s --ei AudioThread %s"
- + " --ei AudioLevel %s --ei TestType %s --ei BufferTestDuration %s";
-
- private static final String ERR_PARAMETER_OUT_OF_BOUNDS =
- "Test parameter '%1$s' is out of bounds. Lower limit = %2$d, upper limit = %3$d";
-
- private static final String KEY_RESULT_LATENCY_MS = "latency_ms";
- private static final String KEY_RESULT_LATENCY_CONFIDENCE = "latency_confidence";
- private static final String KEY_RESULT_RECORDER_BENCHMARK = "recorder_benchmark";
- private static final String KEY_RESULT_RECORDER_OUTLIER = "recorder_outliers";
- private static final String KEY_RESULT_PLAYER_BENCHMARK = "player_benchmark";
- private static final String KEY_RESULT_PLAYER_OUTLIER = "player_outliers";
- private static final String KEY_RESULT_NUMBER_OF_GLITCHES = "number_of_glitches";
- private static final String KEY_RESULT_RECORDER_BUFFER_CALLBACK = "late_recorder_callbacks";
- private static final String KEY_RESULT_PLAYER_BUFFER_CALLBACK = "late_player_callbacks";
- private static final String KEY_RESULT_GLITCHES_PER_HOUR = "glitches_per_hour";
- private static final String KEY_RESULT_TEST_STATUS = "test_status";
- private static final String KEY_RESULT_AUDIO_LEVEL = "audio_level";
- private static final String KEY_RESULT_RMS = "rms";
- private static final String KEY_RESULT_RMS_AVERAGE = "rms_average";
- private static final String KEY_RESULT_SAMPLING_FREQUENCY_CONFIDENCE = "sampling_frequency";
- private static final String KEY_RESULT_PERIOD_CONFIDENCE = "period_confidence";
- private static final String KEY_RESULT_SAMPLING_BLOCK_SIZE = "block_size";
-
- private static final LogFileType[] LATENCY_TEST_LOGS = {
- LogFileType.RESULT,
- LogFileType.GRAPH,
- LogFileType.WAVE,
- LogFileType.PLAYER_BUFFER,
- LogFileType.PLAYER_BUFFER_HISTOGRAM,
- LogFileType.PLAYER_BUFFER_PERIOD_TIMES,
- LogFileType.RECORDER_BUFFER,
- LogFileType.RECORDER_BUFFER_HISTOGRAM,
- LogFileType.RECORDER_BUFFER_PERIOD_TIMES,
- LogFileType.LOGCAT
- };
-
- private static final LogFileType[] GLITCH_TEST_LOGS = {
- LogFileType.RESULT,
- LogFileType.GRAPH,
- LogFileType.WAVE,
- LogFileType.PLAYER_BUFFER,
- LogFileType.PLAYER_BUFFER_HISTOGRAM,
- LogFileType.PLAYER_BUFFER_PERIOD_TIMES,
- LogFileType.RECORDER_BUFFER,
- LogFileType.RECORDER_BUFFER_HISTOGRAM,
- LogFileType.RECORDER_BUFFER_PERIOD_TIMES,
- LogFileType.GLITCHES_MILLIS,
- LogFileType.HEAT_MAP,
- LogFileType.LOGCAT
- };
-
- /**
- * The Audio Latency and Audio Glitch test deals with many various types of log files. To be
- * able to generate log files in a generic manner, this map is provided to get access to log
- * file properties like log name prefix, log name file extension and log type (leveraging
- * tradefed class LogDataType, used when uploading log).
- */
- private final synchronized Map<LogFileType, LogFileData> getLogFileDataKeyMap() {
- if (mFileDataKeyMap != null) {
- return mFileDataKeyMap;
- }
-
- final Map<LogFileType, LogFileData> result = new HashMap<LogFileType, LogFileData>();
-
- // Populate dictionary with info about various types of logfiles
- LogFileData l = new LogFileData(".txt", "result", LogDataType.TEXT);
- result.put(LogFileType.RESULT, l);
-
- l = new LogFileData(".png", "graph", LogDataType.PNG);
- result.put(LogFileType.GRAPH, l);
-
- l = new LogFileData(".wav", "wave", LogDataType.UNKNOWN);
- result.put(LogFileType.WAVE, l);
-
- l = new LogFileData("_playerBufferPeriod.txt", "player_buffer", LogDataType.TEXT);
- result.put(LogFileType.PLAYER_BUFFER, l);
-
- l = new LogFileData("_playerBufferPeriod.png", "player_buffer_histogram", LogDataType.PNG);
- result.put(LogFileType.PLAYER_BUFFER_HISTOGRAM, l);
-
- String fileExtension = "_playerBufferPeriodTimes.txt";
- String uploadName = "player_buffer_period_times";
- l = new LogFileData(fileExtension, uploadName, LogDataType.TEXT);
- result.put(LogFileType.PLAYER_BUFFER_PERIOD_TIMES, l);
-
- l = new LogFileData("_recorderBufferPeriod.txt", "recorder_buffer", LogDataType.TEXT);
- result.put(LogFileType.RECORDER_BUFFER, l);
-
- fileExtension = "_recorderBufferPeriod.png";
- uploadName = "recorder_buffer_histogram";
- l = new LogFileData(fileExtension, uploadName, LogDataType.PNG);
- result.put(LogFileType.RECORDER_BUFFER_HISTOGRAM, l);
-
- fileExtension = "_recorderBufferPeriodTimes.txt";
- uploadName = "recorder_buffer_period_times";
- l = new LogFileData(fileExtension, uploadName, LogDataType.TEXT);
- result.put(LogFileType.RECORDER_BUFFER_PERIOD_TIMES, l);
-
- l = new LogFileData("_glitchMillis.txt", "glitches_millis", LogDataType.TEXT);
- result.put(LogFileType.GLITCHES_MILLIS, l);
-
-
- l = new LogFileData("_heatMap.png", "heat_map", LogDataType.PNG);
- result.put(LogFileType.HEAT_MAP, l);
-
- l = new LogFileData(".txt", "logcat", LogDataType.TEXT);
- result.put(LogFileType.LOGCAT, l);
-
- mFileDataKeyMap = Collections.unmodifiableMap(result);
- return mFileDataKeyMap;
- }
-
- private static final Map<String, String> createMetricsKeyMap() {
- final Map<String, String> result = new HashMap<String, String>();
-
- result.put("LatencyMs", KEY_RESULT_LATENCY_MS);
- result.put("LatencyConfidence", KEY_RESULT_LATENCY_CONFIDENCE);
- result.put("SF", KEY_RESULT_SAMPLING_FREQUENCY_CONFIDENCE);
- result.put("Recorder Benchmark", KEY_RESULT_RECORDER_BENCHMARK);
- result.put("Recorder Number of Outliers", KEY_RESULT_RECORDER_OUTLIER);
- result.put("Player Benchmark", KEY_RESULT_PLAYER_BENCHMARK);
- result.put("Player Number of Outliers", KEY_RESULT_PLAYER_OUTLIER);
- result.put("Total Number of Glitches", KEY_RESULT_NUMBER_OF_GLITCHES);
- result.put("kth% Late Recorder Buffer Callbacks", KEY_RESULT_RECORDER_BUFFER_CALLBACK);
- result.put("kth% Late Player Buffer Callbacks", KEY_RESULT_PLAYER_BUFFER_CALLBACK);
- result.put("Glitches Per Hour", KEY_RESULT_GLITCHES_PER_HOUR);
- result.put("Test Status", KEY_RESULT_TEST_STATUS);
- result.put("AudioLevel", KEY_RESULT_AUDIO_LEVEL);
- result.put("RMS", KEY_RESULT_RMS);
- result.put("Average", KEY_RESULT_RMS_AVERAGE);
- result.put("PeriodConfidence", KEY_RESULT_PERIOD_CONFIDENCE);
- result.put("BS", KEY_RESULT_SAMPLING_BLOCK_SIZE);
-
- return Collections.unmodifiableMap(result);
- }
-
- //===================================================================
- // ENUMS
- //===================================================================
- public enum TestType {
- GLITCH,
- LATENCY,
- LATENCY_STRESS,
- NONE
- }
-
- //===================================================================
- // INNER CLASSES
- //===================================================================
- public final class LogFileData {
- private String fileExtension;
- private String filePrefix;
- private LogDataType logDataType;
-
- private LogFileData(String fileExtension, String filePrefix, LogDataType logDataType) {
- this.fileExtension = fileExtension;
- this.filePrefix = filePrefix;
- this.logDataType = logDataType;
- }
- }
-
- //===================================================================
- // FUNCTIONS
- //===================================================================
-
- /** {@inheritDoc} */
- @Override
- public void setDevice(ITestDevice device) {
- mDevice = device;
- }
-
- /** {@inheritDoc} */
- @Override
- public ITestDevice getDevice() {
- return mDevice;
- }
-
- /**
- * Test Entry Point
- *
- * <p>{@inheritDoc}
- */
- @Override
- public void run(ITestInvocationListener listener) throws DeviceNotAvailableException {
-
- initializeTest(listener);
-
- mTestRunHelper.startTest(1);
-
- try {
- if (!verifyTestParameters()) {
- return;
- }
-
- // Stop logcat logging so we can record one logcat log per iteration
- getDevice().stopLogcat();
-
- // Run test iterations
- for (int i = 0; i < mIterations; i++) {
- CLog.i("---- Iteration " + i + " of " + (mIterations - 1) + " -----");
-
- final ResultData d = new ResultData();
- d.setIteration(i);
- Map<String, String> resultsDictionary = null;
- resultsDictionary = runTest(d, getSingleTestTimeoutValue());
-
- mLoopbackTestHelper.addTestData(d, resultsDictionary);
- }
-
- mLoopbackTestHelper.processTestData();
- } finally {
- Map<String, String> metrics = uploadLogsReturnMetrics(listener);
- CLog.i("Uploading metrics values:\n" + Arrays.toString(metrics.entrySet().toArray()));
- mTestRunHelper.endTest(metrics);
- deleteAllTempFiles();
- getDevice().startLogcat();
- }
- }
-
- private void initializeTest(ITestInvocationListener listener)
- throws UnsupportedOperationException, DeviceNotAvailableException {
-
- mFileDataKeyMap = getLogFileDataKeyMap();
- TestIdentifier testId = new TestIdentifier(getClass().getCanonicalName(), mRunKey);
-
- // Allocate helpers
- mTestRunHelper = new TestRunHelper(listener, testId);
- mLoopbackTestHelper = new AudioLoopbackTestHelper(mIterations);
-
- getDevice().disableKeyguard();
- getDevice().waitForDeviceAvailable(DEVICE_SYNC_MS);
-
- getDevice().setDate(new Date());
- CLog.i("syncing device time to host time");
- }
-
- private Map<String, String> runTest(ResultData data, final long timeout)
- throws DeviceNotAvailableException {
-
- // start measurement and wait for result file
- final NullOutputReceiver receiver = new NullOutputReceiver();
-
- final String loopbackCmd = getTestCommand(data.getIteration());
- CLog.i("Loopback cmd: " + loopbackCmd);
-
- // Clear logcat
- // Seems like getDevice().clearLogcat(); doesn't do anything?
- // Do it through ADB
- getDevice().executeAdbCommand("logcat", "-c");
- final long deviceTestStartTime = getDevice().getDeviceDate();
-
- getDevice()
- .executeShellCommand(
- loopbackCmd, receiver, TIMEOUT_MS, TimeUnit.MILLISECONDS, MAX_ATTEMPTS);
-
- final long loopbackStartTime = System.currentTimeMillis();
- File loopbackReport = null;
-
- data.setDeviceTestStartTime(deviceTestStartTime);
-
- // Try to retrieve result file from device.
- final String resultFilename = getDeviceFilename(LogFileType.RESULT, data.getIteration());
- do {
- RunUtil.getDefault().sleep(POLLING_INTERVAL_MS);
- if (getDevice().doesFileExist(resultFilename)) {
- // Store device log files in tmp directory on Host and add to ResultData object
- storeDeviceFilesOnHost(data);
- final String reportFilename = data.getLogFile(LogFileType.RESULT);
- if (reportFilename != null && !reportFilename.isEmpty()) {
- loopbackReport = new File(reportFilename);
- if (loopbackReport.length() > 0) {
- break;
- }
- }
- }
-
- data.setIsTimedOut(System.currentTimeMillis() - loopbackStartTime >= timeout);
- } while (!data.hasLogFile(LogFileType.RESULT) && !data.isTimedOut());
-
- // Grab logcat for iteration
- final InputStreamSource lc = getDevice().getLogcatSince(deviceTestStartTime);
- saveLogcatForIteration(data, lc, data.getIteration());
-
- // Check if test timed out. If so, don't fail the test, but return to upper logic.
- // We accept certain number of individual test timeouts.
- if (data.isTimedOut()) {
- // No device result files retrieved, so no need to parse
- return null;
- }
-
- // parse result
- Map<String, String> loopbackResult = null;
-
- try {
- loopbackResult =
- AudioLoopbackTestHelper.parseKeyValuePairFromFile(
- loopbackReport, METRICS_KEY_MAP, mKeyPrefix, "=", "%s: %s");
- populateResultData(loopbackResult, data);
-
- // Trust but verify, so get Audio Level from ADB and compare to value from app
- final int adbAudioLevel =
- AudioLevelUtility.extractDeviceAudioLevelFromAdbShell(getDevice());
- if (data.getAudioLevel() != adbAudioLevel) {
- final String errMsg =
- String.format(
- "App Audio Level (%1$d)differs from ADB level (%2$d)",
- data.getAudioLevel(), adbAudioLevel);
- mTestRunHelper.reportFailure(errMsg);
- }
- } catch (final IOException ioe) {
- CLog.e(ioe);
- mTestRunHelper.reportFailure("I/O error while parsing Loopback result.");
- } catch (final NumberFormatException ne) {
- CLog.e(ne);
- mTestRunHelper.reportFailure("Number format error parsing Loopback result.");
- }
-
- return loopbackResult;
- }
-
- private String getMetricsKey(final String key) {
- return mKeyPrefix + key;
- }
- private final long getSingleTestTimeoutValue() {
- return Long.parseLong(mBufferTestDuration) * 1000 + TIMEOUT_MS;
- }
-
- private Map<String, String> uploadLogsReturnMetrics(ITestInvocationListener listener)
- throws DeviceNotAvailableException {
-
- // "resultDictionary" is used to post results to dashboards like BlackBox
- // "results" contains test logs to be uploaded; i.e. to Sponge
-
- List<ResultData> results = null;
- Map<String, String> resultDictionary = new HashMap<String, String>();
-
- switch (getTestType()) {
- case GLITCH:
- resultDictionary = mLoopbackTestHelper.getResultDictionaryForIteration(0);
- // Upload all test files to be backward compatible with old test
- results = mLoopbackTestHelper.getAllTestData();
- break;
- case LATENCY:
- {
- final int nrOfValidResults = mLoopbackTestHelper.processTestData();
- if (nrOfValidResults == 0) {
- mTestRunHelper.reportFailure("No good data was collected");
- } else {
- // use dictionary collected from single test run
- resultDictionary = mLoopbackTestHelper.getResultDictionaryForIteration(0);
- }
-
- // Upload all test files to be backward compatible with old test
- results = mLoopbackTestHelper.getAllTestData();
- }
- break;
- case LATENCY_STRESS:
- {
- final int nrOfValidResults = mLoopbackTestHelper.processTestData();
- if (nrOfValidResults == 0) {
- mTestRunHelper.reportFailure("No good data was collected");
- } else {
- mLoopbackTestHelper.populateStressTestMetrics(resultDictionary, mKeyPrefix);
- }
-
- results = mLoopbackTestHelper.getWorstResults(MAX_NR_OF_LOG_UPLOADS);
-
- // Save all test data in a spreadsheet style csv file for post test analysis
- try {
- saveResultsAsCSVFile(listener);
- } catch (final IOException e) {
- CLog.e(e);
- }
- }
- break;
- default:
- break;
- }
-
- // Upload relevant logs
- for (final ResultData d : results) {
- final LogFileType[] logFileTypes = getLogFileTypesForCurrentTest();
- for (final LogFileType logType : logFileTypes) {
- uploadLog(listener, logType, d);
- }
- }
-
- return resultDictionary;
- }
-
- private TestType getTestType() {
- if (mTestType.equals(TESTTYPE_GLITCH_STR)) {
- if (GLITCH_ITERATIONS_LOWER_BOUND <= mIterations
- && mIterations <= GLITCH_ITERATIONS_UPPER_BOUND) {
- return TestType.GLITCH;
- }
- }
-
- if (mTestType.equals(TESTTYPE_LATENCY_STR)) {
- if (mIterations == 1) {
- return TestType.LATENCY;
- }
-
- if (LATENCY_ITERATIONS_LOWER_BOUND <= mIterations
- && mIterations <= LATENCY_ITERATIONS_UPPER_BOUND) {
- return TestType.LATENCY_STRESS;
- }
- }
-
- return TestType.NONE;
- }
-
- private boolean verifyTestParameters() {
- if (getTestType() != TestType.NONE) {
- return true;
- }
-
- if (mTestType.equals(TESTTYPE_GLITCH_STR)
- && (mIterations < GLITCH_ITERATIONS_LOWER_BOUND
- || mIterations > GLITCH_ITERATIONS_UPPER_BOUND)) {
- final String error =
- String.format(
- ERR_PARAMETER_OUT_OF_BOUNDS,
- "iterations",
- GLITCH_ITERATIONS_LOWER_BOUND,
- GLITCH_ITERATIONS_UPPER_BOUND);
- mTestRunHelper.reportFailure(error);
- return false;
- }
-
- if (mTestType.equals(TESTTYPE_LATENCY_STR)
- && (mIterations < LATENCY_ITERATIONS_LOWER_BOUND
- || mIterations > LATENCY_ITERATIONS_UPPER_BOUND)) {
- final String error =
- String.format(
- ERR_PARAMETER_OUT_OF_BOUNDS,
- "iterations",
- LATENCY_ITERATIONS_LOWER_BOUND,
- LATENCY_ITERATIONS_UPPER_BOUND);
- mTestRunHelper.reportFailure(error);
- return false;
- }
-
- return true;
- }
-
- private void populateResultData(final Map<String, String> results, ResultData data) {
- if (results == null || results.isEmpty()) {
- return;
- }
-
- String key = getMetricsKey(KEY_RESULT_LATENCY_MS);
- if (results.containsKey(key)) {
- data.setLatency(Float.parseFloat(results.get(key)));
- }
-
- key = getMetricsKey(KEY_RESULT_LATENCY_CONFIDENCE);
- if (results.containsKey(key)) {
- data.setConfidence(Float.parseFloat(results.get(key)));
- }
-
- key = getMetricsKey(KEY_RESULT_AUDIO_LEVEL);
- if (results.containsKey(key)) {
- data.setAudioLevel(Integer.parseInt(results.get(key)));
- }
-
- key = getMetricsKey(KEY_RESULT_RMS);
- if (results.containsKey(key)) {
- data.setRMS(Float.parseFloat(results.get(key)));
- }
-
- key = getMetricsKey(KEY_RESULT_RMS_AVERAGE);
- if (results.containsKey(key)) {
- data.setRMSAverage(Float.parseFloat(results.get(key)));
- }
-
- key = getMetricsKey(KEY_RESULT_PERIOD_CONFIDENCE);
- if (results.containsKey(key)) {
- data.setPeriodConfidence(Float.parseFloat(results.get(key)));
- }
-
- key = getMetricsKey(KEY_RESULT_SAMPLING_BLOCK_SIZE);
- if (results.containsKey(key)) {
- data.setBlockSize(Integer.parseInt(results.get(key)));
- }
- }
-
- private void storeDeviceFilesOnHost(ResultData data) throws DeviceNotAvailableException {
- final int iteration = data.getIteration();
- for (final LogFileType log : getLogFileTypesForCurrentTest()) {
- if (getDevice().doesFileExist(getDeviceFilename(log, iteration))) {
- final String deviceFileName = getDeviceFilename(log, iteration);
- final File logFile = getDevice().pullFile(deviceFileName);
- data.setLogFile(log, logFile.getAbsolutePath());
- CLog.i("Delete file from device: " + deviceFileName);
- deleteFileFromDevice(deviceFileName);
- }
- }
- }
-
- private void deleteAllTempFiles() {
- for (final ResultData d : mLoopbackTestHelper.getAllTestData()) {
- final LogFileType[] logFileTypes = getLogFileTypesForCurrentTest();
- for (final LogFileType logType : logFileTypes) {
- final String logFilename = d.getLogFile(logType);
- if (logFilename == null || logFilename.isEmpty()) {
- CLog.e("Logfile not found for LogFileType=" + logType.name());
- } else {
- FileUtil.deleteFile(new File(logFilename));
- }
- }
- }
- }
-
- private void deleteFileFromDevice(String deviceFileName) throws DeviceNotAvailableException {
- getDevice().executeShellCommand("rm -f " + deviceFileName);
- }
-
- private final LogFileType[] getLogFileTypesForCurrentTest() {
- switch (getTestType()) {
- case GLITCH:
- return GLITCH_TEST_LOGS;
- case LATENCY:
- case LATENCY_STRESS:
- return LATENCY_TEST_LOGS;
- default:
- return null;
- }
- }
-
- private String getKeyPrefixForIteration(int iteration) {
- if (mIterations == 1) {
- // If only one run, skip the iteration number
- return mKeyPrefix;
- }
- return mKeyPrefix + iteration + "_";
- }
-
- private String getDeviceFilename(LogFileType key, int iteration) {
- final Map<LogFileType, LogFileData> map = getLogFileDataKeyMap();
- if (map.containsKey(key)) {
- final LogFileData data = map.get(key);
- return String.format(FMT_DEVICE_PATH, iteration, data.fileExtension);
- }
- return null;
- }
-
- private void uploadLog(ITestInvocationListener listener, LogFileType key, ResultData data) {
- final Map<LogFileType, LogFileData> map = getLogFileDataKeyMap();
- if (!map.containsKey(key)) {
- return;
- }
-
- final LogFileData logInfo = map.get(key);
- final String prefix = getKeyPrefixForIteration(data.getIteration()) + logInfo.filePrefix;
- final LogDataType logDataType = logInfo.logDataType;
- final String logFilename = data.getLogFile(key);
- if (logFilename == null || logFilename.isEmpty()) {
- CLog.e("Logfile not found for LogFileType=" + key.name());
- } else {
- File logFile = new File(logFilename);
- InputStreamSource iss = new FileInputStreamSource(logFile);
- listener.testLog(prefix, logDataType, iss);
-
- // cleanup
- iss.cancel();
- }
- }
-
- private void saveLogcatForIteration(ResultData data, InputStreamSource logcat, int iteration) {
- if (logcat == null) {
- CLog.i("Logcat could not be saved for iteration " + iteration);
- return;
- }
-
- //create a temp file
- File temp;
- try {
- temp = FileUtil.createTempFile("logcat_" + iteration + "_", ".txt");
- data.setLogFile(LogFileType.LOGCAT, temp.getAbsolutePath());
-
- // Copy logcat data into temp file
- Files.copy(logcat.createInputStream(), temp.toPath(), REPLACE_EXISTING);
- logcat.cancel();
- } catch (final IOException e) {
- CLog.i("Error when saving logcat for iteration=" + iteration);
- CLog.e(e);
- }
- }
-
- private void saveResultsAsCSVFile(ITestInvocationListener listener)
- throws DeviceNotAvailableException, IOException {
- final File csvTmpFile = File.createTempFile("audio_test_data", "csv");
- mLoopbackTestHelper.writeAllResultsToCSVFile(csvTmpFile, getDevice());
- InputStreamSource iss = new FileInputStreamSource(csvTmpFile);
- listener.testLog("audio_test_data", LogDataType.JACOCO_CSV, iss);
-
- // cleanup
- iss.cancel();
- csvTmpFile.delete();
- }
-
- private String getTestCommand(int currentIteration) {
- return String.format(
- AM_CMD,
- mSamplingFreq,
- String.format(FMT_OUTPUT_PREFIX, currentIteration),
- mMicSource,
- mAudioThread,
- mAudioLevel,
- mTestType,
- mBufferTestDuration);
- }
-}
diff --git a/src/com/android/media/tests/AudioLoopbackTestHelper.java b/src/com/android/media/tests/AudioLoopbackTestHelper.java
deleted file mode 100644
index 4e9c2b0..0000000
--- a/src/com/android/media/tests/AudioLoopbackTestHelper.java
+++ /dev/null
@@ -1,608 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.android.media.tests;
-
-import com.android.media.tests.AudioLoopbackImageAnalyzer.Result;
-import com.android.tradefed.device.DeviceNotAvailableException;
-import com.android.tradefed.device.ITestDevice;
-import com.android.tradefed.log.LogUtil.CLog;
-import com.android.tradefed.util.Pair;
-
-import com.google.common.io.Files;
-
-import java.io.BufferedReader;
-import java.io.File;
-import java.io.FileNotFoundException;
-import java.io.IOException;
-import java.io.PrintWriter;
-import java.io.UnsupportedEncodingException;
-import java.nio.charset.StandardCharsets;
-import java.time.Instant;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.Comparator;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-/** Helper class for AudioLoopbackTest. It keeps runtime data, analytics, */
-public class AudioLoopbackTestHelper {
-
- private StatisticsData mLatencyStats = null;
- private StatisticsData mConfidenceStats = null;
- private ArrayList<ResultData> mAllResults;
- private ArrayList<ResultData> mGoodResults = new ArrayList<ResultData>();
- private ArrayList<ResultData> mBadResults = new ArrayList<ResultData>();
- private ArrayList<Map<String, String>> mResultDictionaries =
- new ArrayList<Map<String, String>>();
-
- // Controls acceptable tolerance in ms around median latency
- private static final double TOLERANCE = 2.0;
-
- //===================================================================
- // ENUMS
- //===================================================================
- public enum LogFileType {
- RESULT,
- WAVE,
- GRAPH,
- PLAYER_BUFFER,
- PLAYER_BUFFER_HISTOGRAM,
- PLAYER_BUFFER_PERIOD_TIMES,
- RECORDER_BUFFER,
- RECORDER_BUFFER_HISTOGRAM,
- RECORDER_BUFFER_PERIOD_TIMES,
- GLITCHES_MILLIS,
- HEAT_MAP,
- LOGCAT
- }
-
- //===================================================================
- // INNER CLASSES
- //===================================================================
- private class StatisticsData {
- double mMin = 0;
- double mMax = 0;
- double mMean = 0;
- double mMedian = 0;
-
- @Override
- public String toString() {
- return String.format(
- "min = %1$f, max = %2$f, median=%3$f, mean = %4$f", mMin, mMax, mMedian, mMean);
- }
- }
-
- /** ResultData is an inner class that holds results and logfile info from each test run */
- public static class ResultData {
- private Float mLatencyMs;
- private Float mLatencyConfidence;
- private Integer mAudioLevel;
- private Integer mIteration;
- private Long mDeviceTestStartTime;
- private boolean mIsTimedOut = false;
- private HashMap<LogFileType, String> mLogs = new HashMap<LogFileType, String>();
- private Result mImageAnalyzerResult = Result.UNKNOWN;
- private String mFailureReason = null;
-
- // Optional
- private Float mPeriodConfidence = Float.valueOf(0.0f);
- private Float mRms = Float.valueOf(0.0f);
- private Float mRmsAverage = Float.valueOf(0.0f);
- private Integer mBblockSize = Integer.valueOf(0);
-
- public float getLatency() {
- return mLatencyMs.floatValue();
- }
-
- public void setLatency(float latencyMs) {
- this.mLatencyMs = Float.valueOf(latencyMs);
- }
-
- public float getConfidence() {
- return mLatencyConfidence.floatValue();
- }
-
- public void setConfidence(float latencyConfidence) {
- this.mLatencyConfidence = Float.valueOf(latencyConfidence);
- }
-
- public float getPeriodConfidence() {
- return mPeriodConfidence.floatValue();
- }
-
- public void setPeriodConfidence(float periodConfidence) {
- this.mPeriodConfidence = Float.valueOf(periodConfidence);
- }
-
- public float getRMS() {
- return mRms.floatValue();
- }
-
- public void setRMS(float rms) {
- this.mRms = Float.valueOf(rms);
- }
-
- public float getRMSAverage() {
- return mRmsAverage.floatValue();
- }
-
- public void setRMSAverage(float rmsAverage) {
- this.mRmsAverage = Float.valueOf(rmsAverage);
- }
-
- public int getAudioLevel() {
- return mAudioLevel.intValue();
- }
-
- public void setAudioLevel(int audioLevel) {
- this.mAudioLevel = Integer.valueOf(audioLevel);
- }
-
- public int getBlockSize() {
- return mBblockSize.intValue();
- }
-
- public void setBlockSize(int blockSize) {
- this.mBblockSize = Integer.valueOf(blockSize);
- }
-
- public int getIteration() {
- return mIteration.intValue();
- }
-
- public void setIteration(int iteration) {
- this.mIteration = Integer.valueOf(iteration);
- }
-
- public long getDeviceTestStartTime() {
- return mDeviceTestStartTime.longValue();
- }
-
- public void setDeviceTestStartTime(long deviceTestStartTime) {
- this.mDeviceTestStartTime = Long.valueOf(deviceTestStartTime);
- }
-
- public Result getImageAnalyzerResult() {
- return mImageAnalyzerResult;
- }
-
- public void setImageAnalyzerResult(Result imageAnalyzerResult) {
- this.mImageAnalyzerResult = imageAnalyzerResult;
- }
-
- public String getFailureReason() {
- return mFailureReason;
- }
-
- public void setFailureReason(String failureReason) {
- this.mFailureReason = failureReason;
- }
-
- public boolean isTimedOut() {
- return mIsTimedOut;
- }
-
- public void setIsTimedOut(boolean isTimedOut) {
- this.mIsTimedOut = isTimedOut;
- }
-
- public String getLogFile(LogFileType log) {
- return mLogs.get(log);
- }
-
- public void setLogFile(LogFileType log, String filename) {
- CLog.i("setLogFile: type=" + log.name() + ", filename=" + filename);
- if (!mLogs.containsKey(log) && filename != null && !filename.isEmpty()) {
- mLogs.put(log, filename);
- }
- }
-
- public boolean hasBadResults() {
- return hasTimedOut()
- || hasNoTestResults()
- || hasNoLatencyResult()
- || hasNoLatencyConfidence()
- || mImageAnalyzerResult == Result.FAIL;
- }
-
- public boolean hasTimedOut() {
- return mIsTimedOut;
- }
-
- public boolean hasLogFile(LogFileType log) {
- return mLogs.containsKey(log);
- }
-
- public boolean hasNoLatencyResult() {
- return mLatencyMs == null;
- }
-
- public boolean hasNoLatencyConfidence() {
- return mLatencyConfidence == null;
- }
-
- public boolean hasNoTestResults() {
- return hasNoLatencyConfidence() && hasNoLatencyResult();
- }
-
- public static Comparator<ResultData> latencyComparator =
- new Comparator<ResultData>() {
- @Override
- public int compare(ResultData o1, ResultData o2) {
- return o1.mLatencyMs.compareTo(o2.mLatencyMs);
- }
- };
-
- public static Comparator<ResultData> confidenceComparator =
- new Comparator<ResultData>() {
- @Override
- public int compare(ResultData o1, ResultData o2) {
- return o1.mLatencyConfidence.compareTo(o2.mLatencyConfidence);
- }
- };
-
- public static Comparator<ResultData> iteratorComparator =
- new Comparator<ResultData>() {
- @Override
- public int compare(ResultData o1, ResultData o2) {
- return Integer.compare(o1.mIteration, o2.mIteration);
- }
- };
-
- @Override
- public String toString() {
- final String NL = "\n";
- final StringBuilder sb = new StringBuilder(512);
- sb.append("{").append(NL);
- sb.append("{\nlatencyMs=").append(mLatencyMs).append(NL);
- sb.append("latencyConfidence=").append(mLatencyConfidence).append(NL);
- sb.append("isTimedOut=").append(mIsTimedOut).append(NL);
- sb.append("iteration=").append(mIteration).append(NL);
- sb.append("logs=").append(Arrays.toString(mLogs.values().toArray())).append(NL);
- sb.append("audioLevel=").append(mAudioLevel).append(NL);
- sb.append("deviceTestStartTime=").append(mDeviceTestStartTime).append(NL);
- sb.append("rms=").append(mRms).append(NL);
- sb.append("rmsAverage=").append(mRmsAverage).append(NL);
- sb.append("}").append(NL);
- return sb.toString();
- }
- }
-
- public AudioLoopbackTestHelper(int iterations) {
- mAllResults = new ArrayList<ResultData>(iterations);
- }
-
- public void addTestData(ResultData data, Map<String, String> resultDictionary) {
- mResultDictionaries.add(data.getIteration(), resultDictionary);
- mAllResults.add(data);
-
- // Analyze captured screenshot to see if wave form is within reason
- final String screenshot = data.getLogFile(LogFileType.GRAPH);
- final Pair<Result, String> result = AudioLoopbackImageAnalyzer.analyzeImage(screenshot);
- data.setImageAnalyzerResult(result.first);
- data.setFailureReason(result.second);
- }
-
- public final List<ResultData> getAllTestData() {
- return mAllResults;
- }
-
- public Map<String, String> getResultDictionaryForIteration(int i) {
- return mResultDictionaries.get(i);
- }
-
- /**
- * Returns a list of the worst test result objects, up to maxNrOfWorstResults
- *
- * <p>
- *
- * <ol>
- * <li> Tests in the bad results list are added first
- * <li> If still space, add test results based on low confidence and then tests that are
- * outside tolerance boundaries
- * </ol>
- *
- * @param maxNrOfWorstResults
- * @return list of worst test result objects
- */
- public List<ResultData> getWorstResults(int maxNrOfWorstResults) {
- int counter = 0;
- final ArrayList<ResultData> worstResults = new ArrayList<ResultData>(maxNrOfWorstResults);
-
- for (final ResultData data : mBadResults) {
- if (counter < maxNrOfWorstResults) {
- worstResults.add(data);
- counter++;
- }
- }
-
- for (final ResultData data : mGoodResults) {
- if (counter < maxNrOfWorstResults) {
- boolean failed = false;
- if (data.getConfidence() < 1.0f) {
- data.setFailureReason("Low confidence");
- failed = true;
- } else if (data.getLatency() < (mLatencyStats.mMedian - TOLERANCE)
- || data.getLatency() > (mLatencyStats.mMedian + TOLERANCE)) {
- data.setFailureReason("Latency not within tolerance from median");
- failed = true;
- }
-
- if (failed) {
- worstResults.add(data);
- counter++;
- }
- }
- }
-
- return worstResults;
- }
-
- public static Map<String, String> parseKeyValuePairFromFile(
- File result,
- final Map<String, String> dictionary,
- final String resultKeyPrefix,
- final String splitOn,
- final String keyValueFormat)
- throws IOException {
-
- final Map<String, String> resultMap = new HashMap<String, String>();
- final BufferedReader br = Files.newReader(result, StandardCharsets.UTF_8);
-
- try {
- String line = br.readLine();
- while (line != null) {
- line = line.trim().replaceAll(" +", " ");
- final String[] tokens = line.split(splitOn);
- if (tokens.length >= 2) {
- final String key = tokens[0].trim();
- final String value = tokens[1].trim();
- if (dictionary.containsKey(key)) {
- CLog.i(String.format(keyValueFormat, key, value));
- resultMap.put(resultKeyPrefix + dictionary.get(key), value);
- }
- }
- line = br.readLine();
- }
- } finally {
- br.close();
- }
- return resultMap;
- }
-
- public int processTestData() {
-
- // Collect statistics about the test run
- int nrOfValidResults = 0;
- double sumLatency = 0;
- double sumConfidence = 0;
-
- final int totalNrOfTests = mAllResults.size();
- mLatencyStats = new StatisticsData();
- mConfidenceStats = new StatisticsData();
- mBadResults = new ArrayList<ResultData>();
- mGoodResults = new ArrayList<ResultData>(totalNrOfTests);
-
- // Copy all results into Good results list
- mGoodResults.addAll(mAllResults);
-
- for (final ResultData data : mAllResults) {
- if (data.hasBadResults()) {
- mBadResults.add(data);
- continue;
- }
- // Get mean values
- sumLatency += data.getLatency();
- sumConfidence += data.getConfidence();
- }
-
- if (!mBadResults.isEmpty()) {
- analyzeBadResults(mBadResults, mAllResults.size());
- }
-
- // Remove bad runs from result array
- mGoodResults.removeAll(mBadResults);
-
- // Fail test immediately if we don't have ANY good results
- if (mGoodResults.isEmpty()) {
- return 0;
- }
-
- nrOfValidResults = mGoodResults.size();
-
- // ---- LATENCY: Get Median, Min and Max values ----
- Collections.sort(mGoodResults, ResultData.latencyComparator);
-
- mLatencyStats.mMin = mGoodResults.get(0).mLatencyMs;
- mLatencyStats.mMax = mGoodResults.get(nrOfValidResults - 1).mLatencyMs;
- mLatencyStats.mMean = sumLatency / nrOfValidResults;
- // Is array even or odd numbered
- if (nrOfValidResults % 2 == 0) {
- final int middle = nrOfValidResults / 2;
- final float middleLeft = mGoodResults.get(middle - 1).mLatencyMs;
- final float middleRight = mGoodResults.get(middle).mLatencyMs;
- mLatencyStats.mMedian = (middleLeft + middleRight) / 2.0f;
- } else {
- // It's and odd numbered array, just grab the middle value
- mLatencyStats.mMedian = mGoodResults.get(nrOfValidResults / 2).mLatencyMs;
- }
-
- // ---- CONFIDENCE: Get Median, Min and Max values ----
- Collections.sort(mGoodResults, ResultData.confidenceComparator);
-
- mConfidenceStats.mMin = mGoodResults.get(0).mLatencyConfidence;
- mConfidenceStats.mMax = mGoodResults.get(nrOfValidResults - 1).mLatencyConfidence;
- mConfidenceStats.mMean = sumConfidence / nrOfValidResults;
- // Is array even or odd numbered
- if (nrOfValidResults % 2 == 0) {
- final int middle = nrOfValidResults / 2;
- final float middleLeft = mGoodResults.get(middle - 1).mLatencyConfidence;
- final float middleRight = mGoodResults.get(middle).mLatencyConfidence;
- mConfidenceStats.mMedian = (middleLeft + middleRight) / 2.0f;
- } else {
- // It's and odd numbered array, just grab the middle value
- mConfidenceStats.mMedian = mGoodResults.get(nrOfValidResults / 2).mLatencyConfidence;
- }
-
- for (final ResultData data : mGoodResults) {
- // Check if within Latency Tolerance
- if (data.getConfidence() < 1.0f) {
- data.setFailureReason("Low confidence");
- } else if (data.getLatency() < (mLatencyStats.mMedian - TOLERANCE)
- || data.getLatency() > (mLatencyStats.mMedian + TOLERANCE)) {
- data.setFailureReason("Latency not within tolerance from median");
- }
- }
-
- // Create histogram
- // Strategy: Create buckets based on whole ints, like 16 ms, 17 ms, 18 ms etc. Count how
- // many tests fall into each bucket. Just cast the float to an int, no rounding up/down
- // required.
- final int[] histogram = new int[(int) mLatencyStats.mMax + 1];
- for (final ResultData rd : mGoodResults) {
- // Increase value in bucket
- histogram[(int) (rd.mLatencyMs.floatValue())]++;
- }
-
- CLog.i("========== VALID RESULTS ============================================");
- CLog.i(String.format("Valid tests: %1$d of %2$d", nrOfValidResults, totalNrOfTests));
- CLog.i("Latency: " + mLatencyStats.toString());
- CLog.i("Confidence: " + mConfidenceStats.toString());
- CLog.i("========== HISTOGRAM ================================================");
- for (int i = 0; i < histogram.length; i++) {
- if (histogram[i] > 0) {
- CLog.i(String.format("%1$01d ms => %2$d", i, histogram[i]));
- }
- }
-
- // VERIFY the good results by running image analysis on the
- // screenshot of the incoming audio waveform
-
- return nrOfValidResults;
- }
-
- public void writeAllResultsToCSVFile(File csvFile, ITestDevice device)
- throws DeviceNotAvailableException, FileNotFoundException,
- UnsupportedEncodingException {
-
- final String deviceType = device.getProperty("ro.build.product");
- final String buildId = device.getBuildAlias();
- final String serialNumber = device.getSerialNumber();
-
- // Sort data on iteration
- Collections.sort(mAllResults, ResultData.iteratorComparator);
-
- final StringBuilder sb = new StringBuilder(256);
- final PrintWriter writer = new PrintWriter(csvFile, StandardCharsets.UTF_8.name());
- final String SEPARATOR = ",";
-
- // Write column labels
- writer.println(
- "Device Time,Device Type,Build Id,Serial Number,Iteration,Latency,"
- + "Confidence,Period Confidence,Block Size,Audio Level,RMS,RMS Average,"
- + "Image Analysis,Failure Reason");
- for (final ResultData data : mAllResults) {
- final Instant instant = Instant.ofEpochSecond(data.mDeviceTestStartTime);
-
- sb.append(instant).append(SEPARATOR);
- sb.append(deviceType).append(SEPARATOR);
- sb.append(buildId).append(SEPARATOR);
- sb.append(serialNumber).append(SEPARATOR);
- sb.append(data.getIteration()).append(SEPARATOR);
- sb.append(data.getLatency()).append(SEPARATOR);
- sb.append(data.getConfidence()).append(SEPARATOR);
- sb.append(data.getPeriodConfidence()).append(SEPARATOR);
- sb.append(data.getBlockSize()).append(SEPARATOR);
- sb.append(data.getAudioLevel()).append(SEPARATOR);
- sb.append(data.getRMS()).append(SEPARATOR);
- sb.append(data.getRMSAverage()).append(SEPARATOR);
- sb.append(data.getImageAnalyzerResult().name()).append(SEPARATOR);
- sb.append(data.getFailureReason());
-
- writer.println(sb.toString());
-
- sb.setLength(0);
- }
- writer.close();
- }
-
- private void analyzeBadResults(ArrayList<ResultData> badResults, int totalNrOfTests) {
- int testNoData = 0;
- int testTimeoutCounts = 0;
- int testResultsNotFoundCounts = 0;
- int testWithoutLatencyResultCount = 0;
- int testWithoutConfidenceResultCount = 0;
-
- for (final ResultData data : badResults) {
- if (data.hasTimedOut()) {
- testTimeoutCounts++;
- testNoData++;
- continue;
- }
-
- if (data.hasNoTestResults()) {
- testResultsNotFoundCounts++;
- testNoData++;
- continue;
- }
-
- if (data.hasNoLatencyResult()) {
- testWithoutLatencyResultCount++;
- testNoData++;
- continue;
- }
-
- if (data.hasNoLatencyConfidence()) {
- testWithoutConfidenceResultCount++;
- testNoData++;
- continue;
- }
- }
-
- CLog.i("========== BAD RESULTS ============================================");
- CLog.i(String.format("No Data: %1$d of %2$d", testNoData, totalNrOfTests));
- CLog.i(String.format("Timed out: %1$d of %2$d", testTimeoutCounts, totalNrOfTests));
- CLog.i(
- String.format(
- "No results: %1$d of %2$d", testResultsNotFoundCounts, totalNrOfTests));
- CLog.i(
- String.format(
- "No Latency results: %1$d of %2$d",
- testWithoutLatencyResultCount, totalNrOfTests));
- CLog.i(
- String.format(
- "No Confidence results: %1$d of %2$d",
- testWithoutConfidenceResultCount, totalNrOfTests));
- }
-
- /** Generates metrics dictionary for stress test */
- public void populateStressTestMetrics(
- Map<String, String> metrics, final String resultKeyPrefix) {
- metrics.put(resultKeyPrefix + "total_nr_of_tests", Integer.toString(mAllResults.size()));
- metrics.put(resultKeyPrefix + "nr_of_good_tests", Integer.toString(mGoodResults.size()));
- metrics.put(resultKeyPrefix + "latency_max", Double.toString(mLatencyStats.mMax));
- metrics.put(resultKeyPrefix + "latency_min", Double.toString(mLatencyStats.mMin));
- metrics.put(resultKeyPrefix + "latency_mean", Double.toString(mLatencyStats.mMean));
- metrics.put(resultKeyPrefix + "latency_median", Double.toString(mLatencyStats.mMedian));
- metrics.put(resultKeyPrefix + "confidence_max", Double.toString(mConfidenceStats.mMax));
- metrics.put(resultKeyPrefix + "confidence_min", Double.toString(mConfidenceStats.mMin));
- metrics.put(resultKeyPrefix + "confidence_mean", Double.toString(mConfidenceStats.mMean));
- metrics.put(
- resultKeyPrefix + "confidence_median", Double.toString(mConfidenceStats.mMedian));
- }
-}
diff --git a/src/com/android/media/tests/Camera2FrameworkStressTest.java b/src/com/android/media/tests/Camera2FrameworkStressTest.java
deleted file mode 100644
index 8d62595..0000000
--- a/src/com/android/media/tests/Camera2FrameworkStressTest.java
+++ /dev/null
@@ -1,188 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.media.tests;
-
-import com.android.ddmlib.testrunner.TestIdentifier;
-import com.android.tradefed.config.OptionClass;
-import com.android.tradefed.device.DeviceNotAvailableException;
-import com.android.tradefed.device.IFileEntry;
-import com.android.tradefed.log.LogUtil.CLog;
-import com.android.tradefed.result.ITestInvocationListener;
-import com.android.tradefed.util.FileUtil;
-
-import java.io.BufferedReader;
-import java.io.File;
-import java.io.FileReader;
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-
-/**
- * Camera2 framework stress test
- * This is a test invocation that runs stress tests against Camera2 framework (API & HAL) to
- * isolate stability issues from Camera application.
- * This invocation uses a Camera2InstrumentationTestRunner to run a set of
- * Camera framework stress tests.
- */
-@OptionClass(alias = "camera2-framework-stress")
-public class Camera2FrameworkStressTest extends CameraTestBase {
-
- // Keys in instrumentation test metrics
- private static final String RESULT_DIR = "/sdcard/camera-out/";
- private static final String RESULT_FILE_FORMAT = RESULT_DIR + "fwk-stress_camera_%s.txt";
- private static final Pattern RESULT_FILE_REGEX = Pattern.compile(
- "^fwk-stress_camera_(?<id>.+).txt");
- private static final String KEY_NUM_ATTEMPTS = "numAttempts";
- private static final String KEY_ITERATION = "iteration";
-
- public Camera2FrameworkStressTest() {
- // Note that default value in constructor will be overridden by the passing option from
- // a command line.
- setTestPackage("com.android.mediaframeworktest");
- setTestRunner("com.android.mediaframeworktest.Camera2InstrumentationTestRunner");
- setRuKey("CameraFrameworkStress");
- setTestTimeoutMs(2 * 60 * 60 * 1000); // 2 hours
- setLogcatOnFailure(true);
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public void run(ITestInvocationListener listener) throws DeviceNotAvailableException {
- runInstrumentationTest(listener, new CollectingListener(listener));
- }
-
- /**
- * A listener to collect the output from test run and fatal errors
- */
- private class CollectingListener extends DefaultCollectingListener {
-
- public CollectingListener(ITestInvocationListener listener) {
- super(listener);
- }
-
- @Override
- public void handleMetricsOnTestEnded(TestIdentifier test, Map<String, String> testMetrics) {
- if (testMetrics == null) {
- return; // No-op if there is nothing to post.
- }
- for (Map.Entry<String, String> metric : testMetrics.entrySet()) {
- getAggregatedMetrics().put(metric.getKey(), metric.getValue());
- }
- }
-
- @Override
- public void testEnded(TestIdentifier test, long endTime, Map<String, String> testMetrics) {
- if (hasTestRunFatalError()) {
- CLog.v("The instrumentation result not found. Fall back to get the metrics from a "
- + "log file. errorMsg: %s", getCollectingListener().getErrorMessage());
- }
-
- // For stress test, parse the metrics from a log file.
- testMetrics = parseLog(test.getTestName());
- super.testEnded(test, endTime, testMetrics);
- }
-
- // Return null if failed to parse the result file or the test didn't even start.
- private Map<String, String> parseLog(String testName) {
- Map<String, String> postMetrics = new HashMap<String, String>();
- String resultFilePath;
- try {
- for (String cameraId : getCameraIdList(RESULT_DIR)) {
- File outputFile = FileUtil.createTempFile("fwk-stress", ".txt");
- resultFilePath = getResultFilePath(cameraId);
- getDevice().pullFile(resultFilePath, outputFile);
- if (outputFile == null) {
- throw new DeviceNotAvailableException(String.format("Failed to pull the "
- + "result file: %s", resultFilePath),
- getDevice().getSerialNumber());
- }
-
- BufferedReader reader = new BufferedReader(new FileReader(outputFile));
- String line;
- Map<String, String> resultMap = new HashMap<String, String>();
-
- // Parse results from log file that contain the key-value pairs.
- // eg. "numAttempts=10|iteration=9[|cameraId=0]"
- try {
- while ((line = reader.readLine()) != null) {
- String[] pairs = line.split("\\|");
- for (String pair : pairs) {
- String[] keyValue = pair.split("=");
- // Each should be a pair of key and value.
- String key = keyValue[0].trim();
- String value = keyValue[1].trim();
- resultMap.put(key, value);
- }
- }
- } finally {
- reader.close();
- }
-
- // Fail if a stress test doesn't start.
- if (0 == Integer.parseInt(resultMap.get(KEY_NUM_ATTEMPTS))) {
- CLog.w("Failed to start stress tests. test setup configured incorrectly?");
- return null;
- }
- // Post the number of iterations only with the key name associated with
- // test name and camera ID.
- String keyName = testName + "_" + cameraId;
- postMetrics.put(keyName, resultMap.get(KEY_ITERATION));
- }
- } catch (IOException e) {
- CLog.w("Couldn't parse the output log file");
- CLog.e(e);
- } catch (DeviceNotAvailableException e) {
- CLog.w("Could not pull file: %s, error:", RESULT_DIR);
- CLog.e(e);
- } catch (NumberFormatException e) {
- CLog.w("Could not find the key in file: %s, error:", KEY_NUM_ATTEMPTS);
- CLog.e(e);
- }
- return postMetrics;
- }
- }
-
- private ArrayList<String> getCameraIdList(String resultDir) throws DeviceNotAvailableException {
- // The result files are created per each camera ID
- ArrayList<String> cameraIds = new ArrayList<>();
- IFileEntry dirEntry = getDevice().getFileEntry(resultDir);
- if (dirEntry != null) {
- for (IFileEntry file : dirEntry.getChildren(false)) {
- String fileName = file.getName();
- Matcher matcher = RESULT_FILE_REGEX.matcher(fileName);
- if (matcher.matches()) {
- cameraIds.add(matcher.group("id"));
- }
- }
- }
-
- if (cameraIds.isEmpty()) {
- CLog.w("No camera ID is found in %s. The resultToFile instrumentation argument is set"
- + " to false?", resultDir);
- }
- return cameraIds;
- }
-
- private String getResultFilePath(String cameraId) {
- return String.format(RESULT_FILE_FORMAT, cameraId);
- }
-}
diff --git a/src/com/android/media/tests/Camera2LatencyTest.java b/src/com/android/media/tests/Camera2LatencyTest.java
deleted file mode 100644
index 5a06822..0000000
--- a/src/com/android/media/tests/Camera2LatencyTest.java
+++ /dev/null
@@ -1,94 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.media.tests;
-
-import com.android.ddmlib.testrunner.TestIdentifier;
-import com.android.tradefed.config.OptionClass;
-import com.android.tradefed.device.DeviceNotAvailableException;
-import com.android.tradefed.log.LogUtil.CLog;
-import com.android.tradefed.result.ITestInvocationListener;
-
-import java.util.HashMap;
-import java.util.Map;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-
-/**
- * Camera app latency test
- *
- * Runs Camera app latency test to measure Camera capture session time and reports the metrics.
- */
-@OptionClass(alias = "camera-latency")
-public class Camera2LatencyTest extends CameraTestBase {
-
- public Camera2LatencyTest() {
- setTestPackage("com.google.android.camera");
- setTestClass("com.android.camera.latency.CameraCaptureSessionTest");
- setTestRunner("android.test.InstrumentationTestRunner");
- setRuKey("CameraAppLatency");
- setTestTimeoutMs(60 * 60 * 1000); // 1 hour
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public void run(ITestInvocationListener listener) throws DeviceNotAvailableException {
- runInstrumentationTest(listener, new CollectingListener(listener));
- }
-
- /**
- * A listener to collect the results from each test run, then forward them to other listeners.
- */
- private class CollectingListener extends DefaultCollectingListener {
-
- public CollectingListener(ITestInvocationListener listener) {
- super(listener);
- }
-
- @Override
- public void handleMetricsOnTestEnded(TestIdentifier test, Map<String, String> testMetrics) {
- // Test metrics accumulated will be posted at the end of test run.
- getAggregatedMetrics().putAll(parseResults(test.getTestName(), testMetrics));
- }
-
- private Map<String, String> parseResults(String testName, Map<String, String> testMetrics) {
- final Pattern STATS_REGEX = Pattern.compile(
- "^(?<latency>[0-9.]+)\\|(?<values>[0-9 .-]+)");
-
- // Parse activity time stats from the instrumentation result.
- // Format : <metric_key>=<average_of_latency>|<raw_data>
- // Example:
- // FirstCaptureResultTimeMs=38|13 48 ... 35
- // SecondCaptureResultTimeMs=29.2|65 24 ... 0
- // CreateTimeMs=373.6|382 364 ... 323
- //
- // Then report only the first two startup time of cold startup and average warm startup.
- Map<String, String> parsed = new HashMap<String, String>();
- for (Map.Entry<String, String> metric : testMetrics.entrySet()) {
- Matcher matcher = STATS_REGEX.matcher(metric.getValue());
- if (matcher.matches()) {
- String keyName = String.format("%s_%s", testName, metric.getKey());
- parsed.put(keyName, matcher.group("latency"));
- } else {
- CLog.w(String.format("Stats not in correct format: %s", metric.getValue()));
- }
- }
- return parsed;
- }
- }
-}
diff --git a/src/com/android/media/tests/Camera2StressTest.java b/src/com/android/media/tests/Camera2StressTest.java
deleted file mode 100644
index 77868d9..0000000
--- a/src/com/android/media/tests/Camera2StressTest.java
+++ /dev/null
@@ -1,188 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.media.tests;
-
-import com.android.ddmlib.testrunner.TestIdentifier;
-import com.android.tradefed.config.OptionClass;
-import com.android.tradefed.device.DeviceNotAvailableException;
-import com.android.tradefed.device.IFileEntry;
-import com.android.tradefed.log.LogUtil.CLog;
-import com.android.tradefed.result.FileInputStreamSource;
-import com.android.tradefed.result.ITestInvocationListener;
-import com.android.tradefed.result.LogDataType;
-import com.android.tradefed.util.FileUtil;
-
-import java.io.BufferedReader;
-import java.io.File;
-import java.io.FileReader;
-import java.io.IOException;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.Map.Entry;
-
-/**
- * Camera2 stress test
- * Since Camera stress test can drain the battery seriously. Need to split
- * the test suite into separate test invocation for each test method.
- * <p/>
- */
-@OptionClass(alias = "camera2-stress")
-public class Camera2StressTest extends CameraTestBase {
-
- private static final String RESULT_FILE = "/sdcard/camera-out/stress.txt";
- private static final String FAILURE_SCREENSHOT_DIR = "/sdcard/camera-screenshot/";
- private static final String KEY_NUM_ATTEMPTS = "numAttempts";
- private static final String KEY_ITERATION = "iteration";
-
- public Camera2StressTest() {
- setTestPackage("com.google.android.camera");
- setTestClass("com.android.camera.stress.CameraStressTest");
- setTestRunner("android.test.InstrumentationTestRunner");
- setRuKey("CameraAppStress");
- setTestTimeoutMs(6 * 60 * 60 * 1000); // 6 hours
- setLogcatOnFailure(true);
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public void run(ITestInvocationListener listener) throws DeviceNotAvailableException {
- runInstrumentationTest(listener, new CollectingListener(listener));
- }
-
- /**
- * A listener to collect the output from test run and fatal errors
- */
- private class CollectingListener extends DefaultCollectingListener {
-
- public CollectingListener(ITestInvocationListener listener) {
- super(listener);
- }
-
- @Override
- public void testEnded(TestIdentifier test, long endTime, Map<String, String> testMetrics) {
- if (hasTestRunFatalError()) {
- CLog.v("The instrumentation result not found. Fall back to get the metrics from a "
- + "log file. errorMsg: %s", getCollectingListener().getErrorMessage());
- }
- // TODO: Will get the additional metrics to file to prevent result loss
-
- // Don't need to report the KEY_NUM_ATTEMPS to dashboard
- // Iteration will be read from file
- testMetrics.remove(KEY_NUM_ATTEMPTS);
- testMetrics.remove(KEY_ITERATION);
-
- // add testMethod name to the metric
- Map<String, String> namedTestMetrics = new HashMap<>();
- for (Entry<String, String> entry : testMetrics.entrySet()) {
- namedTestMetrics.put(test.getTestName() + entry.getKey(), entry.getValue());
- }
-
- // parse the iterations metrics from the stress log files
- parseLog(test.getTestName(), namedTestMetrics);
-
- postScreenshotOnFailure(test);
- super.testEnded(test, endTime, namedTestMetrics);
- }
-
- private void postScreenshotOnFailure(TestIdentifier test) {
- File tmpDir = null;
- try {
- IFileEntry screenshotDir = getDevice().getFileEntry(FAILURE_SCREENSHOT_DIR);
- if (screenshotDir != null && screenshotDir.isDirectory()) {
- tmpDir = FileUtil.createTempDir("screenshot");
- for (IFileEntry remoteFile : screenshotDir.getChildren(false)) {
- if (remoteFile.isDirectory()) {
- continue;
- }
- if (!remoteFile.getName().contains(test.getTestName())) {
- CLog.v("Skipping the screenshot (%s) that doesn't match the current "
- + "test (%s)", remoteFile.getName(), test.getTestName());
- continue;
- }
- File screenshot = new File(tmpDir, remoteFile.getName());
- if (!getDevice().pullFile(remoteFile.getFullPath(), screenshot)) {
- CLog.w("Could not pull screenshot: %s", remoteFile.getFullPath());
- continue;
- }
- testLog(
- "screenshot_" + screenshot.getName(),
- LogDataType.PNG,
- new FileInputStreamSource(screenshot));
- }
- }
- } catch (DeviceNotAvailableException e) {
- CLog.e(e);
- } catch (IOException e) {
- CLog.e(e);
- } finally {
- FileUtil.recursiveDelete(tmpDir);
- }
- }
-
- // Return null if failed to parse the result file or the test didn't even start.
- private void parseLog(String testName, Map<String, String> testMetrics) {
- try {
- File outputFile = FileUtil.createTempFile("stress", ".txt");
- getDevice().pullFile(RESULT_FILE, outputFile);
- if (outputFile == null) {
- throw new DeviceNotAvailableException(String.format("Failed to pull the result"
- + "file: %s", RESULT_FILE), getDevice().getSerialNumber());
- }
- BufferedReader reader = new BufferedReader(new FileReader(outputFile));
- String line;
- Map<String, String> resultMap = new HashMap<>();
-
- // Parse results from log file that contain the key-value pairs.
- // eg. "numAttempts=10|iteration=9"
- try {
- while ((line = reader.readLine()) != null) {
- String[] pairs = line.split("\\|");
- for (String pair : pairs) {
- String[] keyValue = pair.split("=");
- // Each should be a pair of key and value.
- String key = keyValue[0].trim();
- String value = keyValue[1].trim();
- resultMap.put(key, value);
- CLog.v("%s: %s", key, value);
- }
- }
- } finally {
- reader.close();
- }
-
- // Fail if a stress test doesn't start.
- if (0 == Integer.parseInt(resultMap.get(KEY_NUM_ATTEMPTS))) {
- CLog.w("Failed to start stress tests. test setup configured incorrectly?");
- return;
- }
- // Post the number of iterations only with the test name as key.
- testMetrics.put(testName, resultMap.get(KEY_ITERATION));
- } catch (IOException e) {
- CLog.w("Couldn't parse the output log file:");
- CLog.e(e);
- } catch (DeviceNotAvailableException e) {
- CLog.w("Could not pull file: %s, error:", RESULT_FILE);
- CLog.e(e);
- } catch (NumberFormatException e) {
- CLog.w("Could not find the key in file: %s, error:", KEY_NUM_ATTEMPTS);
- CLog.e(e);
- }
- }
- }
-}
diff --git a/src/com/android/media/tests/CameraBurstStartupTest.java b/src/com/android/media/tests/CameraBurstStartupTest.java
deleted file mode 100644
index 74d7e87..0000000
--- a/src/com/android/media/tests/CameraBurstStartupTest.java
+++ /dev/null
@@ -1,84 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.media.tests;
-
-import com.android.ddmlib.testrunner.TestIdentifier;
-import com.android.tradefed.config.OptionClass;
-import com.android.tradefed.device.DeviceNotAvailableException;
-import com.android.tradefed.log.LogUtil.CLog;
-import com.android.tradefed.result.ITestInvocationListener;
-
-import java.util.HashMap;
-import java.util.Map;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-
-/**
- * Camera burst startup test
- *
- * <p>Runs Camera device performance test to measure time for taking a burst shot.
- */
-@OptionClass(alias = "camera-burst-shot")
-public class CameraBurstStartupTest extends CameraTestBase {
-
- private static final Pattern STATS_REGEX = Pattern.compile("^(?<average>[0-9.]+)");
-
- public CameraBurstStartupTest() {
- setTestPackage("com.google.android.camera");
- setTestClass("com.android.camera.latency.BurstStartupTest");
- setTestRunner("android.test.InstrumentationTestRunner");
- setRuKey("CameraBurstStartup");
- setTestTimeoutMs(60 * 60 * 1000); // 1 hour
- }
-
- /** {@inheritDoc} */
- @Override
- public void run(ITestInvocationListener listener) throws DeviceNotAvailableException {
- runInstrumentationTest(listener, new CollectingListener(listener));
- }
-
- /** A listener to collect the output from test run and fatal errors */
- private class CollectingListener extends DefaultCollectingListener {
-
- public CollectingListener(ITestInvocationListener listener) {
- super(listener);
- }
-
- @Override
- public void handleMetricsOnTestEnded(TestIdentifier test, Map<String, String> testMetrics) {
- // Test metrics accumulated will be posted at the end of test run.
- getAggregatedMetrics().putAll(parseResults(test.getTestName(), testMetrics));
- }
-
- public Map<String, String> parseResults(String testName, Map<String, String> testMetrics) {
- // Parse burst startup stats from the instrumentation result.
- Map<String, String> parsed = new HashMap<String, String>();
- for (Map.Entry<String, String> metric : testMetrics.entrySet()) {
- Matcher matcher = STATS_REGEX.matcher(metric.getValue());
-
- if (matcher.matches()) {
- // Key name consists of a pair of test name and metric name.
- String keyName = String.format("%s_%s", testName, metric.getKey());
- parsed.put(keyName, matcher.group("average"));
- } else {
- CLog.w(String.format("Stats not in correct format: %s", metric.getValue()));
- }
- }
- return parsed;
- }
- }
-}
diff --git a/src/com/android/media/tests/CameraLatencyTest.java b/src/com/android/media/tests/CameraLatencyTest.java
deleted file mode 100644
index f44fd59..0000000
--- a/src/com/android/media/tests/CameraLatencyTest.java
+++ /dev/null
@@ -1,369 +0,0 @@
-/*
- * Copyright (C) 2011 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.media.tests;
-
-import com.android.ddmlib.IDevice;
-import com.android.ddmlib.testrunner.IRemoteAndroidTestRunner;
-import com.android.ddmlib.testrunner.RemoteAndroidTestRunner;
-import com.android.tradefed.config.Option;
-import com.android.tradefed.device.DeviceNotAvailableException;
-import com.android.tradefed.device.ITestDevice;
-import com.android.tradefed.log.LogUtil.CLog;
-import com.android.tradefed.result.CollectingTestListener;
-import com.android.tradefed.result.FileInputStreamSource;
-import com.android.tradefed.result.ITestInvocationListener;
-import com.android.tradefed.result.InputStreamSource;
-import com.android.tradefed.result.LogDataType;
-import com.android.tradefed.testtype.IDeviceTest;
-import com.android.tradefed.testtype.IRemoteTest;
-import com.android.tradefed.util.FileUtil;
-import com.android.tradefed.util.RegexTrie;
-import com.android.tradefed.util.StreamUtil;
-
-import junit.framework.TestCase;
-
-import org.junit.Assert;
-
-import java.io.ByteArrayInputStream;
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.HashMap;
-import java.util.List;
-import java.util.ListIterator;
-import java.util.Map;
-import java.util.concurrent.TimeUnit;
-
-/**
- * Runs the Camera latency testcases.
- * FIXME: more details
- * <p/>
- * Note that this test will not run properly unless /sdcard is mounted and writable.
- */
-public class CameraLatencyTest implements IDeviceTest, IRemoteTest {
- ITestDevice mTestDevice = null;
-
- // Constants for running the tests
- private static final String TEST_PACKAGE_NAME = "com.google.android.camera.tests";
-
- private final String mOutputPath = "mediaStressOut.txt";
-
- //Max timeout for the test - 30 mins
- private static final int MAX_TEST_TIMEOUT = 30 * 60 * 1000;
-
- /**
- * Stores the test cases that we should consider running.
- *
- * <p>This currently consists of "startup" and "latency"
- */
- private List<TestInfo> mTestCases = new ArrayList<>();
-
- // Options for the running the gCam test
- @Option(name = "gCam", description = "Run gCam startup test")
- private boolean mGcam = false;
-
-
- /**
- * A struct that contains useful info about the tests to run
- */
- static class TestInfo {
- public String mTestName = null;
- public String mClassName = null;
- public String mTestMetricsName = null;
- public RegexTrie<String> mPatternMap = new RegexTrie<>();
-
- @Override
- public String toString() {
- return String.format("TestInfo: name(%s) class(%s) metric(%s) patterns(%s)", mTestName,
- mClassName, mTestMetricsName, mPatternMap);
- }
- }
-
- /**
- * Set up the configurations for the test cases we want to run
- */
- private void testInfoSetup() {
- // Startup tests
- TestInfo t = new TestInfo();
-
- if (mGcam) {
- t.mTestName = "testLaunchCamera";
- t.mClassName = "com.android.camera.stress.CameraStartUp";
- t.mTestMetricsName = "GCameraStartup";
- RegexTrie<String> map = t.mPatternMap;
- map = t.mPatternMap;
- map.put("FirstCameraStartup", "^First Camera Startup: (\\d+)");
- map.put("CameraStartup", "^Camera average startup time: (\\d+) ms");
- mTestCases.add(t);
- } else {
- t.mTestName = "startup";
- t.mClassName = "com.android.camera.stress.CameraStartUp";
- t.mTestMetricsName = "CameraVideoRecorderStartup";
- RegexTrie<String> map = t.mPatternMap;
- map = t.mPatternMap;
- map.put("FirstCameraStartup", "^First Camera Startup: (\\d+)");
- map.put("CameraStartup", "^Camera average startup time: (\\d+) ms");
- map.put("FirstVideoStartup", "^First Video Startup: (\\d+)");
- map.put("VideoStartup", "^Video average startup time: (\\d+) ms");
- mTestCases.add(t);
-
- // Latency tests
- t = new TestInfo();
- t.mTestName = "latency";
- t.mClassName = "com.android.camera.stress.CameraLatency";
- t.mTestMetricsName = "CameraLatency";
- map = t.mPatternMap;
- map.put("AutoFocus", "^Avg AutoFocus = (\\d+)");
- map.put("ShutterLag", "^Avg mShutterLag = (\\d+)");
- map.put("Preview", "^Avg mShutterToPictureDisplayedTime = (\\d+)");
- map.put("RawPictureGeneration", "^Avg mPictureDisplayedToJpegCallbackTime = (\\d+)");
- map.put("GenTimeDiffOverJPEGAndRaw", "^Avg mJpegCallbackFinishTime = (\\d+)");
- map.put("FirstPreviewTime", "^Avg FirstPreviewTime = (\\d+)");
- mTestCases.add(t);
- }
-
- }
-
- @Override
- public void run(ITestInvocationListener listener) throws DeviceNotAvailableException {
- Assert.assertNotNull(mTestDevice);
- testInfoSetup();
- for (TestInfo test : mTestCases) {
- cleanTmpFiles();
- executeTest(test, listener);
- logOutputFile(test, listener);
- }
-
- cleanTmpFiles();
- }
-
- private void executeTest(TestInfo test, ITestInvocationListener listener)
- throws DeviceNotAvailableException {
- IRemoteAndroidTestRunner runner = new RemoteAndroidTestRunner(TEST_PACKAGE_NAME,
- mTestDevice.getIDevice());
- CollectingTestListener auxListener = new CollectingTestListener();
-
- runner.setClassName(test.mClassName);
- runner.setMaxTimeToOutputResponse(MAX_TEST_TIMEOUT, TimeUnit.MILLISECONDS);
- if (mGcam) {
- runner.setMethodName(test.mClassName, test.mTestName);
- }
- mTestDevice.runInstrumentationTests(runner, listener, auxListener);
-
- // Grab a bugreport if warranted
- if (auxListener.hasFailedTests()) {
- CLog.i("Grabbing bugreport after test '%s' finished with %d failures.",
- test.mTestName, auxListener.getNumAllFailedTests());
- InputStreamSource bugreport = mTestDevice.getBugreport();
- listener.testLog(String.format("bugreport-%s.txt", test.mTestName),
- LogDataType.BUGREPORT, bugreport);
- bugreport.cancel();
- }
- }
-
- /**
- * Clean up temp files from test runs
- * <p />
- * Note that all photos on the test device will be removed
- */
- private void cleanTmpFiles() throws DeviceNotAvailableException {
- String extStore = mTestDevice.getMountPoint(IDevice.MNT_EXTERNAL_STORAGE);
- //TODO: Remove the DCIM folder when the bug is fixed.
- mTestDevice.executeShellCommand(String.format("rm %s/DCIM/Camera/*", extStore));
- mTestDevice.executeShellCommand(String.format("rm %s/%s", extStore, mOutputPath));
- }
-
- /**
- * Pull the output file from the device, add it to the logs, and also parse out the relevant
- * test metrics and report them.
- */
- private void logOutputFile(TestInfo test, ITestInvocationListener listener)
- throws DeviceNotAvailableException {
- File outputFile = null;
- InputStreamSource outputSource = null;
- try {
- outputFile = mTestDevice.pullFileFromExternal(mOutputPath);
-
- if (outputFile == null) {
- return;
- }
-
- // Upload a verbatim copy of the output file
- CLog.d("Sending %d byte file %s into the logosphere!", outputFile.length(), outputFile);
- outputSource = new FileInputStreamSource(outputFile);
- listener.testLog(String.format("output-%s.txt", test.mTestName), LogDataType.TEXT,
- outputSource);
-
- // Parse the output file to upload aggregated metrics
- parseOutputFile(test, new FileInputStream(outputFile), listener);
- } catch (IOException e) {
- CLog.e("IOException while reading or parsing output file");
- CLog.e(e);
- } finally {
- FileUtil.deleteFile(outputFile);
- StreamUtil.cancel(outputSource);
- }
- }
-
- /**
- * Parse the relevant metrics from the Instrumentation test output file
- */
- private void parseOutputFile(TestInfo test, InputStream dataStream,
- ITestInvocationListener listener) {
- Map<String, String> runMetrics = new HashMap<>();
-
- // try to parse it
- String contents;
- try {
- contents = StreamUtil.getStringFromStream(dataStream);
- } catch (IOException e) {
- CLog.e("Got IOException during %s test processing", test.mTestName);
- CLog.e(e);
- return;
- }
-
- List<String> lines = Arrays.asList(contents.split("\n"));
- ListIterator<String> lineIter = lines.listIterator();
- String line;
- while (lineIter.hasNext()) {
- line = lineIter.next();
- List<List<String>> capture = new ArrayList<>(1);
- String key = test.mPatternMap.retrieve(capture, line);
- if (key != null) {
- CLog.d("Got %s key '%s' and captures '%s'", test.mTestName, key,
- capture.toString());
- } else if (line.isEmpty()) {
- // ignore
- continue;
- } else {
- CLog.d("Got unmatched line: %s", line);
- continue;
- }
-
- runMetrics.put(key, capture.get(0).get(0));
- }
-
- reportMetrics(listener, test, runMetrics);
- }
-
- /**
- * Report run metrics by creating an empty test run to stick them in
- * <p />
- * Exposed for unit testing
- */
- void reportMetrics(ITestInvocationListener listener, TestInfo test,
- Map<String, String> metrics) {
- // Create an empty testRun to report the parsed runMetrics
- CLog.d("About to report metrics for %s: %s", test.mTestMetricsName, metrics);
- listener.testRunStarted(test.mTestMetricsName, 0);
- listener.testRunEnded(0, metrics);
- }
-
- @Override
- public void setDevice(ITestDevice device) {
- mTestDevice = device;
- }
-
- @Override
- public ITestDevice getDevice() {
- return mTestDevice;
- }
-
- /**
- * A meta-test to ensure that bits of the CameraLatencyTest are working properly
- */
- public static class MetaTest extends TestCase {
- private CameraLatencyTest mTestInstance = null;
-
- private TestInfo mTestInfo = null;
-
- private TestInfo mReportedTestInfo = null;
- private Map<String, String> mReportedMetrics = null;
-
- private static String join(String... pieces) {
- StringBuilder sb = new StringBuilder();
- for (String piece : pieces) {
- sb.append(piece);
- sb.append("\n");
- }
- return sb.toString();
- }
-
- @Override
- public void setUp() throws Exception {
- mTestInstance = new CameraLatencyTest() {
- @Override
- void reportMetrics(ITestInvocationListener l, TestInfo test,
- Map<String, String> metrics) {
- mReportedTestInfo = test;
- mReportedMetrics = metrics;
- }
- };
-
- // Startup tests
- mTestInfo = new TestInfo();
- TestInfo t = mTestInfo; // convenience alias
- t.mTestName = "startup";
- t.mClassName = "com.android.camera.stress.CameraStartUp";
- t.mTestMetricsName = "camera_video_recorder_startup";
- RegexTrie<String> map = t.mPatternMap;
- map.put("FirstCameraStartup", "^First Camera Startup: (\\d+)");
- map.put("CameraStartup", "^Camera average startup time: (\\d+) ms");
- map.put("FirstVideoStartup", "^First Video Startup: (\\d+)");
- map.put("VideoStartup", "^Video average startup time: (\\d+) ms");
- map.put("FirstPreviewTime", "^Avg FirstPreviewTime = (\\d+)");
- }
-
- /**
- * Make sure that parsing works in the expected case
- */
- public void testParse() throws Exception {
- String output = join(
- "First Camera Startup: 1421", /* "FirstCameraStartup" key */
- "Camerastartup time: ",
- "Number of loop: 19",
- "Individual Camera Startup Time = 1920 ,1929 ,1924 ,1871 ,1840 ,1892 ,1813 " +
- ",1927 ,1856 ,1929 ,1911 ,1873 ,1381 ,1888 ,2405 ,1926 ,1840 ,2502 " +
- ",2357 ,",
- "",
- "Camera average startup time: 1946 ms", /* "CameraStartup" key */
- "",
- "First Video Startup: 2176", /* "FirstVideoStartup" key */
- "Camera Latency : ",
- "Number of loop: 20",
- "Avg AutoFocus = 2304",
- "Avg mShutterLag = 403",
- "Avg mShutterToPictureDisplayedTime = 369",
- "Avg mPictureDisplayedToJpegCallbackTime = 50",
- "Avg mJpegCallbackFinishTime = 1679",
- "Avg FirstPreviewTime = 1340");
-
- InputStream iStream = new ByteArrayInputStream(output.getBytes());
- mTestInstance.parseOutputFile(mTestInfo, iStream, null);
- assertEquals(mTestInfo, mReportedTestInfo);
- assertNotNull(mReportedMetrics);
- assertEquals(4, mReportedMetrics.size());
- assertEquals("1946", mReportedMetrics.get("CameraStartup"));
- assertEquals("2176", mReportedMetrics.get("FirstVideoStartup"));
- assertEquals("1421", mReportedMetrics.get("FirstCameraStartup"));
- assertEquals("1340", mReportedMetrics.get("FirstPreviewTime"));
- }
- }
-}
diff --git a/src/com/android/media/tests/CameraPerformanceTest.java b/src/com/android/media/tests/CameraPerformanceTest.java
deleted file mode 100644
index ebaad68..0000000
--- a/src/com/android/media/tests/CameraPerformanceTest.java
+++ /dev/null
@@ -1,672 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.media.tests;
-
-import com.android.ddmlib.testrunner.TestIdentifier;
-import com.android.tradefed.config.OptionClass;
-import com.android.tradefed.device.DeviceNotAvailableException;
-import com.android.tradefed.log.LogUtil.CLog;
-import com.android.tradefed.result.ITestInvocationListener;
-import com.android.tradefed.util.FileUtil;
-
-import com.google.common.collect.ImmutableMap;
-import com.google.common.collect.ImmutableMultimap;
-
-import org.json.JSONArray;
-import org.json.JSONException;
-import org.json.JSONObject;
-import org.xmlpull.v1.XmlPullParser;
-import org.xmlpull.v1.XmlPullParserException;
-import org.xmlpull.v1.XmlPullParserFactory;
-
-import java.io.ByteArrayInputStream;
-import java.io.File;
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-
-/**
- * This test invocation runs android.hardware.camera2.cts.PerformanceTest - Camera2 API use case
- * performance KPIs (Key Performance Indicator), such as camera open time, session creation time,
- * shutter lag etc. The KPI data will be parsed and reported.
- */
-@OptionClass(alias = "camera-framework")
-public class CameraPerformanceTest extends CameraTestBase {
-
- private static final String TEST_CAMERA_LAUNCH = "testCameraLaunch";
- private static final String TEST_SINGLE_CAPTURE = "testSingleCapture";
- private static final String TEST_REPROCESSING_LATENCY = "testReprocessingLatency";
- private static final String TEST_REPROCESSING_THROUGHPUT = "testReprocessingThroughput";
-
- // KPIs to be reported. The key is test methods and the value is KPIs in the method.
- private final ImmutableMultimap<String, String> mReportingKpis =
- new ImmutableMultimap.Builder<String, String>()
- .put(TEST_CAMERA_LAUNCH, "Camera launch time")
- .put(TEST_CAMERA_LAUNCH, "Camera start preview time")
- .put(TEST_SINGLE_CAPTURE, "Camera capture result latency")
- .put(TEST_REPROCESSING_LATENCY, "YUV reprocessing shot to shot latency")
- .put(TEST_REPROCESSING_LATENCY, "opaque reprocessing shot to shot latency")
- .put(TEST_REPROCESSING_THROUGHPUT, "YUV reprocessing capture latency")
- .put(TEST_REPROCESSING_THROUGHPUT, "opaque reprocessing capture latency")
- .build();
-
- // JSON format keymap, key is test method name and the value is stream name in Json file
- private static final ImmutableMap<String, String> METHOD_JSON_KEY_MAP =
- new ImmutableMap.Builder<String, String>()
- .put(TEST_CAMERA_LAUNCH, "test_camera_launch")
- .put(TEST_SINGLE_CAPTURE, "test_single_capture")
- .put(TEST_REPROCESSING_LATENCY, "test_reprocessing_latency")
- .put(TEST_REPROCESSING_THROUGHPUT, "test_reprocessing_throughput")
- .build();
-
- private <E extends Number> double getAverage(List<E> list) {
- double sum = 0;
- int size = list.size();
- for (E num : list) {
- sum += num.doubleValue();
- }
- if (size == 0) {
- return 0.0;
- }
- return (sum / size);
- }
-
- public CameraPerformanceTest() {
- // Set up the default test info. But this is subject to be overwritten by options passed
- // from commands.
- setTestPackage("android.camera.cts");
- setTestClass("android.hardware.camera2.cts.PerformanceTest");
- setTestRunner("android.support.test.runner.AndroidJUnitRunner");
- setRuKey("camera_framework_performance");
- setTestTimeoutMs(10 * 60 * 1000); // 10 mins
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public void run(ITestInvocationListener listener) throws DeviceNotAvailableException {
- runInstrumentationTest(listener, new CollectingListener(listener));
- }
-
- /**
- * A listener to collect the output from test run and fatal errors
- */
- private class CollectingListener extends DefaultCollectingListener {
-
- public CollectingListener(ITestInvocationListener listener) {
- super(listener);
- }
-
- @Override
- public void handleMetricsOnTestEnded(TestIdentifier test, Map<String, String> testMetrics) {
- // Pass the test name for a key in the aggregated metrics, because
- // it is used to generate the key of the final metrics to post at the end of test run.
- for (Map.Entry<String, String> metric : testMetrics.entrySet()) {
- getAggregatedMetrics().put(test.getTestName(), metric.getValue());
- }
- }
-
- @Override
- public void handleTestRunEnded(
- ITestInvocationListener listener,
- long elapsedTime,
- Map<String, String> runMetrics) {
- // Report metrics at the end of test run.
- Map<String, String> result = parseResult(getAggregatedMetrics());
- listener.testRunEnded(getTestDurationMs(), result);
- }
- }
-
- /**
- * Parse Camera Performance KPIs results and then put them all together to post the final
- * report.
- *
- * @return a {@link HashMap} that contains pairs of kpiName and kpiValue
- */
- private Map<String, String> parseResult(Map<String, String> metrics) {
-
- // if json report exists, return the parse results
- CtsJsonResultParser ctsJsonResultParser = new CtsJsonResultParser();
-
- if (ctsJsonResultParser.isJsonFileExist()) {
- return ctsJsonResultParser.parse();
- }
-
- Map<String, String> resultsAll = new HashMap<String, String>();
-
- CtsResultParserBase parser;
- for (Map.Entry<String, String> metric : metrics.entrySet()) {
- String testMethod = metric.getKey();
- String testResult = metric.getValue();
- CLog.d("test name %s", testMethod);
- CLog.d("test result %s", testResult);
- // Probe which result parser should be used.
- if (shouldUseCtsXmlResultParser(testResult)) {
- parser = new CtsXmlResultParser();
- } else {
- parser = new CtsDelimitedResultParser();
- }
-
- // Get pairs of { KPI name, KPI value } from stdout that each test outputs.
- // Assuming that a device has both the front and back cameras, parser will return
- // 2 KPIs in HashMap. For an example of testCameraLaunch,
- // {
- // ("Camera 0 Camera launch time", "379.2"),
- // ("Camera 1 Camera launch time", "272.8"),
- // }
- Map<String, String> testKpis = parser.parse(testResult, testMethod);
- for (String k : testKpis.keySet()) {
- if (resultsAll.containsKey(k)) {
- throw new RuntimeException(
- String.format("KPI name (%s) conflicts with the existing names.", k));
- }
- }
- parser.clear();
-
- // Put each result together to post the final result
- resultsAll.putAll(testKpis);
- }
- return resultsAll;
- }
-
- public boolean shouldUseCtsXmlResultParser(String result) {
- final String XML_DECLARATION = "<?xml";
- return (result.startsWith(XML_DECLARATION)
- || result.startsWith(XML_DECLARATION.toUpperCase()));
- }
-
- /** Data class of CTS test results for Camera framework performance test */
- public static class CtsMetric {
- String testMethod; // "testSingleCapture"
- String source; // "android.hardware.camera2.cts.PerformanceTest#testSingleCapture:327"
- // or "testSingleCapture" (just test method name)
- String message; // "Camera 0: Camera capture latency"
- String type; // "lower_better"
- String unit; // "ms"
- String value; // "691.0" (is an average of 736.0 688.0 679.0 667.0 686.0)
- String schemaKey; // RU schema key = message (+ testMethodName if needed), derived
-
- // eg. "android.hardware.camera2.cts.PerformanceTest#testSingleCapture:327"
- public static final Pattern SOURCE_REGEX =
- Pattern.compile("^(?<package>[a-zA-Z\\d\\._$]+)#(?<method>[a-zA-Z\\d_$]+)(:\\d+)?");
- // eg. "Camera 0: Camera capture latency"
- public static final Pattern MESSAGE_REGEX =
- Pattern.compile("^Camera\\s+(?<cameraId>\\d+):\\s+(?<kpiName>.*)");
-
- CtsMetric(
- String testMethod,
- String source,
- String message,
- String type,
- String unit,
- String value) {
- this.testMethod = testMethod;
- this.source = source;
- this.message = message;
- this.type = type;
- this.unit = unit;
- this.value = value;
- this.schemaKey = getRuSchemaKeyName(message);
- }
-
- public boolean matches(String testMethod, String kpiName) {
- return (this.testMethod.equals(testMethod) && this.message.endsWith(kpiName));
- }
-
- public String getRuSchemaKeyName(String message) {
- // Note 1: The key shouldn't contain ":" for side by side report.
- String schemaKey = message.replace(":", "");
- // Note 2: Two tests testReprocessingLatency & testReprocessingThroughput have the
- // same metric names to report results. To make the report key name distinct,
- // the test name is added as prefix for these tests for them.
- final String[] TEST_NAMES_AS_PREFIX = {
- "testReprocessingLatency", "testReprocessingThroughput"
- };
- for (String testName : TEST_NAMES_AS_PREFIX) {
- if (testMethod.endsWith(testName)) {
- schemaKey = String.format("%s_%s", testName, schemaKey);
- break;
- }
- }
- return schemaKey;
- }
-
- public String getTestMethodNameInSource(String source) {
- Matcher m = SOURCE_REGEX.matcher(source);
- if (!m.matches()) {
- return source;
- }
- return m.group("method");
- }
- }
-
- /**
- * Base class of CTS test result parser. This is inherited to two derived parsers,
- * {@link CtsDelimitedResultParser} for legacy delimiter separated format and
- * {@link CtsXmlResultParser} for XML typed format introduced since NYC.
- */
- public abstract class CtsResultParserBase {
-
- protected CtsMetric mSummary;
- protected List<CtsMetric> mDetails = new ArrayList<>();
-
- /**
- * Parse Camera Performance KPIs result first, then leave the only KPIs that matter.
- *
- * @param result String to be parsed
- * @param testMethod test method name used to leave the only metric that matters
- * @return a {@link HashMap} that contains kpiName and kpiValue
- */
- public abstract Map<String, String> parse(String result, String testMethod);
-
- protected Map<String, String> filter(List<CtsMetric> metrics, String testMethod) {
- Map<String, String> filtered = new HashMap<String, String>();
- for (CtsMetric metric : metrics) {
- for (String kpiName : mReportingKpis.get(testMethod)) {
- // Post the data only when it matches with the given methods and KPI names.
- if (metric.matches(testMethod, kpiName)) {
- filtered.put(metric.schemaKey, metric.value);
- }
- }
- }
- return filtered;
- }
-
- protected void setSummary(CtsMetric summary) {
- mSummary = summary;
- }
-
- protected void addDetail(CtsMetric detail) {
- mDetails.add(detail);
- }
-
- protected List<CtsMetric> getDetails() {
- return mDetails;
- }
-
- void clear() {
- mSummary = null;
- mDetails.clear();
- }
- }
-
- /**
- * Parses the camera performance test generated by the underlying instrumentation test and
- * returns it to test runner for later reporting.
- *
- * <p>TODO(liuyg): Rename this class to not reference CTS.
- *
- * <p>Format: (summary message)| |(type)|(unit)|(value) ++++
- * (source)|(message)|(type)|(unit)|(value)... +++ ...
- *
- * <p>Example: Camera launch average time for Camera 1| |lower_better|ms|586.6++++
- * android.hardware.camera2.cts.PerformanceTest#testCameraLaunch:171| Camera 0: Camera open
- * time|lower_better|ms|74.0 100.0 70.0 67.0 82.0 +++
- * android.hardware.camera2.cts.PerformanceTest#testCameraLaunch:171| Camera 0: Camera configure
- * stream time|lower_better|ms|9.0 5.0 5.0 8.0 5.0 ...
- *
- * <p>See also com.android.cts.util.ReportLog for the format detail.
- */
- public class CtsDelimitedResultParser extends CtsResultParserBase {
- private static final String LOG_SEPARATOR = "\\+\\+\\+";
- private static final String SUMMARY_SEPARATOR = "\\+\\+\\+\\+";
- private final Pattern mSummaryRegex =
- Pattern.compile(
- "^(?<message>[^|]+)\\| \\|(?<type>[^|]+)\\|(?<unit>[^|]+)\\|(?<value>[0-9 .]+)");
- private final Pattern mDetailRegex =
- Pattern.compile(
- "^(?<source>[^|]+)\\|(?<message>[^|]+)\\|(?<type>[^|]+)\\|(?<unit>[^|]+)\\|"
- + "(?<values>[0-9 .]+)");
-
- @Override
- public Map<String, String> parse(String result, String testMethod) {
- parseToCtsMetrics(result, testMethod);
- parseToCtsMetrics(result, testMethod);
- return filter(getDetails(), testMethod);
- }
-
- void parseToCtsMetrics(String result, String testMethod) {
- // Split summary and KPIs from stdout passes as parameter.
- String[] output = result.split(SUMMARY_SEPARATOR);
- if (output.length != 2) {
- throw new RuntimeException("Value not in the correct format");
- }
- Matcher summaryMatcher = mSummaryRegex.matcher(output[0].trim());
-
- // Parse summary.
- // Example: "Camera launch average time for Camera 1| |lower_better|ms|586.6++++"
- if (summaryMatcher.matches()) {
- setSummary(
- new CtsMetric(
- testMethod,
- null,
- summaryMatcher.group("message"),
- summaryMatcher.group("type"),
- summaryMatcher.group("unit"),
- summaryMatcher.group("value")));
- } else {
- // Fall through since the summary is not posted as results.
- CLog.w("Summary not in the correct format");
- }
-
- // Parse KPIs.
- // Example: "android.hardware.camera2.cts.PerformanceTest#testCameraLaunch:171|Camera 0:
- // Camera open time|lower_better|ms|74.0 100.0 70.0 67.0 82.0 +++"
- String[] details = output[1].split(LOG_SEPARATOR);
- for (String detail : details) {
- Matcher detailMatcher = mDetailRegex.matcher(detail.trim());
- if (detailMatcher.matches()) {
- // get average of kpi values
- List<Double> values = new ArrayList<>();
- for (String value : detailMatcher.group("values").split("\\s+")) {
- values.add(Double.parseDouble(value));
- }
- String kpiValue = String.format("%.1f", getAverage(values));
- addDetail(
- new CtsMetric(
- testMethod,
- detailMatcher.group("source"),
- detailMatcher.group("message"),
- detailMatcher.group("type"),
- detailMatcher.group("unit"),
- kpiValue));
- } else {
- throw new RuntimeException("KPI not in the correct format");
- }
- }
- }
- }
-
- /**
- * Parses the CTS test results in a XML format introduced since NYC.
- * Format:
- * <Summary>
- * <Metric source="android.hardware.camera2.cts.PerformanceTest#testSingleCapture:327"
- * message="Camera capture result average latency for all cameras "
- * score_type="lower_better"
- * score_unit="ms"
- * <Value>353.9</Value>
- * </Metric>
- * </Summary>
- * <Detail>
- * <Metric source="android.hardware.camera2.cts.PerformanceTest#testSingleCapture:303"
- * message="Camera 0: Camera capture latency"
- * score_type="lower_better"
- * score_unit="ms">
- * <Value>335.0</Value>
- * <Value>302.0</Value>
- * <Value>316.0</Value>
- * </Metric>
- * </Detail>
- * }
- * See also com.android.compatibility.common.util.ReportLog for the format detail.
- */
- public class CtsXmlResultParser extends CtsResultParserBase {
- private static final String ENCODING = "UTF-8";
- // XML constants
- private static final String DETAIL_TAG = "Detail";
- private static final String METRIC_TAG = "Metric";
- private static final String MESSAGE_ATTR = "message";
- private static final String SCORETYPE_ATTR = "score_type";
- private static final String SCOREUNIT_ATTR = "score_unit";
- private static final String SOURCE_ATTR = "source";
- private static final String SUMMARY_TAG = "Summary";
- private static final String VALUE_TAG = "Value";
- private String mTestMethod;
-
- @Override
- public Map<String, String> parse(String result, String testMethod) {
- try {
- mTestMethod = testMethod;
- XmlPullParserFactory factory = XmlPullParserFactory.newInstance();
- XmlPullParser parser = factory.newPullParser();
- parser.setInput(new ByteArrayInputStream(result.getBytes(ENCODING)), ENCODING);
- parser.nextTag();
- parse(parser);
- return filter(getDetails(), testMethod);
- } catch (XmlPullParserException | IOException e) {
- throw new RuntimeException("Failed to parse results in XML.", e);
- }
- }
-
- /**
- * Parses a {@link CtsMetric} from the given XML parser.
- *
- * @param parser
- * @throws IOException
- * @throws XmlPullParserException
- */
- private void parse(XmlPullParser parser) throws XmlPullParserException, IOException {
- parser.require(XmlPullParser.START_TAG, null, SUMMARY_TAG);
- parser.nextTag();
- setSummary(parseToCtsMetrics(parser));
- parser.nextTag();
- parser.require(XmlPullParser.END_TAG, null, SUMMARY_TAG);
- parser.nextTag();
- if (parser.getName().equals(DETAIL_TAG)) {
- while (parser.nextTag() == XmlPullParser.START_TAG) {
- addDetail(parseToCtsMetrics(parser));
- }
- parser.require(XmlPullParser.END_TAG, null, DETAIL_TAG);
- }
- }
-
- CtsMetric parseToCtsMetrics(XmlPullParser parser)
- throws IOException, XmlPullParserException {
- parser.require(XmlPullParser.START_TAG, null, METRIC_TAG);
- String source = parser.getAttributeValue(null, SOURCE_ATTR);
- String message = parser.getAttributeValue(null, MESSAGE_ATTR);
- String type = parser.getAttributeValue(null, SCORETYPE_ATTR);
- String unit = parser.getAttributeValue(null, SCOREUNIT_ATTR);
- List<Double> values = new ArrayList<>();
- while (parser.nextTag() == XmlPullParser.START_TAG) {
- parser.require(XmlPullParser.START_TAG, null, VALUE_TAG);
- values.add(Double.parseDouble(parser.nextText()));
- parser.require(XmlPullParser.END_TAG, null, VALUE_TAG);
- }
- String kpiValue = String.format("%.1f", getAverage(values));
- parser.require(XmlPullParser.END_TAG, null, METRIC_TAG);
- return new CtsMetric(mTestMethod, source, message, type, unit, kpiValue);
- }
- }
-
- /*
- * Parse the Json report from the Json String
- * "test_single_capture":
- * {"camera_id":"0","camera_capture_latency":[264.0,229.0,229.0,237.0,234.0],
- * "camera_capture_result_latency":[230.0,197.0,196.0,204.0,202.0]},"
- * "test_reprocessing_latency":
- * {"camera_id":"0","format":35,"reprocess_type":"YUV reprocessing",
- * "capture_message":"shot to shot latency","latency":[102.0,101.0,99.0,99.0,100.0,101.0],
- * "camera_reprocessing_shot_to_shot_average_latency":100.33333333333333},
- *
- * TODO: move this to a seperate class
- */
- public class CtsJsonResultParser {
-
- // report json file set in
- // cts/tools/cts-tradefed/res/config/cts-preconditions.xml
- private static final String JSON_RESULT_FILE =
- "/sdcard/report-log-files/CtsCameraTestCases.reportlog.json";
- private static final String CAMERA_ID_KEY = "camera_id";
- private static final String AVERAGE_LATENCY_KEY = "average_latency";
- private static final String REPROCESS_TYPE_KEY = "reprocess_type";
- private static final String CAPTURE_MESSAGE_KEY = "capture_message";
- private static final String LATENCY_KEY = "latency";
-
- public Map<String, String> parse() {
-
- Map<String, String> metrics = new HashMap<>();
-
- String jsonString = getFormatedJsonReportFromFile();
- if (null == jsonString) {
- throw new RuntimeException("Get null json report string.");
- }
-
- Map<String, List<Double>> metricsData = new HashMap<>();
-
- try {
- JSONObject jsonObject = new JSONObject(jsonString);
-
- for (String testMethod : METHOD_JSON_KEY_MAP.keySet()) {
-
- JSONArray jsonArray =
- (JSONArray) jsonObject.get(METHOD_JSON_KEY_MAP.get(testMethod));
-
- switch (testMethod) {
- case TEST_REPROCESSING_THROUGHPUT:
- case TEST_REPROCESSING_LATENCY:
- for (int i = 0; i < jsonArray.length(); i++) {
- JSONObject element = jsonArray.getJSONObject(i);
-
- // create a kpiKey from camera id,
- // reprocess type and capture message
- String cameraId = element.getString(CAMERA_ID_KEY);
- String reprocessType = element.getString(REPROCESS_TYPE_KEY);
- String captureMessage = element.getString(CAPTURE_MESSAGE_KEY);
- String kpiKey =
- String.format(
- "%s_Camera %s %s %s",
- testMethod,
- cameraId,
- reprocessType,
- captureMessage);
-
- // read the data array from json object
- JSONArray jsonDataArray = element.getJSONArray(LATENCY_KEY);
- if (!metricsData.containsKey(kpiKey)) {
- List<Double> list = new ArrayList<>();
- metricsData.put(kpiKey, list);
- }
- for (int j = 0; j < jsonDataArray.length(); j++) {
- metricsData.get(kpiKey).add(jsonDataArray.getDouble(j));
- }
- }
- break;
- case TEST_SINGLE_CAPTURE:
- case TEST_CAMERA_LAUNCH:
- for (int i = 0; i < jsonArray.length(); i++) {
- JSONObject element = jsonArray.getJSONObject(i);
-
- String cameraid = element.getString(CAMERA_ID_KEY);
- for (String kpiName : mReportingKpis.get(testMethod)) {
-
- // the json key is all lower case
- String jsonKey = kpiName.toLowerCase().replace(" ", "_");
- String kpiKey =
- String.format("Camera %s %s", cameraid, kpiName);
- if (!metricsData.containsKey(kpiKey)) {
- List<Double> list = new ArrayList<>();
- metricsData.put(kpiKey, list);
- }
- JSONArray jsonDataArray = element.getJSONArray(jsonKey);
- for (int j = 0; j < jsonDataArray.length(); j++) {
- metricsData.get(kpiKey).add(jsonDataArray.getDouble(j));
- }
- }
- }
- break;
- default:
- break;
- }
- }
- } catch (JSONException e) {
- CLog.w("JSONException: %s in string %s", e.getMessage(), jsonString);
- }
-
- // take the average of all data for reporting
- for (String kpiKey : metricsData.keySet()) {
- String kpiValue = String.format("%.1f", getAverage(metricsData.get(kpiKey)));
- metrics.put(kpiKey, kpiValue);
- }
- return metrics;
- }
-
- public boolean isJsonFileExist() {
- try {
- return getDevice().doesFileExist(JSON_RESULT_FILE);
- } catch (DeviceNotAvailableException e) {
- throw new RuntimeException("Failed to check json report file on device.", e);
- }
- }
-
- /*
- * read json report file on the device
- */
- private String getFormatedJsonReportFromFile() {
- String jsonString = null;
- try {
- // pull the json report file from device
- File outputFile = FileUtil.createTempFile("json", ".txt");
- getDevice().pullFile(JSON_RESULT_FILE, outputFile);
- jsonString = reformatJsonString(FileUtil.readStringFromFile(outputFile));
- } catch (IOException e) {
- CLog.w("Couldn't parse the output json log file: ", e);
- } catch (DeviceNotAvailableException e) {
- CLog.w("Could not pull file: %s, error: %s", JSON_RESULT_FILE, e);
- }
- return jsonString;
- }
-
- // Reformat the json file to remove duplicate keys
- private String reformatJsonString(String jsonString) {
-
- final String TEST_METRICS_PATTERN = "\\\"([a-z0-9_]*)\\\":(\\{[^{}]*\\})";
- StringBuilder newJsonBuilder = new StringBuilder();
- // Create map of stream names and json objects.
- HashMap<String, List<String>> jsonMap = new HashMap<>();
- Pattern p = Pattern.compile(TEST_METRICS_PATTERN);
- Matcher m = p.matcher(jsonString);
- while (m.find()) {
- String key = m.group(1);
- String value = m.group(2);
- if (!jsonMap.containsKey(key)) {
- jsonMap.put(key, new ArrayList<String>());
- }
- jsonMap.get(key).add(value);
- }
- // Rewrite json string as arrays.
- newJsonBuilder.append("{");
- boolean firstLine = true;
- for (String key : jsonMap.keySet()) {
- if (!firstLine) {
- newJsonBuilder.append(",");
- } else {
- firstLine = false;
- }
- newJsonBuilder.append("\"").append(key).append("\":[");
- boolean firstValue = true;
- for (String stream : jsonMap.get(key)) {
- if (!firstValue) {
- newJsonBuilder.append(",");
- } else {
- firstValue = false;
- }
- newJsonBuilder.append(stream);
- }
- newJsonBuilder.append("]");
- }
- newJsonBuilder.append("}");
- return newJsonBuilder.toString();
- }
- }
-}
diff --git a/src/com/android/media/tests/CameraSettingsTest.java b/src/com/android/media/tests/CameraSettingsTest.java
deleted file mode 100644
index d5fe0dd..0000000
--- a/src/com/android/media/tests/CameraSettingsTest.java
+++ /dev/null
@@ -1,222 +0,0 @@
-/*
- * Copyright (C) 2012 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.media.tests;
-
-import com.android.ddmlib.IDevice;
-import com.android.ddmlib.testrunner.IRemoteAndroidTestRunner;
-import com.android.ddmlib.testrunner.RemoteAndroidTestRunner;
-import com.android.tradefed.config.Option;
-import com.android.tradefed.device.DeviceNotAvailableException;
-import com.android.tradefed.device.ITestDevice;
-import com.android.tradefed.log.LogUtil.CLog;
-import com.android.tradefed.result.BugreportCollector;
-import com.android.tradefed.result.ITestInvocationListener;
-import com.android.tradefed.result.InputStreamSource;
-import com.android.tradefed.result.LogDataType;
-import com.android.tradefed.testtype.IDeviceTest;
-import com.android.tradefed.testtype.IRemoteTest;
-import com.android.tradefed.util.StreamUtil;
-
-import org.junit.Assert;
-
-import java.io.BufferedReader;
-import java.io.File;
-import java.io.FileReader;
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.ListIterator;
-import java.util.Map;
-import java.util.concurrent.TimeUnit;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-
-/**
- * Camera zoom stress test that increments the camera's zoom level across the
- * entire range [min, max], taking a picture at each level.
- */
-public class CameraSettingsTest implements IDeviceTest, IRemoteTest {
-
- private static final String ZOOM_STANZA = "testStressCameraZoom";
- private static final String SCENE_MODES_STANZA = "testStressCameraSceneModes";
- private static final Pattern EXPECTED_LOOP_COUNT_PATTERN =
- Pattern.compile("(Total number of loops:)(\\s*)(\\d+)");
- private static final Pattern ACTUAL_LOOP_COUNT_PATTERN =
- Pattern.compile("(No of loop:)(.*,\\s)(\\d+)$");
-
- private static final String TEST_CLASS_NAME =
- "com.android.mediaframeworktest.stress.CameraStressTest";
- private static final String TEST_PACKAGE_NAME = "com.android.mediaframeworktest";
- private static final String TEST_RUNNER_NAME =
- "com.android.mediaframeworktest.CameraStressTestRunner";
- private static final String TEST_RU = "CameraApplicationStress";
-
- private final String mOutputPath = "cameraStressOutput.txt";
- private static final int MAX_TIME_OUT = 90 * 60 * 1000; //90 mins
-
- @Option(name="testMethodName", description="Used to specify a specific test method to run")
- private String mTestMethodName = null;
-
- ITestDevice mTestDevice = null;
-
- /**
- * {@inheritDoc}
- */
- @Override
- public void run(ITestInvocationListener listener) throws DeviceNotAvailableException {
- Assert.assertNotNull(mTestDevice);
-
- IRemoteAndroidTestRunner runner = new RemoteAndroidTestRunner(TEST_PACKAGE_NAME,
- TEST_RUNNER_NAME, mTestDevice.getIDevice());
- runner.setClassName(TEST_CLASS_NAME);
-
- if (mTestMethodName != null) {
- runner.setMethodName(TEST_CLASS_NAME, mTestMethodName);
- }
- runner.setMaxTimeToOutputResponse(MAX_TIME_OUT, TimeUnit.MILLISECONDS);
-
- BugreportCollector bugListener = new BugreportCollector(listener, mTestDevice);
- bugListener.addPredicate(BugreportCollector.AFTER_FAILED_TESTCASES);
- bugListener.setDescriptiveName(this.getClass().getName());
- Assert.assertTrue(mTestDevice.runInstrumentationTests(runner, bugListener));
-
- Map<String, String> metrics = parseOutputFile();
- reportMetrics(bugListener, TEST_RU, metrics);
- cleanupDevice();
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public void setDevice(ITestDevice device) {
- mTestDevice = device;
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public ITestDevice getDevice() {
- return mTestDevice;
- }
-
- /**
- * Wipes the device's external memory of test collateral from prior runs.
- *
- * @throws DeviceNotAvailableException If the device is unavailable or
- * something happened while deleting files
- */
- private void cleanupDevice() throws DeviceNotAvailableException {
- String extStore = mTestDevice.getMountPoint(IDevice.MNT_EXTERNAL_STORAGE);
- mTestDevice.executeShellCommand(String.format("rm %s/%s", extStore, mOutputPath));
- }
-
- /**
- * Parses the output file generated by the underlying instrumentation test
- * and returns it to the main driver for later reporting.
- *
- * @return The {@link Map} that contains metrics for the test.
- * @throws DeviceNotAvailableException If the device is unavailable or
- * something happened while deleting files
- */
- private Map<String, String> parseOutputFile() throws DeviceNotAvailableException {
- File outputFile = null;
- BufferedReader reader = null;
- ArrayList<String> lines = new ArrayList<String>();
- String line = null;
- String key = null;
- Integer expectedCount = null;
- Integer actualCount = null;
- ListIterator<String> listIterator = null;
- Map<String, String> metrics = new HashMap<String, String>();
-
- // Read in data
- try {
- outputFile = mTestDevice.pullFileFromExternal(mOutputPath);
- reader = new BufferedReader(new FileReader(outputFile));
-
- while ((line = reader.readLine()) != null) {
- if (!line.isEmpty()) {
- lines.add(line);
- }
- }
- } catch (IOException e) {
- CLog.e(String.format("IOException reading from file: %s", e.toString()));
- } finally {
- StreamUtil.close(reader);
- }
-
- // Output file looks like:
- // Test name:
- // Total number of loops: 123
- // No of loop: 0, 1, 2, 3, ..., 122 (0 based)
- // Note that the actual count should be +1 as the # of loop is 0 based.
- listIterator = lines.listIterator();
-
- while (listIterator.hasNext()) {
- line = listIterator.next();
- CLog.d(String.format("Parsing line: \"%s\"", line));
-
- if (ZOOM_STANZA.equals(line)) {
- key = "CameraZoom";
- } else if (SCENE_MODES_STANZA.equals(line)) {
- key = "CameraSceneMode";
- }
-
- Matcher expectedMatcher = EXPECTED_LOOP_COUNT_PATTERN.matcher(line);
- if (expectedMatcher.matches()) {
- expectedCount = Integer.valueOf(expectedMatcher.group(3));
- CLog.d(String.format("Found expected count for key \"%s\": %s",
- key, expectedCount));
- }
-
- Matcher actualMatcher = ACTUAL_LOOP_COUNT_PATTERN.matcher(line);
- if (actualMatcher.matches()) {
- actualCount = 1 + Integer.valueOf(actualMatcher.group(3));
- CLog.d(String.format("Found actual count for key \"%s\": %s", key, actualCount));
- }
-
- if ((key != null) && (expectedCount != null) && (actualCount != null)) {
- metrics.put(key, String.format("%d", actualCount));
- key = null;
- expectedCount = null;
- actualCount = null;
- }
- }
-
- return metrics;
- }
-
- /**
- * Report run metrics by creating an empty test run to stick them in.
- *
- * @param listener The {@link ITestInvocationListener} of test results
- * @param runName The test name
- * @param metrics The {@link Map} that contains metrics for the given test
- */
- private void reportMetrics(ITestInvocationListener listener, String runName,
- Map<String, String> metrics) {
- InputStreamSource bugreport = mTestDevice.getBugreport();
- listener.testLog("bugreport", LogDataType.BUGREPORT, bugreport);
- bugreport.cancel();
-
- CLog.d(String.format("About to report metrics: %s", metrics));
- listener.testRunStarted(runName, 0);
- listener.testRunEnded(0, metrics);
- }
-}
diff --git a/src/com/android/media/tests/CameraShotLatencyTest.java b/src/com/android/media/tests/CameraShotLatencyTest.java
deleted file mode 100644
index f72ded7..0000000
--- a/src/com/android/media/tests/CameraShotLatencyTest.java
+++ /dev/null
@@ -1,92 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.media.tests;
-
-import com.android.ddmlib.testrunner.TestIdentifier;
-import com.android.tradefed.config.OptionClass;
-import com.android.tradefed.device.DeviceNotAvailableException;
-import com.android.tradefed.log.LogUtil.CLog;
-import com.android.tradefed.result.ITestInvocationListener;
-
-import java.util.HashMap;
-import java.util.Map;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-
-/**
- * Camera shot latency test
- *
- * Runs Camera device performance test to measure time from taking a shot to saving a file on disk
- * and time from shutter to shutter in fully saturated case.
- */
-@OptionClass(alias = "camera-shot-latency")
-public class CameraShotLatencyTest extends CameraTestBase {
-
- private static final Pattern STATS_REGEX = Pattern.compile(
- "^(?<average>[0-9.]+)\\|(?<values>[0-9 .-]+)");
-
- public CameraShotLatencyTest() {
- setTestPackage("com.google.android.camera");
- setTestClass("com.android.camera.latency.CameraShotLatencyTest");
- setTestRunner("android.test.InstrumentationTestRunner");
- setRuKey("CameraShotLatency");
- setTestTimeoutMs(60 * 60 * 1000); // 1 hour
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public void run(ITestInvocationListener listener) throws DeviceNotAvailableException {
- runInstrumentationTest(listener, new CollectingListener(listener));
- }
-
- /**
- * A listener to collect the output from test run and fatal errors
- */
- private class CollectingListener extends DefaultCollectingListener {
-
- public CollectingListener(ITestInvocationListener listener) {
- super(listener);
- }
-
- @Override
- public void handleMetricsOnTestEnded(TestIdentifier test, Map<String, String> testMetrics) {
- // Test metrics accumulated will be posted at the end of test run.
- getAggregatedMetrics().putAll(parseResults(test.getTestName(), testMetrics));
- }
-
- public Map<String, String> parseResults(String testName, Map<String, String> testMetrics) {
- // Parse shot latency stats from the instrumentation result.
- // Format : <metric_key>=<average_of_latency>|<raw_data>
- // Example:
- // ElapsedTimeMs=1805|1725 1747 ... 2078
- Map<String, String> parsed = new HashMap<String, String>();
- for (Map.Entry<String, String> metric : testMetrics.entrySet()) {
- Matcher matcher = STATS_REGEX.matcher(metric.getValue());
- if (matcher.matches()) {
- // Key name consists of a pair of test name and metric name.
- String keyName = String.format("%s_%s", testName, metric.getKey());
- parsed.put(keyName, matcher.group("average"));
- } else {
- CLog.w(String.format("Stats not in correct format: %s", metric.getValue()));
- }
- }
- return parsed;
- }
- }
-}
diff --git a/src/com/android/media/tests/CameraShotToShotLatencyTest.java b/src/com/android/media/tests/CameraShotToShotLatencyTest.java
deleted file mode 100644
index c30d5c0..0000000
--- a/src/com/android/media/tests/CameraShotToShotLatencyTest.java
+++ /dev/null
@@ -1,184 +0,0 @@
-/*
- * Copyright (C) 2012 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.media.tests;
-
-import com.android.ddmlib.IDevice;
-import com.android.ddmlib.testrunner.IRemoteAndroidTestRunner;
-import com.android.ddmlib.testrunner.RemoteAndroidTestRunner;
-import com.android.tradefed.device.DeviceNotAvailableException;
-import com.android.tradefed.device.ITestDevice;
-import com.android.tradefed.log.LogUtil.CLog;
-import com.android.tradefed.result.BugreportCollector;
-import com.android.tradefed.result.ITestInvocationListener;
-import com.android.tradefed.result.InputStreamSource;
-import com.android.tradefed.result.LogDataType;
-import com.android.tradefed.testtype.IDeviceTest;
-import com.android.tradefed.testtype.IRemoteTest;
-
-import org.junit.Assert;
-
-import java.io.BufferedReader;
-import java.io.File;
-import java.io.FileReader;
-import java.io.IOException;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-
-public class CameraShotToShotLatencyTest implements IDeviceTest, IRemoteTest {
-
- private static final Pattern MEAN_PATTERN =
- Pattern.compile("(Shot to shot latency - mean:)(\\s*)(\\d+\\.\\d*)");
- private static final Pattern STANDARD_DEVIATION_PATTERN =
- Pattern.compile("(Shot to shot latency - standard deviation:)(\\s*)(\\d+\\.\\d*)");
-
- private static final String TEST_CLASS_NAME = "com.android.camera.stress.ShotToShotLatency";
- private static final String TEST_PACKAGE_NAME = "com.google.android.camera.tests";
- private static final String TEST_RUNNER_NAME = "android.test.InstrumentationTestRunner";
-
- private static final String LATENCY_KEY_MEAN = "Shot2ShotLatencyMean";
- private static final String LATENCY_KEY_SD = "Shot2ShotLatencySD";
- private static final String TEST_RU = "CameraLatency";
-
- private final String mOutputPath = "mediaStressOut.txt";
- ITestDevice mTestDevice = null;
-
- /**
- * {@inheritDoc}
- */
- @Override
- public void run(ITestInvocationListener listener) throws DeviceNotAvailableException {
- Assert.assertNotNull(mTestDevice);
-
- IRemoteAndroidTestRunner runner = new RemoteAndroidTestRunner(TEST_PACKAGE_NAME,
- TEST_RUNNER_NAME, mTestDevice.getIDevice());
- runner.setClassName(TEST_CLASS_NAME);
-
- BugreportCollector bugListener = new BugreportCollector(listener, mTestDevice);
- bugListener.addPredicate(BugreportCollector.AFTER_FAILED_TESTCASES);
- bugListener.setDescriptiveName(this.getClass().getName());
- Assert.assertTrue(mTestDevice.runInstrumentationTests(runner, bugListener));
-
- Map<String, String> metrics = parseOutputFile();
- reportMetrics(bugListener, TEST_RU, metrics);
- cleanupDevice();
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public void setDevice(ITestDevice device) {
- mTestDevice = device;
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public ITestDevice getDevice() {
- return mTestDevice;
- }
-
- /**
- * Wipes the device's external memory of test collateral from prior runs.
- * Note that all photos on the test device will be removed.
- * @throws DeviceNotAvailableException If the device is unavailable or
- * something happened while deleting files
- */
- private void cleanupDevice() throws DeviceNotAvailableException {
- String extStore = mTestDevice.getMountPoint(IDevice.MNT_EXTERNAL_STORAGE);
- mTestDevice.executeShellCommand(String.format("rm -r %s/DCIM", extStore));
- mTestDevice.executeShellCommand(String.format("rm %s/%s", extStore, mOutputPath));
- }
-
- /**
- * Parses the output file generated by the underlying instrumentation test
- * and returns the metrics to the main driver for later reporting.
- * @return The {@link Map} that contains metrics for the test.
- * @throws DeviceNotAvailableException If the device is unavailable or
- * something happened while deleting files
- */
- private Map<String, String> parseOutputFile() throws DeviceNotAvailableException {
- BufferedReader reader = null;
- File outputFile = null;
- String lineMean = null, lineSd = null;
- Matcher m = null;
- Map<String, String> metrics = new HashMap<String, String>();
-
- // Read in data
- // Output file is only 2 lines and should look something like:
- // "Shot to shot latency - mean: 1234.5678901"
- // "Shot to shot latency - standard deviation: 123.45678901"
- try {
- outputFile = mTestDevice.pullFileFromExternal(mOutputPath);
- reader = new BufferedReader(new FileReader(outputFile));
-
- lineMean = reader.readLine();
- lineSd = reader.readLine();
-
- if ((lineMean == null) || (lineSd == null)) {
- CLog.e(String.format("Unable to find output data; hit EOF: \nmean:%s\nsd:%s",
- lineMean, lineSd));
- } else {
- m = MEAN_PATTERN.matcher(lineMean);
- if (m.matches()) {
- metrics.put(LATENCY_KEY_MEAN, m.group(3));
- } else {
- CLog.e(String.format("Unable to find mean: %s", lineMean));
- }
-
- m = STANDARD_DEVIATION_PATTERN.matcher(lineSd);
- if (m.matches()) {
- metrics.put(LATENCY_KEY_SD, m.group(3));
- } else {
- CLog.e(String.format("Unable to find standard deviation: %s", lineSd));
- }
- }
- } catch (IOException e) {
- CLog.e(String.format("IOException reading from file: %s", e.toString()));
- } finally {
- if (reader != null) {
- try {
- reader.close();
- } catch (IOException e) {
- CLog.e(String.format("IOException closing file: %s", e.toString()));
- }
- }
- }
-
- return metrics;
- }
-
- /**
- * Report run metrics by creating an empty test run to stick them in.
- * @param listener The {@link ITestInvocationListener} of test results
- * @param runName The test name
- * @param metrics The {@link Map} that contains metrics for the given test
- */
- private void reportMetrics(ITestInvocationListener listener, String runName,
- Map<String, String> metrics) {
- InputStreamSource bugreport = mTestDevice.getBugreport();
- listener.testLog("bugreport", LogDataType.BUGREPORT, bugreport);
- bugreport.cancel();
-
- CLog.d(String.format("About to report metrics: %s", metrics));
- listener.testRunStarted(runName, 0);
- listener.testRunEnded(0, metrics);
- }
-}
diff --git a/src/com/android/media/tests/CameraStartupTest.java b/src/com/android/media/tests/CameraStartupTest.java
deleted file mode 100644
index c19cd2f..0000000
--- a/src/com/android/media/tests/CameraStartupTest.java
+++ /dev/null
@@ -1,236 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.media.tests;
-
-import com.android.ddmlib.testrunner.TestIdentifier;
-import com.android.tradefed.config.Option;
-import com.android.tradefed.config.OptionClass;
-import com.android.tradefed.device.DeviceNotAvailableException;
-import com.android.tradefed.log.LogUtil.CLog;
-import com.android.tradefed.result.ITestInvocationListener;
-import com.android.tradefed.targetprep.BuildError;
-import com.android.tradefed.targetprep.ITargetPreparer;
-import com.android.tradefed.targetprep.TargetSetupError;
-import com.android.tradefed.targetprep.TemperatureThrottlingWaiter;
-import com.android.tradefed.util.MultiMap;
-
-import org.junit.Assert;
-
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.Set;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-
-/**
- * Camera app startup test
- *
- * Runs CameraActivityTest to measure Camera startup time and reports the metrics.
- */
-@OptionClass(alias = "camera-startup")
-public class CameraStartupTest extends CameraTestBase {
-
- private static final Pattern STATS_REGEX = Pattern.compile(
- "^(?<coldStartup>[0-9.]+)\\|(?<warmStartup>[0-9.]+)\\|(?<values>[0-9 .-]+)");
- private static final String PREFIX_COLD_STARTUP = "Cold";
- // all metrics are expected to be less than 10 mins and greater than 0.
- private static final int METRICS_MAX_THRESHOLD_MS = 10 * 60 * 1000;
- private static final int METRICS_MIN_THRESHOLD_MS = 0;
- private static final String INVALID_VALUE = "-1";
-
- @Option(name="num-test-runs", description="The number of test runs. A instrumentation "
- + "test will be repeatedly executed. Then it posts the average of test results.")
- private int mNumTestRuns = 1;
-
- @Option(name="delay-between-test-runs", description="Time delay between multiple test runs, "
- + "in msecs. Used to wait for device to cool down. "
- + "Note that this will be ignored when TemperatureThrottlingWaiter is configured.")
- private long mDelayBetweenTestRunsMs = 120 * 1000; // 2 minutes
-
- private MultiMap<String, String> mMultipleRunMetrics = new MultiMap<String, String>();
- private Map<String, String> mAverageMultipleRunMetrics = new HashMap<String, String>();
- private long mTestRunsDurationMs = 0;
-
- public CameraStartupTest() {
- setTestPackage("com.google.android.camera");
- setTestClass("com.android.camera.latency.CameraStartupTest");
- setTestRunner("android.test.InstrumentationTestRunner");
- setRuKey("CameraAppStartup");
- setTestTimeoutMs(60 * 60 * 1000); // 1 hour
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public void run(ITestInvocationListener listener) throws DeviceNotAvailableException {
- runMultipleInstrumentationTests(listener, mNumTestRuns);
- }
-
- private void runMultipleInstrumentationTests(ITestInvocationListener listener, int numTestRuns)
- throws DeviceNotAvailableException {
- Assert.assertTrue(numTestRuns > 0);
-
- mTestRunsDurationMs = 0;
- for (int i = 0; i < numTestRuns; ++i) {
- CLog.v("Running multiple instrumentation tests... [%d/%d]", i + 1, numTestRuns);
- CollectingListener singleRunListener = new CollectingListener(listener);
- runInstrumentationTest(listener, singleRunListener);
- mTestRunsDurationMs += getTestDurationMs();
-
- if (singleRunListener.hasFailedTests() ||
- singleRunListener.hasTestRunFatalError()) {
- exitTestRunsOnError(listener, singleRunListener.getErrorMessage());
- return;
- }
- if (i + 1 < numTestRuns) { // Skipping preparation on the last run
- postSetupTestRun();
- }
- }
-
- // Post the average of metrics collected in multiple instrumentation test runs.
- postMultipleRunMetrics(listener);
- CLog.v("multiple instrumentation tests end");
- }
-
- private void exitTestRunsOnError(ITestInvocationListener listener, String errorMessage) {
- CLog.e("The instrumentation result not found. Test runs may have failed due to exceptions."
- + " Test results will not be posted. errorMsg: %s", errorMessage);
- listener.testRunFailed(errorMessage);
- listener.testRunEnded(mTestRunsDurationMs, Collections.<String, String>emptyMap());
- }
-
- private void postMultipleRunMetrics(ITestInvocationListener listener) {
- listener.testRunEnded(mTestRunsDurationMs, getAverageMultipleRunMetrics());
- }
-
- private void postSetupTestRun() throws DeviceNotAvailableException {
- // Reboot for a cold start up of Camera application
- CLog.d("Cold start: Rebooting...");
- getDevice().reboot();
-
- // Wait for device to cool down to target temperature
- // Use TemperatureThrottlingWaiter if configured, otherwise just wait for
- // a specific amount of time.
- CLog.d("Cold start: Waiting for device to cool down...");
- boolean usedTemperatureThrottlingWaiter = false;
- for (ITargetPreparer preparer : mConfiguration.getTargetPreparers()) {
- if (preparer instanceof TemperatureThrottlingWaiter) {
- usedTemperatureThrottlingWaiter = true;
- try {
- preparer.setUp(getDevice(), null);
- } catch (TargetSetupError e) {
- CLog.w("No-op even when temperature is still high after wait timeout. "
- + "error: %s", e.getMessage());
- } catch (BuildError e) {
- // This should not happen.
- }
- }
- }
- if (!usedTemperatureThrottlingWaiter) {
- getRunUtil().sleep(mDelayBetweenTestRunsMs);
- }
- CLog.d("Device gets prepared for the next test run.");
- }
-
- // Call this function once at the end to get the average.
- private Map<String, String> getAverageMultipleRunMetrics() {
- Assert.assertTrue(mMultipleRunMetrics.size() > 0);
-
- Set<String> keys = mMultipleRunMetrics.keySet();
- mAverageMultipleRunMetrics.clear();
- for (String key : keys) {
- int sum = 0;
- int size = 0;
- boolean isInvalid = false;
- for (String valueString : mMultipleRunMetrics.get(key)) {
- int value = Integer.parseInt(valueString);
- // If value is out of valid range, skip posting the result associated with the key
- if (value > METRICS_MAX_THRESHOLD_MS || value < METRICS_MIN_THRESHOLD_MS) {
- isInvalid = true;
- break;
- }
- sum += value;
- ++size;
- }
-
- String valueString = INVALID_VALUE;
- if (isInvalid) {
- CLog.w("Value is out of valid range. Key: %s ", key);
- } else {
- valueString = String.format("%d", (sum / size));
- }
- mAverageMultipleRunMetrics.put(key, valueString);
- }
- return mAverageMultipleRunMetrics;
- }
-
- /**
- * A listener to collect the output from test run and fatal errors
- */
- private class CollectingListener extends DefaultCollectingListener {
-
- public CollectingListener(ITestInvocationListener listener) {
- super(listener);
- }
-
- @Override
- public void handleMetricsOnTestEnded(TestIdentifier test, Map<String, String> testMetrics) {
- // Test metrics accumulated will be posted at the end of test run.
- getAggregatedMetrics().putAll(parseResults(testMetrics));
- }
-
- @Override
- public void handleTestRunEnded(ITestInvocationListener listener, long elapsedTime,
- Map<String, String> runMetrics) {
- // Do not post aggregated metrics from a single run to a dashboard. Instead, it needs
- // to collect all metrics from multiple test runs.
- mMultipleRunMetrics.putAll(getAggregatedMetrics());
- }
-
- public Map<String, String> parseResults(Map<String, String> testMetrics) {
- // Parse activity time stats from the instrumentation result.
- // Format : <metric_key>=<cold_startup>|<average_of_warm_startups>|<all_startups>
- // Example:
- // VideoStartupTimeMs=1098|1184.6|1098 1222 ... 788
- // VideoOnCreateTimeMs=138|103.3|138 114 ... 114
- // VideoOnResumeTimeMs=39|40.4|39 36 ... 41
- // VideoFirstPreviewFrameTimeMs=0|0.0|0 0 ... 0
- // CameraStartupTimeMs=2388|1045.4|2388 1109 ... 746
- // CameraOnCreateTimeMs=574|122.7|574 124 ... 109
- // CameraOnResumeTimeMs=610|504.6|610 543 ... 278
- // CameraFirstPreviewFrameTimeMs=0|0.0|0 0 ... 0
- //
- // Then report only the first two startup time of cold startup and average warm startup.
- Map<String, String> parsed = new HashMap<String, String>();
- for (Map.Entry<String, String> metric : testMetrics.entrySet()) {
- Matcher matcher = STATS_REGEX.matcher(metric.getValue());
- String keyName = metric.getKey();
- String coldStartupValue = INVALID_VALUE;
- String warmStartupValue = INVALID_VALUE;
- if (matcher.matches()) {
- coldStartupValue = matcher.group("coldStartup");
- warmStartupValue = matcher.group("warmStartup");
- }
- parsed.put(PREFIX_COLD_STARTUP + keyName, coldStartupValue);
- parsed.put(keyName, warmStartupValue);
- }
- return parsed;
- }
- }
-}
diff --git a/src/com/android/media/tests/CameraStressTest.java b/src/com/android/media/tests/CameraStressTest.java
deleted file mode 100644
index def3f39..0000000
--- a/src/com/android/media/tests/CameraStressTest.java
+++ /dev/null
@@ -1,513 +0,0 @@
-/*
- * Copyright (C) 2011 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.media.tests;
-
-import com.android.ddmlib.IDevice;
-import com.android.ddmlib.Log;
-import com.android.ddmlib.testrunner.IRemoteAndroidTestRunner;
-import com.android.ddmlib.testrunner.RemoteAndroidTestRunner;
-import com.android.tradefed.config.Option;
-import com.android.tradefed.device.DeviceNotAvailableException;
-import com.android.tradefed.device.ITestDevice;
-import com.android.tradefed.result.CollectingTestListener;
-import com.android.tradefed.result.FileInputStreamSource;
-import com.android.tradefed.result.ITestInvocationListener;
-import com.android.tradefed.result.InputStreamSource;
-import com.android.tradefed.result.LogDataType;
-import com.android.tradefed.testtype.IDeviceTest;
-import com.android.tradefed.testtype.IRemoteTest;
-import com.android.tradefed.util.FileUtil;
-import com.android.tradefed.util.RegexTrie;
-import com.android.tradefed.util.StreamUtil;
-
-import junit.framework.TestCase;
-
-import org.junit.Assert;
-
-import java.io.ByteArrayInputStream;
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.HashMap;
-import java.util.List;
-import java.util.ListIterator;
-import java.util.Map;
-import java.util.Set;
-import java.util.concurrent.TimeUnit;
-
-/**
- * Runs the Camera stress testcases.
- * FIXME: more details
- * <p/>
- * Note that this test will not run properly unless /sdcard is mounted and writable.
- */
-public class CameraStressTest implements IDeviceTest, IRemoteTest {
- private static final String LOG_TAG = "CameraStressTest";
-
- ITestDevice mTestDevice = null;
-
- // Constants for running the tests
- private static final String TEST_PACKAGE_NAME = "com.google.android.camera.tests";
- private static final String TEST_RUNNER = "com.android.camera.stress.CameraStressTestRunner";
-
- //Max test timeout - 3 hrs
- private static final int MAX_TEST_TIMEOUT = 3 * 60 * 60 * 1000;
-
- private final String mOutputPath = "mediaStressOut.txt";
-
- /**
- * Stores the test cases that we should consider running.
- *
- * <p>This currently consists of "startup" and "latency"
- */
- private List<TestInfo> mTestCases = new ArrayList<>();
-
- // Options for the running the gCam test
- @Option(name = "gCam", description = "Run gCam back image capture test")
- private boolean mGcam = false;
-
- /**
- * A struct that contains useful info about the tests to run
- */
- static class TestInfo {
- public String mTestName = null;
- public String mClassName = null;
- public String mTestMetricsName = null;
- public Map<String, String> mInstrumentationArgs = new HashMap<>();
- public RegexTrie<String> mPatternMap = new RegexTrie<>();
-
- @Override
- public String toString() {
- return String.format("TestInfo: name(%s) class(%s) metric(%s) patterns(%s)", mTestName,
- mClassName, mTestMetricsName, mPatternMap);
- }
- }
-
- /**
- * Set up the pattern map for parsing output files
- * <p/>
- * Exposed for unit meta-testing
- */
- static RegexTrie<String> getPatternMap() {
- RegexTrie<String> patMap = new RegexTrie<>();
- patMap.put("SwitchPreview", "^Camera Switch Mode:");
-
- // For versions of the on-device test that don't differentiate between front and back camera
- patMap.put("ImageCapture", "^Camera Image Capture");
- patMap.put("VideoRecording", "^Camera Video Capture");
-
- // For versions that do differentiate
- patMap.put("FrontImageCapture", "^Front Camera Image Capture");
- patMap.put("ImageCapture", "^Back Camera Image Capture");
- patMap.put("FrontVideoRecording", "^Front Camera Video Capture");
- patMap.put("VideoRecording", "^Back Camera Video Capture");
-
- // Actual metrics to collect for a given key
- patMap.put("loopCount", "^No of loops :(\\d+)");
- patMap.put("iters", "^loop:.+,(\\d+)");
-
- return patMap;
- }
-
- /**
- * Set up the configurations for the test cases we want to run
- */
- private void testInfoSetup() {
- RegexTrie<String> patMap = getPatternMap();
- TestInfo t = new TestInfo();
-
- if (mGcam) {
- // Back Image capture stress test for gCam
- t.mTestName = "testBackImageCapture";
- t.mClassName = "com.android.camera.stress.ImageCapture";
- t.mTestMetricsName = "GCamApplicationStress";
- t.mInstrumentationArgs.put("image_iterations", Integer.toString(100));
- t.mPatternMap = patMap;
- mTestCases.add(t);
-
- } else {
- // Image capture stress test
- t.mTestName = "imagecap";
- t.mClassName = "com.android.camera.stress.ImageCapture";
- t.mTestMetricsName = "CameraApplicationStress";
- t.mInstrumentationArgs.put("image_iterations", Integer.toString(100));
- t.mPatternMap = patMap;
- mTestCases.add(t);
-
- // Image capture stress test
- t = new TestInfo();
- t.mTestName = "videocap";
- t.mClassName = "com.android.camera.stress.VideoCapture";
- t.mTestMetricsName = "CameraApplicationStress";
- t.mInstrumentationArgs.put("video_iterations", Integer.toString(100));
- t.mPatternMap = patMap;
- mTestCases.add(t);
-
- // "SwitchPreview" stress test
- t = new TestInfo();
- t.mTestName = "switch";
- t.mClassName = "com.android.camera.stress.SwitchPreview";
- t.mTestMetricsName = "CameraApplicationStress";
- t.mPatternMap = patMap;
- mTestCases.add(t);
- }
- }
-
- @Override
- public void run(ITestInvocationListener listener) throws DeviceNotAvailableException {
- Assert.assertNotNull(mTestDevice);
- testInfoSetup();
- for (TestInfo test : mTestCases) {
- cleanTmpFiles();
- executeTest(test, listener);
- logOutputFiles(test, listener);
- }
-
- cleanTmpFiles();
- }
-
- private void executeTest(TestInfo test, ITestInvocationListener listener)
- throws DeviceNotAvailableException {
- IRemoteAndroidTestRunner runner = new RemoteAndroidTestRunner(TEST_PACKAGE_NAME,
- TEST_RUNNER, mTestDevice.getIDevice());
- CollectingTestListener auxListener = new CollectingTestListener();
-
- runner.setClassName(test.mClassName);
- runner.setMaxTimeToOutputResponse(MAX_TEST_TIMEOUT, TimeUnit.MILLISECONDS);
- if (mGcam){
- runner.setMethodName(test.mClassName, test.mTestName);
- }
-
- Set<String> argumentKeys = test.mInstrumentationArgs.keySet();
- for (String s : argumentKeys) {
- runner.addInstrumentationArg(s, test.mInstrumentationArgs.get(s));
- }
-
- mTestDevice.runInstrumentationTests(runner, listener, auxListener);
-
- // Grab a bugreport if warranted
- if (auxListener.hasFailedTests()) {
- Log.e(LOG_TAG, String.format("Grabbing bugreport after test '%s' finished with " +
- "%d failures.", test.mTestName, auxListener.getNumAllFailedTests()));
- InputStreamSource bugreport = mTestDevice.getBugreport();
- listener.testLog(String.format("bugreport-%s.txt", test.mTestName),
- LogDataType.BUGREPORT, bugreport);
- bugreport.cancel();
- }
- }
-
- /**
- * Clean up temp files from test runs
- * <p />
- * Note that all photos on the test device will be removed
- */
- private void cleanTmpFiles() throws DeviceNotAvailableException {
- String extStore = mTestDevice.getMountPoint(IDevice.MNT_EXTERNAL_STORAGE);
- mTestDevice.executeShellCommand(String.format("rm -r %s/DCIM/Camera", extStore));
- mTestDevice.executeShellCommand(String.format("rm %s/%s", extStore, mOutputPath));
- }
-
- /**
- * Pull the output file from the device, add it to the logs, and also parse out the relevant
- * test metrics and report them. Additionally, pull the memory file (if it exists) and report
- * it.
- */
- private void logOutputFiles(TestInfo test, ITestInvocationListener listener)
- throws DeviceNotAvailableException {
- File outputFile = null;
- InputStreamSource outputSource = null;
- try {
- outputFile = mTestDevice.pullFileFromExternal(mOutputPath);
-
- if (outputFile == null) {
- return;
- }
-
- // Upload a verbatim copy of the output file
- Log.d(LOG_TAG, String.format("Sending %d byte file %s into the logosphere!",
- outputFile.length(), outputFile));
- outputSource = new FileInputStreamSource(outputFile);
- listener.testLog(String.format("output-%s.txt", test.mTestName), LogDataType.TEXT,
- outputSource);
-
- // Parse the output file to upload aggregated metrics
- parseOutputFile(test, new FileInputStream(outputFile), listener);
- } catch (IOException e) {
- Log.e(LOG_TAG, String.format("IOException while reading or parsing output file: %s", e));
- } finally {
- FileUtil.deleteFile(outputFile);
- StreamUtil.cancel(outputSource);
- }
- }
-
- /**
- * Parse the relevant metrics from the Instrumentation test output file
- */
- private void parseOutputFile(TestInfo test, InputStream dataStream,
- ITestInvocationListener listener) {
- Map<String, String> runMetrics = new HashMap<>();
-
- String contents;
- try {
- contents = StreamUtil.getStringFromStream(dataStream);
- } catch (IOException e) {
- Log.e(LOG_TAG, String.format("Got IOException during %s test processing: %s",
- test.mTestName, e));
- return;
- }
-
- String key = null;
- Integer countExpected = null;
- Integer countActual = null;
-
- List<String> lines = Arrays.asList(contents.split("\n"));
- ListIterator<String> lineIter = lines.listIterator();
- String line;
- while (lineIter.hasNext()) {
- line = lineIter.next();
- List<List<String>> capture = new ArrayList<>(1);
- String pattern = test.mPatternMap.retrieve(capture, line);
- if (pattern != null) {
- if ("loopCount".equals(pattern)) {
- // First capture in first (only) string
- countExpected = Integer.parseInt(capture.get(0).get(0));
- } else if ("iters".equals(pattern)) {
- // First capture in first (only) string
- countActual = Integer.parseInt(capture.get(0).get(0));
-
- if (countActual != null) {
- // countActual starts counting at 0
- countActual += 1;
- }
- } else {
- // Assume that the pattern is the name of a key
-
- // commit, if there was a previous key
- if (key != null) {
- int value = coalesceLoopCounts(countActual, countExpected);
- runMetrics.put(key, Integer.toString(value));
- }
-
- key = pattern;
- countExpected = null;
- countActual = null;
- }
-
- Log.d(LOG_TAG, String.format("Got %s key '%s' and captures '%s'",
- test.mTestName, key, capture.toString()));
- } else if (line.isEmpty()) {
- // ignore
- continue;
- } else {
- Log.e(LOG_TAG, String.format("Got unmatched line: %s", line));
- continue;
- }
-
- // commit the final key, if there was one
- if (key != null) {
- int value = coalesceLoopCounts(countActual, countExpected);
- runMetrics.put(key, Integer.toString(value));
- }
- }
-
- reportMetrics(listener, test, runMetrics);
- }
-
- /**
- * Given an actual and an expected iteration count, determine a single metric to report.
- */
- private int coalesceLoopCounts(Integer actual, Integer expected) {
- if (expected == null || expected <= 0) {
- return -1;
- } else if (actual == null) {
- return expected;
- } else {
- return actual;
- }
- }
-
- /**
- * Report run metrics by creating an empty test run to stick them in
- * <p />
- * Exposed for unit testing
- */
- void reportMetrics(ITestInvocationListener listener, TestInfo test,
- Map<String, String> metrics) {
- // Create an empty testRun to report the parsed runMetrics
- Log.e(LOG_TAG, String.format("About to report metrics for %s: %s", test.mTestMetricsName,
- metrics));
- listener.testRunStarted(test.mTestMetricsName, 0);
- listener.testRunEnded(0, metrics);
- }
-
- @Override
- public void setDevice(ITestDevice device) {
- mTestDevice = device;
- }
-
- @Override
- public ITestDevice getDevice() {
- return mTestDevice;
- }
-
- /**
- * A meta-test to ensure that bits of the BluetoothStressTest are working properly
- */
- public static class MetaTest extends TestCase {
- private CameraStressTest mTestInstance = null;
-
- private TestInfo mTestInfo = null;
-
- private TestInfo mReportedTestInfo = null;
- private Map<String, String> mReportedMetrics = null;
-
- private static String join(String... pieces) {
- StringBuilder sb = new StringBuilder();
- for (String piece : pieces) {
- sb.append(piece);
- sb.append("\n");
- }
- return sb.toString();
- }
-
- @Override
- public void setUp() throws Exception {
- mTestInstance = new CameraStressTest() {
- @Override
- void reportMetrics(ITestInvocationListener l, TestInfo test,
- Map<String, String> metrics) {
- mReportedTestInfo = test;
- mReportedMetrics = metrics;
- }
- };
-
- // Image capture stress test
- mTestInfo = new TestInfo();
- TestInfo t = mTestInfo; // for convenience
- t.mTestName = "capture";
- t.mClassName = "com.android.camera.stress.ImageCapture";
- t.mTestMetricsName = "camera_application_stress";
- t.mPatternMap = getPatternMap();
- }
-
- /**
- * Make sure that parsing works for devices sending output in the old format
- */
- public void testParse_old() throws Exception {
- String output = join(
- "Camera Image Capture",
- "No of loops :100",
- "loop: ,0 ,1 ,2 ,3 ,4 ,5 ,6 ,7 ,8 ,9 ,10 ,11 ,12 ,13 ,14 ,15 ,16 ,17 ,18 " +
- ",19 ,20 ,21 ,22 ,23 ,24 ,25 ,26 ,27 ,28 ,29 ,30 ,31 ,32 ,33 ,34 ,35 " +
- ",36 ,37 ,38 ,39 ,40 ,41 ,42",
- "Camera Video Capture",
- "No of loops :100",
- "loop: ,0 ,1 ,2 ,3 ,4 ,5 ,6 ,7 ,8 ,9 ,10 ,11 ,12 ,13 ,14 ,15 ,16 ,17 ,18 " +
- ",19 ,20 ,21 ,22 ,23 ,24 ,25 ,26 ,27 ,28 ,29 ,30 ,31 ,32 ,33 ,34 ,35 " +
- ",36 ,37 ,38 ,39 ,40 ,41 ,42 ,43 ,44 ,45 ,46 ,47 ,48 ,49 ,50 ,51 ,52 " +
- ",53 ,54 ,55 ,56 ,57 ,58 ,59 ,60 ,61 ,62 ,63 ,64 ,65 ,66 ,67 ,68 ,69 " +
- ",70 ,71 ,72 ,73 ,74 ,75 ,76 ,77 ,78 ,79 ,80 ,81 ,82 ,83 ,84 ,85 ,86 " +
- ",87 ,88 ,89 ,90 ,91 ,92 ,93 ,94 ,95 ,96 ,97 ,98 ,99",
- "Camera Switch Mode:",
- "No of loops :200",
- "loop: ,0 ,1 ,2 ,3 ,4 ,5 ,6 ,7 ,8 ,9 ,10 ,11 ,12 ,13");
-
- InputStream iStream = new ByteArrayInputStream(output.getBytes());
- mTestInstance.parseOutputFile(mTestInfo, iStream, null);
- assertEquals(mTestInfo, mReportedTestInfo);
- assertNotNull(mReportedMetrics);
- Log.e(LOG_TAG, String.format("Got reported metrics: %s", mReportedMetrics.toString()));
- assertEquals(3, mReportedMetrics.size());
- assertEquals("43", mReportedMetrics.get("ImageCapture"));
- assertEquals("100", mReportedMetrics.get("VideoRecording"));
- assertEquals("14", mReportedMetrics.get("SwitchPreview"));
- }
-
- /**
- * Make sure that parsing works for devices sending output in the new format
- */
- public void testParse_new() throws Exception {
- String output = join(
- "Camera Stress Test result",
- "/folder/subfolder/data/CameraStressTest_git_honeycomb-mr1-release_" +
- "1700614441c02617_109535_CameraStressOut.txt",
- "Back Camera Image Capture",
- "No of loops :100",
- "loop: ,0 ,1 ,2 ,3 ,4 ,5 ,6 ,7 ,8 ,9 ,10 ,11 ,12 ,13 ,14 ,15 ,16 ,17 ,18 " +
- ",19 ,20 ,21 ,22 ,23 ,24 ,25 ,26 ,27 ,28 ,29 ,30 ,31 ,32 ,33 ,34 ,35 ,36 " +
- ",37 ,38 ,39 ,40 ,41 ,42 ,43 ,44 ,45 ,46 ,47 ,48 ,49 ,50 ,51 ,52 ,53 ,54 " +
- ",55 ,56 ,57 ,58 ,59 ,60 ,61 ,62 ,63 ,64 ,65 ,66 ,67 ,68 ,69 ,70 ,71 ,72 " +
- ",73 ,74 ,75 ,76 ,77 ,78 ,79 ,80 ,81 ,82 ,83 ,84 ,85 ,86 ,87 ,88 ,89 ,90 " +
- ",91 ,92 ,93 ,94 ,95 ,96 ,97 ,98 ,99",
- "Front Camera Image Capture",
- "No of loops :100",
- "loop: ,0 ,1 ,2 ,3 ,4 ,5 ,6 ,7 ,8 ,9 ,10 ,11 ,12 ,13 ,14 ,15 ,16 ,17 ,18 " +
- ",19 ,20 ,21 ,22 ,23 ,24 ,25 ,26 ,27 ,28 ,29 ,30 ,31 ,32 ,33 ,34 ,35 ,36 " +
- ",37 ,38 ,39 ,40 ,41 ,42 ,43 ,44 ,45 ,46 ,47 ,48 ,49 ,50 ,51 ,52 ,53 ,54 " +
- ",55 ,56 ,57 ,58 ,59 ,60 ,61 ,62 ,63 ,64 ,65 ,66 ,67 ,68 ,69 ,70 ,71 ,72 " +
- ",73 ,74 ,75 ,76 ,77 ,78 ,79 ,80 ,81 ,82 ,83 ,84 ,85 ,86 ,87 ,88 ,89 ,90 " +
- ",91 ,92 ,93 ,94 ,95 ,96 ,97 ,98",
- "Back Camera Video Capture",
- "No of loops :100",
- "loop: ,0 ,1 ,2 ,3 ,4 ,5 ,6 ,7 ,8 ,9 ,10 ,11 ,12 ,13 ,14 ,15 ,16 ,17 ,18 " +
- ",19 ,20 ,21 ,22 ,23 ,24 ,25 ,26 ,27 ,28 ,29 ,30 ,31 ,32 ,33 ,34 ,35 ,36 " +
- ",37 ,38 ,39 ,40 ,41 ,42 ,43 ,44 ,45 ,46 ,47 ,48 ,49 ,50 ,51 ,52 ,53 ,54 " +
- ",55 ,56 ,57 ,58 ,59 ,60 ,61 ,62 ,63 ,64 ,65 ,66 ,67 ,68 ,69 ,70 ,71 ,72 " +
- ",73 ,74 ,75 ,76 ,77 ,78 ,79 ,80 ,81 ,82 ,83 ,84 ,85 ,86 ,87 ,88 ,89 ,90 " +
- ",91 ,92 ,93 ,94 ,95 ,96 ,97",
- "Front Camera Video Capture",
- "No of loops :100",
- "loop: ,0 ,1 ,2 ,3 ,4 ,5 ,6 ,7 ,8 ,9 ,10 ,11 ,12 ,13 ,14 ,15 ,16 ,17 ,18 " +
- ",19 ,20 ,21 ,22 ,23 ,24 ,25 ,26 ,27 ,28 ,29 ,30 ,31 ,32 ,33 ,34 ,35 ,36 " +
- ",37 ,38 ,39 ,40 ,41 ,42 ,43 ,44 ,45 ,46 ,47 ,48 ,49 ,50 ,51 ,52 ,53 ,54 " +
- ",55 ,56 ,57 ,58 ,59 ,60 ,61 ,62 ,63 ,64 ,65 ,66 ,67 ,68 ,69 ,70 ,71 ,72 " +
- ",73 ,74 ,75 ,76 ,77 ,78 ,79 ,80 ,81 ,82 ,83 ,84 ,85 ,86 ,87 ,88 ,89 ,90 " +
- ",91 ,92 ,93 ,94 ,95 ,96 ,97 ,98 ,99",
- "Camera Switch Mode:",
- "No of loops :200",
- "loop: ,0 ,1 ,2 ,3 ,4 ,5 ,6 ,7 ,8 ,9 ,10 ,11 ,12 ,13 ,14 ,15 ,16 ,17 ,18 " +
- ",19 ,20 ,21 ,22 ,23 ,24 ,25 ,26 ,27 ,28 ,29 ,30 ,31 ,32 ,33 ,34 ,35 ,36 " +
- ",37 ,38 ,39 ,40 ,41 ,42 ,43 ,44 ,45 ,46 ,47 ,48 ,49 ,50 ,51 ,52 ,53 ,54 " +
- ",55 ,56 ,57 ,58 ,59 ,60 ,61 ,62 ,63 ,64 ,65 ,66 ,67 ,68 ,69 ,70 ,71 ,72 " +
- ",73 ,74 ,75 ,76 ,77 ,78 ,79 ,80 ,81 ,82 ,83 ,84 ,85 ,86 ,87 ,88 ,89 ,90 " +
- ",91 ,92 ,93 ,94 ,95 ,96 ,97 ,98 ,99 ,100 ,101 ,102 ,103 ,104 ,105 ,106 " +
- ",107 ,108 ,109 ,110 ,111 ,112 ,113 ,114 ,115 ,116 ,117 ,118 ,119 ,120 " +
- ",121 ,122 ,123 ,124 ,125 ,126 ,127 ,128 ,129 ,130 ,131 ,132 ,133 ,134 " +
- ",135 ,136 ,137 ,138 ,139 ,140 ,141 ,142 ,143 ,144 ,145 ,146 ,147 ,148 " +
- ",149 ,150 ,151 ,152 ,153 ,154 ,155 ,156 ,157 ,158 ,159 ,160 ,161 ,162 " +
- ",163 ,164 ,165 ,166 ,167 ,168 ,169 ,170 ,171 ,172 ,173 ,174 ,175 ,176 " +
- ",177 ,178 ,179 ,180 ,181 ,182 ,183 ,184 ,185 ,186 ,187 ,188 ,189 ,190 " +
- ",191 ,192 ,193 ,194 ,195 ,196 ,197 ,198 ,199");
-
- InputStream iStream = new ByteArrayInputStream(output.getBytes());
- mTestInstance.parseOutputFile(mTestInfo, iStream, null);
- assertEquals(mTestInfo, mReportedTestInfo);
- assertNotNull(mReportedMetrics);
- Log.e(LOG_TAG, String.format("Got reported metrics: %s", mReportedMetrics.toString()));
- assertEquals(5, mReportedMetrics.size());
- assertEquals("100", mReportedMetrics.get("ImageCapture"));
- assertEquals("99", mReportedMetrics.get("FrontImageCapture"));
- assertEquals("98", mReportedMetrics.get("VideoRecording"));
- assertEquals("100", mReportedMetrics.get("FrontVideoRecording"));
- assertEquals("200", mReportedMetrics.get("SwitchPreview"));
- }
- }
-}
-
diff --git a/src/com/android/media/tests/CameraTestBase.java b/src/com/android/media/tests/CameraTestBase.java
deleted file mode 100644
index 8714a22..0000000
--- a/src/com/android/media/tests/CameraTestBase.java
+++ /dev/null
@@ -1,840 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.media.tests;
-
-import com.android.ddmlib.CollectingOutputReceiver;
-import com.android.ddmlib.testrunner.TestIdentifier;
-import com.android.tradefed.config.IConfiguration;
-import com.android.tradefed.config.IConfigurationReceiver;
-import com.android.tradefed.config.Option;
-import com.android.tradefed.device.DeviceNotAvailableException;
-import com.android.tradefed.device.ITestDevice;
-import com.android.tradefed.log.LogUtil.CLog;
-import com.android.tradefed.result.ByteArrayInputStreamSource;
-import com.android.tradefed.result.CollectingTestListener;
-import com.android.tradefed.result.FileInputStreamSource;
-import com.android.tradefed.result.ITestInvocationListener;
-import com.android.tradefed.result.InputStreamSource;
-import com.android.tradefed.result.LogDataType;
-import com.android.tradefed.testtype.IDeviceTest;
-import com.android.tradefed.testtype.IRemoteTest;
-import com.android.tradefed.testtype.InstrumentationTest;
-import com.android.tradefed.util.FileUtil;
-import com.android.tradefed.util.IRunUtil;
-import com.android.tradefed.util.RunUtil;
-import com.android.tradefed.util.StreamUtil;
-
-import org.junit.Assert;
-
-import java.io.BufferedReader;
-import java.io.BufferedWriter;
-import java.io.File;
-import java.io.FileWriter;
-import java.io.IOException;
-import java.io.StringReader;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.Timer;
-import java.util.TimerTask;
-import java.util.concurrent.TimeUnit;
-
-/**
- * Camera test base class
- *
- * Camera2StressTest, CameraStartupTest, Camera2LatencyTest and CameraPerformanceTest use this base
- * class for Camera ivvavik and later.
- */
-public class CameraTestBase implements IDeviceTest, IRemoteTest, IConfigurationReceiver {
-
- private static final long SHELL_TIMEOUT_MS = 60 * 1000; // 1 min
- private static final int SHELL_MAX_ATTEMPTS = 3;
- protected static final String PROCESS_CAMERA_DAEMON = "mm-qcamera-daemon";
- protected static final String PROCESS_MEDIASERVER = "mediaserver";
- protected static final String PROCESS_CAMERA_APP = "com.google.android.GoogleCamera";
- protected static final String DUMP_ION_HEAPS_COMMAND = "cat /d/ion/heaps/system";
- protected static final String ARGUMENT_TEST_ITERATIONS = "iterations";
-
- @Option(name = "test-package", description = "Test package to run.")
- private String mTestPackage = "com.google.android.camera";
-
- @Option(name = "test-class", description = "Test class to run.")
- private String mTestClass = null;
-
- @Option(name = "test-methods", description = "Test method to run. May be repeated.")
- private Collection<String> mTestMethods = new ArrayList<>();
-
- @Option(name = "test-runner", description = "Test runner for test instrumentation.")
- private String mTestRunner = "android.test.InstrumentationTestRunner";
-
- @Option(name = "test-timeout", description = "Max time allowed in ms for a test run.")
- private int mTestTimeoutMs = 60 * 60 * 1000; // 1 hour
-
- @Option(name = "shell-timeout",
- description="The defined timeout (in milliseconds) is used as a maximum waiting time "
- + "when expecting the command output from the device. At any time, if the "
- + "shell command does not output anything for a period longer than defined "
- + "timeout the TF run terminates. For no timeout, set to 0.")
- private long mShellTimeoutMs = 60 * 60 * 1000; // default to 1 hour
-
- @Option(name = "ru-key", description = "Result key to use when posting to the dashboard.")
- private String mRuKey = null;
-
- @Option(name = "logcat-on-failure", description =
- "take a logcat snapshot on every test failure.")
- private boolean mLogcatOnFailure = false;
-
- @Option(
- name = "instrumentation-arg",
- description = "Additional instrumentation arguments to provide."
- )
- private Map<String, String> mInstrArgMap = new HashMap<>();
-
- @Option(name = "dump-meminfo", description =
- "take a dumpsys meminfo at a given interval time.")
- private boolean mDumpMeminfo = false;
-
- @Option(name="dump-meminfo-interval-ms",
- description="Interval of calling dumpsys meminfo in milliseconds.")
- private int mMeminfoIntervalMs = 5 * 60 * 1000; // 5 minutes
-
- @Option(name = "dump-ion-heap", description =
- "dump ION allocations at the end of test.")
- private boolean mDumpIonHeap = false;
-
- @Option(name = "dump-thread-count", description =
- "Count the number of threads in Camera process at a given interval time.")
- private boolean mDumpThreadCount = false;
-
- @Option(name="dump-thread-count-interval-ms",
- description="Interval of calling ps to count the number of threads in milliseconds.")
- private int mThreadCountIntervalMs = 5 * 60 * 1000; // 5 minutes
-
- @Option(name="iterations", description="The number of iterations to run. Default to 1. "
- + "This takes effect only when Camera2InstrumentationTestRunner is used to execute "
- + "framework stress tests.")
- private int mIterations = 1;
-
- private ITestDevice mDevice = null;
-
- // A base listener to collect the results from each test run. Test results will be forwarded
- // to other listeners.
- private AbstractCollectingListener mCollectingListener = null;
-
- private long mStartTimeMs = 0;
-
- private MeminfoTimer mMeminfoTimer = null;
- private ThreadTrackerTimer mThreadTrackerTimer = null;
-
- protected IConfiguration mConfiguration;
-
- /**
- * {@inheritDoc}
- */
- @Override
- public void run(ITestInvocationListener listener) throws DeviceNotAvailableException {
- // ignore
- }
-
- /**
- * Run Camera instrumentation test with a default listener.
- *
- * @param listener the ITestInvocationListener of test results
- * @throws DeviceNotAvailableException
- */
- protected void runInstrumentationTest(ITestInvocationListener listener)
- throws DeviceNotAvailableException {
- if (mCollectingListener == null) {
- mCollectingListener = new DefaultCollectingListener(listener);
- }
- runInstrumentationTest(listener, mCollectingListener);
- }
-
- /**
- * Run Camera instrumentation test with a listener to gather the metrics from the individual
- * test runs.
- *
- * @param listener the ITestInvocationListener of test results
- * @param collectingListener the {@link CollectingTestListener} to collect the metrics from
- * test runs
- * @throws DeviceNotAvailableException
- */
- protected void runInstrumentationTest(ITestInvocationListener listener,
- AbstractCollectingListener collectingListener)
- throws DeviceNotAvailableException {
- Assert.assertNotNull(collectingListener);
- mCollectingListener = collectingListener;
-
- InstrumentationTest instr = new InstrumentationTest();
- instr.setDevice(getDevice());
- instr.setPackageName(getTestPackage());
- instr.setRunnerName(getTestRunner());
- instr.setClassName(getTestClass());
- instr.setTestTimeout(getTestTimeoutMs());
- instr.setShellTimeout(getShellTimeoutMs());
- instr.setLogcatOnFailure(mLogcatOnFailure);
- instr.setRunName(getRuKey());
- instr.setRerunMode(false);
-
- // Set test iteration.
- if (getIterationCount() > 1) {
- CLog.v("Setting test iterations: %d", getIterationCount());
- Map<String, String> instrArgMap = getInstrumentationArgMap();
- instrArgMap.put(ARGUMENT_TEST_ITERATIONS, String.valueOf(getIterationCount()));
- }
-
- for (Map.Entry<String, String> entry : getInstrumentationArgMap().entrySet()) {
- instr.addInstrumentationArg(entry.getKey(), entry.getValue());
- }
-
- // Check if dumpheap needs to be taken for native processes before test runs.
- if (shouldDumpMeminfo()) {
- mMeminfoTimer = new MeminfoTimer(0, mMeminfoIntervalMs);
- }
- if (shouldDumpThreadCount()) {
- long delayMs = mThreadCountIntervalMs / 2; // Not to run all dump at the same interval.
- mThreadTrackerTimer = new ThreadTrackerTimer(delayMs, mThreadCountIntervalMs);
- }
-
- // Run tests.
- mStartTimeMs = System.currentTimeMillis();
- if (mTestMethods.size() > 0) {
- CLog.d(String.format("The number of test methods is: %d", mTestMethods.size()));
- for (String testName : mTestMethods) {
- instr.setMethodName(testName);
- instr.run(mCollectingListener);
- }
- } else {
- instr.run(mCollectingListener);
- }
-
- dumpIonHeaps(mCollectingListener, getTestClass());
- }
-
- /**
- * A base listener to collect all test results and metrics from Camera instrumentation test run.
- * Abstract methods can be overridden to handle test metrics or inform of test run ended.
- */
- protected abstract class AbstractCollectingListener extends CollectingTestListener {
-
- private ITestInvocationListener mListener = null;
- private Map<String, String> mMetrics = new HashMap<>();
- private Map<String, String> mFatalErrors = new HashMap<>();
-
- private static final String INCOMPLETE_TEST_ERR_MSG_PREFIX =
- "Test failed to run to completion. Reason: 'Instrumentation run failed";
-
- public AbstractCollectingListener(ITestInvocationListener listener) {
- mListener = listener;
- }
-
- /**
- * Override only when subclasses need to get the test metrics from an individual
- * instrumentation test. To aggregate the metrics from each test, update the
- * getAggregatedMetrics and post them at the end of test run.
- *
- * @param test identifies the test
- * @param testMetrics a {@link Map} of the metrics emitted
- */
- abstract public void handleMetricsOnTestEnded(TestIdentifier test,
- Map<String, String> testMetrics);
-
- /**
- * Override only when it needs to inform subclasses of instrumentation test run ended,
- * so that subclasses have a chance to peek the aggregated results at the end of test run
- * and to decide what metrics to be posted.
- * Either {@link ITestInvocationListener#testRunEnded} or
- * {@link ITestInvocationListener#testRunFailed} should be called in this function to
- * report the test run status.
- *
- * @param listener - the ITestInvocationListener of test results
- * @param elapsedTime - device reported elapsed time, in milliseconds
- * @param runMetrics - key-value pairs reported at the end of an instrumentation test run.
- * Use getAggregatedMetrics to retrieve the metrics aggregated
- * from an individual test, instead.
- */
- abstract public void handleTestRunEnded(ITestInvocationListener listener,
- long elapsedTime, Map<String, String> runMetrics);
-
- /**
- * Report the end of an individual camera test and delegate handling the collected metrics
- * to subclasses. Do not override testEnded to manipulate the test metrics after each test.
- * Instead, use handleMetricsOnTestEnded.
- *
- * @param test identifies the test
- * @param testMetrics a {@link Map} of the metrics emitted
- */
- @Override
- public void testEnded(TestIdentifier test, long endTime, Map<String, String> testMetrics) {
- super.testEnded(test, endTime, testMetrics);
- handleMetricsOnTestEnded(test, testMetrics);
- stopDumping(test);
- mListener.testEnded(test, endTime, testMetrics);
- }
-
- @Override
- public void testStarted(TestIdentifier test, long startTime) {
- super.testStarted(test, startTime);
- startDumping(test);
- mListener.testStarted(test, startTime);
- }
-
- @Override
- public void testFailed(TestIdentifier test, String trace) {
- super.testFailed(test, trace);
- // If the test failed to run to complete, this is an exceptional case.
- // Let this test run fail so that it can rerun.
- if (trace.startsWith(INCOMPLETE_TEST_ERR_MSG_PREFIX)) {
- mFatalErrors.put(test.getTestName(), trace);
- CLog.d("Test (%s) failed due to fatal error : %s", test.getTestName(), trace);
- }
- mListener.testFailed(test, trace);
- }
-
- @Override
- public void testRunFailed(String errorMessage) {
- super.testRunFailed(errorMessage);
- mFatalErrors.put(getRuKey(), errorMessage);
- }
-
- @Override
- public void testRunEnded(long elapsedTime, Map<String, String> runMetrics) {
- super.testRunEnded(elapsedTime, runMetrics);
- handleTestRunEnded(mListener, elapsedTime, runMetrics);
- // never be called since handleTestRunEnded will handle it if needed.
- //mListener.testRunEnded(elapsedTime, runMetrics);
- }
-
- @Override
- public void testRunStarted(String runName, int testCount) {
- super.testRunStarted(runName, testCount);
- mListener.testRunStarted(runName, testCount);
- }
-
- @Override
- public void testRunStopped(long elapsedTime) {
- super.testRunStopped(elapsedTime);
- mListener.testRunStopped(elapsedTime);
- }
-
- @Override
- public void testLog(String dataName, LogDataType dataType, InputStreamSource dataStream) {
- super.testLog(dataName, dataType, dataStream);
- mListener.testLog(dataName, dataType, dataStream);
- }
-
- protected void startDumping(TestIdentifier test) {
- if (shouldDumpMeminfo()) {
- mMeminfoTimer.start(test);
- }
- if (shouldDumpThreadCount()) {
- mThreadTrackerTimer.start(test);
- }
- }
-
- protected void stopDumping(TestIdentifier test) {
- InputStreamSource outputSource = null;
- File outputFile = null;
- if (shouldDumpMeminfo()) {
- mMeminfoTimer.stop();
- // Grab a snapshot of meminfo file and post it to dashboard.
- try {
- outputFile = mMeminfoTimer.getOutputFile();
- outputSource = new FileInputStreamSource(outputFile, true /* delete */);
- String logName = String.format("meminfo_%s", test.getTestName());
- mListener.testLog(logName, LogDataType.TEXT, outputSource);
- } finally {
- StreamUtil.cancel(outputSource);
- }
- }
- if (shouldDumpThreadCount()) {
- mThreadTrackerTimer.stop();
- try {
- outputFile = mThreadTrackerTimer.getOutputFile();
- outputSource = new FileInputStreamSource(outputFile, true /* delete */);
- String logName = String.format("ps_%s", test.getTestName());
- mListener.testLog(logName, LogDataType.TEXT, outputSource);
- } finally {
- StreamUtil.cancel(outputSource);
- }
- }
- }
-
- public Map<String, String> getAggregatedMetrics() {
- return mMetrics;
- }
-
- public ITestInvocationListener getListeners() {
- return mListener;
- }
-
- /**
- * Determine that the test run failed with fatal errors.
- *
- * @return True if test run has a failure due to fatal error.
- */
- public boolean hasTestRunFatalError() {
- return (getNumTotalTests() > 0 && mFatalErrors.size() > 0);
- }
-
- public Map<String, String> getFatalErrors() {
- return mFatalErrors;
- }
-
- public String getErrorMessage() {
- StringBuilder sb = new StringBuilder();
- for (Map.Entry<String, String> error : mFatalErrors.entrySet()) {
- sb.append(error.getKey());
- sb.append(" : ");
- sb.append(error.getValue());
- sb.append("\n");
- }
- return sb.toString();
- }
- }
-
- protected class DefaultCollectingListener extends AbstractCollectingListener {
-
- public DefaultCollectingListener(ITestInvocationListener listener) {
- super(listener);
- }
-
- @Override
- public void handleMetricsOnTestEnded(TestIdentifier test, Map<String, String> testMetrics) {
- if (testMetrics == null) {
- return; // No-op if there is nothing to post.
- }
- getAggregatedMetrics().putAll(testMetrics);
- }
-
- @Override
- public void handleTestRunEnded(ITestInvocationListener listener, long elapsedTime,
- Map<String, String> runMetrics) {
- // Post aggregated metrics at the end of test run.
- listener.testRunEnded(getTestDurationMs(), getAggregatedMetrics());
- }
- }
-
- // TODO: Leverage AUPT to collect system logs (meminfo, ION allocations and processes/threads)
- private class MeminfoTimer {
-
- private static final String LOG_HEADER =
- "uptime,pssCameraDaemon,pssCameraApp,ramTotal,ramFree,ramUsed";
- private static final String DUMPSYS_MEMINFO_COMMAND =
- "dumpsys meminfo -c | grep -w -e " + "^ram -e ^time";
- private String[] mDumpsysMemInfoProc = {
- PROCESS_CAMERA_DAEMON, PROCESS_CAMERA_APP, PROCESS_MEDIASERVER
- };
- private static final int STATE_STOPPED = 0;
- private static final int STATE_SCHEDULED = 1;
- private static final int STATE_RUNNING = 2;
-
- private int mState = STATE_STOPPED;
- private Timer mTimer = new Timer(true); // run as a daemon thread
- private long mDelayMs = 0;
- private long mPeriodMs = 60 * 1000; // 60 sec
- private File mOutputFile = null;
- private String mCommand;
-
- public MeminfoTimer(long delayMs, long periodMs) {
- mDelayMs = delayMs;
- mPeriodMs = periodMs;
- mCommand = DUMPSYS_MEMINFO_COMMAND;
- for (String process : mDumpsysMemInfoProc) {
- mCommand += " -e " + process;
- }
- }
-
- synchronized void start(TestIdentifier test) {
- if (isRunning()) {
- stop();
- }
- // Create an output file.
- if (createOutputFile(test) == null) {
- CLog.w("Stop collecting meminfo since meminfo log file not found.");
- mState = STATE_STOPPED;
- return; // No-op
- }
- mTimer.scheduleAtFixedRate(new TimerTask() {
- @Override
- public void run() {
- mState = STATE_RUNNING;
- dumpMeminfo(mCommand, mOutputFile);
- }
- }, mDelayMs, mPeriodMs);
- mState = STATE_SCHEDULED;
- }
-
- synchronized void stop() {
- mState = STATE_STOPPED;
- mTimer.cancel();
- }
-
- synchronized boolean isRunning() {
- return (mState == STATE_RUNNING);
- }
-
- public File getOutputFile() {
- return mOutputFile;
- }
-
- private File createOutputFile(TestIdentifier test) {
- try {
- mOutputFile = FileUtil.createTempFile(
- String.format("meminfo_%s", test.getTestName()), "csv");
- BufferedWriter writer = new BufferedWriter(new FileWriter(mOutputFile, false));
- writer.write(LOG_HEADER);
- writer.newLine();
- writer.flush();
- writer.close();
- } catch (IOException e) {
- CLog.w("Failed to create meminfo log file %s:", mOutputFile.getAbsolutePath());
- CLog.e(e);
- return null;
- }
- return mOutputFile;
- }
- }
-
- void dumpMeminfo(String command, File outputFile) {
- try {
- CollectingOutputReceiver receiver = new CollectingOutputReceiver();
- // Dump meminfo in a compact form.
- getDevice().executeShellCommand(command, receiver,
- SHELL_TIMEOUT_MS, TimeUnit.MILLISECONDS, SHELL_MAX_ATTEMPTS);
- printMeminfo(outputFile, receiver.getOutput());
- } catch (DeviceNotAvailableException e) {
- CLog.w("Failed to dump meminfo:");
- CLog.e(e);
- }
- }
-
- void printMeminfo(File outputFile, String meminfo) {
- // Parse meminfo and print each iteration in a line in a .csv format. The meminfo output
- // are separated into three different formats:
- //
- // Format: time,<uptime>,<realtime>
- // eg. "time,59459911,63354673"
- //
- // Format: proc,<oom_label>,<process_name>,<pid>,<pss>,<hasActivities>
- // eg. "proc,native,mm-qcamera-daemon,522,12881,e"
- // "proc,fore,com.google.android.GoogleCamera,26560,70880,a"
- //
- // Format: ram,<total>,<free>,<used>
- // eg. "ram,1857364,810189,541516"
- BufferedWriter writer = null;
- BufferedReader reader = null;
- try {
- final String DELIMITER = ",";
- writer = new BufferedWriter(new FileWriter(outputFile, true));
- reader = new BufferedReader(new StringReader(meminfo));
- String line;
- String uptime = null;
- String pssCameraNative = null;
- String pssCameraApp = null;
- String ramTotal = null;
- String ramFree = null;
- String ramUsed = null;
- while ((line = reader.readLine()) != null) {
- if (line.startsWith("time")) {
- uptime = line.split(DELIMITER)[1];
- } else if (line.startsWith("ram")) {
- String[] ram = line.split(DELIMITER);
- ramTotal = ram[1];
- ramFree = ram[2];
- ramUsed = ram[3];
- } else if (line.contains(PROCESS_CAMERA_DAEMON)) {
- pssCameraNative = line.split(DELIMITER)[4];
- } else if (line.contains(PROCESS_CAMERA_APP)) {
- pssCameraApp = line.split(DELIMITER)[4];
- }
- }
- String printMsg = String.format(
- "%s,%s,%s,%s,%s,%s", uptime, pssCameraNative, pssCameraApp,
- ramTotal, ramFree, ramUsed);
- writer.write(printMsg);
- writer.newLine();
- writer.flush();
- } catch (IOException e) {
- CLog.w("Failed to print meminfo to %s:", outputFile.getAbsolutePath());
- CLog.e(e);
- } finally {
- StreamUtil.close(writer);
- }
- }
-
- // TODO: Leverage AUPT to collect system logs (meminfo, ION allocations and processes/threads)
- private class ThreadTrackerTimer {
-
- // list all threads in a given process, remove the first header line, squeeze whitespaces,
- // select thread name (in 14th column), then sort and group by its name.
- // Examples:
- // 3 SoundPoolThread
- // 3 SoundPool
- // 2 Camera Job Disp
- // 1 pool-7-thread-1
- // 1 pool-6-thread-1
- // FIXME: Resolve the error "sh: syntax error: '|' unexpected" using the command below
- // $ /system/bin/ps -t -p %s | tr -s ' ' | cut -d' ' -f13- | sort | uniq -c | sort -nr"
- private static final String PS_COMMAND_FORMAT = "/system/bin/ps -t -p %s";
- private static final String PGREP_COMMAND_FORMAT = "pgrep %s";
- private static final int STATE_STOPPED = 0;
- private static final int STATE_SCHEDULED = 1;
- private static final int STATE_RUNNING = 2;
-
- private int mState = STATE_STOPPED;
- private Timer mTimer = new Timer(true); // run as a daemon thread
- private long mDelayMs = 0;
- private long mPeriodMs = 60 * 1000; // 60 sec
- private File mOutputFile = null;
-
- public ThreadTrackerTimer(long delayMs, long periodMs) {
- mDelayMs = delayMs;
- mPeriodMs = periodMs;
- }
-
- synchronized void start(TestIdentifier test) {
- if (isRunning()) {
- stop();
- }
- // Create an output file.
- if (createOutputFile(test) == null) {
- CLog.w("Stop collecting thread counts since log file not found.");
- mState = STATE_STOPPED;
- return; // No-op
- }
- mTimer.scheduleAtFixedRate(new TimerTask() {
- @Override
- public void run() {
- mState = STATE_RUNNING;
- dumpThreadCount(PS_COMMAND_FORMAT, getPid(PROCESS_CAMERA_APP), mOutputFile);
- }
- }, mDelayMs, mPeriodMs);
- mState = STATE_SCHEDULED;
- }
-
- synchronized void stop() {
- mState = STATE_STOPPED;
- mTimer.cancel();
- }
-
- synchronized boolean isRunning() {
- return (mState == STATE_RUNNING);
- }
-
- public File getOutputFile() {
- return mOutputFile;
- }
-
- File createOutputFile(TestIdentifier test) {
- try {
- mOutputFile = FileUtil.createTempFile(
- String.format("ps_%s", test.getTestName()), "txt");
- new BufferedWriter(new FileWriter(mOutputFile, false)).close();
- } catch (IOException e) {
- CLog.w("Failed to create processes and threads file %s:",
- mOutputFile.getAbsolutePath());
- CLog.e(e);
- return null;
- }
- return mOutputFile;
- }
-
- String getPid(String processName) {
- String result = null;
- try {
- result = getDevice().executeShellCommand(String.format(PGREP_COMMAND_FORMAT,
- processName));
- } catch (DeviceNotAvailableException e) {
- CLog.w("Failed to get pid %s:", processName);
- CLog.e(e);
- }
- return result;
- }
-
- String getUptime() {
- String uptime = null;
- try {
- // uptime will typically have a format like "5278.73 1866.80". Use the first one
- // (which is wall-time)
- uptime = getDevice().executeShellCommand("cat /proc/uptime").split(" ")[0];
- Float.parseFloat(uptime);
- } catch (NumberFormatException e) {
- CLog.w("Failed to get valid uptime %s: %s", uptime, e);
- } catch (DeviceNotAvailableException e) {
- CLog.w("Failed to get valid uptime: %s", e);
- }
- return uptime;
- }
-
- void dumpThreadCount(String commandFormat, String pid, File outputFile) {
- try {
- if ("".equals(pid)) {
- return;
- }
- String result = getDevice().executeShellCommand(String.format(commandFormat, pid));
- String header = String.format("UPTIME: %s", getUptime());
- BufferedWriter writer = new BufferedWriter(new FileWriter(outputFile, true));
- writer.write(header);
- writer.newLine();
- writer.write(result);
- writer.newLine();
- writer.flush();
- writer.close();
- } catch (DeviceNotAvailableException | IOException e) {
- CLog.w("Failed to dump thread count:");
- CLog.e(e);
- }
- }
- }
-
- // TODO: Leverage AUPT to collect system logs (meminfo, ION allocations and
- // processes/threads)
- protected void dumpIonHeaps(ITestInvocationListener listener, String testClass) {
- if (!shouldDumpIonHeap()) {
- return; // No-op if option is not set.
- }
- try {
- String result = getDevice().executeShellCommand(DUMP_ION_HEAPS_COMMAND);
- if (!"".equals(result)) {
- String fileName = String.format("ionheaps_%s_onEnd", testClass);
- listener.testLog(fileName, LogDataType.TEXT,
- new ByteArrayInputStreamSource(result.getBytes()));
- }
- } catch (DeviceNotAvailableException e) {
- CLog.w("Failed to dump ION heaps:");
- CLog.e(e);
- }
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public void setDevice(ITestDevice device) {
- mDevice = device;
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public ITestDevice getDevice() {
- return mDevice;
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public void setConfiguration(IConfiguration configuration) {
- mConfiguration = configuration;
- }
-
- /**
- * Get the {@link IRunUtil} instance to use.
- * <p/>
- * Exposed so unit tests can mock.
- */
- IRunUtil getRunUtil() {
- return RunUtil.getDefault();
- }
-
- /**
- * Get the duration of Camera test instrumentation in milliseconds.
- *
- * @return the duration of Camera instrumentation test until it is called.
- */
- public long getTestDurationMs() {
- return System.currentTimeMillis() - mStartTimeMs;
- }
-
- public String getTestPackage() {
- return mTestPackage;
- }
-
- public void setTestPackage(String testPackage) {
- mTestPackage = testPackage;
- }
-
- public String getTestClass() {
- return mTestClass;
- }
-
- public void setTestClass(String testClass) {
- mTestClass = testClass;
- }
-
- public String getTestRunner() {
- return mTestRunner;
- }
-
- public void setTestRunner(String testRunner) {
- mTestRunner = testRunner;
- }
-
- public int getTestTimeoutMs() {
- return mTestTimeoutMs;
- }
-
- public void setTestTimeoutMs(int testTimeoutMs) {
- mTestTimeoutMs = testTimeoutMs;
- }
-
- public long getShellTimeoutMs() {
- return mShellTimeoutMs;
- }
-
- public void setShellTimeoutMs(long shellTimeoutMs) {
- mShellTimeoutMs = shellTimeoutMs;
- }
-
- public String getRuKey() {
- return mRuKey;
- }
-
- public void setRuKey(String ruKey) {
- mRuKey = ruKey;
- }
-
- public boolean shouldDumpMeminfo() {
- return mDumpMeminfo;
- }
-
- public boolean shouldDumpIonHeap() {
- return mDumpIonHeap;
- }
-
- public boolean shouldDumpThreadCount() {
- return mDumpThreadCount;
- }
-
- public AbstractCollectingListener getCollectingListener() {
- return mCollectingListener;
- }
-
- public void setLogcatOnFailure(boolean logcatOnFailure) {
- mLogcatOnFailure = logcatOnFailure;
- }
-
- public int getIterationCount() {
- return mIterations;
- }
-
- public Map<String, String> getInstrumentationArgMap() { return mInstrArgMap; }
-}
diff --git a/src/com/android/media/tests/MediaMemoryTest.java b/src/com/android/media/tests/MediaMemoryTest.java
deleted file mode 100644
index bb09488..0000000
--- a/src/com/android/media/tests/MediaMemoryTest.java
+++ /dev/null
@@ -1,280 +0,0 @@
-/*
- * Copyright (C) 2011 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.media.tests;
-
-import com.android.ddmlib.IDevice;
-import com.android.ddmlib.testrunner.IRemoteAndroidTestRunner;
-import com.android.ddmlib.testrunner.RemoteAndroidTestRunner;
-import com.android.tradefed.config.Option;
-import com.android.tradefed.device.DeviceNotAvailableException;
-import com.android.tradefed.device.ITestDevice;
-import com.android.tradefed.log.LogUtil.CLog;
-import com.android.tradefed.result.BugreportCollector;
-import com.android.tradefed.result.BugreportCollector.Freq;
-import com.android.tradefed.result.BugreportCollector.Noun;
-import com.android.tradefed.result.BugreportCollector.Relation;
-import com.android.tradefed.result.FileInputStreamSource;
-import com.android.tradefed.result.ITestInvocationListener;
-import com.android.tradefed.result.InputStreamSource;
-import com.android.tradefed.result.LogDataType;
-import com.android.tradefed.testtype.IDeviceTest;
-import com.android.tradefed.testtype.IRemoteTest;
-import com.android.tradefed.util.FileUtil;
-import com.android.tradefed.util.StreamUtil;
-
-import org.junit.Assert;
-
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.ListIterator;
-import java.util.Map;
-import java.util.concurrent.TimeUnit;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-
-/**
- * Runs the Media memory test. This test will do various media actions ( ie.
- * playback, recording and etc.) then capture the snapshot of mediaserver memory
- * usage. The test summary is save to /sdcard/mediaMemOutput.txt
- * <p/>
- * Note that this test will not run properly unless /sdcard is mounted and
- * writable.
- */
-public class MediaMemoryTest implements IDeviceTest, IRemoteTest {
-
- ITestDevice mTestDevice = null;
-
- private static final String METRICS_RUN_NAME = "MediaMemoryLeak";
-
- // Constants for running the tests
- private static final String TEST_CLASS_NAME =
- "com.android.mediaframeworktest.performance.MediaPlayerPerformance";
- private static final String TEST_PACKAGE_NAME = "com.android.mediaframeworktest";
- private static final String TEST_RUNNER_NAME = ".MediaFrameworkPerfTestRunner";
-
- private final String mOutputPaths[] = {"mediaMemOutput.txt","mediaProcmemOutput.txt"};
-
- //Max test timeout - 4 hrs
- private static final int MAX_TEST_TIMEOUT = 4 * 60 * 60 * 1000;
-
- public Map<String, String> mPatternMap = new HashMap<>();
- private static final Pattern TOTAL_MEM_DIFF_PATTERN =
- Pattern.compile("^The total diff = (\\d+)");
-
- @Option(name = "getHeapDump", description = "Collect the heap ")
- private boolean mGetHeapDump = false;
-
- @Option(name = "getProcMem", description = "Collect the procmem info ")
- private boolean mGetProcMem = false;
-
- @Option(name = "testName", description = "Test name to run. May be repeated.")
- private Collection<String> mTests = new LinkedList<>();
-
- public MediaMemoryTest() {
- mPatternMap.put("testCameraPreviewMemoryUsage", "CameraPreview");
- mPatternMap.put("testRecordAudioOnlyMemoryUsage", "AudioRecord");
- mPatternMap.put("testH263VideoPlaybackMemoryUsage", "H263Playback");
- mPatternMap.put("testRecordVideoAudioMemoryUsage", "H263RecordVideoAudio");
- mPatternMap.put("testH263RecordVideoOnlyMemoryUsage", "H263RecordVideoOnly");
- mPatternMap.put("testH264VideoPlaybackMemoryUsage", "H264Playback");
- mPatternMap.put("testMpeg4RecordVideoOnlyMemoryUsage", "MPEG4RecordVideoOnly");
- }
-
-
- @Override
- public void run(ITestInvocationListener listener) throws DeviceNotAvailableException {
- Assert.assertNotNull(mTestDevice);
-
- IRemoteAndroidTestRunner runner = new RemoteAndroidTestRunner(TEST_PACKAGE_NAME,
- TEST_RUNNER_NAME, mTestDevice.getIDevice());
- runner.setClassName(TEST_CLASS_NAME);
- runner.setMaxTimeToOutputResponse(MAX_TEST_TIMEOUT, TimeUnit.MILLISECONDS);
- if (mGetHeapDump) {
- runner.addInstrumentationArg("get_heap_dump", "true");
- }
- if (mGetProcMem) {
- runner.addInstrumentationArg("get_procmem", "true");
- }
-
- BugreportCollector bugListener = new BugreportCollector(listener,
- mTestDevice);
- bugListener.addPredicate(new BugreportCollector.Predicate(
- Relation.AFTER, Freq.EACH, Noun.TESTRUN));
-
- if (mTests.size() > 0) {
- for (String testName : mTests) {
- runner.setMethodName(TEST_CLASS_NAME, testName);
- mTestDevice.runInstrumentationTests(runner, bugListener);
- }
- } else {
- mTestDevice.runInstrumentationTests(runner, bugListener);
- }
- logOutputFiles(listener);
- cleanResultFile();
- }
-
- /**
- * Clean up the test result file from test run
- */
- private void cleanResultFile() throws DeviceNotAvailableException {
- String extStore = mTestDevice.getMountPoint(IDevice.MNT_EXTERNAL_STORAGE);
- for(String outputPath : mOutputPaths){
- mTestDevice.executeShellCommand(String.format("rm %s/%s", extStore, outputPath));
- }
- if (mGetHeapDump) {
- mTestDevice.executeShellCommand(String.format("rm %s/%s", extStore, "*.dump"));
- }
- }
-
- private void uploadHeapDumpFiles(ITestInvocationListener listener)
- throws DeviceNotAvailableException {
- // Pull and upload the heap dump output files.
- InputStreamSource outputSource = null;
- File outputFile = null;
-
- String extStore = mTestDevice.getMountPoint(IDevice.MNT_EXTERNAL_STORAGE);
-
- String out = mTestDevice.executeShellCommand(String.format("ls %s/%s",
- extStore, "*.dump"));
- String heapOutputFiles[] = out.split("\n");
-
- for (String heapFile : heapOutputFiles) {
- try {
- outputFile = mTestDevice.pullFile(heapFile.trim());
- if (outputFile == null) {
- continue;
- }
- outputSource = new FileInputStreamSource(outputFile);
- listener.testLog(heapFile, LogDataType.TEXT, outputSource);
- } finally {
- FileUtil.deleteFile(outputFile);
- StreamUtil.cancel(outputSource);
- }
- }
- }
-
- /**
- * Pull the output files from the device, add it to the logs, and also parse
- * out the relevant test metrics and report them.
- */
- private void logOutputFiles(ITestInvocationListener listener)
- throws DeviceNotAvailableException {
- File outputFile = null;
- InputStreamSource outputSource = null;
-
- if (mGetHeapDump) {
- // Upload all the heap dump files.
- uploadHeapDumpFiles(listener);
- }
- for(String outputPath : mOutputPaths){
- try {
- outputFile = mTestDevice.pullFileFromExternal(outputPath);
-
- if (outputFile == null) {
- return;
- }
-
- // Upload a verbatim copy of the output file
- CLog.d("Sending %d byte file %s into the logosphere!",
- outputFile.length(), outputFile);
- outputSource = new FileInputStreamSource(outputFile);
- listener.testLog(outputPath, LogDataType.TEXT, outputSource);
-
- // Parse the output file to upload aggregated metrics
- parseOutputFile(new FileInputStream(outputFile), listener);
- } catch (IOException e) {
- CLog.e("IOException while reading or parsing output file: %s",
- e.getMessage());
- } finally {
- FileUtil.deleteFile(outputFile);
- StreamUtil.cancel(outputSource);
- }
- }
- }
-
- /**
- * Parse the relevant metrics from the Instrumentation test output file
- */
- private void parseOutputFile(InputStream dataStream,
- ITestInvocationListener listener) {
-
- Map<String, String> runMetrics = new HashMap<>();
-
- // try to parse it
- String contents;
- try {
- contents = StreamUtil.getStringFromStream(dataStream);
- } catch (IOException e) {
- CLog.e("Got IOException during test processing: %s",
- e.getMessage());
- return;
- }
-
- List<String> lines = Arrays.asList(contents.split("\n"));
- ListIterator<String> lineIter = lines.listIterator();
- String line;
- while (lineIter.hasNext()) {
- line = lineIter.next();
- if (mPatternMap.containsKey(line)) {
-
- String key = mPatternMap.get(line);
- // Look for the total diff
- while (lineIter.hasNext()) {
- line = lineIter.next();
- Matcher m = TOTAL_MEM_DIFF_PATTERN.matcher(line);
- if (m.matches()) {
- int result = Integer.parseInt(m.group(1));
- runMetrics.put(key, Integer.toString(result));
- break;
- }
- }
- } else {
- CLog.e("Got unmatched line: %s", line);
- continue;
- }
- }
- reportMetrics(listener, runMetrics);
- }
-
- /**
- * Report run metrics by creating an empty test run to stick them in
- * <p />
- * Exposed for unit testing
- */
- void reportMetrics(ITestInvocationListener listener, Map<String, String> metrics) {
- CLog.d("About to report metrics: %s", metrics);
- listener.testRunStarted(METRICS_RUN_NAME, 0);
- listener.testRunEnded(0, metrics);
- }
-
- @Override
- public void setDevice(ITestDevice device) {
- mTestDevice = device;
- }
-
- @Override
- public ITestDevice getDevice() {
- return mTestDevice;
- }
-}
diff --git a/src/com/android/media/tests/MediaPlayerStressTest.java b/src/com/android/media/tests/MediaPlayerStressTest.java
deleted file mode 100644
index 8efab3e..0000000
--- a/src/com/android/media/tests/MediaPlayerStressTest.java
+++ /dev/null
@@ -1,212 +0,0 @@
-/*
- * Copyright (C) 2011 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.media.tests;
-
-import com.android.ddmlib.IDevice;
-import com.android.ddmlib.Log;
-import com.android.ddmlib.testrunner.IRemoteAndroidTestRunner;
-import com.android.ddmlib.testrunner.RemoteAndroidTestRunner;
-import com.android.tradefed.config.Option;
-import com.android.tradefed.config.Option.Importance;
-import com.android.tradefed.device.DeviceNotAvailableException;
-import com.android.tradefed.device.ITestDevice;
-import com.android.tradefed.result.BugreportCollector;
-import com.android.tradefed.result.BugreportCollector.Freq;
-import com.android.tradefed.result.BugreportCollector.Noun;
-import com.android.tradefed.result.BugreportCollector.Relation;
-import com.android.tradefed.result.FileInputStreamSource;
-import com.android.tradefed.result.ITestInvocationListener;
-import com.android.tradefed.result.InputStreamSource;
-import com.android.tradefed.result.LogDataType;
-import com.android.tradefed.testtype.IDeviceTest;
-import com.android.tradefed.testtype.IRemoteTest;
-import com.android.tradefed.util.FileUtil;
-import com.android.tradefed.util.RegexTrie;
-import com.android.tradefed.util.StreamUtil;
-
-import org.junit.Assert;
-
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.HashMap;
-import java.util.List;
-import java.util.ListIterator;
-import java.util.Map;
-import java.util.concurrent.TimeUnit;
-
-/**
- * Runs the Media Player stress test. This test will play the video files under
- * the /sdcard/samples folder and capture the video playback event statistics in
- * a text file under /sdcard/PlaybackTestResult.txt
- * <p/>
- * Note that this test will not run properly unless /sdcard is mounted and
- * writable.
- */
-public class MediaPlayerStressTest implements IDeviceTest, IRemoteTest {
- private static final String LOG_TAG = "MediaPlayerStress";
-
- ITestDevice mTestDevice = null;
- @Option(name = "test-class", importance = Importance.ALWAYS)
- private String mTestClassName =
- "com.android.mediaframeworktest.stress.MediaPlayerStressTest";
- @Option(name = "metrics-name", importance = Importance.ALWAYS)
- private String mMetricsRunName = "MediaPlayerStress";
- @Option(name = "result-file", importance = Importance.ALWAYS)
- private String mOutputPath = "PlaybackTestResult.txt";
-
- //Max test timeout - 10 hrs
- private static final int MAX_TEST_TIMEOUT = 10 * 60 * 60 * 1000;
-
- // Constants for running the tests
- private static final String TEST_PACKAGE_NAME = "com.android.mediaframeworktest";
- private static final String TEST_RUNNER_NAME = ".MediaPlayerStressTestRunner";
-
- public RegexTrie<String> mPatternMap = new RegexTrie<>();
-
- public MediaPlayerStressTest() {
- mPatternMap.put("PlaybackPass", "^Total Complete: (\\d+)");
- mPatternMap.put("PlaybackCrash", "^Total Error: (\\d+)");
- mPatternMap.put("TrackLagging", "^Total Track Lagging: (\\d+)");
- mPatternMap.put("BadInterleave", "^Total Bad Interleaving: (\\d+)");
- mPatternMap.put("FailedToCompleteWithNoError",
- "^Total Failed To Complete With No Error: (\\d+)");
- }
-
- @Override
- public void run(ITestInvocationListener listener) throws DeviceNotAvailableException {
- Assert.assertNotNull(mTestDevice);
- IRemoteAndroidTestRunner runner = new RemoteAndroidTestRunner(TEST_PACKAGE_NAME,
- TEST_RUNNER_NAME, mTestDevice.getIDevice());
- runner.setClassName(mTestClassName);
- runner.setMaxTimeToOutputResponse(MAX_TEST_TIMEOUT, TimeUnit.MILLISECONDS);
-
- BugreportCollector bugListener = new BugreportCollector(listener,
- mTestDevice);
- bugListener.addPredicate(BugreportCollector.AFTER_FAILED_TESTCASES);
- bugListener.setDescriptiveName("media_player_stress_test");
- bugListener.addPredicate(new BugreportCollector.Predicate(
- Relation.AFTER, Freq.EACH, Noun.TESTRUN));
-
- mTestDevice.runInstrumentationTests(runner, bugListener);
-
- logOutputFile(listener);
- cleanResultFile();
- }
-
- /**
- * Clean up the test result file from test run
- */
- private void cleanResultFile() throws DeviceNotAvailableException {
- String extStore = mTestDevice.getMountPoint(IDevice.MNT_EXTERNAL_STORAGE);
- mTestDevice.executeShellCommand(String.format("rm %s/%s", extStore, mOutputPath));
- }
-
- /**
- * Pull the output file from the device, add it to the logs, and also parse
- * out the relevant test metrics and report them.
- */
- private void logOutputFile(ITestInvocationListener listener)
- throws DeviceNotAvailableException {
- File outputFile = null;
- InputStreamSource outputSource = null;
- try {
- outputFile = mTestDevice.pullFileFromExternal(mOutputPath);
-
- if (outputFile == null) {
- return;
- }
-
- // Upload a verbatim copy of the output file
- Log.d(LOG_TAG, String.format("Sending %d byte file %s into the logosphere!",
- outputFile.length(), outputFile));
- outputSource = new FileInputStreamSource(outputFile);
- listener.testLog(mOutputPath, LogDataType.TEXT, outputSource);
- // Parse the output file to upload aggregated metrics
- parseOutputFile(new FileInputStream(outputFile), listener);
- } catch (IOException e) {
- Log.e(LOG_TAG, String.format(
- "IOException while reading or parsing output file: %s", e));
- } finally {
- FileUtil.deleteFile(outputFile);
- StreamUtil.cancel(outputSource);
- }
- }
-
- /**
- * Parse the relevant metrics from the Instrumentation test output file
- */
- private void parseOutputFile(InputStream dataStream,
- ITestInvocationListener listener) {
- Map<String, String> runMetrics = new HashMap<>();
-
- // try to parse it
- String contents;
- try {
- contents = StreamUtil.getStringFromStream(dataStream);
- } catch (IOException e) {
- Log.e(LOG_TAG, String.format(
- "Got IOException during test processing: %s", e));
- return;
- }
-
- List<String> lines = Arrays.asList(contents.split("\n"));
- ListIterator<String> lineIter = lines.listIterator();
- String line;
- while (lineIter.hasNext()) {
- line = lineIter.next();
- List<List<String>> capture = new ArrayList<>(1);
- String key = mPatternMap.retrieve(capture, line);
- if (key != null) {
- Log.d(LOG_TAG, String.format("Got '%s' and captures '%s'",
- key, capture.toString()));
- } else if (line.isEmpty()) {
- // ignore
- continue;
- } else {
- Log.d(LOG_TAG, String.format("Got unmatched line: %s", line));
- continue;
- }
- runMetrics.put(key, capture.get(0).get(0));
- }
- reportMetrics(listener, runMetrics);
- }
-
- /**
- * Report run metrics by creating an empty test run to stick them in
- * <p />
- * Exposed for unit testing
- */
- void reportMetrics(ITestInvocationListener listener, Map<String, String> metrics) {
- Log.d(LOG_TAG, String.format("About to report metrics: %s", metrics));
- listener.testRunStarted(mMetricsRunName, 0);
- listener.testRunEnded(0, metrics);
- }
-
- @Override
- public void setDevice(ITestDevice device) {
- mTestDevice = device;
- }
-
- @Override
- public ITestDevice getDevice() {
- return mTestDevice;
- }
-}
diff --git a/src/com/android/media/tests/MediaResultReporter.java b/src/com/android/media/tests/MediaResultReporter.java
deleted file mode 100644
index 0d348c3..0000000
--- a/src/com/android/media/tests/MediaResultReporter.java
+++ /dev/null
@@ -1,94 +0,0 @@
-/*
- * Copyright (C) 2011 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.media.tests;
-
-import com.android.ddmlib.Log;
-import com.android.tradefed.config.Option;
-import com.android.tradefed.result.EmailResultReporter;
-import com.android.tradefed.result.InputStreamSource;
-import com.android.tradefed.result.LogDataType;
-import com.android.tradefed.result.TestSummary;
-
-import java.io.IOException;
-import java.io.InputStreamReader;
-import java.io.Reader;
-import java.util.List;
-
-/**
- * Media reporter that send the test summary through email.
- */
-public class MediaResultReporter extends EmailResultReporter {
-
- private static final String LOG_TAG = "MediaResultReporter";
-
- public StringBuilder mEmailBodyBuilder;
- private String mSummaryUrl = "";
-
- @Option(name = "log-name", description = "Name of the report that attach to email")
- private String mLogName = null;
-
- public MediaResultReporter() {
- mEmailBodyBuilder = new StringBuilder();
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public String generateEmailBody() {
- return mEmailBodyBuilder.toString();
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public void putSummary(List<TestSummary> summaries) {
- // Get the summary url
- if (summaries.isEmpty()) {
- return;
- }
- mSummaryUrl = summaries.get(0).getSummary().getString();
- mEmailBodyBuilder.append(mSummaryUrl);
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public void testLog(String dataName, LogDataType dataType, InputStreamSource dataStream) {
-
- char[] buf = new char[2048];
-
- try {
- //Attached the test summary to the email body
- if (mLogName.equals(dataName)) {
- Reader r = new InputStreamReader(dataStream.createInputStream());
- while (true) {
- int n = r.read(buf);
- if (n < 0) {
- break;
- }
- mEmailBodyBuilder.append(buf, 0, n);
- }
- mEmailBodyBuilder.append('\n');
- }
- } catch (IOException e) {
- Log.w(LOG_TAG, String.format("Exception while parsing %s: %s", dataName, e));
- }
- }
-}
diff --git a/src/com/android/media/tests/MediaStressTest.java b/src/com/android/media/tests/MediaStressTest.java
deleted file mode 100644
index 189dd60..0000000
--- a/src/com/android/media/tests/MediaStressTest.java
+++ /dev/null
@@ -1,225 +0,0 @@
-/*
- * Copyright (C) 2011 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.media.tests;
-
-import com.android.ddmlib.IDevice;
-import com.android.ddmlib.testrunner.IRemoteAndroidTestRunner;
-import com.android.ddmlib.testrunner.RemoteAndroidTestRunner;
-import com.android.tradefed.device.DeviceNotAvailableException;
-import com.android.tradefed.device.ITestDevice;
-import com.android.tradefed.log.LogUtil.CLog;
-import com.android.tradefed.result.FileInputStreamSource;
-import com.android.tradefed.result.ITestInvocationListener;
-import com.android.tradefed.result.InputStreamSource;
-import com.android.tradefed.result.LogDataType;
-import com.android.tradefed.testtype.IDeviceTest;
-import com.android.tradefed.testtype.IRemoteTest;
-import com.android.tradefed.util.FileUtil;
-import com.android.tradefed.util.StreamUtil;
-
-import org.junit.Assert;
-
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.util.Arrays;
-import java.util.HashMap;
-import java.util.List;
-import java.util.ListIterator;
-import java.util.Map;
-import java.util.concurrent.TimeUnit;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-
-/**
- * Runs the Media stress testcases.
- * FIXME: more details
- * <p/>
- * Note that this test will not run properly unless /sdcard is mounted and writable.
- */
-public class MediaStressTest implements IDeviceTest, IRemoteTest {
-
- ITestDevice mTestDevice = null;
- private static final String METRICS_RUN_NAME = "VideoRecordingStress";
-
- //Max test timeout - 2 hrs
- private static final int MAX_TEST_TIMEOUT = 2 * 60 * 60 * 1000;
-
- // Constants for running the tests
- private static final String TEST_CLASS_NAME =
- "com.android.mediaframeworktest.stress.MediaRecorderStressTest";
- private static final String TEST_PACKAGE_NAME = "com.android.mediaframeworktest";
- private static final String TEST_RUNNER_NAME = ".MediaRecorderStressTestRunner";
-
- // Constants for parsing the output file
- private static final Pattern EXPECTED_LOOP_COUNT_PATTERN =
- Pattern.compile("Total number of loops:\\s*(\\d+)");
- private static final Pattern ACTUAL_LOOP_COUNT_PATTERN =
- Pattern.compile("No of loop:.*,\\s*(\\d+)\\s*");
- private static final String OUTPUT_PATH = "mediaStressOutput.txt";
-
- @Override
- public void run(ITestInvocationListener listener) throws DeviceNotAvailableException {
- Assert.assertNotNull(mTestDevice);
-
- IRemoteAndroidTestRunner runner = new RemoteAndroidTestRunner(TEST_PACKAGE_NAME,
- TEST_RUNNER_NAME, mTestDevice.getIDevice());
- runner.setClassName(TEST_CLASS_NAME);
- runner.setMaxTimeToOutputResponse(MAX_TEST_TIMEOUT, TimeUnit.MILLISECONDS);
-
- cleanTmpFiles();
- mTestDevice.runInstrumentationTests(runner, listener);
- logOutputFile(listener);
- cleanTmpFiles();
- }
-
- /**
- * Clean up temp files from test runs
- */
- private void cleanTmpFiles() throws DeviceNotAvailableException {
- String extStore = mTestDevice.getMountPoint(IDevice.MNT_EXTERNAL_STORAGE);
- mTestDevice.executeShellCommand(String.format("rm %s/temp*.3gp", extStore));
- mTestDevice.executeShellCommand(String.format("rm %s/%s", extStore, OUTPUT_PATH));
- }
-
- /**
- * Pull the output file from the device, add it to the logs, and also parse out the relevant
- * test metrics and report them.
- */
- private void logOutputFile(ITestInvocationListener listener)
- throws DeviceNotAvailableException {
- File outputFile = null;
- InputStreamSource outputSource = null;
- try {
- outputFile = mTestDevice.pullFileFromExternal(OUTPUT_PATH);
-
- if (outputFile == null) {
- return;
- }
-
- CLog.d("Sending %d byte file %s into the logosphere!", outputFile.length(), outputFile);
- outputSource = new FileInputStreamSource(outputFile);
- listener.testLog(OUTPUT_PATH, LogDataType.TEXT, outputSource);
- parseOutputFile(outputFile, listener);
- } finally {
- FileUtil.deleteFile(outputFile);
- StreamUtil.cancel(outputSource);
- }
- }
-
- /**
- * Parse the relevant metrics from the Instrumentation test output file
- */
- private void parseOutputFile(File outputFile, ITestInvocationListener listener) {
- Map<String, String> runMetrics = new HashMap<>();
- Map<String, String> stanzaKeyMap = new HashMap<>();
- stanzaKeyMap.put("testStressRecordVideoAndPlayback1080P", "VideoRecordPlayback1080P");
- stanzaKeyMap.put("testStressRecordVideoAndPlayback720P", "VideoRecordPlayback720P");
- stanzaKeyMap.put("testStressRecordVideoAndPlayback480P", "VideoRecordPlayback480P");
- stanzaKeyMap.put("testStressTimeLapse", "TimeLapseRecord");
-
- // try to parse it
- String contents;
- try {
- InputStream dataStream = new FileInputStream(outputFile);
- contents = StreamUtil.getStringFromStream(dataStream);
- } catch (IOException e) {
- CLog.e("IOException while parsing the output file:");
- CLog.e(e);
- return;
- }
-
- List<String> lines = Arrays.asList(contents.split("\n"));
- ListIterator<String> lineIter = lines.listIterator();
- String line;
- while (lineIter.hasNext()) {
- line = lineIter.next();
- String key = null;
-
- if (stanzaKeyMap.containsKey(line)) {
- key = stanzaKeyMap.get(line);
- } else {
- CLog.d("Got unexpected line: %s", line);
- continue;
- }
-
- Integer countExpected = getIntFromOutput(lineIter, EXPECTED_LOOP_COUNT_PATTERN);
- Integer countActual = getIntFromOutput(lineIter, ACTUAL_LOOP_COUNT_PATTERN);
- int value = coalesceLoopCounts(countActual, countExpected);
- runMetrics.put(key, Integer.toString(value));
- }
-
- reportMetrics(listener, runMetrics);
- }
-
- /**
- * Report run metrics by creating an empty test run to stick them in
- * <p />
- * Exposed for unit testing
- */
- void reportMetrics(ITestInvocationListener listener, Map<String, String> metrics) {
- // Create an empty testRun to report the parsed runMetrics
- CLog.d("About to report metrics: %s", metrics);
- listener.testRunStarted(METRICS_RUN_NAME, 0);
- listener.testRunEnded(0, metrics);
- }
-
- /**
- * Use the provided {@link Pattern} to parse a number out of the output file
- */
- private Integer getIntFromOutput(ListIterator<String> lineIter, Pattern numPattern) {
- Integer retval = null;
- String line = null;
- if (lineIter.hasNext()) {
- line = lineIter.next();
- Matcher m = numPattern.matcher(line);
- if (m.matches()) {
- retval = Integer.parseInt(m.group(1));
- } else {
- CLog.e("Couldn't match pattern %s against line '%s'", numPattern, line);
- }
- } else {
- CLog.e("Encounted EOF while trying to match pattern %s", numPattern);
- }
-
- return retval;
- }
-
- /**
- * Given an actual and an expected iteration count, determine a single metric to report.
- */
- private int coalesceLoopCounts(Integer actual, Integer expected) {
- if (expected == null || expected <= 0) {
- return -1;
- } else if (actual == null) {
- return expected;
- } else {
- return actual;
- }
- }
-
- @Override
- public void setDevice(ITestDevice device) {
- mTestDevice = device;
- }
-
- @Override
- public ITestDevice getDevice() {
- return mTestDevice;
- }
-}
diff --git a/src/com/android/media/tests/MediaTest.java b/src/com/android/media/tests/MediaTest.java
deleted file mode 100644
index 473f989..0000000
--- a/src/com/android/media/tests/MediaTest.java
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * Copyright (C) 2012 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.media.tests;
-
-import junit.framework.TestCase;
-
-import java.util.regex.Matcher;
-
-
-public class MediaTest extends TestCase {
- private String mPositiveOutput = "testStressAddRemoveEffects diff : 472";
- private String mNegativeOutput = "testStressAddRemoveEffects diff : -123";
-
- private String mExpectedTestCaseName = "testStressAddRemoveEffects";
- private String mExpectedPositiveOut = "472";
- private String mExpectedNegativeOut = "-123";
-
- public void testVideoEditorPositiveOut() {
- Matcher m = VideoEditingMemoryTest.TOTAL_MEM_DIFF_PATTERN.matcher(mPositiveOutput);
- assertTrue(m.matches());
- assertEquals("Parse test case name", mExpectedTestCaseName, m.group(1));
- assertEquals("Paser positive out", mExpectedPositiveOut, m.group(2));
- }
-
- public void testVideoEditorNegativeOut() {
- Matcher m = VideoEditingMemoryTest.TOTAL_MEM_DIFF_PATTERN.matcher(mNegativeOutput);
- assertTrue(m.matches());
- assertEquals("Parse test case name", mExpectedTestCaseName, m.group(1));
- assertEquals("Paser negative out", mExpectedNegativeOut, m.group(2));
- }
-}
diff --git a/src/com/android/media/tests/PanoramaBenchMarkTest.java b/src/com/android/media/tests/PanoramaBenchMarkTest.java
deleted file mode 100644
index 355bbb0..0000000
--- a/src/com/android/media/tests/PanoramaBenchMarkTest.java
+++ /dev/null
@@ -1,129 +0,0 @@
-/*
- * Copyright (C) 2012 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.media.tests;
-
-import com.android.ddmlib.IDevice;
-import com.android.tradefed.device.DeviceNotAvailableException;
-import com.android.tradefed.device.ITestDevice;
-import com.android.tradefed.log.LogUtil.CLog;
-import com.android.tradefed.result.ITestInvocationListener;
-import com.android.tradefed.result.InputStreamSource;
-import com.android.tradefed.result.LogDataType;
-import com.android.tradefed.testtype.IDeviceTest;
-import com.android.tradefed.testtype.IRemoteTest;
-
-import org.junit.Assert;
-
-import java.util.HashMap;
-import java.util.Map;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-
-/**
- * Standalone panoramic photo processing benchmark test.
- */
-public class PanoramaBenchMarkTest implements IDeviceTest, IRemoteTest {
-
- private ITestDevice mTestDevice = null;
-
- private static final Pattern ELAPSED_TIME_PATTERN =
- Pattern.compile("(Total elapsed time:)\\s+(\\d+\\.\\d*)\\s+(seconds)");
-
- private static final String PANORAMA_TEST_KEY = "PanoramaElapsedTime";
- private static final String TEST_TAG = "CameraLatency";
-
- /**
- * {@inheritDoc}
- */
- @Override
- public void run(ITestInvocationListener listener) throws DeviceNotAvailableException {
- Assert.assertNotNull(mTestDevice);
-
- String dataStore = mTestDevice.getMountPoint(IDevice.MNT_DATA);
- String externalStore = mTestDevice.getMountPoint(IDevice.MNT_EXTERNAL_STORAGE);
-
- mTestDevice.executeShellCommand(String.format("chmod 777 %s/local/tmp/panorama_bench",
- dataStore));
-
- String shellOutput = mTestDevice.executeShellCommand(
- String.format("%s/local/tmp/panorama_bench %s/panorama_input/test %s/panorama.ppm",
- dataStore, externalStore, externalStore));
-
- String[] lines = shellOutput.split("\n");
-
- Map<String, String> metrics = new HashMap<String, String>();
- for (String line : lines) {
- Matcher m = ELAPSED_TIME_PATTERN.matcher(line.trim());
- if (m.matches()) {
- CLog.d(String.format("Found elapsed time \"%s seconds\" from line %s",
- m.group(2), line));
- metrics.put(PANORAMA_TEST_KEY, m.group(2));
- break;
- } else {
- CLog.d(String.format("Unabled to find elapsed time from line: %s", line));
- }
- }
-
- reportMetrics(listener, TEST_TAG, metrics);
- cleanupDevice();
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public void setDevice(ITestDevice device) {
- mTestDevice = device;
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public ITestDevice getDevice() {
- return mTestDevice;
- }
-
- /**
- * Removes image files used to mock panorama stitching.
- *
- * @throws DeviceNotAvailableException If the device is unavailable or
- * something happened while deleting files
- */
- private void cleanupDevice() throws DeviceNotAvailableException {
- String externalStore = mTestDevice.getMountPoint(IDevice.MNT_EXTERNAL_STORAGE);
- mTestDevice.executeShellCommand(String.format("rm -r %s/panorama_input", externalStore));
- }
-
- /**
- * Report run metrics by creating an empty test run to stick them in.
- *
- * @param listener The {@link ITestInvocationListener} of test results
- * @param runName The test name
- * @param metrics The {@link Map} that contains metrics for the given test
- */
- private void reportMetrics(ITestInvocationListener listener, String runName,
- Map<String, String> metrics) {
- InputStreamSource bugreport = mTestDevice.getBugreport();
- listener.testLog("bugreport", LogDataType.BUGREPORT, bugreport);
- bugreport.cancel();
-
- CLog.d(String.format("About to report metrics: %s", metrics));
- listener.testRunStarted(runName, 0);
- listener.testRunEnded(0, metrics);
- }
-}
diff --git a/src/com/android/media/tests/TestRunHelper.java b/src/com/android/media/tests/TestRunHelper.java
deleted file mode 100644
index f752cf3..0000000
--- a/src/com/android/media/tests/TestRunHelper.java
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.android.media.tests;
-
-import com.android.ddmlib.testrunner.TestIdentifier;
-import com.android.tradefed.log.LogUtil.CLog;
-import com.android.tradefed.result.ITestInvocationListener;
-
-import java.util.HashMap;
-import java.util.Map;
-
-/** Generic helper class for tests */
-public class TestRunHelper {
-
- private long mTestStartTime = -1;
- private long mTestStopTime = -1;
- private ITestInvocationListener mListener;
- private TestIdentifier mTestId;
-
- public TestRunHelper(ITestInvocationListener listener, TestIdentifier testId) {
- mListener = listener;
- mTestId = testId;
- }
-
- public long getTotalTestTime() {
- return mTestStopTime - mTestStartTime;
- }
-
- public void reportFailure(String errMsg) {
- CLog.e(errMsg);
- mListener.testFailed(mTestId, errMsg);
- mListener.testEnded(mTestId, new HashMap<String, String>());
- mListener.testRunFailed(errMsg);
- }
-
- /** @param resultDictionary */
- public void endTest(Map<String, String> resultDictionary) {
- mTestStopTime = System.currentTimeMillis();
- mListener.testEnded(mTestId, resultDictionary);
- mListener.testRunEnded(getTotalTestTime(), resultDictionary);
- }
-
- public void startTest(int numberOfTests) {
- mListener.testRunStarted(mTestId.getTestName(), numberOfTests);
- mListener.testStarted(mTestId);
- mTestStartTime = System.currentTimeMillis();
- }
-}
diff --git a/src/com/android/media/tests/VideoEditingMemoryTest.java b/src/com/android/media/tests/VideoEditingMemoryTest.java
deleted file mode 100644
index bb58df2..0000000
--- a/src/com/android/media/tests/VideoEditingMemoryTest.java
+++ /dev/null
@@ -1,268 +0,0 @@
-/*
- * Copyright (C) 2011 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.media.tests;
-
-import com.android.ddmlib.IDevice;
-import com.android.ddmlib.Log;
-import com.android.ddmlib.testrunner.IRemoteAndroidTestRunner;
-import com.android.ddmlib.testrunner.RemoteAndroidTestRunner;
-import com.android.tradefed.config.Option;
-import com.android.tradefed.device.DeviceNotAvailableException;
-import com.android.tradefed.device.ITestDevice;
-import com.android.tradefed.result.BugreportCollector;
-import com.android.tradefed.result.BugreportCollector.Freq;
-import com.android.tradefed.result.BugreportCollector.Noun;
-import com.android.tradefed.result.BugreportCollector.Relation;
-import com.android.tradefed.result.FileInputStreamSource;
-import com.android.tradefed.result.ITestInvocationListener;
-import com.android.tradefed.result.InputStreamSource;
-import com.android.tradefed.result.LogDataType;
-import com.android.tradefed.testtype.IDeviceTest;
-import com.android.tradefed.testtype.IRemoteTest;
-import com.android.tradefed.util.FileUtil;
-import com.android.tradefed.util.StreamUtil;
-
-import org.junit.Assert;
-
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.util.Arrays;
-import java.util.HashMap;
-import java.util.List;
-import java.util.ListIterator;
-import java.util.Map;
-import java.util.concurrent.TimeUnit;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-
-/**
- * Runs the Video Editing Framework Memory Tests. This test exercise the basic
- * functionality of video editing test and capture the memory usage. The memory
- * usage test out is saved in /sdcard/VideoEditorStressMemOutput.txt and
- * VideoEditorMediaServerMemoryLog.txt.
- * <p/>
- * Note that this test will not run properly unless /sdcard is mounted and
- * writable.
- */
-public class VideoEditingMemoryTest implements IDeviceTest, IRemoteTest {
- private static final String LOG_TAG = "VideoEditorMemoryTest";
-
- ITestDevice mTestDevice = null;
-
- // Constants for running the tests
- private static final String TEST_CLASS_NAME =
- "com.android.mediaframeworktest.stress.VideoEditorStressTest";
- private static final String TEST_PACKAGE_NAME = "com.android.mediaframeworktest";
- private static final String TEST_RUNNER_NAME = ".MediaPlayerStressTestRunner";
-
- //Max test timeout - 3 hrs
- private static final int MAX_TEST_TIMEOUT = 3 * 60 * 60 * 1000;
-
- /*
- * Pattern to find the test case name and test result.
- * Example of a matching line:
- * testStressAddRemoveEffects total diff = 0
- * The first string 'testStressAddRemoveEffects' represent the dashboard key and
- * the last string represent the test result.
- */
- public static final Pattern TOTAL_MEM_DIFF_PATTERN =
- Pattern.compile("(.+?)\\s.*diff.*\\s(-?\\d+)");
-
- public Map<String, String> mRunMetrics = new HashMap<>();
- public Map<String, String> mKeyMap = new HashMap<>();
-
- @Option(name = "getHeapDump", description = "Collect the heap")
- private boolean mGetHeapDump = false;
-
- public VideoEditingMemoryTest() {
- mKeyMap.put("VideoEditorStressMemOutput.txt", "VideoEditorMemory");
- mKeyMap.put("VideoEditorMediaServerMemoryLog.txt",
- "VideoEditorMemoryMediaServer");
- }
-
-
- @Override
- public void run(ITestInvocationListener listener)
- throws DeviceNotAvailableException {
- Assert.assertNotNull(mTestDevice);
-
- IRemoteAndroidTestRunner runner = new RemoteAndroidTestRunner(
- TEST_PACKAGE_NAME, TEST_RUNNER_NAME, mTestDevice.getIDevice());
- runner.setClassName(TEST_CLASS_NAME);
- runner.setMaxTimeToOutputResponse(MAX_TEST_TIMEOUT, TimeUnit.MILLISECONDS);
- if (mGetHeapDump) {
- runner.addInstrumentationArg("get_heap_dump", "getNativeHeap");
- }
-
- BugreportCollector bugListener = new BugreportCollector(listener,
- mTestDevice);
- bugListener.addPredicate(new BugreportCollector.Predicate(
- Relation.AFTER, Freq.EACH, Noun.TESTRUN));
-
- mTestDevice.runInstrumentationTests(runner, bugListener);
-
- logOutputFiles(listener);
- cleanResultFile();
- }
-
- /**
- * Clean up the test result file from test run
- */
- private void cleanResultFile() throws DeviceNotAvailableException {
- String extStore =
- mTestDevice.getMountPoint(IDevice.MNT_EXTERNAL_STORAGE);
- for(String outFile : mKeyMap.keySet()) {
- mTestDevice.executeShellCommand(String.format("rm %s/%s", extStore,
- outFile));
- }
- if (mGetHeapDump) {
- mTestDevice.executeShellCommand(String.format("rm %s/%s", extStore,
- "*.dump"));
- }
- }
-
- private void uploadHeapDumpFiles(ITestInvocationListener listener)
- throws DeviceNotAvailableException {
- // Pull and upload the heap dump output files.
- InputStreamSource outputSource = null;
- File outputFile = null;
-
- String extStore =
- mTestDevice.getMountPoint(IDevice.MNT_EXTERNAL_STORAGE);
-
- String out = mTestDevice.executeShellCommand(String.format("ls %s/%s",
- extStore, "*.dump"));
- String heapOutputFiles[] = out.split("\n");
-
- for (String heapOutputFile : heapOutputFiles) {
- try {
- outputFile = mTestDevice.pullFile(heapOutputFile.trim());
- if (outputFile == null) {
- continue;
- }
- outputSource = new FileInputStreamSource(outputFile);
- listener.testLog(heapOutputFile, LogDataType.TEXT, outputSource);
- } finally {
- FileUtil.deleteFile(outputFile);
- StreamUtil.cancel(outputSource);
- }
- }
- }
-
- /**
- * Pull the output files from the device, add it to the logs, and also parse
- * out the relevant test metrics and report them.
- */
- private void logOutputFiles(ITestInvocationListener listener)
- throws DeviceNotAvailableException {
- File outputFile = null;
- InputStreamSource outputSource = null;
-
- if (mGetHeapDump) {
- // Upload all the heap dump files.
- uploadHeapDumpFiles(listener);
- }
- for (String resultFile : mKeyMap.keySet()) {
- try {
- outputFile = mTestDevice.pullFileFromExternal(resultFile);
-
- if (outputFile == null) {
- return;
- }
-
- // Upload a verbatim copy of the output file
- Log.d(LOG_TAG, String.format(
- "Sending %d byte file %s into the logosphere!",
- outputFile.length(), outputFile));
- outputSource = new FileInputStreamSource(outputFile);
- listener.testLog(resultFile, LogDataType.TEXT, outputSource);
-
- // Parse the output file to upload aggregated metrics
- parseOutputFile(new FileInputStream(outputFile), listener, resultFile);
- } catch (IOException e) {
- Log.e(
- LOG_TAG,
- String.format("IOException while reading or parsing output file: %s", e));
- } finally {
- FileUtil.deleteFile(outputFile);
- StreamUtil.cancel(outputSource);
- }
- }
- }
-
- /**
- * Parse the relevant metrics from the Instrumentation test output file
- */
- private void parseOutputFile(InputStream dataStream,
- ITestInvocationListener listener, String outputFile) {
-
- // try to parse it
- String contents;
- try {
- contents = StreamUtil.getStringFromStream(dataStream);
- } catch (IOException e) {
- Log.e(LOG_TAG, String.format(
- "Got IOException during test processing: %s", e));
- return;
- }
-
- List<String> lines = Arrays.asList(contents.split("\n"));
- ListIterator<String> lineIter = lines.listIterator();
-
- String line;
- String key;
- String memOut;
-
- while (lineIter.hasNext()){
- line = lineIter.next();
-
- // Look for the total diff
- Matcher m = TOTAL_MEM_DIFF_PATTERN.matcher(line);
- if (m.matches()){
- //First group match with the test key name.
- key = m.group(1);
- //Second group match witht the test result.
- memOut = m.group(2);
- mRunMetrics.put(key, memOut);
- }
- }
- reportMetrics(listener, outputFile);
- }
-
- /**
- * Report run metrics by creating an empty test run to stick them in
- * <p />
- * Exposed for unit testing
- */
- void reportMetrics(ITestInvocationListener listener, String outputFile) {
- Log.d(LOG_TAG, String.format("About to report metrics: %s", mRunMetrics));
- listener.testRunStarted(mKeyMap.get(outputFile), 0);
- listener.testRunEnded(0, mRunMetrics);
- }
-
- @Override
- public void setDevice(ITestDevice device) {
- mTestDevice = device;
- }
-
- @Override
- public ITestDevice getDevice() {
- return mTestDevice;
- }
-}
diff --git a/src/com/android/media/tests/VideoEditingPerformanceTest.java b/src/com/android/media/tests/VideoEditingPerformanceTest.java
deleted file mode 100644
index 046403e..0000000
--- a/src/com/android/media/tests/VideoEditingPerformanceTest.java
+++ /dev/null
@@ -1,257 +0,0 @@
-/*
- * Copyright (C) 2011 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.media.tests;
-
-import com.android.ddmlib.IDevice;
-import com.android.ddmlib.Log;
-import com.android.ddmlib.testrunner.IRemoteAndroidTestRunner;
-import com.android.ddmlib.testrunner.RemoteAndroidTestRunner;
-import com.android.tradefed.device.DeviceNotAvailableException;
-import com.android.tradefed.device.ITestDevice;
-import com.android.tradefed.result.BugreportCollector;
-import com.android.tradefed.result.BugreportCollector.Freq;
-import com.android.tradefed.result.BugreportCollector.Noun;
-import com.android.tradefed.result.BugreportCollector.Relation;
-import com.android.tradefed.result.FileInputStreamSource;
-import com.android.tradefed.result.ITestInvocationListener;
-import com.android.tradefed.result.InputStreamSource;
-import com.android.tradefed.result.LogDataType;
-import com.android.tradefed.testtype.IDeviceTest;
-import com.android.tradefed.testtype.IRemoteTest;
-import com.android.tradefed.util.FileUtil;
-import com.android.tradefed.util.RegexTrie;
-import com.android.tradefed.util.StreamUtil;
-
-import org.junit.Assert;
-
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.HashMap;
-import java.util.List;
-import java.util.ListIterator;
-import java.util.Map;
-import java.util.concurrent.TimeUnit;
-
-/**
- * Runs the Video Editing Framework Performance Test.The performance test result
- * is saved in /sdcard/VideoEditorPerformance.txt
- * <p/>
- * Note that this test will not run properly unless /sdcard is mounted and
- * writable.
- */
-public class VideoEditingPerformanceTest implements IDeviceTest, IRemoteTest {
- private static final String LOG_TAG = "VideoEditingPerformanceTest";
-
- ITestDevice mTestDevice = null;
-
- private static final String METRICS_RUN_NAME = "VideoEditor";
-
- //Max test timeout - 3 hrs
- private static final int MAX_TEST_TIMEOUT = 3 * 60 * 60 * 1000;
-
- // Constants for running the tests
- private static final String TEST_CLASS_NAME =
- "com.android.mediaframeworktest.performance.VideoEditorPerformance";
- private static final String TEST_PACKAGE_NAME = "com.android.mediaframeworktest";
- private static final String TEST_RUNNER_NAME = ".MediaFrameworkPerfTestRunner";
-
- private static final String OUTPUT_PATH = "VideoEditorPerformance.txt";
-
- private final RegexTrie<String> mPatternMap = new RegexTrie<>();
-
- public VideoEditingPerformanceTest() {
- mPatternMap.put("ImageItemCreate",
- "^.*Time taken to Create Media Image Item :(\\d+)");
- mPatternMap.put("mageItemAdd",
- "^.*Time taken to add Media Image Item :(\\d+)");
- mPatternMap.put("ImageItemRemove",
- "^.*Time taken to remove Media Image Item :(\\d+)");
- mPatternMap.put("ImageItemCreate640x480",
- "^.*Time taken to Create Media Image Item.*640x480.*:(\\d+)");
- mPatternMap.put("ImageItemAdd640x480",
- "^.*Time taken to add Media Image Item.*640x480.*:(\\d+)");
- mPatternMap.put("ImageItemRemove640x480",
- "^.*Time taken to remove Media Image Item.*640x480.*:(\\d+)");
- mPatternMap.put("CrossFadeTransitionCreate",
- "^.*Time taken to Create CrossFade Transition :(\\d+)");
- mPatternMap.put("CrossFadeTransitionAdd",
- "^.*Time taken to add CrossFade Transition :(\\d+)");
- mPatternMap.put("CrossFadeTransitionRemove",
- "^.*Time taken to remove CrossFade Transition :(\\d+)");
- mPatternMap.put("VideoItemCreate",
- "^.*Time taken to Create Media Video Item :(\\d+)");
- mPatternMap.put("VideoItemAdd",
- "^.*Time taken to Add Media Video Item :(\\d+)");
- mPatternMap.put("VideoItemRemove",
- "^.*Time taken to remove Media Video Item :(\\d+)");
- mPatternMap.put("EffectOverlappingTransition",
- "^.*Time taken to testPerformanceEffectOverlappingTransition :(\\d+.\\d+)");
- mPatternMap.put("ExportStoryboard",
- "^.*Time taken to do ONE export of storyboard duration 69000 is :(\\d+)");
- mPatternMap.put("PreviewWithTransition",
- "^.*Time taken to Generate Preview with transition :(\\d+.\\d+)");
- mPatternMap.put("OverlayCreate",
- "^.*Time taken to add & create Overlay :(\\d+)");
- mPatternMap.put("OverlayRemove",
- "^.*Time taken to remove Overlay :(\\d+)");
- mPatternMap.put("GetVideoThumbnails",
- "^.*Duration taken to get Video Thumbnails :(\\d+)");
- mPatternMap.put("TransitionWithEffectOverlapping",
- "^.*Time taken to TransitionWithEffectOverlapping :(\\d+.\\d+)");
- mPatternMap.put("MediaPropertiesGet",
- "^.*Time taken to get Media Properties :(\\d+)");
- mPatternMap.put("AACLCAdd",
- "^.*Time taken for 1st Audio Track.*AACLC.*:(\\d+)");
- mPatternMap.put("AMRNBAdd",
- "^.*Time taken for 2nd Audio Track.*AMRNB.*:(\\d+)");
- mPatternMap.put("KenBurnGeneration",
- "^.*Time taken to Generate KenBurn Effect :(\\d+.\\d+)");
- mPatternMap.put("ThumbnailsGeneration",
- "^.*Time taken Thumbnail generation :(\\d+.\\d+)");
- mPatternMap.put("H264ThumbnailGeneration",
- "^.*Time taken for Thumbnail generation :(\\d+.\\d+)");
- }
-
- @Override
- public void run(ITestInvocationListener listener)
- throws DeviceNotAvailableException {
- Assert.assertNotNull(mTestDevice);
-
- IRemoteAndroidTestRunner runner = new RemoteAndroidTestRunner(
- TEST_PACKAGE_NAME, TEST_RUNNER_NAME, mTestDevice.getIDevice());
- runner.setClassName(TEST_CLASS_NAME);
- runner.setMaxTimeToOutputResponse(MAX_TEST_TIMEOUT, TimeUnit.MILLISECONDS);
-
- BugreportCollector bugListener = new BugreportCollector(listener,
- mTestDevice);
- bugListener.addPredicate(new BugreportCollector.Predicate(
- Relation.AFTER, Freq.EACH, Noun.TESTRUN));
-
- mTestDevice.runInstrumentationTests(runner, bugListener);
-
- logOutputFiles(listener);
- cleanResultFile();
- }
-
- /**
- * Clean up the test result file from test run
- */
- private void cleanResultFile() throws DeviceNotAvailableException {
- String extStore =
- mTestDevice.getMountPoint(IDevice.MNT_EXTERNAL_STORAGE);
- mTestDevice.executeShellCommand(String.format("rm %s/%s", extStore, OUTPUT_PATH));
- }
-
- /**
- * Pull the output files from the device, add it to the logs, and also parse
- * out the relevant test metrics and report them.
- */
- private void logOutputFiles(ITestInvocationListener listener)
- throws DeviceNotAvailableException {
- File outputFile = null;
- InputStreamSource outputSource = null;
- try {
- outputFile = mTestDevice.pullFileFromExternal(OUTPUT_PATH);
-
- if (outputFile == null) {
- return;
- }
-
- // Upload a verbatim copy of the output file
- Log.d(LOG_TAG, String.format(
- "Sending %d byte file %s into the logosphere!",
- outputFile.length(), outputFile));
- outputSource = new FileInputStreamSource(outputFile);
- listener.testLog(OUTPUT_PATH, LogDataType.TEXT, outputSource);
-
- // Parse the output file to upload aggregated metrics
- parseOutputFile(new FileInputStream(outputFile), listener);
- } catch (IOException e) {
- Log.e(LOG_TAG, String.format(
- "IOException while reading or parsing output file: %s", e));
- } finally {
- FileUtil.deleteFile(outputFile);
- StreamUtil.cancel(outputSource);
- }
- }
-
- /**
- * Parse the relevant metrics from the Instrumentation test output file
- */
- private void parseOutputFile(InputStream dataStream,
- ITestInvocationListener listener) {
-
- Map<String, String> runMetrics = new HashMap<>();
-
- // try to parse it
- String contents;
- try {
- contents = StreamUtil.getStringFromStream(dataStream);
- } catch (IOException e) {
- Log.e(LOG_TAG, String.format(
- "Got IOException during test processing: %s", e));
- return;
- }
-
- List<String> lines = Arrays.asList(contents.split("\n"));
- ListIterator<String> lineIter = lines.listIterator();
- String line;
- while (lineIter.hasNext()) {
- line = lineIter.next();
- List<List<String>> capture = new ArrayList<>(1);
- String key = mPatternMap.retrieve(capture, line);
- if (key != null) {
- Log.d(LOG_TAG, String.format("Got '%s' and captures '%s'", key,
- capture.toString()));
- } else if (line.isEmpty()) {
- // ignore
- continue;
- } else {
- Log.e(LOG_TAG, String.format("Got unmatched line: %s", line));
- continue;
- }
- runMetrics.put(key, capture.get(0).get(0));
- }
- reportMetrics(listener, runMetrics);
- }
-
- /**
- * Report run metrics by creating an empty test run to stick them in
- * <p />
- * Exposed for unit testing
- */
- void reportMetrics(ITestInvocationListener listener,
- Map<String, String> metrics) {
- Log.d(LOG_TAG, String.format("About to report metrics: %s", metrics));
- listener.testRunStarted(METRICS_RUN_NAME, 0);
- listener.testRunEnded(0, metrics);
- }
-
- @Override
- public void setDevice(ITestDevice device) {
- mTestDevice = device;
- }
-
- @Override
- public ITestDevice getDevice() {
- return mTestDevice;
- }
-}
diff --git a/src/com/android/media/tests/VideoMultimeterRunner.java b/src/com/android/media/tests/VideoMultimeterRunner.java
deleted file mode 100644
index 13fd4d1..0000000
--- a/src/com/android/media/tests/VideoMultimeterRunner.java
+++ /dev/null
@@ -1,110 +0,0 @@
-/*
- * Copyright (C) 2014 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.media.tests;
-
-import com.android.ddmlib.testrunner.TestIdentifier;
-import com.android.tradefed.config.Option;
-import com.android.tradefed.config.Option.Importance;
-import com.android.tradefed.device.DeviceNotAvailableException;
-import com.android.tradefed.log.LogUtil.CLog;
-import com.android.tradefed.result.ITestInvocationListener;
-import com.android.tradefed.testtype.IDeviceTest;
-import com.android.tradefed.testtype.IRemoteTest;
-import com.android.tradefed.util.CommandResult;
-
-import java.util.HashMap;
-import java.util.Map;
-import java.util.concurrent.Semaphore;
-
-/**
- * A harness that test video playback with multiple devices and reports result.
- */
-public class VideoMultimeterRunner extends VideoMultimeterTest
- implements IDeviceTest, IRemoteTest {
-
- @Option(name = "robot-util-path", description = "path for robot control util",
- importance = Importance.ALWAYS, mandatory = true)
- String mRobotUtilPath = "/tmp/robot_util.sh";
-
- @Option(name = "device-map", description =
- "Device serials map to location and audio input. May be repeated",
- importance = Importance.ALWAYS)
- Map<String, String> mDeviceMap = new HashMap<String, String>();
-
- @Option(name = "calibration-map", description =
- "Device serials map to calibration values. May be repeated",
- importance = Importance.ALWAYS)
- Map<String, String> mCalibrationMap = new HashMap<String, String>();
-
- static final long ROBOT_TIMEOUT_MS = 60 * 1000;
-
- static final Semaphore runToken = new Semaphore(1);
-
- /**
- * {@inheritDoc}
- */
- @Override
- public void run(ITestInvocationListener listener)
- throws DeviceNotAvailableException {
- long durationMs = 0;
- TestIdentifier testId = new TestIdentifier(getClass()
- .getCanonicalName(), RUN_KEY);
-
- listener.testRunStarted(RUN_KEY, 0);
- listener.testStarted(testId);
-
- long testStartTime = System.currentTimeMillis();
- Map<String, String> metrics = new HashMap<String, String>();
-
- try {
- CLog.v("Waiting to acquire run token");
- runToken.acquire();
-
- String deviceSerial = getDevice().getSerialNumber();
-
- String calibrationValue = (mCalibrationMap.containsKey(deviceSerial) ?
- mCalibrationMap.get(deviceSerial) : null);
- if (mDebugWithoutHardware
- || (moveArm(deviceSerial) && setupTestEnv(calibrationValue))) {
- runMultimeterTest(listener, metrics);
- } else {
- listener.testFailed(testId, "Failed to set up environment");
- }
- } catch (InterruptedException e) {
- CLog.d("Acquire run token interrupted");
- listener.testFailed(testId, "Failed to acquire run token");
- } finally {
- runToken.release();
- listener.testEnded(testId, metrics);
- durationMs = System.currentTimeMillis() - testStartTime;
- listener.testRunEnded(durationMs, metrics);
- }
- }
-
- protected boolean moveArm(String deviceSerial) {
- if (mDeviceMap.containsKey(deviceSerial)) {
- CLog.v("Moving robot arm to device " + deviceSerial);
- CommandResult cr = getRunUtil().runTimedCmd(
- ROBOT_TIMEOUT_MS, mRobotUtilPath, mDeviceMap.get(deviceSerial));
- CLog.v(cr.getStdout());
- return true;
- } else {
- CLog.e("Cannot find device in map, test failed");
- return false;
- }
- }
-}
diff --git a/src/com/android/media/tests/VideoMultimeterTest.java b/src/com/android/media/tests/VideoMultimeterTest.java
deleted file mode 100644
index 038803f..0000000
--- a/src/com/android/media/tests/VideoMultimeterTest.java
+++ /dev/null
@@ -1,490 +0,0 @@
-/*
- * Copyright (C) 2014 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.media.tests;
-
-import com.android.ddmlib.testrunner.TestIdentifier;
-import com.android.tradefed.config.Option;
-import com.android.tradefed.config.Option.Importance;
-import com.android.tradefed.device.CollectingOutputReceiver;
-import com.android.tradefed.device.DeviceNotAvailableException;
-import com.android.tradefed.device.ITestDevice;
-import com.android.tradefed.log.LogUtil.CLog;
-import com.android.tradefed.result.ByteArrayInputStreamSource;
-import com.android.tradefed.result.ITestInvocationListener;
-import com.android.tradefed.result.LogDataType;
-import com.android.tradefed.testtype.IDeviceTest;
-import com.android.tradefed.testtype.IRemoteTest;
-import com.android.tradefed.util.CommandResult;
-import com.android.tradefed.util.IRunUtil;
-import com.android.tradefed.util.RunUtil;
-
-import org.junit.Assert;
-
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.Date;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.concurrent.TimeUnit;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-
-/**
- * A harness that test video playback and reports result.
- */
-public class VideoMultimeterTest implements IDeviceTest, IRemoteTest {
-
- static final String RUN_KEY = "video_multimeter";
-
- @Option(name = "multimeter-util-path", description = "path for multimeter control util",
- importance = Importance.ALWAYS)
- String mMeterUtilPath = "/tmp/util.sh";
-
- @Option(name = "start-video-cmd", description = "adb shell command to start video playback; " +
- "use '%s' as placeholder for media source filename", importance = Importance.ALWAYS)
- String mCmdStartVideo = "am instrument -w -r -e media-file"
- + " \"%s\" -e class com.android.mediaframeworktest.stress.MediaPlayerStressTest"
- + " com.android.mediaframeworktest/.MediaPlayerStressTestRunner";
-
- @Option(name = "stop-video-cmd", description = "adb shell command to stop video playback",
- importance = Importance.ALWAYS)
- String mCmdStopVideo = "am force-stop com.android.mediaframeworktest";
-
- @Option(name="video-spec", description=
- "Comma deliminated information for test video files with the following format: " +
- "video_filename, reporting_key_prefix, fps, duration(in sec) " +
- "May be repeated for test with multiple files.")
- private Collection<String> mVideoSpecs = new ArrayList<>();
-
- @Option(name="wait-time-between-runs", description=
- "wait time between two test video measurements, in millisecond")
- private long mWaitTimeBetweenRuns = 3 * 60 * 1000;
-
- @Option(name="calibration-video", description=
- "filename of calibration video")
- private String mCaliVideoDevicePath = "video_cali.mp4";
-
- @Option(
- name = "debug-without-hardware",
- description = "Use option to debug test without having specialized hardware",
- importance = Importance.NEVER,
- mandatory = false
- )
- protected boolean mDebugWithoutHardware = false;
-
- static final String ROTATE_LANDSCAPE = "content insert --uri content://settings/system"
- + " --bind name:s:user_rotation --bind value:i:1";
-
- // Max number of trailing frames to trim
- static final int TRAILING_FRAMES_MAX = 3;
- // Min threshold for duration of trailing frames
- static final long FRAME_DURATION_THRESHOLD_US = 500 * 1000; // 0.5s
-
- static final String CMD_GET_FRAMERATE_STATE = "GETF";
- static final String CMD_START_CALIBRATION = "STAC";
- static final String CMD_SET_CALIBRATION_VALS = "SETCAL";
- static final String CMD_STOP_CALIBRATION = "STOC";
- static final String CMD_START_MEASUREMENT = "STAM";
- static final String CMD_STOP_MEASUREMENT = "STOM";
- static final String CMD_GET_NUM_FRAMES = "GETN";
- static final String CMD_GET_ALL_DATA = "GETD";
-
- static final long DEVICE_SYNC_TIME_MS = 30 * 1000;
- static final long CALIBRATION_TIMEOUT_MS = 30 * 1000;
- static final long COMMAND_TIMEOUT_MS = 5 * 1000;
- static final long GETDATA_TIMEOUT_MS = 10 * 60 * 1000;
-
- // Regex for: "OK (time); (frame duration); (marker color); (total dropped frames)"
- static final String VIDEO_FRAME_DATA_PATTERN = "OK\\s+\\d+;\\s*(-?\\d+);\\s*[a-z]+;\\s*(\\d+)";
-
- // Regex for: "OK (time); (frame duration); (marker color); (total dropped frames); (lipsync)"
- // results in: $1 == ts, $2 == lipsync
- static final String LIPSYNC_DATA_PATTERN =
- "OK\\s+(\\d+);\\s*\\d+;\\s*[a-z]+;\\s*\\d+;\\s*(-?\\d+)";
- // ts dur color missed latency
- static final int LIPSYNC_SIGNAL = 2000000; // every 2 seconds
- static final int LIPSYNC_SIGNAL_MIN = 1500000; // must be at least 1.5 seconds after prev
-
- ITestDevice mDevice;
-
- /**
- * {@inheritDoc}
- */
- @Override
- public void setDevice(ITestDevice device) {
- mDevice = device;
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public ITestDevice getDevice() {
- return mDevice;
- }
-
- private void rotateScreen() throws DeviceNotAvailableException {
- // rotate to landscape mode, except for manta
- if (!getDevice().getProductType().contains("manta")) {
- getDevice().executeShellCommand(ROTATE_LANDSCAPE);
- }
- }
-
- protected boolean setupTestEnv() throws DeviceNotAvailableException {
- return setupTestEnv(null);
- }
-
- protected void startPlayback(final String videoPath) {
- new Thread() {
- @Override
- public void run() {
- try {
- CollectingOutputReceiver receiver = new CollectingOutputReceiver();
- getDevice().executeShellCommand(String.format(
- mCmdStartVideo, videoPath),
- receiver, 1L, TimeUnit.SECONDS, 0);
- } catch (DeviceNotAvailableException e) {
- CLog.e(e.getMessage());
- }
- }
- }.start();
- }
-
- /**
- * Perform calibration process for video multimeter
- *
- * @return boolean whether calibration succeeds
- * @throws DeviceNotAvailableException
- */
- protected boolean doCalibration() throws DeviceNotAvailableException {
- // play calibration video
- startPlayback(mCaliVideoDevicePath);
- getRunUtil().sleep(3 * 1000);
- rotateScreen();
- getRunUtil().sleep(1 * 1000);
- CommandResult cr = getRunUtil().runTimedCmd(
- COMMAND_TIMEOUT_MS, mMeterUtilPath, CMD_START_CALIBRATION);
- CLog.i("Starting calibration: " + cr.getStdout());
- // check whether multimeter is calibrated
- boolean isCalibrated = false;
- long calibrationStartTime = System.currentTimeMillis();
- while (!isCalibrated &&
- System.currentTimeMillis() - calibrationStartTime <= CALIBRATION_TIMEOUT_MS) {
- getRunUtil().sleep(1 * 1000);
- cr = getRunUtil().runTimedCmd(2 * 1000, mMeterUtilPath, CMD_GET_FRAMERATE_STATE);
- if (cr.getStdout().contains("calib0")) {
- isCalibrated = true;
- }
- }
- if (!isCalibrated) {
- // stop calibration if time out
- cr = getRunUtil().runTimedCmd(
- COMMAND_TIMEOUT_MS, mMeterUtilPath, CMD_STOP_CALIBRATION);
- CLog.e("Calibration timed out.");
- } else {
- CLog.i("Calibration succeeds.");
- }
- getDevice().executeShellCommand(mCmdStopVideo);
- return isCalibrated;
- }
-
- protected boolean setupTestEnv(String caliValues) throws DeviceNotAvailableException {
- getRunUtil().sleep(DEVICE_SYNC_TIME_MS);
- CommandResult cr = getRunUtil().runTimedCmd(
- COMMAND_TIMEOUT_MS, mMeterUtilPath, CMD_STOP_MEASUREMENT);
-
- getDevice().setDate(new Date());
- CLog.i("syncing device time to host time");
- getRunUtil().sleep(3 * 1000);
-
- // TODO: need a better way to clear old data
- // start and stop to clear old data
- cr = getRunUtil().runTimedCmd(COMMAND_TIMEOUT_MS, mMeterUtilPath, CMD_START_MEASUREMENT);
- getRunUtil().sleep(3 * 1000);
- cr = getRunUtil().runTimedCmd(COMMAND_TIMEOUT_MS, mMeterUtilPath, CMD_STOP_MEASUREMENT);
- getRunUtil().sleep(3 * 1000);
- CLog.i("Stopping measurement: " + cr.getStdout());
-
- if (caliValues == null) {
- return doCalibration();
- } else {
- CLog.i("Setting calibration values: " + caliValues);
- final String calibrationValues = CMD_SET_CALIBRATION_VALS + " " + caliValues;
- cr = getRunUtil().runTimedCmd(COMMAND_TIMEOUT_MS, mMeterUtilPath, calibrationValues);
- final String response = mDebugWithoutHardware ? "OK" : cr.getStdout();
- if (response != null && response.startsWith("OK")) {
- CLog.i("Calibration values are set to: " + caliValues);
- return true;
- } else {
- CLog.e("Failed to set calibration values: " + cr.getStdout());
- return false;
- }
- }
- }
-
- private void doMeasurement(final String testVideoPath, long durationSecond)
- throws DeviceNotAvailableException {
- CommandResult cr;
- getDevice().clearErrorDialogs();
- getRunUtil().sleep(mWaitTimeBetweenRuns);
-
- // play test video
- startPlayback(testVideoPath);
-
- getRunUtil().sleep(3 * 1000);
-
- rotateScreen();
- getRunUtil().sleep(1 * 1000);
- cr = getRunUtil().runTimedCmd(COMMAND_TIMEOUT_MS, mMeterUtilPath, CMD_START_MEASUREMENT);
- CLog.i("Starting measurement: " + cr.getStdout());
-
- // end measurement
- getRunUtil().sleep(durationSecond * 1000);
-
- cr = getRunUtil().runTimedCmd(COMMAND_TIMEOUT_MS, mMeterUtilPath, CMD_STOP_MEASUREMENT);
- CLog.i("Stopping measurement: " + cr.getStdout());
- if (cr == null || !cr.getStdout().contains("OK")) {
- cr = getRunUtil().runTimedCmd(
- COMMAND_TIMEOUT_MS, mMeterUtilPath, CMD_STOP_MEASUREMENT);
- CLog.i("Retry - Stopping measurement: " + cr.getStdout());
- }
-
- getDevice().executeShellCommand(mCmdStopVideo);
- getDevice().clearErrorDialogs();
- }
-
- private Map<String, String> getResult(ITestInvocationListener listener,
- Map<String, String> metrics, String keyprefix, float fps, boolean lipsync) {
- CommandResult cr;
-
- // get number of results
- getRunUtil().sleep(5 * 1000);
- cr = getRunUtil().runTimedCmd(COMMAND_TIMEOUT_MS, mMeterUtilPath, CMD_GET_NUM_FRAMES);
- String frameNum = cr.getStdout();
-
- CLog.i("== Video Multimeter Result '%s' ==", keyprefix);
- CLog.i("Number of results: " + frameNum);
-
- String nrOfDataPointsStr = extractNumberOfCollectedDataPoints(frameNum);
- metrics.put(keyprefix + "frame_captured", nrOfDataPointsStr);
-
- long nrOfDataPoints = Long.parseLong(nrOfDataPointsStr);
-
- Assert.assertTrue("Multimeter did not collect any data for " + keyprefix,
- nrOfDataPoints > 0);
-
- CLog.i("Captured frames: " + nrOfDataPointsStr);
-
- // get all results from multimeter and write to output file
- cr = getRunUtil().runTimedCmd(GETDATA_TIMEOUT_MS, mMeterUtilPath, CMD_GET_ALL_DATA);
- String allData = cr.getStdout();
- listener.testLog(
- keyprefix, LogDataType.TEXT, new ByteArrayInputStreamSource(allData.getBytes()));
-
- // parse results
- return parseResult(metrics, nrOfDataPoints, allData, keyprefix, fps, lipsync);
- }
-
- private String extractNumberOfCollectedDataPoints(String numFrames) {
- // Create pattern that matches string like "OK 14132" capturing the
- // number of data points.
- Pattern p = Pattern.compile("OK\\s+(\\d+)$");
- Matcher m = p.matcher(numFrames.trim());
-
- String frameCapturedStr = "0";
- if (m.matches()) {
- frameCapturedStr = m.group(1);
- }
-
- return frameCapturedStr;
- }
-
- protected void runMultimeterTest(ITestInvocationListener listener,
- Map<String,String> metrics) throws DeviceNotAvailableException {
- for (String videoSpec : mVideoSpecs) {
- String[] videoInfo = videoSpec.split(",");
- String filename = videoInfo[0].trim();
- String keyPrefix = videoInfo[1].trim();
- float fps = Float.parseFloat(videoInfo[2].trim());
- long duration = Long.parseLong(videoInfo[3].trim());
- doMeasurement(filename, duration);
- metrics = getResult(listener, metrics, keyPrefix, fps, true);
- }
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public void run(ITestInvocationListener listener)
- throws DeviceNotAvailableException {
- TestIdentifier testId = new TestIdentifier(getClass()
- .getCanonicalName(), RUN_KEY);
-
- listener.testRunStarted(RUN_KEY, 0);
- listener.testStarted(testId);
-
- long testStartTime = System.currentTimeMillis();
- Map<String, String> metrics = new HashMap<>();
-
- if (setupTestEnv()) {
- runMultimeterTest(listener, metrics);
- }
-
- long durationMs = System.currentTimeMillis() - testStartTime;
- listener.testEnded(testId, metrics);
- listener.testRunEnded(durationMs, metrics);
- }
-
- /**
- * Parse Multimeter result.
- *
- * @param result
- * @return a {@link HashMap} that contains metrics keys and results
- */
- private Map<String, String> parseResult(Map<String, String> metrics,
- long frameCaptured, String result, String keyprefix, float fps,
- boolean lipsync) {
- final int MISSING_FRAME_CEILING = 5; //5+ frames missing count the same
- final double[] MISSING_FRAME_WEIGHT = {0.0, 1.0, 2.5, 5.0, 6.25, 8.0};
-
- // Get total captured frames and calculate smoothness and freezing score
- // format: "OK (time); (frame duration); (marker color); (total dropped frames)"
- Pattern p = Pattern.compile(VIDEO_FRAME_DATA_PATTERN);
- Matcher m = null;
- String[] lines = result.split(System.getProperty("line.separator"));
- String totalDropFrame = "-1";
- String lastDropFrame = "0";
- long frameCount = 0;
- long consecutiveDropFrame = 0;
- double freezingPenalty = 0.0;
- long frameDuration = 0;
- double offByOne = 0;
- double offByMultiple = 0;
- double expectedFrameDurationInUs = 1000000.0 / fps;
- for (int i = 0; i < lines.length; i++) {
- m = p.matcher(lines[i].trim());
- if (m.matches()) {
- frameDuration = Long.parseLong(m.group(1));
- // frameDuration = -1 indicates dropped frame
- if (frameDuration > 0) {
- frameCount++;
- }
- totalDropFrame = m.group(2);
- // trim the last few data points if needed
- if (frameCount >= frameCaptured - TRAILING_FRAMES_MAX - 1 &&
- frameDuration > FRAME_DURATION_THRESHOLD_US) {
- metrics.put(keyprefix + "frame_captured", String.valueOf(frameCount));
- break;
- }
- if (lastDropFrame.equals(totalDropFrame)) {
- if (consecutiveDropFrame > 0) {
- freezingPenalty += MISSING_FRAME_WEIGHT[(int) (Math.min(consecutiveDropFrame,
- MISSING_FRAME_CEILING))] * consecutiveDropFrame;
- consecutiveDropFrame = 0;
- }
- } else {
- consecutiveDropFrame++;
- }
- lastDropFrame = totalDropFrame;
-
- if (frameDuration < expectedFrameDurationInUs * 0.5) {
- offByOne++;
- } else if (frameDuration > expectedFrameDurationInUs * 1.5) {
- if (frameDuration < expectedFrameDurationInUs * 2.5) {
- offByOne++;
- } else {
- offByMultiple++;
- }
- }
- }
- }
- if (totalDropFrame.equals("-1")) {
- // no matching result found
- CLog.w("No result found for " + keyprefix);
- return metrics;
- } else {
- metrics.put(keyprefix + "frame_drop", totalDropFrame);
- CLog.i("Dropped frames: " + totalDropFrame);
- }
- double smoothnessScore = 100.0 - (offByOne / frameCaptured) * 100.0 -
- (offByMultiple / frameCaptured) * 300.0;
- metrics.put(keyprefix + "smoothness", String.valueOf(smoothnessScore));
- CLog.i("Off by one frame: " + offByOne);
- CLog.i("Off by multiple frames: " + offByMultiple);
- CLog.i("Smoothness score: " + smoothnessScore);
-
- double freezingScore = 100.0 - 100.0 * freezingPenalty / frameCaptured;
- metrics.put(keyprefix + "freezing", String.valueOf(freezingScore));
- CLog.i("Freezing score: " + freezingScore);
-
- // parse lipsync results (the audio and video synchronization offset)
- // format: "OK (time); (frame duration); (marker color); (total dropped frames); (lipsync)"
- if (lipsync) {
- ArrayList<Integer> lipsyncVals = new ArrayList<>();
- StringBuilder lipsyncValsStr = new StringBuilder("[");
- long lipsyncSum = 0;
- int lipSyncLastTime = -1;
-
- Pattern pLip = Pattern.compile(LIPSYNC_DATA_PATTERN);
- for (int i = 0; i < lines.length; i++) {
- m = pLip.matcher(lines[i].trim());
- if (m.matches()) {
- int lipSyncTime = Integer.parseInt(m.group(1));
- int lipSyncVal = Integer.parseInt(m.group(2));
- if (lipSyncLastTime != -1) {
- if ((lipSyncTime - lipSyncLastTime) < LIPSYNC_SIGNAL_MIN) {
- continue; // ignore the early/spurious one
- }
- }
- lipSyncLastTime = lipSyncTime;
-
- lipsyncVals.add(lipSyncVal);
- lipsyncValsStr.append(lipSyncVal);
- lipsyncValsStr.append(", ");
- lipsyncSum += lipSyncVal;
- }
- }
- if (lipsyncVals.size() > 0) {
- lipsyncValsStr.append("]");
- CLog.i("Lipsync values: " + lipsyncValsStr);
- Collections.sort(lipsyncVals);
- int lipsyncCount = lipsyncVals.size();
- int minLipsync = lipsyncVals.get(0);
- int maxLipsync = lipsyncVals.get(lipsyncCount - 1);
- metrics.put(keyprefix + "lipsync_count", String.valueOf(lipsyncCount));
- CLog.i("Lipsync Count: " + lipsyncCount);
- metrics.put(keyprefix + "lipsync_min", String.valueOf(lipsyncVals.get(0)));
- CLog.i("Lipsync Min: " + minLipsync);
- metrics.put(keyprefix + "lipsync_max", String.valueOf(maxLipsync));
- CLog.i("Lipsync Max: " + maxLipsync);
- double meanLipSync = (double) lipsyncSum / lipsyncCount;
- metrics.put(keyprefix + "lipsync_mean", String.valueOf(meanLipSync));
- CLog.i("Lipsync Mean: " + meanLipSync);
- } else {
- CLog.w("Lipsync value not found in result.");
- }
- }
- CLog.i("== End ==", keyprefix);
- return metrics;
- }
-
- protected IRunUtil getRunUtil() {
- return RunUtil.getDefault();
- }
-}