Merge "Moving touch event into dialog bounds." into klp-dev
diff --git a/hostsidetests/appsecurity/src/com/android/cts/appsecurity/AppSecurityTests.java b/hostsidetests/appsecurity/src/com/android/cts/appsecurity/AppSecurityTests.java
index 5298af2..3779db9 100644
--- a/hostsidetests/appsecurity/src/com/android/cts/appsecurity/AppSecurityTests.java
+++ b/hostsidetests/appsecurity/src/com/android/cts/appsecurity/AppSecurityTests.java
@@ -207,47 +207,6 @@
     }
 
     /**
-     * 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",
-                    getDevice().getMountPoint(IDevice.MNT_EXTERNAL_STORAGE) + "/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);
-        }
-    }
-
-    /**
      * Verify that legacy filesystem paths continue working, and that they all
      * point to same location.
      */
@@ -541,11 +500,4 @@
         getDevice().executeShellCommand(cmd, parser);
         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/src/com/android/cts/externalstorageapp/ExternalStorageTest.java b/hostsidetests/appsecurity/test-apps/ExternalStorageApp/src/com/android/cts/externalstorageapp/ExternalStorageTest.java
index d42353d..a3fcf4a 100644
--- 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
@@ -45,15 +45,6 @@
         }
     }
 
