1 /* 2 * Copyright (C) 2023 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 android.hardware.fingerprint; 18 19 import static android.hardware.biometrics.BiometricAuthenticator.TYPE_FINGERPRINT; 20 21 import android.annotation.NonNull; 22 import android.annotation.Nullable; 23 import android.content.Context; 24 import android.hardware.biometrics.fingerprint.IFingerprint; 25 import android.hardware.biometrics.fingerprint.SensorProps; 26 import android.os.Binder; 27 import android.os.Parcel; 28 import android.os.Parcelable; 29 import android.os.RemoteException; 30 import android.os.ServiceManager; 31 import android.util.Log; 32 33 import java.util.ArrayList; 34 import java.util.HashMap; 35 import java.util.List; 36 import java.util.Map; 37 import java.util.Optional; 38 39 /** 40 * Provides the sensor props for fingerprint sensor, if available. 41 * @hide 42 */ 43 44 public class FingerprintSensorConfigurations implements Parcelable { 45 private static final String TAG = "FingerprintSensorConfigurations"; 46 47 private final Map<String, SensorProps[]> mSensorPropsMap; 48 private final boolean mResetLockoutRequiresHardwareAuthToken; 49 50 public static final Creator<FingerprintSensorConfigurations> CREATOR = 51 new Creator<>() { 52 @Override 53 public FingerprintSensorConfigurations createFromParcel(Parcel in) { 54 return new FingerprintSensorConfigurations(in); 55 } 56 57 @Override 58 public FingerprintSensorConfigurations[] newArray(int size) { 59 return new FingerprintSensorConfigurations[size]; 60 } 61 }; 62 FingerprintSensorConfigurations(boolean resetLockoutRequiresHardwareAuthToken)63 public FingerprintSensorConfigurations(boolean resetLockoutRequiresHardwareAuthToken) { 64 mResetLockoutRequiresHardwareAuthToken = resetLockoutRequiresHardwareAuthToken; 65 mSensorPropsMap = new HashMap<>(); 66 } 67 68 /** 69 * Process AIDL instances to extract sensor props and add it to the sensor map. 70 * @param aidlInstances available face AIDL instances 71 */ addAidlSensors(@onNull String[] aidlInstances)72 public void addAidlSensors(@NonNull String[] aidlInstances) { 73 for (String aidlInstance : aidlInstances) { 74 mSensorPropsMap.put(aidlInstance, null); 75 } 76 } 77 78 /** 79 * Parse through HIDL configuration and add it to the sensor map. 80 */ addHidlSensors(@onNull String[] hidlConfigStrings, @NonNull Context context)81 public void addHidlSensors(@NonNull String[] hidlConfigStrings, 82 @NonNull Context context) { 83 final List<HidlFingerprintSensorConfig> hidlFingerprintSensorConfigs = new ArrayList<>(); 84 for (String hidlConfigString : hidlConfigStrings) { 85 final HidlFingerprintSensorConfig hidlFingerprintSensorConfig = 86 new HidlFingerprintSensorConfig(); 87 try { 88 hidlFingerprintSensorConfig.parse(hidlConfigString, context); 89 } catch (Exception e) { 90 Log.e(TAG, "HIDL sensor configuration format is incorrect."); 91 continue; 92 } 93 if (hidlFingerprintSensorConfig.getModality() == TYPE_FINGERPRINT) { 94 hidlFingerprintSensorConfigs.add(hidlFingerprintSensorConfig); 95 } 96 } 97 final String hidlHalInstanceName = "defaultHIDL"; 98 mSensorPropsMap.put(hidlHalInstanceName, 99 hidlFingerprintSensorConfigs.toArray( 100 new HidlFingerprintSensorConfig[hidlFingerprintSensorConfigs.size()])); 101 } 102 FingerprintSensorConfigurations(Parcel in)103 protected FingerprintSensorConfigurations(Parcel in) { 104 mResetLockoutRequiresHardwareAuthToken = in.readByte() != 0; 105 mSensorPropsMap = in.readHashMap(null /* loader */, String.class, SensorProps[].class); 106 } 107 108 /** 109 * Returns true if any fingerprint sensors have been added. 110 */ hasSensorConfigurations()111 public boolean hasSensorConfigurations() { 112 return mSensorPropsMap.size() > 0; 113 } 114 115 /** 116 * Returns true if there is only a single fingerprint sensor configuration available. 117 */ isSingleSensorConfigurationPresent()118 public boolean isSingleSensorConfigurationPresent() { 119 return mSensorPropsMap.size() == 1; 120 } 121 122 /** 123 * Checks if {@param instance} exists. 124 */ 125 @Nullable doesInstanceExist(String instance)126 public boolean doesInstanceExist(String instance) { 127 return mSensorPropsMap.containsKey(instance); 128 } 129 130 /** 131 * Return the first HAL instance, which does not correspond to the given {@param instance}. 132 * If another instance is not available, then null is returned. 133 */ 134 @Nullable getSensorNameNotForInstance(String instance)135 public String getSensorNameNotForInstance(String instance) { 136 Optional<String> notAVirtualInstance = mSensorPropsMap.keySet().stream().filter( 137 (instanceName) -> !instanceName.equals(instance)).findFirst(); 138 return notAVirtualInstance.orElse(null); 139 } 140 141 /** 142 * Returns the first instance that has been added to the map. 143 */ 144 @Nullable getSensorInstance()145 public String getSensorInstance() { 146 Optional<String> optionalInstance = mSensorPropsMap.keySet().stream().findFirst(); 147 return optionalInstance.orElse(null); 148 } 149 getResetLockoutRequiresHardwareAuthToken()150 public boolean getResetLockoutRequiresHardwareAuthToken() { 151 return mResetLockoutRequiresHardwareAuthToken; 152 } 153 154 @Override describeContents()155 public int describeContents() { 156 return 0; 157 } 158 159 @Override writeToParcel(@onNull Parcel dest, int flags)160 public void writeToParcel(@NonNull Parcel dest, int flags) { 161 dest.writeByte((byte) (mResetLockoutRequiresHardwareAuthToken ? 1 : 0)); 162 dest.writeMap(mSensorPropsMap); 163 } 164 165 /** 166 * Returns fingerprint sensor props for the HAL {@param instance}. 167 */ 168 @Nullable getSensorPropForInstance(String instance)169 public SensorProps[] getSensorPropForInstance(String instance) { 170 SensorProps[] props = mSensorPropsMap.get(instance); 171 172 //Props should not be null for HIDL configs 173 if (props != null) { 174 return props; 175 } 176 177 try { 178 final String fqName = IFingerprint.DESCRIPTOR + "/" + instance; 179 final IFingerprint fp = IFingerprint.Stub.asInterface(Binder.allowBlocking( 180 ServiceManager.waitForDeclaredService(fqName))); 181 if (fp != null) { 182 props = fp.getSensorProps(); 183 } else { 184 Log.d(TAG, "IFingerprint null for instance " + instance); 185 } 186 } catch (RemoteException e) { 187 Log.d(TAG, "Unable to get sensor properties!"); 188 } 189 return props; 190 } 191 } 192