Merge "CameraITS: fix DNG validation logic" into oreo-mr1-cts-dev
diff --git a/apps/CameraITS/build/envsetup.sh b/apps/CameraITS/build/envsetup.sh
index 03b45d1..13c907c 100644
--- a/apps/CameraITS/build/envsetup.sh
+++ b/apps/CameraITS/build/envsetup.sh
@@ -45,8 +45,8 @@
     print \"N/A\"
 ")
 
-echo $CV2_VER | grep -q "^2.4" || \
-    echo ">> Require python opencv 2.4. Got $CV2_VER" >&2
+echo $CV2_VER | grep -q -e "^2.4" -e "^3.2" || \
+    echo ">> Require python opencv 2.4. or 3.2. Got $CV2_VER" >&2
 
 export PYTHONPATH="$PWD/pymodules:$PYTHONPATH"
 
diff --git a/apps/CameraITS/pymodules/its/image.py b/apps/CameraITS/pymodules/its/image.py
index 24b48bb..c1bc0e2 100644
--- a/apps/CameraITS/pymodules/its/image.py
+++ b/apps/CameraITS/pymodules/its/image.py
@@ -642,10 +642,10 @@
     """
     hfull = img.shape[0]
     wfull = img.shape[1]
-    xtile = math.ceil(xnorm * wfull)
-    ytile = math.ceil(ynorm * hfull)
-    wtile = math.floor(wnorm * wfull)
-    htile = math.floor(hnorm * hfull)
+    xtile = int(math.ceil(xnorm * wfull))
+    ytile = int(math.ceil(ynorm * hfull))
+    wtile = int(math.floor(wnorm * wfull))
+    htile = int(math.floor(hnorm * hfull))
     return img[ytile:ytile+htile,xtile:xtile+wtile,:].copy()
 
 
diff --git a/apps/CameraITS/tests/scene0/test_metadata.py b/apps/CameraITS/tests/scene0/test_metadata.py
index 752e02b..e78488e 100644
--- a/apps/CameraITS/tests/scene0/test_metadata.py
+++ b/apps/CameraITS/tests/scene0/test_metadata.py
@@ -90,8 +90,8 @@
         pixel_pitch_w = (sensor_size["width"] / fmts[0]["width"] * 1E3)
         print "Assert pixel_pitch WxH: %.2f um, %.2f um" % (pixel_pitch_w,
                                                             pixel_pitch_h)
-        assert 1.0 <= pixel_pitch_w <= 10
-        assert 1.0 <= pixel_pitch_h <= 10
+        assert 0.9 <= pixel_pitch_w <= 10
+        assert 0.9 <= pixel_pitch_h <= 10
         assert 0.333 <= pixel_pitch_w/pixel_pitch_h <= 3.0
 
         diag = math.sqrt(sensor_size["height"] ** 2 +
diff --git a/apps/CameraITS/tests/scene4/test_aspect_ratio_and_crop.py b/apps/CameraITS/tests/scene4/test_aspect_ratio_and_crop.py
index 13dbe84..06db8bb 100644
--- a/apps/CameraITS/tests/scene4/test_aspect_ratio_and_crop.py
+++ b/apps/CameraITS/tests/scene4/test_aspect_ratio_and_crop.py
@@ -272,8 +272,13 @@
             cv2.THRESH_BINARY + cv2.THRESH_OTSU)
 
     # connected component
-    contours, hierarchy = cv2.findContours(255-img_bw, cv2.RETR_TREE,
-            cv2.CHAIN_APPROX_SIMPLE)
+    cv2_version = cv2.__version__
+    if cv2_version.startswith('2.4.'):
+        contours, hierarchy = cv2.findContours(255-img_bw, cv2.RETR_TREE,
+                cv2.CHAIN_APPROX_SIMPLE)
+    elif cv2_version.startswith('3.2.'):
+        _, contours, hierarchy = cv2.findContours(255-img_bw, cv2.RETR_TREE,
+                cv2.CHAIN_APPROX_SIMPLE)
 
     # Check each component and find the black circle
     min_cmpt = size[0] * size[1] * 0.005
diff --git a/apps/CtsVerifier/AndroidManifest.xml b/apps/CtsVerifier/AndroidManifest.xml
index 868cefb..7ebcdcd 100644
--- a/apps/CtsVerifier/AndroidManifest.xml
+++ b/apps/CtsVerifier/AndroidManifest.xml
@@ -18,7 +18,7 @@
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
       package="com.android.cts.verifier"
       android:versionCode="5"
-      android:versionName="8.1_r3">
+      android:versionName="8.1_r4">
 
     <uses-sdk android:minSdkVersion="19" android:targetSdkVersion="27"/>
 
diff --git a/apps/CtsVerifier/res/values/strings.xml b/apps/CtsVerifier/res/values/strings.xml
index d95843a..f3ab913 100755
--- a/apps/CtsVerifier/res/values/strings.xml
+++ b/apps/CtsVerifier/res/values/strings.xml
@@ -3037,7 +3037,7 @@
         Check that \'Dummy Input method\', along with all other non-system apps, are not enabled in Settings. Then disallow \'Dummy Input method\' from permitted input methods by turning on the switch below.
     </string>
     <string name="set_permitted_input_methods_action">
-        Enabling \'Dummy Input method\' in the list of accessibility services
+        Enabling \'Dummy Input method\' in the list of input methods
     </string>
     <string name="set_permitted_input_methods_widget_label">
         Allow only system input methods:
@@ -4038,7 +4038,7 @@
         This test requires that you have connected a mandated USB Audio Interface peripheral.
         Connect the outputs to the inputs (with patch cables). Start playback by pressing the
         \"Record Loopback\" button and verify that the recorded signal is displayed in the wave
-        display view. ()It may be necessary to adjust the input controls on the peripheral).
+        display view. (It may be necessary to adjust the input controls on the peripheral).
        </string>
 
     <!-- USB Audio Peripheral Buttons Test -->
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/audio/USBAudioPeripheralActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/audio/USBAudioPeripheralActivity.java
index 0c69790..7fdf403 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/audio/USBAudioPeripheralActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/audio/USBAudioPeripheralActivity.java
@@ -32,6 +32,7 @@
 
 public abstract class USBAudioPeripheralActivity extends PassFailButtons.Activity {
     private static final String TAG = "USBAudioPeripheralActivity";
+    private static final boolean DEBUG = false;
 
     // Profile
     protected ProfileManager mProfileManager = new ProfileManager();
@@ -77,6 +78,9 @@
     }
 
     private void showProfileStatus() {
+        if (DEBUG) {
+            Log.d(TAG, "showProfileStatus()" + (mSelectedProfile != null));
+        }
         if (mSelectedProfile != null) {
             mProfileNameTx.setText(mSelectedProfile.getName());
             mProfileDescriptionTx.setText(mSelectedProfile.getDescription());
@@ -88,11 +92,19 @@
 
     private void showPeripheralStatus() {
         if (mIsPeripheralAttached) {
+            String productName = "";
             if (mOutputDevInfo != null) {
-                mPeripheralNameTx.setText(mOutputDevInfo.getProductName().toString());
+                productName = mOutputDevInfo.getProductName().toString();
             } else if (mInputDevInfo != null) {
-                mPeripheralNameTx.setText(mInputDevInfo.getProductName().toString());
+                productName = mInputDevInfo.getProductName().toString();
             }
+            String ctrlText;
+            if (mSelectedProfile == null) {
+                ctrlText = productName + " - UNSUPPORTED";
+            } else {
+                ctrlText = productName;
+            }
+            mPeripheralNameTx.setText(ctrlText);
         } else {
             mPeripheralNameTx.setText("Disconnected");
         }
@@ -117,7 +129,9 @@
             }
         }
         mIsPeripheralAttached = mOutputDevInfo != null || mInputDevInfo != null;
-        // Log.i(TAG, "mIsPeripheralAttached: " + mIsPeripheralAttached);
+        if (DEBUG) {
+            Log.d(TAG, "mIsPeripheralAttached: " + mIsPeripheralAttached);
+        }
 
         // any associated profiles?
         if (mIsPeripheralAttached) {
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/audio/USBAudioPeripheralAttributesActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/audio/USBAudioPeripheralAttributesActivity.java
index 871c2a0..07a99da 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/audio/USBAudioPeripheralAttributesActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/audio/USBAudioPeripheralAttributesActivity.java
@@ -170,8 +170,8 @@
         } else {
             mTestStatusTx.setText("No Peripheral or No Matching Profile.");
         }
+
         // Headset not publicly available, violates CTS Verifier additional equipment guidelines.
-        // Allow skipping test. See b/67777923 for details.
-        getPassButton().setEnabled(true /*outPass && inPass*/);
+        getPassButton().setEnabled(outPass && inPass);
     }
 }
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/audio/USBAudioPeripheralButtonsActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/audio/USBAudioPeripheralButtonsActivity.java
index 861af28..2149ed7 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/audio/USBAudioPeripheralButtonsActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/audio/USBAudioPeripheralButtonsActivity.java
@@ -16,6 +16,7 @@
 
 package com.android.cts.verifier.audio;
 
+import android.content.res.Resources;
 import android.graphics.Color;
 import android.os.Bundle;
 import android.util.Log;
@@ -64,39 +65,15 @@
     }
 
     private void showButtonsState() {
-        if (mIsPeripheralAttached && mSelectedProfile != null) {
-            ProfileButtonAttributes mButtonAttributes = mSelectedProfile.getButtonAttributes();
-            if (mButtonAttributes != null) {
-                if (!mButtonAttributes.mHasBtnA) {
-                    mBtnALabelTxt.setTextColor(Color.GRAY);
-                    mBtnAStatusTxt.setTextColor(Color.GRAY);
-                } else {
-                    mBtnALabelTxt.setTextColor(Color.WHITE);
-                    mBtnAStatusTxt.setTextColor(Color.WHITE);
-                }
-                if (!mButtonAttributes.mHasBtnB) {
-                    mBtnBLabelTxt.setTextColor(Color.GRAY);
-                    mBtnBStatusTxt.setTextColor(Color.GRAY);
-                } else {
-                    mBtnBLabelTxt.setTextColor(Color.WHITE);
-                    mBtnBStatusTxt.setTextColor(Color.WHITE);
-                }
-                if (!mButtonAttributes.mHasBtnC) {
-                    mBtnCLabelTxt.setTextColor(Color.GRAY);
-                    mBtnCStatusTxt.setTextColor(Color.GRAY);
-                } else {
-                    mBtnCLabelTxt.setTextColor(Color.WHITE);
-                    mBtnCStatusTxt.setTextColor(Color.WHITE);
-                }
-            } else {
-                mBtnALabelTxt.setTextColor(Color.GRAY);
-                mBtnAStatusTxt.setTextColor(Color.GRAY);
-                mBtnBLabelTxt.setTextColor(Color.GRAY);
-                mBtnBStatusTxt.setTextColor(Color.GRAY);
-                mBtnCLabelTxt.setTextColor(Color.GRAY);
-                mBtnCStatusTxt.setTextColor(Color.GRAY);
-            }
-        }
+        int ctrlColor = mIsPeripheralAttached && mSelectedProfile != null
+                ? Color.WHITE
+                : Color.GRAY;
+        mBtnALabelTxt.setTextColor(ctrlColor);
+        mBtnAStatusTxt.setTextColor(ctrlColor);
+        mBtnBLabelTxt.setTextColor(ctrlColor);
+        mBtnBStatusTxt.setTextColor(ctrlColor);
+        mBtnCLabelTxt.setTextColor(ctrlColor);
+        mBtnCStatusTxt.setTextColor(ctrlColor);
 
         mBtnAStatusTxt.setText(getString(
             mHasBtnA ? R.string.uapButtonsRecognized : R.string.uapButtonsNotRecognized));
@@ -110,47 +87,51 @@
         if (mIsPeripheralAttached && mSelectedProfile != null) {
             ProfileButtonAttributes mButtonAttributes = mSelectedProfile.getButtonAttributes();
             boolean match = mButtonAttributes != null;
+            boolean interceptedVolume = getResources().getBoolean(Resources.getSystem()
+                .getIdentifier("config_handleVolumeKeysInWindowManager", "bool", "android"));
             if (match && mButtonAttributes.mHasBtnA != mHasBtnA) {
                 match = false;
             }
-            if (match && mButtonAttributes.mHasBtnB != mHasBtnB) {
-                match = false;
-            }
-            if (match && mButtonAttributes.mHasBtnC != mHasBtnC) {
-                match = false;
+            if (!interceptedVolume) {
+                if (match && mButtonAttributes.mHasBtnB != mHasBtnB) {
+                    match = false;
+                }
+                if (match && mButtonAttributes.mHasBtnC != mHasBtnC) {
+                    match = false;
+                }
             }
             Log.i(TAG, "match:" + match);
             getPassButton().setEnabled(match);
         } else {
-            // Headset not publicly available, violates CTS Verifier additional equipment
-            // guidelines. Allow skipping test. See b/67777923 for details.
-            getPassButton().setEnabled(true /*false*/);
+            getPassButton().setEnabled(false);
         }
     }
 
     @Override
     public boolean onKeyDown(int keyCode, KeyEvent event) {
         Log.i(TAG, "onKeyDown(" + keyCode + ")");
-        switch (keyCode) {
-        // Function A control event
-        case KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE:
-            mHasBtnA = true;
-            break;
-
-        // Function B control event
-        case KeyEvent.KEYCODE_VOLUME_UP:
-            mHasBtnB = true;
-            break;
-
-        // Function C control event
-        case KeyEvent.KEYCODE_VOLUME_DOWN:
-            mHasBtnC = true;
-            break;
+        if (mSelectedProfile != null) {
+            switch (keyCode) {
+            // Function A control event
+            case KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE:
+                mHasBtnA = true;
+                break;
+    
+            // Function B control event
+            case KeyEvent.KEYCODE_VOLUME_UP:
+                mHasBtnB = true;
+                break;
+    
+            // Function C control event
+            case KeyEvent.KEYCODE_VOLUME_DOWN:
+                mHasBtnC = true;
+                break;
+            }
+    
+            showButtonsState();
+            calculateMatch();
         }
 
-        showButtonsState();
-        calculateMatch();
-
         return super.onKeyDown(keyCode, event);
     }
 
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/audio/USBAudioPeripheralPlayActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/audio/USBAudioPeripheralPlayActivity.java
index b4b0999..640d489 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/audio/USBAudioPeripheralPlayActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/audio/USBAudioPeripheralPlayActivity.java
@@ -51,9 +51,9 @@
     //
     // USBAudioPeripheralActivity
     // Headset not publicly available, violates CTS Verifier additional equipment guidelines.
-    // Allow skipping test. See b/67777923 for details.
     public void updateConnectStatus() {
-        getPassButton().setEnabled(true /*mOutputDevInfo != null*/);
+        mPlayBtn.setEnabled(mIsPeripheralAttached && mSelectedProfile != null);
+        getPassButton().setEnabled(mSelectedProfile != null && mOutputDevInfo != null);
     }
 
     public class LocalClickListener implements View.OnClickListener {
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/audio/USBAudioPeripheralRecordActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/audio/USBAudioPeripheralRecordActivity.java
index e878c82..5772461 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/audio/USBAudioPeripheralRecordActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/audio/USBAudioPeripheralRecordActivity.java
@@ -134,10 +134,11 @@
 
     //
     // USBAudioPeripheralActivity
-    // Headset not publicly available, violates CTS Verifier additional equipment guidelines.
-    // Allow skipping test. See b/67777923 for details.
+    //
     public void updateConnectStatus() {
-        getPassButton().setEnabled(true /*mOutputDevInfo != null*/);
+        mRecordBtn.setEnabled(mIsPeripheralAttached && mSelectedProfile != null);
+        mRecordLoopbackBtn.setEnabled(mIsPeripheralAttached && mSelectedProfile != null);
+        getPassButton().setEnabled(mSelectedProfile != null && mOutputDevInfo != null);
     }
 
     public class LocalClickListener implements View.OnClickListener {
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/audio/peripheralprofile/PeripheralProfile.java b/apps/CtsVerifier/src/com/android/cts/verifier/audio/peripheralprofile/PeripheralProfile.java
index 4c3fbb8..a0cff31 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/audio/peripheralprofile/PeripheralProfile.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/audio/peripheralprofile/PeripheralProfile.java
@@ -148,7 +148,6 @@
     private static final String kAttr_HasBtnA = "HasBtnA";
     private static final String kAttr_HasBtnB = "HasBtnB";
     private static final String kAttr_HasBtnC = "HasBtnC";
-    private static final String kAttr_HasBtnD = "HasBtnD";
 
     private void parseProfileAttributes(ProfileAttributes attribs, String elementName,
                                         Attributes xmlAtts) {
@@ -164,7 +163,6 @@
         buttonAttributes.mHasBtnA = Integer.parseInt(xmlAtts.getValue(kAttr_HasBtnA)) == 1;
         buttonAttributes.mHasBtnB = Integer.parseInt(xmlAtts.getValue(kAttr_HasBtnB)) == 1;
         buttonAttributes.mHasBtnC = Integer.parseInt(xmlAtts.getValue(kAttr_HasBtnC)) == 1;
-        buttonAttributes.mHasBtnD = Integer.parseInt(xmlAtts.getValue(kAttr_HasBtnD)) == 1;
     }
 
     //
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/audio/peripheralprofile/ProfileButtonAttributes.java b/apps/CtsVerifier/src/com/android/cts/verifier/audio/peripheralprofile/ProfileButtonAttributes.java
index ffe5e6d..8bc4872 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/audio/peripheralprofile/ProfileButtonAttributes.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/audio/peripheralprofile/ProfileButtonAttributes.java
@@ -20,5 +20,4 @@
     public boolean mHasBtnA;
     public boolean mHasBtnB;
     public boolean mHasBtnC;
-    public boolean mHasBtnD;
 }
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/audio/peripheralprofile/ProfileManager.java b/apps/CtsVerifier/src/com/android/cts/verifier/audio/peripheralprofile/ProfileManager.java
index 59b20b0..ebb5991 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/audio/peripheralprofile/ProfileManager.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/audio/peripheralprofile/ProfileManager.java
@@ -18,6 +18,7 @@
 
 import android.os.Environment;
 import android.support.annotation.Nullable;
+import android.util.Log;
 import android.util.Xml;
 
 import org.xml.sax.Attributes;
@@ -40,6 +41,9 @@
 import javax.xml.parsers.SAXParserFactory;
 
 public class ProfileManager {
+    private static final String TAG = "ProfileManager";
+    private static final boolean DEBUG = false;
+
     private static final String mBuiltInprofiles =
             "<?xml version='1.0' encoding='UTF-8' standalone='yes' ?>" +
             "<ProfileList Version=\"1.0.0\">" +
@@ -57,8 +61,13 @@
               "<InputDevInfo ChanCounts=\"1,2\" ChanPosMasks=\"12,16\" ChanIndexMasks=\"3\" Encodings=\"4\" SampleRates=\"44100,48000,88200,96000\" />" +
             "</PeripheralProfile>" +
             "<PeripheralProfile ProfileName=\"AudioBox USB\" ProfileDescription=\"Presonus AudioBox USB\" ProductName=\"USB-Audio - AudioBox USB\">" +
-              "<OutputDevInfo ChanCounts=\"2\" ChanPosMasks=\"12\" ChanIndexMasks=\"3\" Encodings=\"4\" SampleRates=\"44100,48000\" />" +
-              "<InputDevInfo ChanCounts=\"1,2\" ChanPosMasks=\"12,16\" ChanIndexMasks=\"3\" Encodings=\"4\" SampleRates=\"44100,48000\" />" +
+                "<OutputDevInfo ChanCounts=\"2\" ChanPosMasks=\"12\" ChanIndexMasks=\"3\" Encodings=\"4\" SampleRates=\"44100,48000\" />" +
+                "<InputDevInfo ChanCounts=\"1,2\" ChanPosMasks=\"12,16\" ChanIndexMasks=\"3\" Encodings=\"4\" SampleRates=\"44100,48000\" />" +
+            "</PeripheralProfile>" +
+            "<PeripheralProfile ProfileName=\"Pixel USB-C Dongle + Wired Analog Headset\" ProfileDescription=\"Reference USB Dongle\" ProductName=\"USB-Audio - USB-C to 3.5mm-Headphone Adapte\">" +
+                "<OutputDevInfo ChanCounts=\"2\" ChanPosMasks=\"12\" ChanIndexMasks=\"3\" Encodings=\"4\" SampleRates=\"48000\" />" +
+                "<InputDevInfo ChanCounts=\"1,2\" ChanPosMasks=\"12,16\" ChanIndexMasks=\"3\" Encodings=\"4\" SampleRates=\"48000\" />" +
+                "<ButtonInfo HasBtnA=\"1\" HasBtnB=\"1\" HasBtnC=\"1\" HasBtnD=\"1\" />" +
             "</PeripheralProfile>" +
             "<PeripheralProfile ProfileName=\"gen1-headset\" ProfileDescription=\"Reference USB Headset\" ProductName=\"USB-Audio - Skylab\">" +
             "<OutputDevInfo ChanCounts=\"2\" ChanPosMasks=\"12\" ChanIndexMasks=\"3\" Encodings=\"2,4\" SampleRates=\"8000,16000,32000,44100,48000\" />" +
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/CommandReceiverActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/CommandReceiverActivity.java
index 1d4d13a..c51ea0a 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/CommandReceiverActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/CommandReceiverActivity.java
@@ -36,6 +36,8 @@
 import android.provider.MediaStore;
 import android.provider.Settings;
 import android.util.Log;
+import android.view.inputmethod.InputMethodInfo;
+import android.view.inputmethod.InputMethodManager;
 import android.widget.Toast;
 
 import com.android.cts.verifier.R;
@@ -48,6 +50,7 @@
 import java.util.ArrayList;
 import java.util.List;
 import java.util.concurrent.TimeUnit;
+import java.util.stream.Collectors;
 
 public class CommandReceiverActivity extends Activity {
     private static final String TAG = "CommandReceiverActivity";
@@ -222,7 +225,8 @@
                 } break;
                 case COMMAND_ALLOW_ONLY_SYSTEM_INPUT_METHODS: {
                     boolean enforced = intent.getBooleanExtra(EXTRA_ENFORCED, false);
-                    mDpm.setPermittedInputMethods(mAdmin, enforced ? new ArrayList() : null);
+                    mDpm.setPermittedInputMethods(mAdmin,
+                            enforced ? getEnabledNonSystemImes() : null);
                 } break;
                 case COMMAND_ALLOW_ONLY_SYSTEM_ACCESSIBILITY_SERVICES: {
                     boolean enforced = intent.getBooleanExtra(EXTRA_ENFORCED, false);
@@ -562,4 +566,19 @@
             mDpm.removeUser(mAdmin, userHandle);
         }
     }
+
+    private List<String> getEnabledNonSystemImes() {
+        InputMethodManager inputMethodManager = getSystemService(InputMethodManager.class);
+        final List<InputMethodInfo> inputMethods = inputMethodManager.getEnabledInputMethodList();
+        return inputMethods.stream()
+                .filter(inputMethodInfo -> !isSystemInputMethodInfo(inputMethodInfo))
+                .map(inputMethodInfo -> inputMethodInfo.getPackageName())
+                .filter(packageName -> !packageName.equals(getPackageName()))
+                .distinct()
+                .collect(Collectors.toList());
+    }
+
+    private boolean isSystemInputMethodInfo(InputMethodInfo inputMethodInfo) {
+        return inputMethodInfo.getServiceInfo().applicationInfo.isSystemApp();
+    }
 }
diff --git a/common/device-side/util/src/com/android/compatibility/common/util/FeatureUtil.java b/common/device-side/util/src/com/android/compatibility/common/util/FeatureUtil.java
index 5be72b8..ebf881a 100644
--- a/common/device-side/util/src/com/android/compatibility/common/util/FeatureUtil.java
+++ b/common/device-side/util/src/com/android/compatibility/common/util/FeatureUtil.java
@@ -31,6 +31,7 @@
 
     public static final String LEANBACK_FEATURE = "android.software.leanback";
     public static final String LOW_RAM_FEATURE = "android.hardware.ram.low";
+    public static final String TELEPHONY_FEATURE = "android.hardware.telephony";
     public static final String TV_FEATURE = "android.hardware.type.television";
     public static final String WATCH_FEATURE = "android.hardware.type.watch";
 
@@ -93,4 +94,14 @@
     private static PackageManager getPackageManager() {
         return InstrumentationRegistry.getInstrumentation().getTargetContext().getPackageManager();
     }
+
+    /** Returns true if the device has feature TELEPHONY_FEATURE */
+    public static boolean hasTelephony() {
+        return hasSystemFeature(TELEPHONY_FEATURE);
+    }
+
+    /** Returns true if the device has feature FEATURE_MICROPHONE */
+    public static boolean hasMicrophone() {
+        return hasSystemFeature(getPackageManager().FEATURE_MICROPHONE);
+    }
 }
diff --git a/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/targetprep/MediaPreparer.java b/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/targetprep/MediaPreparer.java
index 1bcc6f8..a9369fa 100644
--- a/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/targetprep/MediaPreparer.java
+++ b/common/host-side/tradefed/src/com/android/compatibility/common/tradefed/targetprep/MediaPreparer.java
@@ -322,12 +322,17 @@
             // Option 'local-media-path' has not been defined
             // Get directory to store media files on this host
             File mediaFolder = getDefaultMediaDir();
-            if(!mediaFolder.exists() || mediaFolder.list().length == 0){
-                // If directory already exists and contains files, it has been created by previous
-                // runs of MediaPreparer. Assume media files exist inside.
-                // Else, create directory if needed and download/extract media files inside.
-                mediaFolder.mkdirs();
-                downloadMediaToHost(device, buildInfo, mediaFolder);
+            synchronized (MediaPreparer.class) {
+                // Synchronize this block so that multiple shards won't download/extract
+                // this file to the same location on the host. Only an issue in Android O and above,
+                // where MediaPreparer is used for multiple, shardable modules.
+                if(!mediaFolder.exists() || mediaFolder.list().length == 0){
+                    // If directory already exists and contains files, it has been created by
+                    // previous runs of MediaPreparer. Assume media files exist inside.
+                    // Else, create directory if needed and download/extract media files inside.
+                    mediaFolder.mkdirs();
+                    downloadMediaToHost(device, buildInfo, mediaFolder);
+                }
             }
             // set mLocalMediaPath to where the CTS media files have been extracted
             updateLocalMediaPath(device, mediaFolder);
diff --git a/common/host-side/util/src/com/android/compatibility/common/util/FeatureUtil.java b/common/host-side/util/src/com/android/compatibility/common/util/FeatureUtil.java
index a51df79..87d257a 100644
--- a/common/host-side/util/src/com/android/compatibility/common/util/FeatureUtil.java
+++ b/common/host-side/util/src/com/android/compatibility/common/util/FeatureUtil.java
@@ -29,8 +29,10 @@
 
     public static final String LEANBACK_FEATURE = "android.software.leanback";
     public static final String LOW_RAM_FEATURE = "android.hardware.ram.low";
+    public static final String TELEPHONY_FEATURE = "android.hardware.telephony";
     public static final String TV_FEATURE = "android.hardware.type.television";
     public static final String WATCH_FEATURE = "android.hardware.type.watch";
+    public static final String FEATURE_MICROPHONE = "android.hardware.microphone";
 
     /** Returns true if the device has a given system feature */
     public static boolean hasSystemFeature(ITestDevice device, String feature)
@@ -89,4 +91,14 @@
         return ApiLevelUtil.isAtLeast(device, VersionCodes.O) &&
                 hasSystemFeature(device, LOW_RAM_FEATURE);
     }
+
+    /** Returns true if the device has feature TELEPHONY_FEATURE */
+    public static boolean hasTelephony(ITestDevice device) throws DeviceNotAvailableException {
+        return hasSystemFeature(device, TELEPHONY_FEATURE);
+    }
+
+    /** Returns true if the device has feature FEATURE_MICROPHONE */
+    public static boolean hasMicrophone(ITestDevice device) throws DeviceNotAvailableException {
+        return hasSystemFeature(device, FEATURE_MICROPHONE);
+    }
 }
diff --git a/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/AlwaysOnVpnMultiStageTest.java b/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/AlwaysOnVpnMultiStageTest.java
index 6eed964..25d7be7 100644
--- a/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/AlwaysOnVpnMultiStageTest.java
+++ b/hostsidetests/devicepolicy/app/DeviceAndProfileOwner/src/com/android/cts/deviceandprofileowner/AlwaysOnVpnMultiStageTest.java
@@ -66,6 +66,14 @@
     }
 
     public void testAlwaysOnVpnDisabled() throws Exception {
+        // Wait until always-on vpn package is being removed (with 1 minute timeout).
+        for (int i = 0; i < 60; i++) {
+            if (mDevicePolicyManager.getAlwaysOnVpnPackage(ADMIN_RECEIVER_COMPONENT) == null) {
+                break;
+            }
+            Thread.sleep(1000);  // 1 second.
+        }
+
         // After the vpn app being uninstalled, check that always-on vpn is null
         assertNull(mDevicePolicyManager.getAlwaysOnVpnPackage(ADMIN_RECEIVER_COMPONENT));
         assertFalse(VpnTestHelper.isNetworkVpn(mContext));
diff --git a/hostsidetests/services/activityandwindowmanager/activitymanager/app/AndroidManifest.xml b/hostsidetests/services/activityandwindowmanager/activitymanager/app/AndroidManifest.xml
index 63f41d1..6f70b62 100755
--- a/hostsidetests/services/activityandwindowmanager/activitymanager/app/AndroidManifest.xml
+++ b/hostsidetests/services/activityandwindowmanager/activitymanager/app/AndroidManifest.xml
@@ -323,7 +323,8 @@
         </receiver>
 
         <activity android:name=".AssistantActivity"
-            android:exported="true" />
+            android:exported="true"
+            android:screenOrientation="locked" />
         <activity android:name=".TranslucentAssistantActivity"
             android:exported="true"
             android:theme="@style/Theme.Transparent" />
diff --git a/hostsidetests/services/activityandwindowmanager/activitymanager/src/android/server/cts/ActivityManagerDockedStackTests.java b/hostsidetests/services/activityandwindowmanager/activitymanager/src/android/server/cts/ActivityManagerDockedStackTests.java
index cf3540c..011390a 100644
--- a/hostsidetests/services/activityandwindowmanager/activitymanager/src/android/server/cts/ActivityManagerDockedStackTests.java
+++ b/hostsidetests/services/activityandwindowmanager/activitymanager/src/android/server/cts/ActivityManagerDockedStackTests.java
@@ -125,13 +125,9 @@
         // Remove the docked stack, and ensure that
         final String logSeparator = clearLogcat();
         removeStacks(DOCKED_STACK_ID);
-        final ActivityLifecycleCounts lifecycleCounts = new ActivityLifecycleCounts(
+        final ActivityLifecycleCounts lifecycleCounts = waitForOnMultiWindowModeChanged(
                 TEST_ACTIVITY_NAME, logSeparator);
-        if (lifecycleCounts.mMultiWindowModeChangedCount != 1) {
-            fail(TEST_ACTIVITY_NAME + " has received "
-                    + lifecycleCounts.mMultiWindowModeChangedCount
-                    + " onMultiWindowModeChanged() calls, expecting 1");
-        }
+        assertEquals(1, lifecycleCounts.mMultiWindowModeChangedCount);
     }
 
     public void testLaunchToSideAndBringToFront() throws Exception {
diff --git a/hostsidetests/services/activityandwindowmanager/util/src/android/server/cts/ActivityManagerTestBase.java b/hostsidetests/services/activityandwindowmanager/util/src/android/server/cts/ActivityManagerTestBase.java
old mode 100644
new mode 100755
index 9ba292f..925fa92
--- a/hostsidetests/services/activityandwindowmanager/util/src/android/server/cts/ActivityManagerTestBase.java
+++ b/hostsidetests/services/activityandwindowmanager/util/src/android/server/cts/ActivityManagerTestBase.java
@@ -1236,6 +1236,28 @@
         return null;
     }
 
+    /** Waits for at least one onMultiWindowModeChanged event. */
+    ActivityLifecycleCounts waitForOnMultiWindowModeChanged(
+            String activityName, String logSeparator) throws Exception {
+        int retriesLeft = 5;
+        ActivityLifecycleCounts result;
+        do {
+            result = new ActivityLifecycleCounts(activityName, logSeparator);
+            if (result.mMultiWindowModeChangedCount < 1) {
+                log("***waitForOnMultiWindowModeChanged...");
+                try {
+                    Thread.sleep(1000);
+                } catch (InterruptedException e) {
+                    log(e.toString());
+                    // Well I guess we are not waiting...
+                }
+            } else {
+                break;
+            }
+        } while (retriesLeft-- > 0);
+        return result;
+    }
+
     class ActivityLifecycleCounts {
         int mCreateCount;
         int mStartCount;
diff --git a/hostsidetests/theme/assets/26/280dpi.zip b/hostsidetests/theme/assets/26/280dpi.zip
old mode 100644
new mode 100755
index d5260d9..c2e2ed0
--- a/hostsidetests/theme/assets/26/280dpi.zip
+++ b/hostsidetests/theme/assets/26/280dpi.zip
Binary files differ
diff --git a/hostsidetests/theme/assets/27/420dpi.zip b/hostsidetests/theme/assets/27/420dpi.zip
index 6b46161..e5e228c 100644
--- a/hostsidetests/theme/assets/27/420dpi.zip
+++ b/hostsidetests/theme/assets/27/420dpi.zip
Binary files differ
diff --git a/hostsidetests/theme/assets/27/xxhdpi.zip b/hostsidetests/theme/assets/27/xxhdpi.zip
index 1cae292..f628e5b 100644
--- a/hostsidetests/theme/assets/27/xxhdpi.zip
+++ b/hostsidetests/theme/assets/27/xxhdpi.zip
Binary files differ
diff --git a/hostsidetests/theme/generate_images.py b/hostsidetests/theme/generate_images.py
index 8b70f00..f243ea4 100755
--- a/hostsidetests/theme/generate_images.py
+++ b/hostsidetests/theme/generate_images.py
@@ -50,7 +50,7 @@
 
 
 class ParallelExecutor(threading.Thread):
-    def __init__(self, tasks, q):
+    def __init__(self, tasks, setup, q):
         threading.Thread.__init__(self)
         self._q = q
         self._tasks = tasks
@@ -60,7 +60,7 @@
     def run(self):
         try:
             while True:
-                config = q.get(block=True, timeout=2)
+                config = self._q.get(block=True, timeout=2)
                 for t in self._tasks:
                     try:
                         if t(self._setup, config):
@@ -70,7 +70,7 @@
                     except:
                         print("Failed to execute thread:", sys.exc_info()[0])
                         traceback.print_exc()
-                q.task_done()
+                self._q.task_done()
         except KeyboardInterrupt:
             raise
         except Empty:
@@ -86,7 +86,7 @@
     result = 0
     threads = []
     for i in range(num_threads):
-        t = ParallelExecutor(tasks, q)
+        t = ParallelExecutor(tasks, setup, q)
         t.start()
         threads.append(t)
     for t in threads:
@@ -226,7 +226,7 @@
         tasks = [do_capture]
         setup = (theme_apk, out_path)
 
-        devices = enumerate_android_devices('emulator')
+        devices = enumerate_android_devices()
 
         device_queue = Queue()
         for device in devices:
diff --git a/tests/autofillservice/res/layout/login_activity.xml b/tests/autofillservice/res/layout/login_activity.xml
index e16d1c4..5cf0efd 100644
--- a/tests/autofillservice/res/layout/login_activity.xml
+++ b/tests/autofillservice/res/layout/login_activity.xml
@@ -38,7 +38,8 @@
         <EditText
             android:id="@+id/username"
             android:layout_width="match_parent"
-            android:layout_height="wrap_content" />
+            android:layout_height="wrap_content"
+            android:imeOptions="flagNoFullscreen" />
     </LinearLayout>
 
     <LinearLayout
@@ -56,7 +57,8 @@
             android:id="@+id/password"
             android:layout_width="match_parent"
             android:layout_height="wrap_content"
-            android:inputType="textPassword"/>
+            android:inputType="textPassword"
+            android:imeOptions="flagNoFullscreen" />
     </LinearLayout>
 
     <LinearLayout
diff --git a/tests/autofillservice/res/layout/simple_save_activity.xml b/tests/autofillservice/res/layout/simple_save_activity.xml
index 8eb5255..c48e0c3 100644
--- a/tests/autofillservice/res/layout/simple_save_activity.xml
+++ b/tests/autofillservice/res/layout/simple_save_activity.xml
@@ -36,12 +36,14 @@
         <EditText
             android:id="@+id/input"
             android:layout_width="wrap_content"
-            android:layout_height="wrap_content" />
+            android:layout_height="wrap_content"
+            android:imeOptions="flagNoFullscreen" />
         <EditText
             android:id="@+id/password"
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
-            android:inputType="textPassword"/>
+            android:inputType="textPassword"
+            android:imeOptions="flagNoFullscreen" />
     </LinearLayout>
 
     <LinearLayout
diff --git a/tests/autofillservice/src/android/autofillservice/cts/AutoFillServiceTestCase.java b/tests/autofillservice/src/android/autofillservice/cts/AutoFillServiceTestCase.java
index 74e168b..e72d85d 100644
--- a/tests/autofillservice/src/android/autofillservice/cts/AutoFillServiceTestCase.java
+++ b/tests/autofillservice/src/android/autofillservice/cts/AutoFillServiceTestCase.java
@@ -64,6 +64,7 @@
 
     protected final Context mContext;
     protected final String mPackageName;
+
     /**
      * Stores the previous logging level so it's restored after the test.
      */
diff --git a/tests/autofillservice/src/android/autofillservice/cts/CustomDescriptionWithLinkTestCase.java b/tests/autofillservice/src/android/autofillservice/cts/CustomDescriptionWithLinkTestCase.java
index 210fab8..9130810 100644
--- a/tests/autofillservice/src/android/autofillservice/cts/CustomDescriptionWithLinkTestCase.java
+++ b/tests/autofillservice/src/android/autofillservice/cts/CustomDescriptionWithLinkTestCase.java
@@ -15,6 +15,8 @@
  */
 package android.autofillservice.cts;
 
+import static android.autofillservice.cts.Helper.runShellCommand;
+
 import static com.google.common.truth.Truth.assertThat;
 
 import android.app.Activity;
@@ -64,10 +66,16 @@
     public final void testTapLink_changeOrientationThenTapBack() throws Exception {
         sUiBot.setScreenOrientation(UiBot.PORTRAIT);
         try {
+            runShellCommand("wm density 420");
             saveUiRestoredAfterTappingLinkTest(
                     PostSaveLinkTappedAction.ROTATE_THEN_TAP_BACK_BUTTON);
         } finally {
             sUiBot.setScreenOrientation(UiBot.PORTRAIT);
+            try {
+                cleanUpAfterScreenOrientationIsBackToPortrait();
+            } finally {
+                runShellCommand("wm density reset");
+            }
         }
     }
 
@@ -84,6 +92,9 @@
     protected abstract void saveUiRestoredAfterTappingLinkTest(PostSaveLinkTappedAction type)
             throws Exception;
 
+    protected void cleanUpAfterScreenOrientationIsBackToPortrait() throws Exception {
+    }
+
     /**
      * Tests scenarios when user taps a link in the custom description, taps back to return to the
      * activity with the Save UI, and touch outside the Save UI to dismiss it.
diff --git a/tests/autofillservice/src/android/autofillservice/cts/SimpleSaveActivityTest.java b/tests/autofillservice/src/android/autofillservice/cts/SimpleSaveActivityTest.java
index 8e4ec03..24b5e4c 100644
--- a/tests/autofillservice/src/android/autofillservice/cts/SimpleSaveActivityTest.java
+++ b/tests/autofillservice/src/android/autofillservice/cts/SimpleSaveActivityTest.java
@@ -173,6 +173,7 @@
             saveTest(true);
         } finally {
             sUiBot.setScreenOrientation(UiBot.PORTRAIT);
+            cleanUpAfterScreenOrientationIsBackToPortrait();
         }
     }
 
@@ -200,6 +201,9 @@
         UiObject2 saveUi = sUiBot.assertSaveShowing(SAVE_DATA_TYPE_GENERIC);
 
         if (rotate) {
+            // After the device rotates, the input field get focus and generate a new session.
+            sReplier.addResponse(CannedFillResponse.NO_RESPONSE);
+
             sUiBot.setScreenOrientation(UiBot.LANDSCAPE);
             saveUi = sUiBot.assertSaveShowing(SAVE_DATA_TYPE_GENERIC);
         }
@@ -493,6 +497,9 @@
         // .. then do something to return to previous activity...
         switch (type) {
             case ROTATE_THEN_TAP_BACK_BUTTON:
+                // After the device rotates, the input field get focus and generate a new session.
+                sReplier.addResponse(CannedFillResponse.NO_RESPONSE);
+
                 sUiBot.setScreenOrientation(UiBot.LANDSCAPE);
                 // not breaking on purpose
             case TAP_BACK_BUTTON:
@@ -515,6 +522,12 @@
 
         final SaveRequest saveRequest = sReplier.getNextSaveRequest();
         assertTextAndValue(findNodeByResourceId(saveRequest.structure, ID_INPUT), "108");
+
+    }
+
+    @Override
+    protected void cleanUpAfterScreenOrientationIsBackToPortrait() throws Exception {
+        sReplier.getNextFillRequest();
     }
 
     @Override
diff --git a/tests/jdwp/Android.mk b/tests/jdwp/Android.mk
index 648e4ea..debf41c 100644
--- a/tests/jdwp/Android.mk
+++ b/tests/jdwp/Android.mk
@@ -21,7 +21,7 @@
 LOCAL_STATIC_JAVA_LIBRARIES := apache-harmony-jdwp-tests
 
 # Don't include this package in any target
-LOCAL_MODULE_TAGS := optional
+LOCAL_MODULE_TAGS := tests
 
 # Tag this module as a cts test artifact
 LOCAL_COMPATIBILITY_SUITE := cts vts general-tests
diff --git a/tests/jdwp/runner/device-side/src/com/android/compatibility/dalvik/DalvikTestRunner.java b/tests/jdwp/runner/device-side/src/com/android/compatibility/dalvik/DalvikTestRunner.java
index c55b0e9..65e83ae 100644
--- a/tests/jdwp/runner/device-side/src/com/android/compatibility/dalvik/DalvikTestRunner.java
+++ b/tests/jdwp/runner/device-side/src/com/android/compatibility/dalvik/DalvikTestRunner.java
@@ -55,6 +55,8 @@
     private static final String COLLECT_TESTS_ONLY = "--collect-tests-only";
     private static final String JUNIT_IGNORE = "org.junit.Ignore";
 
+    private static final String RUNNER_JAR = "cts-dalvik-device-test-runner.jar";
+
     public static void main(String[] args) {
         String abiName = null;
         Set<String> includes = new HashSet<>();
@@ -160,18 +162,28 @@
     private static List<Class<?>> getClasses(String[] jars, String abiName) {
         List<Class<?>> classes = new ArrayList<>();
         for (String jar : jars) {
+            if (jar.contains(RUNNER_JAR)) {
+                // The runner jar must be added to the class path to invoke DalvikTestRunner,
+                // but should not be searched for test classes
+                continue;
+            }
             try {
                 ClassLoader loader = createClassLoader(jar, abiName);
                 DexFile file = new DexFile(jar);
                 Enumeration<String> entries = file.entries();
                 while (entries.hasMoreElements()) {
                     String e = entries.nextElement();
-                    Class<?> cls = loader.loadClass(e);
-                    if (isTestClass(cls)) {
-                        classes.add(cls);
+                    try {
+                        Class<?> cls = loader.loadClass(e);
+                        if (isTestClass(cls)) {
+                            classes.add(cls);
+                        }
+                    } catch (ClassNotFoundException ex) {
+                        System.out.println(String.format(
+                                "Skipping dex entry %s in %s", e, jar));
                     }
                 }
-            } catch (IllegalAccessError | IOException | ClassNotFoundException e) {
+            } catch (IllegalAccessError | IOException e) {
                 e.printStackTrace();
             }
         }
diff --git a/tests/tests/permission/src/android/permission/cts/FileSystemPermissionTest.java b/tests/tests/permission/src/android/permission/cts/FileSystemPermissionTest.java
index a2b1b36..bb9f868 100644
--- a/tests/tests/permission/src/android/permission/cts/FileSystemPermissionTest.java
+++ b/tests/tests/permission/src/android/permission/cts/FileSystemPermissionTest.java
@@ -326,7 +326,14 @@
             byte bytes[] = new byte[SIZEOF_U64];
             ByteBuffer buf = ByteBuffer.wrap(bytes).order(ByteOrder.nativeOrder());
             int read = Os.read(pagemap, buf);
-            if (read != bytes.length)
+
+            if (read == 0)
+                // /proc/[pid]/maps may contain entries that are outside the process's VM space,
+                // like the [vectors] page on 32-bit ARM devices.  In this case, seek() succeeds but
+                // read() returns 0.  The kernel is telling us that there are no more pagemap
+                // entries to read, so we can stop here.
+                break;
+            else if (read != bytes.length)
                 throw new IOException("read(" + bytes.length + ") returned " + read);
 
             buf.position(0);
diff --git a/tests/tests/preference2/src/android/preference2/cts/TestUtils.java b/tests/tests/preference2/src/android/preference2/cts/TestUtils.java
index 6fdeff4..b5c02f1 100644
--- a/tests/tests/preference2/src/android/preference2/cts/TestUtils.java
+++ b/tests/tests/preference2/src/android/preference2/cts/TestUtils.java
@@ -45,6 +45,7 @@
     final UiDevice device;
     private final Instrumentation mInstrumentation;
     private final UiAutomation mAutomation;
+    private int mStatusBarHeight = -1;
 
     TestUtils() {
         mInstrumentation = InstrumentationRegistry.getInstrumentation();
@@ -58,8 +59,8 @@
 
         Bitmap bt = mAutomation.takeScreenshot();
         // Crop-out the top bar where current time is displayed since any time change would
-        // introduce flakiness (we are cutting 5% of the screen height).
-        int yToCut = bt.getHeight() / 20;
+        // introduce flakiness (we are cutting 5% of the screen height or status_bar_height).
+        int yToCut = Math.max(bt.getHeight() / 20, getStatusBarHeight());
         // Crop the right side for scrollbar which might or might not be visible. But on
         // watch, the scroll bar is a curve and occupies 20% of the screen on the right
         // hand side.
@@ -194,6 +195,23 @@
         return baseWindowName + activity.getClass().getSimpleName();
     }
 
+    private int getStatusBarHeight() {
+        // Cache the result to keep it fast.
+        if (mStatusBarHeight >= 0) {
+            return mStatusBarHeight;
+        }
+
+        int result = 0;
+        int resourceId = mInstrumentation.getTargetContext().getResources()
+                .getIdentifier("status_bar_height", "dimen", "android");
+        if (resourceId > 0) {
+            result = mInstrumentation.getTargetContext().getResources()
+                    .getDimensionPixelSize(resourceId);
+        }
+        mStatusBarHeight = result;
+        return result;
+    }
+
     private String runShellCommand(String cmd) {
         try {
             return SystemUtil.runShellCommand(mInstrumentation, cmd);
diff --git a/tests/tests/telephony/src/android/telephony/cts/VisualVoicemailServiceTest.java b/tests/tests/telephony/src/android/telephony/cts/VisualVoicemailServiceTest.java
index 01f926b..cfd31d3 100644
--- a/tests/tests/telephony/src/android/telephony/cts/VisualVoicemailServiceTest.java
+++ b/tests/tests/telephony/src/android/telephony/cts/VisualVoicemailServiceTest.java
@@ -678,6 +678,9 @@
     }
 
     private boolean hasDataSms() {
+        if (mTelephonyManager.getPhoneType() == TelephonyManager.PHONE_TYPE_CDMA) {
+            return false;
+        }
         String mccmnc = mTelephonyManager.getSimOperator();
         return !CarrierCapability.UNSUPPORT_DATA_SMS_MESSAGES.contains(mccmnc);
     }
diff --git a/tests/tests/uirendering/src/android/uirendering/cts/testclasses/InfrastructureTests.java b/tests/tests/uirendering/src/android/uirendering/cts/testclasses/InfrastructureTests.java
index ee46601..abaf96e 100644
--- a/tests/tests/uirendering/src/android/uirendering/cts/testclasses/InfrastructureTests.java
+++ b/tests/tests/uirendering/src/android/uirendering/cts/testclasses/InfrastructureTests.java
@@ -39,7 +39,7 @@
     @Test
     public void testScreenshot() {
         for (int i = 0 ; i < 500 ; i ++) {
-            takeScreenshot(new Point());
+            takeScreenshot(new TestPositionInfo(new Point(), new Point()));
             System.gc();
         }
     }
diff --git a/tests/tests/uirendering/src/android/uirendering/cts/testclasses/SurfaceViewTests.java b/tests/tests/uirendering/src/android/uirendering/cts/testclasses/SurfaceViewTests.java
index 741c35c..153bf5b 100644
--- a/tests/tests/uirendering/src/android/uirendering/cts/testclasses/SurfaceViewTests.java
+++ b/tests/tests/uirendering/src/android/uirendering/cts/testclasses/SurfaceViewTests.java
@@ -111,9 +111,11 @@
                 mAnimator.cancel();
             }
         };
-        Screenshotter screenshotter = testOffset -> {
+        Screenshotter screenshotter = testPositionInfo -> {
             Bitmap source = getInstrumentation().getUiAutomation().takeScreenshot();
-            return Bitmap.createBitmap(source, testOffset.x, testOffset.y, TEST_WIDTH, TEST_HEIGHT);
+            return Bitmap.createBitmap(source,
+                    testPositionInfo.screenOffset.x, testPositionInfo.screenOffset.y,
+                    TEST_WIDTH, TEST_HEIGHT);
         };
         createTest()
                 .addLayout(R.layout.frame_layout, initializer, true)
@@ -131,7 +133,7 @@
         }
 
         @Override
-        public Bitmap takeScreenshot(Point point /* ignored */) {
+        public Bitmap takeScreenshot(TestPositionInfo testPositionInfo) {
             SynchronousPixelCopy copy = new SynchronousPixelCopy();
             Bitmap dest = Bitmap.createBitmap(
                     TEST_WIDTH, TEST_HEIGHT, Config.ARGB_8888);
diff --git a/tests/tests/uirendering/src/android/uirendering/cts/testclasses/XfermodeTest.java b/tests/tests/uirendering/src/android/uirendering/cts/testclasses/XfermodeTest.java
index acae80f..eb8e07c 100644
--- a/tests/tests/uirendering/src/android/uirendering/cts/testclasses/XfermodeTest.java
+++ b/tests/tests/uirendering/src/android/uirendering/cts/testclasses/XfermodeTest.java
@@ -128,7 +128,7 @@
                 BG_COLOR, DST_COLOR, SCREEN_COLOR, SRC_COLOR } },
     };
 
-    @Parameterized.Parameters(name = "{0}")
+    @Parameterized.Parameters
     public static List<Config> configs() {
         return configs(MODES_AND_EXPECTED_COLORS);
     }
diff --git a/tests/tests/uirendering/src/android/uirendering/cts/testinfrastructure/ActivityTestBase.java b/tests/tests/uirendering/src/android/uirendering/cts/testinfrastructure/ActivityTestBase.java
index 6fe44c3..57e7d3b 100644
--- a/tests/tests/uirendering/src/android/uirendering/cts/testinfrastructure/ActivityTestBase.java
+++ b/tests/tests/uirendering/src/android/uirendering/cts/testinfrastructure/ActivityTestBase.java
@@ -125,26 +125,25 @@
         }
     }
 
-    public Bitmap takeScreenshot(Point testOffset) {
+    public Bitmap takeScreenshot(TestPositionInfo testPositionInfo) {
         if (mScreenshotter == null) {
             SynchronousPixelCopy copy = new SynchronousPixelCopy();
             Bitmap dest = Bitmap.createBitmap(
                     TEST_WIDTH, TEST_HEIGHT,
                     getActivity().getWindow().isWideColorGamut()
                             ? Config.RGBA_F16 : Config.ARGB_8888);
-            Rect srcRect = new Rect(testOffset.x, testOffset.y,
-                    testOffset.x + TEST_WIDTH, testOffset.y + TEST_HEIGHT);
-            Log.d("UiRendering", "capturing screenshot of " + srcRect.toShortString());
+            Rect srcRect = new Rect(0, 0, TEST_WIDTH, TEST_HEIGHT);
+            srcRect.offset(testPositionInfo.surfaceOffset.x, testPositionInfo.surfaceOffset.y);
+            Log.d(TAG, "capturing screenshot of " + srcRect.toShortString());
             int copyResult = copy.request(getActivity().getWindow(), srcRect, dest);
             Assert.assertEquals(PixelCopy.SUCCESS, copyResult);
             return dest;
         } else {
-            return mScreenshotter.takeScreenshot(testOffset);
+            return mScreenshotter.takeScreenshot(testPositionInfo);
         }
     }
-
-    protected Point runRenderSpec(TestCase testCase) {
-        Point testOffset = getActivity().enqueueRenderSpecAndWait(
+    protected TestPositionInfo runRenderSpec(TestCase testCase) {
+        TestPositionInfo testPositionInfo = getActivity().enqueueRenderSpecAndWait(
                 testCase.layoutID, testCase.canvasClient,
                 testCase.viewInitializer, testCase.useHardware, testCase.usePicture);
         testCase.wasTestRan = true;
@@ -155,15 +154,14 @@
                 throw new RuntimeException("readyFence didn't signal within 5 seconds");
             }
         }
-        return testOffset;
+        return testPositionInfo;
     }
 
     /**
      * Used to execute a specific part of a test and get the resultant bitmap
      */
     protected Bitmap captureRenderSpec(TestCase testCase) {
-        Point testOffset = runRenderSpec(testCase);
-        return takeScreenshot(testOffset);
+        return takeScreenshot(runRenderSpec(testCase));
     }
 
     protected TestCaseBuilder createTest() {
@@ -172,8 +170,28 @@
         return mTestCaseBuilder;
     }
 
+    public static class TestPositionInfo {
+        /**
+         * Position of capture area in surface space - use this offset for e.g.
+         * PixelCopy from a window's surface.
+         */
+        public final Point surfaceOffset;
+
+        /**
+         * Position of capture area in screen space - use this offset for e.g.
+         * {@code getInstrumentation().getUiAutomation().takeScreenshot()},
+         * since those screenshots are captured in screen space.
+         */
+        public final Point screenOffset;
+
+        public TestPositionInfo(Point surfaceOffset, Point screenOffset) {
+            this.surfaceOffset = surfaceOffset;
+            this.screenOffset = screenOffset;
+        }
+    }
+
     public interface Screenshotter {
-        Bitmap takeScreenshot(Point point);
+        Bitmap takeScreenshot(TestPositionInfo params);
     }
 
     /**
@@ -237,7 +255,7 @@
             }
 
             for (TestCase testCase : mTestCases) {
-                Point testOffset = runRenderSpec(testCase);
+                TestPositionInfo testPositionInfo = runRenderSpec(testCase);
 
                 for (int i = 0; i < VERIFY_ANIMATION_LOOP_COUNT; i++) {
                     try {
@@ -245,7 +263,7 @@
                     } catch (InterruptedException e) {
                         e.printStackTrace();
                     }
-                    Bitmap testCaseBitmap = takeScreenshot(testOffset);
+                    Bitmap testCaseBitmap = takeScreenshot(testPositionInfo);
                     mBitmapAsserter.assertBitmapIsVerified(testCaseBitmap, bitmapVerifier,
                             getName(), testCase.getDebugString());
                 }
diff --git a/tests/tests/uirendering/src/android/uirendering/cts/testinfrastructure/DrawActivity.java b/tests/tests/uirendering/src/android/uirendering/cts/testinfrastructure/DrawActivity.java
index 2b5271a..1d4d3f4 100644
--- a/tests/tests/uirendering/src/android/uirendering/cts/testinfrastructure/DrawActivity.java
+++ b/tests/tests/uirendering/src/android/uirendering/cts/testinfrastructure/DrawActivity.java
@@ -45,7 +45,8 @@
     static final String EXTRA_WIDE_COLOR_GAMUT = "DrawActivity.WIDE_COLOR_GAMUT";
 
     private final static long TIME_OUT_MS = 10000;
-    private final Point mLock = new Point();
+    private final Object mLock = new Object();
+    private ActivityTestBase.TestPositionInfo mPositionInfo;
 
     private Handler mHandler;
     private View mView;
@@ -95,11 +96,11 @@
         return mOnTv;
     }
 
-    public Point enqueueRenderSpecAndWait(int layoutId, CanvasClient canvasClient,
-            @Nullable ViewInitializer viewInitializer, boolean useHardware, boolean usePicture) {
+    public ActivityTestBase.TestPositionInfo enqueueRenderSpecAndWait(int layoutId,
+            CanvasClient canvasClient, @Nullable ViewInitializer viewInitializer,
+            boolean useHardware, boolean usePicture) {
         ((RenderSpecHandler) mHandler).setViewInitializer(viewInitializer);
         int arg2 = (useHardware ? View.LAYER_TYPE_NONE : View.LAYER_TYPE_SOFTWARE);
-        Point point = new Point();
         synchronized (mLock) {
             if (canvasClient != null) {
                 mHandler.obtainMessage(RenderSpecHandler.CANVAS_MSG, usePicture ? 1 : 0,
@@ -110,12 +111,11 @@
 
             try {
                 mLock.wait(TIME_OUT_MS);
-                point.set(mLock.x, mLock.y);
             } catch (InterruptedException e) {
                 e.printStackTrace();
             }
         }
-        return point;
+        return mPositionInfo;
     }
 
     public void reset() {
@@ -210,7 +210,6 @@
     }
 
     private class DrawCounterListener implements ViewTreeObserver.OnDrawListener {
-        private final int[] mLocationInWindow = new int[2];
         private static final int DEBUG_REQUIRE_EXTRA_FRAMES = 1;
         private int mDrawCount = 0;
 
@@ -221,11 +220,16 @@
                 return;
             }
             mView.post(() -> {
-                Log.d("UiRendering", "notifying capture");
                 mView.getViewTreeObserver().removeOnDrawListener(this);
+
+                final int[] location = new int[2];
+                mViewWrapper.getLocationInWindow(location);
+                Point surfaceOffset = new Point(location[0], location[1]);
+                mViewWrapper.getLocationOnScreen(location);
+                Point screenOffset = new Point(location[0], location[1]);
                 synchronized (mLock) {
-                    mViewWrapper.getLocationInWindow(mLocationInWindow);
-                    mLock.set(mLocationInWindow[0], mLocationInWindow[1]);
+                    mPositionInfo = new ActivityTestBase.TestPositionInfo(
+                            surfaceOffset, screenOffset);
                     mLock.notify();
                 }
             });
diff --git a/tests/tests/view/src/android/view/cts/surfacevalidator/CapturedActivity.java b/tests/tests/view/src/android/view/cts/surfacevalidator/CapturedActivity.java
index 1ff6dc5..c8b7f14 100644
--- a/tests/tests/view/src/android/view/cts/surfacevalidator/CapturedActivity.java
+++ b/tests/tests/view/src/android/view/cts/surfacevalidator/CapturedActivity.java
@@ -32,10 +32,10 @@
 import android.os.Handler;
 import android.os.Looper;
 import android.support.test.InstrumentationRegistry;
+import android.support.test.uiautomator.By;
 import android.support.test.uiautomator.UiDevice;
-import android.support.test.uiautomator.UiObject;
-import android.support.test.uiautomator.UiObjectNotFoundException;
-import android.support.test.uiautomator.UiSelector;
+import android.support.test.uiautomator.UiObject2;
+import android.support.test.uiautomator.Until;
 import android.util.DisplayMetrics;
 import android.util.Log;
 import android.util.SparseArray;
@@ -69,6 +69,8 @@
 
     private static final long START_CAPTURE_DELAY_MS = 4000;
 
+    private static final String ACCEPT_RESOURCE_ID = "android:id/button1";
+
     private MediaPlayer mMediaPlayer;
 
     private final Handler mHandler = new Handler(Looper.getMainLooper());
@@ -105,14 +107,14 @@
         mMediaPlayer.setLooping(true);
     }
 
-    public void dismissPermissionDialog() throws UiObjectNotFoundException {
+    public void dismissPermissionDialog() {
         // The permission dialog will be auto-opened by the activity - find it and accept
         UiDevice uiDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation());
-        UiSelector acceptButtonSelector = new UiSelector().resourceId("android:id/button1");
-        UiObject acceptButton = uiDevice.findObject(acceptButtonSelector);
-            if (acceptButton.waitForExists(PERMISSION_DIALOG_WAIT_MS)) {
-            boolean success = acceptButton.click();
-            Log.d(TAG, "found permission dialog, click attempt success = " + success);
+        UiObject2 acceptButton = uiDevice.wait(Until.findObject(By.res(ACCEPT_RESOURCE_ID)),
+                PERMISSION_DIALOG_WAIT_MS);
+        if (acceptButton != null) {
+            Log.d(TAG, "found permission dialog after searching all windows, clicked");
+            acceptButton.click();
         }
     }
 
diff --git a/tests/tests/widget/src/android/widget/cts/TextViewTest.java b/tests/tests/widget/src/android/widget/cts/TextViewTest.java
index ac90cb7..367ed40 100644
--- a/tests/tests/widget/src/android/widget/cts/TextViewTest.java
+++ b/tests/tests/widget/src/android/widget/cts/TextViewTest.java
@@ -3506,7 +3506,7 @@
         final float doubleSpacing = mTextView.getLayout().getLineWidth(0);
 
         assertEquals("Double spacing should have two times the spacing of single spacing",
-                doubleSpacing - zeroSpacing, 2f * (singleSpacing - zeroSpacing), 1f);
+                doubleSpacing - zeroSpacing, 2f * (singleSpacing - zeroSpacing), 2f);
     }
 
     @UiThreadTest
diff --git a/tools/cts-tradefed/Android.mk b/tools/cts-tradefed/Android.mk
index 9a2f84f..ba8225c 100644
--- a/tools/cts-tradefed/Android.mk
+++ b/tools/cts-tradefed/Android.mk
@@ -29,7 +29,7 @@
 LOCAL_SUITE_TARGET_ARCH := $(TARGET_ARCH)
 LOCAL_SUITE_NAME := CTS
 LOCAL_SUITE_FULLNAME := "Compatibility Test Suite"
-LOCAL_SUITE_VERSION := 8.1_r3
+LOCAL_SUITE_VERSION := 8.1_r4
 LOCAL_STATIC_JAVA_LIBRARIES += cts-tradefed-harness
 
 LOCAL_MODULE := cts-tradefed