mirror of
https://github.com/Evolution-X/hardware_interfaces
synced 2026-01-29 19:22:01 +00:00
Face VHAL for user build
Bug: 326227403 Test: atest android.hardware.biometrics.face.* -c Test: atest CtsBiometricsTestCases -c Ignore-AOSP-First: Not release until 25q2 Change-Id: Ic300cca9f91af3dec3816f16e729656e91f36024
This commit is contained in:
@@ -100,7 +100,11 @@ class Config {
|
||||
} else if (std::holds_alternative<OptIntVec>(v)) {
|
||||
for (auto x : std::get<OptIntVec>(v))
|
||||
if (x.has_value()) os << x.value() << " ";
|
||||
} else if (std::holds_alternative<OptString>(v)) {
|
||||
OptString ov = std::get<OptString>(v);
|
||||
if (ov.has_value()) os << ov.value();
|
||||
}
|
||||
|
||||
return os.str();
|
||||
}
|
||||
std::string toString() const {
|
||||
|
||||
@@ -11,7 +11,7 @@ aidl_interface {
|
||||
name: "android.hardware.biometrics.face",
|
||||
vendor_available: true,
|
||||
srcs: [
|
||||
"android/hardware/biometrics/face/**/*.aidl",
|
||||
"android/hardware/biometrics/face/*.aidl",
|
||||
],
|
||||
imports: [
|
||||
"android.hardware.biometrics.common-V4",
|
||||
@@ -36,6 +36,10 @@ aidl_interface {
|
||||
additional_shared_libraries: [
|
||||
"libnativewindow",
|
||||
],
|
||||
apex_available: [
|
||||
"//apex_available:platform",
|
||||
"com.android.hardware.biometrics.face.virtual",
|
||||
],
|
||||
},
|
||||
},
|
||||
versions_with_info: [
|
||||
@@ -74,5 +78,39 @@ aidl_interface {
|
||||
|
||||
],
|
||||
frozen: true,
|
||||
|
||||
}
|
||||
|
||||
aidl_interface {
|
||||
name: "android.hardware.biometrics.face.virtualhal",
|
||||
srcs: [
|
||||
"android/hardware/biometrics/face/virtualhal/*.aidl",
|
||||
],
|
||||
imports: [
|
||||
"android.hardware.biometrics.common-V4",
|
||||
"android.hardware.keymaster-V4",
|
||||
"android.hardware.biometrics.face-V4",
|
||||
],
|
||||
vendor_available: true,
|
||||
unstable: true,
|
||||
backend: {
|
||||
java: {
|
||||
platform_apis: true,
|
||||
},
|
||||
rust: {
|
||||
enabled: false,
|
||||
},
|
||||
cpp: {
|
||||
enabled: false,
|
||||
},
|
||||
ndk: {
|
||||
additional_shared_libraries: [
|
||||
"libnativewindow",
|
||||
],
|
||||
apex_available: [
|
||||
"com.android.hardware.biometrics.face.virtual",
|
||||
"//apex_available:platform",
|
||||
],
|
||||
},
|
||||
},
|
||||
frozen: false,
|
||||
}
|
||||
|
||||
@@ -73,7 +73,7 @@ interface ISession {
|
||||
* Note that this interface allows multiple in-flight challenges. Invoking generateChallenge
|
||||
* twice does not invalidate the first challenge. The challenge is invalidated only when:
|
||||
* 1) Its lifespan exceeds the challenge timeout defined in the TEE.
|
||||
* 2) IFingerprint#revokeChallenge is invoked
|
||||
* 2) IFace#revokeChallenge is invoked
|
||||
*
|
||||
* For example, the following is a possible table of valid challenges:
|
||||
* ----------------------------------------------
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* Copyright (C) 2024 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.biometrics.face.virtualhal;
|
||||
|
||||
import android.hardware.biometrics.face.AcquiredInfo;
|
||||
|
||||
/**
|
||||
* @hide
|
||||
*/
|
||||
union AcquiredInfoAndVendorCode {
|
||||
/**
|
||||
* Acquired info as specified in AcqauiredInfo.aidl
|
||||
*/
|
||||
AcquiredInfo acquiredInfo = AcquiredInfo.UNKNOWN;
|
||||
|
||||
/**
|
||||
* Vendor specific code
|
||||
*/
|
||||
int vendorCode;
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* Copyright (C) 2024 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.biometrics.face.virtualhal;
|
||||
|
||||
import android.hardware.biometrics.face.virtualhal.AcquiredInfoAndVendorCode;
|
||||
|
||||
/**
|
||||
* @hide
|
||||
*/
|
||||
parcelable EnrollmentProgressStep {
|
||||
/**
|
||||
* The duration of the enrollment step in milli-seconds
|
||||
*/
|
||||
int durationMs;
|
||||
|
||||
/**
|
||||
* The sequence of acquired info and vendor code to be issued by HAL during the step.
|
||||
* The codes are evenly spread over the duration
|
||||
*/
|
||||
AcquiredInfoAndVendorCode[] acquiredInfoAndVendorCodes;
|
||||
}
|
||||
@@ -0,0 +1,297 @@
|
||||
/*
|
||||
* Copyright (C) 2024 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.biometrics.face.virtualhal;
|
||||
|
||||
import android.hardware.biometrics.common.SensorStrength;
|
||||
import android.hardware.biometrics.face.FaceSensorType;
|
||||
import android.hardware.biometrics.face.IFace;
|
||||
import android.hardware.biometrics.face.virtualhal.AcquiredInfoAndVendorCode;
|
||||
import android.hardware.biometrics.face.virtualhal.NextEnrollment;
|
||||
|
||||
/**
|
||||
* @hide
|
||||
*/
|
||||
interface IVirtualHal {
|
||||
/**
|
||||
* The operation failed due to invalid input parameters, the error messages should
|
||||
* gives more details
|
||||
*/
|
||||
const int STATUS_INVALID_PARAMETER = 1;
|
||||
|
||||
/**
|
||||
* Set Face Virtual HAL behavior parameters
|
||||
*/
|
||||
|
||||
/**
|
||||
* setEnrollments
|
||||
*
|
||||
* Set the ids of the faces that were currently enrolled in the Virtual HAL,
|
||||
*
|
||||
* @param ids ids can contain 1 or more ids, each must be larger than 0
|
||||
*/
|
||||
void setEnrollments(in int[] id);
|
||||
|
||||
/**
|
||||
* setEnrollmentHit
|
||||
*
|
||||
* Set current face enrollment ids in Face Virtual HAL,
|
||||
*
|
||||
* @param ids ids can contain 1 or more ids, each must be larger than 0
|
||||
*/
|
||||
void setEnrollmentHit(in int hit_id);
|
||||
|
||||
/**
|
||||
* setNextEnrollment
|
||||
*
|
||||
* Set the next enrollment behavior
|
||||
*
|
||||
* @param next_enrollment specifies enrollment id, progress stages and final result
|
||||
*/
|
||||
void setNextEnrollment(in NextEnrollment next_enrollment);
|
||||
|
||||
/**
|
||||
* setAuthenticatorId
|
||||
*
|
||||
* Set authenticator id in virtual HAL, the id is returned in ISession#AuthenticatorId() call
|
||||
*
|
||||
* @param id authenticator id value, only applied to the sensor with SensorStrength::STRONG.
|
||||
*/
|
||||
void setAuthenticatorId(in long id);
|
||||
|
||||
/**
|
||||
* setChallenge
|
||||
*
|
||||
* Set the challenge generated by the virtual HAL, which is returned in
|
||||
* ISessionCallback#onChallengeGenerated()
|
||||
*
|
||||
* @param challenge
|
||||
*/
|
||||
void setChallenge(in long challenge);
|
||||
|
||||
/**
|
||||
* setOperationAuthenticateFails
|
||||
*
|
||||
* Set whether to force authentication to fail. If true, the virtual hal will report failure on
|
||||
* authentication attempt until it is set to false
|
||||
*
|
||||
* @param fail if true, then the next authentication will fail
|
||||
*/
|
||||
void setOperationAuthenticateFails(in boolean fail);
|
||||
|
||||
/**
|
||||
* setOperationAuthenticateLatency
|
||||
*
|
||||
* Set authentication latency in the virtual hal in a fixed value (single element) or random
|
||||
* values (two elements representing the bound values)
|
||||
* The latency simulates the delay from the time framework requesting HAL to authetication to
|
||||
* the time when HAL is ready to perform authentication operations.
|
||||
*
|
||||
* This method fails with STATUS_INVALID_PARAMETERS if the passed-in array falls in any of
|
||||
* the following conditions
|
||||
* 1. the array contains no element
|
||||
* 2. the array contains more than two elements
|
||||
* 3. the array contains any negative value
|
||||
* The accompanying error message gives more detail
|
||||
*
|
||||
* @param latencyMs[] value(s) are in milli-seconds
|
||||
*/
|
||||
void setOperationAuthenticateLatency(in int[] latencyMs);
|
||||
|
||||
/**
|
||||
* setOperationAuthenticateDuration
|
||||
*
|
||||
* Set authentication duration covering the HAL authetication from start to end, including
|
||||
* face capturing, and matching, acquired info reporting. In case a sequence of acquired
|
||||
* info code are specified via setOperationAuthenticateAcquired(), the reporting is evenly
|
||||
* distributed over the duration.
|
||||
*
|
||||
* This method fails with STATUS_INVALID_PARAMETERS if the passed-in value is negative
|
||||
*
|
||||
* @param duration value is in milli-seconds
|
||||
*/
|
||||
void setOperationAuthenticateDuration(in int durationMs);
|
||||
|
||||
/**
|
||||
* setOperationAuthenticateError
|
||||
*
|
||||
* Force authentication to error out for non-zero error
|
||||
* Check
|
||||
* hardware/interfaces/biometrics/face/aidl/default/aidl/android/hardware/biometrics/face/Error.aidl
|
||||
* for valid error codes
|
||||
*
|
||||
* @param error if error < 1000
|
||||
* non-vendor error
|
||||
* else
|
||||
* vendor error
|
||||
*/
|
||||
void setOperationAuthenticateError(in int error);
|
||||
|
||||
/**
|
||||
* setOperationAuthenticateAcquired
|
||||
*
|
||||
* Set one of more acquired info codes for the virtual hal to report during authentication
|
||||
* Check
|
||||
* hardware/interfaces/biometrics/face/aidl/aidl/android/hardware/biometrics/face/AcquiredInfo.aidl
|
||||
* for valid acquired info codes
|
||||
*
|
||||
* @param acquired[], one or more acquired info codes
|
||||
*/
|
||||
void setOperationAuthenticateAcquired(in AcquiredInfoAndVendorCode[] acquired);
|
||||
|
||||
/**
|
||||
* setOperationEnrollLatency
|
||||
*
|
||||
* Set enrollment latency in the virtual hal in a fixed value (single element) or random
|
||||
* values (two elements representing the bound values)
|
||||
* The latency simulates the delay from the time framework requesting HAL to enroll to the
|
||||
* time when HAL is ready to perform enrollment operations.
|
||||
*
|
||||
* This method fails with STATUS_INVALID_PARAMETERS if the passed-in array falls in any of
|
||||
* the following conditions
|
||||
* 1. the array contains no element
|
||||
* 2. the array contains more than two elements
|
||||
* 3. the array contains any negative value
|
||||
* The accompanying error message gives more detail
|
||||
*
|
||||
* @param latencyMs[] value(s) are in milli-seconds
|
||||
*/
|
||||
void setOperationEnrollLatency(in int[] latencyMs);
|
||||
|
||||
/**
|
||||
* setOperationDetectInteractionLatency
|
||||
*
|
||||
* Set detect interaction latency in the virtual hal in a fixed value (single element) or random
|
||||
* values (two elements representing the bound values)
|
||||
* The latency simulates the delay from the time framework requesting HAL to detect interaction
|
||||
* to the time when HAL is ready to perform detect interaction operations.
|
||||
*
|
||||
* This method fails with STATUS_INVALID_PARAMETERS if the passed-in array falls in any of
|
||||
* the following conditions
|
||||
* 1. the array contains no element
|
||||
* 2. the array contains more than two elements
|
||||
* 3. the array contains any negative value
|
||||
* The accompanying error message gives more detail
|
||||
*
|
||||
* @param latencyMs[] value(s) are in milli-seconds
|
||||
*/
|
||||
void setOperationDetectInteractionLatency(in int[] latencyMs);
|
||||
|
||||
/**
|
||||
* setOperationDetectInteractionFails
|
||||
*
|
||||
* Force detect interaction operation to fail
|
||||
*/
|
||||
void setOperationDetectInteractionFails(in boolean error);
|
||||
|
||||
/**
|
||||
* setLockout
|
||||
*
|
||||
* Whether to force to lockout on authentcation operation. If true, the virtual hal will report
|
||||
* permanent lockout in processing authentication requrest, regardless of whether
|
||||
* setLockoutEnable(true) is called or not.
|
||||
*
|
||||
* @param lockout, set to true if lockout is desired
|
||||
*/
|
||||
void setLockout(in boolean lockout);
|
||||
|
||||
/**
|
||||
* setLockoutEnable
|
||||
*
|
||||
* Whether to enable authentication-fail-based lockout tracking or not. The lock tracking
|
||||
* includes both timed-based (aka temporary) lockout and permanent lockout.
|
||||
*
|
||||
* @param enable, set true to enable the lockout tracking
|
||||
*/
|
||||
void setLockoutEnable(in boolean enable);
|
||||
|
||||
/**
|
||||
* setLockoutTimedEnable
|
||||
*
|
||||
* Whether to enable authentication-fail-based time-based-lockout tracking or not.
|
||||
*
|
||||
* @param enable, set true to enable the time-basedlockout tracking
|
||||
*/
|
||||
void setLockoutTimedEnable(in boolean enable);
|
||||
|
||||
/**
|
||||
* setLockoutTimedThreshold
|
||||
*
|
||||
* Set the number of consecutive authentication failures that triggers the timed-based lock to
|
||||
* occur
|
||||
*
|
||||
* This method fails with STATUS_INVALID_PARAMETERS if the passed-in value is negative
|
||||
*
|
||||
* @param threshold, the number of consecutive failures
|
||||
*/
|
||||
void setLockoutTimedThreshold(in int threshold);
|
||||
|
||||
/**
|
||||
* setLockoutTimedDuration
|
||||
*
|
||||
* Set the duration to expire timed-based lock during which there is no authentication failure
|
||||
*
|
||||
* This method fails with STATUS_INVALID_PARAMETERS if the passed-in value is negative
|
||||
*
|
||||
* @param duration, in milli-seconds
|
||||
*/
|
||||
void setLockoutTimedDuration(in int durationMs);
|
||||
|
||||
/**
|
||||
* setLockoutPermanentThreshold
|
||||
*
|
||||
* Set the number of consecutive authentication failures that triggers the permanent lock to
|
||||
* occur
|
||||
*
|
||||
* This method fails with STATUS_INVALID_PARAMETERS if the passed-in value is negative
|
||||
*
|
||||
* @param threshold, the number of consecutive failures
|
||||
*/
|
||||
void setLockoutPermanentThreshold(in int threshold);
|
||||
|
||||
/**
|
||||
* resetConfigurations
|
||||
*
|
||||
* Reset all virtual hal configurations to default values
|
||||
*/
|
||||
void resetConfigurations();
|
||||
|
||||
/**
|
||||
* setType
|
||||
*
|
||||
* Configure virtual face sensor type
|
||||
*
|
||||
* @param type, sensor type as specified in FaceSensorType.aidl
|
||||
*
|
||||
*/
|
||||
void setType(in FaceSensorType type);
|
||||
|
||||
/**
|
||||
* setSensorStrength
|
||||
*
|
||||
* Configure virtual face sensor strength
|
||||
*
|
||||
* @param sensor strength as specified in common/SensorStrength.aidl
|
||||
*/
|
||||
void setSensorStrength(in SensorStrength strength);
|
||||
|
||||
/**
|
||||
* getFaceHal
|
||||
*
|
||||
* @return IFace interface associated with IVirtualHal instance
|
||||
*/
|
||||
IFace getFaceHal();
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* Copyright (C) 2024 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.biometrics.face.virtualhal;
|
||||
|
||||
/**
|
||||
* @hide
|
||||
*/
|
||||
parcelable NextEnrollment {
|
||||
/**
|
||||
* Identifier of the next enrollment if successful
|
||||
*/
|
||||
int id;
|
||||
|
||||
/**
|
||||
* Specification of the progress steps of the next enrollment, each step consists of duration
|
||||
* and sequence of acquired info codes to be generated by HAL.
|
||||
* See EnrollmentProgressStep.aidl for more details
|
||||
*/
|
||||
android.hardware.biometrics.face.virtualhal.EnrollmentProgressStep[] progressSteps;
|
||||
|
||||
/**
|
||||
* Success or failure of the next enrollment
|
||||
*/
|
||||
boolean result = true;
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
The aidl files in this directory are used to control/configure face virtual hal
|
||||
via IVirtualHal interface
|
||||
|
||||
@@ -9,21 +9,13 @@ package {
|
||||
}
|
||||
|
||||
filegroup {
|
||||
name: "face-example.rc",
|
||||
srcs: ["face-example.rc"],
|
||||
name: "face-virtual.rc",
|
||||
srcs: ["face-virtual.rc"],
|
||||
}
|
||||
|
||||
filegroup {
|
||||
name: "face-example.xml",
|
||||
srcs: ["face-example.xml"],
|
||||
}
|
||||
|
||||
cc_binary {
|
||||
name: "android.hardware.biometrics.face-service.example",
|
||||
relative_install_path: "hw",
|
||||
init_rc: [":face-example.rc"],
|
||||
vintf_fragments: [":face-example.xml"],
|
||||
vendor: true,
|
||||
cc_library_static {
|
||||
name: "android.hardware.biometrics.face-service.lib",
|
||||
vendor_available: true,
|
||||
|
||||
shared_libs: [
|
||||
"libbinder_ndk",
|
||||
@@ -32,32 +24,80 @@ cc_binary {
|
||||
],
|
||||
srcs: [
|
||||
"FakeLockoutTracker.cpp",
|
||||
"main.cpp",
|
||||
"Face.cpp",
|
||||
"FakeFaceEngine.cpp",
|
||||
"Session.cpp",
|
||||
"FaceConfig.cpp",
|
||||
"VirtualHal.cpp",
|
||||
"main.cpp",
|
||||
],
|
||||
include_dirs: [
|
||||
"frameworks/native/aidl/gui",
|
||||
],
|
||||
stl: "c++_static",
|
||||
static_libs: [
|
||||
whole_static_libs: [
|
||||
"android.hardware.biometrics.common-V4-ndk",
|
||||
"android.hardware.biometrics.common.config",
|
||||
"android.hardware.biometrics.common.thread",
|
||||
"android.hardware.biometrics.common.util",
|
||||
"android.hardware.biometrics.face.virtualhal-ndk",
|
||||
"android.hardware.biometrics.face-V4-ndk",
|
||||
"android.hardware.common-V2-ndk",
|
||||
"android.hardware.keymaster-V4-ndk",
|
||||
"libandroid.hardware.biometrics.face.VirtualProps",
|
||||
"libbase",
|
||||
],
|
||||
apex_available: [
|
||||
"com.android.hardware.biometrics.face.virtual",
|
||||
"//apex_available:platform",
|
||||
],
|
||||
}
|
||||
|
||||
cc_binary {
|
||||
name: "android.hardware.biometrics.face-service.example",
|
||||
system_ext_specific: true,
|
||||
relative_install_path: "hw",
|
||||
|
||||
shared_libs: [
|
||||
"libbinder_ndk",
|
||||
"liblog",
|
||||
"libnativewindow",
|
||||
],
|
||||
whole_static_libs: [
|
||||
"android.hardware.biometrics.face-service.lib",
|
||||
],
|
||||
installable: false, // install APEX instead
|
||||
apex_available: [
|
||||
"com.android.hardware.biometrics.face.virtual",
|
||||
"//apex_available:platform",
|
||||
],
|
||||
}
|
||||
|
||||
cc_binary {
|
||||
name: "android.hardware.biometrics.face-service.default",
|
||||
vendor: true,
|
||||
relative_install_path: "hw",
|
||||
init_rc: ["face-default.rc"],
|
||||
vintf_fragments: ["face-default.xml"],
|
||||
shared_libs: [
|
||||
"libbinder_ndk",
|
||||
"liblog",
|
||||
"libnativewindow",
|
||||
],
|
||||
whole_static_libs: [
|
||||
"android.hardware.biometrics.face-service.lib",
|
||||
],
|
||||
}
|
||||
|
||||
sysprop_library {
|
||||
name: "android.hardware.biometrics.face.VirtualProps",
|
||||
srcs: ["face.sysprop"],
|
||||
property_owner: "Vendor",
|
||||
vendor: true,
|
||||
property_owner: "Platform",
|
||||
vendor_available: true,
|
||||
apex_available: [
|
||||
"//apex_available:platform",
|
||||
"com.android.hardware.biometrics.face.virtual",
|
||||
],
|
||||
}
|
||||
|
||||
cc_test {
|
||||
@@ -66,6 +106,7 @@ cc_test {
|
||||
"tests/FakeFaceEngineTest.cpp",
|
||||
"FakeFaceEngine.cpp",
|
||||
"FakeLockoutTracker.cpp",
|
||||
"FaceConfig.cpp",
|
||||
],
|
||||
shared_libs: [
|
||||
"libbase",
|
||||
@@ -81,6 +122,8 @@ cc_test {
|
||||
"android.hardware.biometrics.common-V4-ndk",
|
||||
"android.hardware.keymaster-V4-ndk",
|
||||
"android.hardware.biometrics.common.util",
|
||||
"android.hardware.biometrics.common.config",
|
||||
"android.hardware.biometrics.common.thread",
|
||||
],
|
||||
vendor: true,
|
||||
test_suites: ["general-tests"],
|
||||
@@ -92,6 +135,7 @@ cc_test {
|
||||
srcs: [
|
||||
"tests/FakeLockoutTrackerTest.cpp",
|
||||
"FakeLockoutTracker.cpp",
|
||||
"FaceConfig.cpp",
|
||||
],
|
||||
shared_libs: [
|
||||
"libbase",
|
||||
@@ -107,8 +151,45 @@ cc_test {
|
||||
"android.hardware.biometrics.common-V4-ndk",
|
||||
"android.hardware.keymaster-V4-ndk",
|
||||
"android.hardware.biometrics.common.util",
|
||||
"android.hardware.biometrics.common.config",
|
||||
"android.hardware.biometrics.common.thread",
|
||||
],
|
||||
vendor: true,
|
||||
test_suites: ["general-tests"],
|
||||
require_root: true,
|
||||
}
|
||||
|
||||
cc_test {
|
||||
name: "android.hardware.biometrics.face.VirtualHalTest",
|
||||
srcs: [
|
||||
"tests/VirtualHalTest.cpp",
|
||||
"FakeLockoutTracker.cpp",
|
||||
"Face.cpp",
|
||||
"FakeFaceEngine.cpp",
|
||||
"Session.cpp",
|
||||
"VirtualHal.cpp",
|
||||
"FaceConfig.cpp",
|
||||
],
|
||||
shared_libs: [
|
||||
"libbase",
|
||||
"libbinder_ndk",
|
||||
"libnativewindow",
|
||||
"liblog",
|
||||
],
|
||||
include_dirs: [
|
||||
"frameworks/native/aidl/gui",
|
||||
],
|
||||
static_libs: [
|
||||
"android.hardware.biometrics.common-V4-ndk",
|
||||
"android.hardware.biometrics.common.config",
|
||||
"android.hardware.biometrics.common.thread",
|
||||
"android.hardware.biometrics.common.util",
|
||||
"android.hardware.biometrics.face-V4-ndk",
|
||||
"android.hardware.common-V2-ndk",
|
||||
"android.hardware.keymaster-V4-ndk",
|
||||
"libandroid.hardware.biometrics.face.VirtualProps",
|
||||
"android.hardware.biometrics.face.virtualhal-ndk",
|
||||
],
|
||||
test_suites: ["general-tests"],
|
||||
require_root: true,
|
||||
}
|
||||
|
||||
@@ -34,9 +34,7 @@ using namespace ::android::face::virt;
|
||||
namespace aidl::android::hardware::biometrics::face {
|
||||
|
||||
const int kSensorId = 4;
|
||||
const common::SensorStrength kSensorStrength = FakeFaceEngine::GetSensorStrength();
|
||||
const int kMaxEnrollmentsPerUser = 5;
|
||||
const FaceSensorType kSensorType = FakeFaceEngine::GetSensorType();
|
||||
const bool kHalControlsPreview = true;
|
||||
const std::string kHwComponentId = "faceSensor";
|
||||
const std::string kHardwareVersion = "vendor/model/revision";
|
||||
@@ -62,13 +60,13 @@ ndk::ScopedAStatus Face::getSensorProps(std::vector<SensorProps>* return_val) {
|
||||
|
||||
common::CommonProps commonProps;
|
||||
commonProps.sensorId = kSensorId;
|
||||
commonProps.sensorStrength = kSensorStrength;
|
||||
commonProps.sensorStrength = FakeFaceEngine::GetSensorStrength();
|
||||
commonProps.maxEnrollmentsPerUser = kMaxEnrollmentsPerUser;
|
||||
commonProps.componentInfo = {std::move(hw_component_info), std::move(sw_component_info)};
|
||||
|
||||
SensorProps props;
|
||||
props.commonProps = std::move(commonProps);
|
||||
props.sensorType = kSensorType;
|
||||
props.sensorType = FakeFaceEngine::GetSensorType();
|
||||
props.halControlsPreview = kHalControlsPreview;
|
||||
props.enrollPreviewWidth = 1080;
|
||||
props.enrollPreviewHeight = 1920;
|
||||
@@ -141,6 +139,30 @@ binder_status_t Face::handleShellCommand(int in, int out, int err, const char**
|
||||
return STATUS_OK;
|
||||
}
|
||||
|
||||
const char* Face::type2String(FaceSensorType type) {
|
||||
switch (type) {
|
||||
case FaceSensorType::RGB:
|
||||
return "rgb";
|
||||
case FaceSensorType::IR:
|
||||
return "ir";
|
||||
default:
|
||||
return "unknown";
|
||||
}
|
||||
}
|
||||
|
||||
const char* Face::strength2String(common::SensorStrength strength) {
|
||||
switch (strength) {
|
||||
case common::SensorStrength::STRONG:
|
||||
return "STRONG";
|
||||
case common::SensorStrength::WEAK:
|
||||
return "WEAK";
|
||||
case common::SensorStrength::CONVENIENCE:
|
||||
return "CONVENIENCE";
|
||||
default:
|
||||
return "unknown";
|
||||
}
|
||||
}
|
||||
|
||||
void Face::onHelp(int fd) {
|
||||
dprintf(fd, "Virtual Face HAL commands:\n");
|
||||
dprintf(fd, " help: print this help\n");
|
||||
@@ -167,7 +189,6 @@ void Face::resetConfigToDefault() {
|
||||
RESET_CONFIG_O(lockout);
|
||||
RESET_CONFIG_O(operation_authenticate_fails);
|
||||
RESET_CONFIG_O(operation_detect_interaction_fails);
|
||||
RESET_CONFIG_O(operation_enroll_fails);
|
||||
RESET_CONFIG_V(operation_authenticate_latency);
|
||||
RESET_CONFIG_V(operation_detect_interaction_latency);
|
||||
RESET_CONFIG_V(operation_enroll_latency);
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
#pragma once
|
||||
|
||||
#include <aidl/android/hardware/biometrics/face/BnFace.h>
|
||||
#include "FaceConfig.h"
|
||||
#include "Session.h"
|
||||
|
||||
namespace aidl::android::hardware::biometrics::face {
|
||||
@@ -33,9 +34,20 @@ class Face : public BnFace {
|
||||
binder_status_t dump(int fd, const char** args, uint32_t numArgs);
|
||||
binder_status_t handleShellCommand(int in, int out, int err, const char** argv, uint32_t argc);
|
||||
|
||||
static FaceConfig& cfg() {
|
||||
static FaceConfig* cfg = nullptr;
|
||||
if (cfg == nullptr) {
|
||||
cfg = new FaceConfig();
|
||||
cfg->init();
|
||||
}
|
||||
return *cfg;
|
||||
}
|
||||
void resetConfigToDefault();
|
||||
static const char* type2String(FaceSensorType type);
|
||||
static const char* strength2String(common::SensorStrength strength);
|
||||
|
||||
private:
|
||||
std::shared_ptr<Session> mSession;
|
||||
void resetConfigToDefault();
|
||||
void onHelp(int);
|
||||
};
|
||||
|
||||
|
||||
93
biometrics/face/aidl/default/FaceConfig.cpp
Normal file
93
biometrics/face/aidl/default/FaceConfig.cpp
Normal file
@@ -0,0 +1,93 @@
|
||||
/*
|
||||
* Copyright (C) 2024 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.
|
||||
*/
|
||||
|
||||
#define LOG_TAG "FaceConfig"
|
||||
|
||||
#include "FaceConfig.h"
|
||||
|
||||
#include <android-base/logging.h>
|
||||
|
||||
#include <face.sysprop.h>
|
||||
|
||||
using namespace ::android::face::virt;
|
||||
|
||||
namespace aidl::android::hardware::biometrics::face {
|
||||
|
||||
// Wrapper to system property access functions
|
||||
#define CREATE_GETTER_SETTER_WRAPPER(_NAME_, _T_) \
|
||||
ConfigValue _NAME_##Getter() { \
|
||||
return FaceHalProperties::_NAME_(); \
|
||||
} \
|
||||
bool _NAME_##Setter(const ConfigValue& v) { \
|
||||
return FaceHalProperties::_NAME_(std::get<_T_>(v)); \
|
||||
}
|
||||
|
||||
CREATE_GETTER_SETTER_WRAPPER(type, OptString)
|
||||
CREATE_GETTER_SETTER_WRAPPER(enrollments, OptIntVec)
|
||||
CREATE_GETTER_SETTER_WRAPPER(enrollment_hit, OptInt32)
|
||||
CREATE_GETTER_SETTER_WRAPPER(next_enrollment, OptString)
|
||||
CREATE_GETTER_SETTER_WRAPPER(authenticator_id, OptInt64)
|
||||
CREATE_GETTER_SETTER_WRAPPER(challenge, OptInt64)
|
||||
CREATE_GETTER_SETTER_WRAPPER(strength, OptString)
|
||||
CREATE_GETTER_SETTER_WRAPPER(operation_authenticate_fails, OptBool)
|
||||
CREATE_GETTER_SETTER_WRAPPER(operation_authenticate_latency, OptIntVec)
|
||||
CREATE_GETTER_SETTER_WRAPPER(operation_authenticate_duration, OptInt32)
|
||||
CREATE_GETTER_SETTER_WRAPPER(operation_authenticate_error, OptInt32)
|
||||
CREATE_GETTER_SETTER_WRAPPER(operation_authenticate_acquired, OptString)
|
||||
CREATE_GETTER_SETTER_WRAPPER(operation_enroll_latency, OptIntVec)
|
||||
CREATE_GETTER_SETTER_WRAPPER(operation_detect_interaction_fails, OptBool)
|
||||
CREATE_GETTER_SETTER_WRAPPER(operation_detect_interaction_latency, OptIntVec)
|
||||
CREATE_GETTER_SETTER_WRAPPER(lockout, OptBool)
|
||||
CREATE_GETTER_SETTER_WRAPPER(lockout_enable, OptBool)
|
||||
CREATE_GETTER_SETTER_WRAPPER(lockout_timed_enable, OptBool)
|
||||
CREATE_GETTER_SETTER_WRAPPER(lockout_timed_threshold, OptInt32)
|
||||
CREATE_GETTER_SETTER_WRAPPER(lockout_timed_duration, OptInt32)
|
||||
CREATE_GETTER_SETTER_WRAPPER(lockout_permanent_threshold, OptInt32)
|
||||
CREATE_GETTER_SETTER_WRAPPER(features, OptIntVec)
|
||||
|
||||
// Name, Getter, Setter, Parser and default value
|
||||
#define NGS(_NAME_) #_NAME_, _NAME_##Getter, _NAME_##Setter
|
||||
static Config::Data configData[] = {
|
||||
{NGS(type), &Config::parseString, "rgb"},
|
||||
{NGS(enrollments), &Config::parseIntVec, ""},
|
||||
{NGS(enrollment_hit), &Config::parseInt32, "0"},
|
||||
{NGS(next_enrollment), &Config::parseString,
|
||||
"1:1000-[21,7,1,1103],1500-[1108,1],2000-[1113,1],2500-[1118,1]:true"},
|
||||
{NGS(authenticator_id), &Config::parseInt64, "0"},
|
||||
{NGS(challenge), &Config::parseInt64, ""},
|
||||
{NGS(strength), &Config::parseString, "strong"},
|
||||
{NGS(operation_authenticate_fails), &Config::parseBool, "false"},
|
||||
{NGS(operation_authenticate_latency), &Config::parseIntVec, ""},
|
||||
{NGS(operation_authenticate_duration), &Config::parseInt32, "500"},
|
||||
{NGS(operation_authenticate_error), &Config::parseInt32, "0"},
|
||||
{NGS(operation_authenticate_acquired), &Config::parseString, ""},
|
||||
{NGS(operation_enroll_latency), &Config::parseIntVec, ""},
|
||||
{NGS(operation_detect_interaction_latency), &Config::parseIntVec, ""},
|
||||
{NGS(operation_detect_interaction_fails), &Config::parseBool, "false"},
|
||||
{NGS(lockout), &Config::parseBool, "false"},
|
||||
{NGS(lockout_enable), &Config::parseBool, "false"},
|
||||
{NGS(lockout_timed_enable), &Config::parseBool, "false"},
|
||||
{NGS(lockout_timed_threshold), &Config::parseInt32, "3"},
|
||||
{NGS(lockout_timed_duration), &Config::parseInt32, "10000"},
|
||||
{NGS(lockout_permanent_threshold), &Config::parseInt32, "5"},
|
||||
{NGS(features), &Config::parseIntVec, ""}};
|
||||
|
||||
Config::Data* FaceConfig::getConfigData(int* size) {
|
||||
*size = sizeof(configData) / sizeof(configData[0]);
|
||||
return configData;
|
||||
}
|
||||
|
||||
} // namespace aidl::android::hardware::biometrics::face
|
||||
27
biometrics/face/aidl/default/FaceConfig.h
Normal file
27
biometrics/face/aidl/default/FaceConfig.h
Normal file
@@ -0,0 +1,27 @@
|
||||
/*
|
||||
* Copyright (C) 2024 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.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "config/Config.h"
|
||||
|
||||
namespace aidl::android::hardware::biometrics::face {
|
||||
|
||||
class FaceConfig : public Config {
|
||||
Config::Data* getConfigData(int* size) override;
|
||||
};
|
||||
|
||||
} // namespace aidl::android::hardware::biometrics::face
|
||||
@@ -23,6 +23,7 @@
|
||||
|
||||
#include <face.sysprop.h>
|
||||
|
||||
#include "Face.h"
|
||||
#include "util/CancellationSignal.h"
|
||||
#include "util/Util.h"
|
||||
|
||||
@@ -31,23 +32,23 @@ using namespace ::android::face::virt;
|
||||
namespace aidl::android::hardware::biometrics::face {
|
||||
|
||||
FaceSensorType FakeFaceEngine::GetSensorType() {
|
||||
std::string type = FaceHalProperties::type().value_or("");
|
||||
std::string type = Face::cfg().get<std::string>("type");
|
||||
if (type == "IR") {
|
||||
return FaceSensorType::IR;
|
||||
} else {
|
||||
FaceHalProperties::type("RGB");
|
||||
Face::cfg().set<std::string>("type", "RGB");
|
||||
return FaceSensorType::RGB;
|
||||
}
|
||||
}
|
||||
|
||||
common::SensorStrength FakeFaceEngine::GetSensorStrength() {
|
||||
std::string strength = FaceHalProperties::strength().value_or("");
|
||||
std::string strength = Face::cfg().get<std::string>("strength");
|
||||
if (strength == "convenience") {
|
||||
return common::SensorStrength::CONVENIENCE;
|
||||
} else if (strength == "weak") {
|
||||
return common::SensorStrength::WEAK;
|
||||
} else {
|
||||
FaceHalProperties::strength("strong");
|
||||
// Face::cfg().set<std::string>("strength", "strong");
|
||||
return common::SensorStrength::STRONG;
|
||||
}
|
||||
}
|
||||
@@ -56,13 +57,13 @@ void FakeFaceEngine::generateChallengeImpl(ISessionCallback* cb) {
|
||||
BEGIN_OP(0);
|
||||
std::uniform_int_distribution<int64_t> dist;
|
||||
auto challenge = dist(mRandom);
|
||||
FaceHalProperties::challenge(challenge);
|
||||
Face::cfg().set<int64_t>("challenge", challenge);
|
||||
cb->onChallengeGenerated(challenge);
|
||||
}
|
||||
|
||||
void FakeFaceEngine::revokeChallengeImpl(ISessionCallback* cb, int64_t challenge) {
|
||||
BEGIN_OP(0);
|
||||
FaceHalProperties::challenge({});
|
||||
Face::cfg().set<int64_t>("challenge", 0);
|
||||
cb->onChallengeRevoked(challenge);
|
||||
}
|
||||
void FakeFaceEngine::getEnrollmentConfigImpl(ISessionCallback* /*cb*/,
|
||||
@@ -71,7 +72,7 @@ void FakeFaceEngine::enrollImpl(ISessionCallback* cb, const keymaster::HardwareA
|
||||
EnrollmentType /*enrollmentType*/,
|
||||
const std::vector<Feature>& /*features*/,
|
||||
const std::future<void>& cancel) {
|
||||
BEGIN_OP(getLatency(FaceHalProperties::operation_enroll_latency()));
|
||||
BEGIN_OP(getLatency(Face::cfg().getopt<OptIntVec>("operation_enroll_latency")));
|
||||
|
||||
// Do proper HAT verification in the real implementation.
|
||||
if (hat.mac.empty()) {
|
||||
@@ -80,18 +81,19 @@ void FakeFaceEngine::enrollImpl(ISessionCallback* cb, const keymaster::HardwareA
|
||||
return;
|
||||
}
|
||||
|
||||
// Format: <id>:<progress_ms-[acquiredInfo,...],...:<success>
|
||||
// ------:-----------------------------------------:--------------
|
||||
// | | |--->enrollment success (true/false)
|
||||
// | |--> progress_steps
|
||||
// Format:
|
||||
// <id>:<progress_ms-[acquiredInfo,...],...:<success>
|
||||
// -------:--------------------------------------------------:--------------
|
||||
// | | |--->enrollment
|
||||
// success (true/false) | |--> progress_steps
|
||||
// |
|
||||
// |-->enrollment id
|
||||
//
|
||||
//
|
||||
// progress_steps
|
||||
// progress_steps:
|
||||
// <progress_duration>-[acquiredInfo,...]+
|
||||
// ---------------------------- ---------------------
|
||||
// | |-> sequence of acquiredInfo code
|
||||
// | |-> sequence of acquiredInfo code
|
||||
// | --> time duration of the step in ms
|
||||
//
|
||||
// E.g. 1:2000-[21,1108,5,6,1],1000-[1113,4,1]:true
|
||||
@@ -101,7 +103,7 @@ void FakeFaceEngine::enrollImpl(ISessionCallback* cb, const keymaster::HardwareA
|
||||
//
|
||||
std::string defaultNextEnrollment =
|
||||
"1:1000-[21,7,1,1103],1500-[1108,1],2000-[1113,1],2500-[1118,1]:true";
|
||||
auto nextEnroll = FaceHalProperties::next_enrollment().value_or(defaultNextEnrollment);
|
||||
auto nextEnroll = Face::cfg().get<std::string>("next_enrollment");
|
||||
auto parts = Util::split(nextEnroll, ":");
|
||||
if (parts.size() != 3) {
|
||||
LOG(ERROR) << "Fail: invalid next_enrollment:" << nextEnroll;
|
||||
@@ -137,19 +139,19 @@ void FakeFaceEngine::enrollImpl(ISessionCallback* cb, const keymaster::HardwareA
|
||||
|
||||
if (left == 0 && !IS_TRUE(parts[2])) { // end and failed
|
||||
LOG(ERROR) << "Fail: requested by caller: " << nextEnroll;
|
||||
FaceHalProperties::next_enrollment({});
|
||||
Face::cfg().setopt<OptString>("next_enrollment", std::nullopt);
|
||||
cb->onError(Error::UNABLE_TO_PROCESS, 0 /* vendorCode */);
|
||||
} else { // progress and update props if last time
|
||||
LOG(INFO) << "onEnroll: " << enrollmentId << " left: " << left;
|
||||
if (left == 0) {
|
||||
auto enrollments = FaceHalProperties::enrollments();
|
||||
auto enrollments = Face::cfg().getopt<OptIntVec>("enrollments");
|
||||
enrollments.emplace_back(enrollmentId);
|
||||
FaceHalProperties::enrollments(enrollments);
|
||||
FaceHalProperties::next_enrollment({});
|
||||
Face::cfg().setopt<OptIntVec>("enrollments", enrollments);
|
||||
Face::cfg().setopt<OptString>("next_enrollment", std::nullopt);
|
||||
// change authenticatorId after new enrollment
|
||||
auto id = FaceHalProperties::authenticator_id().value_or(0);
|
||||
auto id = Face::cfg().get<std::int64_t>("authenticator_id");
|
||||
auto newId = id + 1;
|
||||
FaceHalProperties::authenticator_id(newId);
|
||||
Face::cfg().set<std::int64_t>("authenticator_id", newId);
|
||||
LOG(INFO) << "Enrolled: " << enrollmentId;
|
||||
}
|
||||
cb->onEnrollmentProgress(enrollmentId, left);
|
||||
@@ -159,10 +161,12 @@ void FakeFaceEngine::enrollImpl(ISessionCallback* cb, const keymaster::HardwareA
|
||||
|
||||
void FakeFaceEngine::authenticateImpl(ISessionCallback* cb, int64_t /*operationId*/,
|
||||
const std::future<void>& cancel) {
|
||||
BEGIN_OP(getLatency(FaceHalProperties::operation_authenticate_latency()));
|
||||
BEGIN_OP(getLatency(Face::cfg().getopt<OptIntVec>("operation_authenticate_latency")));
|
||||
|
||||
auto id = FaceHalProperties::enrollment_hit().value_or(0);
|
||||
auto enrolls = FaceHalProperties::enrollments();
|
||||
// SLEEP_MS(3000); //emulate hw HAL
|
||||
|
||||
auto id = Face::cfg().get<std::int32_t>("enrollment_hit");
|
||||
auto enrolls = Face::cfg().getopt<OptIntVec>("enrollments");
|
||||
auto isEnrolled = std::find(enrolls.begin(), enrolls.end(), id) != enrolls.end();
|
||||
|
||||
auto vec2str = [](std::vector<AcquiredInfo> va) {
|
||||
@@ -192,10 +196,12 @@ void FakeFaceEngine::authenticateImpl(ISessionCallback* cb, int64_t /*operationI
|
||||
}
|
||||
|
||||
int64_t now = Util::getSystemNanoTime();
|
||||
int64_t duration =
|
||||
FaceHalProperties::operation_authenticate_duration().value_or(defaultAuthDuration);
|
||||
auto acquired =
|
||||
FaceHalProperties::operation_authenticate_acquired().value_or(defaultAcquiredInfo);
|
||||
int64_t duration = Face::cfg().get<std::int32_t>("operation_authenticate_duration");
|
||||
auto acquired = Face::cfg().get<std::string>("operation_authenticate_acquired");
|
||||
if (acquired.empty()) {
|
||||
Face::cfg().set<std::string>("operation_authenticate_acquired", defaultAcquiredInfo);
|
||||
acquired = defaultAcquiredInfo;
|
||||
}
|
||||
auto acquiredInfos = Util::parseIntSequence(acquired);
|
||||
int N = acquiredInfos.size();
|
||||
|
||||
@@ -211,21 +217,21 @@ void FakeFaceEngine::authenticateImpl(ISessionCallback* cb, int64_t /*operationI
|
||||
|
||||
int i = 0;
|
||||
do {
|
||||
if (FaceHalProperties::lockout().value_or(false)) {
|
||||
if (Face::cfg().get<bool>("lockout")) {
|
||||
LOG(ERROR) << "Fail: lockout";
|
||||
cb->onLockoutPermanent();
|
||||
cb->onError(Error::HW_UNAVAILABLE, 0 /* vendorError */);
|
||||
return;
|
||||
}
|
||||
|
||||
if (FaceHalProperties::operation_authenticate_fails().value_or(false)) {
|
||||
if (Face::cfg().get<bool>("operation_authenticate_fails")) {
|
||||
LOG(ERROR) << "Fail: operation_authenticate_fails";
|
||||
mLockoutTracker.addFailedAttempt(cb);
|
||||
cb->onAuthenticationFailed();
|
||||
return;
|
||||
}
|
||||
|
||||
auto err = FaceHalProperties::operation_authenticate_error().value_or(0);
|
||||
auto err = Face::cfg().get<std::int32_t>("operation_authenticate_error");
|
||||
if (err != 0) {
|
||||
LOG(ERROR) << "Fail: operation_authenticate_error";
|
||||
auto ec = convertError(err);
|
||||
@@ -249,6 +255,15 @@ void FakeFaceEngine::authenticateImpl(ISessionCallback* cb, int64_t /*operationI
|
||||
LOG(INFO) << "AcquiredInfo:" << i << ": (" << (int)ac.first << "," << (int)ac.second
|
||||
<< ")";
|
||||
i++;
|
||||
|
||||
// the captured face id may change during authentication period
|
||||
auto idnew = Face::cfg().get<std::int32_t>("enrollment_hit");
|
||||
if (id != idnew) {
|
||||
isEnrolled = std::find(enrolls.begin(), enrolls.end(), idnew) != enrolls.end();
|
||||
LOG(INFO) << "enrollment_hit changed from " << id << " to " << idnew;
|
||||
id = idnew;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
SLEEP_MS(duration / N);
|
||||
@@ -292,9 +307,9 @@ std::pair<Error, int32_t> FakeFaceEngine::convertError(int32_t code) {
|
||||
}
|
||||
|
||||
void FakeFaceEngine::detectInteractionImpl(ISessionCallback* cb, const std::future<void>& cancel) {
|
||||
BEGIN_OP(getLatency(FaceHalProperties::operation_detect_interaction_latency()));
|
||||
BEGIN_OP(getLatency(Face::cfg().getopt<OptIntVec>("operation_detect_interaction_latency")));
|
||||
|
||||
if (FaceHalProperties::operation_detect_interaction_fails().value_or(false)) {
|
||||
if (Face::cfg().get<bool>("operation_detect_interaction_fails")) {
|
||||
LOG(ERROR) << "Fail: operation_detect_interaction_fails";
|
||||
cb->onError(Error::VENDOR, 0 /* vendorError */);
|
||||
return;
|
||||
@@ -306,8 +321,8 @@ void FakeFaceEngine::detectInteractionImpl(ISessionCallback* cb, const std::futu
|
||||
return;
|
||||
}
|
||||
|
||||
auto id = FaceHalProperties::enrollment_hit().value_or(0);
|
||||
auto enrolls = FaceHalProperties::enrollments();
|
||||
auto id = Face::cfg().get<std::int32_t>("enrollment_hit");
|
||||
auto enrolls = Face::cfg().getopt<OptIntVec>("enrollments");
|
||||
auto isEnrolled = std::find(enrolls.begin(), enrolls.end(), id) != enrolls.end();
|
||||
if (id <= 0 || !isEnrolled) {
|
||||
LOG(ERROR) << "Fail: not enrolled";
|
||||
@@ -321,7 +336,7 @@ void FakeFaceEngine::detectInteractionImpl(ISessionCallback* cb, const std::futu
|
||||
void FakeFaceEngine::enumerateEnrollmentsImpl(ISessionCallback* cb) {
|
||||
BEGIN_OP(0);
|
||||
std::vector<int32_t> enrollments;
|
||||
for (const auto& enrollmentId : FaceHalProperties::enrollments()) {
|
||||
for (const auto& enrollmentId : Face::cfg().getopt<OptIntVec>("enrollments")) {
|
||||
if (enrollmentId) {
|
||||
enrollments.push_back(*enrollmentId);
|
||||
}
|
||||
@@ -334,20 +349,20 @@ void FakeFaceEngine::removeEnrollmentsImpl(ISessionCallback* cb,
|
||||
BEGIN_OP(0);
|
||||
|
||||
std::vector<std::optional<int32_t>> newEnrollments;
|
||||
for (const auto& enrollment : FaceHalProperties::enrollments()) {
|
||||
for (const auto& enrollment : Face::cfg().getopt<OptIntVec>("enrollments")) {
|
||||
auto id = enrollment.value_or(0);
|
||||
if (std::find(enrollmentIds.begin(), enrollmentIds.end(), id) == enrollmentIds.end()) {
|
||||
newEnrollments.emplace_back(id);
|
||||
}
|
||||
}
|
||||
FaceHalProperties::enrollments(newEnrollments);
|
||||
Face::cfg().setopt<OptIntVec>("enrollments", newEnrollments);
|
||||
cb->onEnrollmentsRemoved(enrollmentIds);
|
||||
}
|
||||
|
||||
void FakeFaceEngine::getFeaturesImpl(ISessionCallback* cb) {
|
||||
BEGIN_OP(0);
|
||||
|
||||
if (FaceHalProperties::enrollments().empty()) {
|
||||
if (Face::cfg().getopt<OptIntVec>("enrollments").empty()) {
|
||||
cb->onError(Error::UNABLE_TO_PROCESS, 0 /* vendorCode */);
|
||||
return;
|
||||
}
|
||||
@@ -365,7 +380,7 @@ void FakeFaceEngine::setFeatureImpl(ISessionCallback* cb, const keymaster::Hardw
|
||||
Feature feature, bool enabled) {
|
||||
BEGIN_OP(0);
|
||||
|
||||
if (FaceHalProperties::enrollments().empty()) {
|
||||
if (Face::cfg().getopt<OptIntVec>("enrollments").empty()) {
|
||||
LOG(ERROR) << "Unable to set feature, enrollments are empty";
|
||||
cb->onError(Error::UNABLE_TO_PROCESS, 0 /* vendorCode */);
|
||||
return;
|
||||
@@ -377,7 +392,7 @@ void FakeFaceEngine::setFeatureImpl(ISessionCallback* cb, const keymaster::Hardw
|
||||
return;
|
||||
}
|
||||
|
||||
auto features = FaceHalProperties::features();
|
||||
auto features = Face::cfg().getopt<OptIntVec>("features");
|
||||
|
||||
auto itr = std::find_if(features.begin(), features.end(), [feature](const auto& theFeature) {
|
||||
return *theFeature == (int)feature;
|
||||
@@ -389,7 +404,7 @@ void FakeFaceEngine::setFeatureImpl(ISessionCallback* cb, const keymaster::Hardw
|
||||
features.push_back((int)feature);
|
||||
}
|
||||
|
||||
FaceHalProperties::features(features);
|
||||
Face::cfg().setopt<OptIntVec>("features", features);
|
||||
cb->onFeatureSet(feature);
|
||||
}
|
||||
|
||||
@@ -399,22 +414,22 @@ void FakeFaceEngine::getAuthenticatorIdImpl(ISessionCallback* cb) {
|
||||
if (GetSensorStrength() != common::SensorStrength::STRONG) {
|
||||
cb->onAuthenticatorIdRetrieved(0);
|
||||
} else {
|
||||
cb->onAuthenticatorIdRetrieved(FaceHalProperties::authenticator_id().value_or(0));
|
||||
cb->onAuthenticatorIdRetrieved(Face::cfg().get<std::int64_t>("authenticator_id"));
|
||||
}
|
||||
}
|
||||
|
||||
void FakeFaceEngine::invalidateAuthenticatorIdImpl(ISessionCallback* cb) {
|
||||
BEGIN_OP(0);
|
||||
int64_t authenticatorId = FaceHalProperties::authenticator_id().value_or(0);
|
||||
int64_t authenticatorId = Face::cfg().get<std::int64_t>("authenticator_id");
|
||||
int64_t newId = authenticatorId + 1;
|
||||
FaceHalProperties::authenticator_id(newId);
|
||||
Face::cfg().set<std::int64_t>("authenticator_id", newId);
|
||||
cb->onAuthenticatorIdInvalidated(newId);
|
||||
}
|
||||
|
||||
void FakeFaceEngine::resetLockoutImpl(ISessionCallback* cb,
|
||||
const keymaster::HardwareAuthToken& /*hat*/) {
|
||||
BEGIN_OP(0);
|
||||
FaceHalProperties::lockout(false);
|
||||
Face::cfg().set<bool>("lockout", false);
|
||||
mLockoutTracker.reset();
|
||||
cb->onLockoutCleared();
|
||||
}
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
#include "FakeLockoutTracker.h"
|
||||
#include <android-base/logging.h>
|
||||
#include <face.sysprop.h>
|
||||
#include "Face.h"
|
||||
#include "util/Util.h"
|
||||
|
||||
using namespace ::android::face::virt;
|
||||
@@ -36,15 +37,15 @@ void FakeLockoutTracker::reset(bool dueToTimerExpire) {
|
||||
}
|
||||
|
||||
void FakeLockoutTracker::addFailedAttempt(ISessionCallback* cb) {
|
||||
bool lockoutEnabled = FaceHalProperties::lockout_enable().value_or(false);
|
||||
bool timedLockoutenabled = FaceHalProperties::lockout_timed_enable().value_or(false);
|
||||
bool lockoutEnabled = Face::cfg().get<bool>("lockout_enable");
|
||||
bool timedLockoutenabled = Face::cfg().get<bool>("lockout_timed_enable");
|
||||
if (lockoutEnabled) {
|
||||
mFailedCount++;
|
||||
mTimedFailedCount++;
|
||||
mLastFailedTime = Util::getSystemNanoTime();
|
||||
int32_t lockoutTimedThreshold = FaceHalProperties::lockout_timed_threshold().value_or(3);
|
||||
int32_t lockoutTimedThreshold = Face::cfg().get<std::int32_t>("lockout_timed_threshold");
|
||||
int32_t lockoutPermanetThreshold =
|
||||
FaceHalProperties::lockout_permanent_threshold().value_or(5);
|
||||
Face::cfg().get<std::int32_t>("lockout_permanent_threshold");
|
||||
if (mFailedCount >= lockoutPermanetThreshold) {
|
||||
mCurrentMode = LockoutMode::kPermanent;
|
||||
LOG(ERROR) << "FakeLockoutTracker: lockoutPermanent";
|
||||
@@ -68,7 +69,7 @@ FakeLockoutTracker::LockoutMode FakeLockoutTracker::getMode() {
|
||||
}
|
||||
|
||||
int32_t FakeLockoutTracker::getTimedLockoutDuration() {
|
||||
return FaceHalProperties::lockout_timed_duration().value_or(10 * 1000);
|
||||
return Face::cfg().get<std::int32_t>("lockout_timed_duration");
|
||||
}
|
||||
|
||||
int64_t FakeLockoutTracker::getLockoutTimeLeft() {
|
||||
|
||||
275
biometrics/face/aidl/default/VirtualHal.cpp
Normal file
275
biometrics/face/aidl/default/VirtualHal.cpp
Normal file
@@ -0,0 +1,275 @@
|
||||
/*
|
||||
* Copyright (C) 2024 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.
|
||||
*/
|
||||
|
||||
#include <unordered_map>
|
||||
|
||||
#include "VirtualHal.h"
|
||||
|
||||
#include <android-base/logging.h>
|
||||
|
||||
#include "util/CancellationSignal.h"
|
||||
|
||||
#undef LOG_TAG
|
||||
#define LOG_TAG "FaceVirtualHalAidl"
|
||||
|
||||
namespace aidl::android::hardware::biometrics::face {
|
||||
using AcquiredInfoAndVendorCode = virtualhal::AcquiredInfoAndVendorCode;
|
||||
using Tag = AcquiredInfoAndVendorCode::Tag;
|
||||
|
||||
::ndk::ScopedAStatus VirtualHal::setEnrollments(const std::vector<int32_t>& enrollments) {
|
||||
Face::cfg().sourcedFromAidl();
|
||||
Face::cfg().setopt<OptIntVec>("enrollments", intVec2OptIntVec(enrollments));
|
||||
return ndk::ScopedAStatus::ok();
|
||||
}
|
||||
|
||||
::ndk::ScopedAStatus VirtualHal::setEnrollmentHit(int32_t enrollment_hit) {
|
||||
Face::cfg().sourcedFromAidl();
|
||||
Face::cfg().set<std::int32_t>("enrollment_hit", enrollment_hit);
|
||||
return ndk::ScopedAStatus::ok();
|
||||
}
|
||||
|
||||
::ndk::ScopedAStatus VirtualHal::setNextEnrollment(
|
||||
const ::aidl::android::hardware::biometrics::face::NextEnrollment& next_enrollment) {
|
||||
Face::cfg().sourcedFromAidl();
|
||||
std::ostringstream os;
|
||||
os << next_enrollment.id << ":";
|
||||
|
||||
int stepSize = next_enrollment.progressSteps.size();
|
||||
for (int i = 0; i < stepSize; i++) {
|
||||
auto& step = next_enrollment.progressSteps[i];
|
||||
os << step.durationMs;
|
||||
int acSize = step.acquiredInfoAndVendorCodes.size();
|
||||
for (int j = 0; j < acSize; j++) {
|
||||
if (j == 0) os << "-[";
|
||||
auto& acquiredInfoAndVendorCode = step.acquiredInfoAndVendorCodes[j];
|
||||
if (acquiredInfoAndVendorCode.getTag() == AcquiredInfoAndVendorCode::vendorCode)
|
||||
os << acquiredInfoAndVendorCode.get<Tag::vendorCode>();
|
||||
else if (acquiredInfoAndVendorCode.getTag() == AcquiredInfoAndVendorCode::acquiredInfo)
|
||||
os << (int)acquiredInfoAndVendorCode.get<Tag::acquiredInfo>();
|
||||
else
|
||||
LOG(FATAL) << "ERROR: wrong AcquiredInfoAndVendorCode union tag";
|
||||
if (j == acSize - 1)
|
||||
os << "]";
|
||||
else
|
||||
os << ",";
|
||||
}
|
||||
if (i == stepSize - 1)
|
||||
os << ":";
|
||||
else
|
||||
os << ",";
|
||||
}
|
||||
|
||||
os << (next_enrollment.result ? "true" : "false");
|
||||
Face::cfg().set<std::string>("next_enrollment", os.str());
|
||||
return ndk::ScopedAStatus::ok();
|
||||
}
|
||||
|
||||
::ndk::ScopedAStatus VirtualHal::setAuthenticatorId(int64_t in_id) {
|
||||
Face::cfg().sourcedFromAidl();
|
||||
Face::cfg().set<int64_t>("authenticator_id", in_id);
|
||||
return ndk::ScopedAStatus::ok();
|
||||
}
|
||||
|
||||
::ndk::ScopedAStatus VirtualHal::setChallenge(int64_t in_challenge) {
|
||||
Face::cfg().sourcedFromAidl();
|
||||
Face::cfg().set<int64_t>("challenge", in_challenge);
|
||||
return ndk::ScopedAStatus::ok();
|
||||
}
|
||||
|
||||
::ndk::ScopedAStatus VirtualHal::setOperationAuthenticateFails(bool in_fail) {
|
||||
Face::cfg().sourcedFromAidl();
|
||||
Face::cfg().set<bool>("operation_authenticate_fails", in_fail);
|
||||
return ndk::ScopedAStatus::ok();
|
||||
}
|
||||
|
||||
::ndk::ScopedAStatus VirtualHal::setOperationAuthenticateLatency(
|
||||
const std::vector<int32_t>& in_latency) {
|
||||
ndk::ScopedAStatus status = sanityCheckLatency(in_latency);
|
||||
if (!status.isOk()) {
|
||||
return status;
|
||||
}
|
||||
|
||||
Face::cfg().sourcedFromAidl();
|
||||
Face::cfg().setopt<OptIntVec>("operation_authenticate_latency", intVec2OptIntVec(in_latency));
|
||||
return ndk::ScopedAStatus::ok();
|
||||
}
|
||||
|
||||
::ndk::ScopedAStatus VirtualHal::setOperationAuthenticateDuration(int32_t in_duration) {
|
||||
if (in_duration < 0) {
|
||||
return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(
|
||||
IVirtualHal::STATUS_INVALID_PARAMETER, "Error: duration can not be negative"));
|
||||
}
|
||||
Face::cfg().sourcedFromAidl();
|
||||
Face::cfg().set<int32_t>("operation_authenticate_duration", in_duration);
|
||||
return ndk::ScopedAStatus::ok();
|
||||
}
|
||||
|
||||
::ndk::ScopedAStatus VirtualHal::setOperationAuthenticateError(int32_t in_error) {
|
||||
Face::cfg().sourcedFromAidl();
|
||||
Face::cfg().set<int32_t>("operation_authenticate_error", in_error);
|
||||
return ndk::ScopedAStatus::ok();
|
||||
}
|
||||
|
||||
::ndk::ScopedAStatus VirtualHal::setOperationAuthenticateAcquired(
|
||||
const std::vector<AcquiredInfoAndVendorCode>& in_acquired) {
|
||||
Face::cfg().sourcedFromAidl();
|
||||
Face::cfg().setopt<OptIntVec>("operation_authenticate_acquired",
|
||||
acquiredInfoVec2OptIntVec(in_acquired));
|
||||
return ndk::ScopedAStatus::ok();
|
||||
}
|
||||
|
||||
::ndk::ScopedAStatus VirtualHal::setOperationEnrollLatency(const std::vector<int32_t>& in_latency) {
|
||||
ndk::ScopedAStatus status = sanityCheckLatency(in_latency);
|
||||
if (!status.isOk()) {
|
||||
return status;
|
||||
}
|
||||
Face::cfg().sourcedFromAidl();
|
||||
Face::cfg().setopt<OptIntVec>("operation_enroll_latency", intVec2OptIntVec(in_latency));
|
||||
return ndk::ScopedAStatus::ok();
|
||||
}
|
||||
|
||||
::ndk::ScopedAStatus VirtualHal::setOperationDetectInteractionLatency(
|
||||
const std::vector<int32_t>& in_latency) {
|
||||
ndk::ScopedAStatus status = sanityCheckLatency(in_latency);
|
||||
if (!status.isOk()) {
|
||||
return status;
|
||||
}
|
||||
Face::cfg().sourcedFromAidl();
|
||||
Face::cfg().setopt<OptIntVec>("operation_detect_interact_latency",
|
||||
intVec2OptIntVec(in_latency));
|
||||
return ndk::ScopedAStatus::ok();
|
||||
}
|
||||
|
||||
::ndk::ScopedAStatus VirtualHal::setOperationDetectInteractionFails(bool in_fails) {
|
||||
Face::cfg().sourcedFromAidl();
|
||||
Face::cfg().set<bool>("operation_detect_interaction_fails", in_fails);
|
||||
return ndk::ScopedAStatus::ok();
|
||||
}
|
||||
|
||||
::ndk::ScopedAStatus VirtualHal::setLockout(bool in_lockout) {
|
||||
Face::cfg().sourcedFromAidl();
|
||||
Face::cfg().set<bool>("lockout", in_lockout);
|
||||
return ndk::ScopedAStatus::ok();
|
||||
}
|
||||
|
||||
::ndk::ScopedAStatus VirtualHal::setLockoutEnable(bool in_enable) {
|
||||
Face::cfg().sourcedFromAidl();
|
||||
Face::cfg().set<bool>("lockout_enable", in_enable);
|
||||
return ndk::ScopedAStatus::ok();
|
||||
}
|
||||
|
||||
::ndk::ScopedAStatus VirtualHal::setLockoutTimedEnable(bool in_enable) {
|
||||
Face::cfg().sourcedFromAidl();
|
||||
Face::cfg().set<bool>("lockout_timed_enable", in_enable);
|
||||
return ndk::ScopedAStatus::ok();
|
||||
}
|
||||
|
||||
::ndk::ScopedAStatus VirtualHal::setLockoutTimedThreshold(int32_t in_threshold) {
|
||||
if (in_threshold < 0) {
|
||||
return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(
|
||||
IVirtualHal::STATUS_INVALID_PARAMETER, "Error: threshold can not be negative"));
|
||||
}
|
||||
Face::cfg().sourcedFromAidl();
|
||||
Face::cfg().set<int32_t>("lockout_timed_threshold", in_threshold);
|
||||
return ndk::ScopedAStatus::ok();
|
||||
}
|
||||
|
||||
::ndk::ScopedAStatus VirtualHal::setLockoutTimedDuration(int32_t in_duration) {
|
||||
if (in_duration < 0) {
|
||||
return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(
|
||||
IVirtualHal::STATUS_INVALID_PARAMETER, "Error: duration can not be negative"));
|
||||
}
|
||||
Face::cfg().sourcedFromAidl();
|
||||
Face::cfg().set<int32_t>("lockout_timed_duration", in_duration);
|
||||
return ndk::ScopedAStatus::ok();
|
||||
}
|
||||
|
||||
::ndk::ScopedAStatus VirtualHal::setLockoutPermanentThreshold(int32_t in_threshold) {
|
||||
if (in_threshold < 0) {
|
||||
return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(
|
||||
IVirtualHal::STATUS_INVALID_PARAMETER, "Error: threshold can not be negative"));
|
||||
}
|
||||
Face::cfg().sourcedFromAidl();
|
||||
Face::cfg().set<int32_t>("lockout_permanent_threshold", in_threshold);
|
||||
return ndk::ScopedAStatus::ok();
|
||||
}
|
||||
|
||||
::ndk::ScopedAStatus VirtualHal::resetConfigurations() {
|
||||
Face::cfg().sourcedFromAidl();
|
||||
Face::cfg().init();
|
||||
return ndk::ScopedAStatus::ok();
|
||||
}
|
||||
|
||||
::ndk::ScopedAStatus VirtualHal::setType(
|
||||
::aidl::android::hardware::biometrics::face::FaceSensorType in_type) {
|
||||
Face::cfg().sourcedFromAidl();
|
||||
Face::cfg().set<std::string>("type", Face::type2String(in_type));
|
||||
return ndk::ScopedAStatus::ok();
|
||||
}
|
||||
|
||||
::ndk::ScopedAStatus VirtualHal::setSensorStrength(common::SensorStrength in_strength) {
|
||||
Face::cfg().sourcedFromAidl();
|
||||
Face::cfg().set<std::string>("strength", Face::strength2String(in_strength));
|
||||
return ndk::ScopedAStatus::ok();
|
||||
}
|
||||
|
||||
OptIntVec VirtualHal::intVec2OptIntVec(const std::vector<int32_t>& in_vec) {
|
||||
OptIntVec optIntVec;
|
||||
std::transform(in_vec.begin(), in_vec.end(), std::back_inserter(optIntVec),
|
||||
[](int value) { return std::optional<int>(value); });
|
||||
return optIntVec;
|
||||
}
|
||||
|
||||
OptIntVec VirtualHal::acquiredInfoVec2OptIntVec(
|
||||
const std::vector<AcquiredInfoAndVendorCode>& in_vec) {
|
||||
OptIntVec optIntVec;
|
||||
std::transform(in_vec.begin(), in_vec.end(), std::back_inserter(optIntVec),
|
||||
[](AcquiredInfoAndVendorCode ac) {
|
||||
int value;
|
||||
if (ac.getTag() == AcquiredInfoAndVendorCode::acquiredInfo)
|
||||
value = (int)ac.get<Tag::acquiredInfo>();
|
||||
else if (ac.getTag() == AcquiredInfoAndVendorCode::vendorCode)
|
||||
value = ac.get<Tag::vendorCode>();
|
||||
else
|
||||
LOG(FATAL) << "ERROR: wrong AcquiredInfoAndVendorCode tag";
|
||||
return std::optional<int>(value);
|
||||
});
|
||||
return optIntVec;
|
||||
}
|
||||
|
||||
::ndk::ScopedAStatus VirtualHal::sanityCheckLatency(const std::vector<int32_t>& in_latency) {
|
||||
if (in_latency.size() == 0 || in_latency.size() > 2) {
|
||||
return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(
|
||||
IVirtualHal::STATUS_INVALID_PARAMETER,
|
||||
"Error: input input array must contain 1 or 2 elements"));
|
||||
}
|
||||
|
||||
for (auto x : in_latency) {
|
||||
if (x < 0) {
|
||||
return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(
|
||||
IVirtualHal::STATUS_INVALID_PARAMETER,
|
||||
"Error: input data must not be negative"));
|
||||
}
|
||||
}
|
||||
|
||||
return ndk::ScopedAStatus::ok();
|
||||
}
|
||||
|
||||
::ndk::ScopedAStatus VirtualHal::getFaceHal(std::shared_ptr<IFace>* pFace) {
|
||||
*pFace = mFp;
|
||||
return ndk::ScopedAStatus::ok();
|
||||
}
|
||||
} // namespace aidl::android::hardware::biometrics::face
|
||||
66
biometrics/face/aidl/default/VirtualHal.h
Normal file
66
biometrics/face/aidl/default/VirtualHal.h
Normal file
@@ -0,0 +1,66 @@
|
||||
/*
|
||||
* Copyright (C) 2024 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.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <aidl/android/hardware/biometrics/face/virtualhal/BnVirtualHal.h>
|
||||
|
||||
#include "Face.h"
|
||||
|
||||
namespace aidl::android::hardware::biometrics::face {
|
||||
using namespace virtualhal;
|
||||
class VirtualHal : public BnVirtualHal {
|
||||
public:
|
||||
VirtualHal(std::shared_ptr<Face> fp) : mFp(fp) {}
|
||||
|
||||
::ndk::ScopedAStatus setEnrollments(const std::vector<int32_t>& in_id) override;
|
||||
::ndk::ScopedAStatus setEnrollmentHit(int32_t in_hit_id) override;
|
||||
::ndk::ScopedAStatus setNextEnrollment(
|
||||
const ::aidl::android::hardware::biometrics::face::NextEnrollment& in_next_enrollment)
|
||||
override;
|
||||
::ndk::ScopedAStatus setAuthenticatorId(int64_t in_id) override;
|
||||
::ndk::ScopedAStatus setChallenge(int64_t in_challenge) override;
|
||||
::ndk::ScopedAStatus setOperationAuthenticateFails(bool in_fail) override;
|
||||
::ndk::ScopedAStatus setOperationAuthenticateLatency(
|
||||
const std::vector<int32_t>& in_latency) override;
|
||||
::ndk::ScopedAStatus setOperationAuthenticateDuration(int32_t in_duration) override;
|
||||
::ndk::ScopedAStatus setOperationAuthenticateError(int32_t in_error) override;
|
||||
::ndk::ScopedAStatus setOperationAuthenticateAcquired(
|
||||
const std::vector<AcquiredInfoAndVendorCode>& in_acquired) override;
|
||||
::ndk::ScopedAStatus setOperationEnrollLatency(const std::vector<int32_t>& in_latency) override;
|
||||
::ndk::ScopedAStatus setOperationDetectInteractionLatency(
|
||||
const std::vector<int32_t>& in_latency) override;
|
||||
::ndk::ScopedAStatus setOperationDetectInteractionFails(bool in_fails) override;
|
||||
::ndk::ScopedAStatus setLockout(bool in_lockout) override;
|
||||
::ndk::ScopedAStatus setLockoutEnable(bool in_enable) override;
|
||||
::ndk::ScopedAStatus setLockoutTimedEnable(bool in_enable) override;
|
||||
::ndk::ScopedAStatus setLockoutTimedThreshold(int32_t in_threshold) override;
|
||||
::ndk::ScopedAStatus setLockoutTimedDuration(int32_t in_duration) override;
|
||||
::ndk::ScopedAStatus setLockoutPermanentThreshold(int32_t in_threshold) override;
|
||||
::ndk::ScopedAStatus resetConfigurations() override;
|
||||
::ndk::ScopedAStatus setType(
|
||||
::aidl::android::hardware::biometrics::face::FaceSensorType in_type) override;
|
||||
::ndk::ScopedAStatus setSensorStrength(common::SensorStrength in_strength) override;
|
||||
::ndk::ScopedAStatus getFaceHal(std::shared_ptr<IFace>* _aidl_return);
|
||||
|
||||
private:
|
||||
OptIntVec intVec2OptIntVec(const std::vector<int32_t>& intVec);
|
||||
OptIntVec acquiredInfoVec2OptIntVec(const std::vector<AcquiredInfoAndVendorCode>& intVec);
|
||||
::ndk::ScopedAStatus sanityCheckLatency(const std::vector<int32_t>& in_latency);
|
||||
std::shared_ptr<Face> mFp;
|
||||
};
|
||||
|
||||
} // namespace aidl::android::hardware::biometrics::face
|
||||
@@ -23,7 +23,7 @@ apex {
|
||||
key: "com.android.hardware.key",
|
||||
certificate: ":com.android.hardware.certificate",
|
||||
updatable: false,
|
||||
vendor: true,
|
||||
system_ext_specific: true,
|
||||
|
||||
binaries: [
|
||||
// hal
|
||||
@@ -31,9 +31,7 @@ apex {
|
||||
],
|
||||
prebuilts: [
|
||||
// init_rc
|
||||
"face-example-apex.rc",
|
||||
// vintf_fragment
|
||||
"face-example-apex.xml",
|
||||
"face-virtual-apex.rc",
|
||||
],
|
||||
|
||||
overrides: [
|
||||
@@ -42,21 +40,7 @@ apex {
|
||||
}
|
||||
|
||||
prebuilt_etc {
|
||||
name: "face-example-apex.rc",
|
||||
src: ":gen-face-example-apex.rc",
|
||||
installable: false,
|
||||
}
|
||||
|
||||
genrule {
|
||||
name: "gen-face-example-apex.rc",
|
||||
srcs: [":face-example.rc"],
|
||||
out: ["face-example-apex.rc"],
|
||||
cmd: "sed -e 's@/vendor/bin/@/apex/com.android.hardware.biometrics.face.virtual/bin/@' $(in) > $(out)",
|
||||
}
|
||||
|
||||
prebuilt_etc {
|
||||
name: "face-example-apex.xml",
|
||||
src: ":face-example.xml",
|
||||
sub_dir: "vintf",
|
||||
name: "face-virtual-apex.rc",
|
||||
src: ":face-virtual.rc",
|
||||
installable: false,
|
||||
}
|
||||
|
||||
@@ -0,0 +1,133 @@
|
||||
props {
|
||||
owner: Vendor
|
||||
module: "android.face.virt.FaceHalProperties"
|
||||
prop {
|
||||
api_name: "authenticator_id"
|
||||
type: Long
|
||||
access: ReadWrite
|
||||
prop_name: "vendor.face.virtual.authenticator_id"
|
||||
}
|
||||
prop {
|
||||
api_name: "challenge"
|
||||
type: Long
|
||||
access: ReadWrite
|
||||
prop_name: "vendor.face.virtual.challenge"
|
||||
}
|
||||
prop {
|
||||
api_name: "enrollment_hit"
|
||||
type: Integer
|
||||
access: ReadWrite
|
||||
prop_name: "vendor.face.virtual.enrollment_hit"
|
||||
}
|
||||
prop {
|
||||
api_name: "enrollments"
|
||||
type: IntegerList
|
||||
access: ReadWrite
|
||||
prop_name: "persist.vendor.face.virtual.enrollments"
|
||||
}
|
||||
prop {
|
||||
api_name: "features"
|
||||
type: IntegerList
|
||||
access: ReadWrite
|
||||
prop_name: "persist.vendor.face.virtual.features"
|
||||
}
|
||||
prop {
|
||||
api_name: "lockout"
|
||||
access: ReadWrite
|
||||
prop_name: "vendor.face.virtual.lockout"
|
||||
}
|
||||
prop {
|
||||
api_name: "lockout_enable"
|
||||
access: ReadWrite
|
||||
prop_name: "persist.vendor.face.virtual.lockout_enable"
|
||||
}
|
||||
prop {
|
||||
api_name: "lockout_permanent_threshold"
|
||||
type: Integer
|
||||
access: ReadWrite
|
||||
prop_name: "persist.vendor.face.virtual.lockout_permanent_threshold"
|
||||
}
|
||||
prop {
|
||||
api_name: "lockout_timed_duration"
|
||||
type: Integer
|
||||
access: ReadWrite
|
||||
prop_name: "persist.vendor.face.virtual.lockout_timed_duration"
|
||||
}
|
||||
prop {
|
||||
api_name: "lockout_timed_enable"
|
||||
access: ReadWrite
|
||||
prop_name: "persist.vendor.face.virtual.lockout_timed_enable"
|
||||
}
|
||||
prop {
|
||||
api_name: "lockout_timed_threshold"
|
||||
type: Integer
|
||||
access: ReadWrite
|
||||
prop_name: "persist.vendor.face.virtual.lockout_timed_threshold"
|
||||
}
|
||||
prop {
|
||||
api_name: "next_enrollment"
|
||||
type: String
|
||||
access: ReadWrite
|
||||
prop_name: "vendor.face.virtual.next_enrollment"
|
||||
}
|
||||
prop {
|
||||
api_name: "operation_authenticate_acquired"
|
||||
type: String
|
||||
access: ReadWrite
|
||||
prop_name: "vendor.face.virtual.operation_authenticate_acquired"
|
||||
}
|
||||
prop {
|
||||
api_name: "operation_authenticate_duration"
|
||||
type: Integer
|
||||
access: ReadWrite
|
||||
prop_name: "vendor.face.virtual.operation_authenticate_duration"
|
||||
}
|
||||
prop {
|
||||
api_name: "operation_authenticate_error"
|
||||
type: Integer
|
||||
access: ReadWrite
|
||||
prop_name: "vendor.face.virtual.operation_authenticate_error"
|
||||
}
|
||||
prop {
|
||||
api_name: "operation_authenticate_fails"
|
||||
access: ReadWrite
|
||||
prop_name: "vendor.face.virtual.operation_authenticate_fails"
|
||||
}
|
||||
prop {
|
||||
api_name: "operation_authenticate_latency"
|
||||
type: IntegerList
|
||||
access: ReadWrite
|
||||
prop_name: "vendor.face.virtual.operation_authenticate_latency"
|
||||
}
|
||||
prop {
|
||||
api_name: "operation_detect_interaction_fails"
|
||||
access: ReadWrite
|
||||
prop_name: "vendor.face.virtual.operation_detect_interaction_fails"
|
||||
}
|
||||
prop {
|
||||
api_name: "operation_detect_interaction_latency"
|
||||
type: IntegerList
|
||||
access: ReadWrite
|
||||
prop_name: "vendor.face.virtual.operation_detect_interaction_latency"
|
||||
}
|
||||
prop {
|
||||
api_name: "operation_enroll_latency"
|
||||
type: IntegerList
|
||||
access: ReadWrite
|
||||
prop_name: "vendor.face.virtual.operation_enroll_latency"
|
||||
}
|
||||
prop {
|
||||
api_name: "strength"
|
||||
type: String
|
||||
access: ReadWrite
|
||||
prop_name: "persist.vendor.face.virtual.strength"
|
||||
enum_values: "convenience|weak|strong"
|
||||
}
|
||||
prop {
|
||||
api_name: "type"
|
||||
type: String
|
||||
access: ReadWrite
|
||||
prop_name: "persist.vendor.face.virtual.type"
|
||||
enum_values: "IR|RGB"
|
||||
}
|
||||
}
|
||||
|
||||
8
biometrics/face/aidl/default/face-default.rc
Normal file
8
biometrics/face/aidl/default/face-default.rc
Normal file
@@ -0,0 +1,8 @@
|
||||
service vendor.face-default /vendor/bin/hw/android.hardware.biometrics.face-service.default default
|
||||
class hal
|
||||
user nobody
|
||||
group nobody
|
||||
interface aidl android.hardware.biometrics.face.IFace/default
|
||||
oneshot
|
||||
disabled
|
||||
|
||||
@@ -2,6 +2,6 @@
|
||||
<hal format="aidl">
|
||||
<name>android.hardware.biometrics.face</name>
|
||||
<version>4</version>
|
||||
<fqname>IFace/virtual</fqname>
|
||||
<fqname>IFace/default</fqname>
|
||||
</hal>
|
||||
</manifest>
|
||||
@@ -1,8 +0,0 @@
|
||||
service vendor.face-example /vendor/bin/hw/android.hardware.biometrics.face-service.example
|
||||
class hal
|
||||
user nobody
|
||||
group nobody
|
||||
interface aidl android.hardware.biometrics.face.IFace/virtual
|
||||
oneshot
|
||||
disabled
|
||||
|
||||
8
biometrics/face/aidl/default/face-virtual.rc
Normal file
8
biometrics/face/aidl/default/face-virtual.rc
Normal file
@@ -0,0 +1,8 @@
|
||||
service face-virtual /apex/com.android.hardware.biometrics.face.virtual/bin/hw/android.hardware.biometrics.face-service.example virtual
|
||||
class hal
|
||||
user nobody
|
||||
group nobody
|
||||
interface aidl android.hardware.biometrics.face.virtualhal.IVirtualHal/virtual
|
||||
oneshot
|
||||
disabled
|
||||
|
||||
@@ -7,7 +7,7 @@ owner: Vendor
|
||||
prop {
|
||||
prop_name: "persist.vendor.face.virtual.type"
|
||||
type: String
|
||||
scope: Internal
|
||||
scope: Public
|
||||
access: ReadWrite
|
||||
enum_values: "IR|RGB"
|
||||
api_name: "type"
|
||||
@@ -17,7 +17,7 @@ prop {
|
||||
prop {
|
||||
prop_name: "persist.vendor.face.virtual.strength"
|
||||
type: String
|
||||
scope: Internal
|
||||
scope: Public
|
||||
access: ReadWrite
|
||||
enum_values: "convenience|weak|strong"
|
||||
api_name: "strength"
|
||||
@@ -27,7 +27,7 @@ prop {
|
||||
prop {
|
||||
prop_name: "persist.vendor.face.virtual.enrollments"
|
||||
type: IntegerList
|
||||
scope: Internal
|
||||
scope: Public
|
||||
access: ReadWrite
|
||||
api_name: "enrollments"
|
||||
}
|
||||
@@ -36,7 +36,7 @@ prop {
|
||||
prop {
|
||||
prop_name: "persist.vendor.face.virtual.features"
|
||||
type: IntegerList
|
||||
scope: Internal
|
||||
scope: Public
|
||||
access: ReadWrite
|
||||
api_name: "features"
|
||||
}
|
||||
@@ -46,7 +46,7 @@ prop {
|
||||
prop {
|
||||
prop_name: "vendor.face.virtual.enrollment_hit"
|
||||
type: Integer
|
||||
scope: Internal
|
||||
scope: Public
|
||||
access: ReadWrite
|
||||
api_name: "enrollment_hit"
|
||||
}
|
||||
@@ -60,7 +60,7 @@ prop {
|
||||
prop {
|
||||
prop_name: "vendor.face.virtual.next_enrollment"
|
||||
type: String
|
||||
scope: Internal
|
||||
scope: Public
|
||||
access: ReadWrite
|
||||
api_name: "next_enrollment"
|
||||
}
|
||||
@@ -69,7 +69,7 @@ prop {
|
||||
prop {
|
||||
prop_name: "vendor.face.virtual.authenticator_id"
|
||||
type: Long
|
||||
scope: Internal
|
||||
scope: Public
|
||||
access: ReadWrite
|
||||
api_name: "authenticator_id"
|
||||
}
|
||||
@@ -78,7 +78,7 @@ prop {
|
||||
prop {
|
||||
prop_name: "vendor.face.virtual.challenge"
|
||||
type: Long
|
||||
scope: Internal
|
||||
scope: Public
|
||||
access: ReadWrite
|
||||
api_name: "challenge"
|
||||
}
|
||||
@@ -87,7 +87,7 @@ prop {
|
||||
prop {
|
||||
prop_name: "vendor.face.virtual.lockout"
|
||||
type: Boolean
|
||||
scope: Internal
|
||||
scope: Public
|
||||
access: ReadWrite
|
||||
api_name: "lockout"
|
||||
}
|
||||
@@ -96,7 +96,7 @@ prop {
|
||||
prop {
|
||||
prop_name: "vendor.face.virtual.operation_authenticate_fails"
|
||||
type: Boolean
|
||||
scope: Internal
|
||||
scope: Public
|
||||
access: ReadWrite
|
||||
api_name: "operation_authenticate_fails"
|
||||
}
|
||||
@@ -105,27 +105,18 @@ prop {
|
||||
prop {
|
||||
prop_name: "vendor.face.virtual.operation_detect_interaction_fails"
|
||||
type: Boolean
|
||||
scope: Internal
|
||||
scope: Public
|
||||
access: ReadWrite
|
||||
api_name: "operation_detect_interaction_fails"
|
||||
}
|
||||
|
||||
# force all enroll operations to fail
|
||||
prop {
|
||||
prop_name: "vendor.face.virtual.operation_enroll_fails"
|
||||
type: Boolean
|
||||
scope: Internal
|
||||
access: ReadWrite
|
||||
api_name: "operation_enroll_fails"
|
||||
}
|
||||
|
||||
# add a latency to authentication operations
|
||||
# Note that this latency is the initial authentication latency that occurs before
|
||||
# the HAL will send AcquiredInfo::START and AcquiredInfo::FIRST_FRAME_RECEIVED
|
||||
prop {
|
||||
prop_name: "vendor.face.virtual.operation_authenticate_latency"
|
||||
type: IntegerList
|
||||
scope: Internal
|
||||
scope: Public
|
||||
access: ReadWrite
|
||||
api_name: "operation_authenticate_latency"
|
||||
}
|
||||
@@ -134,7 +125,7 @@ prop {
|
||||
prop {
|
||||
prop_name: "vendor.face.virtual.operation_detect_interaction_latency"
|
||||
type: IntegerList
|
||||
scope: Internal
|
||||
scope: Public
|
||||
access: ReadWrite
|
||||
api_name: "operation_detect_interaction_latency"
|
||||
}
|
||||
@@ -143,7 +134,7 @@ prop {
|
||||
prop {
|
||||
prop_name: "vendor.face.virtual.operation_enroll_latency"
|
||||
type: IntegerList
|
||||
scope: Internal
|
||||
scope: Public
|
||||
access: ReadWrite
|
||||
api_name: "operation_enroll_latency"
|
||||
}
|
||||
@@ -153,7 +144,7 @@ prop {
|
||||
prop {
|
||||
prop_name: "vendor.face.virtual.operation_authenticate_duration"
|
||||
type: Integer
|
||||
scope: Internal
|
||||
scope: Public
|
||||
access: ReadWrite
|
||||
api_name: "operation_authenticate_duration"
|
||||
}
|
||||
@@ -162,7 +153,7 @@ prop {
|
||||
prop {
|
||||
prop_name: "vendor.face.virtual.operation_authenticate_error"
|
||||
type: Integer
|
||||
scope: Internal
|
||||
scope: Public
|
||||
access: ReadWrite
|
||||
api_name: "operation_authenticate_error"
|
||||
}
|
||||
@@ -171,7 +162,7 @@ prop {
|
||||
prop {
|
||||
prop_name: "vendor.face.virtual.operation_authenticate_acquired"
|
||||
type: String
|
||||
scope: Internal
|
||||
scope: Public
|
||||
access: ReadWrite
|
||||
api_name: "operation_authenticate_acquired"
|
||||
}
|
||||
@@ -180,7 +171,7 @@ prop {
|
||||
prop {
|
||||
prop_name: "persist.vendor.face.virtual.lockout_enable"
|
||||
type: Boolean
|
||||
scope: Internal
|
||||
scope: Public
|
||||
access: ReadWrite
|
||||
api_name: "lockout_enable"
|
||||
}
|
||||
@@ -189,7 +180,7 @@ prop {
|
||||
prop {
|
||||
prop_name: "persist.vendor.face.virtual.lockout_timed_enable"
|
||||
type: Boolean
|
||||
scope: Internal
|
||||
scope: Public
|
||||
access: ReadWrite
|
||||
api_name: "lockout_timed_enable"
|
||||
}
|
||||
@@ -198,7 +189,7 @@ prop {
|
||||
prop {
|
||||
prop_name: "persist.vendor.face.virtual.lockout_timed_threshold"
|
||||
type: Integer
|
||||
scope: Internal
|
||||
scope: Public
|
||||
access: ReadWrite
|
||||
api_name: "lockout_timed_threshold"
|
||||
}
|
||||
@@ -207,7 +198,7 @@ prop {
|
||||
prop {
|
||||
prop_name: "persist.vendor.face.virtual.lockout_timed_duration"
|
||||
type: Integer
|
||||
scope: Internal
|
||||
scope: Public
|
||||
access: ReadWrite
|
||||
api_name: "lockout_timed_duration"
|
||||
}
|
||||
@@ -216,7 +207,7 @@ prop {
|
||||
prop {
|
||||
prop_name: "persist.vendor.face.virtual.lockout_permanent_threshold"
|
||||
type: Integer
|
||||
scope: Internal
|
||||
scope: Public
|
||||
access: ReadWrite
|
||||
api_name: "lockout_permanent_threshold"
|
||||
}
|
||||
|
||||
@@ -14,25 +14,49 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#undef LOG_TAG
|
||||
#define LOG_TAG "FaceVirtualHal"
|
||||
|
||||
#include "Face.h"
|
||||
#include "VirtualHal.h"
|
||||
|
||||
#include <android-base/logging.h>
|
||||
#include <android/binder_manager.h>
|
||||
#include <android/binder_process.h>
|
||||
|
||||
using aidl::android::hardware::biometrics::face::Face;
|
||||
using aidl::android::hardware::biometrics::face::VirtualHal;
|
||||
|
||||
int main() {
|
||||
LOG(INFO) << "Face HAL started";
|
||||
int main(int argc, char** argv) {
|
||||
if (argc < 2) {
|
||||
LOG(ERROR) << "Missing argument -> exiting, Valid arguments:[default|virtual]";
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
LOG(INFO) << "Face HAL started: " << argv[1];
|
||||
ABinderProcess_setThreadPoolMaxThreadCount(0);
|
||||
std::shared_ptr<Face> hal = ndk::SharedRefBase::make<Face>();
|
||||
std::shared_ptr<VirtualHal> hal_vhal = ndk::SharedRefBase::make<VirtualHal>(hal);
|
||||
|
||||
const std::string instance = std::string(Face::descriptor) + "/virtual";
|
||||
binder_status_t status =
|
||||
AServiceManager_registerLazyService(hal->asBinder().get(), instance.c_str());
|
||||
CHECK_EQ(status, STATUS_OK);
|
||||
if (strcmp(argv[1], "default") == 0) {
|
||||
const std::string instance = std::string(Face::descriptor) + "/default";
|
||||
auto binder = hal->asBinder();
|
||||
binder_status_t status =
|
||||
AServiceManager_registerLazyService(binder.get(), instance.c_str());
|
||||
CHECK_EQ(status, STATUS_OK);
|
||||
LOG(INFO) << "started IFace/default";
|
||||
} else if (strcmp(argv[1], "virtual") == 0) {
|
||||
const std::string instance = std::string(VirtualHal::descriptor) + "/virtual";
|
||||
auto binder = hal_vhal->asBinder();
|
||||
binder_status_t status =
|
||||
AServiceManager_registerLazyService(binder.get(), instance.c_str());
|
||||
CHECK_EQ(status, STATUS_OK);
|
||||
LOG(INFO) << "started IVirtualHal/virtual";
|
||||
} else {
|
||||
LOG(ERROR) << "Unexpected argument: " << argv[1];
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
AServiceManager_forceLazyServicesPersist(true);
|
||||
|
||||
ABinderProcess_joinThreadPool();
|
||||
return EXIT_FAILURE; // should not reach
|
||||
return EXIT_FAILURE; // should not reach here
|
||||
}
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
#include <aidl/android/hardware/biometrics/face/BnSessionCallback.h>
|
||||
#include <android-base/logging.h>
|
||||
|
||||
#include "Face.h"
|
||||
#include "FakeFaceEngine.h"
|
||||
#include "util/Util.h"
|
||||
|
||||
@@ -141,12 +142,12 @@ class FakeFaceEngineTest : public ::testing::Test {
|
||||
}
|
||||
|
||||
void TearDown() override {
|
||||
FaceHalProperties::enrollments({});
|
||||
FaceHalProperties::challenge({});
|
||||
FaceHalProperties::features({});
|
||||
FaceHalProperties::authenticator_id({});
|
||||
FaceHalProperties::strength("");
|
||||
FaceHalProperties::operation_detect_interaction_latency({});
|
||||
Face::cfg().setopt<OptIntVec>("enrollments", {});
|
||||
Face::cfg().set<std::int64_t>("challenge", 0);
|
||||
Face::cfg().setopt<OptIntVec>("features", {});
|
||||
Face::cfg().set<std::int64_t>("authenticator_id", 0);
|
||||
Face::cfg().set<std::string>("strength", "");
|
||||
Face::cfg().setopt<OptIntVec>("operation_detect_interaction_latency", {});
|
||||
}
|
||||
|
||||
FakeFaceEngine mEngine;
|
||||
@@ -160,81 +161,83 @@ TEST_F(FakeFaceEngineTest, one_eq_one) {
|
||||
|
||||
TEST_F(FakeFaceEngineTest, GenerateChallenge) {
|
||||
mEngine.generateChallengeImpl(mCallback.get());
|
||||
ASSERT_EQ(FaceHalProperties::challenge().value(), mCallback->mLastChallenge);
|
||||
ASSERT_EQ(Face::cfg().get<std::int64_t>("challenge"), mCallback->mLastChallenge);
|
||||
}
|
||||
|
||||
TEST_F(FakeFaceEngineTest, RevokeChallenge) {
|
||||
auto challenge = FaceHalProperties::challenge().value_or(10);
|
||||
auto challenge = Face::cfg().get<std::int64_t>("challenge");
|
||||
mEngine.revokeChallengeImpl(mCallback.get(), challenge);
|
||||
ASSERT_FALSE(FaceHalProperties::challenge().has_value());
|
||||
ASSERT_FALSE(Face::cfg().get<std::int64_t>("challenge"));
|
||||
ASSERT_EQ(challenge, mCallback->mLastChallengeRevoked);
|
||||
}
|
||||
|
||||
TEST_F(FakeFaceEngineTest, ResetLockout) {
|
||||
FaceHalProperties::lockout(true);
|
||||
Face::cfg().set<bool>("lockout", true);
|
||||
mEngine.resetLockoutImpl(mCallback.get(), {});
|
||||
ASSERT_FALSE(mCallback->mLockoutPermanent);
|
||||
ASSERT_FALSE(FaceHalProperties::lockout().value_or(true));
|
||||
ASSERT_FALSE(Face::cfg().get<bool>("lockout"));
|
||||
}
|
||||
|
||||
TEST_F(FakeFaceEngineTest, AuthenticatorId) {
|
||||
FaceHalProperties::authenticator_id(50);
|
||||
Face::cfg().set<std::int64_t>("authenticator_id", 50);
|
||||
mEngine.getAuthenticatorIdImpl(mCallback.get());
|
||||
ASSERT_EQ(50, mCallback->mLastAuthenticatorId);
|
||||
ASSERT_FALSE(mCallback->mAuthenticatorIdInvalidated);
|
||||
}
|
||||
|
||||
TEST_F(FakeFaceEngineTest, GetAuthenticatorIdWeakReturnsZero) {
|
||||
FaceHalProperties::strength("weak");
|
||||
FaceHalProperties::authenticator_id(500);
|
||||
Face::cfg().set<std::string>("strength", "weak");
|
||||
Face::cfg().set<std::int64_t>("authenticator_id", 500);
|
||||
mEngine.getAuthenticatorIdImpl(mCallback.get());
|
||||
ASSERT_EQ(0, mCallback->mLastAuthenticatorId);
|
||||
ASSERT_FALSE(mCallback->mAuthenticatorIdInvalidated);
|
||||
}
|
||||
|
||||
TEST_F(FakeFaceEngineTest, AuthenticatorIdInvalidate) {
|
||||
FaceHalProperties::authenticator_id(500);
|
||||
Face::cfg().set<std::int64_t>("authenticator_id", 500);
|
||||
mEngine.invalidateAuthenticatorIdImpl(mCallback.get());
|
||||
ASSERT_NE(500, FaceHalProperties::authenticator_id().value());
|
||||
ASSERT_NE(500, Face::cfg().get<std::int64_t>("authenticator_id"));
|
||||
ASSERT_TRUE(mCallback->mAuthenticatorIdInvalidated);
|
||||
}
|
||||
|
||||
TEST_F(FakeFaceEngineTest, Enroll) {
|
||||
FaceHalProperties::next_enrollment("1,0:1000-[21,5,6,7,1],1100-[1118,1108,1]:true");
|
||||
Face::cfg().set<std::string>("next_enrollment",
|
||||
"1,0:1000-[21,5,6,7,1],1100-[1118,1108,1]:true");
|
||||
keymaster::HardwareAuthToken hat{.mac = {2, 4}};
|
||||
mEngine.enrollImpl(mCallback.get(), hat, {} /*enrollmentType*/, {} /*features*/,
|
||||
mCancel.get_future());
|
||||
ASSERT_FALSE(FaceHalProperties::next_enrollment().has_value());
|
||||
ASSERT_EQ(1, FaceHalProperties::enrollments().size());
|
||||
ASSERT_EQ(1, FaceHalProperties::enrollments()[0].value());
|
||||
ASSERT_FALSE(Face::cfg().getopt<OptString>("next_enrollment").has_value());
|
||||
ASSERT_EQ(1, Face::cfg().getopt<OptIntVec>("enrollments").size());
|
||||
ASSERT_EQ(1, Face::cfg().getopt<OptIntVec>("enrollments")[0].value());
|
||||
ASSERT_EQ(1, mCallback->mLastEnrolled);
|
||||
ASSERT_EQ(0, mCallback->mRemaining);
|
||||
}
|
||||
|
||||
TEST_F(FakeFaceEngineTest, EnrollFails) {
|
||||
FaceHalProperties::next_enrollment("1,0:1000-[21,5,6,7,1],1100-[1118,1108,1]:false");
|
||||
Face::cfg().set<std::string>("next_enrollment",
|
||||
"1,0:1000-[21,5,6,7,1],1100-[1118,1108,1]:false");
|
||||
keymaster::HardwareAuthToken hat{.mac = {2, 4}};
|
||||
mEngine.enrollImpl(mCallback.get(), hat, {} /*enrollmentType*/, {} /*features*/,
|
||||
mCancel.get_future());
|
||||
ASSERT_FALSE(FaceHalProperties::next_enrollment().has_value());
|
||||
ASSERT_EQ(0, FaceHalProperties::enrollments().size());
|
||||
ASSERT_FALSE(Face::cfg().getopt<OptString>("next_enrollment").has_value());
|
||||
ASSERT_EQ(0, Face::cfg().getopt<OptIntVec>("enrollments").size());
|
||||
}
|
||||
|
||||
TEST_F(FakeFaceEngineTest, EnrollCancel) {
|
||||
FaceHalProperties::next_enrollment("1:2000-[21,8,9],300:false");
|
||||
Face::cfg().set<std::string>("next_enrollment", "1:2000-[21,8,9],300:false");
|
||||
keymaster::HardwareAuthToken hat{.mac = {2, 4}};
|
||||
mCancel.set_value();
|
||||
mEngine.enrollImpl(mCallback.get(), hat, {} /*enrollmentType*/, {} /*features*/,
|
||||
mCancel.get_future());
|
||||
ASSERT_EQ(Error::CANCELED, mCallback->mError);
|
||||
ASSERT_EQ(-1, mCallback->mLastEnrolled);
|
||||
ASSERT_EQ(0, FaceHalProperties::enrollments().size());
|
||||
ASSERT_TRUE(FaceHalProperties::next_enrollment().has_value());
|
||||
ASSERT_EQ(0, Face::cfg().getopt<OptIntVec>("enrollments").size());
|
||||
ASSERT_FALSE(Face::cfg().get<std::string>("next_enrollment").empty());
|
||||
}
|
||||
|
||||
TEST_F(FakeFaceEngineTest, Authenticate) {
|
||||
FaceHalProperties::enrollments({100});
|
||||
FaceHalProperties::enrollment_hit(100);
|
||||
Face::cfg().setopt<OptIntVec>("enrollments", {100});
|
||||
Face::cfg().set<std::int32_t>("enrollment_hit", 100);
|
||||
mEngine.authenticateImpl(mCallback.get(), 0 /* operationId*/, mCancel.get_future());
|
||||
|
||||
ASSERT_EQ(100, mCallback->mLastAuthenticated);
|
||||
@@ -242,32 +245,32 @@ TEST_F(FakeFaceEngineTest, Authenticate) {
|
||||
}
|
||||
|
||||
TEST_F(FakeFaceEngineTest, AuthenticateCancel) {
|
||||
FaceHalProperties::enrollments({100});
|
||||
FaceHalProperties::enrollment_hit(100);
|
||||
Face::cfg().setopt<OptIntVec>("enrollments", {100});
|
||||
Face::cfg().set<std::int32_t>("enrollment_hit", 100);
|
||||
mCancel.set_value();
|
||||
mEngine.authenticateImpl(mCallback.get(), 0 /* operationId*/, mCancel.get_future());
|
||||
ASSERT_EQ(Error::CANCELED, mCallback->mError);
|
||||
}
|
||||
|
||||
TEST_F(FakeFaceEngineTest, AuthenticateFailedForUnEnrolled) {
|
||||
FaceHalProperties::enrollments({3});
|
||||
FaceHalProperties::enrollment_hit(100);
|
||||
Face::cfg().setopt<OptIntVec>("enrollments", {3});
|
||||
Face::cfg().set<std::int32_t>("enrollment_hit", 100);
|
||||
mEngine.authenticateImpl(mCallback.get(), 0 /* operationId*/, mCancel.get_future());
|
||||
ASSERT_EQ(Error::TIMEOUT, mCallback->mError);
|
||||
ASSERT_TRUE(mCallback->mAuthenticateFailed);
|
||||
}
|
||||
|
||||
TEST_F(FakeFaceEngineTest, DetectInteraction) {
|
||||
FaceHalProperties::enrollments({100});
|
||||
FaceHalProperties::enrollment_hit(100);
|
||||
Face::cfg().setopt<OptIntVec>("enrollments", {100});
|
||||
Face::cfg().set<std::int32_t>("enrollment_hit", 100);
|
||||
ASSERT_EQ(0, mCallback->mInteractionDetectedCount);
|
||||
mEngine.detectInteractionImpl(mCallback.get(), mCancel.get_future());
|
||||
ASSERT_EQ(1, mCallback->mInteractionDetectedCount);
|
||||
}
|
||||
|
||||
TEST_F(FakeFaceEngineTest, DetectInteractionCancel) {
|
||||
FaceHalProperties::enrollments({100});
|
||||
FaceHalProperties::enrollment_hit(100);
|
||||
Face::cfg().setopt<OptIntVec>("enrollments", {100});
|
||||
Face::cfg().set<std::int32_t>("enrollment_hit", 100);
|
||||
mCancel.set_value();
|
||||
mEngine.detectInteractionImpl(mCallback.get(), mCancel.get_future());
|
||||
ASSERT_EQ(Error::CANCELED, mCallback->mError);
|
||||
@@ -279,7 +282,7 @@ TEST_F(FakeFaceEngineTest, GetFeatureEmpty) {
|
||||
}
|
||||
|
||||
TEST_F(FakeFaceEngineTest, SetFeature) {
|
||||
FaceHalProperties::enrollments({1});
|
||||
Face::cfg().setopt<OptIntVec>("enrollments", {1});
|
||||
keymaster::HardwareAuthToken hat{.mac = {2, 4}};
|
||||
mEngine.setFeatureImpl(mCallback.get(), hat, Feature::REQUIRE_ATTENTION, true);
|
||||
auto features = mCallback->mFeatures;
|
||||
@@ -294,7 +297,7 @@ TEST_F(FakeFaceEngineTest, SetFeature) {
|
||||
}
|
||||
|
||||
TEST_F(FakeFaceEngineTest, ToggleFeature) {
|
||||
FaceHalProperties::enrollments({1});
|
||||
Face::cfg().setopt<OptIntVec>("enrollments", {1});
|
||||
keymaster::HardwareAuthToken hat{.mac = {2, 4}};
|
||||
mEngine.setFeatureImpl(mCallback.get(), hat, Feature::REQUIRE_ATTENTION, true);
|
||||
mEngine.getFeaturesImpl(mCallback.get());
|
||||
@@ -310,7 +313,7 @@ TEST_F(FakeFaceEngineTest, ToggleFeature) {
|
||||
}
|
||||
|
||||
TEST_F(FakeFaceEngineTest, TurningOffNonExistentFeatureDoesNothing) {
|
||||
FaceHalProperties::enrollments({1});
|
||||
Face::cfg().setopt<OptIntVec>("enrollments", {1});
|
||||
keymaster::HardwareAuthToken hat{.mac = {2, 4}};
|
||||
mEngine.setFeatureImpl(mCallback.get(), hat, Feature::REQUIRE_ATTENTION, false);
|
||||
mEngine.getFeaturesImpl(mCallback.get());
|
||||
@@ -319,7 +322,7 @@ TEST_F(FakeFaceEngineTest, TurningOffNonExistentFeatureDoesNothing) {
|
||||
}
|
||||
|
||||
TEST_F(FakeFaceEngineTest, SetMultipleFeatures) {
|
||||
FaceHalProperties::enrollments({1});
|
||||
Face::cfg().setopt<OptIntVec>("enrollments", {1});
|
||||
keymaster::HardwareAuthToken hat{.mac = {2, 4}};
|
||||
mEngine.setFeatureImpl(mCallback.get(), hat, Feature::REQUIRE_ATTENTION, true);
|
||||
mEngine.setFeatureImpl(mCallback.get(), hat, Feature::REQUIRE_DIVERSE_POSES, true);
|
||||
@@ -335,7 +338,7 @@ TEST_F(FakeFaceEngineTest, SetMultipleFeatures) {
|
||||
}
|
||||
|
||||
TEST_F(FakeFaceEngineTest, SetMultipleFeaturesAndTurnOffSome) {
|
||||
FaceHalProperties::enrollments({1});
|
||||
Face::cfg().setopt<OptIntVec>("enrollments", {1});
|
||||
keymaster::HardwareAuthToken hat{.mac = {2, 4}};
|
||||
mEngine.setFeatureImpl(mCallback.get(), hat, Feature::REQUIRE_ATTENTION, true);
|
||||
mEngine.setFeatureImpl(mCallback.get(), hat, Feature::REQUIRE_DIVERSE_POSES, true);
|
||||
@@ -352,7 +355,7 @@ TEST_F(FakeFaceEngineTest, SetMultipleFeaturesAndTurnOffSome) {
|
||||
}
|
||||
|
||||
TEST_F(FakeFaceEngineTest, Enumerate) {
|
||||
FaceHalProperties::enrollments({120, 3});
|
||||
Face::cfg().setopt<OptIntVec>("enrollments", {120, 3});
|
||||
mEngine.enumerateEnrollmentsImpl(mCallback.get());
|
||||
auto enrolls = mCallback->mLastEnrollmentsEnumerated;
|
||||
ASSERT_FALSE(enrolls.empty());
|
||||
@@ -361,7 +364,7 @@ TEST_F(FakeFaceEngineTest, Enumerate) {
|
||||
}
|
||||
|
||||
TEST_F(FakeFaceEngineTest, RemoveEnrollments) {
|
||||
FaceHalProperties::enrollments({120, 3, 100});
|
||||
Face::cfg().setopt<OptIntVec>("enrollments", {120, 3, 100});
|
||||
mEngine.removeEnrollmentsImpl(mCallback.get(), {120, 100});
|
||||
mEngine.enumerateEnrollmentsImpl(mCallback.get());
|
||||
auto enrolls = mCallback->mLastEnrollmentsEnumerated;
|
||||
@@ -372,9 +375,9 @@ TEST_F(FakeFaceEngineTest, RemoveEnrollments) {
|
||||
}
|
||||
|
||||
TEST_F(FakeFaceEngineTest, ResetLockoutWithAuth) {
|
||||
FaceHalProperties::lockout(true);
|
||||
FaceHalProperties::enrollments({33});
|
||||
FaceHalProperties::enrollment_hit(33);
|
||||
Face::cfg().set<bool>("lockout", true);
|
||||
Face::cfg().setopt<OptIntVec>("enrollments", {33});
|
||||
Face::cfg().set<std::int32_t>("enrollment_hit", 33);
|
||||
auto cancelFuture = mCancel.get_future();
|
||||
mEngine.authenticateImpl(mCallback.get(), 0 /* operationId*/, cancelFuture);
|
||||
|
||||
@@ -382,28 +385,30 @@ TEST_F(FakeFaceEngineTest, ResetLockoutWithAuth) {
|
||||
|
||||
mEngine.resetLockoutImpl(mCallback.get(), {} /* hat */);
|
||||
ASSERT_FALSE(mCallback->mLockoutPermanent);
|
||||
FaceHalProperties::enrollment_hit(33);
|
||||
Face::cfg().set<std::int32_t>("enrollment_hit", 33);
|
||||
mEngine.authenticateImpl(mCallback.get(), 0 /* operationId*/, cancelFuture);
|
||||
ASSERT_EQ(33, mCallback->mLastAuthenticated);
|
||||
ASSERT_FALSE(mCallback->mAuthenticateFailed);
|
||||
}
|
||||
|
||||
TEST_F(FakeFaceEngineTest, LatencyDefault) {
|
||||
FaceHalProperties::operation_detect_interaction_latency({});
|
||||
ASSERT_EQ(DEFAULT_LATENCY,
|
||||
mEngine.getLatency(FaceHalProperties::operation_detect_interaction_latency()));
|
||||
Face::cfg().setopt<OptIntVec>("operation_detect_interaction_latency", {});
|
||||
ASSERT_EQ(DEFAULT_LATENCY, mEngine.getLatency(Face::cfg().getopt<OptIntVec>(
|
||||
"operation_detect_interaction_latency")));
|
||||
}
|
||||
|
||||
TEST_F(FakeFaceEngineTest, LatencyFixed) {
|
||||
FaceHalProperties::operation_detect_interaction_latency({10});
|
||||
ASSERT_EQ(10, mEngine.getLatency(FaceHalProperties::operation_detect_interaction_latency()));
|
||||
Face::cfg().setopt<OptIntVec>("operation_detect_interaction_latency", {10});
|
||||
ASSERT_EQ(10, mEngine.getLatency(
|
||||
Face::cfg().getopt<OptIntVec>("operation_detect_interaction_latency")));
|
||||
}
|
||||
|
||||
TEST_F(FakeFaceEngineTest, LatencyRandom) {
|
||||
FaceHalProperties::operation_detect_interaction_latency({1, 1000});
|
||||
Face::cfg().setopt<OptIntVec>("operation_detect_interaction_latency", {1, 1000});
|
||||
std::set<int32_t> latencySet;
|
||||
for (int i = 0; i < 100; i++) {
|
||||
auto x = mEngine.getLatency(FaceHalProperties::operation_detect_interaction_latency());
|
||||
auto x = mEngine.getLatency(
|
||||
Face::cfg().getopt<OptIntVec>("operation_detect_interaction_latency"));
|
||||
ASSERT_TRUE(x >= 1 && x <= 1000);
|
||||
latencySet.insert(x);
|
||||
}
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
|
||||
#include <android-base/logging.h>
|
||||
|
||||
#include "Face.h"
|
||||
#include "FakeLockoutTracker.h"
|
||||
#include "util/Util.h"
|
||||
|
||||
@@ -103,19 +104,21 @@ class FakeLockoutTrackerTest : public ::testing::Test {
|
||||
static constexpr int32_t LOCKOUT_TIMED_DURATION = 100;
|
||||
|
||||
void SetUp() override {
|
||||
FaceHalProperties::lockout_timed_threshold(LOCKOUT_TIMED_THRESHOLD);
|
||||
FaceHalProperties::lockout_timed_duration(LOCKOUT_TIMED_DURATION);
|
||||
FaceHalProperties::lockout_permanent_threshold(LOCKOUT_PERMANENT_THRESHOLD);
|
||||
Face::cfg().set<std::int32_t>("lockout_timed_threshold", LOCKOUT_TIMED_THRESHOLD);
|
||||
Face::cfg().set<std::int32_t>("lockout_timed_duration", LOCKOUT_TIMED_DURATION);
|
||||
Face::cfg().set<std::int32_t>("lockout_permanent_threshold", LOCKOUT_PERMANENT_THRESHOLD);
|
||||
Face::cfg().set<bool>("lockout_enable", false);
|
||||
Face::cfg().set<bool>("lockout", false);
|
||||
mCallback = ndk::SharedRefBase::make<TestSessionCallback>();
|
||||
}
|
||||
|
||||
void TearDown() override {
|
||||
// reset to default
|
||||
FaceHalProperties::lockout_timed_threshold(5);
|
||||
FaceHalProperties::lockout_timed_duration(20);
|
||||
FaceHalProperties::lockout_permanent_threshold(10000);
|
||||
FaceHalProperties::lockout_enable(false);
|
||||
FaceHalProperties::lockout(false);
|
||||
Face::cfg().set<std::int32_t>("lockout_timed_threshold", 5);
|
||||
Face::cfg().set<std::int32_t>("lockout_timed_duration", 20);
|
||||
Face::cfg().set<std::int32_t>("lockout_permanent_threshold", 10000);
|
||||
Face::cfg().set<bool>("lockout_enable", false);
|
||||
Face::cfg().set<bool>("lockout", false);
|
||||
}
|
||||
|
||||
FakeLockoutTracker mLockoutTracker;
|
||||
@@ -123,7 +126,7 @@ class FakeLockoutTrackerTest : public ::testing::Test {
|
||||
};
|
||||
|
||||
TEST_F(FakeLockoutTrackerTest, addFailedAttemptDisable) {
|
||||
FaceHalProperties::lockout_enable(false);
|
||||
Face::cfg().set<bool>("lockout_enable", false);
|
||||
for (int i = 0; i < LOCKOUT_TIMED_THRESHOLD + 1; i++)
|
||||
mLockoutTracker.addFailedAttempt(mCallback.get());
|
||||
ASSERT_EQ(mLockoutTracker.getMode(), FakeLockoutTracker::LockoutMode::kNone);
|
||||
@@ -131,7 +134,7 @@ TEST_F(FakeLockoutTrackerTest, addFailedAttemptDisable) {
|
||||
}
|
||||
|
||||
TEST_F(FakeLockoutTrackerTest, addFailedAttemptPermanent) {
|
||||
FaceHalProperties::lockout_enable(true);
|
||||
Face::cfg().set<bool>("lockout_enable", true);
|
||||
ASSERT_FALSE(mLockoutTracker.checkIfLockout(mCallback.get()));
|
||||
for (int i = 0; i < LOCKOUT_PERMANENT_THRESHOLD - 1; i++)
|
||||
mLockoutTracker.addFailedAttempt(mCallback.get());
|
||||
@@ -145,8 +148,8 @@ TEST_F(FakeLockoutTrackerTest, addFailedAttemptPermanent) {
|
||||
}
|
||||
|
||||
TEST_F(FakeLockoutTrackerTest, addFailedAttemptLockoutTimed) {
|
||||
FaceHalProperties::lockout_enable(true);
|
||||
FaceHalProperties::lockout_timed_enable(true);
|
||||
Face::cfg().set<bool>("lockout_enable", true);
|
||||
Face::cfg().set<bool>("lockout_timed_enable", true);
|
||||
ASSERT_FALSE(mLockoutTracker.checkIfLockout(mCallback.get()));
|
||||
for (int i = 0; i < LOCKOUT_TIMED_THRESHOLD; i++)
|
||||
mLockoutTracker.addFailedAttempt(mCallback.get());
|
||||
@@ -168,8 +171,8 @@ TEST_F(FakeLockoutTrackerTest, addFailedAttemptLockoutTimed) {
|
||||
}
|
||||
|
||||
TEST_F(FakeLockoutTrackerTest, addFailedAttemptLockout_TimedThenPermanent) {
|
||||
FaceHalProperties::lockout_enable(true);
|
||||
FaceHalProperties::lockout_timed_enable(true);
|
||||
Face::cfg().set<bool>("lockout_enable", true);
|
||||
Face::cfg().set<bool>("lockout_timed_enable", true);
|
||||
ASSERT_FALSE(mLockoutTracker.checkIfLockout(mCallback.get()));
|
||||
for (int i = 0; i < LOCKOUT_TIMED_THRESHOLD; i++)
|
||||
mLockoutTracker.addFailedAttempt(mCallback.get());
|
||||
@@ -182,8 +185,8 @@ TEST_F(FakeLockoutTrackerTest, addFailedAttemptLockout_TimedThenPermanent) {
|
||||
}
|
||||
|
||||
TEST_F(FakeLockoutTrackerTest, addFailedAttemptLockoutTimedTwice) {
|
||||
FaceHalProperties::lockout_enable(true);
|
||||
FaceHalProperties::lockout_timed_enable(true);
|
||||
Face::cfg().set<bool>("lockout_enable", true);
|
||||
Face::cfg().set<bool>("lockout_timed_enable", true);
|
||||
ASSERT_FALSE(mLockoutTracker.checkIfLockout(mCallback.get()));
|
||||
ASSERT_EQ(0, mCallback->mLockoutTimed);
|
||||
for (int i = 0; i < LOCKOUT_TIMED_THRESHOLD; i++)
|
||||
@@ -198,7 +201,7 @@ TEST_F(FakeLockoutTrackerTest, addFailedAttemptLockoutTimedTwice) {
|
||||
}
|
||||
|
||||
TEST_F(FakeLockoutTrackerTest, resetLockout) {
|
||||
FaceHalProperties::lockout_enable(true);
|
||||
Face::cfg().set<bool>("lockout_enable", true);
|
||||
ASSERT_EQ(mLockoutTracker.getMode(), FakeLockoutTracker::LockoutMode::kNone);
|
||||
for (int i = 0; i < LOCKOUT_PERMANENT_THRESHOLD; i++)
|
||||
mLockoutTracker.addFailedAttempt(mCallback.get());
|
||||
|
||||
237
biometrics/face/aidl/default/tests/VirtualHalTest.cpp
Normal file
237
biometrics/face/aidl/default/tests/VirtualHalTest.cpp
Normal file
@@ -0,0 +1,237 @@
|
||||
/*
|
||||
* Copyright (C) 2024 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.
|
||||
*/
|
||||
|
||||
#include <android/binder_process.h>
|
||||
#include <face.sysprop.h>
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include <android-base/logging.h>
|
||||
|
||||
#include "Face.h"
|
||||
#include "VirtualHal.h"
|
||||
|
||||
using namespace ::android::face::virt;
|
||||
using namespace ::aidl::android::hardware::biometrics::face;
|
||||
|
||||
namespace aidl::android::hardware::biometrics::face {
|
||||
|
||||
class VirtualHalTest : public ::testing::Test {
|
||||
public:
|
||||
static const int32_t STATUS_FAILED_TO_SET_PARAMETER = 2;
|
||||
|
||||
protected:
|
||||
void SetUp() override {
|
||||
mHal = ndk::SharedRefBase::make<Face>();
|
||||
mVhal = ndk::SharedRefBase::make<VirtualHal>(mHal);
|
||||
ASSERT_TRUE(mVhal != nullptr);
|
||||
mHal->resetConfigToDefault();
|
||||
}
|
||||
|
||||
void TearDown() override { mHal->resetConfigToDefault(); }
|
||||
|
||||
std::shared_ptr<VirtualHal> mVhal;
|
||||
|
||||
ndk::ScopedAStatus validateNonNegativeInputOfInt32(const char* name,
|
||||
ndk::ScopedAStatus (VirtualHal::*f)(int32_t),
|
||||
const std::vector<int32_t>& in_good);
|
||||
|
||||
private:
|
||||
std::shared_ptr<Face> mHal;
|
||||
};
|
||||
|
||||
ndk::ScopedAStatus VirtualHalTest::validateNonNegativeInputOfInt32(
|
||||
const char* name, ndk::ScopedAStatus (VirtualHal::*f)(int32_t),
|
||||
const std::vector<int32_t>& in_params_good) {
|
||||
ndk::ScopedAStatus status;
|
||||
for (auto& param : in_params_good) {
|
||||
status = (*mVhal.*f)(param);
|
||||
if (!status.isOk()) return status;
|
||||
if (Face::cfg().get<int32_t>(name) != param) {
|
||||
return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(
|
||||
VirtualHalTest::STATUS_FAILED_TO_SET_PARAMETER,
|
||||
"Error: fail to set non-negative parameter"));
|
||||
}
|
||||
}
|
||||
|
||||
int32_t old_param = Face::cfg().get<int32_t>(name);
|
||||
status = (*mVhal.*f)(-1);
|
||||
if (status.isOk()) {
|
||||
return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(
|
||||
VirtualHalTest::STATUS_FAILED_TO_SET_PARAMETER, "Error: should return NOK"));
|
||||
}
|
||||
if (status.getServiceSpecificError() != IVirtualHal::STATUS_INVALID_PARAMETER) {
|
||||
return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(
|
||||
VirtualHalTest::STATUS_FAILED_TO_SET_PARAMETER,
|
||||
"Error: unexpected return error code"));
|
||||
}
|
||||
if (Face::cfg().get<int32_t>(name) != old_param) {
|
||||
return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(
|
||||
VirtualHalTest::STATUS_FAILED_TO_SET_PARAMETER,
|
||||
"Error: unexpected parameter change on failed attempt"));
|
||||
}
|
||||
return ndk::ScopedAStatus::ok();
|
||||
}
|
||||
|
||||
TEST_F(VirtualHalTest, init) {
|
||||
mVhal->setLockout(false);
|
||||
ASSERT_TRUE(Face::cfg().get<bool>("lockout") == false);
|
||||
ASSERT_TRUE(Face::cfg().get<std::string>("type") == "rgb");
|
||||
ASSERT_TRUE(Face::cfg().get<std::string>("strength") == "strong");
|
||||
std::int64_t id = Face::cfg().get<std::int64_t>("authenticator_id");
|
||||
ASSERT_TRUE(Face::cfg().get<std::int64_t>("authenticator_id") == 0);
|
||||
ASSERT_TRUE(Face::cfg().getopt<OptIntVec>("enrollments") == OptIntVec());
|
||||
}
|
||||
|
||||
TEST_F(VirtualHalTest, enrollment_hit_int32) {
|
||||
mVhal->setEnrollmentHit(11);
|
||||
ASSERT_TRUE(Face::cfg().get<int32_t>("enrollment_hit") == 11);
|
||||
}
|
||||
|
||||
TEST_F(VirtualHalTest, next_enrollment) {
|
||||
struct {
|
||||
std::string nextEnrollmentStr;
|
||||
face::NextEnrollment nextEnrollment;
|
||||
} testData[] = {
|
||||
{"1:20:true", {1, {{20}}, true}},
|
||||
{"1:50,60,70:true", {1, {{50}, {60}, {70}}, true}},
|
||||
{"2:50-[21],60,70-[4,1002,1]:false",
|
||||
{2,
|
||||
{{50, {{AcquiredInfo::START}}},
|
||||
{60},
|
||||
{70, {{AcquiredInfo::TOO_DARK}, {1002}, {AcquiredInfo::GOOD}}}},
|
||||
false}},
|
||||
};
|
||||
|
||||
for (auto& d : testData) {
|
||||
mVhal->setNextEnrollment(d.nextEnrollment);
|
||||
ASSERT_TRUE(Face::cfg().get<std::string>("next_enrollment") == d.nextEnrollmentStr);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(VirtualHalTest, authenticator_id_int64) {
|
||||
mVhal->setAuthenticatorId(12345678900);
|
||||
ASSERT_TRUE(Face::cfg().get<int64_t>("authenticator_id") == 12345678900);
|
||||
}
|
||||
|
||||
TEST_F(VirtualHalTest, opeationAuthenticateFails_bool) {
|
||||
mVhal->setOperationAuthenticateFails(true);
|
||||
ASSERT_TRUE(Face::cfg().get<bool>("operation_authenticate_fails"));
|
||||
}
|
||||
|
||||
TEST_F(VirtualHalTest, operationAuthenticateAcquired_int32_vector) {
|
||||
using Tag = AcquiredInfoAndVendorCode::Tag;
|
||||
std::vector<AcquiredInfoAndVendorCode> ac{
|
||||
{AcquiredInfo::START}, {AcquiredInfo::TOO_FAR}, {1023}};
|
||||
mVhal->setOperationAuthenticateAcquired(ac);
|
||||
OptIntVec ac_get = Face::cfg().getopt<OptIntVec>("operation_authenticate_acquired");
|
||||
ASSERT_TRUE(ac_get.size() == ac.size());
|
||||
for (int i = 0; i < ac.size(); i++) {
|
||||
int acCode = (ac[i].getTag() == Tag::acquiredInfo) ? (int)ac[i].get<Tag::acquiredInfo>()
|
||||
: ac[i].get<Tag::vendorCode>();
|
||||
ASSERT_TRUE(acCode == ac_get[i]);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(VirtualHalTest, type) {
|
||||
struct {
|
||||
FaceSensorType type;
|
||||
const char* typeStr;
|
||||
} typeMap[] = {{FaceSensorType::RGB, "rgb"},
|
||||
{FaceSensorType::IR, "ir"},
|
||||
{FaceSensorType::UNKNOWN, "unknown"}};
|
||||
for (auto const& x : typeMap) {
|
||||
mVhal->setType(x.type);
|
||||
ASSERT_TRUE(Face::cfg().get<std::string>("type") == x.typeStr);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(VirtualHalTest, sensorStrength) {
|
||||
struct {
|
||||
common::SensorStrength strength;
|
||||
const char* strengthStr;
|
||||
} strengths[] = {{common::SensorStrength::CONVENIENCE, "CONVENIENCE"},
|
||||
{common::SensorStrength::WEAK, "WEAK"},
|
||||
{common::SensorStrength::STRONG, "STRONG"}};
|
||||
|
||||
for (auto const& x : strengths) {
|
||||
mVhal->setSensorStrength(x.strength);
|
||||
ASSERT_TRUE(Face::cfg().get<std::string>("strength") == x.strengthStr);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(VirtualHalTest, setLatency) {
|
||||
ndk::ScopedAStatus status;
|
||||
std::vector<int32_t> in_lats[] = {{1}, {2, 3}, {5, 4}};
|
||||
for (auto const& in_lat : in_lats) {
|
||||
status = mVhal->setOperationAuthenticateLatency(in_lat);
|
||||
ASSERT_TRUE(status.isOk());
|
||||
OptIntVec out_lat = Face::cfg().getopt<OptIntVec>("operation_authenticate_latency");
|
||||
ASSERT_TRUE(in_lat.size() == out_lat.size());
|
||||
for (int i = 0; i < in_lat.size(); i++) {
|
||||
ASSERT_TRUE(in_lat[i] == out_lat[i]);
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<int32_t> bad_in_lats[] = {{}, {1, 2, 3}, {1, -3}};
|
||||
for (auto const& in_lat : bad_in_lats) {
|
||||
status = mVhal->setOperationAuthenticateLatency(in_lat);
|
||||
ASSERT_TRUE(!status.isOk());
|
||||
ASSERT_TRUE(status.getServiceSpecificError() == IVirtualHal::STATUS_INVALID_PARAMETER);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(VirtualHalTest, setOperationAuthenticateDuration) {
|
||||
ndk::ScopedAStatus status = validateNonNegativeInputOfInt32(
|
||||
"operation_authenticate_duration", &IVirtualHal::setOperationAuthenticateDuration,
|
||||
{0, 33});
|
||||
ASSERT_TRUE(status.isOk());
|
||||
}
|
||||
|
||||
TEST_F(VirtualHalTest, setLockoutTimedDuration) {
|
||||
ndk::ScopedAStatus status = validateNonNegativeInputOfInt32(
|
||||
"lockout_timed_duration", &IVirtualHal::setLockoutTimedDuration, {0, 35});
|
||||
ASSERT_TRUE(status.isOk());
|
||||
}
|
||||
|
||||
TEST_F(VirtualHalTest, setLockoutTimedThreshold) {
|
||||
ndk::ScopedAStatus status = validateNonNegativeInputOfInt32(
|
||||
"lockout_timed_threshold", &IVirtualHal::setLockoutTimedThreshold, {0, 36});
|
||||
ASSERT_TRUE(status.isOk());
|
||||
}
|
||||
|
||||
TEST_F(VirtualHalTest, setLockoutPermanentThreshold) {
|
||||
ndk::ScopedAStatus status = validateNonNegativeInputOfInt32(
|
||||
"lockout_permanent_threshold", &IVirtualHal::setLockoutPermanentThreshold, {0, 37});
|
||||
ASSERT_TRUE(status.isOk());
|
||||
}
|
||||
|
||||
TEST_F(VirtualHalTest, setOthers) {
|
||||
// Verify that there is no CHECK() failures
|
||||
mVhal->setEnrollments({7, 6, 5});
|
||||
mVhal->setChallenge(111222333444555666);
|
||||
mVhal->setOperationAuthenticateError(4);
|
||||
mVhal->setOperationEnrollLatency({4, 5});
|
||||
mVhal->setLockout(false);
|
||||
mVhal->setLockoutEnable(false);
|
||||
}
|
||||
|
||||
} // namespace aidl::android::hardware::biometrics::face
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
testing::InitGoogleTest(&argc, argv);
|
||||
ABinderProcess_startThreadPool();
|
||||
return RUN_ALL_TESTS();
|
||||
}
|
||||
@@ -20,6 +20,7 @@ aidl_interface {
|
||||
},
|
||||
ndk: {
|
||||
apex_available: [
|
||||
"com.android.hardware.biometrics.face.virtual",
|
||||
"com.android.hardware.biometrics.fingerprint.virtual",
|
||||
"//apex_available:platform",
|
||||
],
|
||||
|
||||
Reference in New Issue
Block a user