• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2021 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.systemui.biometrics;
18 
19 import android.annotation.Nullable;
20 import android.content.Context;
21 import android.graphics.RectF;
22 import android.util.AttributeSet;
23 import android.view.View;
24 import android.view.ViewGroup;
25 import android.widget.FrameLayout;
26 
27 /**
28  * Base class for views containing UDFPS animations. Note that this is a FrameLayout so that we
29  * can support multiple child views drawing in the same region around the sensor location.
30  *
31  * - hides animation view when pausing auth
32  * - sends illumination events to fingerprint drawable
33  * - sends sensor rect updates to fingerprint drawable
34  * - optionally can override dozeTimeTick to adjust views for burn-in mitigation
35  */
36 public abstract class UdfpsAnimationView extends FrameLayout {
37     private float mDialogSuggestedAlpha = 1f;
38     private float mNotificationShadeExpansion = 0f;
39 
40     // mAlpha takes into consideration the status bar expansion amount and dialog suggested alpha
41     private int mAlpha;
42     boolean mPauseAuth;
43 
UdfpsAnimationView(Context context, @Nullable AttributeSet attrs)44     public UdfpsAnimationView(Context context, @Nullable AttributeSet attrs) {
45         super(context, attrs);
46     }
47 
48     /**
49      * Fingerprint drawable
50      */
getDrawable()51     abstract UdfpsDrawable getDrawable();
52 
onSensorRectUpdated(RectF bounds)53     void onSensorRectUpdated(RectF bounds) {
54         getDrawable().onSensorRectUpdated(bounds);
55     }
56 
onDisplayConfiguring()57     void onDisplayConfiguring() {
58         getDrawable().setDisplayConfigured(true);
59         getDrawable().invalidateSelf();
60     }
61 
onDisplayUnconfigured()62     void onDisplayUnconfigured() {
63         getDrawable().setDisplayConfigured(false);
64         getDrawable().invalidateSelf();
65     }
66 
67     /**
68      * @return true if changed
69      */
setPauseAuth(boolean pauseAuth)70     boolean setPauseAuth(boolean pauseAuth) {
71         if (pauseAuth != mPauseAuth) {
72             mPauseAuth = pauseAuth;
73             updateAlpha();
74             return true;
75         }
76         return false;
77     }
78 
79     /**
80      * @return current alpha
81      */
updateAlpha()82     protected int updateAlpha() {
83         int alpha = calculateAlpha();
84         getDrawable().setAlpha(alpha);
85 
86         // this is necessary so that touches won't be intercepted if udfps is paused:
87         if (mPauseAuth && alpha == 0 && getParent() != null) {
88             ((ViewGroup) getParent()).setVisibility(View.INVISIBLE);
89         } else {
90             ((ViewGroup) getParent()).setVisibility(View.VISIBLE);
91         }
92 
93         return alpha;
94     }
95 
calculateAlpha()96     int calculateAlpha() {
97         int alpha = expansionToAlpha(mNotificationShadeExpansion);
98         alpha *= mDialogSuggestedAlpha;
99         mAlpha = alpha;
100 
101         return mPauseAuth ? mAlpha : 255;
102     }
103 
isPauseAuth()104     boolean isPauseAuth() {
105         return mPauseAuth;
106     }
107 
expansionToAlpha(float expansion)108     private int expansionToAlpha(float expansion) {
109         // Fade to 0 opacity when reaching this expansion amount
110         final float maxExpansion = 0.4f;
111 
112         if (expansion >= maxExpansion) {
113             return 0; // transparent
114         }
115 
116         final float percent = expansion / maxExpansion;
117         return (int) ((1 - percent) * 255);
118     }
119 
120     /**
121      * Converts coordinates of RectF relative to the screen to coordinates relative to this view.
122      *
123      * @param bounds RectF based off screen coordinates in current orientation
124      */
getBoundsRelativeToView(RectF bounds)125     RectF getBoundsRelativeToView(RectF bounds) {
126         int[] pos = getLocationOnScreen();
127 
128         RectF output = new RectF(
129                 bounds.left - pos[0],
130                 bounds.top - pos[1],
131                 bounds.right - pos[0],
132                 bounds.bottom - pos[1]
133         );
134 
135         return output;
136     }
137 
138     /**
139      * Set the suggested alpha based on whether a dialog was recently shown or hidden.
140      * @param dialogSuggestedAlpha value from 0f to 1f.
141      */
setDialogSuggestedAlpha(float dialogSuggestedAlpha)142     public void setDialogSuggestedAlpha(float dialogSuggestedAlpha) {
143         mDialogSuggestedAlpha = dialogSuggestedAlpha;
144         updateAlpha();
145     }
146 
getDialogSuggestedAlpha()147     public float getDialogSuggestedAlpha() {
148         return mDialogSuggestedAlpha;
149     }
150 
151     /**
152      * Sets the amount the notification shade is expanded. This will influence the opacity of the
153      * this visual affordance.
154      * @param expansion amount the shade has expanded from 0f to 1f.
155      */
onExpansionChanged(float expansion)156     public void onExpansionChanged(float expansion) {
157         mNotificationShadeExpansion = expansion;
158         updateAlpha();
159     }
160 
161     /**
162      * @return true if handled
163      */
dozeTimeTick()164     boolean dozeTimeTick() {
165         return false;
166     }
167 }
168