am 9984961a: am 83af7fea: Merge "CTS tests to verify multi-user emulated storage." into jb-mr1-dev

* commit '9984961a1f4b41c534ad4294d41e22cc29f29c9b':
  CTS tests to verify multi-user emulated storage.
diff --git a/CtsTestCaseList.mk b/CtsTestCaseList.mk
index 8c2b798..2bb02a5 100644
--- a/CtsTestCaseList.mk
+++ b/CtsTestCaseList.mk
@@ -75,6 +75,7 @@
 	CtsLocationTestCases \
 	CtsMediaStressTestCases \
 	CtsMediaTestCases \
+	CtsNativeOpenGLTestCases \
 	CtsNdefTestCases \
 	CtsNetTestCases \
 	CtsOpenGLTestCases \
diff --git a/build/config.mk b/build/config.mk
index c9fa709..14412b4 100644
--- a/build/config.mk
+++ b/build/config.mk
@@ -14,4 +14,5 @@
 
 BUILD_CTS_EXECUTABLE := cts/build/test_executable.mk
 BUILD_CTS_PACKAGE := cts/build/test_package.mk
+BUILD_CTS_GTEST_PACKAGE := cts/build/test_gtest_package.mk
 BUILD_CTS_HOST_JAVA_LIBRARY := cts/build/test_host_java_library.mk
diff --git a/build/test_gtest_package.mk b/build/test_gtest_package.mk
new file mode 100644
index 0000000..2f4c9bb
--- /dev/null
+++ b/build/test_gtest_package.mk
@@ -0,0 +1,49 @@
+# Copyright 2012 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+#
+# Builds a package and defines a rule to generate the associated test
+# package XML needed by CTS.
+#
+# Replace "include $(BUILD_PACKAGE)" with "include $(BUILD_CTS_GTEST_PACKAGE)"
+#
+
+# Disable by default so "m cts" will work in emulator builds
+LOCAL_DEX_PREOPT := false
+
+include $(BUILD_PACKAGE)
+
+cts_package_apk := $(CTS_TESTCASES_OUT)/$(LOCAL_PACKAGE_NAME).apk
+cts_package_xml := $(CTS_TESTCASES_OUT)/$(LOCAL_PACKAGE_NAME).xml
+
+$(cts_package_apk): PRIVATE_PACKAGE := $(LOCAL_PACKAGE_NAME)
+$(cts_package_apk): $(call intermediates-dir-for,APPS,$(LOCAL_PACKAGE_NAME))/package.apk | $(ACP)
+	$(hide) mkdir -p $(CTS_TESTCASES_OUT)
+	$(hide) $(ACP) -fp $(call intermediates-dir-for,APPS,$(PRIVATE_PACKAGE))/package.apk $@
+
+$(cts_package_xml): PRIVATE_PATH := $(LOCAL_PATH)
+$(cts_package_xml): PRIVATE_TEST_PACKAGE := android.$(notdir $(LOCAL_PATH))
+$(cts_package_xml): PRIVATE_EXECUTABLE := $(LOCAL_MODULE)
+$(cts_package_xml): PRIVATE_MANIFEST := $(LOCAL_PATH)/AndroidManifest.xml
+$(cts_package_xml): $(addprefix $(LOCAL_PATH)/,$(LOCAL_SRC_FILES))  $(CTS_NATIVE_TEST_SCANNER) $(CTS_XML_GENERATOR)
+	$(hide) echo Generating test description for wrapped native package $(PRIVATE_EXECUTABLE)
+	$(hide) mkdir -p $(CTS_TESTCASES_OUT)
+	$(hide) $(CTS_NATIVE_TEST_SCANNER) -s $(PRIVATE_PATH) \
+						-t $(PRIVATE_TEST_PACKAGE) | \
+			$(CTS_XML_GENERATOR) -t wrappednative \
+                                                -m $(PRIVATE_MANIFEST) \
+						-n $(PRIVATE_EXECUTABLE) \
+						-p $(PRIVATE_TEST_PACKAGE) \
+						-e $(CTS_EXPECTATIONS) \
+						-o $@
diff --git a/libs/testserver/src/android/webkit/cts/CtsTestServer.java b/libs/testserver/src/android/webkit/cts/CtsTestServer.java
index 16d57ea..ac338dd 100755
--- a/libs/testserver/src/android/webkit/cts/CtsTestServer.java
+++ b/libs/testserver/src/android/webkit/cts/CtsTestServer.java
@@ -544,12 +544,11 @@
             Header[] cookies = request.getHeaders("Cookie");
             Pattern p = Pattern.compile("count=(\\d+)");
             StringBuilder cookieString = new StringBuilder(100);
