// Copyright 2018 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "biod/cros_fp_biometrics_manager.h"

#include <utility>

#include <errno.h>
#include <poll.h>
#include <sys/stat.h>
#include <sys/types.h>

#include <base/base64.h>
#include <base/bind.h>
#include <base/check.h>
#include <base/logging.h>
#include <base/strings/string_number_conversions.h>
#include <base/strings/string_piece.h>
#include <base/threading/platform_thread.h>
#include <base/time/time.h>
#include <crypto/random.h>
#include <metrics/metrics_library.h>
#include <base/timer/timer.h>

#include "biod/biod_crypto.h"
#include "biod/biod_metrics.h"
#include "biod/power_button_filter.h"
#include "biod/utils.h"

namespace {

std::string MatchResultToString(int result) {
  switch (result) {
    case EC_MKBP_FP_ERR_MATCH_NO:
      return "No match";
    case EC_MKBP_FP_ERR_MATCH_NO_INTERNAL:
      return "Internal error";
    case EC_MKBP_FP_ERR_MATCH_NO_TEMPLATES:
      return "No templates";
    case EC_MKBP_FP_ERR_MATCH_NO_LOW_QUALITY:
      return "Low quality";
    case EC_MKBP_FP_ERR_MATCH_NO_LOW_COVERAGE:
      return "Low coverage";
    case EC_MKBP_FP_ERR_MATCH_YES:
      return "Finger matched";
    case EC_MKBP_FP_ERR_MATCH_YES_UPDATED:
      return "Finger matched, template updated";
    case EC_MKBP_FP_ERR_MATCH_YES_UPDATE_FAILED:
      return "Finger matched, template updated failed";
    default:
      return "Unknown matcher result";
  }
}

std::string EnrollResultToString(int result) {
  switch (result) {
    case EC_MKBP_FP_ERR_ENROLL_OK:
      return "Success";
    case EC_MKBP_FP_ERR_ENROLL_LOW_QUALITY:
      return "Low quality";
    case EC_MKBP_FP_ERR_ENROLL_IMMOBILE:
      return "Same area";
    case EC_MKBP_FP_ERR_ENROLL_LOW_COVERAGE:
      return "Low coverage";
    case EC_MKBP_FP_ERR_ENROLL_INTERNAL:
      return "Internal error";
    default:
      return "Unknown enrollment result";
  }
}

};  // namespace

