• 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.content.Context
20 import android.hardware.display.DisplayManager
21 import android.hardware.fingerprint.FingerprintSensorPropertiesInternal
22 import android.os.Handler
23 import android.view.DisplayInfo
24 import com.android.app.tracing.traceSection
25 import com.android.systemui.biometrics.BiometricDisplayListener.SensorType.Generic
26 
27 /**
28  * A listener for keeping overlays for biometric sensors aligned with the physical device device's
29  * screen. The [onChanged] will be dispatched on the [handler] whenever a relevant change to the
30  * device's configuration (orientation, fold, display change, etc.) may require the UI to change for
31  * the given [sensorType].
32  */
33 class BiometricDisplayListener(
34     private val context: Context,
35     private val displayManager: DisplayManager,
36     private val handler: Handler,
37     private val sensorType: SensorType = SensorType.Generic,
38     private val onChanged: () -> Unit,
39 ) : DisplayManager.DisplayListener {
40 
41     private var cachedDisplayInfo = DisplayInfo()
42 
onDisplayAddednull43     override fun onDisplayAdded(displayId: Int) {}
44 
onDisplayRemovednull45     override fun onDisplayRemoved(displayId: Int) {}
46 
onDisplayChangednull47     override fun onDisplayChanged(displayId: Int) {
48         traceSection({ "BiometricDisplayListener($sensorType)#onDisplayChanged" }) {
49             val rotationChanged = didRotationChange()
50 
51             when (sensorType) {
52                 is SensorType.SideFingerprint -> onChanged()
53                 else -> {
54                     if (rotationChanged) {
55                         onChanged()
56                     }
57                 }
58             }
59         }
60     }
61 
didRotationChangenull62     private fun didRotationChange(): Boolean {
63         val last = cachedDisplayInfo.rotation
64         context.display?.getDisplayInfo(cachedDisplayInfo)
65         return last != cachedDisplayInfo.rotation
66     }
67 
68     /** Listen for changes. */
enablenull69     fun enable() {
70         context.display?.getDisplayInfo(cachedDisplayInfo)
71         displayManager.registerDisplayListener(
72             this,
73             handler,
74             DisplayManager.EVENT_TYPE_DISPLAY_CHANGED,
75         )
76     }
77 
78     /** Stop listening for changes. */
disablenull79     fun disable() {
80         displayManager.unregisterDisplayListener(this)
81     }
82 
83     /**
84      * Type of sensor to determine what kind of display changes require layouts.
85      *
86      * The [Generic] type should be used in cases where the modality can vary, such as biometric
87      * prompt (and this object will likely change as multi-mode auth is added).
88      */
89     sealed class SensorType {
90         data object Generic : SensorType()
91 
92         data object UnderDisplayFingerprint : SensorType()
93 
94         data class SideFingerprint(val properties: FingerprintSensorPropertiesInternal) :
95             SensorType()
96     }
97 }
98