+            cookieString.append(cookies.length);
             int count = 0;
             for (Header cookie : cookies) {
+                cookieString.append("|");
                 String value = cookie.getValue();
-                if (cookieString.length() > 0) {
-                    cookieString.append("|");
-                }
                 cookieString.append(value);
                 Matcher m = p.matcher(value);
                 if (m.find()) {
diff --git a/libs/wrappedgtest/Android.mk b/libs/wrappedgtest/Android.mk
new file mode 100644
index 0000000..f89ba9d
--- /dev/null
+++ b/libs/wrappedgtest/Android.mk
@@ -0,0 +1,25 @@
+# Copyright 2012 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+LOCAL_PATH:= $(call my-dir)
+
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+
+LOCAL_MODULE_TAGS := optional
+
+LOCAL_MODULE := ctswrappedgtest
+
+include $(BUILD_STATIC_JAVA_LIBRARY)
diff --git a/libs/wrappedgtest/src/WrappedGTestActivity.java b/libs/wrappedgtest/src/WrappedGTestActivity.java
new file mode 100644
index 0000000..0633a5b
--- /dev/null
+++ b/libs/wrappedgtest/src/WrappedGTestActivity.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.test.wrappedgtest;
+
+import android.app.Activity;
+import android.app.Instrumentation;
+import android.os.Bundle;
+
+public class WrappedGTestActivity extends Activity {
+
+    private WrappedGTestInstrumentation mInstrumentation;
+
+    public void setInstrumentation(WrappedGTestInstrumentation instrumentation) {
+        mInstrumentation = instrumentation;
+    }
+
+    public int runGTests() {
+        return runTests(this);
+    }
+
+    public void sendStatus(String output) {
+        Bundle outputBundle = new Bundle();
+        outputBundle.putString("gtest", output);
+        mInstrumentation.sendStatus(1, outputBundle);
+    }
+
+    protected static native int runTests(WrappedGTestActivity activity);
+}
diff --git a/libs/wrappedgtest/src/WrappedGTestInstrumentation.java b/libs/wrappedgtest/src/WrappedGTestInstrumentation.java
new file mode 100644
index 0000000..b29aaab
--- /dev/null
+++ b/libs/wrappedgtest/src/WrappedGTestInstrumentation.java
@@ -0,0 +1,68 @@
+/*
+ * Copyright 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.test.wrappedgtest;
+
+import android.app.Activity;
+import android.app.Instrumentation;
+import android.app.KeyguardManager;
+import android.content.Context;
+import android.content.pm.PackageManager;
+import android.content.Intent;
+import android.os.Bundle;
+import android.util.Log;
+
+
+public class WrappedGTestInstrumentation extends Instrumentation {
+
+    private static final String TAG = "WrappedGTestInstrumentation";
+    private WrappedGTestActivity mActivity;
+    protected Class mActivityClass;
+
+    public WrappedGTestInstrumentation() {
+    }
+
+    @Override
+    public void onCreate(Bundle arguments) {
+        // attempt to disable keyguard,  if current test has permission to do so
+        if (getContext().checkCallingOrSelfPermission(android.Manifest.permission.DISABLE_KEYGUARD)
+                == PackageManager.PERMISSION_GRANTED) {
+            Log.i(TAG, "Disabling keyguard");
+            KeyguardManager keyguardManager =
+                (KeyguardManager) getContext().getSystemService(Context.KEYGUARD_SERVICE);
+            keyguardManager.newKeyguardLock("cts").disableKeyguard();
+        } else {
+            Log.i(TAG, "Test lacks permission to disable keyguard. " +
+                    "UI based tests may fail if keyguard is up");
+        }
+        super.onCreate(arguments);
+        start();
+    }
+
+    @Override
+    public void onStart() {
+        super.onStart();
+
+        Intent intent = new Intent(getTargetContext(), mActivityClass);
+        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+
+        mActivity = (WrappedGTestActivity)startActivitySync(intent);
+        mActivity.setInstrumentation(this);
+        mActivity.runGTests();
+
+        finish(Activity.RESULT_OK, new Bundle());
+    }
+}
diff --git a/tests/tests/nativeopengl/Android.mk b/tests/tests/nativeopengl/Android.mk
new file mode 100644
index 0000000..dd19548
--- /dev/null
+++ b/tests/tests/nativeopengl/Android.mk
@@ -0,0 +1,41 @@
+# Copyright 2012 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+LOCAL_PATH:= $(call my-dir)
+
+include $(CLEAR_VARS)
+
+LOCAL_PACKAGE_NAME := CtsNativeOpenGLTestCases
+
+# Don't include this package in any target.
+LOCAL_MODULE_TAGS := optional
+
+# When built, explicitly put it in the data partition.
+LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
+
+# All tests should include android.test.runner.
+LOCAL_JAVA_LIBRARIES := android.test.runner
+
+LOCAL_STATIC_JAVA_LIBRARIES := ctstestrunner ctswrappedgtest
+
+LOCAL_JNI_SHARED_LIBRARIES := libnativeopengltests
+
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+
+LOCAL_SDK_VERSION := current
+
+include $(BUILD_CTS_GTEST_PACKAGE)
+
+# Include the associated library's makefile.
+include $(LOCAL_PATH)/libnativeopengltests/Android.mk
diff --git a/tests/tests/nativeopengl/AndroidManifest.xml b/tests/tests/nativeopengl/AndroidManifest.xml
new file mode 100644
index 0000000..52157b4
--- /dev/null
+++ b/tests/tests/nativeopengl/AndroidManifest.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+ * Copyright 2012 Google Inc.
+ *
+ * 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.
+ */
+-->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="com.android.opengl.cts">
+
+    <uses-permission android:name="android.permission.DISABLE_KEYGUARD" />
+
+    <application>
+        <uses-library android:name="android.test.runner" />
+        <activity android:name="com.android.opengl.cts.GLTestActivity"/>
+    </application>
+
+    <!-- This is a self-instrumenting test package. -->
+    <instrumentation android:name="GLTestInstrumentation"
+                     android:targetPackage="com.android.opengl.cts"
+                     android:label="Native OpenGL tests">
+    </instrumentation>
+</manifest>
diff --git a/tests/tests/nativeopengl/libnativeopengltests/Android.mk b/tests/tests/nativeopengl/libnativeopengltests/Android.mk
new file mode 100644
index 0000000..b6ca1cb
--- /dev/null
+++ b/tests/tests/nativeopengl/libnativeopengltests/Android.mk
@@ -0,0 +1,48 @@
+# Copyright 2012 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+#
+# This is the shared library included by the JNI test app.
+#
+
+LOCAL_PATH:= $(call my-dir)
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE := libnativeopengltests
+
+# Don't include this package in any configuration by default.
+LOCAL_MODULE_TAGS := optional
+
+LOCAL_C_INCLUDES := $(JNI_H_INCLUDE) \
+    bionic \
+    bionic/libstdc++/include \
+    external/gtest/include \
+    external/stlport/stlport
+
+LOCAL_SRC_FILES := \
+        register.cpp \
+        GLTestHelper.cpp \
+        android_test_wrappedgtest_WrappedGTestActivity.cpp \
+        com_android_opengl_cts_GLTestActivity.cpp \
+        tests/GLTest_test.cpp
+
+LOCAL_SHARED_LIBRARIES := libEGL \
+                          libGLESv2 \
+                          libstlport \
+                          libandroid
+
+LOCAL_STATIC_LIBRARIES := libgtest
+
+include $(BUILD_SHARED_LIBRARY)
diff --git a/tests/tests/nativeopengl/libnativeopengltests/GLTestHelper.cpp b/tests/tests/nativeopengl/libnativeopengltests/GLTestHelper.cpp
new file mode 100644
index 0000000..ed527a6
--- /dev/null
+++ b/tests/tests/nativeopengl/libnativeopengltests/GLTestHelper.cpp
@@ -0,0 +1,29 @@
+/*
+ * Copyright 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "GLTestHelper.h"
+
+using namespace android;
+
+ANativeWindow* GLTestHelper::mWindow;
+
+ANativeWindow* GLTestHelper::getWindow() {
+    return mWindow;
+}
+
+void GLTestHelper::setWindow(ANativeWindow* value) {
+    mWindow = value;
+}
diff --git a/tests/tests/nativeopengl/libnativeopengltests/GLTestHelper.h b/tests/tests/nativeopengl/libnativeopengltests/GLTestHelper.h
new file mode 100644
index 0000000..c0775f0
--- /dev/null
+++ b/tests/tests/nativeopengl/libnativeopengltests/GLTestHelper.h
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_GL_TEST_HELPER_H
+#define ANDROID_GL_TEST_HELPER_H
+
+#include <stdint.h>
+#include <sys/types.h>
+#include <android/native_window.h>
+#include <utils/RefBase.h>
+
+using namespace android;
+
+class GLTestHelper
+{
+private:
+    static ANativeWindow* mWindow;
+public:
+    static ANativeWindow* getWindow();
+    static void setWindow(ANativeWindow* value);
+};
+
+
+
+#endif // ANDROID_GL_TEST_HELPER_H
diff --git a/tests/tests/nativeopengl/libnativeopengltests/android_test_wrappedgtest_WrappedGTestActivity.cpp b/tests/tests/nativeopengl/libnativeopengltests/android_test_wrappedgtest_WrappedGTestActivity.cpp
new file mode 100644
index 0000000..5e1c30e
--- /dev/null
+++ b/tests/tests/nativeopengl/libnativeopengltests/android_test_wrappedgtest_WrappedGTestActivity.cpp
@@ -0,0 +1,128 @@
+/*
+ * Copyright 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include <android/log.h>
+#include <gtest/gtest.h>
+#include <jni.h>
+
+using namespace testing;
+
+class GTestListener : public EmptyTestEventListener {
+public:
+    GTestListener(JNIEnv *env, jobject activity)
+        : mActivity(activity), mEnv(env) {
+
+        jclass clazz = env->FindClass(
+              "android/test/wrappedgtest/WrappedGTestActivity");
+        mSendStatusID = env->GetMethodID(clazz, "sendStatus",
+              "(Ljava/lang/String;)V");
+        mMessageBuffer = new char[2048];
+    }
+
+    ~GTestListener() {
+        delete[] mMessageBuffer;
+    }
+
+private:
+    jobject   mActivity;
+    JNIEnv *  mEnv;
+    jmethodID mSendStatusID;
+    char *    mMessageBuffer;
+
+    virtual void OnTestIterationStart(const UnitTest& unit_test,
+            int iteration) {
+        snprintf(mMessageBuffer, sizeof(char) * 2048,
+                "[==========] Running %i tests from %i test cases.",
+                unit_test.test_to_run_count(),
+                unit_test.test_case_to_run_count());
+
+        mEnv->CallVoidMethod(mActivity, mSendStatusID,
+                mEnv->NewStringUTF(mMessageBuffer));
+    }
+
+    virtual void OnTestStart(const TestInfo& test_info) {
+        snprintf(mMessageBuffer, sizeof(char) * 2048, "[ RUN      ] %s.%s",
+                test_info.test_case_name(), test_info.name());
+
+        mEnv->CallVoidMethod(mActivity, mSendStatusID,
+                mEnv->NewStringUTF(mMessageBuffer));
+    }
+
+    virtual void OnTestPartResult(const TestPartResult& result) {
+        if (result.type() == TestPartResult::kSuccess) {
+            return;
+        }
+
+        snprintf(mMessageBuffer, sizeof(char) * 2048, "%s:%i: Failure\n%s",
+                result.file_name(), result.line_number(), result.message());
+
+        mEnv->CallVoidMethod(mActivity, mSendStatusID,
+                mEnv->NewStringUTF(mMessageBuffer));
+    }
+
+    virtual void OnTestEnd(const TestInfo& test_info) {
+        const char * result = test_info.result()->Passed() ?
+                "[       OK ] " : "[  FAILED  ] ";
+
+        snprintf(mMessageBuffer, sizeof(char) * 2048, "%s%s.%s (%lli ms)",
+                result, test_info.test_case_name(), test_info.name(),
+                test_info.result()->elapsed_time());
+
+        mEnv->CallVoidMethod(mActivity, mSendStatusID,
+                mEnv->NewStringUTF(mMessageBuffer));
+    }
+
+    virtual void OnTestIterationEnd(const UnitTest& unit_test, int iteration) {
+        snprintf(mMessageBuffer, sizeof(char) * 2048,
+                "[==========] %i tests from %i test cases ran. (%lli ms total)",
+                unit_test.test_to_run_count(),
+                unit_test.test_case_to_run_count(), unit_test.elapsed_time());
+
+        mEnv->CallVoidMethod(mActivity, mSendStatusID,
+                mEnv->NewStringUTF(mMessageBuffer));
+    }
+};
+
+static jboolean WrappedGTestActivity_runTests(JNIEnv *env, jobject obj,
+        jobject activity) {
+    // init gtest with no args
+    int argc = 0;
+    InitGoogleTest(&argc, (char**)NULL);
+
+    // delete the default listener
+    TestEventListeners& listeners = UnitTest::GetInstance()->listeners();
+    delete listeners.Release(listeners.default_result_printer());
+
+    // add custom listener
+    GTestListener * listener = new GTestListener(env, activity);
+    listeners.Append(listener);
+
+    // run tests
+    int result = RUN_ALL_TESTS();
+
+    delete listener;
+    return result;
+};
+
+static JNINativeMethod methods[] = {
+    // name, signature, function
+    { "runTests", "(Landroid/test/wrappedgtest/WrappedGTestActivity;)I", (void*)WrappedGTestActivity_runTests },
+};
+
+int register_WrappedGTestActivity(JNIEnv *env) {
+    return env->RegisterNatives(
+            env->FindClass("android/test/wrappedgtest/WrappedGTestActivity"),
+            methods, sizeof(methods) / sizeof(JNINativeMethod));
+};
diff --git a/tests/tests/nativeopengl/libnativeopengltests/com_android_opengl_cts_GLTestActivity.cpp b/tests/tests/nativeopengl/libnativeopengltests/com_android_opengl_cts_GLTestActivity.cpp
new file mode 100644
index 0000000..8544f2a
--- /dev/null
+++ b/tests/tests/nativeopengl/libnativeopengltests/com_android_opengl_cts_GLTestActivity.cpp
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <gtest/gtest.h>
+#include <jni.h>
+
+#include "GLTestHelper.h"
+#include <android/native_window_jni.h>
+
+using namespace android;
+
+static void GLTestActivity_setSurface(JNIEnv *env, jobject obj,
+        jobject surface) {
+    ANativeWindow* window = ANativeWindow_fromSurface(env, surface);
+    GLTestHelper::setWindow(window);
+};
+
+static JNINativeMethod methods[] = {
+    // name, signature, function
+    { "setSurface", "(Landroid/view/Surface;)V", (void*)GLTestActivity_setSurface },
+};
+
+int register_GLTestActivity(JNIEnv *env) {
+    return env->RegisterNatives(
+            env->FindClass("com/android/opengl/cts/GLTestActivity"),
+            methods, sizeof(methods) / sizeof(JNINativeMethod));
+};
diff --git a/tests/tests/nativeopengl/libnativeopengltests/register.cpp b/tests/tests/nativeopengl/libnativeopengltests/register.cpp
new file mode 100644
index 0000000..97a8bd4
--- /dev/null
+++ b/tests/tests/nativeopengl/libnativeopengltests/register.cpp
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <jni.h>
+#include <stdlib.h>
+
+/*
+ * This function is called automatically by the system when this
+ * library is loaded. We use it to register all our native functions,
+ * which is the recommended practice for Android.
+ */
+jint JNI_OnLoad(JavaVM *vm, void *reserved) {
+    JNIEnv *env = NULL;
+
+    if (vm->GetEnv((void **) &env, JNI_VERSION_1_4) != JNI_OK) {
+        return JNI_ERR;
+    }
+
+    extern int register_WrappedGTestActivity(JNIEnv *);
+    if (register_WrappedGTestActivity(env)) {
+        return JNI_ERR;
+    }
+
+    extern int register_GLTestActivity(JNIEnv *);
+    if (register_GLTestActivity(env)) {
+        return JNI_ERR;
+    }
+
+    return JNI_VERSION_1_4;
+}
diff --git a/tests/tests/nativeopengl/libnativeopengltests/tests/GLTest_test.cpp b/tests/tests/nativeopengl/libnativeopengltests/tests/GLTest_test.cpp
new file mode 100644
index 0000000..37bfcb5
--- /dev/null
+++ b/tests/tests/nativeopengl/libnativeopengltests/tests/GLTest_test.cpp
@@ -0,0 +1,198 @@
+/*
+ * Copyright 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+#include <android/native_window.h>
+
+#include <gtest/gtest.h>
+
+#include <EGL/egl.h>
+#include <EGL/eglext.h>
+#include <GLES2/gl2.h>
+#include <GLES2/gl2ext.h>
+
+
+#include "GLTestHelper.h"
+
+
+namespace android {
+
+class GLTest : public ::testing::Test {
+
+protected:
+
+    GLTest():
+            mEglDisplay(EGL_NO_DISPLAY),
+            mEglSurface(EGL_NO_SURFACE),
+            mEglContext(EGL_NO_CONTEXT) {
+    }
+
+
+   virtual void SetUp() {
+        mEglDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY);
+        ASSERT_EQ(EGL_SUCCESS, eglGetError());
+        ASSERT_NE(EGL_NO_DISPLAY, mEglDisplay);
+
+        EGLint majorVersion;
+        EGLint minorVersion;
+        EXPECT_TRUE(eglInitialize(mEglDisplay, &majorVersion, &minorVersion));
+        ASSERT_EQ(EGL_SUCCESS, eglGetError());
+
+        EGLint numConfigs = 0;
+        EXPECT_TRUE(eglChooseConfig(mEglDisplay, getConfigAttribs(), &mGlConfig,
+                1, &numConfigs));
+        ASSERT_EQ(EGL_SUCCESS, eglGetError());
+
+        char* displaySecsEnv = getenv("GLTEST_DISPLAY_SECS");
+        if (displaySecsEnv != NULL) {
+            mDisplaySecs = atoi(displaySecsEnv);
+            if (mDisplaySecs < 0) {
+                mDisplaySecs = 0;
+            }
+        } else {
+            mDisplaySecs = 0;
+        }
+
+        if (mDisplaySecs > 0) {
+            mEglSurface = eglCreateWindowSurface(mEglDisplay, mGlConfig,
+                    GLTestHelper::getWindow(), NULL);
+        } else {
+            EGLint pbufferAttribs[] = {
+                EGL_WIDTH, getSurfaceWidth(),
+                EGL_HEIGHT, getSurfaceHeight(),
+                EGL_NONE };
+
+            mEglSurface = eglCreatePbufferSurface(mEglDisplay, mGlConfig,
+                    pbufferAttribs);
+        }
+        ASSERT_EQ(EGL_SUCCESS, eglGetError());
+        ASSERT_NE(EGL_NO_SURFACE, mEglSurface);
+
+        mEglContext = eglCreateContext(mEglDisplay, mGlConfig, EGL_NO_CONTEXT,
+                getContextAttribs());
+        ASSERT_EQ(EGL_SUCCESS, eglGetError());
+        ASSERT_NE(EGL_NO_CONTEXT, mEglContext);
+
+        EXPECT_TRUE(eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface,
+                mEglContext));
+        ASSERT_EQ(EGL_SUCCESS, eglGetError());
+
+        EGLint w, h;
+        EXPECT_TRUE(eglQuerySurface(mEglDisplay, mEglSurface, EGL_WIDTH, &w));
+        ASSERT_EQ(EGL_SUCCESS, eglGetError());
+        EXPECT_TRUE(eglQuerySurface(mEglDisplay, mEglSurface, EGL_HEIGHT, &h));
+        ASSERT_EQ(EGL_SUCCESS, eglGetError());
+
+        glViewport(0, 0, w, h);
+        ASSERT_EQ(GLenum(GL_NO_ERROR), glGetError());
+    }
+
+    virtual void TearDown() {
+        // Display the result
+        if (mDisplaySecs > 0 && mEglSurface != EGL_NO_SURFACE) {
+            eglSwapBuffers(mEglDisplay, mEglSurface);
+            sleep(mDisplaySecs);
+        }
+
+        if (mEglContext != EGL_NO_CONTEXT) {
+            eglDestroyContext(mEglDisplay, mEglContext);
+        }
+        if (mEglSurface != EGL_NO_SURFACE) {
+            eglDestroySurface(mEglDisplay, mEglSurface);
+        }
+        if (mEglDisplay != EGL_NO_DISPLAY) {
+            eglMakeCurrent(mEglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE,
+                    EGL_NO_CONTEXT);
+            eglTerminate(mEglDisplay);
+        }
+        ASSERT_EQ(EGL_SUCCESS, eglGetError());
+    }
+
+    virtual EGLint const* getConfigAttribs() {
+        static EGLint sDefaultConfigAttribs[] = {
+            EGL_SURFACE_TYPE, EGL_PBUFFER_BIT,
+            EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
+            EGL_RED_SIZE, 8,
+            EGL_GREEN_SIZE, 8,
+            EGL_BLUE_SIZE, 8,
+            EGL_ALPHA_SIZE, 8,
+            EGL_DEPTH_SIZE, 16,
+            EGL_STENCIL_SIZE, 8,
+            EGL_NONE };
+
+        return sDefaultConfigAttribs;
+    }
+
+    virtual EGLint const* getContextAttribs() {
+        static EGLint sDefaultContextAttribs[] = {
+            EGL_CONTEXT_CLIENT_VERSION, 2,
+            EGL_NONE };
+
+        return sDefaultContextAttribs;
+    }
+
+    virtual EGLint getSurfaceWidth() {
+        return 512;
+    }
+
+    virtual EGLint getSurfaceHeight() {
+        return 512;
+    }
+
+    bool checkPixel(GLubyte * actual, GLubyte * expected, int tolerance) {
+        for (int i = 0; i < 4; i++) {
+            if (abs(actual[i] - expected[i]) > tolerance) {
+                return false;
+            }
+        }
+        return true;
+    }
+
+    ::testing::AssertionResult AssertPixel(const char* a_expr,
+            const char* e_expr, const char* t_expr, GLubyte * actual,
+            GLubyte * expected, int tolerance) {
+
+        if (checkPixel(actual, expected, tolerance)) {
+            return ::testing::AssertionSuccess();
+        }
+
+        return ::testing::AssertionFailure()
+            << "Pixel comparison failed with tolerance " << tolerance << "\n"
+            << "Actual: r=" << (int)actual[0] << " g=" << (int)actual[1]
+            << " b=" << (int)actual[2] << " a=" << (int)actual[3] << "\n"
+            << "Expected: r=" << (int)expected[0] << " g=" << (int)expected[1]
+            << " b=" << (int)expected[2] << " a=" << (int)expected[3] << "\n";
+    }
+
+    int mDisplaySecs;
+
+    EGLDisplay mEglDisplay;
+    EGLSurface mEglSurface;
+    EGLContext mEglContext;
+    EGLConfig  mGlConfig;
+};
+
+TEST_F(GLTest, ClearColorTest) {
+    glClearColor(0.2, 0.2, 0.2, 0.2);
+    glClear(GL_COLOR_BUFFER_BIT);
+    GLubyte expected[4] = { 51, 51, 51, 51 };
+    GLubyte pixel[4];
+    glReadPixels(0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, pixel);
+    ASSERT_EQ(GLenum(GL_NO_ERROR), glGetError());
+    ASSERT_PRED_FORMAT3(AssertPixel, pixel, expected, 2);
+}
+
+} // namespace android
diff --git a/tests/tests/nativeopengl/src/com/android/opengl/cts/GLTestActivity.java b/tests/tests/nativeopengl/src/com/android/opengl/cts/GLTestActivity.java
new file mode 100644
index 0000000..1633a93
--- /dev/null
+++ b/tests/tests/nativeopengl/src/com/android/opengl/cts/GLTestActivity.java
@@ -0,0 +1,57 @@
+/*
+ * Copyright 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.opengl.cts;
+
+import android.app.Activity;
+import android.app.Instrumentation;
+import android.content.Intent;
+import android.os.Bundle;
+import android.test.wrappedgtest.WrappedGTestActivity;
+import android.view.SurfaceHolder;
+import android.view.SurfaceView;
+import android.view.Surface;
+
+public class GLTestActivity extends WrappedGTestActivity {
+
+    private SurfaceView mSurfaceView;
+    private SurfaceHolder.Callback mHolderCallback = new SurfaceHolder.Callback() {
+
+        @Override
+        public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
+             setSurface(holder.getSurface());
+        }
+
+        @Override
+        public void surfaceCreated(SurfaceHolder holder) {
+             setSurface(holder.getSurface());
+        }
+
+        @Override
+        public void surfaceDestroyed(SurfaceHolder holder) {
+        }
+    };
+
+    public void onCreate(Bundle data) {
+        super.onCreate(data);
+        mSurfaceView = new SurfaceView(this);
+        mSurfaceView.getHolder().addCallback(mHolderCallback);
+        setContentView(mSurfaceView);
+        System.loadLibrary("nativeopengltests");
+    }
+
+    private static native void setSurface(Surface surface);
+}
diff --git a/tests/tests/nativeopengl/src/com/android/opengl/cts/GLTestInstrumentation.java b/tests/tests/nativeopengl/src/com/android/opengl/cts/GLTestInstrumentation.java
new file mode 100644
index 0000000..913f0eb
--- /dev/null
+++ b/tests/tests/nativeopengl/src/com/android/opengl/cts/GLTestInstrumentation.java
@@ -0,0 +1,28 @@
+/*
+ * Copyright 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.opengl.cts;
+
+import android.test.wrappedgtest.WrappedGTestInstrumentation;
+
+/**
+ * adb shell am instrument -w com.android.opengl.cts/.GLTestInstrumentation
+ */
+public class GLTestInstrumentation extends WrappedGTestInstrumentation {
+    public GLTestInstrumentation() {
+        mActivityClass = GLTestActivity.class;
+    }
+}
diff --git a/tests/tests/renderscript/src/android/renderscript/cts/ImageProcessingTest.java b/tests/tests/renderscript/src/android/renderscript/cts/ImageProcessingTest.java
new file mode 100644
index 0000000..fae20f4
--- /dev/null
+++ b/tests/tests/renderscript/src/android/renderscript/cts/ImageProcessingTest.java
@@ -0,0 +1,338 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.renderscript.cts;
+
+import android.renderscript.Allocation;
+
+import android.renderscript.Byte2;
+import android.renderscript.Byte3;
+import android.renderscript.Byte4;
+
+import android.renderscript.Double2;
+import android.renderscript.Double3;
+import android.renderscript.Double4;
+
+import android.renderscript.Element;
+
+import android.renderscript.Float2;
+import android.renderscript.Float3;
+import android.renderscript.Float4;
+
+import android.renderscript.Int2;
+import android.renderscript.Int3;
+import android.renderscript.Int4;
+
+import android.renderscript.Long2;
+import android.renderscript.Long3;
+import android.renderscript.Long4;
+
+import android.renderscript.RSRuntimeException;
+
+import android.renderscript.Short2;
+import android.renderscript.Short3;
+import android.renderscript.Short4;
+
+import android.renderscript.Matrix4f;
+
+import android.renderscript.Type;
+
+import android.renderscript.ScriptGroup;
+
+import android.renderscript.ScriptIntrinsicBlend;
+import android.renderscript.ScriptIntrinsicBlur;
+import android.renderscript.ScriptIntrinsicColorMatrix;
+import android.renderscript.ScriptIntrinsicConvolve3x3;
+import android.renderscript.ScriptIntrinsicConvolve5x5;
+import android.renderscript.ScriptIntrinsicLUT;
+
+import com.android.cts.stub.R;
+
+public class ImageProcessingTest extends RSBaseCompute {
+    private Allocation a1, a2;
+
+    private final int MAX_RADIUS = 25;
+    private final int dimX = 256;
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+
+        Type t = new Type.Builder(mRS, Element.U8_4(mRS)).setX(dimX).setY(dimX).create();
+        a1 = Allocation.createTyped(mRS, t);
+        a2 = Allocation.createTyped(mRS, t);
+    }
+
+    public void testBlur() {
+        ScriptIntrinsicBlur mBlur;
+        mBlur = ScriptIntrinsicBlur.create(mRS, Element.U8_4(mRS));
+
+        Allocation a1_copy, a2_copy;
+        a1_copy = Allocation.createTyped(mRS, a1.getType());
+        a2_copy = Allocation.createTyped(mRS, a2.getType());
+
+        for (int i = 1; i < MAX_RADIUS; i++) {
+
+            a1_copy.copy2DRangeFrom(0, 0, a1.getType().getX(), a1.getType().getY(), a1, 0, 0);
+
+            mBlur.setRadius(i);
+            mBlur.setInput(a1_copy);
+
+            mBlur.forEach(a2_copy);
+
+            // validate
+
+        }
+
+    }
+
+    public void testBlend() {
+        ScriptIntrinsicBlend mBlend;
+        mBlend = ScriptIntrinsicBlend.create(mRS, Element.U8_4(mRS));
+
+        Allocation a1_copy, a2_copy;
+        a1_copy = Allocation.createTyped(mRS, a1.getType());
+        a2_copy = Allocation.createTyped(mRS, a2.getType());
+
+        for (int i = 0; i < 14; i++) {
+
+            a1_copy.copy2DRangeFrom(0, 0, a1.getType().getX(), a1.getType().getY(), a1, 0, 0);
+            a2_copy.copy2DRangeFrom(0, 0, a2.getType().getX(), a2.getType().getY(), a2, 0, 0);
+
+            switch (i) {
+            case 0:
+                mBlend.forEachSrc(a1_copy, a2_copy);
+                break;
+            case 1:
+                mBlend.forEachDst(a1_copy, a2_copy);
+                break;
+            case 2:
+                mBlend.forEachSrcOver(a1_copy, a2_copy);
+                break;
+            case 3:
+                mBlend.forEachDstOver(a1_copy, a2_copy);
+                break;
+            case 4:
+                mBlend.forEachSrcIn(a1_copy, a2_copy);
+                break;
+            case 5:
+                mBlend.forEachDstIn(a1_copy, a2_copy);
+                break;
+            case 6:
+                mBlend.forEachSrcOut(a1_copy, a2_copy);
+                break;
+            case 7:
+                mBlend.forEachDstOut(a1_copy, a2_copy);
+                break;
+            case 8:
+                mBlend.forEachSrcAtop(a1_copy, a2_copy);
+                break;
+            case 9:
+                mBlend.forEachDstAtop(a1_copy, a2_copy);
+                break;
+            case 10:
+                mBlend.forEachXor(a1_copy, a2_copy);
+                break;
+            case 11:
+                mBlend.forEachAdd(a1_copy, a2_copy);
+                break;
+            case 12:
+                mBlend.forEachSubtract(a1_copy, a2_copy);
+                break;
+            case 13:
+                mBlend.forEachMultiply(a1_copy, a2_copy);
+                break;
+            }
+
+            // validate
+
+        }
+
+    }
+
+    public void testColorMatrix() {
+        ScriptIntrinsicColorMatrix mColorMatrix;
+        mColorMatrix = ScriptIntrinsicColorMatrix.create(mRS, Element.U8_4(mRS));
+
+        Allocation a1_copy, a2_copy;
+        a1_copy = Allocation.createTyped(mRS, a1.getType());
+        a2_copy = Allocation.createTyped(mRS, a2.getType());
+
+        Matrix4f m = new Matrix4f();
+        m.set(1, 0, 0.2f);
+        m.set(1, 1, 0.9f);
+        m.set(1, 2, 0.2f);
+
+        //test greyscale
+        mColorMatrix.setGreyscale();
+
+        a1_copy.copy2DRangeFrom(0, 0, a1.getType().getX(), a1.getType().getY(), a1, 0, 0);
+        a2_copy.copy2DRangeFrom(0, 0, a2.getType().getX(), a2.getType().getY(), a2, 0, 0);
+
+        mColorMatrix.forEach(a1_copy, a2_copy);
+
+        //validate greyscale
+
+
+        //test color matrix
+        mColorMatrix.setColorMatrix(m);
+
+        a1_copy.copy2DRangeFrom(0, 0, a1.getType().getX(), a1.getType().getY(), a1, 0, 0);
+        a2_copy.copy2DRangeFrom(0, 0, a2.getType().getX(), a2.getType().getY(), a2, 0, 0);
+
+        mColorMatrix.forEach(a1_copy, a2_copy);
+
+        //validate color matrix
+
+
+    }
+
+
+    public void testConvolve3x3() {
+        ScriptIntrinsicConvolve3x3 mConvolve3x3;
+        mConvolve3x3 = ScriptIntrinsicConvolve3x3.create(mRS, Element.U8_4(mRS));
+
+        Allocation a1_copy, a2_copy;
+        a1_copy = Allocation.createTyped(mRS, a1.getType());
+        a2_copy = Allocation.createTyped(mRS, a2.getType());
+
+        a1_copy.copy2DRangeFrom(0, 0, a1.getType().getX(), a1.getType().getY(), a1, 0, 0);
+
+        float f[] = new float[9];
+        f[0] =  0.f;    f[1] = -1.f;    f[2] =  0.f;
+        f[3] = -1.f;    f[4] =  5.f;    f[5] = -1.f;
+        f[6] =  0.f;    f[7] = -1.f;    f[8] =  0.f;
+
+        mConvolve3x3.setCoefficients(f);
+        mConvolve3x3.setInput(a1_copy);
+        mConvolve3x3.forEach(a2_copy);
+
+        // validate
+
+    }
+
+    public void testConvolve5x5() {
+        ScriptIntrinsicConvolve5x5 mConvolve5x5;
+        mConvolve5x5 = ScriptIntrinsicConvolve5x5.create(mRS, Element.U8_4(mRS));
+
+        Allocation a1_copy, a2_copy;
+        a1_copy = Allocation.createTyped(mRS, a1.getType());
+        a2_copy = Allocation.createTyped(mRS, a2.getType());
+
+        a1_copy.copy2DRangeFrom(0, 0, a1.getType().getX(), a1.getType().getY(), a1, 0, 0);
+
+        float f[] = new float[25];
+        f[0] = -1.f; f[1] = -3.f; f[2] = -4.f; f[3] = -3.f; f[4] = -1.f;
+        f[5] = -3.f; f[6] =  0.f; f[7] =  6.f; f[8] =  0.f; f[9] = -3.f;
+        f[10]= -4.f; f[11]=  6.f; f[12]= 20.f; f[13]=  6.f; f[14]= -4.f;
+        f[15]= -3.f; f[16]=  0.f; f[17]=  6.f; f[18]=  0.f; f[19]= -3.f;
+        f[20]= -1.f; f[21]= -3.f; f[22]= -4.f; f[23]= -3.f; f[24]= -1.f;
+
+        mConvolve5x5.setCoefficients(f);
+        mConvolve5x5.setInput(a1_copy);
+        mConvolve5x5.forEach(a2_copy);
+
+        // validate
+
+    }
+
+    public void testLUT() {
+        ScriptIntrinsicLUT mLUT;
+        mLUT = ScriptIntrinsicLUT.create(mRS, Element.U8_4(mRS));
+
+        Allocation a1_copy, a2_copy;
+        a1_copy = Allocation.createTyped(mRS, a1.getType());
+        a2_copy = Allocation.createTyped(mRS, a2.getType());
+
+        a1_copy.copy2DRangeFrom(0, 0, a1.getType().getX(), a1.getType().getY(), a1, 0, 0);
+
+        for (int ct=0; ct < 256; ct++) {
+            float f = ((float)ct) / 255.f;
+
+            float r = f;
+            if (r < 0.5f) {
+                r = 4.0f * r * r * r;
+            } else {
+                r = 1.0f - r;
+                r = 1.0f - (4.0f * r * r * r);
+            }
+            mLUT.setRed(ct, (int)(r * 255.f + 0.5f));
+
+            float g = f;
+            if (g < 0.5f) {
+                g = 2.0f * g * g;
+            } else {
+                g = 1.0f - g;
+                g = 1.0f - (2.0f * g * g);
+            }
+            mLUT.setGreen(ct, (int)(g * 255.f + 0.5f));
+
+            float b = f * 0.5f + 0.25f;
+            mLUT.setBlue(ct, (int)(b * 255.f + 0.5f));
+        }
+
+        mLUT.forEach(a1_copy, a2_copy);
+
+        // validate
+
+    }
+
+    public void testScriptGroup() {
+        ScriptGroup group;
+
+        ScriptIntrinsicConvolve3x3 mConvolve3x3;
+        ScriptIntrinsicColorMatrix mColorMatrix;
+
+        mConvolve3x3 = ScriptIntrinsicConvolve3x3.create(mRS, Element.U8_4(mRS));
+        mColorMatrix = ScriptIntrinsicColorMatrix.create(mRS, Element.U8_4(mRS));
+
+        Allocation a1_copy, a2_copy;
+        a1_copy = Allocation.createTyped(mRS, a1.getType());
+        a2_copy = Allocation.createTyped(mRS, a2.getType());
+
+        a1_copy.copy2DRangeFrom(0, 0, a1.getType().getX(), a1.getType().getY(), a1, 0, 0);
+
+        float f[] = new float[9];
+        f[0] =  0.f;    f[1] = -1.f;    f[2] =  0.f;
+        f[3] = -1.f;    f[4] =  5.f;    f[5] = -1.f;
+        f[6] =  0.f;    f[7] = -1.f;    f[8] =  0.f;
+
+        mConvolve3x3.setCoefficients(f);
+
+        Matrix4f m = new Matrix4f();
+        m.set(1, 0, 0.2f);
+        m.set(1, 1, 0.9f);
+        m.set(1, 2, 0.2f);
+        mColorMatrix.setColorMatrix(m);
+
+        Type connect = new Type.Builder(mRS, Element.U8_4(mRS)).setX(dimX).setY(dimX).create();
+
+        ScriptGroup.Builder b = new ScriptGroup.Builder(mRS);
+        b.addKernel(mConvolve3x3.getKernelID());
+        b.addKernel(mColorMatrix.getKernelID());
+        b.addConnection(connect, mConvolve3x3.getKernelID(), mColorMatrix.getKernelID());
+        group = b.create();
+
+        mConvolve3x3.setInput(a1_copy);
+        group.setOutput(mColorMatrix.getKernelID(), a2_copy);
+        group.execute();
+
+        // validate
+
+    }
+
+
+}
diff --git a/tests/tests/security/src/android/security/cts/BannedFilesTest.java b/tests/tests/security/src/android/security/cts/BannedFilesTest.java
index b4deed5..4409e49 100644
--- a/tests/tests/security/src/android/security/cts/BannedFilesTest.java
+++ b/tests/tests/security/src/android/security/cts/BannedFilesTest.java
@@ -56,7 +56,7 @@
         if (!FileUtils.getFileStatus(file, fs, false)) {
             return;
         }
-        assertTrue((fs.mode & FileUtils.S_ISUID) == 0);
-        assertTrue((fs.mode & FileUtils.S_ISGID) == 0);
+        assertTrue("File \"" + file + "\" is setUID", (fs.mode & FileUtils.S_ISUID) == 0);
+        assertTrue("File \"" + file + "\" is setGID", (fs.mode & FileUtils.S_ISGID) == 0);
     }
 }
