am e565b868: Merge "Add unit tests for DateFormat k, h, K, and H."

* commit 'e565b86841efd6d2da6c5fe456539560b67ec88d':
  Add unit tests for DateFormat k, h, K, and H.
diff --git a/hostsidetests/appsecurity/test-apps/PermissionDeclareApp/src/com/android/cts/permissiondeclareapp/PermissionContentProvider.java b/hostsidetests/appsecurity/test-apps/PermissionDeclareApp/src/com/android/cts/permissiondeclareapp/PermissionContentProvider.java
index 900664f..aea874b 100644
--- a/hostsidetests/appsecurity/test-apps/PermissionDeclareApp/src/com/android/cts/permissiondeclareapp/PermissionContentProvider.java
+++ b/hostsidetests/appsecurity/test-apps/PermissionDeclareApp/src/com/android/cts/permissiondeclareapp/PermissionContentProvider.java
@@ -20,6 +20,10 @@
 import android.content.ContentValues;
 import android.database.Cursor;
 import android.net.Uri;
+import android.os.ParcelFileDescriptor;
+
+import java.io.File;
+import java.io.FileNotFoundException;
 
 /**
  * Empty content provider, all permissions are enforced in manifest
@@ -58,4 +62,10 @@
             String[] selectionArgs) {
         return 0;
     }
+
+    @Override
+    public ParcelFileDescriptor openFile(Uri uri, String mode) throws FileNotFoundException {
+        return ParcelFileDescriptor.open(
+                new File("/dev/null"), ParcelFileDescriptor.MODE_READ_ONLY);
+    }
 }
diff --git a/hostsidetests/appsecurity/test-apps/PermissionDeclareApp/src/com/android/cts/permissiondeclareapp/PermissionContentProviderGranting.java b/hostsidetests/appsecurity/test-apps/PermissionDeclareApp/src/com/android/cts/permissiondeclareapp/PermissionContentProviderGranting.java
index 97bd827..bb88c34 100644
--- a/hostsidetests/appsecurity/test-apps/PermissionDeclareApp/src/com/android/cts/permissiondeclareapp/PermissionContentProviderGranting.java
+++ b/hostsidetests/appsecurity/test-apps/PermissionDeclareApp/src/com/android/cts/permissiondeclareapp/PermissionContentProviderGranting.java
@@ -20,6 +20,10 @@
 import android.content.ContentValues;
 import android.database.Cursor;
 import android.net.Uri;
+import android.os.ParcelFileDescriptor;
+
+import java.io.File;
+import java.io.FileNotFoundException;
 
 /**
  * Empty content provider, all permissions are enforced in manifest
@@ -58,4 +62,10 @@
             String[] selectionArgs) {
         return 0;
     }
+
+    @Override
+    public ParcelFileDescriptor openFile(Uri uri, String mode) throws FileNotFoundException {
+        return ParcelFileDescriptor.open(
+                new File("/dev/null"), ParcelFileDescriptor.MODE_READ_ONLY);
+    }
 }
diff --git a/hostsidetests/appsecurity/test-apps/PermissionDeclareApp/src/com/android/cts/permissiondeclareapp/PermissionContentProviderPath.java b/hostsidetests/appsecurity/test-apps/PermissionDeclareApp/src/com/android/cts/permissiondeclareapp/PermissionContentProviderPath.java
index 4f301a3..13151f5 100644
--- a/hostsidetests/appsecurity/test-apps/PermissionDeclareApp/src/com/android/cts/permissiondeclareapp/PermissionContentProviderPath.java
+++ b/hostsidetests/appsecurity/test-apps/PermissionDeclareApp/src/com/android/cts/permissiondeclareapp/PermissionContentProviderPath.java
@@ -4,6 +4,10 @@
 import android.content.ContentValues;
 import android.database.Cursor;
 import android.net.Uri;
+import android.os.ParcelFileDescriptor;
+
+import java.io.File;
+import java.io.FileNotFoundException;
 
 /**
  * Empty content provider, all permissions are enforced in manifest
@@ -42,4 +46,10 @@
             String[] selectionArgs) {
         return 0;
     }
+
+    @Override
+    public ParcelFileDescriptor openFile(Uri uri, String mode) throws FileNotFoundException {
+        return ParcelFileDescriptor.open(
+                new File("/dev/null"), ParcelFileDescriptor.MODE_READ_ONLY);
+    }
 }
diff --git a/hostsidetests/appsecurity/test-apps/PermissionDeclareApp/src/com/android/cts/permissiondeclareapp/PermissionContentProviderPathRestricting.java b/hostsidetests/appsecurity/test-apps/PermissionDeclareApp/src/com/android/cts/permissiondeclareapp/PermissionContentProviderPathRestricting.java
index 3206206..41dd889 100644
--- a/hostsidetests/appsecurity/test-apps/PermissionDeclareApp/src/com/android/cts/permissiondeclareapp/PermissionContentProviderPathRestricting.java
+++ b/hostsidetests/appsecurity/test-apps/PermissionDeclareApp/src/com/android/cts/permissiondeclareapp/PermissionContentProviderPathRestricting.java
@@ -20,6 +20,10 @@
 import android.content.ContentValues;
 import android.database.Cursor;
 import android.net.Uri;
+import android.os.ParcelFileDescriptor;
+
+import java.io.File;
+import java.io.FileNotFoundException;
 
 /**
  * Empty content provider, all permissions are enforced in manifest
@@ -58,4 +62,10 @@
             String[] selectionArgs) {
         return 0;
     }
+
+    @Override
+    public ParcelFileDescriptor openFile(Uri uri, String mode) throws FileNotFoundException {
+        return ParcelFileDescriptor.open(
+                new File("/dev/null"), ParcelFileDescriptor.MODE_READ_ONLY);
+    }
 }
diff --git a/hostsidetests/appsecurity/test-apps/PermissionDeclareApp/src/com/android/cts/permissiondeclareapp/PrivateContentProvider.java b/hostsidetests/appsecurity/test-apps/PermissionDeclareApp/src/com/android/cts/permissiondeclareapp/PrivateContentProvider.java
index 64ec6e7..6ce5239 100644
--- a/hostsidetests/appsecurity/test-apps/PermissionDeclareApp/src/com/android/cts/permissiondeclareapp/PrivateContentProvider.java
+++ b/hostsidetests/appsecurity/test-apps/PermissionDeclareApp/src/com/android/cts/permissiondeclareapp/PrivateContentProvider.java
@@ -20,6 +20,10 @@
 import android.content.ContentValues;
 import android.database.Cursor;
 import android.net.Uri;
+import android.os.ParcelFileDescriptor;
+
+import java.io.File;
+import java.io.FileNotFoundException;
 
 /**
  * Empty content provider, all permissions are enforced in manifest
@@ -58,4 +62,10 @@
             String[] selectionArgs) {
         return 0;
     }
+
+    @Override
+    public ParcelFileDescriptor openFile(Uri uri, String mode) throws FileNotFoundException {
+        return ParcelFileDescriptor.open(
+                new File("/dev/null"), ParcelFileDescriptor.MODE_READ_ONLY);
+    }
 }
diff --git a/hostsidetests/appsecurity/test-apps/PermissionDeclareApp/src/com/android/cts/permissiondeclareapp/PrivateContentProviderGranting.java b/hostsidetests/appsecurity/test-apps/PermissionDeclareApp/src/com/android/cts/permissiondeclareapp/PrivateContentProviderGranting.java
index f9ae96b..372b399 100644
--- a/hostsidetests/appsecurity/test-apps/PermissionDeclareApp/src/com/android/cts/permissiondeclareapp/PrivateContentProviderGranting.java
+++ b/hostsidetests/appsecurity/test-apps/PermissionDeclareApp/src/com/android/cts/permissiondeclareapp/PrivateContentProviderGranting.java
@@ -20,6 +20,10 @@
 import android.content.ContentValues;
 import android.database.Cursor;
 import android.net.Uri;
+import android.os.ParcelFileDescriptor;
+
+import java.io.File;
+import java.io.FileNotFoundException;
 
 /**
  * Empty content provider, all permissions are enforced in manifest
@@ -58,4 +62,10 @@
             String[] selectionArgs) {
         return 0;
     }
+
+    @Override
+    public ParcelFileDescriptor openFile(Uri uri, String mode) throws FileNotFoundException {
+        return ParcelFileDescriptor.open(
+                new File("/dev/null"), ParcelFileDescriptor.MODE_READ_ONLY);
+    }
 }
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 a6495a9..e7d333c 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
@@ -19,6 +19,7 @@
 import android.content.BroadcastReceiver;
 import android.content.ClipData;
 import android.content.ComponentName;
+import android.content.ContentResolver;
 import android.content.ContentValues;
 import android.content.Context;
 import android.content.Intent;
@@ -28,6 +29,8 @@
 import android.test.AndroidTestCase;
 import android.util.Log;
 
+import java.io.IOException;
+
 /**
  * Tests that signature-enforced permissions cannot be accessed by apps signed
  * with different certs than app that declares the permission.
@@ -88,18 +91,71 @@
         }
     }
 
-    private void assertWritingContentUriNotAllowed(Uri uri, String msg) {
+    private void assertOpenFileDescriptorModeNotAllowed(Uri uri, String msg, String mode) {
         try {
-            getContext().getContentResolver().insert(uri, new ContentValues());
+            getContext().getContentResolver().openFileDescriptor(uri, mode).close();
             fail("expected SecurityException writing " + uri + ": " + msg);
+        } catch (IOException e) {
+            throw new IllegalStateException(e);
         } catch (SecurityException expected) {
             assertNotNull("security exception's error message.", expected.getMessage());
         }
     }
 
-    private void assertWritingContentUriAllowed(Uri uri) {
+    public void assertWritingContentUriNotAllowed(Uri uri, String msg) {
+        final ContentResolver resolver = getContext().getContentResolver();
         try {
-            getContext().getContentResolver().insert(uri, new ContentValues());
+            resolver.insert(uri, new ContentValues());
+            fail("expected SecurityException inserting " + uri + ": " + msg);
+        } catch (SecurityException expected) {
+            assertNotNull("security exception's error message.", expected.getMessage());
+        }
+
+        try {
+            resolver.update(uri, new ContentValues(), null, null);
+            fail("expected SecurityException updating " + uri + ": " + msg);
+        } catch (SecurityException expected) {
+            assertNotNull("security exception's error message.", expected.getMessage());
+        }
+
+        try {
+            resolver.delete(uri, null, null);
+            fail("expected SecurityException deleting " + uri + ": " + msg);
+        } catch (SecurityException expected) {
+            assertNotNull("security exception's error message.", expected.getMessage());
+        }
+
+        try {
+            getContext().getContentResolver().openOutputStream(uri).close();
+            fail("expected SecurityException writing " + uri + ": " + msg);
+        } catch (IOException e) {
+            throw new IllegalStateException(e);
+        } catch (SecurityException expected) {
+            assertNotNull("security exception's error message.", expected.getMessage());
+        }
+
+        assertOpenFileDescriptorModeNotAllowed(uri, msg, "w");
+        assertOpenFileDescriptorModeNotAllowed(uri, msg, "wt");
+        assertOpenFileDescriptorModeNotAllowed(uri, msg, "wa");
+        assertOpenFileDescriptorModeNotAllowed(uri, msg, "rw");
+        assertOpenFileDescriptorModeNotAllowed(uri, msg, "rwt");
+    }
+
+    private void assertWritingContentUriAllowed(Uri uri) {
+        final ContentResolver resolver = getContext().getContentResolver();
+        try {
+            resolver.insert(uri, new ContentValues());
+            resolver.update(uri, new ContentValues(), null, null);
+            resolver.delete(uri, null, null);
+
+            resolver.openOutputStream(uri).close();
+            resolver.openFileDescriptor(uri, "w").close();
+            resolver.openFileDescriptor(uri, "wt").close();
+            resolver.openFileDescriptor(uri, "wa").close();
+            resolver.openFileDescriptor(uri, "rw").close();
+            resolver.openFileDescriptor(uri, "rwt").close();
+        } catch (IOException e) {
+            fail("unexpected IOException writing " + uri + ": " + e.getMessage());
         } catch (SecurityException e) {
             fail("unexpected SecurityException writing " + uri + ": " + e.getMessage());
         }
diff --git a/tests/src/android/view/inputmethod/cts/InputMethodInfoStub.java b/tests/src/android/view/inputmethod/cts/InputMethodSettingsActivityStub.java
similarity index 84%
rename from tests/src/android/view/inputmethod/cts/InputMethodInfoStub.java
rename to tests/src/android/view/inputmethod/cts/InputMethodSettingsActivityStub.java
index 0eeefbe..58aa364 100644
--- a/tests/src/android/view/inputmethod/cts/InputMethodInfoStub.java
+++ b/tests/src/android/view/inputmethod/cts/InputMethodSettingsActivityStub.java
@@ -16,8 +16,8 @@
 
 package android.view.inputmethod.cts;
 
-import android.inputmethodservice.InputMethodService;
+import android.preference.PreferenceActivity;
 
-public class InputMethodInfoStub extends InputMethodService {
+public class InputMethodSettingsActivityStub extends PreferenceActivity {
 
 }
diff --git a/tests/tests/holo/AndroidManifest.xml b/tests/tests/holo/AndroidManifest.xml
index 7eb899c..4a03ba3 100644
--- a/tests/tests/holo/AndroidManifest.xml
+++ b/tests/tests/holo/AndroidManifest.xml
@@ -43,7 +43,12 @@
         <activity android:name="android.holo.cts.ThemeTestActivity"
                 android:configChanges="keyboardHidden|orientation|screenSize|mcc|mnc"
                 android:screenOrientation="nosensor"
-                android:theme="@android:style/Theme.Translucent.NoTitleBar" />
+                android:theme="@android:style/Theme.Translucent.NoTitleBar">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.DEFAULT" />
+            </intent-filter>
+        </activity>
 
         <activity android:name="android.holo.cts.LayoutTestActivity"
                 android:configChanges="keyboardHidden|orientation|screenSize|mcc|mnc"
diff --git a/tests/tests/holo/src/android/holo/cts/ThemeTestActivity.java b/tests/tests/holo/src/android/holo/cts/ThemeTestActivity.java
index 08659df..b7fdd1d 100644
--- a/tests/tests/holo/src/android/holo/cts/ThemeTestActivity.java
+++ b/tests/tests/holo/src/android/holo/cts/ThemeTestActivity.java
@@ -85,7 +85,8 @@
         int layoutIndex = getIntent().getIntExtra(EXTRA_LAYOUT_INDEX, -1);
         int adapterMode = getIntent().getIntExtra(EXTRA_LAYOUT_ADAPTER_MODE, -1);
 
-        Log.i(TAG, "Theme index: " + themeIndex + " Layout index: " + layoutIndex);
+        Log.i(TAG, "Theme index: " + themeIndex + " Layout index: " + layoutIndex +
+                " adapter mode: " + adapterMode);
 
         if (themeIndex < 0 && layoutIndex < 0) {
             mIterator = new AllThemesIterator(task, adapterMode);
@@ -109,6 +110,11 @@
             startActivityForResult(intent, mRequestCode);
         } else {
             mResultFuture.set(mPendingResult);
+            if (mRequestCode == GENERATE_BITMAP_REQUEST_CODE) {
+                // finish with result so that generated bitmaps can be captured automatically
+                setResult(0);
+                finish();
+            }
         }
     }
 
diff --git a/tests/tests/permission/src/android/permission/cts/FileSystemPermissionTest.java b/tests/tests/permission/src/android/permission/cts/FileSystemPermissionTest.java
index 32fd18d..4eb47c2 100644
--- a/tests/tests/permission/src/android/permission/cts/FileSystemPermissionTest.java
+++ b/tests/tests/permission/src/android/permission/cts/FileSystemPermissionTest.java
@@ -23,10 +23,12 @@
 import android.test.suitebuilder.annotation.MediumTest;
 import android.test.suitebuilder.annotation.LargeTest;
 
+import java.io.BufferedReader;
 import java.io.File;
 import java.io.FileFilter;
 import java.io.FileInputStream;
 import java.io.FileOutputStream;
+import java.io.FileReader;
 import java.io.IOException;
 import java.util.Arrays;
 import java.util.HashSet;
@@ -523,7 +525,8 @@
 
     @LargeTest
     public void testReadingSysFilesDoesntFail() throws Exception {
-        tryToReadFromAllIn(new File("/sys"));
+        // TODO: fix b/8148087
+        // tryToReadFromAllIn(new File("/sys"));
     }
 
     private static void tryToReadFromAllIn(File dir) throws IOException {
@@ -615,6 +618,42 @@
         return retval;
     }
 
+    public void testSystemMountedRO() throws IOException {
+        assertSystemMountedROIn("/proc/self/mounts");
+    }
+
+    public void testSystemMountedRO_init() throws IOException {
+        assertSystemMountedROIn("/proc/1/mounts");
+    }
+
+    /**
+     * Scan through {@code filename}, looking for the /system line. If the line
+     * has "ro" in the 4th column, then we know the filesystem is mounted read-only.
+     */
+    private static void assertSystemMountedROIn(String filename) throws IOException {
+        BufferedReader br = new BufferedReader(new FileReader(filename));
+        String line;
+        boolean foundSystem = false;
+        while((line = br.readLine()) != null) {
+            String[] fields = line.split(" ");
+            String mountPoint = fields[1];
+            if ("/system".equals(mountPoint)) {
+                foundSystem = true;
+                String all_options = fields[3];
+                boolean foundRo = false;
+                String[] options = all_options.split(",");
+                for (String option : options) {
+                    if ("ro".equals(option)) {
+                        foundRo = true;
+                        break;
+                    }
+                }
+                assertTrue(mountPoint + " is not mounted read-only", foundRo);
+            }
+        }
+        assertTrue("Cannot find /system partition", foundSystem);
+    }
+
     public void testAllBlockDevicesAreSecure() throws Exception {
         Set<File> insecure = getAllInsecureBlockDevicesInDirAndSubdir(new File("/dev"));
         assertTrue("Found insecure: " + insecure.toString(),
diff --git a/tests/tests/permission/src/android/permission/cts/NoLocationPermissionTest.java b/tests/tests/permission/src/android/permission/cts/NoLocationPermissionTest.java
index da9057e..80dffba 100644
--- a/tests/tests/permission/src/android/permission/cts/NoLocationPermissionTest.java
+++ b/tests/tests/permission/src/android/permission/cts/NoLocationPermissionTest.java
@@ -110,6 +110,33 @@
     }
 
     /**
+     * Verify that get cell location requires permissions.
+     * <p>
+     * Requires Permission: {@link
+     * android.Manifest.permission#ACCESS_COARSE_LOCATION.}
+     */
+    @SmallTest
+    public void testListenCellLocation2() {
+        TelephonyManager telephonyManager = (TelephonyManager) getContext().getSystemService(
+                Context.TELEPHONY_SERVICE);
+        PhoneStateListener phoneStateListener = new PhoneStateListener();
+
+        try {
+            telephonyManager.getNeighboringCellInfo();
+            fail("TelephonyManager.getNeighbouringCellInfo did not throw SecurityException as expected");
+        } catch (SecurityException e) {
+            // expected
+        }
+
+        try {
+            telephonyManager.getAllCellInfo();
+            fail("TelephonyManager.getAllCellInfo did not throw SecurityException as expected");
+        } catch (SecurityException e) {
+            // expected
+        }
+    }
+
+    /**
      * Helper method to verify that calling requestLocationUpdates with given
      * provider throws SecurityException.
      * 
diff --git a/tests/tests/view/src/android/view/inputmethod/cts/InputMethodInfoTest.java b/tests/tests/view/src/android/view/inputmethod/cts/InputMethodInfoTest.java
index 00a8dea..722c1b3 100644
--- a/tests/tests/view/src/android/view/inputmethod/cts/InputMethodInfoTest.java
+++ b/tests/tests/view/src/android/view/inputmethod/cts/InputMethodInfoTest.java
@@ -16,7 +16,6 @@
 
 package android.view.inputmethod.cts;
 
-
 import android.content.ComponentName;
 import android.content.Intent;
 import android.content.pm.PackageManager;
@@ -27,6 +26,7 @@
 import android.util.Printer;
 import android.view.inputmethod.InputMethod;
 import android.view.inputmethod.InputMethodInfo;
+import android.view.inputmethod.InputMethodSubtype;
 
 import org.xmlpull.v1.XmlPullParserException;
 
@@ -40,14 +40,40 @@
     private CharSequence mLabel;
     private String mSettingsActivity;
 
+    private int mSubtypeNameResId;
+    private int mSubtypeIconResId;
+    private String mSubtypeLocale;
+    private String mSubtypeMode;
+    private String mSubtypeExtraValue_key;
+    private String mSubtypeExtraValue_value;
+    private String mSubtypeExtraValue;
+    private boolean mSubtypeIsAuxiliary;
+    private boolean mSubtypeOverridesImplicitlyEnabledSubtype;
+    private int mSubtypeId;
+    private InputMethodSubtype mInputMethodSubtype;
+
     @Override
     protected void setUp() throws Exception {
         super.setUp();
         mPackageName = mContext.getPackageName();
-        mClassName = InputMethodInfoStub.class.getName();
+        mClassName = InputMethodSettingsActivityStub.class.getName();
         mLabel = "test";
-        mSettingsActivity = "android.view.inputmethod.cts.InputMethodInfoStub";
+        mSettingsActivity = "android.view.inputmethod.cts.InputMethodSettingsActivityStub";
         mInputMethodInfo = new InputMethodInfo(mPackageName, mClassName, mLabel, mSettingsActivity);
+
+        mSubtypeNameResId = 0;
+        mSubtypeIconResId = 0;
+        mSubtypeLocale = "en_US";
+        mSubtypeMode = "keyboard";
+        mSubtypeExtraValue_key = "key1";
+        mSubtypeExtraValue_value = "value1";
+        mSubtypeExtraValue = "tag," + mSubtypeExtraValue_key + "=" + mSubtypeExtraValue_value;
+        mSubtypeIsAuxiliary = false;
+        mSubtypeOverridesImplicitlyEnabledSubtype = false;
+        mSubtypeId = 99;
+        mInputMethodSubtype = new InputMethodSubtype(mSubtypeNameResId, mSubtypeIconResId,
+                mSubtypeLocale, mSubtypeMode, mSubtypeExtraValue, mSubtypeIsAuxiliary,
+                mSubtypeOverridesImplicitlyEnabledSubtype, mSubtypeId);
     }
 
     public void testInputMethodInfoProperties() throws XmlPullParserException, IOException {
@@ -58,7 +84,7 @@
         assertEquals(0, mInputMethodInfo.getIsDefaultResourceId());
 
         Intent intent = new Intent(InputMethod.SERVICE_INTERFACE);
-        intent.setClass(mContext, InputMethodInfoStub.class);
+        intent.setClass(mContext, InputMethodSettingsActivityStub.class);
         PackageManager pm = mContext.getPackageManager();
         List<ResolveInfo> ris = pm.queryIntentServices(intent, PackageManager.GET_META_DATA);
         for (int i = 0; i < ris.size(); i++) {
@@ -69,6 +95,22 @@
         }
     }
 
+    public void testInputMethodSubtypeProperties() {
+        // TODO: Test InputMethodSubtype.getDisplayName()
+        assertEquals(mSubtypeNameResId, mInputMethodSubtype.getNameResId());
+        assertEquals(mSubtypeIconResId, mInputMethodSubtype.getIconResId());
+        assertEquals(mSubtypeLocale, mInputMethodSubtype.getLocale());
+        assertEquals(mSubtypeMode, mInputMethodSubtype.getMode());
+        assertEquals(mSubtypeExtraValue, mInputMethodSubtype.getExtraValue());
+        assertTrue(mInputMethodSubtype.containsExtraValueKey(mSubtypeExtraValue_key));
+        assertEquals(mSubtypeExtraValue_value,
+                mInputMethodSubtype.getExtraValueOf(mSubtypeExtraValue_key));
+        assertEquals(mSubtypeIsAuxiliary, mInputMethodSubtype.isAuxiliary());
+        assertEquals(mSubtypeOverridesImplicitlyEnabledSubtype,
+                mInputMethodSubtype.overridesImplicitlyEnabledSubtype());
+        assertEquals(mSubtypeId, mInputMethodSubtype.hashCode());
+    }
+
     private void assertService(ServiceInfo expected, ServiceInfo actual) {
         assertEquals(expected.getIconResource(), actual.getIconResource());
         assertEquals(expected.labelRes, actual.labelRes);
@@ -110,19 +152,39 @@
         assertEquals(expected.toString(), mInputMethodInfo.loadLabel(pm).toString());
     }
 
-    public void testWriteToParcel() {
-        Parcel p = Parcel.obtain();
+    public void testInputMethodInfoWriteToParcel() {
+        final Parcel p = Parcel.obtain();
         mInputMethodInfo.writeToParcel(p, 0);
         p.setDataPosition(0);
-        InputMethodInfo inputMethodInfo = InputMethodInfo.CREATOR.createFromParcel(p);
+        final InputMethodInfo imi = InputMethodInfo.CREATOR.createFromParcel(p);
 
-        assertEquals(mInputMethodInfo.getPackageName(), inputMethodInfo.getPackageName());
-        assertEquals(mInputMethodInfo.getServiceName(), inputMethodInfo.getServiceName());
-        assertEquals(mInputMethodInfo.getSettingsActivity(), inputMethodInfo.getSettingsActivity());
-        assertEquals(mInputMethodInfo.getId(), inputMethodInfo.getId());
-        assertEquals(mInputMethodInfo.getIsDefaultResourceId(), inputMethodInfo
-                .getIsDefaultResourceId());
-        assertService(mInputMethodInfo.getServiceInfo(), inputMethodInfo.getServiceInfo());
+        assertEquals(mInputMethodInfo.getPackageName(), imi.getPackageName());
+        assertEquals(mInputMethodInfo.getServiceName(), imi.getServiceName());
+        assertEquals(mInputMethodInfo.getSettingsActivity(), imi.getSettingsActivity());
+        assertEquals(mInputMethodInfo.getId(), imi.getId());
+        assertEquals(mInputMethodInfo.getIsDefaultResourceId(), imi.getIsDefaultResourceId());
+        assertService(mInputMethodInfo.getServiceInfo(), imi.getServiceInfo());
+    }
+
+    public void testInputMethodSubtypeWriteToParcel() {
+        final Parcel p = Parcel.obtain();
+        mInputMethodSubtype.writeToParcel(p, 0);
+        p.setDataPosition(0);
+        final InputMethodSubtype subtype = InputMethodSubtype.CREATOR.createFromParcel(p);
+
+        assertEquals(mInputMethodSubtype.containsExtraValueKey(mSubtypeExtraValue_key),
+                subtype.containsExtraValueKey(mSubtypeExtraValue_key));
+        assertEquals(mInputMethodSubtype.getExtraValue(), subtype.getExtraValue());
+        assertEquals(mInputMethodSubtype.getExtraValueOf(mSubtypeExtraValue_key),
+                subtype.getExtraValueOf(mSubtypeExtraValue_key));
+        assertEquals(mInputMethodSubtype.getIconResId(), subtype.getIconResId());
+        assertEquals(mInputMethodSubtype.getLocale(), subtype.getLocale());
+        assertEquals(mInputMethodSubtype.getMode(), subtype.getMode());
+        assertEquals(mInputMethodSubtype.getNameResId(), subtype.getNameResId());
+        assertEquals(mInputMethodSubtype.hashCode(), subtype.hashCode());
+        assertEquals(mInputMethodSubtype.isAuxiliary(), subtype.isAuxiliary());
+        assertEquals(mInputMethodSubtype.overridesImplicitlyEnabledSubtype(),
+                subtype.overridesImplicitlyEnabledSubtype());
     }
 
     class MockPrinter implements Printer {
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 6674bdf..8fb2f15 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.2_r1";
+    public static final String CTS_BUILD_VERSION = "4.2_r2";
 
     /**
      * {@inheritDoc}