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 package com.android.systemui.biometrics 17 18 import android.content.Context 19 import android.graphics.ColorFilter 20 import android.graphics.Paint 21 import android.graphics.Rect 22 import android.graphics.RectF 23 import android.graphics.drawable.Drawable 24 import android.graphics.drawable.ShapeDrawable 25 import android.graphics.drawable.shapes.PathShape 26 import android.util.PathParser 27 import com.android.systemui.R 28 29 private const val DEFAULT_STROKE_WIDTH = 3f 30 31 /** 32 * Abstract base class for drawable displayed when the finger is not touching the 33 * sensor area. 34 */ 35 abstract class UdfpsDrawable( 36 protected val context: Context, 37 drawableFactory: (Context) -> ShapeDrawable 38 ) : Drawable() { 39 40 constructor(context: Context) : this(context, defaultFactory) 41 42 /** Fingerprint affordance. */ 43 val fingerprintDrawable: ShapeDrawable = drawableFactory(context) 44 45 private var _alpha: Int = 255 // 0 - 255 46 47 var strokeWidth: Float = fingerprintDrawable.paint.strokeWidth 48 set(value) { 49 field = value 50 fingerprintDrawable.paint.strokeWidth = value 51 invalidateSelf() 52 } 53 54 var isDisplayConfigured: Boolean = false 55 set(showing) { 56 if (field == showing) { 57 return 58 } 59 field = showing 60 invalidateSelf() 61 } 62 63 /** The [sensorRect] coordinates for the sensor area. */ 64 open fun onSensorRectUpdated(sensorRect: RectF) { 65 val margin = sensorRect.height().toInt() / 8 66 val bounds = Rect( 67 sensorRect.left.toInt() + margin, 68 sensorRect.top.toInt() + margin, 69 sensorRect.right.toInt() - margin, 70 sensorRect.bottom.toInt() - margin 71 ) 72 updateFingerprintIconBounds(bounds) 73 } 74 75 /** Bounds for the fingerprint icon. */ 76 protected open fun updateFingerprintIconBounds(bounds: Rect) { 77 fingerprintDrawable.bounds = bounds 78 invalidateSelf() 79 } 80 81 override fun getAlpha(): Int = _alpha 82 83 override fun setAlpha(alpha: Int) { 84 _alpha = alpha 85 fingerprintDrawable.alpha = alpha 86 invalidateSelf() 87 } 88 89 override fun setColorFilter(colorFilter: ColorFilter?) {} 90 91 override fun getOpacity(): Int = 0 92 } 93 94 private val defaultFactory = { context: Context -> 95 val fpPath = context.resources.getString(R.string.config_udfpsIcon) 96 val drawable = ShapeDrawable( 97 PathShape(PathParser.createPathFromPathData(fpPath), 72f, 72f) 98 ) 99 drawable.mutate() 100 drawable.paint.style = Paint.Style.STROKE 101 drawable.paint.strokeCap = Paint.Cap.ROUND 102 drawable.paint.strokeWidth = DEFAULT_STROKE_WIDTH 103 drawable 104 } 105