diff --git a/uiautomator_test_libraries/Android.mk b/uiautomator_test_libraries/Android.mk
new file mode 100644
index 0000000..f975016
--- /dev/null
+++ b/uiautomator_test_libraries/Android.mk
@@ -0,0 +1,33 @@
+#
+# 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.
+#
+local_target_dir := $(TARGET_OUT_DATA)/local/tmp
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+
+LOCAL_MODULE := com.android.uiautomator.platform.common
+
+LOCAL_SDK_VERSION := 16
+
+LOCAL_JAVA_LIBRARIES := uiautomator_sdk_v$(LOCAL_SDK_VERSION)
+
+LOCAL_MODULE_TAGS := optional
+
+LOCAL_MODULE_PATH := $(local_target_dir)
+
+include $(BUILD_STATIC_JAVA_LIBRARY)
diff --git a/uiautomator_test_libraries/src/com/android/uiautomator/common/helpers/AppHelperBase.java b/uiautomator_test_libraries/src/com/android/uiautomator/common/helpers/AppHelperBase.java
new file mode 100644
index 0000000..9bd474e
--- /dev/null
+++ b/uiautomator_test_libraries/src/com/android/uiautomator/common/helpers/AppHelperBase.java
@@ -0,0 +1,96 @@
+/*
+ * 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.uiautomator.common.helpers;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+
+/**
+ * Base app helper class intended for all app helper to extend.
+ * This class provides common APIs that are expected to be present across
+ * all app helpers.
+ */
+public abstract class AppHelperBase {
+
+    /*
+     * App helpers should provide methods for accessing various UI widgets.
+     * Assume the app has an Action Bar, the helper should provide something similar to
+     * SomeAppHelper.ActionBar.getRefreshButton(). Methods like this help the tests check the
+     * state of the targeted widget as well as clicking it if need be. These types of methods are
+     * referred to as object getters. If there are different components, consider creating internal
+     * name spaces as in the .ActionBar example for better context.
+     *
+     * Adding basic units of functionality APIs is also very helpful to test.
+     * Consider the Alarm clock application as an example. It would be helpful if its helper
+     * provided basic functionality such as, setAlarm(Date) and deleteAlarm(Date). Such basic
+     * and key functionality helper methods, will abstract the tests from the UI implementation and
+     * make tests more reliable.
+     */
+
+    /**
+     * Launches the application.
+     *
+     * This is typically performed by executing a shell command to launch the application
+     * via Intent. It is possible to launch the application by automating the Launcher
+     * views and finding the target app icon to launch, however, this is prone to failure if
+     * the Launcher UI implementation differ from one platform to another.
+     */
+    abstract public void open();
+
+    /**
+     * Checks if the application is in foreground.
+     *
+     * This is typically performed by verifying the current package name of the foreground
+     * application. See UiDevice.getCurrentPackageName()
+     * @return true if open, else false.
+     */
+    abstract public boolean isOpen();
+
+
+    /**
+     * Helper to execute a shell command.
+     * @param command
+     */
+    protected void runShellCommand(String command) {
+        Process p = null;
+        BufferedReader resultReader = null;
+        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));
+            }
+        } catch (IOException e) {
+            System.err.println("// Exception from command " + command + ":");
+            System.err.println(e.toString());
+        } catch (InterruptedException e) {
+            System.err.println("// Interrupted while waiting for the command to finish. ");
+            System.err.println(e.toString());
+        } finally {
+            try {
+                if (resultReader != null) {
+                    resultReader.close();
+                }
+                if (p != null) {
+                    p.destroy();
+                }
+            } catch (IOException e) {
+                System.err.println(e.toString());
+            }
+        }
+    }
+}
diff --git a/uiautomator_test_libraries/src/com/android/uiautomator/platform/JankTestBase.java b/uiautomator_test_libraries/src/com/android/uiautomator/platform/JankTestBase.java
new file mode 100644
index 0000000..1e554bd
--- /dev/null
+++ b/uiautomator_test_libraries/src/com/android/uiautomator/platform/JankTestBase.java
@@ -0,0 +1,306 @@
+/*
+ * 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.uiautomation.platform;
+
+import android.os.Bundle;
+import android.os.Environment;
+import android.util.Log;
+
+import com.android.uiautomator.core.UiDevice;
+import com.android.uiautomator.testrunner.UiAutomatorTestCase;
+
+import java.io.BufferedWriter;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.util.Properties;
+
+/**
+ * Helper class for jankiness test.
+ * All the jank test must extend the JankBaseHelper
+ */
+public class JankTestBase extends UiAutomatorTestCase {
+    protected UiDevice mDevice;
+    protected BufferedWriter mWriter = null;
+    protected BufferedWriter mStatusWriter = null;
+    protected int mIteration = 1; // default iteration is set 1
+    protected Bundle mParams;
+    protected String mTestCaseName;
+    protected int mSuccessTestRuns = 0;
+
+    private final static String TAG = "BasePerformance";
+    // holds all params for the derived tests
+    private final static String PROPERTY_FILE_NAME = "UiJankinessTests.conf";
+    private final static String PARAM_CONFIG = "conf";
+    private final static String LOCAL_TMP_DIR = "/data/local/tmp/";
+    // File that hold the test results
+    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 static int SUCCESS_THRESHOLD = 80;
+    private static boolean DEBUG = false;
+
+    /* 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;
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        mDevice = UiDevice.getInstance();
+
+        mWriter = new BufferedWriter(new FileWriter(new File(OUTPUT_FILE_NAME), true));
+        mStatusWriter = new BufferedWriter(new FileWriter(new File(STATUS_FILE_NAME), true));
+
+        mParams = getParams();
+        if (mParams != null && !mParams.isEmpty()) {
+            log("mParams is not empty, get properties.");
+            String mIterationStr;
+            if ((mIterationStr = getPropertyString(mParams, "iteration")) != null) {
+                mIteration = Integer.valueOf(mIterationStr);
+            }
+        }
+        jankinessArray = new int[mIteration];
+        frameRateArray = new double[mIteration];
+        maxDeltaVsyncArray = new int[mIteration];
+        mTestCaseName = this.getName();
+
+        mSuccessTestRuns = 0;
+        mDevice.pressHome();
+    }
+
+    /**
+     * Expects a file from the command line via conf param or default following format each on its
+     * own line. <code>
+     *    key=Value
+     *    Browser_URL1=cnn.com
+     *    Browser_URL2=google.com
+     *    Camera_ShutterDelay=1000
+     *    etc...
+     * </code>
+     * @param Bundle params
+     * @param key
+     * @return the value of the property else defaultValue
+     * @throws FileNotFoundException
+     * @throws IOException
+     */
+    protected String getPropertyString(Bundle params, String key)
+            throws FileNotFoundException, IOException {
+        Properties prop = new Properties();
+        prop.load(new FileInputStream(new File(LOCAL_TMP_DIR,
+                params.getString(PARAM_CONFIG, PROPERTY_FILE_NAME))));
+        String value = prop.getProperty(key);
+        if (value != null && !value.isEmpty())
+            return value;
+        return null;
+    }
+
+    /**
+     * Expects a file from the command line via conf param or default following format each on its
+     * own line. <code>
+     *    key=Value
+     *    Browser_URL1=cnn.com
+     *    Browser_URL2=google.com
+     *    Camera_ShutterDelay=1000
+     *    etc...
+     * </code>
+     * @param Bundle params
+     * @param key
+     * @return the value of the property else defaultValue
+     * @throws FileNotFoundException
+     * @throws IOException
+     */
+    protected long getPropertyLong(Bundle params, String key)
+            throws FileNotFoundException, IOException {
+        Properties prop = new Properties();
+        prop.load(new FileInputStream(new File(LOCAL_TMP_DIR,
+                params.getString(PARAM_CONFIG, PROPERTY_FILE_NAME))));
+        String value = prop.getProperty(key);
+        if (value != null && !value.trim().isEmpty())
+            return Long.valueOf(value.trim());
+        return 0;
+    }
+
+    /**
+     * Process the raw data, calculate jankiness, frame rate and max accumulated frames number
+     * @param testCaseName
+     * @param iteration
+     */
+    protected void recordResults(String testCaseName, int iteration) {
+        long refreshPeriod = SurfaceFlingerHelper.getRefreshPeriod();
+        // get jankiness count
+        int jankinessCount = SurfaceFlingerHelper.getVsyncJankiness();
+        // get frame rate
+        double frameRate = SurfaceFlingerHelper.getFrameRate();
+        // get max accumulated frames
+        int maxDeltaVsync = SurfaceFlingerHelper.getMaxDeltaVsync();
+
+        // only record data when they are valid
+        if (jankinessCount >=0 && frameRate > 0) {
+            jankinessArray[iteration] = jankinessCount;
+            frameRateArray[iteration] = frameRate;
+            maxDeltaVsyncArray[iteration] = maxDeltaVsync;
+            mSuccessTestRuns++;
+        }
+        String msg = String.format("%s, iteration %d\n" +
+                "refresh period: %d\n" +
+                "jankiness count: %d\n" +
+                "frame rate: %f\n" +
+                "max accumulated frames: %d\n",
+                testCaseName, iteration, refreshPeriod,
+                jankinessCount, frameRate, maxDeltaVsync);
+        log(msg);
+        if (DEBUG) {
+            SurfaceFlingerHelper.printData(testCaseName, iteration);
+        }
+    }
+
+    /**
+     * Process data from all test iterations, and save to disk
+     * @param testCaseName
+     */
+    protected void saveResults(String testCaseName) {
+        // write test status into status file
+        try {
+            mStatusWriter.write(String.format("%s: %d success runs out of %d iterations\n",
+                    testCaseName, mSuccessTestRuns, mIteration));
+        } catch (IOException e) {
+            log("failed to write output for test case " + testCaseName);
+        }
+
+        // if successful test runs is less than the threshold, no results will be saved.
+        if (mSuccessTestRuns * 100 / mIteration < SUCCESS_THRESHOLD) {
+            log(String.format("In %s, # of successful test runs out of %s iterations: %d ",
+                    testCaseName, mIteration, mSuccessTestRuns));
+            log(String.format("threshold is %d%%", SUCCESS_THRESHOLD));
+            return;
+        }
+
+        if (DEBUG) {
+            print(jankinessArray, "jankiness array");
+            print(frameRateArray, "frame rate array");
+            print(maxDeltaVsyncArray, "max delta vsync array");
+        }
+        double avgJankinessCount = getAverage(jankinessArray);
+        int maxJankinessCount = getMaxValue(jankinessArray);
+        double avgFrameRate = getAverage(frameRateArray);
+        double avgMaxDeltaVsync = getAverage(maxDeltaVsyncArray);
+
+        String avgMsg = String.format("%s\n" +
+                "average number of jankiness: %f\n" +
+                "max number of jankiness: %d\n" +
+                "average frame rate: %f\n" +
+                "average of max accumulated frames: %f\n",
+                testCaseName, avgJankinessCount, maxJankinessCount, avgFrameRate, avgMaxDeltaVsync);
+        log(avgMsg);
+
+        try {
+            mWriter.write(avgMsg);
+        } catch (IOException e) {
+            log("failed to write output for test case " + testCaseName);
+        }
+    }
+
+    // return the max value in an integer array
+    private int getMaxValue(int[] intArray) {
+        int index = 0;
+        int max = intArray[index];
+        for (int i  = 1; i < intArray.length; i++) {
+            if (max < intArray[i]) {
+                max = intArray[i];
+            }
+        }
+        return max;
+    }
+
+    private double getAverage(int[] intArray) {
+        int mean = 0;
+        int numberTests = 0;
+        for (int i = 0; i < intArray.length; i++) {
+            // in case in some iteration, test fails, no data points is collected
+            if (intArray[i] >= 0) {
+                mean += intArray[i];
+                ++numberTests;
+            }
+        }
+        return (double)mean/numberTests;
+    }
+
+    private double getAverage(double[] doubleArray) {
+        double mean = 0;
+        int numberTests = 0;
+        for (int i = 0; i < doubleArray.length; i++) {
+            // in case in some iteration, test fails, no data points is collected
+            if (doubleArray[i] >= 0) {
+                mean += doubleArray[i];
+                ++numberTests;
+            }
+        }
+        return mean/numberTests;
+    }
+
+    private void print(int[] intArray, String arrayName) {
+        log("start to print array for " + arrayName);
+        for (int i = 0; i < intArray.length; i++) {
+            log(String.format("%d: %d", i, intArray[i]));
+        }
+    }
+
+    private void print(double[] doubleArray, String arrayName) {
+        log("start to print array for " + arrayName);
+        for (int i = 0; i < doubleArray.length; i++) {
+            log(String.format("%d: %f", i, doubleArray[i]));
+        }
+    }
+
+    @Override
+    protected void tearDown() throws Exception {
+        super.tearDown();
+        if (mWriter != null) {
+            mWriter.close();
+        }
+        if (mStatusWriter != null) {
+            mStatusWriter.close();
+        }
+    }
+
+   private void log(String message) {
+       Log.v(TAG, message);
+   }
+
+   /**
+    * Set the total number of test iteration
+    * @param iteration
+    */
+   protected void setIteration(int iteration){
+       mIteration = iteration;
+   }
+
+   /**
+    * Get the total number of test iteration
+    * @return iteration
+    */
+   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
new file mode 100644
index 0000000..f072d95
--- /dev/null
+++ b/uiautomator_test_libraries/src/com/android/uiautomator/platform/SurfaceFlingerHelper.java
@@ -0,0 +1,419 @@
+/*
+ * 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.uiautomation.platform;
+
+import android.os.Environment;
+import android.util.Log;
+
+import java.util.Arrays;
+import java.util.List;
+import java.util.ArrayList;
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileWriter;
+import java.io.BufferedWriter;
+import java.io.InputStreamReader;
+import java.io.IOException;
+import java.lang.Math;
+
+/*
+ * Tools to measure jankiness through SurfaceFlinger
+ */
+public class SurfaceFlingerHelper {
+    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 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
+     * not a jankiness */
+    private final static int PAUSE_LATENCY = 20;
+
+    /* An array list which includes the raw buffer information from frame latency tool */
+    private static List<List<String>> mFrameBufferData = new ArrayList<List<String>>(BUFFER_SIZE);
+
+    /* Record the refresh period returned from driver */
+    private static long mRefreshPeriod = -1;
+
+    /* Record the size of frame latency */
+    private static int mFrameLatencySampleSize = 0;
+
+    /* An integer array which includes delta vsync */
+    private static long[] mDeltaVsync = new long[BUFFER_SIZE];
+
+    /* Integer array for delta of delta vsync */
+    private static long[] mDelta2Vsync = new long[BUFFER_SIZE];
+
+    /* the maximum delta vsync number */
+    private static long mMaxDeltaVsync;
+
+    /* Normalized data */
+    private static double[] mNormalizedDelta2Vsync = new double[BUFFER_SIZE];
+    private static int[] mRoundNormalizedDelta2Vsync = new int[BUFFER_SIZE];
+
+    /**
+     * Run clear buffer command and clear the saved frame buffer results
+     *
+     * @param windowName the window name that the buffer will be cleared
+     */
+    public static void clearBuffer(String windowName) {
+        // clear results
+        if (mFrameBufferData != null) {
+            mFrameBufferData.clear();
+        }
+        Arrays.fill(mDeltaVsync, -1);
+        Arrays.fill(mDelta2Vsync, -1);
+        Arrays.fill(mNormalizedDelta2Vsync, -1.0);
+        Arrays.fill(mRoundNormalizedDelta2Vsync, -1);
+        mRefreshPeriod = -1;
+        mFrameLatencySampleSize = 0;
+        mMaxDeltaVsync = 0;
+
+        Process p = null;
+        BufferedReader resultReader = null;
+        String command = String.format(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",
+                        command, status));
+            }
+        } catch (IOException e) {
+            System.err.println("// Exception from command " + command + ":");
+            System.err.println(e.toString());
+        } catch (InterruptedException e) {
+            System.err.println("// Interrupted while waiting for the command to finish. ");
+            System.err.println(e.toString());
+        } finally {
+            try {
+                if (resultReader != null) {
+                    resultReader.close();
+                }
+                if (p != null) {
+                    p.destroy();
+                }
+            } catch (IOException e) {
+                System.err.println(e.toString());
+            }
+        }
+    }
+
+    /**
+     * Run frame latency command to get the raw data, save raw data on the disk
+     *
+     * @param windowName
+     * @return
+     */
+    public static boolean dumpFrameLatency(String windowName, String fileName, int index) {
+        BufferedWriter fw = null;
+        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 rawFileName = String.format("%s/%s_%d.txt", RAW_DATA_DIR, fileName, index);
+
+        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));
+            }
+            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);
+            if (mRefreshPeriod < 0) {
+                return false;
+            }
+
+            while((line = resultReader.readLine()) != null) {
+                fw.write(line);
+                fw.write("\n");
+
+                // remove the last line which is empty
+                if (line.trim().isEmpty()) {
+                    break;
+                }
+                String[] bufferValues = line.split("\\s+");
+                if (bufferValues[0].trim().compareTo("0") == 0) {
+                    continue;
+                }
+                List<String> delayArray = Arrays.asList(bufferValues);
+                mFrameBufferData.add(delayArray);
+                ++mFrameLatencySampleSize;
+            }
+            log("frame latency sample size: " + mFrameLatencySampleSize);
+        } catch (InterruptedException e) {
+            System.err.println("// Exception from command " + command + ":");
+            System.err.println(e.toString());
+        } catch (IOException e) {
+            log("Open file error: " + e.toString());
+            return false;
+        }
+        finally {
+            try {
+                if (resultReader != null) {
+                    resultReader.close();
+                }
+                if (fw != null) {
+                    fw.close();
+                }
+                if (p != null) {
+                    p.destroy();
+                }
+            } catch (IOException e) {
+                System.err.println(e.toString());
+            }
+        }
+        return true;
+    }
+
+    public static long getRefreshPeriod() {
+        if (mRefreshPeriod < 0) {
+            // Haven't dump the frame latency yet
+            log("Run command \"" + FRAME_LATENCY_CMD + " \" before retrieving the refresh period");
+        }
+        return mRefreshPeriod;
+    }
+
+    public static String getFrameBufferData() {
+        if (mFrameBufferData.get(0) == null) {
+            log("Run command \"" + FRAME_LATENCY_CMD + " \" before retrieving frame buffer data");
+            return null;
+        }
+        String rawData = String.format("%d\n", mRefreshPeriod);
+        List<String> tempList = new ArrayList<String>(BUFFER_NUMBER);
+        for (int i = 0; i < mFrameLatencySampleSize; 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 += " ";
+                } else {
+                    rawData += "\n";
+                }
+            }
+        }
+        return rawData;
+    }
+
+    /**
+     * Calculate delta(vsync)
+     * @return
+     */
+    public static long[] getDeltaVsync() {
+        if (mRefreshPeriod < 0) {
+            log("Run command \"" + FRAME_LATENCY_CMD + " \" before retrieving frame latency");
+            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));
+                mDeltaVsync[i] = curVsyncTime - preVsyncTime;
+                preVsyncTime = curVsyncTime;
+                if (mMaxDeltaVsync < mDeltaVsync[i]) {
+                    mMaxDeltaVsync = mDeltaVsync[i];
+                }
+            }
+        }
+        return mDeltaVsync;
+    }
+
+    /**
+     * Calculate difference between delta vsync
+     * @return
+     */
+    public static long[] getDelta2Vsync() {
+        if (mRefreshPeriod < 0) {
+            log("Run command \"" + FRAME_LATENCY_CMD + " \" before retrieving frame latency");
+            return null;
+        }
+        if (mDeltaVsync[0] < 0) {
+            getDeltaVsync();
+        }
+        if (mDelta2Vsync[0] < 0) {
+            mDelta2Vsync = new long[BUFFER_SIZE];
+            for (int i = 1; i < mFrameLatencySampleSize; i++) {
+                mDelta2Vsync[i] = mDeltaVsync[i] - mDeltaVsync[i - 1];
+            }
+        }
+        return mDelta2Vsync;
+    }
+
+    /**
+     * normalized delta(delta(vsync)) by refresh period
+     * @return
+     */
+    public static double[] getNormalizedDelta2Vsync() {
+        if (mRefreshPeriod < 0) {
+            log("Run command \"" + FRAME_LATENCY_CMD + " \" before retrieving frame latency");
+            return null;
+        }
+        if (mDelta2Vsync[0] < 0) {
+            getDelta2Vsync();
+        }
+        if (mNormalizedDelta2Vsync[0] < 0) {
+            mNormalizedDelta2Vsync = new double[BUFFER_SIZE];
+            for (int i = 0; i < mFrameLatencySampleSize; i++) {
+                mNormalizedDelta2Vsync[i] = (double)mDelta2Vsync[i] /mRefreshPeriod;
+            }
+        }
+        return mNormalizedDelta2Vsync;
+    }
+
+    public static int[] getRoundNormalizedDelta2Vsync() {
+        if (mRefreshPeriod < 0) {
+            log("Run command \"" + FRAME_LATENCY_CMD + " \" for number of jankiness.");
+            return null;
+        }
+        if (mNormalizedDelta2Vsync[0] < 0) {
+            getNormalizedDelta2Vsync();
+        }
+
+        for (int i = 0; i < mFrameLatencySampleSize; i++) {
+             int value = (int)Math.round(Math.max(mNormalizedDelta2Vsync[i], 0.0));
+             mRoundNormalizedDelta2Vsync[i] = value;
+        }
+        return mRoundNormalizedDelta2Vsync;
+    }
+
+    /*
+     * Get number of jankiness using Vsync time difference
+     */
+    public static int getVsyncJankiness() {
+        if (mRefreshPeriod < 0) {
+            log("Run command \"" + FRAME_LATENCY_CMD + " \" for number of jankiness.");
+            return -1;
+        }
+        if (mRoundNormalizedDelta2Vsync[0] < 0) {
+            getRoundNormalizedDelta2Vsync();
+        }
+        int numberJankiness = 0;
+        for (int i = 0; i < mFrameLatencySampleSize; i++) {
+            int value = mRoundNormalizedDelta2Vsync[i];
+            // ignore the latency which is too long
+            if (value > 0 && value < PAUSE_LATENCY) {
+                numberJankiness++;
+            }
+        }
+        return numberJankiness;
+    }
+
+    /* Track the maximum delta which shows the accumulating time
+     * before animation starts */
+    public static int getMaxDeltaVsync() {
+        return Math.round((float)mMaxDeltaVsync /mRefreshPeriod);
+    }
+
+    /**
+     * Calculate frame rate
+     * @return
+     */
+    public static double getFrameRate() {
+        if (mRefreshPeriod < 0) {
+            log("Run command \"" + FRAME_LATENCY_CMD + " \" before calcuating average frame rate");
+            return -1.0;
+        }
+        if (mFrameBufferData.get(0) == null) {
+            log("Run command \"" + FRAME_LATENCY_CMD + " \" before retrieving frame buffer data");
+            return -1.0;
+        }
+        long startTime = Long.parseLong(mFrameBufferData.get(0).get(1));
+        long endTime =  Long.parseLong(mFrameBufferData.get(mFrameLatencySampleSize - 1).get(1));
+        long totalDuration = endTime - startTime;
+        return (double)((mFrameLatencySampleSize - 1) * Math.pow(10, 9))/totalDuration;
+    }
+
+    /**
+     * Print raw data and processed results into file <testcasename_[iteration]_processed.txt>
+     * @param fileName
+     * @param index
+     */
+    public static void printData(String fileName, int index) {
+        String rawAndProcDataFileName = String.format("%s/%s_%d_processed.txt", RAW_DATA_DIR,
+                fileName, index);
+        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));
+            // 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()));
+            fw.write(String.format("Frame rate is: %f\n", getFrameRate()));
+
+            // refresh period
+            fw.write(String.valueOf(mRefreshPeriod));
+            fw.write("\n");
+            fw.write("app\tvsync\tset\tdelta(vsync)\tdelta^2(vsync)\t" +
+                    "delta^2(vsync)/refreshPeriod\t normalized delta^2(vsync)\n");
+
+            for (int i = 0; i < mFrameLatencySampleSize; i++) {
+                // write raw data
+                List<String> rawData = mFrameBufferData.get(i);
+                String line = String.format("%s\t%s\t%s\t%d\t%d\t%f\t%d\n",
+                        rawData.get(0), rawData.get(1), rawData.get(2),
+                        mDeltaVsync[i], mDelta2Vsync[i],
+                        mNormalizedDelta2Vsync[i], mRoundNormalizedDelta2Vsync[i]);
+                fw.write(line);
+            }
+        } catch (IOException e) {
+            log("Open file error: " + e.toString());
+        } finally {
+            try {
+                if (fw != null) {
+                    fw.flush();
+                    fw.close();
+                }
+            }
+            catch (IOException e) {
+                System.err.println(e.toString());
+            }
+        }
+    }
+
+    private static void log(String msg) {
+        Log.v(TAG, msg);
+    }
+}
