Merge "Fixes COMMAND_SET_MAXIMUM_PASSWORD_ATTEMPTS for automotive" into sc-v2-dev
diff --git a/apps/CameraITS/tests/scene1_2/test_post_raw_sensitivity_boost.py b/apps/CameraITS/tests/scene1_2/test_post_raw_sensitivity_boost.py
index 1847d31..2ec5bf5 100644
--- a/apps/CameraITS/tests/scene1_2/test_post_raw_sensitivity_boost.py
+++ b/apps/CameraITS/tests/scene1_2/test_post_raw_sensitivity_boost.py
@@ -15,11 +15,11 @@
 
 
 import logging
+import math
 import os.path
 import matplotlib
 from matplotlib import pylab
 from mobly import test_runner
-import numpy as np
 
 import its_base_test
 import camera_properties_utils
@@ -36,7 +36,7 @@
 _PATCH_W = 0.1
 _PATCH_X = 0.5 - _PATCH_W/2
 _PATCH_Y = 0.5 - _PATCH_H/2
-_RATIO_TOL = 0.1  # +/-10% TOL on images vs expected values
+_RATIO_RTOL = 0.1  # +/-10% TOL on images vs expected values
 _RAW_PIXEL_THRESH = 0.03  # Waive check if RAW [0, 1] value below this thresh
 
 
@@ -189,10 +189,11 @@
                         raw_means[step][ch], ratio_per_step)
           if raw_means[step][ch] <= _RAW_PIXEL_THRESH:
             continue
-          if not np.isclose(ratio_per_step, expected_ratio, atol=_RATIO_TOL):
+          if not math.isclose(ratio_per_step, expected_ratio,
+                              rel_tol=_RATIO_RTOL):
             raise AssertionError(
                 f'step: {step}, ratio: {ratio_per_step}, expected ratio: '
-                f'{expected_ratio:.3f}, ATOL: {_RATIO_TOL}')
+                f'{expected_ratio:.3f}, RTOL: {_RATIO_RTOL}')
 
       # YUV asserts
       for ch, _ in enumerate(_COLORS):
@@ -204,9 +205,9 @@
         logging.debug('%s channel vals %s mean %f', _COLORS[ch], vals, mean)
         for step in range(len(vals)):
           ratio_mean = vals[step] / mean
-          if not np.isclose(1.0, ratio_mean, atol=_RATIO_TOL):
+          if not math.isclose(1.0, ratio_mean, rel_tol=_RATIO_RTOL):
             raise AssertionError(
-                f'Capture vs mean ratio: {ratio_mean}, TOL: +/- {_RATIO_TOL}')
+                f'Capture vs mean ratio: {ratio_mean}, RTOL: +/- {_RATIO_RTOL}')
 
 if __name__ == '__main__':
   test_runner.main()
diff --git a/apps/CtsVerifier/AndroidManifest.xml b/apps/CtsVerifier/AndroidManifest.xml
index 9942995..1f7a904 100644
--- a/apps/CtsVerifier/AndroidManifest.xml
+++ b/apps/CtsVerifier/AndroidManifest.xml
@@ -2631,8 +2631,7 @@
 
         <activity android:name=".camera.formats.CameraFormatsActivity"
                  android:label="@string/camera_format"
-                 android:exported="true"
-                 android:screenOrientation="landscape">
+                 android:exported="true">
             <intent-filter>
                 <action android:name="android.intent.action.MAIN" />
                 <category android:name="android.cts.intent.category.MANUAL_TEST" />
@@ -2685,7 +2684,6 @@
         <activity
             android:name=".camera.fov.PhotoCaptureActivity"
             android:label="@string/camera_fov_calibration"
-            android:screenOrientation="landscape"
             android:exported="true"
             android:theme="@android:style/Theme.Holo.NoActionBar.Fullscreen" >
             <intent-filter android:label="@string/camera_fov_calibration" >
@@ -2702,7 +2700,6 @@
         <activity
             android:name=".camera.fov.DetermineFovActivity"
             android:label="@string/camera_fov_calibration"
