Start of Reference Application Implementation.

Refactoring of primitive benchmarks.

Change-Id: I42005505ec6cb53808b748728606785a52b306f5
diff --git a/suite/pts/deviceTests/opengl/AndroidManifest.xml b/suite/pts/deviceTests/opengl/AndroidManifest.xml
index a91766f..dc906c8 100644
--- a/suite/pts/deviceTests/opengl/AndroidManifest.xml
+++ b/suite/pts/deviceTests/opengl/AndroidManifest.xml
@@ -5,6 +5,7 @@
     android:versionName="1.0" >
 
     <uses-sdk
+        android:targetSdkVersion="17"
         android:minSdkVersion="16" />
 
     <uses-feature
@@ -18,7 +19,7 @@
         <uses-library android:name="android.test.runner" />
 
         <activity
-            android:name="com.android.pts.opengl.primitive.GLActivity"
+            android:name="com.android.pts.opengl.primitive.GLPrimitiveActivity"
             android:theme="@android:style/Theme.NoTitleBar.Fullscreen" >
             <intent-filter>
                 <action android:name="android.intent.action.MAIN" />
@@ -26,6 +27,20 @@
                 <category android:name="android.intent.category.LAUNCHER" />
             </intent-filter>
         </activity>
+
+        <activity
+            android:name="com.android.pts.opengl.reference.GLReferenceActivity" >
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+
+                <category android:name="android.intent.category.LAUNCHER" />
+            </intent-filter>
+        </activity>
+
+        <activity
+            android:name="com.android.pts.opengl.reference.GLGameActivity"
+            android:theme="@android:style/Theme.NoTitleBar.Fullscreen" >
+        </activity>
     </application>
 
     <instrumentation
diff --git a/suite/pts/deviceTests/opengl/jni/primitive/Trace.h b/suite/pts/deviceTests/opengl/jni/Trace.h
similarity index 100%
rename from suite/pts/deviceTests/opengl/jni/primitive/Trace.h
rename to suite/pts/deviceTests/opengl/jni/Trace.h
diff --git a/suite/pts/deviceTests/opengl/jni/primitive/fullpipeline/FullPipelineProgram.cpp b/suite/pts/deviceTests/opengl/jni/graphics/BasicProgram.cpp
similarity index 89%
rename from suite/pts/deviceTests/opengl/jni/primitive/fullpipeline/FullPipelineProgram.cpp
rename to suite/pts/deviceTests/opengl/jni/graphics/BasicProgram.cpp
index b06cdd2..2b5ebbd 100644
--- a/suite/pts/deviceTests/opengl/jni/primitive/fullpipeline/FullPipelineProgram.cpp
+++ b/suite/pts/deviceTests/opengl/jni/graphics/BasicProgram.cpp
@@ -12,13 +12,13 @@
  * the License.
  */
 
-#include "FullPipelineProgram.h"
+#include "BasicProgram.h"
 
 #include <EGL/egl.h>
 #include <GLES2/gl2.h>
 #include <GLES2/gl2ext.h>
 
-FullPipelineProgram::FullPipelineProgram(GLuint programId) :
+BasicProgram::BasicProgram(GLuint programId) :
         Program(programId) {
     mLightPosInModelSpace[0] = 0.0f;
     mLightPosInModelSpace[1] = 2.0f;
@@ -33,7 +33,7 @@
     mTexCoordHandle = glGetAttribLocation(programId, "a_TexCoordinate");
 }
 
