Merge "Remove callback test"
diff --git a/tests/AndroidManifest.xml b/tests/AndroidManifest.xml
index cc5832c..522eb6e 100644
--- a/tests/AndroidManifest.xml
+++ b/tests/AndroidManifest.xml
@@ -117,6 +117,9 @@
     <!-- Used for Transmit IR Test -->
     <uses-permission android:name="android.permission.TRANSMIT_IR" />
 
+    <!-- Used for SystemFeatures Test -->
+    <uses-permission android:name="android.permission.BODY_SENSORS"/>
+
     <!-- Used for PackageManager test, don't delete this permission-tree -->
     <permission-tree android:name="com.android.cts.stub.permission.TEST_DYNAMIC"
                     android:label="Test Tree"/>
diff --git a/tests/src/android/text/EmojiStubActivity.java b/tests/src/android/text/EmojiStubActivity.java
index 1587c94..8d09250 100644
--- a/tests/src/android/text/EmojiStubActivity.java
+++ b/tests/src/android/text/EmojiStubActivity.java
@@ -21,15 +21,20 @@
 import android.app.Activity;
 import android.os.Bundle;
 import android.webkit.WebView;
+import android.webkit.cts.NullWebViewUtils;
 
 public class EmojiStubActivity extends Activity {
     private WebView mWebView;
 
     @Override
     public void onCreate(Bundle savedInstanceState) {
-        super.onCreate(savedInstanceState);
-        setContentView(R.layout.webview_layout);
-        mWebView = (WebView) findViewById(R.id.web_page);
+        try {
+            super.onCreate(savedInstanceState);
+            setContentView(R.layout.webview_layout);
+            mWebView = (WebView) findViewById(R.id.web_page);
+        } catch (Exception e) {
+            NullWebViewUtils.determineIfWebViewAvailable(this, e);
+        }
     }
 
     public WebView getWebView() {
@@ -38,7 +43,9 @@
 
     @Override
     public void onDestroy() {
-        mWebView.destroy();
+        if (mWebView != null) {
+            mWebView.destroy();
+        }
         super.onDestroy();
     }
 }
diff --git a/tests/src/android/webkit/cts/CookieSyncManagerStubActivity.java b/tests/src/android/webkit/cts/CookieSyncManagerStubActivity.java
index 3421ac6..a5ac6ec 100644
--- a/tests/src/android/webkit/cts/CookieSyncManagerStubActivity.java
+++ b/tests/src/android/webkit/cts/CookieSyncManagerStubActivity.java
@@ -27,22 +27,35 @@
     @Override
     public void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
-        CookieSyncManager.createInstance(this);
 
-        mWebView = new WebView(this);
-        setContentView(mWebView);
+        try {
+            CookieSyncManager.createInstance(this);
+
+            mWebView = new WebView(this);
+            setContentView(mWebView);
+        } catch (Exception e) {
+            NullWebViewUtils.determineIfWebViewAvailable(this, e);
+        }
     }
 
     @Override
     protected void onResume() {
         super.onResume();
-        CookieSyncManager.getInstance().startSync();
+        try {
+            CookieSyncManager.getInstance().startSync();
+        } catch (Exception e) {
+            // May throw on a device with no webview, OK to ignore at this point.
+        }
     }
 
     @Override
     protected void onStop() {
         super.onStop();
-        CookieSyncManager.getInstance().stopSync();
+        try {
+            CookieSyncManager.getInstance().stopSync();
+        } catch (Exception e) {
+            // May throw on a device with no webview, OK to ignore at this point.
+        }
     }
 
     public WebView getWebView(){
diff --git a/tests/src/android/webkit/cts/NullWebViewUtils.java b/tests/src/android/webkit/cts/NullWebViewUtils.java
new file mode 100644
index 0000000..c52219f
--- /dev/null
+++ b/tests/src/android/webkit/cts/NullWebViewUtils.java
@@ -0,0 +1,88 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.webkit.cts;
+
+import android.content.Context;
+import android.content.pm.PackageManager;
+
+/**
+ * Utilities to enable the android.webkit.* CTS tests (and others that rely on a functioning
+ * android.webkit.WebView implementation) to determine whether a functioning WebView is present
+ * on the device or not.
+ *
+ * Test cases that require android.webkit.* classes should wrap their first usage of WebView in a
+ * try catch block, and pass any exception that is thrown to
+ * NullWebViewUtils.determineIfWebViewAvailable. The return value of
+ * NullWebViewUtils.isWebViewAvailable will then determine if the test should expect to be able to
+ * use a WebView.
+ */
+public class NullWebViewUtils {
+
+    private static boolean sWebViewUnavailable;
+
+    /**
+     * @param context Current Activity context, used to query the PackageManager.
+     * @param t       An exception thrown by trying to invoke android.webkit.* APIs.
+     */
+    public static void determineIfWebViewAvailable(Context context, Throwable t) {
+        sWebViewUnavailable = !hasWebViewFeature(context) && checkCauseWasUnsupportedOperation(t);
+    }
+
+    /**
+     * After calling determineIfWebViewAvailable, this returns whether a WebView is available on the
+     * device and wheter the test can rely on it.
+     * @return True iff. PackageManager determined that there is no WebView on the device and the
+     *         exception thrown from android.webkit.* was UnsupportedOperationException.
+     */
+    public static boolean isWebViewAvailable() {
+        return !sWebViewUnavailable;
+    }
+
+    private static boolean hasWebViewFeature(Context context) {
+        // Query the system property that determins if there is a functional WebView on the device.
+        PackageManager pm = context.getPackageManager();
+        return pm.hasSystemFeature(PackageManager.FEATURE_WEBVIEW);
+    }
+
+    private static boolean checkCauseWasUnsupportedOperation(Throwable t) {
+        if (t == null) return false;
+        while (t.getCause() != null) {
+            t = t.getCause();
+        }
+        return t instanceof UnsupportedOperationException;
+    }
+
+    /**
+     * Some CTS tests (by design) first use android.webkit.* from a background thread. This helper
+     * allows the test to catch the UnsupportedOperationException from that background thread, and
+     * then query the result from the test main thread.
+     */
+    public static class NullWebViewFromThreadExceptionHandler
+            implements Thread.UncaughtExceptionHandler {
+        private Throwable mPendingException;
+
+        @Override
+        public void uncaughtException(Thread t, Throwable e) {
+            mPendingException = e;
+        }
+
+        public boolean isWebViewAvailable(Context context) {
+            return hasWebViewFeature(context) ||
+                    !checkCauseWasUnsupportedOperation(mPendingException);
+        }
+    }
+}
\ No newline at end of file
diff --git a/tests/src/android/webkit/cts/WebViewStubActivity.java b/tests/src/android/webkit/cts/WebViewStubActivity.java
index 6a51bbe..62adc39 100644
--- a/tests/src/android/webkit/cts/WebViewStubActivity.java
+++ b/tests/src/android/webkit/cts/WebViewStubActivity.java
@@ -29,9 +29,13 @@
 
     @Override
     public void onCreate(Bundle savedInstanceState) {
-        super.onCreate(savedInstanceState);
-        setContentView(R.layout.webview_layout);
-        mWebView = (WebView) findViewById(R.id.web_page);
+        try {
+            super.onCreate(savedInstanceState);
+            setContentView(R.layout.webview_layout);
+            mWebView = (WebView) findViewById(R.id.web_page);
+        } catch (Exception e) {
+            NullWebViewUtils.determineIfWebViewAvailable(this, e);
+        }
     }
 
     public WebView getWebView() {
@@ -40,11 +44,13 @@
 
     @Override
     public void onDestroy() {
-        ViewParent parent =  mWebView.getParent();
-        if (parent instanceof ViewGroup) {
-            ((ViewGroup) parent).removeView(mWebView);
+        if (mWebView != null) {
+            ViewParent parent =  mWebView.getParent();
+            if (parent instanceof ViewGroup) {
+                ((ViewGroup) parent).removeView(mWebView);
+            }
+            mWebView.destroy();
         }
-        mWebView.destroy();
         super.onDestroy();
     }
 }
diff --git a/tests/src/android/widget/cts/RemoteViewsStubActivity.java b/tests/src/android/widget/cts/RemoteViewsStubActivity.java
index f1c0a72..f16ae13 100644
--- a/tests/src/android/widget/cts/RemoteViewsStubActivity.java
+++ b/tests/src/android/widget/cts/RemoteViewsStubActivity.java
@@ -20,6 +20,7 @@
 
 import android.app.Activity;
 import android.os.Bundle;
+import android.webkit.cts.NullWebViewUtils;
 import android.widget.RemoteViews;
 
 /**
@@ -28,7 +29,11 @@
 public class RemoteViewsStubActivity extends Activity {
     @Override
     protected void onCreate(Bundle savedInstanceState) {
-        super.onCreate(savedInstanceState);
-        setContentView(R.layout.remoteviews_host);
+        try {
+            super.onCreate(savedInstanceState);
+            setContentView(R.layout.remoteviews_host);
+        } catch (Exception e) {
+            NullWebViewUtils.determineIfWebViewAvailable(this, e);
+        }
     }
 }
diff --git a/tests/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityWindowQueryActivity.java b/tests/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityWindowQueryActivity.java
index c89d817..698989c 100644
--- a/tests/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityWindowQueryActivity.java
+++ b/tests/tests/accessibilityservice/src/android/accessibilityservice/cts/AccessibilityWindowQueryActivity.java
@@ -55,7 +55,10 @@
 
             @Override
             public boolean performAccessibilityAction(View host, int action, Bundle args) {
-                return (action == R.id.foo_custom_action);
+                if (action == R.id.foo_custom_action) {
+                    return true;
+                }
+                return super.performAccessibilityAction(host, action, args);
             }
         });
     }
diff --git a/tests/tests/app/src/android/app/cts/WallpaperManagerTest.java b/tests/tests/app/src/android/app/cts/WallpaperManagerTest.java
index fdf3cac..65f89f3 100644
--- a/tests/tests/app/src/android/app/cts/WallpaperManagerTest.java
+++ b/tests/tests/app/src/android/app/cts/WallpaperManagerTest.java
@@ -33,26 +33,37 @@
         mWallpaperManager = WallpaperManager.getInstance(mContext);
     }
 
+    /**
+     * Suggesting desired dimensions is only a hint to the system that can be ignored.
+     *
+     * Test if the desired minimum width or height the WallpaperManager returns
+     * is greater than 0. If so, then we check whether that the size is at least the
+     * as big as the screen.
+     */
     public void testSuggestDesiredDimensions() {
-        Point min = getScreenSize();
-        int w = min.x * 3;
-        int h = min.y * 2;
+        final Point min = getScreenSize();
+        final int w = min.x * 3;
+        final int h = min.y * 2;
 
-        mWallpaperManager.suggestDesiredDimensions(min.x / 2, min.y / 2);
-        assertEquals(min.x, mWallpaperManager.getDesiredMinimumWidth());
-        assertEquals(min.y, mWallpaperManager.getDesiredMinimumHeight());
+        assertDesiredMinimum(new Point(min.x / 2, min.y / 2), min);
 
-        mWallpaperManager.suggestDesiredDimensions(w, h);
-        assertEquals(w, mWallpaperManager.getDesiredMinimumWidth());
-        assertEquals(h, mWallpaperManager.getDesiredMinimumHeight());
+        assertDesiredMinimum(new Point(w, h),
+                             new Point(w, h));
 
-        mWallpaperManager.suggestDesiredDimensions(min.x / 2, h);
-        assertEquals(min.x, mWallpaperManager.getDesiredMinimumWidth());
-        assertEquals(h, mWallpaperManager.getDesiredMinimumHeight());
+        assertDesiredMinimum(new Point(min.x / 2, h),
+                             new Point(min.x, h));
 
-        mWallpaperManager.suggestDesiredDimensions(w, min.y / 2);
-        assertEquals(w, mWallpaperManager.getDesiredMinimumWidth());
-        assertEquals(min.y, mWallpaperManager.getDesiredMinimumHeight());
+        assertDesiredMinimum(new Point(w, min.y / 2),
+                             new Point(w, min.y));
+    }
+
+    private void assertDesiredMinimum(Point suggestedSize, Point expectedSize) {
+        mWallpaperManager.suggestDesiredDimensions(suggestedSize.x, suggestedSize.y);
+        Point actualSize = new Point(mWallpaperManager.getDesiredMinimumWidth(),
+                mWallpaperManager.getDesiredMinimumHeight());
+        if (actualSize.x > 0 || actualSize.y > 0) {
+            assertEquals(expectedSize, actualSize);
+        }
     }
 
     private Point getScreenSize() {
diff --git a/tests/tests/drm/src/android/drm/cts/DRMTest.java b/tests/tests/drm/src/android/drm/cts/DRMTest.java
index bb77668..bd4291d 100644
--- a/tests/tests/drm/src/android/drm/cts/DRMTest.java
+++ b/tests/tests/drm/src/android/drm/cts/DRMTest.java
@@ -18,6 +18,7 @@
 
 
 import android.content.ContentValues;
+import android.content.pm.PackageManager;
 import android.test.AndroidTestCase;
 import android.util.Log;
 import java.io.IOException;
@@ -48,22 +49,30 @@
     @Override
     protected void setUp() throws Exception {
         super.setUp();
-        mDrmManagerClient = new DrmManagerClient(getContext());
-        String[] plugins = mDrmManagerClient.getAvailableDrmEngines();
 
-        mConfigs.clear();
-        for(String plugInName : plugins) {
-            Config config = ConfigFactory.getConfig(plugInName);
-            if (null != config) {
-                mConfigs.add(config);
+        if (deviceSupportsDRM()) {
+            mDrmManagerClient = new DrmManagerClient(getContext());
+            String[] plugins = mDrmManagerClient.getAvailableDrmEngines();
+
+            mConfigs.clear();
+            for(String plugInName : plugins) {
+                Config config = ConfigFactory.getConfig(plugInName);
+                if (null != config) {
+                    mConfigs.add(config);
+                }
             }
         }
     }
 
+    private boolean deviceSupportsDRM() {
+       /* Watches don't support DRM */
+        return !getContext().getPackageManager().hasSystemFeature(PackageManager.FEATURE_WATCH);
+    }
+
     private void register(Config config) throws Exception {
         DrmInfo drmInfo = executeAcquireDrmInfo(DrmInfoRequest.TYPE_REGISTRATION_INFO,
-                                            config.getInfoOfRegistration(),
-                                            config.getMimeType());
+                config.getInfoOfRegistration(),
+                config.getMimeType());
         executeProcessDrmInfo(drmInfo, config);
     }
 
@@ -82,86 +91,106 @@
     }
 
     public void testIsDrmDirectoryExist() {
-        assertTrue("/data/drm/ does not exist", new File("/data/drm/").exists());
+        if (deviceSupportsDRM()) {
+            assertTrue("/data/drm/ does not exist", new File("/data/drm/").exists());
+        }
     }
 
     public void testRegisterAndDeregister() throws Exception {
-        for (Config config : mConfigs) {
-            register(config);
-            deregister(config);
+        if (deviceSupportsDRM()) {
+            for (Config config : mConfigs) {
+                register(config);
+                deregister(config);
+            }
         }
     }
 
     public void testAcquireRights() throws Exception {
-        for (Config config : mConfigs) {
-            register(config);
-            acquireRights(config);
-            deregister(config);
+        if (deviceSupportsDRM()) {
+            for (Config config : mConfigs) {
+                register(config);
+                acquireRights(config);
+                deregister(config);
+            }
         }
     }
 
     public void testGetConstraints() throws Exception {
-        for (Config config : mConfigs) {
-            register(config);
-            acquireRights(config);
-            ContentValues constraints = mDrmManagerClient.getConstraints(
-                                            config.getContentPath(),
-                                            DrmStore.Action.DEFAULT);
-            assertNotNull("Failed on plugin: " + config.getPluginName(), constraints);
-            deregister(config);
+        if (deviceSupportsDRM()) {
+            for (Config config : mConfigs) {
+                register(config);
+                acquireRights(config);
+                ContentValues constraints = mDrmManagerClient.getConstraints(
+                                                                             config.getContentPath(),
+                                                                             DrmStore.Action.DEFAULT);
+                assertNotNull("Failed on plugin: " + config.getPluginName(), constraints);
+                deregister(config);
+            }
         }
     }
 
     public void testCanHandle() throws Exception {
-        for (Config config : mConfigs) {
-            assertTrue("Failed on plugin: " + config.getPluginName(),
-                    mDrmManagerClient.canHandle(config.getContentPath(), config.getMimeType()));
+        if (deviceSupportsDRM()) {
+            for (Config config : mConfigs) {
+                assertTrue("Failed on plugin: " + config.getPluginName(),
+                        mDrmManagerClient.canHandle(config.getContentPath(), config.getMimeType()));
+            }
         }
     }
 
     public void testGetOriginalMimeType() throws Exception {
-        for (Config config : mConfigs) {
-            assertNotNull("Failed on plugin: " + config.getPluginName(),
-                    mDrmManagerClient.getOriginalMimeType(config.getContentPath()));
+        if (deviceSupportsDRM()) {
+            for (Config config : mConfigs) {
+                assertNotNull("Failed on plugin: " + config.getPluginName(),
+                        mDrmManagerClient.getOriginalMimeType(config.getContentPath()));
+            }
         }
     }
 
     public void testCheckRightsStatus() throws Exception {
-        for (Config config : mConfigs) {
-            register(config);
-            acquireRights(config);
-            int rightsStatus = mDrmManagerClient.checkRightsStatus(
-                                                config.getContentPath(),
-                                                DrmStore.Action.PLAY);
-            assertEquals("Failed on plugin: " + config.getPluginName(),
-                    DrmStore.RightsStatus.RIGHTS_VALID, rightsStatus);
-            deregister(config);
+        if (deviceSupportsDRM()) {
+            for (Config config : mConfigs) {
+                register(config);
+                acquireRights(config);
+                int rightsStatus = mDrmManagerClient.checkRightsStatus(
+                                                                       config.getContentPath(),
+                                                                       DrmStore.Action.PLAY);
+                assertEquals("Failed on plugin: " + config.getPluginName(),
+                        DrmStore.RightsStatus.RIGHTS_VALID, rightsStatus);
+                deregister(config);
+            }
         }
     }
 
     public void testRemoveRights() throws Exception {
-        for (Config config : mConfigs) {
-            assertEquals("Failed on plugin: " + config.getPluginName(),
-                    DrmManagerClient.ERROR_NONE,
-                    mDrmManagerClient.removeRights(config.getContentPath()));
+        if (deviceSupportsDRM()) {
+            for (Config config : mConfigs) {
+                assertEquals("Failed on plugin: " + config.getPluginName(),
+                        DrmManagerClient.ERROR_NONE,
+                        mDrmManagerClient.removeRights(config.getContentPath()));
+            }
         }
     }
 
     public void testRemoveAllRights() throws Exception {
-        for (Config config : mConfigs) {
-            assertEquals("Failed on plugin: " + config.getPluginName(),
-                    mDrmManagerClient.removeAllRights(), DrmManagerClient.ERROR_NONE);
+        if (deviceSupportsDRM()) {
+            for (Config config : mConfigs) {
+                assertEquals("Failed on plugin: " + config.getPluginName(),
+                        mDrmManagerClient.removeAllRights(), DrmManagerClient.ERROR_NONE);
+            }
         }
     }
 
     public void testConvertData() throws Exception {
-        for (Config config : mConfigs) {
-            byte[] inputData = new byte[]{'T','E','S','T'};
+        if (deviceSupportsDRM()) {
+            for (Config config : mConfigs) {
+                byte[] inputData = new byte[]{'T','E','S','T'};
 
-            int convertId = mDrmManagerClient.openConvertSession(config.getMimeType());
-            DrmConvertedStatus drmConvertStatus
-                                = mDrmManagerClient.convertData(convertId, inputData);
-            mDrmManagerClient.closeConvertSession(convertId);
+                int convertId = mDrmManagerClient.openConvertSession(config.getMimeType());
+                DrmConvertedStatus drmConvertStatus
+                    = mDrmManagerClient.convertData(convertId, inputData);
+                mDrmManagerClient.closeConvertSession(convertId);
+            }
         }
     }
 
diff --git a/tests/tests/graphics/src/android/graphics/cts/PaintFlagsDrawFilterTest.java b/tests/tests/graphics/src/android/graphics/cts/PaintFlagsDrawFilterTest.java
index 31dbf16..ee3ec7c 100644
--- a/tests/tests/graphics/src/android/graphics/cts/PaintFlagsDrawFilterTest.java
+++ b/tests/tests/graphics/src/android/graphics/cts/PaintFlagsDrawFilterTest.java
@@ -107,4 +107,82 @@
         // underline is under the text or at least at the bottom of it
         assertTrue(rect.top >= TEXT_Y);
     }
+
+    // Tests that FILTER_BITMAP_FLAG is handled properly.
+    public void testPaintFlagsDrawFilter2() {
+        // Create a bitmap with alternating black and white pixels.
+        int kWidth = 5;
+        int kHeight = 5;
+        int colors[] = new int [] { Color.WHITE, Color.BLACK };
+        int k = 0;
+        Bitmap grid = Bitmap.createBitmap(kWidth, kHeight, Config.ARGB_8888);
+        for (int i = 0; i < kWidth; ++i) {
+            for (int j = 0; j < kHeight; ++j) {
+                grid.setPixel(i, j, colors[k]);
+                k = (k + 1) % 2;
+            }
+        }
+
+        // Setup a scaled canvas for drawing the bitmap, with and without FILTER_BITMAP_FLAG set.
+        // When the flag is set, there will be gray pixels. When the flag is not set, all pixels
+        // will be either black or white.
+        int kScale = 5;
+        Bitmap dst = Bitmap.createBitmap(kWidth * kScale, kHeight * kScale, Config.ARGB_8888);
+        Canvas canvas = new Canvas(dst);
+        canvas.scale(kScale, kScale);
+
+        // Drawn without FILTER_BITMAP_FLAG, all pixels will be black or white.
+        Paint simplePaint = new Paint();
+        canvas.drawBitmap(grid, 0, 0, simplePaint);
+
+        assertContainsOnlyBlackAndWhite(dst);
+
+        // Drawn with FILTER_BITMAP_FLAG, some pixels will be somewhere in between.
+        Paint filterBitmapPaint = new Paint(Paint.FILTER_BITMAP_FLAG);
+        canvas.drawBitmap(grid, 0, 0, filterBitmapPaint);
+
+        assertContainsNonBW(dst);
+
+        // Drawing with a paint that FILTER_BITMAP_FLAG set and a DrawFilter that removes
+        // FILTER_BITMAP_FLAG should remove the effect of the flag, resulting in all pixels being
+        // either black or white.
+        canvas.setDrawFilter(new PaintFlagsDrawFilter(Paint.FILTER_BITMAP_FLAG, 0));
+        canvas.drawBitmap(grid, 0, 0, filterBitmapPaint);
+
+        assertContainsOnlyBlackAndWhite(dst);
+
+        // Likewise, drawing with a DrawFilter that sets FILTER_BITMAP_FLAG should filter,
+        // resulting in gray pixels.
+        canvas.setDrawFilter(new PaintFlagsDrawFilter(0, Paint.FILTER_BITMAP_FLAG));
+        canvas.drawBitmap(grid, 0, 0, simplePaint);
+
+        assertContainsNonBW(dst);
+    }
+
+    // Assert that at least one pixel is neither black nor white. This is used to verify that
+    // filtering was done, since the original bitmap only contained black and white pixels.
+    private void assertContainsNonBW(Bitmap bitmap) {
+        for (int i = 0; i < bitmap.getWidth(); ++i) {
+            for (int j = 0; j < bitmap.getHeight(); ++j) {
+                int color = bitmap.getPixel(i, j);
+                if (color != Color.BLACK && color != Color.WHITE) {
+                    // Filtering must have been done.
+                    return;
+                }
+            }
+        }
+        // Filtering did not happen.
+        assertTrue(false);
+    }
+
+    // Assert that every pixel is either black or white. Used to verify that no filtering was
+    // done, since the original bitmap contained only black and white pixels.
+    private void assertContainsOnlyBlackAndWhite(Bitmap bitmap) {
+        for (int i = 0; i < bitmap.getWidth(); ++i) {
+            for (int j = 0; j < bitmap.getHeight(); ++j) {
+                int color = bitmap.getPixel(i, j);
+                assertTrue(color == Color.BLACK || color == Color.WHITE);
+            }
+        }
+    }
 }
diff --git a/tests/tests/hardware/src/android/hardware/camera2/cts/CameraCharacteristicsTest.java b/tests/tests/hardware/src/android/hardware/camera2/cts/CameraCharacteristicsTest.java
index 1fcd385..ac5c889 100644
--- a/tests/tests/hardware/src/android/hardware/camera2/cts/CameraCharacteristicsTest.java
+++ b/tests/tests/hardware/src/android/hardware/camera2/cts/CameraCharacteristicsTest.java
@@ -27,7 +27,7 @@
 import android.content.Context;
 import android.hardware.camera2.CameraCharacteristics;
 import android.hardware.camera2.CameraManager;
-import android.hardware.camera2.CameraMetadata.Key;
+import android.hardware.camera2.CameraCharacteristics.Key;
 import android.test.AndroidTestCase;
 import android.util.Log;
 
@@ -797,6 +797,29 @@
         }
     }
 
+    public void testCameraCharacteristicsAndroidScalerCroppingType() throws Exception {
+        String[] ids = mCameraManager.getCameraIdList();
+        for (int i = 0; i < ids.length; i++) {
+            CameraCharacteristics props = mCameraManager.getCameraCharacteristics(ids[i]);
+            assertNotNull(String.format("Can't get camera characteristics from: ID %s", ids[i]),
+                                        props);
+
+            {
+
+                assertNotNull("Invalid property: android.scaler.croppingType",
+                        props.get(CameraCharacteristics.SCALER_CROPPING_TYPE));
+
+                List<Key<?>> allKeys = props.getKeys();
+                assertNotNull(String.format("Can't get camera characteristics keys from: ID %s",
+                        ids[i], props));
+                assertTrue("Key not in keys list: android.scaler.croppingType", allKeys.contains(
+                        CameraCharacteristics.SCALER_CROPPING_TYPE));
+
+            }
+
+        }
+    }
+
     public void testCameraCharacteristicsAndroidSensorReferenceIlluminant1() throws Exception {
         String[] ids = mCameraManager.getCameraIdList();
         for (int i = 0; i < ids.length; i++) {
@@ -1005,33 +1028,6 @@
         }
     }
 
-    public void testCameraCharacteristicsAndroidSensorBaseGainFactor() throws Exception {
-        String[] ids = mCameraManager.getCameraIdList();
-        for (int i = 0; i < ids.length; i++) {
-            CameraCharacteristics props = mCameraManager.getCameraCharacteristics(ids[i]);
-            assertNotNull(String.format("Can't get camera characteristics from: ID %s", ids[i]),
-                                        props);
-
-            Integer hwLevel = props.get(CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL);
-            assertNotNull("No hardware level reported! android.info.supportedHardwareLevel",
-                    hwLevel);
-            if (hwLevel == CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL_FULL)
-            {
-
-                assertNotNull("Invalid property: android.sensor.baseGainFactor",
-                        props.get(CameraCharacteristics.SENSOR_BASE_GAIN_FACTOR));
-
-                List<Key<?>> allKeys = props.getKeys();
-                assertNotNull(String.format("Can't get camera characteristics keys from: ID %s",
-                        ids[i], props));
-                assertTrue("Key not in keys list: android.sensor.baseGainFactor", allKeys.contains(
-                        CameraCharacteristics.SENSOR_BASE_GAIN_FACTOR));
-
-            }
-
-        }
-    }
-
     public void testCameraCharacteristicsAndroidSensorBlackLevelPattern() throws Exception {
         String[] ids = mCameraManager.getCameraIdList();
         for (int i = 0; i < ids.length; i++) {
diff --git a/tests/tests/hardware/src/android/hardware/camera2/cts/CameraDeviceTest.java b/tests/tests/hardware/src/android/hardware/camera2/cts/CameraDeviceTest.java
index 55cd5d2..6c75790 100644
--- a/tests/tests/hardware/src/android/hardware/camera2/cts/CameraDeviceTest.java
+++ b/tests/tests/hardware/src/android/hardware/camera2/cts/CameraDeviceTest.java
@@ -19,14 +19,12 @@
 import static android.hardware.camera2.cts.CameraTestUtils.*;
 import static com.android.ex.camera2.blocking.BlockingStateListener.*;
 import static org.mockito.Mockito.*;
-import static android.hardware.camera2.CameraMetadata.*;
 import static android.hardware.camera2.CaptureRequest.*;
 
 import android.content.Context;
 import android.graphics.ImageFormat;
 import android.hardware.camera2.CameraCharacteristics;
 import android.hardware.camera2.CameraDevice;
-import android.hardware.camera2.CameraMetadata;
 import android.hardware.camera2.CaptureFailure;
 import android.hardware.camera2.CaptureRequest;
 import android.hardware.camera2.CaptureResult;
@@ -439,15 +437,15 @@
         }
     }
 
-    private class IsCameraMetadataNotEmpty<T extends CameraMetadata>
-            extends ArgumentMatcher<T> {
+    private class IsCaptureResultNotEmpty
+            extends ArgumentMatcher<CaptureResult> {
         @Override
         public boolean matches(Object obj) {
             /**
              * Do the simple verification here. Only verify the timestamp for now.
              * TODO: verify more required capture result metadata fields.
              */
-            CameraMetadata result = (CameraMetadata) obj;
+            CaptureResult result = (CaptureResult) obj;
             Long timeStamp = result.get(CaptureResult.SENSOR_TIMESTAMP);
             if (timeStamp != null && timeStamp.longValue() > 0L) {
                 return true;
@@ -621,12 +619,12 @@
                         .onCaptureCompleted(
                                 eq(mCamera),
                                 isA(CaptureRequest.class),
-                                argThat(new IsCameraMetadataNotEmpty<CaptureResult>()));
+                                argThat(new IsCaptureResultNotEmpty()));
         // Should not receive any capture failed callbacks.
         verify(mockListener, never())
                         .onCaptureFailed(
                                 eq(mCamera),
-                                argThat(new IsCameraMetadataNotEmpty<CaptureRequest>()),
+                                isA(CaptureRequest.class),
                                 isA(CaptureFailure.class));
         // Should receive expected number of capture shutter calls
         verify(mockListener,
@@ -640,7 +638,7 @@
 
     private void checkFpsRange(CaptureRequest.Builder request, int template,
             CameraCharacteristics props) {
-        Key<int[]> fpsRangeKey = CONTROL_AE_TARGET_FPS_RANGE;
+        CaptureRequest.Key<int[]> fpsRangeKey = CONTROL_AE_TARGET_FPS_RANGE;
         int[] fpsRange;
         if ((fpsRange = mCollector.expectKeyValueNotNull(request, fpsRangeKey)) == null) {
             return;
@@ -700,15 +698,15 @@
             return;
         }
 
-        int targetAfMode = CONTROL_AF_MODE_AUTO;
+        int targetAfMode = CaptureRequest.CONTROL_AF_MODE_AUTO;
         byte[] availableAfMode = props.get(CameraCharacteristics.CONTROL_AF_AVAILABLE_MODES);
         if (template == CameraDevice.TEMPLATE_PREVIEW ||
                 template == CameraDevice.TEMPLATE_STILL_CAPTURE ||
                 template == CameraDevice.TEMPLATE_ZERO_SHUTTER_LAG) {
             // Default to CONTINUOUS_PICTURE if it is available, otherwise AUTO.
             for (int i = 0; i < availableAfMode.length; i++) {
-                if (availableAfMode[i] == CONTROL_AF_MODE_CONTINUOUS_PICTURE) {
-                    targetAfMode = CONTROL_AF_MODE_CONTINUOUS_PICTURE;
+                if (availableAfMode[i] == CaptureRequest.CONTROL_AF_MODE_CONTINUOUS_PICTURE) {
+                    targetAfMode = CaptureRequest.CONTROL_AF_MODE_CONTINUOUS_PICTURE;
                     break;
                 }
             }
@@ -716,13 +714,13 @@
                 template == CameraDevice.TEMPLATE_VIDEO_SNAPSHOT) {
             // Default to CONTINUOUS_VIDEO if it is available, otherwise AUTO.
             for (int i = 0; i < availableAfMode.length; i++) {
-                if (availableAfMode[i] == CONTROL_AF_MODE_CONTINUOUS_VIDEO) {
-                    targetAfMode = CONTROL_AF_MODE_CONTINUOUS_VIDEO;
+                if (availableAfMode[i] == CaptureRequest.CONTROL_AF_MODE_CONTINUOUS_VIDEO) {
+                    targetAfMode = CaptureRequest.CONTROL_AF_MODE_CONTINUOUS_VIDEO;
                     break;
                 }
             }
         } else if (template == CameraDevice.TEMPLATE_MANUAL) {
-            targetAfMode = CONTROL_AF_MODE_OFF;
+            targetAfMode = CaptureRequest.CONTROL_AF_MODE_OFF;
         }
 
         mCollector.expectKeyValueEquals(request, CONTROL_AF_MODE, targetAfMode);
@@ -743,7 +741,8 @@
             CameraCharacteristics props) {
         // 3A settings--control.mode.
         if (template != CameraDevice.TEMPLATE_MANUAL) {
-            mCollector.expectKeyValueEquals(request, CONTROL_MODE, CONTROL_MODE_AUTO);
+            mCollector
+                    .expectKeyValueEquals(request, CONTROL_MODE, CaptureRequest.CONTROL_MODE_AUTO);
         }
 
         // 3A settings--AE/AWB/AF.
@@ -751,22 +750,27 @@
         checkAfMode(request, template, props);
         checkFpsRange(request, template, props);
         if (template == CameraDevice.TEMPLATE_MANUAL) {
-            mCollector.expectKeyValueEquals(request, CONTROL_MODE, CONTROL_MODE_OFF);
-            mCollector.expectKeyValueEquals(request, CONTROL_AE_MODE, CONTROL_AE_MODE_OFF);
-            mCollector.expectKeyValueEquals(request, CONTROL_AWB_MODE, CONTROL_AWB_MODE_OFF);
+            mCollector.expectKeyValueEquals(request, CONTROL_MODE, CaptureRequest.CONTROL_MODE_OFF);
+            mCollector.expectKeyValueEquals(request, CONTROL_AE_MODE,
+                    CaptureRequest.CONTROL_AE_MODE_OFF);
+            mCollector.expectKeyValueEquals(request, CONTROL_AWB_MODE,
+                    CaptureRequest.CONTROL_AWB_MODE_OFF);
 
         } else {
-            mCollector.expectKeyValueEquals(request, CONTROL_AE_MODE, CONTROL_AE_MODE_ON);
+            mCollector.expectKeyValueEquals(request, CONTROL_AE_MODE,
+                    CaptureRequest.CONTROL_AE_MODE_ON);
             mCollector.expectKeyValueNotEquals(request, CONTROL_AE_ANTIBANDING_MODE,
-                    CONTROL_AE_ANTIBANDING_MODE_OFF);
+                    CaptureRequest.CONTROL_AE_ANTIBANDING_MODE_OFF);
             mCollector.expectKeyValueEquals(request, CONTROL_AE_EXPOSURE_COMPENSATION, 0);
             mCollector.expectKeyValueEquals(request, CONTROL_AE_LOCK, false);
             mCollector.expectKeyValueEquals(request, CONTROL_AE_PRECAPTURE_TRIGGER,
-                    CONTROL_AE_PRECAPTURE_TRIGGER_IDLE);
+                    CaptureRequest.CONTROL_AE_PRECAPTURE_TRIGGER_IDLE);
 
-            mCollector.expectKeyValueEquals(request, CONTROL_AF_TRIGGER, CONTROL_AF_TRIGGER_IDLE);
+            mCollector.expectKeyValueEquals(request, CONTROL_AF_TRIGGER,
+                    CaptureRequest.CONTROL_AF_TRIGGER_IDLE);
 
-            mCollector.expectKeyValueEquals(request, CONTROL_AWB_MODE, CONTROL_AWB_MODE_AUTO);
+            mCollector.expectKeyValueEquals(request, CONTROL_AWB_MODE,
+                    CaptureRequest.CONTROL_AWB_MODE_AUTO);
             mCollector.expectKeyValueEquals(request, CONTROL_AWB_LOCK, false);
 
             // Check 3A regions.
@@ -816,51 +820,61 @@
 
         // ISP-processing settings.
         mCollector.expectKeyValueEquals(
-                request, STATISTICS_FACE_DETECT_MODE, STATISTICS_FACE_DETECT_MODE_OFF);
-        mCollector.expectKeyValueEquals(request, FLASH_MODE, FLASH_MODE_OFF);
+                request, STATISTICS_FACE_DETECT_MODE,
+                CaptureRequest.STATISTICS_FACE_DETECT_MODE_OFF);
+        mCollector.expectKeyValueEquals(request, FLASH_MODE, CaptureRequest.FLASH_MODE_OFF);
         mCollector.expectKeyValueEquals(
-                request, STATISTICS_LENS_SHADING_MAP_MODE, STATISTICS_LENS_SHADING_MAP_MODE_OFF);
+                request, STATISTICS_LENS_SHADING_MAP_MODE,
+                CaptureRequest.STATISTICS_LENS_SHADING_MAP_MODE_OFF);
 
         if (template == CameraDevice.TEMPLATE_STILL_CAPTURE) {
             // Not enforce high quality here, as some devices may not effectively have high quality
             // mode.
             mCollector.expectKeyValueNotEquals(
-                    request, COLOR_CORRECTION_MODE, COLOR_CORRECTION_MODE_TRANSFORM_MATRIX);
+                    request, COLOR_CORRECTION_MODE,
+                    CaptureRequest.COLOR_CORRECTION_MODE_TRANSFORM_MATRIX);
 
             List<Byte> availableEdgeModes =
                     Arrays.asList(toObject(mStaticInfo.getAvailableEdgeModesChecked()));
-            if (availableEdgeModes.contains((byte)EDGE_MODE_HIGH_QUALITY)) {
-                mCollector.expectKeyValueEquals(request, EDGE_MODE, EDGE_MODE_HIGH_QUALITY);
-            } else if (availableEdgeModes.contains((byte)EDGE_MODE_FAST)) {
-                mCollector.expectKeyValueEquals(request, EDGE_MODE, EDGE_MODE_FAST);
+            if (availableEdgeModes.contains((byte) CaptureRequest.EDGE_MODE_HIGH_QUALITY)) {
+                mCollector.expectKeyValueEquals(request, EDGE_MODE,
+                        CaptureRequest.EDGE_MODE_HIGH_QUALITY);
+            } else if (availableEdgeModes.contains((byte) CaptureRequest.EDGE_MODE_FAST)) {
+                mCollector.expectKeyValueEquals(request, EDGE_MODE, CaptureRequest.EDGE_MODE_FAST);
             } else {
-                mCollector.expectKeyValueEquals(request, EDGE_MODE, EDGE_MODE_OFF);
+                mCollector.expectKeyValueEquals(request, EDGE_MODE, CaptureRequest.EDGE_MODE_OFF);
             }
 
             List<Byte> availableNoiseReductionModes =
                     Arrays.asList(toObject(mStaticInfo.getAvailableNoiseReductionModesChecked()));
-            if (availableNoiseReductionModes.contains((byte)NOISE_REDUCTION_MODE_HIGH_QUALITY)) {
+            if (availableNoiseReductionModes
+                    .contains((byte) CaptureRequest.NOISE_REDUCTION_MODE_HIGH_QUALITY)) {
                 mCollector.expectKeyValueEquals(
-                        request, NOISE_REDUCTION_MODE, NOISE_REDUCTION_MODE_HIGH_QUALITY);
-            } else if (availableNoiseReductionModes.contains((byte)NOISE_REDUCTION_MODE_FAST)) {
+                        request, NOISE_REDUCTION_MODE,
+                        CaptureRequest.NOISE_REDUCTION_MODE_HIGH_QUALITY);
+            } else if (availableNoiseReductionModes
+                    .contains((byte) CaptureRequest.NOISE_REDUCTION_MODE_FAST)) {
                 mCollector.expectKeyValueEquals(
-                        request, NOISE_REDUCTION_MODE, NOISE_REDUCTION_MODE_FAST);
+                        request, NOISE_REDUCTION_MODE, CaptureRequest.NOISE_REDUCTION_MODE_FAST);
             } else {
                 mCollector.expectKeyValueEquals(
-                        request, NOISE_REDUCTION_MODE, NOISE_REDUCTION_MODE_OFF);
+                        request, NOISE_REDUCTION_MODE, CaptureRequest.NOISE_REDUCTION_MODE_OFF);
             }
 
             List<Byte> availableToneMapModes =
                     Arrays.asList(toObject(mStaticInfo.getAvailableToneMapModesChecked()));
-            if (availableToneMapModes.contains((byte)TONEMAP_MODE_HIGH_QUALITY)) {
-                mCollector.expectKeyValueEquals(request, TONEMAP_MODE, TONEMAP_MODE_HIGH_QUALITY);
+            if (availableToneMapModes.contains((byte) CaptureRequest.TONEMAP_MODE_HIGH_QUALITY)) {
+                mCollector.expectKeyValueEquals(request, TONEMAP_MODE,
+                        CaptureRequest.TONEMAP_MODE_HIGH_QUALITY);
             } else {
-                mCollector.expectKeyValueEquals(request, TONEMAP_MODE, TONEMAP_MODE_FAST);
+                mCollector.expectKeyValueEquals(request, TONEMAP_MODE,
+                        CaptureRequest.TONEMAP_MODE_FAST);
             }
         } else {
             mCollector.expectKeyValueNotNull(request, EDGE_MODE);
             mCollector.expectKeyValueNotNull(request, NOISE_REDUCTION_MODE);
-            mCollector.expectKeyValueNotEquals(request, TONEMAP_MODE, TONEMAP_MODE_CONTRAST_CURVE);
+            mCollector.expectKeyValueNotEquals(request, TONEMAP_MODE,
+                    CaptureRequest.TONEMAP_MODE_CONTRAST_CURVE);
         }
 
         mCollector.expectKeyValueEquals(request, CONTROL_CAPTURE_INTENT, template);
diff --git a/tests/tests/hardware/src/android/hardware/camera2/cts/CameraTestUtils.java b/tests/tests/hardware/src/android/hardware/camera2/cts/CameraTestUtils.java
index 87d3874..850456d 100644
--- a/tests/tests/hardware/src/android/hardware/camera2/cts/CameraTestUtils.java
+++ b/tests/tests/hardware/src/android/hardware/camera2/cts/CameraTestUtils.java
@@ -25,13 +25,11 @@
 import android.hardware.camera2.CameraAccessException;
 import android.hardware.camera2.CameraDevice;
 import android.hardware.camera2.CameraManager;
-import android.hardware.camera2.CameraMetadata;
 import android.hardware.camera2.CameraCharacteristics;
 import android.hardware.camera2.CaptureFailure;
 import android.hardware.camera2.CaptureRequest;
 import android.hardware.camera2.CaptureResult;
 import android.util.Size;
-import android.hardware.camera2.CameraMetadata.Key;
 import android.hardware.camera2.params.StreamConfigurationMap;
 import android.media.Image;
 import android.media.ImageReader;
@@ -800,7 +798,7 @@
         return;
     }
 
-    public static <T> T getValueNotNull(CaptureResult result, Key<T> key) {
+    public static <T> T getValueNotNull(CaptureResult result, CaptureResult.Key<T> key) {
         if (result == null) {
             throw new IllegalArgumentException("Result must not be null");
         }
diff --git a/tests/tests/hardware/src/android/hardware/camera2/cts/CaptureRequestTest.java b/tests/tests/hardware/src/android/hardware/camera2/cts/CaptureRequestTest.java
index 85306ba..add91a4 100644
--- a/tests/tests/hardware/src/android/hardware/camera2/cts/CaptureRequestTest.java
+++ b/tests/tests/hardware/src/android/hardware/camera2/cts/CaptureRequestTest.java
@@ -25,7 +25,6 @@
 import android.hardware.camera2.CameraCharacteristics;
 import android.hardware.camera2.CameraDevice;
 import android.hardware.camera2.CameraMetadata;
-import android.hardware.camera2.CameraMetadata.Key;
 import android.hardware.camera2.CaptureRequest;
 import android.hardware.camera2.CaptureResult;
 import android.hardware.camera2.cts.CameraTestUtils.SimpleCaptureListener;
@@ -863,7 +862,7 @@
 
         for (int i = 0; i < numFramesVerified; i++) {
             CaptureResult result = listener.getCaptureResult(WAIT_FOR_RESULT_TIMEOUT_MS);
-            Long resultExpTime = result.get(CaptureRequest.SENSOR_EXPOSURE_TIME);
+            Long resultExpTime = result.get(CaptureResult.SENSOR_EXPOSURE_TIME);
             assertNotNull("Exposure time shouldn't be null", resultExpTime);
             Integer flicker = result.get(CaptureResult.STATISTICS_SCENE_FLICKER);
             // Scene flicker result should be always available.
@@ -1335,7 +1334,7 @@
         for (int i = 0; i < numFramesVerified; i++) {
             CaptureResult result = listener.getCaptureResult(WAIT_FOR_RESULT_TIMEOUT_MS);
             mCollector.expectEquals("Capture result tonemap mode should match request", tonemapMode,
-                    result.get(CaptureRequest.TONEMAP_MODE));
+                    result.get(CaptureResult.TONEMAP_MODE));
             float[] mapRed = result.get(CaptureResult.TONEMAP_CURVE_RED);
             float[] mapGreen = result.get(CaptureResult.TONEMAP_CURVE_GREEN);
             float[] mapBlue = result.get(CaptureResult.TONEMAP_CURVE_BLUE);
@@ -1461,8 +1460,8 @@
                     NUM_FRAMES_VERIFIED);
 
             // Verify AF can finish a scan for CONTROL_AF_MODE_CONTINUOUS_* modes
-            if ((int)mode == CaptureRequest.CONTROL_AF_MODE_CONTINUOUS_PICTURE ||
-                    (int)mode == CaptureRequest.CONTROL_AF_MODE_CONTINUOUS_VIDEO) {
+            if (mode == CaptureRequest.CONTROL_AF_MODE_CONTINUOUS_PICTURE ||
+                    mode == CaptureRequest.CONTROL_AF_MODE_CONTINUOUS_VIDEO) {
                 List<Integer> afStateList = new ArrayList<Integer>();
                 afStateList.add(CaptureResult.CONTROL_AF_STATE_PASSIVE_FOCUSED);
                 afStateList.add(CaptureResult.CONTROL_AF_STATE_PASSIVE_UNFOCUSED);
@@ -1498,9 +1497,9 @@
 
         for (int mode : opticalStabModes) {
             listener = new SimpleCaptureListener();
-            requestBuilder.set(CaptureRequest.LENS_OPTICAL_STABILIZATION_MODE, (int) mode);
+            requestBuilder.set(CaptureRequest.LENS_OPTICAL_STABILIZATION_MODE, mode);
             mCamera.setRepeatingRequest(requestBuilder.build(), listener, mHandler);
-            verifyCaptureResultForKey(CaptureResult.LENS_OPTICAL_STABILIZATION_MODE, (int)mode,
+            verifyCaptureResultForKey(CaptureResult.LENS_OPTICAL_STABILIZATION_MODE, mode,
                     listener, NUM_FRAMES_VERIFIED);
         }
 
@@ -1655,16 +1654,6 @@
     }
 
     /**
-     * Enable exposure manual control and change sensitivity and
-     * clamp the value into the supported range.
-     *
-     * <p>The exposure time is set to default value.</p>
-     */
-    private void changeExposure(CaptureRequest.Builder requestBuilder, int sensitivity) {
-        changeExposure(requestBuilder, DEFAULT_EXP_TIME_NS, sensitivity);
-    }
-
-    /**
      * Get the exposure time array that contains multiple exposure time steps in
      * the exposure time range.
      */
@@ -1783,7 +1772,7 @@
         validatePipelineDepth(result);
     }
 
-    private <T> T getValueNotNull(CaptureResult result, Key<T> key) {
+    private <T> T getValueNotNull(CaptureResult result, CaptureResult.Key<T> key) {
         T value = result.get(key);
         assertNotNull("Value of Key " + key.getName() + " shouldn't be null", value);
         return value;
@@ -1797,7 +1786,7 @@
      * @param listener The capture listener to get capture results
      * @param numFramesVerified The number of capture results to be verified
      */
-    private <T> void verifyCaptureResultForKey(Key<T> key, T requestMode,
+    private <T> void verifyCaptureResultForKey(CaptureResult.Key<T> key, T requestMode,
             SimpleCaptureListener listener, int numFramesVerified) {
         for (int i = 0; i < numFramesVerified; i++) {
             CaptureResult result = listener.getCaptureResult(WAIT_FOR_RESULT_TIMEOUT_MS);
@@ -1955,13 +1944,13 @@
         {
             switch (algoIdx) {
                 case INDEX_ALGORITHM_AE:
-                    requestBuilder.set(CaptureResult.CONTROL_AE_REGIONS, region);
+                    requestBuilder.set(CaptureRequest.CONTROL_AE_REGIONS, region);
                     break;
                 case INDEX_ALGORITHM_AWB:
-                    requestBuilder.set(CaptureResult.CONTROL_AWB_REGIONS, region);
+                    requestBuilder.set(CaptureRequest.CONTROL_AWB_REGIONS, region);
                     break;
                 case INDEX_ALGORITHM_AF:
-                    requestBuilder.set(CaptureResult.CONTROL_AF_REGIONS, region);
+                    requestBuilder.set(CaptureRequest.CONTROL_AF_REGIONS, region);
                     break;
                 default:
                     throw new IllegalArgumentException("Unknown 3A Algorithm!");
diff --git a/tests/tests/hardware/src/android/hardware/camera2/cts/CaptureResultTest.java b/tests/tests/hardware/src/android/hardware/camera2/cts/CaptureResultTest.java
index fdd0c0b..412a919 100644
--- a/tests/tests/hardware/src/android/hardware/camera2/cts/CaptureResultTest.java
+++ b/tests/tests/hardware/src/android/hardware/camera2/cts/CaptureResultTest.java
@@ -41,7 +41,7 @@
     private static final long WAIT_FOR_RESULT_TIMEOUT_MS = 3000;
 
     // List that includes all public keys from CaptureResult
-    List<CameraMetadata.Key<?>> mAllKeys;
+    List<CaptureResult.Key<?>> mAllKeys;
 
     // List tracking the failed test keys.
 
@@ -77,7 +77,7 @@
          * Hardcode a key waiver list for the keys that are allowed to be null.
          * FIXME: We need get ride of this list, see bug 11116270.
          */
-        List<CameraMetadata.Key<?>> waiverkeys = new ArrayList<CameraMetadata.Key<?>>();
+        List<CaptureResult.Key<?>> waiverkeys = new ArrayList<CaptureResult.Key<?>>();
         waiverkeys.add(CaptureResult.JPEG_GPS_COORDINATES);
         waiverkeys.add(CaptureResult.JPEG_GPS_PROCESSING_METHOD);
         waiverkeys.add(CaptureResult.JPEG_GPS_TIMESTAMP);
@@ -85,7 +85,6 @@
         waiverkeys.add(CaptureResult.JPEG_QUALITY);
         waiverkeys.add(CaptureResult.JPEG_THUMBNAIL_QUALITY);
         waiverkeys.add(CaptureResult.JPEG_THUMBNAIL_SIZE);
-        waiverkeys.add(CaptureResult.SENSOR_TEMPERATURE);
 
         for (String id : mCameraIds) {
             try {
@@ -145,13 +144,21 @@
     }
 
     private void validateCaptureResult(SimpleCaptureListener captureListener,
-            List<CameraMetadata.Key<?>> skippedKeys, CaptureRequest.Builder requestBuilder,
+            List<CaptureResult.Key<?>> skippedKeys, CaptureRequest.Builder requestBuilder,
             int numFramesVerified) throws Exception {
         CaptureResult result = null;
         for (int i = 0; i < numFramesVerified; i++) {
             String failMsg = "Failed capture result " + i + " test ";
             result = captureListener.getCaptureResult(WAIT_FOR_RESULT_TIMEOUT_MS);
-            for (CameraMetadata.Key<?> key : mAllKeys) {
+
+            if (VERBOSE) {
+                Log.v(TAG, "Dump result for frame " + i);
+                Log.v(TAG, "------------------------------ (START)");
+                result.dumpToLog();
+                Log.v(TAG, "------------------------------ (END)");
+            }
+
+            for (CaptureResult.Key<?> key : mAllKeys) {
                 if (!skippedKeys.contains(key)) {
                     /**
                      * Check the critical tags here.
@@ -211,8 +218,8 @@
      * modify the comment blocks at the start or end.
      *~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~*/
 
-    private static List<CameraMetadata.Key<?>> getAllCaptureResultKeys() {
-        ArrayList<CameraMetadata.Key<?>> resultKeys = new ArrayList<CameraMetadata.Key<?>>();
+    private static List<CaptureResult.Key<?>> getAllCaptureResultKeys() {
+        ArrayList<CaptureResult.Key<?>> resultKeys = new ArrayList<CaptureResult.Key<?>>();
         resultKeys.add(CaptureResult.COLOR_CORRECTION_MODE);
         resultKeys.add(CaptureResult.COLOR_CORRECTION_TRANSFORM);
         resultKeys.add(CaptureResult.COLOR_CORRECTION_GAINS);
@@ -263,7 +270,6 @@
         resultKeys.add(CaptureResult.SENSOR_FRAME_DURATION);
         resultKeys.add(CaptureResult.SENSOR_SENSITIVITY);
         resultKeys.add(CaptureResult.SENSOR_TIMESTAMP);
-        resultKeys.add(CaptureResult.SENSOR_TEMPERATURE);
         resultKeys.add(CaptureResult.SENSOR_NEUTRAL_COLOR_POINT);
         resultKeys.add(CaptureResult.SENSOR_GREEN_SPLIT);
         resultKeys.add(CaptureResult.SENSOR_TEST_PATTERN_DATA);
@@ -271,6 +277,7 @@
         resultKeys.add(CaptureResult.SHADING_MODE);
         resultKeys.add(CaptureResult.STATISTICS_FACE_DETECT_MODE);
         resultKeys.add(CaptureResult.STATISTICS_HOT_PIXEL_MAP_MODE);
+        resultKeys.add(CaptureResult.STATISTICS_FACES);
         resultKeys.add(CaptureResult.STATISTICS_LENS_SHADING_MAP);
         resultKeys.add(CaptureResult.STATISTICS_SCENE_FLICKER);
         resultKeys.add(CaptureResult.STATISTICS_HOT_PIXEL_MAP);
@@ -281,10 +288,6 @@
         resultKeys.add(CaptureResult.TONEMAP_MODE);
         resultKeys.add(CaptureResult.BLACK_LEVEL_LOCK);
 
-        // Add STATISTICS_FACES key separately here because it is not
-        // defined in metadata xml file.
-        resultKeys.add(CaptureResult.STATISTICS_FACES);
-
         return resultKeys;
     }
 
diff --git a/tests/tests/hardware/src/android/hardware/camera2/cts/StillCaptureTest.java b/tests/tests/hardware/src/android/hardware/camera2/cts/StillCaptureTest.java
index 16fc1c7..9f0af9b 100644
--- a/tests/tests/hardware/src/android/hardware/camera2/cts/StillCaptureTest.java
+++ b/tests/tests/hardware/src/android/hardware/camera2/cts/StillCaptureTest.java
@@ -21,7 +21,6 @@
 import android.graphics.ImageFormat;
 import android.graphics.Rect;
 import android.hardware.camera2.CameraDevice;
-import android.hardware.camera2.CameraMetadata.Key;
 import android.hardware.camera2.CaptureRequest;
 import android.hardware.camera2.CaptureResult;
 import android.util.Size;
@@ -338,7 +337,7 @@
     private void previewPersistenceTestByCamera() throws Exception {
         Size maxStillSz = mOrderedStillSizes.get(0);
         Size maxPreviewSz = mOrderedPreviewSizes.get(0);
-        CaptureResult result;
+
         SimpleCaptureListener resultListener = new SimpleCaptureListener();
         SimpleCaptureListener stillResultListener = new SimpleCaptureListener();
         SimpleImageReaderListener imageListener = new SimpleImageReaderListener();
@@ -355,7 +354,7 @@
         // take a picture
         CaptureRequest request = stillRequest.build();
         mCamera.capture(request, stillResultListener, mHandler);
-        result = stillResultListener.getCaptureResultForRequest(request,
+        stillResultListener.getCaptureResultForRequest(request,
                 WAIT_FOR_RESULT_TIMEOUT_MS);
 
         // validate image
@@ -460,7 +459,7 @@
                 previewRequest.get(CaptureRequest.CONTROL_AWB_MODE),
                 result.get(CaptureResult.CONTROL_AWB_MODE));
         if (canSetAwbRegion) {
-            int[] resultAwbRegions = getValueNotNull(result, CaptureRequest.CONTROL_AWB_REGIONS);
+            int[] resultAwbRegions = getValueNotNull(result, CaptureResult.CONTROL_AWB_REGIONS);
             mCollector.expectEquals("AWB regions in result and request should be same",
                     toObject(awbRegions),
                     toObject(resultAwbRegions));
@@ -487,7 +486,7 @@
                 previewRequest.get(CaptureRequest.CONTROL_AE_MODE),
                 result.get(CaptureResult.CONTROL_AE_MODE));
         if (canSetAeRegion) {
-            int[] resultAeRegions = getValueNotNull(result, CaptureRequest.CONTROL_AE_REGIONS);
+            int[] resultAeRegions = getValueNotNull(result, CaptureResult.CONTROL_AE_REGIONS);
             mCollector.expectEquals("AE regions in result and request should be same",
                     toObject(aeRegions),
                     toObject(resultAeRegions));
@@ -505,7 +504,7 @@
                 stillRequest.get(CaptureRequest.CONTROL_AF_MODE),
                 result.get(CaptureResult.CONTROL_AF_MODE));
         if (canSetAfRegion) {
-            int[] resultAfRegions = getValueNotNull(result, CaptureRequest.CONTROL_AF_REGIONS);
+            int[] resultAfRegions = getValueNotNull(result, CaptureResult.CONTROL_AF_REGIONS);
             mCollector.expectEquals("AF regions in result and request should be same",
                     toObject(afRegions),
                     toObject(resultAfRegions));
@@ -720,7 +719,7 @@
             mCollector.expectEquals("JPEG thumbnail size result and request should match",
                     testThumbnailSizes[i],
                     stillResult.get(CaptureResult.JPEG_THUMBNAIL_SIZE));
-            Key<double[]> gpsCoordsKey = CaptureResult.JPEG_GPS_COORDINATES;
+            CaptureResult.Key<double[]> gpsCoordsKey = CaptureResult.JPEG_GPS_COORDINATES;
             if (mCollector.expectKeyValueNotNull(stillResult, gpsCoordsKey) != null) {
                 mCollector.expectEquals("GPS coordinates result and request should match.",
                         toObject(EXIF_TEST_DATA[i].gpsCoordinates),
diff --git a/tests/tests/hardware/src/android/hardware/camera2/cts/helpers/CameraErrorCollector.java b/tests/tests/hardware/src/android/hardware/camera2/cts/helpers/CameraErrorCollector.java
index 86e264d..689bb0d 100644
--- a/tests/tests/hardware/src/android/hardware/camera2/cts/helpers/CameraErrorCollector.java
+++ b/tests/tests/hardware/src/android/hardware/camera2/cts/helpers/CameraErrorCollector.java
@@ -16,10 +16,10 @@
 
 package android.hardware.camera2.cts.helpers;
 
-import android.hardware.camera2.CameraMetadata.Key;
 import android.hardware.camera2.CaptureRequest;
 import android.hardware.camera2.CaptureRequest.Builder;
 import android.hardware.camera2.CaptureResult;
+import android.util.Log;
 
 import org.hamcrest.CoreMatchers;
 import org.hamcrest.Matcher;
@@ -36,6 +36,10 @@
  * instead of failing the test immediately for each failure.
  */
 public class CameraErrorCollector extends ErrorCollector {
+
+    private static final String TAG = "CameraErrorCollector";
+    private static final boolean LOG_ERRORS = Log.isLoggable(TAG, Log.ERROR);
+
     private String mCameraMsg = "";
 
     @Override
@@ -50,7 +54,7 @@
      * @param message A string containing the failure reason.
      */
     public void addMessage(String message) {
-        super.addError(new Throwable(mCameraMsg + message));
+        addErrorSuper(new Throwable(mCameraMsg + message));
     }
 
     /**
@@ -58,7 +62,12 @@
      */
     @Override
     public void addError(Throwable error) {
-        super.addError(new Throwable(mCameraMsg + error.getMessage(), error));
+        addErrorSuper(new Throwable(mCameraMsg + error.getMessage(), error));
+    }
+
+    private void addErrorSuper(Throwable error) {
+        if (LOG_ERRORS) Log.e(TAG, error.getMessage());
+        super.addError(error);
     }
 
     /**
@@ -297,7 +306,7 @@
      * @param key The {@link CaptureRequest} key to be checked.
      * @return The value of the key.
      */
-    public <T> T expectKeyValueNotNull(Builder request, Key<T> key) {
+    public <T> T expectKeyValueNotNull(Builder request, CaptureRequest.Key<T> key) {
 
         T value = request.get(key);
         if (value == null) {
@@ -314,7 +323,7 @@
      * @param key The {@link CaptureResult} key to be checked.
      * @return The value of the key.
      */
-    public <T> T expectKeyValueNotNull(CaptureResult result, Key<T> key) {
+    public <T> T expectKeyValueNotNull(CaptureResult result, CaptureResult.Key<T> key) {
         return expectKeyValueNotNull("", result, key);
     }
 
@@ -326,7 +335,7 @@
      * @param key The {@link CaptureResult} key to be checked.
      * @return The value of the key.
      */
-    public <T> T expectKeyValueNotNull(String msg, CaptureResult result, Key<T> key) {
+    public <T> T expectKeyValueNotNull(String msg, CaptureResult result, CaptureResult.Key<T> key) {
 
         T value = result.get(key);
         if (value == null) {
@@ -343,7 +352,8 @@
      * @param key The {@link CaptureRequest} key to be checked.
      * @param expected The expected value of the CaptureRequest key.
      */
-    public <T> void expectKeyValueNotEquals(Builder request, Key<T> key, T expected) {
+    public <T> void expectKeyValueNotEquals(
+            Builder request, CaptureRequest.Key<T> key, T expected) {
         if (request == null || key == null || expected == null) {
             throw new IllegalArgumentException("request, key and target shouldn't be null");
         }
@@ -364,7 +374,8 @@
      * @param key The {@link CaptureResult} key to be checked.
      * @param expected The expected value of the CaptureResult key.
      */
-    public <T> void expectKeyValueNotEquals(CaptureResult result, Key<T> key, T expected) {
+    public <T> void expectKeyValueNotEquals(
+            CaptureResult result, CaptureResult.Key<T> key, T expected) {
         if (result == null || key == null || expected == null) {
             throw new IllegalArgumentException("result, key and target shouldn't be null");
         }
@@ -387,7 +398,7 @@
      * @param key The {@link CaptureRequest} key to be checked.
      * @param expected The expected value of the CaptureRequest key.
      */
-    public <T> void expectKeyValueEquals(Builder request, Key<T> key, T expected) {
+    public <T> void expectKeyValueEquals(Builder request, CaptureRequest.Key<T> key, T expected) {
         if (request == null || key == null || expected == null) {
             throw new IllegalArgumentException("request, key and target shouldn't be null");
         }
diff --git a/tests/tests/hardware/src/android/hardware/camera2/cts/helpers/StaticMetadata.java b/tests/tests/hardware/src/android/hardware/camera2/cts/helpers/StaticMetadata.java
index 32693ba..e99d64a 100644
--- a/tests/tests/hardware/src/android/hardware/camera2/cts/helpers/StaticMetadata.java
+++ b/tests/tests/hardware/src/android/hardware/camera2/cts/helpers/StaticMetadata.java
@@ -19,8 +19,8 @@
 import android.graphics.Rect;
 import android.graphics.ImageFormat;
 import android.hardware.camera2.CameraCharacteristics;
+import android.hardware.camera2.CameraCharacteristics.Key;
 import android.hardware.camera2.CameraMetadata;
-import android.hardware.camera2.CameraMetadata.Key;
 import android.util.Size;
 import android.hardware.camera2.cts.CameraTestUtils;
 import android.hardware.camera2.params.StreamConfigurationMap;
@@ -354,7 +354,7 @@
     }
 
     public int[] getAvailableTestPatternModesChecked() {
-        CameraMetadata.Key<int[]> key =
+        Key<int[]> key =
                 CameraCharacteristics.SENSOR_AVAILABLE_TEST_PATTERN_MODES;
         int[] modes = getValueFromKeyNonNull(key);
 
@@ -618,7 +618,7 @@
             return 0;
         }
 
-        CameraMetadata.Key<Integer> key = CameraCharacteristics.SENSOR_MAX_ANALOG_SENSITIVITY;
+        Key<Integer> key = CameraCharacteristics.SENSOR_MAX_ANALOG_SENSITIVITY;
         Integer maxAnalogsensitivity = getValueFromKeyNonNull(key);
         int minSensitivity = getSensitivityMinimumOrDefault();
         int maxSensitivity = getSensitivityMaximumOrDefault();
@@ -647,7 +647,7 @@
      * @return hyperfocalDistance of this device, -1 if this tag is not available.
      */
     public float getHyperfocalDistanceChecked() {
-        CameraMetadata.Key<Float> key = CameraCharacteristics.LENS_INFO_HYPERFOCAL_DISTANCE;
+        Key<Float> key = CameraCharacteristics.LENS_INFO_HYPERFOCAL_DISTANCE;
         Float hyperfocalDistance = getValueFromKeyNonNull(key);
         if (hyperfocalDistance == null) {
             return -1;
@@ -797,7 +797,7 @@
      * @return AE available modes
      */
     public byte[] getAeAvailableModesChecked() {
-        CameraMetadata.Key<byte[]> modesKey = CameraCharacteristics.CONTROL_AE_AVAILABLE_MODES;
+        Key<byte[]> modesKey = CameraCharacteristics.CONTROL_AE_AVAILABLE_MODES;
         byte[] modes = getValueFromKeyNonNull(modesKey);
         if (modes == null) {
             modes = new byte[0];
@@ -813,7 +813,7 @@
                 modeList.contains(CameraMetadata.CONTROL_AE_MODE_ON));
 
         // All camera devices with flash units support ON_AUTO_FLASH and ON_ALWAYS_FLASH
-        CameraMetadata.Key<Boolean> flashKey= CameraCharacteristics.FLASH_INFO_AVAILABLE;
+        Key<Boolean> flashKey= CameraCharacteristics.FLASH_INFO_AVAILABLE;
         Boolean hasFlash = getValueFromKeyNonNull(flashKey);
         if (hasFlash == null) {
             hasFlash = false;
@@ -858,7 +858,7 @@
      * unavailable.
      */
     public byte[] getAwbAvailableModesChecked() {
-        CameraMetadata.Key<byte[]> key =
+        Key<byte[]> key =
                 CameraCharacteristics.CONTROL_AWB_AVAILABLE_MODES;
         byte[] awbModes = getValueFromKeyNonNull(key);
 
@@ -884,7 +884,7 @@
      * unavailable.
      */
     public byte[] getAfAvailableModesChecked() {
-        CameraMetadata.Key<byte[]> key =
+        Key<byte[]> key =
                 CameraCharacteristics.CONTROL_AF_AVAILABLE_MODES;
         byte[] afModes = getValueFromKeyNonNull(key);
 
@@ -944,7 +944,7 @@
      * @return The sizes of the given format, empty array if no available size is found.
      */
     public Size[] getAvailableSizesForFormatChecked(int format, StreamDirection direction) {
-        CameraMetadata.Key<StreamConfigurationMap> key =
+        Key<StreamConfigurationMap> key =
                 CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP;
         StreamConfigurationMap config = getValueFromKeyNonNull(key);
 
@@ -966,6 +966,11 @@
         }
 
         // TODO: Get rid of android.util.Size
+        if (utilSizes == null) {
+            Log.i(TAG, "This camera doesn't support format " + format + " for " + direction);
+            return new Size[0];
+        }
+
         Size[] sizes = new Size[utilSizes.length];
         for (int i = 0; i < utilSizes.length; ++i) {
             sizes[i] = new Size(utilSizes[i].getWidth(), utilSizes[i].getHeight());
@@ -981,7 +986,7 @@
      */
     public int[] getAeAvailableTargetFpsRangesChecked() {
         final int NUM_ELEMENTS_IN_FPS_RANGE = 2;
-        CameraMetadata.Key<int[]> key =
+        Key<int[]> key =
                 CameraCharacteristics.CONTROL_AE_AVAILABLE_TARGET_FPS_RANGES;
         int[] fpsRanges = getValueFromKeyNonNull(key);
 
@@ -1017,7 +1022,7 @@
      * @return 0 if maxFrameDuration is null
      */
     public long getMaxFrameDurationChecked() {
-        CameraMetadata.Key<Long> key =
+        Key<Long> key =
                 CameraCharacteristics.SENSOR_INFO_MAX_FRAME_DURATION;
         Long maxDuration = getValueFromKeyNonNull(key);
 
@@ -1041,7 +1046,7 @@
 
         HashMap<Size, Long> minDurationMap = new HashMap<Size, Long>();
 
-        CameraMetadata.Key<StreamConfigurationMap> key =
+        Key<StreamConfigurationMap> key =
                 CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP;
         StreamConfigurationMap config = getValueFromKeyNonNull(key);
 
@@ -1059,7 +1064,7 @@
     }
 
     public byte[] getAvailableEdgeModesChecked() {
-        CameraMetadata.Key<byte[]> key = CameraCharacteristics.EDGE_AVAILABLE_EDGE_MODES;
+        Key<byte[]> key = CameraCharacteristics.EDGE_AVAILABLE_EDGE_MODES;
         byte[] edgeModes = getValueFromKeyNonNull(key);
 
         if (edgeModes == null) {
@@ -1078,7 +1083,7 @@
     }
 
     public byte[] getAvailableNoiseReductionModesChecked() {
-        CameraMetadata.Key<byte[]> key =
+        Key<byte[]> key =
                 CameraCharacteristics.NOISE_REDUCTION_AVAILABLE_NOISE_REDUCTION_MODES;
         byte[] noiseReductionModes = getValueFromKeyNonNull(key);
 
@@ -1103,7 +1108,7 @@
      * @return default value if the value is null.
      */
     public Rational getAeCompensationStepChecked() {
-        CameraMetadata.Key<Rational> key =
+        Key<Rational> key =
                 CameraCharacteristics.CONTROL_AE_COMPENSATION_STEP;
         Rational compensationStep = getValueFromKeyNonNull(key);
 
@@ -1122,7 +1127,7 @@
      * @return default value if the value is null or malformed.
      */
     public int[] getAeCompensationRangeChecked() {
-        CameraMetadata.Key<int[]> key =
+        Key<int[]> key =
                 CameraCharacteristics.CONTROL_AE_COMPENSATION_RANGE;
         int[] compensationRange = getValueFromKeyNonNull(key);
         float compensationStep = getAeCompensationStepChecked().toFloat();
@@ -1151,7 +1156,7 @@
      * @return available video stabilization modes, empty array if it is unavailable.
      */
     public byte[] getAvailableVideoStabilizationModesChecked() {
-        CameraMetadata.Key<byte[]> key =
+        Key<byte[]> key =
                 CameraCharacteristics.CONTROL_AVAILABLE_VIDEO_STABILIZATION_MODES;
         byte[] modes = getValueFromKeyNonNull(key);
 
@@ -1175,7 +1180,7 @@
      * @return available optical stabilization modes, empty array if it is unavailable.
      */
     public byte[] getAvailableOpticalStabilizationChecked() {
-        CameraMetadata.Key<byte[]> key =
+        Key<byte[]> key =
                 CameraCharacteristics.LENS_INFO_AVAILABLE_OPTICAL_STABILIZATION;
         byte[] modes = getValueFromKeyNonNull(key);
 
@@ -1196,7 +1201,7 @@
      * @return available max digitial zoom, default value (1.0) if it is not available.
      */
     public float getAvailableMaxDigitalZoomChecked() {
-        CameraMetadata.Key<Float> key =
+        Key<Float> key =
                 CameraCharacteristics.SCALER_AVAILABLE_MAX_DIGITAL_ZOOM;
         Float maxZoom = getValueFromKeyNonNull(key);
         if (maxZoom == null) {
@@ -1210,7 +1215,7 @@
     }
 
     public byte[] getAvailableSceneModesChecked() {
-        CameraMetadata.Key<byte[]> key =
+        Key<byte[]> key =
                 CameraCharacteristics.CONTROL_AVAILABLE_SCENE_MODES;
         byte[] modes = getValueFromKeyNonNull(key);
 
@@ -1229,7 +1234,7 @@
     }
 
     public byte[] getAvailableEffectModesChecked() {
-        CameraMetadata.Key<byte[]> key =
+        Key<byte[]> key =
                 CameraCharacteristics.CONTROL_AVAILABLE_EFFECTS;
         byte[] modes = getValueFromKeyNonNull(key);
 
@@ -1251,7 +1256,7 @@
      * @return max pipeline depth, default value if it is not available.
      */
     public byte getPipelineMaxDepthChecked() {
-        CameraMetadata.Key<Byte> key =
+        Key<Byte> key =
                 CameraCharacteristics.REQUEST_PIPELINE_MAX_DEPTH;
         Byte maxDepth = getValueFromKeyNonNull(key);
 
diff --git a/tests/tests/hardware/src/android/hardware/camera2/cts/testcases/Camera2SurfaceViewTestCase.java b/tests/tests/hardware/src/android/hardware/camera2/cts/testcases/Camera2SurfaceViewTestCase.java
index 7804009..7470f248 100644
--- a/tests/tests/hardware/src/android/hardware/camera2/cts/testcases/Camera2SurfaceViewTestCase.java
+++ b/tests/tests/hardware/src/android/hardware/camera2/cts/testcases/Camera2SurfaceViewTestCase.java
@@ -34,7 +34,6 @@
 import android.hardware.camera2.CameraAccessException;
 import android.hardware.camera2.CameraDevice;
 import android.hardware.camera2.CameraManager;
-import android.hardware.camera2.CameraMetadata.Key;
 import android.hardware.camera2.CaptureRequest;
 import android.hardware.camera2.CaptureResult;
 import android.util.Size;
@@ -282,7 +281,8 @@
      * seen before the result matching myRequest arrives, or each individual wait
      * for result times out after {@value #WAIT_FOR_RESULT_TIMEOUT_MS}ms.
      */
-    protected static <T> void waitForResultValue(SimpleCaptureListener listener, Key<T> resultKey,
+    protected static <T> void waitForResultValue(SimpleCaptureListener listener,
+            CaptureResult.Key<T> resultKey,
             T expectedValue, int numResultsWait) {
         List<T> expectedValues = new ArrayList<T>();
         expectedValues.add(expectedValue);
@@ -305,7 +305,8 @@
      * seen before the result matching myRequest arrives, or each individual wait
      * for result times out after {@value #WAIT_FOR_RESULT_TIMEOUT_MS}ms.
      */
-    protected static <T> void waitForAnyResultValue(SimpleCaptureListener listener, Key<T> resultKey,
+    protected static <T> void waitForAnyResultValue(SimpleCaptureListener listener,
+            CaptureResult.Key<T> resultKey,
             List<T> expectedValues, int numResultsWait) {
         if (numResultsWait < 0 || listener == null || expectedValues == null) {
             throw new IllegalArgumentException(
diff --git a/tests/tests/hardware/src/android/hardware/consumerir/cts/ConsumerIrTest.java b/tests/tests/hardware/src/android/hardware/consumerir/cts/ConsumerIrTest.java
index 395a69b..e06adac 100644
--- a/tests/tests/hardware/src/android/hardware/consumerir/cts/ConsumerIrTest.java
+++ b/tests/tests/hardware/src/android/hardware/consumerir/cts/ConsumerIrTest.java
@@ -77,12 +77,12 @@
 
         ConsumerIrManager.CarrierFrequencyRange[] freqs = mCIR.getCarrierFrequencies();
         // Transmit two seconds for min and max for each frequency range
-        int[] pattern = {1111, 2222, 3333, 4444, 5555, 6666, 7777, 8888, 9999};
-        long totalXmitTime = 0; // get the length of the pattern
+        int[] pattern = {11111, 22222, 33333, 44444, 55555, 66666, 77777, 88888, 99999};
+        long totalXmitTimeNanos = 0; // get the length of the pattern
         for (int slice : pattern) {
-            totalXmitTime += slice;
+            totalXmitTimeNanos += slice * 1000; // add the time in nanoseconds
         }
-        double margin = 0.1; // max fraction xmit is allowed to be off timing
+        double margin = 0.5; // max fraction xmit is allowed to be off timing
 
         for (ConsumerIrManager.CarrierFrequencyRange range : freqs) {
             // test min freq
@@ -90,18 +90,18 @@
             mCIR.transmit(range.getMinFrequency(), pattern);
             long newTime = SystemClock.elapsedRealtimeNanos();
             String msg = String.format("Pattern length pattern:%d, actual:%d",
-                    totalXmitTime, newTime - currentTime);
-            assertTrue(msg, newTime - currentTime >= totalXmitTime * (1.0 - margin));
-            assertTrue(msg, newTime - currentTime <= totalXmitTime * (1.0 + margin));
+                    totalXmitTimeNanos, newTime - currentTime);
+            assertTrue(msg, newTime - currentTime >= totalXmitTimeNanos * (1.0 - margin));
+            assertTrue(msg, newTime - currentTime <= totalXmitTimeNanos * (1.0 + margin));
 
             // test max freq
             currentTime = SystemClock.elapsedRealtimeNanos();
             mCIR.transmit(range.getMaxFrequency(), pattern);
             newTime = SystemClock.elapsedRealtimeNanos();
             msg = String.format("Pattern length pattern:%d, actual:%d",
-                    totalXmitTime, newTime - currentTime);
-            assertTrue(msg, newTime - currentTime >= totalXmitTime * (1.0 - margin));
-            assertTrue(msg, newTime - currentTime <= totalXmitTime * (1.0 + margin));
+                    totalXmitTimeNanos, newTime - currentTime);
+            assertTrue(msg, newTime - currentTime >= totalXmitTimeNanos * (1.0 - margin));
+            assertTrue(msg, newTime - currentTime <= totalXmitTimeNanos * (1.0 + margin));
         }
     }
 
diff --git a/tests/tests/location/src/android/location/cts/LocationManagerTest.java b/tests/tests/location/src/android/location/cts/LocationManagerTest.java
index 34bc0e4..ab11b3c 100644
--- a/tests/tests/location/src/android/location/cts/LocationManagerTest.java
+++ b/tests/tests/location/src/android/location/cts/LocationManagerTest.java
@@ -267,40 +267,66 @@
      */
     public void testModeAndProviderApisConsistent() {
         ContentResolver cr = mContext.getContentResolver();
+
+        // Find out what the settings say about which providers are enabled
         int mode = Settings.Secure.getInt(
                 cr, Settings.Secure.LOCATION_MODE, Settings.Secure.LOCATION_MODE_OFF);
         boolean gps = Settings.Secure.isLocationProviderEnabled(cr, LocationManager.GPS_PROVIDER);
         boolean nlp = Settings.Secure.isLocationProviderEnabled(
                 cr, LocationManager.NETWORK_PROVIDER);
 
-        // Assert that if there are no test providers enabled, LocationManager just returns the
-        // values from Settings.Secure.
+        // Find out location manager's opinion on the matter, making sure we dont' get spurious
+        // results from test versions of the two providers.
         forceRemoveTestProvider(LocationManager.GPS_PROVIDER);
         forceRemoveTestProvider(LocationManager.NETWORK_PROVIDER);
         boolean lmGps = mManager.isProviderEnabled(LocationManager.GPS_PROVIDER);
         boolean lmNlp = mManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER);
-        assertEquals("Inconsistent GPS values", gps, lmGps);
-        assertEquals("Inconsistent NLP values", nlp, lmNlp);
 
-        // Assert that isLocationProviderEnabled() values are consistent with the location mode
+        // Location Manager will report provider as off if it doesn't know about it
+        boolean expectedGps = gps && deviceHasProvider(LocationManager.GPS_PROVIDER);
+        boolean expectedNlp = nlp && deviceHasProvider(LocationManager.NETWORK_PROVIDER);
+
+        // Assert LocationManager returned the values from Settings.Secure (assuming the device has
+        // the appropriate hardware).
+        assertEquals("Inconsistent GPS values", expectedGps, lmGps);
+        assertEquals("Inconsistent NLP values", expectedNlp, lmNlp);
+
         switch (mode) {
             case Settings.Secure.LOCATION_MODE_OFF:
-                assertFalse("Bad GPS for mode " + mode, gps);
-                assertFalse("Bad NLP for mode " + mode, nlp);
+                expectedGps = false;
+                expectedNlp = false;
                 break;
             case Settings.Secure.LOCATION_MODE_SENSORS_ONLY:
-                assertEquals("Bad GPS for mode " + mode, hasGpsFeature(), gps);
-                assertFalse("Bad NLP for mode " + mode, nlp);
+                expectedGps = true;
+                expectedNlp = false;
                 break;
             case Settings.Secure.LOCATION_MODE_BATTERY_SAVING:
-                assertFalse("Bad GPS for mode " + mode, gps);
-                assertTrue("Bad NLP for mode " + mode, nlp);
+                expectedGps = false;
+                expectedNlp = true;
                 break;
             case Settings.Secure.LOCATION_MODE_HIGH_ACCURACY:
-                assertEquals("Bad GPS for mode " + mode, hasGpsFeature(), gps);
-                assertTrue("Bad NLP for mode " + mode, nlp);
+                expectedGps = true;
+                expectedNlp = true;
                 break;
         }
+
+        // Assert that isLocationProviderEnabled() values are consistent with the location mode
+        assertEquals("Bad GPS for mode " + mode, expectedGps, gps);
+        assertEquals("Bad NLP for mode " + mode, expectedNlp, nlp);
+    }
+
+    /**
+     * Returns true if the {@link LocationManager} reports that the device includes this flavor
+     * of location provider.
+     */
+    private boolean deviceHasProvider(String provider) {
+        List<String> providers = mManager.getAllProviders();
+        for (String aProvider : providers) {
+            if (aProvider.equals(provider)) {
+                return true;
+            }
+        }
+        return false;
     }
 
     /**
diff --git a/tests/tests/media/src/android/media/cts/AdaptivePlaybackTest.java b/tests/tests/media/src/android/media/cts/AdaptivePlaybackTest.java
index e307bbd..1747afa 100644
--- a/tests/tests/media/src/android/media/cts/AdaptivePlaybackTest.java
+++ b/tests/tests/media/src/android/media/cts/AdaptivePlaybackTest.java
@@ -1275,13 +1275,11 @@
 
             /* test if the explicitly named codec is present on the system */
             if (explicitCodecName != null) {
-                try {
-                    MediaCodec codec = MediaCodec.createByCodecName(explicitCodecName);
-                    if (codec != null) {
-                        codec.release();
-                        add(new Codec(explicitCodecName, null, mediaList));
-                    }
-                } catch (IOException e) {}
+                MediaCodec codec = MediaCodec.createByCodecName(explicitCodecName);
+                if (codec != null) {
+                    codec.release();
+                    add(new Codec(explicitCodecName, null, mediaList));
+                }
             }
         } catch (Throwable t) {
             Log.wtf("Constructor failed", t);
diff --git a/tests/tests/text/src/android/text/cts/EmojiTest.java b/tests/tests/text/src/android/text/cts/EmojiTest.java
index f5f191f..4bcc0e1 100644
--- a/tests/tests/text/src/android/text/cts/EmojiTest.java
+++ b/tests/tests/text/src/android/text/cts/EmojiTest.java
@@ -25,6 +25,7 @@
 import android.view.KeyEvent;
 import android.view.Menu;
 import android.view.View;
+import android.webkit.cts.NullWebViewUtils;
 import android.webkit.cts.WebViewOnUiThread;
 import android.widget.TextView;
 import android.widget.EditText;
@@ -58,7 +59,6 @@
      */
     public void testEmojiGlyph() {
         CaptureCanvas ccanvas = new CaptureCanvas(getInstrumentation().getContext());
-        CaptureWebView cwebview = new CaptureWebView(getInstrumentation().getContext());
 
         Bitmap mBitmapA, mBitmapB;  // Emoji displayed Bitmaps to compare
 
@@ -92,11 +92,15 @@
 
             assertFalse(mBitmapA.sameAs(mBitmapB));
 
-            mBitmapA = cwebview.capture(Character.toChars(comparedCodePoints[i][0]));
-            mBitmapB = cwebview.capture(Character.toChars(comparedCodePoints[i][1]));
-
-            assertFalse(mBitmapA.sameAs(mBitmapB));
-
+            // Trigger activity bringup so we can determine if a WebView is available on this
+            // device.
+            EmojiStubActivity activity = getActivity();
+            if (NullWebViewUtils.isWebViewAvailable()) {
+                CaptureWebView cwebview = new CaptureWebView(getInstrumentation().getContext());
+                mBitmapA = cwebview.capture(Character.toChars(comparedCodePoints[i][0]));
+                mBitmapB = cwebview.capture(Character.toChars(comparedCodePoints[i][1]));
+                assertFalse(mBitmapA.sameAs(mBitmapB));
+            }
         }
     }
 
diff --git a/tests/tests/theme/src/android/theme/cts/DeviceDefaultTest.java b/tests/tests/theme/src/android/theme/cts/DeviceDefaultTest.java
index 086dce1..77de0b4 100644
--- a/tests/tests/theme/src/android/theme/cts/DeviceDefaultTest.java
+++ b/tests/tests/theme/src/android/theme/cts/DeviceDefaultTest.java
@@ -19,6 +19,7 @@
 import android.app.Activity;
 import android.content.Context;
 import android.content.Intent;
+import android.content.pm.PackageManager;
 import android.content.res.Configuration;
 import android.test.ActivityInstrumentationTestCase2;
 
@@ -85,7 +86,7 @@
     }
 
     public void testGetActionBar_DeviceDefault_Light_DialogWhenLarge() {
-        assertActionBarWhenLarge(android.R.style.Theme_Holo_Light_DialogWhenLarge);
+        assertActionBarWhenLarge(android.R.style.Theme_DeviceDefault_Light_DialogWhenLarge);
     }
 
     public void testGetActionBar_DeviceDefault_Light_DialogWhenLarge_NoActionBar() {
@@ -122,6 +123,10 @@
 
     private void assertGetActionBar(int themeId, boolean actionBar) {
         Activity activity = startActivity(themeId);
+        if (activity.getPackageManager().hasSystemFeature(PackageManager.FEATURE_WATCH)) {
+            assertNull(activity.getActionBar());
+            return;
+        }
         if (actionBar) {
             assertNotNull(activity.getActionBar());
         } else {
diff --git a/tests/tests/webkit/src/android/webkit/cts/CookieManagerTest.java b/tests/tests/webkit/src/android/webkit/cts/CookieManagerTest.java
index a0b4fa6..ead235e 100644
--- a/tests/tests/webkit/src/android/webkit/cts/CookieManagerTest.java
+++ b/tests/tests/webkit/src/android/webkit/cts/CookieManagerTest.java
@@ -42,13 +42,19 @@
     @Override
     protected void setUp() throws Exception {
         super.setUp();
-        mOnUiThread = new WebViewOnUiThread(this, getActivity().getWebView());
+        WebView webview = getActivity().getWebView();
+        if (webview != null) {
+            mOnUiThread = new WebViewOnUiThread(this, webview);
 
-        mCookieManager = CookieManager.getInstance();
-        assertNotNull(mCookieManager);
+            mCookieManager = CookieManager.getInstance();
+            assertNotNull(mCookieManager);
+        }
     }
 
     public void testGetInstance() {
+        if (!NullWebViewUtils.isWebViewAvailable()) {
+            return;
+        }
         mOnUiThread.cleanUp();
         CookieManager c1 = CookieManager.getInstance();
         CookieManager c2 = CookieManager.getInstance();
@@ -57,9 +63,15 @@
     }
 
     public void testClone() {
+        if (!NullWebViewUtils.isWebViewAvailable()) {
+            return;
+        }
     }
 
     public void testAcceptCookie() throws Exception {
+        if (!NullWebViewUtils.isWebViewAvailable()) {
+            return;
+        }
         mCookieManager.removeAllCookie();
         mCookieManager.setAcceptCookie(false);
         assertFalse(mCookieManager.acceptCookie());
@@ -113,6 +125,9 @@
     }
 
     public void testCookieManager() {
+        if (!NullWebViewUtils.isWebViewAvailable()) {
+            return;
+        }
         // enable cookie
         mCookieManager.setAcceptCookie(true);
         assertTrue(mCookieManager.acceptCookie());
@@ -146,6 +161,9 @@
 
     @SuppressWarnings("deprecation")
     public void testRemoveCookies() throws InterruptedException {
+        if (!NullWebViewUtils.isWebViewAvailable()) {
+            return;
+        }
         // enable cookie
         mCookieManager.setAcceptCookie(true);
         assertTrue(mCookieManager.acceptCookie());
@@ -212,6 +230,9 @@
     }
 
     public void testb3167208() throws Exception {
+        if (!NullWebViewUtils.isWebViewAvailable()) {
+            return;
+        }
         String uri = "http://host.android.com/path/";
         // note the space after the domain=
         String problemCookie = "foo=bar; domain= .android.com; path=/";
diff --git a/tests/tests/webkit/src/android/webkit/cts/CookieSyncManagerTest.java b/tests/tests/webkit/src/android/webkit/cts/CookieSyncManagerTest.java
index 67a77e7..e2112b7 100644
--- a/tests/tests/webkit/src/android/webkit/cts/CookieSyncManagerTest.java
+++ b/tests/tests/webkit/src/android/webkit/cts/CookieSyncManagerTest.java
@@ -33,6 +33,9 @@
     }
 
     public void testCookieSyncManager() throws Exception {
+        if (!NullWebViewUtils.isWebViewAvailable()) {
+            return;
+        }
         CookieSyncManager csm1 = CookieSyncManager.createInstance(getActivity());
         assertNotNull(csm1);
 
diff --git a/tests/tests/webkit/src/android/webkit/cts/CookieTest.java b/tests/tests/webkit/src/android/webkit/cts/CookieTest.java
index 0c0396a..704ae24 100644
--- a/tests/tests/webkit/src/android/webkit/cts/CookieTest.java
+++ b/tests/tests/webkit/src/android/webkit/cts/CookieTest.java
@@ -16,22 +16,30 @@
 
 package android.webkit.cts;
 
-import android.test.AndroidTestCase;
+import android.test.ActivityInstrumentationTestCase2;
 import android.webkit.CookieManager;
 import android.webkit.CookieSyncManager;
 
 /**
  * Original framework tests for CookieManager
  */
-public class CookieTest extends AndroidTestCase {
+public class CookieTest extends ActivityInstrumentationTestCase2<CookieSyncManagerStubActivity> {
 
     private CookieManager mCookieManager;
     private static final long WAIT_TIME = 50;
 
+    public CookieTest() {
+        super("com.android.cts.stub", CookieSyncManagerStubActivity.class);
+    }
+
     @Override
     protected void setUp() throws Exception {
         super.setUp();
-        CookieSyncManager.createInstance(getContext());
+
+        if (!NullWebViewUtils.isWebViewAvailable()) {
+            return;
+        }
+
         mCookieManager = CookieManager.getInstance();
         mCookieManager.removeAllCookie();
         // cookies are removed asynchronously, wait a bit for cookies to be removed
@@ -48,6 +56,9 @@
     }
 
     public void testDomain() {
+        if (!NullWebViewUtils.isWebViewAvailable()) {
+            return;
+        }
         String url = "http://www.foo.com";
 
         // basic
@@ -86,6 +97,9 @@
     }
 
     public void testSubDomain() {
+        if (!NullWebViewUtils.isWebViewAvailable()) {
+            return;
+        }
         String url_abcd = "http://a.b.c.d.com";
         String url_bcd = "http://b.c.d.com";
         String url_cd = "http://c.d.com";
@@ -127,6 +141,9 @@
     }
 
     public void testInvalidDomain() {
+        if (!NullWebViewUtils.isWebViewAvailable()) {
+            return;
+        }
         String url = "http://foo.bar.com";
 
         mCookieManager.setCookie(url, "a=1; domain=.yo.foo.bar.com");
@@ -163,6 +180,9 @@
     }
 
     public void testPath() {
+        if (!NullWebViewUtils.isWebViewAvailable()) {
+            return;
+        }
         String url = "http://www.foo.com";
 
         mCookieManager.setCookie(url, "a=b; path=/wee");
@@ -192,6 +212,9 @@
     }
 
     public void testEmptyValue() {
+        if (!NullWebViewUtils.isWebViewAvailable()) {
+            return;
+        }
         String url = "http://www.foobar.com";
 
         mCookieManager.setCookie(url, "bar=");
diff --git a/tests/tests/webkit/src/android/webkit/cts/GeolocationTest.java b/tests/tests/webkit/src/android/webkit/cts/GeolocationTest.java
index 016d7c2..8ab9eb6 100644
--- a/tests/tests/webkit/src/android/webkit/cts/GeolocationTest.java
+++ b/tests/tests/webkit/src/android/webkit/cts/GeolocationTest.java
@@ -135,49 +135,58 @@
     protected void setUp() throws Exception {
         super.setUp();
 
-        // Set up a WebView with JavaScript and Geolocation enabled
-        final String GEO_DIR = "geo_test";
-        mOnUiThread = new WebViewOnUiThread(this, getActivity().getWebView());
-        mOnUiThread.getSettings().setJavaScriptEnabled(true);
-        mOnUiThread.getSettings().setGeolocationEnabled(true);
-        mOnUiThread.getSettings().setGeolocationDatabasePath(
-                getActivity().getApplicationContext().getDir(GEO_DIR, 0).getPath());
+        WebView webview = getActivity().getWebView();
 
-        // Add a JsInterface to report back to the test when a location is received
-        mJavascriptStatusReceiver = new JavascriptStatusReceiver();
-        mOnUiThread.addJavascriptInterface(mJavascriptStatusReceiver, JS_INTERFACE_NAME);
+        if (webview != null) {
+            // Set up a WebView with JavaScript and Geolocation enabled
+            final String GEO_DIR = "geo_test";
+            mOnUiThread = new WebViewOnUiThread(this, webview);
+            mOnUiThread.getSettings().setJavaScriptEnabled(true);
+            mOnUiThread.getSettings().setGeolocationEnabled(true);
+            mOnUiThread.getSettings().setGeolocationDatabasePath(
+                    getActivity().getApplicationContext().getDir(GEO_DIR, 0).getPath());
 
-        // Always intercept all loads with the same geolocation test page
-        mOnUiThread.setWebViewClient(new InterceptClient(mOnUiThread));
-        // Clear all permissions before each test
-        GeolocationPermissions.getInstance().clearAll();
-        // Cache this mostly because the lookup is two lines of code
-        mLocationManager = (LocationManager)getActivity().getApplicationContext()
-                .getSystemService(Context.LOCATION_SERVICE);
-        // Add a test provider before each test to inject a location
-        mProviders = mLocationManager.getAllProviders();
-        for (String provider : mProviders) {
-            // Can't mock passive provider.
-            if (provider.equals(LocationManager.PASSIVE_PROVIDER)) {
-                mProviders.remove(provider);
-                break;
+            // Add a JsInterface to report back to the test when a location is received
+            mJavascriptStatusReceiver = new JavascriptStatusReceiver();
+            mOnUiThread.addJavascriptInterface(mJavascriptStatusReceiver, JS_INTERFACE_NAME);
+
+            // Always intercept all loads with the same geolocation test page
+            mOnUiThread.setWebViewClient(new InterceptClient(mOnUiThread));
+            // Clear all permissions before each test
+            GeolocationPermissions.getInstance().clearAll();
+            // Cache this mostly because the lookup is two lines of code
+            mLocationManager = (LocationManager)getActivity().getApplicationContext()
+                    .getSystemService(Context.LOCATION_SERVICE);
+            // Add a test provider before each test to inject a location
+            mProviders = mLocationManager.getAllProviders();
+            for (String provider : mProviders) {
+                // Can't mock passive provider.
+                if (provider.equals(LocationManager.PASSIVE_PROVIDER)) {
+                    mProviders.remove(provider);
+                    break;
+                }
             }
+            addTestProviders();
         }
-        addTestProviders();
     }
 
     @Override
     protected void tearDown() throws Exception {
         stopUpdateLocationThread();
-        // Remove the test provider after each test
-        for (String provider : mProviders) {
-            try {
-                // Work around b/11446702 by clearing the test provider before removing it
-                mLocationManager.clearTestProviderEnabled(provider);
-                mLocationManager.removeTestProvider(provider);
-            } catch (IllegalArgumentException e) {} // Not much to do about this
+        if (mProviders != null) {
+            // Remove the test provider after each test
+            for (String provider : mProviders) {
+                try {
+                    // Work around b/11446702 by clearing the test provider before removing it
+                    mLocationManager.clearTestProviderEnabled(provider);
+                    mLocationManager.removeTestProvider(provider);
+                } catch (IllegalArgumentException e) {} // Not much to do about this
+            }
         }
-        mOnUiThread.cleanUp();
+
+        if (mOnUiThread != null) {
+            mOnUiThread.cleanUp();
+        }
         // This will null all member and static variables
         super.tearDown();
     }
@@ -278,6 +287,9 @@
 
     // Test loading a page and accepting the domain for one load
     public void testSimpleGeolocationRequestAcceptOnce() throws Exception {
+        if (!NullWebViewUtils.isWebViewAvailable()) {
+            return;
+        }
         final TestSimpleGeolocationRequestWebChromeClient chromeClientAcceptOnce =
                 new TestSimpleGeolocationRequestWebChromeClient(mOnUiThread, true, false);
         mOnUiThread.setWebChromeClient(chromeClientAcceptOnce);
@@ -368,6 +380,9 @@
 
     // Test loading a page and retaining the domain forever
     public void testSimpleGeolocationRequestAcceptAlways() throws Exception {
+        if (!NullWebViewUtils.isWebViewAvailable()) {
+            return;
+        }
         final TestSimpleGeolocationRequestWebChromeClient chromeClientAcceptAlways =
                 new TestSimpleGeolocationRequestWebChromeClient(mOnUiThread, true, true);
         mOnUiThread.setWebChromeClient(chromeClientAcceptAlways);
@@ -424,6 +439,9 @@
 
     // Test the GeolocationPermissions API
     public void testGeolocationPermissions() {
+        if (!NullWebViewUtils.isWebViewAvailable()) {
+            return;
+        }
         Set<String> acceptedOrigins = new TreeSet<String>();
         BooleanCheck falseCheck = new BooleanCheck(false);
         GeolocationPermissions.getInstance().getAllowed(URL_2, falseCheck);
@@ -483,6 +501,9 @@
 
     // Test loading pages and checks rejecting once and recjecting the domain forever
     public void testSimpleGeolocationRequestReject() throws Exception {
+        if (!NullWebViewUtils.isWebViewAvailable()) {
+            return;
+        }
         final TestSimpleGeolocationRequestWebChromeClient chromeClientRejectOnce =
                 new TestSimpleGeolocationRequestWebChromeClient(mOnUiThread, false, false);
         mOnUiThread.setWebChromeClient(chromeClientRejectOnce);
diff --git a/tests/tests/webkit/src/android/webkit/cts/HttpAuthHandlerTest.java b/tests/tests/webkit/src/android/webkit/cts/HttpAuthHandlerTest.java
index 52e9278..b078c7a 100644
--- a/tests/tests/webkit/src/android/webkit/cts/HttpAuthHandlerTest.java
+++ b/tests/tests/webkit/src/android/webkit/cts/HttpAuthHandlerTest.java
@@ -43,12 +43,18 @@
     @Override
     protected void setUp() throws Exception {
         super.setUp();
-        mOnUiThread = new WebViewOnUiThread(this, getActivity().getWebView());
+        WebView webview = getActivity().getWebView();
+        if (webview != null) {
+            mOnUiThread = new WebViewOnUiThread(this, webview);
+        }
     }
 
     @Override
     protected void tearDown() throws Exception {
-        mOnUiThread.cleanUp();
+        if (mOnUiThread != null) {
+            mOnUiThread.cleanUp();
+        }
+
         if (mWebServer != null) {
             mWebServer.shutdown();
         }
@@ -138,6 +144,9 @@
     }
 
     public void testProceed() throws Throwable {
+        if (!NullWebViewUtils.isWebViewAvailable()) {
+            return;
+        }
         mWebServer = new CtsTestServer(getActivity());
         String url = mWebServer.getAuthAssetUrl(TestHtmlConstants.HELLO_WORLD_URL);
 
@@ -147,6 +156,9 @@
     }
 
     public void testCancel() throws Throwable {
+        if (!NullWebViewUtils.isWebViewAvailable()) {
+            return;
+        }
         mWebServer = new CtsTestServer(getActivity());
         String url = mWebServer.getAuthAssetUrl(TestHtmlConstants.HELLO_WORLD_URL);
 
@@ -159,6 +171,9 @@
     }
 
     public void testUseHttpAuthUsernamePassword() throws Throwable {
+        if (!NullWebViewUtils.isWebViewAvailable()) {
+            return;
+        }
         mWebServer = new CtsTestServer(getActivity());
         String url = mWebServer.getAuthAssetUrl(TestHtmlConstants.HELLO_WORLD_URL);
 
diff --git a/tests/tests/webkit/src/android/webkit/cts/WebBackForwardListTest.java b/tests/tests/webkit/src/android/webkit/cts/WebBackForwardListTest.java
index 34dc697..71893f4 100644
--- a/tests/tests/webkit/src/android/webkit/cts/WebBackForwardListTest.java
+++ b/tests/tests/webkit/src/android/webkit/cts/WebBackForwardListTest.java
@@ -20,6 +20,7 @@
 import android.test.ActivityInstrumentationTestCase2;
 import android.webkit.WebBackForwardList;
 import android.webkit.WebHistoryItem;
+import android.webkit.WebView;
 
 
 public class WebBackForwardListTest extends ActivityInstrumentationTestCase2<WebViewStubActivity> {
@@ -35,16 +36,24 @@
     @Override
     public void setUp() throws Exception {
         super.setUp();
-        mOnUiThread = new WebViewOnUiThread(this, getActivity().getWebView());
+        WebView webview = getActivity().getWebView();
+        if (webview != null) {
+            mOnUiThread = new WebViewOnUiThread(this, webview);
+        }
     }
 
     @Override
     public void tearDown() throws Exception {
-        mOnUiThread.cleanUp();
+        if (mOnUiThread != null) {
+            mOnUiThread.cleanUp();
+        }
         super.tearDown();
     }
 
     public void testGetCurrentItem() throws Exception {
+        if (!NullWebViewUtils.isWebViewAvailable()) {
+            return;
+        }
         WebBackForwardList list = mOnUiThread.copyBackForwardList();
 
         assertNull(list.getCurrentItem());
diff --git a/tests/tests/webkit/src/android/webkit/cts/WebChromeClientTest.java b/tests/tests/webkit/src/android/webkit/cts/WebChromeClientTest.java
index 344b568..fca14e24 100644
--- a/tests/tests/webkit/src/android/webkit/cts/WebChromeClientTest.java
+++ b/tests/tests/webkit/src/android/webkit/cts/WebChromeClientTest.java
@@ -44,13 +44,18 @@
     @Override
     protected void setUp() throws Exception {
         super.setUp();
-        mOnUiThread = new WebViewOnUiThread(this, getActivity().getWebView());
+        WebView webview = getActivity().getWebView();
+        if (webview != null) {
+            mOnUiThread = new WebViewOnUiThread(this, webview);
+        }
         mWebServer = new CtsTestServer(getActivity());
     }
 
     @Override
     protected void tearDown() throws Exception {
-        mOnUiThread.cleanUp();
+        if (mOnUiThread != null) {
+            mOnUiThread.cleanUp();
+        }
         if (mWebServer != null) {
             mWebServer.shutdown();
         }
@@ -62,6 +67,9 @@
     }
 
     public void testOnProgressChanged() {
+        if (!NullWebViewUtils.isWebViewAvailable()) {
+            return;
+        }
         final MockWebChromeClient webChromeClient = new MockWebChromeClient();
         mOnUiThread.setWebChromeClient(webChromeClient);
 
@@ -78,6 +86,9 @@
     }
 
     public void testOnReceivedTitle() throws Exception {
+        if (!NullWebViewUtils.isWebViewAvailable()) {
+            return;
+        }
         final MockWebChromeClient webChromeClient = new MockWebChromeClient();
         mOnUiThread.setWebChromeClient(webChromeClient);
 
@@ -96,6 +107,9 @@
     }
 
     public void testOnReceivedIcon() throws Throwable {
+        if (!NullWebViewUtils.isWebViewAvailable()) {
+            return;
+        }
         final MockWebChromeClient webChromeClient = new MockWebChromeClient();
         mOnUiThread.setWebChromeClient(webChromeClient);
 
@@ -161,20 +175,32 @@
         }
     }
     public void testWindows() throws Exception {
+        if (!NullWebViewUtils.isWebViewAvailable()) {
+            return;
+        }
         runWindowTest(true);
     }
 
     public void testBlockWindowsSync() throws Exception {
+        if (!NullWebViewUtils.isWebViewAvailable()) {
+            return;
+        }
         mBlockWindowCreationSync = true;
         runWindowTest(false);
     }
 
     public void testBlockWindowsAsync() throws Exception {
+        if (!NullWebViewUtils.isWebViewAvailable()) {
+            return;
+        }
         mBlockWindowCreationAsync = true;
         runWindowTest(false);
     }
 
     public void testOnJsBeforeUnload() throws Exception {
+        if (!NullWebViewUtils.isWebViewAvailable()) {
+            return;
+        }
         final MockWebChromeClient webChromeClient = new MockWebChromeClient();
         mOnUiThread.setWebChromeClient(webChromeClient);
 
@@ -198,6 +224,9 @@
     }
 
     public void testOnJsAlert() throws Exception {
+        if (!NullWebViewUtils.isWebViewAvailable()) {
+            return;
+        }
         final MockWebChromeClient webChromeClient = new MockWebChromeClient();
         mOnUiThread.setWebChromeClient(webChromeClient);
 
@@ -220,6 +249,9 @@
     }
 
     public void testOnJsConfirm() throws Exception {
+        if (!NullWebViewUtils.isWebViewAvailable()) {
+            return;
+        }
         final MockWebChromeClient webChromeClient = new MockWebChromeClient();
         mOnUiThread.setWebChromeClient(webChromeClient);
 
@@ -242,6 +274,9 @@
     }
 
     public void testOnJsPrompt() throws Exception {
+        if (!NullWebViewUtils.isWebViewAvailable()) {
+            return;
+        }
         final MockWebChromeClient webChromeClient = new MockWebChromeClient();
         mOnUiThread.setWebChromeClient(webChromeClient);
 
diff --git a/tests/tests/webkit/src/android/webkit/cts/WebHistoryItemTest.java b/tests/tests/webkit/src/android/webkit/cts/WebHistoryItemTest.java
index 468430f..7d276e9 100644
--- a/tests/tests/webkit/src/android/webkit/cts/WebHistoryItemTest.java
+++ b/tests/tests/webkit/src/android/webkit/cts/WebHistoryItemTest.java
@@ -54,12 +54,17 @@
     protected void setUp() throws Exception {
         super.setUp();
         mWebServer = new CtsTestServer(getActivity());
-        mOnUiThread = new WebViewOnUiThread(this, getActivity().getWebView());
+        WebView webview = getActivity().getWebView();
+        if (webview != null) {
+            mOnUiThread = new WebViewOnUiThread(this, webview);
+        }
     }
 
     @Override
     protected void tearDown() throws Exception {
-        mOnUiThread.cleanUp();
+        if (mOnUiThread != null) {
+            mOnUiThread.cleanUp();
+        }
         mWebServer.shutdown();
         super.tearDown();
         if (mIconDb != null) {
@@ -69,6 +74,9 @@
     }
 
     public void testWebHistoryItem() throws Throwable {
+        if (!NullWebViewUtils.isWebViewAvailable()) {
+            return;
+        }
         final WaitForIconClient waitForIconClient = new WaitForIconClient(mOnUiThread);
         mOnUiThread.setWebChromeClient(waitForIconClient);
         runTestOnUiThread(new Runnable() {
diff --git a/tests/tests/webkit/src/android/webkit/cts/WebSettingsTest.java b/tests/tests/webkit/src/android/webkit/cts/WebSettingsTest.java
index 291136f..c2104fe 100644
--- a/tests/tests/webkit/src/android/webkit/cts/WebSettingsTest.java
+++ b/tests/tests/webkit/src/android/webkit/cts/WebSettingsTest.java
@@ -65,8 +65,11 @@
     @Override
     protected void setUp() throws Exception {
         super.setUp();
-        mOnUiThread = new WebViewOnUiThread(this, getActivity().getWebView());
-        mSettings = mOnUiThread.getSettings();
+        WebView webview = getActivity().getWebView();
+        if (webview != null) {
+            mOnUiThread = new WebViewOnUiThread(this, webview);
+            mSettings = mOnUiThread.getSettings();
+        }
         mContext = getInstrumentation().getTargetContext();
     }
 
@@ -75,7 +78,9 @@
         if (mWebServer != null) {
             mWebServer.shutdown();
         }
-        mOnUiThread.cleanUp();
+        if (mOnUiThread != null) {
+            mOnUiThread.cleanUp();
+        }
         super.tearDown();
     }
 
@@ -90,6 +95,9 @@
      * Safari/<major>.<minor>
      */
     public void testUserAgentString_default() {
+        if (!NullWebViewUtils.isWebViewAvailable()) {
+            return;
+        }
         final String actualUserAgentString = mSettings.getUserAgentString();
         Log.i(LOG_TAG, String.format("Checking user agent string %s", actualUserAgentString));
         final String patternString =
@@ -131,6 +139,9 @@
     }
 
     public void testAccessUserAgentString() throws Exception {
+        if (!NullWebViewUtils.isWebViewAvailable()) {
+            return;
+        }
         startWebServer();
         String url = mWebServer.getUserAgentUrl();
 
@@ -159,6 +170,9 @@
     }
 
     public void testAccessAllowFileAccess() {
+        if (!NullWebViewUtils.isWebViewAvailable()) {
+            return;
+        }
         // This test is not compatible with 4.0.3
         if ("4.0.3".equals(Build.VERSION.RELEASE)) {
             return;
@@ -184,6 +198,9 @@
     }
 
     public void testAccessCacheMode() throws Throwable {
+        if (!NullWebViewUtils.isWebViewAvailable()) {
+            return;
+        }
         runTestOnUiThread(new Runnable() {
             @Override
             public void run() {
@@ -256,6 +273,9 @@
     }
 
     public void testAccessCursiveFontFamily() throws Exception {
+        if (!NullWebViewUtils.isWebViewAvailable()) {
+            return;
+        }
         assertNotNull(mSettings.getCursiveFontFamily());
 
         String newCusiveFamily = "Apple Chancery";
@@ -264,6 +284,9 @@
     }
 
     public void testAccessFantasyFontFamily() {
+        if (!NullWebViewUtils.isWebViewAvailable()) {
+            return;
+        }
         assertNotNull(mSettings.getFantasyFontFamily());
 
         String newFantasyFamily = "Papyrus";
@@ -272,6 +295,9 @@
     }
 
     public void testAccessFixedFontFamily() {
+        if (!NullWebViewUtils.isWebViewAvailable()) {
+            return;
+        }
         assertNotNull(mSettings.getFixedFontFamily());
 
         String newFixedFamily = "Courier";
@@ -280,6 +306,9 @@
     }
 
     public void testAccessSansSerifFontFamily() {
+        if (!NullWebViewUtils.isWebViewAvailable()) {
+            return;
+        }
         assertNotNull(mSettings.getSansSerifFontFamily());
 
         String newFixedFamily = "Verdana";
@@ -288,6 +317,9 @@
     }
 
     public void testAccessSerifFontFamily() {
+        if (!NullWebViewUtils.isWebViewAvailable()) {
+            return;
+        }
         assertNotNull(mSettings.getSerifFontFamily());
 
         String newSerifFamily = "Times";
@@ -296,6 +328,9 @@
     }
 
     public void testAccessStandardFontFamily() {
+        if (!NullWebViewUtils.isWebViewAvailable()) {
+            return;
+        }
         assertNotNull(mSettings.getStandardFontFamily());
 
         String newStandardFamily = "Times";
@@ -304,6 +339,9 @@
     }
 
     public void testAccessDefaultFontSize() {
+        if (!NullWebViewUtils.isWebViewAvailable()) {
+            return;
+        }
         int defaultSize = mSettings.getDefaultFontSize();
         assertTrue(defaultSize > 0);
 
@@ -322,6 +360,9 @@
     }
 
     public void testAccessDefaultFixedFontSize() {
+        if (!NullWebViewUtils.isWebViewAvailable()) {
+            return;
+        }
         int defaultSize = mSettings.getDefaultFixedFontSize();
         assertTrue(defaultSize > 0);
 
@@ -340,6 +381,9 @@
     }
 
     public void testAccessDefaultTextEncodingName() {
+        if (!NullWebViewUtils.isWebViewAvailable()) {
+            return;
+        }
         assertNotNull(mSettings.getDefaultTextEncodingName());
 
         String newEncodingName = "iso-8859-1";
@@ -348,6 +392,9 @@
     }
 
     public void testAccessJavaScriptCanOpenWindowsAutomatically() throws Exception {
+        if (!NullWebViewUtils.isWebViewAvailable()) {
+            return;
+        }
         mSettings.setJavaScriptEnabled(true);
 
         mSettings.setJavaScriptCanOpenWindowsAutomatically(false);
@@ -372,6 +419,9 @@
     }
 
     public void testAccessJavaScriptEnabled() throws Exception {
+        if (!NullWebViewUtils.isWebViewAvailable()) {
+            return;
+        }
         mSettings.setJavaScriptEnabled(true);
         assertTrue(mSettings.getJavaScriptEnabled());
         loadAssetUrl(TestHtmlConstants.JAVASCRIPT_URL);
@@ -395,6 +445,9 @@
     }
 
     public void testAccessLayoutAlgorithm() {
+        if (!NullWebViewUtils.isWebViewAvailable()) {
+            return;
+        }
         assertEquals(WebSettings.LayoutAlgorithm.NARROW_COLUMNS, mSettings.getLayoutAlgorithm());
 
         mSettings.setLayoutAlgorithm(WebSettings.LayoutAlgorithm.NORMAL);
@@ -405,6 +458,9 @@
     }
 
     public void testAccessMinimumFontSize() {
+        if (!NullWebViewUtils.isWebViewAvailable()) {
+            return;
+        }
         assertEquals(8, mSettings.getMinimumFontSize());
 
         mSettings.setMinimumFontSize(100);
@@ -418,6 +474,9 @@
     }
 
     public void testAccessMinimumLogicalFontSize() {
+        if (!NullWebViewUtils.isWebViewAvailable()) {
+            return;
+        }
         assertEquals(8, mSettings.getMinimumLogicalFontSize());
 
         mSettings.setMinimumLogicalFontSize(100);
@@ -431,6 +490,9 @@
     }
 
     public void testAccessPluginsEnabled() {
+        if (!NullWebViewUtils.isWebViewAvailable()) {
+            return;
+        }
         assertFalse(mSettings.getPluginsEnabled());
 
         mSettings.setPluginsEnabled(true);
@@ -438,6 +500,9 @@
     }
 
     public void testAccessPluginsPath() {
+        if (!NullWebViewUtils.isWebViewAvailable()) {
+            return;
+        }
         assertNotNull(mSettings.getPluginsPath());
 
         String pluginPath = "pluginPath";
@@ -447,6 +512,9 @@
     }
 
     public void testAccessSaveFormData() {
+        if (!NullWebViewUtils.isWebViewAvailable()) {
+            return;
+        }
         assertTrue(mSettings.getSaveFormData());
 
         mSettings.setSaveFormData(false);
@@ -454,6 +522,9 @@
     }
 
     public void testAccessTextSize() {
+        if (!NullWebViewUtils.isWebViewAvailable()) {
+            return;
+        }
         assertEquals(TextSize.NORMAL, mSettings.getTextSize());
 
         mSettings.setTextSize(TextSize.LARGER);
@@ -470,6 +541,9 @@
     }
 
     public void testAccessUseDoubleTree() {
+        if (!NullWebViewUtils.isWebViewAvailable()) {
+            return;
+        }
         assertFalse(mSettings.getUseDoubleTree());
 
         mSettings.setUseDoubleTree(true);
@@ -478,6 +552,9 @@
     }
 
     public void testAccessUseWideViewPort() {
+        if (!NullWebViewUtils.isWebViewAvailable()) {
+            return;
+        }
         assertFalse(mSettings.getUseWideViewPort());
 
         mSettings.setUseWideViewPort(true);
@@ -485,12 +562,18 @@
     }
 
     public void testSetNeedInitialFocus() {
+        if (!NullWebViewUtils.isWebViewAvailable()) {
+            return;
+        }
         mSettings.setNeedInitialFocus(false);
 
         mSettings.setNeedInitialFocus(true);
     }
 
     public void testSetRenderPriority() {
+        if (!NullWebViewUtils.isWebViewAvailable()) {
+            return;
+        }
         mSettings.setRenderPriority(WebSettings.RenderPriority.HIGH);
 
         mSettings.setRenderPriority(WebSettings.RenderPriority.LOW);
@@ -499,6 +582,9 @@
     }
 
     public void testAccessSupportMultipleWindows() {
+        if (!NullWebViewUtils.isWebViewAvailable()) {
+            return;
+        }
         assertFalse(mSettings.supportMultipleWindows());
 
         mSettings.setSupportMultipleWindows(true);
@@ -506,6 +592,9 @@
     }
 
     public void testAccessSupportZoom() throws Throwable {
+        if (!NullWebViewUtils.isWebViewAvailable()) {
+            return;
+        }
         assertTrue(mSettings.supportZoom());
 
         runTestOnUiThread(new Runnable() {
@@ -518,6 +607,9 @@
     }
 
     public void testAccessBuiltInZoomControls() throws Throwable {
+        if (!NullWebViewUtils.isWebViewAvailable()) {
+            return;
+        }
         assertFalse(mSettings.getBuiltInZoomControls());
 
         runTestOnUiThread(new Runnable() {
@@ -530,6 +622,9 @@
     }
 
     public void testAppCacheDisabled() throws Throwable {
+        if (!NullWebViewUtils.isWebViewAvailable()) {
+            return;
+        }
         // Test that when AppCache is disabled, we don't get any AppCache
         // callbacks.
         startWebServer();
@@ -549,6 +644,9 @@
     }
 
     public void testAppCacheEnabled() throws Throwable {
+        if (!NullWebViewUtils.isWebViewAvailable()) {
+            return;
+        }
         // Note that the AppCache path can only be set once. This limits the
         // amount of testing we can do, and means that we must test all aspects
         // of setting the AppCache path in a single test to guarantee ordering.
@@ -594,6 +692,9 @@
     // using a URL. Finally, it looks like enabling database requires creating a
     // webChromeClient and listening to Quota callbacks, which is not documented.
     public void testDatabaseDisabled() throws Throwable {
+        if (!NullWebViewUtils.isWebViewAvailable()) {
+            return;
+        }
         // Verify that websql database does not work when disabled.
         startWebServer();
 
@@ -612,6 +713,9 @@
     }
 
     public void testLoadsImagesAutomatically() throws Throwable {
+        if (!NullWebViewUtils.isWebViewAvailable()) {
+            return;
+        }
         assertTrue(mSettings.getLoadsImagesAutomatically());
 
         startWebServer();
@@ -644,6 +748,9 @@
     }
 
     public void testBlockNetworkImage() throws Throwable {
+        if (!NullWebViewUtils.isWebViewAvailable()) {
+            return;
+        }
         assertFalse(mSettings.getBlockNetworkImage());
 
         startWebServer();
@@ -673,6 +780,9 @@
     }
 
     public void testBlockNetworkLoads() throws Throwable {
+        if (!NullWebViewUtils.isWebViewAvailable()) {
+            return;
+        }
         assertFalse(mSettings.getBlockNetworkLoads());
 
         startWebServer();
@@ -709,6 +819,9 @@
 
     // Verify that an image in local file system can be loaded by an asset
     public void testLocalImageLoads() throws Throwable {
+        if (!NullWebViewUtils.isWebViewAvailable()) {
+            return;
+        }
 
         mSettings.setJavaScriptEnabled(true);
         // Check that local images are loaded without issues regardless of domain checkings
@@ -723,6 +836,9 @@
     // Verify that javascript cross-domain request permissions matches file domain settings
     // for iframes
     public void testIframesWhenAccessFromFileURLsEnabled() throws Throwable {
+        if (!NullWebViewUtils.isWebViewAvailable()) {
+            return;
+        }
 
         mSettings.setJavaScriptEnabled(true);
         // disable universal access from files
@@ -739,6 +855,9 @@
     // Verify that javascript cross-domain request permissions matches file domain settings
     // for iframes
     public void testIframesWhenAccessFromFileURLsDisabled() throws Throwable {
+        if (!NullWebViewUtils.isWebViewAvailable()) {
+            return;
+        }
 
         mSettings.setJavaScriptEnabled(true);
         // disable universal access from files
@@ -757,11 +876,17 @@
 
     // Verify that enabling file access from file URLs enable XmlHttpRequest (XHR) across files
     public void testXHRWhenAccessFromFileURLsEnabled() throws Throwable {
+        if (!NullWebViewUtils.isWebViewAvailable()) {
+            return;
+        }
         verifyFileXHR(true);
     }
 
     // Verify that disabling file access from file URLs disable XmlHttpRequest (XHR) accross files
     public void testXHRWhenAccessFromFileURLsDisabled() throws Throwable {
+        if (!NullWebViewUtils.isWebViewAvailable()) {
+            return;
+        }
 
         final ChromeClient webChromeClient = new ChromeClient(mOnUiThread);
         mOnUiThread.setWebChromeClient(webChromeClient);
diff --git a/tests/tests/webkit/src/android/webkit/cts/WebViewClientTest.java b/tests/tests/webkit/src/android/webkit/cts/WebViewClientTest.java
index 9aca8c7..5907d2f 100644
--- a/tests/tests/webkit/src/android/webkit/cts/WebViewClientTest.java
+++ b/tests/tests/webkit/src/android/webkit/cts/WebViewClientTest.java
@@ -47,18 +47,24 @@
     protected void setUp() throws Exception {
         super.setUp();
         final WebViewStubActivity activity = getActivity();
-        new PollingCheck(TEST_TIMEOUT) {
-            @Override
-                protected boolean check() {
-                return activity.hasWindowFocus();
-            }
-        }.run();
-        mOnUiThread = new WebViewOnUiThread(this, activity.getWebView());
+        WebView webview = activity.getWebView();
+        if (webview != null) {
+            new PollingCheck(TEST_TIMEOUT) {
+                @Override
+                    protected boolean check() {
+                    return activity.hasWindowFocus();
+                }
+            }.run();
+
+            mOnUiThread = new WebViewOnUiThread(this, webview);
+        }
     }
 
     @Override
     protected void tearDown() throws Exception {
-        mOnUiThread.cleanUp();
+        if (mOnUiThread != null) {
+            mOnUiThread.cleanUp();
+        }
         if (mWebServer != null) {
             mWebServer.shutdown();
         }
@@ -67,12 +73,18 @@
 
     // Verify that the shouldoverrideurlloading is false by default
     public void testShouldOverrideUrlLoadingDefault() {
+        if (!NullWebViewUtils.isWebViewAvailable()) {
+            return;
+        }
         final WebViewClient webViewClient = new WebViewClient();
         assertFalse(webViewClient.shouldOverrideUrlLoading(mOnUiThread.getWebView(), null));
     }
 
     // Verify shouldoverrideurlloading called on top level navigation
     public void testShouldOverrideUrlLoading() {
+        if (!NullWebViewUtils.isWebViewAvailable()) {
+            return;
+        }
         final MockWebViewClient webViewClient = new MockWebViewClient();
         mOnUiThread.setWebViewClient(webViewClient);
         mOnUiThread.getSettings().setJavaScriptEnabled(true);
@@ -87,6 +99,9 @@
     // Verify shouldoverrideurlloading called on webview called via onCreateWindow
     // TODO(sgurun) upstream this test to Aw.
     public void testShouldOverrideUrlLoadingOnCreateWindow() throws Exception {
+        if (!NullWebViewUtils.isWebViewAvailable()) {
+            return;
+        }
         mWebServer = new CtsTestServer(getActivity());
         // WebViewClient for main window
         final MockWebViewClient mainWebViewClient = new MockWebViewClient();
@@ -152,6 +167,9 @@
     }
 
     public void testLoadPage() throws Exception {
+        if (!NullWebViewUtils.isWebViewAvailable()) {
+            return;
+        }
         final MockWebViewClient webViewClient = new MockWebViewClient();
         mOnUiThread.setWebViewClient(webViewClient);
         mWebServer = new CtsTestServer(getActivity());
@@ -185,6 +203,9 @@
     }
 
     public void testOnReceivedError() throws Exception {
+        if (!NullWebViewUtils.isWebViewAvailable()) {
+            return;
+        }
         final MockWebViewClient webViewClient = new MockWebViewClient();
         mOnUiThread.setWebViewClient(webViewClient);
 
@@ -196,6 +217,9 @@
     }
 
     public void testOnFormResubmission() throws Exception {
+        if (!NullWebViewUtils.isWebViewAvailable()) {
+            return;
+        }
         final MockWebViewClient webViewClient = new MockWebViewClient();
         mOnUiThread.setWebViewClient(webViewClient);
         final WebSettings settings = mOnUiThread.getSettings();
@@ -221,6 +245,9 @@
     }
 
     public void testDoUpdateVisitedHistory() throws Exception {
+        if (!NullWebViewUtils.isWebViewAvailable()) {
+            return;
+        }
         final MockWebViewClient webViewClient = new MockWebViewClient();
         mOnUiThread.setWebViewClient(webViewClient);
         mWebServer = new CtsTestServer(getActivity());
@@ -239,6 +266,9 @@
     }
 
     public void testOnReceivedHttpAuthRequest() throws Exception {
+        if (!NullWebViewUtils.isWebViewAvailable()) {
+            return;
+        }
         final MockWebViewClient webViewClient = new MockWebViewClient();
         mOnUiThread.setWebViewClient(webViewClient);
         mWebServer = new CtsTestServer(getActivity());
@@ -250,6 +280,9 @@
     }
 
     public void testShouldOverrideKeyEvent() {
+        if (!NullWebViewUtils.isWebViewAvailable()) {
+            return;
+        }
         final MockWebViewClient webViewClient = new MockWebViewClient();
         mOnUiThread.setWebViewClient(webViewClient);
 
@@ -257,6 +290,9 @@
     }
 
     public void testOnUnhandledKeyEvent() throws Throwable {
+        if (!NullWebViewUtils.isWebViewAvailable()) {
+            return;
+        }
         requireLoadedPage();
         final MockWebViewClient webViewClient = new MockWebViewClient();
         mOnUiThread.setWebViewClient(webViewClient);
@@ -276,6 +312,9 @@
     }
 
     public void testOnScaleChanged() throws Throwable {
+        if (!NullWebViewUtils.isWebViewAvailable()) {
+            return;
+        }
         final MockWebViewClient webViewClient = new MockWebViewClient();
         mOnUiThread.setWebViewClient(webViewClient);
         mWebServer = new CtsTestServer(getActivity());
@@ -301,6 +340,9 @@
     }
 
     private void requireLoadedPage() throws Throwable {
+        if (!NullWebViewUtils.isWebViewAvailable()) {
+            return;
+        }
         mOnUiThread.loadUrlAndWaitForCompletion("about:blank");
     }
 
diff --git a/tests/tests/webkit/src/android/webkit/cts/WebViewStartupTest.java b/tests/tests/webkit/src/android/webkit/cts/WebViewStartupTest.java
index a7ee974..56f8f61 100644
--- a/tests/tests/webkit/src/android/webkit/cts/WebViewStartupTest.java
+++ b/tests/tests/webkit/src/android/webkit/cts/WebViewStartupTest.java
@@ -63,9 +63,17 @@
                 Log.i(TAG, "done setting cookie before creating webview");
             }
         });
+        NullWebViewUtils.NullWebViewFromThreadExceptionHandler h =
+                new NullWebViewUtils.NullWebViewFromThreadExceptionHandler();
+
+        background.setUncaughtExceptionHandler(h);
         background.start();
         background.join();
 
+        if (!h.isWebViewAvailable(mActivity)) {
+            return;
+        }
+
         // Now create WebView and test that setting the cookie beforehand really worked.
         mActivity.createAndAttachWebView();
         WebViewOnUiThread onUiThread = new WebViewOnUiThread(this, mActivity.getWebView());
diff --git a/tests/tests/webkit/src/android/webkit/cts/WebViewTest.java b/tests/tests/webkit/src/android/webkit/cts/WebViewTest.java
index d8d9f12..982acfc 100644
--- a/tests/tests/webkit/src/android/webkit/cts/WebViewTest.java
+++ b/tests/tests/webkit/src/android/webkit/cts/WebViewTest.java
@@ -131,23 +131,28 @@
     protected void setUp() throws Exception {
         super.setUp();
         final WebViewStubActivity activity = getActivity();
-        new PollingCheck() {
-            @Override
-                protected boolean check() {
-                return activity.hasWindowFocus();
-            }
-        }.run();
         mWebView = activity.getWebView();
-        File f = activity.getFileStreamPath("snapshot");
-        if (f.exists()) {
-            f.delete();
+        if (mWebView != null) {
+            new PollingCheck() {
+                @Override
+                    protected boolean check() {
+                        return activity.hasWindowFocus();
+                }
+            }.run();
+            File f = activity.getFileStreamPath("snapshot");
+            if (f.exists()) {
+                f.delete();
+            }
+
+            mOnUiThread = new WebViewOnUiThread(this, mWebView);
         }
-        mOnUiThread = new WebViewOnUiThread(this, mWebView);
     }
 
     @Override
     protected void tearDown() throws Exception {
-        mOnUiThread.cleanUp();
+        if (mOnUiThread != null) {
+            mOnUiThread.cleanUp();
+        }
         if (mWebServer != null) {
             stopWebServer();
         }
@@ -178,6 +183,10 @@
 
     @UiThreadTest
     public void testConstructor() {
+        if (!NullWebViewUtils.isWebViewAvailable()) {
+            return;
+        }
+
         new WebView(getActivity());
         new WebView(getActivity(), null);
         new WebView(getActivity(), null, 0);
@@ -185,12 +194,19 @@
 
     @UiThreadTest
     public void testCreatingWebViewCreatesCookieSyncManager() throws Exception {
+        if (!NullWebViewUtils.isWebViewAvailable()) {
+            return;
+        }
         new WebView(getActivity());
         assertNotNull(CookieSyncManager.getInstance());
     }
 
     @UiThreadTest
     public void testFindAddress() {
+        if (!NullWebViewUtils.isWebViewAvailable()) {
+            return;
+        }
+
         /*
          * Info about USPS
          * http://en.wikipedia.org/wiki/Postal_address#United_States
@@ -206,19 +222,25 @@
     @SuppressWarnings("deprecation")
     @UiThreadTest
     public void testGetZoomControls() {
-         WebSettings settings = mWebView.getSettings();
-         assertTrue(settings.supportZoom());
-         View zoomControls = mWebView.getZoomControls();
-         assertNotNull(zoomControls);
+        if (!NullWebViewUtils.isWebViewAvailable()) {
+            return;
+        }
+        WebSettings settings = mWebView.getSettings();
+        assertTrue(settings.supportZoom());
+        View zoomControls = mWebView.getZoomControls();
+        assertNotNull(zoomControls);
 
-         // disable zoom support
-         settings.setSupportZoom(false);
-         assertFalse(settings.supportZoom());
-         assertNull(mWebView.getZoomControls());
+        // disable zoom support
+        settings.setSupportZoom(false);
+        assertFalse(settings.supportZoom());
+        assertNull(mWebView.getZoomControls());
     }
 
     @UiThreadTest
     public void testInvokeZoomPicker() throws Exception {
+        if (!NullWebViewUtils.isWebViewAvailable()) {
+            return;
+        }
         WebSettings settings = mWebView.getSettings();
         assertTrue(settings.supportZoom());
         startWebServer(false);
@@ -228,6 +250,10 @@
     }
 
     public void testZoom() throws Throwable {
+        if (!NullWebViewUtils.isWebViewAvailable()) {
+            return;
+        }
+
         // Pinch zoom is not supported in wrap_content layouts.
         mOnUiThread.setLayoutHeightToMatchParent();
 
@@ -314,6 +340,10 @@
 
     @UiThreadTest
     public void testSetScrollBarStyle() {
+        if (!NullWebViewUtils.isWebViewAvailable()) {
+            return;
+        }
+
         mWebView.setScrollBarStyle(View.SCROLLBARS_INSIDE_INSET);
         assertFalse(mWebView.overlayHorizontalScrollbar());
         assertFalse(mWebView.overlayVerticalScrollbar());
@@ -333,6 +363,10 @@
 
     @UiThreadTest
     public void testScrollBarOverlay() throws Throwable {
+        if (!NullWebViewUtils.isWebViewAvailable()) {
+            return;
+        }
+
         mWebView.setHorizontalScrollbarOverlay(true);
         mWebView.setVerticalScrollbarOverlay(false);
         assertTrue(mWebView.overlayHorizontalScrollbar());
@@ -346,6 +380,10 @@
 
     @UiThreadTest
     public void testLoadUrl() throws Exception {
+        if (!NullWebViewUtils.isWebViewAvailable()) {
+            return;
+        }
+
         assertNull(mWebView.getUrl());
         assertNull(mWebView.getOriginalUrl());
         assertEquals(INITIAL_PROGRESS, mWebView.getProgress());
@@ -399,6 +437,10 @@
 
     @UiThreadTest
     public void testLoadUrlDoesNotStripParamsWhenLoadingContentUrls() throws Exception {
+        if (!NullWebViewUtils.isWebViewAvailable()) {
+            return;
+        }
+
         Uri.Builder uriBuilder = new Uri.Builder().scheme(
                 ContentResolver.SCHEME_CONTENT).authority(MockContentProvider.AUTHORITY);
         uriBuilder.appendPath("foo.html").appendQueryParameter("param","bar");
@@ -411,6 +453,10 @@
 
     @UiThreadTest
     public void testAppInjectedXRequestedWithHeaderIsNotOverwritten() throws Exception {
+        if (!NullWebViewUtils.isWebViewAvailable()) {
+            return;
+        }
+
         startWebServer(false);
         String url = mWebServer.getAssetUrl(TestHtmlConstants.HELLO_WORLD_URL);
         HashMap<String, String> map = new HashMap<String, String>();
@@ -430,6 +476,10 @@
 
     @UiThreadTest
     public void testAppCanInjectHeadersViaImmutableMap() throws Exception {
+        if (!NullWebViewUtils.isWebViewAvailable()) {
+            return;
+        }
+
         startWebServer(false);
         String url = mWebServer.getAssetUrl(TestHtmlConstants.HELLO_WORLD_URL);
         HashMap<String, String> map = new HashMap<String, String>();
@@ -472,6 +522,10 @@
     @SuppressWarnings("deprecation")
     @UiThreadTest
     public void testGetVisibleTitleHeight() throws Exception {
+        if (!NullWebViewUtils.isWebViewAvailable()) {
+            return;
+        }
+
         startWebServer(false);
         String url = mWebServer.getAssetUrl(TestHtmlConstants.HELLO_WORLD_URL);
         mOnUiThread.loadUrlAndWaitForCompletion(url);
@@ -480,6 +534,10 @@
 
     @UiThreadTest
     public void testGetOriginalUrl() throws Throwable {
+        if (!NullWebViewUtils.isWebViewAvailable()) {
+            return;
+        }
+
         startWebServer(false);
         final String finalUrl = mWebServer.getAssetUrl(TestHtmlConstants.HELLO_WORLD_URL);
         final String redirectUrl =
@@ -500,6 +558,10 @@
     }
 
     public void testStopLoading() throws Exception {
+        if (!NullWebViewUtils.isWebViewAvailable()) {
+            return;
+        }
+
         assertEquals(INITIAL_PROGRESS, mOnUiThread.getProgress());
 
         startWebServer(false);
@@ -535,6 +597,10 @@
 
     @UiThreadTest
     public void testGoBackAndForward() throws Exception {
+        if (!NullWebViewUtils.isWebViewAvailable()) {
+            return;
+        }
+
         assertGoBackOrForwardBySteps(false, -1);
         assertGoBackOrForwardBySteps(false, 1);
 
@@ -581,6 +647,10 @@
 
     @UiThreadTest
     public void testAddJavascriptInterface() throws Exception {
+        if (!NullWebViewUtils.isWebViewAvailable()) {
+            return;
+        }
+
         WebSettings settings = mWebView.getSettings();
         settings.setJavaScriptEnabled(true);
         settings.setJavaScriptCanOpenWindowsAutomatically(true);
@@ -651,6 +721,10 @@
 
     @UiThreadTest
     public void testAddJavascriptInterfaceNullObject() throws Exception {
+        if (!NullWebViewUtils.isWebViewAvailable()) {
+            return;
+        }
+
         WebSettings settings = mWebView.getSettings();
         settings.setJavaScriptEnabled(true);
         String setTitleToPropertyTypeHtml = "<html><head></head>" +
@@ -683,6 +757,10 @@
 
     @UiThreadTest
     public void testRemoveJavascriptInterface() throws Exception {
+        if (!NullWebViewUtils.isWebViewAvailable()) {
+            return;
+        }
+
         WebSettings settings = mWebView.getSettings();
         settings.setJavaScriptEnabled(true);
         String setTitleToPropertyTypeHtml = "<html><head></head>" +
@@ -702,6 +780,10 @@
     }
 
     public void testUseRemovedJavascriptInterface() throws Throwable {
+        if (!NullWebViewUtils.isWebViewAvailable()) {
+            return;
+        }
+
         class RemovedObject {
             @Override
             @JavascriptInterface
@@ -785,6 +867,34 @@
         assertTrue(mJsInterfaceWasCalled.get());
     }
 
+    public void testJavascriptInterfaceCustomPropertiesClearedOnReload() throws Exception {
+        if (!NullWebViewUtils.isWebViewAvailable()) {
+            return;
+        }
+
+        mOnUiThread.getSettings().setJavaScriptEnabled(true);
+
+        class DummyJavaScriptInterface {
+        }
+        final DummyJavaScriptInterface obj = new DummyJavaScriptInterface();
+        mOnUiThread.addJavascriptInterface(obj, "dummy");
+        mOnUiThread.loadUrlAndWaitForCompletion("about:blank");
+
+        EvaluateJsResultPollingCheck jsResult;
+        jsResult = new EvaluateJsResultPollingCheck("42");
+        mOnUiThread.evaluateJavascript("dummy.custom_property = 42", jsResult);
+        jsResult.run();
+        jsResult = new EvaluateJsResultPollingCheck("true");
+        mOnUiThread.evaluateJavascript("'custom_property' in dummy", jsResult);
+        jsResult.run();
+
+        mOnUiThread.reload();
+
+        jsResult = new EvaluateJsResultPollingCheck("false");
+        mOnUiThread.evaluateJavascript("'custom_property' in dummy", jsResult);
+        jsResult.run();
+    }
+
     private final class TestPictureListener implements PictureListener {
         public int callCount;
 
@@ -822,6 +932,9 @@
     }
 
     public void testCapturePicture() throws Exception, Throwable {
+        if (!NullWebViewUtils.isWebViewAvailable()) {
+            return;
+        }
         final TestPictureListener listener = new TestPictureListener();
 
         startWebServer(false);
@@ -846,6 +959,9 @@
     }
 
     public void testSetPictureListener() throws Exception, Throwable {
+        if (!NullWebViewUtils.isWebViewAvailable()) {
+            return;
+        }
         final class MyPictureListener implements PictureListener {
             public int callCount;
             public WebView webView;
@@ -889,6 +1005,9 @@
 
     @UiThreadTest
     public void testAccessHttpAuthUsernamePassword() {
+        if (!NullWebViewUtils.isWebViewAvailable()) {
+            return;
+        }
         try {
             WebViewDatabase.getInstance(getActivity()).clearHttpAuthUsernamePassword();
 
@@ -950,6 +1069,9 @@
     }
 
     public void testLoadData() throws Throwable {
+        if (!NullWebViewUtils.isWebViewAvailable()) {
+            return;
+        }
         final String HTML_CONTENT =
                 "<html><head><title>Hello,World!</title></head><body></body>" +
                 "</html>";
@@ -978,6 +1100,9 @@
 
     @UiThreadTest
     public void testLoadDataWithBaseUrl() throws Throwable {
+        if (!NullWebViewUtils.isWebViewAvailable()) {
+            return;
+        }
         assertNull(mWebView.getUrl());
         String imgUrl = TestHtmlConstants.SMALL_IMG_URL; // relative
         // Snippet of HTML that will prevent favicon requests to the test server.
@@ -1063,6 +1188,9 @@
     }
 
     public void testFindAll()  throws Throwable {
+        if (!NullWebViewUtils.isWebViewAvailable()) {
+            return;
+        }
         // Make the page scrollable, so we can detect the scrolling to make sure the
         // content fully loaded.
         mOnUiThread.setInitialScale(100);
@@ -1087,6 +1215,9 @@
     }
 
     public void testFindNext() throws Throwable {
+        if (!NullWebViewUtils.isWebViewAvailable()) {
+            return;
+        }
         // Reset the scaling so that finding the next "all" text will require scrolling.
         mOnUiThread.setInitialScale(100);
 
@@ -1143,6 +1274,9 @@
     }
 
     public void testDocumentHasImages() throws Exception, Throwable {
+        if (!NullWebViewUtils.isWebViewAvailable()) {
+            return;
+        }
         final class DocumentHasImageCheckHandler extends Handler {
             private boolean mReceived;
             private int mMsgArg1;
@@ -1192,6 +1326,9 @@
     }
 
     public void testPageScroll() throws Throwable {
+        if (!NullWebViewUtils.isWebViewAvailable()) {
+            return;
+        }
         DisplayMetrics metrics = mOnUiThread.getDisplayMetrics();
         int dimension = 2 * Math.max(metrics.widthPixels, metrics.heightPixels);
         String p = "<p style=\"height:" + dimension + "px;\">" +
@@ -1236,6 +1373,9 @@
     }
 
     public void testGetContentHeight() throws Throwable {
+        if (!NullWebViewUtils.isWebViewAvailable()) {
+            return;
+        }
         mOnUiThread.loadDataAndWaitForCompletion(
                 "<html><body></body></html>", "text/html", null);
         new PollingCheck() {
@@ -1274,12 +1414,18 @@
 
     @UiThreadTest
     public void testPlatformNotifications() {
+        if (!NullWebViewUtils.isWebViewAvailable()) {
+            return;
+        }
         WebView.enablePlatformNotifications();
         WebView.disablePlatformNotifications();
     }
 
     @UiThreadTest
     public void testAccessPluginList() {
+        if (!NullWebViewUtils.isWebViewAvailable()) {
+            return;
+        }
         assertNotNull(WebView.getPluginList());
 
         // can not find a way to install plugins
@@ -1288,12 +1434,18 @@
 
     @UiThreadTest
     public void testDestroy() {
+        if (!NullWebViewUtils.isWebViewAvailable()) {
+            return;
+        }
         // Create a new WebView, since we cannot call destroy() on a view in the hierarchy
         WebView localWebView = new WebView(getActivity());
         localWebView.destroy();
     }
 
     public void testFlingScroll() throws Throwable {
+        if (!NullWebViewUtils.isWebViewAvailable()) {
+            return;
+        }
         DisplayMetrics metrics = mOnUiThread.getDisplayMetrics();
         final int dimension = 10 * Math.max(metrics.widthPixels, metrics.heightPixels);
         String p = "<p style=\"height:" + dimension + "px;" +
@@ -1323,6 +1475,9 @@
     }
 
     public void testRequestFocusNodeHref() throws Throwable {
+        if (!NullWebViewUtils.isWebViewAvailable()) {
+            return;
+        }
         startWebServer(false);
         String url1 = mWebServer.getAssetUrl(TestHtmlConstants.HTML_URL1);
         String url2 = mWebServer.getAssetUrl(TestHtmlConstants.HTML_URL2);
@@ -1390,6 +1545,9 @@
     }
 
     public void testRequestImageRef() throws Exception, Throwable {
+        if (!NullWebViewUtils.isWebViewAvailable()) {
+            return;
+        }
         final class ImageLoaded {
             public boolean mImageLoaded;
 
@@ -1470,10 +1628,16 @@
 
     @UiThreadTest
     public void testDebugDump() {
+        if (!NullWebViewUtils.isWebViewAvailable()) {
+            return;
+        }
         mWebView.debugDump();
     }
 
     public void testGetHitTestResult() throws Throwable {
+        if (!NullWebViewUtils.isWebViewAvailable()) {
+            return;
+        }
         final String anchor = "<p><a href=\"" + TestHtmlConstants.EXT_WEB_URL1
                 + "\">normal anchor</a></p>";
         final String blankAnchor = "<p><a href=\"\">blank anchor</a></p>";
@@ -1535,6 +1699,9 @@
     }
 
     public void testSetInitialScale() throws Throwable {
+        if (!NullWebViewUtils.isWebViewAvailable()) {
+            return;
+        }
         final String p = "<p style=\"height:1000px;width:1000px\">Test setInitialScale.</p>";
         final float defaultScale =
             getInstrumentation().getTargetContext().getResources().getDisplayMetrics().density;
@@ -1586,6 +1753,9 @@
 
     @UiThreadTest
     public void testClearHistory() throws Exception {
+        if (!NullWebViewUtils.isWebViewAvailable()) {
+            return;
+        }
         startWebServer(false);
         String url1 = mWebServer.getAssetUrl(TestHtmlConstants.HTML_URL1);
         String url2 = mWebServer.getAssetUrl(TestHtmlConstants.HTML_URL2);
@@ -1608,6 +1778,9 @@
 
     @UiThreadTest
     public void testSaveAndRestoreState() throws Throwable {
+        if (!NullWebViewUtils.isWebViewAvailable()) {
+            return;
+        }
         // nothing to save
         assertNull(mWebView.saveState(new Bundle()));
 
@@ -1670,6 +1843,9 @@
     }
 
     public void testSetWebViewClient() throws Throwable {
+        if (!NullWebViewUtils.isWebViewAvailable()) {
+            return;
+        }
         final ScaleChangedWebViewClient webViewClient = new ScaleChangedWebViewClient();
         mOnUiThread.setWebViewClient(webViewClient);
         startWebServer(false);
@@ -1685,6 +1861,9 @@
 
     @UiThreadTest
     public void testInsecureSiteClearsCertificate() throws Throwable {
+        if (!NullWebViewUtils.isWebViewAvailable()) {
+            return;
+        }
         final class MockWebViewClient extends WaitForLoadedClient {
             public MockWebViewClient() {
                 super(mOnUiThread);
@@ -1713,6 +1892,9 @@
 
     @UiThreadTest
     public void testSecureSiteSetsCertificate() throws Throwable {
+        if (!NullWebViewUtils.isWebViewAvailable()) {
+            return;
+        }
         final class MockWebViewClient extends WaitForLoadedClient {
             public MockWebViewClient() {
                 super(mOnUiThread);
@@ -1741,6 +1923,9 @@
 
     @UiThreadTest
     public void testClearSslPreferences() throws Throwable {
+        if (!NullWebViewUtils.isWebViewAvailable()) {
+            return;
+        }
         // Load the first page. We expect a call to
         // WebViewClient.onReceivedSslError().
         final SslErrorWebViewClient webViewClient = new SslErrorWebViewClient();
@@ -1768,6 +1953,9 @@
     }
 
     public void testOnReceivedSslError() throws Throwable {
+        if (!NullWebViewUtils.isWebViewAvailable()) {
+            return;
+        }
         final class MockWebViewClient extends WaitForLoadedClient {
             private String mErrorUrl;
             private WebView mWebView;
@@ -1801,6 +1989,9 @@
     }
 
     public void testOnReceivedSslErrorProceed() throws Throwable {
+        if (!NullWebViewUtils.isWebViewAvailable()) {
+            return;
+        }
         final class MockWebViewClient extends WaitForLoadedClient {
             public MockWebViewClient() {
                 super(mOnUiThread);
@@ -1819,6 +2010,9 @@
     }
 
     public void testOnReceivedSslErrorCancel() throws Throwable {
+        if (!NullWebViewUtils.isWebViewAvailable()) {
+            return;
+        }
         final class MockWebViewClient extends WaitForLoadedClient {
             public MockWebViewClient() {
                 super(mOnUiThread);
@@ -1838,6 +2032,9 @@
     }
 
     public void testSslErrorProceedResponseReusedForSameHost() throws Throwable {
+        if (!NullWebViewUtils.isWebViewAvailable()) {
+            return;
+        }
         // Load the first page. We expect a call to
         // WebViewClient.onReceivedSslError().
         final SslErrorWebViewClient webViewClient = new SslErrorWebViewClient();
@@ -1858,6 +2055,9 @@
     }
 
     public void testSslErrorProceedResponseNotReusedForDifferentHost() throws Throwable {
+        if (!NullWebViewUtils.isWebViewAvailable()) {
+            return;
+        }
         // Load the first page. We expect a call to
         // WebViewClient.onReceivedSslError().
         final SslErrorWebViewClient webViewClient = new SslErrorWebViewClient();
@@ -1910,6 +2110,9 @@
     }
 
     public void testRequestChildRectangleOnScreen() throws Throwable {
+        if (!NullWebViewUtils.isWebViewAvailable()) {
+            return;
+        }
         DisplayMetrics metrics = mOnUiThread.getDisplayMetrics();
         final int dimension = 2 * Math.max(metrics.widthPixels, metrics.heightPixels);
         String p = "<p style=\"height:" + dimension + "px;width:" + dimension + "px\">&nbsp;</p>";
@@ -1933,6 +2136,10 @@
     }
 
     public void testSetDownloadListener() throws Throwable {
+        if (!NullWebViewUtils.isWebViewAvailable()) {
+            return;
+        }
+
         final CountDownLatch resultLatch = new CountDownLatch(1);
         final class MyDownloadListener implements DownloadListener {
             public String url;
@@ -1979,6 +2186,9 @@
 
     @UiThreadTest
     public void testSetLayoutParams() {
+        if (!NullWebViewUtils.isWebViewAvailable()) {
+            return;
+        }
         LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(600, 800);
         mWebView.setLayoutParams(params);
         assertSame(params, mWebView.getLayoutParams());
@@ -1986,10 +2196,16 @@
 
     @UiThreadTest
     public void testSetMapTrackballToArrowKeys() {
+        if (!NullWebViewUtils.isWebViewAvailable()) {
+            return;
+        }
         mWebView.setMapTrackballToArrowKeys(true);
     }
 
     public void testSetNetworkAvailable() throws Exception {
+        if (!NullWebViewUtils.isWebViewAvailable()) {
+            return;
+        }
         WebSettings settings = mOnUiThread.getSettings();
         settings.setJavaScriptEnabled(true);
         startWebServer(false);
@@ -2020,6 +2236,9 @@
     }
 
     public void testSetWebChromeClient() throws Throwable {
+        if (!NullWebViewUtils.isWebViewAvailable()) {
+            return;
+        }
         final class MockWebChromeClient extends WaitForProgressClient {
             private boolean mOnProgressChanged = false;
 
@@ -2057,6 +2276,9 @@
     }
 
     public void testPauseResumeTimers() throws Throwable {
+        if (!NullWebViewUtils.isWebViewAvailable()) {
+            return;
+        }
         class Monitor {
             private boolean mIsUpdated;
 
@@ -2112,6 +2334,9 @@
 
     // verify query parameters can be passed correctly to android asset files
     public void testAndroidAssetQueryParam() {
+        if (!NullWebViewUtils.isWebViewAvailable()) {
+            return;
+        }
 
         WebSettings settings = mOnUiThread.getSettings();
         settings.setJavaScriptEnabled(true);
@@ -2123,6 +2348,9 @@
 
     // verify anchors work correctly for android asset files
     public void testAndroidAssetAnchor() {
+        if (!NullWebViewUtils.isWebViewAvailable()) {
+            return;
+        }
 
         WebSettings settings = mOnUiThread.getSettings();
         settings.setJavaScriptEnabled(true);
@@ -2133,6 +2361,9 @@
     }
 
     public void testEvaluateJavascript() {
+        if (!NullWebViewUtils.isWebViewAvailable()) {
+            return;
+        }
         mOnUiThread.getSettings().setJavaScriptEnabled(true);
         mOnUiThread.loadUrlAndWaitForCompletion("about:blank");
 
@@ -2156,6 +2387,9 @@
 
     // Verify Print feature can create a PDF file with a correct preamble.
     public void testPrinting() throws Throwable {
+        if (!NullWebViewUtils.isWebViewAvailable()) {
+            return;
+        }
         mOnUiThread.loadDataAndWaitForCompletion("<html><head></head>" +
                 "<body>foo</body></html>",
                 "text/html", null);
diff --git a/tests/tests/webkit/src/android/webkit/cts/WebView_WebViewTransportTest.java b/tests/tests/webkit/src/android/webkit/cts/WebView_WebViewTransportTest.java
index dd784be..cb72ef0 100644
--- a/tests/tests/webkit/src/android/webkit/cts/WebView_WebViewTransportTest.java
+++ b/tests/tests/webkit/src/android/webkit/cts/WebView_WebViewTransportTest.java
@@ -31,6 +31,9 @@
 
     @UiThreadTest
     public void testAccessWebView() {
+        if (!NullWebViewUtils.isWebViewAvailable()) {
+            return;
+        }
         WebView webView = getActivity().getWebView();
         WebViewTransport transport = webView.new WebViewTransport();
 
diff --git a/tests/tests/widget/src/android/widget/cts/RemoteViewsActivityTest.java b/tests/tests/widget/src/android/widget/cts/RemoteViewsActivityTest.java
index 758afd7..b3c0915 100644
--- a/tests/tests/widget/src/android/widget/cts/RemoteViewsActivityTest.java
+++ b/tests/tests/widget/src/android/widget/cts/RemoteViewsActivityTest.java
@@ -23,6 +23,7 @@
 import android.view.InflateException;
 import android.view.View;
 import android.view.ViewGroup;
+import android.webkit.cts.NullWebViewUtils;
 import android.widget.RemoteViews;
 
 import com.android.cts.stub.R;
@@ -96,6 +97,9 @@
 
     @MediumTest
     public void testWebView() throws Exception {
+        if (!NullWebViewUtils.isWebViewAvailable()) {
+            return;
+        }
         RemoteViews orig = new RemoteViews(PACKAGE_NAME, R.layout.remote_view_test_bad_2);
         Parcel p = Parcel.obtain();
         orig.writeToParcel(p, 0);
diff --git a/tools/tradefed-host/res/report/cts_result.xsl b/tools/tradefed-host/res/report/cts_result.xsl
index 2d8bb50..fe49308 100644
--- a/tools/tradefed-host/res/report/cts_result.xsl
+++ b/tools/tradefed-host/res/report/cts_result.xsl
@@ -538,15 +538,7 @@
                                                             <xsl:value-of select="@result"/>
                                                         </div>
                                                     </TD>
-                                                    <TD class="failuredetails">
-                                                        <div class="details">
-                                                            <ul>
-                                                              <xsl:for-each select="Details/ValueArray/Value">
-                                                                <li><xsl:value-of select="."/></li>
-                                                              </xsl:for-each>
-                                                            </ul>
-                                                        </div>
-                                                    </TD>
+                                                    <TD class="failuredetails"/>
                                                 </xsl:if>
 
                                                 <xsl:if test="@result='fail'">