namespace biod {

using Mode = ec::FpMode::Mode;

const std::string& CrosFpBiometricsManager::Record::GetId() const {
  return record_id_;
}

std::string CrosFpBiometricsManager::Record::GetUserId() const {
  CHECK(biometrics_manager_);
  const auto record_metadata =
      biometrics_manager_->GetRecordMetadata(record_id_);
  CHECK(record_metadata);

  return record_metadata->user_id;
}

std::string CrosFpBiometricsManager::Record::GetLabel() const {
  CHECK(biometrics_manager_);
  const auto record_metadata =
      biometrics_manager_->GetRecordMetadata(record_id_);
  CHECK(record_metadata);

  return record_metadata->label;
}

std::vector<uint8_t> CrosFpBiometricsManager::Record::GetValidationVal() const {
  CHECK(biometrics_manager_);
  const auto record_metadata =
      biometrics_manager_->GetRecordMetadata(record_id_);
  CHECK(record_metadata);

  return record_metadata->validation_val;
}

bool CrosFpBiometricsManager::Record::SetLabel(std::string label) {
  CHECK(biometrics_manager_);

  auto record_metadata = biometrics_manager_->GetRecordMetadata(record_id_);
  CHECK(record_metadata);

  record_metadata->label = std::move(label);

  return biometrics_manager_->UpdateRecordMetadata(*record_metadata);
}

bool CrosFpBiometricsManager::Record::Remove() {
  if (!biometrics_manager_)
    return false;

  return biometrics_manager_->RemoveRecord(record_id_);
}

bool CrosFpBiometricsManager::ReloadAllRecords(std::string user_id) {
  // Here we need a copy of user_id because the user_id could be part of
  // loaded_records_ which is cleared in this method.
  loaded_records_.clear();
  suspicious_templates_.clear();

  return ReadRecordsForSingleUser(user_id);
}

BiometricType CrosFpBiometricsManager::GetType() {
  return BIOMETRIC_TYPE_FINGERPRINT;
}

BiometricsManager::EnrollSession CrosFpBiometricsManager::StartEnrollSession(
    std::string user_id, std::string label) {
  LOG(INFO) << __func__;
  // Another session is on-going, fail early ...
  if (!next_session_action_.is_null()) {
    LOG(ERROR) << "Another EnrollSession already exists";
    return BiometricsManager::EnrollSession();
  }

  if (loaded_records_.size() >= cros_dev_->MaxTemplateCount()) {
    LOG(ERROR) << "No space for an additional template.";
    return BiometricsManager::EnrollSession();
  }

  std::vector<uint8_t> validation_val;
  if (!RequestEnrollImage(BiodStorageInterface::RecordMetadata{
          kRecordFormatVersion, BiodStorage::GenerateNewRecordId(),
          std::move(user_id), std::move(label), std::move(validation_val)}))
    return BiometricsManager::EnrollSession();

  return BiometricsManager::EnrollSession(session_weak_factory_.GetWeakPtr());
}

BiometricsManager::AuthSession CrosFpBiometricsManager::StartAuthSession() {
  LOG(INFO) << __func__;
  // Another session is on-going, fail early ...
  if (!next_session_action_.is_null()) {
    LOG(ERROR) << "Another AuthSession already exists";
    return BiometricsManager::AuthSession();
  }

  if (!RequestMatch())
    return BiometricsManager::AuthSession();

  return BiometricsManager::AuthSession(session_weak_factory_.GetWeakPtr());
}

std::vector<std::unique_ptr<BiometricsManagerRecord>>
CrosFpBiometricsManager::GetLoadedRecords() {
  std::vector<std::unique_ptr<BiometricsManagerRecord>> records;

  for (const auto& record_id : loaded_records_) {
    records.emplace_back(
        std::make_unique<Record>(weak_factory_.GetWeakPtr(), record_id));
  }

  return records;
}

base::Optional<BiodStorageInterface::RecordMetadata>
CrosFpBiometricsManager::GetRecordMetadata(const std::string& record_id) const {
  return record_manager_->GetRecordMetadata(record_id);
}

base::Optional<std::string> CrosFpBiometricsManager::GetLoadedRecordId(int id) {
  if (id < 0 || id >= loaded_records_.size()) {
    return base::nullopt;
  }
  return loaded_records_[id];
}

bool CrosFpBiometricsManager::DestroyAllRecords() {
  return record_manager_->DeleteAllRecords();
}

void CrosFpBiometricsManager::RemoveRecordsFromMemory() {
  record_manager_->RemoveRecordsFromMemory();
  loaded_records_.clear();
  suspicious_templates_.clear();
  cros_dev_->ResetContext();
}

bool CrosFpBiometricsManager::RemoveRecord(const std::string& record_id) {
  const auto record = record_manager_->GetRecordMetadata(record_id);
  if (!record) {
    LOG(ERROR) << "Can't find metadata for record " << LogSafeID(record_id);
    return false;
  }

  std::string user_id = record->user_id;

  // TODO(b/115399954): only delete record if user_id is primary user.
  if (!record_manager_->DeleteRecord(record_id))
    return false;

  // We cannot remove only one record if we want to stay in sync with the MCU,
  // Clear and reload everything.
  return ReloadAllRecords(user_id);
}

bool CrosFpBiometricsManager::UpdateRecordMetadata(
    const BiodStorageInterface::RecordMetadata& record_metadata) {
  return record_manager_->UpdateRecordMetadata(record_metadata);
}

bool CrosFpBiometricsManager::ReadRecordsForSingleUser(
    const std::string& user_id) {
  cros_dev_->SetContext(user_id);
  auto valid_records = record_manager_->GetRecordsForUser(user_id);
  for (const auto& record : valid_records) {
    LoadRecord(std::move(record));
  }

  if (record_manager_->UserHasInvalidRecords(user_id)) {
    record_manager_->DeleteInvalidRecords();
    return false;
  }

  return true;
}

void CrosFpBiometricsManager::SetEnrollScanDoneHandler(
    const BiometricsManager::EnrollScanDoneCallback& on_enroll_scan_done) {
  on_enroll_scan_done_ = on_enroll_scan_done;
}

void CrosFpBiometricsManager::SetAuthScanDoneHandler(
    const BiometricsManager::AuthScanDoneCallback& on_auth_scan_done) {
  on_auth_scan_done_ = on_auth_scan_done;
}

void CrosFpBiometricsManager::SetSessionFailedHandler(
    const BiometricsManager::SessionFailedCallback& on_session_failed) {
  on_session_failed_ = on_session_failed;
}

bool CrosFpBiometricsManager::SendStatsOnLogin() {
  bool rc = true;
  rc = biod_metrics_->SendEnrolledFingerCount(loaded_records_.size()) && rc;
  // Even though it looks a bit redundant with the finger count, it's easier to
  // discover and interpret.
  rc = biod_metrics_->SendFpUnlockEnabled(!loaded_records_.empty()) && rc;
  return rc;
}

void CrosFpBiometricsManager::SetDiskAccesses(bool allow) {
  record_manager_->SetAllowAccess(allow);
}

bool CrosFpBiometricsManager::ResetSensor() {
  if (!cros_dev_->SetFpMode(ec::FpMode(Mode::kResetSensor))) {
    LOG(ERROR) << "Failed to send reset_sensor command to FPMCU.";
    return false;
  }

  int retries = 50;
  bool reset_complete = false;
  while (retries--) {
    ec::FpMode cur_mode = cros_dev_->GetFpMode();
    if (cur_mode == ec::FpMode(Mode::kModeInvalid)) {
      LOG(ERROR) << "Failed to query sensor state during reset.";
      return false;
    }

    if (cur_mode != ec::FpMode(Mode::kResetSensor)) {
      reset_complete = true;
      break;
    }
    base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(100));
  }