-    public void testReadExternalStorage() throws Exception {
-        assertExternalStorageMounted();
-        try {
-            readExternalStorage();
-        } catch (IOException e) {
-            fail("unable to read external file");
-        }
-    }
-
     public void testFailReadExternalStorage() throws Exception {
         assertExternalStorageMounted();
         try {
diff --git a/tests/acceleration/Android.mk b/tests/acceleration/Android.mk
index bb6b89f..ef96a24 100644
--- a/tests/acceleration/Android.mk
+++ b/tests/acceleration/Android.mk
@@ -22,6 +22,8 @@
 
 LOCAL_DEX_PREOPT := false
 
+LOCAL_PROGUARD_ENABLED := disabled
+
 LOCAL_JAVA_LIBRARIES := android.test.runner
 
 LOCAL_SRC_FILES := $(call all-java-files-under, src)
diff --git a/tests/src/android/webkit/cts/WebViewOnUiThread.java b/tests/src/android/webkit/cts/WebViewOnUiThread.java
index babb1fc..8da830c 100644
--- a/tests/src/android/webkit/cts/WebViewOnUiThread.java
+++ b/tests/src/android/webkit/cts/WebViewOnUiThread.java
@@ -43,7 +43,6 @@
 import java.util.concurrent.Callable;
 import java.util.Map;
 
-
 /**
  * Many tests need to run WebView code in the UI thread. This class
  * wraps a WebView so that calls are ensured to arrive on the UI thread.
@@ -239,11 +238,20 @@
         });
     }
 
-    public void zoomIn() {
-        runOnUiThread(new Runnable() {
+    public boolean zoomIn() {
+        return getValue(new ValueGetter<Boolean>() {
             @Override
-            public void run() {
-                mWebView.zoomIn();
+            public Boolean capture() {
+                return mWebView.zoomIn();
+            }
+        });
+    }
+
+    public boolean zoomOut() {
+        return getValue(new ValueGetter<Boolean>() {
+            @Override
+            public Boolean capture() {
+                return mWebView.zoomOut();
             }
         });
     }
diff --git a/tests/tests/app/src/android/app/cts/AlertDialog_BuilderTest.java b/tests/tests/app/src/android/app/cts/AlertDialog_BuilderTest.java
index 74f85bb..5f826eb 100644
--- a/tests/tests/app/src/android/app/cts/AlertDialog_BuilderTest.java
+++ b/tests/tests/app/src/android/app/cts/AlertDialog_BuilderTest.java
@@ -249,7 +249,7 @@
         assertTrue(mResult);
     }
 
-    private void setCancelable(final boolean cancelable) throws Throwable {
+    private void testCancelable(final boolean cancelable) throws Throwable {
         runTestOnUiThread(new Runnable() {
             public void run() {
                 mBuilder = new AlertDialog.Builder(mContext);
@@ -258,18 +258,37 @@
             }
         });
         mInstrumentation.waitForIdleSync();
+        new PollingCheck() {
+            @Override
+            protected boolean check() {
+                return mDialog.isShowing();
+            }
+        }.run();
+        mInstrumentation.sendKeyDownUpSync(KeyEvent.KEYCODE_BACK);
+        mInstrumentation.waitForIdleSync();
+        new PollingCheck() {
+            @Override
+            protected boolean check() {
+                boolean showing = mDialog.isShowing();
+                if (cancelable) {
+                    // if the dialog is cancelable, then pressing back
+                    // should cancel it. Thus it should not be showing
+                    return !showing;
+                } else {
+                    // if the dialog is not cancelable, pressing back
+                    // should so nothing and it should still be showing
+                    return showing;
+                }
+            }
+        }.run();
     }
 
     public void testSetCancelable() throws Throwable {
-        setCancelable(true);
-        mInstrumentation.sendKeyDownUpSync(KeyEvent.KEYCODE_BACK);
-        assertFalse(mDialog.isShowing());
+        testCancelable(true);
     }
 
     public void testDisableCancelable() throws Throwable {
-        setCancelable(false);
-        mInstrumentation.sendKeyDownUpSync(KeyEvent.KEYCODE_BACK);
-        assertTrue(mDialog.isShowing());
+        testCancelable(false);
     }
 
     public void testSetOnCancelListener() throws Throwable {
diff --git a/tests/tests/content/AndroidManifest.xml b/tests/tests/content/AndroidManifest.xml
index 0d702f4..5af05eb 100644
--- a/tests/tests/content/AndroidManifest.xml
+++ b/tests/tests/content/AndroidManifest.xml
@@ -18,9 +18,25 @@
     package="com.android.cts.content">
 
     <uses-permission android:name="android.permission.DISABLE_KEYGUARD" />
-    <application>
-        <uses-library android:name="android.test.runner" />
 
+    <application>
+        <activity android:name="android.app.cts.MockActivity">
+            <intent-filter>
+                <action android:name="com.android.cts.content.action.TEST_ACTION" />
+                <category android:name="android.intent.category.DEFAULT" />
+                <category android:name="com.android.cts.content.category.TEST_CATEGORY" />
+            </intent-filter>
+        </activity>
+
+        <activity-alias android:name="android.app.cts.MockActivity2"
+                android:targetActivity="android.app.cts.MockActivity">
+            <intent-filter>
+                <action android:name="com.android.cts.content.action.TEST_ACTION" />
+                <category android:name="android.intent.category.DEFAULT" />
+            </intent-filter>
+        </activity-alias>
+
+        <uses-library android:name="android.test.runner" />
     </application>
 
     <instrumentation android:name="android.test.InstrumentationCtsTestRunner"
diff --git a/tests/tests/content/src/android/content/cts/IntentTest.java b/tests/tests/content/src/android/content/cts/IntentTest.java
index a88fdf2..562c915 100644
--- a/tests/tests/content/src/android/content/cts/IntentTest.java
+++ b/tests/tests/content/src/android/content/cts/IntentTest.java
@@ -17,6 +17,7 @@
 package android.content.cts;
 
 import com.android.internal.app.ResolverActivity;
+import com.android.internal.util.Objects;
 import com.android.internal.util.XmlUtils;
 
 
@@ -41,6 +42,7 @@
 import android.provider.Contacts.People;
 import android.test.AndroidTestCase;
 import android.util.AttributeSet;
+import android.util.Log;
 import android.util.Xml;
 
 import java.io.IOException;
@@ -57,6 +59,7 @@
     private static final Uri ANOTHER_TEST_URI = People.CONTENT_FILTER_URI;
     private static final String TEST_EXTRA_NAME = "testExtraName";
     private Context mContext;
+    private PackageManager mPm;
     private ComponentName mComponentName;
     private ComponentName mAnotherComponentName;
     private static final String TEST_TYPE = "testType";
@@ -71,6 +74,7 @@
         super.setUp();
         mIntent = new Intent();
         mContext = getContext();
+        mPm = mContext.getPackageManager();
         mComponentName = new ComponentName(mContext, MockActivity.class);
         mAnotherComponentName = new ComponentName(mContext, "tmp");
     }
@@ -713,26 +717,51 @@
         assertEquals(expected, mIntent.getParcelableArrayExtra(TEST_EXTRA_NAME));
     }
 
-    public void testResolveActivity() {
-        final PackageManager pm = mContext.getPackageManager();
+    public void testResolveActivityEmpty() {
+        final Intent emptyIntent = new Intent();
 
-        ComponentName target = mIntent.resolveActivity(pm);
+        // Empty intent shouldn't resolve to anything
+        final ComponentName target = emptyIntent.resolveActivity(mPm);
         assertNull(target);
+    }
 
-        mIntent.setComponent(mComponentName);
-        target = mIntent.resolveActivity(pm);
-        assertEquals(mComponentName, target);
+    public void testResolveActivitySingleMatch() {
+        final Intent intent = new Intent("com.android.cts.content.action.TEST_ACTION");
+        intent.addCategory("com.android.cts.content.category.TEST_CATEGORY");
 
-        mIntent.setComponent(null);
-        mIntent.setData(TEST_URI);
-        target = mIntent.resolveActivity(pm);
-        assertEquals(ResolverActivity.class.getName(), target.getClassName());
-        assertEquals("android", target.getPackageName());
+        // Should only have one activity responding to narrow category
+        final ComponentName target = intent.resolveActivity(mPm);
+        assertEquals("com.android.cts.content", target.getPackageName());
+        assertEquals("android.app.cts.MockActivity", target.getClassName());
+    }
 
-        mIntent.setComponent(null);
-        mIntent.setAction(TEST_TYPE);
-        target = mIntent.resolveActivity(pm);
-        assertNull(target);
+    public void testResolveActivityShortcutMatch() {
+        final Intent intent = new Intent("com.android.cts.content.action.TEST_ACTION");
+        intent.setComponent(
+                new ComponentName("com.android.cts.content", "android.app.cts.MockActivity2"));
+
+        // Multiple activities match, but we asked for explicit component
+        final ComponentName target = intent.resolveActivity(mPm);
+        assertEquals("com.android.cts.content", target.getPackageName());
+        assertEquals("android.app.cts.MockActivity2", target.getClassName());
+    }
+
+    public void testResolveActivityMultipleMatch() {
+        final Intent intent = new Intent("com.android.cts.content.action.TEST_ACTION");
+
+        // Should have multiple activities, resulting in resolver dialog
+        final ComponentName target = intent.resolveActivity(mPm);
+        final String pkgName = target.getPackageName();
+        assertFalse("com.android.cts.content".equals(pkgName));
+
+        // Whoever they are must be able to set preferred activities
+        if (!"android".equals(pkgName)) {
+            if (mPm.checkPermission(android.Manifest.permission.SET_PREFERRED_APPLICATIONS, pkgName)
+                    != PackageManager.PERMISSION_GRANTED) {
+                fail("Resolved target " + target
+                        + " doesn't have SET_PREFERRED_APPLICATIONS permission");
+            }
+        }
     }
 
     public void testGetCharExtra() {
diff --git a/tests/tests/content/src/android/content/res/cts/AssetFileDescriptorTest.java b/tests/tests/content/src/android/content/res/cts/AssetFileDescriptorTest.java
index 7891aec..e4a9500 100644
--- a/tests/tests/content/src/android/content/res/cts/AssetFileDescriptorTest.java
+++ b/tests/tests/content/src/android/content/res/cts/AssetFileDescriptorTest.java
@@ -83,8 +83,8 @@
         mOutputStream = null;
         try {
             mOutputStream = mAssetFileDes.createOutputStream();
-            fail("Should throw IllegalArgumentException");
-        } catch (IllegalArgumentException e) {
+            fail("Should throw IOException");
+        } catch (IOException e) {
             // expect
         }
         try {
@@ -120,8 +120,8 @@
         }
         try {
             mOutputStream = mAssetFileDes.createOutputStream();
-            fail("Should throw IllegalArgumentException");
-        } catch (IllegalArgumentException e) {
+            fail("Should throw IOException");
+        } catch (IOException e) {
             // expect
         }
         mAssetFileDes.close();
diff --git a/tests/tests/media/src/android/media/cts/DecoderTest.java b/tests/tests/media/src/android/media/cts/DecoderTest.java
index d251064..65f16b1 100644
--- a/tests/tests/media/src/android/media/cts/DecoderTest.java
+++ b/tests/tests/media/src/android/media/cts/DecoderTest.java
@@ -38,6 +38,10 @@
 public class DecoderTest extends MediaPlayerTestBase {
     private static final String TAG = "DecoderTest";
 
+    private static final int RESET_MODE_NONE = 0;
+    private static final int RESET_MODE_RECONFIGURE = 1;
+    private static final int RESET_MODE_FLUSH = 2;
+
     private Resources mResources;
     short[] mMasterBuffer;
 
@@ -101,7 +105,7 @@
     }
 
     private void monoTest(int res) throws Exception {
-        short [] mono = decodeToMemory(res, false);
+        short [] mono = decodeToMemory(res, RESET_MODE_NONE);
         if (mono.length == 44100) {
             // expected
         } else if (mono.length == 88200) {
@@ -115,8 +119,13 @@
         }
 
         // we should get the same data when reconfiguring the codec
-        short [] mono2 = decodeToMemory(res, true);
+        short [] mono2 = decodeToMemory(res, RESET_MODE_RECONFIGURE);
         assertTrue(Arrays.equals(mono, mono2));
+
+        // NOTE: coming soon
+        // and when flushing it
+//        short [] mono3 = decodeToMemory(res, RESET_MODE_FLUSH);
+//        assertTrue(Arrays.equals(mono, mono3));
     }
 
     /**
@@ -126,7 +135,7 @@
      */
     private void decode(int testinput, float maxerror) throws IOException {
 
-        short [] decoded = decodeToMemory(testinput, false);
+        short [] decoded = decodeToMemory(testinput, RESET_MODE_NONE);
 
         assertEquals("wrong data size", mMasterBuffer.length, decoded.length);
 
@@ -143,14 +152,21 @@
         double rmse = Math.sqrt(avgErrorSquared);
         assertTrue("decoding error too big: " + rmse, rmse <= maxerror);
 
-        short [] decoded2 = decodeToMemory(testinput, true);
+        short [] decoded2 = decodeToMemory(testinput, RESET_MODE_RECONFIGURE);
         assertEquals("count different with reconfigure", decoded.length, decoded2.length);
         for (int i = 0; i < decoded.length; i++) {
             assertEquals("samples don't match", decoded[i], decoded2[i]);
         }
+
+        // NOTE: coming soon
+//        short [] decoded3 = decodeToMemory(testinput, RESET_MODE_FLUSH);
+//        assertEquals("count different with flush", decoded.length, decoded3.length);
+//        for (int i = 0; i < decoded.length; i++) {
+//            assertEquals("samples don't match", decoded[i], decoded3[i]);
+//        }
     }
 
-    private short[] decodeToMemory(int testinput, boolean reconfigure) throws IOException {
+    private short[] decodeToMemory(int testinput, int resetMode) throws IOException {
 
         short [] decoded = new short[0];
         int decodedIdx = 0;
@@ -178,12 +194,14 @@
         codecInputBuffers = codec.getInputBuffers();
         codecOutputBuffers = codec.getOutputBuffers();
 
-        if (reconfigure) {
+        if (resetMode == RESET_MODE_RECONFIGURE) {
             codec.stop();
             codec.configure(format, null /* surface */, null /* crypto */, 0 /* flags */);
             codec.start();
             codecInputBuffers = codec.getInputBuffers();
             codecOutputBuffers = codec.getOutputBuffers();
+        } else if (resetMode == RESET_MODE_FLUSH) {
+            codec.flush();
         }
 
         extractor.selectTrack(0);
@@ -236,16 +254,21 @@
                 if (info.size > 0) {
                     noOutputCounter = 0;
                 }
-                if (info.size > 0 && reconfigure) {
-                    // once we've gotten some data out of the decoder, reconfigure it again
-                    reconfigure = false;
+                if (info.size > 0 && resetMode != RESET_MODE_NONE) {
+                    // once we've gotten some data out of the decoder, reset and start again
+                    if (resetMode == RESET_MODE_RECONFIGURE) {
+                        codec.stop();
+                        codec.configure(format, null /* surface */, null /* crypto */,
+                                0 /* flags */);
+                        codec.start();
+                        codecInputBuffers = codec.getInputBuffers();
+                        codecOutputBuffers = codec.getOutputBuffers();
+                    } else /* resetMode == RESET_MODE_FLUSH */ {
+                        codec.flush();
+                    }
+                    resetMode = RESET_MODE_NONE;
                     extractor.seekTo(0, MediaExtractor.SEEK_TO_NEXT_SYNC);
                     sawInputEOS = false;
-                    codec.stop();
-                    codec.configure(format, null /* surface */, null /* crypto */, 0 /* flags */);
-                    codec.start();
-                    codecInputBuffers = codec.getInputBuffers();
-                    codecOutputBuffers = codec.getOutputBuffers();
                     continue;
                 }
 
@@ -288,12 +311,12 @@
         Surface s = getActivity().getSurfaceHolder().getSurface();
         int frames1 = countFrames(
                 R.raw.video_480x360_mp4_h264_1000kbps_25fps_aac_stereo_128kbps_44100hz,
-                false, -1, s);
+                RESET_MODE_NONE, -1 /* eosframe */, s);
         assertEquals("wrong number of frames decoded", 240, frames1);
 
         int frames2 = countFrames(
                 R.raw.video_480x360_mp4_h264_1000kbps_25fps_aac_stereo_128kbps_44100hz,
-                false, -1, null);
+                RESET_MODE_NONE, -1 /* eosframe */, null);
         assertEquals("different number of frames when using Surface", frames1, frames2);
     }
 
@@ -301,12 +324,12 @@
         Surface s = getActivity().getSurfaceHolder().getSurface();
         int frames1 = countFrames(
                 R.raw.video_176x144_3gp_h263_300kbps_12fps_aac_stereo_128kbps_22050hz,
-                false /* reconfigure */, -1 /* eosframe */, s);
+                RESET_MODE_NONE, -1 /* eosframe */, s);
         assertEquals("wrong number of frames decoded", 122, frames1);
 
         int frames2 = countFrames(
                 R.raw.video_176x144_3gp_h263_300kbps_12fps_aac_stereo_128kbps_22050hz,
-                false /* reconfigure */, -1 /* eosframe */, null);
+                RESET_MODE_NONE, -1 /* eosframe */, null);
         assertEquals("different number of frames when using Surface", frames1, frames2);
     }
 
