1 /* 2 * Copyright (C) 2022 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.graphics.Rect 21 import android.hardware.biometrics.BiometricOverlayConstants.REASON_AUTH_BP 22 import android.hardware.biometrics.BiometricOverlayConstants.REASON_AUTH_KEYGUARD 23 import android.hardware.biometrics.BiometricOverlayConstants.REASON_AUTH_OTHER 24 import android.hardware.biometrics.BiometricOverlayConstants.REASON_AUTH_SETTINGS 25 import android.hardware.biometrics.BiometricOverlayConstants.REASON_ENROLL_ENROLLING 26 import android.hardware.biometrics.BiometricOverlayConstants.REASON_ENROLL_FIND_SENSOR 27 import android.hardware.biometrics.BiometricOverlayConstants.REASON_UNKNOWN 28 import android.hardware.fingerprint.IUdfpsOverlayControllerCallback 29 import android.util.Log 30 import android.view.LayoutInflater 31 import android.view.MotionEvent 32 import android.view.MotionEvent.ACTION_DOWN 33 import android.view.MotionEvent.ACTION_MOVE 34 import android.view.MotionEvent.ACTION_UP 35 import com.android.internal.annotations.VisibleForTesting 36 import com.android.systemui.dagger.SysUISingleton 37 import com.android.systemui.statusbar.commandline.Command 38 import com.android.systemui.statusbar.commandline.CommandRegistry 39 import java.io.PrintWriter 40 import javax.inject.Inject 41 42 private const val TAG = "UdfpsShell" 43 private const val REQUEST_ID = 2L 44 private const val SENSOR_ID = 0 45 private const val MINOR = 10F 46 private const val MAJOR = 10F 47 48 /** 49 * Used to show and hide the UDFPS overlay with statusbar commands. 50 */ 51 @SysUISingleton 52 class UdfpsShell @Inject constructor( 53 commandRegistry: CommandRegistry 54 ) : Command { 55 56 /** 57 * Set in [UdfpsController.java] constructor, used to show and hide the UDFPS overlay. 58 * TODO: inject after b/229290039 is resolved 59 */ 60 var udfpsOverlayController: UdfpsController.UdfpsOverlayController? = null 61 var context: Context? = null 62 var inflater: LayoutInflater? = null 63 64 init { 65 commandRegistry.registerCommand("udfps") { this } 66 } 67 68 override fun execute(pw: PrintWriter, args: List<String>) { 69 if (args.size == 1 && args[0] == "hide") { 70 hideOverlay() 71 } else if (args.size == 2 && args[0] == "show") { 72 showOverlay(getEnrollmentReason(args[1])) 73 } else if (args.size == 1 && args[0] == "onUiReady") { 74 onUiReady() 75 } else if (args.size == 1 && args[0] == "simFingerDown") { 76 simFingerDown() 77 } else if (args.size == 1 && args[0] == "simFingerUp") { 78 simFingerUp() 79 } else { 80 invalidCommand(pw) 81 } 82 } 83 84 override fun help(pw: PrintWriter) { 85 pw.println("Usage: adb shell cmd statusbar udfps <cmd>") 86 pw.println("Supported commands:") 87 pw.println(" - show <reason>") 88 pw.println(" -> supported reasons: [enroll-find-sensor, enroll-enrolling, auth-bp, " + 89 "auth-keyguard, auth-other, auth-settings]") 90 pw.println(" -> reason otherwise defaults to unknown") 91 pw.println(" - hide") 92 pw.println(" - onUiReady") 93 pw.println(" - simFingerDown") 94 pw.println(" -> Simulates onFingerDown on sensor") 95 pw.println(" - simFingerUp") 96 pw.println(" -> Simulates onFingerUp on sensor") 97 } 98 99 private fun invalidCommand(pw: PrintWriter) { 100 pw.println("invalid command") 101 help(pw) 102 } 103 104 private fun getEnrollmentReason(reason: String): Int { 105 return when (reason) { 106 "enroll-find-sensor" -> REASON_ENROLL_FIND_SENSOR 107 "enroll-enrolling" -> REASON_ENROLL_ENROLLING 108 "auth-bp" -> REASON_AUTH_BP 109 "auth-keyguard" -> REASON_AUTH_KEYGUARD 110 "auth-other" -> REASON_AUTH_OTHER 111 "auth-settings" -> REASON_AUTH_SETTINGS 112 else -> REASON_UNKNOWN 113 } 114 } 115 116 private fun showOverlay(reason: Int) { 117 udfpsOverlayController?.showUdfpsOverlay( 118 REQUEST_ID, 119 SENSOR_ID, 120 reason, 121 object : IUdfpsOverlayControllerCallback.Stub() { 122 override fun onUserCanceled() { 123 Log.e(TAG, "User cancelled") 124 } 125 } 126 ) 127 } 128 129 private fun hideOverlay() { 130 udfpsOverlayController?.hideUdfpsOverlay(SENSOR_ID) 131 } 132 133 134 @VisibleForTesting 135 fun onUiReady() { 136 udfpsOverlayController?.debugOnUiReady(SENSOR_ID) 137 } 138 139 @VisibleForTesting 140 fun simFingerDown() { 141 val sensorBounds: Rect = udfpsOverlayController!!.sensorBounds 142 143 val downEvent: MotionEvent? = obtainMotionEvent(ACTION_DOWN, sensorBounds.exactCenterX(), 144 sensorBounds.exactCenterY(), MINOR, MAJOR) 145 udfpsOverlayController?.debugOnTouch(downEvent) 146 147 val moveEvent: MotionEvent? = obtainMotionEvent(ACTION_MOVE, sensorBounds.exactCenterX(), 148 sensorBounds.exactCenterY(), MINOR, MAJOR) 149 udfpsOverlayController?.debugOnTouch(moveEvent) 150 151 downEvent?.recycle() 152 moveEvent?.recycle() 153 } 154 155 @VisibleForTesting 156 fun simFingerUp() { 157 val sensorBounds: Rect = udfpsOverlayController!!.sensorBounds 158 159 val upEvent: MotionEvent? = obtainMotionEvent(ACTION_UP, sensorBounds.exactCenterX(), 160 sensorBounds.exactCenterY(), MINOR, MAJOR) 161 udfpsOverlayController?.debugOnTouch(upEvent) 162 upEvent?.recycle() 163 } 164 165 private fun obtainMotionEvent( 166 action: Int, 167 x: Float, 168 y: Float, 169 minor: Float, 170 major: Float 171 ): MotionEvent? { 172 val pp = MotionEvent.PointerProperties() 173 pp.id = 1 174 val pc = MotionEvent.PointerCoords() 175 pc.x = x 176 pc.y = y 177 pc.touchMinor = minor 178 pc.touchMajor = major 179 return MotionEvent.obtain(0, 0, action, 1, arrayOf(pp), arrayOf(pc), 180 0, 0, 1f, 1f, 0, 0, 0, 0) 181 } 182 } 183