  if (!reset_complete) {
    LOG(ERROR) << "Reset on FPMCU failed to complete.";
    return false;
  }

  return true;
}

bool CrosFpBiometricsManager::ResetEntropy(bool factory_init) {
  bool success = cros_dev_->InitEntropy(!factory_init);
  if (!success) {
    LOG(INFO) << "Entropy source reset failed.";
    return false;
  }
  LOG(INFO) << "Entropy source has been successfully reset.";
  return true;
}

void CrosFpBiometricsManager::EndEnrollSession() {
  LOG(INFO) << __func__;
  KillMcuSession();
}

void CrosFpBiometricsManager::EndAuthSession() {
  LOG(INFO) << __func__;
  KillMcuSession();
}

void CrosFpBiometricsManager::KillMcuSession() {
  // TODO(vpalatin): test cros_dev_->FpMode(FP_MODE_DEEPSLEEP);
  cros_dev_->SetFpMode(ec::FpMode(Mode::kNone));
  session_weak_factory_.InvalidateWeakPtrs();
  OnTaskComplete();
}

CrosFpBiometricsManager::CrosFpBiometricsManager(
    std::unique_ptr<PowerButtonFilterInterface> power_button_filter,
    std::unique_ptr<CrosFpDeviceInterface> cros_fp_device,
    std::unique_ptr<BiodMetricsInterface> biod_metrics,
    std::unique_ptr<CrosFpRecordManagerInterface> record_manager)
    : biod_metrics_(std::move(biod_metrics)),
      cros_dev_(std::move(cros_fp_device)),
      session_weak_factory_(this),
      weak_factory_(this),
      power_button_filter_(std::move(power_button_filter)),
      record_manager_(std::move(record_manager)),
      maintenance_timer_(std::make_unique<base::RepeatingTimer>()) {
  CHECK(power_button_filter_);
  CHECK(cros_dev_);
  CHECK(biod_metrics_);
  CHECK(maintenance_timer_);
  CHECK(record_manager_);

  cros_dev_->SetMkbpEventCallback(base::BindRepeating(
      &CrosFpBiometricsManager::OnMkbpEvent, base::Unretained(this)));

  CHECK(cros_dev_->SupportsPositiveMatchSecret());

// TODO(b/187951992): The following automatic maintenance routine needs to
// be re-enabled in such a way that it will not interfere with the
// auth/unlock or enroll session. This maintenance timer was disabled due
// to b/184783529.
#if 0
  maintenance_timer_->Start(
      FROM_HERE, base::TimeDelta::FromDays(1),
      base::BindRepeating(&CrosFpBiometricsManager::OnMaintenanceTimerFired,
                 base::Unretained(this)));
#endif
}

