// 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 {
  CHECK(biometrics_manager_);
  CHECK(index_ < biometrics_manager_->records_.size());
  return biometrics_manager_->records_[index_].record_id;
}

const std::string& CrosFpBiometricsManager::Record::GetUserId() const {
  CHECK(biometrics_manager_);
  CHECK(index_ <= biometrics_manager_->records_.size());
  return biometrics_manager_->records_[index_].user_id;
}

const std::string& CrosFpBiometricsManager::Record::GetLabel() const {
  CHECK(biometrics_manager_);
  CHECK(index_ < biometrics_manager_->records_.size());
  return biometrics_manager_->records_[index_].label;
}

const std::vector<uint8_t>& CrosFpBiometricsManager::Record::GetValidationVal()
    const {
  CHECK(biometrics_manager_);
  CHECK(index_ <= biometrics_manager_->records_.size());
  return biometrics_manager_->records_[index_].validation_val;
}

bool CrosFpBiometricsManager::Record::SetLabel(std::string label) {
  CHECK(biometrics_manager_);
  CHECK(index_ < biometrics_manager_->records_.size());
  std::string old_label = biometrics_manager_->records_[index_].label;

  std::unique_ptr<VendorTemplate> tmpl =
      biometrics_manager_->cros_dev_->GetTemplate(index_);
  // TODO(vpalatin): would be faster to read it from disk
  if (!tmpl) {
    return false;
  }
  biometrics_manager_->records_[index_].label = std::move(label);

  if (!biometrics_manager_->WriteRecord(*this, tmpl->data(), tmpl->size())) {
    biometrics_manager_->records_[index_].label = std::move(old_label);
    return false;
  }
  return true;
}

bool CrosFpBiometricsManager::Record::SupportsPositiveMatchSecret() const {
  return biometrics_manager_->use_positive_match_secret_;
}