@@ -314,12 +337,12 @@
         Surface s = getActivity().getSurfaceHolder().getSurface();
         int frames1 = countFrames(
                 R.raw.video_480x360_mp4_mpeg4_860kbps_25fps_aac_stereo_128kbps_44100hz,
-                false, -1, s);
+                RESET_MODE_NONE, -1 /* eosframe */, s);
         assertEquals("wrong number of frames decoded", 249, frames1);
 
         int frames2 = countFrames(
                 R.raw.video_480x360_mp4_mpeg4_860kbps_25fps_aac_stereo_128kbps_44100hz,
-                false, -1, null);
+                RESET_MODE_NONE, -1 /* eosframe */, null);
         assertEquals("different number of frames when using Surface", frames1, frames2);
     }
 
@@ -327,12 +350,12 @@
         Surface s = getActivity().getSurfaceHolder().getSurface();
         int frames1 = countFrames(
                 R.raw.video_480x360_webm_vp8_333kbps_25fps_vorbis_stereo_128kbps_44100hz,
-                false, -1, s);
+                RESET_MODE_NONE, -1 /* eosframe */, s);
         assertEquals("wrong number of frames decoded", 240, frames1);
 
         int frames2 = countFrames(
                 R.raw.video_480x360_webm_vp8_333kbps_25fps_vorbis_stereo_128kbps_44100hz,
-                false, -1, null);
+                RESET_MODE_NONE, -1 /* eosframe */, null);
         assertEquals("different number of frames when using Surface", frames1, frames2);
     }
 
