Merge "Fix WebChromeClientTest#testOnProgressChanged DO NOT MERGE" into jb-mr2-dev
diff --git a/suite/pts/deviceTests/opengl/jni/GLNative.cpp b/suite/pts/deviceTests/opengl/jni/GLNative.cpp
index 28e8265..bd132b9 100644
--- a/suite/pts/deviceTests/opengl/jni/GLNative.cpp
+++ b/suite/pts/deviceTests/opengl/jni/GLNative.cpp
@@ -44,16 +44,13 @@
     // Sets up the renderer.
     bool success = gRenderer->setUp();
 
-    // Draw to the screen. This allows debugging and also warms up the HW.
-    success = success && gRenderer->draw(false);
-
     // Records the start time.
     double start = currentTimeMillis();
 
     // Draw off the screen.
     for (int i = 0; i < numFrames && success; i++) {
         // Draw a frame.
-        success = gRenderer->draw(true);
+        success = gRenderer->draw();
     }
 
     // Records the end time.
@@ -73,24 +70,28 @@
 // The following functions create the renderers for the various benchmarks.
 extern "C" JNIEXPORT void JNICALL
 Java_com_android_pts_opengl_primitive_GLActivity_setupFullPipelineBenchmark(
-        JNIEnv* env, jclass clazz, jobject surface, jint workload) {
-    gRenderer = new FullPipelineRenderer(ANativeWindow_fromSurface(env, surface), workload);
+        JNIEnv* env, jclass clazz, jobject surface, jboolean offscreen, jint workload) {
+    gRenderer = new FullPipelineRenderer(
+            ANativeWindow_fromSurface(env, surface), offscreen, workload);
 }
 
 extern "C" JNIEXPORT void JNICALL
 Java_com_android_pts_opengl_primitive_GLActivity_setupPixelOutputBenchmark(
-        JNIEnv* env, jclass clazz, jobject surface, jint workload) {
-    gRenderer = new PixelOutputRenderer(ANativeWindow_fromSurface(env, surface), workload);
+        JNIEnv* env, jclass clazz, jobject surface, jboolean offscreen, jint workload) {
+    gRenderer = new PixelOutputRenderer(
+            ANativeWindow_fromSurface(env, surface), offscreen, workload);
 }
 
 extern "C" JNIEXPORT void JNICALL
 Java_com_android_pts_opengl_primitive_GLActivity_setupShaderPerfBenchmark(
-        JNIEnv* env, jclass clazz, jobject surface, jint workload) {
-    gRenderer = new ShaderPerfRenderer(ANativeWindow_fromSurface(env, surface), workload);
+        JNIEnv* env, jclass clazz, jobject surface, jboolean offscreen, jint workload) {
+    gRenderer = new ShaderPerfRenderer(
+            ANativeWindow_fromSurface(env, surface), offscreen, workload);
 }
 
 extern "C" JNIEXPORT void JNICALL
 Java_com_android_pts_opengl_primitive_GLActivity_setupContextSwitchBenchmark(
-        JNIEnv* env, jclass clazz, jobject surface, jint workload) {
-    gRenderer = new ContextSwitchRenderer(ANativeWindow_fromSurface(env, surface), workload);
+        JNIEnv* env, jclass clazz, jobject surface, jboolean offscreen, jint workload) {
+    gRenderer = new ContextSwitchRenderer(
+            ANativeWindow_fromSurface(env, surface), offscreen, workload);
 }
diff --git a/suite/pts/deviceTests/opengl/jni/Renderer.cpp b/suite/pts/deviceTests/opengl/jni/Renderer.cpp
index 70445dc..0f5c3ba 100644
--- a/suite/pts/deviceTests/opengl/jni/Renderer.cpp
+++ b/suite/pts/deviceTests/opengl/jni/Renderer.cpp
@@ -33,10 +33,9 @@
         EGL_STENCIL_SIZE, 8,
         EGL_NONE };
 
