Merge "Fix ContentWrapperTest#testAccessDatabase" into jb-dev
diff --git a/CtsTestCaseList.mk b/CtsTestCaseList.mk
index 2feb76b..e525c7c 100644
--- a/CtsTestCaseList.mk
+++ b/CtsTestCaseList.mk
@@ -15,6 +15,7 @@
 cts_security_apps_list := \
 	CtsAppAccessData \
 	CtsAppWithData \
+	CtsExternalStorageApp \
 	CtsInstrumentationAppDiffCert \
 	CtsPermissionDeclareApp \
 	CtsSharedUidInstall \
@@ -22,7 +23,8 @@
 	CtsSimpleAppInstall \
 	CtsSimpleAppInstallDiffCert \
 	CtsTargetInstrumentationApp \
-	CtsUsePermissionDiffCert
+	CtsUsePermissionDiffCert \
+	CtsWriteExternalStorageApp
 
 cts_support_packages := \
 	CtsAccelerationTestStubs \
diff --git a/hostsidetests/appsecurity/src/com/android/cts/appsecurity/AppSecurityTests.java b/hostsidetests/appsecurity/src/com/android/cts/appsecurity/AppSecurityTests.java
index 7eb3a33..dc75e7d 100644
--- a/hostsidetests/appsecurity/src/com/android/cts/appsecurity/AppSecurityTests.java
+++ b/hostsidetests/appsecurity/src/com/android/cts/appsecurity/AppSecurityTests.java
@@ -21,6 +21,7 @@
 import com.android.ddmlib.testrunner.RemoteAndroidTestRunner;
 import com.android.tradefed.build.IBuildInfo;
 import com.android.tradefed.device.DeviceNotAvailableException;
+import com.android.tradefed.device.ITestDevice;
 import com.android.tradefed.result.CollectingTestListener;
 import com.android.tradefed.result.TestRunResult;
 import com.android.tradefed.testtype.DeviceTestCase;
@@ -58,6 +59,17 @@
     private static final String APP_ACCESS_DATA_APK = "CtsAppAccessData.apk";
     private static final String APP_ACCESS_DATA_PKG = "com.android.cts.appaccessdata";
 
+    // External storage constants
+    private static final String EXTERNAL_STORAGE_APP_APK = "CtsExternalStorageApp.apk";
+    private static final String EXTERNAL_STORAGE_APP_PKG = "com.android.cts.externalstorageapp";
+    private static final String EXTERNAL_STORAGE_APP_CLASS = EXTERNAL_STORAGE_APP_PKG
+            + ".ExternalStorageTest";
+    private static final String WRITE_EXTERNAL_STORAGE_APP_APK = "CtsWriteExternalStorageApp.apk";
+    private static final String
+            WRITE_EXTERNAL_STORAGE_APP_PKG = "com.android.cts.writeexternalstorageapp";
+    private static final String WRITE_EXTERNAL_STORAGE_APP_CLASS = WRITE_EXTERNAL_STORAGE_APP_PKG
+            + ".WriteExternalStorageTest";
+
     // testInstrumentationDiffCert constants
     private static final String TARGET_INSTRUMENT_APK = "CtsTargetInstrumentationApp.apk";
     private static final String TARGET_INSTRUMENT_PKG = "com.android.cts.targetinstrumentationapp";
@@ -72,6 +84,8 @@
     private static final String PERMISSION_DIFF_CERT_PKG =
         "com.android.cts.usespermissiondiffcertapp";
 
+    private static final String READ_EXTERNAL_STORAGE = "android.permission.READ_EXTERNAL_STORAGE";
+
     private static final String LOG_TAG = "AppSecurityTests";
 
     private CtsBuildHelper mCtsBuild;
@@ -179,6 +193,86 @@
     }
 
     /**
+     * Test behavior when
+     * {@link android.Manifest.permission#READ_EXTERNAL_STORAGE} is unenforced.
+     */
+    public void testReadExternalStorageUnenforced() throws Exception {
+        try {
+            getDevice().uninstallPackage(EXTERNAL_STORAGE_APP_PKG);
+            getDevice().uninstallPackage(WRITE_EXTERNAL_STORAGE_APP_PKG);
+
+            // stage test file on external storage
+            getDevice().pushString("CAEK", "/sdcard/meow");
+
+            // mark permission as not enforced
+            setPermissionEnforced(getDevice(), READ_EXTERNAL_STORAGE, false);
+
+            // install apps and run test
+            assertNull(getDevice()
+                    .installPackage(getTestAppFile(EXTERNAL_STORAGE_APP_APK), false));
+            assertNull(getDevice()
+                    .installPackage(getTestAppFile(WRITE_EXTERNAL_STORAGE_APP_APK), false));
+
+            // normal app should be able to read
+            assertTrue("Normal app unable to read external storage", runDeviceTests(
+                    EXTERNAL_STORAGE_APP_PKG, EXTERNAL_STORAGE_APP_CLASS,
+                    "testReadExternalStorage"));
+
+            // WRITE_EXTERNAL app should be able to read and write
+            assertTrue("WRITE_EXTERNAL app unable to read external storage", runDeviceTests(
+                    WRITE_EXTERNAL_STORAGE_APP_PKG, WRITE_EXTERNAL_STORAGE_APP_CLASS,
+                    "testReadExternalStorage"));
+            assertTrue("WRITE_EXTERNAL app unable to write external storage", runDeviceTests(
+                    WRITE_EXTERNAL_STORAGE_APP_PKG, WRITE_EXTERNAL_STORAGE_APP_CLASS,
+                    "testWriteExternalStorage"));
+
+        } finally {
+            getDevice().uninstallPackage(EXTERNAL_STORAGE_APP_PKG);
+            getDevice().uninstallPackage(WRITE_EXTERNAL_STORAGE_APP_PKG);
+        }
+    }
+
+    /**
+     * Test behavior when
+     * {@link android.Manifest.permission#READ_EXTERNAL_STORAGE} is enforced.
+     */
+    public void testReadExternalStorageEnforced() throws Exception {
+        try {
+            getDevice().uninstallPackage(EXTERNAL_STORAGE_APP_PKG);
+            getDevice().uninstallPackage(WRITE_EXTERNAL_STORAGE_APP_PKG);
+
+            // stage test file on external storage
+            getDevice().pushString("CAEK", "/sdcard/meow");
+
+            // mark permission as enforced
+            setPermissionEnforced(getDevice(), READ_EXTERNAL_STORAGE, true);
+
+            // install apps and run test
+            assertNull(getDevice()
+                    .installPackage(getTestAppFile(EXTERNAL_STORAGE_APP_APK), false));
+            assertNull(getDevice()
+                    .installPackage(getTestAppFile(WRITE_EXTERNAL_STORAGE_APP_APK), false));
+
+            // normal app should not be able to read
+            assertTrue("Normal app able to read external storage", runDeviceTests(
+                    EXTERNAL_STORAGE_APP_PKG, EXTERNAL_STORAGE_APP_CLASS,
+                    "testFailReadExternalStorage"));
+
+            // WRITE_EXTERNAL app should be able to read and write
+            assertTrue("WRITE_EXTERNAL app unable to read external storage", runDeviceTests(
+                    WRITE_EXTERNAL_STORAGE_APP_PKG, WRITE_EXTERNAL_STORAGE_APP_CLASS,
+                    "testReadExternalStorage"));
+            assertTrue("WRITE_EXTERNAL app unable to write external storage", runDeviceTests(
+                    WRITE_EXTERNAL_STORAGE_APP_PKG, WRITE_EXTERNAL_STORAGE_APP_CLASS,
+                    "testWriteExternalStorage"));
+
+        } finally {
+            getDevice().uninstallPackage(EXTERNAL_STORAGE_APP_PKG);
+            getDevice().uninstallPackage(WRITE_EXTERNAL_STORAGE_APP_PKG);
+        }
+    }
+
+    /**
      * Test that uninstall of an app removes its private data.
      */
     public void testUninstallRemovesData() throws Exception {
@@ -319,4 +413,10 @@
         return listener.getCurrentRunResults();
     }
 
+    private static void setPermissionEnforced(
+            ITestDevice device, String permission, boolean enforced)
+            throws DeviceNotAvailableException {
+        device.executeShellCommand("pm set-permission-enforced " + permission + " "
+                + Boolean.toString(enforced));
+    }
 }
diff --git a/hostsidetests/appsecurity/test-apps/ExternalStorageApp/Android.mk b/hostsidetests/appsecurity/test-apps/ExternalStorageApp/Android.mk
new file mode 100644
index 0000000..3c687f1
--- /dev/null
+++ b/hostsidetests/appsecurity/test-apps/ExternalStorageApp/Android.mk
@@ -0,0 +1,25 @@
+# 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_SDK_VERSION := 10
+
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+LOCAL_PACKAGE_NAME := CtsExternalStorageApp
+
+include $(BUILD_PACKAGE)
diff --git a/hostsidetests/appsecurity/test-apps/ExternalStorageApp/AndroidManifest.xml b/hostsidetests/appsecurity/test-apps/ExternalStorageApp/AndroidManifest.xml
new file mode 100644
index 0000000..0ba6684
--- /dev/null
+++ b/hostsidetests/appsecurity/test-apps/ExternalStorageApp/AndroidManifest.xml
@@ -0,0 +1,26 @@
+<?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.externalstorageapp">
+
+    <application>
+        <uses-library android:name="android.test.runner" />
+    </application>
+
+    <instrumentation android:name="android.test.InstrumentationTestRunner"
+        android:targetPackage="com.android.cts.externalstorageapp" />
+
+</manifest>
diff --git a/hostsidetests/appsecurity/test-apps/ExternalStorageApp/src/com/android/cts/externalstorageapp/ExternalStorageTest.java b/hostsidetests/appsecurity/test-apps/ExternalStorageApp/src/com/android/cts/externalstorageapp/ExternalStorageTest.java
new file mode 100644
index 0000000..d42353d
--- /dev/null
+++ b/hostsidetests/appsecurity/test-apps/ExternalStorageApp/src/com/android/cts/externalstorageapp/ExternalStorageTest.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.cts.externalstorageapp;
+
+import android.os.Environment;
+import android.test.AndroidTestCase;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+
+/**
+ * Test if {@link Environment#getExternalStorageDirectory()} is readable.
+ */
+public class ExternalStorageTest extends AndroidTestCase {
+
+    private static final String TEST_FILE = "meow";
+
+    private void assertExternalStorageMounted() {
+        assertEquals(Environment.MEDIA_MOUNTED, Environment.getExternalStorageState());
+    }
+
+    private void readExternalStorage() throws IOException {
+        final File file = new File(Environment.getExternalStorageDirectory(), TEST_FILE);
+        final InputStream is = new FileInputStream(file);
+        try {
+            is.read();
+        } finally {
+            is.close();
+        }
+    }
+
+    public void testReadExternalStorage() throws Exception {
+        assertExternalStorageMounted();
+        try {
+            readExternalStorage();
+        } catch (IOException e) {
+            fail("unable to read external file");
+        }
+    }
+
+    public void testFailReadExternalStorage() throws Exception {
+        assertExternalStorageMounted();
+        try {
+            readExternalStorage();
+            fail("able read external file");
+        } catch (IOException e) {
+            // expected
+            e.printStackTrace();
+        }
+    }
+}
diff --git a/hostsidetests/appsecurity/test-apps/WriteExternalStorageApp/Android.mk b/hostsidetests/appsecurity/test-apps/WriteExternalStorageApp/Android.mk
new file mode 100644
index 0000000..bdb2887
--- /dev/null
+++ b/hostsidetests/appsecurity/test-apps/WriteExternalStorageApp/Android.mk
@@ -0,0 +1,25 @@
+# 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_SDK_VERSION := 10
+
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+LOCAL_PACKAGE_NAME := CtsWriteExternalStorageApp
+
+include $(BUILD_PACKAGE)
diff --git a/hostsidetests/appsecurity/test-apps/WriteExternalStorageApp/AndroidManifest.xml b/hostsidetests/appsecurity/test-apps/WriteExternalStorageApp/AndroidManifest.xml
new file mode 100644
index 0000000..82910aa
--- /dev/null
+++ b/hostsidetests/appsecurity/test-apps/WriteExternalStorageApp/AndroidManifest.xml
@@ -0,0 +1,28 @@
+<?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.writeexternalstorageapp">
+
+    <application>
+        <uses-library android:name="android.test.runner" />
+    </application>
+
+    <instrumentation android:name="android.test.InstrumentationTestRunner"
+        android:targetPackage="com.android.cts.writeexternalstorageapp" />
+
+    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
+
+</manifest>
diff --git a/hostsidetests/appsecurity/test-apps/WriteExternalStorageApp/src/com/android/cts/writeexternalstorageapp/WriteExternalStorageTest.java b/hostsidetests/appsecurity/test-apps/WriteExternalStorageApp/src/com/android/cts/writeexternalstorageapp/WriteExternalStorageTest.java
new file mode 100644
index 0000000..b899bb0
--- /dev/null
+++ b/hostsidetests/appsecurity/test-apps/WriteExternalStorageApp/src/com/android/cts/writeexternalstorageapp/WriteExternalStorageTest.java
@@ -0,0 +1,78 @@
+/*
+ * 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.writeexternalstorageapp;
+
+import android.os.Environment;
+import android.test.AndroidTestCase;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+
+/**
+ * Test if {@link Environment#getExternalStorageDirectory()} is writable.
+ */
+public class WriteExternalStorageTest extends AndroidTestCase {
+
+    private static final String TEST_FILE = "meow";
+
+    private void assertExternalStorageMounted() {
+        assertEquals(Environment.MEDIA_MOUNTED, Environment.getExternalStorageState());
+    }
+
+    private void readExternalStorage() throws IOException {
+        final File file = new File(Environment.getExternalStorageDirectory(), TEST_FILE);
+        final InputStream is = new FileInputStream(file);
+        try {
+            is.read();
+        } finally {
+            is.close();
+        }
+    }
+
+    private void writeExternalStorage() throws IOException {
+        final File file = new File(Environment.getExternalStorageDirectory(), TEST_FILE);
+        final OutputStream os = new FileOutputStream(file);
+        try {
+            os.write(32);
+        } finally {
+            os.close();
+        }
+    }
+
+    public void testReadExternalStorage() throws Exception {
+        assertExternalStorageMounted();
+        try {
+            readExternalStorage();
+        } catch (IOException e) {
+            fail("unable to read external file");
+        }
+    }
+
+    public void testWriteExternalStorage() throws Exception {
+        assertExternalStorageMounted();
+        try {
+            writeExternalStorage();
+        } catch (IOException e) {
+            fail("unable to read external file");
+        }
+    }
+
+}
diff --git a/hostsidetests/monkey/src/com/android/cts/monkey/MonkeyTest.java b/hostsidetests/monkey/src/com/android/cts/monkey/MonkeyTest.java
index 2bf27ed..87e1268 100644
--- a/hostsidetests/monkey/src/com/android/cts/monkey/MonkeyTest.java
+++ b/hostsidetests/monkey/src/com/android/cts/monkey/MonkeyTest.java
@@ -55,7 +55,7 @@
                     assertEquals(isMonkey ? MONKEY : HUMAN, m.group(1));
                 }
             }