-void FullPipelineProgram::before(Matrix& model, Matrix& view, Matrix& projection) {
+void BasicProgram::before(Matrix& model, Matrix& view, Matrix& projection) {
     Program::before(model, view, projection);
     mLightModelMatrix.identity();
 
diff --git a/suite/pts/deviceTests/opengl/jni/primitive/fullpipeline/FullPipelineProgram.h b/suite/pts/deviceTests/opengl/jni/graphics/BasicProgram.h
similarity index 81%
rename from suite/pts/deviceTests/opengl/jni/primitive/fullpipeline/FullPipelineProgram.h
rename to suite/pts/deviceTests/opengl/jni/graphics/BasicProgram.h
index 3eab1c4..d397719 100644
--- a/suite/pts/deviceTests/opengl/jni/primitive/fullpipeline/FullPipelineProgram.h
+++ b/suite/pts/deviceTests/opengl/jni/graphics/BasicProgram.h
@@ -11,20 +11,20 @@
  * or implied. See the License for the specific language governing permissions and limitations under
  * the License.
  */
-#ifndef FULLPIPELINEPROGRAM_H
-#define FULLPIPELINEPROGRAM_H
+#ifndef BASICPROGRAM_H
+#define BASICPROGRAM_H
 
-#include <graphics/Matrix.h>
-#include <graphics/Program.h>
+#include "Matrix.h"
+#include "Program.h"
 
 #include <EGL/egl.h>
 #include <GLES2/gl2.h>
 #include <GLES2/gl2ext.h>
 
-class FullPipelineProgram: public Program {
+class BasicProgram: public Program {
 public:
-    FullPipelineProgram(GLuint programId);
-    virtual ~FullPipelineProgram() {};
+    BasicProgram(GLuint programId);
+    virtual ~BasicProgram() {};
     Matrix mMVMatrix;
     Matrix mMVPMatrix;
     Matrix mLightModelMatrix;
diff --git a/suite/pts/deviceTests/opengl/jni/graphics/GLUtils.cpp b/suite/pts/deviceTests/opengl/jni/graphics/GLUtils.cpp
index 5b74bf3..ed6f84b6 100644
--- a/suite/pts/deviceTests/opengl/jni/graphics/GLUtils.cpp
+++ b/suite/pts/deviceTests/opengl/jni/graphics/GLUtils.cpp
@@ -14,6 +14,7 @@
 
 #include "GLUtils.h"
 #include <stdlib.h>
+#include <sys/time.h>
 
 #define LOG_TAG "PTS_OPENGL"
 #define LOG_NDEBUG 0
@@ -80,6 +81,12 @@
     return program;
 }
 
+double GLUtils::currentTimeMillis() {
+    struct timeval tv;
+    gettimeofday(&tv, (struct timezone *) NULL);
+    return tv.tv_sec * 1000.0 + tv.tv_usec / 1000.0;
+}
+
 // Rounds a number up to the smallest power of 2 that is greater than the original number.
 int GLUtils::roundUpToSmallestPowerOf2(int x) {
     if (x < 0) {
diff --git a/suite/pts/deviceTests/opengl/jni/graphics/GLUtils.h b/suite/pts/deviceTests/opengl/jni/graphics/GLUtils.h
index 8708103..3d3bafd 100644
--- a/suite/pts/deviceTests/opengl/jni/graphics/GLUtils.h
+++ b/suite/pts/deviceTests/opengl/jni/graphics/GLUtils.h
@@ -23,6 +23,7 @@
     // Creates a program with the given vertex and fragment shader source code.
     static GLuint createProgram(const char** vertexSource,
             const char** fragmentSource);
+    static double currentTimeMillis();
     // Rounds a number up to the smallest power of 2 that is greater than the original number.
     static int roundUpToSmallestPowerOf2(int x);
     // Generates a random texture of the given dimensions.
diff --git a/suite/pts/deviceTests/opengl/jni/primitive/Renderer.cpp b/suite/pts/deviceTests/opengl/jni/graphics/Renderer.cpp
similarity index 99%
rename from suite/pts/deviceTests/opengl/jni/primitive/Renderer.cpp
rename to suite/pts/deviceTests/opengl/jni/graphics/Renderer.cpp
index fa3ec83..ece115e 100644
--- a/suite/pts/deviceTests/opengl/jni/primitive/Renderer.cpp
+++ b/suite/pts/deviceTests/opengl/jni/graphics/Renderer.cpp
@@ -18,7 +18,7 @@
 #define LOG_NDEBUG 0
 #include <utils/Log.h>
 
-#include <primitive/Trace.h>
+#include <Trace.h>
 
 static const EGLint contextAttribs[] = {
         EGL_CONTEXT_CLIENT_VERSION, 2,
diff --git a/suite/pts/deviceTests/opengl/jni/primitive/Renderer.h b/suite/pts/deviceTests/opengl/jni/graphics/Renderer.h
similarity index 100%
rename from suite/pts/deviceTests/opengl/jni/primitive/Renderer.h
rename to suite/pts/deviceTests/opengl/jni/graphics/Renderer.h
diff --git a/suite/pts/deviceTests/opengl/jni/primitive/GLPrimitive.cpp b/suite/pts/deviceTests/opengl/jni/primitive/GLPrimitive.cpp
index 1d9cc88..687a0d2 100644
--- a/suite/pts/deviceTests/opengl/jni/primitive/GLPrimitive.cpp
+++ b/suite/pts/deviceTests/opengl/jni/primitive/GLPrimitive.cpp
@@ -14,12 +14,13 @@
 #include <jni.h>
 
 #include <stdlib.h>
-#include <sys/time.h>
 
 #include <android/native_window.h>
 #include <android/native_window_jni.h>
 
-#include "Renderer.h"
+#include <graphics/GLUtils.h>
+#include <graphics/Renderer.h>
+
 #include "fullpipeline/FullPipelineRenderer.h"
 #include "pixeloutput/PixelOutputRenderer.h"
 #include "shaderperf/ShaderPerfRenderer.h"
@@ -28,14 +29,8 @@
 // Holds the current benchmark's renderer.
 Renderer* gRenderer = NULL;
 
-double currentTimeMillis() {
-    struct timeval tv;
-    gettimeofday(&tv, (struct timezone *) NULL);
-    return tv.tv_sec * 1000.0 + tv.tv_usec / 1000.0;
-}
-
 extern "C" JNIEXPORT jboolean JNICALL
-Java_com_android_pts_opengl_primitive_GLActivity_startBenchmark(
+Java_com_android_pts_opengl_primitive_GLPrimitiveActivity_startBenchmark(
         JNIEnv* env, jclass clazz, jint numFrames, jdoubleArray frameTimes) {
     if (gRenderer == NULL) {
         return false;
@@ -45,7 +40,7 @@
     bool success = gRenderer->setUp();
 
     // Records the start time.
-    double start = currentTimeMillis();
+    double start = GLUtils::currentTimeMillis();
 
     // Draw off the screen.
     for (int i = 0; i < numFrames && success; i++) {
@@ -54,7 +49,7 @@
     }
 
     // Records the end time.
-    double end = currentTimeMillis();
+    double end = GLUtils::currentTimeMillis();
 
     // Sets the times in the Java array.
     double times[] = {start, end};
@@ -69,28 +64,28 @@
 
 // The following functions create the renderers for the various benchmarks.
 extern "C" JNIEXPORT void JNICALL
-Java_com_android_pts_opengl_primitive_GLActivity_setupFullPipelineBenchmark(
+Java_com_android_pts_opengl_primitive_GLPrimitiveActivity_setupFullPipelineBenchmark(
         JNIEnv* env, jclass clazz, jobject surface, jboolean offscreen, jint workload) {
     gRenderer = new FullPipelineRenderer(
             ANativeWindow_fromSurface(env, surface), offscreen, workload);
 }
 
 extern "C" JNIEXPORT void JNICALL
-Java_com_android_pts_opengl_primitive_GLActivity_setupPixelOutputBenchmark(
+Java_com_android_pts_opengl_primitive_GLPrimitiveActivity_setupPixelOutputBenchmark(
         JNIEnv* env, jclass clazz, jobject surface, jboolean offscreen, jint workload) {
     gRenderer = new PixelOutputRenderer(
             ANativeWindow_fromSurface(env, surface), offscreen, workload);
 }
 
 extern "C" JNIEXPORT void JNICALL
-Java_com_android_pts_opengl_primitive_GLActivity_setupShaderPerfBenchmark(
+Java_com_android_pts_opengl_primitive_GLPrimitiveActivity_setupShaderPerfBenchmark(
         JNIEnv* env, jclass clazz, jobject surface, jboolean offscreen, jint workload) {
     gRenderer = new ShaderPerfRenderer(
             ANativeWindow_fromSurface(env, surface), offscreen, workload);
 }
 
 extern "C" JNIEXPORT void JNICALL
-Java_com_android_pts_opengl_primitive_GLActivity_setupContextSwitchBenchmark(
+Java_com_android_pts_opengl_primitive_GLPrimitiveActivity_setupContextSwitchBenchmark(
         JNIEnv* env, jclass clazz, jobject surface, jboolean offscreen, jint workload) {
     if (workload <= 8) {
         // This test uses 8 iterations, so workload can't be more than 8.
diff --git a/suite/pts/deviceTests/opengl/jni/primitive/contextswitch/ContextSwitchRenderer.cpp b/suite/pts/deviceTests/opengl/jni/primitive/contextswitch/ContextSwitchRenderer.cpp
index e365db6..44e8909 100644
--- a/suite/pts/deviceTests/opengl/jni/primitive/contextswitch/ContextSwitchRenderer.cpp
+++ b/suite/pts/deviceTests/opengl/jni/primitive/contextswitch/ContextSwitchRenderer.cpp
@@ -23,11 +23,7 @@
 #include "ContextSwitchRenderer.h"
 #include <graphics/GLUtils.h>
 
-#define LOG_TAG "PTS_OPENGL"
-#define LOG_NDEBUG 0
-#include <utils/Log.h>
-
-#include <primitive/Trace.h>
+#include <Trace.h>
 
 static const EGLint contextAttribs[] =
         { EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE };
@@ -112,12 +108,6 @@
         }
     }
 
-    GLuint err = glGetError();
-    if (err != GL_NO_ERROR) {
-        ALOGE("GLError %d", err);
-        return false;
-    }
-
     return true;
 }
 
diff --git a/suite/pts/deviceTests/opengl/jni/primitive/contextswitch/ContextSwitchRenderer.h b/suite/pts/deviceTests/opengl/jni/primitive/contextswitch/ContextSwitchRenderer.h
index d4e7595..9ab05e3 100644
--- a/suite/pts/deviceTests/opengl/jni/primitive/contextswitch/ContextSwitchRenderer.h
+++ b/suite/pts/deviceTests/opengl/jni/primitive/contextswitch/ContextSwitchRenderer.h
@@ -14,7 +14,7 @@
 #ifndef CONTEXTSWITCHRENDERER_H
 #define CONTEXTSWITCHRENDERER_H
 
-#include <primitive/Renderer.h>
+#include <graphics/Renderer.h>
 
 class ContextSwitchRenderer: public Renderer {
 public:
diff --git a/suite/pts/deviceTests/opengl/jni/primitive/fullpipeline/FullPipelineMesh.cpp b/suite/pts/deviceTests/opengl/jni/primitive/fullpipeline/FullPipelineMesh.cpp
index c0e5250..bf1b9d2 100644
--- a/suite/pts/deviceTests/opengl/jni/primitive/fullpipeline/FullPipelineMesh.cpp
+++ b/suite/pts/deviceTests/opengl/jni/primitive/fullpipeline/FullPipelineMesh.cpp
@@ -13,14 +13,15 @@
  */
 
 #include "FullPipelineMesh.h"
-#include "FullPipelineProgram.h"
+
+#include <graphics/BasicProgram.h>
 
 FullPipelineMesh::FullPipelineMesh(const Mesh* mesh) :
         MeshNode(mesh) {
 }
 
 void FullPipelineMesh::before(Program& program, Matrix& model, Matrix& view, Matrix& projection) {
-    FullPipelineProgram& prog = (FullPipelineProgram&) program;
+    BasicProgram& prog = (BasicProgram&) program;
 
     glActiveTexture(GL_TEXTURE0);
     // Bind the texture to this unit.
diff --git a/suite/pts/deviceTests/opengl/jni/primitive/fullpipeline/FullPipelineRenderer.cpp b/suite/pts/deviceTests/opengl/jni/primitive/fullpipeline/FullPipelineRenderer.cpp
index f178912..da65420 100644
--- a/suite/pts/deviceTests/opengl/jni/primitive/fullpipeline/FullPipelineRenderer.cpp
+++ b/suite/pts/deviceTests/opengl/jni/primitive/fullpipeline/FullPipelineRenderer.cpp
@@ -16,17 +16,12 @@
 #include <GLES2/gl2ext.h>
 
 #include "FullPipelineMesh.h"
-#include "FullPipelineProgram.h"
 #include "FullPipelineRenderer.h"
-#include <graphics/Mesh.h>
+
 #include <graphics/TransformationNode.h>
 #include <graphics/GLUtils.h>
 
-#define LOG_TAG "PTS_OPENGL"
-#define LOG_NDEBUG 0
-#include <utils/Log.h>
-
-#include <primitive/Trace.h>
+#include <Trace.h>
 
 static const int FP_NUM_VERTICES = 6;
 
@@ -98,7 +93,8 @@
 
 FullPipelineRenderer::FullPipelineRenderer(ANativeWindow* window, bool offscreen, int workload) :
         Renderer(window, offscreen, workload), mProgram(NULL), mSceneGraph(NULL),
-        mModelMatrix(NULL), mViewMatrix(NULL), mProjectionMatrix(NULL), mMesh(NULL) {
+        mModelMatrix(NULL), mViewMatrix(NULL), mProjectionMatrix(NULL), mMesh(NULL),
+        mTextureId(0) {
 }
 
 bool FullPipelineRenderer::setUp() {
@@ -110,7 +106,7 @@
     mProgramId = GLUtils::createProgram(&FP_VERTEX, &FP_FRAGMENT);
     if (mProgramId == 0)
         return false;
-    mProgram = new FullPipelineProgram(mProgramId);
+    mProgram = new BasicProgram(mProgramId);
 
     mModelMatrix = new Matrix();
 
diff --git a/suite/pts/deviceTests/opengl/jni/primitive/fullpipeline/FullPipelineRenderer.h b/suite/pts/deviceTests/opengl/jni/primitive/fullpipeline/FullPipelineRenderer.h
index 14efcf6..b0b31a2 100644
--- a/suite/pts/deviceTests/opengl/jni/primitive/fullpipeline/FullPipelineRenderer.h
+++ b/suite/pts/deviceTests/opengl/jni/primitive/fullpipeline/FullPipelineRenderer.h
@@ -14,11 +14,10 @@
 #ifndef FULLPIPELINERENDERER_H
 #define FULLPIPELINERENDERER_H
 
-#include "FullPipelineProgram.h"
-
-#include <primitive/Renderer.h>
+#include <graphics/BasicProgram.h>
 #include <graphics/Matrix.h>
 #include <graphics/Mesh.h>
+#include <graphics/Renderer.h>
 #include <graphics/ProgramNode.h>
 
 class FullPipelineRenderer: public Renderer {
@@ -29,7 +28,7 @@
     bool tearDown();
     bool draw();
 private:
-    FullPipelineProgram* mProgram;
+    BasicProgram* mProgram;
     ProgramNode* mSceneGraph;
     Matrix* mModelMatrix;
     Matrix* mViewMatrix;
diff --git a/suite/pts/deviceTests/opengl/jni/primitive/pixeloutput/PixelOutputRenderer.cpp b/suite/pts/deviceTests/opengl/jni/primitive/pixeloutput/PixelOutputRenderer.cpp
index 2f3d647..321235d 100644
--- a/suite/pts/deviceTests/opengl/jni/primitive/pixeloutput/PixelOutputRenderer.cpp
+++ b/suite/pts/deviceTests/opengl/jni/primitive/pixeloutput/PixelOutputRenderer.cpp
@@ -14,11 +14,7 @@
 #include "PixelOutputRenderer.h"
 #include <graphics/GLUtils.h>
 
-#define LOG_TAG "PTS_OPENGL"
-#define LOG_NDEBUG 0
-#include <utils/Log.h>
-
-#include <primitive/Trace.h>
+#include <Trace.h>
 
 static const int PO_NUM_VERTICES = 6;
 
diff --git a/suite/pts/deviceTests/opengl/jni/primitive/pixeloutput/PixelOutputRenderer.h b/suite/pts/deviceTests/opengl/jni/primitive/pixeloutput/PixelOutputRenderer.h
index 90b3f2a..11ffab9 100644
--- a/suite/pts/deviceTests/opengl/jni/primitive/pixeloutput/PixelOutputRenderer.h
+++ b/suite/pts/deviceTests/opengl/jni/primitive/pixeloutput/PixelOutputRenderer.h
@@ -14,7 +14,7 @@
 #ifndef PIXELOUTPUTRENDERER_H
 #define PIXELOUTPUTRENDERER_H
 
-#include <primitive/Renderer.h>
+#include <graphics/Renderer.h>
 
 class PixelOutputRenderer: public Renderer {
 public:
diff --git a/suite/pts/deviceTests/opengl/jni/primitive/shaderperf/ShaderPerfRenderer.cpp b/suite/pts/deviceTests/opengl/jni/primitive/shaderperf/ShaderPerfRenderer.cpp
index 156f81e..cff8599 100644
--- a/suite/pts/deviceTests/opengl/jni/primitive/shaderperf/ShaderPerfRenderer.cpp
+++ b/suite/pts/deviceTests/opengl/jni/primitive/shaderperf/ShaderPerfRenderer.cpp
@@ -16,11 +16,7 @@
 
 #include <math.h>
 
-#define LOG_TAG "PTS_OPENGL"
-#define LOG_NDEBUG 0
-#include <utils/Log.h>
-
-#include <primitive/Trace.h>
+#include <Trace.h>
 
 static const float GOLDEN_RATIO = (1.0f + sqrt(5.0f)) / 2.0f;
 
@@ -141,12 +137,6 @@
     }
     delete[] m;
 
-    GLuint err = glGetError();
-    if (err != GL_NO_ERROR) {
-        ALOGE("GLError %d", err);
-        return false;
-    }
-
     return true;
 }
 
diff --git a/suite/pts/deviceTests/opengl/jni/primitive/shaderperf/ShaderPerfRenderer.h b/suite/pts/deviceTests/opengl/jni/primitive/shaderperf/ShaderPerfRenderer.h
index 3537eba..096e231 100644
--- a/suite/pts/deviceTests/opengl/jni/primitive/shaderperf/ShaderPerfRenderer.h
+++ b/suite/pts/deviceTests/opengl/jni/primitive/shaderperf/ShaderPerfRenderer.h
@@ -14,7 +14,7 @@
 #ifndef SHADERPERFRENDERER_H
 #define SHADERPERFRENDERER_H
 
-#include <primitive/Renderer.h>
+#include <graphics/Renderer.h>
 
 class ShaderPerfRenderer: public Renderer {
 public:
diff --git a/suite/pts/deviceTests/opengl/jni/reference/GLReference.cpp b/suite/pts/deviceTests/opengl/jni/reference/GLReference.cpp
new file mode 100644
index 0000000..53a262e
--- /dev/null
+++ b/suite/pts/deviceTests/opengl/jni/reference/GLReference.cpp
@@ -0,0 +1,22 @@
+/*
+ * 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.
+ */
+#include <jni.h>
+
+extern "C" JNIEXPORT jboolean JNICALL
+Java_com_android_pts_opengl_reference_GLGameActivity_startBenchmark(
+        JNIEnv* env, jclass clazz, jobject surface, jint numFrames,
+        jdoubleArray setUpTimes, jdoubleArray updateTimes, jdoubleArray renderTimes) {
+    // TODO
+    return true;
+}
diff --git a/suite/pts/deviceTests/opengl/res/layout/main.xml b/suite/pts/deviceTests/opengl/res/layout/main.xml
new file mode 100644
index 0000000..5f54a8c
--- /dev/null
+++ b/suite/pts/deviceTests/opengl/res/layout/main.xml
@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+     Copyright (C) 2008 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.
+-->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content"
+    android:orientation="vertical" >
+
+    <TextView
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content" />
+
+    <TextView
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content" />
+
+    <TextView
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content" />
+
+    <TextView
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content" />
+
+    <TextView
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content" />
+
+    <!-- TODO: Make this quite a heavy UI to load, use ImageViews etc -->
+
+</LinearLayout>
\ No newline at end of file
diff --git a/suite/pts/deviceTests/opengl/src/com/android/pts/opengl/GLActivityIntentKeys.java b/suite/pts/deviceTests/opengl/src/com/android/pts/opengl/GLActivityIntentKeys.java
new file mode 100644
index 0000000..da5de80
--- /dev/null
+++ b/suite/pts/deviceTests/opengl/src/com/android/pts/opengl/GLActivityIntentKeys.java
@@ -0,0 +1,37 @@
+/*
+ * 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.pts.opengl;
+
+public class GLActivityIntentKeys {
+    /**
+     * Holds the name of the benchmark to run.
+     */
+    public final static String INTENT_EXTRA_BENCHMARK_NAME = "benchmark_name";
+    /**
+     * Holds whether or not the benchmark is to be run offscreen.
+     */
+    public final static String INTENT_EXTRA_OFFSCREEN = "offscreen";
+    /**
+     * The number of frames to render for each workload.
+     */
+    public final static String INTENT_EXTRA_NUM_FRAMES = "num_frames";
+    /**
+     * The number of iterations to run, the workload increases with each iteration.
+     */
+    public final static String INTENT_EXTRA_NUM_ITERATIONS = "num_iterations";
+    /**
+     * The number of milliseconds to wait before timing out.
+     */
+    public final static String INTENT_EXTRA_TIMEOUT = "timeout";
+}
diff --git a/suite/pts/deviceTests/opengl/src/com/android/pts/opengl/primitive/GLActivity.java b/suite/pts/deviceTests/opengl/src/com/android/pts/opengl/primitive/GLPrimitiveActivity.java
similarity index 79%
rename from suite/pts/deviceTests/opengl/src/com/android/pts/opengl/primitive/GLActivity.java
rename to suite/pts/deviceTests/opengl/src/com/android/pts/opengl/primitive/GLPrimitiveActivity.java
index df0698a..4db037c 100644
--- a/suite/pts/deviceTests/opengl/src/com/android/pts/opengl/primitive/GLActivity.java
+++ b/suite/pts/deviceTests/opengl/src/com/android/pts/opengl/primitive/GLPrimitiveActivity.java
@@ -22,39 +22,21 @@
 import android.view.SurfaceView;
 import android.view.Surface;
 
+import com.android.pts.opengl.GLActivityIntentKeys;
 import com.android.pts.util.ResultType;
 import com.android.pts.util.ResultUnit;
 
 import java.util.ArrayList;
+import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.Semaphore;
 
-public class GLActivity extends Activity {
+public class GLPrimitiveActivity extends Activity {
 
-    public final static String TAG = "GLActivity";
-    /**
-     * Holds the name of the benchmark to run.
-     */
-    public final static String INTENT_EXTRA_BENCHMARK_NAME = "benchmark_name";
-    /**
-     * Holds whether or not the benchmark is to be run offscreen.
-     */
-    public final static String INTENT_EXTRA_OFFSCREEN = "offscreen";
-    /**
-     * The number of frames to render for each workload.
-     */
-    public final static String INTENT_EXTRA_NUM_FRAMES = "num_frames";
-    /**
-     * The number of iterations to run, the workload increases with each iteration.
-     */
-    public final static String INTENT_EXTRA_NUM_ITERATIONS = "num_iterations";
-    /**
-     * The number of milliseconds to wait before timing out.
-     */
-    public final static String INTENT_EXTRA_TIMEOUT = "timeout";
+    public final static String TAG = "GLPrimitiveActivity";
 
-    private Worker runner;
     private volatile Exception mException;
-    private volatile Surface mSurface;
+    private volatile Surface mSurface = null;
+    private CountDownLatch mStartSignal = new CountDownLatch(1);
     private Semaphore mSemaphore = new Semaphore(0);
 
     private Benchmark mBenchmark;
@@ -69,11 +51,12 @@
         super.onCreate(data);
         System.loadLibrary("ptsopengl_jni");
         Intent intent = getIntent();
-        mBenchmark = Benchmark.valueOf(intent.getStringExtra(INTENT_EXTRA_BENCHMARK_NAME));
-        mOffscreen = intent.getBooleanExtra(INTENT_EXTRA_OFFSCREEN, false);
-        mNumFrames = intent.getIntExtra(INTENT_EXTRA_NUM_FRAMES, 0);
-        mNumIterations = intent.getIntExtra(INTENT_EXTRA_NUM_ITERATIONS, 0);
-        mTimeout = intent.getIntExtra(INTENT_EXTRA_TIMEOUT, 0);
+        mBenchmark = Benchmark.valueOf(
+                intent.getStringExtra(GLActivityIntentKeys.INTENT_EXTRA_BENCHMARK_NAME));
+        mOffscreen = intent.getBooleanExtra(GLActivityIntentKeys.INTENT_EXTRA_OFFSCREEN, false);
+        mNumFrames = intent.getIntExtra(GLActivityIntentKeys.INTENT_EXTRA_NUM_FRAMES, 0);
+        mNumIterations = intent.getIntExtra(GLActivityIntentKeys.INTENT_EXTRA_NUM_ITERATIONS, 0);
+        mTimeout = intent.getIntExtra(GLActivityIntentKeys.INTENT_EXTRA_TIMEOUT, 0);
         mFpsValues = new double[mNumIterations];
 
         Log.i(TAG, "Benchmark: " + mBenchmark);
@@ -87,6 +70,7 @@
             @Override
             public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
                 mSurface = holder.getSurface();
+                mStartSignal.countDown();
             }
 
             @Override
@@ -96,12 +80,12 @@
             public void surfaceDestroyed(SurfaceHolder holder) {}
         });
         setContentView(surfaceView);
+        // Spawns a worker to run the benchmark.
+        Worker worker = new Worker();
+        worker.start();
     }
 
-    public void spawnAndWaitForCompletion() throws Exception {
-        // Spawns a worker to run the benchmark.
-        runner = new Worker();
-        runner.start();
+    public void waitForCompletion() throws Exception {
         // Wait for semiphore.
         mSemaphore.acquire();
         if (mException != null) {
@@ -144,6 +128,13 @@
 
         @Override
         public void run() {
+            try {
+                mStartSignal.await();
+            } catch (InterruptedException e) {
+                setException(e);
+                complete();
+                return;
+            }
             // Creates a watchdog to ensure a iteration doesn't exceed the timeout.
             watchDog = new WatchDog(mTimeout, this);
             // Used to record the start and end time of the iteration.
diff --git a/suite/pts/deviceTests/opengl/src/com/android/pts/opengl/primitive/GLBenchmark.java b/suite/pts/deviceTests/opengl/src/com/android/pts/opengl/primitive/GLPrimitiveBenchmark.java
similarity index 77%
rename from suite/pts/deviceTests/opengl/src/com/android/pts/opengl/primitive/GLBenchmark.java
rename to suite/pts/deviceTests/opengl/src/com/android/pts/opengl/primitive/GLPrimitiveBenchmark.java
index 66405cb..3efba20 100644
--- a/suite/pts/deviceTests/opengl/src/com/android/pts/opengl/primitive/GLBenchmark.java
+++ b/suite/pts/deviceTests/opengl/src/com/android/pts/opengl/primitive/GLPrimitiveBenchmark.java
@@ -13,27 +13,27 @@
  */
 package com.android.pts.opengl.primitive;
 
+import com.android.pts.opengl.GLActivityIntentKeys;
 import com.android.pts.util.PtsActivityInstrumentationTestCase2;
 import com.android.pts.util.ResultType;
 import com.android.pts.util.ResultUnit;
 
 import android.content.Intent;
 import android.cts.util.TimeoutReq;
-import android.opengl.Matrix;
 
 import java.util.Arrays;
 
 /**
  * Runs the Primitive OpenGL ES 2.0 Benchmarks.
  */
-public class GLBenchmark extends PtsActivityInstrumentationTestCase2<GLActivity> {
+public class GLPrimitiveBenchmark extends PtsActivityInstrumentationTestCase2<GLPrimitiveActivity> {
 
     private static final int NUM_FRAMES = 100;
     private static final int NUM_ITERATIONS = 8;
-    private static final int TIME_OUT = 1000000;
+    private static final int TIMEOUT = 1000000;
 
-    public GLBenchmark() {
-        super(GLActivity.class);
+    public GLPrimitiveBenchmark() {
+        super(GLPrimitiveActivity.class);
     }
 
     /**
@@ -41,7 +41,7 @@
      */
     @TimeoutReq(minutes = 100)
     public void testFullPipelineOffscreen() throws Exception {
-        runBenchmark(Benchmark.FullPipeline, true, NUM_FRAMES, NUM_ITERATIONS, TIME_OUT);
+        runBenchmark(Benchmark.FullPipeline, true, NUM_FRAMES, NUM_ITERATIONS, TIMEOUT);
     }
 
     /**
@@ -49,7 +49,7 @@
      */
     @TimeoutReq(minutes = 100)
     public void testFullPipelineOnscreen() throws Exception {
-        runBenchmark(Benchmark.FullPipeline, false, NUM_FRAMES, NUM_ITERATIONS, TIME_OUT);
+        runBenchmark(Benchmark.FullPipeline, false, NUM_FRAMES, NUM_ITERATIONS, TIMEOUT);
     }
 
     /**
@@ -57,7 +57,7 @@
      */
     @TimeoutReq(minutes = 100)
     public void testPixelOutputOffscreen() throws Exception {
-        runBenchmark(Benchmark.PixelOutput, true, NUM_FRAMES, NUM_ITERATIONS, TIME_OUT);
+        runBenchmark(Benchmark.PixelOutput, true, NUM_FRAMES, NUM_ITERATIONS, TIMEOUT);
     }
 
     /**
@@ -65,7 +65,7 @@
      */
     @TimeoutReq(minutes = 100)
     public void testPixelOutputOnscreen() throws Exception {
-        runBenchmark(Benchmark.PixelOutput, false, NUM_FRAMES, NUM_ITERATIONS, TIME_OUT);
+        runBenchmark(Benchmark.PixelOutput, false, NUM_FRAMES, NUM_ITERATIONS, TIMEOUT);
     }
 
     /**
@@ -73,7 +73,7 @@
      */
     @TimeoutReq(minutes = 100)
     public void testShaderPerfOffscreen() throws Exception {
-        runBenchmark(Benchmark.ShaderPerf, true, NUM_FRAMES, NUM_ITERATIONS, TIME_OUT);
+        runBenchmark(Benchmark.ShaderPerf, true, NUM_FRAMES, NUM_ITERATIONS, TIMEOUT);
     }
 
     /**
@@ -81,7 +81,7 @@
      */
     @TimeoutReq(minutes = 100)
     public void testShaderPerfOnscreen() throws Exception {
-        runBenchmark(Benchmark.ShaderPerf, false, NUM_FRAMES, NUM_ITERATIONS, TIME_OUT);
+        runBenchmark(Benchmark.ShaderPerf, false, NUM_FRAMES, NUM_ITERATIONS, TIMEOUT);
     }
 
     /**
@@ -89,7 +89,7 @@
      */
     @TimeoutReq(minutes = 100)
     public void testContextSwitchOffscreen() throws Exception {
-        runBenchmark(Benchmark.ContextSwitch, true, NUM_FRAMES, NUM_ITERATIONS, TIME_OUT);
+        runBenchmark(Benchmark.ContextSwitch, true, NUM_FRAMES, NUM_ITERATIONS, TIMEOUT);
     }
 
     /**
@@ -97,7 +97,7 @@
      */
     @TimeoutReq(minutes = 100)
     public void testContextSwitchOnscreen() throws Exception {
-        runBenchmark(Benchmark.ContextSwitch, false, NUM_FRAMES, NUM_ITERATIONS, TIME_OUT);
+        runBenchmark(Benchmark.ContextSwitch, false, NUM_FRAMES, NUM_ITERATIONS, TIMEOUT);
     }
 
     /**
@@ -115,17 +115,17 @@
             throws Exception {
         String benchmarkName = benchmark.toString();
         Intent intent = new Intent();
-        intent.putExtra(GLActivity.INTENT_EXTRA_BENCHMARK_NAME, benchmarkName);
-        intent.putExtra(GLActivity.INTENT_EXTRA_OFFSCREEN, offscreen);
-        intent.putExtra(GLActivity.INTENT_EXTRA_NUM_FRAMES, numFrames);
-        intent.putExtra(GLActivity.INTENT_EXTRA_NUM_ITERATIONS, numIterations);
-        intent.putExtra(GLActivity.INTENT_EXTRA_TIMEOUT, timeout);
+        intent.putExtra(GLActivityIntentKeys.INTENT_EXTRA_BENCHMARK_NAME, benchmarkName);
+        intent.putExtra(GLActivityIntentKeys.INTENT_EXTRA_OFFSCREEN, offscreen);
+        intent.putExtra(GLActivityIntentKeys.INTENT_EXTRA_NUM_FRAMES, numFrames);
+        intent.putExtra(GLActivityIntentKeys.INTENT_EXTRA_NUM_ITERATIONS, numIterations);
+        intent.putExtra(GLActivityIntentKeys.INTENT_EXTRA_TIMEOUT, timeout);
 
-        GLActivity activity = null;
+        GLPrimitiveActivity activity = null;
         setActivityIntent(intent);
         try {
             activity = getActivity();
-            activity.spawnAndWaitForCompletion();
+            activity.waitForCompletion();
         } finally {
             if (activity != null) {
                 double[] fpsValues = activity.mFpsValues;
@@ -135,10 +135,13 @@
                 }
                 score /= numIterations;// Average.
 
+                // TODO: maybe standard deviation / RMSE will be useful?
+
                 getReportLog().printArray(
                         "Fps Values", fpsValues, ResultType.HIGHER_BETTER, ResultUnit.FPS);
-                getReportLog()
-                        .printSummary("Score", score, ResultType.HIGHER_BETTER, ResultUnit.SCORE);
+                getReportLog().printSummary(
+                        "Average Frames Per Second", score, ResultType.HIGHER_BETTER,
+                        ResultUnit.SCORE);
                 activity.finish();
             }
         }
diff --git a/suite/pts/deviceTests/opengl/src/com/android/pts/opengl/reference/GLGameActivity.java b/suite/pts/deviceTests/opengl/src/com/android/pts/opengl/reference/GLGameActivity.java
new file mode 100644
index 0000000..6cb0700
--- /dev/null
+++ b/suite/pts/deviceTests/opengl/src/com/android/pts/opengl/reference/GLGameActivity.java
@@ -0,0 +1,130 @@
+/*
+ * 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.pts.opengl.reference;
+
+import com.android.pts.opengl.GLActivityIntentKeys;
+
+import android.app.Activity;
+import android.content.Intent;
+import android.cts.util.WatchDog;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.Message;
+import android.view.Surface;
+import android.view.SurfaceHolder;
+import android.view.SurfaceView;
+
+import java.util.HashMap;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.Semaphore;
+
+public class GLGameActivity extends Activity {
+
+    public final static String SET_UP_TIME = "set_up_time";
+    public final static String UPDATE_TIMES = "update_times";
+    public final static String RENDER_TIMES = "render_times";
+
+    private int mNumFrames;
+    private int mTimeout;
+    private double[] mSetUpTimes;
+    private double[] mUpdateTimes;
+    private double[] mRenderTimes;
+    private volatile Surface mSurface = null;
+    private CountDownLatch mStartSignal = new CountDownLatch(1);
+
+    @Override
+    public void onCreate(Bundle data) {
+        super.onCreate(data);
+        System.loadLibrary("ptsopengl_jni");
+
+        Intent intent = getIntent();
+        mNumFrames = intent.getIntExtra(GLActivityIntentKeys.INTENT_EXTRA_NUM_FRAMES, 0);
+        mTimeout = intent.getIntExtra(GLActivityIntentKeys.INTENT_EXTRA_TIMEOUT, 0);
+
+        SurfaceView surfaceView = new SurfaceView(this);
+        surfaceView.getHolder().addCallback(new SurfaceHolder.Callback() {
+            @Override
+            public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
+                mSurface = holder.getSurface();
+                mStartSignal.countDown();
+            }
+
+            @Override
+            public void surfaceCreated(SurfaceHolder holder) {}
+
+            @Override
+            public void surfaceDestroyed(SurfaceHolder holder) {}
+        });
+        setContentView(surfaceView);
+
+        // Spawns a worker.
+        Worker worker = new Worker(new Handler() {
+            public void handleMessage(Message msg) {
+                Intent intent = new Intent();
+                intent.putExtra(SET_UP_TIME, mSetUpTimes);
+                intent.putExtra(UPDATE_TIMES, mUpdateTimes);
+                intent.putExtra(RENDER_TIMES, mRenderTimes);
+                setResult((msg.what == 1) ? RESULT_OK : RESULT_CANCELED, intent);
+                finish();
+            }
+        });
+        worker.start();
+    }
+
+    private static native boolean startBenchmark(Surface surface, int numFrames,
+            double[] setUpTimes, double[] updateTimes, double[] renderTimes);
+
+    /**
+     * This thread renderers the benchmarks, freeing the UI thread.
+     */
+    private class Worker extends Thread implements WatchDog.TimeoutCallback {
+
+        private WatchDog watchDog;
+        private Handler mHandler;
+
+        public Worker(Handler handler) {
+            mHandler = handler;
+        }
+
+        @Override
+        public void run() {
+            try {
+                mStartSignal.await();
+            } catch (InterruptedException e) {
+                mHandler.sendEmptyMessage(0);
+                return;
+            }
+            // Creates a watchdog to ensure a iteration doesn't exceed the timeout.
+            watchDog = new WatchDog(mTimeout, this);
+            watchDog.start();
+
+            // Used to record the time taken to setup (GL, context, textures, meshes).
+            mSetUpTimes = new double[4];
+            // Used to record the times taken to update.
+            mUpdateTimes = new double[mNumFrames];
+            // Used to record the times taken to render.
+            mRenderTimes = new double[mNumFrames];
+            boolean success =
+                    startBenchmark(mSurface, mNumFrames, mSetUpTimes, mUpdateTimes, mRenderTimes);
+
+            watchDog.stop();
+            mHandler.sendEmptyMessage((success) ? 1 : 0);
+        }
+
+        public void onTimeout() {
+            mHandler.sendEmptyMessage(0);
+        }
+
+    }
+}
diff --git a/suite/pts/deviceTests/opengl/src/com/android/pts/opengl/reference/GLReferenceActivity.java b/suite/pts/deviceTests/opengl/src/com/android/pts/opengl/reference/GLReferenceActivity.java
new file mode 100644
index 0000000..145fb75
--- /dev/null
+++ b/suite/pts/deviceTests/opengl/src/com/android/pts/opengl/reference/GLReferenceActivity.java
@@ -0,0 +1,78 @@
+/*
+ * 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.pts.opengl.reference;
+
+import com.android.pts.opengl.GLActivityIntentKeys;
+import com.android.pts.opengl.R;
+
+import android.app.Activity;
+import android.content.Intent;
+import android.os.Bundle;
+
+import java.util.HashMap;
+import java.util.concurrent.Semaphore;
+
+public class GLReferenceActivity extends Activity {
+
+    private final static int GAME_ACTIVITY_CODE = 1;
+
+    private int mNumFrames;
+    private int mTimeout;
+
+    public boolean mSuccess = false;
+    public double mUILoadTime;
+    public double[] mSetUpTimes;
+    public double[] mUpdateTimes;
+    public double[] mRenderTimes;
+
+    private Semaphore mSemaphore = new Semaphore(0);
+
+    @Override
+    public void onCreate(Bundle data) {
+        super.onCreate(data);
+        Intent intent = getIntent();
+        mNumFrames = intent.getIntExtra(GLActivityIntentKeys.INTENT_EXTRA_NUM_FRAMES, 0);
+        mTimeout = intent.getIntExtra(GLActivityIntentKeys.INTENT_EXTRA_TIMEOUT, 0);
+
+        double start = System.currentTimeMillis();
+        setContentView(R.layout.main);
+        mUILoadTime = System.currentTimeMillis() - start;
+
+        // Start benchmark
+        intent = new Intent(this, GLGameActivity.class);
+        intent.putExtra(GLActivityIntentKeys.INTENT_EXTRA_NUM_FRAMES, mNumFrames);
+        intent.putExtra(GLActivityIntentKeys.INTENT_EXTRA_TIMEOUT, mTimeout);
+        startActivityForResult(intent, GAME_ACTIVITY_CODE);
+    }
+
+    public void waitForCompletion() throws Exception {
+        // Wait for semiphore.
+        mSemaphore.acquire();
+    }
+
+    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
+        if (requestCode == GAME_ACTIVITY_CODE) {
+            if (resultCode == RESULT_OK) {
+                // Benchmark passed
+                mSuccess = true;
+                mSetUpTimes = data.getDoubleArrayExtra(GLGameActivity.SET_UP_TIME);
+                mUpdateTimes = data.getDoubleArrayExtra(GLGameActivity.UPDATE_TIMES);
+                mRenderTimes = data.getDoubleArrayExtra(GLGameActivity.RENDER_TIMES);
+            }
+            // Release semiphore.
+            mSemaphore.release();
+        }
+    }
+
+}
diff --git a/suite/pts/deviceTests/opengl/src/com/android/pts/opengl/reference/GLReferenceBenchmark.java b/suite/pts/deviceTests/opengl/src/com/android/pts/opengl/reference/GLReferenceBenchmark.java
new file mode 100644
index 0000000..14b247a
--- /dev/null
+++ b/suite/pts/deviceTests/opengl/src/com/android/pts/opengl/reference/GLReferenceBenchmark.java
@@ -0,0 +1,138 @@
+/*
+ * 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.pts.opengl.reference;
+
+import com.android.pts.opengl.GLActivityIntentKeys;
+import com.android.pts.util.PtsActivityInstrumentationTestCase2;
+import com.android.pts.util.ResultType;
+import com.android.pts.util.ResultUnit;
+
+import android.content.Context;
+import android.content.Intent;
+import android.cts.util.TimeoutReq;
+import android.view.Display;
+import android.view.WindowManager;
+
+import java.util.Arrays;
+
+/**
+ * Runs the Reference OpenGL ES 2.0 Benchmark.
+ */
+public class GLReferenceBenchmark extends PtsActivityInstrumentationTestCase2<GLReferenceActivity> {
+
+    private static final int NUM_FRAMES = 100;
+    private static final int TIMEOUT = 1000000;
+    // Reference values collected by averaging across n4, n7, n10.
+    private static final double NEXUS_REF_UI_LOAD = 40;// Milliseconds.
+    private static final double[] NEXUS_REF_SET_UP = {40, 0, 0, 0};// Milliseconds.
+    private static final double NEXUS_REF_UPDATE_AVG = 40;// Milliseconds.
+    private static final double NEXUS_REF_RENDER_AVG = 1;// As fraction of display refresh rate.
+
+    public GLReferenceBenchmark() {
+        super(GLReferenceActivity.class);
+    }
+
+    /**
+     * Runs the reference benchmark.
+     */
+    @TimeoutReq(minutes = 30)
+    public void testReferenceBenchmark() throws Exception {
+        Intent intent = new Intent();
+        intent.putExtra(GLActivityIntentKeys.INTENT_EXTRA_NUM_FRAMES, NUM_FRAMES);
+        intent.putExtra(GLActivityIntentKeys.INTENT_EXTRA_TIMEOUT, TIMEOUT);
+
+        GLReferenceActivity activity = null;
+        setActivityIntent(intent);
+        try {
+            activity = getActivity();
+            activity.waitForCompletion();
+        } finally {
+            if (activity != null) {
+                double score = 0;
+                if (activity.mSuccess) {
+                    // Get frame interval.
+                    WindowManager wm =
+                            (WindowManager) activity.getSystemService(Context.WINDOW_SERVICE);
+                    Display dpy = wm.getDefaultDisplay();
+                    double refreshRate = dpy.getRefreshRate();
+                    double frameIntervalMs = 1000.0 / refreshRate;
+
+                    double uiLoadTime = activity.mUILoadTime;
+                    double[] setUpTimes = activity.mSetUpTimes;
+                    double[] updateTimes = activity.mUpdateTimes;
+                    double[] renderTimes = activity.mRenderTimes;
+
+                    double uiLoadScore = NEXUS_REF_UI_LOAD / uiLoadTime;
+                    double setUpScore = 0;// Lower better
+                    for (int i = 0; i < 4; i++) {
+                        setUpScore += NEXUS_REF_SET_UP[i] / setUpTimes[i];
+                    }
+
+                    // Calculate update and render average.
+                    double updateSum = updateTimes[0];
+                    double renderSum = renderTimes[0];
+                    double[] renderIntervals = new double[NUM_FRAMES - 1];
+                    for (int i = 0; i < NUM_FRAMES - 1; i++) {
+                        updateSum += updateTimes[i + 1];
+                        renderSum += renderTimes[i + 1];
+                        renderIntervals[i] = renderTimes[i + 1] - renderTimes[i];
+                    }
+                    double updateAverage = updateSum / NUM_FRAMES;
+                    double updateScore = NEXUS_REF_UPDATE_AVG / updateAverage;
+                    double renderAverage = renderSum / NUM_FRAMES;
+                    double renderScore = NEXUS_REF_RENDER_AVG / (renderAverage / frameIntervalMs);
+
+                    // Calculate jankiness.
+                    int numJanks = 0;
+                    double totalJanks = 0.0;
+                    double[] janks = new double[NUM_FRAMES - 2];
+                    for (int i = 0; i < NUM_FRAMES - 2; i++) {
+                        double delta = renderIntervals[i + 1] - renderIntervals[i];
+                        janks[i] = Math.max(delta / frameIntervalMs, 0.0);
+                        if (janks[i] > 0) {
+                            numJanks++;
+                        }
+                        totalJanks += janks[i];
+                    }
+
+                    getReportLog().printValue(
+                            "UI Load Time", uiLoadTime, ResultType.LOWER_BETTER, ResultUnit.MS);
+                    getReportLog().printValue(
+                            "UI Load Score", uiLoadScore, ResultType.HIGHER_BETTER,
+                            ResultUnit.SCORE);
+                    getReportLog().printArray(
+                            "Set Up Times", setUpTimes, ResultType.LOWER_BETTER, ResultUnit.MS);
+                    getReportLog().printValue(
+                            "Set Up Score", setUpScore, ResultType.HIGHER_BETTER, ResultUnit.SCORE);
+                    getReportLog().printArray(
+                            "Update Times", updateTimes, ResultType.LOWER_BETTER, ResultUnit.MS);
+                    getReportLog().printValue("Update Score", updateScore, ResultType.HIGHER_BETTER,
+                            ResultUnit.SCORE);
+                    getReportLog().printArray(
+                            "Render Times", renderTimes, ResultType.LOWER_BETTER, ResultUnit.MS);
+                    getReportLog().printValue("Render Score", renderScore, ResultType.HIGHER_BETTER,
+                            ResultUnit.SCORE);
+                    getReportLog().printValue(
+                            "Num Janks", numJanks, ResultType.LOWER_BETTER, ResultUnit.COUNT);
+                    getReportLog().printValue(
+                            "Total Jank", totalJanks, ResultType.LOWER_BETTER, ResultUnit.COUNT);
+                    score = (uiLoadScore + setUpScore + updateScore + renderScore) / 4.0f;
+                }
+                getReportLog()
+                        .printSummary("Score", score, ResultType.HIGHER_BETTER, ResultUnit.SCORE);
+                activity.finish();
+            }
+        }
+    }
+}
diff --git a/suite/pts/utils/grapher.py b/suite/pts/utils/grapher.py
index e326612..12976ec 100755
--- a/suite/pts/utils/grapher.py
+++ b/suite/pts/utils/grapher.py
@@ -42,7 +42,7 @@
 
   # For each of the benchmarks
   for benchmark in tests:
-    if benchmark.startswith('com.android.pts.opengl'):
+    if benchmark.startswith('com.android.pts.opengl.primitive'):
       results = tests[benchmark]
       legend = []
       # Create a new figure
@@ -58,7 +58,7 @@
           y = r['details']['Fps Values']
           x = range(1, len(y) + 1)
           # Get the score, then trim it to 2 decimal places
-          score = r['summary']['Score']
+          score = r['summary']['Average Frames Per Second']
           score = score[0:score.index('.') + 3]
         if score != 'no results':
           # Create a plot