CrosFpBiometricsManager::~CrosFpBiometricsManager() {}

void CrosFpBiometricsManager::OnEnrollScanDone(
    ScanResult result, const BiometricsManager::EnrollStatus& enroll_status) {
  if (!on_enroll_scan_done_.is_null())
    on_enroll_scan_done_.Run(result, enroll_status);
}

void CrosFpBiometricsManager::OnAuthScanDone(
    FingerprintMessage result,
    const BiometricsManager::AttemptMatches& matches) {
  if (!on_auth_scan_done_.is_null())
    on_auth_scan_done_.Run(result, matches);
}

void CrosFpBiometricsManager::OnSessionFailed() {
  LOG(INFO) << __func__;

  if (!on_session_failed_.is_null())
    on_session_failed_.Run();
}

void CrosFpBiometricsManager::OnMkbpEvent(uint32_t event) {
  if (!next_session_action_.is_null())
    next_session_action_.Run(event);
}

bool CrosFpBiometricsManager::RequestEnrollImage(
    BiodStorageInterface::RecordMetadata record) {
  next_session_action_ =
      base::BindRepeating(&CrosFpBiometricsManager::DoEnrollImageEvent,
                          base::Unretained(this), std::move(record));
  if (!cros_dev_->SetFpMode(ec::FpMode(Mode::kEnrollSessionEnrollImage))) {
    next_session_action_ = SessionAction();
    LOG(ERROR) << "Failed to start enrolling mode";
    return false;
  }
  return true;
}

bool CrosFpBiometricsManager::RequestEnrollFingerUp(
    BiodStorageInterface::RecordMetadata record) {
  next_session_action_ =
      base::BindRepeating(&CrosFpBiometricsManager::DoEnrollFingerUpEvent,
                          base::Unretained(this), std::move(record));
  if (!cros_dev_->SetFpMode(ec::FpMode(Mode::kEnrollSessionFingerUp))) {
    next_session_action_ = SessionAction();
    LOG(ERROR) << "Failed to wait for finger up";
    return false;
  }
  return true;
}

bool CrosFpBiometricsManager::RequestMatch(int attempt) {
  next_session_action_ = base::BindRepeating(
      &CrosFpBiometricsManager::DoMatchEvent, base::Unretained(this), attempt);
  if (!cros_dev_->SetFpMode(ec::FpMode(Mode::kMatch))) {
    next_session_action_ = SessionAction();
    LOG(ERROR) << "Failed to start matching mode";
    return false;
  }
  return true;
}

bool CrosFpBiometricsManager::RequestMatchFingerUp() {
  next_session_action_ = base::BindRepeating(
      &CrosFpBiometricsManager::DoMatchFingerUpEvent, base::Unretained(this));
  if (!cros_dev_->SetFpMode(ec::FpMode(Mode::kFingerUp))) {
    next_session_action_ = SessionAction();
    LOG(ERROR) << "Failed to request finger up event";
    return false;
  }
  return true;
}