-            assertTrue(monkeyLogsFound);
+            assertTrue("No monkey logs were found!", monkeyLogsFound);
         } finally {
             s.close();
         }
diff --git a/hostsidetests/monkey/test-apps/CtsMonkeyApp/src/com/android/cts/monkey/BaboonActivity.java b/hostsidetests/monkey/test-apps/CtsMonkeyApp/src/com/android/cts/monkey/BaboonActivity.java
index f7b8f47..0b3c983 100644
--- a/hostsidetests/monkey/test-apps/CtsMonkeyApp/src/com/android/cts/monkey/BaboonActivity.java
+++ b/hostsidetests/monkey/test-apps/CtsMonkeyApp/src/com/android/cts/monkey/BaboonActivity.java
@@ -16,7 +16,5 @@
 
 package com.android.cts.monkey;
 
-import android.app.Activity;
-
-public class BaboonActivity extends Activity {
+public class BaboonActivity extends MonkeyActivity {
 }
diff --git a/tests/accessibilityservice/src/android/accessibilityservice/IAccessibilityServiceDelegateConnection.aidl b/tests/accessibilityservice/src/android/accessibilityservice/IAccessibilityServiceDelegateConnection.aidl
index 50da0d3..253a082 100644
--- a/tests/accessibilityservice/src/android/accessibilityservice/IAccessibilityServiceDelegateConnection.aidl
+++ b/tests/accessibilityservice/src/android/accessibilityservice/IAccessibilityServiceDelegateConnection.aidl
@@ -15,6 +15,7 @@
  */
 package android.accessibilityservice;
 
+import android.os.Bundle;
 import android.os.IBinder;
 import android.view.accessibility.AccessibilityEvent;
 import android.view.accessibility.AccessibilityNodeInfo;
@@ -40,7 +41,8 @@
 
     AccessibilityNodeInfo focusSearch(in AccessibilityNodeInfo current, int direction);
 
-    boolean performAccessibilityAction(in AccessibilityNodeInfo target, int action);
+    boolean performAccessibilityAction(in AccessibilityNodeInfo target, int action,
+           in Bundle arguments);
 
     AccessibilityNodeInfo getSource(in AccessibilityEvent event);
 
diff --git a/tests/accessibilityservice/src/android/accessibilityservice/delegate/DelegatingAccessibilityService.java b/tests/accessibilityservice/src/android/accessibilityservice/delegate/DelegatingAccessibilityService.java
index e5dfca7..b93e626 100644
--- a/tests/accessibilityservice/src/android/accessibilityservice/delegate/DelegatingAccessibilityService.java
+++ b/tests/accessibilityservice/src/android/accessibilityservice/delegate/DelegatingAccessibilityService.java
@@ -22,6 +22,7 @@
 import android.accessibilityservice.IAccessibilityServiceDelegateConnection;
 import android.app.Service;
 import android.content.Intent;
+import android.os.Bundle;
 import android.os.IBinder;
 import android.os.RemoteException;
 import android.util.Log;
@@ -169,8 +170,9 @@
             }
 
             @Override
