Merge "CTS tests for Contactables api" into jb-mr2-dev
diff --git a/suite/pts/deviceTests/opengl/jni/primitive/fullpipeline/FullPipelineMesh.cpp b/suite/pts/deviceTests/opengl/jni/graphics/BasicMeshNode.cpp
similarity index 83%
rename from suite/pts/deviceTests/opengl/jni/primitive/fullpipeline/FullPipelineMesh.cpp
rename to suite/pts/deviceTests/opengl/jni/graphics/BasicMeshNode.cpp
index bf1b9d2..273517a 100644
--- a/suite/pts/deviceTests/opengl/jni/primitive/fullpipeline/FullPipelineMesh.cpp
+++ b/suite/pts/deviceTests/opengl/jni/graphics/BasicMeshNode.cpp
@@ -12,20 +12,21 @@
  * the License.
  */
 
-#include "FullPipelineMesh.h"
+#include "BasicMeshNode.h"
 
-#include <graphics/BasicProgram.h>
+#include "BasicProgram.h"
 
-FullPipelineMesh::FullPipelineMesh(const Mesh* mesh) :
-        MeshNode(mesh) {
+BasicMeshNode::BasicMeshNode(const Mesh* mesh, const GLuint textureId) :
+        MeshNode(mesh),
+        mTextureId(textureId) {
 }
 
-void FullPipelineMesh::before(Program& program, Matrix& model, Matrix& view, Matrix& projection) {
+void BasicMeshNode::before(Program& program, Matrix& model, Matrix& view, Matrix& projection) {
     BasicProgram& prog = (BasicProgram&) program;
 
     glActiveTexture(GL_TEXTURE0);
     // Bind the texture to this unit.
-    glBindTexture(GL_TEXTURE_2D, mMesh->mTextureId);
+    glBindTexture(GL_TEXTURE_2D, mTextureId);
     // Tell the texture uniform sampler to use this texture in the shader by binding to texture
     // unit 0.
     glUniform1i(prog.mTextureUniformHandle, 0);
@@ -58,5 +59,5 @@
     glDrawArrays(GL_TRIANGLES, 0, mMesh->mNumVertices);
 }
 
-void FullPipelineMesh::after(Program& program, Matrix& model, Matrix& view, Matrix& projection) {
+void BasicMeshNode::after(Program& program, Matrix& model, Matrix& view, Matrix& projection) {
 }
diff --git a/suite/pts/deviceTests/opengl/jni/primitive/fullpipeline/FullPipelineMesh.h b/suite/pts/deviceTests/opengl/jni/graphics/BasicMeshNode.h
similarity index 73%
rename from suite/pts/deviceTests/opengl/jni/primitive/fullpipeline/FullPipelineMesh.h
rename to suite/pts/deviceTests/opengl/jni/graphics/BasicMeshNode.h
index 3fcb8ae..97cd24b 100644
--- a/suite/pts/deviceTests/opengl/jni/primitive/fullpipeline/FullPipelineMesh.h
+++ b/suite/pts/deviceTests/opengl/jni/graphics/BasicMeshNode.h
@@ -12,23 +12,24 @@
  * the License.
  */
 
-#ifndef FULLPIPELINEMESH_H
-#define FULLPIPELINEMESH_H
+#ifndef BASICMESHNODE_H
+#define BASICMESHNODE_H
 
-#include <graphics/Matrix.h>
-#include <graphics/Mesh.h>
-#include <graphics/MeshNode.h>
-#include <graphics/Program.h>
+#include "Matrix.h"
+#include "Mesh.h"
+#include "MeshNode.h"
+#include "Program.h"
 
-class FullPipelineMesh: public MeshNode {
+class BasicMeshNode: public MeshNode {
 public:
-    FullPipelineMesh(const Mesh* mesh);
-    virtual ~FullPipelineMesh() {};
+    BasicMeshNode(const Mesh* mesh, const GLuint textureId);
+    virtual ~BasicMeshNode() {};
 protected:
     virtual void before(Program& program, Matrix& model, Matrix& view,
             Matrix& projection);
     virtual void after(Program& program, Matrix& model, Matrix& view,
             Matrix& projection);
+    const GLuint mTextureId;
 };
 
 #endif
diff --git a/suite/pts/deviceTests/opengl/jni/graphics/GLUtils.cpp b/suite/pts/deviceTests/opengl/jni/graphics/GLUtils.cpp
index ed6f84b6..2484153 100644
--- a/suite/pts/deviceTests/opengl/jni/graphics/GLUtils.cpp
+++ b/suite/pts/deviceTests/opengl/jni/graphics/GLUtils.cpp
@@ -101,7 +101,7 @@
     return x + 1;
 }
 
-GLuint GLUtils::genRandTex(int texWidth, int texHeight) {
+GLuint GLUtils::genTexture(int texWidth, int texHeight, int fill) {
     GLuint textureId = 0;
     int w = roundUpToSmallestPowerOf2(texWidth);
     int h = roundUpToSmallestPowerOf2(texHeight);
@@ -110,8 +110,11 @@
         uint32_t* d = m;
         for (int y = 0; y < h; y++) {
             for (int x = 0; x < w; x++) {
-                *d = 0xff000000 | ((y & 0xff) << 16) | ((x & 0xff) << 8)
-                        | ((x + y) & 0xff);
+                if (fill == RANDOM_FILL) {
+                    *d = 0xff000000 | ((y & 0xff) << 16) | ((x & 0xff) << 8) | ((x + y) & 0xff);
+                } else {
+                    *d = 0xff000000 | fill;
+                }
                 d++;
             }
         }
diff --git a/suite/pts/deviceTests/opengl/jni/graphics/GLUtils.h b/suite/pts/deviceTests/opengl/jni/graphics/GLUtils.h
index 3d3bafd..16060ed 100644
--- a/suite/pts/deviceTests/opengl/jni/graphics/GLUtils.h
+++ b/suite/pts/deviceTests/opengl/jni/graphics/GLUtils.h
@@ -26,8 +26,11 @@
     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.
-    static GLuint genRandTex(int texWidth, int texHeight);
+    static const int RANDOM_FILL = -1;
+    // Generates a texture of the given dimensions. The texture can either be filled with the
+    // specified fill color, else if RANDOM_FILL is passed in the texture will be filled with
+    // random values.
+    static GLuint genTexture(int texWidth, int texHeight, int fill);
     static bool createFBO(GLuint& fboId, GLuint& rboId, GLuint& cboId, int width, int height);
 };
 
diff --git a/suite/pts/deviceTests/opengl/jni/graphics/Mesh.cpp b/suite/pts/deviceTests/opengl/jni/graphics/Mesh.cpp
index b92551c..858ec6b 100644
--- a/suite/pts/deviceTests/opengl/jni/graphics/Mesh.cpp
+++ b/suite/pts/deviceTests/opengl/jni/graphics/Mesh.cpp
@@ -14,11 +14,10 @@
 #include "Mesh.h"
 
 Mesh::Mesh(const float* vertices, const float* normals, const float* texCoords,
-           const int numVertices, const GLuint textureId)
+           const int numVertices)
     : mVertices(vertices),
       mNormals(normals),
       mTexCoords(texCoords),
-      mNumVertices(numVertices),
-      mTextureId(textureId) {
+      mNumVertices(numVertices) {
 
 }
diff --git a/suite/pts/deviceTests/opengl/jni/graphics/Mesh.h b/suite/pts/deviceTests/opengl/jni/graphics/Mesh.h
index 5f5ac7d..9ff4103 100644
--- a/suite/pts/deviceTests/opengl/jni/graphics/Mesh.h
+++ b/suite/pts/deviceTests/opengl/jni/graphics/Mesh.h
@@ -21,13 +21,12 @@
 class Mesh {
 public:
     Mesh(const float* vertices, const float* normals, const float* texCoords,
-            const int numVertices, const GLuint textureId);
+            const int numVertices);
     virtual ~Mesh() {};
     const float* mVertices;
     const float* mNormals;
     const float* mTexCoords;
     const int mNumVertices;
-    const GLuint mTextureId;
 };
 
 #endif
diff --git a/suite/pts/deviceTests/opengl/jni/graphics/Renderer.cpp b/suite/pts/deviceTests/opengl/jni/graphics/Renderer.cpp
index ece115e..e9d083d 100644
--- a/suite/pts/deviceTests/opengl/jni/graphics/Renderer.cpp
+++ b/suite/pts/deviceTests/opengl/jni/graphics/Renderer.cpp
@@ -74,20 +74,20 @@
         return false;
     }
 
-    if (!eglQuerySurface(mEglDisplay, mEglSurface, EGL_WIDTH, &width)
+    if (!eglQuerySurface(mEglDisplay, mEglSurface, EGL_WIDTH, &mWidth)
             || EGL_SUCCESS != eglGetError()) {
         return false;
     }
-    if (!eglQuerySurface(mEglDisplay, mEglSurface, EGL_HEIGHT, &height)
+    if (!eglQuerySurface(mEglDisplay, mEglSurface, EGL_HEIGHT, &mHeight)
             || EGL_SUCCESS != eglGetError()) {
         return false;
     }
 
-    glViewport(0, 0, width, height);
+    glViewport(0, 0, mWidth, mHeight);
 
     if (mOffscreen) {
-        mFboWidth = GLUtils::roundUpToSmallestPowerOf2(width);
-        mFboHeight = GLUtils::roundUpToSmallestPowerOf2(height);
+        mFboWidth = GLUtils::roundUpToSmallestPowerOf2(mWidth);
+        mFboHeight = GLUtils::roundUpToSmallestPowerOf2(mHeight);
         if (!GLUtils::createFBO(mFboId, mRboId, mCboId, mFboWidth, mFboHeight)) {
             return false;
         }
diff --git a/suite/pts/deviceTests/opengl/jni/graphics/Renderer.h b/suite/pts/deviceTests/opengl/jni/graphics/Renderer.h
index cbe9419..8da504d 100644
--- a/suite/pts/deviceTests/opengl/jni/graphics/Renderer.h
+++ b/suite/pts/deviceTests/opengl/jni/graphics/Renderer.h
@@ -40,8 +40,8 @@
     GLuint mCboId;// Color buffer id
     GLushort* mBuffer;// Used for FBO read back
     GLuint mProgramId;
-    EGLint width;
-    EGLint height;
+    EGLint mWidth;
+    EGLint mHeight;
     bool mOffscreen;
     int mWorkload;
 };
diff --git a/suite/pts/deviceTests/opengl/jni/graphics/Vector2D.cpp b/suite/pts/deviceTests/opengl/jni/graphics/Vector2D.cpp
new file mode 100644
index 0000000..d4a8c18
--- /dev/null
+++ b/suite/pts/deviceTests/opengl/jni/graphics/Vector2D.cpp
@@ -0,0 +1,68 @@
+/*
+ * 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 "Vector2D.h"
+
+#include <math.h>
+
+Vector2D::Vector2D() :
+        mX(0), mY(0) {
+}
+
+Vector2D::Vector2D(float x, float y) :
+        mX(x), mY(y) {
+}
+
+Vector2D Vector2D::copy() {
+    Vector2D v(mX, mY);
+    return v;
+}
+
+void Vector2D::add(const Vector2D& v) {
+    mX += v.mX;
+    mY += v.mY;
+}
+
+void Vector2D::sub(const Vector2D& v) {
+    mX -= v.mX;
+    mY -= v.mY;
+}
+
+void Vector2D::scale(float s) {
+    mX *= s;
+    mY *= s;
+}
+
+float Vector2D::distance(const Vector2D& v) {
+    float dx = mX - v.mX;
+    float dy = mY - v.mY;
+    return (float) sqrt(dx * dx + dy * dy);
+}
+
+void Vector2D::normalize() {
+    float m = magnitude();
+    if (m > 0) {
+        scale(1 / m);
+    }
+}
+
+void Vector2D::limit(float max) {
+    if (magnitude() > max) {
+        normalize();
+        scale(max);
+    }
+}
+
+float Vector2D::magnitude() {
+    return (float) sqrt(mX * mX + mY * mY);
+}
diff --git a/suite/pts/deviceTests/opengl/jni/graphics/Vector2D.h b/suite/pts/deviceTests/opengl/jni/graphics/Vector2D.h
new file mode 100644
index 0000000..5110975
--- /dev/null
+++ b/suite/pts/deviceTests/opengl/jni/graphics/Vector2D.h
@@ -0,0 +1,33 @@
+/*
+ * 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.
+ */
+#ifndef VECTOR2D_H
+#define VECTOR2D_H
+
+class Vector2D {
+public:
+    Vector2D();
+    Vector2D(float x, float y);
+    Vector2D copy();
+    void normalize();
+    void add(const Vector2D& v);
+    void sub(const Vector2D& v);
+    void scale(float s);
+    void limit(float max);
+    void limit(float maxX, float maxY);
+    float magnitude();
+    float distance(const Vector2D& v);
+    float mX;
+    float mY;
+};
+#endif
diff --git a/suite/pts/deviceTests/opengl/jni/primitive/contextswitch/ContextSwitchRenderer.cpp b/suite/pts/deviceTests/opengl/jni/primitive/contextswitch/ContextSwitchRenderer.cpp
index 44e8909..8865c99 100644
--- a/suite/pts/deviceTests/opengl/jni/primitive/contextswitch/ContextSwitchRenderer.cpp
+++ b/suite/pts/deviceTests/opengl/jni/primitive/contextswitch/ContextSwitchRenderer.cpp
@@ -25,11 +25,14 @@
 
 #include <Trace.h>
 
-static const EGLint contextAttribs[] =
-        { EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE };
+static const EGLint contextAttribs[] = {
+        EGL_CONTEXT_CLIENT_VERSION, 2,
+        EGL_NONE };
 
 static const int NUM_WORKER_CONTEXTS = 7;
 
+static const int CS_TEXTURE_SIZE = 64;
+
 static const int CS_NUM_VERTICES = 6;
 
 static const float CS_VERTICES[CS_NUM_VERTICES * 3] = {
@@ -78,7 +81,7 @@
     }
 
     // Setup texture.
-    mTextureId = GLUtils::genRandTex(64, 64);
+    mTextureId = GLUtils::genTexture(CS_TEXTURE_SIZE, CS_TEXTURE_SIZE, GLUtils::RANDOM_FILL);
     if (mTextureId == 0) {
         return false;
     }
diff --git a/suite/pts/deviceTests/opengl/jni/primitive/fullpipeline/FullPipelineRenderer.cpp b/suite/pts/deviceTests/opengl/jni/primitive/fullpipeline/FullPipelineRenderer.cpp
index da65420..01b143b 100644
--- a/suite/pts/deviceTests/opengl/jni/primitive/fullpipeline/FullPipelineRenderer.cpp
+++ b/suite/pts/deviceTests/opengl/jni/primitive/fullpipeline/FullPipelineRenderer.cpp
@@ -15,11 +15,11 @@
 #include <GLES2/gl2.h>
 #include <GLES2/gl2ext.h>
 
-#include "FullPipelineMesh.h"
 #include "FullPipelineRenderer.h"
 
-#include <graphics/TransformationNode.h>
+#include <graphics/BasicMeshNode.h>
 #include <graphics/GLUtils.h>
+#include <graphics/TransformationNode.h>
 
 #include <Trace.h>
 
@@ -104,8 +104,9 @@
     }
 
     mProgramId = GLUtils::createProgram(&FP_VERTEX, &FP_FRAGMENT);
-    if (mProgramId == 0)
+    if (mProgramId == 0) {
         return false;
+    }
     mProgram = new BasicProgram(mProgramId);
 
     mModelMatrix = new Matrix();
@@ -130,7 +131,7 @@
 
     // Create a new perspective projection matrix. The height will stay the same
     // while the width will vary as per aspect ratio.
-    float ratio = (float) width / height;
+    float ratio = (float) mWidth / mHeight;
     float left = -ratio;
     float right = ratio;
     float bottom = -1.0f;
@@ -141,7 +142,7 @@
     mProjectionMatrix = Matrix::newFrustum(left, right, bottom, top, near, far);
 
     // Setup texture.
-    mTextureId = GLUtils::genRandTex(width, height);
+    mTextureId = GLUtils::genTexture(mWidth, mHeight, GLUtils::RANDOM_FILL);
     if (mTextureId == 0) {
         return false;
     }
@@ -150,7 +151,7 @@
     float middle = count / 2.0f;
     float scale = 2.0f / count;
 
-    mMesh = new Mesh(FP_VERTICES, FP_NORMALS, FP_TEX_COORDS, FP_NUM_VERTICES, mTextureId);
+    mMesh = new Mesh(FP_VERTICES, FP_NORMALS, FP_TEX_COORDS, FP_NUM_VERTICES);
     mSceneGraph = new ProgramNode();
 
     for (int i = 0; i < count; i++) {
@@ -159,7 +160,7 @@
             transformMatrix->translate(i - middle, j - middle, 0.0f);
             TransformationNode* transformNode = new TransformationNode(transformMatrix);
             mSceneGraph->addChild(transformNode);
-            FullPipelineMesh* meshNode = new FullPipelineMesh(mMesh);
+            BasicMeshNode* meshNode = new BasicMeshNode(mMesh, mTextureId);
             transformNode->addChild(meshNode);
         }
     }
diff --git a/suite/pts/deviceTests/opengl/jni/primitive/pixeloutput/PixelOutputRenderer.cpp b/suite/pts/deviceTests/opengl/jni/primitive/pixeloutput/PixelOutputRenderer.cpp
index 321235d..3fdafca 100644
--- a/suite/pts/deviceTests/opengl/jni/primitive/pixeloutput/PixelOutputRenderer.cpp
+++ b/suite/pts/deviceTests/opengl/jni/primitive/pixeloutput/PixelOutputRenderer.cpp
@@ -62,15 +62,16 @@
 
     // Create program.
     mProgramId = GLUtils::createProgram(&PO_VERTEX, &PO_FRAGMENT);
-    if (mProgramId == 0)
+    if (mProgramId == 0) {
         return false;
+    }
     // Bind attributes.
     mTextureUniformHandle = glGetUniformLocation(mProgramId, "u_Texture");
     mPositionHandle = glGetAttribLocation(mProgramId, "a_Position");
     mTexCoordHandle = glGetAttribLocation(mProgramId, "a_TexCoord");
 
     // Setup texture.
-    mTextureId = GLUtils::genRandTex(width, height);
+    mTextureId = GLUtils::genTexture(mWidth, mHeight, GLUtils::RANDOM_FILL);
     if (mTextureId == 0) {
         return false;
     }
diff --git a/suite/pts/deviceTests/opengl/jni/primitive/shaderperf/ShaderPerfRenderer.cpp b/suite/pts/deviceTests/opengl/jni/primitive/shaderperf/ShaderPerfRenderer.cpp
index cff8599..85e6af3 100644
--- a/suite/pts/deviceTests/opengl/jni/primitive/shaderperf/ShaderPerfRenderer.cpp
+++ b/suite/pts/deviceTests/opengl/jni/primitive/shaderperf/ShaderPerfRenderer.cpp
@@ -112,8 +112,9 @@
     // Create program.
     mProgramId = GLUtils::createProgram(&SP_VERTEX, const_cast<const char**>(&spFragment));
     delete[] spFragment;
-    if (mProgramId == 0)
+    if (mProgramId == 0) {
         return false;
+    }
     // Bind attributes.
     mTextureUniformHandle = glGetUniformLocation(mProgramId, "u_Texture");
     mSeedUniformHandle = glGetUniformLocation(mProgramId, "u_Seed");
diff --git a/suite/pts/deviceTests/opengl/jni/reference/GLReference.cpp b/suite/pts/deviceTests/opengl/jni/reference/GLReference.cpp
index 53a262e..333e0da 100644
--- a/suite/pts/deviceTests/opengl/jni/reference/GLReference.cpp
+++ b/suite/pts/deviceTests/opengl/jni/reference/GLReference.cpp
@@ -13,10 +13,46 @@
  */
 #include <jni.h>
 
+#include <android/native_window.h>
+#include <android/native_window_jni.h>
+
+#include <graphics/GLUtils.h>
+#include <graphics/Renderer.h>
+
+#include "ReferenceRenderer.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;
+
+    if (numFrames > (ReferenceRenderer::FRAMES_PER_SCENE * ReferenceRenderer::NUM_SCENES)) {
+        return false;
+    }
+
+    ReferenceRenderer* gRenderer = new ReferenceRenderer(ANativeWindow_fromSurface(env, surface));
+
+    bool success = gRenderer->setUp();
+    env->SetDoubleArrayRegion(
+            setUpTimes, 0, ReferenceRenderer::NUM_SETUP_TIMES, gRenderer->mSetUpTimes);
+
+    double updates[numFrames];
+    double renders[numFrames];
+    for (int i = 0; i < numFrames && success; i++) {
+        double t0 = GLUtils::currentTimeMillis();
+        success = gRenderer->update(i);
+        double t1 = GLUtils::currentTimeMillis();
+        success = success && gRenderer->draw();
+        double t2 = GLUtils::currentTimeMillis();
+        updates[i] = t1 - t0;
+        renders[i] = t2 - t1;
+    }
+
+    env->SetDoubleArrayRegion(updateTimes, 0, numFrames, updates);
+    env->SetDoubleArrayRegion(renderTimes, 0, numFrames, renders);
+
+    success = gRenderer->tearDown() && success;
+    delete gRenderer;
+    gRenderer = NULL;
+    return success;
 }
diff --git a/suite/pts/deviceTests/opengl/jni/reference/ReferenceRenderer.cpp b/suite/pts/deviceTests/opengl/jni/reference/ReferenceRenderer.cpp
new file mode 100644
index 0000000..a168246
--- /dev/null
+++ b/suite/pts/deviceTests/opengl/jni/reference/ReferenceRenderer.cpp
@@ -0,0 +1,100 @@
+/*
+ * 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 "ReferenceRenderer.h"
+
+#include "scene/flocking/FlockingScene.h"
+
+#include <graphics/GLUtils.h>
+#include <graphics/ProgramNode.h>
+
+#include <Trace.h>
+
+ReferenceRenderer::ReferenceRenderer(ANativeWindow* window) :
+        Renderer(window, false, 0) {
+}
+
+bool ReferenceRenderer::setUp() {
+    SCOPED_TRACE();
+    // Reset the times.
+    for (int i = 0; i < NUM_SETUP_TIMES; i++) {
+        mSetUpTimes[i] = 0;
+    }
+    // Set up OpenGLES.
+    double start = GLUtils::currentTimeMillis();
+    if (!Renderer::setUp()) {
+        return false;
+    }
+    mSetUpTimes[0] = GLUtils::currentTimeMillis() - start;
+
+    // Create the scenes.
+    mScenes[0] = new FlockingScene(mWidth, mHeight);
+    // TODO add more scenes to do a comprehensive test.
+
+    // Set up the scenes.
+    double times[NUM_SETUP_TIMES];
+    for (int i = 0; i < NUM_SCENES; i++) {
+        times[0] = GLUtils::currentTimeMillis();
+        mScenes[i]->setUpContext();
+        times[1] = GLUtils::currentTimeMillis();
+        mScenes[i]->setUpTextures();
+        times[2] = GLUtils::currentTimeMillis();
+        mScenes[i]->setUpMeshes();
+        times[3] = GLUtils::currentTimeMillis();
+
+        for (int i = 1; i < NUM_SETUP_TIMES; i++) {
+            // Add on the set up times.
+            mSetUpTimes[i] += times[i] - times[i - 1];
+        }
+    }
+    return true;
+}
+
+bool ReferenceRenderer::tearDown() {
+    SCOPED_TRACE();
+    for (int i = 0; i < NUM_SCENES; i++) {
+        mScenes[i]->tearDown();
+        delete mScenes[i];
+    }
+    mCurrentScene = NULL;
+    if (!Renderer::tearDown()) {
+        return false;
+    }
+    return true;
+}
+
+bool ReferenceRenderer::update(int frame) {
+    SCOPED_TRACE();
+    int sceneId = frame / ReferenceRenderer::FRAMES_PER_SCENE;
+    int localFrame = frame % ReferenceRenderer::FRAMES_PER_SCENE;
+    mCurrentScene = mScenes[sceneId];
+    mCurrentScene->update(localFrame);
+    return true;
+}
+
+bool ReferenceRenderer::draw() {
+    SCOPED_TRACE();
+    if (mOffscreen) {
+        glBindFramebuffer(GL_FRAMEBUFFER, mFboId);
+    }
+    // Set the background clear color to black.
+    glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
+    // Use culling to remove back faces.
+    glEnable(GL_CULL_FACE);
+    // Use depth testing.
+    glEnable(GL_DEPTH_TEST);
+    glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
+    mCurrentScene->draw();
+
+    return Renderer::draw();
+}
diff --git a/suite/pts/deviceTests/opengl/jni/reference/ReferenceRenderer.h b/suite/pts/deviceTests/opengl/jni/reference/ReferenceRenderer.h
new file mode 100644
index 0000000..fa77ec1
--- /dev/null
+++ b/suite/pts/deviceTests/opengl/jni/reference/ReferenceRenderer.h
@@ -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.
+ */
+#ifndef REFERENCERENDERER_H
+#define REFERENCERENDERER_H
+
+#include "scene/Scene.h"
+
+#include <graphics/Mesh.h>
+#include <graphics/Renderer.h>
+
+class ReferenceRenderer: public Renderer {
+public:
+    ReferenceRenderer(ANativeWindow* window);
+    virtual ~ReferenceRenderer() {};
+    bool setUp();
+    bool tearDown();
+    bool update(int frame);
+    bool draw();
+    double mSetUpTimes[4];
+    static const int FRAMES_PER_SCENE = 500;
+    static const int NUM_SCENES = 1;
+    static const int NUM_SETUP_TIMES = 4;
+private:
+    Scene* mScenes[NUM_SCENES];
+    Scene* mCurrentScene;
+
+};
+
+#endif
diff --git a/suite/pts/deviceTests/opengl/jni/reference/scene/Scene.cpp b/suite/pts/deviceTests/opengl/jni/reference/scene/Scene.cpp
new file mode 100644
index 0000000..7ea889b
--- /dev/null
+++ b/suite/pts/deviceTests/opengl/jni/reference/scene/Scene.cpp
@@ -0,0 +1,81 @@
+/*
+ * 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 "Scene.h"
+
+#include <graphics/GLUtils.h>
+#include <graphics/ProgramNode.h>
+
+#include <Trace.h>
+
+Scene::Scene(int width, int height) :
+        mWidth(width), mHeight(height), mSceneGraph(NULL) {
+}
+
+bool Scene::setUpContext() {
+    SCOPED_TRACE();
+    mProgram = setUpProgram();
+    if (mProgram == NULL) {
+        return false;
+    }
+    mModelMatrix = setUpModelMatrix();
+    if (mModelMatrix == NULL) {
+        return false;
+    }
+    mViewMatrix = setUpViewMatrix();
+    if (mViewMatrix == NULL) {
+        return false;
+    }
+    mProjectionMatrix = setUpProjectionMatrix();
+    if (mProjectionMatrix == NULL) {
+        return false;
+    }
+    return true;
+}
+
+bool Scene::tearDown() {
+    SCOPED_TRACE();
+    for (size_t i = 0; i < mTextureIds.size(); i++) {
+        glDeleteTextures(1, &(mTextureIds[i]));
+    }
+    for (size_t i = 0; i < mMeshes.size(); i++) {
+        delete mMeshes[i];
+    }
+    delete mProgram;
+    mProgram = NULL;
+    delete mSceneGraph;
+    mSceneGraph = NULL;
+    delete mModelMatrix;
+    mModelMatrix = NULL;
+    delete mViewMatrix;
+    mViewMatrix = NULL;
+    delete mProjectionMatrix;
+    mProjectionMatrix = NULL;
+    return true;
+}
+
+bool Scene::update(int frame) {
+    SCOPED_TRACE();
+    delete mSceneGraph; // Delete the old scene graph.
+    mSceneGraph = updateSceneGraph();
+    if (mSceneGraph == NULL) {
+        return false;
+    }
+    return true;
+}
+
+bool Scene::draw() {
+    SCOPED_TRACE();
+    mSceneGraph->draw(*mProgram, *mModelMatrix, *mViewMatrix, *mProjectionMatrix);
+    return true;
+}
diff --git a/suite/pts/deviceTests/opengl/jni/reference/scene/Scene.h b/suite/pts/deviceTests/opengl/jni/reference/scene/Scene.h
new file mode 100644
index 0000000..1adb850
--- /dev/null
+++ b/suite/pts/deviceTests/opengl/jni/reference/scene/Scene.h
@@ -0,0 +1,51 @@
+/*
+ * 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.
+ */
+#ifndef SCENE_H
+#define SCENE_H
+
+#include <graphics/Matrix.h>
+#include <graphics/Mesh.h>
+#include <graphics/Program.h>
+#include <graphics/SceneGraphNode.h>
+
+#include <utils/Vector.h>
+
+class Scene {
+public:
+    Scene(int width, int height);
+    virtual ~Scene() {};
+    virtual bool setUpContext();
+    virtual bool setUpTextures() = 0;
+    virtual bool setUpMeshes() = 0;
+    virtual bool tearDown();
+    virtual bool update(int frame);
+    virtual bool draw();
+protected:
+    virtual Program* setUpProgram() = 0;
+    virtual Matrix* setUpModelMatrix() = 0;
+    virtual Matrix* setUpViewMatrix() = 0;
+    virtual Matrix* setUpProjectionMatrix() = 0;
+    virtual SceneGraphNode* updateSceneGraph() = 0;
+    int mWidth;
+    int mHeight;
+    android::Vector<Mesh*> mMeshes;
+    android::Vector<GLuint> mTextureIds;
+private:
+    Program* mProgram;
+    SceneGraphNode* mSceneGraph;
+    Matrix* mModelMatrix;
+    Matrix* mViewMatrix;
+    Matrix* mProjectionMatrix;
+};
+#endif
diff --git a/suite/pts/deviceTests/opengl/jni/reference/scene/flocking/Boid.cpp b/suite/pts/deviceTests/opengl/jni/reference/scene/flocking/Boid.cpp
new file mode 100644
index 0000000..74eef81
--- /dev/null
+++ b/suite/pts/deviceTests/opengl/jni/reference/scene/flocking/Boid.cpp
@@ -0,0 +1,96 @@
+/*
+ * 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 "Boid.h"
+
+Boid::Boid(float x, float y) :
+        mPosition(x, y) {
+}
+
+void Boid::flock(const Boid* boids[], int numBoids, int index, float limitX, float limitY) {
+    // Reset the acceleration.
+    mAcceleration.mX = 0;
+    mAcceleration.mY = 0;
+    Vector2D separation;
+    int separationCount = 0;
+    Vector2D alignment;
+    int alignmentCount = 0;
+    Vector2D cohesion;
+    int cohesionCount = 0;
+    for (int i = 0; i < numBoids; i++) {
+        if (i != index) {
+            const Boid* b = boids[i];
+            float dist = mPosition.distance(b->mPosition);
+            if (dist != 0) {
+                // Separation.
+                if (dist < DESIRED_BOID_DIST) {
+                    Vector2D tmp = mPosition.copy();
+                    tmp.sub(b->mPosition);
+                    tmp.normalize();
+                    tmp.scale(1.0f / dist);
+                    separation.add(tmp);
+                    separationCount++;
+                }
+                if (dist < NEIGHBOUR_RADIUS) {
+                    // Alignment.
+                    alignment.add(b->mVelocity);
+                    alignmentCount++;
+                    // Cohesion.
+                    cohesion.add(b->mPosition);
+                    cohesionCount++;
+                }
+            }
+        }
+    }
+
+    if (separationCount > 0) {
+        separation.scale(1.0f / separationCount);
+        separation.scale(SEPARATION_WEIGHT);
+        mAcceleration.add(separation);
+    }
+    if (alignmentCount > 0) {
+        alignment.scale(1.0f / alignmentCount);
+        alignment.limit(MAX_FORCE);
+        alignment.scale(ALIGNMENT_WEIGHT);
+        mAcceleration.add(alignment);
+    }
+    if (cohesionCount > 0) {
+        cohesion.scale(1.0f / cohesionCount);
+        cohesion.scale(COHESION_WEIGHT);
+        Vector2D desired = cohesion.copy();
+        desired.sub(mPosition);
+        float d = desired.magnitude();
+        if (d > 0) {
+            desired.normalize();
+            desired.scale(MAX_SPEED * ((d < 100.0f) ? d / 100.0f : 1));
+            desired.sub(mVelocity);
+            desired.limit(MAX_FORCE);
+            mAcceleration.add(desired);
+        }
+    }
+
+    mVelocity.add(mAcceleration);
+    mVelocity.limit(MAX_SPEED);
+    mPosition.add(mVelocity);
+    // Wrap around.
+    if (mPosition.mX < -limitX) {
+        mPosition.mX = limitX;
+    } else if (mPosition.mX > limitX) {
+        mPosition.mX = -limitX;
+    }
+    if (mPosition.mY < -limitY) {
+        mPosition.mY = limitY;
+    } else if (mPosition.mY > limitY) {
+        mPosition.mY = -limitY;
+    }
+}
diff --git a/suite/pts/deviceTests/opengl/jni/reference/scene/flocking/Boid.h b/suite/pts/deviceTests/opengl/jni/reference/scene/flocking/Boid.h
new file mode 100644
index 0000000..955b891
--- /dev/null
+++ b/suite/pts/deviceTests/opengl/jni/reference/scene/flocking/Boid.h
@@ -0,0 +1,36 @@
+/*
+ * 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.
+ */
+// An implementation of Craig Reynold's Boid Simulation.
+#ifndef BOID_H
+#define BOID_H
+
+#include <graphics/Vector2D.h>
+
+class Boid {
+public:
+    Boid(float x, float y);
+    void resetAcceleration();
+    void flock(const Boid* boids[], int numBoids, int index, float limitX, float limitY);
+    static const float MAX_SPEED = 2.0f;
+    static const float MAX_FORCE = 0.05f;
+    static const float NEIGHBOUR_RADIUS = 70.0f;//50
+    static const float DESIRED_BOID_DIST = 30.0f;//25
+    static const float SEPARATION_WEIGHT = 2.0f;
+    static const float ALIGNMENT_WEIGHT = 1.0f;
+    static const float COHESION_WEIGHT = 1.0f;
+    Vector2D mPosition;
+    Vector2D mVelocity;
+    Vector2D mAcceleration;
+};
+#endif
diff --git a/suite/pts/deviceTests/opengl/jni/reference/scene/flocking/FlockingScene.cpp b/suite/pts/deviceTests/opengl/jni/reference/scene/flocking/FlockingScene.cpp
new file mode 100644
index 0000000..933891a
--- /dev/null
+++ b/suite/pts/deviceTests/opengl/jni/reference/scene/flocking/FlockingScene.cpp
@@ -0,0 +1,211 @@
+/*
+ * 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 "FlockingScene.h"
+
+#include <cstdlib>
+
+#include <Trace.h>
+
+#include <graphics/BasicMeshNode.h>
+#include <graphics/BasicProgram.h>
+#include <graphics/GLUtils.h>
+#include <graphics/Matrix.h>
+#include <graphics/Mesh.h>
+#include <graphics/ProgramNode.h>
+#include <graphics/TransformationNode.h>
+
+static const int FS_NUM_VERTICES = 6;
+
+static const float FS_VERTICES[FS_NUM_VERTICES * 3] = {
+        1.0f, 1.0f, 0.0f,
+        -1.0f, 1.0f, 0.0f,
+        -1.0f, -1.0f, 0.0f,
+        -1.0f, -1.0f, 0.0f,
+        1.0f, -1.0f, 0.0f,
+        1.0f, 1.0f, 0.0f };
+
+static const float FS_NORMALS[FS_NUM_VERTICES * 3] = {
+        0.0f, 0.0f, 1.0f,
+        0.0f, 0.0f, 1.0f,
+        0.0f, 0.0f, 1.0f,
+        0.0f, 0.0f, 1.0f,
+        0.0f, 0.0f, 1.0f,
+        0.0f, 0.0f, 1.0f };
+
+static const float FS_TEX_COORDS[FS_NUM_VERTICES * 2] = {
+        1.0f, 1.0f,
+        0.0f, 1.0f,
+        0.0f, 0.0f,
+        0.0f, 0.0f,
+        1.0f, 0.0f,
+        1.0f, 1.0f };
+
+static const char* FS_VERTEX =
+        "uniform mat4 u_MVPMatrix;"
+        "uniform mat4 u_MVMatrix;"
+        "attribute vec4 a_Position;"
+        "attribute vec3 a_Normal;"
+        "attribute vec2 a_TexCoordinate;"
+        "varying vec3 v_Position;"
+        "varying vec3 v_Normal;"
+        "varying vec2 v_TexCoordinate;"
+        "void main() {\n"
+        "  // Transform the vertex into eye space.\n"
+        "  v_Position = vec3(u_MVMatrix * a_Position);\n"
+        "  // Pass through the texture coordinate.\n"
+        "  v_TexCoordinate = a_TexCoordinate;\n"
+        "  // Transform the normal\'s orientation into eye space.\n"
+        "  v_Normal = vec3(u_MVMatrix * vec4(a_Normal, 0.0));\n"
+        "  // Multiply to get the final point in normalized screen coordinates.\n"
+        "  gl_Position = u_MVPMatrix * a_Position;\n"
+        "}";
+
+static const char* FS_FRAGMENT =
+        "precision mediump float;"
+        "uniform vec3 u_LightPos;"
+        "uniform sampler2D u_Texture;"
+        "varying vec3 v_Position;"
+        "varying vec3 v_Normal;"
+        "varying vec2 v_TexCoordinate;"
+        "void main() {\n"
+        "  // Will be used for attenuation.\n"
+        "  float distance = length(u_LightPos - v_Position);\n"
+        "  // Get a lighting direction vector from the light to the vertex.\n"
+        "  vec3 lightVector = normalize(u_LightPos - v_Position);\n"
+        "  // Calculate the dot product of the light vector and vertex normal.\n"
+        "  float diffuse = max(dot(v_Normal, lightVector), 0.0);\n"
+        "  // Add attenuation.\n"
+        "  diffuse = diffuse * (1.0 / (1.0 + (0.01 * distance)));\n"
+        "  // Add ambient lighting\n"
+        "  diffuse = diffuse + 0.25;\n"
+        "  // Multiply the diffuse illumination and texture to get final output color.\n"
+        "  gl_FragColor = (diffuse * texture2D(u_Texture, v_TexCoordinate));\n"
+        "}";
+
+FlockingScene::FlockingScene(int width, int height) :
+        Scene(width, height) {
+    for (int i = 0; i < NUM_BOIDS; i++) {
+        // Generate a boid with a random position.
+        float x = ((rand() % 10) / 5.0f) - 0.1f;
+        float y = ((rand() % 10) / 5.0f) - 0.1f;
+        mBoids[i] = new Boid(x, y);
+    }
+}
+
+Program* FlockingScene::setUpProgram() {
+    // TODO Enable loading programs from file.
+    // mProgramId = GLUtils::loadProgram("flocking");
+    GLuint programId = GLUtils::createProgram(&FS_VERTEX, &FS_FRAGMENT);
+    if (programId == 0) {
+        return NULL;
+    }
+    return new BasicProgram(programId);
+}
+
+Matrix* FlockingScene::setUpModelMatrix() {
+    return new Matrix();
+}
+
+Matrix* FlockingScene::setUpViewMatrix() {
+    // Position the eye in front of the origin.
+    float eyeX = 0.0f;
+    float eyeY = 0.0f;
+    float eyeZ = 2.0f;
+
+    // We are looking at the origin
+    float centerX = 0.0f;
+    float centerY = 0.0f;
+    float centerZ = 0.0f;
+
+    // Set our up vector.
+    float upX = 0.0f;
+    float upY = 1.0f;
+    float upZ = 0.0f;
+
+    // Set the view matrix.
+    return Matrix::newLookAt(eyeX, eyeY, eyeZ, centerX, centerY, centerZ, upX, upY, upZ);
+}
+
+Matrix* FlockingScene::setUpProjectionMatrix() {
+    // Create a new perspective projection matrix. The height will stay the same
+    // while the width will vary as per aspect ratio.
+    mDisplayRatio = ((float) mWidth) / ((float) mHeight);
+    mBoardHeight = 1000.0f;
+    mBoardWidth = mDisplayRatio * mBoardHeight;
+    float left = -mDisplayRatio;
+    float right = mDisplayRatio;
+    float bottom = -1.0f;
+    float top = 1.0f;
+    float near = 1.0f;
+    float far = 3.0f;
+    // Set board dimensions
+
+    return Matrix::newFrustum(left, right, bottom, top, near, far);
+}
+
+bool FlockingScene::setUpTextures() {
+    SCOPED_TRACE();
+    mTextureIds.add(GLUtils::genTexture(256, 256, GLUtils::RANDOM_FILL));
+    mTextureIds.add(GLUtils::genTexture(1, 1, 0xc0c0c0));
+    // TODO Enable loading textures from file.
+    // mTextureIds.add(GLUtils::loadTexture("knight.jpg"));
+    return true;
+}
+
+bool FlockingScene::setUpMeshes() {
+    SCOPED_TRACE();
+    mMeshes.add(new Mesh(FS_VERTICES, FS_NORMALS, FS_TEX_COORDS, FS_NUM_VERTICES));
+    // TODO Enable loading meshes from file.
+    // mMeshes.add(GLUtils::loadMesh("knight.obj", mTextureIds[0]));
+    return true;
+}
+
+bool FlockingScene::tearDown() {
+    SCOPED_TRACE();
+    for (int i = 0; i < NUM_BOIDS; i++) {
+        delete mBoids[i];
+    }
+    return Scene::tearDown();
+}
+
+SceneGraphNode* FlockingScene::updateSceneGraph() {
+    const float MAIN_SCALE = 2.0f; // Scale up as the camera is far away.
+    const float LIMIT_X = mBoardWidth / 2.0f;
+    const float LIMIT_Y = mBoardHeight / 2.0f;
+    SceneGraphNode* sceneGraph = new ProgramNode();
+    Matrix* transformMatrix = Matrix::newScale(MAIN_SCALE * mDisplayRatio, MAIN_SCALE, MAIN_SCALE);
+    TransformationNode* transformNode = new TransformationNode(transformMatrix);
+    sceneGraph->addChild(transformNode);
+    BasicMeshNode* meshNode = new BasicMeshNode(mMeshes[0], mTextureIds[1]);
+    transformNode->addChild(meshNode);
+    for (int i = 0; i < NUM_BOIDS; i++) {
+        Boid* b = mBoids[i];
+        b->flock((const Boid**) &mBoids, NUM_BOIDS, i, LIMIT_X, LIMIT_Y);
+        Vector2D* pos = &(b->mPosition);
+        Vector2D* vel = &(b->mVelocity);
+
+        // Normalize to (-1,1)
+        float x = pos->mX / (LIMIT_X * BOID_SCALE) * mDisplayRatio;
+        float y = pos->mY / (LIMIT_Y * BOID_SCALE);
+
+        // TODO need to include rotation.
+        transformMatrix = Matrix::newScale(BOID_SCALE * MAIN_SCALE, BOID_SCALE * MAIN_SCALE, 1.0f);
+        transformMatrix->translate(x, y, 0.01f);
+        transformNode = new TransformationNode(transformMatrix);
+        sceneGraph->addChild(transformNode);
+        meshNode = new BasicMeshNode(mMeshes[0], mTextureIds[0]);
+        transformNode->addChild(meshNode);
+    }
+    return sceneGraph;
+}
diff --git a/suite/pts/deviceTests/opengl/jni/reference/scene/flocking/FlockingScene.h b/suite/pts/deviceTests/opengl/jni/reference/scene/flocking/FlockingScene.h
new file mode 100644
index 0000000..6433f94
--- /dev/null
+++ b/suite/pts/deviceTests/opengl/jni/reference/scene/flocking/FlockingScene.h
@@ -0,0 +1,41 @@
+/*
+ * 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.
+ */
+#ifndef FLOCKINGSCENE_H
+#define FLOCKINGSCENE_H
+
+#include "../Scene.h"
+#include "Boid.h"
+
+class FlockingScene : public Scene {
+public:
+    FlockingScene(int width, int height);
+    virtual ~FlockingScene() {};
+    bool setUpTextures();
+    bool setUpMeshes();
+    bool tearDown();
+    static const int NUM_BOIDS = 100;
+protected:
+    Program* setUpProgram();
+    Matrix* setUpModelMatrix();
+    Matrix* setUpViewMatrix();
+    Matrix* setUpProjectionMatrix();
+    SceneGraphNode* updateSceneGraph();
+private:
+    Boid* mBoids[NUM_BOIDS];
+    float mDisplayRatio;
+    float mBoardWidth;
+    float mBoardHeight;
+    static const float BOID_SCALE = 1.0f / 50.0f;
+};
+#endif
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
index 14b247a..9c56e8e 100644
--- 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
@@ -31,13 +31,16 @@
  */
 public class GLReferenceBenchmark extends PtsActivityInstrumentationTestCase2<GLReferenceActivity> {
 
-    private static final int NUM_FRAMES = 100;
+    private static final int NUM_FRAMES_PER_SCENE = 500;
+    private static final int NUM_SCENES = 1;
+    private static final int NUM_FRAMES = NUM_FRAMES_PER_SCENE * NUM_SCENES;
     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.
+    private static final double NEXUS_REF_UI_LOAD = 39.67f;// Milliseconds.
+    // (GL, Context, Textures, Meshes).
+    private static final double[] NEXUS_REF_SET_UP = {22.58f, 44.49f, 2.47f, 0.02f};// MS.
+    private static final double NEXUS_REF_UPDATE_AVG = 9.8f;// MS.
+    private static final double NEXUS_REF_RENDER_AVG = 0.44f;// Fraction of display refresh rate.
 
     public GLReferenceBenchmark() {
         super(GLReferenceActivity.class);
@@ -117,10 +120,16 @@
                             "Set Up Score", setUpScore, ResultType.HIGHER_BETTER, ResultUnit.SCORE);
                     getReportLog().printArray(
                             "Update Times", updateTimes, ResultType.LOWER_BETTER, ResultUnit.MS);
+                    getReportLog().printValue(
+                            "Update Time Average", updateAverage, 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 Time Average", renderAverage, ResultType.LOWER_BETTER,
+                            ResultUnit.MS);
                     getReportLog().printValue("Render Score", renderScore, ResultType.HIGHER_BETTER,
                             ResultUnit.SCORE);
                     getReportLog().printValue(
diff --git a/tests/accessibilityservice/res/xml/accessibilityservice.xml b/tests/accessibilityservice/res/xml/accessibilityservice.xml
index 69e0651..6d48f9b 100644
--- a/tests/accessibilityservice/res/xml/accessibilityservice.xml
+++ b/tests/accessibilityservice/res/xml/accessibilityservice.xml
@@ -18,6 +18,6 @@
     android:accessibilityFeedbackType="feedbackGeneric"
     android:accessibilityFlags="flagDefault|flagRequestTouchExplorationMode"
     android:canRetrieveWindowContent="true"
-    android:notificationTimeout="50"
+    android:notificationTimeout="0"
     android:settingsActivity="android.accessibilityservice.delegate.SomeActivity"
     android:description="@string/title_delegating_accessibility_service" />
diff --git a/tests/src/android/renderscript/cts/global_sync.rs b/tests/src/android/renderscript/cts/global_sync.rs
new file mode 100644
index 0000000..c947fa2
--- /dev/null
+++ b/tests/src/android/renderscript/cts/global_sync.rs
@@ -0,0 +1,32 @@
+#pragma version(1)
+#pragma rs java_package_name(android.renderscript.cts)
+
+int gInt;
+static int sInt;
+
+rs_allocation aFailed;
+
+void test_global(int expected) {
+    if (gInt != expected) {
+        rsSetElementAt_uchar(aFailed, 1, 0);
+    }
+}
+
+void test_static_global(int expected) {
+    if (sInt != expected) {
+        rsSetElementAt_uchar(aFailed, 1, 0);
+    }
+}
+
+void __attribute__((kernel)) write_global(int ain, uint32_t x) {
+    if (x == 0) {
+        gInt = ain;
+    }
+}
+
+void __attribute__((kernel)) write_static_global(int ain, uint32_t x) {
+    if (x == 0) {
+        sInt = ain;
+    }
+}
+
diff --git a/tests/src/android/renderscript/cts/large_global.rs b/tests/src/android/renderscript/cts/large_global.rs
new file mode 100644
index 0000000..3f2da69
--- /dev/null
+++ b/tests/src/android/renderscript/cts/large_global.rs
@@ -0,0 +1,24 @@
+// 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.
+
+#pragma version(1)
+#pragma rs java_package_name(android.renderscript.cts)
+
+char buf[2*1024*1024];
+
+// Never called, just present to ensure that buf does not get optimized away.
+void __attribute__((kernel)) root(char c) {
+    buf[0] = c;
+}
+
diff --git a/tests/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityActivityTestCase.java b/tests/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityActivityTestCase.java
index a5d92ee..affc9ec 100644
--- a/tests/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityActivityTestCase.java
+++ b/tests/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityActivityTestCase.java
@@ -66,7 +66,7 @@
     /**
      * The timeout after the last accessibility event to consider the device idle.
      */
-    public static final long TIMEOUT_ACCESSIBILITY_STATE_IDLE = 100;
+    public static final long TIMEOUT_ACCESSIBILITY_STATE_IDLE = 200;
 
     /**
      * Instance for detecting the next accessibility event.
@@ -130,9 +130,12 @@
             public boolean accept(AccessibilityEvent event) {
                 final int eventType = event.getEventType();
                 CharSequence packageName = event.getPackageName();
-                Context targetContext = getInstrumentation().getTargetContext();
-                return (eventType == AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED
-                        && targetContext.getPackageName().equals(packageName));
+                // Do not check the package name since an event of this type may
+                // come concurrently from the app and from the IME (since input
+                // focus goes to the first focusable) but we dispatch one event
+                // of each type within a timeout. Hence, sometimes the window
+                // change event from the IME may override the one from the app.
+                return (eventType == AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED);
             }
         },
         TIMEOUT_ASYNC_PROCESSING);
@@ -520,6 +523,8 @@
                 mEventQueue.clear();
                 // Prepare to wait for an event.
                 mWaitingForEventDelivery = true;
+                // We will ignore events from previous interactions.
+                final long executionStartTimeMillis = SystemClock.uptimeMillis();
                 // Execute the command.
                 command.run();
                 try {
@@ -529,11 +534,16 @@
                         // Drain the event queue
                         while (!mEventQueue.isEmpty()) {
                             AccessibilityEvent event = mEventQueue.remove(0);
+
+                            // Ignore events from previous interactions.
+                            if (event.getEventTime() < executionStartTimeMillis) {
+                                continue;
+                            }
                             if (filter.accept(event)) {
                                 return event;
-                            } else {
-                                event.recycle();
                             }
+                            
+                            event.recycle();
                         }
                         // Check if timed out and if not wait.
                         final long elapsedTimeMillis = SystemClock.uptimeMillis() - startTimeMillis;
diff --git a/tests/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityServiceInfoTest.java b/tests/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityServiceInfoTest.java
index 1d28470..ad2dca4 100644
--- a/tests/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityServiceInfoTest.java
+++ b/tests/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityServiceInfoTest.java
@@ -113,7 +113,7 @@
         assertSame(AccessibilityServiceInfo.DEFAULT
                 | AccessibilityServiceInfo.FLAG_REQUEST_TOUCH_EXPLORATION_MODE,
                 speakingService.flags);
-        assertSame(50l, speakingService.notificationTimeout);
+        assertSame(0l, speakingService.notificationTimeout);
         assertEquals("Delegating Accessibility Service", speakingService.getDescription());
         assertNull(speakingService.packageNames /*all packages*/);
         assertNotNull(speakingService.getId());
diff --git a/tests/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityTextTraversalTest.java b/tests/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityTextTraversalTest.java
index 17c7ebd..c8f8a48 100644
--- a/tests/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityTextTraversalTest.java
+++ b/tests/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityTextTraversalTest.java
@@ -1246,6 +1246,261 @@
     }
 
     @MediumTest
+    public void testActionNextAndPreviousAtGranularityWordOverEditTextWithContentDescription()
+            throws Exception {
+
+        final EditText editText = (EditText) getActivity().findViewById(R.id.edit);
+
+        getInstrumentation().runOnMainSync(new Runnable() {
+            @Override
+            public void run() {
+                editText.setText(getString(R.string.foo_bar_baz));
+                editText.setContentDescription(getString(R.string.android_wiki));
+            }
+        });
+
+        final AccessibilityNodeInfo text = getInteractionBridge()
+               .findAccessibilityNodeInfoByTextFromRoot(getString(R.string.foo_bar_baz));
+
+        final int granularities = text.getMovementGranularities();
+        assertEquals(granularities, AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER
+                | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD
+                | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_LINE
+                | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PARAGRAPH
+                | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PAGE);
+
+        final Bundle arguments = new Bundle();
+        arguments.putInt(AccessibilityNodeInfo.ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT,
+                AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD);
+
+        // Move to the next word and wait for an event.
+        AccessibilityEvent firstExpected = getInteractionBridge()
+                .executeCommandAndWaitForAccessibilityEvent(new Runnable() {
+            @Override
+            public void run() {
+                getInteractionBridge().performAction(text,
+                        AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY, arguments);
+            }
+        }, new AccessibilityEventFilter() {
+            @Override
+            public boolean accept(AccessibilityEvent event) {
+                return
+                (event.getEventType() ==
+                    AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
+                        && event.getAction() ==
+                                AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY
+                        && event.getPackageName().equals(getActivity().getPackageName())
+                        && event.getClassName().equals(EditText.class.getName())
+                        && event.getText().size() > 0
+                        && event.getText().get(0).toString().equals(getString(R.string.foo_bar_baz))
+                        && event.getContentDescription().equals(getString(R.string.android_wiki))
+                        && event.getFromIndex() == 0
+                        && event.getToIndex() == 3
+                        && event.getMovementGranularity() ==
+                                AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD);
+            }
+        }, TIMEOUT_ASYNC_PROCESSING);
+
+        // Make sure we got the expected event.
+        assertNotNull(firstExpected);
+
+        // Verify the selection position.
+        assertEquals(3, editText.getSelectionStart());
+        assertEquals(3, editText.getSelectionEnd());
+
+        // Move to the next word and wait for an event.
+        AccessibilityEvent secondExpected = getInteractionBridge()
+                .executeCommandAndWaitForAccessibilityEvent(new Runnable() {
+            @Override
+            public void run() {
+                getInteractionBridge().performAction(text,
+                        AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY, arguments);
+            }
+        }, new AccessibilityEventFilter() {
+            @Override
+            public boolean accept(AccessibilityEvent event) {
+                return
+                (event.getEventType() ==
+                    AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
+                        && event.getAction() ==
+                                AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY
+                        && event.getPackageName().equals(getActivity().getPackageName())
+                        && event.getClassName().equals(EditText.class.getName())
+                        && event.getText().size() > 0
+                        && event.getText().get(0).toString().equals(getString(R.string.foo_bar_baz))
+                        && event.getContentDescription().equals(getString(R.string.android_wiki))
+                        && event.getFromIndex() == 4
+                        && event.getToIndex() == 7
+                        && event.getMovementGranularity() ==
+                                AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD);
+            }
+        }, TIMEOUT_ASYNC_PROCESSING);
+
+        // Make sure we got the expected event.
+        assertNotNull(secondExpected);
+
+        // Verify the selection position.
+        assertEquals(7, editText.getSelectionStart());
+        assertEquals(7, editText.getSelectionEnd());
+
+        // Move to the next word and wait for an event.
+        AccessibilityEvent thirdExpected = getInteractionBridge()
+                .executeCommandAndWaitForAccessibilityEvent(new Runnable() {
+            @Override
+            public void run() {
+                getInteractionBridge().performAction(text,
+                        AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY, arguments);
+            }
+        }, new AccessibilityEventFilter() {
+            @Override
+            public boolean accept(AccessibilityEvent event) {
+                return
+                (event.getEventType() ==
+                    AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
+                        && event.getAction() ==
+                                AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY
+                        && event.getPackageName().equals(getActivity().getPackageName())
+                        && event.getClassName().equals(EditText.class.getName())
+                        && event.getText().size() > 0
+                        && event.getText().get(0).toString().equals(getString(R.string.foo_bar_baz))
+                        && event.getContentDescription().equals(getString(R.string.android_wiki))
+                        && event.getFromIndex() == 8
+                        && event.getToIndex() == 11
+                        && event.getMovementGranularity() ==
+                                 AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD);
+            }
+        }, TIMEOUT_ASYNC_PROCESSING);
+
+        // Make sure we got the expected event.
+        assertNotNull(thirdExpected);
+
+        // Verify the selection position.
+        assertEquals(11, editText.getSelectionStart());
+        assertEquals(11, editText.getSelectionEnd());
+
+        // Make sure there is no next.
+        assertFalse(getInteractionBridge().performAction(text,
+                AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY, arguments));
+
+        // Verify the selection position.
+        assertEquals(11, editText.getSelectionStart());
+        assertEquals(11, editText.getSelectionEnd());
+
+        // Move to the next word and wait for an event.
+        AccessibilityEvent fourthExpected = getInteractionBridge()
+                .executeCommandAndWaitForAccessibilityEvent(new Runnable() {
+            @Override
+            public void run() {
+                getInteractionBridge().performAction(text,
+                        AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY, arguments);
+            }
+        }, new AccessibilityEventFilter() {
+            @Override
+            public boolean accept(AccessibilityEvent event) {
+                return
+                (event.getEventType() ==
+                    AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
+                        && event.getAction() ==
+                                AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY
+                        && event.getPackageName().equals(getActivity().getPackageName())
+                        && event.getClassName().equals(EditText.class.getName())
+                        && event.getText().size() > 0
+                        && event.getText().get(0).toString().equals(getString(R.string.foo_bar_baz))
+                        && event.getContentDescription().equals(getString(R.string.android_wiki))
+                        && event.getFromIndex() == 8
+                        && event.getToIndex() == 11
+                        && event.getMovementGranularity() ==
+                                AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD);
+            }
+        }, TIMEOUT_ASYNC_PROCESSING);
+
+        // Make sure we got the expected event.
+        assertNotNull(fourthExpected);
+
+        // Verify the selection position.
+        assertEquals(8, editText.getSelectionStart());
+        assertEquals(8, editText.getSelectionEnd());
+
+        // Move to the next word and wait for an event.
+        AccessibilityEvent fifthExpected = getInteractionBridge()
+                .executeCommandAndWaitForAccessibilityEvent(new Runnable() {
+            @Override
+            public void run() {
+                getInteractionBridge().performAction(text,
+                        AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY, arguments);
+            }
+        }, new AccessibilityEventFilter() {
+            @Override
+            public boolean accept(AccessibilityEvent event) {
+                return
+                (event.getEventType() ==
+                    AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
+                        && event.getAction() ==
+                                AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY
+                        && event.getPackageName().equals(getActivity().getPackageName())
+                        && event.getClassName().equals(EditText.class.getName())
+                        && event.getText().size() > 0
+                        && event.getText().get(0).toString().equals(getString(R.string.foo_bar_baz))
+                        && event.getContentDescription().equals(getString(R.string.android_wiki))
+                        && event.getFromIndex() == 4
+                        && event.getToIndex() == 7
+                        && event.getMovementGranularity() ==
+                                AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD);
+            }
+        }, TIMEOUT_ASYNC_PROCESSING);
+
+        // Make sure we got the expected event.
+        assertNotNull(fifthExpected);
+
+        // Verify the selection position.
+        assertEquals(4, editText.getSelectionStart());
+        assertEquals(4, editText.getSelectionEnd());
+
+        // Move to the next character and wait for an event.
+        AccessibilityEvent sixthExpected = getInteractionBridge()
+                .executeCommandAndWaitForAccessibilityEvent(new Runnable() {
+            @Override
+            public void run() {
+                getInteractionBridge().performAction(text,
+                        AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY, arguments);
+            }
+        }, new AccessibilityEventFilter() {
+            @Override
+            public boolean accept(AccessibilityEvent event) {
+                return
+                (event.getEventType() ==
+                    AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
+                        && event.getAction() ==
+                                AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY
+                        && event.getPackageName().equals(getActivity().getPackageName())
+                        && event.getClassName().equals(EditText.class.getName())
+                        && event.getText().size() > 0
+                        && event.getText().get(0).toString().equals(getString(R.string.foo_bar_baz))
+                        && event.getContentDescription().equals(getString(R.string.android_wiki))
+                        && event.getFromIndex() == 0
+                        && event.getToIndex() == 3
+                        && event.getMovementGranularity() ==
+                                AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD);
+            }
+        }, TIMEOUT_ASYNC_PROCESSING);
+
+        // Make sure we got the expected event.
+        assertNotNull(sixthExpected);
+
+        // Verify the selection position.
+        assertEquals(0, editText.getSelectionStart());
+        assertEquals(0, editText.getSelectionEnd());
+
+        // Make sure there is no previous.
+        assertFalse(getInteractionBridge().performAction(text,
+                AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY, arguments));
+
+        // Verify the selection position.
+        assertEquals(0, editText.getSelectionStart());
+        assertEquals(0, editText.getSelectionEnd());
+    }
+    
+    @MediumTest
     public void testActionNextAndPreviousAtGranularityWordOverTextExtend() throws Exception {
         final EditText editText = (EditText) getActivity().findViewById(R.id.edit);
 
diff --git a/tests/tests/media/res/raw/loudsoftaac.aac b/tests/tests/media/res/raw/loudsoftaac.aac
new file mode 100644
index 0000000..1534ef2
--- /dev/null
+++ b/tests/tests/media/res/raw/loudsoftaac.aac
Binary files differ
diff --git a/tests/tests/media/res/raw/loudsoftfaac.m4a b/tests/tests/media/res/raw/loudsoftfaac.m4a
new file mode 100644
index 0000000..b4895b5
--- /dev/null
+++ b/tests/tests/media/res/raw/loudsoftfaac.m4a
Binary files differ
diff --git a/tests/tests/media/res/raw/loudsoftitunes.m4a b/tests/tests/media/res/raw/loudsoftitunes.m4a
new file mode 100644
index 0000000..b01b36b
--- /dev/null
+++ b/tests/tests/media/res/raw/loudsoftitunes.m4a
Binary files differ
diff --git a/tests/tests/media/res/raw/loudsoftmp3.mp3 b/tests/tests/media/res/raw/loudsoftmp3.mp3
new file mode 100644
index 0000000..b32c8bd
--- /dev/null
+++ b/tests/tests/media/res/raw/loudsoftmp3.mp3
Binary files differ
diff --git a/tests/tests/media/res/raw/loudsoftogg.ogg b/tests/tests/media/res/raw/loudsoftogg.ogg
new file mode 100644
index 0000000..dc122d9
--- /dev/null
+++ b/tests/tests/media/res/raw/loudsoftogg.ogg
Binary files differ
diff --git a/tests/tests/media/res/raw/loudsoftwav.wav b/tests/tests/media/res/raw/loudsoftwav.wav
new file mode 100644
index 0000000..9930dcb
--- /dev/null
+++ b/tests/tests/media/res/raw/loudsoftwav.wav
Binary files differ
diff --git a/tests/tests/media/src/android/media/cts/DecoderTest.java b/tests/tests/media/src/android/media/cts/DecoderTest.java
index 54a670d..ab7410b 100644
--- a/tests/tests/media/src/android/media/cts/DecoderTest.java
+++ b/tests/tests/media/src/android/media/cts/DecoderTest.java
@@ -30,17 +30,37 @@
 import java.io.IOException;
 import java.io.InputStream;
 import java.nio.ByteBuffer;
+import java.util.Arrays;
 import java.util.zip.CRC32;
 
 public class DecoderTest extends MediaPlayerTestBase {
     private static final String TAG = "DecoderTest";
 
     private Resources mResources;
+    short[] mMasterBuffer;
 
     @Override
     protected void setUp() throws Exception {
         super.setUp();
         mResources = mContext.getResources();
+
+        // read master file into memory
+        AssetFileDescriptor masterFd = mResources.openRawResourceFd(R.raw.sinesweepraw);
+        long masterLength = masterFd.getLength();
+        mMasterBuffer = new short[(int) (masterLength / 2)];
+        InputStream is = masterFd.createInputStream();
+        BufferedInputStream bis = new BufferedInputStream(is);
+        for (int i = 0; i < mMasterBuffer.length; i++) {
+            int lo = bis.read();
+            int hi = bis.read();
+            if (hi >= 128) {
+                hi -= 256;
+            }
+            int sample = hi * 256 + lo;
+            mMasterBuffer[i] = (short) sample;
+        }
+        bis.close();
+        masterFd.close();
     }
 
     // The allowed errors in the following tests are the actual maximum measured
@@ -48,22 +68,22 @@
     // This should allow for some variation in decoders, while still detecting
     // phase and delay errors, channel swap, etc.
     public void testDecodeMp3Lame() throws Exception {
-        decode(R.raw.sinesweepmp3lame, R.raw.sinesweepraw, 804.f);
+        decode(R.raw.sinesweepmp3lame, 804.f);
     }
     public void testDecodeMp3Smpb() throws Exception {
-        decode(R.raw.sinesweepmp3smpb, R.raw.sinesweepraw, 413.f);
+        decode(R.raw.sinesweepmp3smpb, 413.f);
     }
     public void testDecodeM4a() throws Exception {
-        decode(R.raw.sinesweepm4a, R.raw.sinesweepraw, 124.f);
+        decode(R.raw.sinesweepm4a, 124.f);
     }
     public void testDecodeOgg() throws Exception {
-        decode(R.raw.sinesweepogg, R.raw.sinesweepraw, 168.f);
+        decode(R.raw.sinesweepogg, 168.f);
     }
     public void testDecodeWav() throws Exception {
-        decode(R.raw.sinesweepwav, R.raw.sinesweepraw, 0.0f);
+        decode(R.raw.sinesweepwav, 0.0f);
     }
     public void testDecodeFlac() throws Exception {
-        decode(R.raw.sinesweepflac, R.raw.sinesweepraw, 0.0f);
+        decode(R.raw.sinesweepflac, 0.0f);
     }
 
     /**
@@ -72,25 +92,30 @@
      * @param maxerror the maximum allowed root mean squared error
      * @throws IOException
      */
-    private void decode(int testinput, int master, float maxerror) throws IOException {
+    private void decode(int testinput, float maxerror) throws IOException {
 
-        // read master file into memory
-        AssetFileDescriptor masterFd = mResources.openRawResourceFd(master);
-        long masterLength = masterFd.getLength();
-        short[] masterBuffer = new short[(int) (masterLength / 2)];
-        InputStream is = masterFd.createInputStream();
-        BufferedInputStream bis = new BufferedInputStream(is);
-        for (int i = 0; i < masterBuffer.length; i++) {
-            int lo = bis.read();
-            int hi = bis.read();
-            if (hi >= 128) {
-                hi -= 256;
-            }
-            int sample = hi * 256 + lo;
-            masterBuffer[i] = (short) sample;
+        short [] decoded = decodeToMemory(testinput);
+
+        assertEquals("wrong data size", mMasterBuffer.length, decoded.length);
+
+        long totalErrorSquared = 0;
+
+        for (int i = 0; i < decoded.length; i++) {
+            short sample = decoded[i];
+            short mastersample = mMasterBuffer[i];
+            int d = sample - mastersample;
+            totalErrorSquared += d * d;
         }
-        bis.close();
-        masterFd.close();
+
+        long avgErrorSquared = (totalErrorSquared / decoded.length);
+        double rmse = Math.sqrt(avgErrorSquared);
+        assertTrue("decoding error too big: " + rmse, rmse <= maxerror);
+     }
+
+    private short[] decodeToMemory(int testinput) throws IOException {
+
+        short [] decoded = new short[1024];
+        int decodedIdx = 0;
 
         AssetFileDescriptor testFd = mResources.openRawResourceFd(testinput);
 
@@ -118,9 +143,6 @@
         extractor.selectTrack(0);
 
         // start decoding
-        int numBytesDecoded = 0;
-        int maxdelta = 0;
-        long totalErrorSquared = 0;
         final long kTimeOutUs = 5000;
         MediaCodec.BufferInfo info = new MediaCodec.BufferInfo();
         boolean sawInputEOS = false;
@@ -164,17 +186,13 @@
                 int outputBufIndex = res;
                 ByteBuffer buf = codecOutputBuffers[outputBufIndex];
 
-                // check the waveform matches within the specified max error
-                for (int i = 0; i < info.size; i += 2) {
-                    short sample = buf.getShort(i);
-                    int idx = (numBytesDecoded + i) / 2;
-                    assertTrue("decoder returned too much data", idx < masterBuffer.length);
-                    short mastersample = masterBuffer[idx];
-                    int d = sample - mastersample;
-                    totalErrorSquared += d * d;
+                if (decodedIdx + (info.size / 2) >= decoded.length) {
+                    decoded = Arrays.copyOf(decoded, decodedIdx + (info.size / 2));
                 }
 
-                numBytesDecoded += info.size;
+                for (int i = 0; i < info.size; i += 2) {
+                    decoded[decodedIdx++] = buf.getShort(i);
+                }
 
                 codec.releaseOutputBuffer(outputBufIndex, false /* render */);
 
@@ -195,11 +213,7 @@
 
         codec.stop();
         codec.release();
-
-        assertEquals("wrong data size", masterLength, numBytesDecoded);
-        long avgErrorSquared = (totalErrorSquared / (numBytesDecoded / 2));
-        double rmse = Math.sqrt(avgErrorSquared); 
-        assertTrue("decoding error too big: " + rmse, rmse <= maxerror);
+        return decoded;
     }
 
     public void testCodecBasicH264() throws Exception {
@@ -691,5 +705,110 @@
         return crc.getValue();
     }
 
+    public void testFlush() throws Exception {
+        testFlush(R.raw.loudsoftwav);
+        testFlush(R.raw.loudsoftogg);
+        testFlush(R.raw.loudsoftmp3);
+        testFlush(R.raw.loudsoftaac);
+        testFlush(R.raw.loudsoftfaac);
+        testFlush(R.raw.loudsoftitunes);
+    }
+
+    private void testFlush(int resource) throws Exception {
+
+        AssetFileDescriptor testFd = mResources.openRawResourceFd(resource);
+
+        MediaExtractor extractor;
+        MediaCodec codec;
+        ByteBuffer[] codecInputBuffers;
+        ByteBuffer[] codecOutputBuffers;
+
+        extractor = new MediaExtractor();
+        extractor.setDataSource(testFd.getFileDescriptor(), testFd.getStartOffset(),
+                testFd.getLength());
+        testFd.close();
+
+        assertEquals("wrong number of tracks", 1, extractor.getTrackCount());
+        MediaFormat format = extractor.getTrackFormat(0);
+        String mime = format.getString(MediaFormat.KEY_MIME);
+        assertTrue("not an audio file", mime.startsWith("audio/"));
+
+        codec = MediaCodec.createDecoderByType(mime);
+        codec.configure(format, null /* surface */, null /* crypto */, 0 /* flags */);
+        codec.start();
+        codecInputBuffers = codec.getInputBuffers();
+        codecOutputBuffers = codec.getOutputBuffers();
+
+        extractor.selectTrack(0);
+
+        // decode a bit of the first part of the file, and verify the amplitude
+        short maxvalue1 = getAmplitude(extractor, codec);
+
+        // flush the codec and seek the extractor a different position, then decode a bit more
+        // and check the amplitude
+        extractor.seekTo(8000000, 0);
+        codec.flush();
+        short maxvalue2 = getAmplitude(extractor, codec);
+
+        assertTrue(maxvalue1 > 20000);
+        assertTrue(maxvalue2 < 5000);
+        codec.stop();
+        codec.release();
+
+    }
+    
+    private short getAmplitude(MediaExtractor extractor, MediaCodec codec) {
+        short maxvalue = 0;
+        int numBytesDecoded = 0;
+        final long kTimeOutUs = 5000;
+        ByteBuffer[] codecInputBuffers = codec.getInputBuffers();
+        ByteBuffer[] codecOutputBuffers = codec.getOutputBuffers();
+        MediaCodec.BufferInfo info = new MediaCodec.BufferInfo();
+
+        while(numBytesDecoded < 44100 * 2) {
+            int inputBufIndex = codec.dequeueInputBuffer(kTimeOutUs);
+
+            if (inputBufIndex >= 0) {
+                ByteBuffer dstBuf = codecInputBuffers[inputBufIndex];
+
+                int sampleSize = extractor.readSampleData(dstBuf, 0 /* offset */);
+                long presentationTimeUs = extractor.getSampleTime();
+
+                codec.queueInputBuffer(
+                        inputBufIndex,
+                        0 /* offset */,
+                        sampleSize,
+                        presentationTimeUs,
+                        0 /* flags */);
+
+                extractor.advance();
+            }
+            int res = codec.dequeueOutputBuffer(info, kTimeOutUs);
+
+            if (res >= 0) {
+
+                int outputBufIndex = res;
+                ByteBuffer buf = codecOutputBuffers[outputBufIndex];
+
+                for (int i = 0; i < info.size; i += 2) {
+                    short sample = buf.getShort(i);
+                    if (maxvalue < sample) {
+                        maxvalue = sample;
+                    }
+                    int idx = (numBytesDecoded + i) / 2;
+                }
+
+                numBytesDecoded += info.size;
+
+                codec.releaseOutputBuffer(outputBufIndex, false /* render */);
+            } else if (res == MediaCodec.INFO_OUTPUT_BUFFERS_CHANGED) {
+                codecOutputBuffers = codec.getOutputBuffers();
+            } else if (res == MediaCodec.INFO_OUTPUT_FORMAT_CHANGED) {
+                MediaFormat oformat = codec.getOutputFormat();
+            }
+        }
+        return maxvalue; 
+    }
+    
 }
 
diff --git a/tests/tests/media/src/android/media/cts/MediaMuxerTest.java b/tests/tests/media/src/android/media/cts/MediaMuxerTest.java
index b44321c..42ae7a7 100644
--- a/tests/tests/media/src/android/media/cts/MediaMuxerTest.java
+++ b/tests/tests/media/src/android/media/cts/MediaMuxerTest.java
@@ -295,7 +295,7 @@
      * makes sure the samples match.
      */
     private void verifySamplesMatch(int srcMedia, String testMediaPath,
-            int seekToUs) {
+            int seekToUs) throws IOException {
         AssetFileDescriptor testFd = mResources.openRawResourceFd(srcMedia);
         MediaExtractor extractorSrc = new MediaExtractor();
         extractorSrc.setDataSource(testFd.getFileDescriptor(),
diff --git a/tests/tests/net/src/android/net/cts/ConnectivityManagerTest.java b/tests/tests/net/src/android/net/cts/ConnectivityManagerTest.java
index 4fa69a8..c244159 100644
--- a/tests/tests/net/src/android/net/cts/ConnectivityManagerTest.java
+++ b/tests/tests/net/src/android/net/cts/ConnectivityManagerTest.java
@@ -23,6 +23,7 @@
 import android.content.IntentFilter;
 import android.content.pm.PackageManager;
 import android.net.ConnectivityManager;
+import android.net.NetworkConfig;
 import android.net.NetworkInfo;
 import android.net.NetworkInfo.DetailedState;
 import android.net.NetworkInfo.State;
@@ -30,7 +31,10 @@
 import android.test.AndroidTestCase;
 import android.util.Log;
 
+import java.util.ArrayList;
+import java.util.HashMap;
 import java.util.HashSet;
+import java.util.List;
 import java.util.Set;
 import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.TimeUnit;
@@ -51,6 +55,9 @@
     private ConnectivityManager mCm;
     private WifiManager mWifiManager;
     private PackageManager mPackageManager;
+    private final HashMap<Integer, NetworkConfig> mNetworks =
+            new HashMap<Integer, NetworkConfig>();
+    private final List<Integer>mProtectedNetworks = new ArrayList<Integer>();
 
     @Override
     protected void setUp() throws Exception {
@@ -58,45 +65,115 @@
         mCm = (ConnectivityManager) getContext().getSystemService(Context.CONNECTIVITY_SERVICE);
         mWifiManager = (WifiManager) getContext().getSystemService(Context.WIFI_SERVICE);
         mPackageManager = getContext().getPackageManager();
-    }
 
-    public void testGetNetworkInfo() {
-        assertTrue(mCm.getAllNetworkInfo().length >= MIN_NUM_NETWORK_TYPES);
-        NetworkInfo ni = mCm.getNetworkInfo(TYPE_WIFI);
-        if (ni != null) {
-            State state = ni.getState();
-            assertTrue(State.UNKNOWN.ordinal() >= state.ordinal()
-                       && state.ordinal() >= State.CONNECTING.ordinal());
-            DetailedState ds = ni.getDetailedState();
-            assertTrue(DetailedState.FAILED.ordinal() >= ds.ordinal()
-                       && ds.ordinal() >= DetailedState.IDLE.ordinal());
+        String[] naStrings = getContext().getResources().getStringArray(
+                com.android.internal.R.array.networkAttributes);
+        for (String naString : naStrings) {
+            try {
+                NetworkConfig n = new NetworkConfig(naString);
+                mNetworks.put(n.type, n);
+            } catch (Exception e) {}
         }
-        ni = mCm.getNetworkInfo(TYPE_MOBILE);
-        if (ni != null) {
-            State state = ni.getState();
-            assertTrue(State.UNKNOWN.ordinal() >= state.ordinal()
-                    && state.ordinal() >= State.CONNECTING.ordinal());
-            DetailedState ds = ni.getDetailedState();
-            assertTrue(DetailedState.FAILED.ordinal() >= ds.ordinal()
-                    && ds.ordinal() >= DetailedState.IDLE.ordinal());
+
+        int[] protectedNetworks = getContext().getResources().getIntArray(
+                com.android.internal.R.array.config_protectedNetworks);
+        for (int p : protectedNetworks) {
+            mProtectedNetworks.add(p);
         }
-        ni = mCm.getNetworkInfo(-1);
-        assertNull(ni);
     }
 
     public void testIsNetworkTypeValid() {
+        assertTrue(ConnectivityManager.isNetworkTypeValid(ConnectivityManager.TYPE_MOBILE));
+        assertTrue(ConnectivityManager.isNetworkTypeValid(ConnectivityManager.TYPE_WIFI));
+        assertTrue(ConnectivityManager.isNetworkTypeValid(ConnectivityManager.TYPE_MOBILE_MMS));
+        assertTrue(ConnectivityManager.isNetworkTypeValid(ConnectivityManager.TYPE_MOBILE_SUPL));
+        assertTrue(ConnectivityManager.isNetworkTypeValid(ConnectivityManager.TYPE_MOBILE_DUN));
+        assertTrue(ConnectivityManager.isNetworkTypeValid(ConnectivityManager.TYPE_MOBILE_HIPRI));
+        assertTrue(ConnectivityManager.isNetworkTypeValid(ConnectivityManager.TYPE_WIMAX));
+        assertTrue(ConnectivityManager.isNetworkTypeValid(ConnectivityManager.TYPE_BLUETOOTH));
+        assertTrue(ConnectivityManager.isNetworkTypeValid(ConnectivityManager.TYPE_DUMMY));
+        assertTrue(ConnectivityManager.isNetworkTypeValid(ConnectivityManager.TYPE_ETHERNET));
+        assertTrue(mCm.isNetworkTypeValid(ConnectivityManager.TYPE_MOBILE_FOTA));
+        assertTrue(mCm.isNetworkTypeValid(ConnectivityManager.TYPE_MOBILE_IMS));
+        assertTrue(mCm.isNetworkTypeValid(ConnectivityManager.TYPE_MOBILE_CBS));
+        assertTrue(mCm.isNetworkTypeValid(ConnectivityManager.TYPE_WIFI_P2P));
+        assertFalse(mCm.isNetworkTypeValid(-1));
+        assertTrue(mCm.isNetworkTypeValid(0));
+        assertTrue(mCm.isNetworkTypeValid(ConnectivityManager.MAX_NETWORK_TYPE));
+        assertFalse(ConnectivityManager.isNetworkTypeValid(ConnectivityManager.MAX_NETWORK_TYPE+1));
 
         NetworkInfo[] ni = mCm.getAllNetworkInfo();
 
-        for (NetworkInfo n : ni) {
+        for (NetworkInfo n: ni) {
             assertTrue(ConnectivityManager.isNetworkTypeValid(n.getType()));
         }
-        assertFalse(ConnectivityManager.isNetworkTypeValid(-1));
+
+    }
+
+    public void testSetNetworkPreference() {
+        // verify swtiching between two default networks - need to connectable networks though
+        // could use test and whatever the current active network is
+        NetworkInfo active = mCm.getActiveNetworkInfo();
+        int originalPref = mCm.getNetworkPreference();
+        int currentPref = originalPref;
+        for (int type = -1; type <= ConnectivityManager.MAX_NETWORK_TYPE+1; type++) {
+            mCm.setNetworkPreference(type);
+            NetworkConfig c = mNetworks.get(type);
+            boolean expectWorked = (c != null && c.isDefault());
+            try {
+                Thread.currentThread().sleep(100);
+            } catch (InterruptedException e) {}
+            int foundType = mCm.getNetworkPreference();
+            if (expectWorked) {
+                assertTrue("We should have been able to switch prefered type " + type,
+                        foundType == type);
+                currentPref = foundType;
+            } else {
+                assertTrue("We should not have been able to switch type " + type,
+                        foundType == currentPref);
+            }
+        }
+        mCm.setNetworkPreference(originalPref);
+    }
+
+    public void testGetActiveNetworkInfo() {
+        NetworkInfo ni = mCm.getActiveNetworkInfo();
+
+        assertTrue("You must have an active network connection to complete CTS", ni != null);
+        assertTrue(ConnectivityManager.isNetworkTypeValid(ni.getType()));
+        assertTrue(ni.getState() == State.CONNECTED);
+    }
+
+    public void testGetNetworkInfo() {
+        for (int type = -1; type <= ConnectivityManager.MAX_NETWORK_TYPE+1; type++) {
+            if (isSupported(type)) {
+                NetworkInfo ni = mCm.getNetworkInfo(type);
+                assertTrue("Info shouldn't be null for " + type, ni != null);
+                State state = ni.getState();
+                assertTrue("Bad state for " + type, State.UNKNOWN.ordinal() >= state.ordinal()
+                           && state.ordinal() >= State.CONNECTING.ordinal());
+                DetailedState ds = ni.getDetailedState();
+                assertTrue("Bad detailed state for " + type,
+                           DetailedState.FAILED.ordinal() >= ds.ordinal()
+                           && ds.ordinal() >= DetailedState.IDLE.ordinal());
+            } else {
+                assertNull("Info should be null for " + type, mCm.getNetworkInfo(type));
+            }
+        }
     }
 
     public void testGetAllNetworkInfo() {
         NetworkInfo[] ni = mCm.getAllNetworkInfo();
         assertTrue(ni.length >= MIN_NUM_NETWORK_TYPES);
+        for (int type = 0; type <= ConnectivityManager.MAX_NETWORK_TYPE; type++) {
+            int desiredFoundCount = (isSupported(type) ? 1 : 0);
+            int foundCount = 0;
+            for (NetworkInfo i : ni) {
+                if (i.getType() == type) foundCount++;
+            }
+            assertTrue("Unexpected foundCount of " + foundCount + " for type " + type,
+                    foundCount == desiredFoundCount);
+        }
     }
 
     public void testStartUsingNetworkFeature() {
@@ -130,35 +207,46 @@
         }
     }
 
-    public void testRequestRouteToHost() {
-        Set<Integer> exceptionFreeTypes = new HashSet<Integer>();
-        exceptionFreeTypes.add(ConnectivityManager.TYPE_BLUETOOTH);
-        exceptionFreeTypes.add(ConnectivityManager.TYPE_ETHERNET);
-        exceptionFreeTypes.add(ConnectivityManager.TYPE_MOBILE);
-        exceptionFreeTypes.add(ConnectivityManager.TYPE_MOBILE_DUN);
-        exceptionFreeTypes.add(ConnectivityManager.TYPE_MOBILE_HIPRI);
-        exceptionFreeTypes.add(ConnectivityManager.TYPE_MOBILE_MMS);
-        exceptionFreeTypes.add(ConnectivityManager.TYPE_MOBILE_SUPL);
+    private boolean isSupported(int networkType) {
+        return mNetworks.containsKey(networkType);
+    }
 
-        NetworkInfo[] ni = mCm.getAllNetworkInfo();
-        for (NetworkInfo n : ni) {
-            if (n.isConnected() && exceptionFreeTypes.contains(n.getType())) {
-                assertTrue("Network type: " + n.getType(), mCm.requestRouteToHost(n.getType(),
-                        HOST_ADDRESS));
+    // true if only the system can turn it on
+    private boolean isNetworkProtected(int networkType) {
+        return mProtectedNetworks.contains(networkType);
+    }
+
+    public void testIsNetworkSupported() {
+        for (int type = -1; type <= ConnectivityManager.MAX_NETWORK_TYPE; type++) {
+            boolean supported = mCm.isNetworkSupported(type);
+            if (isSupported(type)) {
+                assertTrue(supported);
+            } else {
+                assertFalse(supported);
             }
         }
+    }
+
+    public void testRequestRouteToHost() {
+        for (int type = -1 ; type <= ConnectivityManager.MAX_NETWORK_TYPE; type++) {
+            NetworkInfo ni = mCm.getNetworkInfo(type);
+            boolean expectToWork = isSupported(type) && !isNetworkProtected(type) &&
+                    ni != null && ni.isConnected();
+
+            try {
+                assertTrue("Network type " + type,
+                        mCm.requestRouteToHost(type, HOST_ADDRESS) == expectToWork);
+            } catch (Exception e) {
+                Log.d(TAG, "got exception in requestRouteToHost for type " + type);
+                assertFalse("Exception received for type " + type, expectToWork);
+            }
+
+            //TODO verify route table
+        }
 
         assertFalse(mCm.requestRouteToHost(-1, HOST_ADDRESS));
     }
 
-    public void testGetActiveNetworkInfo() {
-        NetworkInfo ni = mCm.getActiveNetworkInfo();
-
-        if (ni != null) {
-            assertTrue(ni.getType() >= 0);
-        }
-    }
-
     public void testTest() {
         mCm.getBackgroundDataSetting();
     }
@@ -197,12 +285,16 @@
 
             assertTrue("Couldn't requestRouteToHost using HIPRI.",
                     mCm.requestRouteToHost(ConnectivityManager.TYPE_MOBILE_HIPRI, HOST_ADDRESS));
-
+            // TODO check dns selection
+            // TODO check routes
         } catch (InterruptedException e) {
             fail("Broadcast receiver waiting for ConnectivityManager interrupted.");
         } finally {
             mCm.stopUsingNetworkFeature(ConnectivityManager.TYPE_MOBILE,
                     FEATURE_ENABLE_HIPRI);
+            // TODO wait for HIPRI to go
+            // TODO check dns selection
+            // TODO check routes
             if (!isWifiConnected) {
                 mWifiManager.setWifiEnabled(false);
             }
diff --git a/tests/tests/provider/src/android/provider/cts/ContactsContract_DataUsageTest.java b/tests/tests/provider/src/android/provider/cts/ContactsContract_DataUsageTest.java
new file mode 100644
index 0000000..a684e41
--- /dev/null
+++ b/tests/tests/provider/src/android/provider/cts/ContactsContract_DataUsageTest.java
@@ -0,0 +1,173 @@
+/*
+ * 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 android.provider.cts;
+
+import static android.provider.ContactsContract.CommonDataKinds;
+import static android.provider.ContactsContract.DataUsageFeedback;
+
+import android.content.ContentResolver;
+import android.content.ContentValues;
+import android.net.Uri;
+import android.provider.ContactsContract;
+import android.provider.cts.contacts.DataUtil;
+import android.provider.cts.contacts.DatabaseAsserts;
+import android.provider.cts.contacts.RawContactUtil;
+import android.test.AndroidTestCase;
+import android.text.TextUtils;
+
+public class ContactsContract_DataUsageTest extends AndroidTestCase {
+
+    private ContentResolver mResolver;
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        mResolver = getContext().getContentResolver();
+    }
+
+    public void testSingleDataUsageFeedback_incrementsCorrectDataItems() {
+        DatabaseAsserts.ContactIdPair ids = DatabaseAsserts.assertAndCreateContact(mResolver);
+
+        long[] dataIds = setupRawContactDataItems(ids.mRawContactId);
+
+        // Update just 1 data item at a time.
+        updateDataUsageAndAssert(dataIds[1], 1);
+        updateDataUsageAndAssert(dataIds[1], 2);
+
+        updateDataUsageAndAssert(dataIds[2], 1);
+        updateDataUsageAndAssert(dataIds[2], 2);
+        updateDataUsageAndAssert(dataIds[2], 3);
+
+        // Go back and update the previous data item again.
+        updateDataUsageAndAssert(dataIds[1], 3);
+
+        deleteDataUsage();
+        RawContactUtil.delete(mResolver, ids.mRawContactId, true);
+    }
+
+    public void testMultiIdDataUsageFeedback_incrementsCorrectDataItems() {
+        DatabaseAsserts.ContactIdPair ids = DatabaseAsserts.assertAndCreateContact(mResolver);
+
+        long[] dataIds = setupRawContactDataItems(ids.mRawContactId);
+
+        assertDataUsageEquals(dataIds, 0, 0, 0, 0);
+
+        updateMultipleAndAssertUpdateSuccess(new long[] {dataIds[1], dataIds[2]});
+        assertDataUsageEquals(dataIds, 0, 1, 1, 0);
+
+        updateMultipleAndAssertUpdateSuccess(new long[]{dataIds[1], dataIds[2]});
+        assertDataUsageEquals(dataIds, 0, 2, 2, 0);
+
+        updateDataUsageAndAssert(dataIds[1], 3);
+        assertDataUsageEquals(dataIds, 0, 3, 2, 0);
+
+        updateMultipleAndAssertUpdateSuccess(new long[]{dataIds[0], dataIds[1]});
+        assertDataUsageEquals(dataIds, 1, 4, 2, 0);
+
+        deleteDataUsage();
+        RawContactUtil.delete(mResolver, ids.mRawContactId, true);
+    }
+
+    private long[] setupRawContactDataItems(long rawContactId) {
+        // Create 4 data items.
+        long[] dataIds = new long[4];
+
+        ContentValues values = new ContentValues();
+        values.put(ContactsContract.Data.MIMETYPE, CommonDataKinds.Phone.CONTENT_ITEM_TYPE);
+        values.put(CommonDataKinds.Phone.NUMBER, "555-5555");
+        dataIds[0] = DataUtil.insertData(mResolver, rawContactId, values);
+
+        values.clear();
+        values.put(ContactsContract.Data.MIMETYPE, CommonDataKinds.Phone.CONTENT_ITEM_TYPE);
+        values.put(CommonDataKinds.Phone.NUMBER, "555-5554");
+        dataIds[1] = DataUtil.insertData(mResolver, rawContactId, values);
+
+        values.clear();
+        values.put(ContactsContract.Data.MIMETYPE, CommonDataKinds.Email.CONTENT_ITEM_TYPE);
+        values.put(CommonDataKinds.Email.ADDRESS, "test@thisisfake.com");
+        dataIds[2] = DataUtil.insertData(mResolver, rawContactId, values);
+
+        values.clear();
+        values.put(ContactsContract.Data.MIMETYPE, CommonDataKinds.Email.CONTENT_ITEM_TYPE);
+        values.put(CommonDataKinds.Phone.NUMBER, "555-5556");
+        dataIds[3] = DataUtil.insertData(mResolver, rawContactId, values);
+
+        return dataIds;
+    }
+
+    /**
+     * Updates multiple data ids at once.  And asserts the update returned success.
+     */
+    private void updateMultipleAndAssertUpdateSuccess(long[] dataIds) {
+        String[] ids = new String[dataIds.length];
+        for (int i = 0; i < dataIds.length; i++) {
+            ids[i] = String.valueOf(dataIds[i]);
+        }
+        Uri uri = DataUsageFeedback.FEEDBACK_URI.buildUpon().appendPath(TextUtils.join(",", ids))
+                .appendQueryParameter(DataUsageFeedback.USAGE_TYPE,
+                        DataUsageFeedback.USAGE_TYPE_CALL).build();
+        int result = mResolver.update(uri, new ContentValues(), null, null);
+        assertTrue(result > 0);
+    }
+
+    /**
+     * Updates a single data item usage.  Asserts the update was successful.  Asserts the usage
+     * number is equal to expected value.
+     */
+    private void updateDataUsageAndAssert(long dataId, int assertValue) {
+        Uri uri = DataUsageFeedback.FEEDBACK_URI.buildUpon().appendPath(String.valueOf(dataId))
+                .appendQueryParameter(DataUsageFeedback.USAGE_TYPE,
+                        DataUsageFeedback.USAGE_TYPE_CALL).build();
+        int result = mResolver.update(uri, new ContentValues(), null, null);
+        assertTrue(result > 0);
+
+        assertDataUsageEquals(dataId, assertValue);
+    }
+
+    /**
+     * Assert that the given data ids have usage values in the respective order.
+     */
+    private void assertDataUsageEquals(long[] dataIds, int... expectedValues) {
+        if (dataIds.length != expectedValues.length) {
+            throw new IllegalArgumentException("dataIds and expectedValues must be the same size");
+        }
+
+        for (int i = 0; i < dataIds.length; i++) {
+            assertDataUsageEquals(dataIds[i], expectedValues[i]);
+        }
+    }
+
+    /**
+     * Assert a single data item has a specific usage value.
+     */
+    private void assertDataUsageEquals(long dataId, int expectedValue) {
+        // Query and assert value is expected.
+        String[] projection = new String[]{ContactsContract.Data.TIMES_USED};
+        String[] record = DataUtil.queryById(mResolver, dataId, projection);
+        assertNotNull(record);
+        long actual = 0;
+        // Tread null as 0
+        if (record[0] != null) {
+            actual = Long.parseLong(record[0]);
+        }
+        assertEquals(expectedValue, actual);
+    }
+
+    private void deleteDataUsage() {
+        mResolver.delete(DataUsageFeedback.DELETE_USAGE_URI, null, null);
+    }
+}
diff --git a/tests/tests/provider/src/android/provider/cts/contacts/DataUtil.java b/tests/tests/provider/src/android/provider/cts/contacts/DataUtil.java
index adb253c..ae2812e 100644
--- a/tests/tests/provider/src/android/provider/cts/contacts/DataUtil.java
+++ b/tests/tests/provider/src/android/provider/cts/contacts/DataUtil.java
@@ -19,6 +19,7 @@
 import android.content.ContentResolver;
 import android.content.ContentUris;
 import android.content.ContentValues;
+import android.database.Cursor;
 import android.net.Uri;
 import android.provider.ContactsContract;
 
@@ -29,6 +30,12 @@
 
     private static final Uri URI = ContactsContract.Data.CONTENT_URI;
 
+    public static String[] queryById(ContentResolver resolver, long dataId, String[] projection) {
+        Uri uri = ContentUris.withAppendedId(URI, dataId);
+        Cursor cursor = resolver.query(uri, projection, null, null, null);
+        return CommonDatabaseUtils.singleRecordToArray(cursor);
+    }
+
     public static void insertName(ContentResolver resolver, long rawContactId) {
         ContentValues values = new ContentValues();
         values.put(ContactsContract.Data.MIMETYPE,
diff --git a/tests/tests/provider/src/android/provider/cts/contacts/RawContactUtil.java b/tests/tests/provider/src/android/provider/cts/contacts/RawContactUtil.java
index 8f9e7bd5..c87dc01 100644
--- a/tests/tests/provider/src/android/provider/cts/contacts/RawContactUtil.java
+++ b/tests/tests/provider/src/android/provider/cts/contacts/RawContactUtil.java
@@ -49,14 +49,13 @@
         ContentValues values = new ContentValues();
         values.put(ContactsContract.RawContacts.ACCOUNT_NAME, StaticAccountAuthenticator.NAME);
         values.put(ContactsContract.RawContacts.ACCOUNT_TYPE, StaticAccountAuthenticator.TYPE);
-        Uri uri = resolver.insert(ContactsContract.RawContacts.CONTENT_URI, values);
+        Uri uri = resolver.insert(URI, values);
         return ContentUris.parseId(uri);
     }
 
     public static String[] queryByRawContactId(ContentResolver resolver,
             long rawContactId, String[] projection) {
-        Uri uri = ContentUris.withAppendedId(ContactsContract.RawContacts.CONTENT_URI,
-                rawContactId);
+        Uri uri = ContentUris.withAppendedId(URI, rawContactId);
         Cursor cursor = resolver.query(uri, projection, null, null, null);
         return CommonDatabaseUtils.singleRecordToArray(cursor);
     }
@@ -68,14 +67,14 @@
      */
     public static List<String[]> queryByContactId(ContentResolver resolver, long contactId,
             String[] projection) {
-        Uri uri = ContentUris.withAppendedId(ContactsContract.RawContacts.CONTENT_URI, contactId);
+        Uri uri = ContentUris.withAppendedId(URI, contactId);
         Cursor cursor = resolver.query(uri, projection, null, null, null);
         return CommonDatabaseUtils.multiRecordToArray(cursor);
     }
 
     public static void delete(ContentResolver resolver, long rawContactId,
             boolean isSyncAdapter) {
-        Uri uri = ContentUris.withAppendedId(ContactsContract.RawContacts.CONTENT_URI, rawContactId)
+        Uri uri = ContentUris.withAppendedId(URI, rawContactId)
                 .buildUpon()
                 .appendQueryParameter(ContactsContract.CALLER_IS_SYNCADAPTER, isSyncAdapter + "")
                 .build();
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/GlobalSync.java b/tests/tests/renderscript/src/android/renderscript/cts/GlobalSync.java
new file mode 100644
index 0000000..f895661
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/GlobalSync.java
@@ -0,0 +1,88 @@
+/*
+ * 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 android.renderscript.cts;
+
+import android.renderscript.Allocation;
+import android.renderscript.Element;
+import android.renderscript.RenderScript;
+import android.renderscript.Type;
+
+public class GlobalSync extends RSBaseCompute {
+    Allocation AFailed;
+    int [] Failed;
+    Allocation AIn;
+
+    protected void setupGlobalSync(RenderScript mRS, ScriptC_global_sync gs, int v) {
+        Type.Builder typeBuilder = new Type.Builder(mRS, Element.I32(mRS));
+        Type t = typeBuilder.setX(1).create();
+
+        AFailed = Allocation.createTyped(mRS, t);
+        Failed = new int [1];
+        Failed[0] = 0;
+        AFailed.copyFrom(Failed);
+        gs.set_aFailed(AFailed);
+
+        AIn = Allocation.createTyped(mRS, t);
+        int [] In = new int [1];
+        In[0] = v;
+        AIn.copyFrom(In);
+
+    }
+
+    /**
+     * Test whether we are properly synchronizing extern global data
+     * when dealing with mixed kernels/invokables.
+     */
+    public void testGlobalSync() {
+        ScriptC_global_sync gs = new ScriptC_global_sync(mRS);
+
+        int v = 7;
+        setupGlobalSync(mRS, gs, v);
+        gs.forEach_write_global(AIn);
+        gs.invoke_test_global(v);
+
+        AFailed.copyTo(Failed);
+        if (Failed[0] != 0) {
+            FoundError = true;
+        }
+
+        gs.destroy();
+        checkForErrors();
+    }
+
+    /**
+     * Test whether we are properly synchronizing static global data
+     * when dealing with mixed kernels/invokables.
+     */
+    public void testStaticGlobalSync() {
+        ScriptC_global_sync gs = new ScriptC_global_sync(mRS);
+
+        int v = 9;
+        setupGlobalSync(mRS, gs, v);
+        gs.forEach_write_static_global(AIn);
+        gs.invoke_test_static_global(v);
+
+        AFailed.copyTo(Failed);
+        if (Failed[0] != 0) {
+            FoundError = true;
+        }
+
+        gs.destroy();
+        checkForErrors();
+    }
+}
+
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/GlobalTest.java b/tests/tests/renderscript/src/android/renderscript/cts/GlobalTest.java
new file mode 100644
index 0000000..b0c3b63
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/GlobalTest.java
@@ -0,0 +1,31 @@
+/*
+ * 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 android.renderscript.cts;
+
+public class GlobalTest extends RSBaseCompute {
+    /**
+     * Test whether we properly clean up after large global arrays are
+     * allocated/deallocated.
+     */
+    public void testLargeGlobal() {
+        for (int i = 0; i < 1000; i++) {
+            ScriptC_large_global lg = new ScriptC_large_global(mRS);
+            lg.destroy();
+        }
+        checkForErrors();
+    }
+}
diff --git a/tests/tests/text/src/android/text/format/cts/DateUtilsTest.java b/tests/tests/text/src/android/text/format/cts/DateUtilsTest.java
index 52f0d3f..14e01e8 100644
--- a/tests/tests/text/src/android/text/format/cts/DateUtilsTest.java
+++ b/tests/tests/text/src/android/text/format/cts/DateUtilsTest.java
@@ -189,11 +189,11 @@
                 fixedTime, java.text.DateFormat.SHORT, java.text.DateFormat.FULL));
 
         final long HOUR_DURATION = 2 * 60 * 60 * 1000;
-        assertEquals("5:30:15 AM GMT", DateUtils.formatSameDayTime(fixedTime + HOUR_DURATION,
+        assertEquals("5:30:15 AM GMT+00:00", DateUtils.formatSameDayTime(fixedTime + HOUR_DURATION,
                 fixedTime, java.text.DateFormat.FULL, java.text.DateFormat.FULL));
         assertEquals("5:30:15 AM", DateUtils.formatSameDayTime(fixedTime + HOUR_DURATION,
                 fixedTime, java.text.DateFormat.FULL, java.text.DateFormat.DEFAULT));
-        assertEquals("5:30:15 AM GMT", DateUtils.formatSameDayTime(fixedTime + HOUR_DURATION,
+        assertEquals("5:30:15 AM GMT+00:00", DateUtils.formatSameDayTime(fixedTime + HOUR_DURATION,
                 fixedTime, java.text.DateFormat.FULL, java.text.DateFormat.LONG));
         assertEquals("5:30:15 AM", DateUtils.formatSameDayTime(fixedTime + HOUR_DURATION,
                 fixedTime, java.text.DateFormat.FULL, java.text.DateFormat.MEDIUM));