CtsVerifier / Camera format test: Apply a rotation to the format view when necessary.
Foldable devices break assumptions made by the camera format test, namely that mPreviewRotation is
always either 0 or 180. It is possible on a foldable device to change from portrait to landscape
while the camera sensor orientation remains the same, for example by unfolding the device. This
patch introduces a new matrix transformation to both the preview and format views when this
assumption has been broken.
Bug: 205503901
Test: Ran the Camera Format tests on all cameras on all orientations.
Change-Id: I34b1e28cb4828289df613f692a6491fe5dc8f22a
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 3fec587..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
@@ -22,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;
@@ -467,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);
@@ -492,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
@@ -510,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;
@@ -629,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;