-Renderer::Renderer(ANativeWindow* window, int workload) :
-        mEglDisplay(EGL_NO_DISPLAY), mEglSurface(EGL_NO_SURFACE), mEglContext(EGL_NO_CONTEXT) {
-    mWindow = window;
-    mWorkload = workload;
+Renderer::Renderer(ANativeWindow* window, bool offscreen, int workload) :
+        mWindow(window), mEglDisplay(EGL_NO_DISPLAY), mEglSurface(EGL_NO_SURFACE),
+        mEglContext(EGL_NO_CONTEXT), mOffscreen(offscreen), mWorkload(workload) {
 }
 
 bool Renderer::setUp() {
@@ -83,10 +82,16 @@
 
     glViewport(0, 0, width, height);
 
-    int w = GLUtils::roundUpToSmallestPowerOf2(width);
-    int h = GLUtils::roundUpToSmallestPowerOf2(height);
-    if (!createFBO(mFboId, mRboId, mCboId, w, h)) {
-        return false;
+    if (mOffscreen) {
+        int w = GLUtils::roundUpToSmallestPowerOf2(width);
+        int h = GLUtils::roundUpToSmallestPowerOf2(height);
+        if (!createFBO(mFboId, mRboId, mCboId, w, h)) {
+            return false;
+        }
+    } else {
+        mFboId = 0;
+        mRboId = 0;
+        mCboId = 0;
     }
 
     GLuint err = glGetError();
diff --git a/suite/pts/deviceTests/opengl/jni/Renderer.h b/suite/pts/deviceTests/opengl/jni/Renderer.h
index 10e179a..a50d81c 100644
--- a/suite/pts/deviceTests/opengl/jni/Renderer.h
+++ b/suite/pts/deviceTests/opengl/jni/Renderer.h
@@ -22,10 +22,10 @@
 
 class Renderer {
 public:
-    Renderer(ANativeWindow* window, int workload);
+    Renderer(ANativeWindow* window, bool offscreen, int workload);
     virtual bool setUp();
     virtual bool tearDown();
-    virtual bool draw(bool offscreen) = 0;
+    virtual bool draw() = 0;
     virtual ~Renderer() {};
 protected:
     bool createFBO(GLuint& fboId, GLuint& rboId, GLuint& cboId, int width, int height);
@@ -37,9 +37,10 @@
     GLuint mFboId; //Frame buffer
     GLuint mRboId; //Depth buffer
     GLuint mCboId; //Color buffer
-    GLuint mProgram;
+    GLuint mProgramId;
     EGLint width;
     EGLint height;
+    bool mOffscreen;
     int mWorkload;
 };
 #endif
diff --git a/suite/pts/deviceTests/opengl/jni/contextswitch/ContextSwitchRenderer.cpp b/suite/pts/deviceTests/opengl/jni/contextswitch/ContextSwitchRenderer.cpp
index f69a9f5..8e4b7e2 100644
--- a/suite/pts/deviceTests/opengl/jni/contextswitch/ContextSwitchRenderer.cpp
+++ b/suite/pts/deviceTests/opengl/jni/contextswitch/ContextSwitchRenderer.cpp
@@ -65,8 +65,8 @@
         "  gl_FragColor = texture2D(u_Texture, v_TexCoord);"
         "}";
 
-ContextSwitchRenderer::ContextSwitchRenderer(ANativeWindow* window, int workload) :
-        Renderer(window, workload), mContexts(NULL) {
+ContextSwitchRenderer::ContextSwitchRenderer(ANativeWindow* window, bool offscreen, int workload) :
+        Renderer(window, offscreen, workload), mContexts(NULL) {
 }
 
 bool ContextSwitchRenderer::setUp() {
@@ -83,13 +83,15 @@
 
     mContexts = new EGLContext[mWorkload];
     mTextureIds = new GLuint[mWorkload];
-    mFboIds = new GLuint[mWorkload];
-    mRboIds = new GLuint[mWorkload];
-    mCboIds = new GLuint[mWorkload];
-    mPrograms = new GLuint[mWorkload];
+    mProgramIds = new GLuint[mWorkload];
     mTextureUniformHandles = new GLuint[mWorkload];
     mPositionHandles = new GLuint[mWorkload];
     mTexCoordHandles = new GLuint[mWorkload];
+    if (mOffscreen) {
+        mFboIds = new GLuint[mWorkload];
+        mRboIds = new GLuint[mWorkload];
+        mCboIds = new GLuint[mWorkload];
+    }
     for (int i = 0; i < mWorkload; i++) {
         mContexts[i] = eglCreateContext(mEglDisplay, mGlConfig, EGL_NO_CONTEXT, contextAttribs);
         if (EGL_NO_CONTEXT == mContexts[i] || EGL_SUCCESS != eglGetError()) {
@@ -101,26 +103,28 @@
             return false;
         }
 
-        // Setup FBOs.
-        if (!Renderer::createFBO(mFboIds[i], mRboIds[i], mCboIds[i], w, h)) {
-            return false;
+        if (mOffscreen) {
+            // Setup FBOs.
+            if (!Renderer::createFBO(mFboIds[i], mRboIds[i], mCboIds[i], w, h)) {
+                return false;
+            }
         }
 
         // Setup textures.
-        mTextureIds[i] = GLUtils::genRandTex(width, height);
+        mTextureIds[i] = GLUtils::genRandTex(2, 2);
         if (mTextureIds[i] == 0) {
             return false;
         }
 
         // Create program.
-        mPrograms[i] = GLUtils::createProgram(&CS_VERTEX, &CS_FRAGMENT);
-        if (mPrograms[i] == 0) {
+        mProgramIds[i] = GLUtils::createProgram(&CS_VERTEX, &CS_FRAGMENT);
+        if (mProgramIds[i] == 0) {
             return false;
         }
         // Bind attributes.
-        mTextureUniformHandles[i] = glGetUniformLocation(mPrograms[i], "u_Texture");
-        mPositionHandles[i] = glGetAttribLocation(mPrograms[i], "a_Position");
-        mTexCoordHandles[i] = glGetAttribLocation(mPrograms[i], "a_TexCoord");
+        mTextureUniformHandles[i] = glGetUniformLocation(mProgramIds[i], "u_Texture");
+        mPositionHandles[i] = glGetAttribLocation(mProgramIds[i], "a_Position");
+        mTexCoordHandles[i] = glGetAttribLocation(mProgramIds[i], "a_TexCoord");
     }
 
     GLuint err = glGetError();
@@ -139,17 +143,19 @@
         }
         delete[] mContexts;
     }
-    if (mFboIds) {
-        glDeleteFramebuffers(mWorkload, mFboIds);
-        delete[] mFboIds;
-    }
-    if (mRboIds) {
-        glDeleteRenderbuffers(mWorkload, mRboIds);
-        delete[] mRboIds;
-    }
-    if (mCboIds) {
-        glDeleteRenderbuffers(mWorkload, mCboIds);
-        delete[] mCboIds;
+    if (mOffscreen) {
+        if (mFboIds) {
+            glDeleteFramebuffers(mWorkload, mFboIds);
+            delete[] mFboIds;
+        }
+        if (mRboIds) {
+            glDeleteRenderbuffers(mWorkload, mRboIds);
+            delete[] mRboIds;
+        }
+        if (mCboIds) {
+            glDeleteRenderbuffers(mWorkload, mCboIds);
+            delete[] mCboIds;
+        }
     }
     if (mTextureIds) {
         glDeleteTextures(mWorkload, mTextureIds);
@@ -161,22 +167,25 @@
     return true;
 }
 
-bool ContextSwitchRenderer::draw(bool offscreen) {
+bool ContextSwitchRenderer::draw() {
     for (int i = 0; i < mWorkload; i++) {
         if (!eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface, mContexts[i])
                 || EGL_SUCCESS != eglGetError()) {
             return false;
         }
-        glBindFramebuffer(GL_FRAMEBUFFER, (offscreen) ? mFboIds[i] : 0);
-        if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) {
-            return false;
+
+        if (mOffscreen) {
+            glBindFramebuffer(GL_FRAMEBUFFER, mFboIds[i]);
+            if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) {
+                return false;
+            }
         }
 
         glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
         glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
 
-        glUseProgram(mPrograms[i]);
-        glActiveTexture (GL_TEXTURE0);
+        glUseProgram(mProgramIds[i]);
+        glActiveTexture(GL_TEXTURE0);
         // Bind the texture to this unit.
         glBindTexture(GL_TEXTURE_2D, mTextureIds[i]);
 
@@ -199,5 +208,5 @@
         return false;
     }
 
-    return (offscreen) ? true : eglSwapBuffers(mEglDisplay, mEglSurface);
+    return (mOffscreen) ? true : eglSwapBuffers(mEglDisplay, mEglSurface);
 }
diff --git a/suite/pts/deviceTests/opengl/jni/contextswitch/ContextSwitchRenderer.h b/suite/pts/deviceTests/opengl/jni/contextswitch/ContextSwitchRenderer.h
index c2ef8e1..3dfe9f3 100644
--- a/suite/pts/deviceTests/opengl/jni/contextswitch/ContextSwitchRenderer.h
+++ b/suite/pts/deviceTests/opengl/jni/contextswitch/ContextSwitchRenderer.h
@@ -18,11 +18,11 @@
 
 class ContextSwitchRenderer: public Renderer {
 public:
-    ContextSwitchRenderer(ANativeWindow* window, int workload);
+    ContextSwitchRenderer(ANativeWindow* window, bool offscreen, int workload);
     virtual ~ContextSwitchRenderer() {};
     bool setUp();
     bool tearDown();
-    bool draw(bool offscreen);
+    bool draw();
 private:
     GLuint mTextureUniformHandle;
     GLuint mPositionHandle;
@@ -32,7 +32,7 @@
     GLuint* mFboIds;
     GLuint* mRboIds;
     GLuint* mCboIds;
-    GLuint* mPrograms;
+    GLuint* mProgramIds;
     GLuint* mTextureUniformHandles;
     GLuint* mPositionHandles;
     GLuint* mTexCoordHandles;
diff --git a/suite/pts/deviceTests/opengl/jni/fullpipeline/FullPipelineRenderer.cpp b/suite/pts/deviceTests/opengl/jni/fullpipeline/FullPipelineRenderer.cpp
index 35389d2..c2ffecc 100644
--- a/suite/pts/deviceTests/opengl/jni/fullpipeline/FullPipelineRenderer.cpp
+++ b/suite/pts/deviceTests/opengl/jni/fullpipeline/FullPipelineRenderer.cpp
@@ -95,9 +95,9 @@
         "  gl_FragColor = (diffuse * texture2D(u_Texture, v_TexCoordinate));\n"
         "}";
 
-FullPipelineRenderer::FullPipelineRenderer(ANativeWindow* window, int workload) :
-        Renderer(window, workload), mProgram(NULL), mSceneGraph(NULL), mModelMatrix(NULL),
-        mViewMatrix(NULL), mProjectionMatrix(NULL), mMesh(NULL) {
+FullPipelineRenderer::FullPipelineRenderer(ANativeWindow* window, bool offscreen, int workload) :
+        Renderer(window, offscreen, workload), mProgram(NULL), mSceneGraph(NULL),
+        mModelMatrix(NULL), mViewMatrix(NULL), mProjectionMatrix(NULL), mMesh(NULL) {
 }
 
 bool FullPipelineRenderer::setUp() {
@@ -105,10 +105,10 @@
         return false;
     }
 
-    GLuint programId = GLUtils::createProgram(&FP_VERTEX, &FP_FRAGMENT);
-    if (programId == 0)
+    mProgramId = GLUtils::createProgram(&FP_VERTEX, &FP_FRAGMENT);
+    if (mProgramId == 0)
         return false;
-    mProgram = new FullPipelineProgram(programId);
+    mProgram = new FullPipelineProgram(mProgramId);
 
     mModelMatrix = new Matrix();
 
@@ -191,14 +191,16 @@
     return true;
 }
 
-bool FullPipelineRenderer::draw(bool offscreen) {
-    glBindFramebuffer(GL_FRAMEBUFFER, (offscreen) ? mFboId : 0);
+bool FullPipelineRenderer::draw() {
+    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);
+    glEnable(GL_CULL_FACE);
     // Use depth testing.
-    glEnable (GL_DEPTH_TEST);
+    glEnable(GL_DEPTH_TEST);
     glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
     mModelMatrix->identity();
     mSceneGraph->draw(*mProgram, *mModelMatrix, *mViewMatrix, *mProjectionMatrix);
@@ -209,7 +211,7 @@
         return false;
     }
 
-    if (offscreen) {
+    if (mOffscreen) {
         glFinish();
         return true;
     } else {
diff --git a/suite/pts/deviceTests/opengl/jni/fullpipeline/FullPipelineRenderer.h b/suite/pts/deviceTests/opengl/jni/fullpipeline/FullPipelineRenderer.h
index 61a7322..0c5acae 100644
--- a/suite/pts/deviceTests/opengl/jni/fullpipeline/FullPipelineRenderer.h
+++ b/suite/pts/deviceTests/opengl/jni/fullpipeline/FullPipelineRenderer.h
@@ -23,11 +23,11 @@
 
 class FullPipelineRenderer: public Renderer {
 public:
-    FullPipelineRenderer(ANativeWindow* window, int workload);
+    FullPipelineRenderer(ANativeWindow* window, bool offscreen, int workload);
     virtual ~FullPipelineRenderer() {};
     bool setUp();
     bool tearDown();
-    bool draw(bool offscreen);
+    bool draw();
 private:
     FullPipelineProgram* mProgram;
     ProgramNode* mSceneGraph;
diff --git a/suite/pts/deviceTests/opengl/jni/pixeloutput/PixelOutputRenderer.cpp b/suite/pts/deviceTests/opengl/jni/pixeloutput/PixelOutputRenderer.cpp
index cfddafa..95bf52b 100644
--- a/suite/pts/deviceTests/opengl/jni/pixeloutput/PixelOutputRenderer.cpp
+++ b/suite/pts/deviceTests/opengl/jni/pixeloutput/PixelOutputRenderer.cpp
@@ -52,8 +52,8 @@
         "  gl_FragColor = texture2D(u_Texture, v_TexCoord);"
         "}";
 
-PixelOutputRenderer::PixelOutputRenderer(ANativeWindow* window, int workload) :
-        Renderer(window, workload) {
+PixelOutputRenderer::PixelOutputRenderer(ANativeWindow* window, bool offscreen, int workload) :
+        Renderer(window, offscreen, workload) {
 }
 
 bool PixelOutputRenderer::setUp() {
@@ -62,13 +62,13 @@
     }
 
     // Create program.
-    mProgram = GLUtils::createProgram(&PO_VERTEX, &PO_FRAGMENT);
-    if (mProgram == 0)
+    mProgramId = GLUtils::createProgram(&PO_VERTEX, &PO_FRAGMENT);
+    if (mProgramId == 0)
         return false;
     // Bind attributes.
-    mTextureUniformHandle = glGetUniformLocation(mProgram, "u_Texture");
-    mPositionHandle = glGetAttribLocation(mProgram, "a_Position");
-    mTexCoordHandle = glGetAttribLocation(mProgram, "a_TexCoord");
+    mTextureUniformHandle = glGetUniformLocation(mProgramId, "u_Texture");
+    mPositionHandle = glGetAttribLocation(mProgramId, "a_Position");
+    mTexCoordHandle = glGetAttribLocation(mProgramId, "a_TexCoord");
 
     // Setup texture.
     mTextureId = GLUtils::genRandTex(width, height);
@@ -89,9 +89,11 @@
     return true;
 }
 
-bool PixelOutputRenderer::draw(bool offscreen) {
-    glBindFramebuffer(GL_FRAMEBUFFER, (offscreen) ? mFboId : 0);
-    glUseProgram (mProgram);
+bool PixelOutputRenderer::draw() {
+    if (mOffscreen) {
+        glBindFramebuffer(GL_FRAMEBUFFER, mFboId);
+    }
+    glUseProgram(mProgramId);
     // Set the background clear color to black.
     glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
     glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
@@ -106,7 +108,7 @@
     glEnable(GL_BLEND);
     glBlendFunc(GL_ONE, GL_ONE);
 
-    glActiveTexture (GL_TEXTURE0);
+    glActiveTexture(GL_TEXTURE0);
     // Bind the texture to this unit.
     glBindTexture(GL_TEXTURE_2D, mTextureId);
     // Tell the texture uniform sampler to use this texture in the shader by binding to texture
@@ -128,7 +130,7 @@
         return false;
     }
 
-    if (offscreen) {
+    if (mOffscreen) {
         glFinish();
         return true;
     } else {
diff --git a/suite/pts/deviceTests/opengl/jni/pixeloutput/PixelOutputRenderer.h b/suite/pts/deviceTests/opengl/jni/pixeloutput/PixelOutputRenderer.h
index ed631e2..6422517 100644
--- a/suite/pts/deviceTests/opengl/jni/pixeloutput/PixelOutputRenderer.h
+++ b/suite/pts/deviceTests/opengl/jni/pixeloutput/PixelOutputRenderer.h
@@ -18,11 +18,11 @@
 
 class PixelOutputRenderer: public Renderer {
 public:
-    PixelOutputRenderer(ANativeWindow* window, int workload);
+    PixelOutputRenderer(ANativeWindow* window, bool offscreen, int workload);
     virtual ~PixelOutputRenderer() {};
     bool setUp();
     bool tearDown();
-    bool draw(bool offscreen);
+    bool draw();
 private:
     GLuint mTextureId;
     GLuint mTextureUniformHandle;
diff --git a/suite/pts/deviceTests/opengl/jni/shaderperf/ShaderPerfRenderer.cpp b/suite/pts/deviceTests/opengl/jni/shaderperf/ShaderPerfRenderer.cpp
index bbb5f68..a3fea22 100644
--- a/suite/pts/deviceTests/opengl/jni/shaderperf/ShaderPerfRenderer.cpp
+++ b/suite/pts/deviceTests/opengl/jni/shaderperf/ShaderPerfRenderer.cpp
@@ -42,8 +42,8 @@
                                 "  gl_FragColor = v_Position;"
                                 "}";
 
-ShaderPerfRenderer::ShaderPerfRenderer(ANativeWindow* window, int workload) :
-        Renderer(window, workload) {
+ShaderPerfRenderer::ShaderPerfRenderer(ANativeWindow* window, bool offscreen, int workload) :
+        Renderer(window, offscreen, workload) {
 }
 
 bool ShaderPerfRenderer::setUp() {
@@ -51,17 +51,19 @@
         return false;
     }
     // Create program.
-    mProgram = GLUtils::createProgram(&SP_VERTEX, &SP_FRAGMENT);
-    if (mProgram == 0)
+    mProgramId = GLUtils::createProgram(&SP_VERTEX, &SP_FRAGMENT);
+    if (mProgramId == 0)
         return false;
     // Bind attributes.
-    mPositionHandle = glGetAttribLocation(mProgram, "a_Position");
+    mPositionHandle = glGetAttribLocation(mProgramId, "a_Position");
     return true;
 }
 
-bool ShaderPerfRenderer::draw(bool offscreen) {
-    glBindFramebuffer(GL_FRAMEBUFFER, (offscreen) ? mFboId : 0);
-    glUseProgram(mProgram);
+bool ShaderPerfRenderer::draw() {
+    if (mOffscreen) {
+        glBindFramebuffer(GL_FRAMEBUFFER, mFboId);
+    }
+    glUseProgram(mProgramId);
     // Set the background clear color to black.
     glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
     glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
@@ -80,7 +82,7 @@
         return false;
     }
 
-    if (offscreen) {
+    if (mOffscreen) {
         glFinish();
         return true;
     } else {
diff --git a/suite/pts/deviceTests/opengl/jni/shaderperf/ShaderPerfRenderer.h b/suite/pts/deviceTests/opengl/jni/shaderperf/ShaderPerfRenderer.h
index 2e5cb98..22e0420 100644
--- a/suite/pts/deviceTests/opengl/jni/shaderperf/ShaderPerfRenderer.h
+++ b/suite/pts/deviceTests/opengl/jni/shaderperf/ShaderPerfRenderer.h
@@ -18,10 +18,10 @@
 
 class ShaderPerfRenderer: public Renderer {
 public:
-    ShaderPerfRenderer(ANativeWindow* window, int workload);
+    ShaderPerfRenderer(ANativeWindow* window, bool offscreen, int workload);
     virtual ~ShaderPerfRenderer() {};
     bool setUp();
-    bool draw(bool offscreen);
+    bool draw();
 private:
     GLuint mPositionHandle;
 };
diff --git a/suite/pts/deviceTests/opengl/src/com/android/pts/opengl/primitive/GLActivity.java b/suite/pts/deviceTests/opengl/src/com/android/pts/opengl/primitive/GLActivity.java
index 5f75cbb..dece656 100644
--- a/suite/pts/deviceTests/opengl/src/com/android/pts/opengl/primitive/GLActivity.java
+++ b/suite/pts/deviceTests/opengl/src/com/android/pts/opengl/primitive/GLActivity.java
@@ -25,6 +25,8 @@
 import com.android.pts.util.ResultType;
 import com.android.pts.util.ResultUnit;
 
+import java.util.ArrayList;
+
 public class GLActivity extends Activity {
 
     public final static String TAG = "GLActivity";
@@ -33,6 +35,10 @@
      */
     public final static String INTENT_EXTRA_BENCHMARK_NAME = "benchmark_name";
     /**
+     * Holds whether or not the benchmark is to be run offscreen.
+     */
+    public final static String INTENT_EXTRA_OFFSCREEN = "offscreen";
+    /**
      * Holds the number of milliseconds to wait before timing out.
      */
     public final static String INTENT_EXTRA_TIMEOUT = "timeout";
@@ -50,22 +56,27 @@
     private volatile Surface mSurface;
 
     private Benchmark mBenchmark;
+    private boolean mOffscreen;
     private int mTimeout;
-    private double mMinFps;
+    private int mMinFps;
     private int mNumFrames;
     private volatile int mWorkload = 0;
 
+    public ArrayList<Double> fpsValues = new ArrayList<Double>();
+
     @Override
     public void onCreate(Bundle data) {
         super.onCreate(data);
         System.loadLibrary("ptsopengl_jni");
         Intent intent = getIntent();
         mBenchmark = Benchmark.valueOf(intent.getStringExtra(INTENT_EXTRA_BENCHMARK_NAME));
+        mOffscreen = intent.getBooleanExtra(INTENT_EXTRA_OFFSCREEN, false);
         mTimeout = intent.getIntExtra(INTENT_EXTRA_TIMEOUT, 0);
-        mMinFps = intent.getDoubleExtra(INTENT_EXTRA_MIN_FPS, 0);
+        mMinFps = intent.getIntExtra(INTENT_EXTRA_MIN_FPS, 0);
         mNumFrames = intent.getIntExtra(INTENT_EXTRA_NUM_FRAMES, 0);
 
         Log.i(TAG, "Benchmark: " + mBenchmark);
+        Log.i(TAG, "Offscreen: " + mOffscreen);
         Log.i(TAG, "Time Out: " + mTimeout);
         Log.i(TAG, "Min FPS: " + mMinFps);
         Log.i(TAG, "Num Frames: " + mNumFrames);
@@ -97,13 +108,17 @@
         return mWorkload;
     }
 
-    private static native void setupFullPipelineBenchmark(Surface surface, int workload);
+    private static native void setupFullPipelineBenchmark(
+            Surface surface, boolean offscreen, int workload);
 
-    private static native void setupPixelOutputBenchmark(Surface surface, int workload);
+    private static native void setupPixelOutputBenchmark(
+            Surface surface, boolean offscreen, int workload);
 
-    private static native void setupShaderPerfBenchmark(Surface surface, int workload);
+    private static native void setupShaderPerfBenchmark(
+            Surface surface, boolean offscreen, int workload);
 
-    private static native void setupContextSwitchBenchmark(Surface surface, int workload);
+    private static native void setupContextSwitchBenchmark(
+            Surface surface, boolean offscreen, int workload);
 
     private static native boolean startBenchmark(int numFrames, double[] frameTimes);
 
@@ -127,16 +142,16 @@
                 // Setup the benchmark.
                 switch (mBenchmark) {
                     case FullPipeline:
-                        setupFullPipelineBenchmark(mSurface, wl);
+                        setupFullPipelineBenchmark(mSurface, mOffscreen, wl);
                         break;
                     case PixelOutput:
-                        setupPixelOutputBenchmark(mSurface, wl);
+                        setupPixelOutputBenchmark(mSurface, mOffscreen, wl);
                         break;
                     case ShaderPerf:
-                        setupShaderPerfBenchmark(mSurface, wl);
+                        setupShaderPerfBenchmark(mSurface, mOffscreen, wl);
                         break;
                     case ContextSwitch:
-                        setupContextSwitchBenchmark(mSurface, wl);
+                        setupContextSwitchBenchmark(mSurface, mOffscreen, wl);
                         break;
                 }
                 watchDog.start();
@@ -150,8 +165,7 @@
                     // Calculate FPS.
                     double totalTimeTaken = times[1] - times[0];
                     double meanFps = mNumFrames * 1000.0f / totalTimeTaken;
-                    Log.i(TAG, "Workload: " + wl);
-                    Log.i(TAG, "Mean FPS: " + meanFps);
+                    fpsValues.add(meanFps);
                     if (meanFps >= mMinFps) {
                         // Iteration passed, proceed to next one.
                         mWorkload++;
diff --git a/suite/pts/deviceTests/opengl/src/com/android/pts/opengl/primitive/GLBenchmark.java b/suite/pts/deviceTests/opengl/src/com/android/pts/opengl/primitive/GLBenchmark.java
index e944b9a..bb63ee8 100644
--- a/suite/pts/deviceTests/opengl/src/com/android/pts/opengl/primitive/GLBenchmark.java
+++ b/suite/pts/deviceTests/opengl/src/com/android/pts/opengl/primitive/GLBenchmark.java
@@ -22,52 +22,72 @@
 import android.opengl.Matrix;
 import android.util.Log;
 import java.util.Arrays;
+
 /**
  * Runs the Primitive OpenGL ES 2.0 Benchmarks.
  */
 public class GLBenchmark extends PtsActivityInstrumentationTestCase2<GLActivity> {
 
-    private static final double MIN_FPS = 50;
-
     public GLBenchmark() {
         super(GLActivity.class);
     }
 
     /**
-     * Runs the full OpenGL ES 2.0 pipeline test.
-     *
-     * @throws Exception If the benchmark could not be run.
+     * Runs the full OpenGL ES 2.0 pipeline test offscreen.
      */
-    public void testFullPipeline() throws Exception {
-        runBenchmark(Benchmark.FullPipeline, 500, 50000, 1);
+    public void testFullPipelineOffscreen() throws Exception {
+        runBenchmark(Benchmark.FullPipeline, true, 500, 100000, 25, 0);
     }
 
     /**
-     * Runs the pixel output test.
-     *
-     * @throws Exception If the benchmark could not be run.
+     * Runs the full OpenGL ES 2.0 pipeline test onscreen.
      */
-    public void testPixelOutput() throws Exception {
-        runBenchmark(Benchmark.PixelOutput, 500, 50000, 1);
+    public void testFullPipelineOnscreen() throws Exception {
+        runBenchmark(Benchmark.FullPipeline, false, 500, 100000, 25, 0);
     }
 
     /**
-     * Runs the shader performance test.
-     *
-     * @throws Exception If the benchmark could not be run.
+     * Runs the pixel output test offscreen.
      */
-    public void testShaderPerf() throws Exception {
+    public void testPixelOutputOffscreen() throws Exception {
+        runBenchmark(Benchmark.PixelOutput, true, 500, 100000, 25, 0);
+    }
+
+    /**
+     * Runs the pixel output test onscreen.
+     */
+    public void testPixelOutputOnscreen() throws Exception {
+        runBenchmark(Benchmark.PixelOutput, false, 500, 100000, 25, 0);
+    }
+
+    /**
+     * Runs the shader performance test offscreen.
+     */
+    public void testShaderPerfOffscreen() throws Exception {
         // TODO(stuartscott): Not yet implemented
-        // runBenchmark(Benchmark.ShaderPerf, 500, 50000, 1);
+        // runBenchmark(Benchmark.ShaderPerf, true, 500, 100000, 25, 0);
     }
 
     /**
-     * Runs the OpenGL context switch overhead test.
-     *
-     * @throws Exception If the benchmark could not be run.
+     * Runs the shader performance test onscreen.
      */
-    public void testContextSwitch() throws Exception {
-        runBenchmark(Benchmark.ContextSwitch, 500, 50000, 1);
+    public void testShaderPerfOnscreen() throws Exception {
+        // TODO(stuartscott): Not yet implemented
+        // runBenchmark(Benchmark.ShaderPerf, false, 500, 100000, 25, 0);
+    }
+
+    /**
+     * Runs the context switch overhead test offscreen.
+     */
+    public void testContextSwitchOffscreen() throws Exception {
+        runBenchmark(Benchmark.ContextSwitch, true, 500, 100000, 25, 0);
+    }
+
+    /**
+     * Runs the context switch overhead test onscreen.
+     */
+    public void testContextSwitchOnscreen() throws Exception {
+        runBenchmark(Benchmark.ContextSwitch, false, 500, 100000, 25, 0);
     }
 
     /**
@@ -78,13 +98,18 @@
      * @param timeout The milliseconds to wait for an iteration of the benchmark before timing out.
      * @throws Exception If the benchmark could not be run.
      */
-    private void runBenchmark(Benchmark benchmark, int numFrames, int timeout, int target)
-            throws Exception {
+    private void runBenchmark(Benchmark benchmark,
+            boolean offscreen,
+            int numFrames,
+            int timeout,
+            int minFps,
+            int target) throws Exception {
         String benchmarkName = benchmark.toString();
         Intent intent = new Intent();
         intent.putExtra(GLActivity.INTENT_EXTRA_BENCHMARK_NAME, benchmarkName);
+        intent.putExtra(GLActivity.INTENT_EXTRA_OFFSCREEN, offscreen);
         intent.putExtra(GLActivity.INTENT_EXTRA_TIMEOUT, timeout);
-        intent.putExtra(GLActivity.INTENT_EXTRA_MIN_FPS, MIN_FPS);
+        intent.putExtra(GLActivity.INTENT_EXTRA_MIN_FPS, minFps);
         intent.putExtra(GLActivity.INTENT_EXTRA_NUM_FRAMES, numFrames);
 
         GLActivity activity = null;
@@ -94,9 +119,9 @@
             // Represents the maximum workload it can do whilst maintaining MIN_FPS.
             int workload = activity.waitForCompletion();
             if (workload < target) {
-                throw new Exception("Benchmark did not reach target. Got " + workload
-                        + ", target was " + target);
+                throw new Exception("Benchmark did not reach " + target + ", got " + workload);
             }
+            Log.i(GLActivity.TAG, "FPS Values: " + activity.fpsValues);
             getReportLog()
                     .printSummary("Workload", workload, ResultType.HIGHER_BETTER, ResultUnit.SCORE);
         } finally {
diff --git a/tests/AndroidManifest.xml b/tests/AndroidManifest.xml
index e9b802a..6a07ef8 100644
--- a/tests/AndroidManifest.xml
+++ b/tests/AndroidManifest.xml
@@ -427,6 +427,14 @@
             </intent-filter>
         </activity>
 
+        <activity android:name="android.text.cts.EmojiStubActivity"
+            android:label="AvailableIntentsActivity">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
+            </intent-filter>
+        </activity>
+
         <activity android:name="android.widget.cts.TableStubActivity"
             android:label="TableStubActivity">
             <intent-filter>
diff --git a/tests/src/android/text/EmojiStubActivity.java b/tests/src/android/text/EmojiStubActivity.java
new file mode 100755
index 0000000..1587c94
--- /dev/null
+++ b/tests/src/android/text/EmojiStubActivity.java
@@ -0,0 +1,44 @@
+/*
+ * 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.text.cts;
+
+import com.android.cts.stub.R;
+
+import android.app.Activity;
+import android.os.Bundle;
+import android.webkit.WebView;
+
+public class EmojiStubActivity extends Activity {
+    private WebView mWebView;
+
+    @Override
+    public void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.webview_layout);
+        mWebView = (WebView) findViewById(R.id.web_page);
+    }
+
+    public WebView getWebView() {
+        return mWebView;
+    }
+
+    @Override
+    public void onDestroy() {
+        mWebView.destroy();
+        super.onDestroy();
+    }
+}
diff --git a/tests/tests/net/src/android/net/cts/TrafficStatsTest.java b/tests/tests/net/src/android/net/cts/TrafficStatsTest.java
index a5bbd98..89933bf 100644
--- a/tests/tests/net/src/android/net/cts/TrafficStatsTest.java
+++ b/tests/tests/net/src/android/net/cts/TrafficStatsTest.java
@@ -42,19 +42,29 @@
                    TrafficStats.getMobileRxBytes() >= 0);
     }
 
+    long tcpPacketToIpBytes(long packetCount, long bytes) {
+        // ip header + tcp header + data.
+        // Tcp header is mostly 32. Syn has different tcp options -> 40. Don't care.
+        return packetCount * (20 + 32 + bytes);
+    }
+
     public void testTrafficStatsForLocalhost() throws IOException {
-        long mobileTxPacketsBefore = TrafficStats.getTotalTxPackets();
-        long mobileRxPacketsBefore = TrafficStats.getTotalRxPackets();
-        long mobileTxBytesBefore = TrafficStats.getTotalTxBytes();
-        long mobileRxBytesBefore = TrafficStats.getTotalRxBytes();
+        long mobileTxPacketsBefore = TrafficStats.getMobileTxPackets();
+        long mobileRxPacketsBefore = TrafficStats.getMobileRxPackets();
+        long mobileTxBytesBefore = TrafficStats.getMobileTxBytes();
+        long mobileRxBytesBefore = TrafficStats.getMobileRxBytes();
         long totalTxPacketsBefore = TrafficStats.getTotalTxPackets();
         long totalRxPacketsBefore = TrafficStats.getTotalRxPackets();
         long totalTxBytesBefore = TrafficStats.getTotalTxBytes();
         long totalRxBytesBefore = TrafficStats.getTotalRxBytes();
         long uidTxBytesBefore = TrafficStats.getUidTxBytes(Process.myUid());
         long uidRxBytesBefore = TrafficStats.getUidRxBytes(Process.myUid());
+        long uidTxPacketsBefore = TrafficStats.getUidTxPackets(Process.myUid());
+        long uidRxPacketsBefore = TrafficStats.getUidRxPackets(Process.myUid());
 
         // Transfer 1MB of data across an explicitly localhost socket.
+        final int byteCount = 1024;
+        final int packetCount = 1024;
 
         final ServerSocket server = new ServerSocket(0);
         new Thread("TrafficStatsTest.testTrafficStatsForLocalhost") {
@@ -62,9 +72,15 @@
             public void run() {
                 try {
                     Socket socket = new Socket("localhost", server.getLocalPort());
+                    // Make sure that each write()+flush() turns into a packet:
+                    // disable Nagle.
+                    socket.setTcpNoDelay(true);
                     OutputStream out = socket.getOutputStream();
-                    byte[] buf = new byte[1024];
-                    for (int i = 0; i < 1024; i++) out.write(buf);
+                    byte[] buf = new byte[byteCount];
+                    for (int i = 0; i < packetCount; i++) {
+                        out.write(buf);
+                        out.flush();
+                    }
                     out.close();
                     socket.close();
                 } catch (IOException e) {
@@ -75,9 +91,9 @@
         try {
             Socket socket = server.accept();
             InputStream in = socket.getInputStream();
-            byte[] buf = new byte[1024];
+            byte[] buf = new byte[byteCount];
             int read = 0;
-            while (read < 1048576) {
+            while (read < byteCount * packetCount) {
                 int n = in.read(buf);
                 assertTrue("Unexpected EOF", n > 0);
                 read += n;
@@ -92,50 +108,76 @@
         } catch (InterruptedException e) {
         }
 
-        long mobileTxPacketsAfter = TrafficStats.getTotalTxPackets();
-        long mobileRxPacketsAfter = TrafficStats.getTotalRxPackets();
-        long mobileTxBytesAfter = TrafficStats.getTotalTxBytes();
-        long mobileRxBytesAfter = TrafficStats.getTotalRxBytes();
+        long mobileTxPacketsAfter = TrafficStats.getMobileTxPackets();
+        long mobileRxPacketsAfter = TrafficStats.getMobileRxPackets();
+        long mobileTxBytesAfter = TrafficStats.getMobileTxBytes();
+        long mobileRxBytesAfter = TrafficStats.getMobileRxBytes();
         long totalTxPacketsAfter = TrafficStats.getTotalTxPackets();
         long totalRxPacketsAfter = TrafficStats.getTotalRxPackets();
         long totalTxBytesAfter = TrafficStats.getTotalTxBytes();
         long totalRxBytesAfter = TrafficStats.getTotalRxBytes();
         long uidTxBytesAfter = TrafficStats.getUidTxBytes(Process.myUid());
         long uidRxBytesAfter = TrafficStats.getUidRxBytes(Process.myUid());
-
-        // Localhost traffic should *not* count against mobile or total stats.
-        // There might be some other traffic, but nowhere near 1MB.
-
-        assertTrue("mtxp: " + mobileTxPacketsBefore + " -> " + mobileTxPacketsAfter,
-               mobileTxPacketsAfter >= mobileTxPacketsBefore &&
-               mobileTxPacketsAfter <= mobileTxPacketsBefore + 500);
-        assertTrue("mrxp: " + mobileRxPacketsBefore + " -> " + mobileRxPacketsAfter,
-               mobileRxPacketsAfter >= mobileRxPacketsBefore &&
-               mobileRxPacketsAfter <= mobileRxPacketsBefore + 500);
-        assertTrue("mtxb: " + mobileTxBytesBefore + " -> " + mobileTxBytesAfter,
-               mobileTxBytesAfter >= mobileTxBytesBefore &&
-               mobileTxBytesAfter <= mobileTxBytesBefore + 200000);
-        assertTrue("mrxb: " + mobileRxBytesBefore + " -> " + mobileRxBytesAfter,
-               mobileRxBytesAfter >= mobileRxBytesBefore &&
-               mobileRxBytesAfter <= mobileRxBytesBefore + 200000);
-
-        assertTrue("ttxp: " + totalTxPacketsBefore + " -> " + totalTxPacketsAfter,
-               totalTxPacketsAfter >= totalTxPacketsBefore &&
-               totalTxPacketsAfter <= totalTxPacketsBefore + 500);
-        assertTrue("trxp: " + totalRxPacketsBefore + " -> " + totalRxPacketsAfter,
-               totalRxPacketsAfter >= totalRxPacketsBefore &&
-               totalRxPacketsAfter <= totalRxPacketsBefore + 500);
-        assertTrue("ttxb: " + totalTxBytesBefore + " -> " + totalTxBytesAfter,
-               totalTxBytesAfter >= totalTxBytesBefore &&
-               totalTxBytesAfter <= totalTxBytesBefore + 200000);
-        assertTrue("trxb: " + totalRxBytesBefore + " -> " + totalRxBytesAfter,
-               totalRxBytesAfter >= totalRxBytesBefore &&
-               totalRxBytesAfter <= totalRxBytesBefore + 200000);
+        long uidTxPacketsAfter = TrafficStats.getUidTxPackets(Process.myUid());
+        long uidRxPacketsAfter = TrafficStats.getUidRxPackets(Process.myUid());
+        long uidTxDeltaBytes = uidTxBytesAfter - uidTxBytesBefore;
+        long uidTxDeltaPackets = uidTxPacketsAfter - uidTxPacketsBefore;
+        long uidRxDeltaBytes = uidRxBytesAfter - uidRxBytesBefore;
+        long uidRxDeltaPackets = uidRxPacketsAfter - uidRxPacketsBefore;
 
         // Localhost traffic *does* count against per-UID stats.
-        assertTrue("uidtxb: " + uidTxBytesBefore + " -> " + uidTxBytesAfter,
-               uidTxBytesAfter >= uidTxBytesBefore + 1048576);
-        assertTrue("uidrxb: " + uidRxBytesBefore + " -> " + uidRxBytesAfter,
-               uidRxBytesAfter >= uidRxBytesBefore + 1048576);
+        /*
+         * Calculations:
+         *  - bytes
+         *   bytes is approx: packets * data + packets * acks;
+         *   but sometimes there are less acks than packets, so we set a lower
+         *   limit of 1 ack.
+         *  - setup/teardown
+         *   + 7 approx.: syn, syn-ack, ack, fin-ack, ack, fin-ack, ack;
+         *   but sometimes the last find-acks just vanish, so we set a lower limit of +5.
+         */
+        assertTrue("uidtxp: " + uidTxPacketsBefore + " -> " + uidTxPacketsAfter + " delta=" + uidTxDeltaPackets,
+            uidTxDeltaPackets >= packetCount + 5 &&
+            uidTxDeltaPackets <= packetCount + packetCount + 7);
+        assertTrue("uidrxp: " + uidRxPacketsBefore + " -> " + uidRxPacketsAfter + " delta=" + uidRxDeltaPackets,
+            uidRxDeltaPackets >= packetCount + 5 &&
+            uidRxDeltaPackets <= packetCount + packetCount + 7);
+        assertTrue("uidtxb: " + uidTxBytesBefore + " -> " + uidTxBytesAfter + " delta=" + uidTxDeltaBytes,
+            uidTxDeltaBytes >= tcpPacketToIpBytes(packetCount, byteCount) + tcpPacketToIpBytes(5, 0) &&
+            uidTxDeltaBytes <= tcpPacketToIpBytes(packetCount, byteCount) + tcpPacketToIpBytes(packetCount + 7, 0));
+        assertTrue("uidrxb: " + uidRxBytesBefore + " -> " + uidRxBytesAfter + " delta=" + uidRxDeltaBytes,
+            uidRxDeltaBytes >= tcpPacketToIpBytes(packetCount, byteCount) + tcpPacketToIpBytes(5, 0) &&
+            uidRxDeltaBytes <= tcpPacketToIpBytes(packetCount, byteCount) + tcpPacketToIpBytes(packetCount + 7, 0));
+
+        // Localhost traffic *does* count against total stats.
+        // Fudge by 132 packets of 1500 bytes not related to the test.
+        assertTrue("ttxp: " + totalTxPacketsBefore + " -> " + totalTxPacketsAfter,
+            totalTxPacketsAfter >= totalTxPacketsBefore + uidTxDeltaPackets &&
+            totalTxPacketsAfter <= totalTxPacketsBefore + uidTxDeltaPackets + 132);
+        assertTrue("trxp: " + totalRxPacketsBefore + " -> " + totalRxPacketsAfter,
+            totalRxPacketsAfter >= totalRxPacketsBefore + uidRxDeltaPackets &&
+            totalRxPacketsAfter <= totalRxPacketsBefore + uidRxDeltaPackets + 132);
+        assertTrue("ttxb: " + totalTxBytesBefore + " -> " + totalTxBytesAfter,
+            totalTxBytesAfter >= totalTxBytesBefore + uidTxDeltaBytes &&
+            totalTxBytesAfter <= totalTxBytesBefore + uidTxDeltaBytes + 132 * 1500);
+        assertTrue("trxb: " + totalRxBytesBefore + " -> " + totalRxBytesAfter,
+            totalRxBytesAfter >= totalRxBytesBefore + uidRxDeltaBytes &&
+            totalRxBytesAfter <= totalRxBytesBefore + uidRxDeltaBytes + 132 * 1500);
+
+        // Localhost traffic should *not* count against mobile stats,
+        // There might be some other traffic, but nowhere near 1MB.
+        assertTrue("mtxp: " + mobileTxPacketsBefore + " -> " + mobileTxPacketsAfter,
+            mobileTxPacketsAfter >= mobileTxPacketsBefore &&
+            mobileTxPacketsAfter <= mobileTxPacketsBefore + 500);
+        assertTrue("mrxp: " + mobileRxPacketsBefore + " -> " + mobileRxPacketsAfter,
+            mobileRxPacketsAfter >= mobileRxPacketsBefore &&
+            mobileRxPacketsAfter <= mobileRxPacketsBefore + 500);
+        assertTrue("mtxb: " + mobileTxBytesBefore + " -> " + mobileTxBytesAfter,
+            mobileTxBytesAfter >= mobileTxBytesBefore &&
+            mobileTxBytesAfter <= mobileTxBytesBefore + 200000);
+        assertTrue("mrxb: " + mobileRxBytesBefore + " -> " + mobileRxBytesAfter,
+            mobileRxBytesAfter >= mobileRxBytesBefore &&
+            mobileRxBytesAfter <= mobileRxBytesBefore + 200000);
+
     }
 }
diff --git a/tests/tests/text/src/android/text/cts/EmojiConstants.java b/tests/tests/text/src/android/text/cts/EmojiConstants.java
new file mode 100755
index 0000000..dcae622
--- /dev/null
+++ b/tests/tests/text/src/android/text/cts/EmojiConstants.java
@@ -0,0 +1,759 @@
+/*
+ * 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.text.cts;
+
+/**
+ * List of Emoji tested by EmojiTest
+ */
+class EmojiConstants {
+
+    /*
+     * Emoji list from Unicode.org:
+     * http://unicode.org/cldr/utility/list-unicodeset.jsp?a=%5Cp%7BEmoji%7D%0D%0A&g=
+     */
+    static int[] emojiCodePoints = {
+        0x000A9, // COPYRIGHT SIGN
+        0x000AE, // REGISTERED SIGN
+        0x02002, // EN SPACE
+        0x02003, // EM SPACE
+        0x02005, // FOUR-PER-EM SPACE
+        0x0203C, // DOUBLE EXCLAMATION MARK
+        0x02049, // EXCLAMATION QUESTION MARK
+        0x020E3, // COMBINING ENCLOSING KEYCAP
+        0x02122, // TRADE MARK SIGN
+        0x02139, // INFORMATION SOURCE
+        0x02194, // LEFT RIGHT ARROW
+        0x02195, // UP DOWN ARROW
+        0x02196, // NORTH WEST ARROW
+        0x02197, // NORTH EAST ARROW
+        0x02198, // SOUTH EAST ARROW
+        0x02199, // SOUTH WEST ARROW
+        0x021A9, // LEFTWARDS ARROW WITH HOOK
+        0x021AA, // RIGHTWARDS ARROW WITH HOOK
+        0x0231A, // WATCH
+        0x0231B, // HOURGLASS
+        0x023E9, // BLACK RIGHT-POINTING DOUBLE TRIANGLE
+        0x023EA, // BLACK LEFT-POINTING DOUBLE TRIANGLE
+        0x023EB, // BLACK UP-POINTING DOUBLE TRIANGLE
+        0x023EC, // BLACK DOWN-POINTING DOUBLE TRIANGLE
+        0x023F0, // ALARM CLOCK
+        0x023F3, // HOURGLASS WITH FLOWING SAND
+        0x024C2, // CIRCLED LATIN CAPITAL LETTER M
+        0x025AA, // BLACK SMALL SQUARE
+        0x025AB, // WHITE SMALL SQUARE
+        0x025B6, // BLACK RIGHT-POINTING TRIANGLE
+        0x025C0, // BLACK LEFT-POINTING TRIANGLE
+        0x025FB, // WHITE MEDIUM SQUARE
+        0x025FC, // BLACK MEDIUM SQUARE
+        0x025FD, // WHITE MEDIUM SMALL SQUARE
+        0x025FE, // BLACK MEDIUM SMALL SQUARE
+        0x02600, // BLACK SUN WITH RAYS
+        0x02601, // CLOUD
+        0x0260E, // BLACK TELEPHONE
+        0x02611, // BALLOT BOX WITH CHECK
+        0x02615, // HOT BEVERAGE
+        0x02668, // HOT SPRINGS
+        0x0267F, // WHEELCHAIR SYMBOL
+        0x026A0, // WARNING SIGN
+        0x026A1, // HIGH VOLTAGE SIGN
+        0x02614, // UMBRELLA WITH RAIN DROPS
+        0x0261D, // WHITE UP POINTING INDEX
+        0x0263A, // WHITE SMILING FACE
+        0x02648, // ARIES
+        0x02649, // TAURUS
+        0x0264A, // GEMINI
+        0x0264B, // CANCER
+        0x0264C, // LEO
+        0x0264D, // VIRGO
+        0x0264E, // LIBRA
+        0x0264F, // SCORPIUS
+        0x02650, // SAGITTARIUS
+        0x02651, // CAPRICORN
+        0x02652, // AQUARIUS
+        0x02653, // PISCES
+        0x026CE, // OPHIUCHUS
+        0x02660, // BLACK SPADE SUIT
+        0x02663, // BLACK CLUB SUIT
+        0x02665, // BLACK HEART SUIT
+        0x02666, // BLACK DIAMOND SUIT
+        0x0267B, // BLACK UNIVERSAL RECYCLING SYMBOL
+        0x02693, // ANCHOR
+        0x026AA, // MEDIUM WHITE CIRCLE
+        0x026AB, // MEDIUM BLACK CIRCLE
+        0x026BD, // SOCCER BALL
+        0x026BE, // BASEBALL
+        0x026C4, // SNOWMAN WITHOUT SNOW
+        0x026C5, // SUN BEHIND CLOUD
+        0x026D4, // NO ENTRY
+        0x026EA, // CHURCH
+        0x026F2, // FOUNTAIN
+        0x026F3, // FLAG IN HOLE
+        0x026F5, // SAILBOAT
+        0x026FA, // TENT
+        0x026FD, // FUEL PUMP
+        0x02702, // BLACK SCISSORS
+        0x02705, // WHITE HEAVY CHECK MARK
+        0x02708, // AIRPLANE
+        0x02709, // ENVELOPE
+        0x0270A, // RAISED FIST
+        0x0270B, // RAISED HAND
+        0x0270C, // VICTORY HAND
+        0x0270F, // PENCIL
+        0x02712, // BLACK NIB
+        0x02714, // HEAVY CHECK MARK
+        0x02716, // HEAVY MULTIPLICATION X
+        0x0274C, // CROSS MARK
+        0x0274E, // NEGATIVE SQUARED CROSS MARK
+        0x02753, // BLACK QUESTION MARK ORNAMENT
+        0x02754, // WHITE QUESTION MARK ORNAMENT
+        0x02755, // WHITE EXCLAMATION MARK ORNAMENT
+        0x02757, // HEAVY EXCLAMATION MARK SYMBOL
+        0x027B0, // CURLY LOOP
+        0x027BF, // DOUBLE CURLY LOOP
+        0x02728, // SPARKLES
+        0x02733, // EIGHT SPOKED ASTERISK
+        0x02734, // EIGHT POINTED BLACK STAR
+        0x02744, // SNOWFLAKE
+        0x02747, // SPARKLE
+        0x02764, // HEAVY BLACK HEART
+        0x02795, // HEAVY PLUS SIGN
+        0x02796, // HEAVY MINUS SIGN
+        0x02797, // HEAVY DIVISION SIGN
+        0x027A1, // BLACK RIGHTWARDS ARROW
+        0x02934, // ARROW POINTING RIGHTWARDS THEN CURVING UPWARDS
+        0x02935, // ARROW POINTING RIGHTWARDS THEN CURVING DOWNWARDS
+        0x02B05, // LEFTWARDS BLACK ARROW
+        0x02B06, // UPWARDS BLACK ARROW
+        0x02B07, // DOWNWARDS BLACK ARROW
+        0x02B1B, // BLACK LARGE SQUARE
+        0x02B1C, // WHITE LARGE SQUARE
+        0x02B50, // WHITE MEDIUM STAR
+        0x02B55, // HEAVY LARGE CIRCLE
+        0x03030, // WAVY DASH
+        0x0303D, // PART ALTERNATION MARK
+        0x03297, // CIRCLED IDEOGRAPH CONGRATULATION
+        0x03299, // CIRCLED IDEOGRAPH SECRET
+        0x1F004, // MAHJONG TILE RED DRAGON
+        0x1F0CF, // PLAYING CARD BLACK JOKER
+        0x1F170, // NEGATIVE SQUARED LATIN CAPITAL LETTER A
+        0x1F171, // NEGATIVE SQUARED LATIN CAPITAL LETTER B
+        0x1F17E, // NEGATIVE SQUARED LATIN CAPITAL LETTER O
+        0x1F17F, // NEGATIVE SQUARED LATIN CAPITAL LETTER P
+        0x1F18E, // NEGATIVE SQUARED AB
+        0x1F191, // SQUARED CL
+        0x1F192, // SQUARED COOL
+        0x1F193, // SQUARED FREE
+        0x1F194, // SQUARED ID
+        0x1F195, // SQUARED NEW
+        0x1F196, // SQUARED NG
+        0x1F197, // SQUARED OK
+        0x1F198, // SQUARED SOS
+        0x1F199, // SQUARED UP WITH EXCLAMATION MARK
+        0x1F19A, // SQUARED VS
+        0x1F1E6, // REGIONAL INDICATOR SYMBOL LETTER A
+        0x1F1E7, // REGIONAL INDICATOR SYMBOL LETTER B
+        0x1F1E8, // REGIONAL INDICATOR SYMBOL LETTER C
+        0x1F1E9, // REGIONAL INDICATOR SYMBOL LETTER D
+        0x1F1EA, // REGIONAL INDICATOR SYMBOL LETTER E
+        0x1F1EB, // REGIONAL INDICATOR SYMBOL LETTER F
+        0x1F1EC, // REGIONAL INDICATOR SYMBOL LETTER G
+        0x1F1ED, // REGIONAL INDICATOR SYMBOL LETTER H
+        0x1F1EE, // REGIONAL INDICATOR SYMBOL LETTER I
+        0x1F1EF, // REGIONAL INDICATOR SYMBOL LETTER J
+        0x1F1F0, // REGIONAL INDICATOR SYMBOL LETTER K
+        0x1F1F1, // REGIONAL INDICATOR SYMBOL LETTER L
+        0x1F1F2, // REGIONAL INDICATOR SYMBOL LETTER M
+        0x1F1F3, // REGIONAL INDICATOR SYMBOL LETTER N
+        0x1F1F4, // REGIONAL INDICATOR SYMBOL LETTER O
+        0x1F1F5, // REGIONAL INDICATOR SYMBOL LETTER P
+        0x1F1F6, // REGIONAL INDICATOR SYMBOL LETTER Q
+        0x1F1F7, // REGIONAL INDICATOR SYMBOL LETTER R
+        0x1F1F8, // REGIONAL INDICATOR SYMBOL LETTER S
+        0x1F1F9, // REGIONAL INDICATOR SYMBOL LETTER T
+        0x1F1FA, // REGIONAL INDICATOR SYMBOL LETTER U
+        0x1F1FB, // REGIONAL INDICATOR SYMBOL LETTER V
+        0x1F1FC, // REGIONAL INDICATOR SYMBOL LETTER W
+        0x1F1FD, // REGIONAL INDICATOR SYMBOL LETTER X
+        0x1F1FE, // REGIONAL INDICATOR SYMBOL LETTER Y
+        0x1F1FF, // REGIONAL INDICATOR SYMBOL LETTER Z
+        0x1F201, // SQUARED KATAKANA KOKO
+        0x1F202, // SQUARED KATAKANA SA
+        0x1F21A, // SQUARED CJK UNIFIED IDEOGRAPH-7121
+        0x1F22F, // SQUARED CJK UNIFIED IDEOGRAPH-6307
+        0x1F232, // SQUARED CJK UNIFIED IDEOGRAPH-7981
+        0x1F233, // SQUARED CJK UNIFIED IDEOGRAPH-7A7A
+        0x1F234, // SQUARED CJK UNIFIED IDEOGRAPH-5408
+        0x1F235, // SQUARED CJK UNIFIED IDEOGRAPH-6E80
+        0x1F236, // SQUARED CJK UNIFIED IDEOGRAPH-6709
+        0x1F237, // SQUARED CJK UNIFIED IDEOGRAPH-6708
+        0x1F238, // SQUARED CJK UNIFIED IDEOGRAPH-7533
+        0x1F239, // SQUARED CJK UNIFIED IDEOGRAPH-5272
+        0x1F23A, // SQUARED CJK UNIFIED IDEOGRAPH-55B6
+        0x1F250, // CIRCLED IDEOGRAPH ADVANTAGE
+        0x1F251, // CIRCLED IDEOGRAPH ACCEPT
+        0x1F300, // CYCLONE
+        0x1F301, // FOGGY
+        0x1F302, // CLOSED UMBRELLA
+        0x1F303, // NIGHT WITH STARS
+        0x1F304, // SUNRISE OVER MOUNTAINS
+        0x1F305, // SUNRISE
+        0x1F306, // CITYSCAPE AT DUSK
+        0x1F307, // SUNSET OVER BUILDINGS
+        0x1F308, // RAINBOW
+        0x1F309, // BRIDGE AT NIGHT
+        0x1F30A, // WATER WAVE
+        0x1F30B, // VOLCANO
+        0x1F30C, // MILKY WAY
+        0x1F30F, // EARTH GLOBE ASIA-AUSTRALIA
+        0x1F311, // NEW MOON SYMBOL
+        0x1F313, // FIRST QUARTER MOON SYMBOL
+        0x1F314, // WAXING GIBBOUS MOON SYMBOL
+        0x1F315, // FULL MOON SYMBOL
+        0x1F319, // CRESCENT MOON
+        0x1F31B, // FIRST QUARTER MOON WITH FACE
+        0x1F31F, // GLOWING STAR
+        0x1F320, // SHOOTING STAR
+        0x1F330, // CHESTNUT
+        0x1F331, // SEEDLING
+        0x1F334, // PALM TREE
+        0x1F335, // CACTUS
+        0x1F337, // TULIP
+        0x1F338, // CHERRY BLOSSOM
+        0x1F339, // ROSE
+        0x1F33A, // HIBISCUS
+        0x1F33B, // SUNFLOWER
+        0x1F33C, // BLOSSOM
+        0x1F33D, // EAR OF MAIZE
+        0x1F33E, // EAR OF RICE
+        0x1F33F, // HERB
+        0x1F340, // FOUR LEAF CLOVER
+        0x1F341, // MAPLE LEAF
+        0x1F342, // FALLEN LEAF
+        0x1F343, // LEAF FLUTTERING IN WIND
+        0x1F344, // MUSHROOM
+        0x1F345, // TOMATO
+        0x1F346, // AUBERGINE
+        0x1F347, // GRAPES
+        0x1F348, // MELON
+        0x1F349, // WATERMELON
+        0x1F34A, // TANGERINE
+        0x1F34C, // BANANA
+        0x1F34D, // PINEAPPLE
+        0x1F34E, // RED APPLE
+        0x1F34F, // GREEN APPLE
+        0x1F351, // PEACH
+        0x1F352, // CHERRIES
+        0x1F353, // STRAWBERRY
+        0x1F354, // HAMBURGER
+        0x1F355, // SLICE OF PIZZA
+        0x1F356, // MEAT ON BONE
+        0x1F357, // POULTRY LEG
+        0x1F358, // RICE CRACKER
+        0x1F359, // RICE BALL
+        0x1F35A, // COOKED RICE
+        0x1F35B, // CURRY AND RICE
+        0x1F35C, // STEAMING BOWL
+        0x1F35D, // SPAGHETTI
+        0x1F35E, // BREAD
+        0x1F35F, // FRENCH FRIES
+        0x1F360, // ROASTED SWEET POTATO
+        0x1F361, // DANGO
+        0x1F362, // ODEN
+        0x1F363, // SUSHI
+        0x1F364, // FRIED SHRIMP
+        0x1F365, // FISH CAKE WITH SWIRL DESIGN
+        0x1F366, // SOFT ICE CREAM
+        0x1F367, // SHAVED ICE
+        0x1F368, // ICE CREAM
+        0x1F369, // DOUGHNUT
+        0x1F36A, // COOKIE
+        0x1F36B, // CHOCOLATE BAR
+        0x1F36C, // CANDY
+        0x1F36D, // LOLLIPOP
+        0x1F36E, // CUSTARD
+        0x1F36F, // HONEY POT
+        0x1F370, // SHORTCAKE
+        0x1F371, // BENTO BOX
+        0x1F372, // POT OF FOOD
+        0x1F373, // COOKING
+        0x1F374, // FORK AND KNIFE
+        0x1F375, // TEACUP WITHOUT HANDLE
+        0x1F376, // SAKE BOTTLE AND CUP
+        0x1F377, // WINE GLASS
+        0x1F378, // COCKTAIL GLASS
+        0x1F379, // TROPICAL DRINK
+        0x1F37A, // BEER MUG
+        0x1F37B, // CLINKING BEER MUGS
+        0x1F380, // RIBBON
+        0x1F381, // WRAPPED PRESENT
+        0x1F382, // BIRTHDAY CAKE
+        0x1F383, // JACK-O-LANTERN
+        0x1F384, // CHRISTMAS TREE
+        0x1F385, // FATHER CHRISTMAS
+        0x1F386, // FIREWORKS
+        0x1F387, // FIREWORK SPARKLER
+        0x1F388, // BALLOON
+        0x1F389, // PARTY POPPER
+        0x1F38A, // CONFETTI BALL
+        0x1F38B, // TANABATA TREE
+        0x1F38C, // CROSSED FLAGS
+        0x1F38D, // PINE DECORATION
+        0x1F38E, // JAPANESE DOLLS
+        0x1F38F, // CARP STREAMER
+        0x1F390, // WIND CHIME
+        0x1F391, // MOON VIEWING CEREMONY
+        0x1F392, // SCHOOL SATCHEL
+        0x1F393, // GRADUATION CAP
+        0x1F3A0, // CAROUSEL HORSE
+        0x1F3A1, // FERRIS WHEEL
+        0x1F3A2, // ROLLER COASTER
+        0x1F3A3, // FISHING POLE AND FISH
+        0x1F3A4, // MICROPHONE
+        0x1F3A5, // MOVIE CAMERA
+        0x1F3A6, // CINEMA
+        0x1F3A7, // HEADPHONE
+        0x1F3A8, // ARTIST PALETTE
+        0x1F3A9, // TOP HAT
+        0x1F3AA, // CIRCUS TENT
+        0x1F3AB, // TICKET
+        0x1F3AC, // CLAPPER BOARD
+        0x1F3AD, // PERFORMING ARTS
+        0x1F3AE, // VIDEO GAME
+        0x1F3AF, // DIRECT HIT
+        0x1F3B0, // SLOT MACHINE
+        0x1F3B1, // BILLIARDS
+        0x1F3B2, // GAME DIE
+        0x1F3B3, // BOWLING
+        0x1F3B4, // FLOWER PLAYING CARDS
+        0x1F3B5, // MUSICAL NOTE
+        0x1F3B6, // MULTIPLE MUSICAL NOTES
+        0x1F3B7, // SAXOPHONE
+        0x1F3B8, // GUITAR
+        0x1F3B9, // MUSICAL KEYBOARD
+        0x1F3BA, // TRUMPET
+        0x1F3BB, // VIOLIN
+        0x1F3BC, // MUSICAL SCORE
+        0x1F3BD, // RUNNING SHIRT WITH SASH
+        0x1F3BE, // TENNIS RACQUET AND BALL
+        0x1F3BF, // SKI AND SKI BOOT
+        0x1F3C0, // BASKETBALL AND HOOP
+        0x1F3C1, // CHEQUERED FLAG
+        0x1F3C2, // SNOWBOARDER
+        0x1F3C3, // RUNNER
+        0x1F3C4, // SURFER
+        0x1F3C6, // TROPHY
+        0x1F3C8, // AMERICAN FOOTBALL
+        0x1F3CA, // SWIMMER
+        0x1F3E0, // HOUSE BUILDING
+        0x1F3E1, // HOUSE WITH GARDEN
+        0x1F3E2, // OFFICE BUILDING
+        0x1F3E3, // JAPANESE POST OFFICE
+        0x1F3E5, // HOSPITAL
+        0x1F3E6, // BANK
+        0x1F3E7, // AUTOMATED TELLER MACHINE
+        0x1F3E8, // HOTEL
+        0x1F3E9, // LOVE HOTEL
+        0x1F3EA, // CONVENIENCE STORE
+        0x1F3EB, // SCHOOL
+        0x1F3EC, // DEPARTMENT STORE
+        0x1F3ED, // FACTORY
+        0x1F3EE, // IZAKAYA LANTERN
+        0x1F3EF, // JAPANESE CASTLE
+        0x1F3F0, // EUROPEAN CASTLE
+        0x1F40C, // SNAIL
+        0x1F40D, // SNAKE
+        0x1F40E, // HORSE
+        0x1F411, // SHEEP
+        0x1F412, // MONKEY
+        0x1F414, // CHICKEN
+        0x1F417, // BOAR
+        0x1F418, // ELEPHANT
+        0x1F419, // OCTOPUS
+        0x1F41A, // SPIRAL SHELL
+        0x1F41B, // BUG
+        0x1F41C, // ANT
+        0x1F41D, // HONEYBEE
+        0x1F41E, // LADY BEETLE
+        0x1F41F, // FISH
+        0x1F420, // TROPICAL FISH
+        0x1F421, // BLOWFISH
+        0x1F422, // TURTLE
+        0x1F423, // HATCHING CHICK
+        0x1F424, // BABY CHICK
+        0x1F425, // FRONT-FACING BABY CHICK
+        0x1F426, // BIRD
+        0x1F427, // PENGUIN
+        0x1F428, // KOALA
+        0x1F429, // POODLE
+        0x1F42B, // BACTRIAN CAMEL
+        0x1F42C, // DOLPHIN
+        0x1F42D, // MOUSE FACE
+        0x1F42E, // COW FACE
+        0x1F42F, // TIGER FACE
+        0x1F430, // RABBIT FACE
+        0x1F431, // CAT FACE
+        0x1F432, // DRAGON FACE
+        0x1F433, // SPOUTING WHALE
+        0x1F434, // HORSE FACE
+        0x1F435, // MONKEY FACE
+        0x1F436, // DOG FACE
+        0x1F437, // PIG FACE
+        0x1F438, // FROG FACE
+        0x1F439, // HAMSTER FACE
+        0x1F43A, // WOLF FACE
+        0x1F43B, // BEAR FACE
+        0x1F43C, // PANDA FACE
+        0x1F43D, // PIG NOSE
+        0x1F43E, // PAW PRINTS
+        0x1F440, // EYES
+        0x1F442, // EAR
+        0x1F443, // NOSE
+        0x1F444, // MOUTH
+        0x1F445, // TONGUE
+        0x1F446, // WHITE UP POINTING BACKHAND INDEX
+        0x1F447, // WHITE DOWN POINTING BACKHAND INDEX
+        0x1F448, // WHITE LEFT POINTING BACKHAND INDEX
+        0x1F449, // WHITE RIGHT POINTING BACKHAND INDEX
+        0x1F44A, // FISTED HAND SIGN
+        0x1F44B, // WAVING HAND SIGN
+        0x1F44C, // OK HAND SIGN
+        0x1F44D, // THUMBS UP SIGN
+        0x1F44E, // THUMBS DOWN SIGN
+        0x1F44F, // CLAPPING HANDS SIGN
+        0x1F450, // OPEN HANDS SIGN
+        0x1F451, // CROWN
+        0x1F452, // WOMANS HAT
+        0x1F453, // EYEGLASSES
+        0x1F454, // NECKTIE
+        0x1F455, // T-SHIRT
+        0x1F456, // JEANS
+        0x1F457, // DRESS
+        0x1F458, // KIMONO
+        0x1F459, // BIKINI
+        0x1F45A, // WOMANS CLOTHES
+        0x1F45B, // PURSE
+        0x1F45C, // HANDBAG
+        0x1F45D, // POUCH
+        0x1F45E, // MANS SHOE
+        0x1F45F, // ATHLETIC SHOE
+        0x1F460, // HIGH-HEELED SHOE
+        0x1F461, // WOMANS SANDAL
+        0x1F462, // WOMANS BOOTS
+        0x1F463, // FOOTPRINTS
+        0x1F464, // BUST IN SILHOUETTE
+        0x1F466, // BOY
+        0x1F467, // GIRL
+        0x1F468, // MAN
+        0x1F469, // WOMAN
+        0x1F46A, // FAMILY
+        0x1F46B, // MAN AND WOMAN HOLDING HANDS
+        0x1F46E, // POLICE OFFICER
+        0x1F46F, // WOMAN WITH BUNNY EARS
+        0x1F470, // BRIDE WITH VEIL
+        0x1F471, // PERSON WITH BLOND HAIR
+        0x1F472, // MAN WITH GUA PI MAO
+        0x1F473, // MAN WITH TURBAN
+        0x1F474, // OLDER MAN
+        0x1F475, // OLDER WOMAN
+        0x1F476, // BABY
+        0x1F477, // CONSTRUCTION WORKER
+        0x1F478, // PRINCESS
+        0x1F479, // JAPANESE OGRE
+        0x1F47A, // JAPANESE GOBLIN
+        0x1F47B, // GHOST
+        0x1F47C, // BABY ANGEL
+        0x1F47D, // EXTRATERRESTRIAL ALIEN
+        0x1F47E, // ALIEN MONSTER
+        0x1F47F, // IMP
+        0x1F480, // SKULL
+        0x1F481, // INFORMATION DESK PERSON
+        0x1F482, // GUARDSMAN
+        0x1F483, // DANCER
+        0x1F484, // LIPSTICK
+        0x1F485, // NAIL POLISH
+        0x1F486, // FACE MASSAGE
+        0x1F487, // HAIRCUT
+        0x1F488, // BARBER POLE
+        0x1F489, // SYRINGE
+        0x1F48A, // PILL
+        0x1F48B, // KISS MARK
+        0x1F48C, // LOVE LETTER
+        0x1F48D, // RING
+        0x1F48E, // GEM STONE
+        0x1F48F, // KISS
+        0x1F490, // BOUQUET
+        0x1F491, // COUPLE WITH HEART
+        0x1F492, // WEDDING
+        0x1F493, // BEATING HEART
+        0x1F494, // BROKEN HEART
+        0x1F495, // TWO HEARTS
+        0x1F496, // SPARKLING HEART
+        0x1F497, // GROWING HEART
+        0x1F498, // HEART WITH ARROW
+        0x1F499, // BLUE HEART
+        0x1F49A, // GREEN HEART
+        0x1F49B, // YELLOW HEART
+        0x1F49C, // PURPLE HEART
+        0x1F49D, // HEART WITH RIBBON
+        0x1F49E, // REVOLVING HEARTS
+        0x1F49F, // HEART DECORATION
+        0x1F4A0, // DIAMOND SHAPE WITH A DOT INSIDE
+        0x1F4A1, // ELECTRIC LIGHT BULB
+        0x1F4A2, // ANGER SYMBOL
+        0x1F4A3, // BOMB
+        0x1F4A4, // SLEEPING SYMBOL
+        0x1F4A5, // COLLISION SYMBOL
+        0x1F4A6, // SPLASHING SWEAT SYMBOL
+        0x1F4A7, // DROPLET
+        0x1F4A8, // DASH SYMBOL
+        0x1F4A9, // PILE OF POO
+        0x1F4AA, // FLEXED BICEPS
+        0x1F4AB, // DIZZY SYMBOL
+        0x1F4AC, // SPEECH BALLOON
+        0x1F4AE, // WHITE FLOWER
+        0x1F4AF, // HUNDRED POINTS SYMBOL
+        0x1F4B0, // MONEY BAG
+        0x1F4B1, // CURRENCY EXCHANGE
+        0x1F4B2, // HEAVY DOLLAR SIGN
+        0x1F4B3, // CREDIT CARD
+        0x1F4B4, // BANKNOTE WITH YEN SIGN
+        0x1F4B5, // BANKNOTE WITH DOLLAR SIGN
+        0x1F4B8, // MONEY WITH WINGS
+        0x1F4B9, // CHART WITH UPWARDS TREND AND YEN SIGN
+        0x1F4BA, // SEAT
+        0x1F4BB, // PERSONAL COMPUTER
+        0x1F4BC, // BRIEFCASE
+        0x1F4BD, // MINIDISC
+        0x1F4BE, // FLOPPY DISK
+        0x1F4BF, // OPTICAL DISC
+        0x1F4C0, // DVD
+        0x1F4C1, // FILE FOLDER
+        0x1F4C2, // OPEN FILE FOLDER
+        0x1F4C3, // PAGE WITH CURL
+        0x1F4C4, // PAGE FACING UP
+        0x1F4C5, // CALENDAR
+        0x1F4C6, // TEAR-OFF CALENDAR
+        0x1F4C7, // CARD INDEX
+        0x1F4C8, // CHART WITH UPWARDS TREND
+        0x1F4C9, // CHART WITH DOWNWARDS TREND
+        0x1F4CA, // BAR CHART
+        0x1F4CB, // CLIPBOARD
+        0x1F4CC, // PUSHPIN
+        0x1F4CD, // ROUND PUSHPIN
+        0x1F4CE, // PAPERCLIP
+        0x1F4CF, // STRAIGHT RULER
+        0x1F4D0, // TRIANGULAR RULER
+        0x1F4D1, // BOOKMARK TABS
+        0x1F4D2, // LEDGER
+        0x1F4D3, // NOTEBOOK
+        0x1F4D4, // NOTEBOOK WITH DECORATIVE COVER
+        0x1F4D5, // CLOSED BOOK
+        0x1F4D6, // OPEN BOOK
+        0x1F4D7, // GREEN BOOK
+        0x1F4D8, // BLUE BOOK
+        0x1F4D9, // ORANGE BOOK
+        0x1F4DA, // BOOKS
+        0x1F4DB, // NAME BADGE
+        0x1F4DC, // SCROLL
+        0x1F4DD, // MEMO
+        0x1F4DE, // TELEPHONE RECEIVER
+        0x1F4DF, // PAGER
+        0x1F4E0, // FAX MACHINE
+        0x1F4E1, // SATELLITE ANTENNA
+        0x1F4E2, // PUBLIC ADDRESS LOUDSPEAKER
+        0x1F4E3, // CHEERING MEGAPHONE
+        0x1F4E4, // OUTBOX TRAY
+        0x1F4E5, // INBOX TRAY
+        0x1F4E6, // PACKAGE
+        0x1F4E7, // E-MAIL SYMBOL
+        0x1F4E8, // INCOMING ENVELOPE
+        0x1F4E9, // ENVELOPE WITH DOWNWARDS ARROW ABOVE
+        0x1F4EA, // CLOSED MAILBOX WITH LOWERED FLAG
+        0x1F4EB, // CLOSED MAILBOX WITH RAISED FLAG
+        0x1F4EE, // POSTBOX
+        0x1F4F0, // NEWSPAPER
+        0x1F4F1, // MOBILE PHONE
+        0x1F4F2, // MOBILE PHONE WITH RIGHTWARDS ARROW AT LEFT
+        0x1F4F3, // VIBRATION MODE
+        0x1F4F4, // MOBILE PHONE OFF
+        0x1F4F6, // ANTENNA WITH BARS
+        0x1F4F7, // CAMERA
+        0x1F4F9, // VIDEO CAMERA
+        0x1F4FA, // TELEVISION
+        0x1F4FB, // RADIO
+        0x1F4FC, // VIDEOCASSETTE
+        0x1F503, // CLOCKWISE DOWNWARDS AND UPWARDS OPEN CIRCLE ARROWS
+        0x1F50A, // SPEAKER WITH THREE SOUND WAVES
+        0x1F50B, // BATTERY
+        0x1F50C, // ELECTRIC PLUG
+        0x1F50D, // LEFT-POINTING MAGNIFYING GLASS
+        0x1F50E, // RIGHT-POINTING MAGNIFYING GLASS
+        0x1F50F, // LOCK WITH INK PEN
+        0x1F510, // CLOSED LOCK WITH KEY
+        0x1F511, // KEY
+        0x1F512, // LOCK
+        0x1F513, // OPEN LOCK
+        0x1F514, // BELL
+        0x1F516, // BOOKMARK
+        0x1F517, // LINK SYMBOL
+        0x1F518, // RADIO BUTTON
+        0x1F53A, // UP-POINTING RED TRIANGLE
+        0x1F53B, // DOWN-POINTING RED TRIANGLE
+        0x1F53C, // UP-POINTING SMALL RED TRIANGLE
+        0x1F53D, // DOWN-POINTING SMALL RED TRIANGLE
+        0x1F519, // BACK WITH LEFTWARDS ARROW ABOVE
+        0x1F51A, // END WITH LEFTWARDS ARROW ABOVE
+        0x1F51B, // ON WITH EXCLAMATION MARK WITH LEFT RIGHT ARROW ABOVE
+        0x1F51C, // SOON WITH RIGHTWARDS ARROW ABOVE
+        0x1F51D, // TOP WITH UPWARDS ARROW ABOVE
+        0x1F51E, // NO ONE UNDER EIGHTEEN SYMBOL
+        0x1F51F, // KEYCAP TEN
+        0x1F520, // INPUT SYMBOL FOR LATIN CAPITAL LETTERS
+        0x1F521, // INPUT SYMBOL FOR LATIN SMALL LETTERS
+        0x1F522, // INPUT SYMBOL FOR NUMBERS
+        0x1F523, // INPUT SYMBOL FOR SYMBOLS
+        0x1F524, // INPUT SYMBOL FOR LATIN LETTERS
+        0x1F525, // FIRE
+        0x1F526, // ELECTRIC TORCH
+        0x1F527, // WRENCH
+        0x1F528, // HAMMER
+        0x1F529, // NUT AND BOLT
+        0x1F52A, // HOCHO
+        0x1F52B, // PISTOL
+        0x1F52E, // CRYSTAL BALL
+        0x1F52F, // SIX POINTED STAR WITH MIDDLE DOT
+        0x1F530, // JAPANESE SYMBOL FOR BEGINNER
+        0x1F531, // TRIDENT EMBLEM
+        0x1F532, // BLACK SQUARE BUTTON
+        0x1F533, // WHITE SQUARE BUTTON
+        0x1F534, // LARGE RED CIRCLE
+        0x1F535, // LARGE BLUE CIRCLE
+        0x1F536, // LARGE ORANGE DIAMOND
+        0x1F537, // LARGE BLUE DIAMOND
+        0x1F538, // SMALL ORANGE DIAMOND
+        0x1F539, // SMALL BLUE DIAMOND
+        0x1F550, // CLOCK FACE ONE OCLOCK
+        0x1F551, // CLOCK FACE TWO OCLOCK
+        0x1F552, // CLOCK FACE THREE OCLOCK
+        0x1F553, // CLOCK FACE FOUR OCLOCK
+        0x1F554, // CLOCK FACE FIVE OCLOCK
+        0x1F555, // CLOCK FACE SIX OCLOCK
+        0x1F556, // CLOCK FACE SEVEN OCLOCK
+        0x1F557, // CLOCK FACE EIGHT OCLOCK
+        0x1F558, // CLOCK FACE NINE OCLOCK
+        0x1F559, // CLOCK FACE TEN OCLOCK
+        0x1F55A, // CLOCK FACE ELEVEN OCLOCK
+        0x1F55B, // CLOCK FACE TWELVE OCLOCK
+        0x1F5FB, // MOUNT FUJI
+        0x1F5FC, // TOKYO TOWER
+        0x1F5FD, // STATUE OF LIBERTY
+        0x1F5FE, // SILHOUETTE OF JAPAN
+        0x1F5FF, // MOYAI
+        0x1F601, // GRINNING FACE WITH SMILING EYES
+        0x1F602, // FACE WITH TEARS OF JOY
+        0x1F603, // SMILING FACE WITH OPEN MOUTH
+        0x1F604, // SMILING FACE WITH OPEN MOUTH AND SMILING EYES
+        0x1F605, // SMILING FACE WITH OPEN MOUTH AND COLD SWEAT
+        0x1F606, // SMILING FACE WITH OPEN MOUTH AND TIGHTLY-CLOSED EYES
+        0x1F609, // WINKING FACE
+        0x1F60A, // SMILING FACE WITH SMILING EYES
+        0x1F60B, // FACE SAVOURING DELICIOUS FOOD
+        0x1F60C, // RELIEVED FACE
+        0x1F60D, // SMILING FACE WITH HEART-SHAPED EYES
+        0x1F60F, // SMIRKING FACE
+        0x1F612, // UNAMUSED FACE
+        0x1F613, // FACE WITH COLD SWEAT
+        0x1F614, // PENSIVE FACE
+        0x1F616, // CONFOUNDED FACE
+        0x1F618, // FACE THROWING A KISS
+        0x1F61A, // KISSING FACE WITH CLOSED EYES
+        0x1F61C, // FACE WITH STUCK-OUT TONGUE AND WINKING EYE
+        0x1F61D, // FACE WITH STUCK-OUT TONGUE AND TIGHTLY-CLOSED EYES
+        0x1F61E, // DISAPPOINTED FACE
+        0x1F620, // ANGRY FACE
+        0x1F621, // POUTING FACE
+        0x1F622, // CRYING FACE
+        0x1F623, // PERSEVERING FACE
+        0x1F624, // FACE WITH LOOK OF TRIUMPH
+        0x1F625, // DISAPPOINTED BUT RELIEVED FACE
+        0x1F628, // FEARFUL FACE
+        0x1F629, // WEARY FACE
+        0x1F62A, // SLEEPY FACE
+        0x1F62B, // TIRED FACE
+        0x1F62D, // LOUDLY CRYING FACE
+        0x1F630, // FACE WITH OPEN MOUTH AND COLD SWEAT
+        0x1F631, // FACE SCREAMING IN FEAR
+        0x1F632, // ASTONISHED FACE
+        0x1F633, // FLUSHED FACE
+        0x1F635, // DIZZY FACE
+        0x1F637, // FACE WITH MEDICAL MASK
+        0x1F638, // GRINNING CAT FACE WITH SMILING EYES
+        0x1F639, // CAT FACE WITH TEARS OF JOY
+        0x1F63A, // SMILING CAT FACE WITH OPEN MOUTH
+        0x1F63B, // SMILING CAT FACE WITH HEART-SHAPED EYES
+        0x1F63C, // CAT FACE WITH WRY SMILE
+        0x1F63D, // KISSING CAT FACE WITH CLOSED EYES
+        0x1F63E, // POUTING CAT FACE
+        0x1F63F, // CRYING CAT FACE
+        0x1F640, // WEARY CAT FACE
+        0x1F645, // FACE WITH NO GOOD GESTURE
+        0x1F646, // FACE WITH OK GESTURE
+        0x1F647, // PERSON BOWING DEEPLY
+        0x1F648, // SEE-NO-EVIL MONKEY
+        0x1F649, // HEAR-NO-EVIL MONKEY
+        0x1F64A, // SPEAK-NO-EVIL MONKEY
+        0x1F64B, // HAPPY PERSON RAISING ONE HAND
+        0x1F64C, // PERSON RAISING BOTH HANDS IN CELEBRATION
+        0x1F64D, // PERSON FROWNING
+        0x1F64E, // PERSON WITH POUTING FACE
+        0x1F64F, // PERSON WITH FOLDED HANDS
+        0x1F680, // ROCKET
+        0x1F683, // RAILWAY CAR
+        0x1F684, // HIGH-SPEED TRAIN
+        0x1F685, // HIGH-SPEED TRAIN WITH BULLET NOSE
+        0x1F687, // METRO
+        0x1F689, // STATION
+        0x1F68C, // BUS
+        0x1F68F, // BUS STOP
+        0x1F691, // AMBULANCE
+        0x1F692, // FIRE ENGINE
+        0x1F693, // POLICE CAR
+        0x1F695, // TAXI
+        0x1F697, // AUTOMOBILE
+        0x1F699, // RECREATIONAL VEHICLE
+        0x1F69A, // DELIVERY TRUCK
+        0x1F6A2, // SHIP
+        0x1F6A4, // SPEEDBOAT
+        0x1F6A5, // HORIZONTAL TRAFFIC LIGHT
+        0x1F6A7, // CONSTRUCTION SIGN
+        0x1F6A8, // POLICE CARS REVOLVING LIGHT
+        0x1F6A9, // TRIANGULAR FLAG ON POST
+        0x1F6AA, // DOOR
+        0x1F6AB, // NO ENTRY SIGN
+        0x1F6AC, // SMOKING SYMBOL
+        0x1F6AD, // NO SMOKING SYMBOL
+        0x1F6B2, // BICYCLE
+        0x1F6B6, // PEDESTRIAN
+        0x1F6B9, // MENS SYMBOL
+        0x1F6BA, // WOMENS SYMBOL
+        0x1F6BB, // RESTROOM
+        0x1F6BC, // BABY SYMBOL
+        0x1F6BD, // TOILET
+        0x1F6BE, // WATER CLOSET
+        0x1F6C0  // BAT
+    };
+}
diff --git a/tests/tests/text/src/android/text/cts/EmojiTest.java b/tests/tests/text/src/android/text/cts/EmojiTest.java
new file mode 100755
index 0000000..867cb8d
--- /dev/null
+++ b/tests/tests/text/src/android/text/cts/EmojiTest.java
@@ -0,0 +1,248 @@
+/*
+ * 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.text.cts;
+
+import android.content.Context;
+import android.graphics.Bitmap;
+import android.graphics.Canvas;
+import android.graphics.Paint;
+import android.graphics.Picture;
+import android.test.ActivityInstrumentationTestCase2;
+import android.view.KeyEvent;
+import android.view.Menu;
+import android.view.View;
+import android.webkit.WebView;
+import android.widget.TextView;
+import android.widget.EditText;
+
+public class EmojiTest extends ActivityInstrumentationTestCase2<EmojiStubActivity> {
+
+    public EmojiTest() {
+        super("com.android.cts.stub", EmojiStubActivity.class);
+    }
+
+    protected void setUp() throws Exception {
+        super.setUp();
+    }
+
+    protected void tearDown() throws Exception {
+        super.tearDown();
+    }
+
+    /**
+     * Tests all Emoji are defined in Character class
+     */
+    public void testEmojiCodePoints() {
+        for (int i = 0; i < EmojiConstants.emojiCodePoints.length; i++) {
+            assertTrue(Character.isDefined(EmojiConstants.emojiCodePoints[i]));
+        }
+    }
+
+    /**
+     * Tests Emoji has different glyph for different meaning characters.
+     * Test on Canvas, TextView, EditText and WebView
+     */
+    public void testEmojiGlyph() {
+        CaptureCanvas ccanvas = new CaptureCanvas(getInstrumentation().getContext());
+        CaptureWebView cwebview = new CaptureWebView(getInstrumentation().getContext());
+
+        Bitmap mBitmapA, mBitmapB;  // Emoji displayed Bitmaps to compare
+
+        int comparedCodePoints[][] = {   // Emojis should have different characters
+            {0x1F436, 0x1F435},      // Dog(U+1F436) and Monkey(U+1F435)
+            {0x26BD, 0x26BE},        // Soccer ball(U+26BD) and Baseball(U+26BE)
+            {0x1F47B, 0x1F381},      // Ghost(U+1F47B) and wrapped present(U+1F381)
+            {0x2764, 0x1F494},       // Heavy black heart(U+2764) and broken heart(U+1F494)
+            {0x1F603, 0x1F33B}       // Smiling face with open mouth(U+1F603) and sunflower(U+1F33B)
+        };
+
+        for (int i = 0; i < comparedCodePoints.length; i++) {
+
+            mBitmapA = ccanvas.capture(Character.toChars(comparedCodePoints[i][0]));
+            mBitmapB = ccanvas.capture(Character.toChars(comparedCodePoints[i][1]));
+
+            assertFalse(mBitmapA.sameAs(mBitmapB));
+
+            // cannot reuse CaptureTextView as 2nd setText call throws NullPointerException
+            CaptureTextView cviewA = new CaptureTextView(getInstrumentation().getContext());
+            mBitmapA = cviewA.capture(Character.toChars(comparedCodePoints[i][0]));
+            CaptureTextView cviewB = new CaptureTextView(getInstrumentation().getContext());
+            mBitmapB = cviewB.capture(Character.toChars(comparedCodePoints[i][1]));
+
+            assertFalse(mBitmapA.sameAs(mBitmapB));
+
+            CaptureEditText cedittextA = new CaptureEditText(getInstrumentation().getContext());
+            mBitmapA = cedittextA.capture(Character.toChars(comparedCodePoints[i][0]));
+            CaptureEditText cedittextB = new CaptureEditText(getInstrumentation().getContext());
+            mBitmapB = cedittextB.capture(Character.toChars(comparedCodePoints[i][1]));
+
+            assertFalse(mBitmapA.sameAs(mBitmapB));
+
+            mBitmapA = cwebview.capture(Character.toChars(comparedCodePoints[i][0]));
+            mBitmapB = cwebview.capture(Character.toChars(comparedCodePoints[i][1]));
+
+            assertFalse(mBitmapA.sameAs(mBitmapB));
+
+        }
+    }
+
+    /**
+     * Tests EditText handles Emoji
+     */
+    public void testEmojiEditable() {
+        int testedCodePoints[] = {
+            0xAE,    // registered mark
+            0x2764,    // heavy black heart
+            0x1F353    // strawberry - surrogate pair sample. Count as two characters.
+        };
+
+        String origStr, newStr;
+
+        // delete Emoji by sending KEYCODE_DEL
+        for (int i = 0; i < testedCodePoints.length; i++) {
+            origStr = "Test character  ";
+            // cannot reuse CaptureTextView as 2nd setText call throws NullPointerException
+            EditText editText = new EditText(getInstrumentation().getContext());
+            editText.setText(origStr + String.valueOf(Character.toChars(testedCodePoints[i])));
+
+            // confirm the emoji is added.
+            newStr = editText.getText().toString();
+            assertEquals(newStr.codePointCount(0, newStr.length()), origStr.length() + 1);
+
+            // Delete added character by sending KEYCODE_DEL event
+            editText.dispatchKeyEvent(new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_DEL));
+
+            newStr = editText.getText().toString();
+            assertEquals(newStr.codePointCount(0, newStr.length()), origStr.length() + 1);
+        }
+    }
+
+    private class CaptureCanvas extends View {
+
+        String mTestStr;
+        Paint paint = new Paint();
+
+        CaptureCanvas(Context context) {
+            super(context);
+        }
+
+        public void onDraw(Canvas canvas) {
+            if (mTestStr != null) {
+                canvas.drawText(mTestStr, 50, 50, paint);
+            }
+            return;
+        }
+
+        Bitmap capture(char c[]) {
+            mTestStr = String.valueOf(c);
+            invalidate();
+
+            setDrawingCacheEnabled(true);
+            measure(MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED),
+                    MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED));
+            layout(0, 0, 200,200);
+
+            Bitmap bitmap = Bitmap.createBitmap(getDrawingCache());
+            setDrawingCacheEnabled(false);
+            return bitmap;
+        }
+
+    }
+
+    private class CaptureTextView extends TextView {
+
+        CaptureTextView(Context context) {
+            super(context);
+        }
+
+        Bitmap capture(char c[]) {
+            setText(String.valueOf(c));
+
+            invalidate();
+
+            setDrawingCacheEnabled(true);
+            measure(MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED),
+                    MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED));
+            layout(0, 0, 200,200);
+
+            Bitmap bitmap = Bitmap.createBitmap(getDrawingCache());
+            setDrawingCacheEnabled(false);
+            return bitmap;
+        }
+
+    }
+
+    private class CaptureEditText extends EditText {
+
+        CaptureEditText(Context context) {
+            super(context);
+        }
+
+        Bitmap capture(char c[]) {
+            setText(String.valueOf(c));
+
+            invalidate();
+
+            setDrawingCacheEnabled(true);
+            measure(MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED),
+                    MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED));
+            layout(0, 0, 200,200);
+
+            Bitmap bitmap = Bitmap.createBitmap(getDrawingCache());
+            setDrawingCacheEnabled(false);
+            return bitmap;
+        }
+
+    }
+
+
+    private class CaptureWebView {
+
+        WebView view;
+        Bitmap bitmap;
+        CaptureWebView(Context context) {
+            view = getActivity().getWebView();
+        }
+
+        Bitmap capture(char c[]) {
+
+            view.loadData("<html><body>" + String.valueOf(c) + "</body></html>",
+                    "text/html; charset=utf-8", "utf-8");
+
+            try {
+                Thread.sleep(200);
+            } catch (InterruptedException ie) {
+                return null;
+            }
+
+            Picture picture = view.capturePicture();
+            if (picture == null || picture.getHeight() <= 0 || picture.getWidth() <= 0) {
+                return null;
+            } else {
+                bitmap = Bitmap.createBitmap(picture.getWidth(), picture.getHeight(),
+                        Bitmap.Config.ARGB_8888);
+                Canvas canvas = new Canvas(bitmap);
+                picture.draw(canvas);
+            }
+
+            return bitmap;
+        }
+
+    }
+
+}
+
diff --git a/tests/tests/webkit/src/android/webkit/cts/WebViewTest.java b/tests/tests/webkit/src/android/webkit/cts/WebViewTest.java
index 05b2d6e..813f830 100755
--- a/tests/tests/webkit/src/android/webkit/cts/WebViewTest.java
+++ b/tests/tests/webkit/src/android/webkit/cts/WebViewTest.java
@@ -1418,9 +1418,31 @@
     }
 
     @UiThreadTest
-    public void testClearSslPreferences() {
-        // FIXME: Implement this. See http://b/5378046.
-        mWebView.clearSslPreferences();
+    public void testClearSslPreferences() throws Throwable {
+        // Load the first page. We expect a call to
+        // WebViewClient.onReceivedSslError().
+        final SslErrorWebViewClient webViewClient = new SslErrorWebViewClient();
+        startWebServer(true);
+        final String url = mWebServer.getAssetUrl(TestHtmlConstants.HELLO_WORLD_URL);
+        mOnUiThread.setWebViewClient(webViewClient);
+        mOnUiThread.clearSslPreferences();
+        mOnUiThread.loadUrlAndWaitForCompletion(url);
+        assertTrue(webViewClient.wasOnReceivedSslErrorCalled());
+
+        // Load the page again. We expect another call to
+        // WebViewClient.onReceivedSslError() since we cleared sslpreferences.
+        mOnUiThread.clearSslPreferences();
+        webViewClient.resetWasOnReceivedSslErrorCalled();
+        mOnUiThread.loadUrlAndWaitForCompletion(url);
+        assertTrue(webViewClient.wasOnReceivedSslErrorCalled());
+        assertEquals(TestHtmlConstants.HELLO_WORLD_TITLE, mOnUiThread.getTitle());
+
+        // Load the page once again, without clearing the sslpreferences.
+        // Make sure we do not get the callback.
+        webViewClient.resetWasOnReceivedSslErrorCalled();
+        mOnUiThread.loadUrlAndWaitForCompletion(url);
+        assertFalse(webViewClient.wasOnReceivedSslErrorCalled());
+        assertEquals(TestHtmlConstants.HELLO_WORLD_TITLE, mOnUiThread.getTitle());
     }
 
     public void testOnReceivedSslError() throws Throwable {
@@ -1912,6 +1934,7 @@
     // Note that this class is not thread-safe.
     final class SslErrorWebViewClient extends WaitForLoadedClient {
         private boolean mWasOnReceivedSslErrorCalled;
+        private String mErrorUrl;
 
         public SslErrorWebViewClient() {
             super(mOnUiThread);
@@ -1919,6 +1942,7 @@
         @Override
         public void onReceivedSslError(WebView view, SslErrorHandler handler, SslError error) {
             mWasOnReceivedSslErrorCalled = true;
+            mErrorUrl = error.getUrl();
             handler.proceed();
         }
         public void resetWasOnReceivedSslErrorCalled() {
@@ -1927,5 +1951,8 @@
         public boolean wasOnReceivedSslErrorCalled() {
             return mWasOnReceivedSslErrorCalled;
         }
+        public String errorUrl() {
+            return mErrorUrl;
+        }
     }
 }