void CrosFpBiometricsManager::DoEnrollImageEvent(
    BiodStorageInterface::RecordMetadata record, uint32_t event) {
  if (!(event & EC_MKBP_FP_ENROLL)) {
    LOG(WARNING) << "Unexpected MKBP event: 0x" << std::hex << event;
    // Continue waiting for the proper event, do not abort session.
    return;
  }

  int image_result = EC_MKBP_FP_ERRCODE(event);
  LOG(INFO) << __func__ << " result: '" << EnrollResultToString(image_result)
            << "'";
  ScanResult scan_result;
  switch (image_result) {
    case EC_MKBP_FP_ERR_ENROLL_OK:
      scan_result = ScanResult::SCAN_RESULT_SUCCESS;
      break;
    case EC_MKBP_FP_ERR_ENROLL_IMMOBILE:
      scan_result = ScanResult::SCAN_RESULT_IMMOBILE;
      break;
    case EC_MKBP_FP_ERR_ENROLL_LOW_COVERAGE:
      scan_result = ScanResult::SCAN_RESULT_PARTIAL;
      break;
    case EC_MKBP_FP_ERR_ENROLL_LOW_QUALITY:
      scan_result = ScanResult::SCAN_RESULT_INSUFFICIENT;
      break;
    case EC_MKBP_FP_ERR_ENROLL_INTERNAL:
    default:
      LOG(ERROR) << "Unexpected result from capture: " << std::hex << event;
      OnSessionFailed();
      return;
  }

  int percent = EC_MKBP_FP_ENROLL_PROGRESS(event);

  if (percent < 100) {
    BiometricsManager::EnrollStatus enroll_status = {false, percent};

    OnEnrollScanDone(scan_result, enroll_status);

    // The user needs to remove the finger before the next enrollment image.
    if (!RequestEnrollFingerUp(std::move(record)))
      OnSessionFailed();

    return;
  }

  // we are done with captures, save the template.
  OnTaskComplete();

  std::unique_ptr<VendorTemplate> tmpl =
      cros_dev_->GetTemplate(CrosFpDevice::kLastTemplate);
  if (!tmpl) {
    LOG(ERROR) << "Failed to retrieve enrolled finger";
    OnSessionFailed();
    return;
  }

  base::Optional<brillo::SecureVector> secret =
      cros_dev_->GetPositiveMatchSecret(CrosFpDevice::kLastTemplate);
  if (!secret) {
    LOG(ERROR) << "Failed to get positive match secret.";
    OnSessionFailed();
    return;
  }

  std::vector<uint8_t> validation_val;
  if (!BiodCrypto::ComputeValidationValue(*secret, record.user_id,
                                          &validation_val)) {
    LOG(ERROR) << "Failed to compute validation value.";
    OnSessionFailed();
    return;
  }
  record.validation_val = std::move(validation_val);
  LOG(INFO) << "Computed validation value for enrolled finger.";

  std::string record_id = record.record_id;

  if (!record_manager_->CreateRecord(record, std::move(tmpl))) {
    OnSessionFailed();
    return;
  }

  // This record is now loaded in FPMCU, so add it to the list.
  loaded_records_.emplace_back(record_id);

  BiometricsManager::EnrollStatus enroll_status = {true, 100};
  OnEnrollScanDone(ScanResult::SCAN_RESULT_SUCCESS, enroll_status);
}

void CrosFpBiometricsManager::DoEnrollFingerUpEvent(
    BiodStorageInterface::RecordMetadata record, uint32_t event) {
  if (!(event & EC_MKBP_FP_FINGER_UP)) {
    LOG(WARNING) << "Unexpected MKBP event: 0x" << std::hex << event;
    // Continue waiting for the proper event, do not abort session.
    return;
  }

  if (!RequestEnrollImage(std::move(record)))
    OnSessionFailed();
}

void CrosFpBiometricsManager::DoMatchFingerUpEvent(uint32_t event) {
  if (!(event & EC_MKBP_FP_FINGER_UP)) {
    LOG(WARNING) << "Unexpected MKBP event: 0x" << std::hex << event;
    // Continue waiting for the proper event, do not abort session.
    return;
  }
  // The user has lifted their finger, try to match the next touch.
  if (!RequestMatch())
    OnSessionFailed();
}

