From 22b4edd79ee19b84c09c74ec5d32ddfc3d12cc87 Mon Sep 17 00:00:00 2001 From: Kevin Chyn Date: Mon, 30 Jul 2018 19:20:01 -0700 Subject: [PATCH] 6/n: Add camera preview to FaceEnrollEnrolling Bug: 112005540 Test: manual Change-Id: Ie4f810dffecdec9731e20d5756854d9c9f420f4b --- AndroidManifest.xml | 15 +- res/layout/face_enroll_enrolling.xml | 23 +- .../face/FaceEnrollAnimationDrawable.java | 85 +++++ .../biometrics/face/FaceEnrollEnrolling.java | 14 + .../face/FaceEnrollPreviewFragment.java | 347 ++++++++++++++++++ .../face/FaceSquareFrameLayout.java | 60 +++ .../face/FaceSquareTextureView.java | 52 +++ 7 files changed, 583 insertions(+), 13 deletions(-) create mode 100644 src/com/android/settings/biometrics/face/FaceEnrollAnimationDrawable.java create mode 100644 src/com/android/settings/biometrics/face/FaceEnrollPreviewFragment.java create mode 100644 src/com/android/settings/biometrics/face/FaceSquareFrameLayout.java create mode 100644 src/com/android/settings/biometrics/face/FaceSquareTextureView.java diff --git a/AndroidManifest.xml b/AndroidManifest.xml index 0a5f24ba1be..51de8024d8a 100644 --- a/AndroidManifest.xml +++ b/AndroidManifest.xml @@ -94,6 +94,7 @@ + - - - + + + + + diff --git a/res/layout/face_enroll_enrolling.xml b/res/layout/face_enroll_enrolling.xml index 6ced80f0413..2208cc264d7 100644 --- a/res/layout/face_enroll_enrolling.xml +++ b/res/layout/face_enroll_enrolling.xml @@ -39,20 +39,23 @@ android:gravity="center" android:orientation="vertical"> - - - + - + + + bigEnough = new ArrayList<>(); + // Collect the supported resolutions that are smaller than the preview Surface + List notBigEnough = new ArrayList<>(); + + for (Size option : choices) { + if (option.getWidth() <= maxWidth && option.getHeight() <= maxHeight && + option.getHeight() == option.getWidth()) { + if (option.getWidth() >= textureViewWidth && + option.getHeight() >= textureViewHeight) { + bigEnough.add(option); + } else { + notBigEnough.add(option); + } + } + } + + // Pick the smallest of those big enough. If there is no one big enough, pick the + // largest of those not big enough. + if (bigEnough.size() > 0) { + return Collections.min(bigEnough, new CompareSizesByArea()); + } else if (notBigEnough.size() > 0) { + return Collections.max(notBigEnough, new CompareSizesByArea()); + } else { + Log.e(TAG, "Couldn't find any suitable preview size"); + return choices[0]; + } + } + + /** + * Configures the necessary {@link android.graphics.Matrix} transformation to `mTextureView`. + * This method should be called after the camera preview size is determined in + * setUpCameraOutputs and also the size of `mTextureView` is fixed. + * + * @param viewWidth The width of `mTextureView` + * @param viewHeight The height of `mTextureView` + */ + private void configureTransform(int viewWidth, int viewHeight) { + if (mTextureView == null) { + return; + } + + // Fix the aspect ratio + Matrix matrix = new Matrix(); + float scaleX = (float) viewWidth / mPreviewSize.getWidth(); + float scaleY = (float) viewHeight / mPreviewSize.getHeight(); + + // Now divide by smaller one so it fills up the original space + float smaller = Math.min(scaleX, scaleY); + scaleX = scaleX / smaller; + scaleY = scaleY / smaller; + + // Apply the scale + matrix.setScale(scaleX, scaleY); + + mTextureView.setTransform(matrix); + } + + private void closeCamera() { + if (mCaptureSession != null) { + mCaptureSession.close(); + mCaptureSession = null; + } + if (mCameraDevice != null) { + mCameraDevice.close(); + mCameraDevice = null; + } + } + + /** + * Compares two {@code Size}s based on their areas. + */ + private static class CompareSizesByArea implements Comparator { + @Override + public int compare(Size lhs, Size rhs) { + // We cast here to ensure the multiplications won't overflow + return Long.signum((long) lhs.getWidth() * lhs.getHeight() - + (long) rhs.getWidth() * rhs.getHeight()); + } + + } + +} diff --git a/src/com/android/settings/biometrics/face/FaceSquareFrameLayout.java b/src/com/android/settings/biometrics/face/FaceSquareFrameLayout.java new file mode 100644 index 00000000000..3aed5241f9a --- /dev/null +++ b/src/com/android/settings/biometrics/face/FaceSquareFrameLayout.java @@ -0,0 +1,60 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License + */ + +package com.android.settings.biometrics.face; + +import android.content.Context; +import android.util.AttributeSet; +import android.widget.FrameLayout; + +/** + * Square layout that sets the height to be the same as width. + */ +public class FaceSquareFrameLayout extends FrameLayout { + + public FaceSquareFrameLayout(Context context) { + super(context); + } + + public FaceSquareFrameLayout(Context context, AttributeSet attrs) { + super(context, attrs); + } + + public FaceSquareFrameLayout(Context context, AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + } + + public FaceSquareFrameLayout(Context context, AttributeSet attrs, int defStyleAttr, + int defStyleRes) { + super(context, attrs, defStyleAttr, defStyleRes); + } + + @Override + public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + // Don't call super, manually set their size below + int size = MeasureSpec.getSize(widthMeasureSpec); + + // Set this frame layout to be a square + setMeasuredDimension(size, size); + + // Set the children to be the same size (square) as well + final int numChildren = getChildCount(); + for (int i = 0; i < numChildren; i++) { + int spec = MeasureSpec.makeMeasureSpec(size, MeasureSpec.EXACTLY); + this.getChildAt(i).measure(spec, spec); + } + } +} diff --git a/src/com/android/settings/biometrics/face/FaceSquareTextureView.java b/src/com/android/settings/biometrics/face/FaceSquareTextureView.java new file mode 100644 index 00000000000..ebbbc27cb75 --- /dev/null +++ b/src/com/android/settings/biometrics/face/FaceSquareTextureView.java @@ -0,0 +1,52 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License + */ + +package com.android.settings.biometrics.face; + +import android.content.Context; +import android.util.AttributeSet; +import android.view.TextureView; + +/** + * A square {@link TextureView}. + */ +public class FaceSquareTextureView extends TextureView { + + public FaceSquareTextureView(Context context) { + this(context, null); + } + + public FaceSquareTextureView(Context context, AttributeSet attrs) { + this(context, attrs, 0); + } + + public FaceSquareTextureView(Context context, AttributeSet attrs, int defStyle) { + super(context, attrs, defStyle); + } + + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + super.onMeasure(widthMeasureSpec, heightMeasureSpec); + int width = MeasureSpec.getSize(widthMeasureSpec); + int height = MeasureSpec.getSize(heightMeasureSpec); + + if (width < height) { + setMeasuredDimension(width, width); + } else { + setMeasuredDimension(height, height); + } + } +}