-            public boolean performAccessibilityAction(AccessibilityNodeInfo target, int action) {
-                return target.performAction(action);
+            public boolean performAccessibilityAction(AccessibilityNodeInfo target, int action,
+                    Bundle arguments) {
+                return target.performAction(action, arguments);
             }
 
             @Override
diff --git a/tests/src/android/content/cts/MockContentProvider.java b/tests/src/android/content/cts/MockContentProvider.java
index 4cd870f..29c64805 100644
--- a/tests/src/android/content/cts/MockContentProvider.java
+++ b/tests/src/android/content/cts/MockContentProvider.java
@@ -18,7 +18,6 @@
 
 import java.util.HashMap;
 
-import android.content.CancellationSignal;
 import android.content.ContentProvider;
 import android.content.ContentUris;
 import android.content.ContentValues;
@@ -30,6 +29,7 @@
 import android.database.sqlite.SQLiteOpenHelper;
 import android.database.sqlite.SQLiteQueryBuilder;
 import android.net.Uri;
+import android.os.CancellationSignal;
 import android.text.TextUtils;
 
 public class MockContentProvider extends ContentProvider {
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 d539b4a..119aea1 100644
--- a/tests/tests/accessibility/src/android/view/accessibility/cts/AccessibilityNodeInfoTest.java
+++ b/tests/tests/accessibility/src/android/view/accessibility/cts/AccessibilityNodeInfoTest.java
@@ -33,7 +33,7 @@
 public class AccessibilityNodeInfoTest extends AndroidTestCase {
 
     /** The number of properties of the {@link AccessibilityNodeInfo} class. */
-    private static final int NON_STATIC_FIELD_COUNT = 28;
+    private static final int NON_STATIC_FIELD_COUNT = 30;
 
     @SmallTest
     public void testMarshaling() throws Exception {
@@ -141,6 +141,8 @@
         info.setScrollable(true);
         info.setSelected(true);
         info.addAction(AccessibilityNodeInfo.ACTION_CLEAR_FOCUS);
+        info.setAccessibilityFocused(true);
+        info.setMovementGranularities(AccessibilityNodeInfo.MOVEMENT_GRANULARITY_LINE);
     }
 
     /**
@@ -191,6 +193,12 @@
                 receivedInfo.getChildCount());
         assertSame("childCount has incorrect value", expectedInfo.getChildCount(),
                 receivedInfo.getChildCount());
+        assertSame("accessibilityFocused has incorrect value",
+                expectedInfo.isAccessibilityFocused(),
+                receivedInfo.isAccessibilityFocused());
+        assertSame("movementGranularities has incorrect value",
+                expectedInfo.getMovementGranularities(),
+                receivedInfo.getMovementGranularities());
     }
 
     /**
@@ -219,5 +227,8 @@
         assertFalse("scrollable not properly recycled", info.isScrollable());
         assertFalse("selected not properly recycled", info.isSelected());
         assertSame("actions not properly recycled", 0, info.getActions());
+        assertFalse("accessibilityFocused not properly recycled", info.isAccessibilityFocused());
+        assertSame("movementGranularities not properly recycled", 0,
+                info.getMovementGranularities());
     }
 }
diff --git a/tests/tests/accessibilityservice/AndroidManifest.xml b/tests/tests/accessibilityservice/AndroidManifest.xml
index 678775d..59fc8b0 100644
--- a/tests/tests/accessibilityservice/AndroidManifest.xml
+++ b/tests/tests/accessibilityservice/AndroidManifest.xml
@@ -40,6 +40,9 @@
       <activity android:label="@string/accessibility_focus_and_input_focus_sync_test_activity"
               android:name="android.accessibilityservice.cts.AccessibilityFocusAndInputFocusSyncActivity"/>
 
+      <activity android:label="@string/accessibility_text_traversal_test_activity"
+              android:name="android.accessibilityservice.cts.AccessibilityTextTraversalActivity"/> 
+
   </application>
 
   <instrumentation android:name="android.test.InstrumentationTestRunner"
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 bccb563..383f209 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
@@ -30,7 +30,7 @@
 
           <EditText
               android:id="@+id/firstEditText"
-              android:layout_width="200dip"
+              android:layout_width="wrap_content"
               android:layout_height="wrap_content"
               android:contentDescription="@string/firstEditText" />
 
@@ -67,7 +67,7 @@
 
           <EditText
               android:id="@+id/secondEditText"
-              android:layout_width="200dip"
+              android:layout_width="wrap_content"
               android:layout_height="wrap_content"
               android:contentDescription="@string/secondEditText" />
 
diff --git a/tests/tests/accessibilityservice/res/layout/accessibility_text_traversal_test.xml b/tests/tests/accessibilityservice/res/layout/accessibility_text_traversal_test.xml
new file mode 100644
index 0000000..1c15f8e
--- /dev/null
+++ b/tests/tests/accessibilityservice/res/layout/accessibility_text_traversal_test.xml
@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 2012, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:orientation="vertical"
+    android:layout_width="fill_parent"
+    android:layout_height="wrap_content"
+    >
+
+   <View
+       android:id="@+id/view"
+       android:layout_width="50dip"
+       android:layout_height="50dip"
+       />
+
+   <TextView
+       android:id="@+id/text"
+       android:layout_width="200dip"
+       android:layout_height="200dip"
+       />
+
+   <EditText
+       android:id="@+id/edit"
+       android:layout_width="200dip"
+       android:layout_height="200dip"
+       android:maxLines="1000"
+       android:scrollbars="vertical"
+       />
+
+</LinearLayout>
diff --git a/tests/tests/accessibilityservice/res/values/strings.xml b/tests/tests/accessibilityservice/res/values/strings.xml
index 48a5052..16ad575 100644
--- a/tests/tests/accessibilityservice/res/values/strings.xml
+++ b/tests/tests/accessibilityservice/res/values/strings.xml
@@ -125,4 +125,33 @@
     <!-- String title of the accessibility focus and input focus sync test activity -->
     <string name="accessibility_focus_and_input_focus_sync_test_activity">Accessibility focus and input focus sync test</string>
 
+    <!-- String title of the accessibility text traversal test activity. -->
+    <string name="accessibility_text_traversal_test_activity">Accessibility text traversal test</string>
+
+    <string name="android_wiki_short">
+        Android is a Linux-based operating system for mobile devices</string>
+
+    <string name="android_wiki">
+        Android is a Linux-based operating system for mobile devices such as smartphones and tablet
+        computers. It is developed by the Open Handset Alliance, led by Google, and other companies.
+        Google purchased the initial developer of the software, Android Inc., in 2005. The
+        unveiling of the Android distribution in 2007 was announced with the founding of the Open
+        Handset Alliance, a consortium of 86 hardware, software, and telecommunication companies
+        devoted to advancing open </string>
+
+    <string name="a_b">A B</string>
+
+    <string name="android_wiki_search">Android is a Linux-based</string>
+
+    <string name="foo_bar_baz">Foo bar baz.</string>
+
+    <string name="android_wiki_paragraphs">
+        \n\nAndroid is a Linux-based operating system for mobile devices such as smartphones and tablet
+        computers.\n\n It is developed by the Open Handset Alliance, led by Google, and other companies.
+        Google purchased the initial developer of the software, Android Inc., in 2005.\n The
+        unveiling of the Android distribution in 2007 was announced with the founding of the Open
+        Handset Alliance, a consortium of 86 hardware, software, and telecommunication companies
+        devoted to advancing open standards for mobile devices. Google releases the
+        Android code as open-source, under the Apache License.\n\n</string>
+
 </resources>
diff --git a/tests/tests/accessibilityservice/src/android/accessibilityservice/IAccessibilityServiceDelegateConnection.aidl b/tests/tests/accessibilityservice/src/android/accessibilityservice/IAccessibilityServiceDelegateConnection.aidl
index 50da0d3..253a082 100644
--- a/tests/tests/accessibilityservice/src/android/accessibilityservice/IAccessibilityServiceDelegateConnection.aidl
+++ b/tests/tests/accessibilityservice/src/android/accessibilityservice/IAccessibilityServiceDelegateConnection.aidl
@@ -15,6 +15,7 @@
  */
 package android.accessibilityservice;
 
+import android.os.Bundle;
 import android.os.IBinder;
 import android.view.accessibility.AccessibilityEvent;
 import android.view.accessibility.AccessibilityNodeInfo;
@@ -40,7 +41,8 @@
 
     AccessibilityNodeInfo focusSearch(in AccessibilityNodeInfo current, int direction);
 
-    boolean performAccessibilityAction(in AccessibilityNodeInfo target, int action);
+    boolean performAccessibilityAction(in AccessibilityNodeInfo target, int action,
+           in Bundle arguments);
 
     AccessibilityNodeInfo getSource(in AccessibilityEvent event);
 
diff --git a/tests/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityActivityTestCase.java b/tests/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityActivityTestCase.java
index 80a41a2..e6ef33d 100644
--- a/tests/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityActivityTestCase.java
+++ b/tests/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityActivityTestCase.java
@@ -28,6 +28,7 @@
 import android.content.pm.PackageManager;
 import android.content.pm.PackageManager.NameNotFoundException;
 import android.content.pm.ServiceInfo;
+import android.os.Bundle;
 import android.os.IBinder;
 import android.os.RemoteException;
 import android.os.SystemClock;
@@ -360,11 +361,16 @@
         }
 
         public boolean performAction(AccessibilityNodeInfo target, int action) {
+            return performAction(target, action, null);
+        }
+
+        public boolean performAction(AccessibilityNodeInfo target, int action, Bundle arguments) {
             try {
                 // Sending a node info across processes recycles
                 // it so use a clone to avoid losing state
                 AccessibilityNodeInfo targetClone = AccessibilityNodeInfo.obtain(target);
-                return getQueryConnection().performAccessibilityAction(targetClone, action);
+                return getQueryConnection().performAccessibilityAction(targetClone, action,
+                        arguments);
             } catch (RemoteException re) {
                 /* ignore */
             }
diff --git a/tests/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityTextTraversalActivity.java b/tests/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityTextTraversalActivity.java
new file mode 100644
index 0000000..7c9b45a
--- /dev/null
+++ b/tests/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityTextTraversalActivity.java
@@ -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.
+ */
+
+package android.accessibilityservice.cts;
+
+import android.app.Activity;
+import android.os.Bundle;
+
+import com.android.cts.accessibilityservice.R;
+
+/**
+ * Activity for testing the accessibility APIs for traversing the
+ * text content of a View at several granularities.
+ */
+public class AccessibilityTextTraversalActivity extends Activity {
+
+    @Override
+    public void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.accessibility_text_traversal_test);
+    }
+}
diff --git a/tests/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityTextTraversalTest.java b/tests/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityTextTraversalTest.java
new file mode 100644
index 0000000..0bc59f8
--- /dev/null
+++ b/tests/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityTextTraversalTest.java
@@ -0,0 +1,1726 @@
+/**
+ * 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.accessibilityservice.cts;
+
+import android.os.Bundle;
+import android.test.suitebuilder.annotation.MediumTest;
+import android.text.Selection;
+import android.view.View;
+import android.view.accessibility.AccessibilityEvent;
+import android.view.accessibility.AccessibilityNodeInfo;
+import android.widget.EditText;
+import android.widget.TextView;
+
+import com.android.cts.accessibilityservice.R;
+
+/**
+ * Test cases for testing the accessibility APIs for traversing the text content of
+ * a View at several granularities.
+ * <p>
+ * Note: The accessibility CTS tests are composed of two APKs, one with delegating
+ * accessibility service and another with the instrumented activity and test cases.
+ * The delegating service is installed and enabled during test execution. It serves
+ * as a proxy to the system used by the tests. This indirection is needed since the
+ * test runner stops the package before running the tests. Hence, if the accessibility
+ * service is in the test package running the tests would break the binding between
+ * the service and the system.  The delegating service is in
+ * <strong>CtsDelegatingAccessibilityService.apk</strong> whose source is located at
+ * <strong>cts/tests/accessibilityservice</strong>.
+ * </p>
+ */
+public class AccessibilityTextTraversalTest
+        extends AccessibilityActivityTestCase<AccessibilityTextTraversalActivity>{
+
+    public AccessibilityTextTraversalTest() {
+        super(AccessibilityTextTraversalActivity.class);
+    }
+
+    @MediumTest
+    public void testActionNextAndPreviousAtGranularityCharacterOverContentDescription()
+            throws Exception {
+
+        final View view = getActivity().findViewById(R.id.view);
+
+        getInstrumentation().runOnMainSync(new Runnable() {
+            @Override
+            public void run() {
+                view.setContentDescription(getString(R.string.a_b));
+            }
+        });
+
+        final AccessibilityNodeInfo text = getInteractionBridge()
+               .findAccessibilityNodeInfoByTextFromRoot(getString(R.string.a_b));
+
+        final int granularities = text.getMovementGranularities();
+        assertEquals(granularities, AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER
+                | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD
+                | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PARAGRAPH);
+
+        final Bundle arguments = new Bundle();
+        arguments.putInt(AccessibilityNodeInfo.ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT,
+                AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER);
+
+        // Move to the next character and wait for an event.
+        AccessibilityEvent firstExpected = getInteractionBridge()
+                .executeCommandAndWaitForAccessibilityEvent(new Runnable() {
+            @Override
+            public void run() {
+                getInteractionBridge().performAction(text,
+                        AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY, arguments);
+            }
+        }, new AccessibilityEventFilter() {
+            @Override
+            public boolean accept(AccessibilityEvent event) {
+                return
+                (event.getEventType() ==
+                    AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
+                        && event.getAction() ==
+                            AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY
+                        && event.getPackageName().equals(getActivity().getPackageName())
+                        && event.getClassName().equals(View.class.getName())
+                        && event.getContentDescription().toString().equals(
+                                getString(R.string.a_b))
+                        && event.getFromIndex() == 0
+                        && event.getToIndex() == 1
+                        && event.getMovementGranularity() ==
+                            AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER);
+            }
+        }, TIMEOUT_ASYNC_PROCESSING);
+
+        // Make sure we got the expected event.
+        assertNotNull(firstExpected);
+
+        // Move to the next character and wait for an event.
+        AccessibilityEvent secondExpected = getInteractionBridge()
+                .executeCommandAndWaitForAccessibilityEvent(new Runnable() {
+            @Override
+            public void run() {
+                getInteractionBridge().performAction(text,
+                        AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY, arguments);
+            }
+        }, new AccessibilityEventFilter() {
+            @Override
+            public boolean accept(AccessibilityEvent event) {
+                return
+                (event.getEventType() ==
+                    AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
+                        && event.getAction() ==
+                            AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY
+                        && event.getPackageName().equals(getActivity().getPackageName())
+                        && event.getClassName().equals(View.class.getName())
+                        && event.getContentDescription().toString().equals(
+                                getString(R.string.a_b))
+                        && event.getFromIndex() == 1
+                        && event.getToIndex() == 2
+                        && event.getMovementGranularity() ==
+                            AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER);
+            }
+        }, TIMEOUT_ASYNC_PROCESSING);
+
+        // Make sure we got the expected event.
+        assertNotNull(secondExpected);
+
+        // Move to the next character and wait for an event.
+        AccessibilityEvent thirdExpected = getInteractionBridge()
+                .executeCommandAndWaitForAccessibilityEvent(new Runnable() {
+            @Override
+            public void run() {
+                getInteractionBridge().performAction(text,
+                        AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY, arguments);
+            }
+        }, new AccessibilityEventFilter() {
+            @Override
+            public boolean accept(AccessibilityEvent event) {
+                return
+                (event.getEventType() ==
+                    AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
+                        && event.getAction() ==
+                            AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY
+                        && event.getPackageName().equals(getActivity().getPackageName())
+                        && event.getClassName().equals(View.class.getName())
+                        && event.getContentDescription().toString().equals(
+                                getString(R.string.a_b))
+                        && event.getFromIndex() == 2
+                        && event.getToIndex() == 3
+                        && event.getMovementGranularity() ==
+                            AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER);
+            }
+        }, TIMEOUT_ASYNC_PROCESSING);
+
+        // Make sure we got the expected event.
+        assertNotNull(thirdExpected);
+
+        // Make sure there is no next.
+        assertFalse(getInteractionBridge().performAction(text,
+                AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY, arguments));
+
+        // Move to the next character and wait for an event.
+        AccessibilityEvent fourthExpected = getInteractionBridge()
+                .executeCommandAndWaitForAccessibilityEvent(new Runnable() {
+            @Override
+            public void run() {
+                getInteractionBridge().performAction(text,
+                        AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY, arguments);
+            }
+        }, new AccessibilityEventFilter() {
+            @Override
+            public boolean accept(AccessibilityEvent event) {
+                return
+                (event.getEventType() ==
+                    AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
+                        && event.getAction() ==
+                            AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY
+                        && event.getPackageName().equals(getActivity().getPackageName())
+                        && event.getClassName().equals(View.class.getName())
+                        && event.getContentDescription().toString().equals(
+                                getString(R.string.a_b))
+                        && event.getFromIndex() == 2
+                        && event.getToIndex() == 3
+                        && event.getMovementGranularity() ==
+                            AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER);
+            }
+        }, TIMEOUT_ASYNC_PROCESSING);
+
+        // Make sure we got the expected event.
+        assertNotNull(fourthExpected);
+
+        // Move to the next character and wait for an event.
+        AccessibilityEvent fifthExpected = getInteractionBridge()
+                .executeCommandAndWaitForAccessibilityEvent(new Runnable() {
+            @Override
+            public void run() {
+                getInteractionBridge().performAction(text,
+                        AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY, arguments);
+            }
+        }, new AccessibilityEventFilter() {
+            @Override
+            public boolean accept(AccessibilityEvent event) {
+                return
+                (event.getEventType() ==
+                    AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
+                        && event.getAction() ==
+                            AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY
+                        && event.getPackageName().equals(getActivity().getPackageName())
+                        && event.getClassName().equals(View.class.getName())
+                        && event.getContentDescription().toString().equals(
+                                getString(R.string.a_b))
+                        && event.getFromIndex() == 1
+                        && event.getToIndex() == 2
+                        && event.getMovementGranularity() ==
+                            AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER);
+            }
+        }, TIMEOUT_ASYNC_PROCESSING);
+
+        // Make sure we got the expected event.
+        assertNotNull(fifthExpected);
+
+        // Move to the next character and wait for an event.
+        AccessibilityEvent sixthExpected = getInteractionBridge()
+                .executeCommandAndWaitForAccessibilityEvent(new Runnable() {
+            @Override
+            public void run() {
+                getInteractionBridge().performAction(text,
+                        AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY, arguments);
+            }
+        }, new AccessibilityEventFilter() {
+            @Override
+            public boolean accept(AccessibilityEvent event) {
+                return
+                (event.getEventType() ==
+                    AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
+                        && event.getAction() ==
+                            AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY
+                        && event.getPackageName().equals(getActivity().getPackageName())
+                        && event.getClassName().equals(View.class.getName())
+                        && event.getContentDescription().toString().equals(
+                                getString(R.string.a_b))
+                        && event.getFromIndex() == 0
+                        && event.getToIndex() == 1
+                        && event.getMovementGranularity() ==
+                            AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER);
+            }
+        }, TIMEOUT_ASYNC_PROCESSING);
+
+        // Make sure we got the expected event.
+        assertNotNull(sixthExpected);
+
+        // Make sure there is no previous.
+        assertFalse(getInteractionBridge().performAction(text,
+                AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY, arguments));
+    }
+
+    @MediumTest
+    public void testActionNextAndPreviousAtGranularityWordOverContentDescription()
+            throws Exception {
+        final View view = getActivity().findViewById(R.id.view);
+
+        getInstrumentation().runOnMainSync(new Runnable() {
+            @Override
+            public void run() {
+                view.setContentDescription(getString(R.string.foo_bar_baz));
+            }
+        });
+
+        final AccessibilityNodeInfo text = getInteractionBridge()
+               .findAccessibilityNodeInfoByTextFromRoot(getString(R.string.foo_bar_baz));
+
+        final int granularities = text.getMovementGranularities();
+        assertEquals(granularities, AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER
+                | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD
+                | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PARAGRAPH);
+
+        final Bundle arguments = new Bundle();
+        arguments.putInt(AccessibilityNodeInfo.ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT,
+                AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD);
+
+        // Move to the next character and wait for an event.
+        AccessibilityEvent firstExpected = getInteractionBridge()
+                .executeCommandAndWaitForAccessibilityEvent(new Runnable() {
+            @Override
+            public void run() {
+                getInteractionBridge().performAction(text,
+                        AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY, arguments);
+            }
+        }, new AccessibilityEventFilter() {
+            @Override
+            public boolean accept(AccessibilityEvent event) {
+                return
+                (event.getEventType() ==
+                    AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
+                        && event.getAction() ==
+                            AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY
+                        && event.getPackageName().equals(getActivity().getPackageName())
+                        && event.getClassName().equals(View.class.getName())
+                        && event.getContentDescription().toString().equals(
+                                getString(R.string.foo_bar_baz))
+                        && event.getFromIndex() == 0
+                        && event.getToIndex() == 3
+                        && event.getMovementGranularity() ==
+                            AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD);
+            }
+        }, TIMEOUT_ASYNC_PROCESSING);
+
+        // Make sure we got the expected event.
+        assertNotNull(firstExpected);
+
+        // Move to the next character and wait for an event.
+        AccessibilityEvent secondExpected = getInteractionBridge()
+                .executeCommandAndWaitForAccessibilityEvent(new Runnable() {
+            @Override
+            public void run() {
+                getInteractionBridge().performAction(text,
+                        AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY, arguments);
+            }
+        }, new AccessibilityEventFilter() {
+            @Override
+            public boolean accept(AccessibilityEvent event) {
+                return
+                (event.getEventType() ==
+                    AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
+                        && event.getAction() ==
+                            AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY
+                        && event.getPackageName().equals(getActivity().getPackageName())
+                        && event.getClassName().equals(View.class.getName())
+                        && event.getContentDescription().toString().equals(
+                                getString(R.string.foo_bar_baz))
+                        && event.getFromIndex() == 4
+                        && event.getToIndex() == 7
+                        && event.getMovementGranularity() ==
+                            AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD);
+            }
+        }, TIMEOUT_ASYNC_PROCESSING);
+
+        // Make sure we got the expected event.
+        assertNotNull(secondExpected);
+
+        // Move to the next character and wait for an event.
+        AccessibilityEvent thirdExpected = getInteractionBridge()
+                .executeCommandAndWaitForAccessibilityEvent(new Runnable() {
+            @Override
+            public void run() {
+                getInteractionBridge().performAction(text,
+                        AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY, arguments);
+            }
+        }, new AccessibilityEventFilter() {
+            @Override
+            public boolean accept(AccessibilityEvent event) {
+                return
+                (event.getEventType() ==
+                    AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
+                        && event.getAction() ==
+                            AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY
+                        && event.getPackageName().equals(getActivity().getPackageName())
+                        && event.getClassName().equals(View.class.getName())
+                        && event.getContentDescription().toString().equals(
+                                getString(R.string.foo_bar_baz))
+                        && event.getFromIndex() == 8
+                        && event.getToIndex() == 11
+                        && event.getMovementGranularity() ==
+                            AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD);
+            }
+        }, TIMEOUT_ASYNC_PROCESSING);
+
+        // Make sure we got the expected event.
+        assertNotNull(thirdExpected);
+
+        // Make sure there is no next.
+        assertFalse(getInteractionBridge().performAction(text,
+                AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY, arguments));
+
+        // Move to the next character and wait for an event.
+        AccessibilityEvent fourthExpected = getInteractionBridge()
+                .executeCommandAndWaitForAccessibilityEvent(new Runnable() {
+            @Override
+            public void run() {
+                getInteractionBridge().performAction(text,
+                        AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY, arguments);
+            }
+        }, new AccessibilityEventFilter() {
+            @Override
+            public boolean accept(AccessibilityEvent event) {
+                return
+                (event.getEventType() ==
+                    AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
+                        && event.getAction() ==
+                            AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY
+                        && event.getPackageName().equals(getActivity().getPackageName())
+                        && event.getClassName().equals(View.class.getName())
+                        && event.getContentDescription().toString().equals(
+                                getString(R.string.foo_bar_baz))
+                        && event.getFromIndex() == 8
+                        && event.getToIndex() == 11
+                        && event.getMovementGranularity() ==
+                            AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD);
+            }
+        }, TIMEOUT_ASYNC_PROCESSING);
+
+        // Make sure we got the expected event.
+        assertNotNull(fourthExpected);
+
+        // Move to the next character and wait for an event.
+        AccessibilityEvent fifthExpected = getInteractionBridge()
+                .executeCommandAndWaitForAccessibilityEvent(new Runnable() {
+            @Override
+            public void run() {
+                getInteractionBridge().performAction(text,
+                        AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY, arguments);
+            }
+        }, new AccessibilityEventFilter() {
+            @Override
+            public boolean accept(AccessibilityEvent event) {
+                return
+                (event.getEventType() ==
+                    AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
+                        && event.getAction() ==
+                            AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY
+                        && event.getPackageName().equals(getActivity().getPackageName())
+                        && event.getClassName().equals(View.class.getName())
+                        && event.getContentDescription().toString().equals(
+                                getString(R.string.foo_bar_baz))
+                        && event.getFromIndex() == 4
+                        && event.getToIndex() == 7
+                        && event.getMovementGranularity() ==
+                            AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD);
+            }
+        }, TIMEOUT_ASYNC_PROCESSING);
+
+        // Make sure we got the expected event.
+        assertNotNull(fifthExpected);
+
+        // Move to the next character and wait for an event.
+        AccessibilityEvent sixthExpected = getInteractionBridge()
+                .executeCommandAndWaitForAccessibilityEvent(new Runnable() {
+            @Override
+            public void run() {
+                getInteractionBridge().performAction(text,
+                        AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY, arguments);
+            }
+        }, new AccessibilityEventFilter() {
+            @Override
+            public boolean accept(AccessibilityEvent event) {
+                return
+                (event.getEventType() ==
+                    AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
+                        && event.getAction() ==
+                            AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY
+                        && event.getPackageName().equals(getActivity().getPackageName())
+                        && event.getClassName().equals(View.class.getName())
+                        && event.getContentDescription().toString().equals(
+                                getString(R.string.foo_bar_baz))
+                        && event.getFromIndex() == 0
+                        && event.getToIndex() == 3
+                        && event.getMovementGranularity() ==
+                            AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD);
+            }
+        }, TIMEOUT_ASYNC_PROCESSING);
+
+        // Make sure we got the expected event.
+        assertNotNull(sixthExpected);
+
+        // Make sure there is no previous.
+        assertFalse(getInteractionBridge().performAction(text,
+                AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY, arguments));
+    }
+
+    @MediumTest
+    public void testActionNextAndPreviousAtGranularityCharacterOverText()
+            throws Exception {
+        final TextView textView = (TextView) getActivity().findViewById(R.id.text);
+
+        getInstrumentation().runOnMainSync(new Runnable() {
+            @Override
+            public void run() {
+                textView.setText(getString(R.string.a_b));
+            }
+        });
+
+        final AccessibilityNodeInfo text = getInteractionBridge()
+               .findAccessibilityNodeInfoByTextFromRoot(getString(R.string.a_b));
+
+        final int granularities = text.getMovementGranularities();
+        assertEquals(granularities, AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER
+                | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD
+                | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_LINE
+                | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PARAGRAPH
+                | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PAGE);
+
+        final Bundle arguments = new Bundle();
+        arguments.putInt(AccessibilityNodeInfo.ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT,
+                AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER);
+
+        // Move to the next character and wait for an event.
+        AccessibilityEvent firstExpected = getInteractionBridge()
+                .executeCommandAndWaitForAccessibilityEvent(new Runnable() {
+            @Override
+            public void run() {
+                getInteractionBridge().performAction(text,
+                        AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY, arguments);
+            }
+        }, new AccessibilityEventFilter() {
+            @Override
+            public boolean accept(AccessibilityEvent event) {
+                return
+                (event.getEventType() ==
+                    AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
+                        && event.getAction() ==
+                            AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY
+                        && event.getPackageName().equals(getActivity().getPackageName())
+                        && event.getClassName().equals(TextView.class.getName())
+                        && event.getText().size() > 0
+                        && event.getText().get(0).toString().equals(getString(R.string.a_b))
+                        && event.getFromIndex() == 0
+                        && event.getToIndex() == 1
+                        && event.getMovementGranularity() ==
+                            AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER);
+            }
+        }, TIMEOUT_ASYNC_PROCESSING);
+
+        // Make sure we got the expected event.
+        assertNotNull(firstExpected);
+
+        // Verify the selection position.
+        assertEquals(0, Selection.getSelectionStart(textView.getText()));
+        assertEquals(0, Selection.getSelectionEnd(textView.getText()));
+
+        // Move to the next character and wait for an event.
+        AccessibilityEvent secondExpected = getInteractionBridge()
+                .executeCommandAndWaitForAccessibilityEvent(new Runnable() {
+            @Override
+            public void run() {
+                getInteractionBridge().performAction(text,
+                        AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY, arguments);
+            }
+        }, new AccessibilityEventFilter() {
+            @Override
+            public boolean accept(AccessibilityEvent event) {
+                return
+                (event.getEventType() ==
+                    AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
+                        && event.getAction() ==
+                            AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY
+                        && event.getPackageName().equals(getActivity().getPackageName())
+                        && event.getClassName().equals(TextView.class.getName())
+                        && event.getText().size() > 0
+                        && event.getText().get(0).toString().equals(getString(R.string.a_b))
+                        && event.getFromIndex() == 1
+                        && event.getToIndex() == 2
+                        && event.getMovementGranularity() ==
+                            AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER);
+            }
+        }, TIMEOUT_ASYNC_PROCESSING);
+
+        // Make sure we got the expected event.
+        assertNotNull(secondExpected);
+
+        // Verify the selection position.
+        assertEquals(1, Selection.getSelectionStart(textView.getText()));
+        assertEquals(1, Selection.getSelectionEnd(textView.getText()));
+
+        // Move to the next character and wait for an event.
+        AccessibilityEvent thirdExpected = getInteractionBridge()
+                .executeCommandAndWaitForAccessibilityEvent(new Runnable() {
+            @Override
+            public void run() {
+                getInteractionBridge().performAction(text,
+                        AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY, arguments);
+            }
+        }, new AccessibilityEventFilter() {
+            @Override
+            public boolean accept(AccessibilityEvent event) {
+                return
+                (event.getEventType() ==
+                    AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
+                        && event.getAction() ==
+                            AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY
+                        && event.getPackageName().equals(getActivity().getPackageName())
+                        && event.getClassName().equals(TextView.class.getName())
+                        && event.getText().size() > 0
+                        && event.getText().get(0).toString().equals(getString(R.string.a_b))
+                        && event.getFromIndex() == 2
+                        && event.getToIndex() == 3
+                        && event.getMovementGranularity() ==
+                            AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER);
+            }
+        }, TIMEOUT_ASYNC_PROCESSING);
+
+        // Make sure we got the expected event.
+        assertNotNull(thirdExpected);
+
+        // Verify the selection position.
+        assertEquals(2, Selection.getSelectionStart(textView.getText()));
+        assertEquals(2, Selection.getSelectionEnd(textView.getText()));
+
+        // Make sure there is no next.
+        assertFalse(getInteractionBridge().performAction(text,
+                AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY, arguments));
+
+        // Verify the selection position.
+        assertEquals(-1, Selection.getSelectionStart(textView.getText()));
+        assertEquals(-1, Selection.getSelectionEnd(textView.getText()));
+
+        // Move to the next character and wait for an event.
+        AccessibilityEvent fourthExpected = getInteractionBridge()
+                .executeCommandAndWaitForAccessibilityEvent(new Runnable() {
+            @Override
+            public void run() {
+                getInteractionBridge().performAction(text,
+                        AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY, arguments);
+            }
+        }, new AccessibilityEventFilter() {
+            @Override
+            public boolean accept(AccessibilityEvent event) {
+                return
+                (event.getEventType() ==
+                    AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
+                        && event.getAction() ==
+                            AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY
+                        && event.getPackageName().equals(getActivity().getPackageName())
+                        && event.getClassName().equals(TextView.class.getName())
+                        && event.getText().size() > 0
+                        && event.getText().get(0).toString().equals(getString(R.string.a_b))
+                        && event.getFromIndex() == 2
+                        && event.getToIndex() == 3
+                        && event.getMovementGranularity() ==
+                            AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER);
+            }
+        }, TIMEOUT_ASYNC_PROCESSING);
+
+        // Make sure we got the expected event.
+        assertNotNull(fourthExpected);
+
+        // Verify the selection position.
+        assertEquals(3, Selection.getSelectionStart(textView.getText()));
+        assertEquals(3, Selection.getSelectionEnd(textView.getText()));
+
+        // Move to the next character and wait for an event.
+        AccessibilityEvent fifthExpected = getInteractionBridge()
+                .executeCommandAndWaitForAccessibilityEvent(new Runnable() {
+            @Override
+            public void run() {
+                getInteractionBridge().performAction(text,
+                        AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY, arguments);
+            }
+        }, new AccessibilityEventFilter() {
+            @Override
+            public boolean accept(AccessibilityEvent event) {
+                return
+                (event.getEventType() ==
+                    AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
+                        && event.getAction() ==
+                            AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY
+                        && event.getPackageName().equals(getActivity().getPackageName())
+                        && event.getClassName().equals(TextView.class.getName())
+                        && event.getText().size() > 0
+                        && event.getText().get(0).toString().equals(getString(R.string.a_b))
+                        && event.getFromIndex() == 1
+                        && event.getToIndex() == 2
+                        && event.getMovementGranularity() ==
+                            AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER);
+            }
+        }, TIMEOUT_ASYNC_PROCESSING);
+
+        // Make sure we got the expected event.
+        assertNotNull(fifthExpected);
+
+        // Verify the selection position.
+        assertEquals(2, Selection.getSelectionStart(textView.getText()));
+        assertEquals(2, Selection.getSelectionEnd(textView.getText()));
+
+        // Move to the next character and wait for an event.
+        AccessibilityEvent sixthExpected = getInteractionBridge()
+                .executeCommandAndWaitForAccessibilityEvent(new Runnable() {
+            @Override
+            public void run() {
+                getInteractionBridge().performAction(text,
+                        AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY, arguments);
+            }
+        }, new AccessibilityEventFilter() {
+            @Override
+            public boolean accept(AccessibilityEvent event) {
+                return
+                (event.getEventType() ==
+                    AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
+                        && event.getAction() ==
+                            AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY
+                        && event.getPackageName().equals(getActivity().getPackageName())
+                        && event.getClassName().equals(TextView.class.getName())
+                        && event.getText().size() > 0
+                        && event.getText().get(0).toString().equals(getString(R.string.a_b))
+                        && event.getFromIndex() == 0
+                        && event.getToIndex() == 1
+                        && event.getMovementGranularity() ==
+                            AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER);
+            }
+        }, TIMEOUT_ASYNC_PROCESSING);
+
+        // Make sure we got the expected event.
+        assertNotNull(sixthExpected);
+
+        // Verify the selection position.
+        assertEquals(1, Selection.getSelectionStart(textView.getText()));
+        assertEquals(1, Selection.getSelectionEnd(textView.getText()));
+
+        // Make sure there is no previous.
+        assertFalse(getInteractionBridge().performAction(text,
+                AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY, arguments));
+
+        // Verify the selection position.
+        assertEquals(-1, Selection.getSelectionStart(textView.getText()));
+        assertEquals(-1, Selection.getSelectionEnd(textView.getText()));
+    }
+
+    @MediumTest
+    public void testActionNextAndPreviousAtGranularityWordOverText() throws Exception {
+        final TextView textView = (TextView) getActivity().findViewById(R.id.text);
+
+        getInstrumentation().runOnMainSync(new Runnable() {
+            @Override
+            public void run() {
+                textView.setText(getString(R.string.foo_bar_baz));
+            }
+        });
+
+        final AccessibilityNodeInfo text = getInteractionBridge()
+               .findAccessibilityNodeInfoByTextFromRoot(getString(R.string.foo_bar_baz));
+
+        final int granularities = text.getMovementGranularities();
+        assertEquals(granularities, AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER
+                | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD
+                | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_LINE
+                | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PARAGRAPH
+                | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PAGE);
+
+        final Bundle arguments = new Bundle();
+        arguments.putInt(AccessibilityNodeInfo.ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT,
+                AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD);
+
+        // Move to the next character and wait for an event.
+        AccessibilityEvent firstExpected = getInteractionBridge()
+                .executeCommandAndWaitForAccessibilityEvent(new Runnable() {
+            @Override
+            public void run() {
+                getInteractionBridge().performAction(text,
+                        AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY, arguments);
+            }
+        }, new AccessibilityEventFilter() {
+            @Override
+            public boolean accept(AccessibilityEvent event) {
+                return
+                (event.getEventType() ==
+                    AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
+                        && event.getAction() ==
+                            AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY
+                        && event.getPackageName().equals(getActivity().getPackageName())
+                        && event.getClassName().equals(TextView.class.getName())
+                        && event.getText().size() > 0
+                        && event.getText().get(0).toString().equals(getString(R.string.foo_bar_baz))
+                        && event.getFromIndex() == 0
+                        && event.getToIndex() == 3
+                        && event.getMovementGranularity() ==
+                            AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD);
+            }
+        }, TIMEOUT_ASYNC_PROCESSING);
+
+        // Make sure we got the expected event.
+        assertNotNull(firstExpected);
+
+        // Verify the selection position.
+        assertEquals(0, Selection.getSelectionStart(textView.getText()));
+        assertEquals(0, Selection.getSelectionEnd(textView.getText()));
+
+        // Move to the next character and wait for an event.
+        AccessibilityEvent secondExpected = getInteractionBridge()
+                .executeCommandAndWaitForAccessibilityEvent(new Runnable() {
+            @Override
+            public void run() {
+                getInteractionBridge().performAction(text,
+                        AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY, arguments);
+            }
+        }, new AccessibilityEventFilter() {
+            @Override
+            public boolean accept(AccessibilityEvent event) {
+                return
+                (event.getEventType() ==
+                    AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
+                        && event.getAction() ==
+                            AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY
+                        && event.getPackageName().equals(getActivity().getPackageName())
+                        && event.getClassName().equals(TextView.class.getName())
+                        && event.getText().size() > 0
+                        && event.getText().get(0).toString().equals(getString(R.string.foo_bar_baz))
+                        && event.getFromIndex() == 4
+                        && event.getToIndex() == 7
+                        && event.getMovementGranularity() ==
+                            AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD);
+            }
+        }, TIMEOUT_ASYNC_PROCESSING);
+
+        // Make sure we got the expected event.
+        assertNotNull(secondExpected);
+
+        // Verify the selection position.
+        assertEquals(4, Selection.getSelectionStart(textView.getText()));
+        assertEquals(4, Selection.getSelectionEnd(textView.getText()));
+
+        // Move to the next character and wait for an event.
+        AccessibilityEvent thirdExpected = getInteractionBridge()
+                .executeCommandAndWaitForAccessibilityEvent(new Runnable() {
+            @Override
+            public void run() {
+                getInteractionBridge().performAction(text,
+                        AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY, arguments);
+            }
+        }, new AccessibilityEventFilter() {
+            @Override
+            public boolean accept(AccessibilityEvent event) {
+                return
+                (event.getEventType() ==
+                    AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
+                        && event.getAction() ==
+                            AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY
+                        && event.getPackageName().equals(getActivity().getPackageName())
+                        && event.getClassName().equals(TextView.class.getName())
+                        && event.getText().size() > 0
+                        && event.getText().get(0).toString().equals(getString(R.string.foo_bar_baz))
+                        && event.getFromIndex() == 8
+                        && event.getToIndex() == 11
+                        && event.getMovementGranularity() ==
+                            AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD);
+            }
+        }, TIMEOUT_ASYNC_PROCESSING);
+
+        // Make sure we got the expected event.
+        assertNotNull(thirdExpected);
+
+        // Verify the selection position.
+        assertEquals(8, Selection.getSelectionStart(textView.getText()));
+        assertEquals(8, Selection.getSelectionEnd(textView.getText()));
+
+        // Make sure there is no next.
+        assertFalse(getInteractionBridge().performAction(text,
+                AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY, arguments));
+
+        // Verify the selection position.
+        assertEquals(-1, Selection.getSelectionStart(textView.getText()));
+        assertEquals(-1, Selection.getSelectionEnd(textView.getText()));
+
+        // Move to the next character and wait for an event.
+        AccessibilityEvent fourthExpected = getInteractionBridge()
+                .executeCommandAndWaitForAccessibilityEvent(new Runnable() {
+            @Override
+            public void run() {
+                getInteractionBridge().performAction(text,
+                        AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY, arguments);
+            }
+        }, new AccessibilityEventFilter() {
+            @Override
+            public boolean accept(AccessibilityEvent event) {
+                return
+                (event.getEventType() ==
+                    AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
+                        && event.getAction() ==
+                            AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY
+                        && event.getPackageName().equals(getActivity().getPackageName())
+                        && event.getClassName().equals(TextView.class.getName())
+                        && event.getText().size() > 0
+                        && event.getText().get(0).toString().equals(getString(R.string.foo_bar_baz))
+                        && event.getFromIndex() == 8
+                        && event.getToIndex() == 11
+                        && event.getMovementGranularity() ==
+                            AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD);
+            }
+        }, TIMEOUT_ASYNC_PROCESSING);
+
+        // Make sure we got the expected event.
+        assertNotNull(fourthExpected);
+
+        // Verify the selection position.
+        assertEquals(11, Selection.getSelectionStart(textView.getText()));
+        assertEquals(11, Selection.getSelectionEnd(textView.getText()));
+
+        // Move to the next character and wait for an event.
+        AccessibilityEvent fifthExpected = getInteractionBridge()
+                .executeCommandAndWaitForAccessibilityEvent(new Runnable() {
+            @Override
+            public void run() {
+                getInteractionBridge().performAction(text,
+                        AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY, arguments);
+            }
+        }, new AccessibilityEventFilter() {
+            @Override
+            public boolean accept(AccessibilityEvent event) {
+                return
+                (event.getEventType() ==
+                    AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
+                        && event.getAction() ==
+                            AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY
+                        && event.getPackageName().equals(getActivity().getPackageName())
+                        && event.getClassName().equals(TextView.class.getName())
+                        && event.getText().size() > 0
+                        && event.getText().get(0).toString().equals(getString(R.string.foo_bar_baz))
+                        && event.getFromIndex() == 4
+                        && event.getToIndex() == 7
+                        && event.getMovementGranularity() ==
+                            AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD);
+            }
+        }, TIMEOUT_ASYNC_PROCESSING);
+
+        // Make sure we got the expected event.
+        assertNotNull(fifthExpected);
+
+        // Verify the selection position.
+        assertEquals(7, Selection.getSelectionStart(textView.getText()));
+        assertEquals(7, Selection.getSelectionEnd(textView.getText()));
+
+        // Move to the next character and wait for an event.
+        AccessibilityEvent sixthExpected = getInteractionBridge()
+                .executeCommandAndWaitForAccessibilityEvent(new Runnable() {
+            @Override
+            public void run() {
+                getInteractionBridge().performAction(text,
+                        AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY, arguments);
+            }
+        }, new AccessibilityEventFilter() {
+            @Override
+            public boolean accept(AccessibilityEvent event) {
+                return
+                (event.getEventType() ==
+                    AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
+                        && event.getAction() ==
+                            AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY
+                        && event.getPackageName().equals(getActivity().getPackageName())
+                        && event.getClassName().equals(TextView.class.getName())
+                        && event.getText().size() > 0
+                        && event.getText().get(0).toString().equals(getString(R.string.foo_bar_baz))
+                        && event.getFromIndex() == 0
+                        && event.getToIndex() == 3
+                        && event.getMovementGranularity() ==
+                            AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD);
+            }
+        }, TIMEOUT_ASYNC_PROCESSING);
+
+        // Make sure we got the expected event.
+        assertNotNull(sixthExpected);
+
+        // Verify the selection position.
+        assertEquals(3, Selection.getSelectionStart(textView.getText()));
+        assertEquals(3, Selection.getSelectionEnd(textView.getText()));
+
+        // Make sure there is no previous.
+        assertFalse(getInteractionBridge().performAction(text,
+                AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY, arguments));
+
+        // Verify the selection position.
+        assertEquals(-1, Selection.getSelectionStart(textView.getText()));
+        assertEquals(-1, Selection.getSelectionEnd(textView.getText()));
+    }
+
+    @MediumTest
+    public void testActionNextAndPreviousAtGranularityLineOverText() throws Exception {
+        final TextView textView = (TextView) getActivity().findViewById(R.id.text);
+
+        getInstrumentation().runOnMainSync(new Runnable() {
+            @Override
+            public void run() {
+                textView.setText(getString(R.string.android_wiki_short));
+            }
+        });
+
+        final AccessibilityNodeInfo text = getInteractionBridge()
+               .findAccessibilityNodeInfoByTextFromRoot(getString(R.string.android_wiki_short));
+
+        final int granularities = text.getMovementGranularities();
+        assertEquals(granularities, AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER
+                | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD
+                | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_LINE
+                | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PARAGRAPH
+                | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PAGE);
+
+        final Bundle arguments = new Bundle();
+        arguments.putInt(AccessibilityNodeInfo.ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT,
+                AccessibilityNodeInfo.MOVEMENT_GRANULARITY_LINE);
+
+        // Move to the next character and wait for an event.
+        AccessibilityEvent firstExpected = getInteractionBridge()
+                .executeCommandAndWaitForAccessibilityEvent(new Runnable() {
+            @Override
+            public void run() {
+                getInteractionBridge().performAction(text,
+                        AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY, arguments);
+            }
+        }, new AccessibilityEventFilter() {
+            @Override
+            public boolean accept(AccessibilityEvent event) {
+                return
+                (event.getEventType() ==
+                    AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
+                        && event.getAction() ==
+                            AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY
+                        && event.getPackageName().equals(getActivity().getPackageName())
+                        && event.getClassName().equals(TextView.class.getName())
+                        && event.getText().size() > 0
+                        && event.getText().get(0).toString().equals(getString(
+                                R.string.android_wiki_short))
+                        && event.getFromIndex() == 0
+                        && event.getToIndex() == 25
+                        && event.getMovementGranularity() ==
+                            AccessibilityNodeInfo.MOVEMENT_GRANULARITY_LINE);
+            }
+        }, TIMEOUT_ASYNC_PROCESSING);
+
+        // Make sure we got the expected event.
+        assertNotNull(firstExpected);
+
+        // Verify the selection position.
+        assertEquals(0, Selection.getSelectionStart(textView.getText()));
+        assertEquals(0, Selection.getSelectionEnd(textView.getText()));
+
+        // Move to the next character and wait for an event.
+        AccessibilityEvent secondExpected = getInteractionBridge()
+                .executeCommandAndWaitForAccessibilityEvent(new Runnable() {
+            @Override
+            public void run() {
+                getInteractionBridge().performAction(text,
+                        AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY, arguments);
+            }
+        }, new AccessibilityEventFilter() {
+            @Override
+            public boolean accept(AccessibilityEvent event) {
+                return
+                (event.getEventType() ==
+                    AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
+                        && event.getAction() ==
+                            AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY
+                        && event.getPackageName().equals(getActivity().getPackageName())
+                        && event.getClassName().equals(TextView.class.getName())
+                        && event.getText().size() > 0
+                        && event.getText().get(0).toString().equals(getString(
+                                R.string.android_wiki_short))
+                        && event.getFromIndex() == 25
+                        && event.getToIndex() == 53
+                        && event.getMovementGranularity() ==
+                            AccessibilityNodeInfo.MOVEMENT_GRANULARITY_LINE);
+            }
+        }, TIMEOUT_ASYNC_PROCESSING);
+
+        // Make sure we got the expected event.
+        assertNotNull(secondExpected);
+
+        // Verify the selection position.
+        assertEquals(25, Selection.getSelectionStart(textView.getText()));
+        assertEquals(25, Selection.getSelectionEnd(textView.getText()));
+
+        // Move to the next character and wait for an event.
+        AccessibilityEvent thirdExpected = getInteractionBridge()
+                .executeCommandAndWaitForAccessibilityEvent(new Runnable() {
+            @Override
+            public void run() {
+                getInteractionBridge().performAction(text,
+                        AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY, arguments);
+            }
+        }, new AccessibilityEventFilter() {
+            @Override
+            public boolean accept(AccessibilityEvent event) {
+                return
+                (event.getEventType() ==
+                    AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
+                        && event.getAction() ==
+                            AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY
+                        && event.getPackageName().equals(getActivity().getPackageName())
+                        && event.getClassName().equals(TextView.class.getName())
+                        && event.getText().size() > 0
+                        && event.getText().get(0).toString().equals(getString(
+                                R.string.android_wiki_short))
+                        && event.getFromIndex() == 53
+                        && event.getToIndex() == 60
+                        && event.getMovementGranularity() ==
+                            AccessibilityNodeInfo.MOVEMENT_GRANULARITY_LINE);
+            }
+        }, TIMEOUT_ASYNC_PROCESSING);
+
+        // Make sure we got the expected event.
+        assertNotNull(thirdExpected);
+
+        // Verify the selection position.
+        assertEquals(53, Selection.getSelectionStart(textView.getText()));
+        assertEquals(53, Selection.getSelectionEnd(textView.getText()));
+
+        // Make sure there is no next.
+        assertFalse(getInteractionBridge().performAction(text,
+                AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY, arguments));
+
+        // Verify the selection position.
+        assertEquals(-1, Selection.getSelectionStart(textView.getText()));
+        assertEquals(-1, Selection.getSelectionEnd(textView.getText()));
+
+        // Move to the next character and wait for an event.
+        AccessibilityEvent fourthExpected = getInteractionBridge()
+                .executeCommandAndWaitForAccessibilityEvent(new Runnable() {
+            @Override
+            public void run() {
+                getInteractionBridge().performAction(text,
+                        AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY, arguments);
+            }
+        }, new AccessibilityEventFilter() {
+            @Override
+            public boolean accept(AccessibilityEvent event) {
+                return
+                (event.getEventType() ==
+                    AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
+                        && event.getAction() ==
+                            AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY
+                        && event.getPackageName().equals(getActivity().getPackageName())
+                        && event.getClassName().equals(TextView.class.getName())
+                        && event.getText().size() > 0
+                        && event.getText().get(0).toString().equals(getString(
+                                R.string.android_wiki_short))
+                        && event.getFromIndex() == 53
+                        && event.getToIndex() == 60
+                        && event.getMovementGranularity() ==
+                            AccessibilityNodeInfo.MOVEMENT_GRANULARITY_LINE);
+            }
+        }, TIMEOUT_ASYNC_PROCESSING);
+
+        // Make sure we got the expected event.
+        assertNotNull(fourthExpected);
+
+        // Verify the selection position.
+        assertEquals(60, Selection.getSelectionStart(textView.getText()));
+        assertEquals(60, Selection.getSelectionEnd(textView.getText()));
+
+        // Move to the next character and wait for an event.
+        AccessibilityEvent fifthExpected = getInteractionBridge()
+                .executeCommandAndWaitForAccessibilityEvent(new Runnable() {
+            @Override
+            public void run() {
+                getInteractionBridge().performAction(text,
+                        AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY, arguments);
+            }
+        }, new AccessibilityEventFilter() {
+            @Override
+            public boolean accept(AccessibilityEvent event) {
+                return
+                (event.getEventType() ==
+                    AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
+                        && event.getAction() ==
+                            AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY
+                        && event.getPackageName().equals(getActivity().getPackageName())
+                        && event.getClassName().equals(TextView.class.getName())
+                        && event.getText().size() > 0
+                        && event.getText().get(0).toString().equals(getString(
+                                R.string.android_wiki_short))
+                        && event.getFromIndex() == 25
+                        && event.getToIndex() == 53
+                        && event.getMovementGranularity() ==
+                            AccessibilityNodeInfo.MOVEMENT_GRANULARITY_LINE);
+            }
+        }, TIMEOUT_ASYNC_PROCESSING);
+
+        // Make sure we got the expected event.
+        assertNotNull(fifthExpected);
+
+        // Verify the selection position.
+        assertEquals(53, Selection.getSelectionStart(textView.getText()));
+        assertEquals(53, Selection.getSelectionEnd(textView.getText()));
+
+        // Move to the next character and wait for an event.
+        AccessibilityEvent sixthExpected = getInteractionBridge()
+                .executeCommandAndWaitForAccessibilityEvent(new Runnable() {
+            @Override
+            public void run() {
+                getInteractionBridge().performAction(text,
+                        AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY, arguments);
+            }
+        }, new AccessibilityEventFilter() {
+            @Override
+            public boolean accept(AccessibilityEvent event) {
+                return
+                (event.getEventType() ==
+                    AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
+                        && event.getAction() ==
+                            AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY
+                        && event.getPackageName().equals(getActivity().getPackageName())
+                        && event.getClassName().equals(TextView.class.getName())
+                        && event.getText().size() > 0
+                        && event.getText().get(0).toString().equals(getString(
+                                R.string.android_wiki_short))
+                        && event.getFromIndex() == 0
+                        && event.getToIndex() == 25
+                        && event.getMovementGranularity() ==
+                            AccessibilityNodeInfo.MOVEMENT_GRANULARITY_LINE);
+            }
+        }, TIMEOUT_ASYNC_PROCESSING);
+
+        // Make sure we got the expected event.
+        assertNotNull(sixthExpected);
+
+        // Verify the selection position.
+        assertEquals(25, Selection.getSelectionStart(textView.getText()));
+        assertEquals(25, Selection.getSelectionEnd(textView.getText()));
+
+        // Make sure there is no previous.
+        assertFalse(getInteractionBridge().performAction(text,
+                AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY, arguments));
+
+        // Verify the selection position.
+        assertEquals(-1, Selection.getSelectionStart(textView.getText()));
+        assertEquals(-1, Selection.getSelectionEnd(textView.getText()));
+    }
+
+    @MediumTest
+    public void testActionNextAndPreviousAtGranularityPageOverText() throws Exception {
+        final EditText editText = (EditText) getActivity().findViewById(R.id.edit);
+
+        getInstrumentation().runOnMainSync(new Runnable() {
+            @Override
+            public void run() {
+                editText.setText(getString(R.string.android_wiki));
+                Selection.removeSelection(editText.getText());
+            }
+        });
+
+        final AccessibilityNodeInfo text = getInteractionBridge()
+               .findAccessibilityNodeInfoByTextFromRoot(getString(R.string.android_wiki));
+
+        final int granularities = text.getMovementGranularities();
+        assertEquals(granularities, AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER
+                | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD
+                | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_LINE
+                | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PARAGRAPH
+                | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PAGE);
+
+        final Bundle arguments = new Bundle();
+        arguments.putInt(AccessibilityNodeInfo.ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT,
+                AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PAGE);
+
+        // Move to the next character and wait for an event.
+        AccessibilityEvent firstExpected = getInteractionBridge()
+                .executeCommandAndWaitForAccessibilityEvent(new Runnable() {
+            @Override
+            public void run() {
+                getInteractionBridge().performAction(text,
+                        AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY, arguments);
+            }
+        }, new AccessibilityEventFilter() {
+            @Override
+            public boolean accept(AccessibilityEvent event) {
+                return
+                (event.getEventType() ==
+                    AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
+                        && event.getAction() ==
+                            AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY
+                        && event.getPackageName().equals(getActivity().getPackageName())
+                        && event.getClassName().equals(EditText.class.getName())
+                        && event.getText().size() > 0
+                        && event.getText().get(0).toString().equals(getString(
+                                R.string.android_wiki))
+                        && event.getFromIndex() == 0
+                        && event.getToIndex() == 156
+                        && event.getMovementGranularity() ==
+                            AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PAGE);
+            }
+        }, TIMEOUT_ASYNC_PROCESSING);
+
+        // Make sure we got the expected event.
+        assertNotNull(firstExpected);
+
+        // Verify the selection position.
+        assertEquals(0, Selection.getSelectionStart(editText.getText()));
+        assertEquals(0, Selection.getSelectionEnd(editText.getText()));
+
+        // Move to the next character and wait for an event.
+        AccessibilityEvent secondExpected = getInteractionBridge()
+                .executeCommandAndWaitForAccessibilityEvent(new Runnable() {
+            @Override
+            public void run() {
+                getInteractionBridge().performAction(text,
+                        AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY, arguments);
+            }
+        }, new AccessibilityEventFilter() {
+            @Override
+            public boolean accept(AccessibilityEvent event) {
+                return
+                (event.getEventType() ==
+                    AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
+                        && event.getAction() ==
+                            AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY
+                        && event.getPackageName().equals(getActivity().getPackageName())
+                        && event.getClassName().equals(EditText.class.getName())
+                        && event.getText().size() > 0
+                        && event.getText().get(0).toString().equals(getString(
+                                R.string.android_wiki))
+                        && event.getFromIndex() == 156
+                        && event.getToIndex() == 318
+                        && event.getMovementGranularity() ==
+                            AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PAGE);
+            }
+        }, TIMEOUT_ASYNC_PROCESSING);
+
+        // Make sure we got the expected event.
+        assertNotNull(secondExpected);
+
+        // Verify the selection position.
+        assertEquals(156, Selection.getSelectionStart(editText.getText()));
+        assertEquals(156, Selection.getSelectionEnd(editText.getText()));
+
+        // Move to the next character and wait for an event.
+        AccessibilityEvent thirdExpected = getInteractionBridge()
+                .executeCommandAndWaitForAccessibilityEvent(new Runnable() {
+            @Override
+            public void run() {
+                getInteractionBridge().performAction(text,
+                        AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY, arguments);
+            }
+        }, new AccessibilityEventFilter() {
+            @Override
+            public boolean accept(AccessibilityEvent event) {
+                return
+                (event.getEventType() ==
+                    AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
+                        && event.getAction() ==
+                            AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY
+                        && event.getPackageName().equals(getActivity().getPackageName())
+                        && event.getClassName().equals(EditText.class.getName())
+                        && event.getText().size() > 0
+                        && event.getText().get(0).toString().equals(getString(
+                                R.string.android_wiki))
+                        && event.getFromIndex() == 318
+                        && event.getToIndex() == 472
+                        && event.getMovementGranularity() ==
+                            AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PAGE);
+            }
+        }, TIMEOUT_ASYNC_PROCESSING);
+
+        // Make sure we got the expected event.
+        assertNotNull(thirdExpected);
+
+        // Verify the selection position.
+        assertEquals(318, Selection.getSelectionStart(editText.getText()));
+        assertEquals(318, Selection.getSelectionEnd(editText.getText()));
+
+        // Make sure there is no next.
+        assertFalse(getInteractionBridge().performAction(text,
+                AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY, arguments));
+
+        // Verify the selection position.
+        assertEquals(-1, Selection.getSelectionStart(editText.getText()));
+        assertEquals(-1, Selection.getSelectionEnd(editText.getText()));
+
+        // Move to the next character and wait for an event.
+        AccessibilityEvent fourthExpected = getInteractionBridge()
+                .executeCommandAndWaitForAccessibilityEvent(new Runnable() {
+            @Override
+            public void run() {
+                getInteractionBridge().performAction(text,
+                        AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY, arguments);
+            }
+        }, new AccessibilityEventFilter() {
+            @Override
+            public boolean accept(AccessibilityEvent event) {
+                return
+                (event.getEventType() ==
+                    AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
+                        && event.getAction() ==
+                            AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY
+                        && event.getPackageName().equals(getActivity().getPackageName())
+                        && event.getClassName().equals(EditText.class.getName())
+                        && event.getText().size() > 0
+                        && event.getText().get(0).toString().equals(getString(
+                                R.string.android_wiki))
+                        && event.getFromIndex() == 318
+                        && event.getToIndex() == 472
+                        && event.getMovementGranularity() ==
+                            AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PAGE);
+            }
+        }, TIMEOUT_ASYNC_PROCESSING);
+
+        // Make sure we got the expected event.
+        assertNotNull(fourthExpected);
+
+        // Verify the selection position.
+        assertEquals(472, Selection.getSelectionStart(editText.getText()));
+        assertEquals(472, Selection.getSelectionEnd(editText.getText()));
+
+        // Move to the next character and wait for an event.
+        AccessibilityEvent fifthExpected = getInteractionBridge()
+                .executeCommandAndWaitForAccessibilityEvent(new Runnable() {
+            @Override
+            public void run() {
+                getInteractionBridge().performAction(text,
+                        AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY, arguments);
+            }
+        }, new AccessibilityEventFilter() {
+            @Override
+            public boolean accept(AccessibilityEvent event) {
+                return
+                (event.getEventType() ==
+                    AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
+                        && event.getAction() ==
+                            AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY
+                        && event.getPackageName().equals(getActivity().getPackageName())
+                        && event.getClassName().equals(EditText.class.getName())
+                        && event.getText().size() > 0
+                        && event.getText().get(0).toString().equals(getString(
+                                R.string.android_wiki))
+                        && event.getFromIndex() == 156
+                        && event.getToIndex() == 318
+                        && event.getMovementGranularity() ==
+                            AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PAGE);
+            }
+        }, TIMEOUT_ASYNC_PROCESSING);
+
+        // Make sure we got the expected event.
+        assertNotNull(fifthExpected);
+
+        // Verify the selection position.
+        assertEquals(318, Selection.getSelectionStart(editText.getText()));
+        assertEquals(318, Selection.getSelectionEnd(editText.getText()));
+
+        // Move to the next character and wait for an event.
+        AccessibilityEvent sixthExpected = getInteractionBridge()
+                .executeCommandAndWaitForAccessibilityEvent(new Runnable() {
+            @Override
+            public void run() {
+                getInteractionBridge().performAction(text,
+                        AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY, arguments);
+            }
+        }, new AccessibilityEventFilter() {
+            @Override
+            public boolean accept(AccessibilityEvent event) {
+                return
+                (event.getEventType() ==
+                    AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
+                        && event.getAction() ==
+                            AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY
+                        && event.getPackageName().equals(getActivity().getPackageName())
+                        && event.getClassName().equals(EditText.class.getName())
+                        && event.getText().size() > 0
+                        && event.getText().get(0).toString().equals(getString(
+                                R.string.android_wiki))
+                        && event.getFromIndex() == 0
+                        && event.getToIndex() == 156
+                        && event.getMovementGranularity() ==
+                            AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PAGE);
+            }
+        }, TIMEOUT_ASYNC_PROCESSING);
+
+        // Make sure we got the expected event.
+        assertNotNull(sixthExpected);
+
+        // Verify the selection position.
+        assertEquals(156, Selection.getSelectionStart(editText.getText()));
+        assertEquals(156, Selection.getSelectionEnd(editText.getText()));
+
+        // Make sure there is no previous.
+        assertFalse(getInteractionBridge().performAction(text,
+                AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY, arguments));
+
+        // Verify the selection position.
+        assertEquals(-1, Selection.getSelectionStart(editText.getText()));
+        assertEquals(-1, Selection.getSelectionEnd(editText.getText()));
+    }
+
+    @MediumTest
+    public void testActionNextAndPreviousAtGranularityParagraphOverText() throws Exception {
+        final TextView textView = (TextView) getActivity().findViewById(R.id.edit);
+
+        getInstrumentation().runOnMainSync(new Runnable() {
+            @Override
+            public void run() {
+                textView.setText(getString(R.string.android_wiki_paragraphs));
+            }
+        });
+
+        final AccessibilityNodeInfo text = getInteractionBridge()
+               .findAccessibilityNodeInfoByTextFromRoot(getString(R.string.android_wiki_short));
+
+        final int granularities = text.getMovementGranularities();
+        assertEquals(granularities, AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER
+                | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD
+                | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_LINE
+                | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PARAGRAPH
+                | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PAGE);
+
+        final Bundle arguments = new Bundle();
+        arguments.putInt(AccessibilityNodeInfo.ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT,
+                AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PARAGRAPH);
+
+        // Move to the next character and wait for an event.
+        AccessibilityEvent firstExpected = getInteractionBridge()
+                .executeCommandAndWaitForAccessibilityEvent(new Runnable() {
+            @Override
+            public void run() {
+                getInteractionBridge().performAction(text,
+                        AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY, arguments);
+            }
+        }, new AccessibilityEventFilter() {
+            @Override
+            public boolean accept(AccessibilityEvent event) {
+                return
+                (event.getEventType() ==
+                    AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
+                        && event.getAction() ==
+                            AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY
+                        && event.getPackageName().equals(getActivity().getPackageName())
+                        && event.getClassName().equals(EditText.class.getName())
+                        && event.getText().size() > 0
+                        && event.getText().get(0).toString().equals(getString(
+                                R.string.android_wiki_paragraphs))
+                        && event.getFromIndex() == 2
+                        && event.getToIndex() == 106
+                        && event.getMovementGranularity()
+                            == AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PARAGRAPH);
+            }
+        }, TIMEOUT_ASYNC_PROCESSING);
+
+        // Make sure we got the expected event.
+        assertNotNull(firstExpected);
+
+        // Verify the selection position.
+        assertEquals(2, Selection.getSelectionStart(textView.getText()));
+        assertEquals(2, Selection.getSelectionEnd(textView.getText()));
+
+        // Move to the next character and wait for an event.
+        AccessibilityEvent secondExpected = getInteractionBridge()
+                .executeCommandAndWaitForAccessibilityEvent(new Runnable() {
+            @Override
+            public void run() {
+                getInteractionBridge().performAction(text,
+                        AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY, arguments);
+            }
+        }, new AccessibilityEventFilter() {
+            @Override
+            public boolean accept(AccessibilityEvent event) {
+                return
+                (event.getEventType() ==
+                    AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
+                        && event.getAction() ==
+                            AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY
+                        && event.getPackageName().equals(getActivity().getPackageName())
+                        && event.getClassName().equals(EditText.class.getName())
+                        && event.getText().size() > 0
+                        && event.getText().get(0).toString().equals(getString(
+                                R.string.android_wiki_paragraphs))
+                        && event.getFromIndex() == 106
+                        && event.getToIndex() == 268
+                        && event.getMovementGranularity() ==
+                            AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PARAGRAPH);
+            }
+        }, TIMEOUT_ASYNC_PROCESSING);
+
+        // Make sure we got the expected event.
+        assertNotNull(secondExpected);
+
+        // Verify the selection position.
+        assertEquals(106, Selection.getSelectionStart(textView.getText()));
+        assertEquals(106, Selection.getSelectionEnd(textView.getText()));
+
+        // Move to the next character and wait for an event.
+        AccessibilityEvent thirdExpected = getInteractionBridge()
+                .executeCommandAndWaitForAccessibilityEvent(new Runnable() {
+            @Override
+            public void run() {
+                getInteractionBridge().performAction(text,
+                        AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY, arguments);
+            }
+        }, new AccessibilityEventFilter() {
+            @Override
+            public boolean accept(AccessibilityEvent event) {
+                return
+                (event.getEventType() ==
+                    AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
+                        && event.getAction() ==
+                            AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY
+                        && event.getPackageName().equals(getActivity().getPackageName())
+                        && event.getClassName().equals(EditText.class.getName())
+                        && event.getText().size() > 0
+                        && event.getText().get(0).toString().equals(getString(
+                                R.string.android_wiki_paragraphs))
+                        && event.getFromIndex() == 268
+                        && event.getToIndex() == 584
+                        && event.getMovementGranularity() ==
+                            AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PARAGRAPH);
+            }
+        }, TIMEOUT_ASYNC_PROCESSING);
+
+        // Make sure we got the expected event.
+        assertNotNull(thirdExpected);
+
+        // Verify the selection position.
+        assertEquals(268, Selection.getSelectionStart(textView.getText()));
+        assertEquals(268, Selection.getSelectionEnd(textView.getText()));
+
+        // Make sure there is no next.
+        assertFalse(getInteractionBridge().performAction(text,
+                AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY, arguments));
+
+        // Verify the selection position.
+        assertEquals(-1, Selection.getSelectionStart(textView.getText()));
+        assertEquals(-1, Selection.getSelectionEnd(textView.getText()));
+
+        // Move to the next character and wait for an event.
+        AccessibilityEvent fourthExpected = getInteractionBridge()
+                .executeCommandAndWaitForAccessibilityEvent(new Runnable() {
+            @Override
+            public void run() {
+                getInteractionBridge().performAction(text,
+                        AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY, arguments);
+            }
+        }, new AccessibilityEventFilter() {
+            @Override
+            public boolean accept(AccessibilityEvent event) {
+                return
+                (event.getEventType() ==
+                    AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
+                        && event.getAction() ==
+                            AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY
+                        && event.getPackageName().equals(getActivity().getPackageName())
+                        && event.getClassName().equals(EditText.class.getName())
+                        && event.getText().size() > 0
+                        && event.getText().get(0).toString().equals(getString(
+                                R.string.android_wiki_paragraphs))
+                        && event.getFromIndex() == 268
+                        && event.getToIndex() == 584
+                        && event.getMovementGranularity() ==
+                            AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PARAGRAPH);
+            }
+        }, TIMEOUT_ASYNC_PROCESSING);
+
+        // Make sure we got the expected event.
+        assertNotNull(fourthExpected);
+
+        // Verify the selection position.
+        assertEquals(584, Selection.getSelectionStart(textView.getText()));
+        assertEquals(584, Selection.getSelectionEnd(textView.getText()));
+
+        // Move to the next character and wait for an event.
+        AccessibilityEvent fifthExpected = getInteractionBridge()
+                .executeCommandAndWaitForAccessibilityEvent(new Runnable() {
+            @Override
+            public void run() {
+                getInteractionBridge().performAction(text,
+                        AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY, arguments);
+            }
+        }, new AccessibilityEventFilter() {
+            @Override
+            public boolean accept(AccessibilityEvent event) {
+                return
+                (event.getEventType() ==
+                    AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
+                        && event.getAction() ==
+                            AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY
+                        && event.getPackageName().equals(getActivity().getPackageName())
+                        && event.getClassName().equals(EditText.class.getName())
+                        && event.getText().size() > 0
+                        && event.getText().get(0).toString().equals(getString(
+                                R.string.android_wiki_paragraphs))
+                        && event.getFromIndex() == 106
+                        && event.getToIndex() == 268
+                        && event.getMovementGranularity() ==
+                            AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PARAGRAPH);
+            }
+        }, TIMEOUT_ASYNC_PROCESSING);
+
+        // Make sure we got the expected event.
+        assertNotNull(fifthExpected);
+
+        // Verify the selection position.
+        assertEquals(268, Selection.getSelectionStart(textView.getText()));
+        assertEquals(268, Selection.getSelectionEnd(textView.getText()));
+
+        // Move to the next character and wait for an event.
+        AccessibilityEvent sixthExpected = getInteractionBridge()
+                .executeCommandAndWaitForAccessibilityEvent(new Runnable() {
+            @Override
+            public void run() {
+                getInteractionBridge().performAction(text,
+                        AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY, arguments);
+            }
+        }, new AccessibilityEventFilter() {
+            @Override
+            public boolean accept(AccessibilityEvent event) {
+                return
+                (event.getEventType() ==
+                    AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
+                        && event.getAction() ==
+                            AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY
+                        && event.getPackageName().equals(getActivity().getPackageName())
+                        && event.getClassName().equals(EditText.class.getName())
+                        && event.getText().size() > 0
+                        && event.getText().get(0).toString().equals(getString(
+                                R.string.android_wiki_paragraphs))
+                        && event.getFromIndex() == 2
+                        && event.getToIndex() == 106
+                        && event.getMovementGranularity()
+                                == AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PARAGRAPH);
+            }
+        }, TIMEOUT_ASYNC_PROCESSING);
+
+        // Make sure we got the expected event.
+        assertNotNull(sixthExpected);
+
+        // Verify the selection position.
+        assertEquals(106, Selection.getSelectionStart(textView.getText()));
+        assertEquals(106, Selection.getSelectionEnd(textView.getText()));
+
+        // Make sure there is no previous.
+        assertFalse(getInteractionBridge().performAction(text,
+                AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY, arguments));
+
+        // Verify the selection position.
+        assertEquals(-1, Selection.getSelectionStart(textView.getText()));
+        assertEquals(-1, Selection.getSelectionEnd(textView.getText()));
+    }
+}
diff --git a/tests/tests/content/src/android/content/cts/ContentProviderTest.java b/tests/tests/content/src/android/content/cts/ContentProviderTest.java
index 39b7185..2baa904 100644
--- a/tests/tests/content/src/android/content/cts/ContentProviderTest.java
+++ b/tests/tests/content/src/android/content/cts/ContentProviderTest.java
@@ -23,7 +23,6 @@
 import android.content.ContentResolver;
 import android.content.ContentValues;
 import android.content.Context;
-import android.content.ICancellationSignal;
 import android.content.IContentProvider;
 import android.content.ContentProviderResult;
 import android.content.ContentProviderOperation;
@@ -35,6 +34,7 @@
 import android.net.Uri;
 import android.os.Bundle;
 import android.os.IBinder;
+import android.os.ICancellationSignal;
 import android.os.ParcelFileDescriptor;
 import android.os.RemoteException;
 import android.test.AndroidTestCase;
diff --git a/tests/tests/content/src/android/content/cts/ContentResolverTest.java b/tests/tests/content/src/android/content/cts/ContentResolverTest.java
index 7042140..3276c8e 100644
--- a/tests/tests/content/src/android/content/cts/ContentResolverTest.java
+++ b/tests/tests/content/src/android/content/cts/ContentResolverTest.java
@@ -20,11 +20,9 @@
 
 
 import android.accounts.Account;
-import android.content.CancellationSignal;
 import android.content.ContentResolver;
 import android.content.ContentValues;
 import android.content.Context;
-import android.content.OperationCanceledException;
 import android.content.res.AssetFileDescriptor;
 import android.cts.util.PollingCheck;
 import android.database.ContentObserver;
@@ -32,6 +30,8 @@
 import android.database.sqlite.SQLiteQueryBuilder;
 import android.net.Uri;
 import android.os.Bundle;
+import android.os.CancellationSignal;
+import android.os.OperationCanceledException;
 import android.os.ParcelFileDescriptor;
 import android.test.AndroidTestCase;
 
diff --git a/tests/tests/database/src/android/database/sqlite/cts/SQLiteQueryBuilderTest.java b/tests/tests/database/src/android/database/sqlite/cts/SQLiteQueryBuilderTest.java
index 8eb089f..09903df 100644
--- a/tests/tests/database/src/android/database/sqlite/cts/SQLiteQueryBuilderTest.java
+++ b/tests/tests/database/src/android/database/sqlite/cts/SQLiteQueryBuilderTest.java
@@ -17,15 +17,15 @@
 package android.database.sqlite.cts;
 
 
-import android.content.CancellationSignal;
 import android.content.Context;
-import android.content.OperationCanceledException;
 import android.database.Cursor;
 import android.database.sqlite.SQLiteCursor;
 import android.database.sqlite.SQLiteCursorDriver;
 import android.database.sqlite.SQLiteDatabase;
 import android.database.sqlite.SQLiteQuery;
 import android.database.sqlite.SQLiteQueryBuilder;
+import android.os.CancellationSignal;
+import android.os.OperationCanceledException;
 import android.test.AndroidTestCase;
 
 import java.util.HashMap;
diff --git a/tests/tests/graphics2/src/android/graphics2/cts/TextureViewCameraActivity.java b/tests/tests/graphics2/src/android/graphics2/cts/TextureViewCameraActivity.java
index d947565..88d529c 100644
--- a/tests/tests/graphics2/src/android/graphics2/cts/TextureViewCameraActivity.java
+++ b/tests/tests/graphics2/src/android/graphics2/cts/TextureViewCameraActivity.java
@@ -17,6 +17,7 @@
 package android.graphics2.cts;
 
 import android.app.Activity;
+import android.content.pm.PackageManager;
 import android.graphics.Bitmap;
 import android.graphics.Canvas;
 import android.graphics.Matrix;
@@ -54,7 +55,19 @@
         Assert.assertTrue(mTextureView.isOpaque());
         mWidth = width;
         mHeight = height;
-        mCamera = Camera.open();
+        PackageManager packageManager = getPackageManager();
+        boolean hasRearCamera = packageManager.hasSystemFeature(PackageManager.FEATURE_CAMERA);
+        boolean hasFrontCamera =
+                packageManager.hasSystemFeature(PackageManager.FEATURE_CAMERA_FRONT);
+        if (hasRearCamera) {
+            mCamera = Camera.open();
+        } else if (hasFrontCamera) {
+            mCamera = Camera.open(0);
+        } else {
+            // no camera, and no frame update, so just complete here.
+            mLatch.countDown();
+            return;
+        }
 
         try {
             mCamera.setPreviewTexture(surface);
diff --git a/tests/tests/media/src/android/media/cts/DecoderTest.java b/tests/tests/media/src/android/media/cts/DecoderTest.java
index 8c7158e..a63eaac 100644
--- a/tests/tests/media/src/android/media/cts/DecoderTest.java
+++ b/tests/tests/media/src/android/media/cts/DecoderTest.java
@@ -114,34 +114,6 @@
         codecInputBuffers = codec.getInputBuffers();
         codecOutputBuffers = codec.getOutputBuffers();
 
-        // set up codec specific data, if any
-        int n = 0;
-        while (format.containsKey("csd-" + n)) {
-            ByteBuffer srcBuf = format.getByteBuffer("csd-" + n);
-
-            // Specifying a timeout of -1 indicates an infinite timeout, i.e.
-            // we're going to block until we get a buffer.
-            int dstBufIndex = codec.dequeueInputBuffer(-1 /* timeoutUs */);
-            ByteBuffer dstBuf = codecInputBuffers[dstBufIndex];
-
-            int srcBufLen = srcBuf.limit();
-
-            // The clear() calls below do not "clear" anything,
-            // they merely reset read/write offsets to 0.
-            srcBuf.clear();
-            dstBuf.clear();
-            dstBuf.put(srcBuf);
-
-            codec.queueInputBuffer(
-                    dstBufIndex,
-                    0 /* offset */,
-                    srcBufLen,
-                    0 /* sampleTimeUs */,
-                    MediaCodec.BUFFER_FLAG_CODEC_CONFIG);
-
-            ++n;
-        }
-
         extractor.selectTrack(0);
 
         // start decoding
@@ -190,7 +162,6 @@
             if (res >= 0) {
                 int outputBufIndex = res;
                 ByteBuffer buf = codecOutputBuffers[outputBufIndex];
-                buf.order(null);
 
                 // check the waveform matches within the specified max error
                 for (int i = 0; i < info.size; i += 2) {
diff --git a/tests/tests/permission/src/android/permission/cts/FileSystemPermissionTest.java b/tests/tests/permission/src/android/permission/cts/FileSystemPermissionTest.java
index f7f2000..3485574 100644
--- a/tests/tests/permission/src/android/permission/cts/FileSystemPermissionTest.java
+++ b/tests/tests/permission/src/android/permission/cts/FileSystemPermissionTest.java
@@ -252,6 +252,7 @@
                     "/data/data/com.lge.ers/android",
                     "/data/data/com.lge.ers/arm9",
                     "/data/data/com.lge.ers/kernel",
+                    "/data/data/com.lge.wmc",
                     "/data/data/recovery",
                     "/data/data/recovery/HTCFOTA",
                     "/data/data/recovery/OMADM",
@@ -299,6 +300,7 @@
                     "/data/misc/wimax/sockets",
                     "/data/misc/wminput",
                     "/data/misc/wpa_supplicant",
+                    "/data/nv",
                     "/data/nvcam",
                     "/data/panicreports",
                     "/data/property",
diff --git a/tests/tests/security/src/android/security/cts/VoldExploitTest.java b/tests/tests/security/src/android/security/cts/VoldExploitTest.java
index 7247a79..d428c60 100644
--- a/tests/tests/security/src/android/security/cts/VoldExploitTest.java
+++ b/tests/tests/security/src/android/security/cts/VoldExploitTest.java
@@ -19,9 +19,6 @@
 import android.content.Context;
 import android.content.pm.PackageManager;
 import android.net.cts.NetlinkSocket;
-import android.os.IBinder;
-import android.os.Parcel;
-import android.os.RemoteException;
 import android.os.storage.StorageManager;
 import android.test.AndroidTestCase;
 
@@ -30,7 +27,6 @@
 import java.io.FileReader;
 import java.io.IOException;
 import java.io.UnsupportedEncodingException;
-import java.lang.reflect.InvocationTargetException;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.HashSet;
@@ -88,79 +84,6 @@
     }
 
     /**
-     * Validate that this device isn't vulnerable to the "ZergRush"
-     * vold vulnerability (CVE-2011-3874).
-     *
-     * https://github.com/revolutionary/zergRush/blob/master/zergRush.c
-     *
-     * Note: If the ZergRush vulnerability is present, the call to
-     * {@link IBinder#transact(int, android.os.Parcel, android.os.Parcel, int)}}
-     * below hangs until CTS kills the testsuite (10 minutes). A timeout,
-     * while not desirable, is the typical failure for this test.
-     *
-     * This test accomplishes the same thing as {@link #testZergRushCrash()}
-     */
-    public void testZergRushUsingRelection() throws Exception {
-        // This test assumes we have the MOUNT_UNMOUNT_FILESYSTEMS permission
-        // Check it first so we know we're reaching the vulnerable code.
-        assertEquals(PackageManager.PERMISSION_GRANTED,
-                getContext().checkCallingOrSelfPermission(
-                        android.Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS));
-
-        int pid = findVold();
-
-        try {
-            Object iBinderObj = Class.forName("android.os.ServiceManager")
-                    .getDeclaredMethod("getService", String.class)
-                    .invoke(null, "mount");
-            if (!(iBinderObj instanceof IBinder)) {
-                // unexpected return value, return.  Assume not exploitable.
-                return;
-            }
-
-            String[] names = new String[] {
-                    "IMountService",                   // Android 2.3
-                    "android.os.storage.IMountService" // Android 2.2
-            };
-
-            for (String name : names) {
-                IBinder iBinder = (IBinder) iBinderObj;
-                Parcel data = Parcel.obtain();
-                data.writeInterfaceToken(name);
-                data.writeString("AAAA AAAA AAAA AAAA "
-                        + "AAAA AAAA AAAA AAAA "
-                        + "AAAA AAAA AAAA AAAA "
-                        + "AAAA AAAA AAAA AAAA"
-                        + "AAAA AAAA AAAA AAAA"
-                        + "AAAA AAAA AAAA AAAA"
-                        + "AAAA AAAA AAAA AAAA"
-                        + "AAAA AAAA AAAA AAAA");
-
-                // If vold crashes, this next line will hang forever.
-                iBinder.transact(6, data, null, 0);
-            }
-        } catch (ClassNotFoundException e) {
-            // class doesn't exist. Assume not exploitable.
-        } catch (NoSuchMethodException e) {
-            // no such method exists. Assume not exploitable.
-        } catch (InvocationTargetException e) {
-            // can't invoke.  Assume not exploitable.
-        } catch (IllegalAccessException e) {
-            // can't access.  Assume not exploitable.
-        } catch (RemoteException e) {
-            // remote failure. Assume not exploitable.
-        }
-
-        Thread.sleep(2000);  // give vold some time to crash
-
-        // Check to see if vold is still alive.
-        assertTrue(
-                "PID=" + pid + " crashed due to a malformed mount message."
-                        + " Detected unpatched ZergRush vulnerability (CVE-2011-3874).",
-                new File("/proc/" + pid + "/cmdline").exists());
-    }
-
-    /**
      * Try to crash the vold program using CVE-2011-1823.
      *
      * This test attempts to send an invalid netlink messages to
diff --git a/tests/tests/text/src/android/text/cts/SpannableStringBuilderSpanTest.java b/tests/tests/text/src/android/text/cts/SpannableStringBuilderSpanTest.java
index db9dbdd..352767c 100644
--- a/tests/tests/text/src/android/text/cts/SpannableStringBuilderSpanTest.java
+++ b/tests/tests/text/src/android/text/cts/SpannableStringBuilderSpanTest.java
@@ -96,9 +96,9 @@
         String subReplacement = replacement.substring(replacementStart, replacementEnd);
         String expected = original.substring(0, replaceStart) +
                 subReplacement + original.substring(replaceEnd, original.length());
-        if (DEBUG) System.out.println("Replace \"" + original + "\" [" +
+        if (DEBUG) System.out.println("#" + testCounter + ", replace \"" + original + "\" [" +
                 replaceStart + " " + replaceEnd + "] by \"" + subReplacement + "\" -> \"" +
-                expected + "\", flag=" + flag + ", test #" + testCounter);
+                expected + "\", flag=" + flag);
 
         SpannableStringBuilder originalSpannable = new SpannableStringBuilder(original);
         Spannable replacementSpannable = new SpannableStringBuilder(replacement);
@@ -111,7 +111,8 @@
 
         assertEquals(expected, originalSpannable.toString());
 
-        checkSpanPositions(originalSpannable, replaceStart, replaceEnd, subReplacement.length(), flag);
+        checkSpanPositions(originalSpannable, replaceStart, replaceEnd, subReplacement.length(),
+                flag);
         checkReplacementSpanPositions(originalSpannable, replaceStart, replacementSpannable,
                 replacementStart, replacementEnd, flag);
     }
@@ -142,7 +143,9 @@
                 // This is the exception to the following generic code where we need to consider
                 // both the start and end styles.
                 if (startStyle == SpanSet.INSIDE && endStyle == SpanSet.INSIDE &&
-                        flag == Spanned.SPAN_EXCLUSIVE_EXCLUSIVE) {
+                        flag == Spanned.SPAN_EXCLUSIVE_EXCLUSIVE &&
+                        (replacementLength == 0 || originalStart > replaceStart ||
+                        originalEnd < replaceEnd)) {
                     // 0-length spans should have been removed
                     assertEquals(-1, start);
                     assertEquals(-1, end);
diff --git a/tests/tests/view/src/android/view/animation/cts/AnimationTest.java b/tests/tests/view/src/android/view/animation/cts/AnimationTest.java
index a76951c..2d88dc4 100644
--- a/tests/tests/view/src/android/view/animation/cts/AnimationTest.java
+++ b/tests/tests/view/src/android/view/animation/cts/AnimationTest.java
@@ -388,10 +388,7 @@
         Animation anim = AnimationUtils.loadAnimation(mActivity, R.anim.accelerate_alpha);
         assertEquals(Animation.START_ON_FIRST_FRAME, anim.getStartTime());
         assertFalse(anim.hasStarted());
-        currentTime = AnimationUtils.currentAnimationTimeMillis();
         AnimationTestUtils.assertRunAnimation(getInstrumentation(), animWindow, anim);
-        // add delta 100 in case the system is sluggish when run animation
-        assertEquals(currentTime, anim.getStartTime(), 100);
     }
 
     public void testGetTransformation() {
diff --git a/tests/tests/view/src/android/view/cts/ViewGroupTest.java b/tests/tests/view/src/android/view/cts/ViewGroupTest.java
index 34b7742..e975a27 100644
--- a/tests/tests/view/src/android/view/cts/ViewGroupTest.java
+++ b/tests/tests/view/src/android/view/cts/ViewGroupTest.java
@@ -1496,8 +1496,6 @@
         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);
 
@@ -1505,83 +1503,6 @@
         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(start, vg.getPaddingLeft());
-        assertEquals(end, 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 453e200..d92fd9b 100644
--- a/tests/tests/view/src/android/view/cts/ViewGroup_MarginLayoutParamsTest.java
+++ b/tests/tests/view/src/android/view/cts/ViewGroup_MarginLayoutParamsTest.java
@@ -83,90 +83,5 @@
 
         assertEquals(Integer.MIN_VALUE, mMarginLayoutParams.startMargin);
         assertEquals(Integer.MIN_VALUE, mMarginLayoutParams.endMargin);
-
-        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.startMargin);
-        assertEquals(30, mMarginLayoutParams.topMargin);
-        assertEquals(120, mMarginLayoutParams.endMargin);
-        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.startMargin);
-        assertEquals(Integer.MIN_VALUE, mMarginLayoutParams.endMargin);
-
-        assertEquals(false, mMarginLayoutParams.isMarginRelative());
-
-        // LTR / relative margin case
-        mMarginLayoutParams.setMarginsRelative(20, 30, 120, 140);
-        vg.setLayoutParams(mMarginLayoutParams);
-        vg.requestLayout();
-
-        assertEquals(20, mMarginLayoutParams.startMargin);
-        assertEquals(30, mMarginLayoutParams.topMargin);
-        assertEquals(120, mMarginLayoutParams.endMargin);
-        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.startMargin);
-        assertEquals(Integer.MIN_VALUE, mMarginLayoutParams.endMargin);
-
-        assertEquals(false, mMarginLayoutParams.isMarginRelative());
-
-        // RTL / relative margin case
-        mMarginLayoutParams.setMarginsRelative(20, 30, 120, 140);
-        vg.setLayoutParams(mMarginLayoutParams);
-        vg.requestLayout();
-
-        assertEquals(20, mMarginLayoutParams.startMargin);
-        assertEquals(30, mMarginLayoutParams.topMargin);
-        assertEquals(120, mMarginLayoutParams.endMargin);
-        assertEquals(140, mMarginLayoutParams.bottomMargin);
-
-        assertEquals(120, mMarginLayoutParams.leftMargin);
-        assertEquals(20, mMarginLayoutParams.rightMargin);
-
-        assertEquals(true, mMarginLayoutParams.isMarginRelative());
     }
 }
diff --git a/tests/tests/webkit/src/android/webkit/cts/WebHistoryItemTest.java b/tests/tests/webkit/src/android/webkit/cts/WebHistoryItemTest.java
index 9fc308d..92f4cac 100644
--- a/tests/tests/webkit/src/android/webkit/cts/WebHistoryItemTest.java
+++ b/tests/tests/webkit/src/android/webkit/cts/WebHistoryItemTest.java
@@ -56,7 +56,7 @@
         assertNotNull(item);
         int firstId = item.getId();
         assertEquals(url, item.getUrl());
-        assertNull(item.getOriginalUrl());
+        assertEquals(url, item.getOriginalUrl());
         assertEquals(TestHtmlConstants.HELLO_WORLD_TITLE, item.getTitle());
         Bitmap icon = mOnUiThread.getFavicon();
         assertEquals(icon, item.getFavicon());