bool CrosFpBiometricsManager::CheckPositiveMatchSecret(
    const std::string& record_id, int match_idx) {
  base::Optional<brillo::SecureVector> secret =
      cros_dev_->GetPositiveMatchSecret(match_idx);
  biod_metrics_->SendReadPositiveMatchSecretSuccess(secret.has_value());

  if (!secret) {
    LOG(ERROR) << "Failed to read positive match secret on match for finger "
               << match_idx << ".";
    return false;
  }

  const auto record_metadata = record_manager_->GetRecordMetadata(record_id);
  if (!record_metadata) {
    LOG(ERROR) << "Can't find metadata for record " << LogSafeID(record_id);
    return false;
  }

  std::vector<uint8_t> validation_value;
  if (!BiodCrypto::ComputeValidationValue(*secret, record_metadata->user_id,
                                          &validation_value)) {
    LOG(ERROR) << "Failed to compute validation value for finger " << match_idx
               << ".";
    return false;
  }

  if (validation_value != record_metadata->validation_val) {
    LOG(ERROR) << "Validation value does not match for finger " << match_idx;
    biod_metrics_->SendPositiveMatchSecretCorrect(false);
    suspicious_templates_.emplace(match_idx);
    return false;
  }

  LOG(INFO) << "Verified validation value for finger " << match_idx;
  biod_metrics_->SendPositiveMatchSecretCorrect(true);
  suspicious_templates_.erase(match_idx);
  return true;
}