bool CrosFpBiometricsManager::Record::Remove() {
  if (!biometrics_manager_)
    return false;
  if (index_ >= biometrics_manager_->records_.size())
    return false;

  const auto& record = biometrics_manager_->records_[index_];
  std::string user_id = record.user_id;

  // TODO(mqg): only delete record if user_id is primary user.
  if (!biometrics_manager_->biod_storage_.DeleteRecord(user_id,
                                                       record.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 biometrics_manager_->ReloadAllRecords(user_id);
}

bool CrosFpBiometricsManager::ReloadAllRecords(std::string user_id) {
  // Here we need a copy of user_id because the user_id could be part of
  // records_ which is cleared in this method.
  records_.clear();
  suspicious_templates_.clear();
  cros_dev_->SetContext(user_id);
  auto result = biod_storage_.ReadRecordsForSingleUser(user_id);
  for (const auto& record : result.valid_records) {
    LoadRecord(std::move(record));
  }
  return result.invalid_records.empty();
}

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 (records_.size() >= cros_dev_->MaxTemplateCount()) {
    LOG(ERROR) << "No space for an additional template.";
    return BiometricsManager::EnrollSession();
  }

  std::vector<uint8_t> validation_val;
  if (!RequestEnrollImage(BiodStorage::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::GetRecords() {
  std::vector<std::unique_ptr<BiometricsManagerRecord>> records;
  for (int i = 0; i < records_.size(); i++)
    records.emplace_back(
        std::make_unique<Record>(weak_factory_.GetWeakPtr(), i));
  return records;
}

bool CrosFpBiometricsManager::DestroyAllRecords() {
  // Enumerate through records_ and delete each record.
  bool delete_all_records = true;
  for (auto& record : records_) {
    delete_all_records &=
        biod_storage_.DeleteRecord(record.user_id, record.record_id);
  }
  RemoveRecordsFromMemory();
  return delete_all_records;
}

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

bool CrosFpBiometricsManager::ReadRecordsForSingleUser(
    const std::string& user_id) {
  cros_dev_->SetContext(user_id);
  auto result = biod_storage_.ReadRecordsForSingleUser(user_id);
  for (const auto& record : result.valid_records) {
    LoadRecord(record);
  }
  return result.invalid_records.empty();
}

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(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(!records_.empty()) && rc;
  return rc;
}

void CrosFpBiometricsManager::SetDiskAccesses(bool allow) {
  biod_storage_.set_allow_access(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)
    : 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)),
      biod_storage_(kCrosFpBiometricsManagerName),
      use_positive_match_secret_(false),
      maintenance_timer_(std::make_unique<base::RepeatingTimer>()) {
  CHECK(power_button_filter_);
  CHECK(cros_dev_);
  CHECK(biod_metrics_);
  CHECK(maintenance_timer_);

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

  use_positive_match_secret_ = cros_dev_->SupportsPositiveMatchSecret();

  maintenance_timer_->Start(
      FROM_HERE, base::TimeDelta::FromDays(1),
      base::Bind(&CrosFpBiometricsManager::OnMaintenanceTimerFired,
                 base::Unretained(this)));
}

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(
    ScanResult 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(
    BiodStorage::RecordMetadata record) {
  next_session_action_ =
      base::Bind(&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(
    BiodStorage::RecordMetadata record) {
  next_session_action_ =
      base::Bind(&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::Bind(&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::Bind(
      &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(
    BiodStorage::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;
  }

  if (use_positive_match_secret_) {
    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.";
  }

  records_.emplace_back(record);
  Record current_record(weak_factory_.GetWeakPtr(), records_.size() - 1);
  if (!WriteRecord(current_record, tmpl->data(), tmpl->size())) {
    records_.pop_back();
    OnSessionFailed();
    return;
  }

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

void CrosFpBiometricsManager::DoEnrollFingerUpEvent(
    BiodStorage::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::ValidationValueIsCorrect(uint32_t 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;
  }

  std::vector<uint8_t> validation_value;
  if (!BiodCrypto::ComputeValidationValue(*secret, records_[match_idx].user_id,
                                          &validation_value)) {
    LOG(ERROR) << "Got positive match secret but failed to compute validation "
                  "value for finger "
               << match_idx << ".";
    return false;
  }

  if (validation_value != records_[match_idx].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;
}

BiometricsManager::AttemptMatches CrosFpBiometricsManager::CalculateMatches(
    int match_idx, bool matched) {
  BiometricsManager::AttemptMatches matches;
  if (!matched)
    return matches;

  if (match_idx >= records_.size()) {
    LOG(ERROR) << "Invalid finger index " << match_idx;
    return matches;
  }

  if (!use_positive_match_secret_ || ValidationValueIsCorrect(match_idx)) {
    matches.emplace(records_[match_idx].user_id,
                    std::vector<std::string>({records_[match_idx].record_id}));
  }
  return matches;
}

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);
  ScanResult result;
  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();
  }

  bool matched = false;

  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 = ScanResult::SCAN_RESULT_SUCCESS;
      break;
    case EC_MKBP_FP_ERR_MATCH_NO_INTERNAL:
      LOG(ERROR) << "Internal error when matching templates: " << std::hex
                 << event;
      result = ScanResult::SCAN_RESULT_SUCCESS;
      break;
    case EC_MKBP_FP_ERR_MATCH_NO:
      // This is the API: empty matches but still SCAN_RESULT_SUCCESS.
      result = ScanResult::SCAN_RESULT_SUCCESS;
      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:
      result = ScanResult::SCAN_RESULT_SUCCESS;
      matched = true;
      break;
    case EC_MKBP_FP_ERR_MATCH_NO_LOW_QUALITY:
      result = ScanResult::SCAN_RESULT_INSUFFICIENT;
      break;
    case EC_MKBP_FP_ERR_MATCH_NO_LOW_COVERAGE:
      result = ScanResult::SCAN_RESULT_PARTIAL;
      break;
    default:
      LOG(ERROR) << "Unexpected result from matching templates: " << std::hex
                 << event;
      OnSessionFailed();
      return;
  }

  BiometricsManager::AttemptMatches matches =
      CalculateMatches(match_idx, matched);
  if (matches.empty())
    matched = false;

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

  base::Optional<CrosFpDeviceInterface::FpStats> stats =
      cros_dev_->GetFpStats();
  if (stats) {
    biod_metrics_->SendFpLatencyStats(matched, *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 BiodStorage::Record record) {
  std::string tmpl_data_str;
  base::Base64Decode(record.data, &tmpl_data_str);

  if (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() << ")";
    biod_storage_.DeleteRecord(record.metadata.user_id,
                               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;
  }

  records_.emplace_back(std::move(record.metadata));
  return true;
}

bool CrosFpBiometricsManager::WriteRecord(const BiometricsManagerRecord& record,
                                          uint8_t* tmpl_data,
                                          size_t tmpl_size) {
  base::StringPiece tmpl_sp(reinterpret_cast<char*>(tmpl_data), tmpl_size);
  std::string tmpl_base64;
  base::Base64Encode(tmpl_sp, &tmpl_base64);

  return biod_storage_.WriteRecord(record, base::Value(std::move(tmpl_base64)));
}

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 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;
    }

    Record current_record(weak_factory_.GetWeakPtr(), i);
    if (!WriteRecord(current_record, templ->data(), templ->size())) {
      LOG(ERROR) << "Cannot update record " << LogSafeID(records_[i].record_id)
                 << " in storage during AuthSession because writing failed.";
      ret = false;
    }
  }

  return ret;
}

}  // namespace biod
