Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit c5da528e authored by Jeff Pu's avatar Jeff Pu Committed by Android (Google) Code Review
Browse files

Merge "Face Virtual HAL lockout support" into main

parents e52b4d14 3e7448dc
Loading
Loading
Loading
Loading
+28 −0
Original line number Diff line number Diff line
@@ -30,6 +30,7 @@ cc_binary {
        "libnativewindow",
    ],
    srcs: [
        "FakeLockoutTracker.cpp",
        "main.cpp",
        "Face.cpp",
        "FakeFaceEngine.cpp",
@@ -63,6 +64,33 @@ cc_test {
    srcs: [
        "tests/FakeFaceEngineTest.cpp",
        "FakeFaceEngine.cpp",
        "FakeLockoutTracker.cpp",
    ],
    shared_libs: [
        "libbase",
        "libbinder_ndk",
        "libnativewindow",
    ],
    include_dirs: [
        "frameworks/native/aidl/gui",
    ],
    static_libs: [
        "libandroid.hardware.biometrics.face.VirtualProps",
        "android.hardware.biometrics.face-V4-ndk",
        "android.hardware.biometrics.common-V4-ndk",
        "android.hardware.keymaster-V4-ndk",
        "android.hardware.biometrics.common.util",
    ],
    vendor: true,
    test_suites: ["general-tests"],
    require_root: true,
}

cc_test {
    name: "android.hardware.biometrics.face.FakeLockoutTrackerTest",
    srcs: [
        "tests/FakeLockoutTrackerTest.cpp",
        "FakeLockoutTracker.cpp",
    ],
    shared_libs: [
        "libbase",
+26 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2023 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#define LOG_TAG "FaceVirtualHalEngine"

#include "FakeFaceEngine.h"

#include <android-base/logging.h>
@@ -186,6 +204,10 @@ void FakeFaceEngine::authenticateImpl(ISessionCallback* cb, int64_t /*operationI
        return;
    }

    if (mLockoutTracker.checkIfLockout(cb)) {
        return;
    }

    int i = 0;
    do {
        if (FaceHalProperties::lockout().value_or(false)) {
@@ -197,6 +219,7 @@ void FakeFaceEngine::authenticateImpl(ISessionCallback* cb, int64_t /*operationI

        if (FaceHalProperties::operation_authenticate_fails().value_or(false)) {
            LOG(ERROR) << "Fail: operation_authenticate_fails";
            mLockoutTracker.addFailedAttempt(cb);
            cb->onAuthenticationFailed();
            return;
        }
@@ -231,10 +254,12 @@ void FakeFaceEngine::authenticateImpl(ISessionCallback* cb, int64_t /*operationI
    } while (!Util::hasElapsed(now, duration));

    if (id > 0 && isEnrolled) {
        mLockoutTracker.reset();
        cb->onAuthenticationSucceeded(id, {} /* hat */);
        return;
    } else {
        LOG(ERROR) << "Fail: face not enrolled";
        mLockoutTracker.addFailedAttempt(cb);
        cb->onAuthenticationFailed();
        cb->onError(Error::TIMEOUT, 0 /* vendorError*/);
        return;
@@ -389,6 +414,7 @@ void FakeFaceEngine::resetLockoutImpl(ISessionCallback* cb,
                                      const keymaster::HardwareAuthToken& /*hat*/) {
    BEGIN_OP(0);
    FaceHalProperties::lockout(false);
    mLockoutTracker.reset();
    cb->onLockoutCleared();
}

+12 −4
Original line number Diff line number Diff line
@@ -16,18 +16,17 @@

#pragma once

#define LOG_TAG "FaceVirtualHal"

#include <aidl/android/hardware/biometrics/common/SensorStrength.h>
#include <aidl/android/hardware/biometrics/face/BnSession.h>
#include <aidl/android/hardware/biometrics/face/FaceSensorType.h>
#include <aidl/android/hardware/biometrics/face/ISessionCallback.h>

#include <random>

#include <future>
#include <random>
#include <vector>

#include "FakeLockoutTracker.h"

namespace aidl::android::hardware::biometrics::face {

namespace face = aidl::android::hardware::biometrics::face;
@@ -39,6 +38,7 @@ using aidl::android::hardware::common::NativeHandle;
class FakeFaceEngine {
  public:
    FakeFaceEngine() : mRandom(std::mt19937::default_seed) {}
    virtual ~FakeFaceEngine() {}

    static face::FaceSensorType GetSensorType();
    static common::SensorStrength GetSensorStrength();
@@ -61,6 +61,13 @@ class FakeFaceEngine {
    void invalidateAuthenticatorIdImpl(ISessionCallback* cb);
    void resetLockoutImpl(ISessionCallback* cb, const keymaster::HardwareAuthToken& /*hat*/);

    virtual std::string toString() const {
        std::ostringstream os;
        os << "----- FakeFaceEngine:: -----" << std::endl;
        os << mLockoutTracker.toString();
        return os.str();
    }

    std::mt19937 mRandom;

  private:
@@ -68,6 +75,7 @@ class FakeFaceEngine {
    static constexpr int32_t FACE_ERROR_VENDOR_BASE = 1000;
    std::pair<AcquiredInfo, int32_t> convertAcquiredInfo(int32_t code);
    std::pair<Error, int32_t> convertError(int32_t code);
    FakeLockoutTracker mLockoutTracker;
};

}  // namespace aidl::android::hardware::biometrics::face
+138 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2023 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#define LOG_TAG "FaceVirtualHalLockoutTracker"

#include "FakeLockoutTracker.h"
#include <android-base/logging.h>
#include <face.sysprop.h>
#include "util/Util.h"

using namespace ::android::face::virt;

namespace aidl::android::hardware::biometrics::face {

void FakeLockoutTracker::reset(bool dueToTimerExpire) {
    if (!dueToTimerExpire) {
        mFailedCount = 0;
        mLastFailedTime = 0;
    }
    mTimedFailedCount = 0;
    mCurrentMode = LockoutMode::kNone;
    abortTimer();
}

void FakeLockoutTracker::addFailedAttempt(ISessionCallback* cb) {
    bool lockoutEnabled = FaceHalProperties::lockout_enable().value_or(false);
    bool timedLockoutenabled = FaceHalProperties::lockout_timed_enable().value_or(false);
    if (lockoutEnabled) {
        mFailedCount++;
        mTimedFailedCount++;
        mLastFailedTime = Util::getSystemNanoTime();
        int32_t lockoutTimedThreshold = FaceHalProperties::lockout_timed_threshold().value_or(3);
        int32_t lockoutPermanetThreshold =
                FaceHalProperties::lockout_permanent_threshold().value_or(5);
        if (mFailedCount >= lockoutPermanetThreshold) {
            mCurrentMode = LockoutMode::kPermanent;
            LOG(ERROR) << "FakeLockoutTracker: lockoutPermanent";
            cb->onLockoutPermanent();
            abortTimer();
        } else if (timedLockoutenabled && mTimedFailedCount >= lockoutTimedThreshold) {
            if (mCurrentMode == LockoutMode::kNone) {
                mCurrentMode = LockoutMode::kTimed;
                startLockoutTimer(getTimedLockoutDuration(), cb);
            }
            LOG(ERROR) << "FakeLockoutTracker: lockoutTimed";
            cb->onLockoutTimed(getLockoutTimeLeft());
        }
    } else {
        reset();
    }
}

FakeLockoutTracker::LockoutMode FakeLockoutTracker::getMode() {
    return mCurrentMode;
}

int32_t FakeLockoutTracker::getTimedLockoutDuration() {
    return FaceHalProperties::lockout_timed_duration().value_or(10 * 1000);
}

int64_t FakeLockoutTracker::getLockoutTimeLeft() {
    int64_t res = 0;

    if (mLastFailedTime > 0) {
        auto now = Util::getSystemNanoTime();
        auto elapsed = (now - mLastFailedTime) / 1000000LL;
        res = getTimedLockoutDuration() - elapsed;
        LOG(INFO) << "elapsed=" << elapsed << " now = " << now
                  << " mLastFailedTime=" << mLastFailedTime << " res=" << res;
    }

    return res;
}

bool FakeLockoutTracker::checkIfLockout(ISessionCallback* cb) {
    if (mCurrentMode == LockoutMode::kPermanent) {
        LOG(ERROR) << "Lockout permanent";
        cb->onLockoutPermanent();
        return true;
    } else if (mCurrentMode == LockoutMode::kTimed) {
        auto timeLeft = getLockoutTimeLeft();
        LOG(ERROR) << "Lockout timed " << timeLeft;
        cb->onLockoutTimed(timeLeft);
        return true;
    }
    return false;
}

void FakeLockoutTracker::startLockoutTimer(int64_t timeout, ISessionCallback* cb) {
    LOG(ERROR) << "startLockoutTimer: to=" << timeout;
    if (mIsLockoutTimerStarted) return;
    std::function<void(ISessionCallback*)> action =
            std::bind(&FakeLockoutTracker::lockoutTimerExpired, this, std::placeholders::_1);
    std::thread([timeout, action, cb]() {
        std::this_thread::sleep_for(std::chrono::milliseconds(timeout));
        action(cb);
    }).detach();

    mIsLockoutTimerStarted = true;
}

void FakeLockoutTracker::lockoutTimerExpired(ISessionCallback* cb) {
    LOG(INFO) << "lockout timer expired";
    mIsLockoutTimerStarted = false;

    if (mIsLockoutTimerAborted) {
        mIsLockoutTimerAborted = false;
        return;
    }

    // if more failures seen since the timer started, need to restart timer again
    auto deltaTime = getLockoutTimeLeft();
    if (deltaTime <= 0) {
        cb->onLockoutCleared();
        reset(true);
    } else {
        startLockoutTimer(deltaTime, cb);
    }
}

void FakeLockoutTracker::abortTimer() {
    if (mIsLockoutTimerStarted) mIsLockoutTimerAborted = true;
}

}  // namespace aidl::android::hardware::biometrics::face
+70 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2023 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#pragma once

#include <aidl/android/hardware/biometrics/face/ISessionCallback.h>
#include <android/binder_to_string.h>
#include <stdint.h>
#include <string>

namespace aidl::android::hardware::biometrics::face {

// Lockout implementation for Face Virtual HAL
class FakeLockoutTracker {
  public:
    FakeLockoutTracker()
        : mFailedCount(0),
          mLastFailedTime(0),
          mIsLockoutTimerStarted(false),
          mIsLockoutTimerAborted(false) {}
    ~FakeLockoutTracker() {}

    enum class LockoutMode : int8_t { kNone = 0, kTimed, kPermanent };

    bool checkIfLockout(ISessionCallback*);
    void addFailedAttempt(ISessionCallback*);
    int64_t getLockoutTimeLeft();
    LockoutMode getMode();
    void reset(bool dueToTimerExpire = false);
    inline std::string toString() const {
        std::ostringstream os;
        os << "----- FakeLockoutTracker:: -----" << std::endl;
        os << "mFailedCount:" << mFailedCount;
        os << ", mCurrentMode:" << (int)mCurrentMode;
        os << ", mLastFailedTime:" << (int)(mLastFailedTime / 1000000LL);
        os << ",  mIsLockoutTimerStarted:" << mIsLockoutTimerStarted;
        os << ", mIsLockoutTimerAborted:" << mIsLockoutTimerAborted;
        os << std::endl;
        return os.str();
    }

  private:
    void startLockoutTimer(int64_t timeout, ISessionCallback* cb);
    void lockoutTimerExpired(ISessionCallback* cb);
    int32_t getTimedLockoutDuration();
    void abortTimer();

  private:
    int32_t mFailedCount;
    int32_t mTimedFailedCount;
    int64_t mLastFailedTime;
    LockoutMode mCurrentMode;
    bool mIsLockoutTimerStarted;
    bool mIsLockoutTimerAborted;
};

}  // namespace aidl::android::hardware::biometrics::face
Loading