@@ -340,12 +363,12 @@
         Surface s = getActivity().getSurfaceHolder().getSurface();
         int frames1 = countFrames(
                 R.raw.video_480x360_webm_vp9_333kbps_25fps_vorbis_stereo_128kbps_44100hz,
-                false, -1, s);
+                RESET_MODE_NONE, -1 /* eosframe */, s);
         assertEquals("wrong number of frames decoded", 240, frames1);
 
         int frames2 = countFrames(
                 R.raw.video_480x360_webm_vp9_333kbps_25fps_vorbis_stereo_128kbps_44100hz,
-                false, -1, null);
+                RESET_MODE_NONE, -1 /* eosframe */, null);
         assertEquals("different number of frames when using Surface", frames1, frames2);
     }
 
@@ -353,7 +376,7 @@
         Surface s = getActivity().getSurfaceHolder().getSurface();
         int frames1 = countFrames(
                 R.raw.video_176x144_3gp_h263_300kbps_12fps_aac_stereo_128kbps_22050hz,
-                false, 64, s);
+                RESET_MODE_NONE, 64 /* eosframe */, s);
         assertEquals("wrong number of frames decoded", 64, frames1);
     }
 
@@ -361,7 +384,7 @@
         Surface s = getActivity().getSurfaceHolder().getSurface();
         int frames1 = countFrames(
                 R.raw.video_480x360_mp4_h264_1000kbps_25fps_aac_stereo_128kbps_44100hz,
-                false, 120, s);
+                RESET_MODE_NONE, 120 /* eosframe */, s);
         assertEquals("wrong number of frames decoded", 120, frames1);
     }
 
@@ -369,7 +392,7 @@
         Surface s = getActivity().getSurfaceHolder().getSurface();
         int frames1 = countFrames(
                 R.raw.video_480x360_mp4_mpeg4_860kbps_25fps_aac_stereo_128kbps_44100hz,
-                false, 120, s);
+                RESET_MODE_NONE, 120 /* eosframe */, s);
         assertEquals("wrong number of frames decoded", 120, frames1);
     }
 
@@ -377,7 +400,7 @@
         Surface s = getActivity().getSurfaceHolder().getSurface();
         int frames1 = countFrames(
                 R.raw.video_480x360_webm_vp8_333kbps_25fps_vorbis_stereo_128kbps_44100hz,
-                false, 120, s);
+                RESET_MODE_NONE, 120 /* eosframe */, s);
         assertEquals("wrong number of frames decoded", 120, frames1);
     }
 
@@ -385,80 +408,93 @@
         Surface s = getActivity().getSurfaceHolder().getSurface();
         int frames1 = countFrames(
                 R.raw.video_480x360_webm_vp9_333kbps_25fps_vorbis_stereo_128kbps_44100hz,
-                false, 120, s);
+                RESET_MODE_NONE, 120 /* eosframe */, s);
         assertEquals("wrong number of frames decoded", 120, frames1);
     }
 