void CrosFpBiometricsManager::DoMatchEvent(int attempt, uint32_t event) {
  if (!(event & EC_MKBP_FP_MATCH)) {
    LOG(WARNING) << "Unexpected MKBP event: 0x" << std::hex << event;
    // Continue waiting for the proper event, do not abort session.
    return;
  }

  // The user intention might be to press the power button. If so, ignore the
  // current match.
  if (power_button_filter_->ShouldFilterFingerprintMatch()) {
    LOG(INFO)
        << "Power button event seen along with fp match. Ignoring fp match.";

    // Try to match the next touch once the user lifts the finger as the client
    // is still waiting for an auth. Wait for finger up event here is to prevent
    // the following scenario.
    // 1. Display is on. Now user presses power button with an enrolled finger.
    // 3. Display goes off. biod starts auth session.
    // 4. Fp match happens and is filtered by biod. biod immediately restarts
    //    a new auth session (if we do not wait for finger up).
    // 5. fp sensor immediately sends a match event before user gets a chance to
    //    lift the finger.
    // 6. biod sees a match again and this time notifies chrome without
    //    filtering it as it has filtered one already.

    if (!RequestMatchFingerUp())
      OnSessionFailed();

    biod_metrics_->SendIgnoreMatchEventOnPowerButtonPress(true);
    return;
  }

  biod_metrics_->SendIgnoreMatchEventOnPowerButtonPress(false);
  int match_result = EC_MKBP_FP_ERRCODE(event);

  // If the finger is positioned slightly off the sensor, retry a few times
  // before failing. Typically the user has put their finger down and is now
  // moving their finger to the correct position on the sensor. Instead of
  // immediately failing, retry until we get a good image.
  // Retry 20 times, which takes about 5 to 15s, before giving up and sending
  // an error back to the user. Assume ~1s for user noticing that no matching
  // happened, some time to move the finger on the sensor to allow a full
  // capture and another 1s for the second matching attempt. 5s gives a bit of
  // margin to avoid interrupting the user while they're moving the finger on
  // the sensor.
  const int kMaxPartialAttempts = 20;

  if (match_result == EC_MKBP_FP_ERR_MATCH_NO_LOW_COVERAGE &&
      attempt < kMaxPartialAttempts) {
    /* retry a match */
    if (!RequestMatch(attempt + 1))
      OnSessionFailed();
    return;
  }

  // Don't try to match again until the user has lifted their finger from the
  // sensor. Request the FingerUp event as soon as the HW signaled a match so it
  // doesn't attempt a new match while the host is processing the first
  // match event.
  if (!RequestMatchFingerUp()) {
    OnSessionFailed();
    return;
  }

  std::vector<int> dirty_list;
  if (match_result == EC_MKBP_FP_ERR_MATCH_YES_UPDATED) {
    dirty_list = GetDirtyList();
  }

  FingerprintMessage result;
  base::Optional<std::string> matched_record_id;
  base::Optional<RecordMetadata> matched_record_meta;

  uint32_t match_idx = EC_MKBP_FP_MATCH_IDX(event);
  LOG(INFO) << __func__ << " result: '" << MatchResultToString(match_result)
            << "' (finger: " << match_idx << ")";
  switch (match_result) {
    case EC_MKBP_FP_ERR_MATCH_NO_TEMPLATES:
      LOG(ERROR) << "No templates to match: " << std::hex << event;
      result.set_error(FingerprintError::ERROR_NO_TEMPLATES);
      break;
    case EC_MKBP_FP_ERR_MATCH_NO_INTERNAL:
      LOG(ERROR) << "Internal error when matching templates: " << std::hex
                 << event;
      result.set_error(FingerprintError::ERROR_UNABLE_TO_PROCESS);
      break;
    case EC_MKBP_FP_ERR_MATCH_NO:
      result.set_scan_result(ScanResult::SCAN_RESULT_NO_MATCH);
      break;
    case EC_MKBP_FP_ERR_MATCH_YES:
    case EC_MKBP_FP_ERR_MATCH_YES_UPDATED:
    case EC_MKBP_FP_ERR_MATCH_YES_UPDATE_FAILED:
      // We are on a good path to successfully authenticate user, but
      // we still need to confirm that positive match secret is correct.
      // Set UNABLE_TO_PROCESS error for now, it will be changed to
      // SUCCESS scan result when positive match secret is validated.
      result.set_error(FingerprintError::ERROR_UNABLE_TO_PROCESS);
      matched_record_id = GetLoadedRecordId(match_idx);
      if (matched_record_id) {
        matched_record_meta =
            record_manager_->GetRecordMetadata(*matched_record_id);
        if (!matched_record_meta) {
          LOG(ERROR) << "Can't find metadata for record "
                     << LogSafeID(*matched_record_id);
        }
      } else {
        LOG(ERROR) << "Invalid finger index " << match_idx;
      }
      break;
    case EC_MKBP_FP_ERR_MATCH_NO_LOW_QUALITY:
      result.set_scan_result(ScanResult::SCAN_RESULT_INSUFFICIENT);
      break;
    case EC_MKBP_FP_ERR_MATCH_NO_LOW_COVERAGE:
      result.set_scan_result(ScanResult::SCAN_RESULT_PARTIAL);
      break;
    default:
      LOG(ERROR) << "Unexpected result from matching templates: " << std::hex
                 << event;
      OnSessionFailed();
      return;
  }

  BiometricsManager::AttemptMatches matches;

  if (matched_record_meta) {
    // CrosFp says that match was successful, let's check if this is true
    if (CheckPositiveMatchSecret(matched_record_meta->record_id, match_idx)) {
      matches.emplace(
          matched_record_meta->user_id,
          std::vector<std::string>({matched_record_meta->record_id}));
      result.set_scan_result(ScanResult::SCAN_RESULT_SUCCESS);
    } else {
      LOG(ERROR) << "Failed to check Secure Secret for " << match_idx;
      matched_record_meta = base::nullopt;
    }
  }

  // Send back the result directly (as we are running on the main thread).
  OnAuthScanDone(std::move(result), std::move(matches));

  base::Optional<CrosFpDeviceInterface::FpStats> stats =
      cros_dev_->GetFpStats();
  if (stats) {
    biod_metrics_->SendFpLatencyStats(matched_record_meta.has_value(), *stats);
  }

  // Record updated templates
  // TODO(vpalatin): this is slow, move to end of session ?
  UpdateTemplatesOnDisk(dirty_list, suspicious_templates_);
}

void CrosFpBiometricsManager::OnTaskComplete() {
  next_session_action_ = SessionAction();
}