-            android:screenOrientation="landscape"
             android:theme="@android:style/Theme.Holo.NoActionBar.Fullscreen" >
             <meta-data android:name="test_excluded_features"
                        android:value="android.hardware.type.automotive"/>
@@ -2721,8 +2718,7 @@
 
         <activity android:name=".camera.video.CameraVideoActivity"
                  android:label="@string/camera_video"
-                 android:exported="true"
-                 android:screenOrientation="landscape">
+                 android:exported="true">
             <intent-filter>
                 <action android:name="android.intent.action.MAIN" />
                 <category android:name="android.cts.intent.category.MANUAL_TEST" />
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/TestListActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/TestListActivity.java
index 13b2ec3..b4b99db 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/TestListActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/TestListActivity.java
@@ -16,15 +16,20 @@
 
 package com.android.cts.verifier;
 
+import static android.content.pm.PermissionInfo.PROTECTION_DANGEROUS;
+
+import android.Manifest;
 import android.app.AlertDialog;
 import android.app.ListActivity;
 import android.content.DialogInterface;
+import android.content.Intent;
 import android.content.SharedPreferences;
 import android.content.pm.PackageInfo;
 import android.content.pm.PackageManager;
 import android.content.pm.PackageManager.NameNotFoundException;
-import android.content.pm.PermissionInfo;
+import android.net.Uri;
 import android.os.Bundle;
+import android.provider.Settings;
 import android.util.Log;
 import android.view.Menu;
 import android.view.MenuInflater;
@@ -35,9 +40,13 @@
 import android.widget.Switch;
 import android.widget.Toast;
 
+import java.util.Arrays;
+import java.util.Objects;
+
 /** Top-level {@link ListActivity} for launching tests and managing results. */
 public class TestListActivity extends AbstractTestListActivity implements View.OnClickListener {
     private static final int CTS_VERIFIER_PERMISSION_REQUEST = 1;
+    private static final int CTS_VERIFIER_BACKGROUND_LOCATION_PERMISSION_REQUEST = 2;
 
     private static final String TAG = TestListActivity.class.getSimpleName();
     // Records the current display mode.
@@ -84,25 +93,17 @@
                     getApplicationInfo().packageName, PackageManager.GET_PERMISSIONS);
 
             if (packageInfo.requestedPermissions != null) {
-                for (String permission : packageInfo.requestedPermissions) {
-                    Log.v(TAG, "Checking permissions for: " + permission);
+                String[] permissionsToRequest = removeString(packageInfo.requestedPermissions,
+                                Manifest.permission.ACCESS_BACKGROUND_LOCATION);
+                permissionsToRequest = Arrays.stream(permissionsToRequest).filter(s -> {
                     try {
-                        PermissionInfo info = pm.getPermissionInfo(permission, 0);
-                        if ((info.protectionLevel & PermissionInfo.PROTECTION_DANGEROUS) == 0) {
-                            continue;
-                        }
+                        return (pm.getPermissionInfo(s, 0).getProtection() & PROTECTION_DANGEROUS)
+                                != 0;
                     } catch (NameNotFoundException e) {
-                        Log.v(TAG, "Checking permissions for: " + permission + "not found");
-                        continue;
+                        return false;
                     }
-                    if (checkSelfPermission(permission) != PackageManager.PERMISSION_GRANTED) {
-                        requestPermissions(packageInfo.requestedPermissions,
-                                CTS_VERIFIER_PERMISSION_REQUEST);
-                        /* don't return here. Some tests (i.e. USB Restrict Access test)
-                         * which need to run even if permissions are incomplete.
-                         */
-                    }
-                }
+                }).toArray(String[]::new);
+                requestPermissions(permissionsToRequest, CTS_VERIFIER_PERMISSION_REQUEST);
             }
             createContinue();
         } catch (NameNotFoundException e) {
@@ -117,6 +118,11 @@
         }
         sInitialLaunch = true;
 