diff --git a/tests/tests/security/src/android/security/cts/CertificateData.java b/tests/tests/security/src/android/security/cts/CertificateData.java
index 1714461..7af4243 100644
--- a/tests/tests/security/src/android/security/cts/CertificateData.java
+++ b/tests/tests/security/src/android/security/cts/CertificateData.java
@@ -48,6 +48,7 @@
       "AD:7E:1C:28:B0:64:EF:8F:60:03:40:20:14:C3:D0:E3:37:0E:B5:8A",
       "8D:17:84:D5:37:F3:03:7D:EC:70:FE:57:8B:51:9A:99:E6:10:D7:B0",
       "AE:50:83:ED:7C:F4:5C:BC:8F:61:C6:21:FE:68:5D:79:42:21:15:6E",
+      "DA:FA:F7:FA:66:84:EC:06:8F:14:50:BD:C7:C2:81:A5:BC:A9:64:57",
       "5F:4E:1F:CF:31:B7:91:3B:85:0B:54:F6:E5:FF:50:1A:2B:6F:C6:CF",
       "74:F8:A3:C3:EF:E7:B3:90:06:4B:83:90:3C:21:64:60:20:E5:DF:CE",
       "85:B5:FF:67:9B:0C:79:96:1F:C8:6E:44:22:00:46:13:DB:17:92:84",
