Merge the jank test tools to unbundle branch
bug: 8549606
Change-Id: I60c25d3dce60aa9da675c71c8245c789d42671ab
diff --git a/uiautomator_test_libraries/src/com/android/uiautomator/common/UiWatchers.java b/uiautomator_test_libraries/src/com/android/uiautomator/common/UiWatchers.java
new file mode 100644
index 0000000..dd1bb5b
--- /dev/null
+++ b/uiautomator_test_libraries/src/com/android/uiautomator/common/UiWatchers.java
@@ -0,0 +1,163 @@
+/*
+ * Copyright (C) 2013 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.uiautomator.common;
+
+import android.util.Log;
+
+import com.android.uiautomator.core.UiDevice;
+import com.android.uiautomator.core.UiObject;
+import com.android.uiautomator.core.UiObjectNotFoundException;
+import com.android.uiautomator.core.UiSelector;
+import com.android.uiautomator.core.UiWatcher;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+public class UiWatchers {
+ private static final String LOG_TAG = UiWatchers.class.getSimpleName();
+ private final List<String> mErrors = new ArrayList<String>();
+
+ /**
+ * We can use the UiDevice registerWatcher to register a small script to be executed when the
+ * framework is waiting for a control to appear. Waiting may be the cause of an unexpected
+ * dialog on the screen and it is the time when the framework runs the registered watchers.
+ * This is a sample watcher looking for ANR and crashes. it closes it and moves on. You should
+ * create your own watchers and handle error logging properly for your type of tests.
+ */
+ public void registerAnrAndCrashWatchers() {
+
+ UiDevice.getInstance().registerWatcher("ANR", new UiWatcher() {
+ @Override
+ public boolean checkForCondition() {
+ UiObject window = new UiObject(new UiSelector().className(
+ "com.android.server.am.AppNotRespondingDialog"));
+ String errorText = null;
+ if (window.exists()) {
+ try {
+ errorText = window.getText();
+ } catch (UiObjectNotFoundException e) {
+ Log.e(LOG_TAG, "dialog gone?", e);
+ }
+ onAnrDetected(errorText);
+ postHandler();
+ return true; // triggered
+ }
+ return false; // no trigger
+ }
+ });
+
+ // class names may have changed
+ UiDevice.getInstance().registerWatcher("ANR2", new UiWatcher() {
+ @Override
+ public boolean checkForCondition() {
+ UiObject window = new UiObject(new UiSelector().packageName("android")
+ .textContains("isn't responding."));
+ if (window.exists()) {
+ String errorText = null;
+ try {
+ errorText = window.getText();
+ } catch (UiObjectNotFoundException e) {
+ Log.e(LOG_TAG, "dialog gone?", e);
+ }
+ onAnrDetected(errorText);
+ postHandler();
+ return true; // triggered
+ }
+ return false; // no trigger
+ }
+ });
+
+ UiDevice.getInstance().registerWatcher("CRASH", new UiWatcher() {
+ @Override
+ public boolean checkForCondition() {
+ UiObject window = new UiObject(new UiSelector().className(
+ "com.android.server.am.AppErrorDialog"));
+ if (window.exists()) {
+ String errorText = null;
+ try {
+ errorText = window.getText();
+ } catch (UiObjectNotFoundException e) {
+ Log.e(LOG_TAG, "dialog gone?", e);
+ }
+ onCrashDetected(errorText);
+ postHandler();
+ return true; // triggered
+ }
+ return false; // no trigger
+ }
+ });
+
+ UiDevice.getInstance().registerWatcher("CRASH2", new UiWatcher() {
+ @Override
+ public boolean checkForCondition() {
+ UiObject window = new UiObject(new UiSelector().packageName("android")
+ .textContains("has stopped"));
+ if (window.exists()) {
+ String errorText = null;
+ try {
+ errorText = window.getText();
+ } catch (UiObjectNotFoundException e) {
+ Log.e(LOG_TAG, "dialog gone?", e);
+ }
+ onCrashDetected(errorText);
+ postHandler();
+ return true; // triggered
+ }
+ return false; // no trigger
+ }
+ });
+
+ Log.i(LOG_TAG, "Registed GUI Exception watchers");
+ }
+
+ public void onAnrDetected(String errorText) {
+ mErrors.add(errorText);
+ }
+
+ public void onCrashDetected(String errorText) {
+ mErrors.add(errorText);
+ }
+
+ public void reset() {
+ mErrors.clear();
+ }
+
+ public List<String> getErrors() {
+ return Collections.unmodifiableList(mErrors);
+ }
+
+ /**
+ * Current implementation ignores the exception and continues.
+ */
+ public void postHandler() {
+ // TODO: Add custom error logging here
+
+ String formatedOutput = String.format("UI Exception Message: %-20s\n", UiDevice
+ .getInstance().getCurrentPackageName());
+ Log.e(LOG_TAG, formatedOutput);
+
+ UiObject buttonOK = new UiObject(new UiSelector().text("OK").enabled(true));
+ // sometimes it takes a while for the OK button to become enabled
+ buttonOK.waitForExists(5000);
+ try {
+ buttonOK.click();
+ } catch (UiObjectNotFoundException e) {
+ Log.e(LOG_TAG, "Exception", e);
+ }
+ }
+}
diff --git a/uiautomator_test_libraries/src/com/android/uiautomator/platform/JankTestBase.java b/uiautomator_test_libraries/src/com/android/uiautomator/platform/JankTestBase.java
index 31e7773..bac710e 100644
--- a/uiautomator_test_libraries/src/com/android/uiautomator/platform/JankTestBase.java
+++ b/uiautomator_test_libraries/src/com/android/uiautomator/platform/JankTestBase.java
@@ -23,28 +23,40 @@
import com.android.uiautomator.core.UiDevice;
import com.android.uiautomator.testrunner.UiAutomatorTestCase;
+import java.io.BufferedOutputStream;
+import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
import java.io.FileWriter;
import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.util.ArrayList;
+import java.util.List;
import java.util.Properties;
/**
- * Helper class for jankiness test.
- * All the jank test must extend the JankBaseHelper
+ * Base class for jank test.
+ * All jank test needs to extend JankTestBase
*/
public class JankTestBase extends UiAutomatorTestCase {
+ private final static String TAG = JankTestBase.class.getSimpleName();
+
protected UiDevice mDevice;
+ protected TestWatchers mTestWatchers = null;
protected BufferedWriter mWriter = null;
protected BufferedWriter mStatusWriter = null;
protected int mIteration = 20; // default iteration is set 20
+ /* can be used to enable/disable systrace in the test */
+ protected int mTraceTime = 0;
protected Bundle mParams;
protected String mTestCaseName;
protected int mSuccessTestRuns = 0;
+ protected Thread mThread = null;
- private final static String TAG = JankTestBase.class.getSimpleName();
// holds all params for the derived tests
private final static String PROPERTY_FILE_NAME = "UiJankinessTests.conf";
private final static String PARAM_CONFIG = "conf";
@@ -53,20 +65,112 @@
private static String OUTPUT_FILE_NAME = LOCAL_TMP_DIR + "UiJankinessTestsOutput.txt";
// File that hold test status, e.g successful test iterations
private static String STATUS_FILE_NAME = LOCAL_TMP_DIR + "UiJankinessTestsStatus.txt";
+ private final static String RAW_DATA_DIR = LOCAL_TMP_DIR + "UiJankinessRawData";
+
private static int SUCCESS_THRESHOLD = 80;
private static boolean DEBUG = false;
+ /* default animation time is set to 2 seconds */
+ protected final static long DEFAULT_ANIMATION_TIME = 2 * 1000;
+ /* default swipe steps for fling animation */
+ protected final static int DEFAULT_FLING_STEPS = 8;
+
/* Array to record jankiness data in each test iteration */
private int[] jankinessArray;
/* Array to record frame rate in each test iteration */
private double[] frameRateArray;
/* Array to save max accumulated frame number in each test iteration */
private int[] maxDeltaVsyncArray;
+ /* Default file to store the systrace */
+ private final static File SYSTRACE_DIR = new File(LOCAL_TMP_DIR, "systrace");
+ /* Default trace file name */
+ private final static String TRACE_FILE_NAME = "trace.txt";
+ /* Default tracing time is 5 seconds */
+ private final static int DEFAULT_TRACE_TIME = 5; // 5 seconds
+ // Command to dump compressed trace data
+ private final static String ATRACE_COMMAND = "atrace -z -t %d gfx input view sched freq";
+
+ /**
+ * Thread to capture systrace log from the test
+ */
+ public class SystraceTracker implements Runnable {
+ File mFile = new File(SYSTRACE_DIR, TRACE_FILE_NAME);
+ int mTime = DEFAULT_TRACE_TIME;
+
+ public SystraceTracker(int traceTime, String fileName) {
+ try {
+ if (!SYSTRACE_DIR.exists()) {
+ if (!SYSTRACE_DIR.mkdir()) {
+ log(String.format("create directory %s failed, you can manually create "
+ + "it and start the test again", SYSTRACE_DIR.getAbsolutePath()));
+ return;
+ }
+ }
+ } catch (SecurityException e) {
+ Log.e(TAG, "creating directory failed?", e);
+ }
+
+ if (traceTime > 0) {
+ mTime = traceTime;
+ }
+ if (fileName != null) {
+ mFile = new File(SYSTRACE_DIR, fileName);
+ }
+ }
+
+ @Override
+ public void run() {
+ String command = String.format(ATRACE_COMMAND, mTime);
+ Log.v(TAG, "command: " + command);
+ Process p = null;
+ InputStream in = null;
+ BufferedOutputStream out = null;
+ try {
+ p = Runtime.getRuntime().exec(command);
+ Log.v(TAG, "write systrace into file: " + mFile.getAbsolutePath());
+ // read bytes from the process output stream as the output is compressed
+ byte[] buffer = new byte[1024];
+ in = p.getInputStream();
+ out = new BufferedOutputStream(new FileOutputStream(mFile));
+ int n;
+ while ((n = in.read(buffer)) != -1) {
+ out.write(buffer, 0, n);
+ out.flush();
+ }
+ in.close();
+ out.close();
+ // read error message
+ BufferedReader br = new BufferedReader(new InputStreamReader(p.getErrorStream()));
+ String line;
+ while ((line = br.readLine()) != null) {
+ Log.e(TAG, "Command return errors: " + line);
+ }
+ br.close();
+
+ // Due to limited buffer size for standard input and output stream,
+ // promptly reading from the input stream or output stream to avoid block
+ int status = p.waitFor();
+ if (status != 0) {
+ Log.e(TAG, String.format("Run shell command: %s, status: %s",
+ command, status));
+ }
+ } catch (InterruptedException e) {
+ Log.e(TAG, "Exception from command " + command + ":");
+ Log.e(TAG, "Thread interrupted? ", e);
+ } catch (IOException e) {
+ Log.e(TAG, "Open file error: ", e);
+ } catch (IllegalThreadStateException e) {
+ Log.e(TAG, "the process has not exit yet ", e);
+ }
+ }
+ }
@Override
protected void setUp() throws Exception {
super.setUp();
mDevice = UiDevice.getInstance();
+ mTestWatchers = new TestWatchers(); // extends the common class UiWatchers
+ mTestWatchers.registerAnrAndCrashWatchers();
mWriter = new BufferedWriter(new FileWriter(new File(OUTPUT_FILE_NAME), true));
mStatusWriter = new BufferedWriter(new FileWriter(new File(STATUS_FILE_NAME), true));
@@ -74,10 +178,14 @@
mParams = getParams();
if (mParams != null && !mParams.isEmpty()) {
log("mParams is not empty, get properties.");
- String mIterationStr;
- if ((mIterationStr = getPropertyString(mParams, "iteration")) != null) {
+ String mIterationStr = getPropertyString(mParams, "iteration");
+ if (mIterationStr != null) {
mIteration = Integer.valueOf(mIterationStr);
}
+ String mTraceTimeStr = getPropertyString(mParams, "tracetime");
+ if (mTraceTimeStr != null) {
+ mTraceTime = Integer.valueOf(mTraceTimeStr);
+ }
}
jankinessArray = new int[mIteration];
frameRateArray = new double[mIteration];
@@ -89,6 +197,33 @@
}
/**
+ * Create a new thread for systrace and start the thread
+ *
+ * @param testCaseName
+ * @param iteration
+ */
+ protected void startTrace(String testCaseName, int iteration) {
+ if (mTraceTime > 0) {
+ String outputFile = String.format("%s_%d_trace", mTestCaseName, iteration);
+ mThread = new Thread(new SystraceTracker(mTraceTime, outputFile));
+ mThread.start();
+ }
+ }
+
+ /**
+ * Wait for the tracing thread to exit
+ */
+ protected void endTrace() {
+ if (mThread != null) {
+ try {
+ mThread.join();
+ } catch (InterruptedException e) {
+ Log.e(TAG, "wait for the trace thread to exit exception:", e);
+ }
+ }
+ }
+
+ /**
* Expects a file from the command line via conf param or default following format each on its
* own line. <code>
* key=Value
@@ -147,6 +282,38 @@
*/
protected void recordResults(String testCaseName, int iteration) {
long refreshPeriod = SurfaceFlingerHelper.getRefreshPeriod();
+ // if the raw directory doesn't exit, create the directory
+ File rawDataDir = new File(RAW_DATA_DIR);
+ try {
+ if (!rawDataDir.exists()) {
+ if (!rawDataDir.mkdir()) {
+ log(String.format("create directory %s failed, you can manually create " +
+ "it and start the test again", rawDataDir));
+ }
+ }
+ } catch (SecurityException e) {
+ Log.e(TAG, "create directory failed: ", e);
+ }
+ String rawFileName = String.format("%s/%s_%d.txt", RAW_DATA_DIR, testCaseName, iteration);
+ // write results into a file
+ BufferedWriter fw = null;
+ try {
+ fw = new BufferedWriter(new FileWriter(new File(rawFileName), false));
+ fw.write(SurfaceFlingerHelper.getFrameBufferData());
+ } catch (IOException e) {
+ Log.e(TAG, "failed to write to file", e);
+ return;
+ } finally {
+ try {
+ if (fw != null) {
+ fw.close();
+ }
+ }
+ catch (IOException e) {
+ Log.e(TAG, "close file failed.", e);
+ }
+ }
+
// get jankiness count
int jankinessCount = SurfaceFlingerHelper.getVsyncJankiness();
// get frame rate
@@ -302,5 +469,4 @@
protected int getIteration(){
return mIteration;
}
-
}
diff --git a/uiautomator_test_libraries/src/com/android/uiautomator/platform/SurfaceFlingerHelper.java b/uiautomator_test_libraries/src/com/android/uiautomator/platform/SurfaceFlingerHelper.java
index 1fcdafd..fe69ea9 100644
--- a/uiautomator_test_libraries/src/com/android/uiautomator/platform/SurfaceFlingerHelper.java
+++ b/uiautomator_test_libraries/src/com/android/uiautomator/platform/SurfaceFlingerHelper.java
@@ -37,8 +37,8 @@
private static String TAG = "SurfaceFlingerHelper";
private static int BUFFER_SIZE = 128;
private static int BUFFER_NUMBER = 3;
- private static String CLEAR_BUFFER_CMD = "dumpsys SurfaceFlinger --latency-clear %s";
- private static String FRAME_LATENCY_CMD = "dumpsys SurfaceFlinger --latency %s";
+ private static String CLEAR_BUFFER_CMD = "dumpsys SurfaceFlinger --latency-clear";
+ private static String FRAME_LATENCY_CMD = "dumpsys SurfaceFlinger --latency";
private final static String RAW_DATA_DIR = "UiJankinessRawData";
private final static String LOCAL_TMP_DIR = "/data/local/tmp/";
/* If the latency between two frames is greater than this number, it it treated as a pause
@@ -66,6 +66,8 @@
/* Normalized data */
private static double[] mNormalizedDelta2Vsync = new double[BUFFER_SIZE];
private static int[] mRoundNormalizedDelta2Vsync = new int[BUFFER_SIZE];
+ // Symbol of unfinished frame time */
+ public final static String PENDING_FENCE_TIME = new Long(Long.MAX_VALUE).toString();
/**
* Run clear buffer command and clear the saved frame buffer results
@@ -87,20 +89,21 @@
Process p = null;
BufferedReader resultReader = null;
- String command = String.format(CLEAR_BUFFER_CMD, windowName);
+ String command = CLEAR_BUFFER_CMD;
+ if (windowName != null) {
+ command = String.format("%s %s", CLEAR_BUFFER_CMD, windowName);
+ }
try {
p = Runtime.getRuntime().exec(command);
int status = p.waitFor();
if (status != 0) {
- System.err.println(String.format("Run shell command: %s, status: %s",
+ Log.e(TAG, String.format("Run shell command: %s, status: %s",
command, status));
}
} catch (IOException e) {
- System.err.println("// Exception from command " + command + ":");
- System.err.println(e.toString());
+ Log.e(TAG, "// Exception from command " + command + ":", e);
} catch (InterruptedException e) {
- System.err.println("// Interrupted while waiting for the command to finish. ");
- System.err.println(e.toString());
+ Log.e(TAG, "// Interrupted while waiting for the command to finish. ", e);
} finally {
try {
if (resultReader != null) {
@@ -110,80 +113,81 @@
p.destroy();
}
} catch (IOException e) {
- System.err.println(e.toString());
+ Log.e(TAG, "exception " + e);
}
}
}
/**
- * Run frame latency command to get the raw data, save raw data on the disk
+ * Run frame latency command without ignoring pending fence time
*
- * @param windowName
- * @return
+ * @param windowName the window name which SurfaceFlinger will acquire frame time for
*/
- public static boolean dumpFrameLatency(String windowName, String fileName, int index) {
- BufferedWriter fw = null;
+ public static boolean dumpFrameLatency(String windowName) {
+ return dumpFrameLatency(windowName, false);
+ }
+
+ /**
+ * Run frame latency command to get frame time
+ *
+ * @param windowName the window name which SurfaceFlinger will get frame time for
+ * @param ignorePendingFenceTime flag to process frames with pending fence time
+ * set true to ignore pending fence time
+ * set false to fail the test if pending fence time is not allowed
+ */
+ public static boolean dumpFrameLatency(String windowName, boolean ignorePendingFenceTime) {
Process p = null;
BufferedReader resultReader = null;
- String command = String.format(FRAME_LATENCY_CMD, windowName);
- // if the raw directory doesn't exit, create the directory
- File rawDataDir = new File(LOCAL_TMP_DIR, RAW_DATA_DIR);
- try {
- if (!rawDataDir.exists()) {
- if (!rawDataDir.mkdir()) {
- log(String.format("create directory %s failed, you can manually create " +
- "it and start the test again", rawDataDir));
- return false;
- }
- }
- } catch (SecurityException e) {
- System.err.println(e.toString());
+ String command = FRAME_LATENCY_CMD;
+ if (windowName != null) {
+ command = String.format("%s %s", FRAME_LATENCY_CMD, windowName);
}
- String rawFileName = String.format("%s/%s_%d.txt", RAW_DATA_DIR, fileName, index);
-
+ log("dump frame latency command: " + command);
try {
p = Runtime.getRuntime().exec(command);
int status = p.waitFor();
if (status != 0) {
- System.err.println(String.format("Run shell command: %s, status: %s",
- command, status));
+ Log.e(TAG, String.format("Run shell command: %s, status: %s",command, status));
}
resultReader = new BufferedReader(new InputStreamReader(p.getInputStream()));
- fw = new BufferedWriter(new FileWriter(new File(
- LOCAL_TMP_DIR, rawFileName), false));
- // The first line will always show the refresh period
String line = resultReader.readLine();
- Log.v("testing", "output line = " + line);
- fw.write(line);
- fw.write("\n");
mRefreshPeriod = Long.parseLong(line.trim());
- //log("reading refresh period: " + mRefreshPeriod);
+ log("reading refresh period: " + mRefreshPeriod);
if (mRefreshPeriod < 0) {
return false;
}
-
+ boolean dataInvalidFlag = false;
while((line = resultReader.readLine()) != null) {
- fw.write(line);
- fw.write("\n");
-
- // remove the last line which is empty
+ // remove lines which are empty
if (line.trim().isEmpty()) {
break;
}
String[] bufferValues = line.split("\\s+");
if (bufferValues[0].trim().compareTo("0") == 0) {
continue;
+ } else if (bufferValues[1].trim().compareTo(PENDING_FENCE_TIME) == 0 ) {
+ if (ignorePendingFenceTime) {
+ log("ignore pending fence time");
+ dataInvalidFlag = true;
+ } else {
+ log("the data contains unfinished frame time, please allow the animation"
+ + " to finish in the test before calling dumpFrameLatency.");
+ return false;
+ }
}
+ // store raw data which could have both valid and invalid data
List<String> delayArray = Arrays.asList(bufferValues);
mFrameBufferData.add(delayArray);
- ++mFrameLatencySampleSize;
+ if (!dataInvalidFlag) {
+ // only count frames which have valid time
+ ++mFrameLatencySampleSize;
+ }
}
log("frame latency sample size: " + mFrameLatencySampleSize);
} catch (InterruptedException e) {
- System.err.println("// Exception from command " + command + ":");
- System.err.println(e.toString());
+ Log.e(TAG, "// Exception from command " + command + ":", e);
} catch (IOException e) {
- log("Open file error: " + e.toString());
+ Log.e(TAG, "Open file error: ", e);
return false;
}
finally {
@@ -191,14 +195,11 @@
if (resultReader != null) {
resultReader.close();
}
- if (fw != null) {
- fw.close();
- }
if (p != null) {
p.destroy();
}
} catch (IOException e) {
- System.err.println(e.toString());
+ Log.e(TAG, "io exception: ", e);
}
}
return true;
@@ -219,12 +220,12 @@
}
String rawData = String.format("%d\n", mRefreshPeriod);
List<String> tempList = new ArrayList<String>(BUFFER_NUMBER);
- for (int i = 0; i < mFrameLatencySampleSize; i++) {
+ for (int i = 0; i < mFrameBufferData.size(); i++) {
tempList = mFrameBufferData.get(i);
for (int j = 0; j < BUFFER_NUMBER; j++) {
rawData += String.format("%s", tempList.get(j));
- if (j < BUFFER_NUMBER -1) {
- rawData += " ";
+ if (j < BUFFER_NUMBER - 1) {
+ rawData += "\t";
} else {
rawData += "\n";
}
@@ -243,13 +244,12 @@
return null;
}
if (mDeltaVsync[0] < 0 ) {
- mDeltaVsync = new long[BUFFER_SIZE];
// keep a record of the max DeltaVsync
mMaxDeltaVsync = 0;
// get the first frame vsync time
long preVsyncTime = Long.parseLong(mFrameBufferData.get(0).get(1));
- for (int i = 1; i < mFrameLatencySampleSize; i++) {
- long curVsyncTime = Long.parseLong(mFrameBufferData.get(i).get(1));
+ for (int i = 0; i < mFrameLatencySampleSize - 1; i++) {
+ long curVsyncTime = Long.parseLong(mFrameBufferData.get(i + 1).get(1));
mDeltaVsync[i] = curVsyncTime - preVsyncTime;
preVsyncTime = curVsyncTime;
if (mMaxDeltaVsync < mDeltaVsync[i]) {
@@ -273,9 +273,9 @@
getDeltaVsync();
}
if (mDelta2Vsync[0] < 0) {
- mDelta2Vsync = new long[BUFFER_SIZE];
- for (int i = 1; i < mFrameLatencySampleSize; i++) {
- mDelta2Vsync[i] = mDeltaVsync[i] - mDeltaVsync[i - 1];
+ int numDeltaVsync = mFrameLatencySampleSize - 1;
+ for (int i = 0; i < numDeltaVsync - 1; i++) {
+ mDelta2Vsync[i] = mDeltaVsync[i + 1] - mDeltaVsync[i];
}
}
return mDelta2Vsync;
@@ -294,8 +294,7 @@
getDelta2Vsync();
}
if (mNormalizedDelta2Vsync[0] < 0) {
- mNormalizedDelta2Vsync = new double[BUFFER_SIZE];
- for (int i = 0; i < mFrameLatencySampleSize; i++) {
+ for (int i = 0; i < mFrameLatencySampleSize - 2; i++) {
mNormalizedDelta2Vsync[i] = (double)mDelta2Vsync[i] /mRefreshPeriod;
}
}
@@ -311,7 +310,7 @@
getNormalizedDelta2Vsync();
}
- for (int i = 0; i < mFrameLatencySampleSize; i++) {
+ for (int i = 0; i < mFrameLatencySampleSize - 2; i++) {
int value = (int)Math.round(Math.max(mNormalizedDelta2Vsync[i], 0.0));
mRoundNormalizedDelta2Vsync[i] = value;
}
@@ -330,7 +329,7 @@
getRoundNormalizedDelta2Vsync();
}
int numberJankiness = 0;
- for (int i = 0; i < mFrameLatencySampleSize; i++) {
+ for (int i = 0; i < mFrameLatencySampleSize - 2; i++) {
int value = mRoundNormalizedDelta2Vsync[i];
// ignore the latency which is too long
if (value > 0 && value < PAUSE_LATENCY) {
@@ -376,8 +375,7 @@
log("write raw data and process data into file: " + rawAndProcDataFileName);
BufferedWriter fw = null;
try {
- fw = new BufferedWriter(new FileWriter(new File(
- LOCAL_TMP_DIR, rawAndProcDataFileName), false));
+ fw = new BufferedWriter(new FileWriter(new File(rawAndProcDataFileName), false));
// Show the number of jankiness first:
fw.write(String.format("Jankiness count: %d\n", getVsyncJankiness()));
fw.write(String.format("Max accumulated frames: %d\n", getMaxDeltaVsync()));
@@ -408,7 +406,7 @@
}
}
catch (IOException e) {
- System.err.println(e.toString());
+ Log.e(TAG, "close file exception: ", e);
}
}
}
diff --git a/uiautomator_test_libraries/src/com/android/uiautomator/platform/TestWatchers.java b/uiautomator_test_libraries/src/com/android/uiautomator/platform/TestWatchers.java
new file mode 100644
index 0000000..5cab83a
--- /dev/null
+++ b/uiautomator_test_libraries/src/com/android/uiautomator/platform/TestWatchers.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2013 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.uiautomator.platform;
+
+import com.android.uiautomator.common.UiWatchers;
+
+public class TestWatchers extends UiWatchers {
+ private String TAG = "TestWatchers";
+
+ @Override
+ public void onAnrDetected(String errorText) {
+ // The ANR dialog is still open now and upon returning from here
+ // it will automatically get closed. See UiWatchers or implement
+ // your handlers directly.
+ super.onAnrDetected("ANR:" + errorText);
+ }
+
+ @Override
+ public void onCrashDetected(String errorText) {
+ // what do we need to do here?
+ // The Crash dialog is still open now and upon returning from here
+ // it will automatically get closed. See UiWatchers or implement
+ // your handlers directly.
+ super.onCrashDetected("CRASH:" + errorText);
+ }
+}