+        // Restores the last display mode when launching the app after killing the process.
+        if (getCurrentDisplayMode().equals(DisplayMode.FOLDED.toString())) {
+            sCurrentDisplayMode = DisplayMode.FOLDED.toString();
+        }
+
         setTitle(getString(R.string.title_version, Version.getVersionName(this)));
 
         if (!getWindow().hasFeature(Window.FEATURE_ACTION_BAR)) {
@@ -135,13 +141,37 @@
     public void onRequestPermissionsResult(
             int requestCode, String permissions[], int[] grantResults) {
         if (requestCode == CTS_VERIFIER_PERMISSION_REQUEST) {
-            if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
-                createContinue();
-                return;
+            if (arrayContains(grantResults, PackageManager.PERMISSION_DENIED)) {
+                Log.v(TAG, "Didn't grant all permissions.");
+                // If we're sending them to settings we don't need to request background location
+                // since they can just grant in settings.
+                sendUserToSettings();
+            } else {
+                requestPermissions(new String[] {Manifest.permission.ACCESS_BACKGROUND_LOCATION},
+                        CTS_VERIFIER_BACKGROUND_LOCATION_PERMISSION_REQUEST);
             }
-            Log.v(TAG, "Permission not granted.");
-            Toast.makeText(this, R.string.runtime_permissions_error, Toast.LENGTH_SHORT).show();
         }
+        if (requestCode == CTS_VERIFIER_BACKGROUND_LOCATION_PERMISSION_REQUEST) {
+            if (grantResults[0] == PackageManager.PERMISSION_DENIED) {
+                Log.v(TAG, "Didn't grant background permission.");
+                sendUserToSettings();
+            }
+            return;
+        }
+    }
+
+    private AlertDialog sendUserToSettings() {
+        return new AlertDialog.Builder(this)
+                .setTitle("Please grant all permissions")
+                .setPositiveButton(
+                        "Ok", (dialog, which) -> {
+                            if (which == AlertDialog.BUTTON_POSITIVE) {
+                                startActivity(new Intent(
+                                        Settings.ACTION_APPLICATION_DETAILS_SETTINGS).setData(
+                                        Uri.fromParts("package", getPackageName(), null)));
+                            }
+                        })
+                .show();
     }
 
     @Override
@@ -154,14 +184,8 @@
         item.setActionView(R.layout.display_mode_switch);
         Switch displayModeSwitch = item.getActionView().findViewById(R.id.switch_button);
 
-        // Restores the original display mode when launching the app after killing the process.
-        // Otherwise, gets the current display mode to show switch status.
-        boolean isFoldedMode;
-        if (sInitialLaunch) {
-            isFoldedMode = getCurrentDisplayMode().equals(DisplayMode.FOLDED.toString());
-        } else {
-            isFoldedMode = sCurrentDisplayMode.equals(DisplayMode.FOLDED.toString());
-        }
+        // Get the current display mode to show switch status.
+        boolean isFoldedMode = sCurrentDisplayMode.equals(DisplayMode.FOLDED.toString());
         displayModeSwitch.setChecked(isFoldedMode);
 
         displayModeSwitch.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
@@ -244,4 +268,34 @@
             .getString(DisplayMode.class.getName(), "");
         return mode;
     }