@@ -64,6 +65,7 @@
       "8C:F4:27:FD:79:0C:3A:D1:66:06:8D:E8:1E:57:EF:BB:93:22:72:D4",
       "56:E0:FA:C0:3B:8F:18:23:55:18:E5:D3:11:CA:E8:C2:43:31:AB:66",
       "02:72:68:29:3E:5F:5D:17:AA:A4:B3:C3:E6:36:1E:1F:92:57:5E:AA",
+      "2F:78:3D:25:52:18:A7:4A:65:39:71:B5:2C:A2:9C:45:15:6F:E9:19",
       "97:81:79:50:D8:1C:96:70:CC:34:D8:09:CF:79:44:31:36:7E:F4:74",
       "85:A4:08:C0:9C:19:3E:5D:51:58:7D:CD:D6:13:30:FD:8C:DE:37:BF",
       "58:11:9F:0E:12:82:87:EA:50:FD:D9:87:45:6F:4F:78:DC:FA:D6:D4",
@@ -98,6 +100,7 @@
       "69:BD:8C:F4:9C:D3:00:FB:59:2E:17:93:CA:55:6A:F3:EC:AA:35:FB",
       "13:2D:0D:45:53:4B:69:97:CD:B2:D5:C3:39:E2:55:76:60:9B:5C:C6",
       "5F:B7:EE:06:33:E2:59:DB:AD:0C:4C:9A:E6:D3:8F:1A:61:C7:DC:25",
