1 /*
2  * Copyright (C) 2020 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.biometrics.sensors.fingerprint;
18 
19 import android.hardware.fingerprint.IFingerprintClientActiveCallback;
20 import android.os.RemoteException;
21 import android.util.Slog;
22 
23 import java.util.HashMap;
24 import java.util.Map;
25 import java.util.concurrent.CopyOnWriteArrayList;
26 
27 /**
28  * Keeps track of sensor gesture availability (e.g. swipe), and notifies clients when its
29  * availability changes
30  */
31 public class GestureAvailabilityDispatcher {
32     private static final String TAG = "GestureAvailabilityTracker";
33 
34     private final CopyOnWriteArrayList<IFingerprintClientActiveCallback> mClientActiveCallbacks;
35     private final Map<Integer, Boolean> mActiveSensors;
36 
37     private boolean mIsActive;
38 
GestureAvailabilityDispatcher()39     GestureAvailabilityDispatcher() {
40         mClientActiveCallbacks = new CopyOnWriteArrayList<>();
41         mActiveSensors = new HashMap<>();
42     }
43 
44     /**
45      * @return true if any sensor is active.
46      */
isAnySensorActive()47     public boolean isAnySensorActive() {
48         return mIsActive;
49     }
50 
markSensorActive(int sensorId, boolean active)51     public void markSensorActive(int sensorId, boolean active) {
52         mActiveSensors.put(sensorId, active);
53 
54         final boolean wasActive = mIsActive;
55         boolean isActive = false;
56         for (Boolean b : mActiveSensors.values()) {
57             if (b) {
58                 isActive = true;
59                 break;
60             }
61         }
62 
63         if (wasActive != isActive) {
64             Slog.d(TAG, "Notifying gesture availability, active=" + mIsActive);
65             mIsActive = isActive;
66             notifyClientActiveCallbacks(mIsActive);
67         }
68     }
69 
registerCallback(IFingerprintClientActiveCallback callback)70     void registerCallback(IFingerprintClientActiveCallback callback) {
71         mClientActiveCallbacks.add(callback);
72     }
73 
removeCallback(IFingerprintClientActiveCallback callback)74     void removeCallback(IFingerprintClientActiveCallback callback) {
75         mClientActiveCallbacks.remove(callback);
76     }
77 
notifyClientActiveCallbacks(boolean isActive)78     private void notifyClientActiveCallbacks(boolean isActive) {
79         for (IFingerprintClientActiveCallback callback : mClientActiveCallbacks) {
80             try {
81                 callback.onClientActiveChanged(isActive);
82             } catch (RemoteException re) {
83                 // If the remote is dead, stop notifying it
84                 mClientActiveCallbacks.remove(callback);
85             }
86         }
87     }
88 }
89