File size: 6,063 Bytes
f8dc3a0
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
// Copyright 2020 The Chromium 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 "chromeos/services/machine_learning/cpp/ash/handwriting_model_loader.h"

#include <string>
#include <utility>

#include "ash/constants/ash_switches.h"
#include "base/callback_helpers.h"
#include "base/command_line.h"
#include "base/metrics/histogram_macros.h"
#include "chromeos/services/machine_learning/public/cpp/service_connection.h"
#include "third_party/cros_system_api/dbus/service_constants.h"

namespace ash {
namespace machine_learning {
namespace {

using ::chromeos::machine_learning::mojom::HandwritingRecognizerSpecPtr;
using ::chromeos::machine_learning::mojom::LoadHandwritingModelResult;
using HandwritingRecognizer = mojo::PendingReceiver<
    ::chromeos::machine_learning::mojom::HandwritingRecognizer>;
using LoadHandwritingModelCallback = ::chromeos::machine_learning::mojom::
    MachineLearningService::LoadHandwritingModelCallback;

// Records CrOSActionRecorder event.
void RecordLoadHandwritingModelResult(const LoadHandwritingModelResult val) {
  UMA_HISTOGRAM_ENUMERATION(
      "MachineLearningService.HandwritingModel.LoadModelResult.Event", val,
      LoadHandwritingModelResult::LOAD_MODEL_FILES_ERROR);
}

constexpr char kLibHandwritingDlcId[] = "libhandwriting";
// A list of supported language code.
constexpr char kLanguageCodeEn[] = "en";
constexpr char kLanguageCodeGesture[] = "gesture_in_context";

// Returns whether the `value` is set for command line switch
// kOndeviceHandwritingSwitch.
bool HandwritingSwitchHasValue(const std::string& value) {
  base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
  return command_line->HasSwitch(ash::switches::kOndeviceHandwritingSwitch) &&
         command_line->GetSwitchValueASCII(
             ash::switches::kOndeviceHandwritingSwitch) == value;
}

// Returns true if switch kOndeviceHandwritingSwitch is set to use_rootfs.
bool IsLibHandwritingRootfsEnabled() {
  return HandwritingSwitchHasValue("use_rootfs");
}

// Returns true if switch kOndeviceHandwritingSwitch is set to use_dlc.
bool IsLibHandwritingDlcEnabled() {
  return HandwritingSwitchHasValue("use_dlc");
}

// Called when InstallDlc completes.
// Returns an error if the `result.error` is not dlcservice::kErrorNone.
// Calls mlservice to LoadHandwritingModel otherwise.
void OnInstallDlcComplete(
    HandwritingRecognizerSpecPtr spec,
    HandwritingRecognizer receiver,
    LoadHandwritingModelCallback callback,
    const chromeos::DlcserviceClient::InstallResult& result) {
  // Call LoadHandwritingModelWithSpec if no error was found.
  if (result.error == dlcservice::kErrorNone) {
    chromeos::machine_learning::ServiceConnection::GetInstance()
        ->GetMachineLearningService()
        .LoadHandwritingModel(std::move(spec), std::move(receiver),
                              std::move(callback));
    return;
  }

  RecordLoadHandwritingModelResult(
      LoadHandwritingModelResult::DLC_INSTALL_ERROR);
  std::move(callback).Run(LoadHandwritingModelResult::DLC_INSTALL_ERROR);
}

// Called when the existing-dlc-list is returned.
// Returns an error if libhandwriting is not in the existing-dlc-list.
// Calls InstallDlc otherwise.
void OnGetExistingDlcsComplete(
    HandwritingRecognizerSpecPtr spec,
    HandwritingRecognizer receiver,
    LoadHandwritingModelCallback callback,
    chromeos::DlcserviceClient* const dlc_client,
    const std::string& err,
    const dlcservice::DlcsWithContent& dlcs_with_content) {
  // Loop over dlcs_with_content, and installs libhandwriting if already exists.
  // Since we don't want to trigger downloading here, we only install(mount)
  // the handwriting dlc if it is already on device.
  for (const auto& dlc_info : dlcs_with_content.dlc_infos()) {
    if (dlc_info.id() == kLibHandwritingDlcId) {
      dlc_client->Install(
          kLibHandwritingDlcId,
          base::BindOnce(&OnInstallDlcComplete, std::move(spec),
                         std::move(receiver), std::move(callback)),
          base::DoNothing());
      return;
    }
  }

  // Returns error if the handwriting dlc is not on the device.
  RecordLoadHandwritingModelResult(
      LoadHandwritingModelResult::DLC_DOES_NOT_EXIST);
  std::move(callback).Run(LoadHandwritingModelResult::DLC_DOES_NOT_EXIST);
}

}  // namespace

void LoadHandwritingModelFromRootfsOrDlc(
    HandwritingRecognizerSpecPtr spec,
    HandwritingRecognizer receiver,
    LoadHandwritingModelCallback callback,
    chromeos::DlcserviceClient* const dlc_client) {
  // Returns FEATURE_NOT_SUPPORTED_ERROR if both rootfs and dlc are not enabled.
  if (!IsLibHandwritingRootfsEnabled() && !IsLibHandwritingDlcEnabled()) {
    RecordLoadHandwritingModelResult(
        LoadHandwritingModelResult::FEATURE_NOT_SUPPORTED_ERROR);
    std::move(callback).Run(
        LoadHandwritingModelResult::FEATURE_NOT_SUPPORTED_ERROR);
    return;
  }

  // Returns LANGUAGE_NOT_SUPPORTED_ERROR if the language is not supported yet.
  if (spec->language != kLanguageCodeEn &&
      spec->language != kLanguageCodeGesture) {
    RecordLoadHandwritingModelResult(
        LoadHandwritingModelResult::LANGUAGE_NOT_SUPPORTED_ERROR);
    std::move(callback).Run(
        LoadHandwritingModelResult::LANGUAGE_NOT_SUPPORTED_ERROR);
    return;
  }

  // Load from rootfs if enabled.
  if (IsLibHandwritingRootfsEnabled()) {
    chromeos::machine_learning::ServiceConnection::GetInstance()
        ->GetMachineLearningService()
        .LoadHandwritingModel(std::move(spec), std::move(receiver),
                              std::move(callback));
    return;
  }

  // Gets existing dlc list and based on the presence of libhandwriting
  // either returns an error or installs the libhandwriting dlc.
  dlc_client->GetExistingDlcs(
      base::BindOnce(&OnGetExistingDlcsComplete, std::move(spec),
                     std::move(receiver), std::move(callback), dlc_client));
}

}  // namespace machine_learning
}  // namespace ash