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.server.policy; 18 19 import static android.hardware.fingerprint.FingerprintStateListener.STATE_ENROLLING; 20 import static android.hardware.fingerprint.FingerprintStateListener.STATE_IDLE; 21 22 import android.annotation.NonNull; 23 import android.app.AlertDialog; 24 import android.app.Dialog; 25 import android.content.Context; 26 import android.content.DialogInterface; 27 import android.content.pm.PackageManager; 28 import android.hardware.fingerprint.FingerprintManager; 29 import android.hardware.fingerprint.FingerprintSensorPropertiesInternal; 30 import android.hardware.fingerprint.FingerprintStateListener; 31 import android.hardware.fingerprint.IFingerprintAuthenticatorsRegisteredCallback; 32 import android.os.Handler; 33 import android.os.PowerManager; 34 import android.view.WindowManager; 35 36 import com.android.internal.R; 37 38 import java.util.List; 39 import java.util.concurrent.atomic.AtomicBoolean; 40 41 /** 42 * Defines behavior for handling interactions between power button events and 43 * fingerprint-related operations, for devices where the fingerprint sensor (side fps) 44 * lives on the power button. 45 */ 46 public class SideFpsEventHandler { 47 @NonNull private final Context mContext; 48 @NonNull private final Handler mHandler; 49 @NonNull private final PowerManager mPowerManager; 50 @NonNull private final AtomicBoolean mIsSideFps; 51 @NonNull private final AtomicBoolean mSideFpsEventHandlerReady; 52 53 private @FingerprintStateListener.State int mFingerprintState; 54 SideFpsEventHandler(Context context, Handler handler, PowerManager powerManager)55 SideFpsEventHandler(Context context, Handler handler, PowerManager powerManager) { 56 mContext = context; 57 mHandler = handler; 58 mPowerManager = powerManager; 59 mFingerprintState = STATE_IDLE; 60 mIsSideFps = new AtomicBoolean(false); 61 mSideFpsEventHandlerReady = new AtomicBoolean(false); 62 } 63 64 /** 65 * Called from {@link PhoneWindowManager} after power button is pressed. Checks fingerprint 66 * sensor state and if mFingerprintState = STATE_ENROLLING, displays a dialog confirming intent 67 * to turn screen off. If confirmed, the device goes to sleep, and if canceled, the dialog is 68 * dismissed. 69 * @param eventTime powerPress event time 70 * @return true if powerPress was consumed, false otherwise 71 */ onSinglePressDetected(long eventTime)72 public boolean onSinglePressDetected(long eventTime) { 73 if (!mSideFpsEventHandlerReady.get() || !mIsSideFps.get() 74 || mFingerprintState != STATE_ENROLLING) { 75 return false; 76 } 77 mHandler.post(() -> { 78 Dialog confirmScreenOffDialog = new AlertDialog.Builder(mContext) 79 .setTitle(R.string.fp_enrollment_powerbutton_intent_title) 80 .setMessage(R.string.fp_enrollment_powerbutton_intent_message) 81 .setPositiveButton( 82 R.string.fp_enrollment_powerbutton_intent_positive_button, 83 new DialogInterface.OnClickListener() { 84 @Override 85 public void onClick(DialogInterface dialog, int which) { 86 dialog.dismiss(); 87 mPowerManager.goToSleep( 88 eventTime, 89 PowerManager.GO_TO_SLEEP_REASON_POWER_BUTTON, 90 0 /* flags */ 91 ); 92 } 93 }) 94 .setNegativeButton( 95 R.string.fp_enrollment_powerbutton_intent_negative_button, 96 new DialogInterface.OnClickListener() { 97 @Override 98 public void onClick(DialogInterface dialog, int which) { 99 dialog.dismiss(); 100 } 101 }) 102 .setCancelable(false) 103 .create(); 104 confirmScreenOffDialog.getWindow().setType( 105 WindowManager.LayoutParams.TYPE_STATUS_BAR_SUB_PANEL); 106 confirmScreenOffDialog.show(); 107 }); 108 return true; 109 } 110 111 /** 112 * Awaits notification from PhoneWindowManager that fingerprint service is ready 113 * to send updates about power button fps sensor state. Then configures a 114 * FingerprintStateListener to receive and record updates to fps state, and 115 * registers the FingerprintStateListener in FingerprintManager. 116 */ onFingerprintSensorReady()117 public void onFingerprintSensorReady() { 118 final PackageManager pm = mContext.getPackageManager(); 119 if (!pm.hasSystemFeature(PackageManager.FEATURE_FINGERPRINT)) return; 120 FingerprintManager fingerprintManager = 121 mContext.getSystemService(FingerprintManager.class); 122 fingerprintManager.addAuthenticatorsRegisteredCallback( 123 new IFingerprintAuthenticatorsRegisteredCallback.Stub() { 124 @Override 125 public void onAllAuthenticatorsRegistered( 126 List<FingerprintSensorPropertiesInternal> sensors) { 127 mIsSideFps.set(fingerprintManager.isPowerbuttonFps()); 128 FingerprintStateListener fingerprintStateListener = 129 new FingerprintStateListener() { 130 @Override 131 public void onStateChanged( 132 @FingerprintStateListener.State int newState) { 133 mFingerprintState = newState; 134 } 135 }; 136 fingerprintManager.registerFingerprintStateListener( 137 fingerprintStateListener); 138 mSideFpsEventHandlerReady.set(true); 139 } 140 }); 141 } 142 } 143