-    public void testCodecReconfigH264WithoutSurface() throws Exception {
-        testCodecReconfig(
+    public void testCodecResetsH264WithoutSurface() throws Exception {
+        testCodecResets(
                 R.raw.video_480x360_mp4_h264_1000kbps_25fps_aac_stereo_128kbps_44100hz, null);
     }
 
-    public void testCodecReconfigH264WithSurface() throws Exception {
+    public void testCodecResetsH264WithSurface() throws Exception {
         Surface s = getActivity().getSurfaceHolder().getSurface();
-        testCodecReconfig(
+        testCodecResets(
                 R.raw.video_480x360_mp4_h264_1000kbps_25fps_aac_stereo_128kbps_44100hz, s);
     }
 
-    public void testCodecReconfigH263WithoutSurface() throws Exception {
-        testCodecReconfig(
+    public void testCodecResetsH263WithoutSurface() throws Exception {
+        testCodecResets(
                 R.raw.video_176x144_3gp_h263_300kbps_12fps_aac_stereo_128kbps_22050hz, null);
     }
 
-    public void testCodecReconfigH263WithSurface() throws Exception {
+    public void testCodecResetsH263WithSurface() throws Exception {
         Surface s = getActivity().getSurfaceHolder().getSurface();
-        testCodecReconfig(
+        testCodecResets(
                 R.raw.video_176x144_3gp_h263_300kbps_12fps_aac_stereo_128kbps_22050hz, s);
     }
 
-    public void testCodecReconfigMpeg4WithoutSurface() throws Exception {
-        testCodecReconfig(
+    public void testCodecResetsMpeg4WithoutSurface() throws Exception {
+        testCodecResets(
                 R.raw.video_480x360_mp4_mpeg4_860kbps_25fps_aac_stereo_128kbps_44100hz, null);
     }
 
-    public void testCodecReconfigMpeg4WithSurface() throws Exception {
+    public void testCodecResetsMpeg4WithSurface() throws Exception {
         Surface s = getActivity().getSurfaceHolder().getSurface();
-        testCodecReconfig(
+        testCodecResets(
                 R.raw.video_480x360_mp4_mpeg4_860kbps_25fps_aac_stereo_128kbps_44100hz, s);
     }
 
-    public void testCodecReconfigVP8WithoutSurface() throws Exception {
-        testCodecReconfig(
+    public void testCodecResetsVP8WithoutSurface() throws Exception {
+        testCodecResets(
                 R.raw.video_480x360_webm_vp8_333kbps_25fps_vorbis_stereo_128kbps_44100hz, null);
     }
 
-    public void testCodecReconfigVP8WithSurface() throws Exception {
+    public void testCodecResetsVP8WithSurface() throws Exception {
         Surface s = getActivity().getSurfaceHolder().getSurface();
-        testCodecReconfig(
+        testCodecResets(
                 R.raw.video_480x360_webm_vp8_333kbps_25fps_vorbis_stereo_128kbps_44100hz, s);
     }
 
-    public void testCodecReconfigVP9WithoutSurface() throws Exception {
-        testCodecReconfig(
+    public void testCodecResetsVP9WithoutSurface() throws Exception {
+        testCodecResets(
                 R.raw.video_480x360_webm_vp9_333kbps_25fps_vorbis_stereo_128kbps_44100hz, null);
     }
 
-    public void testCodecReconfigVP9WithSurface() throws Exception {
+    public void testCodecResetsVP9WithSurface() throws Exception {
         Surface s = getActivity().getSurfaceHolder().getSurface();
-        testCodecReconfig(
+        testCodecResets(
                 R.raw.video_480x360_webm_vp9_333kbps_25fps_vorbis_stereo_128kbps_44100hz, s);
     }
-//    public void testCodecReconfigOgg() throws Exception {
-//        testCodecReconfig(R.raw.sinesweepogg, null);
+
+//    public void testCodecResetsOgg() throws Exception {
+//        testCodecResets(R.raw.sinesweepogg, null);
 //    }
-//
-    public void testCodecReconfigMp3() throws Exception {
+
+    public void testCodecResetsMp3() throws Exception {
         testCodecReconfig(R.raw.sinesweepmp3lame, null);
+        // NOTE: replacing testCodecReconfig call soon
+//        testCodecResets(R.raw.sinesweepmp3lame, null);
     }
 
-    public void testCodecReconfigM4a() throws Exception {
+    public void testCodecResetsM4a() throws Exception {
         testCodecReconfig(R.raw.sinesweepm4a, null);
+        // NOTE: replacing testCodecReconfig call soon
+//        testCodecResets(R.raw.sinesweepm4a, null);
     }
 
     private void testCodecReconfig(int video, Surface s) throws Exception {
-        int frames1 = countFrames(video, false /* reconfigure */, -1 /* eosframe */, s);
-        int frames2 = countFrames(video, true /* reconfigure */, -1 /* eosframe */, s);
-        assertEquals("different number of frames when reusing codec", frames1, frames2);
+        int frames1 = countFrames(video, RESET_MODE_NONE, -1 /* eosframe */, s);
+        int frames2 = countFrames(video, RESET_MODE_RECONFIGURE, -1 /* eosframe */, s);
+        assertEquals("different number of frames when using reconfigured codec", frames1, frames2);
+    }
+
+    private void testCodecResets(int video, Surface s) throws Exception {
+        int frames1 = countFrames(video, RESET_MODE_NONE, -1 /* eosframe */, s);
+        int frames2 = countFrames(video, RESET_MODE_RECONFIGURE, -1 /* eosframe */, s);
+        int frames3 = countFrames(video, RESET_MODE_FLUSH, -1 /* eosframe */, s);
+        assertEquals("different number of frames when using reconfigured codec", frames1, frames2);
+        assertEquals("different number of frames when using flushed codec", frames1, frames3);
     }
 
     private MediaCodec createDecoder(String mime) {
@@ -479,7 +515,8 @@
         return MediaCodec.createDecoderByType(mime);
     }
 
-    private int countFrames(int video, boolean reconfigure, int eosframe, Surface s) throws Exception {
+    private int countFrames(int video, int resetMode, int eosframe, Surface s)
+            throws Exception {
         int numframes = 0;
 
         AssetFileDescriptor testFd = mResources.openRawResourceFd(video);
@@ -506,13 +543,16 @@
         codecInputBuffers = codec.getInputBuffers();
         codecOutputBuffers = codec.getOutputBuffers();
 
-        if (reconfigure) {
+        if (resetMode == RESET_MODE_RECONFIGURE) {
             codec.stop();
             codec.configure(format, s /* surface */, null /* crypto */, 0 /* flags */);
             codec.start();
             codecInputBuffers = codec.getInputBuffers();
             codecOutputBuffers = codec.getOutputBuffers();
+        } else if (resetMode == RESET_MODE_FLUSH) {
+            codec.flush();
         }
+
         Log.i("@@@@", "format: " + format);
 
         extractor.selectTrack(0);
@@ -575,18 +615,23 @@
                 // Some decoders output a 0-sized buffer at the end. Disregard those.
                 if (info.size > 0) {
                     deadDecoderCounter = 0;
-                    if (reconfigure) {
-                        // once we've gotten some data out of the decoder, reconfigure it again
-                        reconfigure = false;
-                        numframes = 0;
+                    if (resetMode != RESET_MODE_NONE) {
+                        // once we've gotten some data out of the decoder, reset and start again
+                        if (resetMode == RESET_MODE_RECONFIGURE) {
+                            codec.stop();
+                            codec.configure(format, s /* surface */, null /* crypto */,
+                                    0 /* flags */);
+                            codec.start();
+                            codecInputBuffers = codec.getInputBuffers();
+                            codecOutputBuffers = codec.getOutputBuffers();
+                        } else /* resetMode == RESET_MODE_FLUSH */ {
+                            codec.flush();
+                        }
+                        resetMode = RESET_MODE_NONE;
                         extractor.seekTo(0, MediaExtractor.SEEK_TO_NEXT_SYNC);
                         sawInputEOS = false;
+                        numframes = 0;
                         timestamps.clear();
-                        codec.stop();
-                        codec.configure(format, s /* surface */, null /* crypto */, 0 /* flags */);
-                        codec.start();
-                        codecInputBuffers = codec.getInputBuffers();
-                        codecOutputBuffers = codec.getOutputBuffers();
                         continue;
                     }
 
@@ -994,7 +1039,7 @@
         codec.release();
 
     }
-    
+
     private short getAmplitude(MediaExtractor extractor, MediaCodec codec) {
         short maxvalue = 0;
         int numBytesDecoded = 0;
@@ -1045,7 +1090,7 @@
                 MediaFormat oformat = codec.getOutputFormat();
             }
         }
-        return maxvalue; 
+        return maxvalue;
     }
 
 }
diff --git a/tests/tests/os/Android.mk b/tests/tests/os/Android.mk
index a5d5d74..f43043b 100644
--- a/tests/tests/os/Android.mk
+++ b/tests/tests/os/Android.mk
@@ -21,6 +21,8 @@
 # and when built explicitly put it in the data partition
 LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
 
+LOCAL_PROGUARD_ENABLED := disabled
+
 LOCAL_JAVA_LIBRARIES := android.test.runner
 
 LOCAL_STATIC_JAVA_LIBRARIES := ctstestrunner guava
diff --git a/tests/tests/os/AndroidManifest.xml b/tests/tests/os/AndroidManifest.xml
index 168d318..2418132 100644
--- a/tests/tests/os/AndroidManifest.xml
+++ b/tests/tests/os/AndroidManifest.xml
@@ -25,16 +25,17 @@
     <application>
         <service
             android:name="android.os.cts.ParcelFileDescriptorPeer$Red"
-            android:process=":red" />
+            android:process=":red"
+            android:exported="true" />
         <service
             android:name="android.os.cts.ParcelFileDescriptorPeer$Blue"
-            android:process=":blue" />
+            android:process=":blue"
+            android:exported="true" />
         <uses-library android:name="android.test.runner" />
     </application>
 
     <instrumentation android:name="android.test.InstrumentationCtsTestRunner"
-                     android:targetPackage="com.android.cts.os"
+                     android:targetPackage="com.android.cts.stub"
                      android:label="CTS tests of android.os"/>
 
 </manifest>
-
diff --git a/tests/tests/os/src/android/os/cts/BuildVersionTest.java b/tests/tests/os/src/android/os/cts/BuildVersionTest.java
index dfa8301..00af150 100644
--- a/tests/tests/os/src/android/os/cts/BuildVersionTest.java
+++ b/tests/tests/os/src/android/os/cts/BuildVersionTest.java
@@ -29,8 +29,8 @@
 
     private static final String LOG_TAG = "BuildVersionTest";
     private static final Set<String> EXPECTED_RELEASES =
-            new HashSet<String>(Arrays.asList("4.2", "4.2.1", "4.2.2"));
-    private static final int EXPECTED_SDK = 17;
+            new HashSet<String>(Arrays.asList("4.4"));
+    private static final int EXPECTED_SDK = 19;
 
     @SuppressWarnings("deprecation")
     public void testReleaseVersion() {
diff --git a/tests/tests/os/src/android/os/cts/ParcelFileDescriptorProcessTest.java b/tests/tests/os/src/android/os/cts/ParcelFileDescriptorProcessTest.java
index d7d3a15..679a35c 100644
--- a/tests/tests/os/src/android/os/cts/ParcelFileDescriptorProcessTest.java
+++ b/tests/tests/os/src/android/os/cts/ParcelFileDescriptorProcessTest.java
@@ -87,8 +87,12 @@
         final Context context = getContext();
 
         // Bring up both remote processes and wire them to each other
-        redIntent = new Intent(context, ParcelFileDescriptorPeer.Red.class);
-        blueIntent = new Intent(context, ParcelFileDescriptorPeer.Blue.class);
+        redIntent = new Intent();
+        redIntent.setComponent(new ComponentName(
+                "com.android.cts.os", "android.os.cts.ParcelFileDescriptorPeer$Red"));
+        blueIntent = new Intent();
+        blueIntent.setComponent(new ComponentName(
+                "com.android.cts.os", "android.os.cts.ParcelFileDescriptorPeer$Blue"));
         redConn = new PeerConnection();
         blueConn = new PeerConnection();
         context.startService(redIntent);
diff --git a/tests/tests/text/src/android/text/method/cts/ArrowKeyMovementMethodTest.java b/tests/tests/text/src/android/text/method/cts/ArrowKeyMovementMethodTest.java
index 6e9996c..1d8a032 100644
--- a/tests/tests/text/src/android/text/method/cts/ArrowKeyMovementMethodTest.java
+++ b/tests/tests/text/src/android/text/method/cts/ArrowKeyMovementMethodTest.java
@@ -180,9 +180,10 @@
         // last line
         Selection.setSelection(mEditable, SPACE_IN_2ND_LINE);
         pressBothShiftAlt();
+        KeyEvent event = new KeyEvent(0, 0, KeyEvent.ACTION_UP,
+            KeyEvent.KEYCODE_DPAD_UP, 0, KeyEvent.META_ALT_ON | KeyEvent.META_SHIFT_ON);
         assertTrue(mArrowKeyMovementMethod.onKeyDown(mTextView, mEditable,
-                KeyEvent.KEYCODE_DPAD_UP, new KeyEvent(KeyEvent.ACTION_DOWN,
-                        KeyEvent.KEYCODE_DPAD_UP)));
+                KeyEvent.KEYCODE_DPAD_UP, event));
         // |first line
         // second |line
         // last line
@@ -190,9 +191,10 @@
 
         Selection.setSelection(mEditable, SPACE_IN_2ND_LINE);
         pressShift();
+        event = new KeyEvent(0, 0, KeyEvent.ACTION_UP,
+            KeyEvent.KEYCODE_DPAD_UP, 0, KeyEvent.META_SHIFT_ON);
         assertTrue(mArrowKeyMovementMethod.onKeyDown(mTextView, mEditable,
-                KeyEvent.KEYCODE_DPAD_UP, new KeyEvent(KeyEvent.ACTION_DOWN,
-                        KeyEvent.KEYCODE_DPAD_UP)));
+                KeyEvent.KEYCODE_DPAD_UP, event));
         // first lin|e
         // second |line
         // last line
@@ -212,9 +214,10 @@
 
         Selection.setSelection(mEditable, SPACE_IN_2ND_LINE);
         pressAlt();
+        event = new KeyEvent(0, 0, KeyEvent.ACTION_UP,
+            KeyEvent.KEYCODE_DPAD_UP, 0, KeyEvent.META_ALT_ON);
         assertTrue(mArrowKeyMovementMethod.onKeyDown(mTextView, mEditable,
-                KeyEvent.KEYCODE_DPAD_UP, new KeyEvent(KeyEvent.ACTION_DOWN,
-                        KeyEvent.KEYCODE_DPAD_UP)));
+                KeyEvent.KEYCODE_DPAD_UP, event));
         // |first line
         // second line
         // last line
@@ -312,9 +315,10 @@
         // last line
         Selection.setSelection(mEditable, SPACE_IN_2ND_LINE);
         pressBothShiftAlt();
+        KeyEvent event = new KeyEvent(0, 0, KeyEvent.ACTION_UP,
+            KeyEvent.KEYCODE_DPAD_LEFT, 0, KeyEvent.META_ALT_ON | KeyEvent.META_SHIFT_ON);
         assertTrue(mArrowKeyMovementMethod.onKeyDown(mTextView, mEditable,
-                KeyEvent.KEYCODE_DPAD_LEFT, new KeyEvent(KeyEvent.ACTION_DOWN,
-                        KeyEvent.KEYCODE_DPAD_LEFT)));
+                KeyEvent.KEYCODE_DPAD_LEFT, event));
         // first line
         // |second |line
         // last line
@@ -322,8 +326,7 @@
 
         pressBothShiftAlt();
         assertTrue(mArrowKeyMovementMethod.onKeyDown(mTextView, mEditable,
-                KeyEvent.KEYCODE_DPAD_LEFT, new KeyEvent(KeyEvent.ACTION_DOWN,
-                        KeyEvent.KEYCODE_DPAD_LEFT)));
+                KeyEvent.KEYCODE_DPAD_LEFT, event));
         // first line
         // |second |line
         // last line
@@ -331,9 +334,10 @@
 
         Selection.setSelection(mEditable, SPACE_IN_2ND_LINE);
         pressShift();
+        event = new KeyEvent(0, 0, KeyEvent.ACTION_UP,
+            KeyEvent.KEYCODE_DPAD_LEFT, 0, KeyEvent.META_SHIFT_ON);
         assertTrue(mArrowKeyMovementMethod.onKeyDown(mTextView, mEditable,
-                KeyEvent.KEYCODE_DPAD_LEFT, new KeyEvent(KeyEvent.ACTION_DOWN,
-                        KeyEvent.KEYCODE_DPAD_LEFT)));
+                KeyEvent.KEYCODE_DPAD_LEFT, event));
         // first line
         // second| |line
         // last line
@@ -350,9 +354,10 @@
 
         Selection.setSelection(mEditable, SPACE_IN_2ND_LINE);
         pressAlt();
+        event = new KeyEvent(0, 0, KeyEvent.ACTION_UP,
+            KeyEvent.KEYCODE_DPAD_LEFT, 0, KeyEvent.META_ALT_ON);
         assertTrue(mArrowKeyMovementMethod.onKeyDown(mTextView, mEditable,
-                KeyEvent.KEYCODE_DPAD_LEFT, new KeyEvent(KeyEvent.ACTION_DOWN,
-                        KeyEvent.KEYCODE_DPAD_LEFT)));
+                KeyEvent.KEYCODE_DPAD_LEFT, event));
         // first line
         // |second line
         // last line
@@ -360,8 +365,7 @@
 
         pressAlt();
         assertTrue(mArrowKeyMovementMethod.onKeyDown(mTextView, mEditable,
-                KeyEvent.KEYCODE_DPAD_LEFT, new KeyEvent(KeyEvent.ACTION_DOWN,
-                        KeyEvent.KEYCODE_DPAD_LEFT)));
+                KeyEvent.KEYCODE_DPAD_LEFT, event));
         // first line
         // |second line
         // last line
@@ -397,9 +401,10 @@
         // last line
         Selection.setSelection(mEditable, SPACE_IN_2ND_LINE);
         pressBothShiftAlt();
+        KeyEvent event = new KeyEvent(0, 0, KeyEvent.ACTION_UP,
+            KeyEvent.KEYCODE_DPAD_RIGHT, 0, KeyEvent.META_ALT_ON | KeyEvent.META_SHIFT_ON);
         assertTrue(mArrowKeyMovementMethod.onKeyDown(mTextView, mEditable,
-                KeyEvent.KEYCODE_DPAD_RIGHT, new KeyEvent(KeyEvent.ACTION_DOWN,
-                        KeyEvent.KEYCODE_DPAD_RIGHT)));
+                KeyEvent.KEYCODE_DPAD_RIGHT, event));
         // first line
         // second |line|
         // last line
@@ -407,8 +412,7 @@
 
         pressBothShiftAlt();
         assertTrue(mArrowKeyMovementMethod.onKeyDown(mTextView, mEditable,
-                KeyEvent.KEYCODE_DPAD_RIGHT, new KeyEvent(KeyEvent.ACTION_DOWN,
-                        KeyEvent.KEYCODE_DPAD_RIGHT)));
+                KeyEvent.KEYCODE_DPAD_RIGHT, event));
         // first line
         // second |line|
         // last line
@@ -416,9 +420,10 @@
 
         Selection.setSelection(mEditable, SPACE_IN_2ND_LINE);
         pressShift();
+        event = new KeyEvent(0, 0, KeyEvent.ACTION_UP,
+            KeyEvent.KEYCODE_DPAD_RIGHT, 0, KeyEvent.META_SHIFT_ON);
         assertTrue(mArrowKeyMovementMethod.onKeyDown(mTextView, mEditable,
-                KeyEvent.KEYCODE_DPAD_RIGHT, new KeyEvent(KeyEvent.ACTION_DOWN,
-                        KeyEvent.KEYCODE_DPAD_RIGHT)));
+                KeyEvent.KEYCODE_DPAD_RIGHT, event));
         // first line
         // second |l|ine
         // last line
@@ -426,8 +431,7 @@
 
         pressShift();
         assertTrue(mArrowKeyMovementMethod.onKeyDown(mTextView, mEditable,
-                KeyEvent.KEYCODE_DPAD_RIGHT, new KeyEvent(KeyEvent.ACTION_DOWN,
-                        KeyEvent.KEYCODE_DPAD_RIGHT)));
+                KeyEvent.KEYCODE_DPAD_RIGHT, event));
         // first line
         // second |li|ne
         // last line