+      "49:0A:75:74:DE:87:0A:47:FE:58:EE:F6:C7:6B:EB:C6:0B:12:40:99",
       "25:01:90:19:CF:FB:D9:99:1C:B7:68:25:74:8D:94:5F:30:93:95:42",
       "79:98:A3:08:E1:4D:65:85:E6:C2:1E:15:3A:71:9F:BA:5A:D3:4A:D9",
       "B5:1C:06:7C:EE:2B:0C:3D:F8:55:AB:2D:92:F4:FE:39:D4:E7:0F:0E",
diff --git a/tests/tests/webkit/src/android/webkit/cts/CacheManagerTest.java b/tests/tests/webkit/src/android/webkit/cts/CacheManagerTest.java
deleted file mode 100644
index 66b1e02..0000000
--- a/tests/tests/webkit/src/android/webkit/cts/CacheManagerTest.java
+++ /dev/null
@@ -1,99 +0,0 @@
-/*
- * Copyright (C) 2009 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.webkit.cts;
-
-import android.cts.util.PollingCheck;
-import android.test.ActivityInstrumentationTestCase2;
-import android.webkit.CacheManager;
-import android.webkit.CacheManager.CacheResult;
-
-
-import java.util.Map;
-
-public class CacheManagerTest extends ActivityInstrumentationTestCase2<WebViewStubActivity> {
-    private static final long CACHEMANAGER_INIT_TIMEOUT = 5000L;
-    private static final long NETWORK_OPERATION_TIMEOUT = 10000L;
-
-    private CtsTestServer mWebServer;
-    private WebViewOnUiThread mOnUiThread;
-
-    public CacheManagerTest() {
-        super("com.android.cts.stub", WebViewStubActivity.class);
-    }
-
-    @Override
-    protected void setUp() throws Exception {
-        super.setUp();
-        mOnUiThread = new WebViewOnUiThread(this, getActivity().getWebView());
-    }
-
-    @Override
-    protected void tearDown() throws Exception {
-        mOnUiThread.cleanUp();
-        if (mWebServer != null) {
-            mWebServer.shutdown();
-        }
-        super.tearDown();
-    }
-
-    public void testGetCacheFileBaseDir() {
-        assertTrue(CacheManager.getCacheFileBaseDir().exists());
-    }
-
-    public void testCacheTransaction() {
-    }
-
-    public void testCacheFile() throws Exception {
-        mWebServer = new CtsTestServer(getActivity());
-        final String url = mWebServer.getAssetUrl(TestHtmlConstants.EMBEDDED_IMG_URL);
-
-        // Wait for CacheManager#init() finish.
-        new PollingCheck(CACHEMANAGER_INIT_TIMEOUT) {
-            @Override
-            protected boolean check() {
-                return CacheManager.getCacheFileBaseDir() != null;
-            }
-        }.run();
-
-        mOnUiThread.clearCache(true);
-        new PollingCheck(NETWORK_OPERATION_TIMEOUT) {
-            @Override
-            protected boolean check() {
-                CacheResult result = CacheManager.getCacheFile(url, null);
-                return result == null;
-            }
-        }.run();
-
-        mOnUiThread.loadUrlAndWaitForCompletion(url);
-        new PollingCheck(NETWORK_OPERATION_TIMEOUT) {
-            @Override
-            protected boolean check() {
-                CacheResult result = CacheManager.getCacheFile(url, null);
-                return result != null;
-            }
-        }.run();
-
-        // Can not test saveCacheFile(), because the output stream is null and
-        // saveCacheFile() will throw a NullPointerException.  There is no
-        // public API to set the output stream.
-    }
-
-    public void testCacheDisabled() {
-        // The cache should always be enabled.
-        assertFalse(CacheManager.cacheDisabled());
-    }
-}
diff --git a/tests/tests/webkit/src/android/webkit/cts/CacheManager_CacheResultTest.java b/tests/tests/webkit/src/android/webkit/cts/CacheManager_CacheResultTest.java
deleted file mode 100755
index 0c2a51a..0000000
--- a/tests/tests/webkit/src/android/webkit/cts/CacheManager_CacheResultTest.java
+++ /dev/null
@@ -1,109 +0,0 @@
-/*
- * Copyright (C) 2009 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.webkit.cts;
-
-import android.cts.util.PollingCheck;
-import android.test.ActivityInstrumentationTestCase2;
-import android.webkit.CacheManager;
-import android.webkit.CacheManager.CacheResult;
-import android.webkit.WebView;
-
-
-import org.apache.http.HttpStatus;
-import org.apache.http.impl.cookie.DateUtils;
-
-import java.io.File;
-import java.io.InputStream;
-import java.util.HashMap;
-import java.util.Map;
-
-public class CacheManager_CacheResultTest
-        extends ActivityInstrumentationTestCase2<WebViewStubActivity> {
-    private static final long NETWORK_OPERATION_TIMEOUT = 10000L;
-
-    private CtsTestServer mWebServer;
-    private WebViewOnUiThread mOnUiThread;
-
-    public CacheManager_CacheResultTest() {
-        super("com.android.cts.stub", WebViewStubActivity.class);
-    }
-
-    @Override
-    protected void setUp() throws Exception {
-        super.setUp();
-        mOnUiThread = new WebViewOnUiThread(this, getActivity().getWebView());
-    }
-
-    @Override
-    protected void tearDown() throws Exception {
-        mOnUiThread.cleanUp();
-        if (mWebServer != null) {
-            mWebServer.shutdown();
-        }
-        super.tearDown();
-    }
-
-    public void testCacheResult() throws Exception {
-        final long validity = 5 * 60 * 1000; // 5 min
-        final long age = 30 * 60 * 1000; // 30 min
-        final long tolerance = 5 * 1000; // 5s
-
-        mWebServer = new CtsTestServer(getActivity());
-        final String url = mWebServer.getAssetUrl(TestHtmlConstants.HELLO_WORLD_URL);
-        mWebServer.setDocumentAge(age);
-        mWebServer.setDocumentValidity(validity);
-
-        mOnUiThread.clearCache(true);
-        new PollingCheck(NETWORK_OPERATION_TIMEOUT) {
-            @Override
-            protected boolean check() {
-                CacheResult result =
-                    CacheManager.getCacheFile(url, null);
-                return result == null;
-            }
-        }.run();
-        final long time = System.currentTimeMillis();
-        mOnUiThread.loadUrlAndWaitForCompletion(url);
-
-        Map<String, String> headers = new HashMap<String, String>();
-        CacheResult result = CacheManager.getCacheFile(url, headers);
-        assertTrue(headers.isEmpty());
-
-        assertNotNull(result);
-        assertNotNull(result.getInputStream());
-        assertTrue(result.getContentLength() > 0);
-        assertNull(result.getETag());
-        assertEquals((double)(time - age),
-                (double)DateUtils.parseDate(result.getLastModified()).getTime(),
-                (double)tolerance);
-        File file = new File(CacheManager.getCacheFileBaseDir().getPath(), result.getLocalPath());
-        assertTrue(file.exists());
-        assertNull(result.getLocation());
-        assertEquals("text/html", result.getMimeType());
-        assertNull(result.getOutputStream());
-        assertEquals((double)(time + validity), (double)result.getExpires(),
-                (double)tolerance);
-        assertEquals(HttpStatus.SC_OK, result.getHttpStatusCode());
-        assertNotNull(result.getEncoding());
-
-        result.setEncoding("iso-8859-1");
-        assertEquals("iso-8859-1", result.getEncoding());
-
-        result.setInputStream(null);
-        assertNull(result.getInputStream());
-    }
-}
diff --git a/tests/tests/webkit/src/android/webkit/cts/CookieManagerTest.java b/tests/tests/webkit/src/android/webkit/cts/CookieManagerTest.java
index 51eae48..a0b4fa6 100755
--- a/tests/tests/webkit/src/android/webkit/cts/CookieManagerTest.java
+++ b/tests/tests/webkit/src/android/webkit/cts/CookieManagerTest.java
@@ -68,7 +68,7 @@
         CtsTestServer server = new CtsTestServer(getActivity(), false);
         String url = server.getCookieUrl("conquest.html");
         mOnUiThread.loadUrlAndWaitForCompletion(url);
-        assertEquals(null, mOnUiThread.getTitle()); // no cookies passed
+        assertEquals("0", mOnUiThread.getTitle()); // no cookies passed
         Thread.sleep(500);
         assertNull(mCookieManager.getCookie(url));
 
@@ -77,7 +77,7 @@
 
         url = server.getCookieUrl("war.html");
         mOnUiThread.loadUrlAndWaitForCompletion(url);
-        assertEquals(null, mOnUiThread.getTitle()); // no cookies passed
+        assertEquals("0", mOnUiThread.getTitle()); // no cookies passed
         waitForCookie(url);
         String cookie = mCookieManager.getCookie(url);
         assertNotNull(cookie);
@@ -89,7 +89,7 @@
 
         url = server.getCookieUrl("famine.html");
         mOnUiThread.loadUrlAndWaitForCompletion(url);
-        assertEquals("count=0", mOnUiThread.getTitle()); // outgoing cookie
+        assertEquals("1|count=0", mOnUiThread.getTitle()); // outgoing cookie
         waitForCookie(url);
         cookie = mCookieManager.getCookie(url);
         assertNotNull(cookie);
@@ -100,7 +100,7 @@
         url = server.getCookieUrl("death.html");
         mCookieManager.setCookie(url, "count=41");
         mOnUiThread.loadUrlAndWaitForCompletion(url);
-        assertEquals("count=41", mOnUiThread.getTitle()); // outgoing cookie
+        assertEquals("1|count=41", mOnUiThread.getTitle()); // outgoing cookie
         waitForCookie(url);
         cookie = mCookieManager.getCookie(url);
         assertNotNull(cookie);
diff --git a/tests/tests/webkit/src/android/webkit/cts/CookieTest.java b/tests/tests/webkit/src/android/webkit/cts/CookieTest.java
index 14a14d0..0c0396a 100644
--- a/tests/tests/webkit/src/android/webkit/cts/CookieTest.java
+++ b/tests/tests/webkit/src/android/webkit/cts/CookieTest.java
@@ -45,23 +45,6 @@
             }
         }
         assertFalse(mCookieManager.hasCookies());
-
-    }
-
-    public void testParse() {
-        String url = "http://www.foo.com";
-
-        // basic
-        mCookieManager.setCookie(url, "a=b");
-        String cookie = mCookieManager.getCookie(url);
-        assertTrue(cookie.equals("a=b"));
-
-        // quoted
-        mCookieManager.setCookie(url, "c=\"d;\"");
-        cookie = mCookieManager.getCookie(url);
-
-        assertTrue(cookie.contains("a=b"));
-        assertTrue(cookie.contains("c=\"d;\""));
     }
 
     public void testDomain() {
diff --git a/tests/tests/webkit/src/android/webkit/cts/WebSettingsTest.java b/tests/tests/webkit/src/android/webkit/cts/WebSettingsTest.java
index 054217e..42991d8 100644
--- a/tests/tests/webkit/src/android/webkit/cts/WebSettingsTest.java
+++ b/tests/tests/webkit/src/android/webkit/cts/WebSettingsTest.java
@@ -164,7 +164,7 @@
         assertEquals(1, mSettings.getUserAgent());
         mOnUiThread.loadUrlAndWaitForCompletion(url);
         String userAgent1 = mOnUiThread.getTitle();
-        assertNotNull(userAgent1);
+        assertEquals(userAgent1, mSettings.getUserAgentString());
 
         mSettings.setUserAgent(3);
         assertEquals(1, mSettings.getUserAgent());
@@ -175,7 +175,7 @@
         assertEquals(2, mSettings.getUserAgent());
         mOnUiThread.loadUrlAndWaitForCompletion(url);
         String userAgent2 = mOnUiThread.getTitle();
-        assertNotNull(userAgent2);
+        assertEquals(userAgent2, mSettings.getUserAgentString());
 
         mSettings.setUserAgent(3);
         assertEquals(2, mSettings.getUserAgent());
@@ -186,7 +186,7 @@
         assertEquals(0, mSettings.getUserAgent());
         mOnUiThread.loadUrlAndWaitForCompletion(url);
         String userAgent0 = mOnUiThread.getTitle();
-        assertNotNull(userAgent0);
+        assertEquals(userAgent0, mSettings.getUserAgentString());
 
         final String customUserAgent = "Cts/Test";
         mSettings.setUserAgentString(customUserAgent);
@@ -387,11 +387,9 @@
         new PollingCheck(WEBVIEW_TIMEOUT) {
             @Override
             protected boolean check() {
-                String title = mOnUiThread.getTitle();
-                return title != null && title.length() > 0;
+                return "Popup blocked".equals(mOnUiThread.getTitle());
             }
         }.run();
-        assertEquals("Popup blocked", mOnUiThread.getTitle());
 
         mSettings.setJavaScriptCanOpenWindowsAutomatically(true);
         assertTrue(mSettings.getJavaScriptCanOpenWindowsAutomatically());
@@ -399,15 +397,9 @@
         new PollingCheck(WEBVIEW_TIMEOUT) {
             @Override
             protected boolean check() {
-                String title = mOnUiThread.getTitle();
-                // The title may not change immediately after loading, so
-                // we have to discount the initial "Popup blocked" from the
-                // previous load.
-                return title != null && title.length() > 0
-                        && !title.equals("Popup blocked");
+                return "Popup allowed".equals(mOnUiThread.getTitle());
             }
         }.run();
-        assertEquals("Popup allowed", mOnUiThread.getTitle());
     }
 
     public void testAccessJavaScriptEnabled() throws Exception {
@@ -417,10 +409,9 @@
         new PollingCheck(WEBVIEW_TIMEOUT) {
             @Override
             protected boolean check() {
-                return mOnUiThread.getTitle() != null;
+                return "javascript on".equals(mOnUiThread.getTitle());
             }
         }.run();
-        assertEquals("javascript on", mOnUiThread.getTitle());
 
         mSettings.setJavaScriptEnabled(false);
         assertFalse(mSettings.getJavaScriptEnabled());
@@ -428,10 +419,10 @@
         new PollingCheck(WEBVIEW_TIMEOUT) {
             @Override
             protected boolean check() {
-                return mOnUiThread.getTitle() != null;
+                return "javascript off".equals(mOnUiThread.getTitle());
             }
         }.run();
-        assertEquals("javascript off", mOnUiThread.getTitle());
+
     }
 
     public void testAccessLayoutAlgorithm() {
@@ -727,7 +718,7 @@
         mOnUiThread.clearCache(true);
         mOnUiThread.loadUrlAndWaitForCompletion(
             mWebServer.getAssetUrl(TestHtmlConstants.HELLO_WORLD_URL));
-        assertEquals(TestHtmlConstants.WEBPAGE_NOT_AVAILABLE_TITLE, mOnUiThread.getTitle());
+        assertFalse(TestHtmlConstants.HELLO_WORLD_TITLE.equals(mOnUiThread.getTitle()));
         mOnUiThread.loadDataAndWaitForCompletion(getNetworkImageHtml(), "text/html", null);
         assertEquals(EMPTY_IMAGE_HEIGHT, mOnUiThread.getTitle());
         mOnUiThread.loadDataAndWaitForCompletion(DATA_URL_IMAGE_HTML, "text/html", null);
diff --git a/tests/tests/webkit/src/android/webkit/cts/WebViewTest.java b/tests/tests/webkit/src/android/webkit/cts/WebViewTest.java
index 6c66f52..01d58ae 100755
--- a/tests/tests/webkit/src/android/webkit/cts/WebViewTest.java
+++ b/tests/tests/webkit/src/android/webkit/cts/WebViewTest.java
@@ -41,8 +41,6 @@
 import android.view.KeyEvent;
 import android.view.MotionEvent;
 import android.view.View;
-import android.webkit.CacheManager;
-import android.webkit.CacheManager.CacheResult;
 import android.webkit.ConsoleMessage;
 import android.webkit.DownloadListener;
 import android.webkit.JavascriptInterface;
@@ -762,7 +760,6 @@
         final String HTML_CONTENT =
                 "<html><head><title>Hello,World!</title></head><body></body>" +
                 "</html>";
-        assertNull(mOnUiThread.getTitle());
         mOnUiThread.loadDataAndWaitForCompletion(HTML_CONTENT,
                 "text/html", null);
         assertEquals("Hello,World!", mOnUiThread.getTitle());
@@ -788,7 +785,6 @@
 
     @UiThreadTest
     public void testLoadDataWithBaseUrl() throws Throwable {
-        assertNull(mWebView.getTitle());
         assertNull(mWebView.getUrl());
         String imgUrl = TestHtmlConstants.SMALL_IMG_URL; // relative
 
@@ -1024,40 +1020,6 @@
     }
 
     @UiThreadTest
-    public void testClearCache() throws Exception {
-        final File cacheFileBaseDir = CacheManager.getCacheFileBaseDir();
-        mWebView.clearCache(true);
-        assertEquals(0, cacheFileBaseDir.list().length);
-
-        startWebServer(false);
-        final String url = mWebServer.getAssetUrl(TestHtmlConstants.HELLO_WORLD_URL);
-        mOnUiThread.loadUrlAndWaitForCompletion(url);
-        new PollingCheck(TEST_TIMEOUT) {
-            @Override
-            protected boolean check() {
-                CacheResult result = CacheManager.getCacheFile(url, null);
-                return result != null;
-            }
-        }.run();
-        int cacheFileCount = cacheFileBaseDir.list().length;
-        assertTrue(cacheFileCount > 0);
-
-        mWebView.clearCache(false);
-        // the cache files are still there
-        // can not check other effects of the method
-        assertEquals(cacheFileCount, cacheFileBaseDir.list().length);
-
-        mWebView.clearCache(true);
-        // check the files are deleted
-        new PollingCheck(TEST_TIMEOUT) {
-            @Override
-            protected boolean check() {
-                return cacheFileBaseDir.list().length == 0;
-            }
-        }.run();
-    }
-
-    @UiThreadTest
     public void testPlatformNotifications() {
         WebView.enablePlatformNotifications();
         WebView.disablePlatformNotifications();
diff --git a/tests/tests/webkit/src/android/webkit/cts/WebView_WebViewTransportTest.java b/tests/tests/webkit/src/android/webkit/cts/WebView_WebViewTransportTest.java
index eaa5e69..dd784be 100644
--- a/tests/tests/webkit/src/android/webkit/cts/WebView_WebViewTransportTest.java
+++ b/tests/tests/webkit/src/android/webkit/cts/WebView_WebViewTransportTest.java
@@ -16,16 +16,22 @@
 
 package android.webkit.cts;
 
-import android.test.AndroidTestCase;
+import android.test.ActivityInstrumentationTestCase2;
 import android.test.UiThreadTest;
 import android.webkit.WebView;
 import android.webkit.WebView.WebViewTransport;
 
 
-public class WebView_WebViewTransportTest extends AndroidTestCase {
+public class WebView_WebViewTransportTest
+        extends ActivityInstrumentationTestCase2<WebViewStubActivity> {
+
+    public WebView_WebViewTransportTest() {
+        super("com.android.cts.stub", WebViewStubActivity.class);
+    }
+
     @UiThreadTest
     public void testAccessWebView() {
-        WebView webView = new WebView(mContext);
+        WebView webView = getActivity().getWebView();
         WebViewTransport transport = webView.new WebViewTransport();
 
         assertNull(transport.getWebView());
diff --git a/tools/cts-native-scanner/Android.mk b/tools/cts-native-scanner/Android.mk
index f8b1629..8bcff1c 100644
--- a/tools/cts-native-scanner/Android.mk
+++ b/tools/cts-native-scanner/Android.mk
@@ -34,10 +34,5 @@
 	$(copy-file-to-new-target)
 	$(hide) chmod 755 $@
 
-# the other stuff
-# ============================================================
-subdirs := $(addprefix $(LOCAL_PATH)/,$(addsuffix /Android.mk, \
-		src \
-	))
-
-include $(subdirs)
+# Build all sub-directories
+include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/tools/cts-native-scanner/src/com/android/cts/nativescanner/TestScanner.java b/tools/cts-native-scanner/src/com/android/cts/nativescanner/TestScanner.java
index 9411566..0a1b207 100644
--- a/tools/cts-native-scanner/src/com/android/cts/nativescanner/TestScanner.java
+++ b/tools/cts-native-scanner/src/com/android/cts/nativescanner/TestScanner.java
@@ -30,12 +30,14 @@
  * Scanner of C++ gTest source files.
  *
  * It looks for test declarations and outputs a file following this format:
- *
- * class:TestClass1
- * method:testMethod1
- * method:testMethod2
- * class:TestClass2
- * method:testMethod1
+ * suite:TestSuite
+ * case:TestCase1
+ * test:Test1
+ * test:Test2
+ * suite:TestSuite
+ * case:TestCase2
+ * test:Test1
+ * test:Test2
  *
  */
 class TestScanner {
@@ -71,38 +73,36 @@
             if (file.isDirectory()) {
                 scanDir(file, testNames);
             } else {
-                scanFile(file, testNames);
+                scanFile(new Scanner(file), testNames);
             }
         }
     }
