blob: dcbcce1a79c899ae56f90ce5f7c84f703f9be6d5 [file] [log] [blame]
/*
* 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 android.sustainedPerformance.cts;
import com.android.ddmlib.MultiLineReceiver;
import com.android.ddmlib.IShellOutputReceiver;
import com.android.tradefed.device.ITestDevice;
import com.android.tradefed.testtype.DeviceTestCase;
import com.android.ddmlib.Log;
import java.util.Scanner;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.concurrent.TimeUnit;
import java.util.*;
/**
* Test to check if device implements Sustained Performance Mode
*/
public class SustainedPerformanceHostTest extends DeviceTestCase {
ITestDevice device;
private static final String PACKAGE = "com.android.gputest";
private static final String CLASS = "GPUStressTestActivity";
private static final String START_COMMAND = String.format(
"am start -W -a android.intent.action.MAIN -n %s/%s.%s",
PACKAGE, PACKAGE, CLASS);
private static final String START_COMMAND_MODE = String.format(
"am start -W -a android.intent.action.MAIN -n %s/%s.%s --ez SustainedPerformanceMode true",
PACKAGE, PACKAGE, CLASS);
private static final String STOP_COMMAND = String.format(
"am force-stop %s", PACKAGE);
private static final String TEST_PACKAGE = "android.test.app";
private static final String TEST_CLASS = "DeviceTestActivity";
private static final String START_TEST_COMMAND = String.format(
"am start -W -a android.intent.action.MAIN -n %s/%s.%s",
TEST_PACKAGE, TEST_PACKAGE, TEST_CLASS);
private static final String DHRYSTONE = "/data/local/tmp/";
private static final String LOG_TAG = "sustainedPerfTest";
private static ArrayList<Double> appResultsWithMode = new ArrayList<Double>();
private static ArrayList<Double> appResultsWithoutMode = new ArrayList<Double>();
private static ArrayList<Double> dhrystoneResultsWithMode = new ArrayList<Double>();
private static ArrayList<Double> dhrystoneResultsWithoutMode = new ArrayList<Double>();
private double dhryMin = Double.MAX_VALUE, dhryMax = Double.MIN_VALUE;
private static long testDuration = 1800000; //30 minutes
public class Dhrystone implements Runnable {
private boolean modeEnabled;
private long startTime;
private long loopCount = 3000000;
public Dhrystone(boolean enabled) {
modeEnabled = enabled;
startTime = System.currentTimeMillis();
}
public void run() {
double[] testSet = new double[3];
int index = 0;
try {
device.executeShellCommand("cd " + DHRYSTONE + " ; chmod 777 dhry");
while (true) {
String result = device.executeShellCommand("echo " + loopCount + " | " + DHRYSTONE + "dhry");
if (Math.abs(System.currentTimeMillis() - startTime) >= testDuration) {
break;
} else if (result.contains("Measured time too small")) {
loopCount = loopCount*10;
} else if (!result.isEmpty()){
double dmips = Double.parseDouble(result);
testSet[index++] = dmips;
if (index == 3) {
synchronized(this) {
if (modeEnabled) {
dhrystoneResultsWithMode.add(testSet[1]);
} else {
dhrystoneResultsWithoutMode.add(testSet[1]);
}
if (testSet[1] > dhryMax) {
dhryMax = testSet[1];
}
if (testSet[1] < dhryMin) {
dhryMin = testSet[1];
}
index = 0;
}
}
}
}
} catch (Exception e) {
Log.e(LOG_TAG, e.toString());
}
}
}
public void analyzeResults(String logs, boolean mode) {
Double[] testSet = new Double[10];
int index = 0;
double min = Double.MAX_VALUE, max = Double.MIN_VALUE;
boolean first = true;
Scanner in = new Scanner(logs);
while (in.hasNextLine()) {
String line = in.nextLine();
if(line.startsWith("I/"+CLASS)) {
Double time = Double.parseDouble(line.split(":")[1]);
testSet[index++] = time;
if (index == 10) {
if (first) {
first = false;
index = 0;
continue;
}
Arrays.sort(testSet);
if (mode) {
appResultsWithMode.add(testSet[5]);
} else {
appResultsWithoutMode.add(testSet[5]);
}
if (testSet[5] > max) {
max = testSet[5];
}
if (testSet[5] < min) {
min = testSet[5];
}
index = 0;
}
}
}
in.close();
double diff = (max - min)*100/max;
if (mode) {
appResultsWithMode.add(0, min);
appResultsWithMode.add(1, max);
appResultsWithMode.add(2, diff);
} else {
appResultsWithoutMode.add(0, min);
appResultsWithoutMode.add(1, max);
appResultsWithoutMode.add(2, diff);
}
}
private void setUpEnvironment() throws Exception {
device.disconnectFromWifi();
dhryMin = Double.MAX_VALUE;
dhryMax = Double.MIN_VALUE;
Thread.sleep(600000);
device.executeAdbCommand("logcat", "-c");
device.executeShellCommand("settings put global airplane_mode_on 1");
device.executeShellCommand("am broadcast -a android.intent.action.AIRPLANE_MODE --ez state true");
}
public void testShader() throws Exception {
device = getDevice();
/**
* Check if the device supports Sustained Performance Mode.
* If not then assert true and return.
**/
device.executeAdbCommand("logcat", "-c");
device.executeShellCommand(START_TEST_COMMAND);
String logs = device.executeAdbCommand("logcat", "-v", "brief", "-d", TEST_CLASS + ":I", "*:S");
String testString = "";
Scanner in = new Scanner(logs);
while (in.hasNextLine()) {
String line = in.nextLine();
if(line.startsWith("I/"+TEST_CLASS)) {
testString = line.split(":")[1].trim();
}
}
in.close();
if (testString.isEmpty()) {
assertTrue(true);
return;
}
appResultsWithoutMode.clear();
appResultsWithMode.clear();
dhrystoneResultsWithoutMode.clear();
dhrystoneResultsWithMode.clear();
/*
* Run the test without the mode.
* Start the application and collect stats.
* Run two threads of dhrystone and collect stats.
*/
setUpEnvironment();
device.executeShellCommand(START_COMMAND);
Thread dhrystone = new Thread(new Dhrystone(false));
Thread dhrystone1 = new Thread(new Dhrystone(false));
dhrystone.start();
dhrystone1.start();
Thread.sleep(testDuration);
device.executeShellCommand(STOP_COMMAND);
dhrystone.join();
dhrystone1.join();
logs = device.executeAdbCommand("logcat", "-v", "brief", "-d", CLASS + ":I", "*:S");
analyzeResults(logs, false);
double diff = (dhryMax - dhryMin)*100/dhryMax;
dhrystoneResultsWithoutMode.add(0, dhryMin);
dhrystoneResultsWithoutMode.add(1, dhryMax);
dhrystoneResultsWithoutMode.add(2, diff);
/*
* Run the test with the mode.
* Start the application and collect stats.
* Run two threads of dhrystone and collect stats.
*/
setUpEnvironment();
device.executeShellCommand(START_COMMAND_MODE);
dhrystone = new Thread(new Dhrystone(true));
dhrystone1 = new Thread(new Dhrystone(true));
dhrystone.start();
dhrystone1.start();
Thread.sleep(testDuration);
device.executeShellCommand(STOP_COMMAND);
dhrystone.join();
dhrystone1.join();
logs = device.executeAdbCommand("logcat", "-v", "brief", "-d", CLASS + ":I", "*:S");
analyzeResults(logs, true);
diff = (dhryMax - dhryMin)*100/dhryMax;
dhrystoneResultsWithMode.add(0, dhryMin);
dhrystoneResultsWithMode.add(1, dhryMax);
dhrystoneResultsWithMode.add(2, diff);
device.executeShellCommand("settings put global airplane_mode_on 0");
device.executeShellCommand("am broadcast -a android.intent.action.AIRPLANE_MODE --ez state false");
double perfdegradapp = (appResultsWithMode.get(1) - appResultsWithoutMode.get(1))*100/appResultsWithMode.get(1);
double perfdegraddhry = (dhrystoneResultsWithoutMode.get(0) - dhrystoneResultsWithMode.get(0))*100/dhrystoneResultsWithoutMode.get(0);
/*
* Checks if the performance in the mode is consistent with
* 5% error margin.
*/
assertFalse("Results in the mode are not sustainable",
(dhrystoneResultsWithMode.get(2) > 5) ||
(appResultsWithMode.get(2)) > 5);
}
}