@@ -435,9 +439,10 @@
 
         Selection.setSelection(mEditable, SPACE_IN_2ND_LINE);
         pressAlt();
+        event = new KeyEvent(0, 0, KeyEvent.ACTION_UP,
+            KeyEvent.KEYCODE_DPAD_RIGHT, 0, KeyEvent.META_ALT_ON);
         assertTrue(mArrowKeyMovementMethod.onKeyDown(mTextView, mEditable,
-                KeyEvent.KEYCODE_DPAD_RIGHT, new KeyEvent(KeyEvent.ACTION_DOWN,
-                        KeyEvent.KEYCODE_DPAD_RIGHT)));
+                KeyEvent.KEYCODE_DPAD_RIGHT, event));
         // first line
         // second line|
         // last line
@@ -445,8 +450,7 @@
 
         pressAlt();
         assertTrue(mArrowKeyMovementMethod.onKeyDown(mTextView, mEditable,
-                KeyEvent.KEYCODE_DPAD_RIGHT, new KeyEvent(KeyEvent.ACTION_DOWN,
-                        KeyEvent.KEYCODE_DPAD_RIGHT)));
+                KeyEvent.KEYCODE_DPAD_RIGHT, event));
         // first line
         // second line|
         // last line
diff --git a/tests/tests/text/src/android/text/method/cts/BaseKeyListenerTest.java b/tests/tests/text/src/android/text/method/cts/BaseKeyListenerTest.java
index 91c0bf6..34ed2dc 100644
--- a/tests/tests/text/src/android/text/method/cts/BaseKeyListenerTest.java
+++ b/tests/tests/text/src/android/text/method/cts/BaseKeyListenerTest.java
@@ -139,7 +139,10 @@
      */
     private void sendAltDelete() {
         mInstrumentation.sendKeySync(new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_ALT_LEFT));