-}
\ No newline at end of file
+
+    private static boolean arrayContains(int[] array, int value) {
+        if (array == null) return false;
+        for (int element : array) {
+            if (element == value) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    private static String[] removeString(String[] cur, String val) {
+        if (cur == null) {
+            return null;
+        }
+        final int n = cur.length;
+        for (int i = 0; i < n; i++) {
+            if (Objects.equals(cur[i], val)) {
+                String[] ret = new String[n - 1];
+                if (i > 0) {
+                    System.arraycopy(cur, 0, ret, 0, i);
+                }
+                if (i < (n - 1)) {
+                    System.arraycopy(cur, i + 1, ret, i, n - i - 1);
+                }
+                return ret;
+            }
+        }
+        return cur;
+    }
+}
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/camera/formats/CameraFormatsActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/camera/formats/CameraFormatsActivity.java
index 7fead16..793cbf7 100755
--- a/apps/CtsVerifier/src/com/android/cts/verifier/camera/formats/CameraFormatsActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/camera/formats/CameraFormatsActivity.java
@@ -15,9 +15,6 @@
  */
 package com.android.cts.verifier.camera.formats;
 
-import com.android.cts.verifier.PassFailButtons;
-import com.android.cts.verifier.R;
-
 import android.app.AlertDialog;
 import android.graphics.Bitmap;
 import android.graphics.Color;
@@ -25,6 +22,7 @@
 import android.graphics.ColorMatrixColorFilter;
 import android.graphics.ImageFormat;
 import android.graphics.Matrix;
+import android.graphics.Rect;
 import android.graphics.SurfaceTexture;
 import android.hardware.Camera;
 import android.hardware.Camera.CameraInfo;
@@ -35,9 +33,9 @@
 import android.util.SparseArray;
 import android.view.Menu;
 import android.view.MenuItem;
-import android.view.View;
 import android.view.Surface;
 import android.view.TextureView;
+import android.view.View;
 import android.widget.AdapterView;
 import android.widget.ArrayAdapter;
 import android.widget.Button;
@@ -46,11 +44,13 @@
 import android.widget.Spinner;
 import android.widget.Toast;
 
+import com.android.cts.verifier.PassFailButtons;
+import com.android.cts.verifier.R;
+
 import java.io.IOException;
-import java.lang.Math;
 import java.util.ArrayList;
-import java.util.HashSet;
 import java.util.Comparator;
+import java.util.HashSet;
 import java.util.List;
 import java.util.Optional;
 import java.util.TreeSet;
@@ -468,10 +468,6 @@
         } else {  // back-facing
             mPreviewRotation = (info.orientation - degrees + 360) % 360;
         }
-        if (mPreviewRotation != 0 && mPreviewRotation != 180) {
-            Log.w(TAG,
-                "Display orientation correction is not 0 or 180, as expected!");
-        }
 
         mCamera.setDisplayOrientation(mPreviewRotation);
 
@@ -493,6 +489,36 @@
         }
     }
 
