• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
<lambda>null2  * Copyright (C) 2024 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.deviceentry.ui.binder
18 
19 import android.content.pm.PackageManager
20 import android.hardware.Sensor
21 import android.hardware.TriggerEvent
22 import android.hardware.TriggerEventListener
23 import com.android.keyguard.ActiveUnlockConfig
24 import com.android.keyguard.KeyguardUpdateMonitor
25 import com.android.systemui.CoreStartable
26 import com.android.systemui.bouncer.domain.interactor.AlternateBouncerInteractor
27 import com.android.systemui.bouncer.domain.interactor.PrimaryBouncerInteractor
28 import com.android.systemui.dagger.SysUISingleton
29 import com.android.systemui.dagger.qualifiers.Application
30 import com.android.systemui.deviceentry.domain.interactor.DeviceEntryFaceAuthInteractor
31 import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor
32 import com.android.systemui.power.domain.interactor.PowerInteractor
33 import com.android.systemui.util.Assert
34 import com.android.systemui.util.sensors.AsyncSensorManager
35 import java.io.PrintWriter
36 import javax.inject.Inject
37 import kotlinx.coroutines.CoroutineScope
38 import kotlinx.coroutines.flow.Flow
39 import kotlinx.coroutines.flow.MutableStateFlow
40 import kotlinx.coroutines.flow.combine
41 import kotlinx.coroutines.flow.filterNot
42 import kotlinx.coroutines.flow.map
43 import kotlinx.coroutines.launch
44 
45 /**
46  * Triggers face auth and active unlock on lift when the device is showing the lock screen or
47  * bouncer. Only initialized if face auth is supported on the device. Not to be confused with the
48  * lift to wake gesture which is handled by {@link com.android.server.policy.PhoneWindowManager}.
49  */
50 @SysUISingleton
51 class LiftToRunFaceAuthBinder
52 @Inject
53 constructor(
54     @Application private val scope: CoroutineScope,
55     private val packageManager: PackageManager,
56     private val asyncSensorManager: AsyncSensorManager,
57     private val keyguardUpdateMonitor: KeyguardUpdateMonitor,
58     keyguardInteractor: KeyguardInteractor,
59     primaryBouncerInteractor: PrimaryBouncerInteractor,
60     alternateBouncerInteractor: AlternateBouncerInteractor,
61     private val deviceEntryFaceAuthInteractor: DeviceEntryFaceAuthInteractor,
62     powerInteractor: PowerInteractor,
63 ) : CoreStartable {
64 
65     private var pickupSensor: Sensor? = null
66     private val isListening: MutableStateFlow<Boolean> = MutableStateFlow(false)
67     private val stoppedListening: Flow<Unit> = isListening.filterNot { it }.map {} // map to Unit
68 
69     private val onAwakeKeyguard: Flow<Boolean> =
70         combine(
71             powerInteractor.isInteractive,
72             keyguardInteractor.isKeyguardVisible,
73         ) { isInteractive, isKeyguardVisible ->
74             isInteractive && isKeyguardVisible
75         }
76     private val bouncerShowing: Flow<Boolean> =
77         combine(
78             primaryBouncerInteractor.isShowing,
79             alternateBouncerInteractor.isVisible,
80         ) { primaryBouncerShowing, alternateBouncerShowing ->
81             primaryBouncerShowing || alternateBouncerShowing
82         }
83     private val listenForPickupSensor: Flow<Boolean> =
84         combine(
85             stoppedListening,
86             bouncerShowing,
87             onAwakeKeyguard,
88         ) { _, bouncerShowing, onAwakeKeyguard ->
89             (onAwakeKeyguard || bouncerShowing) &&
90                 deviceEntryFaceAuthInteractor.isFaceAuthEnabledAndEnrolled()
91         }
92 
93     override fun start() {
94         if (packageManager.hasSystemFeature(PackageManager.FEATURE_FACE)) {
95             init()
96         }
97     }
98 
99     private fun init() {
100         pickupSensor = asyncSensorManager.getDefaultSensor(Sensor.TYPE_PICK_UP_GESTURE)
101         scope.launch {
102             listenForPickupSensor.collect { listenForPickupSensor ->
103                 updateListeningState(listenForPickupSensor)
104             }
105         }
106     }
107 
108     private val listener: TriggerEventListener =
109         object : TriggerEventListener() {
110             override fun onTrigger(event: TriggerEvent?) {
111                 Assert.isMainThread()
112                 deviceEntryFaceAuthInteractor.onDeviceLifted()
113                 keyguardUpdateMonitor.requestActiveUnlock(
114                     ActiveUnlockConfig.ActiveUnlockRequestOrigin.WAKE,
115                     "KeyguardLiftController"
116                 )
117 
118                 // Not listening anymore since trigger events unregister themselves
119                 isListening.value = false
120             }
121         }
122 
123     override fun dump(pw: PrintWriter, args: Array<out String>) {
124         pw.println("LiftToRunFaceAuthBinder:")
125         pw.println("  pickupSensor: $pickupSensor")
126         pw.println("  isListening: ${isListening.value}")
127     }
128 
129     private fun updateListeningState(shouldListen: Boolean) {
130         if (pickupSensor == null) {
131             return
132         }
133         if (shouldListen != isListening.value) {
134             isListening.value = shouldListen
135 
136             if (shouldListen) {
137                 asyncSensorManager.requestTriggerSensor(listener, pickupSensor)
138             } else {
139                 asyncSensorManager.cancelTriggerSensor(listener, pickupSensor)
140             }
141         }
142     }
143 }
144