1 /* 2 * Copyright (C) 2019 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.statusbar.phone 18 19 import android.content.Context 20 import android.content.pm.PackageManager 21 import android.hardware.Sensor 22 import android.hardware.TriggerEvent 23 import android.hardware.TriggerEventListener 24 import com.android.keyguard.ActiveUnlockConfig 25 import com.android.keyguard.FaceAuthApiRequestReason 26 import com.android.keyguard.KeyguardUpdateMonitor 27 import com.android.keyguard.KeyguardUpdateMonitorCallback 28 import com.android.systemui.CoreStartable 29 import com.android.systemui.Dumpable 30 import com.android.systemui.dagger.SysUISingleton 31 import com.android.systemui.dump.DumpManager 32 import com.android.systemui.plugins.statusbar.StatusBarStateController 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 38 /** 39 * Triggers face auth on lift when the device is showing the lock screen. Only initialized 40 * if face auth is supported on the device. Not to be confused with the lift to wake gesture 41 * which is handled by {@link com.android.server.policy.PhoneWindowManager}. 42 */ 43 @SysUISingleton 44 class KeyguardLiftController @Inject constructor( 45 private val context: Context, 46 private val statusBarStateController: StatusBarStateController, 47 private val asyncSensorManager: AsyncSensorManager, 48 private val keyguardUpdateMonitor: KeyguardUpdateMonitor, 49 private val dumpManager: DumpManager 50 ) : Dumpable, CoreStartable { 51 52 private val pickupSensor = asyncSensorManager.getDefaultSensor(Sensor.TYPE_PICK_UP_GESTURE) 53 private var isListening = false 54 private var bouncerVisible = false 55 startnull56 override fun start() { 57 if (context.packageManager.hasSystemFeature(PackageManager.FEATURE_FACE)) { 58 init() 59 } 60 } 61 initnull62 private fun init() { 63 dumpManager.registerDumpable(javaClass.name, this) 64 statusBarStateController.addCallback(statusBarStateListener) 65 keyguardUpdateMonitor.registerCallback(keyguardUpdateMonitorCallback) 66 updateListeningState() 67 } 68 69 private val listener: TriggerEventListener = object : TriggerEventListener() { onTriggernull70 override fun onTrigger(event: TriggerEvent?) { 71 Assert.isMainThread() 72 // Not listening anymore since trigger events unregister themselves 73 isListening = false 74 updateListeningState() 75 keyguardUpdateMonitor.requestFaceAuth( 76 FaceAuthApiRequestReason.PICK_UP_GESTURE_TRIGGERED 77 ) 78 keyguardUpdateMonitor.requestActiveUnlock( 79 ActiveUnlockConfig.ActiveUnlockRequestOrigin.WAKE, 80 "KeyguardLiftController") 81 } 82 } 83 84 private val keyguardUpdateMonitorCallback = object : KeyguardUpdateMonitorCallback() { onKeyguardBouncerFullyShowingChangednull85 override fun onKeyguardBouncerFullyShowingChanged(bouncer: Boolean) { 86 bouncerVisible = bouncer 87 updateListeningState() 88 } 89 onKeyguardVisibilityChangednull90 override fun onKeyguardVisibilityChanged(visible: Boolean) { 91 updateListeningState() 92 } 93 } 94 95 private val statusBarStateListener = object : StatusBarStateController.StateListener { onDozingChangednull96 override fun onDozingChanged(isDozing: Boolean) { 97 updateListeningState() 98 } 99 } 100 dumpnull101 override fun dump(pw: PrintWriter, args: Array<out String>) { 102 pw.println("KeyguardLiftController:") 103 pw.println(" pickupSensor: $pickupSensor") 104 pw.println(" isListening: $isListening") 105 pw.println(" bouncerVisible: $bouncerVisible") 106 } 107 updateListeningStatenull108 private fun updateListeningState() { 109 if (pickupSensor == null) { 110 return 111 } 112 val onKeyguard = keyguardUpdateMonitor.isKeyguardVisible && 113 !statusBarStateController.isDozing 114 115 val userId = KeyguardUpdateMonitor.getCurrentUser() 116 val isFaceEnabled = keyguardUpdateMonitor.isFaceAuthEnabledForUser(userId) 117 val shouldListen = (onKeyguard || bouncerVisible) && isFaceEnabled 118 if (shouldListen != isListening) { 119 isListening = shouldListen 120 121 if (shouldListen) { 122 asyncSensorManager.requestTriggerSensor(listener, pickupSensor) 123 } else { 124 asyncSensorManager.cancelTriggerSensor(listener, pickupSensor) 125 } 126 } 127 } 128 } 129