+    /**
+     * Rotate and scale the matrix to be applied to the preview or format view, such that no
+     * stretching of the image occurs. To achieve this, the image is centered in the SurfaceTexture
+     * with black bars filling the excess space.
+     */
+    private void concatPreviewTransform(Matrix transform) {
+        float widthRatio = mNextPreviewSize.width / (float) mPreviewTexWidth;
+        float heightRatio = mNextPreviewSize.height / (float) mPreviewTexHeight;
+        float scaledWidth = (float) mPreviewTexWidth;
+        float scaledHeight = (float) mPreviewTexHeight;
+
+        if (heightRatio < widthRatio) {
+            scaledHeight = mPreviewTexHeight * (heightRatio / widthRatio);
+            transform.postScale(1, heightRatio / widthRatio);
+            transform.postTranslate(0,
+                    mPreviewTexHeight * (1 - heightRatio / widthRatio) / 2);
+        } else {
+            scaledWidth = mPreviewTexWidth * (widthRatio / heightRatio);
+            transform.postScale(widthRatio / heightRatio, 1);
+            transform.postTranslate(mPreviewTexWidth * (1 - widthRatio / heightRatio) / 2, 0);
+        }
+
+        if (mPreviewRotation == 90 || mPreviewRotation == 270) {
+            float scaledAspect = scaledWidth / scaledHeight;
+            float previewAspect = (float) mNextPreviewSize.width / (float) mNextPreviewSize.height;
+            transform.postScale(1.0f, scaledAspect * previewAspect,
+                                (float) mPreviewTexWidth / 2, (float) mPreviewTexHeight / 2);
+        }
+    }
+
     private void startPreview() {
         if (mState != STATE_OFF) {
             // Stop for a while to drain callbacks
@@ -511,19 +537,7 @@
         mState = STATE_PREVIEW;
 
         Matrix transform = new Matrix();
-        float widthRatio = mNextPreviewSize.width / (float)mPreviewTexWidth;
-        float heightRatio = mNextPreviewSize.height / (float)mPreviewTexHeight;
-
-        if (heightRatio < widthRatio) {
-            transform.setScale(1, heightRatio/widthRatio);
-            transform.postTranslate(0,
-                mPreviewTexHeight * (1 - heightRatio/widthRatio)/2);
-        } else {
-            transform.setScale(widthRatio/heightRatio, 1);
-            transform.postTranslate(mPreviewTexWidth * (1 - widthRatio/heightRatio)/2,
-            0);
-        }
-
+        concatPreviewTransform(transform);
         mPreviewView.setTransform(transform);
 
         mPreviewFormat = mNextPreviewFormat;
@@ -630,6 +644,31 @@
         protected void onPostExecute(Boolean result) {
             if (result) {
                 mFormatView.setImageBitmap(mCallbackBitmap);
+
+                CameraInfo info = new CameraInfo();
+                Camera.getCameraInfo(mCurrentCameraId, info);
+
+                int rotation = mPreviewRotation;
+                if (info.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {
+                    rotation = (360 - rotation) % 360;  // de-compensate the mirror
+                }
+
+                if (rotation != 0) {
+                    Matrix transform = new Matrix();
+                    mFormatView.setScaleType(ImageView.ScaleType.MATRIX);
+                    Rect viewRect = mFormatView.getDrawable().getBounds();
+                    transform.postTranslate(-viewRect.width() / 2, -viewRect.height() / 2);
+                    transform.postRotate(rotation);
+                    transform.postTranslate(viewRect.height() / 2, viewRect.width() / 2);
+                    transform.postScale(
+                            mPreviewView.getMeasuredWidth() / (float) viewRect.height(),
+                            mPreviewView.getMeasuredHeight() / (float) viewRect.width());
+                    concatPreviewTransform(transform);
+                    mFormatView.setImageMatrix(transform);
+                } else {
+                    mFormatView.setScaleType(ImageView.ScaleType.FIT_CENTER);
+                }
+
                 if (mProcessingFirstFrame) {
                     mProcessingFirstFrame = false;
 
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/camera/fov/DetermineFovActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/camera/fov/DetermineFovActivity.java
index 959e98f..b40a24f 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/camera/fov/DetermineFovActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/camera/fov/DetermineFovActivity.java
@@ -16,16 +16,16 @@
 
 package com.android.cts.verifier.camera.fov;
 
-import com.android.cts.verifier.R;
-
 import android.app.Activity;
 import android.content.SharedPreferences;
 import android.graphics.Bitmap;
 import android.graphics.BitmapFactory;
 import android.graphics.Canvas;
 import android.graphics.Color;
+import android.graphics.Matrix;
 import android.graphics.Paint;
 import android.graphics.RectF;
+import android.media.ExifInterface;
 import android.os.Bundle;
 import android.preference.PreferenceManager;
 import android.view.SurfaceHolder;
@@ -35,6 +35,8 @@
 import android.widget.SeekBar;
 import android.widget.SeekBar.OnSeekBarChangeListener;
 
+import com.android.cts.verifier.R;
+
 import java.io.File;
 import java.io.FileInputStream;
 import java.io.IOException;
@@ -77,6 +79,28 @@
             e.printStackTrace();
         }
 
+        int previewOrientation;
+        try {
+            ExifInterface exif = new ExifInterface(pictureFile);
+            int exifOrientation = exif.getAttributeInt(ExifInterface.TAG_ORIENTATION,
+                                                       ExifInterface.ORIENTATION_NORMAL);
+            switch (exifOrientation) {
+                case ExifInterface.ORIENTATION_ROTATE_90: previewOrientation = 90; break;
+                case ExifInterface.ORIENTATION_ROTATE_180: previewOrientation = 180; break;
+                case ExifInterface.ORIENTATION_ROTATE_270: previewOrientation = 270; break;
+                default: previewOrientation = 0; break;
+            }
+        } catch (IOException e) {
+            previewOrientation = 0;
+        }
+
+        if (previewOrientation != 0) {
+            Matrix transform = new Matrix();
+            transform.setRotate(previewOrientation);
+            mPhotoBitmap = Bitmap.createBitmap(mPhotoBitmap, 0, 0, mPhotoBitmap.getWidth(),
+                                               mPhotoBitmap.getHeight(), transform, true);
+        }
+
         mSurfaceView = (SurfaceView) findViewById(R.id.camera_fov_photo_surface);
         mSurfaceHolder = mSurfaceView.getHolder();
         mSurfaceHolder.addCallback(new SurfaceHolder.Callback() {
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/camera/fov/PhotoCaptureActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/camera/fov/PhotoCaptureActivity.java
index b627797..6c8c501 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/camera/fov/PhotoCaptureActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/camera/fov/PhotoCaptureActivity.java
@@ -453,8 +453,13 @@
         if (mPreviewSizes != null) {
             selectedPreviewSize = mPreviewSizes[mSelectedResolution.cameraId];
         } else if (mSurfaceSize != null) {
-            selectedPreviewSize = getBestPreviewSize(
-                    mSurfaceSize.width, mSurfaceSize.height, params);
+            if (mPreviewOrientation == 0 || mPreviewOrientation == 180) {
+                selectedPreviewSize = getBestPreviewSize(
+                        mSurfaceSize.width, mSurfaceSize.height, params);
+            } else {
+                selectedPreviewSize = getBestPreviewSize(
+                        mSurfaceSize.height, mSurfaceSize.width, params);
+            }
         }
 
         if (selectedPreviewSize != null) {
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/camera/video/CameraVideoActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/camera/video/CameraVideoActivity.java
index f38ba85..d508f7a 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/camera/video/CameraVideoActivity.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/camera/video/CameraVideoActivity.java
@@ -16,22 +16,17 @@
 package com.android.cts.verifier.camera.video;
 
 import android.app.AlertDialog;
-import android.content.Context;
 import android.content.DialogInterface;
 import android.graphics.Matrix;
 import android.graphics.SurfaceTexture;
 import android.hardware.Camera;
 import android.hardware.Camera.CameraInfo;
 import android.hardware.Camera.Size;
-import android.hardware.camera2.CameraAccessException;
-import android.hardware.camera2.CameraCharacteristics;
-import android.hardware.camera2.CameraManager;
 import android.hardware.cts.helpers.CameraUtils;
 import android.media.CamcorderProfile;
 import android.media.MediaPlayer;
 import android.media.MediaRecorder;
 import android.os.Bundle;
-import android.os.Environment;
 import android.os.Handler;
 import android.text.method.ScrollingMovementMethod;
 import android.util.Log;
@@ -871,10 +866,6 @@
             mVideoRotation = (info.orientation - degrees + 360) % 360;
             mPreviewRotation = mVideoRotation;
         }
-        if (mPreviewRotation != 0 && mPreviewRotation != 180) {
-            Log.w(TAG,
-                "Display orientation correction is not 0 or 180, as expected!");
-        }
 
         mCamera.setDisplayOrientation(mPreviewRotation);
 
@@ -903,26 +894,36 @@
         Matrix transform = new Matrix();
         float widthRatio = mNextPreviewSize.width / (float)mPreviewTexWidth;
         float heightRatio = mNextPreviewSize.height / (float)mPreviewTexHeight;
+        float scaledWidth = (float) mPreviewTexWidth;
+        float scaledHeight = (float) mPreviewTexHeight;
         if (VERBOSE) {
             Log.v(TAG, "startPreview: widthRatio=" + widthRatio + " " + "heightRatio=" +
                     heightRatio);
         }
 
         if (heightRatio < widthRatio) {
+            scaledHeight = mPreviewTexHeight * (heightRatio / widthRatio);
             transform.setScale(1, heightRatio / widthRatio);
-            transform.postTranslate(0,
-                    mPreviewTexHeight * (1 - heightRatio / widthRatio) / 2);
+            transform.postTranslate(0, (mPreviewTexHeight - scaledHeight) / 2);
             if (VERBOSE) {
                 Log.v(TAG, "startPreview: shrink vertical by " + heightRatio / widthRatio);
             }
         } else {
+            scaledWidth = mPreviewTexWidth * (widthRatio / heightRatio);
             transform.setScale(widthRatio / heightRatio, 1);
-            transform.postTranslate(mPreviewTexWidth * (1 - widthRatio / heightRatio) / 2, 0);
+            transform.postTranslate((mPreviewTexWidth - scaledWidth) / 2, 0);
             if (VERBOSE) {
                 Log.v(TAG, "startPreview: shrink horizontal by " + widthRatio / heightRatio);
             }
         }
 
+        if (mPreviewRotation == 90 || mPreviewRotation == 270) {
+            float scaledAspect = scaledWidth / scaledHeight;
+            float previewAspect = (float) mNextPreviewSize.width / (float) mNextPreviewSize.height;
+            transform.postScale(1.0f, scaledAspect * previewAspect,
+                                (float) mPreviewTexWidth / 2, (float) mPreviewTexHeight / 2);
+        }
+
         mPreviewView.setTransform(transform);
 
         mPreviewSize = mNextPreviewSize;
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/Utils.java b/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/Utils.java
index 68685ba..5fad20c 100644
--- a/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/Utils.java
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/managedprovisioning/Utils.java
@@ -28,8 +28,11 @@
 import android.content.DialogInterface;
 import android.content.Intent;
 import android.content.pm.PackageManager;
+import android.os.UserHandle;
+import android.os.UserManager;
 import android.util.Log;
 import android.widget.Toast;
+
 import com.android.cts.verifier.IntentDrivenTestActivity;
 import com.android.cts.verifier.IntentDrivenTestActivity.ButtonInfo;
 import com.android.cts.verifier.R;
@@ -82,26 +85,36 @@
     }
 
     static void showBugreportNotification(Context context, String msg, int notificationId) {
-        NotificationManager mNotificationManager =
-                (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
-
+        NotificationManager notificationManager = getNotificationManager(context);
         NotificationChannel channel = new NotificationChannel(CHANNEL_ID,
                 CHANNEL_ID, NotificationManager.IMPORTANCE_HIGH);
-        mNotificationManager.createNotificationChannel(channel);
+        notificationManager.createNotificationChannel(channel);
+        CharSequence title = context.getString(R.string.device_owner_requesting_bugreport_tests);
         Notification notification = new Notification.Builder(context)
                 .setChannelId(CHANNEL_ID)
                 .setSmallIcon(R.drawable.icon)
-                .setContentTitle(context.getString(
-                        R.string.device_owner_requesting_bugreport_tests))
+                .setContentTitle(title)
                 .setContentText(msg)
                 .setStyle(new Notification.BigTextStyle().bigText(msg))
                 .extend(new Notification.TvExtender())
                 .build();
-        mNotificationManager.notify(notificationId, notification);
+        Log.d(TAG, "Sending notification: id=" + notificationId + ", title='" + title
+                + "' text='" + msg + "'");
+        notificationManager.notify(notificationId, notification);
+    }
+
+    private static NotificationManager getNotificationManager(Context context) {
+        if (UserManager.isHeadlessSystemUserMode()) {
+            Log.d(TAG, "getNotificationManager(): using context for current user");
+            context = context.createContextAsUser(UserHandle.CURRENT, /* flags= */ 0);
+        }
+        return context.getSystemService(NotificationManager.class);
     }
 
     static void showToast(Context context, int messageId) {
-        Toast.makeText(context, messageId, Toast.LENGTH_SHORT).show();
+        CharSequence msg = context.getString(messageId);
+        Log.d(TAG, "showToast(): " + msg);
+        Toast.makeText(context, msg, Toast.LENGTH_SHORT).show();
     }
 
     /**
diff --git a/hostsidetests/devicepolicy/app/DeviceOwner/src/com/android/cts/deviceowner/WifiConfigLockdownTest.java b/hostsidetests/devicepolicy/app/DeviceOwner/src/com/android/cts/deviceowner/WifiConfigLockdownTest.java
index f717086..627ef61 100644
--- a/hostsidetests/devicepolicy/app/DeviceOwner/src/com/android/cts/deviceowner/WifiConfigLockdownTest.java
+++ b/hostsidetests/devicepolicy/app/DeviceOwner/src/com/android/cts/deviceowner/WifiConfigLockdownTest.java
@@ -104,6 +104,21 @@
                 .that(updateCount).isAtLeast(2);
     }
 
+    public void testDeviceOwnerCanRemoveConfig() throws Exception {
+        List<WifiConfiguration> configs = mWifiManager.getConfiguredNetworks();
+        int removeCount = 0;
+        for (WifiConfiguration config : configs) {
+            if (areMatchingSsids(ORIGINAL_DEVICE_OWNER_SSID, config.SSID)
+                    || areMatchingSsids(ORIGINAL_REGULAR_SSID, config.SSID)) {
+                assertWithMessage("mWifiManager.removeNetwork(%s)", config.networkId)
+                        .that(mWifiManager.removeNetwork(config.networkId)).isTrue();
+                ++removeCount;
+            }
+        }
+        assertWithMessage("number of removed configs (the DO created one and the regular one)")
+                .that(removeCount).isEqualTo(2);
+    }
+
     public void testRegularAppCannotUpdateDeviceOwnerConfig() throws Exception {
         List<WifiConfiguration> configs = mWifiConfigCreator.getConfiguredNetworks();
         logConfigs("testRegularAppCannotUpdateDeviceOwnerConfig()", configs);
diff --git a/tests/framework/base/windowmanager/src/android/server/wm/CompatChangeTests.java b/tests/framework/base/windowmanager/src/android/server/wm/CompatChangeTests.java
index ad1d0e3..7435c9c 100644
--- a/tests/framework/base/windowmanager/src/android/server/wm/CompatChangeTests.java
+++ b/tests/framework/base/windowmanager/src/android/server/wm/CompatChangeTests.java
@@ -45,6 +45,7 @@
 import android.util.Size;
 
 import androidx.annotation.Nullable;
+import androidx.test.filters.FlakyTest;
 
 import libcore.junit.util.compat.CoreCompatChangeRule.DisableCompatChanges;
 import libcore.junit.util.compat.CoreCompatChangeRule.EnableCompatChanges;
@@ -69,6 +70,7 @@
  * atest CtsWindowManagerDeviceTestCases:CompatChangeTests
  */
 @Presubmit
+@FlakyTest(bugId = 190609681)
 public final class CompatChangeTests extends MultiDisplayTestBase {
     private static final ComponentName RESIZEABLE_PORTRAIT_ACTIVITY =
             component(ResizeablePortraitActivity.class);
diff --git a/tests/tests/media/src/android/media/cts/MediaCodecBlockModelTest.java b/tests/tests/media/src/android/media/cts/MediaCodecBlockModelTest.java
index cbfdf35..696e37f 100644
--- a/tests/tests/media/src/android/media/cts/MediaCodecBlockModelTest.java
+++ b/tests/tests/media/src/android/media/cts/MediaCodecBlockModelTest.java
@@ -845,18 +845,19 @@
                             rowSampling = 2;
                             colSampling = 2;
                         }
-                        long timestampUs = 1000000l * frameIndex / kFrameRate;
-                        ++frameIndex;
-                        if (frameIndex >= 32) {
-                            signaledEos = true;
-                        }
-                        timestampList.add(timestampUs);
-                        mediaCodec.getQueueRequest(event.index)
-                                .setHardwareBuffer(buffer)
-                                .setPresentationTimeUs(timestampUs)
-                                .setFlags(signaledEos ? MediaCodec.BUFFER_FLAG_END_OF_STREAM : 0)
-                                .queue();
                     }
+
+                    long timestampUs = 1000000l * frameIndex / kFrameRate;
+                    ++frameIndex;
+                    if (frameIndex >= 32) {
+                        signaledEos = true;
+                    }
+                    timestampList.add(timestampUs);
+                    mediaCodec.getQueueRequest(event.index)
+                            .setHardwareBuffer(buffer)
+                            .setPresentationTimeUs(timestampUs)
+                            .setFlags(signaledEos ? MediaCodec.BUFFER_FLAG_END_OF_STREAM : 0)
+                            .queue();
                 } else {
                     MediaCodec.OutputFrame frame = mediaCodec.getOutputFrame(event.index);
                     eos = (frame.getFlags() & MediaCodec.BUFFER_FLAG_END_OF_STREAM) != 0;