-        sendKeys(KeyEvent.KEYCODE_DEL);
+        mInstrumentation.sendKeySync(new KeyEvent(0, 0, KeyEvent.ACTION_DOWN,
+                KeyEvent.KEYCODE_DEL, 0, KeyEvent.META_ALT_ON));
+        mInstrumentation.sendKeySync(new KeyEvent(0, 0, KeyEvent.ACTION_UP,
+                KeyEvent.KEYCODE_DEL, 0, KeyEvent.META_ALT_ON));
         mInstrumentation.sendKeySync(new KeyEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_ALT_LEFT));
     }
 
diff --git a/tests/tests/webkit/src/android/webkit/cts/WebViewTest.java b/tests/tests/webkit/src/android/webkit/cts/WebViewTest.java
index 69ad3a5..ef0e0f4 100644
--- a/tests/tests/webkit/src/android/webkit/cts/WebViewTest.java
+++ b/tests/tests/webkit/src/android/webkit/cts/WebViewTest.java
@@ -203,65 +203,86 @@
         mWebView.invokeZoomPicker();
     }
 
-    @UiThreadTest
-    public void testZoom() {
-        WebSettings settings = mWebView.getSettings();
+    public void testZoom() throws Throwable {
+        final ScaleChangedWebViewClient webViewClient = new ScaleChangedWebViewClient();
+        mOnUiThread.setWebViewClient(webViewClient);
+
+        mWebServer = new CtsTestServer(getActivity());
+        mOnUiThread.loadUrlAndWaitForCompletion(
+                mWebServer.getAssetUrl(TestHtmlConstants.HELLO_WORLD_URL));
+        // Wait for initial scale to be set.
+        webViewClient.waitForScaleChanged();
+
+        WebSettings settings = mOnUiThread.getSettings();
         settings.setSupportZoom(false);
         assertFalse(settings.supportZoom());
-        float currScale = mWebView.getScale();
+        float currScale = mOnUiThread.getScale();
         float previousScale = currScale;
 
         // can zoom in or out although zoom support is disabled in web settings
-        assertTrue(mWebView.zoomIn());
-        currScale = mWebView.getScale();
+        assertTrue(mOnUiThread.zoomIn());
+        webViewClient.waitForScaleChanged();
+
+        currScale = mOnUiThread.getScale();
         assertTrue(currScale > previousScale);
 
-        // zoom in
-        assertTrue(mWebView.zoomOut());
+        assertTrue(mOnUiThread.zoomOut());
         previousScale = currScale;
-        currScale = mWebView.getScale();
+        webViewClient.waitForScaleChanged();
+
+        currScale = mOnUiThread.getScale();
         assertTrue(currScale < previousScale);
 
         // enable zoom support
         settings.setSupportZoom(true);
         assertTrue(settings.supportZoom());
-        currScale = mWebView.getScale();
+        previousScale = mOnUiThread.getScale();
 
-        assertTrue(mWebView.zoomIn());
-        previousScale = currScale;
-        currScale = mWebView.getScale();
+        assertTrue(mOnUiThread.zoomIn());
+        webViewClient.waitForScaleChanged();
+
+        currScale = mOnUiThread.getScale();
         assertTrue(currScale > previousScale);
 
         // zoom in until it reaches maximum scale
-        while (currScale > previousScale) {
-            mWebView.zoomIn();
+        while (mOnUiThread.zoomIn()) {
             previousScale = currScale;
-            currScale = mWebView.getScale();
+            webViewClient.waitForScaleChanged();
+            currScale = mOnUiThread.getScale();
+            assertTrue(currScale > previousScale);
         }
 
-        // can not zoom in further
-        assertFalse(mWebView.zoomIn());
         previousScale = currScale;
-        currScale = mWebView.getScale();
+        // can not zoom in further
+        assertFalse(mOnUiThread.zoomIn());
+        // We sleep to assert to the best of our ability
+        // that a scale change does *not* happen.
+        Thread.sleep(500);
+        currScale = mOnUiThread.getScale();
         assertEquals(currScale, previousScale);
 
         // zoom out
-        assertTrue(mWebView.zoomOut());
+        assertTrue(mOnUiThread.zoomOut());
         previousScale = currScale;
-        currScale = mWebView.getScale();
+        webViewClient.waitForScaleChanged();
+        currScale = mOnUiThread.getScale();
         assertTrue(currScale < previousScale);
 
         // zoom out until it reaches minimum scale
-        while (currScale < previousScale) {
-            mWebView.zoomOut();
+        while (mOnUiThread.zoomOut()) {
             previousScale = currScale;
-            currScale = mWebView.getScale();
+            webViewClient.waitForScaleChanged();
+            currScale = mOnUiThread.getScale();
+            assertTrue(currScale < previousScale);
         }
 
-        // can not zoom out further
-        assertFalse(mWebView.zoomOut());
         previousScale = currScale;
-        currScale = mWebView.getScale();
+        assertFalse(mOnUiThread.zoomOut());
+
+        // We sleep to assert to the best of our ability
+        // that a scale change does *not* happen.
+        Thread.sleep(500);
+        currScale = mOnUiThread.getScale();
         assertEquals(currScale, previousScale);
     }
 
@@ -1476,22 +1497,7 @@
     }
 
     public void testSetWebViewClient() throws Throwable {
-        final class MockWebViewClient extends WaitForLoadedClient {
-            private boolean mOnScaleChangedCalled = false;
-            public MockWebViewClient() {
-                super(mOnUiThread);
-            }
-            @Override
-            public void onScaleChanged(WebView view, float oldScale, float newScale) {
-                super.onScaleChanged(view, oldScale, newScale);
-                mOnScaleChangedCalled = true;
-            }
-            public boolean onScaleChangedCalled() {
-                return mOnScaleChangedCalled;
-            }
-        }
-
-        final MockWebViewClient webViewClient = new MockWebViewClient();
+        final ScaleChangedWebViewClient webViewClient = new ScaleChangedWebViewClient();
         mOnUiThread.setWebViewClient(webViewClient);
         startWebServer(false);
 
@@ -1500,12 +1506,7 @@
         mOnUiThread.loadUrlAndWaitForCompletion(url1);
 
         mOnUiThread.zoomIn();
-        new PollingCheck() {
-            @Override
-            protected boolean check() {
-                return webViewClient.onScaleChangedCalled();
-            }
-        }.run();
+        webViewClient.waitForScaleChanged();
     }
 
     @UiThreadTest
@@ -2158,4 +2159,35 @@
             mActualResult = result;
         }
     }
+
+    final class ScaleChangedWebViewClient extends WaitForLoadedClient {
+        private boolean mOnScaleChangedCalled = false;
+        public ScaleChangedWebViewClient() {
+            super(mOnUiThread);
+        }
+
+        @Override
+        public void onScaleChanged(WebView view, float oldScale, float newScale) {
+            super.onScaleChanged(view, oldScale, newScale);
+            synchronized (this) {
+                mOnScaleChangedCalled = true;
+            }
+        }
+
+        public void waitForScaleChanged() {
+            new PollingCheck(TEST_TIMEOUT) {
+                 @Override
+                 protected boolean check() {
+                     return onScaleChangedCalled();
+                 }
+            }.run();
+            synchronized (this) {
+                mOnScaleChangedCalled = false;
+            }
+        }
+
+        public synchronized boolean onScaleChangedCalled() {
+            return mOnScaleChangedCalled;
+        }
+    }
 }