xref: /aosp_15_r20/hardware/interfaces/biometrics/face/aidl/default/FakeLockoutTracker.cpp (revision 4d7e907c777eeecc4c5bd7cf640a754fac206ff7)
1 /*
2  * Copyright (C) 2023 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #define LOG_TAG "FaceVirtualHalLockoutTracker"
18 
19 #include "FakeLockoutTracker.h"
20 #include <android-base/logging.h>
21 #include <face.sysprop.h>
22 #include "Face.h"
23 #include "util/Util.h"
24 
25 using namespace ::android::face::virt;
26 
27 namespace aidl::android::hardware::biometrics::face {
28 
reset(bool dueToTimerExpire)29 void FakeLockoutTracker::reset(bool dueToTimerExpire) {
30     if (!dueToTimerExpire) {
31         mFailedCount = 0;
32         mLastFailedTime = 0;
33     }
34     mTimedFailedCount = 0;
35     mCurrentMode = LockoutMode::kNone;
36     abortTimer();
37 }
38 
addFailedAttempt(ISessionCallback * cb)39 void FakeLockoutTracker::addFailedAttempt(ISessionCallback* cb) {
40     bool lockoutEnabled = Face::cfg().get<bool>("lockout_enable");
41     bool timedLockoutenabled = Face::cfg().get<bool>("lockout_timed_enable");
42     if (lockoutEnabled) {
43         mFailedCount++;
44         mTimedFailedCount++;
45         mLastFailedTime = Util::getSystemNanoTime();
46         int32_t lockoutTimedThreshold = Face::cfg().get<std::int32_t>("lockout_timed_threshold");
47         int32_t lockoutPermanetThreshold =
48                 Face::cfg().get<std::int32_t>("lockout_permanent_threshold");
49         if (mFailedCount >= lockoutPermanetThreshold) {
50             mCurrentMode = LockoutMode::kPermanent;
51             LOG(ERROR) << "FakeLockoutTracker: lockoutPermanent";
52             cb->onLockoutPermanent();
53             abortTimer();
54         } else if (timedLockoutenabled && mTimedFailedCount >= lockoutTimedThreshold) {
55             if (mCurrentMode == LockoutMode::kNone) {
56                 mCurrentMode = LockoutMode::kTimed;
57                 startLockoutTimer(getTimedLockoutDuration(), cb);
58             }
59             LOG(ERROR) << "FakeLockoutTracker: lockoutTimed";
60             cb->onLockoutTimed(getLockoutTimeLeft());
61         }
62     } else {
63         reset();
64     }
65 }
66 
getMode()67 FakeLockoutTracker::LockoutMode FakeLockoutTracker::getMode() {
68     return mCurrentMode;
69 }
70 
getTimedLockoutDuration()71 int32_t FakeLockoutTracker::getTimedLockoutDuration() {
72     return Face::cfg().get<std::int32_t>("lockout_timed_duration");
73 }
74 
getLockoutTimeLeft()75 int64_t FakeLockoutTracker::getLockoutTimeLeft() {
76     int64_t res = 0;
77 
78     if (mLastFailedTime > 0) {
79         auto now = Util::getSystemNanoTime();
80         auto elapsed = (now - mLastFailedTime) / 1000000LL;
81         res = getTimedLockoutDuration() - elapsed;
82         LOG(INFO) << "elapsed=" << elapsed << " now = " << now
83                   << " mLastFailedTime=" << mLastFailedTime << " res=" << res;
84     }
85 
86     return res;
87 }
88 
checkIfLockout(ISessionCallback * cb)89 bool FakeLockoutTracker::checkIfLockout(ISessionCallback* cb) {
90     if (mCurrentMode == LockoutMode::kPermanent) {
91         LOG(ERROR) << "Lockout permanent";
92         cb->onLockoutPermanent();
93         return true;
94     } else if (mCurrentMode == LockoutMode::kTimed) {
95         auto timeLeft = getLockoutTimeLeft();
96         LOG(ERROR) << "Lockout timed " << timeLeft;
97         cb->onLockoutTimed(timeLeft);
98         return true;
99     }
100     return false;
101 }
102 
startLockoutTimer(int64_t timeout,ISessionCallback * cb)103 void FakeLockoutTracker::startLockoutTimer(int64_t timeout, ISessionCallback* cb) {
104     LOG(ERROR) << "startLockoutTimer: to=" << timeout;
105     if (mIsLockoutTimerStarted) return;
106     std::function<void(ISessionCallback*)> action =
107             std::bind(&FakeLockoutTracker::lockoutTimerExpired, this, std::placeholders::_1);
108     std::thread([timeout, action, cb]() {
109         std::this_thread::sleep_for(std::chrono::milliseconds(timeout));
110         action(cb);
111     }).detach();
112 
113     mIsLockoutTimerStarted = true;
114 }
115 
lockoutTimerExpired(ISessionCallback * cb)116 void FakeLockoutTracker::lockoutTimerExpired(ISessionCallback* cb) {
117     LOG(INFO) << "lockout timer expired";
118     mIsLockoutTimerStarted = false;
119 
120     if (mIsLockoutTimerAborted) {
121         mIsLockoutTimerAborted = false;
122         return;
123     }
124 
125     // if more failures seen since the timer started, need to restart timer again
126     auto deltaTime = getLockoutTimeLeft();
127     if (deltaTime <= 0) {
128         cb->onLockoutCleared();
129         reset(true);
130     } else {
131         startLockoutTimer(deltaTime, cb);
132     }
133 }
134 
abortTimer()135 void FakeLockoutTracker::abortTimer() {
136     if (mIsLockoutTimerStarted) mIsLockoutTimerAborted = true;
137 }
138 
139 }  // namespace aidl::android::hardware::biometrics::face
140