am 259aedec: am a567a8cb: change log MSG level to error

* commit '259aedec4083a1c2d1d6335197522fab7f5dba0e':
  change log MSG level to error
diff --git a/CtsTestCaseList.mk b/CtsTestCaseList.mk
index 589f155..60a8cf2 100644
--- a/CtsTestCaseList.mk
+++ b/CtsTestCaseList.mk
@@ -18,6 +18,7 @@
 	CtsExternalStorageApp \
 	CtsInstrumentationAppDiffCert \
 	CtsPermissionDeclareApp \
+	CtsPermissionDeclareAppCompat \
 	CtsSharedUidInstall \
 	CtsSharedUidInstallDiffCert \
 	CtsSimpleAppInstall \
@@ -47,14 +48,11 @@
 	$(cts_support_packages) \
 	$(cts_external_packages)
 
-# Temporarily blacklisted packages
-#   CtsWebkitSecurityTestCases \
-
 # Test packages that require an associated test package XML.
 cts_test_packages := \
 	CtsAccelerationTestCases \
-	CtsAccessibilityServiceTestCases \
 	CtsAccountManagerTestCases \
+	CtsAccessibilityServiceTestCases \
 	CtsAccessibilityTestCases \
 	CtsAdminTestCases \
 	CtsAnimationTestCases \
@@ -97,6 +95,7 @@
 	CtsUtilTestCases \
 	CtsViewTestCases \
 	CtsWebkitTestCases \
+	CtsWebkitSecurityTestCases \
 	CtsWidgetTestCases
 
 # All APKs that need to be scanned by the coverage utilities.
diff --git a/apps/CtsVerifier/AndroidManifest.xml b/apps/CtsVerifier/AndroidManifest.xml
index 0898369..a8cb020 100644
--- a/apps/CtsVerifier/AndroidManifest.xml
+++ b/apps/CtsVerifier/AndroidManifest.xml
@@ -18,7 +18,7 @@
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
       package="com.android.cts.verifier"
       android:versionCode="1"
-      android:versionName="4.1_r2">
+      android:versionName="1337">
 
     <!-- Using 10 for more complete NFC support... -->
     <uses-sdk android:minSdkVersion="10"></uses-sdk>
@@ -306,6 +306,7 @@
                  android:screenOrientation="landscape">
             <intent-filter>
                 <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.cts.intent.category.MANUAL_TEST" />
             </intent-filter>
             <meta-data android:name="test_category" android:value="@string/test_category_camera" />
 
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/location/LocationVerifier.java b/apps/CtsVerifier/src/com/android/cts/verifier/location/LocationVerifier.java
index fd226a6..e3f58c3 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/location/LocationVerifier.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/location/LocationVerifier.java
@@ -58,6 +58,14 @@
             long delta = timestamp - mLastActiveTimestamp;
             mLastActiveTimestamp = timestamp;
 
+            if (location.getAccuracy() <= 0.0) {
+                fail(mProvider + " location has invalid accuracy: " + location.getAccuracy());
+            }
+            if (location.getElapsedRealtimeNano() <= 0) {
+                fail(mProvider + " location has invalid elapsed realtime: " +
+                        location.getElapsedRealtimeNano());
+            }
+
             if (mNumActiveUpdates != 1 && delta < mMinActiveInterval) {
                 fail(mProvider + " location updated too fast: " + delta + "ms < " +
                         mMinActiveInterval + "ms");
@@ -100,6 +108,14 @@
             long delta = timestamp - mLastPassiveTimestamp;
             mLastPassiveTimestamp = timestamp;
 
+            if (location.getAccuracy() <= 0.0) {
+                fail(mProvider + " location has invalid accuracy: " + location.getAccuracy());
+            }
+            if (location.getElapsedRealtimeNano() <= 0) {
+                fail(mProvider + " location has invalid elapsed realtime: " +
+                        location.getElapsedRealtimeNano());
+            }
+
             if (mNumPassiveUpdates != 1 && delta < mMinPassiveInterval) {
                 fail("passive " + mProvider + " location updated too fast: " + delta + "ms < " +
                         mMinPassiveInterval + "ms");
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/nfc/tech/MifareUltralightTagTester.java b/apps/CtsVerifier/src/com/android/cts/verifier/nfc/tech/MifareUltralightTagTester.java
index 23f4762..038d276 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/nfc/tech/MifareUltralightTagTester.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/nfc/tech/MifareUltralightTagTester.java
@@ -29,7 +29,7 @@
  */
 public class MifareUltralightTagTester implements TagTester {
 
-    private static final int USER_PAGE_OFFSET = 4;
+    private static final int USER_PAGE_OFFSET = 5;
 
     private static final int NUM_PAGES = 4;
 
@@ -77,4 +77,4 @@
             }
         };
     }
-}
\ No newline at end of file
+}
diff --git a/build/test_package.mk b/build/test_package.mk
index e8d812b..071acee 100644
--- a/build/test_package.mk
+++ b/build/test_package.mk
@@ -19,6 +19,9 @@
 # Replace "include $(BUILD_PACKAGE)" with "include $(BUILD_CTS_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
diff --git a/hostsidetests/appsecurity/src/com/android/cts/appsecurity/AppSecurityTests.java b/hostsidetests/appsecurity/src/com/android/cts/appsecurity/AppSecurityTests.java
index 23d353e..5c28a4f4 100644
--- a/hostsidetests/appsecurity/src/com/android/cts/appsecurity/AppSecurityTests.java
+++ b/hostsidetests/appsecurity/src/com/android/cts/appsecurity/AppSecurityTests.java
@@ -17,6 +17,7 @@
 package com.android.cts.appsecurity;
 
 import com.android.cts.tradefed.build.CtsBuildHelper;
+import com.android.ddmlib.IDevice;
 import com.android.ddmlib.Log;
 import com.android.ddmlib.testrunner.RemoteAndroidTestRunner;
 import com.android.ddmlib.testrunner.TestIdentifier;
@@ -84,6 +85,9 @@
     // testPermissionDiffCert constants
     private static final String DECLARE_PERMISSION_APK = "CtsPermissionDeclareApp.apk";
     private static final String DECLARE_PERMISSION_PKG = "com.android.cts.permissiondeclareapp";
+    private static final String DECLARE_PERMISSION_COMPAT_APK = "CtsPermissionDeclareAppCompat.apk";
+    private static final String DECLARE_PERMISSION_COMPAT_PKG = "com.android.cts.permissiondeclareappcompat";
+
     private static final String PERMISSION_DIFF_CERT_APK = "CtsUsePermissionDiffCert.apk";
     private static final String PERMISSION_DIFF_CERT_PKG =
         "com.android.cts.usespermissiondiffcertapp";
@@ -206,7 +210,8 @@
             getDevice().uninstallPackage(WRITE_EXTERNAL_STORAGE_APP_PKG);
 
             // stage test file on external storage
-            getDevice().pushString("CAEK", "/sdcard/meow");
+            getDevice().pushString("CAEK",
+                    getDevice().getMountPoint(IDevice.MNT_EXTERNAL_STORAGE) + "/meow");
 
             // mark permission as not enforced
             setPermissionEnforced(getDevice(), READ_EXTERNAL_STORAGE, false);
@@ -311,6 +316,7 @@
         try {
             // cleanup test app that might be installed from previous partial test run
             getDevice().uninstallPackage(DECLARE_PERMISSION_PKG);
+            getDevice().uninstallPackage(DECLARE_PERMISSION_COMPAT_PKG);
             getDevice().uninstallPackage(PERMISSION_DIFF_CERT_PKG);
 
             String installResult = getDevice().installPackage(
@@ -318,6 +324,11 @@
             assertNull(String.format("failed to install declare permission app. Reason: %s",
                     installResult), installResult);
 
+            installResult = getDevice().installPackage(
+                    getTestAppFile(DECLARE_PERMISSION_COMPAT_APK), false);
+            assertNull(String.format("failed to install declare permission compat app. Reason: %s",
+                    installResult), installResult);
+
             // the app will install, but will get error at runtime
             installResult = getDevice().installPackage(getTestAppFile(PERMISSION_DIFF_CERT_APK),
                     false);
@@ -329,6 +340,7 @@
         }
         finally {
             getDevice().uninstallPackage(DECLARE_PERMISSION_PKG);
+            getDevice().uninstallPackage(DECLARE_PERMISSION_COMPAT_PKG);
             getDevice().uninstallPackage(PERMISSION_DIFF_CERT_PKG);
         }
     }
diff --git a/hostsidetests/appsecurity/test-apps/AppAccessData/Android.mk b/hostsidetests/appsecurity/test-apps/AppAccessData/Android.mk
index 6c31fd9..308992e 100644
--- a/hostsidetests/appsecurity/test-apps/AppAccessData/Android.mk
+++ b/hostsidetests/appsecurity/test-apps/AppAccessData/Android.mk
@@ -27,4 +27,6 @@
 # although not strictly necessary, sign this app with different cert than CtsAppWithData
 LOCAL_CERTIFICATE := cts/hostsidetests/appsecurity/certs/cts-testkey2
 
+LOCAL_DEX_PREOPT := false
+
 include $(BUILD_PACKAGE)
diff --git a/hostsidetests/appsecurity/test-apps/AppWithData/Android.mk b/hostsidetests/appsecurity/test-apps/AppWithData/Android.mk
index ae14b7c..8bcb045 100644
--- a/hostsidetests/appsecurity/test-apps/AppWithData/Android.mk
+++ b/hostsidetests/appsecurity/test-apps/AppWithData/Android.mk
@@ -26,4 +26,6 @@
 
 LOCAL_CERTIFICATE := cts/hostsidetests/appsecurity/certs/cts-testkey1
 
+LOCAL_DEX_PREOPT := false
+
 include $(BUILD_PACKAGE)
diff --git a/hostsidetests/appsecurity/test-apps/ExternalStorageApp/Android.mk b/hostsidetests/appsecurity/test-apps/ExternalStorageApp/Android.mk
index 3c687f1..91d6ccf 100644
--- a/hostsidetests/appsecurity/test-apps/ExternalStorageApp/Android.mk
+++ b/hostsidetests/appsecurity/test-apps/ExternalStorageApp/Android.mk
@@ -22,4 +22,6 @@
 LOCAL_SRC_FILES := $(call all-java-files-under, src)
 LOCAL_PACKAGE_NAME := CtsExternalStorageApp
 
+LOCAL_DEX_PREOPT := false
+
 include $(BUILD_PACKAGE)
diff --git a/hostsidetests/appsecurity/test-apps/InstrumentationAppDiffCert/Android.mk b/hostsidetests/appsecurity/test-apps/InstrumentationAppDiffCert/Android.mk
index 67b2246..268ac73 100644
--- a/hostsidetests/appsecurity/test-apps/InstrumentationAppDiffCert/Android.mk
+++ b/hostsidetests/appsecurity/test-apps/InstrumentationAppDiffCert/Android.mk
@@ -27,4 +27,6 @@
 # sign this app with different cert than CtsTargetInstrumentationApp
 LOCAL_CERTIFICATE := cts/hostsidetests/appsecurity/certs/cts-testkey2
 
+LOCAL_DEX_PREOPT := false
+
 include $(BUILD_PACKAGE)
diff --git a/hostsidetests/appsecurity/test-apps/PermissionDeclareApp/Android.mk b/hostsidetests/appsecurity/test-apps/PermissionDeclareApp/Android.mk
index 41ddb64..938b325 100644
--- a/hostsidetests/appsecurity/test-apps/PermissionDeclareApp/Android.mk
+++ b/hostsidetests/appsecurity/test-apps/PermissionDeclareApp/Android.mk
@@ -27,4 +27,6 @@
 # sign this app with a different cert than CtsUsePermissionDiffCert
 LOCAL_CERTIFICATE := cts/hostsidetests/appsecurity/certs/cts-testkey1
 
+LOCAL_DEX_PREOPT := false
+
 include $(BUILD_PACKAGE)
diff --git a/hostsidetests/appsecurity/test-apps/PermissionDeclareApp/AndroidManifest.xml b/hostsidetests/appsecurity/test-apps/PermissionDeclareApp/AndroidManifest.xml
index 00c996c..ad7a640 100644
--- a/hostsidetests/appsecurity/test-apps/PermissionDeclareApp/AndroidManifest.xml
+++ b/hostsidetests/appsecurity/test-apps/PermissionDeclareApp/AndroidManifest.xml
@@ -41,7 +41,8 @@
         <provider android:name="PermissionContentProvider"
                 android:authorities="ctspermissionwithsignature"
                 android:readPermission="com.android.cts.permissionWithSignature"
-                android:writePermission="com.android.cts.permissionWithSignature">
+                android:writePermission="com.android.cts.permissionWithSignature"
+                android:exported="true">
         </provider>
 
         <!-- Need a way for another app to try to access the permission, but will
@@ -49,7 +50,8 @@
         <provider android:name="PermissionContentProviderGranting"
                 android:authorities="ctspermissionwithsignaturegranting"
                 android:readPermission="com.android.cts.permissionWithSignature"
-                android:writePermission="com.android.cts.permissionWithSignature">
+                android:writePermission="com.android.cts.permissionWithSignature"
+                android:exported="true">
             <grant-uri-permission android:pathPattern="/foo.*" />
             <grant-uri-permission android:pathPattern="/yes.*" />
         </provider>
@@ -68,12 +70,19 @@
             <grant-uri-permission android:pathPattern="/yes.*" />
         </provider>
 
+        <!-- An ambiguous content provider, where "exported" was not specified.
+             Nobody should get access to this. -->
+        <provider android:name="AmbiguousContentProvider"
+                android:authorities="ctsambiguousprovider">
+        </provider>
+
         <!-- Target for tests about how path permissions interact with granting
              URI permissions. -->
         <provider android:name="PermissionContentProviderPath"
                 android:authorities="ctspermissionwithsignaturepath"
                 android:readPermission="com.android.cts.permissionNotUsedWithSignature"
-                android:writePermission="com.android.cts.permissionNotUsedWithSignature">
+                android:writePermission="com.android.cts.permissionNotUsedWithSignature"
+                android:exported="true">
             <path-permission
                     android:pathPrefix="/foo"
                     android:readPermission="com.android.cts.permissionWithSignature"
@@ -88,7 +97,8 @@
         <!-- Target for tests that verify path permissions can restrict access
              when no default top-level permission. -->
         <provider android:name="PermissionContentProviderPathRestricting"
-                android:authorities="ctspermissionwithsignaturepathrestricting">
+                android:authorities="ctspermissionwithsignaturepathrestricting"
+                android:exported="true">
             <!-- Require signature permission to get into path. -->
             <path-permission
                     android:pathPrefix="/foo"
diff --git a/hostsidetests/appsecurity/test-apps/PermissionDeclareApp/src/com/android/cts/permissiondeclareapp/AmbiguousContentProvider.java b/hostsidetests/appsecurity/test-apps/PermissionDeclareApp/src/com/android/cts/permissiondeclareapp/AmbiguousContentProvider.java
new file mode 100644
index 0000000..3536979
--- /dev/null
+++ b/hostsidetests/appsecurity/test-apps/PermissionDeclareApp/src/com/android/cts/permissiondeclareapp/AmbiguousContentProvider.java
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.cts.permissiondeclareapp;
+
+import android.content.ContentProvider;
+import android.content.ContentValues;
+import android.database.Cursor;
+import android.net.Uri;
+
+/**
+ * Empty content provider, manifest did not declare exported=true nor exported=false.
+ */
+public class AmbiguousContentProvider extends ContentProvider {
+
+    @Override
+    public int delete(Uri uri, String selection, String[] selectionArgs) {
+        // do nothing
+        return 0;
+    }
+
+    @Override
+    public String getType(Uri uri) {
+        return "got/theMIME";
+    }
+
+    @Override
+    public Uri insert(Uri uri, ContentValues values) {
+        return null;
+    }
+
+    @Override
+    public boolean onCreate() {
+        return false;
+    }
+
+    @Override
+    public Cursor query(Uri uri, String[] projection, String selection,
+            String[] selectionArgs, String sortOrder) {
+        return null;
+    }
+
+    @Override
+    public int update(Uri uri, ContentValues values, String selection,
+            String[] selectionArgs) {
+        return 0;
+    }
+}
diff --git a/hostsidetests/appsecurity/test-apps/PermissionDeclareAppCompat/Android.mk b/hostsidetests/appsecurity/test-apps/PermissionDeclareAppCompat/Android.mk
new file mode 100644
index 0000000..acdc20f
--- /dev/null
+++ b/hostsidetests/appsecurity/test-apps/PermissionDeclareAppCompat/Android.mk
@@ -0,0 +1,32 @@
+# Copyright (C) 2012 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+LOCAL_PATH:= $(call my-dir)
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_TAGS := tests
+
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+
+LOCAL_SDK_VERSION := 16
+
+LOCAL_PACKAGE_NAME := CtsPermissionDeclareAppCompat
+
+# sign this app with a different cert than CtsUsePermissionDiffCert
+LOCAL_CERTIFICATE := cts/hostsidetests/appsecurity/certs/cts-testkey1
+
+LOCAL_DEX_PREOPT := false
+
+include $(BUILD_PACKAGE)
diff --git a/hostsidetests/appsecurity/test-apps/PermissionDeclareAppCompat/AndroidManifest.xml b/hostsidetests/appsecurity/test-apps/PermissionDeclareAppCompat/AndroidManifest.xml
new file mode 100644
index 0000000..5bbf93f
--- /dev/null
+++ b/hostsidetests/appsecurity/test-apps/PermissionDeclareAppCompat/AndroidManifest.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="com.android.cts.permissiondeclareappcompat">
+
+    <application>
+        <!--
+             This provider doesn't specify an android:exported line. Because we specify
+             LOCAL_SDK_VERSION:=16 in Android.mk, we preserve the old behavior of defaulting
+             android:exported="true".
+         -->
+        <provider android:name="AmbiguousContentProvider"
+                android:authorities="ctsambiguousprovidercompat">
+        </provider>
+
+    </application>
+</manifest>
diff --git a/hostsidetests/appsecurity/test-apps/PermissionDeclareAppCompat/src/com/android/cts/permissiondeclareappcompat/AmbiguousContentProvider.java b/hostsidetests/appsecurity/test-apps/PermissionDeclareAppCompat/src/com/android/cts/permissiondeclareappcompat/AmbiguousContentProvider.java
new file mode 100644
index 0000000..8665b70
--- /dev/null
+++ b/hostsidetests/appsecurity/test-apps/PermissionDeclareAppCompat/src/com/android/cts/permissiondeclareappcompat/AmbiguousContentProvider.java
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.cts.permissiondeclareappcompat;
+
+import android.content.ContentProvider;
+import android.content.ContentValues;
+import android.database.Cursor;
+import android.net.Uri;
+
+/**
+ * Empty content provider, all permissions are enforced in manifest
+ */
+public class AmbiguousContentProvider extends ContentProvider {
+
+    @Override
+    public int delete(Uri uri, String selection, String[] selectionArgs) {
+        // do nothing
+        return 0;
+    }
+
+    @Override
+    public String getType(Uri uri) {
+        return "got/theUnspecifiedMIME";
+    }
+
+    @Override
+    public Uri insert(Uri uri, ContentValues values) {
+        return null;
+    }
+
+    @Override
+    public boolean onCreate() {
+        return false;
+    }
+
+    @Override
+    public Cursor query(Uri uri, String[] projection, String selection,
+            String[] selectionArgs, String sortOrder) {
+        return null;
+    }
+
+    @Override
+    public int update(Uri uri, ContentValues values, String selection,
+            String[] selectionArgs) {
+        return 0;
+    }
+}
diff --git a/hostsidetests/appsecurity/test-apps/SharedUidInstall/Android.mk b/hostsidetests/appsecurity/test-apps/SharedUidInstall/Android.mk
index f852c56..25ba1fe 100644
--- a/hostsidetests/appsecurity/test-apps/SharedUidInstall/Android.mk
+++ b/hostsidetests/appsecurity/test-apps/SharedUidInstall/Android.mk
@@ -29,4 +29,6 @@
 
 LOCAL_PROGUARD_ENABLED := disabled
 
+LOCAL_DEX_PREOPT := false
+
 include $(BUILD_PACKAGE)
diff --git a/hostsidetests/appsecurity/test-apps/SharedUidInstallDiffCert/Android.mk b/hostsidetests/appsecurity/test-apps/SharedUidInstallDiffCert/Android.mk
index 3f0a6b6..a00b009 100644
--- a/hostsidetests/appsecurity/test-apps/SharedUidInstallDiffCert/Android.mk
+++ b/hostsidetests/appsecurity/test-apps/SharedUidInstallDiffCert/Android.mk
@@ -27,4 +27,6 @@
 # sign this app with a different cert than CtsSharedUidInstall
 LOCAL_CERTIFICATE := cts/hostsidetests/appsecurity/certs/cts-testkey2
 
+LOCAL_DEX_PREOPT := false
+
 include $(BUILD_PACKAGE)
diff --git a/hostsidetests/appsecurity/test-apps/SimpleAppInstall/Android.mk b/hostsidetests/appsecurity/test-apps/SimpleAppInstall/Android.mk
index f7e0f27..3cd78cf 100644
--- a/hostsidetests/appsecurity/test-apps/SimpleAppInstall/Android.mk
+++ b/hostsidetests/appsecurity/test-apps/SimpleAppInstall/Android.mk
@@ -27,4 +27,6 @@
 # sign this app with a different cert than CtsSimpleAppInstallDiffCert
 LOCAL_CERTIFICATE := cts/hostsidetests/appsecurity/certs/cts-testkey1
 
+LOCAL_DEX_PREOPT := false
+
 include $(BUILD_PACKAGE)
diff --git a/hostsidetests/appsecurity/test-apps/SimpleAppInstallDiffCert/Android.mk b/hostsidetests/appsecurity/test-apps/SimpleAppInstallDiffCert/Android.mk
index 06290be..5fbc910 100644
--- a/hostsidetests/appsecurity/test-apps/SimpleAppInstallDiffCert/Android.mk
+++ b/hostsidetests/appsecurity/test-apps/SimpleAppInstallDiffCert/Android.mk
@@ -27,4 +27,6 @@
 # sign this app with a different cert than CtsSimpleAppInstall
 LOCAL_CERTIFICATE := cts/hostsidetests/appsecurity/certs/cts-testkey2
 
+LOCAL_DEX_PREOPT := false
+
 include $(BUILD_PACKAGE)
diff --git a/hostsidetests/appsecurity/test-apps/TargetInstrumentationApp/Android.mk b/hostsidetests/appsecurity/test-apps/TargetInstrumentationApp/Android.mk
index 532403c..cc87e29 100644
--- a/hostsidetests/appsecurity/test-apps/TargetInstrumentationApp/Android.mk
+++ b/hostsidetests/appsecurity/test-apps/TargetInstrumentationApp/Android.mk
@@ -27,4 +27,6 @@
 # sign this app with different cert than CtsInstrumentationAppDiffCert
 LOCAL_CERTIFICATE := cts/hostsidetests/appsecurity/certs/cts-testkey1
 
+LOCAL_DEX_PREOPT := false
+
 include $(BUILD_PACKAGE)
diff --git a/hostsidetests/appsecurity/test-apps/UsePermissionDiffCert/Android.mk b/hostsidetests/appsecurity/test-apps/UsePermissionDiffCert/Android.mk
index 44ff270..acf9f6f 100644
--- a/hostsidetests/appsecurity/test-apps/UsePermissionDiffCert/Android.mk
+++ b/hostsidetests/appsecurity/test-apps/UsePermissionDiffCert/Android.mk
@@ -27,4 +27,6 @@
 # sign this app with a different cert than CtsPermissionDeclareApp
 LOCAL_CERTIFICATE := cts/hostsidetests/appsecurity/certs/cts-testkey2
 
+LOCAL_DEX_PREOPT := false
+
 include $(BUILD_PACKAGE)
diff --git a/hostsidetests/appsecurity/test-apps/UsePermissionDiffCert/src/com/android/cts/usespermissiondiffcertapp/AccessPermissionWithDiffSigTest.java b/hostsidetests/appsecurity/test-apps/UsePermissionDiffCert/src/com/android/cts/usespermissiondiffcertapp/AccessPermissionWithDiffSigTest.java
index 41cddf5..a6495a9 100644
--- a/hostsidetests/appsecurity/test-apps/UsePermissionDiffCert/src/com/android/cts/usespermissiondiffcertapp/AccessPermissionWithDiffSigTest.java
+++ b/hostsidetests/appsecurity/test-apps/UsePermissionDiffCert/src/com/android/cts/usespermissiondiffcertapp/AccessPermissionWithDiffSigTest.java
@@ -35,20 +35,23 @@
  * Accesses app cts/tests/appsecurity-tests/test-apps/PermissionDeclareApp/...
  */
 public class AccessPermissionWithDiffSigTest extends AndroidTestCase {
-    static final ComponentName GRANT_URI_PERM_COMP
+    private static final ComponentName GRANT_URI_PERM_COMP
             = new ComponentName("com.android.cts.permissiondeclareapp",
                     "com.android.cts.permissiondeclareapp.GrantUriPermission");
-    static final Uri PERM_URI = Uri.parse("content://ctspermissionwithsignature");
-    static final Uri PERM_URI_GRANTING = Uri.parse("content://ctspermissionwithsignaturegranting");
-    static final Uri PERM_URI_PATH = Uri.parse("content://ctspermissionwithsignaturepath");
-    static final Uri PERM_URI_PATH_RESTRICTING = Uri.parse(
+    private static final Uri PERM_URI = Uri.parse("content://ctspermissionwithsignature");
+    private static final Uri PERM_URI_GRANTING = Uri.parse("content://ctspermissionwithsignaturegranting");
+    private static final Uri PERM_URI_PATH = Uri.parse("content://ctspermissionwithsignaturepath");
+    private static final Uri PERM_URI_PATH_RESTRICTING = Uri.parse(
             "content://ctspermissionwithsignaturepathrestricting");
-    static final Uri PRIV_URI = Uri.parse("content://ctsprivateprovider");
-    static final Uri PRIV_URI_GRANTING = Uri.parse("content://ctsprivateprovidergranting");
+    private static final Uri PRIV_URI = Uri.parse("content://ctsprivateprovider");
+    private static final Uri PRIV_URI_GRANTING = Uri.parse("content://ctsprivateprovidergranting");
+    private static final String EXPECTED_MIME_TYPE = "got/theMIME";
 
-    static final String EXPECTED_MIME_TYPE = "got/theMIME";
-    
-    public void assertReadingContentUriNotAllowed(Uri uri, String msg) {
+    private static final Uri AMBIGUOUS_URI_COMPAT = Uri.parse("content://ctsambiguousprovidercompat");
+    private static final String EXPECTED_MIME_TYPE_AMBIGUOUS = "got/theUnspecifiedMIME";
+    private static final Uri AMBIGUOUS_URI = Uri.parse("content://ctsambiguousprovider");
+
+    private void assertReadingContentUriNotAllowed(Uri uri, String msg) {
         try {
             getContext().getContentResolver().query(uri, null, null, null, null);
             fail("expected SecurityException reading " + uri + ": " + msg);
@@ -57,15 +60,15 @@
         }
     }
 
-    public void assertReadingContentUriAllowed(Uri uri) {
+    private void assertReadingContentUriAllowed(Uri uri) {
         try {
             getContext().getContentResolver().query(uri, null, null, null, null);
         } catch (SecurityException e) {
-            fail("unexpected SecurityException reading " + uri);
+            fail("unexpected SecurityException reading " + uri + ": " + e.getMessage());
         }
     }
 
-    public void assertReadingClipNotAllowed(ClipData clip, String msg) {
+    private void assertReadingClipNotAllowed(ClipData clip, String msg) {
         for (int i=0; i<clip.getItemCount(); i++) {
             ClipData.Item item = clip.getItemAt(i);
             Uri uri = item.getUri();
@@ -85,7 +88,7 @@
         }
     }
 
-    public void assertWritingContentUriNotAllowed(Uri uri, String msg) {
+    private void assertWritingContentUriNotAllowed(Uri uri, String msg) {
         try {
             getContext().getContentResolver().insert(uri, new ContentValues());
             fail("expected SecurityException writing " + uri + ": " + msg);
@@ -94,15 +97,15 @@
         }
     }
 
-    public void assertWritingContentUriAllowed(Uri uri) {
+    private void assertWritingContentUriAllowed(Uri uri) {
         try {
             getContext().getContentResolver().insert(uri, new ContentValues());
         } catch (SecurityException e) {
-            fail("unexpected SecurityException writing " + uri);
+            fail("unexpected SecurityException writing " + uri + ": " + e.getMessage());
         }
     }
 
-    public void assertWritingClipNotAllowed(ClipData clip, String msg) {
+    private void assertWritingClipNotAllowed(ClipData clip, String msg) {
         for (int i=0; i<clip.getItemCount(); i++) {
             ClipData.Item item = clip.getItemAt(i);
             Uri uri = item.getUri();
@@ -145,8 +148,35 @@
      * since it is not exported from its app.
      */
     public void testReadProviderWhenPrivate() {
-        assertReadingContentUriNotAllowed(PRIV_URI,
-                "shouldn't read private provider");
+        assertReadingContentUriNotAllowed(PRIV_URI, "shouldn't read private provider");
+    }
+
+    /**
+     * Test that the ctsambiguousprovider content provider cannot be read,
+     * since it doesn't have an "exported=" line.
+     */
+    public void testReadProviderWhenAmbiguous() {
+        assertReadingContentUriNotAllowed(AMBIGUOUS_URI, "shouldn't read ambiguous provider");
+    }
+
+    /**
+     * Old App Compatibility Test
+     *
+     * Test that the ctsambiguousprovidercompat content provider can be read for older
+     * API versions, because it didn't specify either exported=true or exported=false.
+     */
+    public void testReadProviderWhenAmbiguousCompat() {
+        assertReadingContentUriAllowed(AMBIGUOUS_URI_COMPAT);
+    }
+
+    /**
+     * Old App Compatibility Test
+     *
+     * Test that the ctsambiguousprovidercompat content provider can be written for older
+     * API versions, because it didn't specify either exported=true or exported=false.
+     */
+    public void testWriteProviderWhenAmbiguousCompat() {
+        assertWritingContentUriAllowed(AMBIGUOUS_URI_COMPAT);
     }
 
     /**
@@ -154,16 +184,23 @@
      * since it is not exported from its app.
      */
     public void testWriteProviderWhenPrivate() {
-        assertWritingContentUriNotAllowed(PRIV_URI,
-                "shouldn't write private provider");
+        assertWritingContentUriNotAllowed(PRIV_URI, "shouldn't write private provider");
     }
 
-    public static ClipData makeSingleClipData(Uri uri) {
+    /**
+     * Test that the ctsambiguousprovider content provider cannot be written,
+     * since it doesn't have an exported= line.
+     */
+    public void testWriteProviderWhenAmbiguous() {
+        assertWritingContentUriNotAllowed(AMBIGUOUS_URI, "shouldn't write ambiguous provider");
+    }
+
+    private static ClipData makeSingleClipData(Uri uri) {
         return new ClipData("foo", new String[] { "foo/bar" },
                 new ClipData.Item(uri));
     }
 
-    public static ClipData makeMultiClipData(Uri uri) {
+    private static ClipData makeMultiClipData(Uri uri) {
         Uri grantClip1Uri = Uri.withAppendedPath(uri, "clip1");
         Uri grantClip2Uri = Uri.withAppendedPath(uri, "clip2");
         Uri grantClip3Uri = Uri.withAppendedPath(uri, "clip3");
@@ -187,18 +224,18 @@
         return clip;
     }
 
-    public static Intent makeClipIntent(ClipData clip, int flags) {
+    private static Intent makeClipIntent(ClipData clip, int flags) {
         Intent intent = new Intent();
         intent.setClipData(clip);
         intent.addFlags(flags);
         return intent;
     }
 
-    public static Intent makeClipIntent(Uri uri, int flags) {
+    private static Intent makeClipIntent(Uri uri, int flags) {
         return makeClipIntent(makeMultiClipData(uri), flags);
     }
 
-    public void doTryGrantUriActivityPermissionToSelf(Uri uri, int mode) {
+    private void doTryGrantUriActivityPermissionToSelf(Uri uri, int mode) {
         Uri grantDataUri = Uri.withAppendedPath(uri, "data");
         Intent grantIntent = new Intent();
         grantIntent.setData(grantDataUri);
@@ -261,7 +298,7 @@
                 Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
     }
 
-    public void doTryGrantUriServicePermissionToSelf(Uri uri, int mode) {
+    private void doTryGrantUriServicePermissionToSelf(Uri uri, int mode) {
         Uri grantDataUri = Uri.withAppendedPath(uri, "data");
         Intent grantIntent = new Intent();
         grantIntent.setData(grantDataUri);
@@ -320,7 +357,7 @@
                 Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
     }
 
-    static class GrantResultReceiver extends BroadcastReceiver {
+    private static class GrantResultReceiver extends BroadcastReceiver {
         boolean mHaveResult = false;
         boolean mGoodResult = false;
         boolean mSucceeded = false;
@@ -389,7 +426,7 @@
         }
     }
 
-    void grantUriPermissionFail(Uri uri, int mode, boolean service) {
+    private void grantUriPermissionFail(Uri uri, int mode, boolean service) {
         Uri grantDataUri = Uri.withAppendedPath(uri, "data");
         Intent grantIntent = new Intent();
         grantIntent.setData(grantDataUri);
@@ -417,7 +454,7 @@
                 + " when should not");
     }
 
-    void doTestGrantUriPermissionFail(Uri uri) {
+    private void doTestGrantUriPermissionFail(Uri uri) {
         grantUriPermissionFail(uri, Intent.FLAG_GRANT_READ_URI_PERMISSION, false);
         grantUriPermissionFail(uri, Intent.FLAG_GRANT_WRITE_URI_PERMISSION, false);
         grantUriPermissionFail(uri, Intent.FLAG_GRANT_READ_URI_PERMISSION, true);
@@ -450,6 +487,14 @@
     }
 
     /**
+     * Test that the ctsambiguousprovider content provider can not grant
+     * URI permissions to others.
+     */
+    public void testGrantAmbiguousNonGrantingFail() {
+        doTestGrantUriPermissionFail(AMBIGUOUS_URI);
+    }
+
+    /**
      * Test that the ctsprivateprovidergranting content provider can not grant
      * URI permissions to paths outside of the grant tree
      */
@@ -458,7 +503,7 @@
         doTestGrantUriPermissionFail(Uri.withAppendedPath(PRIV_URI_GRANTING, "invalid"));
     }
 
-    void grantClipUriPermission(ClipData clip, int mode, boolean service) {
+    private void grantClipUriPermission(ClipData clip, int mode, boolean service) {
         Intent grantIntent = new Intent();
         if (clip.getItemCount() == 1) {
             grantIntent.setData(clip.getItemAt(0).getUri());
@@ -482,7 +527,7 @@
         getContext().sendBroadcast(intent);
     }
 
-    void assertReadingClipAllowed(ClipData clip) {
+    private void assertReadingClipAllowed(ClipData clip) {
         for (int i=0; i<clip.getItemCount(); i++) {
             ClipData.Item item = clip.getItemAt(i);
             Uri uri = item.getUri();
@@ -510,7 +555,7 @@
         }
     }
 
-    void doTestGrantActivityUriReadPermission(Uri uri, boolean useClip) {
+    private void doTestGrantActivityUriReadPermission(Uri uri, boolean useClip) {
         final Uri subUri = Uri.withAppendedPath(uri, "foo");
         final Uri subSubUri = Uri.withAppendedPath(subUri, "bar");
         final Uri sub2Uri = Uri.withAppendedPath(uri, "yes");
@@ -598,7 +643,7 @@
         assertReadingClipNotAllowed(sub2Clip, "shouldn't read after losing granted URI");
     }
 
-    void assertWritingClipAllowed(ClipData clip) {
+    private void assertWritingClipAllowed(ClipData clip) {
         for (int i=0; i<clip.getItemCount(); i++) {
             ClipData.Item item = clip.getItemAt(i);
             Uri uri = item.getUri();
@@ -618,7 +663,7 @@
         }
     }
 
-    void doTestGrantActivityUriWritePermission(Uri uri, boolean useClip) {
+    private void doTestGrantActivityUriWritePermission(Uri uri, boolean useClip) {
         final Uri subUri = Uri.withAppendedPath(uri, "foo");
         final Uri subSubUri = Uri.withAppendedPath(subUri, "bar");
         final Uri sub2Uri = Uri.withAppendedPath(uri, "yes");
@@ -833,7 +878,7 @@
         assertReadingClipNotAllowed(sub2Clip, "shouldn't read after losing granted URI");
     }
 
-    void doTestGrantServiceUriWritePermission(Uri uri, boolean useClip) {
+    private void doTestGrantServiceUriWritePermission(Uri uri, boolean useClip) {
         final Uri subUri = Uri.withAppendedPath(uri, "foo");
         final Uri subSubUri = Uri.withAppendedPath(subUri, "bar");
         final Uri sub2Uri = Uri.withAppendedPath(uri, "yes");
@@ -1069,7 +1114,7 @@
 
     public void testGetMimeTypePermission() {
         // Precondition: no current access.
-        assertWritingContentUriNotAllowed(PERM_URI, "shouldn't write when starting test");
+        assertReadingContentUriNotAllowed(PERM_URI, "shouldn't read when starting test");
         assertWritingContentUriNotAllowed(PERM_URI, "shouldn't write when starting test");
         
         // All apps should be able to get MIME type regardless of permission.
@@ -1078,10 +1123,32 @@
 
     public void testGetMimeTypePrivate() {
         // Precondition: no current access.
-        assertWritingContentUriNotAllowed(PRIV_URI, "shouldn't write when starting test");
+        assertReadingContentUriNotAllowed(PRIV_URI, "shouldn't read when starting test");
         assertWritingContentUriNotAllowed(PRIV_URI, "shouldn't write when starting test");
         
         // All apps should be able to get MIME type even if provider is private.
         assertEquals(getContext().getContentResolver().getType(PRIV_URI), EXPECTED_MIME_TYPE);
     }
+
+    public void testGetMimeTypeAmbiguous() {
+        // Precondition: no current access.
+        assertReadingContentUriNotAllowed(AMBIGUOUS_URI, "shouldn't read when starting test");
+        assertWritingContentUriNotAllowed(AMBIGUOUS_URI, "shouldn't write when starting test");
+
+        // All apps should be able to get MIME type even if provider is private.
+        assertEquals(getContext().getContentResolver().getType(AMBIGUOUS_URI), EXPECTED_MIME_TYPE);
+    }
+
+    /**
+     * Old App Compatibility Test
+     *
+     * We should be able to access the mime type of a content provider of an older
+     * application, even if that application didn't explicitly declare either
+     * exported=true or exported=false
+     */
+    public void testGetMimeTypeAmbiguousCompat() {
+        // All apps should be able to get MIME type even if provider is private.
+        assertEquals(EXPECTED_MIME_TYPE_AMBIGUOUS,
+                getContext().getContentResolver().getType(AMBIGUOUS_URI_COMPAT));
+    }
 }
diff --git a/hostsidetests/appsecurity/test-apps/WriteExternalStorageApp/Android.mk b/hostsidetests/appsecurity/test-apps/WriteExternalStorageApp/Android.mk
index bdb2887..9e056a9 100644
--- a/hostsidetests/appsecurity/test-apps/WriteExternalStorageApp/Android.mk
+++ b/hostsidetests/appsecurity/test-apps/WriteExternalStorageApp/Android.mk
@@ -22,4 +22,6 @@
 LOCAL_SRC_FILES := $(call all-java-files-under, src)
 LOCAL_PACKAGE_NAME := CtsWriteExternalStorageApp
 
+LOCAL_DEX_PREOPT := false
+
 include $(BUILD_PACKAGE)
diff --git a/hostsidetests/monkey/test-apps/CtsMonkeyApp/Android.mk b/hostsidetests/monkey/test-apps/CtsMonkeyApp/Android.mk
index 9365af3..f6543fb 100644
--- a/hostsidetests/monkey/test-apps/CtsMonkeyApp/Android.mk
+++ b/hostsidetests/monkey/test-apps/CtsMonkeyApp/Android.mk
@@ -26,4 +26,8 @@
 
 LOCAL_PROGUARD_ENABLED := disabled
 
+LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
+
+LOCAL_DEX_PREOPT := false
+
 include $(BUILD_PACKAGE)
diff --git a/hostsidetests/monkey/test-apps/CtsMonkeyApp2/Android.mk b/hostsidetests/monkey/test-apps/CtsMonkeyApp2/Android.mk
index 0d76f2d..29bf9d6 100644
--- a/hostsidetests/monkey/test-apps/CtsMonkeyApp2/Android.mk
+++ b/hostsidetests/monkey/test-apps/CtsMonkeyApp2/Android.mk
@@ -26,4 +26,8 @@
 
 LOCAL_PROGUARD_ENABLED := disabled
 
+LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
+
+LOCAL_DEX_PREOPT := false
+
 include $(BUILD_PACKAGE)
diff --git a/suite/pts/Android.mk b/suite/pts/Android.mk
new file mode 100644
index 0000000..07b30e3
--- /dev/null
+++ b/suite/pts/Android.mk
@@ -0,0 +1,18 @@
+#
+# 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.
+#
+
+include cts/suite/pts/PtsBuild.mk
+include $(call all-subdir-makefiles)
diff --git a/suite/pts/PtsBuild.mk b/suite/pts/PtsBuild.mk
new file mode 100644
index 0000000..cb79956
--- /dev/null
+++ b/suite/pts/PtsBuild.mk
@@ -0,0 +1,128 @@
+#
+# 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.
+#
+
+# several makefiles for CTS merged for PTS
+
+LOCAL_PATH:= $(call my-dir)
+
+# New packages should be added here
+PTS_TEST_PACKAGES = \
+    PtsDeviceFilePerf \
+    PtsDeviceUi
+
+PTS_SUPPORT_PACKAGES := \
+	TestDeviceSetup
+
+BUILD_PTS_PACKAGE := cts/suite/pts/build/test_package.mk
+
+PTS_JAVA_TEST_SCANNER := $(HOST_OUT_EXECUTABLES)/cts-java-scanner
+PTS_JAVA_TEST_SCANNER_DOCLET := $(HOST_OUT_JAVA_LIBRARIES)/cts-java-scanner-doclet.jar
+
+# Generator of test XMLs from scanner output.
+PTS_XML_GENERATOR := $(HOST_OUT_EXECUTABLES)/cts-xml-generator
+
+# File indicating which tests should be blacklisted due to problems.
+PTS_EXPECTATIONS := cts/suite/pts/expectations/knownfailures.txt
+
+PTS_TESTCASES_OUT := $(HOST_OUT)/pts-testcases
+
+define pts-get-package-paths
+	$(foreach pkg,$(1),$(PTS_TESTCASES_OUT)/$(pkg).apk)
+endef
+
+define pts-get-test-xmls
+	$(foreach name,$(1),$(PTS_TESTCASES_OUT)/$(name).xml)
+endef
+
+PTS_TEST_CASE_LIST := \
+	$(PTS_SUPPORT_PACKAGES)
+
+PTS_TEST_CASES := \
+		$(call pts-get-package-paths,$(PTS_TEST_PACKAGES))
+
+PTS_TEST_XMLS := $(call pts-get-test-xmls,$(PTS_TEST_PACKAGES))
+
+pts_dir := $(HOST_OUT)/pts
+pts_tools_src_dir := cts/tools
+
+pts_name := android-pts
+
+DDMLIB_JAR := $(HOST_OUT_JAVA_LIBRARIES)/ddmlib-prebuilt.jar
+junit_host_jar := $(HOST_OUT_JAVA_LIBRARIES)/junit.jar
+HOSTTESTLIB_JAR := $(HOST_OUT_JAVA_LIBRARIES)/hosttestlib.jar
+TF_JAR := $(HOST_OUT_JAVA_LIBRARIES)/tradefed-prebuilt.jar
+PTS_TF_JAR := $(HOST_OUT_JAVA_LIBRARIES)/cts-tradefed.jar
+PTS_TF_EXEC := $(HOST_OUT_EXECUTABLES)/pts-tradefed
+PTS_TF_README := $(pts_tools_src_dir)/tradefed-host/README
+
+
+DEFAULT_TEST_PLAN := $(pts_dir)/$(pts_name)/resource/plans/PTS.xml
+
+$(pts_dir)/all_pts_files_stamp: PRIVATE_JUNIT_HOST_JAR := $(junit_host_jar)
+
+$(pts_dir)/all_pts_files_stamp: $(PTS_TEST_CASES) $(PTS_TEST_CASE_LIST) $(junit_host_jar) $(HOSTTESTLIB_JAR) $(PTS_HOST_LIBRARY_JARS) $(TF_JAR) $(VMTESTSTF_JAR) $(PTS_TF_JAR) $(PTS_TF_EXEC) $(PTS_TF_README) $(ACP)
+# Make necessary directory for PTS
+	$(hide) rm -rf $(PRIVATE_PTS_DIR)
+	$(hide) mkdir -p $(TMP_DIR)
+	$(hide) mkdir -p $(PRIVATE_DIR)/docs
+	$(hide) mkdir -p $(PRIVATE_DIR)/tools
+	$(hide) mkdir -p $(PRIVATE_DIR)/repository/testcases
+	$(hide) mkdir -p $(PRIVATE_DIR)/repository/plans
+# Copy executable and JARs to PTS directory
+	$(hide) $(ACP) -fp $(DDMLIB_JAR) $(PRIVATE_JUNIT_HOST_JAR) $(HOSTTESTLIB_JAR) $(PTS_HOST_LIBRARY_JARS) $(TF_JAR) $(PTS_TF_JAR) $(PTS_TF_EXEC) $(PTS_TF_README) $(PRIVATE_DIR)/tools
+# Change mode of the executables
+	$(foreach apk,$(PTS_TEST_CASE_LIST),$(call copy-testcase-apk,$(apk)))
+	$(foreach testcase,$(PTS_TEST_CASES),$(call copy-testcase,$(testcase)))
+	$(hide) touch $@
+
+# Generate the default test plan for User.
+# Usage: buildCts.py <testRoot> <ctsOutputDir> <tempDir> <androidRootDir> <docletPath>
+
+$(DEFAULT_TEST_PLAN): $(pts_dir)/all_pts_files_stamp $(pts_tools_src_dir)/utils/buildCts.py $(HOST_OUT_JAVA_LIBRARIES)/descGen.jar $(PTS_TEST_XMLS) | $(ACP)
+	$(hide) $(ACP) -fp $(PTS_TEST_XMLS) $(PRIVATE_DIR)/repository/testcases
+	$(hide) $(pts_tools_src_dir)/utils/buildCts.py cts/suite/pts $(PRIVATE_DIR) $(TMP_DIR) \
+		$(TOP) $(HOST_OUT_JAVA_LIBRARIES)/descGen.jar -pts
+
+# Package PTS and clean up.
+INTERNAL_PTS_TARGET := $(pts_dir)/$(pts_name).zip
+$(INTERNAL_PTS_TARGET): PRIVATE_NAME := $(pts_name)
+$(INTERNAL_PTS_TARGET): PRIVATE_PTS_DIR := $(pts_dir)
+$(INTERNAL_PTS_TARGET): PRIVATE_DIR := $(pts_dir)/$(pts_name)
+$(INTERNAL_PTS_TARGET): TMP_DIR := $(pts_dir)/temp
+$(INTERNAL_PTS_TARGET): $(pts_dir)/all_pts_files_stamp $(DEFAULT_TEST_PLAN)
+	$(hide) echo "Package PTS: $@"
+	$(hide) cd $(dir $@) && zip -rq $(notdir $@) $(PRIVATE_NAME)
+
+.PHONY: pts
+pts: $(INTERNAL_PTS_TARGET)
+cts: pts
+# generate PTS during CTS build
+ifneq ($(filter cts, $(MAKECMDGOALS)),)
+$(call dist-for-goals,cts,$(INTERNAL_PTS_TARGET))
+endif
+
+define copy-testcase-apk
+
+$(hide) $(ACP) -fp $(call intermediates-dir-for,APPS,$(1))/package.apk \
+	$(PRIVATE_DIR)/repository/testcases/$(1).apk
+
+endef
+
+define copy-testcase
+
+$(hide) $(ACP) -fp $(1) $(PRIVATE_DIR)/repository/testcases/$(notdir $1)
+
+endef
diff --git a/suite/pts/build/test_package.mk b/suite/pts/build/test_package.mk
new file mode 100644
index 0000000..f677c3b
--- /dev/null
+++ b/suite/pts/build/test_package.mk
@@ -0,0 +1,49 @@
+# 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.
+
+# copied from cts/build. modified for PTS
+
+# Disable by default so "m pts" will work in emulator builds
+LOCAL_DEX_PREOPT := false
+
+include $(BUILD_PACKAGE)
+
+pts_package_apk := $(PTS_TESTCASES_OUT)/$(LOCAL_PACKAGE_NAME).apk
+pts_package_xml := $(PTS_TESTCASES_OUT)/$(LOCAL_PACKAGE_NAME).xml
+
+$(pts_package_apk): PRIVATE_PACKAGE := $(LOCAL_PACKAGE_NAME)
+$(pts_package_apk): $(call intermediates-dir-for,APPS,$(LOCAL_PACKAGE_NAME))/package.apk | $(ACP)
+	$(hide) mkdir -p $(PTS_TESTCASES_OUT)
+	$(hide) $(ACP) -fp $< $@
+
+$(pts_package_xml): PRIVATE_PATH := $(LOCAL_PATH)
+$(pts_package_xml): PRIVATE_INSTRUMENTATION := $(LOCAL_INSTRUMENTATION_FOR)
+$(pts_package_xml): PRIVATE_PACKAGE := $(LOCAL_PACKAGE_NAME)
+$(pts_package_xml): PRIVATE_TEST_PACKAGE := com.android.pts.$(notdir $(LOCAL_PATH))
+$(pts_package_xml): PRIVATE_MANIFEST := $(LOCAL_PATH)/AndroidManifest.xml
+$(pts_package_xml): PRIVATE_TEST_TYPE := $(if $(LOCAL_PTS_TEST_RUNNER),$(LOCAL_PTS_TEST_RUNNER),'')
+$(pts_package_xml): $(call intermediates-dir-for,APPS,$(LOCAL_PACKAGE_NAME))/package.apk $(PTS_EXPECTATIONS) $(PTS_JAVA_TEST_SCANNER_DOCLET) $(PTS_JAVA_TEST_SCANNER) $(PTS_XML_GENERATOR)
+	$(hide) echo Generating test description for java package $(PRIVATE_PACKAGE)
+	$(hide) mkdir -p $(PTS_TESTCASES_OUT)
+	$(hide) $(PTS_JAVA_TEST_SCANNER) \
+						-s $(PRIVATE_PATH) \
+						-d $(PTS_JAVA_TEST_SCANNER_DOCLET) | \
+			$(PTS_XML_GENERATOR) \
+						-t $(PRIVATE_TEST_TYPE) \
+						-m $(PRIVATE_MANIFEST) \
+						-i "$(PRIVATE_INSTRUMENTATION)" \
+						-n $(PRIVATE_PACKAGE) \
+						-p $(PRIVATE_TEST_PACKAGE) \
+						-e $(PTS_EXPECTATIONS) \
+						-o $@
diff --git a/suite/pts/deviceTests/Android.mk b/suite/pts/deviceTests/Android.mk
new file mode 100644
index 0000000..c141484
--- /dev/null
+++ b/suite/pts/deviceTests/Android.mk
@@ -0,0 +1,17 @@
+#
+# 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.
+#
+
+include $(call all-subdir-makefiles)
diff --git a/suite/pts/deviceTests/filesystemperf/Android.mk b/suite/pts/deviceTests/filesystemperf/Android.mk
new file mode 100644
index 0000000..3709ecc
--- /dev/null
+++ b/suite/pts/deviceTests/filesystemperf/Android.mk
@@ -0,0 +1,32 @@
+# Copyright (C) 2012 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+# don't include this package in any target
+LOCAL_MODULE_TAGS := optional
+
+LOCAL_JAVA_LIBRARIES := android.test.runner
+
+LOCAL_STATIC_JAVA_LIBRARIES := ptsutil
+
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+
+LOCAL_PACKAGE_NAME := PtsDeviceFilePerf
+
+LOCAL_SDK_VERSION := 16
+
+include $(BUILD_PTS_PACKAGE)
+
diff --git a/suite/pts/deviceTests/filesystemperf/AndroidManifest.xml b/suite/pts/deviceTests/filesystemperf/AndroidManifest.xml
new file mode 100644
index 0000000..0492900
--- /dev/null
+++ b/suite/pts/deviceTests/filesystemperf/AndroidManifest.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+        package="com.android.pts.filesystemperf">
+
+    <uses-permission android:name="android.permission.DISABLE_KEYGUARD" />
+    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
+
+    <application>
+        <uses-library android:name="android.test.runner" />
+    </application>
+    <instrumentation android:name="android.test.InstrumentationTestRunner"
+            android:targetPackage="com.android.pts.filesystemperf"
+            android:label="UI Latency measurement" />
+</manifest>
diff --git a/suite/pts/deviceTests/filesystemperf/src/com/android/pts/filesystemperf/FileUtil.java b/suite/pts/deviceTests/filesystemperf/src/com/android/pts/filesystemperf/FileUtil.java
new file mode 100644
index 0000000..3b51630
--- /dev/null
+++ b/suite/pts/deviceTests/filesystemperf/src/com/android/pts/filesystemperf/FileUtil.java
@@ -0,0 +1,222 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.pts.filesystemperf;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.util.Random;
+
+import com.android.pts.util.MeasureRun;
+
+import android.content.Context;
+import android.util.Log;
+
+public class FileUtil {
+    private static final String TAG = "FileUtil";
+    private static final Random mRandom = new Random(0);
+    private static long mFileId = 0;
+    /**
+     * create array with different data per each call
+     *
+     * @param length
+     * @param randomSeed
+     * @return
+     */
+    public static byte[] generateRandomData(int length) {
+        byte[] buffer = new byte[length];
+        int val = mRandom.nextInt();
+        for (int i = 0; i < length / 4; i++) {
+            // in little-endian
+            buffer[i * 4] = (byte)(val & 0x000000ff);
+            buffer[i * 4 + 1] = (byte)((val & 0x0000ff00) >> 8);
+            buffer[i * 4 + 2] = (byte)((val & 0x00ff0000) >> 16);
+            buffer[i * 4 + 3] = (byte)((val & 0xff000000) >> 24);
+            val++;
+        }
+        for (int i = (length / 4) * 4; i < length; i++) {
+            buffer[i] = 0;
+        }
+        return buffer;
+    }
+
+    /**
+     * create a new file under the given dirName.
+     * Existing files will not be affected.
+     * @param context
+     * @param dirName
+     * @return
+     */
+    public static File createNewFile(Context context, String dirName) {
+        File topDir = new File(context.getFilesDir(), dirName);
+        topDir.mkdir();
+        String[] list = topDir.list();
+
+        String newFileName;
+        while (true) {
+            newFileName = Long.toString(mFileId);
+            boolean fileExist = false;
+            for (String child : list) {
+                if (child.equals(newFileName)) {
+                    fileExist = true;
+                    break;
+                }
+            }
+            if (!fileExist) {
+                break;
+            }
+            mFileId++;
+        }
+        mFileId++;
+        //Log.i(TAG, "filename" + Long.toString(mFileId));
+        return new File(topDir, newFileName);
+    }
+
+    /**
+     * create multiple new files
+     * @param context
+     * @param dirName
+     * @param count number of files to create
+     * @return
+     */
+    public static File[] createNewFiles(Context context, String dirName, int count) {
+        File[] files = new File[count];
+        for (int i = 0; i < count; i++) {
+            files[i] = createNewFile(context, dirName);
+        }
+        return files;
+    }
+
+    /**
+     * write file with given byte array
+     * @param file
+     * @param data
+     * @param append will append if set true. Otherwise, write from beginning
+     * @throws IOException
+     */
+    public static void writeFile(File file, byte[] data, boolean append) throws IOException {
+        FileOutputStream out = new FileOutputStream(file, append);
+        out.write(data);
+        out.flush();
+        out.close();
+    }
+
+    /**
+     * create a new file with given length.
+     * @param context
+     * @param dirName
+     * @param length
+     * @return
+     * @throws IOException
+     */
+    public static File createNewFilledFile(Context context, String dirName, long length)
+            throws IOException {
+        final int BUFFER_SIZE = 10 * 1024 * 1024;
+        File file = createNewFile(context, dirName);
+        FileOutputStream out = new FileOutputStream(file);
+        byte[] data = generateRandomData(BUFFER_SIZE);
+        long written = 0;
+        while (written < length) {
+            out.write(data);
+            written += BUFFER_SIZE;
+        }
+        out.flush();
+        out.close();
+        return file;
+    }
+
+    /**
+     * remove given file or directory under the current app's files dir.
+     * @param context
+     * @param name
+     */
+    public static void removeFileOrDir(Context context, String name) {
+        File entry = new File(context.getFilesDir(), name);
+        if (entry.exists()) {
+            removeEntry(entry);
+        }
+    }
+
+    private static void removeEntry(File entry) {
+        if (entry.isDirectory()) {
+            String[] children = entry.list();
+            for (String child : children) {
+                removeEntry(new File(entry, child));
+            }
+        }
+        entry.delete();
+    }
+
+    /**
+     * measure time taken for each IO run with amount R/W
+     * @param count
+     * @param run
+     * @param readAmount returns amount of read in bytes for each interval.
+     *        Value will not be written if /proc/self/io does not exist.
+     * @param writeAmount returns amount of write in bytes for each interval.
+     * @return time per each interval
+     * @throws IOException
+     */
+    public static double[] measureIO(int count, double[] readAmount, double[] writeAmount,
+            MeasureRun run)  throws IOException {
+        double[] result = new double[count];
+        File procIo = new File("/proc/self/io");
+        boolean measureIo = procIo.exists();
+        long prev = System.currentTimeMillis();
+        RWAmount prevAmount = new RWAmount();
+        if (measureIo) {
+            prevAmount = getRWAmount(procIo);
+        }
+        for (int i = 0; i < count; i++) {
+            run.run(i);
+            long current =  System.currentTimeMillis();
+            result[i] = current - prev;
+            prev = current;
+            if (measureIo) {
+                RWAmount currentAmount = getRWAmount(procIo);
+                readAmount[i] = currentAmount.mRd - prevAmount.mRd;
+                writeAmount[i] = currentAmount.mWr - prevAmount.mWr;
+                prevAmount = currentAmount;
+            }
+        }
+        return result;
+    }
+
+    private static class RWAmount {
+        public double mRd = 0.0;
+        public double mWr = 0.0;
+    };
+
+    private static RWAmount getRWAmount(File file) throws IOException {
+        RWAmount amount = new RWAmount();
+
+        BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream(file)));
+        String line;
+        while((line = br.readLine())!= null) {
+            if (line.startsWith("read_bytes")) {
+                amount.mRd = Double.parseDouble(line.split(" ")[1]);
+            } else if (line.startsWith("write_bytes")) {
+                amount.mWr = Double.parseDouble(line.split(" ")[1]);
+            }
+        }
+        br.close();
+        return amount;
+    }
+}
diff --git a/suite/pts/deviceTests/filesystemperf/src/com/android/pts/filesystemperf/FullUpdateTest.java b/suite/pts/deviceTests/filesystemperf/src/com/android/pts/filesystemperf/FullUpdateTest.java
new file mode 100644
index 0000000..261735c
--- /dev/null
+++ b/suite/pts/deviceTests/filesystemperf/src/com/android/pts/filesystemperf/FullUpdateTest.java
@@ -0,0 +1,86 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.pts.filesystemperf;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+
+import com.android.pts.util.MeasureRun;
+import com.android.pts.util.MeasureTime;
+import com.android.pts.util.PtsAndroidTestCase;
+import com.android.pts.util.ReportLog;
+import com.android.pts.util.SystemUtil;
+
+import android.util.Log;
+
+public class FullUpdateTest extends PtsAndroidTestCase {
+    private static final String DIR_INITIAL_FILL = "INITIAL_FILL";
+    private static final String DIR_WORK = "WORK";
+    private static final String TAG = "FullUpdateTest";
+
+    @Override
+    protected void tearDown() throws Exception {
+        FileUtil.removeFileOrDir(getContext(), DIR_INITIAL_FILL);
+        FileUtil.removeFileOrDir(getContext(), DIR_WORK);
+        super.tearDown();
+    }
+
+    // fill disk almost, update exceeding free space, then update some amount
+    // idea is to drain all free blocks and measure update performance
+    public void testAlmostFilledUpdate() throws IOException {
+        long freeDisk = SystemUtil.getFreeDiskSize(getContext());
+        final long FREE_SPACE_TO_LEAVE = 500L * 1024L * 1024L; // leave this much
+        long diskToFill = freeDisk - FREE_SPACE_TO_LEAVE;
+        Log.i(TAG, "free disk " + freeDisk + ", to fill " + diskToFill);
+        final long MAX_FILE_SIZE_TO_FILL = 1024L * 1024L * 1024L;
+        long filled = 0;
+        while (filled < diskToFill) {
+            long toFill = diskToFill - filled;
+            if (toFill > MAX_FILE_SIZE_TO_FILL) {
+                toFill = MAX_FILE_SIZE_TO_FILL;
+            }
+            Log.i(TAG, "Generating file " + toFill);
+            FileUtil.createNewFilledFile(getContext(),
+                    DIR_INITIAL_FILL, toFill);
+            filled += toFill;
+        }
+
+        // now about freeSpaceToLeave should be left
+        // and try updating exceeding the free space size
+        final long FILE_SIZE = FREE_SPACE_TO_LEAVE / 2;
+        File file = FileUtil.createNewFilledFile(getContext(),
+                DIR_WORK, FILE_SIZE);
+        final int BUFFER_SIZE = 10 * 1024 * 1024;
+        final byte[] data = FileUtil.generateRandomData(BUFFER_SIZE);
+        for (int i = 0; i < 10; i++) {
+            final FileOutputStream out = new FileOutputStream(file);
+            int numberRepeat = (int)(FILE_SIZE / BUFFER_SIZE);
+            double[] times = MeasureTime.measure(numberRepeat, new MeasureRun() {
+
+                @Override
+                public void run(int i) throws IOException {
+                    out.write(data);
+                    out.flush();
+                }
+            });
+            out.close();
+            getReportLog().printArray(i + "-th round MB/s",
+                    ReportLog.calcRatePerSecArray(BUFFER_SIZE / 1024 / 1024, times), true);
+        }
+    }
+}
diff --git a/suite/pts/deviceTests/filesystemperf/src/com/android/pts/filesystemperf/RWTest.java b/suite/pts/deviceTests/filesystemperf/src/com/android/pts/filesystemperf/RWTest.java
new file mode 100644
index 0000000..f44e797
--- /dev/null
+++ b/suite/pts/deviceTests/filesystemperf/src/com/android/pts/filesystemperf/RWTest.java
@@ -0,0 +1,128 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.pts.filesystemperf;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+
+import com.android.pts.util.MeasureRun;
+import com.android.pts.util.MeasureTime;
+import com.android.pts.util.PtsAndroidTestCase;
+import com.android.pts.util.ReportLog;
+import com.android.pts.util.SystemUtil;
+
+public class RWTest extends PtsAndroidTestCase {
+    private static final String DIR_SEQ_WR = "SEQ_WR";
+    private static final String DIR_SEQ_UPD = "SEQ_UPD";
+    private static final String DIR_SEQ_RD = "SEQ_RD";
+    private static final int BUFFER_SIZE = 10 * 1024 * 1024;
+
+    @Override
+    protected void tearDown() throws Exception {
+        FileUtil.removeFileOrDir(getContext(), DIR_SEQ_WR);
+        FileUtil.removeFileOrDir(getContext(), DIR_SEQ_UPD);
+        FileUtil.removeFileOrDir(getContext(), DIR_SEQ_RD);
+        super.tearDown();
+    }
+
+    public void testSingleSequentialWrite() throws IOException {
+        final int numberOfFiles = (int)(getFileSizeExceedingMemory() / BUFFER_SIZE);
+        getReportLog().printValue("files", numberOfFiles);
+        final byte[] data = FileUtil.generateRandomData(BUFFER_SIZE);
+        final File[] files = FileUtil.createNewFiles(getContext(), DIR_SEQ_WR,
+                numberOfFiles);
+        double[] rdAmount = new double[numberOfFiles];
+        double[] wrAmount = new double[numberOfFiles];
+        double[] times = FileUtil.measureIO(numberOfFiles, rdAmount, wrAmount, new MeasureRun() {
+
+            @Override
+            public void run(int i) throws IOException {
+                FileUtil.writeFile(files[i], data, false);
+            }
+        });
+        getReportLog().printArray("try " + numberOfFiles + " files, result MB/s",
+                ReportLog.calcRatePerSecArray(BUFFER_SIZE / 1024 / 1024, times), true);
+        getReportLog().printArray("Wr amount", wrAmount, true);
+    }
+
+
+    public void testSingleSequentialUpdate() throws IOException {
+        final long fileSize = getFileSizeExceedingMemory();
+        File file = FileUtil.createNewFilledFile(getContext(),
+                DIR_SEQ_UPD, fileSize);
+        final byte[] data = FileUtil.generateRandomData(BUFFER_SIZE);
+        for (int i = 0; i < 4; i++) {
+            final FileOutputStream out = new FileOutputStream(file);
+            int numberRepeat = (int)(fileSize / BUFFER_SIZE);
+            double[] rdAmount = new double[numberRepeat];
+            double[] wrAmount = new double[numberRepeat];
+            double[] times = FileUtil.measureIO(numberRepeat, rdAmount, wrAmount, new MeasureRun() {
+
+                @Override
+                public void run(int i) throws IOException {
+                    out.write(data);
+                    out.flush();
+                }
+            });
+            out.close();
+            getReportLog().printArray(i + "-th round MB/s",
+                    ReportLog.calcRatePerSecArray(BUFFER_SIZE / 1024 / 1024, times), true);
+            getReportLog().printArray("Wr amount", wrAmount, true);
+        }
+    }
+
+    public void testSingleSequentialRead() throws IOException {
+        final long fileSize = getFileSizeExceedingMemory();
+        long start = System.currentTimeMillis();
+        final File file = FileUtil.createNewFilledFile(getContext(),
+                DIR_SEQ_RD, fileSize);
+        long finish = System.currentTimeMillis();
+        getReportLog().printValue("write size " + fileSize + " result MB/s",
+                ReportLog.calcRatePerSec(fileSize / 1024 / 1024, finish - start));
+
+        final int NUMBER_READ = 4;
+
+        final byte[] data = new byte[BUFFER_SIZE];
+        double[] times = MeasureTime.measure(NUMBER_READ, new MeasureRun() {
+
+            @Override
+            public void run(int i) throws IOException {
+                final FileInputStream in = new FileInputStream(file);
+                long read = 0;
+                while (read < fileSize) {
+                    in.read(data);
+                    read += BUFFER_SIZE;
+                }
+                in.close();
+            }
+        });
+        getReportLog().printArray("read MB/s",
+                ReportLog.calcRatePerSecArray(fileSize / 1024 / 1024, times), true);
+    }
+
+    private long getFileSizeExceedingMemory() {
+        long freeDisk = SystemUtil.getFreeDiskSize(getContext());
+        long memSize = SystemUtil.getTotalMemory(getContext());
+        long diskSizeTarget = (2 * memSize / BUFFER_SIZE) * BUFFER_SIZE;
+        if (diskSizeTarget > freeDisk) {
+            fail("Free disk size " + freeDisk + " too small");
+        }
+        return diskSizeTarget;
+    }
+}
diff --git a/suite/pts/deviceTests/filesystemperf/src/com/android/pts/filesystemperf/TestTest.java b/suite/pts/deviceTests/filesystemperf/src/com/android/pts/filesystemperf/TestTest.java
new file mode 100644
index 0000000..32e1878
--- /dev/null
+++ b/suite/pts/deviceTests/filesystemperf/src/com/android/pts/filesystemperf/TestTest.java
@@ -0,0 +1,43 @@
+/*
+ * 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.
+ */
+
+
+// code for testing, will be removed / moved before release
+
+package com.android.pts.filesystemperf;
+
+import com.android.pts.util.PtsAndroidTestCase;
+
+public class TestTest extends PtsAndroidTestCase {
+    @Override
+    protected void tearDown() throws Exception {
+        super.tearDown();
+    }
+
+    public void testPass() {
+        double[] array = new double[] {1.0, 2.0, 3.0};
+        getReportLog().printArray(" ", array, true);
+        getReportLog().printArray(" ", array, false);
+        getReportLog().printValue(" ", 1.0);
+        getReportLog().printValue(" ", 2.0);
+    }
+
+    public void testFail() throws Exception {
+        getReportLog().printValue(" ", 1.0);
+        getReportLog().printValue(" ", 2.0);
+        throw new Exception("failed");
+    }
+}
diff --git a/suite/pts/deviceTests/ptsutil/Android.mk b/suite/pts/deviceTests/ptsutil/Android.mk
new file mode 100644
index 0000000..d097036
--- /dev/null
+++ b/suite/pts/deviceTests/ptsutil/Android.mk
@@ -0,0 +1,29 @@
+# Copyright (C) 2012 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+LOCAL_PATH:= $(call my-dir)
+
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+
+LOCAL_MODULE_TAGS := optional
+
+LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
+
+LOCAL_MODULE := ptsutil
+
+LOCAL_SDK_VERSION := 16
+
+include $(BUILD_STATIC_JAVA_LIBRARY)
diff --git a/tests/core/libcore/src/Dummy.java b/suite/pts/deviceTests/ptsutil/src/com/android/pts/util/MeasureRun.java
similarity index 60%
rename from tests/core/libcore/src/Dummy.java
rename to suite/pts/deviceTests/ptsutil/src/com/android/pts/util/MeasureRun.java
index 64b67de..1f6f6ed 100644
--- a/tests/core/libcore/src/Dummy.java
+++ b/suite/pts/deviceTests/ptsutil/src/com/android/pts/util/MeasureRun.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2011 The Android Open Source Project
+ * 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.
@@ -14,11 +14,14 @@
  * limitations under the License.
  */
 
+package com.android.pts.util;
+
+import java.io.IOException;
+
 /**
- * We really just want the core-tests classes from the static java
- * library, but the build system currently needs at least one input
- * file, not just because its a sanity check, but because the static
- * class files and resources are included in the output of the local
- * java compilation.
+ * interface for measuring time for each run.
  */
-public final class Dummy {}
+public interface MeasureRun {
+
+    abstract public void run(int i) throws IOException;
+}
diff --git a/suite/pts/deviceTests/ptsutil/src/com/android/pts/util/MeasureTime.java b/suite/pts/deviceTests/ptsutil/src/com/android/pts/util/MeasureTime.java
new file mode 100644
index 0000000..337a472
--- /dev/null
+++ b/suite/pts/deviceTests/ptsutil/src/com/android/pts/util/MeasureTime.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.pts.util;
+
+import java.io.IOException;
+
+public class MeasureTime {
+    /**
+     * measure time taken for each run for given count
+     * @param count
+     * @param run
+     * @return array of time taken in each run in msec.
+     * @throws IOException
+     */
+    public static double[] measure(int count, MeasureRun run)  throws IOException {
+        double[] result = new double[count];
+        long prev = System.currentTimeMillis();
+        for (int i = 0; i < count; i++) {
+            run.run(i);
+            long current =  System.currentTimeMillis();
+            result[i] = current - prev;
+            prev = current;
+        }
+        return result;
+    }
+}
diff --git a/suite/pts/deviceTests/ptsutil/src/com/android/pts/util/PtsActivityInstrumentationTestCase2.java b/suite/pts/deviceTests/ptsutil/src/com/android/pts/util/PtsActivityInstrumentationTestCase2.java
new file mode 100644
index 0000000..84c1718
--- /dev/null
+++ b/suite/pts/deviceTests/ptsutil/src/com/android/pts/util/PtsActivityInstrumentationTestCase2.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+package com.android.pts.util;
+
+import android.app.Activity;
+import android.test.ActivityInstrumentationTestCase2;
+
+
+public class PtsActivityInstrumentationTestCase2<T extends Activity> extends
+        ActivityInstrumentationTestCase2<T> {
+
+    private ReportLog mReportLog = new ReportLog();
+
+    public PtsActivityInstrumentationTestCase2(Class<T> activityClass) {
+        super(activityClass);
+    }
+
+    public ReportLog getReportLog() {
+        return mReportLog;
+    }
+
+    @Override
+    protected void tearDown() throws Exception {
+        mReportLog.throwReportToHost();
+    }
+
+}
diff --git a/suite/pts/deviceTests/ptsutil/src/com/android/pts/util/PtsAndroidTestCase.java b/suite/pts/deviceTests/ptsutil/src/com/android/pts/util/PtsAndroidTestCase.java
new file mode 100644
index 0000000..bf17956
--- /dev/null
+++ b/suite/pts/deviceTests/ptsutil/src/com/android/pts/util/PtsAndroidTestCase.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+package com.android.pts.util;
+
+import android.test.AndroidTestCase;
+
+public class PtsAndroidTestCase extends AndroidTestCase {
+
+    private ReportLog mReportLog = new ReportLog();
+
+    public ReportLog getReportLog() {
+        return mReportLog;
+    }
+
+    @Override
+    protected void tearDown() throws Exception {
+        mReportLog.throwReportToHost();
+    }
+}
diff --git a/suite/pts/deviceTests/ptsutil/src/com/android/pts/util/PtsException.java b/suite/pts/deviceTests/ptsutil/src/com/android/pts/util/PtsException.java
new file mode 100644
index 0000000..e8ec5be
--- /dev/null
+++ b/suite/pts/deviceTests/ptsutil/src/com/android/pts/util/PtsException.java
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.pts.util;
+
+/**
+ * Exception throw by PTS test to pass the result to host
+ * This should not be thrown by test app unless the result is complete.
+ */
+@SuppressWarnings("serial")
+public class PtsException extends Exception {
+    public PtsException(String message) {
+        super(message);
+    }
+}
diff --git a/suite/pts/deviceTests/ptsutil/src/com/android/pts/util/ReportLog.java b/suite/pts/deviceTests/ptsutil/src/com/android/pts/util/ReportLog.java
new file mode 100644
index 0000000..15be1aa
--- /dev/null
+++ b/suite/pts/deviceTests/ptsutil/src/com/android/pts/util/ReportLog.java
@@ -0,0 +1,154 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.pts.util;
+
+import android.util.Log;
+
+import java.util.LinkedList;
+import java.util.List;
+
+
+/**
+ * Utility class to print performance measurement result back to host.
+ * For now, throws know exception with message.
+ *
+ * Format:
+ * LOG_SEPARATOR : separates each log
+ * Message = log [LOG_SEPARATOR log]*
+ * log for single value = classMethodName:line_number|header|d|value
+ * log for array = classMethodName:line_number|header|da|values|
+ *                     average average_value min|max value stddev value
+ */
+public class ReportLog {
+    private static final String TAG = "PtsReport";
+    private static final String LOG_SEPARATOR = "+++";
+    private static final String LOG_ELEM_SEPARATOR = "|";
+
+    private List<String> mMessages = new LinkedList<String> ();
+    /**
+     * print given value to the report
+     * @param header string to explain the contents. It can be unit for the value.
+     * @param val
+     */
+    public void printValue(String header, double val) {
+        String message = getClassMethodNames(4, true) + LOG_ELEM_SEPARATOR + header +
+                LOG_ELEM_SEPARATOR + "d" + LOG_ELEM_SEPARATOR + val;
+        mMessages.add(message);
+        Log.i(TAG, message);
+    }
+
+    /**
+     * array version of printValue
+     * @param header
+     * @param val
+     * @param addMin add minimum to the result. If false, add maximum to the result
+     */
+    public void printArray(String header, double[] val, boolean addMin) {
+        StringBuilder builder = new StringBuilder();
+        builder.append(getClassMethodNames(4, true) + LOG_ELEM_SEPARATOR + header +
+                LOG_ELEM_SEPARATOR + "da" + LOG_ELEM_SEPARATOR);
+        double average = 0.0;
+        double min = val[0];
+        double max = val[0];
+        for (double v : val) {
+            builder.append(v);
+            builder.append(" ");
+            average += v;
+            if (v > max) {
+                max = v;
+            }
+            if (v < min) {
+                min = v;
+            }
+        }
+        average /= val.length;
+        double power = 0;
+        for (double v : val) {
+            double delta = v - average;
+            power += (delta * delta);
+        }
+        power /= val.length;
+        double stdDev = Math.sqrt(power);
+        builder.append(LOG_ELEM_SEPARATOR + "average " + average +
+                (addMin ? (" min " + min) : (" max " + max)) + " stddev " + stdDev);
+        mMessages.add(builder.toString());
+        Log.i(TAG, builder.toString());
+    }
+
+    public void throwReportToHost() throws PtsException {
+        StringBuilder builder = new StringBuilder();
+        for (String entry : mMessages) {
+            builder.append(entry);
+            builder.append(LOG_SEPARATOR);
+        }
+        // delete the last separator
+        if (builder.length() >= LOG_SEPARATOR.length()) {
+            builder.delete(builder.length() - LOG_SEPARATOR.length(), builder.length());
+        }
+        throw new PtsException(builder.toString());
+    }
+
+    /**
+     * calculate rate per sec for given change happened during given timeInMSec.
+     * timeInSec with 0 value will be changed to small value to prevent divide by zero.
+     * @param change
+     * @param timeInMSec
+     * @return
+     */
+    public static double calcRatePerSec(double change, double timeInMSec) {
+        if (timeInMSec == 0) {
+            return change * 1000.0 / 0.001; // do not allow zero
+        } else {
+            return change * 1000.0 / timeInMSec;
+        }
+    }
+
+    /**
+     * array version of calcRatePerSecArray
+     * @param change
+     * @param timeInMSec
+     * @return
+     */
+    public static double[] calcRatePerSecArray(double change, double[] timeInMSec) {
+        double[] result = new double[timeInMSec.length];
+        change *= 1000.0;
+        for (int i = 0; i < timeInMSec.length; i++) {
+            if (timeInMSec[i] == 0) {
+                result[i] = change / 0.001;
+            } else {
+                result[i] = change / timeInMSec[i];
+            }
+        }
+        return result;
+    }
+
+    /**
+     * get classname.methodname from call stack of the current thread
+     *
+     * @return
+     */
+    public static String getClassMethodNames() {
+        return getClassMethodNames(4, false);
+    }
+
+    private static String getClassMethodNames(int depth, boolean addLineNumber) {
+        StackTraceElement[] elements = Thread.currentThread().getStackTrace();
+        String names = elements[depth].getClassName() + "." + elements[depth].getMethodName() +
+                (addLineNumber ? ":" + elements[depth].getLineNumber() : "");
+        return names;
+    }
+}
diff --git a/suite/pts/deviceTests/ptsutil/src/com/android/pts/util/SystemUtil.java b/suite/pts/deviceTests/ptsutil/src/com/android/pts/util/SystemUtil.java
new file mode 100644
index 0000000..7975463
--- /dev/null
+++ b/suite/pts/deviceTests/ptsutil/src/com/android/pts/util/SystemUtil.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.pts.util;
+
+import android.app.ActivityManager;
+import android.app.ActivityManager.MemoryInfo;
+import android.content.Context;
+import android.os.StatFs;
+
+public class SystemUtil {
+    public static long getFreeDiskSize(Context context) {
+        StatFs statFs = new StatFs(context.getFilesDir().getAbsolutePath());
+        return (long)statFs.getAvailableBlocks() * statFs.getBlockSize();
+    }
+
+    public static long getFreeMemory(Context context) {
+        MemoryInfo info = new MemoryInfo();
+        ActivityManager activityManager = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
+        activityManager.getMemoryInfo(info);
+        return info.availMem;
+    }
+
+    public static long getTotalMemory(Context context) {
+        MemoryInfo info = new MemoryInfo();
+        ActivityManager activityManager = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
+        activityManager.getMemoryInfo(info);
+        return info.totalMem; // TODO totalMem N/A in ICS.
+    }
+}
diff --git a/suite/pts/deviceTests/ui/Android.mk b/suite/pts/deviceTests/ui/Android.mk
new file mode 100644
index 0000000..f3c3944
--- /dev/null
+++ b/suite/pts/deviceTests/ui/Android.mk
@@ -0,0 +1,35 @@
+# Copyright (C) 2012 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+# don't include this package in any target
+LOCAL_MODULE_TAGS := optional
+
+LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
+
+LOCAL_JAVA_LIBRARIES := android.test.runner
+
+LOCAL_STATIC_JAVA_LIBRARIES := ptsutil
+
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+
+LOCAL_PACKAGE_NAME := PtsDeviceUi
+
+LOCAL_SDK_VERSION := 16
+
+include $(BUILD_PTS_PACKAGE)
+
+
diff --git a/suite/pts/deviceTests/ui/AndroidManifest.xml b/suite/pts/deviceTests/ui/AndroidManifest.xml
new file mode 100644
index 0000000..f750d14
--- /dev/null
+++ b/suite/pts/deviceTests/ui/AndroidManifest.xml
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+        package="com.android.pts.ui">
+
+    <uses-permission android:name="android.permission.DISABLE_KEYGUARD" />
+    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
+
+    <application>
+        <uses-library android:name="android.test.runner" />
+        <activity
+                android:name=".ScrollingActivity"
+                android:screenOrientation="portrait"
+                android:configChanges="keyboard|keyboardHidden|orientation|screenSize">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.LAUNCHER"/>
+            </intent-filter>
+        </activity>
+    </application>
+    <instrumentation android:name="android.test.InstrumentationTestRunner"
+            android:targetPackage="com.android.pts.ui"
+            android:label="UI Latency measurement" />
+</manifest>
diff --git a/suite/pts/deviceTests/ui/src/com/android/pts/ui/ScrollingActivity.java b/suite/pts/deviceTests/ui/src/com/android/pts/ui/ScrollingActivity.java
new file mode 100644
index 0000000..7bdfff9
--- /dev/null
+++ b/suite/pts/deviceTests/ui/src/com/android/pts/ui/ScrollingActivity.java
@@ -0,0 +1,104 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.pts.ui;
+
+import android.app.ListActivity;
+import android.os.Bundle;
+import android.widget.AbsListView;
+import android.widget.AbsListView.OnScrollListener;
+import android.widget.ArrayAdapter;
+import android.widget.ListView;
+
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+
+public class ScrollingActivity extends ListActivity implements OnScrollListener
+{
+    static final String TAG = "ScrollingActivity";
+    private static final int NUMBER_ELEMENTS = 10000;
+    private static final int SCROLL_TIME_IN_MS = 1;
+    private static final int WAIT_TIMEOUT_IN_SECS = 5 * 60;
+    private String[] mItems = new String[NUMBER_ELEMENTS];
+    private CountDownLatch mLatchStop = null;
+    private int mTargetLoc;
+
+    public void onCreate(Bundle icicle)
+    {
+        super.onCreate(icicle);
+        for (int i = 0; i < NUMBER_ELEMENTS; i++) {
+            mItems[i] = Integer.toString(i);
+        }
+        setListAdapter(new ArrayAdapter<String>(this,
+                android.R.layout.simple_list_item_1, mItems));
+        ListView view = getListView();
+        view.setOnScrollListener(this);
+        //view.setVelocityScale(100.0f);
+    }
+
+    public boolean scrollToTop() {
+        return doScroll(0);
+    }
+    public boolean scrollToBottom() {
+        return doScroll(NUMBER_ELEMENTS - 1);
+    }
+
+    private boolean doScroll(final int loc) {
+        mLatchStop = new CountDownLatch(1);
+        mTargetLoc = loc;
+        final ListView view = getListView();
+        runOnUiThread( new Runnable() {
+            @Override
+            public void run() {
+                view.smoothScrollToPositionFromTop(loc, 0, SCROLL_TIME_IN_MS);
+            }
+        });
+        boolean result = false;
+        try {
+            result = mLatchStop.await(WAIT_TIMEOUT_IN_SECS, TimeUnit.SECONDS);
+        } catch (InterruptedException e) {
+            // ignore
+        }
+        mLatchStop = null;
+        return result;
+    }
+    public void onStop()
+    {
+        super.onStop();
+    }
+
+    public void onResume()
+    {
+        super.onResume();
+    }
+
+    @Override
+    public void onScrollStateChanged(AbsListView view, int scrollState) {
+
+    }
+
+    @Override
+    public void onScroll(AbsListView view, int firstVisibleItem,
+            int visibleItemCount, int totalItemCount) {
+        //Log.i(TAG, "onScroll " + firstVisibleItem + " " + visibleItemCount);
+        if ((mTargetLoc >= firstVisibleItem) &&
+                (mTargetLoc <= (firstVisibleItem + visibleItemCount))) {
+            if (mLatchStop != null) {
+                mLatchStop.countDown();
+            }
+        }
+    }
+}
diff --git a/suite/pts/deviceTests/ui/src/com/android/pts/ui/ScrollingTest.java b/suite/pts/deviceTests/ui/src/com/android/pts/ui/ScrollingTest.java
new file mode 100644
index 0000000..a985591
--- /dev/null
+++ b/suite/pts/deviceTests/ui/src/com/android/pts/ui/ScrollingTest.java
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.pts.ui;
+
+import java.io.IOException;
+
+import com.android.pts.util.MeasureRun;
+import com.android.pts.util.MeasureTime;
+import com.android.pts.util.PtsActivityInstrumentationTestCase2;
+import com.android.pts.util.ReportLog;
+
+public class ScrollingTest extends PtsActivityInstrumentationTestCase2<ScrollingActivity> {
+    private ScrollingActivity mActivity;
+
+    public ScrollingTest() {
+        super(ScrollingActivity.class);
+    }
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        mActivity = getActivity();
+        getInstrumentation().waitForIdleSync();
+        try {
+            runTestOnUiThread(new Runnable() {
+                public void run() {
+                }
+            });
+        } catch (Throwable e) {
+            e.printStackTrace();
+            fail();
+        }
+    }
+
+    @Override
+    protected void tearDown() throws Exception {
+        mActivity = null;
+        super.tearDown();
+    }
+
+    public void testFullScrolling() throws IOException {
+        final int NUMBER_REPEAT = 10;
+        final ScrollingActivity activity = mActivity;
+        double[] results = MeasureTime.measure(NUMBER_REPEAT, new MeasureRun() {
+
+            @Override
+            public void run(int i) throws IOException {
+                assertTrue(activity.scrollToBottom());
+                assertTrue(activity.scrollToTop());
+            }
+        });
+        getReportLog().printArray("ms", results, false);
+    }
+}
diff --git a/suite/pts/expectations/knownfailures.txt b/suite/pts/expectations/knownfailures.txt
new file mode 100644
index 0000000..0d4f101
--- /dev/null
+++ b/suite/pts/expectations/knownfailures.txt
@@ -0,0 +1,2 @@
+[
+]
diff --git a/suite/pts/tools/Android.mk b/suite/pts/tools/Android.mk
new file mode 100644
index 0000000..c141484
--- /dev/null
+++ b/suite/pts/tools/Android.mk
@@ -0,0 +1,17 @@
+#
+# 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.
+#
+
+include $(call all-subdir-makefiles)
diff --git a/suite/pts/tools/tradefed/Android.mk b/suite/pts/tools/tradefed/Android.mk
new file mode 100644
index 0000000..09e49b1
--- /dev/null
+++ b/suite/pts/tools/tradefed/Android.mk
@@ -0,0 +1,22 @@
+# Copyright (C) 2011 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_MODULE_TAGS := optional
+
+LOCAL_PREBUILT_EXECUTABLES := pts-tradefed
+include $(BUILD_HOST_PREBUILT)
+
diff --git a/suite/pts/tools/tradefed/pts-tradefed b/suite/pts/tools/tradefed/pts-tradefed
new file mode 100755
index 0000000..fedbfaf
--- /dev/null
+++ b/suite/pts/tools/tradefed/pts-tradefed
@@ -0,0 +1,86 @@
+#!/bin/bash
+
+# Copyright (C) 2011 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.
+
+# launcher script for cts-tradefed harness for PTS
+# can be used from an Android build environment, or a standalone pts zip
+
+checkFile() {
+    if [ ! -f "$1" ]; then
+        echo "Unable to locate $1"
+        exit
+    fi;
+}
+
+checkPath() {
+    if ! type -P $1 &> /dev/null; then
+        echo "Unable to find $1 in path."
+        exit
+    fi;
+}
+
+checkPath adb
+checkPath java
+
+# check java version
+JAVA_VERSION=$(java -version 2>&1 | head -n 1 | grep '[ "]1\.6[\. "$$]')
+if [ "${JAVA_VERSION}" == "" ]; then
+    echo "Wrong java version. 1.6 is required."
+    exit
+fi
+
+# check debug flag and set up remote debugging
+if [ -n "${TF_DEBUG}" ]; then
+  if [ -z "${TF_DEBUG_PORT}" ]; then
+    TF_DEBUG_PORT=10088
+  fi
+  RDBG_FLAG=-agentlib:jdwp=transport=dt_socket,server=y,suspend=y,address=${TF_DEBUG_PORT}
+fi
+
+
+# check if in Android build env
+if [ ! -z ${ANDROID_BUILD_TOP} ]; then
+    HOST=`uname`
+    if [ "$HOST" == "Linux" ]; then
+        OS="linux-x86"
+    elif [ "$HOST" == "Darwin" ]; then
+        OS="darwin-x86"
+    else
+        echo "Unrecognized OS"
+        exit
+    fi;
+    PTS_ROOT=${ANDROID_BUILD_TOP}/out/host/${OS}/pts
+    if [ ! -d ${PTS_ROOT} ]; then
+        echo "Could not find $PTS_ROOT in Android build environment. Try 'make pts'"
+        exit
+    fi;
+fi;
+
+if [ -z ${PTS_ROOT} ]; then
+    # assume we're in an extracted pts install
+    PTS_ROOT="$(dirname $0)/../.."
+fi;
+
+JAR_DIR=${PTS_ROOT}/android-pts/tools
+JARS="ddmlib-prebuilt.jar tradefed-prebuilt.jar hosttestlib.jar cts-tradefed.jar"
+
+for JAR in $JARS; do
+    checkFile ${JAR_DIR}/${JAR}
+    JAR_PATH=${JAR_PATH}:${JAR_DIR}/${JAR}
+done
+
+java $RDBG_FLAG \
+  -cp ${JAR_PATH} -DCTS_ROOT=${PTS_ROOT} -DPTS=1 com.android.cts.tradefed.command.CtsConsole "$@"
+
diff --git a/tests/Android.mk b/tests/Android.mk
index 77340df..15705dd 100644
--- a/tests/Android.mk
+++ b/tests/Android.mk
@@ -36,6 +36,8 @@
 
 LOCAL_STATIC_JAVA_LIBRARIES := ctsutil ctstestserver ctstestrunner
 
+LOCAL_DEX_PREOPT := false
+
 include $(BUILD_PACKAGE)
 
 # Build the test APK using its own makefile, and any other CTS-related packages
diff --git a/tests/AndroidManifest.xml b/tests/AndroidManifest.xml
index f9999f4..590ee36 100644
--- a/tests/AndroidManifest.xml
+++ b/tests/AndroidManifest.xml
@@ -118,7 +118,8 @@
 
     <application android:label="Android TestCase"
                 android:icon="@drawable/size_48x48"
-                android:name="android.app.cts.MockApplication">
+                android:name="android.app.cts.MockApplication"
+                android:supportsRtl="true">
 
         <activity android:name="android.app.cts.ActionBarActivity" />
         <activity android:name="android.widget.cts.TwoLineListItemStubActivity"
@@ -243,6 +244,14 @@
             </intent-filter>
         </activity>
 
+        <activity android:name="android.widget.cts.LayoutDirectionStubActivity"
+            android:label="LayoutDirectionStubActivity">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
+            </intent-filter>
+        </activity>
+
         <activity android:name="android.widget.cts.ProgressBarStubActivity"
             android:label="ProgressBarStubActivity">
             <intent-filter>
diff --git a/tests/SignatureTest/Android.mk b/tests/SignatureTest/Android.mk
index 3ebab34..cc0d53c 100644
--- a/tests/SignatureTest/Android.mk
+++ b/tests/SignatureTest/Android.mk
@@ -19,6 +19,8 @@
 LOCAL_MODULE_TAGS := optional
 # and when built explicitly put it in the data partition
 LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
+# and because it is in data, do not strip classes.dex
+LOCAL_DEX_PREOPT := false
 
 LOCAL_SRC_FILES := $(call all-java-files-under, src)
 
diff --git a/tests/acceleration/Android.mk b/tests/acceleration/Android.mk
index 6e30f59..bb6b89f 100644
--- a/tests/acceleration/Android.mk
+++ b/tests/acceleration/Android.mk
@@ -20,6 +20,8 @@
 
 LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
 
+LOCAL_DEX_PREOPT := false
+
 LOCAL_JAVA_LIBRARIES := android.test.runner
 
 LOCAL_SRC_FILES := $(call all-java-files-under, src)
diff --git a/tests/accessibility/Android.mk b/tests/accessibility/Android.mk
index 2ffe162..43fa291 100644
--- a/tests/accessibility/Android.mk
+++ b/tests/accessibility/Android.mk
@@ -24,4 +24,8 @@
 
 LOCAL_SDK_VERSION := current
 
+LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
+
+LOCAL_DEX_PREOPT := false
+
 include $(BUILD_PACKAGE)
diff --git a/tests/accessibilityservice/Android.mk b/tests/accessibilityservice/Android.mk
index 50fe6b0..f9fec93 100644
--- a/tests/accessibilityservice/Android.mk
+++ b/tests/accessibilityservice/Android.mk
@@ -20,6 +20,8 @@
 
 LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
 
+LOCAL_DEX_PREOPT := false
+
 LOCAL_JAVA_LIBRARIES := android.test.runner
 
 LOCAL_SRC_FILES := $(call all-java-files-under, src)
diff --git a/tests/core/ctscore.mk b/tests/core/ctscore.mk
index 049a58e..27ff881 100644
--- a/tests/core/ctscore.mk
+++ b/tests/core/ctscore.mk
@@ -12,60 +12,14 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-# First we build an apk without the core-tests resource
-cts_ORIGINAL_PACKAGE_NAME := $(LOCAL_PACKAGE_NAME)
-
-LOCAL_PACKAGE_NAME := $(LOCAL_PACKAGE_NAME).no-core-tests-res
-# Make sure this apk won't get installed
-LOCAL_UNINSTALLABLE_MODULE := true
-
 LOCAL_JAVA_LIBRARIES := android.test.runner bouncycastle
 LOCAL_PROGUARD_ENABLED := disabled
 LOCAL_DEX_PREOPT := false
 
-include $(BUILD_PACKAGE)
-# Vars set by $(BUILD_PACKAGE) and needed by the below module definition.
-cts_no-core-tests-res_BUILT_MODULE := $(LOCAL_BUILT_MODULE)
-cts_no-core-tests-res_private_key := $(private_key)
-cts_no-core-tests-res_certificate := $(certificate)
-
-##################################
-# Now the rules to build the apk with core-tests resource
-include $(CLEAR_VARS)
-
-LOCAL_MODULE := $(cts_ORIGINAL_PACKAGE_NAME)
-LOCAL_MODULE_CLASS := APPS
 # don't include these packages in any target
 LOCAL_MODULE_TAGS := optional
-# and when built explicitly put them in the data partition
+# and when installed explicitly put them in the data partition
 LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
-LOCAL_MODULE_SUFFIX := $(COMMON_ANDROID_PACKAGE_SUFFIX)
-LOCAL_BUILT_MODULE_STEM := package.apk
-
-include $(BUILD_SYSTEM)/base_rules.mk
-
-CORETESTS_INTERMEDIATES := $(call intermediates-dir-for,JAVA_LIBRARIES,core-tests,,COMMON)
-
-$(LOCAL_BUILT_MODULE): PRIVATE_INTERMEDIATES_COMMON := $(intermediates.COMMON)
-$(LOCAL_BUILT_MODULE): PRIVATE_CORETESTS_INTERMEDIATES_COMMON := $(CORETESTS_INTERMEDIATES)
-$(LOCAL_BUILT_MODULE): PRIVATE_PRIVATE_KEY := $(cts_no-core-tests-res_private_key)
-$(LOCAL_BUILT_MODULE): PRIVATE_CERTIFICATE := $(cts_no-core-tests-res_certificate)
-$(LOCAL_BUILT_MODULE): $(cts_no-core-tests-res_BUILT_MODULE) $(CORETESTS_INTERMEDIATES)/javalib.jar
-	@echo "Add resources to package ($@)"
-	$(hide) mkdir -p $(dir $@) $(PRIVATE_INTERMEDIATES_COMMON)
-	$(hide) rm -rf $(PRIVATE_INTERMEDIATES_COMMON)/ctsclasses
-	# javalib.jar should only contain .dex files, but the harmony tests also include
-	# some .class files, so get rid of them
-	$(hide) unzip -qo $(PRIVATE_CORETESTS_INTERMEDIATES_COMMON)/javalib.jar \
-		-d $(PRIVATE_INTERMEDIATES_COMMON)/ctsclasses
-	$(hide) find $(PRIVATE_INTERMEDIATES_COMMON)/ctsclasses -type f -name "*.class" -delete
-	$(hide) rm -f $(PRIVATE_INTERMEDIATES_COMMON)/ctsclasses/classes.dex
-	$(hide) cp $< $@
-	$(hide) jar uf $@ -C $(PRIVATE_INTERMEDIATES_COMMON)/ctsclasses .
-	$(sign-package)
-	$(align-package)
-
-# some global vars set in $(BUILD_PACKAGE), not sure if we really need here
-PACKAGES.$(cts_ORIGINAL_PACKAGE_NAME).PRIVATE_KEY := $(cts_no-core-tests-res_private_key)
-PACKAGES.$(cts_ORIGINAL_PACKAGE_NAME).CERTIFICATE := $(cts_no-core-tests-res_certificate)
-PACKAGES := $(PACKAGES) $(cts_ORIGINAL_PACKAGE_NAME)
+# Don't delete META-INF from the core-tests jar
+LOCAL_DONT_DELETE_JAR_META_INF := true
+include $(BUILD_PACKAGE)
diff --git a/tests/core/libcore/com/Android.mk b/tests/core/libcore/com/Android.mk
index 91a5da0..02dc3de 100644
--- a/tests/core/libcore/com/Android.mk
+++ b/tests/core/libcore/com/Android.mk
@@ -19,7 +19,6 @@
 endif
 
 include $(CLEAR_VARS)
-LOCAL_SRC_FILES := ../src/Dummy.java
 LOCAL_PACKAGE_NAME := android.core.tests.libcore.package.com
 LOCAL_STATIC_JAVA_LIBRARIES := core-tests
 include $(BUILD_CTSCORE_PACKAGE)
diff --git a/tests/core/libcore/dalvik/Android.mk b/tests/core/libcore/dalvik/Android.mk
index 45f6e7e..7b77a75 100644
--- a/tests/core/libcore/dalvik/Android.mk
+++ b/tests/core/libcore/dalvik/Android.mk
@@ -19,7 +19,6 @@
 endif
 
 include $(CLEAR_VARS)
-LOCAL_SRC_FILES := ../src/Dummy.java
 LOCAL_PACKAGE_NAME := android.core.tests.libcore.package.dalvik
 LOCAL_STATIC_JAVA_LIBRARIES := core-tests
 include $(BUILD_CTSCORE_PACKAGE)
diff --git a/tests/core/libcore/libcore/Android.mk b/tests/core/libcore/libcore/Android.mk
index 97e32bc..382b386 100644
--- a/tests/core/libcore/libcore/Android.mk
+++ b/tests/core/libcore/libcore/Android.mk
@@ -19,7 +19,6 @@
 endif
 
 include $(CLEAR_VARS)
-LOCAL_SRC_FILES := ../src/Dummy.java
 LOCAL_PACKAGE_NAME := android.core.tests.libcore.package.libcore
 LOCAL_STATIC_JAVA_LIBRARIES := core-tests
 include $(BUILD_CTSCORE_PACKAGE)
diff --git a/tests/core/libcore/org/Android.mk b/tests/core/libcore/org/Android.mk
index 8fad8de..d7a96b3 100644
--- a/tests/core/libcore/org/Android.mk
+++ b/tests/core/libcore/org/Android.mk
@@ -19,7 +19,6 @@
 endif
 
 include $(CLEAR_VARS)
-LOCAL_SRC_FILES := ../src/Dummy.java
 LOCAL_PACKAGE_NAME := android.core.tests.libcore.package.org
 LOCAL_STATIC_JAVA_LIBRARIES := core-tests
 include $(BUILD_CTSCORE_PACKAGE)
diff --git a/tests/core/libcore/sun/Android.mk b/tests/core/libcore/sun/Android.mk
index 5fc0c48..44d3d70 100644
--- a/tests/core/libcore/sun/Android.mk
+++ b/tests/core/libcore/sun/Android.mk
@@ -19,7 +19,6 @@
 endif
 
 include $(CLEAR_VARS)
-LOCAL_SRC_FILES := ../src/Dummy.java
 LOCAL_PACKAGE_NAME := android.core.tests.libcore.package.sun
 LOCAL_STATIC_JAVA_LIBRARIES := core-tests
 include $(BUILD_CTSCORE_PACKAGE)
diff --git a/tests/core/libcore/tests/Android.mk b/tests/core/libcore/tests/Android.mk
index bcb6628..bfd235f 100644
--- a/tests/core/libcore/tests/Android.mk
+++ b/tests/core/libcore/tests/Android.mk
@@ -19,7 +19,6 @@
 endif
 
 include $(CLEAR_VARS)
-LOCAL_SRC_FILES := ../src/Dummy.java
 LOCAL_PACKAGE_NAME := android.core.tests.libcore.package.tests
 LOCAL_STATIC_JAVA_LIBRARIES := core-tests
 include $(BUILD_CTSCORE_PACKAGE)
diff --git a/tests/core/runner/Android.mk b/tests/core/runner/Android.mk
index 7658b7a..fb548fc 100644
--- a/tests/core/runner/Android.mk
+++ b/tests/core/runner/Android.mk
@@ -27,4 +27,6 @@
 
 LOCAL_PACKAGE_NAME := android.core.tests.runner
 
+LOCAL_STATIC_JAVA_LIBRARIES := core-tests
+
 include $(BUILD_CTSCORE_PACKAGE)
diff --git a/tests/core/runner/src/android/test/InstrumentationCtsTestRunner.java b/tests/core/runner/src/android/test/InstrumentationCtsTestRunner.java
index 6dce943..d992839 100644
--- a/tests/core/runner/src/android/test/InstrumentationCtsTestRunner.java
+++ b/tests/core/runner/src/android/test/InstrumentationCtsTestRunner.java
@@ -119,16 +119,6 @@
              */
             private Class<?> lastClass;
 
-            /**
-             * The minimum time we expect a test to take.
-             */
-            private static final int MINIMUM_TIME = 100;
-
-            /**
-             * The start time of our current test in System.currentTimeMillis().
-             */
-            private long startTime;
-
             @Override
             public void startTest(Test test) {
                 if (test.getClass() != lastClass) {
@@ -140,30 +130,12 @@
                         test.getClass().getClassLoader());
 
                 mEnvironment.reset();
-
-                startTime = System.currentTimeMillis();
             }
 
             @Override
             public void endTest(Test test) {
                 if (test instanceof TestCase) {
                     cleanup((TestCase)test);
-
-                    /*
-                     * Make sure all tests take at least MINIMUM_TIME to
-                     * complete. If they don't, we wait a bit. The Cupcake
-                     * Binder can't handle too many operations in a very
-                     * short time, which causes headache for the CTS.
-                     */
-                    long timeTaken = System.currentTimeMillis() - startTime;
-
-                    if (timeTaken < MINIMUM_TIME) {
-                        try {
-                            Thread.sleep(MINIMUM_TIME - timeTaken);
-                        } catch (InterruptedException ignored) {
-                            // We don't care.
-                        }
-                    }
                 }
             }
 
diff --git a/tests/deviceadmin/Android.mk b/tests/deviceadmin/Android.mk
index 7322ad5..c354599 100644
--- a/tests/deviceadmin/Android.mk
+++ b/tests/deviceadmin/Android.mk
@@ -28,4 +28,6 @@
 
 LOCAL_SDK_VERSION := current
 
+LOCAL_DEX_PREOPT := false
+
 include $(BUILD_PACKAGE)
diff --git a/tests/expectations/knownfailures.txt b/tests/expectations/knownfailures.txt
index 9228564..0d4f101 100644
--- a/tests/expectations/knownfailures.txt
+++ b/tests/expectations/knownfailures.txt
@@ -1,77 +1,2 @@
 [
-  {
-    names: [
-      "com.android.cts.appsecurity.AppSecurityTests#testReadExternalStorageEnforced",
-      "com.android.cts.appsecurity.AppSecurityTests#testReadExternalStorageUnenforced"
-    ],
-    bug: 6721185
-  },
-  {
-    name: "android.accessibilityservice.cts.AccessibilityTextTraversalTest#testActionNextAndPreviousAtGranularityPageOverText",
-    bug: 6468754
-  },
-  {
-    name: "android.accessibilityservice.cts.AccessibilityWindowQueryTest#testPerformGlobalActionBack",
-    bug: 6365037
-  },
-  {
-    names: [
-      "android.media.cts.StreamingMediaPlayerTest#testRTSP_MPEG4SP_AAC_Video1",
-      "android.media.cts.StreamingMediaPlayerTest#testRTSP_MPEG4SP_AAC_Video2"
-    ],
-    bug: 6422606
-  },
-  {
-    names: [
-      "android.media.cts.StreamingMediaPlayerTest#testRTSP_H263_AMR_Video1",
-      "android.media.cts.StreamingMediaPlayerTest#testRTSP_H263_AMR_Video2"
-    ],
-    bug: 6216077
-  },
-  {
-    names: [
-      "android.media.cts.StreamingMediaPlayerTest#testRTSP_H264Base_AAC_Video1",
-      "android.media.cts.StreamingMediaPlayerTest#testRTSP_H264Base_AAC_Video2"
-    ],
-    bug: 6215719
-  },
-  {
-    name: "android.nativemedia.sl.SLObjectCreationTest#testAudioRecorderCreation",
-    bug: 4970300
-  },
-  {
-    name: "android.opengl.cts.AttachShaderTest#test_glAttachedShaders_invalidshader",
-    bug: 6404341
-  },
-  {
-    name: "android.openglperf.cts.GlVboPerfTest#testVboWithVaryingIndexBufferNumbers",
-    bug: 5898262
-  },
-  {
-    name: "android.text.cts.AndroidCharacterTest#testMirror",
-    bug: 4371654
-  },
-  {
-    name: "android.text.format.cts.DateUtilsTest#test2038",
-    bug: 6293653
-  },
-  {
-    description: "flakey libcore tests",
-    names: [
-      "libcore.java.net.ConcurrentCloseTest",
-      "libcore.java.net.SocketTest#testAvailable",
-      "libcore.java.net.URLConnectionTest",
-      "libcore.java.util.prefs.OldAbstractPreferencesTest",
-      "libcore.java.util.prefs.OldPreferencesTest#testAddNodeChangeListener",
-      "libcore.net.http.HttpResponseCacheTest#testClientPrematureDisconnectWithChunkedEncoding",
-      "org.apache.harmony.luni.tests.java.net.URLConnectionTest",
-      "org.apache.harmony.xnet.provider.jsse.NativeCryptoTest#test_SSL_do_handshake_server_timeout"
-    ]
-  },
-  {
-    description: "MediaPlayerFlakyNetworkTest tests",
-    name: "android.media.cts.MediaPlayerFlakyNetworkTest",
-    bug: 6782035
-  }
 ]
-
diff --git a/tests/res/layout/layoutdirection_layout.xml b/tests/res/layout/layoutdirection_layout.xml
new file mode 100644
index 0000000..e506dc1
--- /dev/null
+++ b/tests/res/layout/layoutdirection_layout.xml
@@ -0,0 +1,130 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ * 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.
+ -->
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+              android:layout_width="match_parent"
+              android:layout_height="wrap_content"
+              android:orientation="vertical">
+
+    <LinearLayout android:id="@+id/layout_linearlayout_ltr"
+                  android:layout_width="wrap_content"
+                  android:layout_height="wrap_content"
+                  android:layoutDirection="ltr">
+
+        <LinearLayout android:id="@+id/layout_linearlayout_ltr_child_1"
+                      android:layout_width="wrap_content"
+                      android:layout_height="wrap_content"
+                      android:layoutDirection="ltr" />
+
+        <LinearLayout android:id="@+id/layout_linearlayout_ltr_child_2"
+                      android:layout_width="wrap_content"
+                      android:layout_height="wrap_content"
+                      android:layoutDirection="rtl" />
+
+        <LinearLayout android:id="@+id/layout_linearlayout_ltr_child_3"
+                      android:layout_width="wrap_content"
+                      android:layout_height="wrap_content"
+                      android:layoutDirection="inherit" />
+
+        <LinearLayout android:id="@+id/layout_linearlayout_ltr_child_4"
+                      android:layout_width="wrap_content"
+                      android:layout_height="wrap_content"
+                      android:layoutDirection="locale" />
+
+    </LinearLayout>
+
+    <LinearLayout android:id="@+id/layout_linearlayout_rtl"
+                  android:layout_width="wrap_content"
+                  android:layout_height="wrap_content"
+                  android:layoutDirection="rtl">
+
+        <LinearLayout android:id="@+id/layout_linearlayout_rtl_child_1"
+                      android:layout_width="wrap_content"
+                      android:layout_height="wrap_content"
+                      android:layoutDirection="ltr" />
+
+        <LinearLayout android:id="@+id/layout_linearlayout_rtl_child_2"
+                      android:layout_width="wrap_content"
+                      android:layout_height="wrap_content"
+                      android:layoutDirection="rtl" />
+
+        <LinearLayout android:id="@+id/layout_linearlayout_rtl_child_3"
+                      android:layout_width="wrap_content"
+                      android:layout_height="wrap_content"
+                      android:layoutDirection="inherit" />
+
+        <LinearLayout android:id="@+id/layout_linearlayout_rtl_child_4"
+                      android:layout_width="wrap_content"
+                      android:layout_height="wrap_content"
+                      android:layoutDirection="locale" />
+
+    </LinearLayout>
+
+    <LinearLayout android:id="@+id/layout_linearlayout_locale"
+                  android:layout_width="wrap_content"
+                  android:layout_height="wrap_content"
+                  android:layoutDirection="locale">
+
+        <LinearLayout android:id="@+id/layout_linearlayout_locale_child_1"
+                      android:layout_width="wrap_content"
+                      android:layout_height="wrap_content"
+                      android:layoutDirection="ltr" />
+
+        <LinearLayout android:id="@+id/layout_linearlayout_locale_child_2"
+                      android:layout_width="wrap_content"
+                      android:layout_height="wrap_content"
+                      android:layoutDirection="rtl" />
+
+        <LinearLayout android:id="@+id/layout_linearlayout_locale_child_3"
+                      android:layout_width="wrap_content"
+                      android:layout_height="wrap_content"
+                      android:layoutDirection="inherit" />
+
+        <LinearLayout android:id="@+id/layout_linearlayout_locale_child_4"
+                      android:layout_width="wrap_content"
+                      android:layout_height="wrap_content"
+                      android:layoutDirection="locale" />
+
+    </LinearLayout>
+
+    <LinearLayout android:id="@+id/layout_linearlayout_inherit"
+                  android:layout_width="wrap_content"
+                  android:layout_height="wrap_content"
+                  android:layoutDirection="inherit">
+
+        <LinearLayout android:id="@+id/layout_linearlayout_inherit_child_1"
+                      android:layout_width="wrap_content"
+                      android:layout_height="wrap_content"
+                      android:layoutDirection="ltr" />
+
+        <LinearLayout android:id="@+id/layout_linearlayout_inherit_child_2"
+                      android:layout_width="wrap_content"
+                      android:layout_height="wrap_content"
+                      android:layoutDirection="rtl" />
+
+        <LinearLayout android:id="@+id/layout_linearlayout_inherit_child_3"
+                      android:layout_width="wrap_content"
+                      android:layout_height="wrap_content"
+                      android:layoutDirection="inherit" />
+
+        <LinearLayout android:id="@+id/layout_linearlayout_inherit_child_4"
+                      android:layout_width="wrap_content"
+                      android:layout_height="wrap_content"
+                      android:layoutDirection="locale" />
+
+    </LinearLayout>
+
+</LinearLayout>
diff --git a/tests/res/layout/relative_layout.xml b/tests/res/layout/relative_layout.xml
index 669e86e..db4b2e8 100644
--- a/tests/res/layout/relative_layout.xml
+++ b/tests/res/layout/relative_layout.xml
@@ -162,4 +162,97 @@
         android:layout_height="match_parent"
         android:prompt="@string/text_view_hello"/>
 
+    <RelativeLayout
+            android:id="@+id/relative_sublayout_attrs_2"
+            android:background="@drawable/blue"
+            android:layout_width="match_parent"
+            android:layout_height="match_parent">
+
+        <!-- view21, centered within its parent. -->
+        <TextView
+                android:id="@+id/relative_view21"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_centerInParent="true"
+                android:text="@string/relative_view1"/>
+
+        <!-- view22, below view1 and has same start position with view21. -->
+        <TextView
+                android:id="@+id/relative_view22"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_below="@id/relative_view21"
+                android:layout_alignStart="@id/relative_view21"
+                android:text="@string/relative_view2"/>
+
+        <!-- view23, has same top position with view21 and same bottom position with view22,
+             and on the end of view1. -->
+        <TextView
+                android:id="@+id/relative_view23"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_alignTop="@id/relative_view21"
+                android:layout_alignBottom="@id/relative_view22"
+                android:layout_toEndOf="@id/relative_view21"
+                android:text="@string/relative_view3"/>
+
+        <!-- view24, has same end position with view23 and above view23. -->
+        <TextView
+                android:id="@+id/relative_view24"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_alignEnd="@id/relative_view23"
+                android:layout_above="@id/relative_view23"
+                android:text="@string/relative_view4"/>
+
+        <!-- view25 goes on the start-bottom -->
+        <TextView
+                android:id="@+id/relative_view25"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_alignParentBottom="true"
+                android:layout_alignParentStart="true"
+                android:text="@string/relative_view5"/>
+
+        <!-- view26 goes on the top-end -->
+        <TextView
+                android:id="@+id/relative_view26"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_alignParentTop="true"
+                android:layout_alignParentEnd="true"
+                android:text="@string/relative_view6"/>
+
+        <!-- view27, has same baseline with view26 and centered horizontally within its parent. -->
+        <TextView
+                android:id="@+id/relative_view27"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_alignBaseline="@id/relative_view26"
+                android:layout_centerHorizontal="true"
+                android:text="@string/relative_view7"/>
+
+        <!-- view28, centered vertically within its parent and on the start of view21. -->
+        <TextView
+                android:id="@+id/relative_view28"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_toStartOf="@id/relative_view21"
+                android:layout_centerVertical="true"
+                android:text="@string/relative_view8"/>
+
+        <!-- view29, has same top and bottom position with view23 and same start position
+             with its parent. -->
+        <TextView
+                android:id="@+id/relative_view29"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_alignStart="@id/gravity_bottom"
+                android:layout_alignTop="@id/relative_view23"
+                android:layout_alignBottom="@id/relative_view23"
+                android:layout_alignWithParentIfMissing="true"
+                android:text="@string/relative_view9"/>
+
+    </RelativeLayout>
+
 </RelativeLayout>
diff --git a/tests/src/android/widget/cts/LayoutDirectionStubActivity.java b/tests/src/android/widget/cts/LayoutDirectionStubActivity.java
new file mode 100644
index 0000000..66f24f74
--- /dev/null
+++ b/tests/src/android/widget/cts/LayoutDirectionStubActivity.java
@@ -0,0 +1,32 @@
+/*
+ * 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.widget.cts;
+
+import android.app.Activity;
+import android.os.Bundle;
+import com.android.cts.stub.R;
+
+/**
+ * A minimal application for layout direction test.
+ */
+public class LayoutDirectionStubActivity extends Activity {
+    @Override
+    public void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.layoutdirection_layout);
+    }
+}
diff --git a/tests/tests/accessibility/src/android/view/accessibility/cts/AccessibilityNodeInfoTest.java b/tests/tests/accessibility/src/android/view/accessibility/cts/AccessibilityNodeInfoTest.java
index 5cac9f9..73883e2 100644
--- a/tests/tests/accessibility/src/android/view/accessibility/cts/AccessibilityNodeInfoTest.java
+++ b/tests/tests/accessibility/src/android/view/accessibility/cts/AccessibilityNodeInfoTest.java
@@ -30,7 +30,7 @@
 public class AccessibilityNodeInfoTest extends AndroidTestCase {
 
     /** The number of properties of the {@link AccessibilityNodeInfo} class. */
-    private static final int NON_STATIC_FIELD_COUNT = 19;
+    private static final int NON_STATIC_FIELD_COUNT = 17;
 
     @SmallTest
     public void testMarshaling() throws Exception {
diff --git a/tests/tests/accessibilityservice/res/layout/accessibility_focus_and_input_focus_sync_test.xml b/tests/tests/accessibilityservice/res/layout/accessibility_focus_and_input_focus_sync_test.xml
index 383f209..cb3d153 100644
--- a/tests/tests/accessibilityservice/res/layout/accessibility_focus_and_input_focus_sync_test.xml
+++ b/tests/tests/accessibilityservice/res/layout/accessibility_focus_and_input_focus_sync_test.xml
@@ -20,6 +20,7 @@
           android:layout_width="wrap_content"
           android:layout_height="wrap_content"
           android:orientation="horizontal"
+          android:layoutDirection="ltr"
           android:contentDescription="@string/firstLinearLayout" >
 
           <TextView
@@ -55,6 +56,7 @@
           android:layout_width="wrap_content"
           android:layout_height="wrap_content"
           android:orientation="horizontal"
+          android:layoutDirection="rtl"
           android:contentDescription="@string/secondLinearLayout"
           android:clickable="true"
           android:importantForAccessibility="no" >
diff --git a/tests/tests/accessibilityservice/res/layout/accessibility_text_traversal_test.xml b/tests/tests/accessibilityservice/res/layout/accessibility_text_traversal_test.xml
index 1c15f8e..5b3d2e6 100644
--- a/tests/tests/accessibilityservice/res/layout/accessibility_text_traversal_test.xml
+++ b/tests/tests/accessibilityservice/res/layout/accessibility_text_traversal_test.xml
@@ -40,6 +40,7 @@
        android:layout_height="200dip"
        android:maxLines="1000"
        android:scrollbars="vertical"
+       android:focusable="false"
        />
 
 </LinearLayout>
diff --git a/tests/tests/accessibilityservice/res/layout/accessibility_view_tree_reporting_test.xml b/tests/tests/accessibilityservice/res/layout/accessibility_view_tree_reporting_test.xml
index 26f60bf..fe420bc 100644
--- a/tests/tests/accessibilityservice/res/layout/accessibility_view_tree_reporting_test.xml
+++ b/tests/tests/accessibilityservice/res/layout/accessibility_view_tree_reporting_test.xml
@@ -4,6 +4,7 @@
     android:layout_width="fill_parent"
     android:layout_height="fill_parent"
     android:orientation="vertical"
+    android:layoutDirection="rtl"
     android:importantForAccessibility="yes"
     android:contentDescription="@string/rootLinearLayout">
 
@@ -20,6 +21,7 @@
           android:layout_width="wrap_content"
           android:layout_height="wrap_content"
           android:orientation="horizontal"
+          android:layoutDirection="ltr"
           android:importantForAccessibility="no"
           android:contentDescription="@string/firstLinearLayout" >
 
@@ -57,6 +59,7 @@
           android:layout_width="wrap_content"
           android:layout_height="wrap_content"
           android:orientation="horizontal"
+          android:layoutDirection="rtl"
           android:contentDescription="@string/secondLinearLayout"
           android:clickable="true"
           android:importantForAccessibility="no" >
diff --git a/tests/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityServiceInfoTest.java b/tests/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityServiceInfoTest.java
index 80ddd87..0f687d0 100644
--- a/tests/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityServiceInfoTest.java
+++ b/tests/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityServiceInfoTest.java
@@ -77,8 +77,11 @@
                 AccessibilityServiceInfo.FEEDBACK_SPOKEN));
         assertEquals("[FEEDBACK_VISUAL]", AccessibilityServiceInfo.feedbackTypeToString(
                 AccessibilityServiceInfo.FEEDBACK_VISUAL));
+        assertEquals("[FEEDBACK_BRAILLE]", AccessibilityServiceInfo.feedbackTypeToString(
+                AccessibilityServiceInfo.FEEDBACK_BRAILLE));
         assertEquals("[FEEDBACK_SPOKEN, FEEDBACK_HAPTIC, FEEDBACK_AUDIBLE, FEEDBACK_VISUAL,"
-                + " FEEDBACK_GENERIC]", AccessibilityServiceInfo.feedbackTypeToString(
+                + " FEEDBACK_GENERIC, FEEDBACK_BRAILLE]",
+                AccessibilityServiceInfo.feedbackTypeToString(
                         AccessibilityServiceInfo.FEEDBACK_ALL_MASK));
     }
 
diff --git a/tests/tests/animation/src/android/animation/cts/ObjectAnimatorTest.java b/tests/tests/animation/src/android/animation/cts/ObjectAnimatorTest.java
index 71945ac..f8f1f43 100644
--- a/tests/tests/animation/src/android/animation/cts/ObjectAnimatorTest.java
+++ b/tests/tests/animation/src/android/animation/cts/ObjectAnimatorTest.java
@@ -20,7 +20,6 @@
 import android.animation.ObjectAnimator;
 import android.animation.PropertyValuesHolder;
 import android.animation.ValueAnimator;
-import android.os.SystemClock;
 import android.test.ActivityInstrumentationTestCase2;
 import android.view.animation.AccelerateInterpolator;
 import android.view.animation.Interpolator;
@@ -250,5 +249,3 @@
         this.runTestOnUiThread(mAnimationRunnable);
     }
 }
-
-
diff --git a/tests/tests/bluetooth/src/android/bluetooth/cts/BasicAdapterTest.java b/tests/tests/bluetooth/src/android/bluetooth/cts/BasicAdapterTest.java
index e8e32ee..e64da89 100644
--- a/tests/tests/bluetooth/src/android/bluetooth/cts/BasicAdapterTest.java
+++ b/tests/tests/bluetooth/src/android/bluetooth/cts/BasicAdapterTest.java
@@ -31,8 +31,8 @@
  * BluetoothAdapter}.
  */
 public class BasicAdapterTest extends AndroidTestCase {
-    private static final int DISABLE_TIMEOUT = 60000; // ms timeout for BT disable
-    private static final int ENABLE_TIMEOUT = 60000;  // ms timeout for BT enable
+    private static final int DISABLE_TIMEOUT = 5000;  // ms timeout for BT disable
+    private static final int ENABLE_TIMEOUT = 10000;  // ms timeout for BT enable
     private static final int POLL_TIME = 400;         // ms to poll BT state
 
     private boolean mHasBluetooth;
@@ -227,13 +227,12 @@
             return;
         }
 
+        assertEquals(BluetoothAdapter.STATE_ON, adapter.getState());
+        assertTrue(adapter.isEnabled());
         adapter.disable();
         for (int i=0; i<DISABLE_TIMEOUT/POLL_TIME; i++) {
             sleep(POLL_TIME);
             switch (adapter.getState()) {
-            case BluetoothAdapter.STATE_ON:
-                assertTrue(adapter.isEnabled());
-                continue;
             case BluetoothAdapter.STATE_OFF:
                 assertFalse(adapter.isEnabled());
                 return;
@@ -256,13 +255,12 @@
             return;
         }
 
+        assertEquals(BluetoothAdapter.STATE_OFF, adapter.getState());
+        assertFalse(adapter.isEnabled());
         adapter.enable();
         for (int i=0; i<ENABLE_TIMEOUT/POLL_TIME; i++) {
             sleep(POLL_TIME);
             switch (adapter.getState()) {
-            case BluetoothAdapter.STATE_OFF:
-                assertFalse(adapter.isEnabled());
-                continue;
             case BluetoothAdapter.STATE_ON:
                 assertTrue(adapter.isEnabled());
                 return;
diff --git a/tests/tests/content/src/android/content/res/cts/ConfigurationTest.java b/tests/tests/content/src/android/content/res/cts/ConfigurationTest.java
index 70443b0..9c13fe1 100644
--- a/tests/tests/content/src/android/content/res/cts/ConfigurationTest.java
+++ b/tests/tests/content/src/android/content/res/cts/ConfigurationTest.java
@@ -22,6 +22,8 @@
 import android.content.res.Configuration;
 import android.os.Parcel;
 import android.test.AndroidTestCase;
+import android.util.LocaleUtil;
+import android.view.View;
 
 public class ConfigurationTest extends AndroidTestCase {
 
@@ -154,24 +156,29 @@
         doConfigCompare(ActivityInfo.CONFIG_MCC
                 | ActivityInfo.CONFIG_MNC, mConfigDefault, config);
         config.locale = Locale.getDefault();
+        config.setLayoutDirection(config.locale);
         doConfigCompare(ActivityInfo.CONFIG_MCC
                 | ActivityInfo.CONFIG_MNC
-                | ActivityInfo.CONFIG_LOCALE, mConfigDefault, config);
+                | ActivityInfo.CONFIG_LOCALE
+                | ActivityInfo.CONFIG_LAYOUT_DIRECTION, mConfigDefault, config);
         config.screenLayout = 1;
         doConfigCompare(ActivityInfo.CONFIG_MCC
                 | ActivityInfo.CONFIG_MNC
                 | ActivityInfo.CONFIG_LOCALE
+                | ActivityInfo.CONFIG_LAYOUT_DIRECTION
                 | ActivityInfo.CONFIG_SCREEN_LAYOUT, mConfigDefault, config);
         config.touchscreen = 1;
         doConfigCompare(ActivityInfo.CONFIG_MCC
                 | ActivityInfo.CONFIG_MNC
                 | ActivityInfo.CONFIG_LOCALE
+                | ActivityInfo.CONFIG_LAYOUT_DIRECTION
                 | ActivityInfo.CONFIG_SCREEN_LAYOUT
                 | ActivityInfo.CONFIG_TOUCHSCREEN, mConfigDefault, config);
         config.keyboard = 1;
         doConfigCompare(ActivityInfo.CONFIG_MCC
                 | ActivityInfo.CONFIG_MNC
                 | ActivityInfo.CONFIG_LOCALE
+                | ActivityInfo.CONFIG_LAYOUT_DIRECTION
                 | ActivityInfo.CONFIG_SCREEN_LAYOUT
                 | ActivityInfo.CONFIG_TOUCHSCREEN
                 | ActivityInfo.CONFIG_KEYBOARD, mConfigDefault, config);
@@ -179,6 +186,7 @@
         doConfigCompare(ActivityInfo.CONFIG_MCC
                 | ActivityInfo.CONFIG_MNC
                 | ActivityInfo.CONFIG_LOCALE
+                | ActivityInfo.CONFIG_LAYOUT_DIRECTION
                 | ActivityInfo.CONFIG_SCREEN_LAYOUT
                 | ActivityInfo.CONFIG_TOUCHSCREEN
                 | ActivityInfo.CONFIG_KEYBOARD
@@ -188,6 +196,7 @@
         doConfigCompare(ActivityInfo.CONFIG_MCC
                 | ActivityInfo.CONFIG_MNC
                 | ActivityInfo.CONFIG_LOCALE
+                | ActivityInfo.CONFIG_LAYOUT_DIRECTION
                 | ActivityInfo.CONFIG_SCREEN_LAYOUT
                 | ActivityInfo.CONFIG_TOUCHSCREEN
                 | ActivityInfo.CONFIG_KEYBOARD
@@ -197,6 +206,7 @@
         doConfigCompare(ActivityInfo.CONFIG_MCC
                 | ActivityInfo.CONFIG_MNC
                 | ActivityInfo.CONFIG_LOCALE
+                | ActivityInfo.CONFIG_LAYOUT_DIRECTION
                 | ActivityInfo.CONFIG_SCREEN_LAYOUT
                 | ActivityInfo.CONFIG_TOUCHSCREEN
                 | ActivityInfo.CONFIG_KEYBOARD
@@ -205,6 +215,7 @@
         doConfigCompare(ActivityInfo.CONFIG_MCC
                 | ActivityInfo.CONFIG_MNC
                 | ActivityInfo.CONFIG_LOCALE
+                | ActivityInfo.CONFIG_LAYOUT_DIRECTION
                 | ActivityInfo.CONFIG_SCREEN_LAYOUT
                 | ActivityInfo.CONFIG_TOUCHSCREEN
                 | ActivityInfo.CONFIG_KEYBOARD
@@ -214,6 +225,7 @@
         doConfigCompare(ActivityInfo.CONFIG_MCC
                 | ActivityInfo.CONFIG_MNC
                 | ActivityInfo.CONFIG_LOCALE
+                | ActivityInfo.CONFIG_LAYOUT_DIRECTION
                 | ActivityInfo.CONFIG_SCREEN_LAYOUT
                 | ActivityInfo.CONFIG_TOUCHSCREEN
                 | ActivityInfo.CONFIG_KEYBOARD
@@ -224,6 +236,7 @@
         doConfigCompare(ActivityInfo.CONFIG_MCC
                 | ActivityInfo.CONFIG_MNC
                 | ActivityInfo.CONFIG_LOCALE
+                | ActivityInfo.CONFIG_LAYOUT_DIRECTION
                 | ActivityInfo.CONFIG_SCREEN_LAYOUT
                 | ActivityInfo.CONFIG_TOUCHSCREEN
                 | ActivityInfo.CONFIG_KEYBOARD
@@ -235,6 +248,7 @@
         doConfigCompare(ActivityInfo.CONFIG_MCC
                 | ActivityInfo.CONFIG_MNC
                 | ActivityInfo.CONFIG_LOCALE
+                | ActivityInfo.CONFIG_LAYOUT_DIRECTION
                 | ActivityInfo.CONFIG_SCREEN_LAYOUT
                 | ActivityInfo.CONFIG_TOUCHSCREEN
                 | ActivityInfo.CONFIG_KEYBOARD
@@ -280,6 +294,62 @@
         assertWriteToParcel(createConfig(Locale.JAPAN), Parcel.obtain());
     }
 
+    public void testSetLocale() {
+        Configuration config = new Configuration();
+
+        config.setLocale(Locale.getDefault());
+        assertEquals(Locale.getDefault(), config.locale);
+        assertEquals(View.LAYOUT_DIRECTION_LTR, config.getLayoutDirection());
+
+        config.setLocale(Locale.ENGLISH);
+        assertEquals(Locale.ENGLISH, config.locale);
+        assertEquals(View.LAYOUT_DIRECTION_LTR, config.getLayoutDirection());
+
+        config.setLocale(Locale.US);
+        assertEquals(Locale.US, config.locale);
+        assertEquals(View.LAYOUT_DIRECTION_LTR, config.getLayoutDirection());
+
+        final Locale arEGLocale = new Locale("ar", "EG");
+        config.setLocale(arEGLocale);
+        assertEquals(arEGLocale, config.locale);
+        assertEquals(View.LAYOUT_DIRECTION_RTL, config.getLayoutDirection());
+
+        final Locale faFALocale = new Locale("fa", "FA");
+        config.setLocale(faFALocale);
+        assertEquals(faFALocale, config.locale);
+        assertEquals(View.LAYOUT_DIRECTION_RTL, config.getLayoutDirection());
+
+        final Locale iwILLocale = new Locale("iw", "IL");
+        config.setLocale(iwILLocale);
+        assertEquals(iwILLocale, config.locale);
+        assertEquals(View.LAYOUT_DIRECTION_RTL, config.getLayoutDirection());
+    }
+
+    public void testSetGetLayoutDirection() {
+        Configuration config = new Configuration();
+
+        config.setLayoutDirection(Locale.getDefault());
+        assertEquals(View.LAYOUT_DIRECTION_LTR, config.getLayoutDirection());
+
+        config.setLayoutDirection(Locale.ENGLISH);
+        assertEquals(View.LAYOUT_DIRECTION_LTR, config.getLayoutDirection());
+
+        config.setLayoutDirection(Locale.US);
+        assertEquals(View.LAYOUT_DIRECTION_LTR, config.getLayoutDirection());
+
+        final Locale arEGLocale = new Locale("ar", "EG");
+        config.setLayoutDirection(arEGLocale);
+        assertEquals(View.LAYOUT_DIRECTION_RTL, config.getLayoutDirection());
+
+        final Locale faFALocale = new Locale("fa", "FA");
+        config.setLayoutDirection(faFALocale);
+        assertEquals(View.LAYOUT_DIRECTION_RTL, config.getLayoutDirection());
+
+        final Locale iwILLocale = new Locale("iw", "IL");
+        config.setLayoutDirection(iwILLocale);
+        assertEquals(View.LAYOUT_DIRECTION_RTL, config.getLayoutDirection());
+    }
+
     private Configuration createConfig(Locale locale) {
         Configuration config = new Configuration();
         config.fontScale = 13.37f;
diff --git a/tests/tests/graphics/src/android/graphics/cts/PaintTest.java b/tests/tests/graphics/src/android/graphics/cts/PaintTest.java
index bc9a822..75e90cf 100644
--- a/tests/tests/graphics/src/android/graphics/cts/PaintTest.java
+++ b/tests/tests/graphics/src/android/graphics/cts/PaintTest.java
@@ -535,6 +535,41 @@
         assertEquals(Align.RIGHT, p.getTextAlign());
     }
 
+    public void testAccessTextLocale() {
+        Paint p = new Paint();
+
+        final Locale defaultLocale = Locale.getDefault();
+
+        // Check default
+        assertEquals(defaultLocale, p.getTextLocale());
+
+        // Check setter / getter
+        p.setTextLocale(Locale.US);
+        assertEquals(Locale.US, p.getTextLocale());
+
+        p.setTextLocale(Locale.CHINESE);
+        assertEquals(Locale.CHINESE, p.getTextLocale());
+
+        p.setTextLocale(Locale.JAPANESE);
+        assertEquals(Locale.JAPANESE, p.getTextLocale());
+
+        p.setTextLocale(Locale.KOREAN);
+        assertEquals(Locale.KOREAN, p.getTextLocale());
+
+        // Check reverting back to default
+        p.setTextLocale(defaultLocale);
+        assertEquals(defaultLocale, p.getTextLocale());
+
+        // Check that we cannot pass a null locale
+        try {
+            p.setTextLocale(null);
+            assertFalse(true);
+        }
+        catch (IllegalArgumentException iae) {
+            // OK !!
+        }
+    }
+
     public void testGetFillPath() {
         Paint p = new Paint();
         Path path1 = new Path();
diff --git a/tests/tests/graphics/src/android/graphics/drawable/cts/ClipDrawableTest.java b/tests/tests/graphics/src/android/graphics/drawable/cts/ClipDrawableTest.java
index 33d81f3..5af5607 100644
--- a/tests/tests/graphics/src/android/graphics/drawable/cts/ClipDrawableTest.java
+++ b/tests/tests/graphics/src/android/graphics/drawable/cts/ClipDrawableTest.java
@@ -397,7 +397,7 @@
         }
     }
 
-    private class MockCallback implements Drawable.Callback2 {
+    private class MockCallback implements Drawable.Callback {
         private Drawable mInvalidateDrawable;
         private Drawable mScheduleDrawable;
         private Runnable mRunnable;
diff --git a/tests/tests/graphics/src/android/graphics/drawable/cts/DrawableContainerTest.java b/tests/tests/graphics/src/android/graphics/drawable/cts/DrawableContainerTest.java
index d2c2244..0672db6 100644
--- a/tests/tests/graphics/src/android/graphics/drawable/cts/DrawableContainerTest.java
+++ b/tests/tests/graphics/src/android/graphics/drawable/cts/DrawableContainerTest.java
@@ -943,7 +943,7 @@
         }
     }
 
-    private class MockCallBack implements Drawable.Callback2 {
+    private class MockCallBack implements Drawable.Callback {
         private boolean mCalledInvalidateDrawable;
 
         private boolean mCalledScheduleDrawable;
diff --git a/tests/tests/graphics/src/android/graphics/drawable/cts/DrawableTest.java b/tests/tests/graphics/src/android/graphics/drawable/cts/DrawableTest.java
index f14f59f..df29211 100644
--- a/tests/tests/graphics/src/android/graphics/drawable/cts/DrawableTest.java
+++ b/tests/tests/graphics/src/android/graphics/drawable/cts/DrawableTest.java
@@ -567,17 +567,6 @@
         assertSame(mockDrawable, mockDrawable.mutate());
     }
 
-    public void getResolvedLayoutDirectionSelf() {
-        MockDrawable mockDrawable = new MockDrawable();
-        MockCallback mockCallback = new MockCallback(1);
-        mockDrawable.setCallback(mockCallback);
-        assertEquals(1, mockDrawable.getResolvedLayoutDirectionSelf());
-
-        mockCallback = new MockCallback(0);
-        mockDrawable.setCallback(mockCallback);
-        assertEquals(0, mockDrawable.getResolvedLayoutDirectionSelf());
-    }
-
     private static class MockDrawable extends Drawable {
         private ColorFilter mColorFilter;
 
@@ -612,20 +601,13 @@
         }
     }
 
-    private static class MockCallback implements Drawable.Callback2 {
+    private static class MockCallback implements Drawable.Callback {
         private Drawable mInvalidateDrawable;
         private Drawable mScheduleDrawable;
         private Runnable mRunnable;
         private long mWhen;
-        private int mLayoutDirection;
 
         public MockCallback() {
-            // 0 for LTR layout direction
-            this(0);
-        }
-
-        public MockCallback(int direction) {
-            mLayoutDirection = direction;
         }
 
         public Drawable getInvalidateDrawable() {
@@ -658,9 +640,5 @@
             mScheduleDrawable = who;
             mRunnable = what;
         }
-
-        public int getResolvedLayoutDirection(Drawable who) {
-            return mLayoutDirection;
-        }
     }
 }
diff --git a/tests/tests/graphics/src/android/graphics/drawable/cts/LayerDrawableTest.java b/tests/tests/graphics/src/android/graphics/drawable/cts/LayerDrawableTest.java
index bf688d2..4e4648f 100644
--- a/tests/tests/graphics/src/android/graphics/drawable/cts/LayerDrawableTest.java
+++ b/tests/tests/graphics/src/android/graphics/drawable/cts/LayerDrawableTest.java
@@ -335,7 +335,7 @@
         assertFalse(cb.hasCalledUnschedule());
     }
 
-    private static class MockCallback implements Drawable.Callback2 {
+    private static class MockCallback implements Drawable.Callback {
         private boolean mCalledInvalidate;
         private boolean mCalledSchedule;
         private boolean mCalledUnschedule;
diff --git a/tests/tests/graphics/src/android/graphics/drawable/cts/RotateDrawableTest.java b/tests/tests/graphics/src/android/graphics/drawable/cts/RotateDrawableTest.java
index 75838e0..a3398f6 100644
--- a/tests/tests/graphics/src/android/graphics/drawable/cts/RotateDrawableTest.java
+++ b/tests/tests/graphics/src/android/graphics/drawable/cts/RotateDrawableTest.java
@@ -231,7 +231,7 @@
         assertEquals(50, ((BitmapDrawable) d3.getDrawable()).getPaint().getAlpha());
     }
 
-    private static class MockCallback implements Drawable.Callback2 {
+    private static class MockCallback implements Drawable.Callback {
         private boolean mCalledInvalidate;
         private boolean mCalledSchedule;
         private boolean mCalledUnschedule;
diff --git a/tests/tests/graphics/src/android/graphics/drawable/cts/ScaleDrawableTest.java b/tests/tests/graphics/src/android/graphics/drawable/cts/ScaleDrawableTest.java
index 305f32d..e0cd2ee 100644
--- a/tests/tests/graphics/src/android/graphics/drawable/cts/ScaleDrawableTest.java
+++ b/tests/tests/graphics/src/android/graphics/drawable/cts/ScaleDrawableTest.java
@@ -114,7 +114,7 @@
         assertFalse(cb.hasCalledUnschedule());
     }
 
-    private static class MockCallback implements Drawable.Callback2 {
+    private static class MockCallback implements Drawable.Callback {
         private boolean mCalledInvalidate;
         private boolean mCalledSchedule;
         private boolean mCalledUnschedule;
diff --git a/tests/tests/graphics/src/android/graphics/drawable/cts/TransitionDrawableTest.java b/tests/tests/graphics/src/android/graphics/drawable/cts/TransitionDrawableTest.java
index aeb21cf..25b08d5 100644
--- a/tests/tests/graphics/src/android/graphics/drawable/cts/TransitionDrawableTest.java
+++ b/tests/tests/graphics/src/android/graphics/drawable/cts/TransitionDrawableTest.java
@@ -242,7 +242,7 @@
         }
     }
 
-    private class MockCallBack implements Drawable.Callback2 {
+    private class MockCallBack implements Drawable.Callback {
         private boolean mHasCalledInvalidateDrawable;
 
         public boolean hasCalledInvalidateDrawable() {
diff --git a/tests/tests/hardware/src/android/hardware/cts/CameraTest.java b/tests/tests/hardware/src/android/hardware/cts/CameraTest.java
index d0a2bf0..440d054 100755
--- a/tests/tests/hardware/src/android/hardware/cts/CameraTest.java
+++ b/tests/tests/hardware/src/android/hardware/cts/CameraTest.java
@@ -2754,4 +2754,63 @@
         }
         terminateMessageLooper();
     }
+
+    public void testPreviewCallbackWithPicture() throws Exception {
+        int nCameras = Camera.getNumberOfCameras();
+        for (int id = 0; id < nCameras; id++) {
+            Log.v(TAG, "Camera id=" + id);
+            testPreviewCallbackWithPictureByCamera(id);
+        }
+    }
+
+    private void testPreviewCallbackWithPictureByCamera(int cameraId)
+            throws Exception {
+        initializeMessageLooper(cameraId);
+
+        SimplePreviewStreamCb callback = new SimplePreviewStreamCb(1);
+        mCamera.setPreviewCallback(callback);
+
+        Log.v(TAG, "Starting preview");
+        mCamera.startPreview();
+
+        // Wait until callbacks are flowing
+        for (int i = 0; i < 30; i++) {
+            assertTrue("testPreviewCallbackWithPicture: Not receiving preview callbacks!",
+                    mPreviewDone.block( WAIT_FOR_COMMAND_TO_COMPLETE ) );
+            mPreviewDone.close();
+        }
+
+        // Now take a picture
+        Log.v(TAG, "Taking picture now");
+
+        Size pictureSize = mCamera.getParameters().getPictureSize();
+        mCamera.takePicture(mShutterCallback, mRawPictureCallback,
+                mJpegPictureCallback);
+
+        waitForSnapshotDone();
+
+        assertTrue("Shutter callback not received", mShutterCallbackResult);
+        assertTrue("Raw picture callback not received", mRawPictureCallbackResult);
+        assertTrue("Jpeg picture callback not received", mJpegPictureCallbackResult);
+        assertNotNull(mJpegData);
+        BitmapFactory.Options bmpOptions = new BitmapFactory.Options();
+        bmpOptions.inJustDecodeBounds = true;
+        BitmapFactory.decodeByteArray(mJpegData, 0, mJpegData.length, bmpOptions);
+        assertEquals(pictureSize.width, bmpOptions.outWidth);
+        assertEquals(pictureSize.height, bmpOptions.outHeight);
+
+        // Restart preview, confirm callbacks still happen
+        Log.v(TAG, "Restarting preview");
+        mCamera.startPreview();
+
+        for (int i = 0; i < 30; i++) {
+            assertTrue("testPreviewCallbackWithPicture: Not receiving preview callbacks!",
+                    mPreviewDone.block( WAIT_FOR_COMMAND_TO_COMPLETE ) );
+            mPreviewDone.close();
+        }
+
+        mCamera.stopPreview();
+
+        terminateMessageLooper();
+    }
 }
diff --git a/tests/tests/holo/res/drawable-hdpi/display_info.png b/tests/tests/holo/res/drawable-hdpi/display_info.png
deleted file mode 100644
index 10b3950..0000000
--- a/tests/tests/holo/res/drawable-hdpi/display_info.png
+++ /dev/null
Binary files differ
diff --git a/tests/tests/holo/res/drawable-land-hdpi/display_info.png b/tests/tests/holo/res/drawable-land-hdpi/display_info.png
deleted file mode 100644
index a665018..0000000
--- a/tests/tests/holo/res/drawable-land-hdpi/display_info.png
+++ /dev/null
Binary files differ
diff --git a/tests/tests/holo/res/drawable-land-ldpi/display_info.png b/tests/tests/holo/res/drawable-land-ldpi/display_info.png
deleted file mode 100644
index 64c8f3a..0000000
--- a/tests/tests/holo/res/drawable-land-ldpi/display_info.png
+++ /dev/null
Binary files differ
diff --git a/tests/tests/holo/res/drawable-land-mdpi/display_info.png b/tests/tests/holo/res/drawable-land-mdpi/display_info.png
deleted file mode 100644
index f3e6765..0000000
--- a/tests/tests/holo/res/drawable-land-mdpi/display_info.png
+++ /dev/null
Binary files differ
diff --git a/tests/tests/holo/res/drawable-land-tvdpi/display_info.png b/tests/tests/holo/res/drawable-land-tvdpi/display_info.png
deleted file mode 100644
index 99de970..0000000
--- a/tests/tests/holo/res/drawable-land-tvdpi/display_info.png
+++ /dev/null
Binary files differ
diff --git a/tests/tests/holo/res/drawable-land-xhdpi/display_info.png b/tests/tests/holo/res/drawable-land-xhdpi/display_info.png
deleted file mode 100644
index 4c0c2b4..0000000
--- a/tests/tests/holo/res/drawable-land-xhdpi/display_info.png
+++ /dev/null
Binary files differ
diff --git a/tests/tests/holo/res/drawable-ldpi/display_info.png b/tests/tests/holo/res/drawable-ldpi/display_info.png
deleted file mode 100644
index af1fda5..0000000
--- a/tests/tests/holo/res/drawable-ldpi/display_info.png
+++ /dev/null
Binary files differ
diff --git a/tests/tests/holo/res/drawable-mdpi/display_info.png b/tests/tests/holo/res/drawable-mdpi/display_info.png
deleted file mode 100644
index 4378b14..0000000
--- a/tests/tests/holo/res/drawable-mdpi/display_info.png
+++ /dev/null
Binary files differ
diff --git a/tests/tests/holo/res/drawable-sw600dp-hdpi/display_info.png b/tests/tests/holo/res/drawable-sw600dp-hdpi/display_info.png
deleted file mode 100644
index 1e61b19..0000000
--- a/tests/tests/holo/res/drawable-sw600dp-hdpi/display_info.png
+++ /dev/null
Binary files differ
diff --git a/tests/tests/holo/res/drawable-sw600dp-land-hdpi/display_info.png b/tests/tests/holo/res/drawable-sw600dp-land-hdpi/display_info.png
deleted file mode 100644
index 123440e..0000000
--- a/tests/tests/holo/res/drawable-sw600dp-land-hdpi/display_info.png
+++ /dev/null
Binary files differ
diff --git a/tests/tests/holo/res/drawable-sw600dp-land-ldpi/display_info.png b/tests/tests/holo/res/drawable-sw600dp-land-ldpi/display_info.png
deleted file mode 100644
index 7b8a0ad..0000000
--- a/tests/tests/holo/res/drawable-sw600dp-land-ldpi/display_info.png
+++ /dev/null
Binary files differ
diff --git a/tests/tests/holo/res/drawable-sw600dp-land-mdpi/display_info.png b/tests/tests/holo/res/drawable-sw600dp-land-mdpi/display_info.png
deleted file mode 100644
index e285898..0000000
--- a/tests/tests/holo/res/drawable-sw600dp-land-mdpi/display_info.png
+++ /dev/null
Binary files differ
diff --git a/tests/tests/holo/res/drawable-sw600dp-land-tvdpi/display_info.png b/tests/tests/holo/res/drawable-sw600dp-land-tvdpi/display_info.png
deleted file mode 100644
index af4eaaa8..0000000
--- a/tests/tests/holo/res/drawable-sw600dp-land-tvdpi/display_info.png
+++ /dev/null
Binary files differ
diff --git a/tests/tests/holo/res/drawable-sw600dp-land-xhdpi/display_info.png b/tests/tests/holo/res/drawable-sw600dp-land-xhdpi/display_info.png
deleted file mode 100644
index 995af67..0000000
--- a/tests/tests/holo/res/drawable-sw600dp-land-xhdpi/display_info.png
+++ /dev/null
Binary files differ
diff --git a/tests/tests/holo/res/drawable-sw600dp-ldpi/display_info.png b/tests/tests/holo/res/drawable-sw600dp-ldpi/display_info.png
deleted file mode 100644
index 4d9d810..0000000
--- a/tests/tests/holo/res/drawable-sw600dp-ldpi/display_info.png
+++ /dev/null
Binary files differ
diff --git a/tests/tests/holo/res/drawable-sw600dp-mdpi/display_info.png b/tests/tests/holo/res/drawable-sw600dp-mdpi/display_info.png
deleted file mode 100644
index b875d76..0000000
--- a/tests/tests/holo/res/drawable-sw600dp-mdpi/display_info.png
+++ /dev/null
Binary files differ
diff --git a/tests/tests/holo/res/drawable-sw600dp-tvdpi/display_info.png b/tests/tests/holo/res/drawable-sw600dp-tvdpi/display_info.png
deleted file mode 100644
index 6db0c61..0000000
--- a/tests/tests/holo/res/drawable-sw600dp-tvdpi/display_info.png
+++ /dev/null
Binary files differ
diff --git a/tests/tests/holo/res/drawable-sw600dp-xhdpi/display_info.png b/tests/tests/holo/res/drawable-sw600dp-xhdpi/display_info.png
deleted file mode 100644
index 0ebb8c7..0000000
--- a/tests/tests/holo/res/drawable-sw600dp-xhdpi/display_info.png
+++ /dev/null
Binary files differ
diff --git a/tests/tests/holo/res/drawable-tvdpi/display_info.png b/tests/tests/holo/res/drawable-tvdpi/display_info.png
deleted file mode 100644
index d9825fb..0000000
--- a/tests/tests/holo/res/drawable-tvdpi/display_info.png
+++ /dev/null
Binary files differ
diff --git a/tests/tests/holo/res/drawable-xhdpi/display_info.png b/tests/tests/holo/res/drawable-xhdpi/display_info.png
deleted file mode 100644
index 585af2f..0000000
--- a/tests/tests/holo/res/drawable-xhdpi/display_info.png
+++ /dev/null
Binary files differ
diff --git a/tests/tests/holo/res/layout/display_info.xml b/tests/tests/holo/res/layout/display_info.xml
index 9804b8c..130ce1f 100644
--- a/tests/tests/holo/res/layout/display_info.xml
+++ b/tests/tests/holo/res/layout/display_info.xml
@@ -13,20 +13,8 @@
      See the License for the specific language governing permissions and
      limitations under the License.
 -->
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
-    android:orientation="vertical"
-    android:layout_width="match_parent"
-    android:layout_height="match_parent"
-    >
-    <ImageView
-        android:src="@drawable/display_info"
-        android:layout_width="fill_parent"
-        android:layout_height="wrap_content"
-        />
-    <TextView 
+<TextView xmlns:android="http://schemas.android.com/apk/res/android"
         android:id="@+id/text"
         android:layout_width="fill_parent"
-        android:layout_height="wrap_content"
+        android:layout_height="fill_parent"
         />
-</LinearLayout>
-
diff --git a/tests/tests/holo/res/values/strings.xml b/tests/tests/holo/res/values/strings.xml
index d2f6fd6..5eb7d82 100644
--- a/tests/tests/holo/res/values/strings.xml
+++ b/tests/tests/holo/res/values/strings.xml
@@ -24,7 +24,7 @@
     <string name="task_clear_diff_bitmaps">Clear Diff Bitmaps</string>
 
     <string name="display_info">Display Info</string>
-    <string name="display_info_text">Density DPI: %1$d\nDensity Bucket: %2$s\nWidth DP: %3$d\nHeight DP: %4$d</string>
+    <string name="display_info_text">Density DPI: %1$d\nDensity Bucket: %2$s</string>
 
     <string name="pick_theme">Pick Theme</string>
     <string name="pick_layout">Pick Layout</string>
diff --git a/tests/tests/holo/src/android/holo/cts/DisplayInfoActivity.java b/tests/tests/holo/src/android/holo/cts/DisplayInfoActivity.java
index bdd7925..a11179a 100644
--- a/tests/tests/holo/src/android/holo/cts/DisplayInfoActivity.java
+++ b/tests/tests/holo/src/android/holo/cts/DisplayInfoActivity.java
@@ -37,13 +37,9 @@
         DisplayMetrics metrics = new DisplayMetrics();
         display.getMetrics(metrics);
 
-        DisplayMetrics dm = getResources().getDisplayMetrics();
-        int width = Math.round(dm.widthPixels / dm.density);
-        int height = Math.round(dm.heightPixels / dm.density);
-
         TextView text = (TextView) findViewById(R.id.text);
         text.setText(getString(R.string.display_info_text, metrics.densityDpi,
-                getScreenDensityBucket(metrics), width, height));
+                getScreenDensityBucket(metrics)));
     }
 
     private String getScreenDensityBucket(DisplayMetrics metrics) {
diff --git a/tests/tests/location/src/android/location/cts/LocationManagerTest.java b/tests/tests/location/src/android/location/cts/LocationManagerTest.java
index 46e777f..0fc9b4d 100755
--- a/tests/tests/location/src/android/location/cts/LocationManagerTest.java
+++ b/tests/tests/location/src/android/location/cts/LocationManagerTest.java
@@ -33,10 +33,10 @@
 import android.os.Bundle;
 import android.os.HandlerThread;
 import android.os.Looper;
+import android.os.SystemClock;
 import android.provider.Settings;
 import android.test.InstrumentationTestCase;
 
-import java.lang.Thread;
 import java.util.List;
 import java.lang.Thread;
 
@@ -54,6 +54,8 @@
 
     private static final String UNKNOWN_PROVIDER_NAME = "unknown_provider";
 
+    private static final String FUSED_PROVIDER_NAME = "fused";
+
     private LocationManager mManager;
 
     private Context mContext;
@@ -454,7 +456,7 @@
         i.setAction("android.location.cts.TEST_GET_GPS_STATUS_ACTION");
         PendingIntent pi = PendingIntent.getBroadcast(mContext, 0, i, PendingIntent.FLAG_ONE_SHOT);
 
-        mManager.addProximityAlert(0, 0, 0, 5000, pi);
+        mManager.addProximityAlert(0, 0, 1.0f, 5000, pi);
         mManager.removeProximityAlert(pi);
     }
 
@@ -608,9 +610,6 @@
 
         // now update to trigger exit proximity proximity
         mIntentReceiver.clearReceivedIntents();
-
-        // delay 2 seconds since location update in less than 1s will be neglected.
-        Thread.sleep(2000);
         updateLocation(20, 20);
         waitForReceiveBroadcast();
         assertProximityType(false);
@@ -623,12 +622,17 @@
      * @param expiration - expiration of proximity alert
      */
     private void doTestEnterProximity(long expiration) throws Exception {
+        // need to mock the fused location provider for proximity tests
+        mockFusedLocation();
+
         // update location to outside proximity range
-        updateLocation(30, 30);
+        updateLocation(FUSED_PROVIDER_NAME, 30, 30);
         registerProximityListener(0, 0, 1000, expiration);
-        updateLocation(0, 0);
+        updateLocation(FUSED_PROVIDER_NAME, 0, 0);
         waitForReceiveBroadcast();
         assertProximityType(true);
+
+        unmockFusedLocation();
     }
 
     private void registerIntentReceiver() {
@@ -679,8 +683,9 @@
         Location location = new Location(providerName);
         location.setLatitude(latitude);
         location.setLongitude(longitude);
-
+        location.setAccuracy(1.0f);
         location.setTime(java.lang.System.currentTimeMillis());
+        location.setElapsedRealtimeNano(SystemClock.elapsedRealtimeNano());
         mManager.setTestProviderLocation(providerName, location);
     }
 
@@ -688,6 +693,14 @@
         updateLocation(TEST_MOCK_PROVIDER_NAME, latitude, longitude);
     }
 
+    private void mockFusedLocation() {
+        addTestProvider(FUSED_PROVIDER_NAME);
+    }
+
+    private void unmockFusedLocation() {
+        mManager.removeTestProvider(FUSED_PROVIDER_NAME);
+    }
+
     /**
      * Helper class that receives a proximity intent and notifies the main class
      * when received
diff --git a/tests/tests/media/res/raw/test_subtitle1_srt.3gp b/tests/tests/media/res/raw/test_subtitle1_srt.3gp
new file mode 100644
index 0000000..8dbc240
--- /dev/null
+++ b/tests/tests/media/res/raw/test_subtitle1_srt.3gp
@@ -0,0 +1,39 @@
+1
+00:00:0,000 --> 00:00:0,500
+2:0000
+
+2
+00:00:1,000 --> 00:00:1,500
+2:1000
+
+3
+00:00:2,000 --> 00:00:2,500
+2:2000
+
+4
+00:00:3,000 --> 00:00:3,500
+2:3000
+
+5
+00:00:4,000 --> 00:00:4,500
+2:4000
+
+6
+00:00:5,000 --> 00:00:5,500
+2:5000
+
+7
+00:00:6,000 --> 00:00:6,500
+2:6000
+
+8
+00:00:7,000 --> 00:00:7,500
+2:7000
+
+9
+00:00:8,000 --> 00:00:8,500
+2:8000
+
+10
+00:00:9,000 --> 00:00:9,500
+2:9000
diff --git a/tests/tests/media/res/raw/test_subtitle2_srt.3gp b/tests/tests/media/res/raw/test_subtitle2_srt.3gp
new file mode 100644
index 0000000..7ac2e72
--- /dev/null
+++ b/tests/tests/media/res/raw/test_subtitle2_srt.3gp
@@ -0,0 +1,39 @@
+1
+00:00:0,500 --> 00:00:1,000
+3:500
+
+2
+00:00:1,500 --> 00:00:2,000
+3:1500
+
+3
+00:00:2,500 --> 00:00:3,000
+3:2500
+
+4
+00:00:3,500 --> 00:00:4,000
+3:3500
+
+5
+00:00:4,500 --> 00:00:5,000
+3:4500
+
+6
+00:00:5,500 --> 00:00:6,000
+3:5500
+
+7
+00:00:6,500 --> 00:00:7,000
+3:6500
+
+8
+00:00:7,500 --> 00:00:8,000
+3:7500
+
+9
+00:00:8,500 --> 00:00:9,000
+3:8500
+
+10
+00:00:9,500 --> 00:00:10,000
+3:9500
diff --git a/tests/tests/media/res/raw/testvideo_with_2_subtitles.3gp b/tests/tests/media/res/raw/testvideo_with_2_subtitles.3gp
new file mode 100644
index 0000000..1de14a5
--- /dev/null
+++ b/tests/tests/media/res/raw/testvideo_with_2_subtitles.3gp
Binary files differ
diff --git a/tests/tests/media/src/android/media/cts/AudioTrackTest.java b/tests/tests/media/src/android/media/cts/AudioTrackTest.java
index f85375d..94fc008 100644
--- a/tests/tests/media/src/android/media/cts/AudioTrackTest.java
+++ b/tests/tests/media/src/android/media/cts/AudioTrackTest.java
@@ -22,6 +22,8 @@
 import android.test.AndroidTestCase;
 import android.util.Log;
 
+import java.nio.ByteBuffer;
+
 public class AudioTrackTest extends AndroidTestCase {
     private String TAG = "AudioTrackTest";
     private final long WAIT_MSEC = 200;
@@ -1314,6 +1316,27 @@
         track.release();
     }
 
+    public void testResourceLeakage() throws Exception {
+        final int BUFFER_SIZE = 600 * 1024;
+        ByteBuffer data = ByteBuffer.allocate(BUFFER_SIZE);
+        for (int i = 0; i < 10; i++) {
+            Log.i(TAG, "testResourceLeakage round " + i);
+            data.rewind();
+            AudioTrack track = new AudioTrack(AudioManager.STREAM_VOICE_CALL,
+                                              44100,
+                                              AudioFormat.CHANNEL_OUT_STEREO,
+                                              AudioFormat.ENCODING_PCM_16BIT,
+                                              data.capacity(),
+                                              AudioTrack.MODE_STREAM);
+            assertTrue(track != null);
+            track.write(data.array(), 0, data.capacity());
+            track.play();
+            Thread.sleep(100);
+            track.stop();
+            track.release();
+        }
+    }
+
     private class MockAudioTrack extends AudioTrack {
 
         public MockAudioTrack(int streamType, int sampleRateInHz, int channelConfig,
diff --git a/tests/tests/media/src/android/media/cts/CamcorderProfileTest.java b/tests/tests/media/src/android/media/cts/CamcorderProfileTest.java
index 3f28218..1df5011 100644
--- a/tests/tests/media/src/android/media/cts/CamcorderProfileTest.java
+++ b/tests/tests/media/src/android/media/cts/CamcorderProfileTest.java
@@ -266,6 +266,7 @@
                 return true;
             }
         }
+        Log.e(TAG, "Size (" + width + "x" + height + ") is not supported");
         return false;
     }
 }
diff --git a/tests/tests/media/src/android/media/cts/MediaPlayerTest.java b/tests/tests/media/src/android/media/cts/MediaPlayerTest.java
index 0c39531..4e78805 100644
--- a/tests/tests/media/src/android/media/cts/MediaPlayerTest.java
+++ b/tests/tests/media/src/android/media/cts/MediaPlayerTest.java
@@ -23,15 +23,20 @@
 import android.media.AudioManager;
 import android.media.MediaPlayer;
 import android.media.MediaRecorder;
+import android.media.MediaMetadataRetriever;
+import android.media.TimedText;
 import android.media.audiofx.AudioEffect;
 import android.media.audiofx.Visualizer;
 import android.net.Uri;
 import android.os.Environment;
 import android.os.PowerManager;
 import android.os.SystemClock;
+import android.util.Log;
 
 import java.io.File;
+import java.util.StringTokenizer;
 import java.util.UUID;
+import java.util.Vector;
 import java.util.concurrent.CountDownLatch;
 
 /**
@@ -44,10 +49,63 @@
 public class MediaPlayerTest extends MediaPlayerTestBase {
 
     private String RECORDED_FILE;
+    private static final String LOG_TAG = "MediaPlayerTest";
 
     private static final int  RECORDED_VIDEO_WIDTH  = 176;
     private static final int  RECORDED_VIDEO_HEIGHT = 144;
     private static final long RECORDED_DURATION_MS  = 3000;
+    private Vector<Integer> mTimedTextTrackIndex = new Vector<Integer>();
+
+    public class SubtitleMonitor {
+        private int selectedTrack;
+        private int numSignal;
+
+        public synchronized void reset() {
+            selectedTrack = 0;
+            numSignal = 0;
+        }
+
+        public synchronized void setSelectedTrack(int index) {
+            selectedTrack = index;
+        }
+
+        public synchronized int getSelectedTrack() {
+            return selectedTrack;
+        }
+
+        public synchronized void signal() {
+            numSignal++;
+            notifyAll();
+        }
+
+        public synchronized int getNumSignal() {
+            return numSignal;
+        }
+
+        public synchronized void waitForSignal(int targetCount) throws InterruptedException {
+            while (numSignal < targetCount) {
+                wait();
+            }
+        }
+
+        public synchronized void waitForSignal(int targetCount, long millis)
+                throws InterruptedException {
+            if (millis == 0) {
+                waitForSignal(targetCount);
+                return;
+            }
+            long deadline = System.currentTimeMillis() + millis;
+            while (numSignal < targetCount) {
+                long delay = deadline - System.currentTimeMillis();
+                if (delay < 0) {
+                    return;
+                }
+                wait(delay);
+            }
+        }
+    }
+
+    private SubtitleMonitor mSubtitleStatus = new SubtitleMonitor();
 
     private File mOutFile;
 
@@ -412,6 +470,7 @@
         checkOrientation(angle);
         recordVideo(width, height, angle, file, durationMs);
         checkDisplayedVideoSize(width, height, angle, file);
+        checkVideoRotationAngle(angle, file);
     }
 
     private void checkOrientation(int angle) throws Exception {
@@ -453,6 +512,17 @@
         playVideoTest(file, displayWidth, displayHeight);
     }
 
+    private void checkVideoRotationAngle(int angle, String file) {
+        MediaMetadataRetriever retriever = new MediaMetadataRetriever();
+        retriever.setDataSource(file);
+        String rotation = retriever.extractMetadata(
+                    MediaMetadataRetriever.METADATA_KEY_VIDEO_ROTATION);
+        retriever.release();
+        retriever = null;
+        assertNotNull(rotation);
+        assertEquals(Integer.parseInt(rotation), angle);
+    }
+
     public void testLocalVideo_MP4_H264_480x360_500kbps_25fps_AAC_Stereo_128kbps_44110Hz()
             throws Exception {
         playVideoTest(
@@ -639,6 +709,100 @@
                 R.raw.video_176x144_3gp_h263_300kbps_25fps_aac_stereo_128kbps_22050hz, 176, 144);
     }
 
+    private void readTimedTextTracks() throws Exception {
+        mTimedTextTrackIndex.clear();
+        MediaPlayer.TrackInfo[] trackInfos = mMediaPlayer.getTrackInfo();
+        if (trackInfos == null || trackInfos.length == 0) {
+            return;
+        }
+        for (int i = 0; i < trackInfos.length; ++i) {
+            if (trackInfos[i] == null) continue;
+            if (trackInfos[i].getTrackType() ==
+                 MediaPlayer.TrackInfo.MEDIA_TRACK_TYPE_TIMEDTEXT) {
+                mTimedTextTrackIndex.add(i);
+            }
+        }
+    }
+
+    private int getTimedTextTrackCount() {
+        return mTimedTextTrackIndex.size();
+    }
+
+    private void selectSubtitleTrack(int index) throws Exception {
+        int trackIndex = mTimedTextTrackIndex.get(index);
+        mMediaPlayer.selectTrack(trackIndex);
+        mSubtitleStatus.setSelectedTrack(index);
+    }
+
+    public void testChangeSubtitleTrack() throws Exception {
+        loadResource(R.raw.testvideo_with_2_subtitles);
+        readTimedTextTracks();
+        assertEquals(getTimedTextTrackCount(), 2);
+
+        // Adds two more external subtitle files.
+        loadSubtitleSource(R.raw.test_subtitle1_srt);
+        loadSubtitleSource(R.raw.test_subtitle2_srt);
+        readTimedTextTracks();
+        assertEquals(getTimedTextTrackCount(), 4);
+
+        mMediaPlayer.setDisplay(getActivity().getSurfaceHolder());
+        mMediaPlayer.setScreenOnWhilePlaying(true);
+        mMediaPlayer.setWakeMode(mContext, PowerManager.PARTIAL_WAKE_LOCK);
+        mMediaPlayer.setOnTimedTextListener(new MediaPlayer.OnTimedTextListener() {
+            @Override
+            public void onTimedText(MediaPlayer mp, TimedText text) {
+                final int toleranceMs = 100;
+                final int durationMs = 500;
+                int posMs = mMediaPlayer.getCurrentPosition();
+                if (text != null) {
+                    String plainText = text.getText();
+                    if (plainText != null) {
+                        StringTokenizer tokens = new StringTokenizer(plainText.trim(), ":");
+                        int subtitleTrackIndex = Integer.parseInt(tokens.nextToken());
+                        int startMs = Integer.parseInt(tokens.nextToken());
+                        Log.w(LOG_TAG, "text: " + plainText.trim() +
+                              ", trackId: " + subtitleTrackIndex + ", posMs: " + posMs);
+                        assertTrue(posMs >= startMs - toleranceMs);
+                        assertTrue(posMs < startMs + durationMs + toleranceMs);
+                        assertEquals(mSubtitleStatus.getSelectedTrack(), subtitleTrackIndex);
+                        mSubtitleStatus.signal();
+                    }
+                }
+            }
+        });
+
+        mMediaPlayer.prepare();
+        assertFalse(mMediaPlayer.isPlaying());
+
+        mSubtitleStatus.reset();
+        selectSubtitleTrack(0);
+
+        mMediaPlayer.start();
+        assertTrue(mMediaPlayer.isPlaying());
+
+        // Waits until at least two subtitles are fired. Timeout is 2 sec.
+        // Please refer the test srt files:
+        // test_subtitle1_srt.3gp and test_subtitle2_srt.3gp
+        mSubtitleStatus.waitForSignal(2, 2000);
+        assertTrue(mSubtitleStatus.getNumSignal() >= 2);
+        mSubtitleStatus.reset();
+
+        selectSubtitleTrack(1);
+        mSubtitleStatus.waitForSignal(2, 2000);
+        assertTrue(mSubtitleStatus.getNumSignal() >= 2);
+        mSubtitleStatus.reset();
+
+        selectSubtitleTrack(2);
+        mSubtitleStatus.waitForSignal(2, 2000);
+        assertTrue(mSubtitleStatus.getNumSignal() >= 2);
+        mSubtitleStatus.reset();
+
+        selectSubtitleTrack(3);
+        mSubtitleStatus.waitForSignal(2, 2000);
+        assertTrue(mSubtitleStatus.getNumSignal() >= 2);
+        mMediaPlayer.stop();
+    }
+
     public void testCallback() throws Throwable {
         final int mp4Duration = 8484;
 
diff --git a/tests/tests/media/src/android/media/cts/MediaPlayerTestBase.java b/tests/tests/media/src/android/media/cts/MediaPlayerTestBase.java
index 8b9da47..203afc2 100644
--- a/tests/tests/media/src/android/media/cts/MediaPlayerTestBase.java
+++ b/tests/tests/media/src/android/media/cts/MediaPlayerTestBase.java
@@ -33,6 +33,7 @@
     protected static final int SLEEP_TIME = 1000;
     protected static final int LONG_SLEEP_TIME = 6000;
     protected static final int STREAM_RETRIES = 20;
+    protected static boolean sUseScaleToFitMode = false;
 
     public static class Monitor {
         private boolean signalled;
@@ -74,6 +75,7 @@
     }
 
     protected Monitor mOnVideoSizeChangedCalled = new Monitor();
+    protected Monitor mOnVideoRenderingStartCalled = new Monitor();
     protected Monitor mOnBufferingUpdateCalled = new Monitor();
     protected Monitor mOnPrepareCalled = new Monitor();
     protected Monitor mOnSeekCompleteCalled = new Monitor();
@@ -132,6 +134,25 @@
         try {
             mMediaPlayer.setDataSource(afd.getFileDescriptor(), afd.getStartOffset(),
                     afd.getLength());
+
+            // Although it is only meant for video playback, it should not
+            // cause issues for audio-only playback.
+            int videoScalingMode = sUseScaleToFitMode?
+                                    MediaPlayer.VIDEO_SCALING_MODE_SCALE_TO_FIT
+                                  : MediaPlayer.VIDEO_SCALING_MODE_SCALE_TO_FIT_WITH_CROPPING;
+
+            mMediaPlayer.setVideoScalingMode(videoScalingMode);
+        } finally {
+            afd.close();
+        }
+        sUseScaleToFitMode = !sUseScaleToFitMode;  // Alternate the scaling mode
+    }
+
+    protected void loadSubtitleSource(int resid) throws Exception {
+        AssetFileDescriptor afd = mResources.openRawResourceFd(resid);
+        try {
+            mMediaPlayer.addTimedTextSource(afd.getFileDescriptor(), afd.getStartOffset(),
+                      afd.getLength(), MediaPlayer.MEDIA_MIMETYPE_TEXT_SUBRIP);
         } finally {
             afd.close();
         }
@@ -209,6 +230,15 @@
                 return true;
             }
         });
+        mMediaPlayer.setOnInfoListener(new MediaPlayer.OnInfoListener() {
+            @Override
+            public boolean onInfo(MediaPlayer mp, int what, int extra) {
+                if (what == MediaPlayer.MEDIA_INFO_VIDEO_RENDERING_START) {
+                    mOnVideoRenderingStartCalled.signal();
+                }
+                return true;
+            }
+        });
         try {
           mMediaPlayer.prepare();
         } catch (IOException e) {
@@ -218,6 +248,7 @@
 
         mMediaPlayer.start();
         mOnVideoSizeChangedCalled.waitForSignal();
+        mOnVideoRenderingStartCalled.waitForSignal();
         mMediaPlayer.setVolume(leftVolume, rightVolume);
 
         // waiting to complete
diff --git a/tests/tests/media/src/android/media/cts/MediaRandomTest.java b/tests/tests/media/src/android/media/cts/MediaRandomTest.java
new file mode 100644
index 0000000..adee09d
--- /dev/null
+++ b/tests/tests/media/src/android/media/cts/MediaRandomTest.java
@@ -0,0 +1,347 @@
+/*
+ * 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.media.cts;
+
+
+import com.android.cts.media.R;
+
+import android.media.MediaRecorder;
+import android.media.MediaPlayer;
+import android.view.SurfaceHolder;
+import android.test.ActivityInstrumentationTestCase2;
+import android.os.Environment;
+import android.content.res.AssetFileDescriptor;
+import android.content.res.Resources;
+import android.util.Log;
+
+import java.util.Random;
+
+/**
+ * Tests for the MediaPlayer.java and MediaRecorder.java APIs
+ *
+ * These testcases make randomized calls to the public APIs available, and
+ * the focus is on whether the randomized calls can lead to crash in
+ * mediaserver process and/or ANRs.
+ *
+ * The files in res/raw used by testLocalVideo* are (c) copyright 2008,
+ * Blender Foundation / www.bigbuckbunny.org, and are licensed under the Creative Commons
+ * Attribution 3.0 License at http://creativecommons.org/licenses/by/3.0/us/.
+ */
+public class MediaRandomTest extends ActivityInstrumentationTestCase2<MediaStubActivity> {
+    private static final String TAG = "MediaRandomTest";
+
+    private static final String OUTPUT_FILE =
+                Environment.getExternalStorageDirectory().toString() + "/record.3gp";
+
+    private static final int NUMBER_OF_RECORDER_RANDOM_ACTIONS = 100000;
+    private static final int NUMBER_OF_PLAYER_RANDOM_ACTIONS   = 100000;
+
+    private MediaRecorder mRecorder;
+    private MediaPlayer mPlayer;
+    private SurfaceHolder mSurfaceHolder;
+    private Resources mResources;
+
+    // Modified across multiple threads
+    private volatile boolean mMediaServerDied;
+    private volatile int mAction;
+    private volatile int mParam;
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        getInstrumentation().waitForIdleSync();
+        mMediaServerDied = false;
+        mSurfaceHolder = getActivity().getSurfaceHolder();
+        mResources = getInstrumentation().getTargetContext().getResources();
+        try {
+            // Running this on UI thread make sure that
+            // onError callback can be received.
+            runTestOnUiThread(new Runnable() {
+                public void run() {
+                    mRecorder = new MediaRecorder();
+                    mPlayer = new MediaPlayer();
+                }
+            });
+        } catch (Throwable e) {
+            e.printStackTrace();
+            fail();
+        }
+    }
+
+    @Override
+    protected void tearDown() throws Exception {
+        if (mRecorder != null) {
+            mRecorder.release();
+            mRecorder = null;
+        }
+        if (mPlayer != null) {
+            mPlayer.release();
+            mPlayer = null;
+        }
+        super.tearDown();
+    }
+
+    /**
+     * This is a watchdog used to stop the process if it hasn't been pinged
+     * for more than specified milli-seconds. It is used like:
+     *
+     * Watchdog w = new Watchdog(10000);  // 10 seconds.
+     * w.start();       // start the watchdog.
+     * ...
+     * w.ping();
+     * ...
+     * w.ping();
+     * ...
+     * w.end();        // ask the watchdog to stop.
+     * w.join();        // join the thread.
+     */
+    class Watchdog extends Thread {
+        private final long mTimeoutMs;
+        private boolean mWatchdogStop;
+        private boolean mWatchdogPinged;
+
+        public Watchdog(long timeoutMs) {
+            mTimeoutMs = timeoutMs;
+            mWatchdogStop = false;
+            mWatchdogPinged = false;
+        }
+
+        public synchronized void run() {
+            while (true) {
+                // avoid early termination by "spurious" waitup.
+                final long startTimeMs = System.currentTimeMillis();
+                long remainingWaitTimeMs = mTimeoutMs;
+                do {
+                    try {
+                        wait(remainingWaitTimeMs);
+                    } catch (InterruptedException ex) {
+                        // ignore.
+                    }
+                    remainingWaitTimeMs = mTimeoutMs - (System.currentTimeMillis() - startTimeMs);
+                } while (remainingWaitTimeMs > 0);
+
+                if (mWatchdogStop) {
+                    break;
+                }
+
+                if (!mWatchdogPinged) {
+                    fail("Action " + mAction + " Param " + mParam
+                            + " waited over " + (mTimeoutMs - remainingWaitTimeMs) + " ms");
+                    return;
+                }
+                mWatchdogPinged = false;
+            }
+        }
+
+        public synchronized void ping() {
+            mWatchdogPinged = true;
+            this.notify();
+        }
+
+        public synchronized void end() {
+            mWatchdogStop = true;
+            this.notify();
+        }
+    }
+
+    public MediaRandomTest() {
+        super("com.android.cts.media", MediaStubActivity.class);
+    }
+
+    private void loadSource(int resid) throws Exception {
+        AssetFileDescriptor afd = mResources.openRawResourceFd(resid);
+        try {
+            mPlayer.setDataSource(afd.getFileDescriptor(), afd.getStartOffset(),
+                    afd.getLength());
+        } finally {
+            afd.close();
+        }
+    }
+
+    public void testPlayerRandomAction() throws Exception {
+        try {
+            mPlayer.setOnErrorListener(new MediaPlayer.OnErrorListener() {
+                @Override
+                public boolean onError(MediaPlayer mp, int what, int extra) {
+                    if (mPlayer == mp &&
+                        what == MediaPlayer.MEDIA_ERROR_SERVER_DIED) {
+                        Log.e(TAG, "mediaserver process died");
+                        mMediaServerDied = true;
+                    }
+                    return true;
+                }
+            });
+            loadSource(R.raw.video_480x360_mp4_h264_500kbps_30fps_aac_stereo_128kbps_44100hz);
+            mPlayer.setDisplay(mSurfaceHolder);
+            mPlayer.prepare();
+            mPlayer.start();
+
+            long seed = System.currentTimeMillis();
+            Log.v(TAG, "seed = " + seed);
+            Random r = new Random(seed);
+
+            Watchdog watchdog = new Watchdog(5000);
+            watchdog.start();
+            for (int i = 0; i < NUMBER_OF_PLAYER_RANDOM_ACTIONS; i++){
+                watchdog.ping();
+                assertTrue(!mMediaServerDied);
+
+                mAction = (int)(r.nextInt() % 12);
+                mParam = (int)(r.nextInt() % 1000000);
+                try {
+                    switch (mAction) {
+                    case 0:
+                        mPlayer.getCurrentPosition();
+                        break;
+                    case 1:
+                        mPlayer.getDuration();
+                        break;
+                    case 2:
+                        mPlayer.getVideoHeight();
+                        break;
+                    case 3:
+                        mPlayer.getVideoWidth();
+                       break;
+                    case 4:
+                        mPlayer.isPlaying();
+                        break;
+                    case 5:
+                        mPlayer.pause();
+                        break;
+                    case 6:
+                        // Don't add mPlayer.prepare() call here for two reasons:
+                        // 1. calling prepare() is a bad idea since it is a blocking call, and
+                        // 2. when prepare() is in progress, mediaserver died message will not be sent to apps
+                        mPlayer.prepareAsync();
+                        break;
+                    case 7:
+                        mPlayer.seekTo((int)(mParam));
+                        break;
+                    case 8:
+                        mPlayer.setLooping(mParam % 2 == 0);
+                        break;
+                    case 9:
+                        mPlayer.setVolume((mParam % 1000) / 500.0f,
+                                     (mParam / 1000) / 500.0f);
+                        break;
+                    case 10:
+                        mPlayer.start();
+                        break;
+                    case 11:
+                        Thread.sleep(mParam % 20);
+                        break;
+                    }
+                } catch (Exception e) {
+                }
+            }
+            mPlayer.stop();
+            watchdog.end();
+            watchdog.join();
+        } catch (Exception e) {
+            Log.v(TAG, e.toString());
+        }
+    }
+
+    public void testRecorderRandomAction() throws Exception {
+        try {
+            long seed = System.currentTimeMillis();
+            Log.v(TAG, "seed = " + seed);
+            Random r = new Random(seed);
+
+            mMediaServerDied = false;
+            mRecorder.setOnErrorListener(new MediaRecorder.OnErrorListener() {
+                @Override
+                public void onError(MediaRecorder recorder, int what, int extra) {
+                    if (mRecorder == recorder &&
+                        what == MediaRecorder.MEDIA_ERROR_SERVER_DIED) {
+                        Log.e(TAG, "mediaserver process died");
+                        mMediaServerDied = true;
+                    }
+                }
+            });
+
+            final int[] width  = {176, 352, 320, 640, 1280, 1920};
+            final int[] height = {144, 288, 240, 480,  720, 1080};
+
+            Watchdog watchdog = new Watchdog(5000);
+            watchdog.start();
+            for (int i = 0; i < NUMBER_OF_RECORDER_RANDOM_ACTIONS; i++) {
+                watchdog.ping();
+                assertTrue(!mMediaServerDied);
+
+                mAction = (int)(r.nextInt(14));
+                mParam = (int)(r.nextInt(1000000));
+                try {
+                    switch (mAction) {
+                    case 0:
+                        mRecorder.setAudioSource(mParam % 3);
+                        break;
+                    case 1:
+                        // XXX:
+                        // Fix gralloc source and change
+                        // mRecorder.setVideoSource(mParam % 3);
+                        mRecorder.setVideoSource(mParam % 2);
+                        break;
+                    case 2:
+                        mRecorder.setOutputFormat(mParam % 5);
+                        break;
+                    case 3:
+                        mRecorder.setAudioEncoder(mParam % 3);
+                        break;
+                    case 4:
+                        mRecorder.setVideoEncoder(mParam % 5);
+                        break;
+                    case 5:
+                        mRecorder.setPreviewDisplay(mSurfaceHolder.getSurface());
+                        break;
+                    case 6:
+                        int index = mParam % width.length;
+                        mRecorder.setVideoSize(width[index], height[index]);
+                        break;
+                    case 7:
+                        mRecorder.setVideoFrameRate(mParam % 40 - 5);
+                        break;
+                    case 8:
+                        mRecorder.setOutputFile(OUTPUT_FILE);
+                        break;
+                    case 9:
+                        mRecorder.prepare();
+                        break;
+                    case 10:
+                        mRecorder.start();
+                        break;
+                    case 11:
+                        Thread.sleep(mParam % 20);
+                        break;
+                    case 12:
+                        mRecorder.stop();
+                        break;
+                    case 13:
+                        mRecorder.reset();
+                        break;
+                    default:
+                        break;
+                    }
+                } catch (Exception e) {
+                }
+            }
+            watchdog.end();
+            watchdog.join();
+        } catch (Exception e) {
+            Log.v(TAG, e.toString());
+        }
+    }
+}
diff --git a/tests/tests/media/src/android/media/cts/MediaRecorderTest.java b/tests/tests/media/src/android/media/cts/MediaRecorderTest.java
index 55be9ac..f31f552 100644
--- a/tests/tests/media/src/android/media/cts/MediaRecorderTest.java
+++ b/tests/tests/media/src/android/media/cts/MediaRecorderTest.java
@@ -18,11 +18,13 @@
 
 import android.content.pm.PackageManager;
 import android.hardware.Camera;
+import android.media.MediaMetadataRetriever;
 import android.media.MediaRecorder;
 import android.media.MediaRecorder.OnErrorListener;
 import android.media.MediaRecorder.OnInfoListener;
 import android.media.MediaMetadataRetriever;
 import android.os.Environment;
+import android.os.ConditionVariable;
 import android.test.ActivityInstrumentationTestCase2;
 import android.test.UiThreadTest;
 import android.view.Surface;
@@ -43,6 +45,7 @@
     private final String OUTPUT_PATH2;
     private static final float TOLERANCE = 0.0002f;
     private static final int RECORD_TIME = 3000;
+    private static final int THREE_MINUTES = 180000;
     private static final int VIDEO_WIDTH = 176;
     private static final int VIDEO_HEIGHT = 144;
     private static final int VIDEO_BIT_RATE_IN_BPS = 128000;
@@ -62,6 +65,8 @@
     private MediaStubActivity mActivity = null;
 
     private MediaRecorder mMediaRecorder;
+    private ConditionVariable mMaxDurationCond;
+    private ConditionVariable mMaxFileSizeCond;
 
     public MediaRecorderTest() {
         super("com.android.cts.media", MediaStubActivity.class);
@@ -97,10 +102,23 @@
                 mMediaRecorder = new MediaRecorder();
                 mOutFile = new File(OUTPUT_PATH);
                 mOutFile2 = new File(OUTPUT_PATH2);
+
+                mMaxDurationCond = new ConditionVariable();
+                mMaxFileSizeCond = new ConditionVariable();
+
                 mMediaRecorder.setOutputFile(OUTPUT_PATH);
                 mMediaRecorder.setOnInfoListener(new OnInfoListener() {
                     public void onInfo(MediaRecorder mr, int what, int extra) {
                         mOnInfoCalled = true;
+                        if (what ==
+                            MediaRecorder.MEDIA_RECORDER_INFO_MAX_DURATION_REACHED) {
+                            Log.v(TAG, "max duration reached");
+                            mMaxDurationCond.open();
+                        } else if (what ==
+                            MediaRecorder.MEDIA_RECORDER_INFO_MAX_FILESIZE_REACHED) {
+                            Log.v(TAG, "max file size reached");
+                            mMaxFileSizeCond.open();
+                        }
                     }
                 });
                 mMediaRecorder.setOnErrorListener(new OnErrorListener() {
@@ -127,6 +145,10 @@
             mCamera.release();
             mCamera = null;
         }
+        mMaxDurationCond.close();
+        mMaxDurationCond = null;
+        mMaxFileSizeCond.close();
+        mMaxFileSizeCond = null;
         mActivity = null;
         super.tearDown();
     }
@@ -352,30 +374,74 @@
         if (!hasMicrophone()) {
             return;
         }
+        testSetMaxDuration(20000, 1000);
+    }
+
+    private void testSetMaxDuration(long durationMs, long toleranceMs) throws Exception {
         mMediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
         mMediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
-        mMediaRecorder.setMaxDuration(0);
+        mMediaRecorder.setMaxDuration((int)durationMs);
         mMediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
         mMediaRecorder.prepare();
         mMediaRecorder.start();
-        Thread.sleep(RECORD_TIME * 30);
+        long startTimeMs = System.currentTimeMillis();
+        if (!mMaxDurationCond.block(durationMs + toleranceMs)) {
+            fail("timed out waiting for MEDIA_RECORDER_INFO_MAX_DURATION_REACHED");
+        }
+        long endTimeMs = System.currentTimeMillis();
+        long actualDurationMs = endTimeMs - startTimeMs;
         mMediaRecorder.stop();
-        checkOutputExist();
+        checkRecordedTime(durationMs, actualDurationMs, toleranceMs);
+    }
+
+    private void checkRecordedTime(long expectedMs, long actualMs, long tolerance) {
+        assertEquals(expectedMs, actualMs, tolerance);
+        long actualFileDurationMs = getRecordedFileDurationMs(OUTPUT_PATH);
+        assertEquals(actualFileDurationMs, actualMs, tolerance);
+    }
+
+    private int getRecordedFileDurationMs(final String fileName) {
+        MediaMetadataRetriever retriever = new MediaMetadataRetriever();
+        retriever.setDataSource(fileName);
+        String durationStr = retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_DURATION);
+        assertNotNull(durationStr);
+        return Integer.parseInt(durationStr);
     }
 
     public void testSetMaxFileSize() throws Exception {
         if (!hasMicrophone()) {
             return;
         }
+        testSetMaxFileSize(512 * 1024, 50 * 1024);
+    }
+
+    private void testSetMaxFileSize(
+            long fileSize, long tolerance) throws Exception {
         mMediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
+        mMediaRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA);
         mMediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
         mMediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
-        mMediaRecorder.setMaxFileSize(0);
+        mMediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.H264);
+        mMediaRecorder.setVideoSize(VIDEO_WIDTH, VIDEO_HEIGHT);
+        mMediaRecorder.setVideoEncodingBitRate(256000);
+        mMediaRecorder.setPreviewDisplay(mActivity.getSurfaceHolder().getSurface());
+        mMediaRecorder.setMaxFileSize(fileSize);
         mMediaRecorder.prepare();
         mMediaRecorder.start();
-        Thread.sleep(RECORD_TIME * 30);
+
+        // Recording a scene with moving objects would greatly help reduce
+        // the time for waiting.
+        if (!mMaxFileSizeCond.block(THREE_MINUTES)) {
+            fail("timed out waiting for MEDIA_RECORDER_INFO_MAX_FILESIZE_REACHED");
+        }
         mMediaRecorder.stop();
-        checkOutputExist();
+        checkOutputFileSize(OUTPUT_PATH, fileSize, tolerance);
+    }
+
+    private void checkOutputFileSize(final String fileName, long fileSize, long tolerance) {
+        assertTrue(mOutFile.exists());
+        assertEquals(fileSize, mOutFile.length(), tolerance);
+        assertTrue(mOutFile.delete());
     }
 
     public void testOnErrorListener() throws Exception {
diff --git a/tests/tests/net/src/android/net/cts/NetworkInfo_DetailedStateTest.java b/tests/tests/net/src/android/net/cts/NetworkInfo_DetailedStateTest.java
index b8d0ea4..590ce89 100644
--- a/tests/tests/net/src/android/net/cts/NetworkInfo_DetailedStateTest.java
+++ b/tests/tests/net/src/android/net/cts/NetworkInfo_DetailedStateTest.java
@@ -37,7 +37,7 @@
 
     public void testValues() {
         DetailedState[] expected = DetailedState.values();
-        assertEquals(12, expected.length);
+        assertEquals(13, expected.length);
         assertEquals(DetailedState.IDLE, expected[0]);
         assertEquals(DetailedState.SCANNING, expected[1]);
         assertEquals(DetailedState.CONNECTING, expected[2]);
@@ -50,6 +50,7 @@
         assertEquals(DetailedState.FAILED, expected[9]);
         assertEquals(DetailedState.BLOCKED, expected[10]);
         assertEquals(DetailedState.VERIFYING_POOR_LINK, expected[11]);
+        assertEquals(DetailedState.CAPTIVE_PORTAL_CHECK, expected[12]);
     }
 
 }
diff --git a/tests/tests/net/src/android/net/wifi/cts/ScanResultTest.java b/tests/tests/net/src/android/net/wifi/cts/ScanResultTest.java
index 26cfff83..c9b82ee 100644
--- a/tests/tests/net/src/android/net/wifi/cts/ScanResultTest.java
+++ b/tests/tests/net/src/android/net/wifi/cts/ScanResultTest.java
@@ -26,6 +26,7 @@
 import android.net.wifi.WifiManager;
 import android.net.wifi.WifiManager.WifiLock;
 import android.test.AndroidTestCase;
+import android.util.Log;
 
 public class ScanResultTest extends AndroidTestCase {
     private static class MySync {
@@ -39,11 +40,14 @@
     private static final int STATE_NULL = 0;
     private static final int STATE_WIFI_CHANGING = 1;
     private static final int STATE_WIFI_CHANGED = 2;
+    private static final int STATE_START_SCAN = 3;
+    private static final int STATE_SCAN_RESULTS_AVAILABLE = 4;
 
     private static final String TAG = "WifiInfoTest";
     private static final int TIMEOUT_MSEC = 6000;
     private static final int WAIT_MSEC = 60;
-    private static final int DURATION = 10000;
+    private static final int ENABLE_WAIT_MSEC = 10000;
+    private static final int SCAN_WAIT_MSEC = 10000;
     private IntentFilter mIntentFilter;
     private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
         @Override
@@ -54,6 +58,11 @@
                     mMySync.expectedState = STATE_WIFI_CHANGED;
                     mMySync.notify();
                 }
+            } else if (action.equals(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION)) {
+                synchronized (mMySync) {
+                    mMySync.expectedState = STATE_SCAN_RESULTS_AVAILABLE;
+                    mMySync.notify();
+                }
             }
         }
     };
@@ -83,7 +92,7 @@
         mWifiLock.acquire();
         if (!mWifiManager.isWifiEnabled())
             setWifiEnabled(true);
-        Thread.sleep(DURATION);
+        Thread.sleep(ENABLE_WAIT_MSEC);
         assertTrue(mWifiManager.isWifiEnabled());
         mMySync.expectedState = STATE_NULL;
     }
@@ -99,7 +108,7 @@
         mContext.unregisterReceiver(mReceiver);
         if (!mWifiManager.isWifiEnabled())
             setWifiEnabled(true);
-        Thread.sleep(DURATION);
+        Thread.sleep(ENABLE_WAIT_MSEC);
         super.tearDown();
     }
 
@@ -107,11 +116,15 @@
         synchronized (mMySync) {
             mMySync.expectedState = STATE_WIFI_CHANGING;
             assertTrue(mWifiManager.setWifiEnabled(enable));
-            long timeout = System.currentTimeMillis() + TIMEOUT_MSEC;
-            while (System.currentTimeMillis() < timeout
-                    && mMySync.expectedState == STATE_WIFI_CHANGING)
-                mMySync.wait(WAIT_MSEC);
-        }
+            waitForBroadcast(TIMEOUT_MSEC, STATE_WIFI_CHANGED);
+       }
+    }
+
+    private void waitForBroadcast(long timeout, int expectedState) throws Exception {
+        long waitTime = System.currentTimeMillis() + timeout;
+        while (System.currentTimeMillis() < waitTime
+                && mMySync.expectedState != expectedState)
+            mMySync.wait(WAIT_MSEC);
     }
 
     public void testScanResultProperties() {
@@ -127,4 +140,49 @@
         }
     }
 
+    private void scanAndWait() throws Exception {
+        synchronized (mMySync) {
+            mMySync.expectedState = STATE_START_SCAN;
+            mWifiManager.startScan();
+            waitForBroadcast(SCAN_WAIT_MSEC, STATE_SCAN_RESULTS_AVAILABLE);
+        }
+   }
+
+    public void testScanResultTimeStamp() throws Exception {
+        if (!WifiFeature.isWifiSupported(getContext())) {
+            // skip the test if WiFi is not supported
+            return;
+        }
+
+        long timestamp = 0;
+        String BSSID = null;
+
+        /* Multiple scans to ensure bssid is updated */
+        scanAndWait();
+        scanAndWait();
+        scanAndWait();
+
+        List<ScanResult> scanResults = mWifiManager.getScanResults();
+        for (ScanResult result : scanResults) {
+            BSSID = result.BSSID;
+            timestamp = result.timestamp;
+            assertTrue(timestamp != 0);
+            break;
+        }
+
+        scanAndWait();
+        scanAndWait();
+        scanAndWait();
+
+        scanResults = mWifiManager.getScanResults();
+        for (ScanResult result : scanResults) {
+            if (result.BSSID.equals(BSSID)) {
+                long timeDiff = (result.timestamp - timestamp) / 1000;
+                assertTrue (timeDiff > 0);
+                assertTrue (timeDiff < 6 * SCAN_WAIT_MSEC);
+            }
+        }
+
+    }
+
 }
diff --git a/tests/tests/net/src/android/net/wifi/cts/WifiManagerTest.java b/tests/tests/net/src/android/net/wifi/cts/WifiManagerTest.java
index 5fc23e7..a64477d 100644
--- a/tests/tests/net/src/android/net/wifi/cts/WifiManagerTest.java
+++ b/tests/tests/net/src/android/net/wifi/cts/WifiManagerTest.java
@@ -21,17 +21,22 @@
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentFilter;
+import android.net.NetworkInfo;
 import android.net.wifi.ScanResult;
 import android.net.wifi.WifiConfiguration;
-import android.net.wifi.WifiManager;
 import android.net.wifi.WifiConfiguration.Status;
+import android.net.wifi.WifiManager;
+import android.net.wifi.WifiManager.TxPacketCountListener;
 import android.net.wifi.WifiManager.WifiLock;
 import android.test.AndroidTestCase;
 import android.util.Log;
 
+import java.net.HttpURLConnection;
+import java.net.URL;
 import java.util.HashSet;
 import java.util.List;
 import java.util.Set;
+import java.util.concurrent.atomic.AtomicInteger;
 
 public class WifiManagerTest extends AndroidTestCase {
     private static class MySync {
@@ -42,6 +47,7 @@
     private WifiLock mWifiLock;
     private static MySync mMySync;
     private List<ScanResult> mScanResult = null;
+    private NetworkInfo mNetworkInfo;
 
     // Please refer to WifiManager
     private static final int MIN_RSSI = -100;
@@ -78,6 +84,13 @@
                     mMySync.expectedState = STATE_WIFI_CHANGED;
                     mMySync.notify();
                 }
+            } else if (action.equals(WifiManager.NETWORK_STATE_CHANGED_ACTION)) {
+                synchronized (mMySync) {
+                    mNetworkInfo =
+                            (NetworkInfo) intent.getParcelableExtra(WifiManager.EXTRA_NETWORK_INFO);
+                    if (mNetworkInfo.getState() == NetworkInfo.State.CONNECTED)
+                        mMySync.notify();
+                }
             }
         }
     };
@@ -148,6 +161,18 @@
         }
     }
 
+    private void connectWifi() throws Exception {
+        synchronized (mMySync) {
+            if (mNetworkInfo.getState() == NetworkInfo.State.CONNECTED) return;
+            assertTrue(mWifiManager.reconnect());
+            long timeout = System.currentTimeMillis() + TIMEOUT_MSEC;
+            while (System.currentTimeMillis() < timeout
+                    && mNetworkInfo.getState() != NetworkInfo.State.CONNECTED)
+                mMySync.wait(WAIT_MSEC);
+            assertTrue(mNetworkInfo.getState() == NetworkInfo.State.CONNECTED);
+        }
+    }
+
     private boolean existSSID(String ssid) {
         for (final WifiConfiguration w : mWifiManager.getConfiguredNetworks()) {
             if (w.SSID.equals(ssid))
@@ -339,4 +364,65 @@
         rssiB = 4;
         assertTrue(WifiManager.compareSignalLevel(rssiA, rssiB) > 0);
     }
+
+    private int getTxPacketCount() throws Exception {
+        final AtomicInteger ret = new AtomicInteger(-1);
+
+        mWifiManager.getTxPacketCount(new TxPacketCountListener() {
+            @Override
+            public void onSuccess(int count) {
+                ret.set(count);
+            }
+            @Override
+            public void onFailure(int reason) {
+                ret.set(0);
+            }
+        });
+
+        long timeout = System.currentTimeMillis() + TIMEOUT_MSEC;
+        while (ret.get() < 0 && System.currentTimeMillis() < timeout)
+            Thread.sleep(WAIT_MSEC);
+        assertTrue(ret.get() >= 0);
+        return ret.get();
+    }
+
+    /**
+     * The new WiFi watchdog requires kernel/driver to export some packet loss
+     * counters. This CTS tests whether those counters are correctly exported.
+     * To pass this CTS test, a connected WiFi link is required.
+     */
+    public void testWifiWatchdog() throws Exception {
+        // Make sure WiFi is enabled
+        if (!mWifiManager.isWifiEnabled()) {
+            setWifiEnabled(true);
+            Thread.sleep(DURATION);
+        }
+        assertTrue(mWifiManager.isWifiEnabled());
+
+        // Wait for a WiFi connection
+        connectWifi();
+
+        // Read TX packet counter
+        int txcount1 = getTxPacketCount();
+
+        // Do some network operations
+        HttpURLConnection connection = null;
+        try {
+            URL url = new URL("http://www.google.com/");
+            connection = (HttpURLConnection) url.openConnection();
+            connection.setInstanceFollowRedirects(false);
+            connection.setConnectTimeout(TIMEOUT_MSEC);
+            connection.setReadTimeout(TIMEOUT_MSEC);
+            connection.setUseCaches(false);
+            connection.getInputStream();
+        } catch (Exception e) {
+            // ignore
+        } finally {
+            if (connection != null) connection.disconnect();
+        }
+
+        // Read TX packet counter again and make sure it increases
+        int txcount2 = getTxPacketCount();
+        assertTrue(txcount2 > txcount1);
+    }
 }
diff --git a/tests/tests/opengl/Android.mk b/tests/tests/opengl/Android.mk
index 0610c5f..98f11e9 100644
--- a/tests/tests/opengl/Android.mk
+++ b/tests/tests/opengl/Android.mk
@@ -27,9 +27,9 @@
 # All tests should include android.test.runner.
 LOCAL_JAVA_LIBRARIES := android.test.runner
 
-LOCAL_STATIC_JAVA_LIBRARIES := ctstestrunner
+LOCAL_JNI_SHARED_LIBRARIES := libopengltest_jni
 
-LOCAL_JNI_SHARED_LIBRARIES := libopengltest
+LOCAL_STATIC_JAVA_LIBRARIES := ctstestrunner
 
 LOCAL_SRC_FILES := $(call all-java-files-under, src)
 
diff --git a/tests/tests/opengl/AndroidManifest.xml b/tests/tests/opengl/AndroidManifest.xml
index 4619512..266216f 100644
--- a/tests/tests/opengl/AndroidManifest.xml
+++ b/tests/tests/opengl/AndroidManifest.xml
@@ -31,15 +31,17 @@
          <activity
             android:label="@string/app_name"
             android:name="android.opengl.cts.OpenGLES20ActivityOne">
-            <intent-filter>
-                <action android:name="android.intent.action.MAIN" />
-
-                <category android:name="android.intent.category.LAUNCHER" />
-            </intent-filter>
+         </activity>
+          <activity
+            android:label="@string/app_name"
+            android:name="android.opengl.cts.OpenGLES20ActivityTwo">
          </activity> 
          <uses-library  android:name="android.test.runner" />
          <activity
-            android:name="android.opengl.cts.OpenGLES20NativeActivity"
+            android:name="android.opengl.cts.OpenGLES20NativeActivityOne"
+            android:label="@string/app_name" />
+         <activity
+            android:name="android.opengl.cts.OpenGLES20NativeActivityTwo"
             android:label="@string/app_name" />
     </application>
 
diff --git a/tests/tests/opengl/libopengltest/Android.mk b/tests/tests/opengl/libopengltest/Android.mk
index a54816e..a141550 100755
--- a/tests/tests/opengl/libopengltest/Android.mk
+++ b/tests/tests/opengl/libopengltest/Android.mk
@@ -17,7 +17,7 @@
 #
 LOCAL_PATH := $(call my-dir)
 include $(CLEAR_VARS)
-LOCAL_MODULE := libopengltest
+LOCAL_MODULE := libopengltest_jni
 LOCAL_MODULE_TAGS := optional
 LOCAL_SRC_FILES := common.cpp \
                    gl2_jni_libone.cpp \
@@ -27,6 +27,12 @@
                    attach_shader_four.cpp \
                    attach_shader_five.cpp \
                    attach_shader_six.cpp \
+                   attach_shader_seven.cpp \
+                   attach_shader_eight.cpp \
+                   attach_shader_nine.cpp \
+                   attach_shader_ten.cpp \
+                   attach_shader_eleven.cpp \
+                   color_one.cpp
 
 LOCAL_C_INCLUDES := $(JNI_H_INCLUDE)
 
diff --git a/tests/tests/opengl/libopengltest/attach_shader_eight.cpp b/tests/tests/opengl/libopengltest/attach_shader_eight.cpp
new file mode 100755
index 0000000..180399b
--- /dev/null
+++ b/tests/tests/opengl/libopengltest/attach_shader_eight.cpp
@@ -0,0 +1,36 @@
+/*
+ * 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.
+ */
+#include <GLES2/gl2.h>
+#include <GLES2/gl2ext.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include "attach_shader_eight.h"
+
+#define  LOG_TAG    "attach_shader_eight"
+#define  LOGI(...)  __android_log_print(ANDROID_LOG_INFO,LOG_TAG,__VA_ARGS__)
+
+Data attachShaderEight(){
+    GLuint fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
+
+    GLuint program = glCreateProgram();
+    glAttachShader(program, fragmentShader);
+
+    GLint error = glGetError();
+    Data data = {error, -9 , -1};
+    glDeleteShader(fragmentShader);
+    glDeleteProgram(program);
+    return data;
+}
diff --git a/tests/tests/opengl/libopengltest/attach_shader_eight.h b/tests/tests/opengl/libopengltest/attach_shader_eight.h
new file mode 100755
index 0000000..2f317e2
--- /dev/null
+++ b/tests/tests/opengl/libopengltest/attach_shader_eight.h
@@ -0,0 +1,30 @@
+/*
+ * 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 _ATTACH_SHADER_EIGHT_H_
+#define _ATTACH_SHADER_EIGHT_H_
+
+#include <GLES2/gl2.h>
+#include <GLES2/gl2ext.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <android/log.h>
+#include "types.h"
+
+Data attachShaderEight();
+
+#endif
+
diff --git a/tests/tests/opengl/libopengltest/attach_shader_eleven.cpp b/tests/tests/opengl/libopengltest/attach_shader_eleven.cpp
new file mode 100755
index 0000000..597de83
--- /dev/null
+++ b/tests/tests/opengl/libopengltest/attach_shader_eleven.cpp
@@ -0,0 +1,46 @@
+/*
+ * 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.
+ */
+#include <GLES2/gl2.h>
+#include <GLES2/gl2ext.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include "attach_shader_eleven.h"
+#include "common.h"
+#include "vertex.h"
+
+#define  LOG_TAG    "attach_shader_eleven"
+#define  LOGI(...)  __android_log_print(ANDROID_LOG_INFO,LOG_TAG,__VA_ARGS__)
+
+Data attachShaderEleven(){
+    GLuint vertexShader = loadShader(GL_VERTEX_SHADER, attach_shader_successful_complile_vertex);
+    GLuint program = glCreateProgram();
+    glAttachShader(program, vertexShader);
+
+    GLsizei maxCount = 10;
+    GLsizei count;
+    GLuint shaders[maxCount];
+
+    glGetAttachedShaders(program, maxCount,
+         &count,
+         shaders);
+    LOGI("Attached Shader First element :  %d\n", *shaders);
+    LOGI("ShaderCount %d\n", count);
+    GLint error = glGetError();
+    Data data = {error, count, -1};
+
+    glDeleteProgram(program);
+    return data;
+}
diff --git a/tests/tests/opengl/libopengltest/attach_shader_eleven.h b/tests/tests/opengl/libopengltest/attach_shader_eleven.h
new file mode 100755
index 0000000..5cb39c1
--- /dev/null
+++ b/tests/tests/opengl/libopengltest/attach_shader_eleven.h
@@ -0,0 +1,29 @@
+/*
+ * 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.
+ */
+#include <GLES2/gl2.h>
+#include <GLES2/gl2ext.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <android/log.h>
+#include "types.h"
+
+#ifndef _ATTACH_SHADER_ELEVEN_H_
+#define _ATTACH_SHADER_ELEVEN_H_
+
+Data attachShaderEleven();
+
+#endif
+
diff --git a/tests/tests/opengl/libopengltest/attach_shader_nine.cpp b/tests/tests/opengl/libopengltest/attach_shader_nine.cpp
new file mode 100755
index 0000000..154c351
--- /dev/null
+++ b/tests/tests/opengl/libopengltest/attach_shader_nine.cpp
@@ -0,0 +1,35 @@
+/*
+ * 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.
+ */
+#include <GLES2/gl2.h>
+#include <GLES2/gl2ext.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include "attach_shader_nine.h"
+
+#define  LOG_TAG    "attach_shader_nine"
+#define  LOGI(...)  __android_log_print(ANDROID_LOG_INFO,LOG_TAG,__VA_ARGS__)
+
+Data attachShaderNine(){
+    GLuint fragmentShader = 0;
+    GLuint program = glCreateProgram();
+    glAttachShader(program, fragmentShader);
+
+    GLint error = glGetError();
+    Data data = {error, -9, -1};
+    glDeleteShader(fragmentShader);
+    glDeleteProgram(program);
+    return data;
+}
diff --git a/tests/tests/opengl/libopengltest/attach_shader_nine.h b/tests/tests/opengl/libopengltest/attach_shader_nine.h
new file mode 100755
index 0000000..e2ea44f
--- /dev/null
+++ b/tests/tests/opengl/libopengltest/attach_shader_nine.h
@@ -0,0 +1,30 @@
+/*
+ * 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 _ATTACH_SHADER_NINE_H_
+#define _ATTACH_SHADER_NINE_H_
+
+#include <GLES2/gl2.h>
+#include <GLES2/gl2ext.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <android/log.h>
+#include "types.h"
+
+Data attachShaderNine();
+
+#endif
+
diff --git a/tests/tests/opengl/libopengltest/attach_shader_seven.cpp b/tests/tests/opengl/libopengltest/attach_shader_seven.cpp
new file mode 100755
index 0000000..f7e9c47
--- /dev/null
+++ b/tests/tests/opengl/libopengltest/attach_shader_seven.cpp
@@ -0,0 +1,40 @@
+/*
+ * 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.
+ */
+#include <GLES2/gl2.h>
+#include <GLES2/gl2ext.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include "attach_shader_seven.h"
+
+#define  LOG_TAG    "attach_shader_seven"
+#define  LOGI(...)  __android_log_print(ANDROID_LOG_INFO,LOG_TAG,__VA_ARGS__)
+
+Data attachShaderSeven(){
+    GLuint vertexShaderOne = glCreateShader(GL_VERTEX_SHADER);
+    GLuint vertexShaderTwo = glCreateShader(GL_VERTEX_SHADER);
+
+    GLuint program = glCreateProgram();
+    glAttachShader(program, vertexShaderOne);
+    glAttachShader(program, vertexShaderTwo);
+
+
+    GLint error = glGetError();
+    Data data = {error, -9 , -1};
+    glDeleteShader(vertexShaderOne);
+    glDeleteShader(vertexShaderTwo);
+    glDeleteProgram(program);
+    return data;
+}
diff --git a/tests/tests/opengl/libopengltest/attach_shader_seven.h b/tests/tests/opengl/libopengltest/attach_shader_seven.h
new file mode 100755
index 0000000..b13ac55
--- /dev/null
+++ b/tests/tests/opengl/libopengltest/attach_shader_seven.h
@@ -0,0 +1,30 @@
+/*
+ * 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 _ATTACH_SHADER_SEVEN_H_
+#define _ATTACH_SHADER_SEVEN_H_
+
+#include <GLES2/gl2.h>
+#include <GLES2/gl2ext.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <android/log.h>
+#include "types.h"
+
+Data attachShaderSeven();
+
+#endif
+
diff --git a/tests/tests/opengl/libopengltest/attach_shader_ten.cpp b/tests/tests/opengl/libopengltest/attach_shader_ten.cpp
new file mode 100755
index 0000000..3bc197e
--- /dev/null
+++ b/tests/tests/opengl/libopengltest/attach_shader_ten.cpp
@@ -0,0 +1,45 @@
+/*
+ * 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.
+ */
+#include <GLES2/gl2.h>
+#include <GLES2/gl2ext.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include "attach_shader_ten.h"
+#include "common.h"
+#include "shader.h"
+#define  LOG_TAG    "attach_shader_ten"
+#define  LOGI(...)  __android_log_print(ANDROID_LOG_INFO,LOG_TAG,__VA_ARGS__)
+
+Data attachShaderTen(){
+    GLuint fragmentShader = loadShader(GL_FRAGMENT_SHADER, attach_shader_successful_complile_shader);
+    GLuint program = glCreateProgram();
+    glAttachShader(program, fragmentShader);
+
+    GLsizei maxCount = 10;
+    GLsizei count;
+    GLuint shaders[maxCount];
+
+    glGetAttachedShaders(program, maxCount,
+         &count,
+         shaders);
+    LOGI("Attached Shader First element :  %d\n", *shaders);
+    LOGI("ShaderCount %d\n", count);
+    GLint error = glGetError();
+    Data data = {error, count, -1};
+    glDeleteShader(fragmentShader);
+    glDeleteProgram(program);
+    return data;
+}
diff --git a/tests/tests/opengl/libopengltest/attach_shader_ten.h b/tests/tests/opengl/libopengltest/attach_shader_ten.h
new file mode 100755
index 0000000..9bb8d0b
--- /dev/null
+++ b/tests/tests/opengl/libopengltest/attach_shader_ten.h
@@ -0,0 +1,29 @@
+/*
+ * 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.
+ */
+#include <GLES2/gl2.h>
+#include <GLES2/gl2ext.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <android/log.h>
+#include "types.h"
+
+#ifndef _ATTACH_SHADER_TEN_H_
+#define _ATTACH_SHADER_TEN_H_
+
+Data attachShaderTen();
+
+#endif
+
diff --git a/tests/tests/opengl/libopengltest/color_one.cpp b/tests/tests/opengl/libopengltest/color_one.cpp
new file mode 100755
index 0000000..27d400c
--- /dev/null
+++ b/tests/tests/opengl/libopengltest/color_one.cpp
@@ -0,0 +1,130 @@
+/*
+ * 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.
+ */
+#include <GLES2/gl2.h>
+#include <GLES2/gl2ext.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include "color_one.h"
+#include "common.h"
+#include "vertex.h"
+#include "shader.h"
+
+#define  LOG_TAG    "color_one"
+#define  LOGI(...)  __android_log_print(ANDROID_LOG_INFO,LOG_TAG,__VA_ARGS__)
+#define  LOGE(...)  __android_log_print(ANDROID_LOG_ERROR,LOG_TAG,__VA_ARGS__)
+
+static const GLfloat gTriangleVertices[] = { 0.0f, 0.5f, -0.5f, -0.5f,
+        0.5f, -0.5f };
+GLuint gProgram;
+GLuint gvPositionHandle;
+GLuint gvColorHandle;
+int width;
+int height;
+
+float dataFloat[4];
+void initColorOne(int w, int h){
+    GLuint vertexShader = loadShader(GL_VERTEX_SHADER, color_one_vertex_shader_one);
+    GLuint fragmentShader = loadShader(GL_FRAGMENT_SHADER, color_one_fragment_shader_one);
+    gProgram = glCreateProgram();
+    LOGI("Program %d\n", gProgram);
+    width = w;
+    height = h;
+    glAttachShader(gProgram, vertexShader);
+    checkGlError("glAttachShader");
+    glAttachShader(gProgram, fragmentShader);
+    checkGlError("glAttachShader");
+    glBindAttribLocation(gProgram, 0, "vPosition");
+    glBindAttribLocation(gProgram, 1, "vColor");
+    glLinkProgram(gProgram);
+    GLint linkStatus = GL_FALSE;
+    glGetProgramiv(gProgram, GL_LINK_STATUS, &linkStatus);
+    if (linkStatus != GL_TRUE) {
+        GLint bufLength = 0;
+        glGetProgramiv(gProgram, GL_INFO_LOG_LENGTH, &bufLength);
+        if (bufLength) {
+            char* buf = (char*) malloc(bufLength);
+            if (buf) {
+                glGetProgramInfoLog(gProgram, bufLength, NULL, buf);
+                LOGE("Could not link program:\n%s\n", buf);
+                free(buf);
+             }
+        }
+    }
+    LOGI("w %d, h %d\n",w, h);
+    glViewport(0, 0, w, h);
+
+    checkGlError("glViewport");
+    gvPositionHandle = glGetAttribLocation(gProgram, "vPosition");
+    gvColorHandle = glGetAttribLocation(gProgram, "vColor");
+    GLsizei maxCount = 10;
+    GLsizei count;
+    GLuint shaders[maxCount];
+
+    glGetAttachedShaders(gProgram, maxCount,
+         &count,
+         shaders);
+    LOGI("Attached Shader First element :  %d\n", *shaders);
+    LOGI("ShaderCount %d\n", count);
+    GLint error = glGetError();
+    return;
+}
+
+float* drawColorOne(float mColor[]){
+     LOGI("drawColorOne start");
+    static float grey;
+    grey = 0.01f;
+
+    glClearColor(grey, grey, grey, 1.0f);
+    checkGlError("glClearColor");
+    glClear( GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
+    checkGlError("glClear");
+
+    glUseProgram(gProgram);
+    checkGlError("glUseProgram");
+
+    glVertexAttribPointer(gvPositionHandle, 2, GL_FLOAT, GL_FALSE, 0, gTriangleVertices);
+    checkGlError("glVertexAttribPointer");
+    glEnableVertexAttribArray(0);
+    checkGlError("glEnableVertexAttribArray");
+
+    glVertexAttribPointer(gvColorHandle,4, GL_FLOAT, GL_FALSE, 0, mColor);
+    checkGlError("glVertexAttribPointer");
+    glEnableVertexAttribArray(1);
+    checkGlError("glEnableVertexAttribArray");
+
+    glDrawArrays(GL_TRIANGLES, 0, 3);
+    checkGlError("glDrawArrays");
+    GLubyte data[4*1];
+
+
+    glReadPixels(width/2, height/2, 1,1, GL_RGBA, GL_UNSIGNED_BYTE, (GLvoid*)&data);
+    for(int i = 0; i < sizeof(data); i++){
+        dataFloat[i] = data[i];
+    }
+
+    return dataFloat;
+}
+
+void deleteColorOne() {
+     glDeleteProgram(gProgram);
+}
+
+static void checkGlError(const char* op) {
+    for (GLint error = glGetError(); error; error
+            = glGetError()) {
+        LOGI("after %s() glError (0x%x)\n", op, error);
+    }
+}
diff --git a/tests/tests/opengl/libopengltest/color_one.h b/tests/tests/opengl/libopengltest/color_one.h
new file mode 100755
index 0000000..21dd9fd
--- /dev/null
+++ b/tests/tests/opengl/libopengltest/color_one.h
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef _COLOR_ONE_H_
+#define _COLOR_ONE_H_
+
+#include <GLES2/gl2.h>
+#include <GLES2/gl2ext.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <android/log.h>
+#include "types.h"
+
+void initColorOne(int w,int h);
+float* drawColorOne(float color[]);
+
+static void checkGlError(const char* op);
+
+#endif
+
diff --git a/tests/tests/opengl/libopengltest/gl2_jni_libone.cpp b/tests/tests/opengl/libopengltest/gl2_jni_libone.cpp
index 9433702..fe49b1b 100755
--- a/tests/tests/opengl/libopengltest/gl2_jni_libone.cpp
+++ b/tests/tests/opengl/libopengltest/gl2_jni_libone.cpp
@@ -14,7 +14,6 @@
  * limitations under the License.
  */
 
-
 #include <jni.h>
 #include <android/log.h>
 
@@ -24,12 +23,19 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <math.h>
+
 #include "attach_shader_one.h"
 #include "attach_shader_two.h"
 #include "attach_shader_three.h"
 #include "attach_shader_four.h"
 #include "attach_shader_five.h"
 #include "attach_shader_six.h"
+#include "attach_shader_seven.h"
+#include "attach_shader_eight.h"
+#include "attach_shader_nine.h"
+#include "attach_shader_ten.h"
+#include "attach_shader_eleven.h"
+#include "color_one.h"
 
 #define  LOG_TAG    "gl2_jni_libone"
 #define  LOGI(...)  __android_log_print(ANDROID_LOG_INFO,LOG_TAG,__VA_ARGS__)
@@ -40,7 +46,7 @@
 
 
 extern "C" JNIEXPORT void JNICALL Java_android_opengl_cts_GL2JniLibOne_init
-  (JNIEnv *, jclass pClass, jint pCategory, jint pSubCategory)  {
+  (JNIEnv *, jclass pClass, jint pCategory, jint pSubCategory, jint width, jint height)  {
     LOGI("Category :  %d\n", pCategory);
 
     if(pCategory == 1) {
@@ -72,6 +78,34 @@
             Data data = attachShaderSix();
             LOGI("Attach Shader Error :  %d\n", data.mShaderError);
             errorAttachShader = data.mShaderError;
+        }else if(pSubCategory == 7) {
+            Data data = attachShaderSeven();
+            LOGI("Attach Shader Error :  %d\n", data.mShaderError);
+            errorAttachShader = data.mShaderError;
+        }else if(pSubCategory == 8) {
+            Data data = attachShaderEight();
+            LOGI("Attach Shader Error :  %d\n", data.mShaderError);
+            errorAttachShader = data.mShaderError;
+        }else if(pSubCategory == 9) {
+            Data data = attachShaderNine();
+            LOGI("Attach Shader Error :  %d\n", data.mShaderError);
+            errorAttachShader = data.mShaderError;
+        }else if(pSubCategory == 10) {
+            Data data = attachShaderTen();
+            LOGI("Attach Shader Error :  %d\n", data.mShaderError);
+            LOGI("Shader Count :  %d\n", data.mShaderCount);
+            errorAttachShader = data.mShaderError;
+            shaderCount = data.mShaderCount;
+        }else if(pSubCategory == 11) {
+            Data data = attachShaderEleven();
+            LOGI("Attach Shader Error :  %d\n", data.mShaderError);
+            LOGI("Shader Count :  %d\n", data.mShaderCount);
+            errorAttachShader = data.mShaderError;
+            shaderCount = data.mShaderCount;
+        }
+    }else if(pCategory == 3){//Color Test
+        if(pSubCategory == 1){
+            initColorOne( width,height);
         }
     }
 }
@@ -97,4 +131,23 @@
     return shaderCount;
 }
 
+extern "C" JNIEXPORT jfloatArray JNICALL Java_android_opengl_cts_GL2JniLibOne_draw(JNIEnv * env,
+        jclass obj, jint pCategory, jint pSubCategory, jfloatArray color)
+{
+    LOGI("Inside draw %d %d", pCategory, pSubCategory);
+    jfloatArray result;
+    if(pCategory == 3){
+        if(pSubCategory == 1){
+            result = env->NewFloatArray(4);
 
+            jfloat *lColor =  env->GetFloatArrayElements(color,0);
+
+            float * actualColor = drawColorOne(lColor);
+            for( int i= 0; i < sizeof(actualColor); i++) {
+                LOGI("actualColor[%d] ; %f", i, actualColor[i]);
+            }
+            env->SetFloatArrayRegion(result, 0, 4, actualColor);
+        }
+    }
+    return result;
+}
diff --git a/tests/tests/opengl/libopengltest/shader.h b/tests/tests/opengl/libopengltest/shader.h
new file mode 100755
index 0000000..12131f1
--- /dev/null
+++ b/tests/tests/opengl/libopengltest/shader.h
@@ -0,0 +1,52 @@
+/*
+ * 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 _SHADER_H_
+#define _SHADER_H_
+
+static const char attach_shader_successful_complile_shader[] =
+           "attribute vec3 gtf_Normal;\n"
+            "attribute vec4 gtf_Vertex;\n"
+            "uniform mat3 gtf_NormalMatrix;\n"
+            "uniform mat4 gtf_ModelViewMatrix;\n"
+            "uniform mat4 gtf_ModelViewProjectionMatrix;\n"
+
+            "varying float lightIntensity;\n"
+            "varying vec3 Position;\n"
+            "uniform vec3 LightPosition;\n"
+            "uniform float Scale;\n"
+            "void main(void) {\n"
+            "vec4 pos = gtf_ModelViewMatrix * gtf_Vertex;\n"
+            "Position = vec3(gtf_Vertex) * Scale;\n"
+            "vec3 tnorm = normalize(gtf_NormalMatrix * gtf_Normal);\n"
+            "lightIntensity = dot(normalize(LightPosition - vec3(pos)), tnorm) * 1.5;\n"
+            "gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex;\n";
+
+static const char color_one_fragment_shader_one[] =
+        "precision mediump float;     \n"
+        "varying vec4 varyColor;      \n"
+        "void main()                  \n"
+        "{                            \n"
+        "  gl_FragColor = varyColor;  \n"
+        "}       ";
+
+static const char color_one_fragment_shader[] =
+        "precision mediump float;     \n"
+        "void main()                  \n"
+        "{                            \n"
+        "  gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);  \n"
+        "}       ";
+
+#endif
diff --git a/tests/tests/opengl/libopengltest/vertex.h b/tests/tests/opengl/libopengltest/vertex.h
new file mode 100755
index 0000000..50a4c7a
--- /dev/null
+++ b/tests/tests/opengl/libopengltest/vertex.h
@@ -0,0 +1,76 @@
+/*
+ * 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 _VERTEX_H_
+#define _VERTEX_H_
+
+static const char attach_shader_successful_complile_vertex[] =
+    "#ifdef GL_ES \n"
+    "precision mediump float;\n"
+    "#endif\n"
+    "uniform float    mortarThickness;\n"
+    "uniform vec3    brickColor;\n"
+    "uniform vec3    mortarColor;\n"
+    " \n"
+    "uniform float    brickMortarWidth;\n"
+    "uniform float    brickMortarHeight;\n"
+    "uniform float    mwf; \n"
+    "uniform float    mhf; \n"
+    ""
+    "varying vec3  Position; \n"
+    "varying float lightIntensity; \n"
+    " \n"
+    "void main (void) \n"
+    "{\n"
+    "    vec3    ct; \n"
+    "    float    ss, tt, w, h; \n"
+    " \n"
+    "    vec3 pos = Position; \n"
+    ""
+    "    ss = pos.x / brickMortarWidth; \n"
+    "    tt = pos.z / brickMortarHeight; \n"
+    ""
+    "    if (fract (tt * 0.5) > 0.5) \n"
+    "        ss += 0.5; \n"
+    ""
+    "    ss = fract (ss); \n"
+    "    tt = fract (tt); \n"
+
+    "    w = step (mwf, ss) - step (1.0 - mwf, ss); \n"
+    "    h = step (mhf, tt) - step (1.0 - mhf, tt); \n"
+    ""
+    "    ct = clamp(mix (mortarColor, brickColor, w * h) * lightIntensity, 0.0, 1.0); \n"
+    ""
+    "    gl_FragColor = vec4 (ct, 1.0); \n"
+    "} \n";
+
+static const char color_one_vertex_shader_one[] =
+        "attribute vec4 vPosition;    \n"
+        "attribute vec4 vColor;       \n"
+        "varying vec4 varyColor;      \n"
+        "void main()                  \n"
+        "{                            \n"
+        "   gl_Position = vPosition;  \n"
+        "   varyColor = vColor;       \n"
+        "}                            \n";
+
+static const char color_one_vertex_shader[] =
+        "attribute vec4 vPosition;    \n"
+        "void main()                  \n"
+        "{                            \n"
+        "   gl_Position = vPosition;  \n"
+        "}                            \n";
+
+#endif
diff --git a/tests/tests/opengl/src/android/opengl/cts/AttachShaderTest.java b/tests/tests/opengl/src/android/opengl/cts/AttachShaderTest.java
index 21efd6f..62ca1f9 100644
--- a/tests/tests/opengl/src/android/opengl/cts/AttachShaderTest.java
+++ b/tests/tests/opengl/src/android/opengl/cts/AttachShaderTest.java
@@ -29,8 +29,8 @@
 
     private OpenGLES20ActivityOne getShaderActivity(int viewType, int viewIndex) {
         Intent intent = new Intent();
-        intent.putExtra(OpenGLES20NativeActivity.EXTRA_VIEW_TYPE, viewType);
-        intent.putExtra(OpenGLES20NativeActivity.EXTRA_VIEW_INDEX, viewIndex);
+        intent.putExtra(OpenGLES20NativeActivityOne.EXTRA_VIEW_TYPE, viewType);
+        intent.putExtra(OpenGLES20NativeActivityOne.EXTRA_VIEW_INDEX, viewIndex);
         setActivityIntent(intent);
         OpenGLES20ActivityOne activity = getActivity();
         assertTrue(activity.waitForFrameDrawn());
@@ -133,4 +133,16 @@
         int error = mActivity.glGetError();
         assertEquals(GLES20.GL_NO_ERROR, error);
     }
+
+    public void test_glAttachShaders_successfulcompile_attach_vert() throws Throwable {
+        mActivity = getShaderActivity(Constants.SHADER, 11);
+        int error = mActivity.glGetError();
+        assertEquals(GLES20.GL_NO_ERROR, error);
+    }
+
+    public void test_glAttachShaders_successfulcompile_attach_invalid_handle_frag() throws Throwable {
+        mActivity = getShaderActivity(Constants.SHADER, 12);
+        int error = mActivity.glGetError();
+        assertTrue(GLES20.GL_NO_ERROR != error);
+    }
 }
diff --git a/tests/tests/opengl/src/android/opengl/cts/ColorBufferTest.java b/tests/tests/opengl/src/android/opengl/cts/ColorBufferTest.java
new file mode 100755
index 0000000..5ec1ce1
--- /dev/null
+++ b/tests/tests/opengl/src/android/opengl/cts/ColorBufferTest.java
@@ -0,0 +1,198 @@
+/*
+ * 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.opengl.cts;
+
+import android.test.ActivityInstrumentationTestCase2;
+
+public class ColorBufferTest extends ActivityInstrumentationTestCase2<OpenGLES20ActivityTwo> {
+    private static final long SLEEP_TIME = 500l;
+    public ColorBufferTest(Class<OpenGLES20ActivityTwo> activityClass) {
+        super(activityClass);
+    }
+
+    private OpenGLES20ActivityTwo mActivity;
+
+    public ColorBufferTest() {
+        super(OpenGLES20ActivityTwo.class);
+    }
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        mActivity = getActivity();
+    }
+    /**
+     *Test: Attach an two valid shaders to a program
+     * <pre>
+     * shader count : 2
+     * error        : GLES20.GL_NO_ERROR
+     * </pre>
+     */
+    public void test_RGBA_1001() throws Throwable {
+        float r = 1.0f;
+        float g = 0.0f;
+        float b = 0.0f;
+        float a = 1.0f;
+        final float[] vertexColors =  getVertexColors(r, g, b, a);
+        mActivity = getActivity();
+        float[] expectedColor = {r, g, b, a};
+        this.runTestOnUiThread(new Runnable() {
+            public void run() {
+                mActivity.setView(Constants.COLOR, 1, vertexColors);
+            }
+        });
+        assertTrue(mActivity.waitForFrameDrawn());
+        float[] actualColor = mActivity.getActualColor();
+        compare(expectedColor, actualColor);
+    }
+
+    public void test_RGBA_1101() throws Throwable {
+        float r = 1.0f;
+        float g = 1.0f;
+        float b = 0.0f;
+        float a = 1.0f;
+        final float[] vertexColors = getVertexColors(r, g, b, a);
+        float[] expectedColor = {r, g, b, a};
+        mActivity = getActivity();
+        this.runTestOnUiThread(new Runnable() {
+            public void run() {
+                mActivity.setView(Constants.COLOR, 1, vertexColors);
+            }
+        });
+        assertTrue(mActivity.waitForFrameDrawn());
+        float[] actualColor = mActivity.getActualColor();
+        compare(expectedColor, actualColor);
+    }
+
+    public void test_RGBA_1111() throws Throwable {
+        float r = 1.0f;
+        float g = 1.0f;
+        float b = 1.0f;
+        float a = 1.0f;
+        final float[] vertexColors = getVertexColors(r, g, b, a);
+
+        float[] expectedColor = {r, g, b, a};
+        mActivity = getActivity();
+        this.runTestOnUiThread(new Runnable() {
+            public void run() {
+                mActivity.setView(Constants.COLOR, 1, vertexColors);
+            }
+        });
+        assertTrue(mActivity.waitForFrameDrawn());
+        float[] actualColor = mActivity.getActualColor();
+        compare(expectedColor, actualColor);
+    }
+
+    public void test_RGBA_0101() throws Throwable {
+        float r = 0.0f;
+        float g = 1.0f;
+        float b = 0.0f;
+        float a = 1.0f;
+        final float[] vertexColors = getVertexColors(r, g, b, a);
+
+        float[] expectedColor = {r, g, b, a};
+        mActivity = getActivity();
+        this.runTestOnUiThread(new Runnable() {
+            public void run() {
+                mActivity.setView(Constants.COLOR, 1, vertexColors);
+            }
+        });
+        assertTrue(mActivity.waitForFrameDrawn());
+        float[] actualColor = mActivity.getActualColor();
+        compare(expectedColor, actualColor);
+    }
+
+    public void test_RGBA_0011() throws Throwable {
+        float r = 0.0f;
+        float g = 0.0f;
+        float b = 1.0f;
+        float a = 1.0f;
+        final float[] vertexColors = getVertexColors(r, g, b, a);
+
+        float[] expectedColor = {r, g, b, a};
+        mActivity = getActivity();
+        this.runTestOnUiThread(new Runnable() {
+            public void run() {
+                mActivity.setView(Constants.COLOR, 1, vertexColors);
+            }
+        });
+        assertTrue(mActivity.waitForFrameDrawn());
+        float[] actualColor = mActivity.getActualColor();
+        compare(expectedColor, actualColor);
+    }
+
+    public void test_RGBA_0000() throws Throwable {
+        float r = 0.0f;
+        float g = 0.0f;
+        float b = 0.0f;
+        float a = 0.0f;
+        final float[] vertexColors = getVertexColors(r, g, b, a);
+
+        float[] expectedColor = {r, g, b, a};
+        mActivity = getActivity();
+        this.runTestOnUiThread(new Runnable() {
+            public void run() {
+                mActivity.setView(Constants.COLOR, 1, vertexColors);
+            }
+        });
+        assertTrue(mActivity.waitForFrameDrawn());
+        float[] actualColor = mActivity.getActualColor();
+        compare(expectedColor, actualColor);
+    }
+
+    public void test_RGBA_rand_val_one() throws Throwable {
+        float r = 0.6f;
+        float g = 0.7f;
+        float b = 0.25f;
+        float a = 0.5f;
+        final float[] vertexColors = getVertexColors(r, g, b, a);
+
+        float[] expectedColor = {r, g, b, a};
+        mActivity = getActivity();
+        this.runTestOnUiThread(new Runnable() {
+            public void run() {
+                mActivity.setView(Constants.COLOR, 1, vertexColors);
+            }
+        });
+        assertTrue(mActivity.waitForFrameDrawn());
+        float[] actualColor = mActivity.getActualColor();
+        compare(expectedColor, actualColor);
+    }
+
+    private float[] getVertexColors(float r, float g, float b, float a) {
+        float[] vertexColors =
+              { r, g, b, a,
+                r, g, b, a,
+                r, g, b, a,
+                r, g, b, a
+               };
+        return vertexColors;
+    }
+
+    private void compare(float[] expectedColor, float[] actualColor) {
+        assertNotNull(actualColor);
+        assertEquals(4, actualColor.length);
+        float r = expectedColor[0];
+        float g = expectedColor[1];
+        float b = expectedColor[2];
+        float a = expectedColor[3];
+        //We are giving 0.1 buffer as colors might not be exactly same as input color
+        assertTrue(Math.abs(r - (actualColor[0]/255)) < 0.1f);
+        assertTrue(Math.abs(g - (actualColor[1]/255)) < 0.1f);
+        assertTrue(Math.abs(b - (actualColor[2]/255)) < 0.1f);
+        //assertTrue(Math.abs(a - (actualColor[3]/255)) < 0.1f);
+    }
+}
diff --git a/tests/tests/opengl/src/android/opengl/cts/Constants.java b/tests/tests/opengl/src/android/opengl/cts/Constants.java
index 9bd1acc..cba455a 100644
--- a/tests/tests/opengl/src/android/opengl/cts/Constants.java
+++ b/tests/tests/opengl/src/android/opengl/cts/Constants.java
@@ -18,4 +18,5 @@
 public class Constants {
     public static final int SHADER = 1;
     public static final int PROGRAM = 2;
+    public static final int COLOR = 3;
 }
diff --git a/tests/tests/opengl/src/android/opengl/cts/GL2JniLibOne.java b/tests/tests/opengl/src/android/opengl/cts/GL2JniLibOne.java
index 26de6ff..c306fc7 100755
--- a/tests/tests/opengl/src/android/opengl/cts/GL2JniLibOne.java
+++ b/tests/tests/opengl/src/android/opengl/cts/GL2JniLibOne.java
@@ -18,11 +18,12 @@
 
 public class GL2JniLibOne {
      static {
-         System.loadLibrary("opengltest");
+         System.loadLibrary("opengltest_jni");
      }
 
-     public static native void init(int category, int subcategory);
+     public static native void init(int category, int subcategory, int width, int height);
      public static native void step();
+     public static native float[] draw(int category, int subcategory, float[] color);
 
      public static native int getAttachShaderError();
      public static native int getLoadShaderError();
diff --git a/tests/tests/opengl/src/android/opengl/cts/NativeAttachShaderTest.java b/tests/tests/opengl/src/android/opengl/cts/NativeAttachShaderTest.java
index dbe3ea6..9985e87 100755
--- a/tests/tests/opengl/src/android/opengl/cts/NativeAttachShaderTest.java
+++ b/tests/tests/opengl/src/android/opengl/cts/NativeAttachShaderTest.java
@@ -20,24 +20,20 @@
 import android.test.ActivityInstrumentationTestCase2;
 
 public class NativeAttachShaderTest
-        extends ActivityInstrumentationTestCase2<OpenGLES20NativeActivity> {
+        extends ActivityInstrumentationTestCase2<OpenGLES20NativeActivityOne> {
 
-    public NativeAttachShaderTest(Class<OpenGLES20NativeActivity> activityClass) {
-        super(activityClass);
-    }
-
-    private OpenGLES20NativeActivity mActivity;
+    private OpenGLES20NativeActivityOne mActivity;
 
     public NativeAttachShaderTest() {
-        super(OpenGLES20NativeActivity.class);
+        super(OpenGLES20NativeActivityOne.class);
     }
 
-    private OpenGLES20NativeActivity getShaderActivity(int viewType, int viewIndex) {
+    private OpenGLES20NativeActivityOne getShaderActivity(int viewType, int viewIndex) {
         Intent intent = new Intent();
-        intent.putExtra(OpenGLES20NativeActivity.EXTRA_VIEW_TYPE, viewType);
-        intent.putExtra(OpenGLES20NativeActivity.EXTRA_VIEW_INDEX, viewIndex);
+        intent.putExtra(OpenGLES20NativeActivityOne.EXTRA_VIEW_TYPE, viewType);
+        intent.putExtra(OpenGLES20NativeActivityOne.EXTRA_VIEW_INDEX, viewIndex);
         setActivityIntent(intent);
-        OpenGLES20NativeActivity activity = getActivity();
+        OpenGLES20NativeActivityOne activity = getActivity();
         assertTrue(activity.waitForFrameDrawn());
         return activity;
     }
@@ -113,4 +109,37 @@
         int error = mActivity.mRenderer.mAttachShaderError;;
         assertEquals(GLES20.GL_NO_ERROR, error);
     }
+
+    public void test_glAttachShaders_emptyvertexshader_emptyvertexshader() throws Throwable {
+        mActivity = getShaderActivity(Constants.SHADER, 7);
+        int error = mActivity.mRenderer.mAttachShaderError;
+        assertTrue(GLES20.GL_NO_ERROR != error);
+    }
+
+    public void test_glAttachShaders_programobject_attach_fragshaderobject() throws Throwable {
+        mActivity = getShaderActivity(Constants.SHADER, 8);
+        int error = mActivity.mRenderer.mAttachShaderError;
+        // The operations are valid
+        assertEquals(GLES20.GL_NO_ERROR, error);
+    }
+
+    public void test_glAttachShaders_invalidshader_attach_valid_handle() throws Throwable{
+        mActivity = getShaderActivity(Constants.SHADER, 9);
+        int error = mActivity.mRenderer.mAttachShaderError;
+        assertTrue(GLES20.GL_NO_ERROR != error);
+    }
+
+    public void test_glAttachShaders_successfulcompile_attach_frag() throws Throwable {
+        mActivity = getShaderActivity(Constants.SHADER, 10);
+        int shaderCount = mActivity.mRenderer.mShaderCount;
+        assertEquals(1,shaderCount);
+        int error = mActivity.mRenderer.mAttachShaderError;
+        assertEquals(GLES20.GL_NO_ERROR, error);
+    }
+
+    public void test_glAttachShaders_successfulcompile_attach_vert() throws Throwable {
+        mActivity = getShaderActivity(Constants.SHADER, 11);
+        int error = mActivity.mRenderer.mAttachShaderError;
+        assertEquals(GLES20.GL_NO_ERROR, error);
+    }
 }
diff --git a/tests/tests/opengl/src/android/opengl/cts/NativeColorBufferTest.java b/tests/tests/opengl/src/android/opengl/cts/NativeColorBufferTest.java
new file mode 100755
index 0000000..7f4dbb2
--- /dev/null
+++ b/tests/tests/opengl/src/android/opengl/cts/NativeColorBufferTest.java
@@ -0,0 +1,194 @@
+/*
+ * 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.opengl.cts;
+
+import android.test.ActivityInstrumentationTestCase2;
+
+public class NativeColorBufferTest extends ActivityInstrumentationTestCase2<OpenGLES20NativeActivityTwo> {
+    private static final long SLEEP_TIME = 500l;
+    private static final String TAG = NativeColorBufferTest.class.getName();
+    public NativeColorBufferTest(Class<OpenGLES20NativeActivityTwo> activityClass) {
+        super(activityClass);
+    }
+
+    private OpenGLES20NativeActivityTwo mActivity;
+
+    public NativeColorBufferTest() {
+        super(OpenGLES20NativeActivityTwo.class);
+    }
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+        mActivity = getActivity();
+    }
+
+    public void test_RGBA_1001() throws Throwable {
+        float r = 1.0f;
+        float g = 0.0f;
+        float b = 0.0f;
+        float a = 1.0f;
+        final float[] vertexColors =  getVertexColors(r, g, b, a);
+        mActivity = getActivity();
+        float[] expectedColor = {r, g, b, a};
+        this.runTestOnUiThread(new Runnable() {
+            public void run() {
+                mActivity.setView(Constants.COLOR, 1, vertexColors);
+            }
+        });
+        assertTrue(mActivity.waitForFrameDrawn());
+        float[] actualColor = mActivity.getActualColor();
+        compare(expectedColor, actualColor);
+    }
+
+    public void test_RGBA_1101() throws Throwable {
+        float r = 1.0f;
+        float g = 1.0f;
+        float b = 0.0f;
+        float a = 1.0f;
+        final float[] vertexColors = getVertexColors(r, g, b, a);
+        float[] expectedColor = {r, g, b, a};
+        mActivity = getActivity();
+        this.runTestOnUiThread(new Runnable() {
+            public void run() {
+                mActivity.setView(Constants.COLOR, 1, vertexColors);
+            }
+        });
+        assertTrue(mActivity.waitForFrameDrawn());
+        float[] actualColor = mActivity.getActualColor();
+        compare(expectedColor, actualColor);
+    }
+
+    public void test_RGBA_1111() throws Throwable {
+        float r = 1.0f;
+        float g = 1.0f;
+        float b = 1.0f;
+        float a = 1.0f;
+        final float[] vertexColors = getVertexColors(r, g, b, a);
+
+        float[] expectedColor = {r, g, b, a};
+        mActivity = getActivity();
+        this.runTestOnUiThread(new Runnable() {
+            public void run() {
+                mActivity.setView(Constants.COLOR, 1, vertexColors);
+            }
+        });
+        assertTrue(mActivity.waitForFrameDrawn());
+        float[] actualColor = mActivity.getActualColor();
+        compare(expectedColor, actualColor);
+    }
+
+    public void test_RGBA_0101() throws Throwable {
+        float r = 0.0f;
+        float g = 1.0f;
+        float b = 0.0f;
+        float a = 1.0f;
+        final float[] vertexColors = getVertexColors(r, g, b, a);
+
+        float[] expectedColor = {r, g, b, a};
+        mActivity = getActivity();
+        this.runTestOnUiThread(new Runnable() {
+            public void run() {
+                mActivity.setView(Constants.COLOR, 1, vertexColors);
+            }
+        });
+        assertTrue(mActivity.waitForFrameDrawn());
+        float[] actualColor = mActivity.getActualColor();
+        compare(expectedColor, actualColor);
+    }
+
+    public void test_RGBA_0011() throws Throwable {
+        float r = 0.0f;
+        float g = 0.0f;
+        float b = 1.0f;
+        float a = 1.0f;
+        final float[] vertexColors = getVertexColors(r, g, b, a);
+
+        float[] expectedColor = {r, g, b, a};
+        mActivity = getActivity();
+        this.runTestOnUiThread(new Runnable() {
+            public void run() {
+                mActivity.setView(Constants.COLOR, 1, vertexColors);
+            }
+        });
+        assertTrue(mActivity.waitForFrameDrawn());
+        float[] actualColor = mActivity.getActualColor();
+        compare(expectedColor, actualColor);
+    }
+
+    public void test_RGBA_0000() throws Throwable {
+        float r = 0.0f;
+        float g = 0.0f;
+        float b = 0.0f;
+        float a = 0.0f;
+        final float[] vertexColors = getVertexColors(r, g, b, a);
+
+        float[] expectedColor = {r, g, b, a};
+        mActivity = getActivity();
+        this.runTestOnUiThread(new Runnable() {
+            public void run() {
+                mActivity.setView(Constants.COLOR, 1, vertexColors);
+            }
+        });
+        assertTrue(mActivity.waitForFrameDrawn());
+        float[] actualColor = mActivity.getActualColor();
+        compare(expectedColor, actualColor);
+    }
+
+    public void test_RGBA_rand_val_one() throws Throwable {
+        float r = 0.6f;
+        float g = 0.7f;
+        float b = 0.25f;
+        float a = 0.5f;
+        final float[] vertexColors = getVertexColors(r, g, b, a);
+
+        float[] expectedColor = {r, g, b, a};
+        mActivity = getActivity();
+        this.runTestOnUiThread(new Runnable() {
+            public void run() {
+                mActivity.setView(Constants.COLOR, 1, vertexColors);
+            }
+        });
+        assertTrue(mActivity.waitForFrameDrawn());
+        float[] actualColor = mActivity.getActualColor();
+        compare(expectedColor, actualColor);
+    }
+
+    private float[] getVertexColors(float r, float g, float b, float a) {
+        float[] vertexColors =
+              { r, g, b, a,
+                r, g, b, a,
+                r, g, b, a
+               };
+        return vertexColors;
+    }
+
+    private void compare(float[] expectedColor, float[] actualColor) {
+        assertNotNull(actualColor);
+        assertEquals(4, actualColor.length);
+        float r = expectedColor[0];
+        float g = expectedColor[1];
+        float b = expectedColor[2];
+        float a = expectedColor[3];
+        //We are giving 0.1 buffer as colors might not be exactly same as input color
+        assertTrue(Math.abs(r - (actualColor[0]/255.0)) < 0.1f);
+        assertTrue(Math.abs(g - (actualColor[1]/255.0)) < 0.1f);
+        assertTrue(Math.abs(b - (actualColor[2]/255.0)) < 0.1f);
+        float actualAlpha = (float) (actualColor[3]/255.0);
+        //Commented as of now as the Alpha being returned is always 1
+        //assertTrue(Math.abs(a - (actualColor[3]/255)) < 0.1f);
+    }
+}
diff --git a/tests/tests/opengl/src/android/opengl/cts/NativeRendererOneColorBufferTest.java b/tests/tests/opengl/src/android/opengl/cts/NativeRendererOneColorBufferTest.java
new file mode 100755
index 0000000..623daea
--- /dev/null
+++ b/tests/tests/opengl/src/android/opengl/cts/NativeRendererOneColorBufferTest.java
@@ -0,0 +1,88 @@
+/*
+ * 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.opengl.cts;
+
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+import java.nio.FloatBuffer;
+import java.nio.IntBuffer;
+import java.nio.ShortBuffer;
+import java.util.concurrent.CountDownLatch;
+import javax.microedition.khronos.egl.EGLConfig;
+import javax.microedition.khronos.opengles.GL10;
+
+import android.content.Context;
+import android.opengl.GLES20;
+import android.opengl.GLSurfaceView;
+import android.opengl.GLU;
+import android.util.Log;
+
+public class NativeRendererOneColorBufferTest extends RendererBase {
+    private int mProgramObject;
+    private int mWidth;
+    private int mHeight;
+    private FloatBuffer mVertices;
+    private ShortBuffer mIndexBuffer;
+
+    private static String TAG = "HelloTriangleRenderer";
+
+    // Our vertices.
+    private float mVerticesData[] = {
+           -0.5f,  0.5f, 0.0f,  // 0, Top Left
+           -0.5f, -0.5f, 0.0f,  // 1, Bottom Left
+            0.5f, -0.5f, 0.0f,  // 2, Bottom Right
+            0.5f,  0.5f, 0.0f,  // 3, Top Right
+    };
+
+    private float[] mVertexColor = {};
+
+    private short[] mIndices = { 0, 1, 2, 0, 2, 3 };
+    private FloatBuffer mColor;
+
+    public NativeRendererOneColorBufferTest(Context context, CountDownLatch latch) {
+        super(latch);
+    }
+
+    public NativeRendererOneColorBufferTest(Context context, float[] color, CountDownLatch latch) {
+        super(latch);
+        this.mVertexColor = color;
+    }
+
+    public void onSurfaceCreated(GL10 glUnused, EGLConfig config) {
+
+    }
+
+    public void doOnDrawFrame(GL10 glUnused) {
+      Log.i(TAG,"onDrawFrame start");
+
+      float[] result = GL2JniLibOne.draw(3, 1, mVertexColor);
+      mColorOne = result;
+    }
+
+    public float[] getActualRGBA() {
+        return this.mColorOne;
+    }
+
+    public void onSurfaceChanged(GL10 glUnused, int width, int height) {
+        mWidth = width;
+        mHeight = height;
+        Log.i(TAG,"onSurfaceCreated start");
+        GL2JniLibOne.init(3,1, width, height);
+        Log.i(TAG,"onSurfaceCreated finish");
+    }
+}
diff --git a/tests/tests/opengl/src/android/opengl/cts/OpenGLES20ActivityOne.java b/tests/tests/opengl/src/android/opengl/cts/OpenGLES20ActivityOne.java
index a8388c2..5acac32 100644
--- a/tests/tests/opengl/src/android/opengl/cts/OpenGLES20ActivityOne.java
+++ b/tests/tests/opengl/src/android/opengl/cts/OpenGLES20ActivityOne.java
@@ -89,6 +89,7 @@
         public OpenGLES20View(Context context, int type, int index, CountDownLatch latch) {
             super(context);
             setEGLContextClientVersion(2);
+
             if (type == Constants.SHADER) {
                 if (index == 1) {
                     mRenderer = new RendererOneShaderTest(latch);
@@ -110,6 +111,10 @@
                     mRenderer = new RendererNineShaderTest(latch);
                 } else if(index == 10) {
                     mRenderer = new RendererTenShaderTest(latch);
+                } else if(index == 11) {
+                    mRenderer = new RendererElevenShaderTest(latch);
+                } else if(index == 12) {
+                    mRenderer = new RendererTwelveShaderTest(latch);
                 } else {
                     throw new RuntimeException();
                 }
diff --git a/tests/tests/opengl/src/android/opengl/cts/OpenGLES20ActivityTwo.java b/tests/tests/opengl/src/android/opengl/cts/OpenGLES20ActivityTwo.java
new file mode 100755
index 0000000..6bb34e4
--- /dev/null
+++ b/tests/tests/opengl/src/android/opengl/cts/OpenGLES20ActivityTwo.java
@@ -0,0 +1,110 @@
+/*
+ * 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.opengl.cts;
+
+import android.app.Activity;
+import android.content.Context;
+import android.opengl.GLSurfaceView;
+import android.opengl.GLSurfaceView.Renderer;
+import android.os.Bundle;
+
+import java.lang.InterruptedException;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+
+
+public class OpenGLES20ActivityTwo extends Activity {
+    OpenGLES20View view;
+    Renderer mRenderer;
+    int mRendererType;
+    private CountDownLatch mLatch = new CountDownLatch(1);
+
+    @Override
+    public void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+    }
+
+    public boolean waitForFrameDrawn() {
+        boolean result = false;
+        try {
+            result = mLatch.await(10L, TimeUnit.SECONDS);
+        } catch (InterruptedException e) {
+            // just return false
+        }
+        return result;
+    }
+
+    public void setView(int type, int i, float[] vertexColors ) {
+        view = new OpenGLES20View(this,type,i, vertexColors, mLatch);
+        setContentView(view);
+    }
+
+    public void setView(int type, int i) {
+        float[] f = {};
+        view = new OpenGLES20View(this, type, i, f, mLatch)  ;
+        setContentView(view);
+    }
+
+    public int getNoOfAttachedShaders() {
+       return ((RendererBase)mRenderer).mShaderCount[0];
+    }
+
+    public int glGetError() {
+        return ((RendererBase)mRenderer).mError;
+    }
+
+    @Override
+    protected void onPause() {
+        super.onPause();
+        view.onPause();
+
+    }
+
+    @Override
+    protected void onResume() {
+        super.onResume();
+        if(view != null) {
+            view.onResume();
+        }
+    }
+
+    public float[] getActualColor() {
+        return ((RendererBase) mRenderer).mColorOne;
+    }
+
+    class OpenGLES20View extends GLSurfaceView {
+
+        public OpenGLES20View(Context context, int type, int index, float[] rgba,
+                              CountDownLatch latch) {
+            super(context);
+            setEGLContextClientVersion(2);
+            if(type == Constants.COLOR) {
+                if(index == 1) {
+                    mRenderer = new RendererOneColorBufferTest(context, rgba, latch);
+                }else {
+                    throw new RuntimeException();
+                }
+            }
+            setRenderer(mRenderer);
+        }
+
+        @Override
+        public void setEGLContextClientVersion(int version) {
+            super.setEGLContextClientVersion(version);
+        }
+
+    }
+}
diff --git a/tests/tests/opengl/src/android/opengl/cts/OpenGLES20NativeActivity.java b/tests/tests/opengl/src/android/opengl/cts/OpenGLES20NativeActivityOne.java
similarity index 81%
rename from tests/tests/opengl/src/android/opengl/cts/OpenGLES20NativeActivity.java
rename to tests/tests/opengl/src/android/opengl/cts/OpenGLES20NativeActivityOne.java
index 36f986b..ac4fce5 100755
--- a/tests/tests/opengl/src/android/opengl/cts/OpenGLES20NativeActivity.java
+++ b/tests/tests/opengl/src/android/opengl/cts/OpenGLES20NativeActivityOne.java
@@ -1,23 +1,9 @@
-/*
- * 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.opengl.cts;
 
 import android.app.Activity;
 import android.content.Context;
 import android.opengl.GLSurfaceView;
+
 import android.os.Bundle;
 import android.util.Log;
 import android.view.Window;
@@ -30,7 +16,7 @@
 import javax.microedition.khronos.egl.EGLConfig;
 import javax.microedition.khronos.opengles.GL10;
 
-public class OpenGLES20NativeActivity extends Activity {
+public class OpenGLES20NativeActivityOne extends Activity {
 
     public static final String EXTRA_VIEW_TYPE = "viewType";
     public static final String EXTRA_VIEW_INDEX = "viewIndex";
@@ -49,7 +35,6 @@
     @Override
     public void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
-
         Window window = getWindow();
         window.addFlags(WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD);
 
@@ -122,16 +107,16 @@
     }
 
     public void onSurfaceChanged(GL10 gl, int width, int height) {
-
-    }
-
-    public void onSurfaceCreated(GL10 gl, EGLConfig config) {
         Log.i(TAG ,"onSurfaceCreated");
-        GL2JniLibOne.init(mCategory, mTestCase);
+        GL2JniLibOne.init(mCategory, mTestCase, width, height);
         this.mAttachShaderError = GL2JniLibOne.getAttachShaderError();
         Log.i(TAG,"error:" + mAttachShaderError);
         this.mShaderCount = GL2JniLibOne.getAttachedShaderCount();
         Log.i(TAG,"ShaderCount:" + mShaderCount);
         mLatch.countDown();
     }
+
+    public void onSurfaceCreated(GL10 gl, EGLConfig config) {
+
+    }
 }
diff --git a/tests/tests/opengl/src/android/opengl/cts/OpenGLES20NativeActivityTwo.java b/tests/tests/opengl/src/android/opengl/cts/OpenGLES20NativeActivityTwo.java
new file mode 100755
index 0000000..6bdf95f
--- /dev/null
+++ b/tests/tests/opengl/src/android/opengl/cts/OpenGLES20NativeActivityTwo.java
@@ -0,0 +1,120 @@
+/*
+ * 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.opengl.cts;
+
+import android.app.Activity;
+import android.content.Context;
+import android.opengl.GLSurfaceView;
+import android.opengl.GLSurfaceView.Renderer;
+import android.os.Bundle;
+
+import java.lang.InterruptedException;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+
+public class OpenGLES20NativeActivityTwo extends Activity {
+    OpenGLES20View view;
+    Renderer mRenderer;
+    int mRendererType;
+
+    private CountDownLatch mLatch = new CountDownLatch(1);
+
+    @Override
+    public void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+    }
+
+    public boolean waitForFrameDrawn() {
+        boolean result = false;
+        try {
+            result = mLatch.await(10L, TimeUnit.SECONDS);
+        } catch (InterruptedException e) {
+            // just return false
+        }
+        return result;
+    }
+
+    public void setView(int type, int i, float[] vertexColors ) {
+        view = new OpenGLES20View(this,type,i, vertexColors, mLatch);
+        setContentView(view);
+    }
+
+    public void setView(int type, int i) {
+
+    }
+
+    public int getNoOfAttachedShaders() {
+       return ((RendererBase)mRenderer).mShaderCount[0];
+    }
+
+    public int glGetError() {
+        return ((RendererBase)mRenderer).mError;
+    }
+
+    @Override
+    protected void onPause() {
+        super.onPause();
+        if(view != null) {
+            view.onPause();
+        }
+
+    }
+
+    @Override
+    protected void onResume() {
+        super.onResume();
+        if(view != null) {
+            view.onResume();
+        }
+    }
+
+    public float[] getActualColor() {
+        return ((RendererBase) mRenderer).mColorOne;
+    }
+
+    class OpenGLES20View extends GLSurfaceView {
+
+        @Override
+        public void onPause() {
+            super.onPause();
+        }
+
+        @Override
+        public void onResume() {
+            super.onResume();
+        }
+
+        public OpenGLES20View(Context context, int type, int index, float[] rgba,
+                              CountDownLatch latch) {
+            super(context);
+            setEGLContextClientVersion(2);
+            if(type == Constants.COLOR) {
+                if(index == 1) {
+                    mRenderer = new NativeRendererOneColorBufferTest(context, rgba, latch);
+                }else {
+                    throw new RuntimeException();
+                }
+            }
+            setRenderer(mRenderer);
+        }
+
+        @Override
+        public void setEGLContextClientVersion(int version) {
+            super.setEGLContextClientVersion(version);
+        }
+
+    }
+}
diff --git a/tests/tests/opengl/src/android/opengl/cts/ProgramTest.java b/tests/tests/opengl/src/android/opengl/cts/ProgramTest.java
index 4c59070..a69c8e5 100644
--- a/tests/tests/opengl/src/android/opengl/cts/ProgramTest.java
+++ b/tests/tests/opengl/src/android/opengl/cts/ProgramTest.java
@@ -29,8 +29,8 @@
 
     private OpenGLES20ActivityOne getShaderActivity(int viewType, int viewIndex) {
         Intent intent = new Intent();
-        intent.putExtra(OpenGLES20NativeActivity.EXTRA_VIEW_TYPE, viewType);
-        intent.putExtra(OpenGLES20NativeActivity.EXTRA_VIEW_INDEX, viewIndex);
+        intent.putExtra(OpenGLES20NativeActivityOne.EXTRA_VIEW_TYPE, viewType);
+        intent.putExtra(OpenGLES20NativeActivityOne.EXTRA_VIEW_INDEX, viewIndex);
         setActivityIntent(intent);
         return getActivity();
     }
diff --git a/tests/tests/opengl/src/android/opengl/cts/RendererBase.java b/tests/tests/opengl/src/android/opengl/cts/RendererBase.java
index d015fcd..994c1c6 100644
--- a/tests/tests/opengl/src/android/opengl/cts/RendererBase.java
+++ b/tests/tests/opengl/src/android/opengl/cts/RendererBase.java
@@ -30,6 +30,7 @@
     FloatBuffer floatBuffer;
     int mProgram;
     int maPositionHandle;
+    float[] mColorOne = new float[4];
 
     int[] mShaderCount = null;
     int mError;
diff --git a/tests/tests/opengl/src/android/opengl/cts/RendererElevenShaderTest.java b/tests/tests/opengl/src/android/opengl/cts/RendererElevenShaderTest.java
new file mode 100755
index 0000000..35df7b5
--- /dev/null
+++ b/tests/tests/opengl/src/android/opengl/cts/RendererElevenShaderTest.java
@@ -0,0 +1,43 @@
+/*
+ * 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.opengl.cts;
+
+import java.util.concurrent.CountDownLatch;
+import javax.microedition.khronos.egl.EGLConfig;
+import javax.microedition.khronos.opengles.GL10;
+
+import android.opengl.GLES20;
+
+public class RendererElevenShaderTest extends RendererBase {
+    private String fragmentShaderCode = Vertex.successfulcompile_vertex;
+
+    public RendererElevenShaderTest(CountDownLatch latch) {
+        super(latch);
+    }
+
+    @Override
+    public void onSurfaceCreated(GL10 gl, EGLConfig config) {
+        GLES20.glClearColor(0.5f, 0.5f, 0.5f, 1.0f);
+        int fragmentShader = loadShader(GLES20.GL_FRAGMENT_SHADER, fragmentShaderCode);
+        mProgram =  GLES20.glCreateProgram();
+
+        GLES20.glAttachShader(mProgram, fragmentShader);
+        GLES20.glLinkProgram(mProgram);
+
+        mError = GLES20.glGetError();
+        mLatch.countDown();
+    }
+}
diff --git a/tests/tests/opengl/src/android/opengl/cts/RendererOneColorBufferTest.java b/tests/tests/opengl/src/android/opengl/cts/RendererOneColorBufferTest.java
new file mode 100755
index 0000000..50a4085
--- /dev/null
+++ b/tests/tests/opengl/src/android/opengl/cts/RendererOneColorBufferTest.java
@@ -0,0 +1,238 @@
+/*
+ * 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.opengl.cts;
+
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+import java.nio.FloatBuffer;
+import java.nio.IntBuffer;
+import java.nio.ShortBuffer;
+import java.util.concurrent.CountDownLatch;
+import javax.microedition.khronos.egl.EGLConfig;
+import javax.microedition.khronos.opengles.GL10;
+
+import android.content.Context;
+import android.opengl.GLES20;
+import android.opengl.GLSurfaceView;
+import android.opengl.GLU;
+import android.util.Log;
+
+public class RendererOneColorBufferTest extends RendererBase {
+    private int mProgramObject;
+    private int mWidth;
+    private int mHeight;
+    private FloatBuffer mVertices;
+    private ShortBuffer mIndexBuffer;
+
+    private static String TAG = "HelloTriangleRenderer";
+
+    // Our vertices.
+    private float mVerticesData[] = {
+           -0.5f,  0.5f, 0.0f,  // 0, Top Left
+           -0.5f, -0.5f, 0.0f,  // 1, Bottom Left
+            0.5f, -0.5f, 0.0f,  // 2, Bottom Right
+            0.5f,  0.5f, 0.0f,  // 3, Top Right
+    };
+
+    private float[] mVertexColor = {1.0f,0.0f,0.0f,1.0f,
+            1.0f,0.0f,0.0f,1.0f,
+            1.0f,0.0f,0.0f,1.0f,
+            1.0f,0.0f,0.0f,1.0f};
+
+    // The order we like to connect them.
+    private short[] mIndices = { 0, 1, 2, 0, 2, 3 };
+    private FloatBuffer mColor;
+
+
+    public RendererOneColorBufferTest(Context context, CountDownLatch latch) {
+        super(latch);
+        mVertices = ByteBuffer.allocateDirect(mVerticesData.length * 4)
+        .order(ByteOrder.nativeOrder()).asFloatBuffer();
+        mVertices.put(mVerticesData).position(0);
+
+        ByteBuffer ibb = ByteBuffer.allocateDirect(mIndices.length * 2);
+        ibb.order(ByteOrder.nativeOrder());
+        mIndexBuffer = ibb.asShortBuffer();
+        mIndexBuffer.put(mIndices);
+        mIndexBuffer.position(0);
+
+        mColor = ByteBuffer.allocateDirect(mVertexColor.length*4).
+                order(ByteOrder.nativeOrder()).asFloatBuffer();
+        mColor.put(mVertexColor).position(0);
+    }
+
+    public RendererOneColorBufferTest(Context context, float[] colors, CountDownLatch latch) {
+        super(latch);
+        mVertexColor = colors;
+        mVertices = ByteBuffer.allocateDirect(mVerticesData.length * 4)
+        .order(ByteOrder.nativeOrder()).asFloatBuffer();
+        mVertices.put(mVerticesData).position(0);
+
+        ByteBuffer ibb = ByteBuffer.allocateDirect(mIndices.length * 2);
+        ibb.order(ByteOrder.nativeOrder());
+        mIndexBuffer = ibb.asShortBuffer();
+        mIndexBuffer.put(mIndices);
+        mIndexBuffer.position(0);
+
+        mColor = ByteBuffer.allocateDirect(mVertexColor.length*4).
+                order(ByteOrder.nativeOrder()).asFloatBuffer();
+        mColor.put(mVertexColor).position(0);
+    }
+
+    private int LoadShader(int type, String shaderSrc) {
+        int shader;
+        int[] compiled = new int[1];
+
+        // Create the shader object
+        shader = GLES20.glCreateShader(type);
+
+        if (shader == 0)
+            return 0;
+
+        // Load the shader source
+        GLES20.glShaderSource(shader, shaderSrc);
+
+        // Compile the shader
+        GLES20.glCompileShader(shader);
+
+        // Check the compile status
+        GLES20.glGetShaderiv(shader, GLES20.GL_COMPILE_STATUS, compiled, 0);
+
+        if (compiled[0] == 0) {
+            Log.e(TAG, GLES20.glGetShaderInfoLog(shader));
+            GLES20.glDeleteShader(shader);
+            return 0;
+        }
+        return shader;
+    }
+
+
+    public void onSurfaceCreated(GL10 glUnused, EGLConfig config) {
+        String vShaderStr =
+              "attribute vec4 vPosition;    \n"
+            + "attribute vec4 vColor;       \n"
+            + "varying vec4 varyColor;      \n"
+            + "void main()                  \n"
+            + "{                            \n"
+            + "   gl_Position = vPosition;  \n"
+            + "   varyColor = vColor;       \n"
+            + "}                            \n";
+
+        String fShaderStr =
+            "precision mediump float;       \n"
+            + "varying vec4 varyColor;      \n"
+            + "void main()                  \n"
+            + "{                            \n"
+            + "  gl_FragColor = varyColor;  \n"
+            + "}                            \n";
+
+        int vertexShader;
+        int fragmentShader;
+        int programObject;
+        int[] linked = new int[1];
+
+        // Load the vertex/fragment shaders
+        vertexShader = LoadShader(GLES20.GL_VERTEX_SHADER, vShaderStr);
+        fragmentShader = LoadShader(GLES20.GL_FRAGMENT_SHADER, fShaderStr);
+
+        // Create the program object
+        programObject = GLES20.glCreateProgram();
+
+        if (programObject == 0)
+            return;
+
+        GLES20.glAttachShader(programObject, vertexShader);
+        GLES20.glAttachShader(programObject, fragmentShader);
+
+        // Bind vPosition to attribute 0
+        GLES20.glBindAttribLocation(programObject, 0, "vPosition");
+        GLES20.glBindAttribLocation(programObject, 1, "vColor");
+
+        // Link the program
+        GLES20.glLinkProgram(programObject);
+
+        // Check the link status
+        GLES20.glGetProgramiv(programObject, GLES20.GL_LINK_STATUS, linked, 0);
+
+        if (linked[0] == 0)
+        {
+            Log.e(TAG, "Error linking program:");
+            Log.e(TAG, GLES20.glGetProgramInfoLog(programObject));
+            GLES20.glDeleteProgram(programObject);
+            return;
+        }
+
+        // Store the program object
+        mProgramObject = programObject;
+
+        GLES20.glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
+    }
+
+    public void doOnDrawFrame(GL10 glUnused)
+    {
+        // Set the viewport
+        GLES20.glViewport(0, 0, mWidth, mHeight);
+
+        // Clear the color buffer
+        GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT);
+
+        // Use the program object
+        GLES20.glUseProgram(mProgramObject);
+
+        // Load the vertex data
+        GLES20.glVertexAttribPointer(0,3, GLES20.GL_FLOAT, false, 0, mVertices);
+        GLES20.glEnableVertexAttribArray(0);
+
+        int mColorHandle = GLES20.glGetAttribLocation(mProgramObject, "vColor");
+        GLES20.glVertexAttribPointer(mColorHandle,4, GLES20.GL_FLOAT, false, 0, mColor);
+        GLES20.glEnableVertexAttribArray(1);
+
+        GLES20.glDrawElements(GLES20.GL_TRIANGLES, mIndices.length, 
+                GLES20.GL_UNSIGNED_SHORT, mIndexBuffer);
+
+        int x = 1;
+        int y =1;
+        IntBuffer   pinbuffer   = IntBuffer.allocate(1*1*4);
+        IntBuffer   poutbuffer  = IntBuffer.allocate(x*y*4);
+           int         i,j,z;
+           int []      pin         = pinbuffer.array();
+           int []      pout        = poutbuffer.array();
+
+        GLES20.glReadPixels(mWidth/2, mWidth/2, 1, 1, GLES20.GL_RGBA, GLES20.GL_UNSIGNED_BYTE,
+                pinbuffer);
+        int pixel = pin[0];
+        float a = (pixel >> 24) & 0xFF;
+        float b = (pixel >> 16) & 0xFF;
+        float g = (pixel >> 8) & 0xFF;
+        float r = pixel & 0xFF;
+        Log.i(TAG,"rgba" + r + " " + g + " " + b + " " + a);
+        mColorOne[0] = r;
+        mColorOne[1] = g;
+        mColorOne[2] = b;
+        mColorOne[3] = a;
+    }
+
+    public float[] getActualRGBA() {
+        return this.mColorOne;
+    }
+
+    public void onSurfaceChanged(GL10 glUnused, int width, int height) {
+        mWidth = width;
+        mHeight = height;
+    }
+}
diff --git a/tests/tests/opengl/src/android/opengl/cts/RendererTwelveShaderTest.java b/tests/tests/opengl/src/android/opengl/cts/RendererTwelveShaderTest.java
new file mode 100755
index 0000000..a3dab8e
--- /dev/null
+++ b/tests/tests/opengl/src/android/opengl/cts/RendererTwelveShaderTest.java
@@ -0,0 +1,44 @@
+/*
+ * 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.opengl.cts;
+
+import java.util.concurrent.CountDownLatch;
+import javax.microedition.khronos.egl.EGLConfig;
+import javax.microedition.khronos.opengles.GL10;
+
+import android.opengl.GLES20;
+
+public class RendererTwelveShaderTest extends RendererBase {
+    private String fragmentShaderCode = Shaders.successfulcompile_frag;
+
+    public RendererTwelveShaderTest(CountDownLatch latch) {
+        super(latch);
+    }
+
+    @Override
+    public void onSurfaceCreated(GL10 gl, EGLConfig config) {
+        GLES20.glClearColor(0.5f, 0.5f, 0.5f, 1.0f);
+        int fragmentShader = loadShader(GLES20.GL_FRAGMENT_SHADER, fragmentShaderCode);
+        //invalid value
+        mProgram =  0;
+
+        GLES20.glAttachShader(mProgram, fragmentShader);
+        GLES20.glLinkProgram(mProgram);
+
+        mError = GLES20.glGetError();
+        mLatch.countDown();
+    }
+}
diff --git a/tests/tests/opengl/src/android/opengl/cts/Vertex.java b/tests/tests/opengl/src/android/opengl/cts/Vertex.java
new file mode 100755
index 0000000..5041167
--- /dev/null
+++ b/tests/tests/opengl/src/android/opengl/cts/Vertex.java
@@ -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.
+ */
+package android.opengl.cts;
+
+public class Vertex {
+    public static String successfulcompile_vertex =
+          "attribute vec3 gtf_Normal; \n"
+        + "attribute vec4 gtf_Vertex; \n"
+        + "uniform mat3 gtf_NormalMatrix; \n"
+        + "uniform mat4 gtf_ModelViewMatrix; \n"
+        + "uniform mat4 gtf_ModelViewProjectionMatrix; \n"
+        + "\n"
+        + "varying float lightIntensity; \n"
+        + "varying vec3 Position; \n"
+        + "uniform vec3 LightPosition; \n"
+        + "uniform float Scale; \n"
+        + "\n"
+        + "void main(void) { \n"
+        + "    vec4 pos = gtf_ModelViewMatrix * gtf_Vertex; \n"
+        + "    Position = vec3(gtf_Vertex) * Scale; \n"
+        + "    vec3 tnorm = normalize(gtf_NormalMatrix * gtf_Normal); \n"
+        + "    lightIntensity = dot(normalize(LightPosition - vec3(pos)), tnorm) * 1.5; \n"
+        + "    gl_Position = gtf_ModelViewProjectionMatrix * gtf_Vertex; \n"
+        + "}";
+}
diff --git a/tests/tests/permission/src/android/permission/cts/PackageManagerRequiringPermissionsTest.java b/tests/tests/permission/src/android/permission/cts/PackageManagerRequiringPermissionsTest.java
index dca2bde..7ff67eb 100644
--- a/tests/tests/permission/src/android/permission/cts/PackageManagerRequiringPermissionsTest.java
+++ b/tests/tests/permission/src/android/permission/cts/PackageManagerRequiringPermissionsTest.java
@@ -81,4 +81,34 @@
             // expected
         }
     }
+
+    /**
+     * Verify that PackageManager.verifyPendingInstall requires permission.
+     * <p>Requires Permission:
+     *   {@link android.Manifest.permission#PACKAGE_VERIFICATION_AGENT}
+     */
+    public void testVerifyPendingInstall() {
+        try {
+            mPackageManager.verifyPendingInstall(1, 1);
+            fail("PackageManager.verifyPendingInstall did not throw SecurityException"
+                    + " as expected");
+        } catch (SecurityException e) {
+            // expected
+        }
+    }
+
+    /**
+     * Verify that PackageManager.extendVerificationTimeout requires permission.
+     * <p>Requires Permission:
+     *   {@link android.Manifest.permission#PACKAGE_VERIFICATION_AGENT}.
+     */
+    public void testExtendVerificationTimeout() {
+        try {
+            mPackageManager.extendVerificationTimeout(1, 1, 10000);
+            fail("PackageManager.extendVerificationTimeout did not throw SecurityException"
+                    + " as expected");
+        } catch (SecurityException e) {
+            // expected
+        }
+    }
 }
diff --git a/tests/tests/text/src/android/text/cts/StaticLayoutLineBreakingTest.java b/tests/tests/text/src/android/text/cts/StaticLayoutLineBreakingTest.java
index aa8874c..7e06697 100644
--- a/tests/tests/text/src/android/text/cts/StaticLayoutLineBreakingTest.java
+++ b/tests/tests/text/src/android/text/cts/StaticLayoutLineBreakingTest.java
@@ -20,14 +20,17 @@
 import android.text.SpannableStringBuilder;
 import android.text.Spanned;
 import android.text.StaticLayout;
+import android.text.TextDirectionHeuristics;
 import android.text.TextPaint;
 import android.text.Layout.Alignment;
 import android.text.style.MetricAffectingSpan;
+import android.util.Log;
 
 public class StaticLayoutLineBreakingTest extends AndroidTestCase {
     // Span test are currently not supported because text measurement uses the MeasuredText
     // internal mWorkPaint instead of the provided MockTestPaint.
     private static final boolean SPAN_TESTS_SUPPORTED = false;
+    private static final boolean DEBUG = false;
 
     private static final float SPACE_MULTI = 1.0f;
     private static final float SPACE_ADD = 0.0f;
@@ -89,7 +92,7 @@
             case 'L': return 50.0f;
             case 'C': return 100.0f; // equals to WIDTH
             case ' ': return 10.0f;
-            case '.': return 0.0f; // 0-width character
+            case '_': return 0.0f; // 0-width character
             case SURR_FIRST: return 7.0f;
             case SURR_SECOND: return 3.0f; // Sum of SURR_FIRST-SURR_SECOND is 10
             default: return 10.0f;
@@ -100,11 +103,13 @@
         return new StaticLayout(source, mTextPaint, width, ALIGN, SPACE_MULTI, SPACE_ADD, false);
     }
 
-    private static StaticLayout getStaticLayout(CharSequence source) {
-        return getStaticLayout(source, WIDTH);
+    private static int[] getBreaks(CharSequence source) {
+        return getBreaks(source, WIDTH);
     }
 
-    private static int[] getBreaks(StaticLayout staticLayout) {
+    private static int[] getBreaks(CharSequence source, int width) {
+        StaticLayout staticLayout = getStaticLayout(source, width);
+
         int[] breaks = new int[staticLayout.getLineCount() - 1];
         for (int line = 0; line < breaks.length; line++) {
             breaks[line] = staticLayout.getLineEnd(line);
@@ -112,14 +117,28 @@
         return breaks;
     }
 
-    private static void layout(CharSequence source, int[] breaks) {
-        StaticLayout staticLayout = getStaticLayout(source);
-        layout(staticLayout, source, breaks);
+    private static void debugLayout(CharSequence source, StaticLayout staticLayout) {
+        if (DEBUG) {
+            int count = staticLayout.getLineCount();
+            Log.i("StaticLayoutLineBreakingTest", "\"" + source.toString() + "\": " +
+                    count + " lines");
+            for (int line = 0; line < count; line++) {
+                int lineStart = staticLayout.getLineStart(line);
+                int lineEnd = staticLayout.getLineEnd(line);
+                Log.i("StaticLayoutLineBreakingTest", "Line " + line + " [" + lineStart + ".." +
+                        lineEnd + "]\t" + source.subSequence(lineStart, lineEnd));
+            }
+        }
     }
 
-    private static void layout(StaticLayout staticLayout, CharSequence source, int[] breaks) {
-        //Log.i("StaticLayoutLineWrappingTest", "String " + source.toString() + "; " +
-        //        staticLayout.getLineCount() + " lines");
+    private static void layout(CharSequence source, int[] breaks) {
+        layout(source, breaks, WIDTH);
+    }
+
+    private static void layout(CharSequence source, int[] breaks, int width) {
+        StaticLayout staticLayout = getStaticLayout(source, width);
+
+        debugLayout(source, staticLayout);
 
         int lineCount = breaks.length + 1;
         assertEquals("Number of lines", lineCount, staticLayout.getLineCount());
@@ -128,9 +147,6 @@
             int lineStart = staticLayout.getLineStart(line);
             int lineEnd = staticLayout.getLineEnd(line);
 
-            //Log.i("StaticLayoutLineWrappingTest", "Line " + line + " [" + lineStart + ".." +
-            //        lineEnd + "]\t" + source.subSequence(lineStart, lineEnd));
-
             if (line == 0) {
                 assertEquals("Line start for first line", 0, lineStart);
             } else {
@@ -145,6 +161,34 @@
         }
     }
 
+    private static void layoutMaxLines(CharSequence source, int[] breaks, int maxLines) {
+        StaticLayout staticLayout = new StaticLayout(source, 0, source.length(), mTextPaint, WIDTH,
+                ALIGN, TextDirectionHeuristics.LTR, SPACE_MULTI, SPACE_ADD, false /* includePad */,
+                null, WIDTH, maxLines);
+
+        debugLayout(source, staticLayout);
+
+        int lineCount = staticLayout.getLineCount();
+        assertTrue("Number of lines", lineCount <= maxLines);
+
+        for (int line = 0; line < lineCount; line++) {
+            int lineStart = staticLayout.getLineStart(line);
+            int lineEnd = staticLayout.getLineEnd(line);
+
+            if (line == 0) {
+                assertEquals("Line start for first line", 0, lineStart);
+            } else {
+                assertEquals("Line start for line " + line, breaks[line - 1], lineStart);
+            }
+
+            if (line == lineCount - 1 && line != breaks.length - 1) {
+                assertEquals("Line end for last line", source.length(), lineEnd);
+            } else {
+                assertEquals("Line end for line " + line, breaks[line], lineEnd);
+            }
+        }
+    }
+
     final static int MAX_SPAN_COUNT = 10;
     final static int[] spanStarts = new int[MAX_SPAN_COUNT];
     final static int[] spanEnds = new int[MAX_SPAN_COUNT];
@@ -218,7 +262,7 @@
         layout("  XX  XXX  ", NO_BREAK);
         layout("XX XXX XXX ", NO_BREAK);
         layout("XX XXX XXX     ", NO_BREAK);
-        layout("XXXXXXXXXX     ", new int[] {10}); // Bug, should be NO_BREAK as above
+        layout("XXXXXXXXXX     ", NO_BREAK);
         //      01234567890
     }
 
@@ -235,18 +279,18 @@
         layout("XXXXXXX XXX", new int[] {8});
         layout("XXXXXX XXXX", new int[] {7});
         //      01234567890
-        layout("LL LL", new int[] {2, 3}); // Bug: should be {3}
+        layout("LL LL", new int[] {3});
         layout("LLLL", new int[] {2});
-        layout("C C", new int[] {1, 2}); // Bug: should be {2}
+        layout("C C", new int[] {2});
         layout("CC", new int[] {1});
     }
 
     public void testSpaceAtBreak() {
         //      0123456789012
         layout("XXXX XXXXX X", new int[] {11});
-        layout("XXXXXXXXXX X", new int[] {10}); // Bug: should be {11}. Consume spaces in the non ok case too
-        layout("XXXXXXXXXV X", new int[] {10}); // Bug: should be {11}
-        layout("C X", new int[] {1}); // Should be 2
+        layout("XXXXXXXXXX X", new int[] {11});
+        layout("XXXXXXXXXV X", new int[] {11});
+        layout("C X", new int[] {2});
     }
 
     public void testMultipleSpacesAtBreak() {
@@ -260,10 +304,10 @@
 
     public void testZeroWidthCharacters() {
         //      0123456789012345678901234
-        layout("X.X.X.X.X.X.X.X.X.X", NO_BREAK);
-        layout("...X.X.X.X.X.X.X.X.X.X...", NO_BREAK);
-        layout("C.X", new int[] {2});
-        layout("C..X", new int[] {3});
+        layout("X_X_X_X_X_X_X_X_X_X", NO_BREAK);
+        layout("___X_X_X_X_X_X_X_X_X_X___", NO_BREAK);
+        layout("C_X", new int[] {2});
+        layout("C__X", new int[] {3});
     }
 
     /**
@@ -289,11 +333,6 @@
         layout(spanify("012 456 89 <LXX> XX XX"), new int[] {11, 18});
     }
 
-    public void testWithOverlappingSpans() {
-        // TODO Also try overlapping spans. The current implementation does not care, but would be
-        // good to have before any serious refactoring.
-    }
-
     /*
      * Adding a span to the string should not change the layout, since the metrics are unchanged.
      */
@@ -307,8 +346,7 @@
 
         for (String text : texts) {
             // Get the line breaks without any span
-            StaticLayout sl = getStaticLayout(text);
-            int[] breaks = getBreaks(sl);
+            int[] breaks = getBreaks(text);
 
             // Add spans on all possible offsets
             for (int spanStart = 0; spanStart < text.length(); spanStart++) {
@@ -333,8 +371,7 @@
 
         for (String text : texts) {
             // Get the line breaks without any span
-            StaticLayout sl = getStaticLayout(text);
-            int[] breaks = getBreaks(sl);
+            int[] breaks = getBreaks(text);
 
             // Add spans on all possible offsets
             for (int spanStart1 = 0; spanStart1 < text.length(); spanStart1++) {
@@ -355,8 +392,82 @@
         }
     }
 
-    public void testBreakCondition() {
-        // Try all the different line break characters, space, tab, ','...
+    public static String replace(String string, char c, char r) {
+        return string.replaceAll(String.valueOf(c), String.valueOf(r));
+    }
+
+    public void testClassIS() {
+        char[] classISCharacters = new char[] {'.', ',', ':', ';'};
+        char[] digitCharacters = new char[] {'0', '\u0660', '\u06F0', '\u0966', '\uFF10'};
+
+        for (char c : classISCharacters) {
+            // .,:; are class IS breakpoints...
+            //              01234567
+            layout(replace("L XXX#X", '#', c), new int[] {6});
+            layout(replace("L XXXX#X", '#', c), new int[] {2});
+
+            // ...except when adjacent to digits
+            for (char d : digitCharacters) {
+                //                      01234567
+                layout(replace(replace("L XX0#X", '#', c), '0', d), new int[] {2});
+                layout(replace(replace("L XXX#0", '#', c), '0', d), new int[] {2});
+                layout(replace(replace("L XXX0#X", '#', c), '0', d), new int[] {2});
+                layout(replace(replace("L XXXX#0", '#', c), '0', d), new int[] {2});
+            }
+        }
+    }
+
+    public void testClassSYandHY() {
+        char[] classSYorHYCharacters = new char[] {'/', '-'};
+        char[] digitCharacters = new char[] {'0', '\u0660', '\u06F0', '\u0966', '\uFF10'};
+
+        for (char c : classSYorHYCharacters) {
+            // / is a class SY breakpoint, - a class HY...
+            //              01234567
+            layout(replace("L XXX#X", '#', c), new int[] {6});
+            layout(replace("L XXXX#X", '#', c), new int[] {2});
+
+            // ...except when followed by a digits
+            for (char d : digitCharacters) {
+                //                      01234567
+                layout(replace(replace("L XX0#X", '#', c), '0', d), new int[] {6});
+                layout(replace(replace("L XXX#0", '#', c), '0', d), new int[] {2});
+                layout(replace(replace("L XXX0#X", '#', c), '0', d), new int[] {2});
+                layout(replace(replace("L XXXX#0", '#', c), '0', d), new int[] {2});
+            }
+        }
+    }
+
+    public void testClassID() {
+        char ideographic = '\u8a9e'; // regular ideographic character
+        char hyphen = '\u30A0'; // KATAKANA-HIRAGANA DOUBLE HYPHEN, ideographic but non starter
+
+        // Single ideographs are normal characters
+        layout("L XXX" + ideographic, NO_BREAK);
+        layout("L XXX" + ideographic + "X", new int[] {2});
+        layout("L XXXX" + ideographic, new int[] {2});
+        layout("L XXXX" + ideographic + "X", new int[] {2});
+
+        // Two adjacent ideographs create a possible breakpoint
+        layout("L X" + ideographic + ideographic + "X", NO_BREAK);
+        layout("L X" + ideographic + ideographic + "XX", new int[] {4});
+        layout("L XX" + ideographic + ideographic + "XX", new int[] {5});
+        layout("L XXX" + ideographic + ideographic + "X", new int[] {6});
+        layout("L XXXX" + ideographic + ideographic + "X", new int[] {2});
+
+        // Except when the second one is a non starter
+        layout("L X" + ideographic + hyphen + "X", NO_BREAK);
+        layout("L X" + ideographic + hyphen + "XX", new int[] {2});
+        layout("L XX" + ideographic + hyphen + "XX", new int[] {2});
+        layout("L XXX" + ideographic + hyphen + "X", new int[] {2});
+        layout("L XXXX" + ideographic + hyphen + "X", new int[] {2});
+
+        // When the non-starter is first, a pair of ideographic characters is a line break
+        layout("L X" + hyphen + ideographic + "X", NO_BREAK);
+        layout("L X" + hyphen + ideographic + "XX", new int[] {4});
+        layout("L XX" + hyphen + ideographic + "XX", new int[] {5});
+        layout("L XXX" + hyphen + ideographic + "X", new int[] {6});
+        layout("L XXXX" + hyphen + ideographic + "X", new int[] {2});
     }
 
     public void testReplacementSpan() {
@@ -387,19 +498,58 @@
 
     public void testNarrowWidth() {
         int[] widths = new int[] { 0, 4, 10 };
-        String[] texts = new String[] { "", "X", " ", "XX", "XX ", "X ", "XXX", "XXX ", "X X",
-            " X X " /* Bug "X  X", ".X..", "  ", "XX  ", "X." should work too */ };
+        String[] texts = new String[] { "", "X", " ", "XX", " X", "XXX" };
 
         for (String text: texts) {
             // 15 is such that only one character will fit
-            StaticLayout reference = getStaticLayout(text, 15);
-            int[] breaks = getBreaks(reference);
+            int[] breaks = getBreaks(text, 15);
 
             // Width under 15 should all lead to the same line break
             for (int width: widths) {
-                StaticLayout sl = getStaticLayout(text, width);
-                layout(sl, text, breaks);
+                layout(text, breaks, width);
             }
         }
     }
+
+    public void testNarrowWidthWithSpace() {
+        int[] widths = new int[] { 0, 4 };
+        for (int width: widths) {
+            layout("X ", new int[] {1}, width);
+            layout("X  ", new int[] {1}, width);
+            layout("XX ", new int[] {1, 2}, width);
+            layout("XX  ", new int[] {1, 2}, width);
+            layout("X  X", new int[] {1, 3}, width);
+            layout("X X", new int[] {1, 2}, width);
+
+            layout(" ", NO_BREAK, width);
+            layout(" X", new int[] {1}, width);
+            layout("  ", NO_BREAK, width);
+            layout(" X X", new int[] {1, 2, 3}, width);
+            layout("  X", new int[] {2}, width);
+        }
+    }
+
+    public void testNarrowWidthZeroWidth() {
+        int[] widths = new int[] { 0, 4 };
+        for (int width: widths) {
+            layout("X.", new int[] {1}, width);
+            layout("X__", new int[] {1}, width);
+            layout("X__X", new int[] {1, 3}, width); // Could be {1}
+            layout("X__X_", new int[] {1, 3, 4}, width); // Could be {1, 4}
+
+            layout("_", NO_BREAK, width);
+            layout("__", NO_BREAK, width);
+            layout("_X", new int[] {1}, width); // Could be NO_BREAK
+            layout("_X_", new int[] {1, 2}, width); // Could be {2}
+            layout("_X__", new int[] {1, 2}, width); // Could be {2}
+        }
+    }
+
+    public void testMaxLines() {
+        layoutMaxLines("C", NO_BREAK, 1);
+        layoutMaxLines("C C", new int[] {2}, 1);
+        layoutMaxLines("C C", new int[] {2}, 2);
+        layoutMaxLines("CC", new int[] {1}, 1);
+        layoutMaxLines("CC", new int[] {1}, 2);
+    }
 }
diff --git a/tests/tests/text/src/android/text/format/cts/DateUtilsTest.java b/tests/tests/text/src/android/text/format/cts/DateUtilsTest.java
index 1907ac7..25e6306 100644
--- a/tests/tests/text/src/android/text/format/cts/DateUtilsTest.java
+++ b/tests/tests/text/src/android/text/format/cts/DateUtilsTest.java
@@ -52,9 +52,9 @@
                 DateUtils.getDayOfWeekString(Calendar.SUNDAY, DateUtils.LENGTH_LONG));
         assertEquals("Sun",
                 DateUtils.getDayOfWeekString(Calendar.SUNDAY, DateUtils.LENGTH_MEDIUM));
-        assertEquals("Su",
+        assertEquals("Sun",
                 DateUtils.getDayOfWeekString(Calendar.SUNDAY, DateUtils.LENGTH_SHORT));
-        assertEquals("Su",
+        assertEquals("Sun",
                 DateUtils.getDayOfWeekString(Calendar.SUNDAY, DateUtils.LENGTH_SHORTER));
         assertEquals("S",
                 DateUtils.getDayOfWeekString(Calendar.SUNDAY, DateUtils.LENGTH_SHORTEST));
@@ -83,8 +83,8 @@
         if (!LocaleUtils.isCurrentLocale(mContext, Locale.US)) {
             return;
         }
-        assertEquals("am", DateUtils.getAMPMString(Calendar.AM));
-        assertEquals("pm", DateUtils.getAMPMString(Calendar.PM));
+        assertEquals("AM", DateUtils.getAMPMString(Calendar.AM));
+        assertEquals("PM", DateUtils.getAMPMString(Calendar.PM));
     }
 
 
@@ -169,7 +169,7 @@
                 + HOUR_DURATION, DateUtils.FORMAT_SHOW_WEEKDAY));
         assertEquals("January 19", DateUtils.formatDateRange(mContext, timeWithCurrentYear,
                 timeWithCurrentYear + HOUR_DURATION, DateUtils.FORMAT_SHOW_DATE));
-        assertEquals("3:30am", DateUtils.formatDateRange(mContext, fixedTime, fixedTime,
+        assertEquals("3:30AM", DateUtils.formatDateRange(mContext, fixedTime, fixedTime,
                 DateUtils.FORMAT_SHOW_TIME));
         assertEquals("January 19, 2009", DateUtils.formatDateRange(mContext, fixedTime,
                 fixedTime + HOUR_DURATION, DateUtils.FORMAT_SHOW_YEAR));
@@ -177,7 +177,7 @@
                 timeWithCurrentYear + HOUR_DURATION, DateUtils.FORMAT_NO_YEAR));
         assertEquals("January", DateUtils.formatDateRange(mContext, timeWithCurrentYear,
                 timeWithCurrentYear + HOUR_DURATION, DateUtils.FORMAT_NO_MONTH_DAY));
-        assertEquals("3:30am", DateUtils.formatDateRange(mContext, fixedTime, fixedTime,
+        assertEquals("3:30AM", DateUtils.formatDateRange(mContext, fixedTime, fixedTime,
                 DateUtils.FORMAT_12HOUR | DateUtils.FORMAT_SHOW_TIME));
         assertEquals("03:30", DateUtils.formatDateRange(mContext, fixedTime, fixedTime,
                 DateUtils.FORMAT_24HOUR | DateUtils.FORMAT_SHOW_TIME));
@@ -188,14 +188,14 @@
         assertEquals("Noon", DateUtils.formatDateRange(mContext, fixedTime + noonDuration,
                 fixedTime + noonDuration,
                 DateUtils.FORMAT_12HOUR | DateUtils.FORMAT_SHOW_TIME | DateUtils.FORMAT_CAP_NOON));
-        assertEquals("12:00pm", DateUtils.formatDateRange(mContext, fixedTime + noonDuration,
+        assertEquals("12:00PM", DateUtils.formatDateRange(mContext, fixedTime + noonDuration,
                 fixedTime + noonDuration,
                 DateUtils.FORMAT_12HOUR | DateUtils.FORMAT_NO_NOON | DateUtils.FORMAT_SHOW_TIME));
-        assertEquals("12:00am", DateUtils.formatDateRange(mContext, fixedTime - midnightDuration,
+        assertEquals("12:00AM", DateUtils.formatDateRange(mContext, fixedTime - midnightDuration,
                 fixedTime - midnightDuration,
                 DateUtils.FORMAT_12HOUR | DateUtils.FORMAT_SHOW_TIME
                 | DateUtils.FORMAT_NO_MIDNIGHT));
-        assertEquals("3:30am", DateUtils.formatDateRange(mContext, fixedTime, fixedTime,
+        assertEquals("3:30AM", DateUtils.formatDateRange(mContext, fixedTime, fixedTime,
                 DateUtils.FORMAT_SHOW_TIME | DateUtils.FORMAT_UTC));
         assertEquals("3am", DateUtils.formatDateRange(mContext, fixedTime - integralDuration,
                 fixedTime - integralDuration,
diff --git a/tests/tests/text/src/android/text/format/cts/TimeTest.java b/tests/tests/text/src/android/text/format/cts/TimeTest.java
index c1587ae..98ba55f 100644
--- a/tests/tests/text/src/android/text/format/cts/TimeTest.java
+++ b/tests/tests/text/src/android/text/format/cts/TimeTest.java
@@ -125,6 +125,49 @@
         }
     }
 
+    public void testParseNull() {
+        Time t = new Time();
+        try {
+            t.parse(null);
+            fail();
+        } catch (NullPointerException expected) {
+        }
+
+        try {
+            t.parse3339(null);
+            fail();
+        } catch (NullPointerException expected) {
+        }
+    }
+
+    // http://code.google.com/p/android/issues/detail?id=16002
+    // We'd leak one JNI global reference each time parsing failed.
+    // This would cause a crash when we filled the global reference table.
+    public void testBug16002() {
+        Time t = new Time();
+        for (int i = 0; i < 8192; ++i) {
+            try {
+                t.parse3339("xxx");
+                fail();
+            } catch (TimeFormatException expected) {
+            }
+        }
+    }
+
+    // http://code.google.com/p/android/issues/detail?id=22225
+    // We'd leak one JNI global reference each time parsing failed.
+    // This would cause a crash when we filled the global reference table.
+    public void testBug22225() {
+        Time t = new Time();
+        for (int i = 0; i < 8192; ++i) {
+            try {
+                t.parse("xxx");
+                fail();
+            } catch (TimeFormatException expected) {
+            }
+        }
+    }
+
     public void testIsEpoch() {
         Time time = new Time();
         assertTrue(Time.isEpoch(time));
diff --git a/tests/tests/view/src/android/view/cts/GravityTest.java b/tests/tests/view/src/android/view/cts/GravityTest.java
index 86bbb2c..86b1283 100644
--- a/tests/tests/view/src/android/view/cts/GravityTest.java
+++ b/tests/tests/view/src/android/view/cts/GravityTest.java
@@ -16,6 +16,7 @@
 
 package android.view.cts;
 
+import android.test.suitebuilder.annotation.SmallTest;
 import android.view.View;
 
 import android.graphics.Rect;
@@ -288,4 +289,55 @@
         assertEquals(30, inoutRect.top);
         assertEquals(50, inoutRect.bottom);
     }
+
+    @SmallTest
+    public void testGetAbsoluteGravity() throws Exception {
+        assertOneGravity(Gravity.LEFT, Gravity.LEFT, false);
+        assertOneGravity(Gravity.LEFT, Gravity.LEFT, true);
+
+        assertOneGravity(Gravity.RIGHT, Gravity.RIGHT, false);
+        assertOneGravity(Gravity.RIGHT, Gravity.RIGHT, true);
+
+        assertOneGravity(Gravity.TOP, Gravity.TOP, false);
+        assertOneGravity(Gravity.TOP, Gravity.TOP, true);
+
+        assertOneGravity(Gravity.BOTTOM, Gravity.BOTTOM, false);
+        assertOneGravity(Gravity.BOTTOM, Gravity.BOTTOM, true);
+
+        assertOneGravity(Gravity.CENTER_VERTICAL, Gravity.CENTER_VERTICAL, false);
+        assertOneGravity(Gravity.CENTER_VERTICAL, Gravity.CENTER_VERTICAL, true);
+
+        assertOneGravity(Gravity.CENTER_HORIZONTAL, Gravity.CENTER_HORIZONTAL, false);
+        assertOneGravity(Gravity.CENTER_HORIZONTAL, Gravity.CENTER_HORIZONTAL, true);
+
+        assertOneGravity(Gravity.CENTER, Gravity.CENTER, false);
+        assertOneGravity(Gravity.CENTER, Gravity.CENTER, true);
+
+        assertOneGravity(Gravity.FILL_VERTICAL, Gravity.FILL_VERTICAL, false);
+        assertOneGravity(Gravity.FILL_VERTICAL, Gravity.FILL_VERTICAL, true);
+
+        assertOneGravity(Gravity.FILL_HORIZONTAL, Gravity.FILL_HORIZONTAL, false);
+        assertOneGravity(Gravity.FILL_HORIZONTAL, Gravity.FILL_HORIZONTAL, true);
+
+        assertOneGravity(Gravity.FILL, Gravity.FILL, false);
+        assertOneGravity(Gravity.FILL, Gravity.FILL, true);
+
+        assertOneGravity(Gravity.CLIP_HORIZONTAL, Gravity.CLIP_HORIZONTAL, false);
+        assertOneGravity(Gravity.CLIP_HORIZONTAL, Gravity.CLIP_HORIZONTAL, true);
+
+        assertOneGravity(Gravity.CLIP_VERTICAL, Gravity.CLIP_VERTICAL, false);
+        assertOneGravity(Gravity.CLIP_VERTICAL, Gravity.CLIP_VERTICAL, true);
+
+        assertOneGravity(Gravity.LEFT, Gravity.START, false);
+        assertOneGravity(Gravity.RIGHT, Gravity.START, true);
+
+        assertOneGravity(Gravity.RIGHT, Gravity.END, false);
+        assertOneGravity(Gravity.LEFT, Gravity.END, true);
+    }
+
+    private void assertOneGravity(int expected, int initial, boolean isRtl) {
+        final int layoutDirection = isRtl ? View.LAYOUT_DIRECTION_RTL : View.LAYOUT_DIRECTION_LTR;
+
+        assertEquals(expected, Gravity.getAbsoluteGravity(initial, layoutDirection));
+    }
 }
diff --git a/tests/tests/view/src/android/view/cts/LocaleUtilTest.java b/tests/tests/view/src/android/view/cts/LocaleUtilTest.java
new file mode 100644
index 0000000..d80ebbe
--- /dev/null
+++ b/tests/tests/view/src/android/view/cts/LocaleUtilTest.java
@@ -0,0 +1,204 @@
+/*
+ * 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.view.cts;
+
+import android.test.AndroidTestCase;
+import android.util.LocaleUtil;
+import dalvik.annotation.TestLevel;
+import dalvik.annotation.TestTargetNew;
+
+import java.util.Locale;
+
+import static android.view.View.LAYOUT_DIRECTION_LTR;
+import static android.view.View.LAYOUT_DIRECTION_RTL;
+
+/**
+ * Test {@link LocaleUtil}.
+ */
+public class LocaleUtilTest extends AndroidTestCase {
+
+    @TestTargetNew(
+            level = TestLevel.COMPLETE,
+            method = "getLayoutDirectionFromLocale",
+            args = {Locale.class}
+    )
+    public void testGetLayoutDirectionFromLocale() {
+        assertEquals(LAYOUT_DIRECTION_LTR,
+                LocaleUtil.getLayoutDirectionFromLocale(null));
+
+        assertEquals(LAYOUT_DIRECTION_LTR,
+                LocaleUtil.getLayoutDirectionFromLocale(Locale.ENGLISH));
+        assertEquals(LAYOUT_DIRECTION_LTR,
+                LocaleUtil.getLayoutDirectionFromLocale(Locale.CANADA));
+        assertEquals(LAYOUT_DIRECTION_LTR,
+                LocaleUtil.getLayoutDirectionFromLocale(Locale.CANADA_FRENCH));
+        assertEquals(LAYOUT_DIRECTION_LTR,
+                LocaleUtil.getLayoutDirectionFromLocale(Locale.FRANCE));
+        assertEquals(LAYOUT_DIRECTION_LTR,
+                LocaleUtil.getLayoutDirectionFromLocale(Locale.FRENCH));
+        assertEquals(LAYOUT_DIRECTION_LTR,
+                LocaleUtil.getLayoutDirectionFromLocale(Locale.GERMAN));
+        assertEquals(LAYOUT_DIRECTION_LTR,
+                LocaleUtil.getLayoutDirectionFromLocale(Locale.GERMANY));
+        assertEquals(LAYOUT_DIRECTION_LTR,
+                LocaleUtil.getLayoutDirectionFromLocale(Locale.ITALIAN));
+        assertEquals(LAYOUT_DIRECTION_LTR,
+                LocaleUtil.getLayoutDirectionFromLocale(Locale.ITALY));
+        assertEquals(LAYOUT_DIRECTION_LTR,
+                LocaleUtil.getLayoutDirectionFromLocale(Locale.UK));
+        assertEquals(LAYOUT_DIRECTION_LTR,
+                LocaleUtil.getLayoutDirectionFromLocale(Locale.US));
+
+        assertEquals(LAYOUT_DIRECTION_LTR,
+                LocaleUtil.getLayoutDirectionFromLocale(Locale.ROOT));
+
+        assertEquals(LAYOUT_DIRECTION_LTR,
+                LocaleUtil.getLayoutDirectionFromLocale(Locale.CHINA));
+        assertEquals(LAYOUT_DIRECTION_LTR,
+                LocaleUtil.getLayoutDirectionFromLocale(Locale.CHINESE));
+        assertEquals(LAYOUT_DIRECTION_LTR,
+                LocaleUtil.getLayoutDirectionFromLocale(Locale.JAPAN));
+        assertEquals(LAYOUT_DIRECTION_LTR,
+                LocaleUtil.getLayoutDirectionFromLocale(Locale.JAPANESE));
+        assertEquals(LAYOUT_DIRECTION_LTR,
+                LocaleUtil.getLayoutDirectionFromLocale(Locale.KOREA));
+        assertEquals(LAYOUT_DIRECTION_LTR,
+                LocaleUtil.getLayoutDirectionFromLocale(Locale.KOREAN));
+        assertEquals(LAYOUT_DIRECTION_LTR,
+                LocaleUtil.getLayoutDirectionFromLocale(Locale.PRC));
+        assertEquals(LAYOUT_DIRECTION_LTR,
+                LocaleUtil.getLayoutDirectionFromLocale(Locale.SIMPLIFIED_CHINESE));
+        assertEquals(LAYOUT_DIRECTION_LTR,
+                LocaleUtil.getLayoutDirectionFromLocale(Locale.TAIWAN));
+        assertEquals(LAYOUT_DIRECTION_LTR,
+                LocaleUtil.getLayoutDirectionFromLocale(Locale.TRADITIONAL_CHINESE));
+
+        Locale locale = new Locale("ar");
+        assertEquals(LAYOUT_DIRECTION_RTL,
+                LocaleUtil.getLayoutDirectionFromLocale(locale));
+        locale = new Locale("ar", "AE");
+        assertEquals(LAYOUT_DIRECTION_RTL,
+                LocaleUtil.getLayoutDirectionFromLocale(locale));
+        locale = new Locale("ar", "BH");
+        assertEquals(LAYOUT_DIRECTION_RTL,
+                LocaleUtil.getLayoutDirectionFromLocale(locale));
+        locale = new Locale("ar", "DZ");
+        assertEquals(LAYOUT_DIRECTION_RTL,
+                LocaleUtil.getLayoutDirectionFromLocale(locale));
+        locale = new Locale("ar", "EG");
+        assertEquals(LAYOUT_DIRECTION_RTL,
+                LocaleUtil.getLayoutDirectionFromLocale(locale));
+        locale = new Locale("ar", "IQ");
+        assertEquals(LAYOUT_DIRECTION_RTL,
+                LocaleUtil.getLayoutDirectionFromLocale(locale));
+        locale = new Locale("ar", "JO");
+        assertEquals(LAYOUT_DIRECTION_RTL,
+                LocaleUtil.getLayoutDirectionFromLocale(locale));
+        locale = new Locale("ar", "KW");
+        assertEquals(LAYOUT_DIRECTION_RTL,
+                LocaleUtil.getLayoutDirectionFromLocale(locale));
+        locale = new Locale("ar", "LB");
+        assertEquals(LAYOUT_DIRECTION_RTL,
+                LocaleUtil.getLayoutDirectionFromLocale(locale));
+        locale = new Locale("ar", "LY");
+        assertEquals(LAYOUT_DIRECTION_RTL,
+                LocaleUtil.getLayoutDirectionFromLocale(locale));
+        locale = new Locale("ar", "MA");
+        assertEquals(LAYOUT_DIRECTION_RTL,
+                LocaleUtil.getLayoutDirectionFromLocale(locale));
+        locale = new Locale("ar", "OM");
+        assertEquals(LAYOUT_DIRECTION_RTL,
+                LocaleUtil.getLayoutDirectionFromLocale(locale));
+        locale = new Locale("ar", "QA");
+        assertEquals(LAYOUT_DIRECTION_RTL,
+                LocaleUtil.getLayoutDirectionFromLocale(locale));
+        locale = new Locale("ar", "SA");
+        assertEquals(LAYOUT_DIRECTION_RTL,
+                LocaleUtil.getLayoutDirectionFromLocale(locale));
+        locale = new Locale("ar", "SD");
+        assertEquals(LAYOUT_DIRECTION_RTL,
+                LocaleUtil.getLayoutDirectionFromLocale(locale));
+        locale = new Locale("ar", "SY");
+        assertEquals(LAYOUT_DIRECTION_RTL,
+                LocaleUtil.getLayoutDirectionFromLocale(locale));
+        locale = new Locale("ar", "TN");
+        assertEquals(LAYOUT_DIRECTION_RTL,
+                LocaleUtil.getLayoutDirectionFromLocale(locale));
+        locale = new Locale("ar", "YE");
+        assertEquals(LAYOUT_DIRECTION_RTL,
+                LocaleUtil.getLayoutDirectionFromLocale(locale));
+
+        locale = new Locale("fa");
+        assertEquals(LAYOUT_DIRECTION_RTL,
+                LocaleUtil.getLayoutDirectionFromLocale(locale));
+        locale = new Locale("fa", "AF");
+        assertEquals(LAYOUT_DIRECTION_RTL,
+                LocaleUtil.getLayoutDirectionFromLocale(locale));
+        locale = new Locale("fa", "IR");
+        assertEquals(LAYOUT_DIRECTION_RTL,
+                LocaleUtil.getLayoutDirectionFromLocale(locale));
+
+        locale = new Locale("iw");
+        assertEquals(LAYOUT_DIRECTION_RTL,
+                LocaleUtil.getLayoutDirectionFromLocale(locale));
+        locale = new Locale("iw", "IL");
+        assertEquals(LAYOUT_DIRECTION_RTL,
+                LocaleUtil.getLayoutDirectionFromLocale(locale));
+        locale = new Locale("he");
+        assertEquals(LAYOUT_DIRECTION_RTL,
+                LocaleUtil.getLayoutDirectionFromLocale(locale));
+        locale = new Locale("he", "IL");
+        assertEquals(LAYOUT_DIRECTION_RTL,
+                LocaleUtil.getLayoutDirectionFromLocale(locale));
+
+        locale = new Locale("pa_Arab");
+        assertEquals(LAYOUT_DIRECTION_RTL,
+                LocaleUtil.getLayoutDirectionFromLocale(locale));
+        locale = new Locale("pa_Arab", "PK");
+        assertEquals(LAYOUT_DIRECTION_RTL,
+                LocaleUtil.getLayoutDirectionFromLocale(locale));
+
+        locale = new Locale("ps");
+        assertEquals(LAYOUT_DIRECTION_RTL,
+                LocaleUtil.getLayoutDirectionFromLocale(locale));
+        locale = new Locale("ps", "AF");
+        assertEquals(LAYOUT_DIRECTION_RTL,
+                LocaleUtil.getLayoutDirectionFromLocale(locale));
+
+        locale = new Locale("ur");
+        assertEquals(LAYOUT_DIRECTION_RTL,
+                LocaleUtil.getLayoutDirectionFromLocale(locale));
+        locale = new Locale("ur", "IN");
+        assertEquals(LAYOUT_DIRECTION_RTL,
+                LocaleUtil.getLayoutDirectionFromLocale(locale));
+        locale = new Locale("ur", "PK");
+        assertEquals(LAYOUT_DIRECTION_RTL,
+                LocaleUtil.getLayoutDirectionFromLocale(locale));
+
+        locale = new Locale("uz_Arab");
+        assertEquals(LAYOUT_DIRECTION_RTL,
+                LocaleUtil.getLayoutDirectionFromLocale(locale));
+        locale = new Locale("uz_Arab", "AF");
+        assertEquals(LAYOUT_DIRECTION_RTL,
+                LocaleUtil.getLayoutDirectionFromLocale(locale));
+
+        // Locale without a real language
+        locale = new Locale("zz");
+        assertEquals(LAYOUT_DIRECTION_LTR,
+                LocaleUtil.getLayoutDirectionFromLocale(locale));
+    }
+}
\ No newline at end of file
diff --git a/tests/tests/view/src/android/view/cts/ViewGroupTest.java b/tests/tests/view/src/android/view/cts/ViewGroupTest.java
index e975a27..1fc9a88 100644
--- a/tests/tests/view/src/android/view/cts/ViewGroupTest.java
+++ b/tests/tests/view/src/android/view/cts/ViewGroupTest.java
@@ -1496,6 +1496,8 @@
         assertEquals(0, vg.getPaddingTop());
         assertEquals(0, vg.getPaddingLeft());
         assertEquals(0, vg.getPaddingRight());
+        assertEquals(0, vg.getPaddingStart());
+        assertEquals(0, vg.getPaddingEnd());
 
         vg.setPadding(left, top, right, bottom);
 
@@ -1503,6 +1505,83 @@
         assertEquals(top, vg.getPaddingTop());
         assertEquals(left, vg.getPaddingLeft());
         assertEquals(right, vg.getPaddingRight());
+
+        assertEquals(left, vg.getPaddingStart());
+        assertEquals(right, vg.getPaddingEnd());
+        assertEquals(false, vg.isPaddingRelative());
+
+        // force RTL direction
+        vg.setLayoutDirection(View.LAYOUT_DIRECTION_RTL);
+
+        assertEquals(bottom, vg.getPaddingBottom());
+        assertEquals(top, vg.getPaddingTop());
+        assertEquals(left, vg.getPaddingLeft());
+        assertEquals(right, vg.getPaddingRight());
+
+        assertEquals(right, vg.getPaddingStart());
+        assertEquals(left, vg.getPaddingEnd());
+        assertEquals(false, vg.isPaddingRelative());
+    }
+
+    public void testSetPaddingRelative() {
+        final int start = 1;
+        final int top = 2;
+        final int end = 3;
+        final int bottom = 4;
+
+        MockViewGroup vg = new MockViewGroup(mContext);
+
+        assertEquals(0, vg.getPaddingBottom());
+        assertEquals(0, vg.getPaddingTop());
+        assertEquals(0, vg.getPaddingLeft());
+        assertEquals(0, vg.getPaddingRight());
+        assertEquals(0, vg.getPaddingStart());
+        assertEquals(0, vg.getPaddingEnd());
+
+        vg.setPaddingRelative(start, top, end, bottom);
+
+        assertEquals(bottom, vg.getPaddingBottom());
+        assertEquals(top, vg.getPaddingTop());
+        assertEquals(start, vg.getPaddingLeft());
+        assertEquals(end, vg.getPaddingRight());
+
+        assertEquals(start, vg.getPaddingStart());
+        assertEquals(end, vg.getPaddingEnd());
+        assertEquals(true, vg.isPaddingRelative());
+
+        // force RTL direction after setting relative padding
+        vg.setLayoutDirection(View.LAYOUT_DIRECTION_RTL);
+
+        assertEquals(bottom, vg.getPaddingBottom());
+        assertEquals(top, vg.getPaddingTop());
+        assertEquals(end, vg.getPaddingLeft());
+        assertEquals(start, vg.getPaddingRight());
+
+        assertEquals(start, vg.getPaddingStart());
+        assertEquals(end, vg.getPaddingEnd());
+        assertEquals(true, vg.isPaddingRelative());
+
+        // force RTL direction before setting relative padding
+        vg = new MockViewGroup(mContext);
+        vg.setLayoutDirection(View.LAYOUT_DIRECTION_RTL);
+
+        assertEquals(0, vg.getPaddingBottom());
+        assertEquals(0, vg.getPaddingTop());
+        assertEquals(0, vg.getPaddingLeft());
+        assertEquals(0, vg.getPaddingRight());
+        assertEquals(0, vg.getPaddingStart());
+        assertEquals(0, vg.getPaddingEnd());
+
+        vg.setPaddingRelative(start, top, end, bottom);
+
+        assertEquals(bottom, vg.getPaddingBottom());
+        assertEquals(top, vg.getPaddingTop());
+        assertEquals(end, vg.getPaddingLeft());
+        assertEquals(start, vg.getPaddingRight());
+
+        assertEquals(start, vg.getPaddingStart());
+        assertEquals(end, vg.getPaddingEnd());
+        assertEquals(true, vg.isPaddingRelative());
     }
 
     public void testSetPersistentDrawingCache() {
diff --git a/tests/tests/view/src/android/view/cts/ViewGroup_MarginLayoutParamsTest.java b/tests/tests/view/src/android/view/cts/ViewGroup_MarginLayoutParamsTest.java
index d92fd9b..397735f 100644
--- a/tests/tests/view/src/android/view/cts/ViewGroup_MarginLayoutParamsTest.java
+++ b/tests/tests/view/src/android/view/cts/ViewGroup_MarginLayoutParamsTest.java
@@ -81,7 +81,92 @@
         assertEquals(120, mMarginLayoutParams.rightMargin);
         assertEquals(140, mMarginLayoutParams.bottomMargin);
 
-        assertEquals(Integer.MIN_VALUE, mMarginLayoutParams.startMargin);
-        assertEquals(Integer.MIN_VALUE, mMarginLayoutParams.endMargin);
+        assertEquals(Integer.MIN_VALUE, mMarginLayoutParams.getMarginStart());
+        assertEquals(Integer.MIN_VALUE, mMarginLayoutParams.getMarginEnd());
+
+        assertEquals(false, mMarginLayoutParams.isMarginRelative());
+    }
+
+    public void testSetMarginsRelative() {
+        // create a new MarginLayoutParams instance
+        mMarginLayoutParams = new ViewGroup.MarginLayoutParams(320, 480);
+        mMarginLayoutParams.setMarginsRelative(20, 30, 120, 140);
+        assertEquals(20, mMarginLayoutParams.getMarginStart());
+        assertEquals(30, mMarginLayoutParams.topMargin);
+        assertEquals(120, mMarginLayoutParams.getMarginEnd());
+        assertEquals(140, mMarginLayoutParams.bottomMargin);
+
+        assertEquals(0, mMarginLayoutParams.leftMargin);
+        assertEquals(0, mMarginLayoutParams.rightMargin);
+
+        assertEquals(true, mMarginLayoutParams.isMarginRelative());
+    }
+
+    public void testResolveMarginsRelative() {
+        ViewGroup vg = new LinearLayout(mContext);
+
+        // LTR / normal margin case
+        mMarginLayoutParams = new ViewGroup.MarginLayoutParams(320, 480);
+        mMarginLayoutParams.setMargins(20, 30, 120, 140);
+        vg.setLayoutParams(mMarginLayoutParams);
+        vg.requestLayout();
+
+        assertEquals(20, mMarginLayoutParams.leftMargin);
+        assertEquals(30, mMarginLayoutParams.topMargin);
+        assertEquals(120, mMarginLayoutParams.rightMargin);
+        assertEquals(140, mMarginLayoutParams.bottomMargin);
+
+        assertEquals(Integer.MIN_VALUE, mMarginLayoutParams.getMarginStart());
+        assertEquals(Integer.MIN_VALUE, mMarginLayoutParams.getMarginEnd());
+
+        assertEquals(false, mMarginLayoutParams.isMarginRelative());
+
+        // LTR / relative margin case
+        mMarginLayoutParams.setMarginsRelative(20, 30, 120, 140);
+        vg.setLayoutParams(mMarginLayoutParams);
+        vg.requestLayout();
+
+        assertEquals(20, mMarginLayoutParams.getMarginStart());
+        assertEquals(30, mMarginLayoutParams.topMargin);
+        assertEquals(120, mMarginLayoutParams.getMarginEnd());
+        assertEquals(140, mMarginLayoutParams.bottomMargin);
+
+        assertEquals(20, mMarginLayoutParams.leftMargin);
+        assertEquals(120, mMarginLayoutParams.rightMargin);
+
+        assertEquals(true, mMarginLayoutParams.isMarginRelative());
+
+        // RTL / normal margin case
+        vg.setLayoutDirection(View.LAYOUT_DIRECTION_RTL);
+
+        mMarginLayoutParams = new ViewGroup.MarginLayoutParams(320, 480);
+        mMarginLayoutParams.setMargins(20, 30, 120, 140);
+        vg.setLayoutParams(mMarginLayoutParams);
+        vg.requestLayout();
+
+        assertEquals(20, mMarginLayoutParams.leftMargin);
+        assertEquals(30, mMarginLayoutParams.topMargin);
+        assertEquals(120, mMarginLayoutParams.rightMargin);
+        assertEquals(140, mMarginLayoutParams.bottomMargin);
+
+        assertEquals(Integer.MIN_VALUE, mMarginLayoutParams.getMarginStart());
+        assertEquals(Integer.MIN_VALUE, mMarginLayoutParams.getMarginEnd());
+
+        assertEquals(false, mMarginLayoutParams.isMarginRelative());
+
+        // RTL / relative margin case
+        mMarginLayoutParams.setMarginsRelative(20, 30, 120, 140);
+        vg.setLayoutParams(mMarginLayoutParams);
+        vg.requestLayout();
+
+        assertEquals(20, mMarginLayoutParams.getMarginStart());
+        assertEquals(30, mMarginLayoutParams.topMargin);
+        assertEquals(120, mMarginLayoutParams.getMarginEnd());
+        assertEquals(140, mMarginLayoutParams.bottomMargin);
+
+        assertEquals(120, mMarginLayoutParams.leftMargin);
+        assertEquals(20, mMarginLayoutParams.rightMargin);
+
+        assertEquals(true, mMarginLayoutParams.isMarginRelative());
     }
 }
diff --git a/tests/tests/view/src/android/view/cts/ViewTest.java b/tests/tests/view/src/android/view/cts/ViewTest.java
index 9065592..288552d 100644
--- a/tests/tests/view/src/android/view/cts/ViewTest.java
+++ b/tests/tests/view/src/android/view/cts/ViewTest.java
@@ -61,7 +61,7 @@
 import android.view.ViewConfiguration;
 import android.view.ViewGroup;
 import android.view.ViewParent;
-import android.view.WindowManagerImpl;
+import android.view.WindowManager;
 import android.view.accessibility.AccessibilityEvent;
 import android.view.animation.AlphaAnimation;
 import android.view.animation.Animation;
@@ -2730,7 +2730,8 @@
         Rect outRect = new Rect();
         View view = new View(mActivity);
         // mAttachInfo is null
-        Display d = WindowManagerImpl.getDefault().getDefaultDisplay();
+        WindowManager wm = (WindowManager)mActivity.getSystemService(Context.WINDOW_SERVICE);
+        Display d = wm.getDefaultDisplay();
         view.getWindowVisibleDisplayFrame(outRect);
         assertEquals(0, outRect.left);
         assertEquals(0, outRect.top);
@@ -3388,11 +3389,6 @@
         public void childAccessibilityStateChanged(View child) {
 
         }
-
-        @Override
-        public View findViewToTakeAccessibilityFocusFromHover(View child, View descendant) {
-            return null;
-        }
     }
 
     private final class OnCreateContextMenuListenerImpl implements OnCreateContextMenuListener {
diff --git a/tests/tests/webkit/src/android/webkit/cts/WebSettingsTest.java b/tests/tests/webkit/src/android/webkit/cts/WebSettingsTest.java
index 1bc8a4f..054217e 100644
--- a/tests/tests/webkit/src/android/webkit/cts/WebSettingsTest.java
+++ b/tests/tests/webkit/src/android/webkit/cts/WebSettingsTest.java
@@ -235,9 +235,6 @@
         Thread.sleep(100); // Wait for open to be received on the icon db thread.
         assertEquals(WebSettings.LOAD_DEFAULT, mSettings.getCacheMode());
 
-        mSettings.setCacheMode(WebSettings.LOAD_NORMAL);
-        assertEquals(WebSettings.LOAD_NORMAL, mSettings.getCacheMode());
-
         mSettings.setCacheMode(WebSettings.LOAD_CACHE_ELSE_NETWORK);
         assertEquals(WebSettings.LOAD_CACHE_ELSE_NETWORK, mSettings.getCacheMode());
         final IconListenerClient iconListener = new IconListenerClient();
diff --git a/tests/tests/webkit/src/android/webkit/cts/WebViewTest.java b/tests/tests/webkit/src/android/webkit/cts/WebViewTest.java
index 3f7ea78..6c66f52 100755
--- a/tests/tests/webkit/src/android/webkit/cts/WebViewTest.java
+++ b/tests/tests/webkit/src/android/webkit/cts/WebViewTest.java
@@ -45,6 +45,7 @@
 import android.webkit.CacheManager.CacheResult;
 import android.webkit.ConsoleMessage;
 import android.webkit.DownloadListener;
+import android.webkit.JavascriptInterface;
 import android.webkit.SslErrorHandler;
 import android.webkit.WebBackForwardList;
 import android.webkit.WebChromeClient;
@@ -411,6 +412,7 @@
                 return mWasProvideResultCalled;
             }
 
+            @JavascriptInterface
             public synchronized void provideResult(String result) {
                 mWasProvideResultCalled = true;
                 mResult = result;
@@ -483,9 +485,12 @@
     public void testUseRemovedJavascriptInterface() throws Throwable {
         class RemovedObject {
             @Override
+            @JavascriptInterface
             public String toString() {
                 return "removedObject";
             }
+
+            @JavascriptInterface
             public void remove() throws Throwable {
                 mOnUiThread.removeJavascriptInterface("removedObject");
                 System.gc();
@@ -494,6 +499,8 @@
         class ResultObject {
             private String mResult;
             private boolean mIsResultAvailable;
+
+            @JavascriptInterface
             public synchronized void setResult(String result) {
                 mResult = result;
                 mIsResultAvailable = true;
@@ -1170,6 +1177,7 @@
         final class ImageLoaded {
             public boolean mImageLoaded;
 
+            @JavascriptInterface
             public void loaded() {
                 mImageLoaded = true;
             }
@@ -1769,6 +1777,8 @@
     public void testPauseResumeTimers() throws Throwable {
         class Monitor {
             private boolean mIsUpdated;
+
+            @JavascriptInterface
             public synchronized void update() {
                 mIsUpdated  = true;
                 notify();
diff --git a/tests/tests/widget/src/android/widget/cts/AutoCompleteTextViewTest.java b/tests/tests/widget/src/android/widget/cts/AutoCompleteTextViewTest.java
index 760a160..0198b10 100755
--- a/tests/tests/widget/src/android/widget/cts/AutoCompleteTextViewTest.java
+++ b/tests/tests/widget/src/android/widget/cts/AutoCompleteTextViewTest.java
@@ -515,13 +515,11 @@
         // re-set 'clicked' flag to false
         listener.clearItemClickedStatus();
 
-
         runTestOnUiThread(new Runnable() {
             public void run() {
                 mAutoCompleteTextView.showDropDown();
             }
         });
-        mInstrumentation.waitForIdleSync();
         mInstrumentation.sendKeyDownUpSync(KeyEvent.KEYCODE_DPAD_DOWN);
         mInstrumentation.sendKeyDownUpSync(KeyEvent.KEYCODE_DPAD_CENTER);
         assertTrue(listener.isOnItemClicked());
@@ -534,7 +532,6 @@
                 mAutoCompleteTextView.showDropDown();
             }
         });
-        mInstrumentation.waitForIdleSync();
         mInstrumentation.sendKeyDownUpSync(KeyEvent.KEYCODE_DPAD_DOWN);
         // Test normal key code.
         mInstrumentation.sendKeyDownUpSync(KeyEvent.KEYCODE_0);
@@ -550,7 +547,7 @@
                mAutoCompleteTextView.dismissDropDown();
             }
         });
-        mInstrumentation.waitForIdleSync();
+
         mInstrumentation.sendKeyDownUpSync(KeyEvent.KEYCODE_DPAD_DOWN);
         mInstrumentation.sendKeyDownUpSync(KeyEvent.KEYCODE_ENTER);
         assertFalse(listener.isOnItemClicked());
diff --git a/tests/tests/widget/src/android/widget/cts/LayoutDirectionTest.java b/tests/tests/widget/src/android/widget/cts/LayoutDirectionTest.java
new file mode 100644
index 0000000..2c4c798
--- /dev/null
+++ b/tests/tests/widget/src/android/widget/cts/LayoutDirectionTest.java
@@ -0,0 +1,179 @@
+/*
+ * 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.widget.cts;
+
+import android.test.ActivityInstrumentationTestCase2;
+import android.test.UiThreadTest;
+import android.view.ViewGroup;
+import android.widget.*;
+import com.android.cts.stub.R;
+
+import static android.view.View.LAYOUT_DIRECTION_LTR;
+import static android.view.View.LAYOUT_DIRECTION_RTL;
+import static android.view.View.LAYOUT_DIRECTION_INHERIT;
+import static android.view.View.LAYOUT_DIRECTION_LOCALE;
+
+public class LayoutDirectionTest extends ActivityInstrumentationTestCase2<LayoutDirectionStubActivity> {
+
+    public LayoutDirectionTest() {
+        super(LayoutDirectionStubActivity.class);
+    }
+
+    private void checkDefaultDirectionForOneLayoutWithCode(ViewGroup vg) {
+        assertEquals(LAYOUT_DIRECTION_INHERIT, vg.getLayoutDirection());
+        assertEquals(LAYOUT_DIRECTION_LTR, vg.getResolvedLayoutDirection());
+    }
+
+    @UiThreadTest
+    public void testLayoutDirectionDefaults() {
+        checkDefaultDirectionForOneLayoutWithCode(new LinearLayout(getActivity()));
+        checkDefaultDirectionForOneLayoutWithCode(new FrameLayout(getActivity()));
+        checkDefaultDirectionForOneLayoutWithCode(new TableLayout(getActivity()));
+        checkDefaultDirectionForOneLayoutWithCode(new RelativeLayout(getActivity()));
+        checkDefaultDirectionForOneLayoutWithCode(new GridLayout(getActivity()));
+    }
+
+    private void checkDirectionForOneLayoutWithCode(ViewGroup vg) {
+        vg.setLayoutDirection(LAYOUT_DIRECTION_LTR);
+        assertEquals(LAYOUT_DIRECTION_LTR, vg.getLayoutDirection());
+        assertEquals(LAYOUT_DIRECTION_LTR, vg.getResolvedLayoutDirection());
+
+        vg.setLayoutDirection(LAYOUT_DIRECTION_RTL);
+        assertEquals(LAYOUT_DIRECTION_RTL, vg.getLayoutDirection());
+        assertEquals(LAYOUT_DIRECTION_RTL, vg.getResolvedLayoutDirection());
+
+        vg.setLayoutDirection(LAYOUT_DIRECTION_LOCALE);
+        assertEquals(LAYOUT_DIRECTION_LOCALE, vg.getLayoutDirection());
+        // running with English locale
+        assertEquals(LAYOUT_DIRECTION_LTR, vg.getResolvedLayoutDirection());
+
+        vg.setLayoutDirection(LAYOUT_DIRECTION_INHERIT);
+        assertEquals(LAYOUT_DIRECTION_INHERIT, vg.getLayoutDirection());
+        // default is LTR
+        assertEquals(LAYOUT_DIRECTION_LTR, vg.getResolvedLayoutDirection());
+    }
+
+    @UiThreadTest
+    public void testDirectionForAllLayoutsWithCode() {
+        checkDirectionForOneLayoutWithCode(new LinearLayout(getActivity()));
+        checkDirectionForOneLayoutWithCode(new FrameLayout(getActivity()));
+        checkDirectionForOneLayoutWithCode(new TableLayout(getActivity()));
+        checkDirectionForOneLayoutWithCode(new RelativeLayout(getActivity()));
+        checkDirectionForOneLayoutWithCode(new GridLayout(getActivity()));
+    }
+
+    private void checkDirectionInheritanceForOneLayoutWithCode(ViewGroup parent) {
+        LinearLayout child = new LinearLayout(getActivity());
+        child.setLayoutDirection(LAYOUT_DIRECTION_INHERIT);
+        parent.addView(child);
+
+        // Parent is LTR
+        parent.setLayoutDirection(LAYOUT_DIRECTION_LTR);
+
+        assertEquals(LAYOUT_DIRECTION_LTR, parent.getLayoutDirection());
+        assertEquals(LAYOUT_DIRECTION_LTR, parent.getResolvedLayoutDirection());
+
+        assertEquals(LAYOUT_DIRECTION_INHERIT, child.getLayoutDirection());
+        assertEquals(LAYOUT_DIRECTION_LTR, child.getResolvedLayoutDirection());
+
+        // Parent is RTL
+        parent.setLayoutDirection(LAYOUT_DIRECTION_RTL);
+
+        assertEquals(LAYOUT_DIRECTION_RTL, parent.getLayoutDirection());
+        assertEquals(LAYOUT_DIRECTION_RTL, parent.getResolvedLayoutDirection());
+
+        assertEquals(LAYOUT_DIRECTION_INHERIT, child.getLayoutDirection());
+        assertEquals(LAYOUT_DIRECTION_RTL, child.getResolvedLayoutDirection());
+    }
+
+    @UiThreadTest
+    public void testDirectionInheritanceForAllLayoutsWithCode() {
+        checkDirectionInheritanceForOneLayoutWithCode(new LinearLayout(getActivity()));
+        checkDirectionInheritanceForOneLayoutWithCode(new FrameLayout(getActivity()));
+        checkDirectionInheritanceForOneLayoutWithCode(new TableLayout(getActivity()));
+        checkDirectionInheritanceForOneLayoutWithCode(new RelativeLayout(getActivity()));
+        checkDirectionInheritanceForOneLayoutWithCode(new GridLayout(getActivity()));
+    }
+
+    private void checkDirectionForOneLayoutFromXml(int parentId, int parentDir, int parentResDir,
+                                                   int child1Id, int child1Dir, int child1ResDir,
+                                                   int child2Id, int child2Dir, int child2ResDir,
+                                                   int child3Id, int child3Dir, int child3ResDir,
+                                                   int child4Id, int child4Dir, int child4ResDir) {
+        ViewGroup ll = (ViewGroup) getActivity().findViewById(parentId);
+        assertEquals(parentDir, ll.getLayoutDirection());
+        assertEquals(parentResDir, ll.getResolvedLayoutDirection());
+
+        ViewGroup child1 = (ViewGroup) getActivity().findViewById(child1Id);
+        assertEquals(child1Dir, child1.getLayoutDirection());
+        assertEquals(child1ResDir, child1.getResolvedLayoutDirection());
+
+        ViewGroup child2 = (ViewGroup) getActivity().findViewById(child2Id);
+        assertEquals(child2Dir, child2.getLayoutDirection());
+        assertEquals(child2ResDir, child2.getResolvedLayoutDirection());
+
+        ViewGroup child3 = (ViewGroup) getActivity().findViewById(child3Id);
+        assertEquals(child3Dir, child3.getLayoutDirection());
+        assertEquals(child3ResDir, child3.getResolvedLayoutDirection());
+
+        ViewGroup child4 = (ViewGroup) getActivity().findViewById(child4Id);
+        assertEquals(child4Dir, child4.getLayoutDirection());
+        assertEquals(child4ResDir, child4.getResolvedLayoutDirection());
+    }
+
+    @UiThreadTest
+    public void testDirectionFromXml() {
+        // We only test LinearLayout as the others would be the same (they extend ViewGroup / View)
+        checkDirectionForOneLayoutFromXml(
+                R.id.layout_linearlayout_ltr, LAYOUT_DIRECTION_LTR, LAYOUT_DIRECTION_LTR,
+                R.id.layout_linearlayout_ltr_child_1, LAYOUT_DIRECTION_LTR, LAYOUT_DIRECTION_LTR,
+                R.id.layout_linearlayout_ltr_child_2, LAYOUT_DIRECTION_RTL, LAYOUT_DIRECTION_RTL,
+                // parent is LTR
+                R.id.layout_linearlayout_ltr_child_3, LAYOUT_DIRECTION_INHERIT, LAYOUT_DIRECTION_LTR,
+                // running with English locale
+                R.id.layout_linearlayout_ltr_child_4, LAYOUT_DIRECTION_LOCALE, LAYOUT_DIRECTION_LTR);
+
+        checkDirectionForOneLayoutFromXml(
+                R.id.layout_linearlayout_rtl, LAYOUT_DIRECTION_RTL, LAYOUT_DIRECTION_RTL,
+                R.id.layout_linearlayout_rtl_child_1, LAYOUT_DIRECTION_LTR, LAYOUT_DIRECTION_LTR,
+                R.id.layout_linearlayout_rtl_child_2, LAYOUT_DIRECTION_RTL, LAYOUT_DIRECTION_RTL,
+                // parent is RTL
+                R.id.layout_linearlayout_rtl_child_3, LAYOUT_DIRECTION_INHERIT, LAYOUT_DIRECTION_RTL,
+                // running with English locale
+                R.id.layout_linearlayout_rtl_child_4, LAYOUT_DIRECTION_LOCALE, LAYOUT_DIRECTION_LTR);
+
+        checkDirectionForOneLayoutFromXml(
+                // default is LTR
+                R.id.layout_linearlayout_inherit, LAYOUT_DIRECTION_INHERIT, LAYOUT_DIRECTION_LTR,
+                R.id.layout_linearlayout_inherit_child_1, LAYOUT_DIRECTION_LTR, LAYOUT_DIRECTION_LTR,
+                R.id.layout_linearlayout_inherit_child_2, LAYOUT_DIRECTION_RTL, LAYOUT_DIRECTION_RTL,
+                // parent is LTR
+                R.id.layout_linearlayout_inherit_child_3, LAYOUT_DIRECTION_INHERIT, LAYOUT_DIRECTION_LTR,
+                // running with English locale
+                R.id.layout_linearlayout_inherit_child_4, LAYOUT_DIRECTION_LOCALE, LAYOUT_DIRECTION_LTR);
+
+        checkDirectionForOneLayoutFromXml(
+                // running with English locale
+                R.id.layout_linearlayout_locale, LAYOUT_DIRECTION_LOCALE, LAYOUT_DIRECTION_LTR,
+                R.id.layout_linearlayout_locale_child_1, LAYOUT_DIRECTION_LTR, LAYOUT_DIRECTION_LTR,
+                R.id.layout_linearlayout_locale_child_2, LAYOUT_DIRECTION_RTL, LAYOUT_DIRECTION_RTL,
+                // parent is LTR
+                R.id.layout_linearlayout_locale_child_3, LAYOUT_DIRECTION_INHERIT, LAYOUT_DIRECTION_LTR,
+                // running with English locale
+                R.id.layout_linearlayout_locale_child_4, LAYOUT_DIRECTION_LOCALE, LAYOUT_DIRECTION_LTR);
+    }
+}
diff --git a/tests/tests/widget/src/android/widget/cts/RadioGroupTest.java b/tests/tests/widget/src/android/widget/cts/RadioGroupTest.java
index a7593c4..f7baab7 100644
--- a/tests/tests/widget/src/android/widget/cts/RadioGroupTest.java
+++ b/tests/tests/widget/src/android/widget/cts/RadioGroupTest.java
@@ -102,9 +102,9 @@
         assertEquals(View.NO_ID, newButton.getId());
         mDefaultRadioGroup.addView(newButton, new RadioGroup.LayoutParams(
                 RadioGroup.LayoutParams.WRAP_CONTENT, RadioGroup.LayoutParams.WRAP_CONTENT));
-        // set the id with hashCode
-        // (PassThroughHierarchyChangeListener's behaviour when button is added)
-        assertEquals(newButton.hashCode(), newButton.getId());
+        // aapt-generated IDs have a nonzero high byte; check that the ID generated by
+        // RadioGroup falls within a range that will not collide with aapt IDs.
+        assertEquals(0, newButton.getId() & 0xFF000000);
     }
 
     public void testInternalCheckedStateTracker() {
diff --git a/tests/tests/widget/src/android/widget/cts/RelativeLayout_LayoutParamsTest.java b/tests/tests/widget/src/android/widget/cts/RelativeLayout_LayoutParamsTest.java
index 4c9d2ab..e034562 100644
--- a/tests/tests/widget/src/android/widget/cts/RelativeLayout_LayoutParamsTest.java
+++ b/tests/tests/widget/src/android/widget/cts/RelativeLayout_LayoutParamsTest.java
@@ -160,6 +160,167 @@
         assertEquals(R.id.relative_view3, rules[RelativeLayout.ALIGN_BOTTOM]);
     }
 
+    public void testStartEnd() {
+        RelativeLayout.LayoutParams layoutParams;
+
+        // Test RelativeLayout.Params which generated from the xml file.
+        int rules[];
+        RelativeLayoutStubActivity activity = getActivity();
+
+        // test attributes used in RelativeLayout.
+        RelativeLayout relativeLayout = (RelativeLayout) activity.findViewById(
+                R.id.relative_sublayout_attrs_2);
+
+        // view1, centered within its parent.
+        // TEST: android:layout_centerInParent
+        View view1 = activity.findViewById(R.id.relative_view21);
+        ViewAsserts.assertHorizontalCenterAligned(relativeLayout, view1);
+        ViewAsserts.assertVerticalCenterAligned(relativeLayout, view1);
+        layoutParams = (RelativeLayout.LayoutParams) (view1.getLayoutParams());
+        rules = layoutParams.getRules();
+        assertEquals(RelativeLayout.TRUE, rules[RelativeLayout.CENTER_IN_PARENT]);
+
+        // view2, below view1 and has same left position with view1.
+        // TEST: android:layout_below; android:layout_alignStart
+        View view2 = activity.findViewById(R.id.relative_view22);
+        ViewAsserts.assertLeftAligned(view1, view2);
+        assertEquals(view1.getBottom(), view2.getTop());
+        layoutParams = (RelativeLayout.LayoutParams) (view2.getLayoutParams());
+        rules = layoutParams.getRules();
+        assertEquals(R.id.relative_view21, rules[RelativeLayout.BELOW]);
+        assertEquals(R.id.relative_view21, rules[RelativeLayout.ALIGN_START]);
+        assertEquals(R.id.relative_view21, rules[RelativeLayout.ALIGN_LEFT]);
+        assertEquals(0, rules[RelativeLayout.ALIGN_RIGHT]);
+        rules = layoutParams.getRules(View.LAYOUT_DIRECTION_RTL);
+        assertEquals(R.id.relative_view21, rules[RelativeLayout.BELOW]);
+        assertEquals(R.id.relative_view21, rules[RelativeLayout.ALIGN_START]);
+        assertEquals(0, rules[RelativeLayout.ALIGN_LEFT]);
+        assertEquals(R.id.relative_view21, rules[RelativeLayout.ALIGN_RIGHT]);
+
+        // view3, has same top position with view1 and same bottom position with view2,
+        // and on the right of view1.1.
+        // TEST: android:layout_alignTop; android:layout_alignBottom; android:layout_toEndOf
+        View view3 = activity.findViewById(R.id.relative_view23);
+        ViewAsserts.assertTopAligned(view1, view3);
+        ViewAsserts.assertBottomAligned(view2, view3);
+        assertEquals(view1.getRight(), view3.getLeft());
+        layoutParams = (RelativeLayout.LayoutParams) (view3.getLayoutParams());
+        rules = layoutParams.getRules();
+        assertEquals(R.id.relative_view21, rules[RelativeLayout.ALIGN_TOP]);
+        assertEquals(R.id.relative_view22, rules[RelativeLayout.ALIGN_BOTTOM]);
+        assertEquals(R.id.relative_view21, rules[RelativeLayout.END_OF]);
+        assertEquals(0, rules[RelativeLayout.LEFT_OF]);
+        assertEquals(R.id.relative_view21, rules[RelativeLayout.RIGHT_OF]);
+        rules = layoutParams.getRules(View.LAYOUT_DIRECTION_RTL);
+        assertEquals(R.id.relative_view21, rules[RelativeLayout.ALIGN_TOP]);
+        assertEquals(R.id.relative_view22, rules[RelativeLayout.ALIGN_BOTTOM]);
+        assertEquals(R.id.relative_view21, rules[RelativeLayout.END_OF]);
+        assertEquals(R.id.relative_view21, rules[RelativeLayout.LEFT_OF]);
+        assertEquals(0, rules[RelativeLayout.RIGHT_OF]);
+
+        // view4, has same right position with view3 and above view3.
+        // TEST: android:layout_alignEnd; android:layout_above
+        View view4 = activity.findViewById(R.id.relative_view24);
+        ViewAsserts.assertRightAligned(view3, view4);
+        assertEquals(view3.getTop(), view4.getBottom());
+        layoutParams = (RelativeLayout.LayoutParams) (view4.getLayoutParams());
+        rules = layoutParams.getRules();
+        assertEquals(R.id.relative_view23, rules[RelativeLayout.ALIGN_END]);
+        assertEquals(0, rules[RelativeLayout.ALIGN_LEFT]);
+        assertEquals(R.id.relative_view23, rules[RelativeLayout.ALIGN_RIGHT]);
+        assertEquals(R.id.relative_view23, rules[RelativeLayout.ABOVE]);
+        rules = layoutParams.getRules(View.LAYOUT_DIRECTION_RTL);
+        assertEquals(R.id.relative_view23, rules[RelativeLayout.ALIGN_END]);
+        assertEquals(R.id.relative_view23, rules[RelativeLayout.ALIGN_LEFT]);
+        assertEquals(0, rules[RelativeLayout.ALIGN_RIGHT]);
+        assertEquals(R.id.relative_view23, rules[RelativeLayout.ABOVE]);
+
+        // view5 goes on the left-bottom.
+        // TEST: android:layout_alignParentBottom; android:layout_alignParentStart
+        View view5 = activity.findViewById(R.id.relative_view25);
+        ViewAsserts.assertLeftAligned(relativeLayout, view5);
+        ViewAsserts.assertBottomAligned(relativeLayout, view5);
+        layoutParams = (RelativeLayout.LayoutParams) (view5.getLayoutParams());
+        rules = layoutParams.getRules();
+        assertEquals(RelativeLayout.TRUE, rules[RelativeLayout.ALIGN_PARENT_BOTTOM]);
+        assertEquals(RelativeLayout.TRUE, rules[RelativeLayout.ALIGN_PARENT_START]);
+        assertEquals(RelativeLayout.TRUE, rules[RelativeLayout.ALIGN_PARENT_LEFT]);
+        assertEquals(0, rules[RelativeLayout.ALIGN_PARENT_RIGHT]);
+        rules = layoutParams.getRules(View.LAYOUT_DIRECTION_RTL);
+        assertEquals(RelativeLayout.TRUE, rules[RelativeLayout.ALIGN_PARENT_BOTTOM]);
+        assertEquals(RelativeLayout.TRUE, rules[RelativeLayout.ALIGN_PARENT_START]);
+        assertEquals(0, rules[RelativeLayout.ALIGN_PARENT_LEFT]);
+        assertEquals(RelativeLayout.TRUE, rules[RelativeLayout.ALIGN_PARENT_RIGHT]);
+
+        // view6 goes on the top-right.
+        // TEST: android:layout_alignParentTop; android:layout_alignParentEnd
+        View view6 = activity.findViewById(R.id.relative_view26);
+        ViewAsserts.assertTopAligned(relativeLayout, view6);
+        ViewAsserts.assertRightAligned(relativeLayout, view6);
+        layoutParams = (RelativeLayout.LayoutParams) (view6.getLayoutParams());
+        rules = layoutParams.getRules();
+        assertEquals(RelativeLayout.TRUE, rules[RelativeLayout.ALIGN_PARENT_TOP]);
+        assertEquals(RelativeLayout.TRUE, rules[RelativeLayout.ALIGN_PARENT_END]);
+        assertEquals(0, rules[RelativeLayout.ALIGN_PARENT_LEFT]);
+        assertEquals(RelativeLayout.TRUE, rules[RelativeLayout.ALIGN_PARENT_RIGHT]);
+        rules = layoutParams.getRules(View.LAYOUT_DIRECTION_RTL);
+        assertEquals(RelativeLayout.TRUE, rules[RelativeLayout.ALIGN_PARENT_TOP]);
+        assertEquals(RelativeLayout.TRUE, rules[RelativeLayout.ALIGN_PARENT_END]);
+        assertEquals(RelativeLayout.TRUE, rules[RelativeLayout.ALIGN_PARENT_LEFT]);
+        assertEquals(0, rules[RelativeLayout.ALIGN_PARENT_RIGHT]);
+
+        // view7, has same baseline with view6 and centered horizontally within its parent.
+        // TEST: android:layout_alignBaseline; android:layout_centerHorizontal
+        View view7 = activity.findViewById(R.id.relative_view27);
+        ViewAsserts.assertBaselineAligned(view6, view7);
+        ViewAsserts.assertHorizontalCenterAligned(relativeLayout, view7);
+        layoutParams = (RelativeLayout.LayoutParams) (view7.getLayoutParams());
+        rules = layoutParams.getRules();
+        assertEquals(R.id.relative_view26, rules[RelativeLayout.ALIGN_BASELINE]);
+        assertEquals(RelativeLayout.TRUE, rules[RelativeLayout.CENTER_HORIZONTAL]);
+        rules = layoutParams.getRules(View.LAYOUT_DIRECTION_RTL);
+        assertEquals(R.id.relative_view26, rules[RelativeLayout.ALIGN_BASELINE]);
+        assertEquals(RelativeLayout.TRUE, rules[RelativeLayout.CENTER_HORIZONTAL]);
+
+        // view8, centered vertically within its parent and on the left of view1.
+        // TEST: android:layout_toStartOf; android:layout_centerVertical
+        View view8 = activity.findViewById(R.id.relative_view28);
+        ViewAsserts.assertVerticalCenterAligned(relativeLayout, view8);
+        assertEquals(view1.getLeft(), view8.getRight());
+        layoutParams = (RelativeLayout.LayoutParams) (view8.getLayoutParams());
+        rules = layoutParams.getRules();
+        assertEquals(R.id.relative_view21, rules[RelativeLayout.START_OF]);
+        assertEquals(R.id.relative_view21, rules[RelativeLayout.LEFT_OF]);
+        assertEquals(0, rules[RelativeLayout.RIGHT_OF]);
+        assertEquals(RelativeLayout.TRUE, rules[RelativeLayout.CENTER_VERTICAL]);
+        rules = layoutParams.getRules(View.LAYOUT_DIRECTION_RTL);
+        assertEquals(R.id.relative_view21, rules[RelativeLayout.START_OF]);
+        assertEquals(0, rules[RelativeLayout.LEFT_OF]);
+        assertEquals(R.id.relative_view21, rules[RelativeLayout.RIGHT_OF]);
+        assertEquals(RelativeLayout.TRUE, rules[RelativeLayout.CENTER_VERTICAL]);
+
+        // view9, has same top and bottom position with view3 and same left position with its parent
+        // TEST: android:layout_alignStart; android:layout_alignTop; android:layout_alignBottom;
+        // android:layout_alignWithParentIfMissing
+        View view9 = activity.findViewById(R.id.relative_view29);
+        ViewAsserts.assertTopAligned(view3, view9);
+        ViewAsserts.assertBottomAligned(view3, view9);
+        ViewAsserts.assertLeftAligned(relativeLayout, view9);
+        layoutParams = (RelativeLayout.LayoutParams) (view9.getLayoutParams());
+        rules = layoutParams.getRules();
+        assertEquals(R.id.gravity_bottom, rules[RelativeLayout.ALIGN_START]);
+        assertEquals(R.id.gravity_bottom, rules[RelativeLayout.ALIGN_LEFT]);
+        assertEquals(0, rules[RelativeLayout.ALIGN_RIGHT]);
+        assertEquals(R.id.relative_view23, rules[RelativeLayout.ALIGN_TOP]);
+        assertEquals(R.id.relative_view23, rules[RelativeLayout.ALIGN_BOTTOM]);
+        rules = layoutParams.getRules(View.LAYOUT_DIRECTION_RTL);
+        assertEquals(R.id.gravity_bottom, rules[RelativeLayout.ALIGN_START]);
+        assertEquals(0, rules[RelativeLayout.ALIGN_LEFT]);
+        assertEquals(R.id.gravity_bottom, rules[RelativeLayout.ALIGN_RIGHT]);
+        assertEquals(R.id.relative_view23, rules[RelativeLayout.ALIGN_TOP]);
+        assertEquals(R.id.relative_view23, rules[RelativeLayout.ALIGN_BOTTOM]);
+    }
+
     public void testAccessRule1() {
         RelativeLayout.LayoutParams layoutParams = new RelativeLayout.LayoutParams(200, 300);
         int rules[]= layoutParams.getRules();
diff --git a/tests/tests/widget/src/android/widget/cts/TextViewTest.java b/tests/tests/widget/src/android/widget/cts/TextViewTest.java
index e295c40..24a8440 100755
--- a/tests/tests/widget/src/android/widget/cts/TextViewTest.java
+++ b/tests/tests/widget/src/android/widget/cts/TextViewTest.java
@@ -2984,6 +2984,299 @@
                 outText.text.toString());
     }
 
+    @UiThreadTest
+    public void testTextDirectionDefault() {
+        TextView tv = new TextView(mActivity);
+        assertEquals(View.TEXT_DIRECTION_INHERIT, tv.getTextDirection());
+    }
+
+    @UiThreadTest
+    public void testSetGetTextDirection() {
+        TextView tv = new TextView(mActivity);
+
+        tv.setTextDirection(View.TEXT_DIRECTION_FIRST_STRONG);
+        assertEquals(View.TEXT_DIRECTION_FIRST_STRONG, tv.getTextDirection());
+
+        tv.setTextDirection(View.TEXT_DIRECTION_ANY_RTL);
+        assertEquals(View.TEXT_DIRECTION_ANY_RTL, tv.getTextDirection());
+
+        tv.setTextDirection(View.TEXT_DIRECTION_INHERIT);
+        assertEquals(View.TEXT_DIRECTION_INHERIT, tv.getTextDirection());
+
+        tv.setTextDirection(View.TEXT_DIRECTION_LTR);
+        assertEquals(View.TEXT_DIRECTION_LTR, tv.getTextDirection());
+
+        tv.setTextDirection(View.TEXT_DIRECTION_RTL);
+        assertEquals(View.TEXT_DIRECTION_RTL, tv.getTextDirection());
+
+        tv.setTextDirection(View.TEXT_DIRECTION_LOCALE);
+        assertEquals(View.TEXT_DIRECTION_LOCALE, tv.getTextDirection());
+    }
+
+    @UiThreadTest
+    public void testGetResolvedTextDirectionLtr() {
+        TextView tv = new TextView(mActivity);
+        tv.setText("this is a test");
+
+        assertEquals(View.TEXT_DIRECTION_FIRST_STRONG, tv.getResolvedTextDirection());
+
+        tv.setTextDirection(View.TEXT_DIRECTION_FIRST_STRONG);
+        assertEquals(View.TEXT_DIRECTION_FIRST_STRONG, tv.getResolvedTextDirection());
+
+        tv.setTextDirection(View.TEXT_DIRECTION_ANY_RTL);
+        assertEquals(View.TEXT_DIRECTION_ANY_RTL, tv.getResolvedTextDirection());
+
+        tv.setTextDirection(View.TEXT_DIRECTION_INHERIT);
+        assertEquals(View.TEXT_DIRECTION_FIRST_STRONG, tv.getResolvedTextDirection());
+
+        tv.setTextDirection(View.TEXT_DIRECTION_LTR);
+        assertEquals(View.TEXT_DIRECTION_LTR, tv.getResolvedTextDirection());
+
+        tv.setTextDirection(View.TEXT_DIRECTION_RTL);
+        assertEquals(View.TEXT_DIRECTION_RTL, tv.getResolvedTextDirection());
+
+        tv.setTextDirection(View.TEXT_DIRECTION_LOCALE);
+        assertEquals(View.TEXT_DIRECTION_LOCALE, tv.getResolvedTextDirection());
+    }
+
+    @UiThreadTest
+    public void testGetResolvedTextDirectionLtrWithInheritance() {
+        LinearLayout ll = new LinearLayout(mActivity);
+        ll.setTextDirection(View.TEXT_DIRECTION_ANY_RTL);
+
+        TextView tv = new TextView(mActivity);
+        tv.setText("this is a test");
+        ll.addView(tv);
+
+        tv.setTextDirection(View.TEXT_DIRECTION_FIRST_STRONG);
+        assertEquals(View.TEXT_DIRECTION_FIRST_STRONG, tv.getResolvedTextDirection());
+
+        tv.setTextDirection(View.TEXT_DIRECTION_ANY_RTL);
+        assertEquals(View.TEXT_DIRECTION_ANY_RTL, tv.getResolvedTextDirection());
+
+        tv.setTextDirection(View.TEXT_DIRECTION_INHERIT);
+        assertEquals(View.TEXT_DIRECTION_ANY_RTL, tv.getResolvedTextDirection());
+
+        tv.setTextDirection(View.TEXT_DIRECTION_LTR);
+        assertEquals(View.TEXT_DIRECTION_LTR, tv.getResolvedTextDirection());
+
+        tv.setTextDirection(View.TEXT_DIRECTION_RTL);
+        assertEquals(View.TEXT_DIRECTION_RTL, tv.getResolvedTextDirection());
+
+        tv.setTextDirection(View.TEXT_DIRECTION_LOCALE);
+        assertEquals(View.TEXT_DIRECTION_LOCALE, tv.getResolvedTextDirection());
+    }
+
+    @UiThreadTest
+    public void testGetResolvedTextDirectionRtl() {
+        TextView tv = new TextView(mActivity);
+        tv.setText("\u05DD\u05DE"); // hebrew
+
+        assertEquals(View.TEXT_DIRECTION_FIRST_STRONG, tv.getResolvedTextDirection());
+
+        tv.setTextDirection(View.TEXT_DIRECTION_FIRST_STRONG);
+        assertEquals(View.TEXT_DIRECTION_FIRST_STRONG, tv.getResolvedTextDirection());
+
+        tv.setTextDirection(View.TEXT_DIRECTION_ANY_RTL);
+        assertEquals(View.TEXT_DIRECTION_ANY_RTL, tv.getResolvedTextDirection());
+
+        tv.setTextDirection(View.TEXT_DIRECTION_INHERIT);
+        assertEquals(View.TEXT_DIRECTION_FIRST_STRONG, tv.getResolvedTextDirection());
+
+        tv.setTextDirection(View.TEXT_DIRECTION_LTR);
+        assertEquals(View.TEXT_DIRECTION_LTR, tv.getResolvedTextDirection());
+
+        tv.setTextDirection(View.TEXT_DIRECTION_RTL);
+        assertEquals(View.TEXT_DIRECTION_RTL, tv.getResolvedTextDirection());
+
+        tv.setTextDirection(View.TEXT_DIRECTION_LOCALE);
+        assertEquals(View.TEXT_DIRECTION_LOCALE, tv.getResolvedTextDirection());
+    }
+
+    @UiThreadTest
+    public void testGetResolvedTextDirectionRtlWithInheritance() {
+        LinearLayout ll = new LinearLayout(mActivity);
+        ll.setTextDirection(View.TEXT_DIRECTION_FIRST_STRONG);
+
+        TextView tv = new TextView(mActivity);
+        tv.setText("\u05DD\u05DE"); // hebrew
+        ll.addView(tv);
+
+        tv.setTextDirection(View.TEXT_DIRECTION_FIRST_STRONG);
+        assertEquals(View.TEXT_DIRECTION_FIRST_STRONG, tv.getResolvedTextDirection());
+
+        tv.setTextDirection(View.TEXT_DIRECTION_ANY_RTL);
+        assertEquals(View.TEXT_DIRECTION_ANY_RTL, tv.getResolvedTextDirection());
+
+        tv.setTextDirection(View.TEXT_DIRECTION_INHERIT);
+        assertEquals(View.TEXT_DIRECTION_FIRST_STRONG, tv.getResolvedTextDirection());
+
+        tv.setTextDirection(View.TEXT_DIRECTION_LTR);
+        assertEquals(View.TEXT_DIRECTION_LTR, tv.getResolvedTextDirection());
+
+        tv.setTextDirection(View.TEXT_DIRECTION_RTL);
+        assertEquals(View.TEXT_DIRECTION_RTL, tv.getResolvedTextDirection());
+
+        tv.setTextDirection(View.TEXT_DIRECTION_LOCALE);
+        assertEquals(View.TEXT_DIRECTION_LOCALE, tv.getResolvedTextDirection());
+
+        // Force to RTL text direction on the layout
+        ll.setTextDirection(View.TEXT_DIRECTION_RTL);
+
+        tv.setTextDirection(View.TEXT_DIRECTION_FIRST_STRONG);
+        assertEquals(View.TEXT_DIRECTION_FIRST_STRONG, tv.getResolvedTextDirection());
+
+        tv.setTextDirection(View.TEXT_DIRECTION_ANY_RTL);
+        assertEquals(View.TEXT_DIRECTION_ANY_RTL, tv.getResolvedTextDirection());
+
+        tv.setTextDirection(View.TEXT_DIRECTION_INHERIT);
+        assertEquals(View.TEXT_DIRECTION_RTL, tv.getResolvedTextDirection());
+
+        tv.setTextDirection(View.TEXT_DIRECTION_LTR);
+        assertEquals(View.TEXT_DIRECTION_LTR, tv.getResolvedTextDirection());
+
+        tv.setTextDirection(View.TEXT_DIRECTION_RTL);
+        assertEquals(View.TEXT_DIRECTION_RTL, tv.getResolvedTextDirection());
+
+        tv.setTextDirection(View.TEXT_DIRECTION_LOCALE);
+        assertEquals(View.TEXT_DIRECTION_LOCALE, tv.getResolvedTextDirection());
+    }
+
+    @UiThreadTest
+    public void testResetTextDirection() {
+        LinearLayout ll = (LinearLayout) mActivity.findViewById(R.id.layout_textviewtest);
+        TextView tv = (TextView) mActivity.findViewById(R.id.textview_rtl);
+
+        ll.setTextDirection(View.TEXT_DIRECTION_RTL);
+        tv.setTextDirection(View.TEXT_DIRECTION_INHERIT);
+        assertEquals(View.TEXT_DIRECTION_RTL, tv.getResolvedTextDirection());
+
+        ll.removeView(tv);
+        assertEquals(View.TEXT_DIRECTION_FIRST_STRONG, tv.getResolvedTextDirection());
+    }
+
+    @UiThreadTest
+    public void testTextAlignmentDefault() {
+        TextView tv = new TextView(getActivity());
+        assertEquals(View.TEXT_ALIGNMENT_GRAVITY, tv.getTextAlignment());
+        // resolved default text alignment is GRAVITY
+        assertEquals(View.TEXT_ALIGNMENT_GRAVITY, tv.getResolvedTextAlignment());
+    }
+
+    @UiThreadTest
+    public void testSetGetTextAlignment() {
+        TextView tv = new TextView(getActivity());
+
+        tv.setTextAlignment(View.TEXT_ALIGNMENT_GRAVITY);
+        assertEquals(View.TEXT_ALIGNMENT_GRAVITY, tv.getTextAlignment());
+
+        tv.setTextAlignment(View.TEXT_ALIGNMENT_CENTER);
+        assertEquals(View.TEXT_ALIGNMENT_CENTER, tv.getTextAlignment());
+
+        tv.setTextAlignment(View.TEXT_ALIGNMENT_TEXT_START);
+        assertEquals(View.TEXT_ALIGNMENT_TEXT_START, tv.getTextAlignment());
+
+        tv.setTextAlignment(View.TEXT_ALIGNMENT_TEXT_END);
+        assertEquals(View.TEXT_ALIGNMENT_TEXT_END, tv.getTextAlignment());
+
+        tv.setTextAlignment(View.TEXT_ALIGNMENT_VIEW_START);
+        assertEquals(View.TEXT_ALIGNMENT_VIEW_START, tv.getTextAlignment());
+
+        tv.setTextAlignment(View.TEXT_ALIGNMENT_VIEW_END);
+        assertEquals(View.TEXT_ALIGNMENT_VIEW_END, tv.getTextAlignment());
+    }
+
+    @UiThreadTest
+    public void testGetResolvedTextAlignment() {
+        TextView tv = new TextView(getActivity());
+
+        assertEquals(View.TEXT_ALIGNMENT_GRAVITY, tv.getResolvedTextAlignment());
+
+        tv.setTextAlignment(View.TEXT_ALIGNMENT_GRAVITY);
+        assertEquals(View.TEXT_ALIGNMENT_GRAVITY, tv.getResolvedTextAlignment());
+
+        tv.setTextAlignment(View.TEXT_ALIGNMENT_CENTER);
+        assertEquals(View.TEXT_ALIGNMENT_CENTER, tv.getResolvedTextAlignment());
+
+        tv.setTextAlignment(View.TEXT_ALIGNMENT_TEXT_START);
+        assertEquals(View.TEXT_ALIGNMENT_TEXT_START, tv.getResolvedTextAlignment());
+
+        tv.setTextAlignment(View.TEXT_ALIGNMENT_TEXT_END);
+        assertEquals(View.TEXT_ALIGNMENT_TEXT_END, tv.getResolvedTextAlignment());
+
+        tv.setTextAlignment(View.TEXT_ALIGNMENT_VIEW_START);
+        assertEquals(View.TEXT_ALIGNMENT_VIEW_START, tv.getResolvedTextAlignment());
+
+        tv.setTextAlignment(View.TEXT_ALIGNMENT_VIEW_END);
+        assertEquals(View.TEXT_ALIGNMENT_VIEW_END, tv.getResolvedTextAlignment());
+    }
+
+    @UiThreadTest
+    public void testGetResolvedTextAlignmentWithInheritance() {
+        LinearLayout ll = new LinearLayout(getActivity());
+        ll.setTextAlignment(View.TEXT_ALIGNMENT_GRAVITY);
+
+        TextView tv = new TextView(getActivity());
+        ll.addView(tv);
+
+        // check defaults
+        assertEquals(View.TEXT_ALIGNMENT_GRAVITY, tv.getTextAlignment());
+        assertEquals(View.TEXT_ALIGNMENT_GRAVITY, tv.getResolvedTextAlignment());
+
+        // set inherit and check that child is following parent
+        tv.setTextAlignment(View.TEXT_ALIGNMENT_INHERIT);
+        assertEquals(View.TEXT_ALIGNMENT_INHERIT, tv.getTextAlignment());
+
+        ll.setTextAlignment(View.TEXT_ALIGNMENT_CENTER);
+        assertEquals(View.TEXT_ALIGNMENT_CENTER, tv.getResolvedTextAlignment());
+
+        ll.setTextAlignment(View.TEXT_ALIGNMENT_TEXT_START);
+        assertEquals(View.TEXT_ALIGNMENT_TEXT_START, tv.getResolvedTextAlignment());
+
+        ll.setTextAlignment(View.TEXT_ALIGNMENT_TEXT_END);
+        assertEquals(View.TEXT_ALIGNMENT_TEXT_END, tv.getResolvedTextAlignment());
+
+        ll.setTextAlignment(View.TEXT_ALIGNMENT_VIEW_START);
+        assertEquals(View.TEXT_ALIGNMENT_VIEW_START, tv.getResolvedTextAlignment());
+
+        ll.setTextAlignment(View.TEXT_ALIGNMENT_VIEW_END);
+        assertEquals(View.TEXT_ALIGNMENT_VIEW_END, tv.getResolvedTextAlignment());
+
+        // now get rid of the inheritance but still change the parent
+        tv.setTextAlignment(View.TEXT_ALIGNMENT_CENTER);
+
+        ll.setTextAlignment(View.TEXT_ALIGNMENT_CENTER);
+        assertEquals(View.TEXT_ALIGNMENT_CENTER, tv.getResolvedTextAlignment());
+
+        ll.setTextAlignment(View.TEXT_ALIGNMENT_TEXT_START);
+        assertEquals(View.TEXT_ALIGNMENT_CENTER, tv.getResolvedTextAlignment());
+
+        ll.setTextAlignment(View.TEXT_ALIGNMENT_TEXT_END);
+        assertEquals(View.TEXT_ALIGNMENT_CENTER, tv.getResolvedTextAlignment());
+
+        ll.setTextAlignment(View.TEXT_ALIGNMENT_VIEW_START);
+        assertEquals(View.TEXT_ALIGNMENT_CENTER, tv.getResolvedTextAlignment());
+
+        ll.setTextAlignment(View.TEXT_ALIGNMENT_VIEW_END);
+        assertEquals(View.TEXT_ALIGNMENT_CENTER, tv.getResolvedTextAlignment());
+    }
+
+    @UiThreadTest
+    public void testResetTextAlignment() {
+        TextViewStubActivity activity = getActivity();
+
+        LinearLayout ll = (LinearLayout) activity.findViewById(R.id.layout_textviewtest);
+        TextView tv = (TextView) activity.findViewById(R.id.textview_rtl);
+
+        ll.setTextAlignment(View.TEXT_ALIGNMENT_CENTER);
+        tv.setTextAlignment(View.TEXT_ALIGNMENT_INHERIT);
+        assertEquals(View.TEXT_ALIGNMENT_CENTER, tv.getResolvedTextAlignment());
+
+        ll.removeView(tv);
+        // default text alignment is GRAVITY
+        assertEquals(View.TEXT_ALIGNMENT_GRAVITY, tv.getResolvedTextAlignment());
+    }
+
     private static class MockOnEditorActionListener implements OnEditorActionListener {
         private boolean isOnEditorActionCalled;
 
diff --git a/tools/cts-java-scanner/src/com/android/cts/javascanner/DocletRunner.java b/tools/cts-java-scanner/src/com/android/cts/javascanner/DocletRunner.java
index 995408a..592b145 100644
--- a/tools/cts-java-scanner/src/com/android/cts/javascanner/DocletRunner.java
+++ b/tools/cts-java-scanner/src/com/android/cts/javascanner/DocletRunner.java
@@ -65,10 +65,12 @@
         List<String> sourcePath = new ArrayList<String>();
         sourcePath.add("./frameworks/base/core/java");
         sourcePath.add("./frameworks/base/test-runner/src");
-        sourcePath.add("./libcore/junit/src/main/java");
+        sourcePath.add("./external/junit/src");
         sourcePath.add("./development/tools/hosttestlib/src");
         sourcePath.add("./libcore/dalvik/src/main/java");
         sourcePath.add("./cts/tests/src");
+        // PTS adds PtsAndroidTestCase
+        sourcePath.add("./cts/suite/pts/deviceTests/ptsutil/src");
         sourcePath.add(sourceDir.toString());
         return join(sourcePath, ":");
     }
diff --git a/tools/device-setup/TestDeviceSetup/Android.mk b/tools/device-setup/TestDeviceSetup/Android.mk
index 413f50b..5642736 100644
--- a/tools/device-setup/TestDeviceSetup/Android.mk
+++ b/tools/device-setup/TestDeviceSetup/Android.mk
@@ -21,6 +21,8 @@
 LOCAL_MODULE_TAGS := optional
 # and when built explicitly put it in the data partition
 LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
+# and because it is in data, do not strip classes.dex
+LOCAL_DEX_PREOPT := false
 
 LOCAL_JAVA_LIBRARIES := android.test.runner
 
diff --git a/tools/tradefed-host/res/report/cts_result.xsl b/tools/tradefed-host/res/report/cts_result.xsl
index fd2b732..3dfd893 100644
--- a/tools/tradefed-host/res/report/cts_result.xsl
+++ b/tools/tradefed-host/res/report/cts_result.xsl
@@ -461,7 +461,7 @@
                         <TR>
                             <TH width="30%">Test</TH>
                             <TH width="5%">Result</TH>
-                            <TH>Failure Details</TH>
+                            <TH>Failure Details / Details</TH>
                         </TR>
 
                         <!-- test case -->
@@ -526,6 +526,11 @@
                                                             <xsl:value-of select="@result"/>
                                                         </div>
                                                     </TD>
+                                                    <TD class="failuredetails">
+                                                        <div class="details">
+                                                            <xsl:value-of select="FailedScene/@message"/>
+                                                        </div>
+                                                    </TD>
                                                     <TD class="failuredetails"></TD>
                                                 </xsl:if>
 
diff --git a/tools/tradefed-host/src/com/android/cts/tradefed/build/CtsBuildHelper.java b/tools/tradefed-host/src/com/android/cts/tradefed/build/CtsBuildHelper.java
index 8029b75..3c46d9b 100644
--- a/tools/tradefed-host/src/com/android/cts/tradefed/build/CtsBuildHelper.java
+++ b/tools/tradefed-host/src/com/android/cts/tradefed/build/CtsBuildHelper.java
@@ -30,11 +30,17 @@
 public class CtsBuildHelper {
 
     static final String CTS_DIR_NAME = "android-cts";
+    static final String PTS_DIR_NAME = "android-pts";
+    static private boolean mCtsMode = true;
     /** The root location of the extracted CTS package */
     private final File mRootDir;
     /** the {@link CTS_DIR_NAME} directory */
     private final File mCtsDir;
 
+    public static void changeToPtsMode() {
+        mCtsMode = false;
+    }
+
     /**
      * Creates a {@link CtsBuildHelper}.
      *
@@ -43,7 +49,7 @@
      */
     public CtsBuildHelper(File rootDir) {
         mRootDir = rootDir;
-        mCtsDir = new File(mRootDir, CTS_DIR_NAME);
+        mCtsDir = new File(mRootDir, mCtsMode ? CTS_DIR_NAME : PTS_DIR_NAME);
     }
 
     /**
diff --git a/tools/tradefed-host/src/com/android/cts/tradefed/build/CtsBuildProvider.java b/tools/tradefed-host/src/com/android/cts/tradefed/build/CtsBuildProvider.java
index 5ad7e25..f53507d 100644
--- a/tools/tradefed-host/src/com/android/cts/tradefed/build/CtsBuildProvider.java
+++ b/tools/tradefed-host/src/com/android/cts/tradefed/build/CtsBuildProvider.java
@@ -31,7 +31,7 @@
     @Option(name="cts-install-path", description="the path to the cts installation to use")
     private String mCtsRootDirPath = System.getProperty("CTS_ROOT");
 
-    public static final String CTS_BUILD_VERSION = "4.1_r1";
+    public static final String CTS_BUILD_VERSION = "4.0_r1";
 
     /**
      * {@inheritDoc}
diff --git a/tools/tradefed-host/src/com/android/cts/tradefed/command/CtsConsole.java b/tools/tradefed-host/src/com/android/cts/tradefed/command/CtsConsole.java
index a815a48..8e59cc5 100644
--- a/tools/tradefed-host/src/com/android/cts/tradefed/command/CtsConsole.java
+++ b/tools/tradefed-host/src/com/android/cts/tradefed/command/CtsConsole.java
@@ -246,6 +246,11 @@
     }
 
     public static void main(String[] args) throws InterruptedException {
+        // change to PTS mode before anything else
+        String ptsMode = System.getProperty("PTS");
+        if ((ptsMode != null) && ptsMode.equals("1")) {
+            CtsBuildHelper.changeToPtsMode();
+        }
         Console console = new CtsConsole();
         Console.startConsole(console, args);
     }
diff --git a/tools/tradefed-host/src/com/android/cts/tradefed/result/CtsXmlResultReporter.java b/tools/tradefed-host/src/com/android/cts/tradefed/result/CtsXmlResultReporter.java
index 686c90a..839b34d 100644
--- a/tools/tradefed-host/src/com/android/cts/tradefed/result/CtsXmlResultReporter.java
+++ b/tools/tradefed-host/src/com/android/cts/tradefed/result/CtsXmlResultReporter.java
@@ -44,6 +44,8 @@
 import java.io.InputStream;
 import java.io.OutputStream;
 import java.util.Map;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
 
 /**
  * Writes results to an XML files in the CTS format.
@@ -96,6 +98,9 @@
 
     private File mLogDir;
 
+    private static final String PTS_PERFORMANCE_EXCEPTION = "com.android.pts.util.PtsException";
+    private static final Pattern mPtsLogPattern = Pattern.compile(
+            "com\\.android\\.pts\\.util\\.PtsException:\\s(.*)");
     public void setReportDir(File reportDir) {
         mReportDir = reportDir;
     }
@@ -216,7 +221,20 @@
      */
     @Override
     public void testFailed(TestFailure status, TestIdentifier test, String trace) {
-        mCurrentPkgResult.reportTestFailure(test, CtsTestStatus.FAIL, trace);
+        if (trace.startsWith(PTS_PERFORMANCE_EXCEPTION)) { //PTS result
+            Test tst = mCurrentPkgResult.findTest(test);
+            // this exception is always thrown as exception is thrown from tearDown.
+            // Just ignore it.
+            if (tst.getName().endsWith("testAndroidTestCaseSetupProperly")) {
+                return;
+            }
+            Matcher m = mPtsLogPattern.matcher(trace);
+            if (m.find()) {
+                mCurrentPkgResult.reportPerformanceResult(test, CtsTestStatus.PASS, m.group(1));
+            }
+        } else {
+            mCurrentPkgResult.reportTestFailure(test, CtsTestStatus.FAIL, trace);
+        }
     }
 
     /**
diff --git a/tools/tradefed-host/src/com/android/cts/tradefed/result/Test.java b/tools/tradefed-host/src/com/android/cts/tradefed/result/Test.java
index 3c78df7..df1d4f1 100644
--- a/tools/tradefed-host/src/com/android/cts/tradefed/result/Test.java
+++ b/tools/tradefed-host/src/com/android/cts/tradefed/result/Test.java
@@ -84,6 +84,10 @@
         return mMessage;
     }
 
+    public void setMessage(String message) {
+        mMessage = message;
+    }
+
     public String getStartTime() {
         return mStartTime;
     }
@@ -125,14 +129,20 @@
         serializer.attribute(CtsXmlResultReporter.ns, ENDTIME_ATTR, mEndTime);
 
         if (mMessage != null) {
-            serializer.startTag(CtsXmlResultReporter.ns, SCENE_TAG);
-            serializer.attribute(CtsXmlResultReporter.ns, MESSAGE_ATTR, mMessage);
-            if (mStackTrace != null) {
-                serializer.startTag(CtsXmlResultReporter.ns, STACK_TAG);
-                serializer.text(mStackTrace);
-                serializer.endTag(CtsXmlResultReporter.ns, STACK_TAG);
+            if (mResult == CtsTestStatus.PASS) { // PTS will add performance result
+                serializer.startTag(CtsXmlResultReporter.ns, SCENE_TAG);
+                serializer.attribute(CtsXmlResultReporter.ns, MESSAGE_ATTR, mMessage);
+                serializer.endTag(CtsXmlResultReporter.ns, SCENE_TAG);
+            } else {
+                serializer.startTag(CtsXmlResultReporter.ns, SCENE_TAG);
+                serializer.attribute(CtsXmlResultReporter.ns, MESSAGE_ATTR, mMessage);
+                if (mStackTrace != null) {
+                    serializer.startTag(CtsXmlResultReporter.ns, STACK_TAG);
+                    serializer.text(mStackTrace);
+                    serializer.endTag(CtsXmlResultReporter.ns, STACK_TAG);
+                }
+                serializer.endTag(CtsXmlResultReporter.ns, SCENE_TAG);
             }
-            serializer.endTag(CtsXmlResultReporter.ns, SCENE_TAG);
         }
         serializer.endTag(CtsXmlResultReporter.ns, TAG);
     }
diff --git a/tools/tradefed-host/src/com/android/cts/tradefed/result/TestPackageResult.java b/tools/tradefed-host/src/com/android/cts/tradefed/result/TestPackageResult.java
index 23590e7..5997ec8 100644
--- a/tools/tradefed-host/src/com/android/cts/tradefed/result/TestPackageResult.java
+++ b/tools/tradefed-host/src/com/android/cts/tradefed/result/TestPackageResult.java
@@ -275,6 +275,18 @@
     }
 
     /**
+     * report performance result
+     * @param test
+     * @param status
+     * @param perf
+     */
+    public void reportPerformanceResult(TestIdentifier test, CtsTestStatus status, String perf) {
+        Test result = findTest(test);
+        result.setResultStatus(status);
+        result.setMessage(perf);
+    }
+
+    /**
      * Report that the given test has completed.
      *
      * @param test
diff --git a/tools/utils/buildCts.py b/tools/utils/buildCts.py
index 60c9084..77e93b1 100755
--- a/tools/utils/buildCts.py
+++ b/tools/utils/buildCts.py
@@ -54,20 +54,24 @@
 
   def __init__(self, argv):
     """Initialize the CtsBuilder from command line arguments."""
-    if not len(argv) == 6:
-      print 'Usage: %s <testRoot> <ctsOutputDir> <tempDir> <androidRootDir> <docletPath>' % argv[0]
+    if not (len(argv) == 6 or len(argv)==7):
+      print 'Usage: %s <testRoot> <ctsOutputDir> <tempDir> <androidRootDir> <docletPath> [-pts]' % argv[0]
       print ''
       print 'testRoot:       Directory under which to search for CTS tests.'
       print 'ctsOutputDir:   Directory in which the CTS repository should be created.'
       print 'tempDir:        Directory to use for storing temporary files.'
       print 'androidRootDir: Root directory of the Android source tree.'
       print 'docletPath:     Class path where the DescriptionGenerator doclet can be found.'
+      print '-pts:           generate plan for PTS.'
       sys.exit(1)
     self.test_root = sys.argv[1]
     self.out_dir = sys.argv[2]
     self.temp_dir = sys.argv[3]
     self.android_root = sys.argv[4]
     self.doclet_path = sys.argv[5]
+    self.isCts = True
+    if len(argv) ==7 and sys.argv[6] == "-pts":
+      self.isCts = False
 
     self.test_repository = os.path.join(self.out_dir, 'repository/testcases')
     self.plan_repository = os.path.join(self.out_dir, 'repository/plans')
@@ -99,6 +103,13 @@
       doc = tools.XmlFile(description)
       packages.append(doc.GetAttr('TestPackage', 'appPackageName'))
 
+    if not self.isCts: # PTS
+      plan = tools.TestPlan(packages)
+      plan.Include('.*')
+      plan.Exclude(r'android\.tests\.sigtest')
+      self.__WritePlan(plan, 'PTS')
+      return
+
     plan = tools.TestPlan(packages)
     plan.Exclude('android\.performance.*')
     self.__WritePlan(plan, 'CTS')
@@ -124,6 +135,19 @@
     plan.Include(r'android\.tests\.appsecurity')
     self.__WritePlan(plan, 'AppSecurity')
 
+    # hard-coded white list for PDK plan
+    plan.Exclude('.*')
+    plan.Include('android\.bluetooth')
+    plan.Include('android\.graphics.*')
+    plan.Include('android\.hardware')
+    plan.Include('android\.media.*')
+    plan.Include('android\.net')
+    plan.Include('android\.opengl.*')
+    plan.Include('android\.renderscript')
+    plan.Include('android\.telephony')
+    plan.Include('android\.nativemedia.*')
+    self.__WritePlan(plan, 'PDK')
+
 def LogGenerateDescription(name):
   print 'Generating test description for package %s' % name
 
@@ -145,3 +169,4 @@
   if result != 0:
     sys.exit(result)
   builder.GenerateTestPlans()
+
diff --git a/tools/utils/rerun.py b/tools/utils/rerun.py
new file mode 100644
index 0000000..86853a1
--- /dev/null
+++ b/tools/utils/rerun.py
@@ -0,0 +1,89 @@
+#!/usr/bin/env python
+#
+# 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.
+#
+import os
+import sys
+from xml.dom import Node
+from xml.dom import minidom
+
+def getChildrenWithTag(parent, tagName):
+    children = []
+    for child in  parent.childNodes:
+        if (child.nodeType == Node.ELEMENT_NODE) and (child.tagName == tagName):
+            #print "parent " + parent.getAttribute("name") + " " + tagName +\
+            #    " " + child.getAttribute("name")
+            children.append(child)
+    return children
+
+def parseSuite(suite, parentName):
+    if parentName != "":
+        parentName += '.'
+    failedCases = []
+    childSuites = getChildrenWithTag(suite, "TestSuite")
+    for child in childSuites:
+        for failure in parseSuite(child, parentName + child.getAttribute("name")):
+            failedCases.append(failure)
+    childTestCases = getChildrenWithTag(suite, "TestCase")
+    for child in childTestCases:
+        className = parentName + child.getAttribute("name")
+        for test in getChildrenWithTag(child, "Test"):
+            if test.getAttribute("result") != "pass":
+                failureName = className + "#" + test.getAttribute("name")
+                failedCases.append(failureName)
+    #if len(failedCases) > 0:
+    #    print failedCases
+    return failedCases
+
+def getFailedCases(resultXml):
+    failedCases = []
+    doc = minidom.parse(resultXml)
+    testResult = doc.getElementsByTagName("TestResult")[0]
+    packages = getChildrenWithTag(testResult, "TestPackage")
+    for package in packages:
+        casesFromChild = parseSuite(package, "")
+        for case in casesFromChild:
+            if case not in failedCases:
+                failedCases.append(case)
+
+    return failedCases
+
+def main(argv):
+    if len(argv) < 3:
+        print "rerun.py cts_path result_xml [-s serial]"
+        print " cts_path should end with android-cts"
+        sys.exit(1)
+    ctsPath = os.path.abspath(argv[1])
+    resultXml = os.path.abspath(argv[2])
+    deviceSerial = ""
+    if len(argv) > 3:
+        if argv[3] == "-s":
+            deviceSerial = argv[4]
+
+    failedCases = getFailedCases(resultXml)
+    print "Re-run follwong cases:"
+    for failure in failedCases:
+        print " " + failure
+    for failure in failedCases:
+        [className, methodName] = failure.split('#')
+        command = ctsPath + "/tools/cts-tradefed run singleCommand cts"
+        if deviceSerial != "":
+            command += " --serial " + deviceSerial
+        command += " --class " + className + " --method " + methodName
+        print command
+        os.system(command)
+
+if __name__ == '__main__':
+    main(sys.argv)
diff --git a/tools/vm-tests-tf/Android.mk b/tools/vm-tests-tf/Android.mk
index 44dac66..88f2a53 100644
--- a/tools/vm-tests-tf/Android.mk
+++ b/tools/vm-tests-tf/Android.mk
@@ -18,7 +18,9 @@
 # ============================================================
 include $(CLEAR_VARS)
 
+# custom variables used to generate test description. do not touch!
 LOCAL_TEST_TYPE := vmHostTest
+LOCAL_JAR_PATH := android.core.vm-tests-tf.jar
 
 LOCAL_SRC_FILES := $(call all-java-files-under, src)