| /* |
| * Copyright (C) 2023 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| package android.hardware.fingerprint; |
| |
| import static android.hardware.biometrics.BiometricAuthenticator.TYPE_FINGERPRINT; |
| |
| import android.annotation.NonNull; |
| import android.annotation.Nullable; |
| import android.content.Context; |
| import android.hardware.biometrics.fingerprint.IFingerprint; |
| import android.hardware.biometrics.fingerprint.SensorProps; |
| import android.os.Binder; |
| import android.os.Parcel; |
| import android.os.Parcelable; |
| import android.os.RemoteException; |
| import android.os.ServiceManager; |
| import android.util.Log; |
| |
| import java.util.ArrayList; |
| import java.util.HashMap; |
| import java.util.List; |
| import java.util.Map; |
| import java.util.Optional; |
| |
| /** |
| * Provides the sensor props for fingerprint sensor, if available. |
| * @hide |
| */ |
| |
| public class FingerprintSensorConfigurations implements Parcelable { |
| private static final String TAG = "FingerprintSensorConfigurations"; |
| |
| private final Map<String, SensorProps[]> mSensorPropsMap; |
| private final boolean mResetLockoutRequiresHardwareAuthToken; |
| |
| public static final Creator<FingerprintSensorConfigurations> CREATOR = |
| new Creator<>() { |
| @Override |
| public FingerprintSensorConfigurations createFromParcel(Parcel in) { |
| return new FingerprintSensorConfigurations(in); |
| } |
| |
| @Override |
| public FingerprintSensorConfigurations[] newArray(int size) { |
| return new FingerprintSensorConfigurations[size]; |
| } |
| }; |
| |
| public FingerprintSensorConfigurations(boolean resetLockoutRequiresHardwareAuthToken) { |
| mResetLockoutRequiresHardwareAuthToken = resetLockoutRequiresHardwareAuthToken; |
| mSensorPropsMap = new HashMap<>(); |
| } |
| |
| /** |
| * Process AIDL instances to extract sensor props and add it to the sensor map. |
| * @param aidlInstances available face AIDL instances |
| */ |
| public void addAidlSensors(@NonNull String[] aidlInstances) { |
| for (String aidlInstance : aidlInstances) { |
| mSensorPropsMap.put(aidlInstance, null); |
| } |
| } |
| |
| /** |
| * Parse through HIDL configuration and add it to the sensor map. |
| */ |
| public void addHidlSensors(@NonNull String[] hidlConfigStrings, |
| @NonNull Context context) { |
| final List<HidlFingerprintSensorConfig> hidlFingerprintSensorConfigs = new ArrayList<>(); |
| for (String hidlConfigString : hidlConfigStrings) { |
| final HidlFingerprintSensorConfig hidlFingerprintSensorConfig = |
| new HidlFingerprintSensorConfig(); |
| try { |
| hidlFingerprintSensorConfig.parse(hidlConfigString, context); |
| } catch (Exception e) { |
| Log.e(TAG, "HIDL sensor configuration format is incorrect."); |
| continue; |
| } |
| if (hidlFingerprintSensorConfig.getModality() == TYPE_FINGERPRINT) { |
| hidlFingerprintSensorConfigs.add(hidlFingerprintSensorConfig); |
| } |
| } |
| final String hidlHalInstanceName = "defaultHIDL"; |
| mSensorPropsMap.put(hidlHalInstanceName, |
| hidlFingerprintSensorConfigs.toArray( |
| new HidlFingerprintSensorConfig[hidlFingerprintSensorConfigs.size()])); |
| } |
| |
| protected FingerprintSensorConfigurations(Parcel in) { |
| mResetLockoutRequiresHardwareAuthToken = in.readByte() != 0; |
| mSensorPropsMap = in.readHashMap(null /* loader */, String.class, SensorProps[].class); |
| } |
| |
| /** |
| * Returns true if any fingerprint sensors have been added. |
| */ |
| public boolean hasSensorConfigurations() { |
| return mSensorPropsMap.size() > 0; |
| } |
| |
| /** |
| * Returns true if there is only a single fingerprint sensor configuration available. |
| */ |
| public boolean isSingleSensorConfigurationPresent() { |
| return mSensorPropsMap.size() == 1; |
| } |
| |
| /** |
| * Checks if {@param instance} exists. |
| */ |
| @Nullable |
| public boolean doesInstanceExist(String instance) { |
| return mSensorPropsMap.containsKey(instance); |
| } |
| |
| /** |
| * Return the first HAL instance, which does not correspond to the given {@param instance}. |
| * If another instance is not available, then null is returned. |
| */ |
| @Nullable |
| public String getSensorNameNotForInstance(String instance) { |
| Optional<String> notAVirtualInstance = mSensorPropsMap.keySet().stream().filter( |
| (instanceName) -> !instanceName.equals(instance)).findFirst(); |
| return notAVirtualInstance.orElse(null); |
| } |
| |
| /** |
| * Returns the first instance that has been added to the map. |
| */ |
| @Nullable |
| public String getSensorInstance() { |
| Optional<String> optionalInstance = mSensorPropsMap.keySet().stream().findFirst(); |
| return optionalInstance.orElse(null); |
| } |
| |
| public boolean getResetLockoutRequiresHardwareAuthToken() { |
| return mResetLockoutRequiresHardwareAuthToken; |
| } |
| |
| @Override |
| public int describeContents() { |
| return 0; |
| } |
| |
| @Override |
| public void writeToParcel(@NonNull Parcel dest, int flags) { |
| dest.writeByte((byte) (mResetLockoutRequiresHardwareAuthToken ? 1 : 0)); |
| dest.writeMap(mSensorPropsMap); |
| } |
| |
| /** |
| * Returns fingerprint sensor props for the HAL {@param instance}. |
| */ |
| @Nullable |
| public SensorProps[] getSensorPropForInstance(String instance) { |
| SensorProps[] props = mSensorPropsMap.get(instance); |
| |
| //Props should not be null for HIDL configs |
| if (props != null) { |
| return props; |
| } |
| |
| try { |
| final String fqName = IFingerprint.DESCRIPTOR + "/" + instance; |
| final IFingerprint fp = IFingerprint.Stub.asInterface(Binder.allowBlocking( |
| ServiceManager.waitForDeclaredService(fqName))); |
| if (fp != null) { |
| props = fp.getSensorProps(); |
| } else { |
| Log.d(TAG, "IFingerprint null for instance " + instance); |
| } |
| } catch (RemoteException e) { |
| Log.d(TAG, "Unable to get sensor properties!"); |
| } |
| return props; |
| } |
| } |