• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2022 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.settings.biometrics.fingerprint;
18 
19 import android.content.Context;
20 import android.graphics.Rect;
21 import android.graphics.RectF;
22 import android.hardware.fingerprint.FingerprintSensorProperties;
23 import android.os.Handler;
24 import android.os.Looper;
25 import android.util.AttributeSet;
26 import android.util.RotationUtils;
27 import android.view.Gravity;
28 import android.view.Surface;
29 import android.view.ViewGroup;
30 import android.widget.FrameLayout;
31 import android.widget.ImageView;
32 
33 import androidx.annotation.NonNull;
34 import androidx.annotation.Nullable;
35 
36 import com.android.settings.R;
37 import com.android.systemui.biometrics.shared.model.UdfpsOverlayParams;
38 
39 /**
40  * View corresponding with udfps_enroll_view.xml
41  */
42 public class UdfpsEnrollView extends FrameLayout implements UdfpsEnrollHelper.Listener {
43     private static final String TAG = "UdfpsEnrollView";
44     @NonNull
45     private final UdfpsEnrollDrawable mFingerprintDrawable;
46     @NonNull
47     private final UdfpsEnrollProgressBarDrawable mFingerprintProgressDrawable;
48     @NonNull
49     private final Handler mHandler;
50 
51     @NonNull
52     private ImageView mFingerprintProgressView;
53 
54     private int mProgressBarRadius;
55 
56     // sensorRect may be bigger than the sensor. True sensor dimensions are defined in
57     // overlayParams.sensorBounds
58     private Rect mSensorRect;
59     private UdfpsOverlayParams mOverlayParams;
60 
UdfpsEnrollView(Context context, @Nullable AttributeSet attrs)61     public UdfpsEnrollView(Context context, @Nullable AttributeSet attrs) {
62         super(context, attrs);
63         mFingerprintDrawable = new UdfpsEnrollDrawable(mContext, attrs);
64         mFingerprintProgressDrawable = new UdfpsEnrollProgressBarDrawable(context, attrs);
65         mHandler = new Handler(Looper.getMainLooper());
66     }
67 
68     @Override
onFinishInflate()69     protected void onFinishInflate() {
70         ImageView fingerprintView = findViewById(R.id.udfps_enroll_animation_fp_view);
71         fingerprintView.setImageDrawable(mFingerprintDrawable);
72         mFingerprintProgressView = findViewById(R.id.udfps_enroll_animation_fp_progress_view);
73         mFingerprintProgressView.setImageDrawable(mFingerprintProgressDrawable);
74     }
75 
76     // Implements UdfpsEnrollHelper.Listener
77     @Override
onEnrollmentProgress(int remaining, int totalSteps)78     public void onEnrollmentProgress(int remaining, int totalSteps) {
79         mHandler.post(() -> {
80             mFingerprintProgressDrawable.onEnrollmentProgress(remaining, totalSteps);
81             mFingerprintDrawable.onEnrollmentProgress(remaining, totalSteps);
82         });
83     }
84 
85     @Override
onEnrollmentHelp(int remaining, int totalSteps)86     public void onEnrollmentHelp(int remaining, int totalSteps) {
87         mHandler.post(() -> mFingerprintProgressDrawable.onEnrollmentHelp(remaining, totalSteps));
88     }
89 
90     @Override
onAcquired(boolean animateIfLastStepGood)91     public void onAcquired(boolean animateIfLastStepGood) {
92         mHandler.post(() -> {
93             onFingerUp();
94             if (animateIfLastStepGood) mFingerprintProgressDrawable.onLastStepAcquired();
95         });
96     }
97 
98     @Override
onPointerDown(int sensorId)99     public void onPointerDown(int sensorId) {
100         onFingerDown();
101     }
102 
103     @Override
onPointerUp(int sensorId)104     public void onPointerUp(int sensorId) {
105         onFingerUp();
106     }
107 
getOverlayParams()108     public UdfpsOverlayParams getOverlayParams() {
109         return mOverlayParams;
110     }
111 
112     /**
113      * Set UdfpsOverlayParams
114      */
setOverlayParams(UdfpsOverlayParams params)115     public void setOverlayParams(UdfpsOverlayParams params) {
116         mOverlayParams = params;
117 
118         post(() -> {
119             mProgressBarRadius =
120                     (int) (mOverlayParams.getScaleFactor() * getContext().getResources().getInteger(
121                             R.integer.config_udfpsEnrollProgressBar));
122             mSensorRect = new Rect(mOverlayParams.getSensorBounds());
123 
124             onSensorRectUpdated();
125         });
126     }
127 
128     /**
129      * Set UdfpsEnrollHelper
130      */
setEnrollHelper(UdfpsEnrollHelper enrollHelper)131     public void setEnrollHelper(UdfpsEnrollHelper enrollHelper) {
132         mFingerprintDrawable.setEnrollHelper(enrollHelper);
133         enrollHelper.setListener(this);
134     }
135 
136     /**
137      * Adjust progress bar radius only for decreasing.
138      * @param decreasePadding the decrease padding
139      */
setDecreasePadding(int decreasePadding)140     void setDecreasePadding(int decreasePadding) {
141         mProgressBarRadius -= decreasePadding;
142         onSensorRectUpdated();
143     }
144 
onSensorRectUpdated()145     private void onSensorRectUpdated() {
146         updateDimensions();
147 
148         // Updates sensor rect in relation to the overlay view
149         mSensorRect.set(getPaddingX(), getPaddingY(),
150                 (mOverlayParams.getSensorBounds().width() + getPaddingX()),
151                 (mOverlayParams.getSensorBounds().height() + getPaddingY()));
152         mFingerprintDrawable.onSensorRectUpdated(new RectF(mSensorRect));
153     }
154 
updateDimensions()155     private void updateDimensions() {
156         // Original sensorBounds assume portrait mode.
157         final Rect rotatedBounds = new Rect(mOverlayParams.getSensorBounds());
158         int rotation = mOverlayParams.getRotation();
159         if (rotation == Surface.ROTATION_90 || rotation == Surface.ROTATION_270) {
160             RotationUtils.rotateBounds(
161                     rotatedBounds,
162                     mOverlayParams.getNaturalDisplayWidth(),
163                     mOverlayParams.getNaturalDisplayHeight(),
164                     rotation
165             );
166         }
167 
168         // Use parent view's and rotatedBound's absolute coordinates to decide the margins of
169         // UdfpsEnrollView, so that its center keeps consistent with sensor rect's.
170         ViewGroup parentView = (ViewGroup) getParent();
171         MarginLayoutParams marginLayoutParams = (MarginLayoutParams) getLayoutParams();
172         FrameLayout.LayoutParams params = (LayoutParams) getLayoutParams();
173         if (rotation == Surface.ROTATION_0 || rotation == Surface.ROTATION_180) {
174             final int[] coords = parentView.getLocationOnScreen();
175             final int parentLeft = coords[0];
176             final int parentTop = coords[1];
177             final int parentRight = parentLeft + parentView.getWidth();
178             params.gravity = Gravity.RIGHT | Gravity.TOP;
179             final int rightMargin = parentRight - rotatedBounds.right - getPaddingX();
180             final int topMargin = rotatedBounds.top - parentTop - getPaddingY();
181             if (marginLayoutParams.rightMargin == rightMargin
182                     && marginLayoutParams.topMargin == topMargin) {
183                 return;
184             }
185             marginLayoutParams.rightMargin = rightMargin;
186             marginLayoutParams.topMargin = topMargin;
187             setLayoutParams(params);
188         } else {
189             final int[] coords = parentView.getLocationOnScreen();
190             final int parentLeft = coords[0];
191             final int parentTop = coords[1];
192             final int parentRight = parentLeft + parentView.getWidth();
193             final int parentBottom = parentTop + parentView.getHeight();
194             if (rotation == Surface.ROTATION_90) {
195                 params.gravity = Gravity.RIGHT | Gravity.BOTTOM;
196                 marginLayoutParams.rightMargin = parentRight - rotatedBounds.right - getPaddingX();
197                 marginLayoutParams.bottomMargin =
198                         parentBottom - rotatedBounds.bottom - getPaddingY();
199             } else if (rotation == Surface.ROTATION_270) {
200                 params.gravity = Gravity.LEFT | Gravity.BOTTOM;
201                 marginLayoutParams.leftMargin = rotatedBounds.left - parentLeft - getPaddingX();
202                 marginLayoutParams.bottomMargin =
203                         parentBottom - rotatedBounds.bottom - getPaddingY();
204             }
205         }
206 
207         params.height = rotatedBounds.height() + 2 * getPaddingX();
208         params.width = rotatedBounds.width() + 2 * getPaddingY();
209         setLayoutParams(params);
210 
211 
212     }
213 
onFingerDown()214     private void onFingerDown() {
215         if (mOverlayParams.getSensorType() == FingerprintSensorProperties.TYPE_UDFPS_OPTICAL) {
216             mFingerprintDrawable.setShouldSkipDraw(true);
217         }
218         mFingerprintDrawable.invalidateSelf();
219     }
220 
onFingerUp()221     private void onFingerUp() {
222         mFingerprintDrawable.setShouldSkipDraw(false);
223         mFingerprintDrawable.invalidateSelf();
224     }
225 
getPaddingX()226     private int getPaddingX() {
227         return mProgressBarRadius;
228     }
229 
getPaddingY()230     private int getPaddingY() {
231         return mProgressBarRadius;
232     }
233 }
234