bool CrosFpBiometricsManager::LoadRecord(
    const BiodStorageInterface::Record record) {
  std::string tmpl_data_str;
  base::Base64Decode(record.data, &tmpl_data_str);

  if (loaded_records_.size() >= cros_dev_->MaxTemplateCount()) {
    LOG(ERROR) << "No space to upload template from "
               << LogSafeID(record.metadata.record_id) << ".";
    return false;
  }

  biod_metrics_->SendRecordFormatVersion(record.metadata.record_format_version);
  LOG(INFO) << "Upload record " << LogSafeID(record.metadata.record_id) << ".";
  VendorTemplate tmpl(tmpl_data_str.begin(), tmpl_data_str.end());
  auto* metadata =
      reinterpret_cast<const ec_fp_template_encryption_metadata*>(tmpl.data());
  if (metadata->struct_version != cros_dev_->TemplateVersion()) {
    LOG(ERROR) << "Version mismatch between template ("
               << metadata->struct_version << ") and hardware ("
               << cros_dev_->TemplateVersion() << ")";
    record_manager_->DeleteRecord(record.metadata.record_id);
    return false;
  }
  if (!cros_dev_->UploadTemplate(tmpl)) {
    LOG(ERROR) << "Cannot send template to the MCU from "
               << LogSafeID(record.metadata.record_id) << ".";
    return false;
  }

  loaded_records_.emplace_back(record.metadata.record_id);
  return true;
}

void CrosFpBiometricsManager::OnMaintenanceTimerFired() {
  LOG(INFO) << "Maintenance timer fired";

  // Report the number of dead pixels
  cros_dev_->UpdateFpInfo();
  biod_metrics_->SendDeadPixelCount(cros_dev_->DeadPixelCount());

  // The maintenance operation can take a couple hundred milliseconds, so it's
  // an asynchronous mode (the state is cleared by the FPMCU after it is
  // finished with the operation).
  cros_dev_->SetFpMode(ec::FpMode(Mode::kSensorMaintenance));
}

std::vector<int> CrosFpBiometricsManager::GetDirtyList() {
  std::vector<int> dirty_list;

  // Retrieve which templates have been updated.
  base::Optional<std::bitset<32>> dirty_bitmap = cros_dev_->GetDirtyMap();
  if (!dirty_bitmap) {
    LOG(ERROR) << "Failed to get updated templates map";
    return dirty_list;
  }

  // Create a list of modified template indexes from the bitmap.
  dirty_list.reserve(dirty_bitmap->count());
  for (int i = 0; dirty_bitmap->any() && i < dirty_bitmap->size(); i++) {
    if ((*dirty_bitmap)[i]) {
      dirty_list.emplace_back(i);
      dirty_bitmap->reset(i);
    }
  }

  return dirty_list;
}

bool CrosFpBiometricsManager::UpdateTemplatesOnDisk(
    const std::vector<int>& dirty_list,
    const std::unordered_set<uint32_t>& suspicious_templates) {
  bool ret = true;
  for (int i : dirty_list) {
    if (!GetLoadedRecordId(i)) {
      LOG(ERROR)
          << "Index " << i
          << " is on dirty list, but corresponding record doesn't exist.";
      continue;
    }
    // If the template previously came with wrong validation value, do not
    // accept it until it comes with correct validation value.
    if (suspicious_templates.find(i) != suspicious_templates.end()) {
      continue;
    }

    std::unique_ptr<VendorTemplate> templ = cros_dev_->GetTemplate(i);
    LOG(INFO) << "Retrieve updated template " << i << " -> " << std::boolalpha
              << templ.get();
    if (!templ) {
      continue;
    }

    const auto record_metadata =
        record_manager_->GetRecordMetadata(*GetLoadedRecordId(i));
    if (!record_metadata) {
      LOG(ERROR) << "Can't find metadata for record "
                 << LogSafeID(*GetLoadedRecordId(i));
      ret = false;
    }

    if (!record_manager_->UpdateRecord(*record_metadata, std::move(templ))) {
      LOG(ERROR) << "Cannot update record "
                 << LogSafeID(GetLoadedRecordId(i).value())
                 << " in storage during AuthSession because writing failed.";
      ret = false;
    }
  }

  return ret;
}

}  // namespace biod