-    // We want to find lines like class SLObjectCreationTest : public ::testing::Test { ...
-    // and extract the "SLObjectCreationTest" as group #1
-    private static final Pattern CLASS_REGEX =
-            Pattern.compile("\\s*class\\s+(\\w+).*");
 
     // We want to find lines like TEST_F(SLObjectCreationTest, testAudioPlayerFromFdCreation) { ...
-    // and extract the "testAudioPlayerFromFdCreation" as group #1
+    // and extract the "SLObjectCreationTest" as group #1,
+    // "testAudioPlayerFromFdCreation" as group #2
     private static final Pattern METHOD_REGEX =
-            Pattern.compile("\\s*TEST_F\\(\\w+,\\s*(\\w+)\\).*");
+            Pattern.compile("\\s*TEST_F\\((\\w+),\\s*(\\w+)\\).*");
 
-    private void scanFile(File file, List<String> testNames) throws FileNotFoundException {
-        Scanner scanner = null;
+    public void scanFile(Scanner scanner, List<String> testNames) {
         try {
-            scanner = new Scanner(file);
+            String lastCase = "";
             while (scanner.hasNextLine()) {
                 String line = scanner.nextLine();
-                Matcher matcher = CLASS_REGEX.matcher(line);
-                if (matcher.matches()) {
-                    testNames.add("suite:" + mTestSuite);
-                    testNames.add("case:" + matcher.group(1));
+
+                Matcher matcher = METHOD_REGEX.matcher(line);
+
+                if (!matcher.matches()) {
                     continue;
                 }
 
-                matcher = METHOD_REGEX.matcher(line);
-                if (matcher.matches()) {
-                    testNames.add("test:" + matcher.group(1));
-                    continue;
+                if (!lastCase.equals(matcher.group(1))) {
+                    testNames.add("suite:" + mTestSuite);
+                    testNames.add("case:" + matcher.group(1));
+                    lastCase = matcher.group(1);
                 }
+
+                testNames.add("test:" + matcher.group(2));
             }
         } finally {
             if (scanner != null) {
diff --git a/tools/cts-native-scanner/tests/Android.mk b/tools/cts-native-scanner/tests/Android.mk
new file mode 100644
index 0000000..6044b0d
--- /dev/null
+++ b/tools/cts-native-scanner/tests/Android.mk
@@ -0,0 +1,28 @@
+# Copyright 2012 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+
+# Only compile source java files in this lib
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+
+LOCAL_MODULE := cts-native-scanner-tests
+LOCAL_MODULE_TAGS := optional
+LOCAL_JAVA_LIBRARIES := ddmlib-prebuilt tradefed-prebuilt cts-native-scanner
+
+include $(BUILD_HOST_JAVA_LIBRARY)
+
+
diff --git a/tools/cts-native-scanner/tests/run_unit_tests.sh b/tools/cts-native-scanner/tests/run_unit_tests.sh
new file mode 100755
index 0000000..a42e42b
--- /dev/null
+++ b/tools/cts-native-scanner/tests/run_unit_tests.sh
@@ -0,0 +1,36 @@
+#!/bin/bash
+
+# Copyright 2012 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#       http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# helper script for running the cts-tradefed unit tests
+
+checkFile() {
+    if [ ! -f "$1" ]; then
+        echo "Unable to locate $1"
+        exit
+    fi;
+}
+
+JAR_DIR=${ANDROID_HOST_OUT}/framework
+JARS="ddmlib-prebuilt.jar tradefed-prebuilt.jar hosttestlib.jar cts-native-scanner.jar cts-native-scanner-tests.jar"
+
+for JAR in $JARS; do
+    checkFile ${JAR_DIR}/${JAR}
+    JAR_PATH=${JAR_PATH}:${JAR_DIR}/${JAR}
+done
+
+java $RDBG_FLAG \
+  -cp ${JAR_PATH} com.android.tradefed.command.Console run singleCommand host -n --class com.android.cts.nativescanner.UnitTests "$@"
+
diff --git a/tools/cts-native-scanner/tests/src/com/android/cts/nativescanner/TestScannerTest.java b/tools/cts-native-scanner/tests/src/com/android/cts/nativescanner/TestScannerTest.java
new file mode 100644
index 0000000..18732fd
--- /dev/null
+++ b/tools/cts-native-scanner/tests/src/com/android/cts/nativescanner/TestScannerTest.java
@@ -0,0 +1,62 @@
+/*
+ * Copyright 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.cts.nativescanner;
+
+import com.android.cts.nativescanner.TestScanner;
+
+import junit.framework.TestCase;
+
+import java.io.File;
+import java.io.StringReader;
+import java.lang.StringBuilder;
+import java.util.Scanner;
+import java.util.List;
+import java.util.ArrayList;
+import java.util.Iterator;
+
+/**
+ * Unit tests for {@link TestScanner}.
+ */
+public class TestScannerTest extends TestCase {
+
+    public void testScanFile() {
+        TestScanner testScanner = new TestScanner(new File("unused"), "TestSuite");
+
+        String newLine = System.getProperty("line.separator");
+        StringBuilder sb = new StringBuilder();
+        sb.append("foobar" + newLine);  // ignored
+        sb.append("TEST_F(TestCase1, TestName1)" + newLine);  // valid
+        sb.append("TEST_F(TestCase1, TestName2)" + newLine);  // valid
+        sb.append("TEST_F(TestCase2, TestName1) foo" + newLine);  // valid
+        sb.append("TEST_F(TestCase2, TestName1 foo)" + newLine);  // ignored
+        sb.append("foo TEST_F(TestCase2, TestName1)" + newLine);  // ignored
+
+        List<String> names = new ArrayList<String>();
+        Scanner scanner = new Scanner(new StringReader(sb.toString()));
+        testScanner.scanFile(scanner, names);
+        Iterator it = names.iterator();
+
+        assertEquals("suite:TestSuite", it.next());
+        assertEquals("case:TestCase1", it.next());
+        assertEquals("test:TestName1", it.next());
+        assertEquals("test:TestName2", it.next());
+        assertEquals("suite:TestSuite", it.next());
+        assertEquals("case:TestCase2", it.next());
+        assertEquals("test:TestName1", it.next());
+        assertFalse(it.hasNext());
+        scanner.close();
+    }
+}
diff --git a/tools/cts-native-scanner/tests/src/com/android/cts/nativescanner/UnitTests.java b/tools/cts-native-scanner/tests/src/com/android/cts/nativescanner/UnitTests.java
new file mode 100644
index 0000000..13d4e5b
--- /dev/null
+++ b/tools/cts-native-scanner/tests/src/com/android/cts/nativescanner/UnitTests.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.cts.nativescanner;
+
+import com.android.cts.nativescanner.TestScannerTest;
+
+import junit.framework.Test;
+import junit.framework.TestSuite;
+
+/**
+ * A test suite for all cts-native-scanner unit tests.
+ * <p/>
+ * All tests listed here should be self-contained, and do not require any external dependencies
+ */
+public class UnitTests extends TestSuite {
+
+    public UnitTests() {
+        super();
+
+        // result package
+        addTestSuite(TestScannerTest.class);
+    }
+
+    public static Test suite() {
+        return new UnitTests();
+    }
+}
diff --git a/tools/tradefed-host/src/com/android/cts/tradefed/testtype/TestPackageDef.java b/tools/tradefed-host/src/com/android/cts/tradefed/testtype/TestPackageDef.java
index ffbb930..0112071 100644
--- a/tools/tradefed-host/src/com/android/cts/tradefed/testtype/TestPackageDef.java
+++ b/tools/tradefed-host/src/com/android/cts/tradefed/testtype/TestPackageDef.java
@@ -43,6 +43,7 @@
 
     public static final String HOST_SIDE_ONLY_TEST = "hostSideOnly";
     public static final String NATIVE_TEST = "native";
+    public static final String WRAPPED_NATIVE_TEST = "wrappednative";
     public static final String VM_HOST_TEST = "vmHostTest";
     public static final String ACCESSIBILITY_TEST =
         "com.android.cts.tradefed.testtype.AccessibilityTestRunner";
@@ -219,6 +220,9 @@
             return vmHostTest;
         } else if (NATIVE_TEST.equals(mTestType)) {
             return new GeeTest(mUri, mName);
+        } else if (WRAPPED_NATIVE_TEST.equals(mTestType)) {
+            CLog.d("Creating new wrapped native test for %s", mName);
+            return new WrappedGTest(mAppNameSpace, mUri, mName, mRunner);
         } else if (ACCESSIBILITY_TEST.equals(mTestType)) {
             AccessibilityTestRunner test = new AccessibilityTestRunner();
             return setInstrumentationTest(test, testCaseDir);
diff --git a/tools/tradefed-host/src/com/android/cts/tradefed/testtype/WrappedGTest.java b/tools/tradefed-host/src/com/android/cts/tradefed/testtype/WrappedGTest.java
new file mode 100644
index 0000000..74c15f6
--- /dev/null
+++ b/tools/tradefed-host/src/com/android/cts/tradefed/testtype/WrappedGTest.java
@@ -0,0 +1,117 @@
+/*
+ * Copyright 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.cts.tradefed.testtype;
+
+import com.android.cts.tradefed.build.CtsBuildHelper;
+import com.android.ddmlib.testrunner.ITestRunListener;
+import com.android.tradefed.build.IBuildInfo;
+import com.android.tradefed.device.DeviceNotAvailableException;
+import com.android.tradefed.device.ITestDevice;
+import com.android.tradefed.log.LogUtil.CLog;
+import com.android.tradefed.result.ITestInvocationListener;
+import com.android.tradefed.testtype.IBuildReceiver;
+import com.android.tradefed.testtype.IDeviceTest;
+import com.android.tradefed.testtype.IRemoteTest;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+
+/**
+ * Test runner for wrapped (native) GTests
+ */
+public class WrappedGTest implements IBuildReceiver, IDeviceTest, IRemoteTest {
+
+    private int mMaxTestTimeMs = 1 * 60 * 1000;
+
+    private CtsBuildHelper mCtsBuild;
+    private ITestDevice mDevice;
+
+    private final String mAppNameSpace;
+    private final String mRunner;
+    private final String mName;
+    private final String mUri;
+
+
+    public WrappedGTest(String appNameSpace, String uri, String name, String runner) {
+        mAppNameSpace = appNameSpace;
+        mRunner = runner;
+        mName = name;
+        mUri = uri;
+    }
+
+    @Override
+    public void setBuild(IBuildInfo buildInfo) {
+        mCtsBuild = CtsBuildHelper.createBuildHelper(buildInfo);
+    }
+
+    @Override
+    public void setDevice(ITestDevice device) {
+        mDevice = device;
+    }
+
+    @Override
+    public ITestDevice getDevice() {
+        return mDevice;
+    }
+
+    @Override
+    public void run(ITestInvocationListener listener) throws DeviceNotAvailableException {
+        if (installTest()) {
+            runTest(listener);
+            uninstallTest();
+        } else {
+            CLog.e("Failed to install test");
+        }
+    }
+
+    private boolean installTest() throws DeviceNotAvailableException {
+        try {
+            File testApp = mCtsBuild.getTestApp(String.format("%s.apk", mName));
+            String installCode = mDevice.installPackage(testApp, true);
+
+            if (installCode != null) {
+                CLog.e("Failed to install %s.apk on %s. Reason: %s", mName,
+                    mDevice.getSerialNumber(), installCode);
+                return false;
+            }
+        }
+        catch (FileNotFoundException e) {
+            CLog.e("Package %s.apk not found", mName);
+            return false;
+        }
+        return true;
+    }
+
+    private void runTest(ITestRunListener listener) throws DeviceNotAvailableException {
+        WrappedGTestResultParser resultParser = new WrappedGTestResultParser(mUri, listener);
+        resultParser.setFakePackagePrefix(mUri + ".");
+        try {
+            String command = String.format("am instrument -w %s/.%s", mAppNameSpace, mRunner);
+            mDevice.executeShellCommand(command, resultParser, mMaxTestTimeMs, 0);
+        } catch (DeviceNotAvailableException e) {
+            resultParser.flush();
+            throw e;
+        } catch (RuntimeException e) {
+            resultParser.flush();
+            throw e;
+        }
+    }
+
+    private void uninstallTest() throws DeviceNotAvailableException {
+        mDevice.uninstallPackage(mAppNameSpace);
+    }
+}
diff --git a/tools/tradefed-host/src/com/android/cts/tradefed/testtype/WrappedGTestResultParser.java b/tools/tradefed-host/src/com/android/cts/tradefed/testtype/WrappedGTestResultParser.java
new file mode 100644
index 0000000..cc3c53a
--- /dev/null
+++ b/tools/tradefed-host/src/com/android/cts/tradefed/testtype/WrappedGTestResultParser.java
@@ -0,0 +1,106 @@
+/*
+ * Copyright 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.cts.tradefed.testtype;
+
+import com.android.ddmlib.testrunner.ITestRunListener;
+import com.android.tradefed.log.LogUtil.CLog;
+
+import java.util.Collection;
+import java.util.List;
+import java.util.ArrayList;
+
+public class WrappedGTestResultParser extends GeeTestResultParser {
+
+    private boolean mInstrumentationError;
+
+    /**
+     * Creates the WrappedGTestResultParser.
+     *
+     * @param testRunName the test run name to provide to
+     *            {@link ITestRunListener#testRunStarted(String, int)}
+     * @param listeners informed of test results as the tests are executing
+     */
+    public WrappedGTestResultParser(String testRunName, Collection<ITestRunListener> listeners) {
+        super(testRunName, listeners);
+    }
+
+    /**
+     * Creates the WrappedGTestResultParser for a single listener.
+     *
+     * @param testRunName the test run name to provide to
+     *            {@link ITestRunListener#testRunStarted(String, int)}
+     * @param listener informed of test results as the tests are executing
+     */
+    public WrappedGTestResultParser(String testRunName, ITestRunListener listener) {
+        super(testRunName, listener);
+    }
+
+    /**
+     * Strips the instrumentation information and then forwards
+     * the raw gtest output to the {@link GeeTestResultParser}.
+     */
+    @Override
+    public void processNewLines(String[] lines) {
+        if (mInstrumentationError) {
+            return;
+        }
+
+        String[] gtestOutput = parseInstrumentation(lines);
+        super.processNewLines(gtestOutput);
+    }
+
+    /**
+     * Parses raw instrumentation output and returns the
+     * contained gtest output
+     *
+     * @param lines the raw instrumentation output
+     * @return the gtest output
+     */
+    public String[] parseInstrumentation(String[] lines) {
+        List<String> output = new ArrayList<String>();
+        boolean readMultiLine = false;
+        for (String line : lines) {
+
+            if (line.startsWith("INSTRUMENTATION_RESULT: ")) {
+                CLog.e("Instrumentation Error:");
+                mInstrumentationError = true;
+            }
+
+            if (mInstrumentationError) {
+                CLog.e(line);
+                continue;
+            }
+
+            if (line.startsWith("INSTRUMENTATION_STATUS: gtest=")) {
+                output.add(line.replace("INSTRUMENTATION_STATUS: gtest=", ""));
+                readMultiLine = true;
+                continue;
+            }
+
+            if (line.startsWith("INSTRUMENTATION_")) {
+                readMultiLine = false;
+                continue;
+            }
+
+            if (readMultiLine) {
+                output.add(line);
+            }
+        }
+
+        return output.toArray(new String[output.size()]);
+    }
+}
+
diff --git a/tools/tradefed-host/tests/src/com/android/cts/tradefed/UnitTests.java b/tools/tradefed-host/tests/src/com/android/cts/tradefed/UnitTests.java
index 7dfac13..3c36a3d 100644
--- a/tools/tradefed-host/tests/src/com/android/cts/tradefed/UnitTests.java
+++ b/tools/tradefed-host/tests/src/com/android/cts/tradefed/UnitTests.java
@@ -27,6 +27,7 @@
 import com.android.cts.tradefed.testtype.TestPackageDefTest;
 import com.android.cts.tradefed.testtype.TestPackageXmlParserTest;
 import com.android.cts.tradefed.testtype.TestPlanTest;
+import com.android.cts.tradefed.testtype.WrappedGTestResultParserTest;
 
 import junit.framework.Test;
 import junit.framework.TestSuite;
@@ -57,6 +58,7 @@
         addTestSuite(TestPackageDefTest.class);
         addTestSuite(TestPackageXmlParserTest.class);
         addTestSuite(TestPlanTest.class);
+        addTestSuite(WrappedGTestResultParserTest.class);
     }
 
     public static Test suite() {
diff --git a/tools/tradefed-host/tests/src/com/android/cts/tradefed/testtype/WrappedGTestResultParserTest.java b/tools/tradefed-host/tests/src/com/android/cts/tradefed/testtype/WrappedGTestResultParserTest.java
new file mode 100644
index 0000000..d386c7a
--- /dev/null
+++ b/tools/tradefed-host/tests/src/com/android/cts/tradefed/testtype/WrappedGTestResultParserTest.java
@@ -0,0 +1,105 @@
+/*
+ * Copyright 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.cts.tradefed.testtype;
+
+import com.android.ddmlib.testrunner.ITestRunListener;
+
+import junit.framework.TestCase;
+
+
+
+/**
+ * Unit tests for {@link WrappedGTestResultParser}.
+ */
+public class WrappedGTestResultParserTest extends TestCase {
+
+    private WrappedGTestResultParser mParser;
+    private final String[] INPUT1 = new String[] {
+        "INSTRUMENTATION_STATUS: gtest=[==========] Running 9 tests from 2 test cases.",
+        "INSTRUMENTATION_STATUS_CODE: 1",
+        "INSTRUMENTATION_STATUS: gtest=[ RUN      ] GLTest.Test1",
+        "INSTRUMENTATION_STATUS: gtest=[       OK ] GLTest.Test1 (10 ms)",
+        "INSTRUMENTATION_STATUS: gtest=/tests/SomeTestFile.cpp:1337: Failure",
+        "Value of: 1 == 0",
+        "  Actual: false",
+        "Expected: true",
+        "INSTRUMENTATION_STATUS: gtest=[  FAILED  ] GLTest.Test2 (1016 ms)",
+        "INSTRUMENTATION_STATUS: gtest=[==========] 2 tests from 1 test cases ran. (17 ms total)",
+        "INSTRUMENTATION_CODE: -1"
+    };
+
+    private final String[] EXPECTED_OUTPUT1 = new String[] {
+        "[==========] Running 9 tests from 2 test cases.",
+        "[ RUN      ] GLTest.Test1",
+        "[       OK ] GLTest.Test1 (10 ms)",
+        "/tests/SomeTestFile.cpp:1337: Failure",
+        "Value of: 1 == 0",
+        "  Actual: false",
+        "Expected: true",
+        "[  FAILED  ] GLTest.Test2 (1016 ms)",
+        "[==========] 2 tests from 1 test cases ran. (17 ms total)",
+    };
+
+    private final String[] INPUT2 = new String[] {
+        "INSTRUMENTATION_STATUS_CODE: 1",
+        "invalid text",
+        "INSTRUMENTATION_STATUS: gtest=[==========] Running 9 tests from 2 test cases.",
+        "INSTRUMENTATION_RESULT: some error",
+        "INSTRUMENTATION_STATUS: gtest=[ RUN      ] GLTest.ExpectTestThatShouldBeSuccessful",
+    };
+
+    private final String[] EXPECTED_OUTPUT2 = new String[] {
+        "[==========] Running 9 tests from 2 test cases.",
+    };
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        mParser = new WrappedGTestResultParser("unused", (ITestRunListener)null);
+    }
+
+    private void assertArrayEquals(String[] expected, String[] result) throws Exception {
+        if (expected == null) {
+            assertNull(result);
+            return;
+        }
+
+        assertEquals(expected.length, result.length);
+
+        for (int i = 0; i < expected.length; i++) {
+            assertEquals(expected[i], result[i]);
+        }
+    }
+
+    /**
+     * Test normal case {@link WrappedGTestResultParser#getRawGTestOutput(java.lang.String[])}
+     * with all kinds of valid input lines.
+     */
+    public void testGetRawGTestOutput_valid() throws Exception {
+        assertArrayEquals(EXPECTED_OUTPUT1, mParser.parseInstrumentation(INPUT1));
+    }
+
+    /**
+     * Test normal case {@link WrappedGTestResultParser#getRawGTestOutput(java.lang.String[])}
+     * with a instrumentation error/invalid input.
+     */
+    public void testGetRawGTestOutput_invalid() throws Exception {
+        assertArrayEquals(EXPECTED_OUTPUT2, mParser.parseInstrumentation(INPUT2));
+    }
+}