Upload 29 files
Browse files- 19/DEPS +5 -0
- 19/DIR_METADATA +3 -0
- 19/OWNERS +4 -0
- 19/cpp/ash/handwriting_model_loader.cc +154 -0
- 19/cpp/ash/handwriting_model_loader.h +47 -0
- 19/cpp/ash/handwriting_model_loader_unittest.cc +154 -0
- 19/cpp/ash/service_connection_ash.cc +169 -0
- 19/cpp/lacros/service_connection_lacros.cc +78 -0
- 19/public/cpp/BUILD.gn +84 -0
- 19/public/cpp/fake_service_connection.cc +574 -0
- 19/public/cpp/fake_service_connection.h +383 -0
- 19/public/cpp/service_connection.cc +30 -0
- 19/public/cpp/service_connection.h +77 -0
- 19/public/cpp/service_connection_unittest.cc +800 -0
- 19/public/mojom/BUILD.gn +36 -0
- 19/public/mojom/OWNERS +2 -0
- 19/public/mojom/document_scanner.mojom +76 -0
- 19/public/mojom/document_scanner_param_types.mojom +30 -0
- 19/public/mojom/grammar_checker.mojom +80 -0
- 19/public/mojom/graph_executor.mojom +47 -0
- 19/public/mojom/handwriting_recognizer.mojom +196 -0
- 19/public/mojom/machine_learning_service.mojom +103 -0
- 19/public/mojom/model.mojom +119 -0
- 19/public/mojom/roll_mojoms.sh +70 -0
- 19/public/mojom/soda.mojom +214 -0
- 19/public/mojom/tensor.mojom +64 -0
- 19/public/mojom/text_classifier.mojom +160 -0
- 19/public/mojom/text_suggester.mojom +131 -0
- 19/public/mojom/web_platform_handwriting.mojom +134 -0
19/DEPS
ADDED
@@ -0,0 +1,5 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
include_rules = [
|
2 |
+
"+chromeos/dbus",
|
3 |
+
"+mojo/core/embedder",
|
4 |
+
"+mojo/public",
|
5 |
+
]
|
19/DIR_METADATA
ADDED
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
1 |
+
monorail {
|
2 |
+
component: "UI>ML>Service"
|
3 |
+
}
|
19/OWNERS
ADDED
@@ -0,0 +1,4 @@
|
|
|
|
|
|
|
|
|
|
|
1 | |
2 | |
3 | |
4 |
19/cpp/ash/handwriting_model_loader.cc
ADDED
@@ -0,0 +1,154 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
// Copyright 2020 The Chromium Authors. All rights reserved.
|
2 |
+
// Use of this source code is governed by a BSD-style license that can be
|
3 |
+
// found in the LICENSE file.
|
4 |
+
|
5 |
+
#include "chromeos/services/machine_learning/cpp/ash/handwriting_model_loader.h"
|
6 |
+
|
7 |
+
#include <string>
|
8 |
+
#include <utility>
|
9 |
+
|
10 |
+
#include "ash/constants/ash_switches.h"
|
11 |
+
#include "base/callback_helpers.h"
|
12 |
+
#include "base/command_line.h"
|
13 |
+
#include "base/metrics/histogram_macros.h"
|
14 |
+
#include "chromeos/services/machine_learning/public/cpp/service_connection.h"
|
15 |
+
#include "third_party/cros_system_api/dbus/service_constants.h"
|
16 |
+
|
17 |
+
namespace ash {
|
18 |
+
namespace machine_learning {
|
19 |
+
namespace {
|
20 |
+
|
21 |
+
using ::chromeos::machine_learning::mojom::HandwritingRecognizerSpecPtr;
|
22 |
+
using ::chromeos::machine_learning::mojom::LoadHandwritingModelResult;
|
23 |
+
using HandwritingRecognizer = mojo::PendingReceiver<
|
24 |
+
::chromeos::machine_learning::mojom::HandwritingRecognizer>;
|
25 |
+
using LoadHandwritingModelCallback = ::chromeos::machine_learning::mojom::
|
26 |
+
MachineLearningService::LoadHandwritingModelCallback;
|
27 |
+
|
28 |
+
// Records CrOSActionRecorder event.
|
29 |
+
void RecordLoadHandwritingModelResult(const LoadHandwritingModelResult val) {
|
30 |
+
UMA_HISTOGRAM_ENUMERATION(
|
31 |
+
"MachineLearningService.HandwritingModel.LoadModelResult.Event", val,
|
32 |
+
LoadHandwritingModelResult::LOAD_MODEL_FILES_ERROR);
|
33 |
+
}
|
34 |
+
|
35 |
+
constexpr char kLibHandwritingDlcId[] = "libhandwriting";
|
36 |
+
// A list of supported language code.
|
37 |
+
constexpr char kLanguageCodeEn[] = "en";
|
38 |
+
constexpr char kLanguageCodeGesture[] = "gesture_in_context";
|
39 |
+
|
40 |
+
// Returns whether the `value` is set for command line switch
|
41 |
+
// kOndeviceHandwritingSwitch.
|
42 |
+
bool HandwritingSwitchHasValue(const std::string& value) {
|
43 |
+
base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
|
44 |
+
return command_line->HasSwitch(ash::switches::kOndeviceHandwritingSwitch) &&
|
45 |
+
command_line->GetSwitchValueASCII(
|
46 |
+
ash::switches::kOndeviceHandwritingSwitch) == value;
|
47 |
+
}
|
48 |
+
|
49 |
+
// Returns true if switch kOndeviceHandwritingSwitch is set to use_rootfs.
|
50 |
+
bool IsLibHandwritingRootfsEnabled() {
|
51 |
+
return HandwritingSwitchHasValue("use_rootfs");
|
52 |
+
}
|
53 |
+
|
54 |
+
// Returns true if switch kOndeviceHandwritingSwitch is set to use_dlc.
|
55 |
+
bool IsLibHandwritingDlcEnabled() {
|
56 |
+
return HandwritingSwitchHasValue("use_dlc");
|
57 |
+
}
|
58 |
+
|
59 |
+
// Called when InstallDlc completes.
|
60 |
+
// Returns an error if the `result.error` is not dlcservice::kErrorNone.
|
61 |
+
// Calls mlservice to LoadHandwritingModel otherwise.
|
62 |
+
void OnInstallDlcComplete(
|
63 |
+
HandwritingRecognizerSpecPtr spec,
|
64 |
+
HandwritingRecognizer receiver,
|
65 |
+
LoadHandwritingModelCallback callback,
|
66 |
+
const chromeos::DlcserviceClient::InstallResult& result) {
|
67 |
+
// Call LoadHandwritingModelWithSpec if no error was found.
|
68 |
+
if (result.error == dlcservice::kErrorNone) {
|
69 |
+
chromeos::machine_learning::ServiceConnection::GetInstance()
|
70 |
+
->GetMachineLearningService()
|
71 |
+
.LoadHandwritingModel(std::move(spec), std::move(receiver),
|
72 |
+
std::move(callback));
|
73 |
+
return;
|
74 |
+
}
|
75 |
+
|
76 |
+
RecordLoadHandwritingModelResult(
|
77 |
+
LoadHandwritingModelResult::DLC_INSTALL_ERROR);
|
78 |
+
std::move(callback).Run(LoadHandwritingModelResult::DLC_INSTALL_ERROR);
|
79 |
+
}
|
80 |
+
|
81 |
+
// Called when the existing-dlc-list is returned.
|
82 |
+
// Returns an error if libhandwriting is not in the existing-dlc-list.
|
83 |
+
// Calls InstallDlc otherwise.
|
84 |
+
void OnGetExistingDlcsComplete(
|
85 |
+
HandwritingRecognizerSpecPtr spec,
|
86 |
+
HandwritingRecognizer receiver,
|
87 |
+
LoadHandwritingModelCallback callback,
|
88 |
+
chromeos::DlcserviceClient* const dlc_client,
|
89 |
+
const std::string& err,
|
90 |
+
const dlcservice::DlcsWithContent& dlcs_with_content) {
|
91 |
+
// Loop over dlcs_with_content, and installs libhandwriting if already exists.
|
92 |
+
// Since we don't want to trigger downloading here, we only install(mount)
|
93 |
+
// the handwriting dlc if it is already on device.
|
94 |
+
for (const auto& dlc_info : dlcs_with_content.dlc_infos()) {
|
95 |
+
if (dlc_info.id() == kLibHandwritingDlcId) {
|
96 |
+
dlc_client->Install(
|
97 |
+
kLibHandwritingDlcId,
|
98 |
+
base::BindOnce(&OnInstallDlcComplete, std::move(spec),
|
99 |
+
std::move(receiver), std::move(callback)),
|
100 |
+
base::DoNothing());
|
101 |
+
return;
|
102 |
+
}
|
103 |
+
}
|
104 |
+
|
105 |
+
// Returns error if the handwriting dlc is not on the device.
|
106 |
+
RecordLoadHandwritingModelResult(
|
107 |
+
LoadHandwritingModelResult::DLC_DOES_NOT_EXIST);
|
108 |
+
std::move(callback).Run(LoadHandwritingModelResult::DLC_DOES_NOT_EXIST);
|
109 |
+
}
|
110 |
+
|
111 |
+
} // namespace
|
112 |
+
|
113 |
+
void LoadHandwritingModelFromRootfsOrDlc(
|
114 |
+
HandwritingRecognizerSpecPtr spec,
|
115 |
+
HandwritingRecognizer receiver,
|
116 |
+
LoadHandwritingModelCallback callback,
|
117 |
+
chromeos::DlcserviceClient* const dlc_client) {
|
118 |
+
// Returns FEATURE_NOT_SUPPORTED_ERROR if both rootfs and dlc are not enabled.
|
119 |
+
if (!IsLibHandwritingRootfsEnabled() && !IsLibHandwritingDlcEnabled()) {
|
120 |
+
RecordLoadHandwritingModelResult(
|
121 |
+
LoadHandwritingModelResult::FEATURE_NOT_SUPPORTED_ERROR);
|
122 |
+
std::move(callback).Run(
|
123 |
+
LoadHandwritingModelResult::FEATURE_NOT_SUPPORTED_ERROR);
|
124 |
+
return;
|
125 |
+
}
|
126 |
+
|
127 |
+
// Returns LANGUAGE_NOT_SUPPORTED_ERROR if the language is not supported yet.
|
128 |
+
if (spec->language != kLanguageCodeEn &&
|
129 |
+
spec->language != kLanguageCodeGesture) {
|
130 |
+
RecordLoadHandwritingModelResult(
|
131 |
+
LoadHandwritingModelResult::LANGUAGE_NOT_SUPPORTED_ERROR);
|
132 |
+
std::move(callback).Run(
|
133 |
+
LoadHandwritingModelResult::LANGUAGE_NOT_SUPPORTED_ERROR);
|
134 |
+
return;
|
135 |
+
}
|
136 |
+
|
137 |
+
// Load from rootfs if enabled.
|
138 |
+
if (IsLibHandwritingRootfsEnabled()) {
|
139 |
+
chromeos::machine_learning::ServiceConnection::GetInstance()
|
140 |
+
->GetMachineLearningService()
|
141 |
+
.LoadHandwritingModel(std::move(spec), std::move(receiver),
|
142 |
+
std::move(callback));
|
143 |
+
return;
|
144 |
+
}
|
145 |
+
|
146 |
+
// Gets existing dlc list and based on the presence of libhandwriting
|
147 |
+
// either returns an error or installs the libhandwriting dlc.
|
148 |
+
dlc_client->GetExistingDlcs(
|
149 |
+
base::BindOnce(&OnGetExistingDlcsComplete, std::move(spec),
|
150 |
+
std::move(receiver), std::move(callback), dlc_client));
|
151 |
+
}
|
152 |
+
|
153 |
+
} // namespace machine_learning
|
154 |
+
} // namespace ash
|
19/cpp/ash/handwriting_model_loader.h
ADDED
@@ -0,0 +1,47 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
// Copyright 2020 The Chromium Authors. All rights reserved.
|
2 |
+
// Use of this source code is governed by a BSD-style license that can be
|
3 |
+
// found in the LICENSE file.
|
4 |
+
|
5 |
+
#ifndef CHROMEOS_SERVICES_MACHINE_LEARNING_CPP_ASH_HANDWRITING_MODEL_LOADER_H_
|
6 |
+
#define CHROMEOS_SERVICES_MACHINE_LEARNING_CPP_ASH_HANDWRITING_MODEL_LOADER_H_
|
7 |
+
|
8 |
+
#include "chromeos/dbus/dlcservice/dlcservice_client.h"
|
9 |
+
#include "chromeos/services/machine_learning/public/mojom/handwriting_recognizer.mojom.h"
|
10 |
+
#include "chromeos/services/machine_learning/public/mojom/machine_learning_service.mojom.h"
|
11 |
+
#include "mojo/public/cpp/bindings/pending_receiver.h"
|
12 |
+
|
13 |
+
namespace ash {
|
14 |
+
namespace machine_learning {
|
15 |
+
|
16 |
+
// Helper function decides either to load handwriting model from rootfs or dlc.
|
17 |
+
// New Handwriting clients should call this helper instead of calling
|
18 |
+
// ServiceConnection::GetInstance()->LoadHandwritingModel.
|
19 |
+
// Three typical examples of the callstack are:
|
20 |
+
// Case 1: handwriting in enabled on rootfs.
|
21 |
+
// client calls LoadHandwritingModelFromRootfsOrDlc("en", receiver, callback)
|
22 |
+
// which calls LoadHandwritingModel -> handwriting model loaded from rootfs.
|
23 |
+
// Case 2: handwriting is enabled for dlc and dlc is already on the device.
|
24 |
+
// client calls LoadHandwritingModelFromRootfsOrDlc("en", receiver, callback)
|
25 |
+
// which calls -> GetExistingDlcs -> libhandwriting dlc already exists
|
26 |
+
// -> InstallDlc -> LoadHandwritingModel
|
27 |
+
// The correct handwriting model will be loaded and bond to the receiver.
|
28 |
+
// Case 3: handwriting is enabled for dlc and dlc is not on the device yet.
|
29 |
+
// client calls LoadHandwritingModelFromRootfsOrDlc("en", receiver, callback)
|
30 |
+
// which calls -> GetExistingDlcs -> NO libhandwriting dlc exists
|
31 |
+
// -> Return error DLC_NOT_EXISTED.
|
32 |
+
// Then it will be the client's duty to install the dlc and then calls
|
33 |
+
// LoadHandwritingModelFromRootfsOrDlc("en", receiver, callback) again.
|
34 |
+
//
|
35 |
+
// `dlc_client` should only be replaced with non-default value in unit tests.
|
36 |
+
void LoadHandwritingModelFromRootfsOrDlc(
|
37 |
+
chromeos::machine_learning::mojom::HandwritingRecognizerSpecPtr spec,
|
38 |
+
mojo::PendingReceiver<
|
39 |
+
chromeos::machine_learning::mojom::HandwritingRecognizer> receiver,
|
40 |
+
chromeos::machine_learning::mojom::MachineLearningService::
|
41 |
+
LoadHandwritingModelCallback callback,
|
42 |
+
chromeos::DlcserviceClient* dlc_client = chromeos::DlcserviceClient::Get());
|
43 |
+
|
44 |
+
} // namespace machine_learning
|
45 |
+
} // namespace ash
|
46 |
+
|
47 |
+
#endif // CHROMEOS_SERVICES_MACHINE_LEARNING_CPP_ASH_HANDWRITING_MODEL_LOADER_H_
|
19/cpp/ash/handwriting_model_loader_unittest.cc
ADDED
@@ -0,0 +1,154 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
// Copyright 2020 The Chromium Authors. All rights reserved.
|
2 |
+
// Use of this source code is governed by a BSD-style license that can be
|
3 |
+
// found in the LICENSE file.
|
4 |
+
|
5 |
+
#include "chromeos/services/machine_learning/cpp/ash/handwriting_model_loader.h"
|
6 |
+
|
7 |
+
#include <string>
|
8 |
+
|
9 |
+
#include "ash/constants/ash_switches.h"
|
10 |
+
#include "base/bind.h"
|
11 |
+
#include "base/command_line.h"
|
12 |
+
#include "base/run_loop.h"
|
13 |
+
#include "base/test/scoped_command_line.h"
|
14 |
+
#include "base/test/task_environment.h"
|
15 |
+
#include "chromeos/dbus/dlcservice/fake_dlcservice_client.h"
|
16 |
+
#include "chromeos/services/machine_learning/public/cpp/fake_service_connection.h"
|
17 |
+
#include "testing/gtest/include/gtest/gtest.h"
|
18 |
+
#include "third_party/cros_system_api/dbus/service_constants.h"
|
19 |
+
|
20 |
+
namespace ash {
|
21 |
+
namespace machine_learning {
|
22 |
+
|
23 |
+
using ::base::test::ScopedCommandLine;
|
24 |
+
using ::base::test::TaskEnvironment;
|
25 |
+
using ::chromeos::machine_learning::mojom::LoadHandwritingModelResult;
|
26 |
+
|
27 |
+
constexpr char kLibHandwritingDlcId[] = "libhandwriting";
|
28 |
+
|
29 |
+
class HandwritingModelLoaderTest : public testing::Test {
|
30 |
+
protected:
|
31 |
+
void SetUp() override {
|
32 |
+
chromeos::machine_learning::ServiceConnection::
|
33 |
+
UseFakeServiceConnectionForTesting(&fake_service_connection_);
|
34 |
+
chromeos::machine_learning::ServiceConnection::GetInstance()->Initialize();
|
35 |
+
result_ = LoadHandwritingModelResult::DEPRECATED_MODEL_SPEC_ERROR;
|
36 |
+
language_ = "en";
|
37 |
+
}
|
38 |
+
|
39 |
+
// Callback that called when loader_->Load() is over to save the returned
|
40 |
+
// result.
|
41 |
+
void OnHandwritingModelLoaderComplete(
|
42 |
+
const LoadHandwritingModelResult result) {
|
43 |
+
result_ = result;
|
44 |
+
}
|
45 |
+
|
46 |
+
// Runs loader_->Load() and check the returned result as expected.
|
47 |
+
void ExpectLoadHandwritingModelResult(
|
48 |
+
const LoadHandwritingModelResult expected_result) {
|
49 |
+
LoadHandwritingModelFromRootfsOrDlc(
|
50 |
+
chromeos::machine_learning::mojom::HandwritingRecognizerSpec::New(
|
51 |
+
language_),
|
52 |
+
recognizer_.BindNewPipeAndPassReceiver(),
|
53 |
+
base::BindOnce(
|
54 |
+
&HandwritingModelLoaderTest::OnHandwritingModelLoaderComplete,
|
55 |
+
base::Unretained(this)),
|
56 |
+
&fake_client_);
|
57 |
+
|
58 |
+
base::RunLoop().RunUntilIdle();
|
59 |
+
EXPECT_EQ(result_, expected_result);
|
60 |
+
}
|
61 |
+
|
62 |
+
void SetLanguage(const std::string& language) { language_ = language; }
|
63 |
+
|
64 |
+
// Creates a dlc list with one dlc inside.
|
65 |
+
void AddDlcsWithContent(const std::string& dlc_id) {
|
66 |
+
dlcservice::DlcsWithContent dlcs_with_content;
|
67 |
+
dlcs_with_content.add_dlc_infos()->set_id(dlc_id);
|
68 |
+
fake_client_.set_dlcs_with_content(dlcs_with_content);
|
69 |
+
}
|
70 |
+
|
71 |
+
// Sets InstallDlc error.
|
72 |
+
void SetInstallError(const std::string& error) {
|
73 |
+
fake_client_.set_install_error(error);
|
74 |
+
fake_client_.set_install_root_path("/any-path");
|
75 |
+
}
|
76 |
+
|
77 |
+
// Sets "ondevice_handwriting" value.
|
78 |
+
void SetSwitchValue(const std::string& switch_value) {
|
79 |
+
base::CommandLine::ForCurrentProcess()->AppendSwitchASCII(
|
80 |
+
ash::switches::kOndeviceHandwritingSwitch, switch_value);
|
81 |
+
}
|
82 |
+
|
83 |
+
private:
|
84 |
+
TaskEnvironment task_environment_{
|
85 |
+
TaskEnvironment::MainThreadType::DEFAULT,
|
86 |
+
TaskEnvironment::ThreadPoolExecutionMode::QUEUED};
|
87 |
+
ScopedCommandLine scoped_command_line_;
|
88 |
+
chromeos::FakeDlcserviceClient fake_client_;
|
89 |
+
chromeos::machine_learning::FakeServiceConnectionImpl
|
90 |
+
fake_service_connection_;
|
91 |
+
LoadHandwritingModelResult result_;
|
92 |
+
std::string language_;
|
93 |
+
mojo::Remote<chromeos::machine_learning::mojom::HandwritingRecognizer>
|
94 |
+
recognizer_;
|
95 |
+
};
|
96 |
+
|
97 |
+
TEST_F(HandwritingModelLoaderTest, HandwritingNotEnabled) {
|
98 |
+
SetSwitchValue("random_string");
|
99 |
+
|
100 |
+
// Random switch value should return FEATURE_NOT_SUPPORTED_ERROR.
|
101 |
+
ExpectLoadHandwritingModelResult(
|
102 |
+
LoadHandwritingModelResult::FEATURE_NOT_SUPPORTED_ERROR);
|
103 |
+
}
|
104 |
+
|
105 |
+
TEST_F(HandwritingModelLoaderTest, LoadingWithInvalidLanguage) {
|
106 |
+
SetSwitchValue("use_rootfs");
|
107 |
+
|
108 |
+
SetLanguage("random string as language");
|
109 |
+
|
110 |
+
// Random language code should return LANGUAGE_NOT_SUPPORTED_ERROR.
|
111 |
+
ExpectLoadHandwritingModelResult(
|
112 |
+
LoadHandwritingModelResult::LANGUAGE_NOT_SUPPORTED_ERROR);
|
113 |
+
}
|
114 |
+
|
115 |
+
TEST_F(HandwritingModelLoaderTest, LoadingWithUseRootfs) {
|
116 |
+
SetSwitchValue("use_rootfs");
|
117 |
+
|
118 |
+
// Load from rootfs should return success.
|
119 |
+
ExpectLoadHandwritingModelResult(LoadHandwritingModelResult::OK);
|
120 |
+
}
|
121 |
+
|
122 |
+
TEST_F(HandwritingModelLoaderTest, LoadingWithoutDlcOnDevice) {
|
123 |
+
SetSwitchValue("use_dlc");
|
124 |
+
|
125 |
+
AddDlcsWithContent("random dlc-id");
|
126 |
+
|
127 |
+
// Random dlc id should return DLC_DOES_NOT_EXIST.
|
128 |
+
ExpectLoadHandwritingModelResult(
|
129 |
+
LoadHandwritingModelResult::DLC_DOES_NOT_EXIST);
|
130 |
+
}
|
131 |
+
|
132 |
+
TEST_F(HandwritingModelLoaderTest, DlcInstalledWithError) {
|
133 |
+
SetSwitchValue("use_dlc");
|
134 |
+
|
135 |
+
AddDlcsWithContent(kLibHandwritingDlcId);
|
136 |
+
SetInstallError("random error");
|
137 |
+
|
138 |
+
// InstallDlc error should return DLC_INSTALL_ERROR.
|
139 |
+
ExpectLoadHandwritingModelResult(
|
140 |
+
LoadHandwritingModelResult::DLC_INSTALL_ERROR);
|
141 |
+
}
|
142 |
+
|
143 |
+
TEST_F(HandwritingModelLoaderTest, DlcInstalledWithoutError) {
|
144 |
+
SetSwitchValue("use_dlc");
|
145 |
+
|
146 |
+
AddDlcsWithContent(kLibHandwritingDlcId);
|
147 |
+
SetInstallError(dlcservice::kErrorNone);
|
148 |
+
|
149 |
+
// InstallDlc without an error should return success.
|
150 |
+
ExpectLoadHandwritingModelResult(LoadHandwritingModelResult::OK);
|
151 |
+
}
|
152 |
+
|
153 |
+
} // namespace machine_learning
|
154 |
+
} // namespace ash
|
19/cpp/ash/service_connection_ash.cc
ADDED
@@ -0,0 +1,169 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
// Copyright 2021 The Chromium Authors. All rights reserved.
|
2 |
+
// Use of this source code is governed by a BSD-style license that can be
|
3 |
+
// found in the LICENSE file.
|
4 |
+
|
5 |
+
#include "chromeos/services/machine_learning/public/cpp/service_connection.h"
|
6 |
+
|
7 |
+
#include <utility>
|
8 |
+
|
9 |
+
#include "base/bind.h"
|
10 |
+
#include "base/component_export.h"
|
11 |
+
#include "base/no_destructor.h"
|
12 |
+
#include "base/sequence_checker.h"
|
13 |
+
#include "base/task/sequenced_task_runner.h"
|
14 |
+
#include "chromeos/dbus/machine_learning/machine_learning_client.h"
|
15 |
+
#include "chromeos/services/machine_learning/public/mojom/machine_learning_service.mojom.h"
|
16 |
+
#include "mojo/public/cpp/bindings/remote.h"
|
17 |
+
#include "mojo/public/cpp/platform/platform_channel.h"
|
18 |
+
#include "mojo/public/cpp/system/invitation.h"
|
19 |
+
#include "third_party/cros_system_api/dbus/service_constants.h"
|
20 |
+
|
21 |
+
namespace ash {
|
22 |
+
namespace machine_learning {
|
23 |
+
|
24 |
+
namespace {
|
25 |
+
|
26 |
+
// Real Impl of ServiceConnection
|
27 |
+
class COMPONENT_EXPORT(CHROMEOS_MLSERVICE) ServiceConnectionAsh
|
28 |
+
: public chromeos::machine_learning::ServiceConnection {
|
29 |
+
public:
|
30 |
+
ServiceConnectionAsh();
|
31 |
+
ServiceConnectionAsh(const ServiceConnectionAsh&) = delete;
|
32 |
+
ServiceConnectionAsh& operator=(const ServiceConnectionAsh&) = delete;
|
33 |
+
|
34 |
+
~ServiceConnectionAsh() override;
|
35 |
+
|
36 |
+
chromeos::machine_learning::mojom::MachineLearningService&
|
37 |
+
GetMachineLearningService() override;
|
38 |
+
|
39 |
+
void BindMachineLearningService(
|
40 |
+
mojo::PendingReceiver<
|
41 |
+
chromeos::machine_learning::mojom::MachineLearningService> receiver)
|
42 |
+
override;
|
43 |
+
|
44 |
+
void Initialize() override;
|
45 |
+
|
46 |
+
private:
|
47 |
+
// Binds the primordial, top-level interface |machine_learning_service_| to an
|
48 |
+
// implementation in the ML Service daemon, if it is not already bound. The
|
49 |
+
// binding is accomplished via D-Bus bootstrap.
|
50 |
+
void BindPrimordialMachineLearningServiceIfNeeded();
|
51 |
+
|
52 |
+
// Mojo disconnect handler. Resets |machine_learning_service_|, which
|
53 |
+
// will be reconnected upon next use.
|
54 |
+
void OnMojoDisconnect();
|
55 |
+
|
56 |
+
// Response callback for MlClient::BootstrapMojoConnection.
|
57 |
+
void OnBootstrapMojoConnectionResponse(bool success);
|
58 |
+
|
59 |
+
mojo::Remote<chromeos::machine_learning::mojom::MachineLearningService>
|
60 |
+
machine_learning_service_;
|
61 |
+
scoped_refptr<base::SequencedTaskRunner> task_runner_;
|
62 |
+
|
63 |
+
SEQUENCE_CHECKER(sequence_checker_);
|
64 |
+
};
|
65 |
+
|
66 |
+
ServiceConnectionAsh::ServiceConnectionAsh() {
|
67 |
+
DETACH_FROM_SEQUENCE(sequence_checker_);
|
68 |
+
}
|
69 |
+
|
70 |
+
ServiceConnectionAsh::~ServiceConnectionAsh() = default;
|
71 |
+
|
72 |
+
chromeos::machine_learning::mojom::MachineLearningService&
|
73 |
+
ServiceConnectionAsh::GetMachineLearningService() {
|
74 |
+
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
|
75 |
+
DCHECK(task_runner_)
|
76 |
+
<< "Call Initialize before first use of ServiceConnection.";
|
77 |
+
BindPrimordialMachineLearningServiceIfNeeded();
|
78 |
+
return *machine_learning_service_.get();
|
79 |
+
}
|
80 |
+
|
81 |
+
void ServiceConnectionAsh::BindMachineLearningService(
|
82 |
+
mojo::PendingReceiver<
|
83 |
+
chromeos::machine_learning::mojom::MachineLearningService> receiver) {
|
84 |
+
DCHECK(task_runner_)
|
85 |
+
<< "Call Initialize before first use of ServiceConnection.";
|
86 |
+
if (!task_runner_->RunsTasksInCurrentSequence()) {
|
87 |
+
task_runner_->PostTask(
|
88 |
+
FROM_HERE,
|
89 |
+
base::BindOnce(&ServiceConnectionAsh::BindMachineLearningService,
|
90 |
+
base::Unretained(this), std::move(receiver)));
|
91 |
+
return;
|
92 |
+
}
|
93 |
+
|
94 |
+
GetMachineLearningService().Clone(std::move(receiver));
|
95 |
+
}
|
96 |
+
|
97 |
+
void ServiceConnectionAsh::Initialize() {
|
98 |
+
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
|
99 |
+
DCHECK(!task_runner_) << "Initialize must be called only once.";
|
100 |
+
|
101 |
+
task_runner_ = base::SequencedTaskRunnerHandle::Get();
|
102 |
+
}
|
103 |
+
|
104 |
+
void ServiceConnectionAsh::BindPrimordialMachineLearningServiceIfNeeded() {
|
105 |
+
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
|
106 |
+
if (machine_learning_service_) {
|
107 |
+
return;
|
108 |
+
}
|
109 |
+
|
110 |
+
mojo::PlatformChannel platform_channel;
|
111 |
+
|
112 |
+
// Prepare a Mojo invitation to send through |platform_channel|.
|
113 |
+
mojo::OutgoingInvitation invitation;
|
114 |
+
// Include an initial Mojo pipe in the invitation.
|
115 |
+
mojo::ScopedMessagePipeHandle pipe =
|
116 |
+
invitation.AttachMessagePipe(ml::kBootstrapMojoConnectionChannelToken);
|
117 |
+
mojo::OutgoingInvitation::Send(std::move(invitation),
|
118 |
+
base::kNullProcessHandle,
|
119 |
+
platform_channel.TakeLocalEndpoint());
|
120 |
+
|
121 |
+
// Bind our end of |pipe| to our mojo::Remote<MachineLearningService>. The
|
122 |
+
// daemon should bind its end to a MachineLearningService implementation.
|
123 |
+
machine_learning_service_.Bind(
|
124 |
+
mojo::PendingRemote<
|
125 |
+
chromeos::machine_learning::mojom::MachineLearningService>(
|
126 |
+
std::move(pipe), 0u /* version */));
|
127 |
+
machine_learning_service_.set_disconnect_handler(base::BindOnce(
|
128 |
+
&ServiceConnectionAsh::OnMojoDisconnect, base::Unretained(this)));
|
129 |
+
|
130 |
+
// Send the file descriptor for the other end of |platform_channel| to the
|
131 |
+
// ML service daemon over D-Bus.
|
132 |
+
chromeos::MachineLearningClient::Get()->BootstrapMojoConnection(
|
133 |
+
platform_channel.TakeRemoteEndpoint().TakePlatformHandle().TakeFD(),
|
134 |
+
base::BindOnce(&ServiceConnectionAsh::OnBootstrapMojoConnectionResponse,
|
135 |
+
base::Unretained(this)));
|
136 |
+
}
|
137 |
+
|
138 |
+
void ServiceConnectionAsh::OnMojoDisconnect() {
|
139 |
+
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
|
140 |
+
// Connection errors are not expected so log a warning.
|
141 |
+
LOG(WARNING) << "ML Service Mojo connection closed";
|
142 |
+
machine_learning_service_.reset();
|
143 |
+
}
|
144 |
+
|
145 |
+
void ServiceConnectionAsh::OnBootstrapMojoConnectionResponse(
|
146 |
+
const bool success) {
|
147 |
+
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
|
148 |
+
if (!success) {
|
149 |
+
LOG(WARNING) << "BootstrapMojoConnection D-Bus call failed";
|
150 |
+
machine_learning_service_.reset();
|
151 |
+
}
|
152 |
+
}
|
153 |
+
|
154 |
+
} // namespace
|
155 |
+
|
156 |
+
} // namespace machine_learning
|
157 |
+
} // namespace ash
|
158 |
+
|
159 |
+
namespace chromeos {
|
160 |
+
namespace machine_learning {
|
161 |
+
|
162 |
+
ServiceConnection* ServiceConnection::CreateRealInstance() {
|
163 |
+
static base::NoDestructor<ash::machine_learning::ServiceConnectionAsh>
|
164 |
+
service_connection;
|
165 |
+
return service_connection.get();
|
166 |
+
}
|
167 |
+
|
168 |
+
} // namespace machine_learning
|
169 |
+
} // namespace chromeos
|
19/cpp/lacros/service_connection_lacros.cc
ADDED
@@ -0,0 +1,78 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
// Copyright 2021 The Chromium Authors. All rights reserved.
|
2 |
+
// Use of this source code is governed by a BSD-style license that can be
|
3 |
+
// found in the LICENSE file.
|
4 |
+
|
5 |
+
#include "chromeos/services/machine_learning/public/cpp/service_connection.h"
|
6 |
+
|
7 |
+
#include <utility>
|
8 |
+
|
9 |
+
#include "base/component_export.h"
|
10 |
+
#include "base/no_destructor.h"
|
11 |
+
#include "chromeos/lacros/lacros_service.h"
|
12 |
+
#include "chromeos/services/machine_learning/public/mojom/machine_learning_service.mojom.h"
|
13 |
+
#include "mojo/public/cpp/bindings/remote.h"
|
14 |
+
|
15 |
+
namespace lacros {
|
16 |
+
namespace machine_learning {
|
17 |
+
namespace {
|
18 |
+
|
19 |
+
// Real Impl of ServiceConnection
|
20 |
+
class COMPONENT_EXPORT(CHROMEOS_MLSERVICE) ServiceConnectionLacros
|
21 |
+
: public chromeos::machine_learning::ServiceConnection {
|
22 |
+
public:
|
23 |
+
ServiceConnectionLacros();
|
24 |
+
ServiceConnectionLacros(const ServiceConnectionLacros&) = delete;
|
25 |
+
ServiceConnectionLacros& operator=(const ServiceConnectionLacros&) = delete;
|
26 |
+
|
27 |
+
~ServiceConnectionLacros() override;
|
28 |
+
|
29 |
+
chromeos::machine_learning::mojom::MachineLearningService&
|
30 |
+
GetMachineLearningService() override;
|
31 |
+
|
32 |
+
void BindMachineLearningService(
|
33 |
+
mojo::PendingReceiver<
|
34 |
+
chromeos::machine_learning::mojom::MachineLearningService> receiver)
|
35 |
+
override;
|
36 |
+
|
37 |
+
void Initialize() override;
|
38 |
+
};
|
39 |
+
|
40 |
+
ServiceConnectionLacros::ServiceConnectionLacros() = default;
|
41 |
+
|
42 |
+
ServiceConnectionLacros::~ServiceConnectionLacros() = default;
|
43 |
+
|
44 |
+
chromeos::machine_learning::mojom::MachineLearningService&
|
45 |
+
ServiceConnectionLacros::GetMachineLearningService() {
|
46 |
+
mojo::Remote<chromeos::machine_learning::mojom::MachineLearningService>&
|
47 |
+
machine_learning_service_remote =
|
48 |
+
chromeos::LacrosService::Get()
|
49 |
+
->GetRemote<
|
50 |
+
chromeos::machine_learning::mojom::MachineLearningService>();
|
51 |
+
return *machine_learning_service_remote.get();
|
52 |
+
}
|
53 |
+
|
54 |
+
void ServiceConnectionLacros::BindMachineLearningService(
|
55 |
+
mojo::PendingReceiver<
|
56 |
+
chromeos::machine_learning::mojom::MachineLearningService> receiver) {
|
57 |
+
chromeos::LacrosService::Get()->BindMachineLearningService(
|
58 |
+
std::move(receiver));
|
59 |
+
}
|
60 |
+
|
61 |
+
void ServiceConnectionLacros::Initialize() {}
|
62 |
+
|
63 |
+
} // namespace
|
64 |
+
|
65 |
+
} // namespace machine_learning
|
66 |
+
} // namespace lacros
|
67 |
+
|
68 |
+
namespace chromeos {
|
69 |
+
namespace machine_learning {
|
70 |
+
|
71 |
+
ServiceConnection* ServiceConnection::CreateRealInstance() {
|
72 |
+
static base::NoDestructor<lacros::machine_learning::ServiceConnectionLacros>
|
73 |
+
service_connection;
|
74 |
+
return service_connection.get();
|
75 |
+
}
|
76 |
+
|
77 |
+
} // namespace machine_learning
|
78 |
+
} // namespace chromeos
|
19/public/cpp/BUILD.gn
ADDED
@@ -0,0 +1,84 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
# Copyright 2018 The Chromium Authors. All rights reserved.
|
2 |
+
# Use of this source code is governed by a BSD-style license that can be
|
3 |
+
# found in the LICENSE file.
|
4 |
+
|
5 |
+
import("//build/config/chromeos/ui_mode.gni")
|
6 |
+
|
7 |
+
assert(is_chromeos, "Non-ChromeOS builds cannot depend on //chromeos")
|
8 |
+
|
9 |
+
source_set("cpp") {
|
10 |
+
sources = [
|
11 |
+
"service_connection.cc",
|
12 |
+
"service_connection.h",
|
13 |
+
]
|
14 |
+
defines = [ "IS_CHROMEOS_MLSERVICE_IMPL" ]
|
15 |
+
deps = [
|
16 |
+
"//base",
|
17 |
+
"//chromeos/services/machine_learning/public/mojom",
|
18 |
+
]
|
19 |
+
|
20 |
+
if (is_chromeos_ash) {
|
21 |
+
sources += [
|
22 |
+
"../../cpp/ash/handwriting_model_loader.cc",
|
23 |
+
"../../cpp/ash/handwriting_model_loader.h",
|
24 |
+
"../../cpp/ash/service_connection_ash.cc",
|
25 |
+
]
|
26 |
+
deps += [
|
27 |
+
"//ash/constants:constants",
|
28 |
+
"//chromeos/dbus/dlcservice",
|
29 |
+
"//chromeos/dbus/dlcservice:dlcservice_proto",
|
30 |
+
"//chromeos/dbus/machine_learning",
|
31 |
+
]
|
32 |
+
} else if (is_chromeos_lacros) {
|
33 |
+
sources += [ "../../cpp/lacros/service_connection_lacros.cc" ]
|
34 |
+
deps += [
|
35 |
+
"//chromeos/lacros",
|
36 |
+
"//mojo/public/cpp/bindings",
|
37 |
+
"//skia",
|
38 |
+
]
|
39 |
+
}
|
40 |
+
}
|
41 |
+
|
42 |
+
component("stub") {
|
43 |
+
sources = [
|
44 |
+
"fake_service_connection.cc",
|
45 |
+
"fake_service_connection.h",
|
46 |
+
]
|
47 |
+
defines = [ "IS_CHROMEOS_MLSERVICE_IMPL" ]
|
48 |
+
deps = [
|
49 |
+
"//base",
|
50 |
+
"//chromeos/services/machine_learning/public/mojom",
|
51 |
+
"//mojo/public/cpp/bindings",
|
52 |
+
]
|
53 |
+
public_deps = [ ":cpp" ]
|
54 |
+
}
|
55 |
+
|
56 |
+
source_set("unit_tests") {
|
57 |
+
testonly = true
|
58 |
+
sources = [ "service_connection_unittest.cc" ]
|
59 |
+
deps = [
|
60 |
+
":cpp",
|
61 |
+
":stub",
|
62 |
+
"//base/test:test_support",
|
63 |
+
"//chromeos/dbus/machine_learning",
|
64 |
+
"//chromeos/services/machine_learning/public/mojom",
|
65 |
+
"//mojo/core/embedder",
|
66 |
+
"//mojo/public/cpp/bindings",
|
67 |
+
"//testing/gtest",
|
68 |
+
]
|
69 |
+
}
|
70 |
+
|
71 |
+
if (is_chromeos_ash) {
|
72 |
+
source_set("ash_unit_tests") {
|
73 |
+
sources = [ "../../cpp/ash/handwriting_model_loader_unittest.cc" ]
|
74 |
+
testonly = true
|
75 |
+
deps = [
|
76 |
+
":cpp",
|
77 |
+
"//ash/constants:constants",
|
78 |
+
"//base/test:test_support",
|
79 |
+
"//chromeos/dbus/dlcservice",
|
80 |
+
"//chromeos/services/machine_learning/public/cpp:stub",
|
81 |
+
"//testing/gtest",
|
82 |
+
]
|
83 |
+
}
|
84 |
+
}
|
19/public/cpp/fake_service_connection.cc
ADDED
@@ -0,0 +1,574 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
// Copyright 2019 The Chromium Authors. All rights reserved.
|
2 |
+
// Use of this source code is governed by a BSD-style license that can be
|
3 |
+
// found in the LICENSE file.
|
4 |
+
|
5 |
+
#include "chromeos/services/machine_learning/public/cpp/fake_service_connection.h"
|
6 |
+
|
7 |
+
#include <utility>
|
8 |
+
|
9 |
+
#include "base/bind.h"
|
10 |
+
#include "base/notreached.h"
|
11 |
+
#include "third_party/abseil-cpp/absl/types/optional.h"
|
12 |
+
|
13 |
+
namespace chromeos {
|
14 |
+
namespace machine_learning {
|
15 |
+
|
16 |
+
FakeServiceConnectionImpl::FakeServiceConnectionImpl()
|
17 |
+
: output_tensor_(mojom::Tensor::New()),
|
18 |
+
load_handwriting_model_result_(mojom::LoadHandwritingModelResult::OK),
|
19 |
+
load_web_platform_handwriting_model_result_(
|
20 |
+
mojom::LoadHandwritingModelResult::OK),
|
21 |
+
load_model_result_(mojom::LoadModelResult::OK),
|
22 |
+
load_text_classifier_result_(mojom::LoadModelResult::OK),
|
23 |
+
load_soda_result_(mojom::LoadModelResult::OK),
|
24 |
+
create_graph_executor_result_(mojom::CreateGraphExecutorResult::OK),
|
25 |
+
execute_result_(mojom::ExecuteResult::OK),
|
26 |
+
async_mode_(false) {}
|
27 |
+
|
28 |
+
FakeServiceConnectionImpl::~FakeServiceConnectionImpl() {}
|
29 |
+
|
30 |
+
mojom::MachineLearningService&
|
31 |
+
FakeServiceConnectionImpl::GetMachineLearningService() {
|
32 |
+
DCHECK(machine_learning_service_)
|
33 |
+
<< "Call Initialize() before GetMachineLearningService()";
|
34 |
+
return *machine_learning_service_.get();
|
35 |
+
}
|
36 |
+
|
37 |
+
void FakeServiceConnectionImpl::BindMachineLearningService(
|
38 |
+
mojo::PendingReceiver<mojom::MachineLearningService> receiver) {
|
39 |
+
DCHECK(machine_learning_service_)
|
40 |
+
<< "Call Initialize() before BindMachineLearningService()";
|
41 |
+
machine_learning_service_->Clone(std::move(receiver));
|
42 |
+
}
|
43 |
+
|
44 |
+
void FakeServiceConnectionImpl::Clone(
|
45 |
+
mojo::PendingReceiver<mojom::MachineLearningService> receiver) {
|
46 |
+
clone_ml_service_receivers_.Add(this, std::move(receiver));
|
47 |
+
}
|
48 |
+
|
49 |
+
void FakeServiceConnectionImpl::Initialize() {
|
50 |
+
clone_ml_service_receivers_.Add(
|
51 |
+
this, machine_learning_service_.BindNewPipeAndPassReceiver());
|
52 |
+
}
|
53 |
+
|
54 |
+
void FakeServiceConnectionImpl::LoadBuiltinModel(
|
55 |
+
mojom::BuiltinModelSpecPtr spec,
|
56 |
+
mojo::PendingReceiver<mojom::Model> receiver,
|
57 |
+
mojom::MachineLearningService::LoadBuiltinModelCallback callback) {
|
58 |
+
ScheduleCall(base::BindOnce(
|
59 |
+
&FakeServiceConnectionImpl::HandleLoadBuiltinModelCall,
|
60 |
+
base::Unretained(this), std::move(receiver), std::move(callback)));
|
61 |
+
}
|
62 |
+
|
63 |
+
void FakeServiceConnectionImpl::LoadFlatBufferModel(
|
64 |
+
mojom::FlatBufferModelSpecPtr spec,
|
65 |
+
mojo::PendingReceiver<mojom::Model> receiver,
|
66 |
+
mojom::MachineLearningService::LoadFlatBufferModelCallback callback) {
|
67 |
+
ScheduleCall(base::BindOnce(
|
68 |
+
&FakeServiceConnectionImpl::HandleLoadFlatBufferModelCall,
|
69 |
+
base::Unretained(this), std::move(receiver), std::move(callback)));
|
70 |
+
}
|
71 |
+
|
72 |
+
void FakeServiceConnectionImpl::REMOVED_0(
|
73 |
+
mojo::PendingReceiver<mojom::GraphExecutor> receiver,
|
74 |
+
mojom::Model::REMOVED_0Callback callback) {
|
75 |
+
NOTIMPLEMENTED();
|
76 |
+
}
|
77 |
+
|
78 |
+
void FakeServiceConnectionImpl::REMOVED_4(
|
79 |
+
mojom::HandwritingRecognizerSpecPtr spec,
|
80 |
+
mojo::PendingReceiver<mojom::HandwritingRecognizer> receiver,
|
81 |
+
mojom::MachineLearningService::REMOVED_4Callback callback) {
|
82 |
+
NOTIMPLEMENTED();
|
83 |
+
}
|
84 |
+
|
85 |
+
void FakeServiceConnectionImpl::CreateGraphExecutor(
|
86 |
+
mojom::GraphExecutorOptionsPtr options,
|
87 |
+
mojo::PendingReceiver<mojom::GraphExecutor> receiver,
|
88 |
+
mojom::Model::CreateGraphExecutorCallback callback) {
|
89 |
+
ScheduleCall(
|
90 |
+
base::BindOnce(&FakeServiceConnectionImpl::HandleCreateGraphExecutorCall,
|
91 |
+
base::Unretained(this), std::move(options),
|
92 |
+
std::move(receiver), std::move(callback)));
|
93 |
+
}
|
94 |
+
|
95 |
+
void FakeServiceConnectionImpl::LoadTextClassifier(
|
96 |
+
mojo::PendingReceiver<mojom::TextClassifier> receiver,
|
97 |
+
mojom::MachineLearningService::LoadTextClassifierCallback callback) {
|
98 |
+
ScheduleCall(base::BindOnce(
|
99 |
+
&FakeServiceConnectionImpl::HandleLoadTextClassifierCall,
|
100 |
+
base::Unretained(this), std::move(receiver), std::move(callback)));
|
101 |
+
}
|
102 |
+
|
103 |
+
void FakeServiceConnectionImpl::LoadHandwritingModel(
|
104 |
+
mojom::HandwritingRecognizerSpecPtr spec,
|
105 |
+
mojo::PendingReceiver<mojom::HandwritingRecognizer> receiver,
|
106 |
+
mojom::MachineLearningService::LoadHandwritingModelCallback callback) {
|
107 |
+
ScheduleCall(base::BindOnce(
|
108 |
+
&FakeServiceConnectionImpl::HandleLoadHandwritingModelCall,
|
109 |
+
base::Unretained(this), std::move(receiver), std::move(callback)));
|
110 |
+
}
|
111 |
+
|
112 |
+
void FakeServiceConnectionImpl::HandleLoadWebPlatformHandwritingModelCall(
|
113 |
+
mojo::PendingReceiver<web_platform::mojom::HandwritingRecognizer> receiver,
|
114 |
+
mojom::MachineLearningService::LoadHandwritingModelCallback callback) {
|
115 |
+
if (load_handwriting_model_result_ == mojom::LoadHandwritingModelResult::OK)
|
116 |
+
web_platform_handwriting_receivers_.Add(this, std::move(receiver));
|
117 |
+
std::move(callback).Run(load_web_platform_handwriting_model_result_);
|
118 |
+
}
|
119 |
+
|
120 |
+
void FakeServiceConnectionImpl::LoadWebPlatformHandwritingModel(
|
121 |
+
web_platform::mojom::HandwritingModelConstraintPtr constraint,
|
122 |
+
mojo::PendingReceiver<web_platform::mojom::HandwritingRecognizer> receiver,
|
123 |
+
mojom::MachineLearningService::LoadWebPlatformHandwritingModelCallback
|
124 |
+
callback) {
|
125 |
+
ScheduleCall(base::BindOnce(
|
126 |
+
&FakeServiceConnectionImpl::HandleLoadWebPlatformHandwritingModelCall,
|
127 |
+
base::Unretained(this), std::move(receiver), std::move(callback)));
|
128 |
+
}
|
129 |
+
|
130 |
+
void FakeServiceConnectionImpl::LoadGrammarChecker(
|
131 |
+
mojo::PendingReceiver<mojom::GrammarChecker> receiver,
|
132 |
+
mojom::MachineLearningService::LoadGrammarCheckerCallback callback) {
|
133 |
+
ScheduleCall(base::BindOnce(
|
134 |
+
&FakeServiceConnectionImpl::HandleLoadGrammarCheckerCall,
|
135 |
+
base::Unretained(this), std::move(receiver), std::move(callback)));
|
136 |
+
}
|
137 |
+
|
138 |
+
void FakeServiceConnectionImpl::LoadSpeechRecognizer(
|
139 |
+
mojom::SodaConfigPtr soda_config,
|
140 |
+
mojo::PendingRemote<mojom::SodaClient> soda_client,
|
141 |
+
mojo::PendingReceiver<mojom::SodaRecognizer> soda_recognizer,
|
142 |
+
mojom::MachineLearningService::LoadSpeechRecognizerCallback callback) {
|
143 |
+
ScheduleCall(
|
144 |
+
base::BindOnce(&FakeServiceConnectionImpl::HandleLoadSpeechRecognizerCall,
|
145 |
+
base::Unretained(this), std::move(soda_client),
|
146 |
+
std::move(soda_recognizer), std::move(callback)));
|
147 |
+
}
|
148 |
+
|
149 |
+
void FakeServiceConnectionImpl::LoadTextSuggester(
|
150 |
+
mojo::PendingReceiver<mojom::TextSuggester> receiver,
|
151 |
+
mojom::TextSuggesterSpecPtr spec,
|
152 |
+
mojom::MachineLearningService::LoadTextSuggesterCallback callback) {
|
153 |
+
ScheduleCall(
|
154 |
+
base::BindOnce(&FakeServiceConnectionImpl::HandleLoadTextSuggesterCall,
|
155 |
+
base::Unretained(this), std::move(receiver),
|
156 |
+
std::move(spec), std::move(callback)));
|
157 |
+
}
|
158 |
+
|
159 |
+
void FakeServiceConnectionImpl::LoadDocumentScanner(
|
160 |
+
mojo::PendingReceiver<mojom::DocumentScanner> receiver,
|
161 |
+
mojom::MachineLearningService::LoadDocumentScannerCallback callback) {
|
162 |
+
ScheduleCall(base::BindOnce(
|
163 |
+
&FakeServiceConnectionImpl::HandleLoadDocumentScannerCall,
|
164 |
+
base::Unretained(this), std::move(receiver), std::move(callback)));
|
165 |
+
}
|
166 |
+
|
167 |
+
void FakeServiceConnectionImpl::Execute(
|
168 |
+
base::flat_map<std::string, mojom::TensorPtr> inputs,
|
169 |
+
const std::vector<std::string>& output_names,
|
170 |
+
mojom::GraphExecutor::ExecuteCallback callback) {
|
171 |
+
ScheduleCall(base::BindOnce(&FakeServiceConnectionImpl::HandleExecuteCall,
|
172 |
+
base::Unretained(this), std::move(callback)));
|
173 |
+
}
|
174 |
+
|
175 |
+
void FakeServiceConnectionImpl::SetLoadModelFailure() {
|
176 |
+
load_model_result_ = mojom::LoadModelResult::LOAD_MODEL_ERROR;
|
177 |
+
}
|
178 |
+
|
179 |
+
void FakeServiceConnectionImpl::SetCreateGraphExecutorFailure() {
|
180 |
+
load_model_result_ = mojom::LoadModelResult::OK;
|
181 |
+
create_graph_executor_result_ =
|
182 |
+
mojom::CreateGraphExecutorResult::MODEL_INTERPRETATION_ERROR;
|
183 |
+
}
|
184 |
+
|
185 |
+
void FakeServiceConnectionImpl::SetExecuteFailure() {
|
186 |
+
load_model_result_ = mojom::LoadModelResult::OK;
|
187 |
+
create_graph_executor_result_ = mojom::CreateGraphExecutorResult::OK;
|
188 |
+
execute_result_ = mojom::ExecuteResult::EXECUTION_ERROR;
|
189 |
+
}
|
190 |
+
|
191 |
+
void FakeServiceConnectionImpl::SetExecuteSuccess() {
|
192 |
+
load_model_result_ = mojom::LoadModelResult::OK;
|
193 |
+
create_graph_executor_result_ = mojom::CreateGraphExecutorResult::OK;
|
194 |
+
execute_result_ = mojom::ExecuteResult::OK;
|
195 |
+
}
|
196 |
+
|
197 |
+
void FakeServiceConnectionImpl::SetTextClassifierSuccess() {
|
198 |
+
load_text_classifier_result_ = mojom::LoadModelResult::OK;
|
199 |
+
}
|
200 |
+
|
201 |
+
void FakeServiceConnectionImpl::SetLoadTextClassifierFailure() {
|
202 |
+
load_text_classifier_result_ = mojom::LoadModelResult::LOAD_MODEL_ERROR;
|
203 |
+
}
|
204 |
+
|
205 |
+
void FakeServiceConnectionImpl::SetOutputValue(
|
206 |
+
const std::vector<int64_t>& shape,
|
207 |
+
const std::vector<double>& value) {
|
208 |
+
output_tensor_->shape = mojom::Int64List::New();
|
209 |
+
output_tensor_->shape->value = shape;
|
210 |
+
output_tensor_->data = mojom::ValueList::New();
|
211 |
+
output_tensor_->data->set_float_list(mojom::FloatList::New());
|
212 |
+
output_tensor_->data->get_float_list()->value = value;
|
213 |
+
}
|
214 |
+
|
215 |
+
void FakeServiceConnectionImpl::SetAsyncMode(bool async_mode) {
|
216 |
+
async_mode_ = async_mode;
|
217 |
+
}
|
218 |
+
|
219 |
+
void FakeServiceConnectionImpl::RunPendingCalls() {
|
220 |
+
for (auto& call : pending_calls_) {
|
221 |
+
std::move(call).Run();
|
222 |
+
}
|
223 |
+
|
224 |
+
pending_calls_.clear();
|
225 |
+
}
|
226 |
+
|
227 |
+
void FakeServiceConnectionImpl::FlushForTesting() {
|
228 |
+
clone_ml_service_receivers_.FlushForTesting();
|
229 |
+
machine_learning_service_.FlushForTesting();
|
230 |
+
model_receivers_.FlushForTesting();
|
231 |
+
graph_receivers_.FlushForTesting();
|
232 |
+
text_classifier_receivers_.FlushForTesting();
|
233 |
+
handwriting_receivers_.FlushForTesting();
|
234 |
+
web_platform_handwriting_receivers_.FlushForTesting();
|
235 |
+
grammar_checker_receivers_.FlushForTesting();
|
236 |
+
soda_recognizer_receivers_.FlushForTesting();
|
237 |
+
text_suggester_receivers_.FlushForTesting();
|
238 |
+
document_scanner_receivers_.FlushForTesting();
|
239 |
+
soda_client_remotes_.FlushForTesting();
|
240 |
+
}
|
241 |
+
|
242 |
+
void FakeServiceConnectionImpl::HandleLoadBuiltinModelCall(
|
243 |
+
mojo::PendingReceiver<mojom::Model> receiver,
|
244 |
+
mojom::MachineLearningService::LoadBuiltinModelCallback callback) {
|
245 |
+
if (load_model_result_ == mojom::LoadModelResult::OK)
|
246 |
+
model_receivers_.Add(this, std::move(receiver));
|
247 |
+
|
248 |
+
std::move(callback).Run(load_model_result_);
|
249 |
+
}
|
250 |
+
|
251 |
+
void FakeServiceConnectionImpl::HandleLoadTextClassifierCall(
|
252 |
+
mojo::PendingReceiver<mojom::TextClassifier> receiver,
|
253 |
+
mojom::MachineLearningService::LoadTextClassifierCallback callback) {
|
254 |
+
if (load_text_classifier_result_ == mojom::LoadModelResult::OK)
|
255 |
+
text_classifier_receivers_.Add(this, std::move(receiver));
|
256 |
+
|
257 |
+
std::move(callback).Run(load_text_classifier_result_);
|
258 |
+
}
|
259 |
+
|
260 |
+
void FakeServiceConnectionImpl::ScheduleCall(base::OnceClosure call) {
|
261 |
+
if (async_mode_)
|
262 |
+
pending_calls_.push_back(std::move(call));
|
263 |
+
else
|
264 |
+
std::move(call).Run();
|
265 |
+
}
|
266 |
+
|
267 |
+
void FakeServiceConnectionImpl::HandleLoadFlatBufferModelCall(
|
268 |
+
mojo::PendingReceiver<mojom::Model> receiver,
|
269 |
+
mojom::MachineLearningService::LoadFlatBufferModelCallback callback) {
|
270 |
+
if (load_model_result_ == mojom::LoadModelResult::OK)
|
271 |
+
model_receivers_.Add(this, std::move(receiver));
|
272 |
+
|
273 |
+
std::move(callback).Run(load_model_result_);
|
274 |
+
}
|
275 |
+
|
276 |
+
void FakeServiceConnectionImpl::HandleCreateGraphExecutorCall(
|
277 |
+
mojom::GraphExecutorOptionsPtr options,
|
278 |
+
mojo::PendingReceiver<mojom::GraphExecutor> receiver,
|
279 |
+
mojom::Model::CreateGraphExecutorCallback callback) {
|
280 |
+
if (create_graph_executor_result_ == mojom::CreateGraphExecutorResult::OK)
|
281 |
+
graph_receivers_.Add(this, std::move(receiver));
|
282 |
+
|
283 |
+
std::move(callback).Run(create_graph_executor_result_);
|
284 |
+
}
|
285 |
+
|
286 |
+
void FakeServiceConnectionImpl::HandleExecuteCall(
|
287 |
+
mojom::GraphExecutor::ExecuteCallback callback) {
|
288 |
+
if (execute_result_ != mojom::ExecuteResult::OK) {
|
289 |
+
std::move(callback).Run(execute_result_, absl::nullopt);
|
290 |
+
return;
|
291 |
+
}
|
292 |
+
|
293 |
+
std::vector<mojom::TensorPtr> output_tensors;
|
294 |
+
output_tensors.push_back(output_tensor_.Clone());
|
295 |
+
std::move(callback).Run(execute_result_, std::move(output_tensors));
|
296 |
+
}
|
297 |
+
|
298 |
+
void FakeServiceConnectionImpl::HandleAnnotateCall(
|
299 |
+
mojom::TextAnnotationRequestPtr request,
|
300 |
+
mojom::TextClassifier::AnnotateCallback callback) {
|
301 |
+
std::vector<mojom::TextAnnotationPtr> annotations;
|
302 |
+
for (auto const& annotate : annotate_result_) {
|
303 |
+
annotations.emplace_back(annotate.Clone());
|
304 |
+
}
|
305 |
+
std::move(callback).Run(std::move(annotations));
|
306 |
+
}
|
307 |
+
|
308 |
+
void FakeServiceConnectionImpl::HandleFindLanguagesCall(
|
309 |
+
std::string request,
|
310 |
+
mojom::TextClassifier::FindLanguagesCallback callback) {
|
311 |
+
std::vector<mojom::TextLanguagePtr> languages;
|
312 |
+
for (auto const& language : find_languages_result_) {
|
313 |
+
languages.emplace_back(language.Clone());
|
314 |
+
}
|
315 |
+
std::move(callback).Run(std::move(languages));
|
316 |
+
}
|
317 |
+
|
318 |
+
void FakeServiceConnectionImpl::SetOutputAnnotation(
|
319 |
+
const std::vector<mojom::TextAnnotationPtr>& annotations) {
|
320 |
+
annotate_result_.clear();
|
321 |
+
for (auto const& annotate : annotations) {
|
322 |
+
annotate_result_.emplace_back(annotate.Clone());
|
323 |
+
}
|
324 |
+
}
|
325 |
+
|
326 |
+
void FakeServiceConnectionImpl::SetOutputLanguages(
|
327 |
+
const std::vector<mojom::TextLanguagePtr>& languages) {
|
328 |
+
find_languages_result_.clear();
|
329 |
+
for (auto const& language : languages) {
|
330 |
+
find_languages_result_.emplace_back(language.Clone());
|
331 |
+
}
|
332 |
+
}
|
333 |
+
|
334 |
+
void FakeServiceConnectionImpl::SetOutputHandwritingRecognizerResult(
|
335 |
+
const mojom::HandwritingRecognizerResultPtr& result) {
|
336 |
+
handwriting_result_ = result.Clone();
|
337 |
+
}
|
338 |
+
|
339 |
+
void FakeServiceConnectionImpl::SetOutputWebPlatformHandwritingRecognizerResult(
|
340 |
+
const std::vector<web_platform::mojom::HandwritingPredictionPtr>&
|
341 |
+
predictions) {
|
342 |
+
web_platform_handwriting_result_.clear();
|
343 |
+
for (auto const& prediction : predictions) {
|
344 |
+
web_platform_handwriting_result_.emplace_back(prediction.Clone());
|
345 |
+
}
|
346 |
+
}
|
347 |
+
|
348 |
+
void FakeServiceConnectionImpl::SetOutputGrammarCheckerResult(
|
349 |
+
const mojom::GrammarCheckerResultPtr& result) {
|
350 |
+
grammar_checker_result_ = result.Clone();
|
351 |
+
}
|
352 |
+
|
353 |
+
void FakeServiceConnectionImpl::SetOutputTextSuggesterResult(
|
354 |
+
const mojom::TextSuggesterResultPtr& result) {
|
355 |
+
text_suggester_result_ = result.Clone();
|
356 |
+
}
|
357 |
+
|
358 |
+
void FakeServiceConnectionImpl::SetOutputDetectCornersResult(
|
359 |
+
const mojom::DetectCornersResultPtr& result) {
|
360 |
+
detect_corners_result_ = result.Clone();
|
361 |
+
}
|
362 |
+
|
363 |
+
void FakeServiceConnectionImpl::SetOutputDoPostProcessingResult(
|
364 |
+
const mojom::DoPostProcessingResultPtr& result) {
|
365 |
+
do_post_processing_result_ = result.Clone();
|
366 |
+
}
|
367 |
+
|
368 |
+
void FakeServiceConnectionImpl::Annotate(
|
369 |
+
mojom::TextAnnotationRequestPtr request,
|
370 |
+
mojom::TextClassifier::AnnotateCallback callback) {
|
371 |
+
ScheduleCall(base::BindOnce(&FakeServiceConnectionImpl::HandleAnnotateCall,
|
372 |
+
base::Unretained(this), std::move(request),
|
373 |
+
std::move(callback)));
|
374 |
+
}
|
375 |
+
|
376 |
+
void FakeServiceConnectionImpl::FindLanguages(
|
377 |
+
const std::string& text,
|
378 |
+
mojom::TextClassifier::FindLanguagesCallback callback) {
|
379 |
+
ScheduleCall(
|
380 |
+
base::BindOnce(&FakeServiceConnectionImpl::HandleFindLanguagesCall,
|
381 |
+
base::Unretained(this), text, std::move(callback)));
|
382 |
+
}
|
383 |
+
|
384 |
+
void FakeServiceConnectionImpl::REMOVED_1(
|
385 |
+
mojom::REMOVED_TextSuggestSelectionRequestPtr request,
|
386 |
+
mojom::TextClassifier::REMOVED_1Callback callback) {
|
387 |
+
NOTIMPLEMENTED();
|
388 |
+
}
|
389 |
+
|
390 |
+
void FakeServiceConnectionImpl::Recognize(
|
391 |
+
mojom::HandwritingRecognitionQueryPtr query,
|
392 |
+
mojom::HandwritingRecognizer::RecognizeCallback callback) {
|
393 |
+
ScheduleCall(base::BindOnce(&FakeServiceConnectionImpl::HandleRecognizeCall,
|
394 |
+
base::Unretained(this), std::move(query),
|
395 |
+
std::move(callback)));
|
396 |
+
}
|
397 |
+
|
398 |
+
void FakeServiceConnectionImpl::GetPrediction(
|
399 |
+
std::vector<web_platform::mojom::HandwritingStrokePtr> strokes,
|
400 |
+
web_platform::mojom::HandwritingHintsPtr hints,
|
401 |
+
web_platform::mojom::HandwritingRecognizer::GetPredictionCallback
|
402 |
+
callback) {
|
403 |
+
ScheduleCall(
|
404 |
+
base::BindOnce(&FakeServiceConnectionImpl::HandleGetPredictionCall,
|
405 |
+
base::Unretained(this), std::move(strokes),
|
406 |
+
std::move(hints), std::move(callback)));
|
407 |
+
}
|
408 |
+
|
409 |
+
void FakeServiceConnectionImpl::Check(
|
410 |
+
mojom::GrammarCheckerQueryPtr query,
|
411 |
+
mojom::GrammarChecker::CheckCallback callback) {
|
412 |
+
ScheduleCall(base::BindOnce(
|
413 |
+
&FakeServiceConnectionImpl::HandleGrammarCheckerQueryCall,
|
414 |
+
base::Unretained(this), std::move(query), std::move(callback)));
|
415 |
+
}
|
416 |
+
void FakeServiceConnectionImpl::HandleStopCall() {
|
417 |
+
// Do something on the client
|
418 |
+
}
|
419 |
+
|
420 |
+
void FakeServiceConnectionImpl::HandleStartCall() {
|
421 |
+
// Do something on the client.
|
422 |
+
}
|
423 |
+
|
424 |
+
void FakeServiceConnectionImpl::HandleMarkDoneCall() {
|
425 |
+
HandleStopCall();
|
426 |
+
}
|
427 |
+
|
428 |
+
void FakeServiceConnectionImpl::AddAudio(const std::vector<uint8_t>& audio) {}
|
429 |
+
void FakeServiceConnectionImpl::Stop() {
|
430 |
+
ScheduleCall(base::BindOnce(&FakeServiceConnectionImpl::HandleStopCall,
|
431 |
+
base::Unretained(this)));
|
432 |
+
}
|
433 |
+
void FakeServiceConnectionImpl::Start() {
|
434 |
+
ScheduleCall(base::BindOnce(&FakeServiceConnectionImpl::HandleStartCall,
|
435 |
+
base::Unretained(this)));
|
436 |
+
}
|
437 |
+
void FakeServiceConnectionImpl::MarkDone() {
|
438 |
+
ScheduleCall(base::BindOnce(&FakeServiceConnectionImpl::HandleMarkDoneCall,
|
439 |
+
base::Unretained(this)));
|
440 |
+
}
|
441 |
+
|
442 |
+
void FakeServiceConnectionImpl::Suggest(
|
443 |
+
mojom::TextSuggesterQueryPtr query,
|
444 |
+
mojom::TextSuggester::SuggestCallback callback) {
|
445 |
+
ScheduleCall(base::BindOnce(
|
446 |
+
&FakeServiceConnectionImpl::HandleTextSuggesterSuggestCall,
|
447 |
+
base::Unretained(this), std::move(query), std::move(callback)));
|
448 |
+
}
|
449 |
+
|
450 |
+
void FakeServiceConnectionImpl::DetectCornersFromNV12Image(
|
451 |
+
base::ReadOnlySharedMemoryRegion nv12_image,
|
452 |
+
mojom::DocumentScanner::DetectCornersFromNV12ImageCallback callback) {
|
453 |
+
ScheduleCall(base::BindOnce(
|
454 |
+
&FakeServiceConnectionImpl::HandleDocumentScannerDetectNV12Call,
|
455 |
+
base::Unretained(this), std::move(nv12_image), std::move(callback)));
|
456 |
+
}
|
457 |
+
|
458 |
+
void FakeServiceConnectionImpl::DetectCornersFromJPEGImage(
|
459 |
+
base::ReadOnlySharedMemoryRegion jpeg_image,
|
460 |
+
mojom::DocumentScanner::DetectCornersFromJPEGImageCallback callback) {
|
461 |
+
ScheduleCall(base::BindOnce(
|
462 |
+
&FakeServiceConnectionImpl::HandleDocumentScannerDetectJPEGCall,
|
463 |
+
base::Unretained(this), std::move(jpeg_image), std::move(callback)));
|
464 |
+
}
|
465 |
+
|
466 |
+
void FakeServiceConnectionImpl::DoPostProcessing(
|
467 |
+
base::ReadOnlySharedMemoryRegion jpeg_image,
|
468 |
+
const std::vector<gfx::PointF>& corners,
|
469 |
+
chromeos::machine_learning::mojom::Rotation rotation,
|
470 |
+
mojom::DocumentScanner::DoPostProcessingCallback callback) {
|
471 |
+
ScheduleCall(base::BindOnce(
|
472 |
+
&FakeServiceConnectionImpl::HandleDocumentScannerPostProcessingCall,
|
473 |
+
base::Unretained(this), std::move(jpeg_image), std::move(corners),
|
474 |
+
std::move(callback)));
|
475 |
+
}
|
476 |
+
|
477 |
+
void FakeServiceConnectionImpl::HandleLoadHandwritingModelCall(
|
478 |
+
mojo::PendingReceiver<mojom::HandwritingRecognizer> receiver,
|
479 |
+
mojom::MachineLearningService::LoadHandwritingModelCallback callback) {
|
480 |
+
if (load_handwriting_model_result_ == mojom::LoadHandwritingModelResult::OK)
|
481 |
+
handwriting_receivers_.Add(this, std::move(receiver));
|
482 |
+
std::move(callback).Run(load_handwriting_model_result_);
|
483 |
+
}
|
484 |
+
|
485 |
+
void FakeServiceConnectionImpl::HandleRecognizeCall(
|
486 |
+
mojom::HandwritingRecognitionQueryPtr query,
|
487 |
+
mojom::HandwritingRecognizer::RecognizeCallback callback) {
|
488 |
+
std::move(callback).Run(handwriting_result_.Clone());
|
489 |
+
}
|
490 |
+
|
491 |
+
void FakeServiceConnectionImpl::HandleGetPredictionCall(
|
492 |
+
std::vector<web_platform::mojom::HandwritingStrokePtr> strokes,
|
493 |
+
web_platform::mojom::HandwritingHintsPtr hints,
|
494 |
+
web_platform::mojom::HandwritingRecognizer::GetPredictionCallback
|
495 |
+
callback) {
|
496 |
+
std::vector<web_platform::mojom::HandwritingPredictionPtr> predictions;
|
497 |
+
for (auto const& prediction : web_platform_handwriting_result_) {
|
498 |
+
predictions.emplace_back(prediction.Clone());
|
499 |
+
}
|
500 |
+
std::move(callback).Run(std::move(predictions));
|
501 |
+
}
|
502 |
+
|
503 |
+
void FakeServiceConnectionImpl::HandleLoadGrammarCheckerCall(
|
504 |
+
mojo::PendingReceiver<mojom::GrammarChecker> receiver,
|
505 |
+
mojom::MachineLearningService::LoadGrammarCheckerCallback callback) {
|
506 |
+
if (load_model_result_ == mojom::LoadModelResult::OK)
|
507 |
+
grammar_checker_receivers_.Add(this, std::move(receiver));
|
508 |
+
|
509 |
+
std::move(callback).Run(load_model_result_);
|
510 |
+
}
|
511 |
+
|
512 |
+
void FakeServiceConnectionImpl::HandleLoadSpeechRecognizerCall(
|
513 |
+
mojo::PendingRemote<mojom::SodaClient> soda_client,
|
514 |
+
mojo::PendingReceiver<mojom::SodaRecognizer> soda_recognizer,
|
515 |
+
mojom::MachineLearningService::LoadSpeechRecognizerCallback callback) {
|
516 |
+
if (load_soda_result_ == mojom::LoadModelResult::OK) {
|
517 |
+
soda_recognizer_receivers_.Add(this, std::move(soda_recognizer));
|
518 |
+
soda_client_remotes_.Add(std::move(soda_client));
|
519 |
+
}
|
520 |
+
std::move(callback).Run(load_soda_result_);
|
521 |
+
}
|
522 |
+
|
523 |
+
void FakeServiceConnectionImpl::HandleGrammarCheckerQueryCall(
|
524 |
+
mojom::GrammarCheckerQueryPtr query,
|
525 |
+
mojom::GrammarChecker::CheckCallback callback) {
|
526 |
+
std::move(callback).Run(grammar_checker_result_.Clone());
|
527 |
+
}
|
528 |
+
|
529 |
+
void FakeServiceConnectionImpl::HandleLoadTextSuggesterCall(
|
530 |
+
mojo::PendingReceiver<mojom::TextSuggester> receiver,
|
531 |
+
mojom::TextSuggesterSpecPtr spec,
|
532 |
+
mojom::MachineLearningService::LoadTextSuggesterCallback callback) {
|
533 |
+
if (load_model_result_ == mojom::LoadModelResult::OK)
|
534 |
+
text_suggester_receivers_.Add(this, std::move(receiver));
|
535 |
+
|
536 |
+
std::move(callback).Run(load_model_result_);
|
537 |
+
}
|
538 |
+
|
539 |
+
void FakeServiceConnectionImpl::HandleTextSuggesterSuggestCall(
|
540 |
+
mojom::TextSuggesterQueryPtr query,
|
541 |
+
mojom::TextSuggester::SuggestCallback callback) {
|
542 |
+
std::move(callback).Run(text_suggester_result_.Clone());
|
543 |
+
}
|
544 |
+
|
545 |
+
void FakeServiceConnectionImpl::HandleLoadDocumentScannerCall(
|
546 |
+
mojo::PendingReceiver<mojom::DocumentScanner> receiver,
|
547 |
+
mojom::MachineLearningService::LoadDocumentScannerCallback callback) {
|
548 |
+
if (load_model_result_ == mojom::LoadModelResult::OK)
|
549 |
+
document_scanner_receivers_.Add(this, std::move(receiver));
|
550 |
+
|
551 |
+
std::move(callback).Run(load_model_result_);
|
552 |
+
}
|
553 |
+
|
554 |
+
void FakeServiceConnectionImpl::HandleDocumentScannerDetectNV12Call(
|
555 |
+
base::ReadOnlySharedMemoryRegion nv12_image,
|
556 |
+
mojom::DocumentScanner::DetectCornersFromNV12ImageCallback callback) {
|
557 |
+
std::move(callback).Run(detect_corners_result_.Clone());
|
558 |
+
}
|
559 |
+
|
560 |
+
void FakeServiceConnectionImpl::HandleDocumentScannerDetectJPEGCall(
|
561 |
+
base::ReadOnlySharedMemoryRegion jpeg_image,
|
562 |
+
mojom::DocumentScanner::DetectCornersFromJPEGImageCallback callback) {
|
563 |
+
std::move(callback).Run(detect_corners_result_.Clone());
|
564 |
+
}
|
565 |
+
|
566 |
+
void FakeServiceConnectionImpl::HandleDocumentScannerPostProcessingCall(
|
567 |
+
base::ReadOnlySharedMemoryRegion jpeg_image,
|
568 |
+
const std::vector<gfx::PointF>& corners,
|
569 |
+
mojom::DocumentScanner::DoPostProcessingCallback callback) {
|
570 |
+
std::move(callback).Run(do_post_processing_result_.Clone());
|
571 |
+
}
|
572 |
+
|
573 |
+
} // namespace machine_learning
|
574 |
+
} // namespace chromeos
|
19/public/cpp/fake_service_connection.h
ADDED
@@ -0,0 +1,383 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
// Copyright 2019 The Chromium Authors. All rights reserved.
|
2 |
+
// Use of this source code is governed by a BSD-style license that can be
|
3 |
+
// found in the LICENSE file.
|
4 |
+
|
5 |
+
#ifndef CHROMEOS_SERVICES_MACHINE_LEARNING_PUBLIC_CPP_FAKE_SERVICE_CONNECTION_H_
|
6 |
+
#define CHROMEOS_SERVICES_MACHINE_LEARNING_PUBLIC_CPP_FAKE_SERVICE_CONNECTION_H_
|
7 |
+
|
8 |
+
#include <memory>
|
9 |
+
#include <vector>
|
10 |
+
|
11 |
+
#include "base/callback_forward.h"
|
12 |
+
#include "base/component_export.h"
|
13 |
+
#include "chromeos/services/machine_learning/public/cpp/service_connection.h"
|
14 |
+
#include "chromeos/services/machine_learning/public/mojom/document_scanner.mojom.h"
|
15 |
+
#include "chromeos/services/machine_learning/public/mojom/grammar_checker.mojom.h"
|
16 |
+
#include "chromeos/services/machine_learning/public/mojom/graph_executor.mojom.h"
|
17 |
+
#include "chromeos/services/machine_learning/public/mojom/handwriting_recognizer.mojom.h"
|
18 |
+
#include "chromeos/services/machine_learning/public/mojom/machine_learning_service.mojom.h"
|
19 |
+
#include "chromeos/services/machine_learning/public/mojom/model.mojom.h"
|
20 |
+
#include "chromeos/services/machine_learning/public/mojom/soda.mojom.h"
|
21 |
+
#include "chromeos/services/machine_learning/public/mojom/tensor.mojom.h"
|
22 |
+
#include "chromeos/services/machine_learning/public/mojom/text_classifier.mojom.h"
|
23 |
+
#include "chromeos/services/machine_learning/public/mojom/text_suggester.mojom.h"
|
24 |
+
#include "chromeos/services/machine_learning/public/mojom/web_platform_handwriting.mojom.h"
|
25 |
+
#include "mojo/public/cpp/bindings/pending_receiver.h"
|
26 |
+
#include "mojo/public/cpp/bindings/receiver_set.h"
|
27 |
+
#include "mojo/public/cpp/bindings/remote_set.h"
|
28 |
+
|
29 |
+
namespace chromeos {
|
30 |
+
namespace machine_learning {
|
31 |
+
|
32 |
+
// Fake implementation of chromeos::machine_learning::ServiceConnection.
|
33 |
+
// Handles LoadModel (and Model::CreateGraphExecutor) by binding to itself.
|
34 |
+
// Handles GraphExecutor::Execute by always returning the value specified by
|
35 |
+
// a previous call to SetOutputValue.
|
36 |
+
// Handles TextClassifier::Annotate by always returning the value specified by
|
37 |
+
// a previous call to SetOutputAnnotation.
|
38 |
+
// For use with ServiceConnection::UseFakeServiceConnectionForTesting().
|
39 |
+
class COMPONENT_EXPORT(CHROMEOS_MLSERVICE) FakeServiceConnectionImpl
|
40 |
+
: public ServiceConnection,
|
41 |
+
public mojom::MachineLearningService,
|
42 |
+
public mojom::Model,
|
43 |
+
public mojom::TextClassifier,
|
44 |
+
public mojom::HandwritingRecognizer,
|
45 |
+
public mojom::GrammarChecker,
|
46 |
+
public mojom::GraphExecutor,
|
47 |
+
public mojom::SodaRecognizer,
|
48 |
+
public mojom::TextSuggester,
|
49 |
+
public mojom::DocumentScanner,
|
50 |
+
public web_platform::mojom::HandwritingRecognizer {
|
51 |
+
public:
|
52 |
+
FakeServiceConnectionImpl();
|
53 |
+
|
54 |
+
FakeServiceConnectionImpl(const FakeServiceConnectionImpl&) = delete;
|
55 |
+
FakeServiceConnectionImpl& operator=(const FakeServiceConnectionImpl&) =
|
56 |
+
delete;
|
57 |
+
|
58 |
+
~FakeServiceConnectionImpl() override;
|
59 |
+
|
60 |
+
// ServiceConnection:
|
61 |
+
mojom::MachineLearningService& GetMachineLearningService() override;
|
62 |
+
void BindMachineLearningService(
|
63 |
+
mojo::PendingReceiver<mojom::MachineLearningService> receiver) override;
|
64 |
+
void Initialize() override;
|
65 |
+
|
66 |
+
// mojom::MachineLearningService:
|
67 |
+
void Clone(
|
68 |
+
mojo::PendingReceiver<mojom::MachineLearningService> receiver) override;
|
69 |
+
|
70 |
+
// It's safe to execute LoadBuiltinModel, LoadFlatBufferModel and
|
71 |
+
// LoadTextClassifier for multi times, but all the receivers will be bound to
|
72 |
+
// the same instance.
|
73 |
+
void LoadBuiltinModel(mojom::BuiltinModelSpecPtr spec,
|
74 |
+
mojo::PendingReceiver<mojom::Model> receiver,
|
75 |
+
mojom::MachineLearningService::LoadBuiltinModelCallback
|
76 |
+
callback) override;
|
77 |
+
void LoadFlatBufferModel(
|
78 |
+
mojom::FlatBufferModelSpecPtr spec,
|
79 |
+
mojo::PendingReceiver<mojom::Model> receiver,
|
80 |
+
mojom::MachineLearningService::LoadFlatBufferModelCallback callback)
|
81 |
+
override;
|
82 |
+
|
83 |
+
void LoadTextClassifier(
|
84 |
+
mojo::PendingReceiver<mojom::TextClassifier> receiver,
|
85 |
+
mojom::MachineLearningService::LoadTextClassifierCallback callback)
|
86 |
+
override;
|
87 |
+
|
88 |
+
void LoadHandwritingModel(
|
89 |
+
mojom::HandwritingRecognizerSpecPtr spec,
|
90 |
+
mojo::PendingReceiver<mojom::HandwritingRecognizer> receiver,
|
91 |
+
mojom::MachineLearningService::LoadHandwritingModelCallback
|
92 |
+
result_callback) override;
|
93 |
+
|
94 |
+
// Dedicated HWR API for Web Platform.
|
95 |
+
void LoadWebPlatformHandwritingModel(
|
96 |
+
web_platform::mojom::HandwritingModelConstraintPtr constraint,
|
97 |
+
mojo::PendingReceiver<web_platform::mojom::HandwritingRecognizer>
|
98 |
+
receiver,
|
99 |
+
LoadWebPlatformHandwritingModelCallback callback) override;
|
100 |
+
|
101 |
+
void LoadGrammarChecker(
|
102 |
+
mojo::PendingReceiver<mojom::GrammarChecker> receiver,
|
103 |
+
mojom::MachineLearningService::LoadGrammarCheckerCallback callback)
|
104 |
+
override;
|
105 |
+
|
106 |
+
void LoadSpeechRecognizer(
|
107 |
+
mojom::SodaConfigPtr soda_config,
|
108 |
+
mojo::PendingRemote<mojom::SodaClient> soda_client,
|
109 |
+
mojo::PendingReceiver<mojom::SodaRecognizer> soda_recognizer,
|
110 |
+
mojom::MachineLearningService::LoadSpeechRecognizerCallback callback)
|
111 |
+
override;
|
112 |
+
|
113 |
+
void LoadTextSuggester(
|
114 |
+
mojo::PendingReceiver<mojom::TextSuggester> receiver,
|
115 |
+
mojom::TextSuggesterSpecPtr spec,
|
116 |
+
mojom::MachineLearningService::LoadTextSuggesterCallback callback)
|
117 |
+
override;
|
118 |
+
|
119 |
+
void LoadDocumentScanner(
|
120 |
+
mojo::PendingReceiver<mojom::DocumentScanner> receiver,
|
121 |
+
mojom::MachineLearningService::LoadDocumentScannerCallback callback)
|
122 |
+
override;
|
123 |
+
|
124 |
+
// mojom::Model:
|
125 |
+
void REMOVED_0(mojo::PendingReceiver<mojom::GraphExecutor> receiver,
|
126 |
+
mojom::Model::REMOVED_0Callback callback) override;
|
127 |
+
|
128 |
+
// mojom::Model:
|
129 |
+
void REMOVED_4(mojom::HandwritingRecognizerSpecPtr spec,
|
130 |
+
mojo::PendingReceiver<mojom::HandwritingRecognizer> receiver,
|
131 |
+
mojom::MachineLearningService::REMOVED_4Callback
|
132 |
+
result_callback) override;
|
133 |
+
|
134 |
+
// mojom::Model:
|
135 |
+
void CreateGraphExecutor(
|
136 |
+
mojom::GraphExecutorOptionsPtr options,
|
137 |
+
mojo::PendingReceiver<mojom::GraphExecutor> receiver,
|
138 |
+
mojom::Model::CreateGraphExecutorCallback callback) override;
|
139 |
+
|
140 |
+
// mojom::GraphExecutor:
|
141 |
+
// Execute() will return the tensor set by SetOutputValue() as the output.
|
142 |
+
void Execute(base::flat_map<std::string, mojom::TensorPtr> inputs,
|
143 |
+
const std::vector<std::string>& output_names,
|
144 |
+
mojom::GraphExecutor::ExecuteCallback callback) override;
|
145 |
+
|
146 |
+
// Useful for simulating a failure at different stage.
|
147 |
+
// There are different error codes at each stage, we just randomly pick one.
|
148 |
+
void SetLoadModelFailure();
|
149 |
+
void SetCreateGraphExecutorFailure();
|
150 |
+
void SetExecuteFailure();
|
151 |
+
void SetLoadTextClassifierFailure();
|
152 |
+
// Reset all the Model related failures and make Execute succeed.
|
153 |
+
void SetExecuteSuccess();
|
154 |
+
// Reset all the TextClassifier related failures and make LoadTextClassifier
|
155 |
+
// succeed.
|
156 |
+
// Currently, there are two interfaces related to TextClassifier
|
157 |
+
// (|LoadTextClassifier|, |Annotate|) but only
|
158 |
+
// |LoadTextClassifier| can fail.
|
159 |
+
void SetTextClassifierSuccess();
|
160 |
+
|
161 |
+
// Call SetOutputValue() before Execute() to set the output tensor.
|
162 |
+
void SetOutputValue(const std::vector<int64_t>& shape,
|
163 |
+
const std::vector<double>& value);
|
164 |
+
|
165 |
+
// In async mode, FakeServiceConnectionImpl adds requests like
|
166 |
+
// LoadBuiltinModel, CreateGraphExecutor to |pending_calls_| instead of
|
167 |
+
// responding immediately. Calls in |pending_calls_| will run when
|
168 |
+
// RunPendingCalls() is called.
|
169 |
+
// It's useful when an unit test wants to test the async behaviour of real
|
170 |
+
// ml-service.
|
171 |
+
void SetAsyncMode(bool async_mode);
|
172 |
+
void RunPendingCalls();
|
173 |
+
|
174 |
+
// Call SetOutputAnnotation() before Annotate() to set the output annotation.
|
175 |
+
void SetOutputAnnotation(
|
176 |
+
const std::vector<mojom::TextAnnotationPtr>& annotation);
|
177 |
+
|
178 |
+
// Call SetOutputLanguages() before FindLanguages() to set the output
|
179 |
+
// languages.
|
180 |
+
void SetOutputLanguages(const std::vector<mojom::TextLanguagePtr>& languages);
|
181 |
+
|
182 |
+
// Call SetOutputGrammarCheckerResult() before Check() to set the output of
|
183 |
+
// grammar checker.
|
184 |
+
void SetOutputGrammarCheckerResult(
|
185 |
+
const mojom::GrammarCheckerResultPtr& result);
|
186 |
+
|
187 |
+
// Call SetOutputHandwritingRecognizerResult() before Recognize() to set the
|
188 |
+
// output of handwriting.
|
189 |
+
void SetOutputHandwritingRecognizerResult(
|
190 |
+
const mojom::HandwritingRecognizerResultPtr& result);
|
191 |
+
|
192 |
+
// Call SetOutputWebPlatformHandwritingRecognizerResult() before
|
193 |
+
// GetPrediction() to set the output of handwriting.
|
194 |
+
void SetOutputWebPlatformHandwritingRecognizerResult(
|
195 |
+
const std::vector<web_platform::mojom::HandwritingPredictionPtr>&
|
196 |
+
predictions);
|
197 |
+
|
198 |
+
// Call SetOutputTextSuggesterResult() before Suggest() to set the
|
199 |
+
// output of a text suggestion query.
|
200 |
+
void SetOutputTextSuggesterResult(
|
201 |
+
const mojom::TextSuggesterResultPtr& result);
|
202 |
+
|
203 |
+
// Call SetOutputDetectCornersResult() before
|
204 |
+
// DetectCornersFrom{NV12/JPEG}Image() to set the output of corners detection.
|
205 |
+
void SetOutputDetectCornersResult(
|
206 |
+
const mojom::DetectCornersResultPtr& result);
|
207 |
+
|
208 |
+
// Call SetOutputDoPostProcessingResult() before DoPostProcessing() to set the
|
209 |
+
// output of document post processing.
|
210 |
+
void SetOutputDoPostProcessingResult(
|
211 |
+
const mojom::DoPostProcessingResultPtr& result);
|
212 |
+
|
213 |
+
// mojom::TextClassifier:
|
214 |
+
void Annotate(mojom::TextAnnotationRequestPtr request,
|
215 |
+
mojom::TextClassifier::AnnotateCallback callback) override;
|
216 |
+
|
217 |
+
// mojom::TextClassifier:
|
218 |
+
void FindLanguages(
|
219 |
+
const std::string& text,
|
220 |
+
mojom::TextClassifier::FindLanguagesCallback callback) override;
|
221 |
+
|
222 |
+
// mojom::TextClassifier:
|
223 |
+
void REMOVED_1(
|
224 |
+
mojom::REMOVED_TextSuggestSelectionRequestPtr request,
|
225 |
+
mojom::TextClassifier::REMOVED_1Callback callback) override;
|
226 |
+
|
227 |
+
// mojom::HandwritingRecognizer:
|
228 |
+
void Recognize(
|
229 |
+
mojom::HandwritingRecognitionQueryPtr query,
|
230 |
+
mojom::HandwritingRecognizer::RecognizeCallback callback) override;
|
231 |
+
|
232 |
+
// web_platform::mojom::HandwritingRecognizer
|
233 |
+
void GetPrediction(
|
234 |
+
std::vector<web_platform::mojom::HandwritingStrokePtr> strokes,
|
235 |
+
web_platform::mojom::HandwritingHintsPtr hints,
|
236 |
+
web_platform::mojom::HandwritingRecognizer::GetPredictionCallback
|
237 |
+
callback) override;
|
238 |
+
|
239 |
+
// mojom::GrammarChecker:
|
240 |
+
void Check(mojom::GrammarCheckerQueryPtr query,
|
241 |
+
mojom::GrammarChecker::CheckCallback callback) override;
|
242 |
+
|
243 |
+
// mojom::SpeechRecognizer
|
244 |
+
void AddAudio(const std::vector<uint8_t>& audio) override;
|
245 |
+
void Stop() override;
|
246 |
+
void Start() override;
|
247 |
+
void MarkDone() override;
|
248 |
+
|
249 |
+
// mojom::TextSuggester:
|
250 |
+
void Suggest(mojom::TextSuggesterQueryPtr query,
|
251 |
+
mojom::TextSuggester::SuggestCallback callback) override;
|
252 |
+
|
253 |
+
// mojom::DocumentScanner:
|
254 |
+
void DetectCornersFromNV12Image(
|
255 |
+
base::ReadOnlySharedMemoryRegion nv12_image,
|
256 |
+
mojom::DocumentScanner::DetectCornersFromNV12ImageCallback callback)
|
257 |
+
override;
|
258 |
+
void DetectCornersFromJPEGImage(
|
259 |
+
base::ReadOnlySharedMemoryRegion jpeg_image,
|
260 |
+
mojom::DocumentScanner::DetectCornersFromJPEGImageCallback callback)
|
261 |
+
override;
|
262 |
+
void DoPostProcessing(
|
263 |
+
base::ReadOnlySharedMemoryRegion jpeg_image,
|
264 |
+
const std::vector<gfx::PointF>& corners,
|
265 |
+
chromeos::machine_learning::mojom::Rotation rotation,
|
266 |
+
mojom::DocumentScanner::DoPostProcessingCallback callback) override;
|
267 |
+
|
268 |
+
// Flush all relevant Mojo pipes.
|
269 |
+
void FlushForTesting();
|
270 |
+
|
271 |
+
private:
|
272 |
+
void ScheduleCall(base::OnceClosure call);
|
273 |
+
void HandleLoadBuiltinModelCall(
|
274 |
+
mojo::PendingReceiver<mojom::Model> receiver,
|
275 |
+
mojom::MachineLearningService::LoadBuiltinModelCallback callback);
|
276 |
+
void HandleLoadFlatBufferModelCall(
|
277 |
+
mojo::PendingReceiver<mojom::Model> receiver,
|
278 |
+
mojom::MachineLearningService::LoadFlatBufferModelCallback callback);
|
279 |
+
void HandleCreateGraphExecutorCall(
|
280 |
+
mojom::GraphExecutorOptionsPtr options,
|
281 |
+
mojo::PendingReceiver<mojom::GraphExecutor> receiver,
|
282 |
+
mojom::Model::CreateGraphExecutorCallback callback);
|
283 |
+
void HandleExecuteCall(mojom::GraphExecutor::ExecuteCallback callback);
|
284 |
+
void HandleLoadTextClassifierCall(
|
285 |
+
mojo::PendingReceiver<mojom::TextClassifier> receiver,
|
286 |
+
mojom::MachineLearningService::LoadTextClassifierCallback callback);
|
287 |
+
void HandleAnnotateCall(mojom::TextAnnotationRequestPtr request,
|
288 |
+
mojom::TextClassifier::AnnotateCallback callback);
|
289 |
+
void HandleFindLanguagesCall(
|
290 |
+
std::string text,
|
291 |
+
mojom::TextClassifier::FindLanguagesCallback callback);
|
292 |
+
void HandleLoadHandwritingModelCall(
|
293 |
+
mojo::PendingReceiver<mojom::HandwritingRecognizer> receiver,
|
294 |
+
mojom::MachineLearningService::LoadHandwritingModelCallback callback);
|
295 |
+
void HandleLoadWebPlatformHandwritingModelCall(
|
296 |
+
mojo::PendingReceiver<web_platform::mojom::HandwritingRecognizer>
|
297 |
+
receiver,
|
298 |
+
mojom::MachineLearningService::LoadHandwritingModelCallback callback);
|
299 |
+
void HandleRecognizeCall(
|
300 |
+
mojom::HandwritingRecognitionQueryPtr query,
|
301 |
+
mojom::HandwritingRecognizer::RecognizeCallback callback);
|
302 |
+
void HandleGetPredictionCall(
|
303 |
+
std::vector<web_platform::mojom::HandwritingStrokePtr> strokes,
|
304 |
+
web_platform::mojom::HandwritingHintsPtr hints,
|
305 |
+
web_platform::mojom::HandwritingRecognizer::GetPredictionCallback
|
306 |
+
callback);
|
307 |
+
void HandleLoadGrammarCheckerCall(
|
308 |
+
mojo::PendingReceiver<mojom::GrammarChecker> receiver,
|
309 |
+
mojom::MachineLearningService::LoadGrammarCheckerCallback callback);
|
310 |
+
void HandleGrammarCheckerQueryCall(
|
311 |
+
mojom::GrammarCheckerQueryPtr query,
|
312 |
+
mojom::GrammarChecker::CheckCallback callback);
|
313 |
+
void HandleLoadSpeechRecognizerCall(
|
314 |
+
mojo::PendingRemote<mojom::SodaClient> soda_client,
|
315 |
+
mojo::PendingReceiver<mojom::SodaRecognizer> soda_recognizer,
|
316 |
+
mojom::MachineLearningService::LoadSpeechRecognizerCallback callback);
|
317 |
+
void HandleLoadTextSuggesterCall(
|
318 |
+
mojo::PendingReceiver<mojom::TextSuggester> receiver,
|
319 |
+
mojom::TextSuggesterSpecPtr spec,
|
320 |
+
mojom::MachineLearningService::LoadTextSuggesterCallback callback);
|
321 |
+
void HandleTextSuggesterSuggestCall(
|
322 |
+
mojom::TextSuggesterQueryPtr query,
|
323 |
+
mojom::TextSuggester::SuggestCallback callback);
|
324 |
+
void HandleLoadDocumentScannerCall(
|
325 |
+
mojo::PendingReceiver<mojom::DocumentScanner> receiver,
|
326 |
+
mojom::MachineLearningService::LoadDocumentScannerCallback callback);
|
327 |
+
void HandleDocumentScannerDetectNV12Call(
|
328 |
+
base::ReadOnlySharedMemoryRegion nv12_image,
|
329 |
+
mojom::DocumentScanner::DetectCornersFromNV12ImageCallback callback);
|
330 |
+
void HandleDocumentScannerDetectJPEGCall(
|
331 |
+
base::ReadOnlySharedMemoryRegion jpeg_image,
|
332 |
+
mojom::DocumentScanner::DetectCornersFromJPEGImageCallback callback);
|
333 |
+
void HandleDocumentScannerPostProcessingCall(
|
334 |
+
base::ReadOnlySharedMemoryRegion jpeg_image,
|
335 |
+
const std::vector<gfx::PointF>& corners,
|
336 |
+
mojom::DocumentScanner::DoPostProcessingCallback callback);
|
337 |
+
|
338 |
+
void HandleStopCall();
|
339 |
+
void HandleStartCall();
|
340 |
+
void HandleMarkDoneCall();
|
341 |
+
|
342 |
+
// Additional receivers bound via `Clone`.
|
343 |
+
mojo::ReceiverSet<mojom::MachineLearningService> clone_ml_service_receivers_;
|
344 |
+
|
345 |
+
mojo::Remote<mojom::MachineLearningService> machine_learning_service_;
|
346 |
+
mojo::ReceiverSet<mojom::Model> model_receivers_;
|
347 |
+
mojo::ReceiverSet<mojom::GraphExecutor> graph_receivers_;
|
348 |
+
mojo::ReceiverSet<mojom::TextClassifier> text_classifier_receivers_;
|
349 |
+
mojo::ReceiverSet<mojom::HandwritingRecognizer> handwriting_receivers_;
|
350 |
+
mojo::ReceiverSet<web_platform::mojom::HandwritingRecognizer>
|
351 |
+
web_platform_handwriting_receivers_;
|
352 |
+
mojo::ReceiverSet<mojom::GrammarChecker> grammar_checker_receivers_;
|
353 |
+
mojo::ReceiverSet<mojom::SodaRecognizer> soda_recognizer_receivers_;
|
354 |
+
mojo::ReceiverSet<mojom::TextSuggester> text_suggester_receivers_;
|
355 |
+
mojo::ReceiverSet<mojom::DocumentScanner> document_scanner_receivers_;
|
356 |
+
mojo::RemoteSet<mojom::SodaClient> soda_client_remotes_;
|
357 |
+
mojom::TensorPtr output_tensor_;
|
358 |
+
mojom::LoadHandwritingModelResult load_handwriting_model_result_;
|
359 |
+
mojom::LoadHandwritingModelResult load_web_platform_handwriting_model_result_;
|
360 |
+
mojom::LoadModelResult load_model_result_;
|
361 |
+
mojom::LoadModelResult load_text_classifier_result_;
|
362 |
+
mojom::LoadModelResult load_soda_result_;
|
363 |
+
mojom::CreateGraphExecutorResult create_graph_executor_result_;
|
364 |
+
mojom::ExecuteResult execute_result_;
|
365 |
+
std::vector<mojom::TextAnnotationPtr> annotate_result_;
|
366 |
+
mojom::CodepointSpanPtr suggest_selection_result_;
|
367 |
+
std::vector<mojom::TextLanguagePtr> find_languages_result_;
|
368 |
+
mojom::HandwritingRecognizerResultPtr handwriting_result_;
|
369 |
+
std::vector<web_platform::mojom::HandwritingPredictionPtr>
|
370 |
+
web_platform_handwriting_result_;
|
371 |
+
mojom::GrammarCheckerResultPtr grammar_checker_result_;
|
372 |
+
mojom::TextSuggesterResultPtr text_suggester_result_;
|
373 |
+
mojom::DetectCornersResultPtr detect_corners_result_;
|
374 |
+
mojom::DoPostProcessingResultPtr do_post_processing_result_;
|
375 |
+
|
376 |
+
bool async_mode_;
|
377 |
+
std::vector<base::OnceClosure> pending_calls_;
|
378 |
+
};
|
379 |
+
|
380 |
+
} // namespace machine_learning
|
381 |
+
} // namespace chromeos
|
382 |
+
|
383 |
+
#endif // CHROMEOS_SERVICES_MACHINE_LEARNING_PUBLIC_CPP_FAKE_SERVICE_CONNECTION_H_
|
19/public/cpp/service_connection.cc
ADDED
@@ -0,0 +1,30 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
// Copyright 2018 The Chromium Authors. All rights reserved.
|
2 |
+
// Use of this source code is governed by a BSD-style license that can be
|
3 |
+
// found in the LICENSE file.
|
4 |
+
|
5 |
+
#include "chromeos/services/machine_learning/public/cpp/service_connection.h"
|
6 |
+
|
7 |
+
namespace chromeos {
|
8 |
+
namespace machine_learning {
|
9 |
+
|
10 |
+
namespace {
|
11 |
+
static ServiceConnection* g_fake_service_connection_for_testing = nullptr;
|
12 |
+
} // namespace
|
13 |
+
|
14 |
+
ServiceConnection* ServiceConnection::GetInstance() {
|
15 |
+
if (g_fake_service_connection_for_testing) {
|
16 |
+
return g_fake_service_connection_for_testing;
|
17 |
+
}
|
18 |
+
|
19 |
+
// The real impl lies in service_connection_ash.cc and
|
20 |
+
// service_connection_lacros.cc.
|
21 |
+
return CreateRealInstance();
|
22 |
+
}
|
23 |
+
|
24 |
+
void ServiceConnection::UseFakeServiceConnectionForTesting(
|
25 |
+
ServiceConnection* const fake_service_connection) {
|
26 |
+
g_fake_service_connection_for_testing = fake_service_connection;
|
27 |
+
}
|
28 |
+
|
29 |
+
} // namespace machine_learning
|
30 |
+
} // namespace chromeos
|
19/public/cpp/service_connection.h
ADDED
@@ -0,0 +1,77 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
// Copyright 2018 The Chromium Authors. All rights reserved.
|
2 |
+
// Use of this source code is governed by a BSD-style license that can be
|
3 |
+
// found in the LICENSE file.
|
4 |
+
|
5 |
+
#ifndef CHROMEOS_SERVICES_MACHINE_LEARNING_PUBLIC_CPP_SERVICE_CONNECTION_H_
|
6 |
+
#define CHROMEOS_SERVICES_MACHINE_LEARNING_PUBLIC_CPP_SERVICE_CONNECTION_H_
|
7 |
+
|
8 |
+
#include "base/component_export.h"
|
9 |
+
#include "chromeos/services/machine_learning/public/mojom/machine_learning_service.mojom.h"
|
10 |
+
#include "mojo/public/cpp/bindings/pending_receiver.h"
|
11 |
+
|
12 |
+
namespace chromeos {
|
13 |
+
namespace machine_learning {
|
14 |
+
|
15 |
+
// Encapsulates a connection to the Chrome OS ML Service daemon via its Mojo
|
16 |
+
// interface.
|
17 |
+
//
|
18 |
+
// Usage for BindMachineLearningService:
|
19 |
+
// mojo::Remote<mojom::MachineLearningService> ml_service;
|
20 |
+
// chromeos::machine_learning::ServiceConnection::GetInstance()
|
21 |
+
// ->BindMachineLearningService(
|
22 |
+
// ml_service.BindNewPipeAndPassReceiver());
|
23 |
+
// // Use ml_service to LoadBuiltinModel(), LoadFlatBufferModel() etc. e.g
|
24 |
+
// ml_service->LoadBuiltinModel(...);
|
25 |
+
//
|
26 |
+
// Usage for GetMachineLearningService:
|
27 |
+
// chromeos::machine_learning::ServiceConnection::GetInstance()
|
28 |
+
// ->GetMachineLearningService()
|
29 |
+
// .LoadBuiltinModel(...);
|
30 |
+
//
|
31 |
+
// Sequencing: BindMachineLearningService can be called from any sequence, while
|
32 |
+
// GetMachineLearningService must be called from the sequence that the instance
|
33 |
+
// is created on.
|
34 |
+
class COMPONENT_EXPORT(CHROMEOS_MLSERVICE) ServiceConnection {
|
35 |
+
public:
|
36 |
+
// Gets the ServiceConnection singleton, or a test fake if one has been
|
37 |
+
// specified.
|
38 |
+
static ServiceConnection* GetInstance();
|
39 |
+
// Overrides the result of GetInstance() for use in tests.
|
40 |
+
// Does not take ownership of |fake_service_connection|.
|
41 |
+
// Note: Caller is responsible for calling Initialize() on
|
42 |
+
// `fake_service_connection`.
|
43 |
+
static void UseFakeServiceConnectionForTesting(
|
44 |
+
ServiceConnection* fake_service_connection);
|
45 |
+
|
46 |
+
// Gets the primordial top-level machine learning service interface.
|
47 |
+
// Must be called from the sequence that the instance is created on.
|
48 |
+
virtual mojom::MachineLearningService& GetMachineLearningService() = 0;
|
49 |
+
|
50 |
+
// Binds the receiver to a Clone of the primordial top-level interface.
|
51 |
+
// May be called from any sequence.
|
52 |
+
// Note: A mojo::Remote<mojom::MachineLearningService> bound using this method
|
53 |
+
// does not control the lifetime of the underlying ML Service daemon. It is
|
54 |
+
// safe to release the mojo::Remote<mojom::MachineLearningService> as soon as
|
55 |
+
// you are finished called methods on it and processing callbacks. The ML
|
56 |
+
// Service daemon (and any other mojo remotes subsequently bound to it) will
|
57 |
+
// continue.
|
58 |
+
virtual void BindMachineLearningService(
|
59 |
+
mojo::PendingReceiver<mojom::MachineLearningService> receiver) = 0;
|
60 |
+
|
61 |
+
// Call this once at startup (e.g. PostBrowserStart) on the sequence that
|
62 |
+
// should own the Mojo connection to MachineLearningService (e.g. UI thread).
|
63 |
+
virtual void Initialize() = 0;
|
64 |
+
|
65 |
+
protected:
|
66 |
+
ServiceConnection() = default;
|
67 |
+
virtual ~ServiceConnection() {}
|
68 |
+
|
69 |
+
private:
|
70 |
+
// Creates the ServiceConnection singleton.
|
71 |
+
static ServiceConnection* CreateRealInstance();
|
72 |
+
};
|
73 |
+
|
74 |
+
} // namespace machine_learning
|
75 |
+
} // namespace chromeos
|
76 |
+
|
77 |
+
#endif // CHROMEOS_SERVICES_MACHINE_LEARNING_PUBLIC_CPP_SERVICE_CONNECTION_H_
|
19/public/cpp/service_connection_unittest.cc
ADDED
@@ -0,0 +1,800 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
// Copyright 2018 The Chromium Authors. All rights reserved.
|
2 |
+
// Use of this source code is governed by a BSD-style license that can be
|
3 |
+
// found in the LICENSE file.
|
4 |
+
|
5 |
+
#include "chromeos/services/machine_learning/public/cpp/service_connection.h"
|
6 |
+
|
7 |
+
#include <utility>
|
8 |
+
#include <vector>
|
9 |
+
|
10 |
+
#include "base/bind.h"
|
11 |
+
#include "base/memory/read_only_shared_memory_region.h"
|
12 |
+
#include "base/message_loop/message_pump_type.h"
|
13 |
+
#include "base/run_loop.h"
|
14 |
+
#include "base/test/bind.h"
|
15 |
+
#include "base/test/task_environment.h"
|
16 |
+
#include "base/threading/thread.h"
|
17 |
+
#include "chromeos/dbus/machine_learning/machine_learning_client.h"
|
18 |
+
#include "chromeos/services/machine_learning/public/cpp/fake_service_connection.h"
|
19 |
+
#include "chromeos/services/machine_learning/public/mojom/graph_executor.mojom.h"
|
20 |
+
#include "chromeos/services/machine_learning/public/mojom/handwriting_recognizer.mojom.h"
|
21 |
+
#include "chromeos/services/machine_learning/public/mojom/machine_learning_service.mojom.h"
|
22 |
+
#include "chromeos/services/machine_learning/public/mojom/model.mojom.h"
|
23 |
+
#include "chromeos/services/machine_learning/public/mojom/tensor.mojom.h"
|
24 |
+
#include "chromeos/services/machine_learning/public/mojom/text_suggester.mojom.h"
|
25 |
+
#include "mojo/core/embedder/embedder.h"
|
26 |
+
#include "mojo/core/embedder/scoped_ipc_support.h"
|
27 |
+
#include "mojo/public/cpp/bindings/remote.h"
|
28 |
+
#include "testing/gtest/include/gtest/gtest.h"
|
29 |
+
|
30 |
+
namespace chromeos {
|
31 |
+
namespace machine_learning {
|
32 |
+
namespace {
|
33 |
+
|
34 |
+
class ServiceConnectionTest : public testing::Test {
|
35 |
+
public:
|
36 |
+
ServiceConnectionTest() = default;
|
37 |
+
|
38 |
+
ServiceConnectionTest(const ServiceConnectionTest&) = delete;
|
39 |
+
ServiceConnectionTest& operator=(const ServiceConnectionTest&) = delete;
|
40 |
+
|
41 |
+
void SetUp() override { MachineLearningClient::InitializeFake(); }
|
42 |
+
|
43 |
+
void TearDown() override { MachineLearningClient::Shutdown(); }
|
44 |
+
|
45 |
+
protected:
|
46 |
+
static void SetUpTestCase() {
|
47 |
+
task_environment_ = new base::test::TaskEnvironment();
|
48 |
+
static base::Thread ipc_thread("ipc");
|
49 |
+
ipc_thread.StartWithOptions(
|
50 |
+
base::Thread::Options(base::MessagePumpType::IO, 0));
|
51 |
+
static mojo::core::ScopedIPCSupport ipc_support(
|
52 |
+
ipc_thread.task_runner(),
|
53 |
+
mojo::core::ScopedIPCSupport::ShutdownPolicy::CLEAN);
|
54 |
+
ServiceConnection::GetInstance()->Initialize();
|
55 |
+
}
|
56 |
+
|
57 |
+
static void TearDownTestCase() {
|
58 |
+
if (task_environment_) {
|
59 |
+
delete task_environment_;
|
60 |
+
task_environment_ = nullptr;
|
61 |
+
}
|
62 |
+
}
|
63 |
+
|
64 |
+
private:
|
65 |
+
static base::test::TaskEnvironment* task_environment_;
|
66 |
+
};
|
67 |
+
|
68 |
+
base::test::TaskEnvironment* ServiceConnectionTest::task_environment_;
|
69 |
+
|
70 |
+
// Tests that LoadBuiltinModel runs OK (no crash) in a basic Mojo
|
71 |
+
// environment.
|
72 |
+
TEST_F(ServiceConnectionTest, LoadBuiltinModel) {
|
73 |
+
mojo::Remote<mojom::Model> model;
|
74 |
+
|
75 |
+
mojo::Remote<mojom::MachineLearningService> ml_service;
|
76 |
+
ServiceConnection::GetInstance()->BindMachineLearningService(
|
77 |
+
ml_service.BindNewPipeAndPassReceiver());
|
78 |
+
|
79 |
+
ml_service->LoadBuiltinModel(
|
80 |
+
mojom::BuiltinModelSpec::New(mojom::BuiltinModelId::TEST_MODEL),
|
81 |
+
model.BindNewPipeAndPassReceiver(),
|
82 |
+
base::BindOnce([](mojom::LoadModelResult result) {}));
|
83 |
+
|
84 |
+
// Also tests GetMachineLearningService runs OK.
|
85 |
+
model.reset();
|
86 |
+
ServiceConnection::GetInstance()
|
87 |
+
->GetMachineLearningService()
|
88 |
+
.LoadBuiltinModel(
|
89 |
+
mojom::BuiltinModelSpec::New(mojom::BuiltinModelId::TEST_MODEL),
|
90 |
+
model.BindNewPipeAndPassReceiver(),
|
91 |
+
base::BindOnce([](mojom::LoadModelResult result) {}));
|
92 |
+
}
|
93 |
+
|
94 |
+
// Tests that LoadFlatBufferModel runs OK (no crash) in a basic Mojo
|
95 |
+
// environment.
|
96 |
+
TEST_F(ServiceConnectionTest, LoadFlatBufferModel) {
|
97 |
+
mojo::Remote<mojom::MachineLearningService> ml_service;
|
98 |
+
ServiceConnection::GetInstance()->BindMachineLearningService(
|
99 |
+
ml_service.BindNewPipeAndPassReceiver());
|
100 |
+
|
101 |
+
mojo::Remote<mojom::Model> model;
|
102 |
+
ml_service->LoadFlatBufferModel(
|
103 |
+
mojom::FlatBufferModelSpec::New(), model.BindNewPipeAndPassReceiver(),
|
104 |
+
base::BindOnce([](mojom::LoadModelResult result) {}));
|
105 |
+
|
106 |
+
model.reset();
|
107 |
+
ServiceConnection::GetInstance()
|
108 |
+
->GetMachineLearningService()
|
109 |
+
.LoadFlatBufferModel(
|
110 |
+
mojom::FlatBufferModelSpec::New(), model.BindNewPipeAndPassReceiver(),
|
111 |
+
base::BindOnce([](mojom::LoadModelResult result) {}));
|
112 |
+
}
|
113 |
+
|
114 |
+
// Tests that LoadTextClassifier runs OK (no crash) in a basic Mojo
|
115 |
+
// environment.
|
116 |
+
TEST_F(ServiceConnectionTest, LoadTextClassifier) {
|
117 |
+
mojo::Remote<mojom::MachineLearningService> ml_service;
|
118 |
+
ServiceConnection::GetInstance()->BindMachineLearningService(
|
119 |
+
ml_service.BindNewPipeAndPassReceiver());
|
120 |
+
|
121 |
+
mojo::Remote<mojom::TextClassifier> text_classifier;
|
122 |
+
ml_service->LoadTextClassifier(
|
123 |
+
text_classifier.BindNewPipeAndPassReceiver(),
|
124 |
+
base::BindOnce([](mojom::LoadModelResult result) {}));
|
125 |
+
|
126 |
+
text_classifier.reset();
|
127 |
+
ServiceConnection::GetInstance()
|
128 |
+
->GetMachineLearningService()
|
129 |
+
.LoadTextClassifier(text_classifier.BindNewPipeAndPassReceiver(),
|
130 |
+
base::BindOnce([](mojom::LoadModelResult result) {}));
|
131 |
+
}
|
132 |
+
|
133 |
+
// Tests that LoadHandwritingModel runs OK (no crash) in a basic Mojo
|
134 |
+
// environment.
|
135 |
+
TEST_F(ServiceConnectionTest, LoadHandwritingModel) {
|
136 |
+
mojo::Remote<mojom::MachineLearningService> ml_service;
|
137 |
+
ServiceConnection::GetInstance()->BindMachineLearningService(
|
138 |
+
ml_service.BindNewPipeAndPassReceiver());
|
139 |
+
|
140 |
+
mojo::Remote<mojom::HandwritingRecognizer> handwriting_recognizer;
|
141 |
+
ml_service->LoadHandwritingModel(
|
142 |
+
mojom::HandwritingRecognizerSpec::New("en"),
|
143 |
+
handwriting_recognizer.BindNewPipeAndPassReceiver(),
|
144 |
+
base::BindOnce([](mojom::LoadHandwritingModelResult result) {}));
|
145 |
+
|
146 |
+
handwriting_recognizer.reset();
|
147 |
+
ServiceConnection::GetInstance()
|
148 |
+
->GetMachineLearningService()
|
149 |
+
.LoadHandwritingModel(
|
150 |
+
mojom::HandwritingRecognizerSpec::New("en"),
|
151 |
+
handwriting_recognizer.BindNewPipeAndPassReceiver(),
|
152 |
+
base::BindOnce([](mojom::LoadHandwritingModelResult result) {}));
|
153 |
+
}
|
154 |
+
|
155 |
+
// Tests that LoadGrammarChecker runs OK (no crash) in a basic Mojo environment.
|
156 |
+
TEST_F(ServiceConnectionTest, LoadGrammarModel) {
|
157 |
+
mojo::Remote<mojom::MachineLearningService> ml_service;
|
158 |
+
ServiceConnection::GetInstance()->BindMachineLearningService(
|
159 |
+
ml_service.BindNewPipeAndPassReceiver());
|
160 |
+
|
161 |
+
mojo::Remote<mojom::GrammarChecker> grammar_checker;
|
162 |
+
ml_service->LoadGrammarChecker(
|
163 |
+
grammar_checker.BindNewPipeAndPassReceiver(),
|
164 |
+
base::BindOnce([](mojom::LoadModelResult result) {}));
|
165 |
+
|
166 |
+
grammar_checker.reset();
|
167 |
+
ServiceConnection::GetInstance()
|
168 |
+
->GetMachineLearningService()
|
169 |
+
.LoadGrammarChecker(grammar_checker.BindNewPipeAndPassReceiver(),
|
170 |
+
base::BindOnce([](mojom::LoadModelResult result) {}));
|
171 |
+
}
|
172 |
+
|
173 |
+
// Tests the fake ML service for binding ml_service receiver.
|
174 |
+
TEST_F(ServiceConnectionTest, BindMachineLearningService) {
|
175 |
+
FakeServiceConnectionImpl fake_service_connection;
|
176 |
+
ServiceConnection::UseFakeServiceConnectionForTesting(
|
177 |
+
&fake_service_connection);
|
178 |
+
ServiceConnection::GetInstance()->Initialize();
|
179 |
+
|
180 |
+
std::unique_ptr<base::RunLoop> run_loop = std::make_unique<base::RunLoop>();
|
181 |
+
mojo::Remote<mojom::MachineLearningService> ml_service;
|
182 |
+
base::OnceClosure callback =
|
183 |
+
base::BindOnce(&ServiceConnection::BindMachineLearningService,
|
184 |
+
base::Unretained(ServiceConnection::GetInstance()),
|
185 |
+
ml_service.BindNewPipeAndPassReceiver())
|
186 |
+
.Then(run_loop->QuitClosure());
|
187 |
+
std::move(callback).Run();
|
188 |
+
run_loop->Run();
|
189 |
+
ASSERT_TRUE(ml_service.is_bound());
|
190 |
+
|
191 |
+
// Check the bound ml_service remote can be used to call
|
192 |
+
// MachineLearningService methods.
|
193 |
+
mojo::Remote<mojom::Model> model;
|
194 |
+
bool callback_done = false;
|
195 |
+
|
196 |
+
run_loop.reset(new base::RunLoop);
|
197 |
+
ml_service->LoadBuiltinModel(
|
198 |
+
mojom::BuiltinModelSpec::New(mojom::BuiltinModelId::TEST_MODEL),
|
199 |
+
model.BindNewPipeAndPassReceiver(),
|
200 |
+
base::BindOnce(
|
201 |
+
[](bool* callback_done, mojom::LoadModelResult result) {
|
202 |
+
EXPECT_EQ(result, mojom::LoadModelResult::OK);
|
203 |
+
*callback_done = true;
|
204 |
+
},
|
205 |
+
&callback_done)
|
206 |
+
.Then(run_loop->QuitClosure()));
|
207 |
+
|
208 |
+
run_loop->Run();
|
209 |
+
EXPECT_TRUE(callback_done);
|
210 |
+
EXPECT_TRUE(model.is_bound());
|
211 |
+
}
|
212 |
+
|
213 |
+
class TestSodaClient : public mojom::SodaClient {
|
214 |
+
void OnStop() override {}
|
215 |
+
void OnStart() override {}
|
216 |
+
void OnSpeechRecognizerEvent(mojom::SpeechRecognizerEventPtr event) override {
|
217 |
+
}
|
218 |
+
};
|
219 |
+
|
220 |
+
// Tests that LoadSpeechRecognizer runs OK without a crash in a basic Mojo
|
221 |
+
// Environment.
|
222 |
+
TEST_F(ServiceConnectionTest, LoadSpeechRecognizerAndCallback) {
|
223 |
+
mojo::Remote<mojom::SodaRecognizer> soda_recognizer;
|
224 |
+
TestSodaClient test_client;
|
225 |
+
FakeServiceConnectionImpl fake_service_connection;
|
226 |
+
ServiceConnection::UseFakeServiceConnectionForTesting(
|
227 |
+
&fake_service_connection);
|
228 |
+
ServiceConnection::GetInstance()->Initialize();
|
229 |
+
|
230 |
+
mojo::Receiver<mojom::SodaClient> soda_client{&test_client};
|
231 |
+
bool callback_done = false;
|
232 |
+
auto config = mojom::SodaConfig::New();
|
233 |
+
base::RunLoop run_loop;
|
234 |
+
ServiceConnection::GetInstance()
|
235 |
+
->GetMachineLearningService()
|
236 |
+
.LoadSpeechRecognizer(
|
237 |
+
std::move(config), soda_client.BindNewPipeAndPassRemote(),
|
238 |
+
soda_recognizer.BindNewPipeAndPassReceiver(),
|
239 |
+
base::BindLambdaForTesting([&](mojom::LoadModelResult result) {
|
240 |
+
callback_done = true;
|
241 |
+
EXPECT_EQ(result, mojom::LoadModelResult::OK);
|
242 |
+
run_loop.Quit();
|
243 |
+
}));
|
244 |
+
run_loop.Run();
|
245 |
+
ASSERT_TRUE(callback_done);
|
246 |
+
}
|
247 |
+
|
248 |
+
// Tests the fake ML service for builtin model.
|
249 |
+
TEST_F(ServiceConnectionTest, FakeServiceConnectionForBuiltinModel) {
|
250 |
+
mojo::Remote<mojom::Model> model;
|
251 |
+
bool callback_done = false;
|
252 |
+
FakeServiceConnectionImpl fake_service_connection;
|
253 |
+
ServiceConnection::UseFakeServiceConnectionForTesting(
|
254 |
+
&fake_service_connection);
|
255 |
+
ServiceConnection::GetInstance()->Initialize();
|
256 |
+
|
257 |
+
const double expected_value = 200.002;
|
258 |
+
fake_service_connection.SetOutputValue(std::vector<int64_t>{1L},
|
259 |
+
std::vector<double>{expected_value});
|
260 |
+
std::unique_ptr<base::RunLoop> run_loop = std::make_unique<base::RunLoop>();
|
261 |
+
ServiceConnection::GetInstance()
|
262 |
+
->GetMachineLearningService()
|
263 |
+
.LoadBuiltinModel(
|
264 |
+
mojom::BuiltinModelSpec::New(mojom::BuiltinModelId::TEST_MODEL),
|
265 |
+
model.BindNewPipeAndPassReceiver(),
|
266 |
+
base::BindOnce(
|
267 |
+
[](bool* callback_done, mojom::LoadModelResult result) {
|
268 |
+
EXPECT_EQ(result, mojom::LoadModelResult::OK);
|
269 |
+
*callback_done = true;
|
270 |
+
},
|
271 |
+
&callback_done)
|
272 |
+
.Then(run_loop->QuitClosure()));
|
273 |
+
run_loop->Run();
|
274 |
+
ASSERT_TRUE(callback_done);
|
275 |
+
ASSERT_TRUE(model.is_bound());
|
276 |
+
|
277 |
+
callback_done = false;
|
278 |
+
mojo::Remote<mojom::GraphExecutor> graph;
|
279 |
+
run_loop.reset(new base::RunLoop);
|
280 |
+
model->CreateGraphExecutor(
|
281 |
+
mojom::GraphExecutorOptions::New(), graph.BindNewPipeAndPassReceiver(),
|
282 |
+
base::BindOnce(
|
283 |
+
[](bool* callback_done, mojom::CreateGraphExecutorResult result) {
|
284 |
+
EXPECT_EQ(result, mojom::CreateGraphExecutorResult::OK);
|
285 |
+
*callback_done = true;
|
286 |
+
},
|
287 |
+
&callback_done)
|
288 |
+
.Then(run_loop->QuitClosure()));
|
289 |
+
run_loop->Run();
|
290 |
+
ASSERT_TRUE(callback_done);
|
291 |
+
ASSERT_TRUE(graph.is_bound());
|
292 |
+
|
293 |
+
callback_done = false;
|
294 |
+
base::flat_map<std::string, mojom::TensorPtr> inputs;
|
295 |
+
std::vector<std::string> outputs;
|
296 |
+
run_loop.reset(new base::RunLoop);
|
297 |
+
graph->Execute(std::move(inputs), std::move(outputs),
|
298 |
+
base::BindOnce(
|
299 |
+
[](bool* callback_done, double expected_value,
|
300 |
+
const mojom::ExecuteResult result,
|
301 |
+
absl::optional<std::vector<mojom::TensorPtr>> outputs) {
|
302 |
+
EXPECT_EQ(result, mojom::ExecuteResult::OK);
|
303 |
+
ASSERT_TRUE(outputs.has_value());
|
304 |
+
ASSERT_EQ(outputs->size(), 1LU);
|
305 |
+
mojom::TensorPtr& tensor = (*outputs)[0];
|
306 |
+
EXPECT_EQ(tensor->data->get_float_list()->value[0],
|
307 |
+
expected_value);
|
308 |
+
|
309 |
+
*callback_done = true;
|
310 |
+
},
|
311 |
+
&callback_done, expected_value)
|
312 |
+
.Then(run_loop->QuitClosure()));
|
313 |
+
|
314 |
+
run_loop->Run();
|
315 |
+
ASSERT_TRUE(callback_done);
|
316 |
+
}
|
317 |
+
|
318 |
+
// Tests the fake ML service for flatbuffer model.
|
319 |
+
TEST_F(ServiceConnectionTest, FakeServiceConnectionForFlatBufferModel) {
|
320 |
+
mojo::Remote<mojom::Model> model;
|
321 |
+
bool callback_done = false;
|
322 |
+
FakeServiceConnectionImpl fake_service_connection;
|
323 |
+
ServiceConnection::UseFakeServiceConnectionForTesting(
|
324 |
+
&fake_service_connection);
|
325 |
+
ServiceConnection::GetInstance()->Initialize();
|
326 |
+
|
327 |
+
const double expected_value = 200.002;
|
328 |
+
fake_service_connection.SetOutputValue(std::vector<int64_t>{1L},
|
329 |
+
std::vector<double>{expected_value});
|
330 |
+
|
331 |
+
std::unique_ptr<base::RunLoop> run_loop = std::make_unique<base::RunLoop>();
|
332 |
+
ServiceConnection::GetInstance()
|
333 |
+
->GetMachineLearningService()
|
334 |
+
.LoadFlatBufferModel(
|
335 |
+
mojom::FlatBufferModelSpec::New(), model.BindNewPipeAndPassReceiver(),
|
336 |
+
base::BindOnce(
|
337 |
+
[](bool* callback_done, mojom::LoadModelResult result) {
|
338 |
+
EXPECT_EQ(result, mojom::LoadModelResult::OK);
|
339 |
+
*callback_done = true;
|
340 |
+
},
|
341 |
+
&callback_done)
|
342 |
+
.Then(run_loop->QuitClosure()));
|
343 |
+
run_loop->Run();
|
344 |
+
ASSERT_TRUE(callback_done);
|
345 |
+
ASSERT_TRUE(model.is_bound());
|
346 |
+
|
347 |
+
callback_done = false;
|
348 |
+
mojo::Remote<mojom::GraphExecutor> graph;
|
349 |
+
run_loop.reset(new base::RunLoop);
|
350 |
+
model->CreateGraphExecutor(
|
351 |
+
mojom::GraphExecutorOptions::New(), graph.BindNewPipeAndPassReceiver(),
|
352 |
+
base::BindOnce(
|
353 |
+
[](bool* callback_done, mojom::CreateGraphExecutorResult result) {
|
354 |
+
EXPECT_EQ(result, mojom::CreateGraphExecutorResult::OK);
|
355 |
+
*callback_done = true;
|
356 |
+
},
|
357 |
+
&callback_done)
|
358 |
+
.Then(run_loop->QuitClosure()));
|
359 |
+
run_loop->Run();
|
360 |
+
ASSERT_TRUE(callback_done);
|
361 |
+
ASSERT_TRUE(graph.is_bound());
|
362 |
+
|
363 |
+
callback_done = false;
|
364 |
+
base::flat_map<std::string, mojom::TensorPtr> inputs;
|
365 |
+
std::vector<std::string> outputs;
|
366 |
+
run_loop.reset(new base::RunLoop);
|
367 |
+
graph->Execute(std::move(inputs), std::move(outputs),
|
368 |
+
base::BindOnce(
|
369 |
+
[](bool* callback_done, double expected_value,
|
370 |
+
const mojom::ExecuteResult result,
|
371 |
+
absl::optional<std::vector<mojom::TensorPtr>> outputs) {
|
372 |
+
EXPECT_EQ(result, mojom::ExecuteResult::OK);
|
373 |
+
ASSERT_TRUE(outputs.has_value());
|
374 |
+
ASSERT_EQ(outputs->size(), 1LU);
|
375 |
+
mojom::TensorPtr& tensor = (*outputs)[0];
|
376 |
+
EXPECT_EQ(tensor->data->get_float_list()->value[0],
|
377 |
+
expected_value);
|
378 |
+
|
379 |
+
*callback_done = true;
|
380 |
+
},
|
381 |
+
&callback_done, expected_value)
|
382 |
+
.Then(run_loop->QuitClosure()));
|
383 |
+
run_loop->Run();
|
384 |
+
ASSERT_TRUE(callback_done);
|
385 |
+
}
|
386 |
+
|
387 |
+
// Tests the fake ML service for text classifier annotation.
|
388 |
+
TEST_F(ServiceConnectionTest,
|
389 |
+
FakeServiceConnectionForTextClassifierAnnotation) {
|
390 |
+
mojo::Remote<mojom::TextClassifier> text_classifier;
|
391 |
+
bool callback_done = false;
|
392 |
+
FakeServiceConnectionImpl fake_service_connection;
|
393 |
+
ServiceConnection::UseFakeServiceConnectionForTesting(
|
394 |
+
&fake_service_connection);
|
395 |
+
ServiceConnection::GetInstance()->Initialize();
|
396 |
+
|
397 |
+
auto dummy_data = mojom::TextEntityData::New();
|
398 |
+
dummy_data->set_numeric_value(123456789.);
|
399 |
+
std::vector<mojom::TextEntityPtr> entities;
|
400 |
+
entities.emplace_back(
|
401 |
+
mojom::TextEntity::New("dummy", // Entity name.
|
402 |
+
1.0, // Confidence score.
|
403 |
+
std::move(dummy_data))); // Data extracted.
|
404 |
+
auto dummy_annotation = mojom::TextAnnotation::New(123, // Start offset.
|
405 |
+
321, // End offset.
|
406 |
+
std::move(entities));
|
407 |
+
std::vector<mojom::TextAnnotationPtr> annotations;
|
408 |
+
annotations.emplace_back(std::move(dummy_annotation));
|
409 |
+
fake_service_connection.SetOutputAnnotation(annotations);
|
410 |
+
|
411 |
+
std::unique_ptr<base::RunLoop> run_loop = std::make_unique<base::RunLoop>();
|
412 |
+
ServiceConnection::GetInstance()
|
413 |
+
->GetMachineLearningService()
|
414 |
+
.LoadTextClassifier(
|
415 |
+
text_classifier.BindNewPipeAndPassReceiver(),
|
416 |
+
base::BindOnce(
|
417 |
+
[](bool* callback_done, mojom::LoadModelResult result) {
|
418 |
+
EXPECT_EQ(result, mojom::LoadModelResult::OK);
|
419 |
+
*callback_done = true;
|
420 |
+
},
|
421 |
+
&callback_done)
|
422 |
+
.Then(run_loop->QuitClosure()));
|
423 |
+
run_loop->Run();
|
424 |
+
ASSERT_TRUE(callback_done);
|
425 |
+
ASSERT_TRUE(text_classifier.is_bound());
|
426 |
+
|
427 |
+
auto request = mojom::TextAnnotationRequest::New();
|
428 |
+
bool infer_callback_done = false;
|
429 |
+
run_loop.reset(new base::RunLoop);
|
430 |
+
text_classifier->Annotate(
|
431 |
+
std::move(request),
|
432 |
+
base::BindOnce(
|
433 |
+
[](bool* infer_callback_done,
|
434 |
+
std::vector<mojom::TextAnnotationPtr> annotations) {
|
435 |
+
*infer_callback_done = true;
|
436 |
+
// Check if the annotation is correct.
|
437 |
+
EXPECT_EQ(annotations[0]->start_offset, 123u);
|
438 |
+
EXPECT_EQ(annotations[0]->end_offset, 321u);
|
439 |
+
EXPECT_EQ(annotations[0]->entities[0]->name, "dummy");
|
440 |
+
EXPECT_EQ(annotations[0]->entities[0]->confidence_score, 1.0);
|
441 |
+
EXPECT_EQ(annotations[0]->entities[0]->data->get_numeric_value(),
|
442 |
+
123456789.);
|
443 |
+
},
|
444 |
+
&infer_callback_done)
|
445 |
+
.Then(run_loop->QuitClosure()));
|
446 |
+
run_loop->Run();
|
447 |
+
ASSERT_TRUE(infer_callback_done);
|
448 |
+
}
|
449 |
+
|
450 |
+
// Tests the fake ML service for text classifier language identification.
|
451 |
+
TEST_F(ServiceConnectionTest,
|
452 |
+
FakeServiceConnectionForTextClassifierFindLanguages) {
|
453 |
+
mojo::Remote<mojom::TextClassifier> text_classifier;
|
454 |
+
bool callback_done = false;
|
455 |
+
FakeServiceConnectionImpl fake_service_connection;
|
456 |
+
ServiceConnection::UseFakeServiceConnectionForTesting(
|
457 |
+
&fake_service_connection);
|
458 |
+
ServiceConnection::GetInstance()->Initialize();
|
459 |
+
|
460 |
+
std::vector<mojom::TextLanguagePtr> languages;
|
461 |
+
languages.emplace_back(mojom::TextLanguage::New("en", 0.9));
|
462 |
+
languages.emplace_back(mojom::TextLanguage::New("fr", 0.1));
|
463 |
+
fake_service_connection.SetOutputLanguages(languages);
|
464 |
+
|
465 |
+
std::unique_ptr<base::RunLoop> run_loop = std::make_unique<base::RunLoop>();
|
466 |
+
ServiceConnection::GetInstance()
|
467 |
+
->GetMachineLearningService()
|
468 |
+
.LoadTextClassifier(
|
469 |
+
text_classifier.BindNewPipeAndPassReceiver(),
|
470 |
+
base::BindOnce(
|
471 |
+
[](bool* callback_done, mojom::LoadModelResult result) {
|
472 |
+
EXPECT_EQ(result, mojom::LoadModelResult::OK);
|
473 |
+
*callback_done = true;
|
474 |
+
},
|
475 |
+
&callback_done)
|
476 |
+
.Then(run_loop->QuitClosure()));
|
477 |
+
run_loop->Run();
|
478 |
+
ASSERT_TRUE(callback_done);
|
479 |
+
ASSERT_TRUE(text_classifier.is_bound());
|
480 |
+
|
481 |
+
std::string input_text = "dummy input text";
|
482 |
+
bool infer_callback_done = false;
|
483 |
+
run_loop.reset(new base::RunLoop);
|
484 |
+
text_classifier->FindLanguages(
|
485 |
+
input_text, base::BindOnce(
|
486 |
+
[](bool* infer_callback_done,
|
487 |
+
std::vector<mojom::TextLanguagePtr> languages) {
|
488 |
+
*infer_callback_done = true;
|
489 |
+
// Check if the suggestion is correct.
|
490 |
+
ASSERT_EQ(languages.size(), 2ul);
|
491 |
+
EXPECT_EQ(languages[0]->locale, "en");
|
492 |
+
EXPECT_EQ(languages[0]->confidence, 0.9f);
|
493 |
+
EXPECT_EQ(languages[1]->locale, "fr");
|
494 |
+
EXPECT_EQ(languages[1]->confidence, 0.1f);
|
495 |
+
},
|
496 |
+
&infer_callback_done)
|
497 |
+
.Then(run_loop->QuitClosure()));
|
498 |
+
run_loop->Run();
|
499 |
+
ASSERT_TRUE(infer_callback_done);
|
500 |
+
}
|
501 |
+
|
502 |
+
// Tests the fake ML service for handwriting.
|
503 |
+
TEST_F(ServiceConnectionTest, FakeHandWritingRecognizer) {
|
504 |
+
mojo::Remote<mojom::HandwritingRecognizer> recognizer;
|
505 |
+
bool callback_done = false;
|
506 |
+
FakeServiceConnectionImpl fake_service_connection;
|
507 |
+
ServiceConnection::UseFakeServiceConnectionForTesting(
|
508 |
+
&fake_service_connection);
|
509 |
+
ServiceConnection::GetInstance()->Initialize();
|
510 |
+
|
511 |
+
std::unique_ptr<base::RunLoop> run_loop = std::make_unique<base::RunLoop>();
|
512 |
+
ServiceConnection::GetInstance()
|
513 |
+
->GetMachineLearningService()
|
514 |
+
.LoadHandwritingModel(
|
515 |
+
mojom::HandwritingRecognizerSpec::New("en"),
|
516 |
+
recognizer.BindNewPipeAndPassReceiver(),
|
517 |
+
base::BindOnce(
|
518 |
+
[](bool* callback_done,
|
519 |
+
mojom::LoadHandwritingModelResult result) {
|
520 |
+
EXPECT_EQ(result, mojom::LoadHandwritingModelResult::OK);
|
521 |
+
*callback_done = true;
|
522 |
+
},
|
523 |
+
&callback_done)
|
524 |
+
.Then(run_loop->QuitClosure()));
|
525 |
+
run_loop->Run();
|
526 |
+
ASSERT_TRUE(callback_done);
|
527 |
+
ASSERT_TRUE(recognizer.is_bound());
|
528 |
+
|
529 |
+
// Construct fake output.
|
530 |
+
mojom::HandwritingRecognizerResultPtr result =
|
531 |
+
mojom::HandwritingRecognizerResult::New();
|
532 |
+
result->status = mojom::HandwritingRecognizerResult::Status::OK;
|
533 |
+
mojom::HandwritingRecognizerCandidatePtr candidate =
|
534 |
+
mojom::HandwritingRecognizerCandidate::New();
|
535 |
+
candidate->text = "cat";
|
536 |
+
candidate->score = 0.5f;
|
537 |
+
result->candidates.emplace_back(std::move(candidate));
|
538 |
+
fake_service_connection.SetOutputHandwritingRecognizerResult(result);
|
539 |
+
|
540 |
+
auto query = mojom::HandwritingRecognitionQuery::New();
|
541 |
+
bool infer_callback_done = false;
|
542 |
+
run_loop.reset(new base::RunLoop);
|
543 |
+
recognizer->Recognize(
|
544 |
+
std::move(query),
|
545 |
+
base::BindOnce(
|
546 |
+
[](bool* infer_callback_done,
|
547 |
+
mojom::HandwritingRecognizerResultPtr result) {
|
548 |
+
*infer_callback_done = true;
|
549 |
+
// Check if the annotation is correct.
|
550 |
+
ASSERT_EQ(result->status,
|
551 |
+
mojom::HandwritingRecognizerResult::Status::OK);
|
552 |
+
EXPECT_EQ(result->candidates.at(0)->text, "cat");
|
553 |
+
EXPECT_EQ(result->candidates.at(0)->score, 0.5f);
|
554 |
+
},
|
555 |
+
&infer_callback_done)
|
556 |
+
.Then(run_loop->QuitClosure()));
|
557 |
+
run_loop->Run();
|
558 |
+
ASSERT_TRUE(infer_callback_done);
|
559 |
+
}
|
560 |
+
|
561 |
+
// Tests the fake ML service for web platform handwriting recognizer.
|
562 |
+
TEST_F(ServiceConnectionTest, FakeWebPlatformHandWritingRecognizer) {
|
563 |
+
mojo::Remote<web_platform::mojom::HandwritingRecognizer> recognizer;
|
564 |
+
bool callback_done = false;
|
565 |
+
FakeServiceConnectionImpl fake_service_connection;
|
566 |
+
ServiceConnection::UseFakeServiceConnectionForTesting(
|
567 |
+
&fake_service_connection);
|
568 |
+
ServiceConnection::GetInstance()->Initialize();
|
569 |
+
auto constraint = web_platform::mojom::HandwritingModelConstraint::New();
|
570 |
+
constraint->languages.emplace_back("en");
|
571 |
+
std::unique_ptr<base::RunLoop> run_loop = std::make_unique<base::RunLoop>();
|
572 |
+
ServiceConnection::GetInstance()
|
573 |
+
->GetMachineLearningService()
|
574 |
+
.LoadWebPlatformHandwritingModel(
|
575 |
+
std::move(constraint), recognizer.BindNewPipeAndPassReceiver(),
|
576 |
+
base::BindOnce(
|
577 |
+
[](bool* callback_done,
|
578 |
+
mojom::LoadHandwritingModelResult result) {
|
579 |
+
EXPECT_EQ(result, mojom::LoadHandwritingModelResult::OK);
|
580 |
+
*callback_done = true;
|
581 |
+
},
|
582 |
+
&callback_done)
|
583 |
+
.Then(run_loop->QuitClosure()));
|
584 |
+
run_loop->Run();
|
585 |
+
ASSERT_TRUE(callback_done);
|
586 |
+
ASSERT_TRUE(recognizer.is_bound());
|
587 |
+
|
588 |
+
// Construct fake output.
|
589 |
+
std::vector<web_platform::mojom::HandwritingPredictionPtr> predictions;
|
590 |
+
auto prediction1 = web_platform::mojom::HandwritingPrediction::New();
|
591 |
+
prediction1->text = "recognition1";
|
592 |
+
predictions.emplace_back(std::move(prediction1));
|
593 |
+
fake_service_connection.SetOutputWebPlatformHandwritingRecognizerResult(
|
594 |
+
predictions);
|
595 |
+
|
596 |
+
std::vector<web_platform::mojom::HandwritingStrokePtr> strokes;
|
597 |
+
auto hints = web_platform::mojom::HandwritingHints::New();
|
598 |
+
bool infer_callback_done = false;
|
599 |
+
run_loop.reset(new base::RunLoop);
|
600 |
+
recognizer->GetPrediction(
|
601 |
+
std::move(strokes), std::move(hints),
|
602 |
+
base::BindOnce(
|
603 |
+
[](bool* infer_callback_done,
|
604 |
+
absl::optional<std::vector<
|
605 |
+
web_platform::mojom::HandwritingPredictionPtr>> predictions) {
|
606 |
+
*infer_callback_done = true;
|
607 |
+
ASSERT_TRUE(predictions.has_value());
|
608 |
+
ASSERT_EQ(predictions.value().size(), 1u);
|
609 |
+
},
|
610 |
+
&infer_callback_done)
|
611 |
+
.Then(run_loop->QuitClosure()));
|
612 |
+
run_loop->Run();
|
613 |
+
ASSERT_TRUE(infer_callback_done);
|
614 |
+
}
|
615 |
+
|
616 |
+
TEST_F(ServiceConnectionTest, FakeGrammarChecker) {
|
617 |
+
mojo::Remote<mojom::GrammarChecker> checker;
|
618 |
+
bool callback_done = false;
|
619 |
+
FakeServiceConnectionImpl fake_service_connection;
|
620 |
+
ServiceConnection::UseFakeServiceConnectionForTesting(
|
621 |
+
&fake_service_connection);
|
622 |
+
ServiceConnection::GetInstance()->Initialize();
|
623 |
+
|
624 |
+
std::unique_ptr<base::RunLoop> run_loop = std::make_unique<base::RunLoop>();
|
625 |
+
ServiceConnection::GetInstance()
|
626 |
+
->GetMachineLearningService()
|
627 |
+
.LoadGrammarChecker(
|
628 |
+
checker.BindNewPipeAndPassReceiver(),
|
629 |
+
base::BindOnce(
|
630 |
+
[](bool* callback_done, mojom::LoadModelResult result) {
|
631 |
+
EXPECT_EQ(result, mojom::LoadModelResult::OK);
|
632 |
+
*callback_done = true;
|
633 |
+
},
|
634 |
+
&callback_done)
|
635 |
+
.Then(run_loop->QuitClosure()));
|
636 |
+
run_loop->Run();
|
637 |
+
ASSERT_TRUE(callback_done);
|
638 |
+
ASSERT_TRUE(checker.is_bound());
|
639 |
+
|
640 |
+
// Construct fake output
|
641 |
+
mojom::GrammarCheckerResultPtr result = mojom::GrammarCheckerResult::New();
|
642 |
+
result->status = mojom::GrammarCheckerResult::Status::OK;
|
643 |
+
mojom::GrammarCheckerCandidatePtr candidate =
|
644 |
+
mojom::GrammarCheckerCandidate::New();
|
645 |
+
candidate->text = "cat";
|
646 |
+
candidate->score = 0.5f;
|
647 |
+
mojom::GrammarCorrectionFragmentPtr fragment =
|
648 |
+
mojom::GrammarCorrectionFragment::New();
|
649 |
+
fragment->offset = 3;
|
650 |
+
fragment->length = 5;
|
651 |
+
fragment->replacement = "dog";
|
652 |
+
candidate->fragments.emplace_back(std::move(fragment));
|
653 |
+
result->candidates.emplace_back(std::move(candidate));
|
654 |
+
fake_service_connection.SetOutputGrammarCheckerResult(result);
|
655 |
+
|
656 |
+
auto query = mojom::GrammarCheckerQuery::New();
|
657 |
+
bool infer_callback_done = false;
|
658 |
+
run_loop.reset(new base::RunLoop);
|
659 |
+
checker->Check(
|
660 |
+
std::move(query),
|
661 |
+
base::BindOnce(
|
662 |
+
[](bool* infer_callback_done, mojom::GrammarCheckerResultPtr result) {
|
663 |
+
*infer_callback_done = true;
|
664 |
+
// Check if the annotation is correct.
|
665 |
+
ASSERT_EQ(result->status, mojom::GrammarCheckerResult::Status::OK);
|
666 |
+
ASSERT_EQ(result->candidates.size(), 1UL);
|
667 |
+
EXPECT_EQ(result->candidates.at(0)->text, "cat");
|
668 |
+
EXPECT_EQ(result->candidates.at(0)->score, 0.5f);
|
669 |
+
|
670 |
+
ASSERT_EQ(result->candidates.at(0)->fragments.size(), 1UL);
|
671 |
+
EXPECT_EQ(result->candidates.at(0)->fragments.at(0)->offset, 3U);
|
672 |
+
EXPECT_EQ(result->candidates.at(0)->fragments.at(0)->length, 5U);
|
673 |
+
EXPECT_EQ(result->candidates.at(0)->fragments.at(0)->replacement,
|
674 |
+
"dog");
|
675 |
+
},
|
676 |
+
&infer_callback_done)
|
677 |
+
.Then(run_loop->QuitClosure()));
|
678 |
+
run_loop->Run();
|
679 |
+
ASSERT_TRUE(infer_callback_done);
|
680 |
+
}
|
681 |
+
|
682 |
+
TEST_F(ServiceConnectionTest, FakeTextSuggester) {
|
683 |
+
mojo::Remote<mojom::TextSuggester> suggester;
|
684 |
+
bool callback_done = false;
|
685 |
+
FakeServiceConnectionImpl fake_service_connection;
|
686 |
+
ServiceConnection::UseFakeServiceConnectionForTesting(
|
687 |
+
&fake_service_connection);
|
688 |
+
ServiceConnection::GetInstance()->Initialize();
|
689 |
+
|
690 |
+
std::unique_ptr<base::RunLoop> run_loop = std::make_unique<base::RunLoop>();
|
691 |
+
ServiceConnection::GetInstance()
|
692 |
+
->GetMachineLearningService()
|
693 |
+
.LoadTextSuggester(
|
694 |
+
suggester.BindNewPipeAndPassReceiver(),
|
695 |
+
mojom::TextSuggesterSpec::New(),
|
696 |
+
base::BindOnce(
|
697 |
+
[](bool* callback_done, mojom::LoadModelResult result) {
|
698 |
+
EXPECT_EQ(result, mojom::LoadModelResult::OK);
|
699 |
+
*callback_done = true;
|
700 |
+
},
|
701 |
+
&callback_done)
|
702 |
+
.Then(run_loop->QuitClosure()));
|
703 |
+
run_loop->Run();
|
704 |
+
ASSERT_TRUE(callback_done);
|
705 |
+
ASSERT_TRUE(suggester.is_bound());
|
706 |
+
|
707 |
+
// Construct fake output
|
708 |
+
mojom::TextSuggesterResultPtr result = mojom::TextSuggesterResult::New();
|
709 |
+
result->status = mojom::TextSuggesterResult::Status::OK;
|
710 |
+
|
711 |
+
mojom::MultiWordSuggestionCandidatePtr multi_word =
|
712 |
+
mojom::MultiWordSuggestionCandidate::New();
|
713 |
+
multi_word->text = "hello";
|
714 |
+
multi_word->normalized_score = 0.5f;
|
715 |
+
mojom::TextSuggestionCandidatePtr candidate =
|
716 |
+
mojom::TextSuggestionCandidate::New();
|
717 |
+
candidate->set_multi_word(std::move(multi_word));
|
718 |
+
|
719 |
+
result->candidates.emplace_back(std::move(candidate));
|
720 |
+
fake_service_connection.SetOutputTextSuggesterResult(result);
|
721 |
+
|
722 |
+
auto query = mojom::TextSuggesterQuery::New();
|
723 |
+
bool infer_callback_done = false;
|
724 |
+
run_loop.reset(new base::RunLoop);
|
725 |
+
suggester->Suggest(
|
726 |
+
std::move(query),
|
727 |
+
base::BindOnce(
|
728 |
+
[](bool* infer_callback_done, mojom::TextSuggesterResultPtr result) {
|
729 |
+
*infer_callback_done = true;
|
730 |
+
// Check the fake suggestion is returned
|
731 |
+
ASSERT_EQ(result->status, mojom::TextSuggesterResult::Status::OK);
|
732 |
+
ASSERT_EQ(result->candidates.size(), 1UL);
|
733 |
+
ASSERT_TRUE(result->candidates.at(0)->is_multi_word());
|
734 |
+
EXPECT_EQ(result->candidates.at(0)->get_multi_word()->text,
|
735 |
+
"hello");
|
736 |
+
EXPECT_EQ(
|
737 |
+
result->candidates.at(0)->get_multi_word()->normalized_score,
|
738 |
+
0.5f);
|
739 |
+
},
|
740 |
+
&infer_callback_done)
|
741 |
+
.Then(run_loop->QuitClosure()));
|
742 |
+
run_loop->Run();
|
743 |
+
ASSERT_TRUE(infer_callback_done);
|
744 |
+
}
|
745 |
+
|
746 |
+
// Tests the fake ML service for document scanner.
|
747 |
+
TEST_F(ServiceConnectionTest, FakeDocumentScanner) {
|
748 |
+
mojo::Remote<mojom::DocumentScanner> scanner;
|
749 |
+
bool callback_done = false;
|
750 |
+
FakeServiceConnectionImpl fake_service_connection;
|
751 |
+
ServiceConnection::UseFakeServiceConnectionForTesting(
|
752 |
+
&fake_service_connection);
|
753 |
+
ServiceConnection::GetInstance()->Initialize();
|
754 |
+
|
755 |
+
std::unique_ptr<base::RunLoop> run_loop = std::make_unique<base::RunLoop>();
|
756 |
+
ServiceConnection::GetInstance()
|
757 |
+
->GetMachineLearningService()
|
758 |
+
.LoadDocumentScanner(
|
759 |
+
scanner.BindNewPipeAndPassReceiver(),
|
760 |
+
base::BindOnce(
|
761 |
+
[](bool* callback_done, mojom::LoadModelResult result) {
|
762 |
+
EXPECT_EQ(result, mojom::LoadModelResult::OK);
|
763 |
+
*callback_done = true;
|
764 |
+
},
|
765 |
+
&callback_done)
|
766 |
+
.Then(run_loop->QuitClosure()));
|
767 |
+
run_loop->Run();
|
768 |
+
ASSERT_TRUE(callback_done);
|
769 |
+
ASSERT_TRUE(scanner.is_bound());
|
770 |
+
|
771 |
+
constexpr int kNv12ImageSize = 256 * 256;
|
772 |
+
std::vector<uint8_t> fake_nv12_data(kNv12ImageSize, 0);
|
773 |
+
base::MappedReadOnlyRegion memory =
|
774 |
+
base::ReadOnlySharedMemoryRegion::Create(fake_nv12_data.size());
|
775 |
+
memcpy(memory.mapping.memory(), fake_nv12_data.data(), fake_nv12_data.size());
|
776 |
+
|
777 |
+
mojom::DetectCornersResultPtr result = mojom::DetectCornersResult::New();
|
778 |
+
result->status = mojom::DocumentScannerResultStatus::OK;
|
779 |
+
result->corners = {};
|
780 |
+
fake_service_connection.SetOutputDetectCornersResult(std::move(result));
|
781 |
+
|
782 |
+
bool infer_callback_done = false;
|
783 |
+
run_loop.reset(new base::RunLoop);
|
784 |
+
scanner->DetectCornersFromNV12Image(
|
785 |
+
std::move(memory.region),
|
786 |
+
base::BindOnce(
|
787 |
+
[](bool* infer_callback_done, mojom::DetectCornersResultPtr result) {
|
788 |
+
*infer_callback_done = true;
|
789 |
+
ASSERT_EQ(result->status, mojom::DocumentScannerResultStatus::OK);
|
790 |
+
ASSERT_TRUE(result->corners.size() == 0);
|
791 |
+
},
|
792 |
+
&infer_callback_done)
|
793 |
+
.Then(run_loop->QuitClosure()));
|
794 |
+
run_loop->Run();
|
795 |
+
ASSERT_TRUE(infer_callback_done);
|
796 |
+
}
|
797 |
+
|
798 |
+
} // namespace
|
799 |
+
} // namespace machine_learning
|
800 |
+
} // namespace chromeos
|
19/public/mojom/BUILD.gn
ADDED
@@ -0,0 +1,36 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
# Copyright 2018 The Chromium Authors. All rights reserved.
|
2 |
+
# Use of this source code is governed by a BSD-style license that can be
|
3 |
+
# found in the LICENSE file.
|
4 |
+
|
5 |
+
import("//mojo/public/tools/bindings/mojom.gni")
|
6 |
+
|
7 |
+
mojom_component("mojom") {
|
8 |
+
sources = [
|
9 |
+
"document_scanner.mojom",
|
10 |
+
"grammar_checker.mojom",
|
11 |
+
"graph_executor.mojom",
|
12 |
+
"handwriting_recognizer.mojom",
|
13 |
+
"machine_learning_service.mojom",
|
14 |
+
"model.mojom",
|
15 |
+
"soda.mojom",
|
16 |
+
"tensor.mojom",
|
17 |
+
"text_classifier.mojom",
|
18 |
+
"text_suggester.mojom",
|
19 |
+
"web_platform_handwriting.mojom",
|
20 |
+
]
|
21 |
+
|
22 |
+
public_deps = [
|
23 |
+
":document_scanner_param_types",
|
24 |
+
"//mojo/public/mojom/base",
|
25 |
+
]
|
26 |
+
|
27 |
+
deps = [ "//ui/gfx/geometry/mojom" ]
|
28 |
+
|
29 |
+
output_prefix = "mlservice_mojom"
|
30 |
+
macro_prefix = "MLSERVICE_MOJOM"
|
31 |
+
}
|
32 |
+
|
33 |
+
mojom("document_scanner_param_types") {
|
34 |
+
sources = [ "document_scanner_param_types.mojom" ]
|
35 |
+
webui_module_path = "/chromeos/services/machine_learning/public/mojom"
|
36 |
+
}
|
19/public/mojom/OWNERS
ADDED
@@ -0,0 +1,2 @@
|
|
|
|
|
|
|
1 |
+
per-file *.mojom=set noparent
|
2 |
+
per-file *.mojom=file://ipc/SECURITY_OWNERS
|
19/public/mojom/document_scanner.mojom
ADDED
@@ -0,0 +1,76 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
// Copyright 2021 The Chromium Authors. All rights reserved.
|
2 |
+
// Use of this source code is governed by a BSD-style license that can be
|
3 |
+
// found in the LICENSE file.
|
4 |
+
|
5 |
+
// Next MinVersion: 2
|
6 |
+
|
7 |
+
// Datatypes and interfaces of document scanner API.
|
8 |
+
|
9 |
+
// NOTE: This mojom exists in two places and must be kept in sync:
|
10 |
+
// Chromium: //chromeos/services/machine_learning/public/mojom/
|
11 |
+
// Chrome OS: src/platform2/ml/mojom/
|
12 |
+
// Note: Other repos downstream of Chromium might also use this mojom.
|
13 |
+
// Example: A backwards-compatible mojom change (and corresponding
|
14 |
+
// implementation change) can be made in Chrome OS first, then replicated to the
|
15 |
+
// clients (Chromium, other downstream repos) later.
|
16 |
+
// Use //chromeos/services/machine_learning/public/mojom/roll_mojoms.sh to help
|
17 |
+
// replicate Chrome OS-side changes over to Chromium.
|
18 |
+
|
19 |
+
module chromeos.machine_learning.mojom;
|
20 |
+
|
21 |
+
import "chromeos/services/machine_learning/public/mojom/document_scanner_param_types.mojom";
|
22 |
+
import "ui/gfx/geometry/mojom/geometry.mojom";
|
23 |
+
import "mojo/public/mojom/base/shared_memory.mojom";
|
24 |
+
|
25 |
+
// Status of the document scanner response.
|
26 |
+
[Stable, Extensible]
|
27 |
+
enum DocumentScannerResultStatus {
|
28 |
+
OK = 0,
|
29 |
+
ERROR = 1,
|
30 |
+
};
|
31 |
+
|
32 |
+
// The corner detection response.
|
33 |
+
// Next min field ID: 2
|
34 |
+
[Stable]
|
35 |
+
struct DetectCornersResult {
|
36 |
+
// Status of the result. Even when there is no corners detected, the detection
|
37 |
+
// can still be considered successful if there is no error occurs.
|
38 |
+
DocumentScannerResultStatus status@0;
|
39 |
+
|
40 |
+
// Detected document corners.
|
41 |
+
array<gfx.mojom.PointF> corners@1;
|
42 |
+
};
|
43 |
+
|
44 |
+
// The post processing response.
|
45 |
+
// Next min field ID: 2
|
46 |
+
[Stable]
|
47 |
+
struct DoPostProcessingResult {
|
48 |
+
// Status of the result.
|
49 |
+
DocumentScannerResultStatus status@0;
|
50 |
+
|
51 |
+
// Image data after processing. Will be in JPG format.
|
52 |
+
array<uint8> processed_jpeg_image@1;
|
53 |
+
};
|
54 |
+
|
55 |
+
// The mojom interface for performing document scanning.
|
56 |
+
// Next ordinal: 3
|
57 |
+
[Stable]
|
58 |
+
interface DocumentScanner {
|
59 |
+
// Detect document corners for given `nv12_image` which is in 256x256 size.
|
60 |
+
DetectCornersFromNV12Image@0(
|
61 |
+
mojo_base.mojom.ReadOnlySharedMemoryRegion nv12_image)
|
62 |
+
=> (DetectCornersResult result);
|
63 |
+
|
64 |
+
// Detect document corners for given `jpeg_image`.
|
65 |
+
DetectCornersFromJPEGImage@1(
|
66 |
+
mojo_base.mojom.ReadOnlySharedMemoryRegion jpeg_image)
|
67 |
+
=> (DetectCornersResult result);
|
68 |
+
|
69 |
+
// Do post processing such as rectification for the document region, contrast
|
70 |
+
// enhancement on the given `jpeg_image` according to document `corners`,
|
71 |
+
// clockwise rotation in `rotation` degrees.
|
72 |
+
DoPostProcessing@2(mojo_base.mojom.ReadOnlySharedMemoryRegion jpeg_image,
|
73 |
+
array<gfx.mojom.PointF> corners,
|
74 |
+
[MinVersion=1] Rotation rotation)
|
75 |
+
=> (DoPostProcessingResult result);
|
76 |
+
};
|
19/public/mojom/document_scanner_param_types.mojom
ADDED
@@ -0,0 +1,30 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
// Copyright 2021 The Chromium Authors. All rights reserved.
|
2 |
+
// Use of this source code is governed by a BSD-style license that can be
|
3 |
+
// found in the LICENSE file.
|
4 |
+
|
5 |
+
// Common datatypes shared between document scanner API and camera app.
|
6 |
+
|
7 |
+
// NOTE: This mojom exists in two places and must be kept in sync:
|
8 |
+
// Chromium: //chromeos/services/machine_learning/public/mojom/
|
9 |
+
// Chrome OS: src/platform2/ml/mojom/
|
10 |
+
// Note: Other repos downstream of Chromium might also use this mojom.
|
11 |
+
// Example: A backwards-compatible mojom change (and corresponding
|
12 |
+
// implementation change) can be made in Chrome OS first, then replicated to the
|
13 |
+
// clients (Chromium, other downstream repos) later.
|
14 |
+
// Use //chromeos/services/machine_learning/public/mojom/roll_mojoms.sh to help
|
15 |
+
// replicate Chrome OS-side changes over to Chromium.
|
16 |
+
|
17 |
+
module chromeos.machine_learning.mojom;
|
18 |
+
|
19 |
+
// Image rotation in clockwise direction.
|
20 |
+
[Stable, Extensible]
|
21 |
+
enum Rotation {
|
22 |
+
// 0 degree rotation (no rotation).
|
23 |
+
ROTATION_0 = 0,
|
24 |
+
// 90 degree rotation.
|
25 |
+
ROTATION_90 = 1,
|
26 |
+
// 180 degree rotation.
|
27 |
+
ROTATION_180 = 2,
|
28 |
+
// 270 degree rotation.
|
29 |
+
ROTATION_270 = 3,
|
30 |
+
};
|
19/public/mojom/grammar_checker.mojom
ADDED
@@ -0,0 +1,80 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
// Copyright 2020 The Chromium Authors. All rights reserved.
|
2 |
+
// Use of this source code is governed by a BSD-style license that can be
|
3 |
+
// found in the LICENSE file.
|
4 |
+
|
5 |
+
// Datatypes and interfaces of grammar checker API.
|
6 |
+
|
7 |
+
// NOTE: This mojom exists in two places and must be kept in sync:
|
8 |
+
// Chromium: //chromeos/services/machine_learning/public/mojom/
|
9 |
+
// Chrome OS: src/platform2/ml/mojom/
|
10 |
+
// Note: Other repos downstream of Chromium might also use this mojom.
|
11 |
+
// Example: A backwards-compatible mojom change (and corresponding
|
12 |
+
// implementation change) can be made in Chrome OS first, then replicated to the
|
13 |
+
// clients (Chromium, other downstream repos) later.
|
14 |
+
// Use //chromeos/services/machine_learning/public/mojom/roll_mojoms.sh to help
|
15 |
+
// replicate Chrome OS-side changes over to Chromium.
|
16 |
+
|
17 |
+
module chromeos.machine_learning.mojom;
|
18 |
+
|
19 |
+
// Defines a grammar check query.
|
20 |
+
[Stable]
|
21 |
+
struct GrammarCheckerQuery {
|
22 |
+
// Required: Text to be checked. This is expected to be a full sentence.
|
23 |
+
string text;
|
24 |
+
|
25 |
+
// Required: Language of the text to be checked, in BCP-47 format.
|
26 |
+
string language;
|
27 |
+
};
|
28 |
+
|
29 |
+
// A span with suggested corrections.
|
30 |
+
[Stable]
|
31 |
+
struct GrammarCorrectionFragment {
|
32 |
+
// The start offset in the original text.
|
33 |
+
uint32 offset;
|
34 |
+
|
35 |
+
// The length of the fragment in the original text.
|
36 |
+
uint32 length;
|
37 |
+
|
38 |
+
// The replacement string.
|
39 |
+
string replacement;
|
40 |
+
};
|
41 |
+
|
42 |
+
// One possible candidate returned from the grammar checker model.
|
43 |
+
[Stable]
|
44 |
+
struct GrammarCheckerCandidate {
|
45 |
+
// Corrected text.
|
46 |
+
string text;
|
47 |
+
|
48 |
+
// Score of the text. Log of conditional probability.
|
49 |
+
float score;
|
50 |
+
|
51 |
+
// The list of individual corrections.
|
52 |
+
array<GrammarCorrectionFragment> fragments;
|
53 |
+
};
|
54 |
+
|
55 |
+
// The grammar check response.
|
56 |
+
[Stable]
|
57 |
+
struct GrammarCheckerResult {
|
58 |
+
// Status of the response.
|
59 |
+
[Stable, Extensible]
|
60 |
+
enum Status {
|
61 |
+
// Grammar check succeeded.
|
62 |
+
OK = 0,
|
63 |
+
// Grammar check failed. In this case, candidates will be empty.
|
64 |
+
ERROR = 1,
|
65 |
+
};
|
66 |
+
Status status;
|
67 |
+
|
68 |
+
// Candidates of corrected text and their scores, sorted by higher score
|
69 |
+
// first.
|
70 |
+
array<GrammarCheckerCandidate> candidates;
|
71 |
+
};
|
72 |
+
|
73 |
+
// The mojom interface for performing the grammar check.
|
74 |
+
// Next ordinal: 1
|
75 |
+
[Stable]
|
76 |
+
interface GrammarChecker {
|
77 |
+
// Performs grammar check on a piece of text, and returns a set of
|
78 |
+
// candidates of corrected text and their scores.
|
79 |
+
Check@0(GrammarCheckerQuery query) => (GrammarCheckerResult result);
|
80 |
+
};
|
19/public/mojom/graph_executor.mojom
ADDED
@@ -0,0 +1,47 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
// Copyright 2018 The Chromium Authors. All rights reserved.
|
2 |
+
// Use of this source code is governed by a BSD-style license that can be
|
3 |
+
// found in the LICENSE file.
|
4 |
+
|
5 |
+
// NOTE: This mojom exists in two places and must be kept in sync:
|
6 |
+
// Chromium: //chromeos/services/machine_learning/public/mojom/
|
7 |
+
// Chrome OS: src/platform2/ml/mojom/
|
8 |
+
// Note: Other repos downstream of Chromium might also use this mojom.
|
9 |
+
// Example: A backwards-compatible mojom change (and corresponding
|
10 |
+
// implementation change) can be made in Chrome OS first, then replicated to the
|
11 |
+
// clients (Chromium, other downstream repos) later.
|
12 |
+
// Use //chromeos/services/machine_learning/public/mojom/roll_mojoms.sh to help
|
13 |
+
// replicate Chrome OS-side changes over to Chromium.
|
14 |
+
|
15 |
+
module chromeos.machine_learning.mojom;
|
16 |
+
|
17 |
+
// NOTE: The base directory for 'import' statements is expected to differ
|
18 |
+
// between Chromium and Chrome OS versions of this file.
|
19 |
+
import "chromeos/services/machine_learning/public/mojom/tensor.mojom";
|
20 |
+
|
21 |
+
// These values are persisted to logs. Entries should not be renumbered and
|
22 |
+
// numeric values should never be reused.
|
23 |
+
[Stable, Extensible]
|
24 |
+
enum ExecuteResult {
|
25 |
+
OK = 0,
|
26 |
+
INPUT_MISSING_ERROR = 1,
|
27 |
+
UNKNOWN_INPUT_ERROR = 2,
|
28 |
+
INPUT_TYPE_ERROR = 3,
|
29 |
+
INPUT_SHAPE_ERROR = 4,
|
30 |
+
INPUT_FORMAT_ERROR = 5,
|
31 |
+
OUTPUT_MISSING_ERROR = 6,
|
32 |
+
UNKNOWN_OUTPUT_ERROR = 7,
|
33 |
+
DUPLICATE_OUTPUT_ERROR = 8,
|
34 |
+
EXECUTION_ERROR = 9,
|
35 |
+
};
|
36 |
+
|
37 |
+
// API for performing inference on a TensorFlow graph. A given graph can be
|
38 |
+
// executed multiple times with a single instance of GraphExecutor.
|
39 |
+
// Next ordinal: 1
|
40 |
+
[Stable]
|
41 |
+
interface GraphExecutor {
|
42 |
+
// Initializes input node values as specified in `inputs`, then executes the
|
43 |
+
// graph. The returned `outputs` are the values for the nodes specified in
|
44 |
+
// `output_names`.
|
45 |
+
Execute@0(map<string, Tensor> inputs, array<string> output_names)
|
46 |
+
=> (ExecuteResult result, array<Tensor>? outputs);
|
47 |
+
};
|
19/public/mojom/handwriting_recognizer.mojom
ADDED
@@ -0,0 +1,196 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
// Copyright 2020 The Chromium Authors. All rights reserved.
|
2 |
+
// Use of this source code is governed by a BSD-style license that can be
|
3 |
+
// found in the LICENSE file.
|
4 |
+
|
5 |
+
// Next MinVersion: 2
|
6 |
+
|
7 |
+
// Datatypes and interfaces of handwriting recognition API.
|
8 |
+
|
9 |
+
// NOTE: This mojom exists in two places and must be kept in sync:
|
10 |
+
// Chromium: //chromeos/services/machine_learning/public/mojom/
|
11 |
+
// Chrome OS: src/platform2/ml/mojom/
|
12 |
+
// Note: Other repos downstream of Chromium might also use this mojom.
|
13 |
+
// Example: A backwards-compatible mojom change (and corresponding
|
14 |
+
// implementation change) can be made in Chrome OS first, then replicated to the
|
15 |
+
// clients (Chromium, other downstream repos) later.
|
16 |
+
// Use //chromeos/services/machine_learning/public/mojom/roll_mojoms.sh to help
|
17 |
+
// replicate Chrome OS-side changes over to Chromium.
|
18 |
+
|
19 |
+
module chromeos.machine_learning.mojom;
|
20 |
+
|
21 |
+
import "mojo/public/mojom/base/time.mojom";
|
22 |
+
|
23 |
+
// A single point in an ink stroke.
|
24 |
+
[Stable]
|
25 |
+
struct InkPoint {
|
26 |
+
// (x, y) coordinates of the point. The upper-left corner of the writing area
|
27 |
+
// is (0, 0). The positive x-axis points to the right. The positive y-axis
|
28 |
+
// points down.
|
29 |
+
float x;
|
30 |
+
float y;
|
31 |
+
// Optional TimeDelta from the point was captured relative to the beginning of
|
32 |
+
// the ink. So first point of a request should have t=0.
|
33 |
+
mojo_base.mojom.TimeDelta? t;
|
34 |
+
};
|
35 |
+
|
36 |
+
// A single ink stroke.
|
37 |
+
[Stable]
|
38 |
+
struct InkStroke {
|
39 |
+
// The set of points representing the stroke.
|
40 |
+
array<InkPoint> points;
|
41 |
+
};
|
42 |
+
|
43 |
+
// The writing guide shown to the user during input.
|
44 |
+
[Stable]
|
45 |
+
struct WritingGuide {
|
46 |
+
// Size of the writing area. The writing area must have (0, 0) at the top
|
47 |
+
// left.
|
48 |
+
// width is the max value of x-axis (to the right) and height is the max
|
49 |
+
// value of y-axis (to the bottom).
|
50 |
+
float width;
|
51 |
+
float height;
|
52 |
+
};
|
53 |
+
|
54 |
+
// Options that will influence the recognition output.
|
55 |
+
[Stable]
|
56 |
+
struct RecognitionContext {
|
57 |
+
// The writing guide shown to the user when the ink was captured.
|
58 |
+
WritingGuide? writing_guide;
|
59 |
+
// The context before the written text.
|
60 |
+
string? pre_context;
|
61 |
+
};
|
62 |
+
|
63 |
+
// Defines a handwriting recognition query.
|
64 |
+
[Stable]
|
65 |
+
struct HandwritingRecognitionQuery {
|
66 |
+
// The set of ink strokes to be recognized.
|
67 |
+
array<InkStroke> ink;
|
68 |
+
// The optional context in which the ink was generated.
|
69 |
+
RecognitionContext? context;
|
70 |
+
// Maximum number of results to be returned.
|
71 |
+
uint32 max_num_results;
|
72 |
+
// If true, returns the segmentation results. This will make the response
|
73 |
+
// struct much larger.
|
74 |
+
bool return_segmentation;
|
75 |
+
};
|
76 |
+
|
77 |
+
// Represents a contiguous range of ink. Start and end strokes / points are
|
78 |
+
// inclusive.
|
79 |
+
[Stable]
|
80 |
+
struct HandwritingRecognizerInkRange {
|
81 |
+
// Zero-based start- and end-stroke indices in the ink strokes.
|
82 |
+
uint32 start_stroke;
|
83 |
+
uint32 end_stroke;
|
84 |
+
// Zero-based start- and end-point indices with the start / end strokes.
|
85 |
+
uint32 start_point;
|
86 |
+
uint32 end_point;
|
87 |
+
};
|
88 |
+
|
89 |
+
// A segment defines the substrokes that are associated with a substring of the
|
90 |
+
// recognized text.
|
91 |
+
[Stable]
|
92 |
+
struct HandwritingRecognizerSegment {
|
93 |
+
// The substring of the recognized text represented by this segment.
|
94 |
+
string sublabel;
|
95 |
+
// The ink ranges represented by this segment.
|
96 |
+
array<HandwritingRecognizerInkRange> ink_ranges;
|
97 |
+
};
|
98 |
+
|
99 |
+
// The ink segmentation information.
|
100 |
+
[Stable]
|
101 |
+
struct HandwritingRecognizerSegmentation {
|
102 |
+
// The grouping of the cut strokes into characters.
|
103 |
+
array<HandwritingRecognizerSegment> segments;
|
104 |
+
};
|
105 |
+
|
106 |
+
// One possible candidate from the handwriting recognition.
|
107 |
+
[Stable]
|
108 |
+
struct HandwritingRecognizerCandidate {
|
109 |
+
// The recognized text.
|
110 |
+
string text;
|
111 |
+
// Scores will most often correspond to -log(p(c)) or a scaling thereof, so
|
112 |
+
// lower scores represent higher confidence.
|
113 |
+
float score;
|
114 |
+
// The stroke segmentation that was used to generate the result.
|
115 |
+
HandwritingRecognizerSegmentation? segmentation;
|
116 |
+
};
|
117 |
+
|
118 |
+
// The handwriting recognition response.
|
119 |
+
[Stable]
|
120 |
+
struct HandwritingRecognizerResult {
|
121 |
+
// Status of the recognition response.
|
122 |
+
[Stable, Extensible]
|
123 |
+
enum Status {
|
124 |
+
OK = 0,
|
125 |
+
ERROR = 1,
|
126 |
+
};
|
127 |
+
Status status;
|
128 |
+
|
129 |
+
// The recognition candidates with additional alternatives, sorted by lower
|
130 |
+
// score first (lower score present higher confidence).
|
131 |
+
array<HandwritingRecognizerCandidate> candidates;
|
132 |
+
};
|
133 |
+
|
134 |
+
// The specification of a handwriting recognizer.
|
135 |
+
[Stable]
|
136 |
+
struct HandwritingRecognizerSpec {
|
137 |
+
// The language the recognizer will handle. Only "en" (for english) and
|
138 |
+
// "gesture_in_context" (for gesture) are supported.
|
139 |
+
string language;
|
140 |
+
|
141 |
+
// Path to the language pack to use (downloaded by Chrome via DLC).
|
142 |
+
[MinVersion=1] string? language_pack_path;
|
143 |
+
};
|
144 |
+
|
145 |
+
// The mojom interface for performing the recognition of handwritten text.
|
146 |
+
// Next ordinal: 1
|
147 |
+
[Stable]
|
148 |
+
interface HandwritingRecognizer {
|
149 |
+
// Performs handwriting recognition on a set of ink strokes, and returns a set
|
150 |
+
// of alternative recognition results.
|
151 |
+
Recognize@0(HandwritingRecognitionQuery query) =>
|
152 |
+
(HandwritingRecognizerResult result);
|
153 |
+
};
|
154 |
+
|
155 |
+
// Enum indicates the result of LoadHandwritingModel in mlservice.
|
156 |
+
[Stable, Extensible]
|
157 |
+
enum LoadHandwritingModelResult {
|
158 |
+
OK = 0,
|
159 |
+
|
160 |
+
// Deprecated enum values.
|
161 |
+
DEPRECATED_MODEL_SPEC_ERROR = 1,
|
162 |
+
LOAD_MODEL_ERROR = 2,
|
163 |
+
|
164 |
+
// If both USE.ondevice_handwriting and USE.ondevice_handwriting_dlc
|
165 |
+
// are not defined. (checked in chrome)
|
166 |
+
FEATURE_NOT_SUPPORTED_ERROR = 3,
|
167 |
+
|
168 |
+
// If the required language is not in an allowlist, "en" and
|
169 |
+
// "gesture_in_context" for now. (checked in chrome)
|
170 |
+
LANGUAGE_NOT_SUPPORTED_ERROR = 4,
|
171 |
+
|
172 |
+
// If the user goes to chrome://flag page and manually disable
|
173 |
+
// handwriting or handwriting_dlc. (checked in chrome)
|
174 |
+
FEATURE_DISABLED_BY_USER = 5,
|
175 |
+
|
176 |
+
// if the USE.ondevice_handwriting_dlc is enabled, but dlc is not
|
177 |
+
// on the device. (checked in chrome)
|
178 |
+
DLC_DOES_NOT_EXIST = 6,
|
179 |
+
|
180 |
+
// If the dlc is on the device, but InstallDlc returns an error.
|
181 |
+
// (checked in chrome).
|
182 |
+
DLC_INSTALL_ERROR = 7,
|
183 |
+
|
184 |
+
// If dlc is installed successfully, but GetDlcState returns an error.
|
185 |
+
// (checked inside MachineLearningServiceImpl)
|
186 |
+
DLC_GET_PATH_ERROR = 8,
|
187 |
+
|
188 |
+
// if loading libhandwriting.so fails. (checked inside HandWritingLibrary)
|
189 |
+
LOAD_NATIVE_LIB_ERROR = 9,
|
190 |
+
|
191 |
+
// if getting the function pointers fails. (checked inside HandWritingLibrary)
|
192 |
+
LOAD_FUNC_PTR_ERROR = 10,
|
193 |
+
|
194 |
+
// If loading model files fails. (checked inside HandWritingLibrary)
|
195 |
+
LOAD_MODEL_FILES_ERROR = 11,
|
196 |
+
};
|
19/public/mojom/machine_learning_service.mojom
ADDED
@@ -0,0 +1,103 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
// Copyright 2018 The Chromium Authors. All rights reserved.
|
2 |
+
// Use of this source code is governed by a BSD-style license that can be
|
3 |
+
// found in the LICENSE file.
|
4 |
+
|
5 |
+
// Next MinVersion: 5
|
6 |
+
|
7 |
+
// Top-level API of the Machine Learning Service: loading models for inference.
|
8 |
+
|
9 |
+
// NOTE: This mojom exists in two places and must be kept in sync:
|
10 |
+
// Chromium: //chromeos/services/machine_learning/public/mojom/
|
11 |
+
// Chrome OS: src/platform2/ml/mojom/
|
12 |
+
// Note: Other repos downstream of Chromium might also use this mojom.
|
13 |
+
// Example: A backwards-compatible mojom change (and corresponding
|
14 |
+
// implementation change) can be made in Chrome OS first, then replicated to the
|
15 |
+
// clients (Chromium, other downstream repos) later.
|
16 |
+
// Use //chromeos/services/machine_learning/public/mojom/roll_mojoms.sh to help
|
17 |
+
// replicate Chrome OS-side changes over to Chromium.
|
18 |
+
|
19 |
+
module chromeos.machine_learning.mojom;
|
20 |
+
|
21 |
+
// NOTE: The base directory for 'import' statements is expected to differ
|
22 |
+
// between Chromium and Chrome OS versions of this file.
|
23 |
+
import "chromeos/services/machine_learning/public/mojom/document_scanner.mojom";
|
24 |
+
import "chromeos/services/machine_learning/public/mojom/grammar_checker.mojom";
|
25 |
+
import "chromeos/services/machine_learning/public/mojom/handwriting_recognizer.mojom";
|
26 |
+
import "chromeos/services/machine_learning/public/mojom/model.mojom";
|
27 |
+
import "chromeos/services/machine_learning/public/mojom/soda.mojom";
|
28 |
+
import "chromeos/services/machine_learning/public/mojom/text_classifier.mojom";
|
29 |
+
import "chromeos/services/machine_learning/public/mojom/text_suggester.mojom";
|
30 |
+
import "chromeos/services/machine_learning/public/mojom/web_platform_handwriting.mojom";
|
31 |
+
|
32 |
+
// These values are persisted to logs. Entries should not be renumbered and
|
33 |
+
// numeric values should never be reused.
|
34 |
+
[Stable, Extensible]
|
35 |
+
enum LoadModelResult {
|
36 |
+
OK = 0,
|
37 |
+
MODEL_SPEC_ERROR = 1,
|
38 |
+
LOAD_MODEL_ERROR = 2,
|
39 |
+
FEATURE_NOT_SUPPORTED_ERROR = 3,
|
40 |
+
LANGUAGE_NOT_SUPPORTED_ERROR = 4,
|
41 |
+
};
|
42 |
+
|
43 |
+
// Top-level interface between Chromium browser process and the ML Service
|
44 |
+
// daemon.
|
45 |
+
// Next ordinal: 11
|
46 |
+
[Stable, Uuid="9e5e4750-40cc-4eda-ac09-3457d06a45ab"]
|
47 |
+
interface MachineLearningService {
|
48 |
+
// Binds another pipe to this instance.
|
49 |
+
Clone@5(pending_receiver<MachineLearningService> receiver);
|
50 |
+
|
51 |
+
// The BuiltinModelId inside BuiltinModelSpec is used to specify the model to
|
52 |
+
// be loaded.
|
53 |
+
LoadBuiltinModel@0(BuiltinModelSpec spec, pending_receiver<Model> receiver)
|
54 |
+
=> (LoadModelResult result);
|
55 |
+
// The FlatbufferModelSpec contains both of the flatbuffer content and the
|
56 |
+
// metadata.
|
57 |
+
LoadFlatBufferModel@1(FlatBufferModelSpec spec,
|
58 |
+
pending_receiver<Model> receiver)
|
59 |
+
=> (LoadModelResult result);
|
60 |
+
// Create a new TextClassifier.
|
61 |
+
LoadTextClassifier@2(pending_receiver<TextClassifier> receiver)
|
62 |
+
=> (LoadModelResult result);
|
63 |
+
// Create and initialize a handwriting recognizer with given `spec`.
|
64 |
+
LoadHandwritingModel@3(
|
65 |
+
HandwritingRecognizerSpec spec,
|
66 |
+
pending_receiver<HandwritingRecognizer> receiver)
|
67 |
+
=> (LoadHandwritingModelResult result);
|
68 |
+
// Create and initialize a speech recognizer with given `config`.
|
69 |
+
LoadSpeechRecognizer@6(SodaConfig config,
|
70 |
+
pending_remote<SodaClient> soda_client,
|
71 |
+
pending_receiver<SodaRecognizer> soda_recognizer)
|
72 |
+
=> (LoadModelResult result);
|
73 |
+
// Create and initialize a grammar checker.
|
74 |
+
LoadGrammarChecker@7(pending_receiver<GrammarChecker> receiver)
|
75 |
+
=> (LoadModelResult result);
|
76 |
+
// Create and initialize a text suggester.
|
77 |
+
[MinVersion=2] LoadTextSuggester@8(
|
78 |
+
pending_receiver<TextSuggester> receiver,
|
79 |
+
[MinVersion=3] TextSuggesterSpec? spec)
|
80 |
+
=> (LoadModelResult result);
|
81 |
+
// Create a handwriting recognizer for web platform API.
|
82 |
+
// This API shares the same HWR engine with `LoadHandwritingModel`
|
83 |
+
// but with a different interface. This API is as identical to
|
84 |
+
// the Web Platform HWR API as possible so that we do not
|
85 |
+
// need to convert the input/output in the browser process.
|
86 |
+
// This is required for security reasons.
|
87 |
+
[MinVersion=1] LoadWebPlatformHandwritingModel@9(
|
88 |
+
chromeos.machine_learning.web_platform.mojom.HandwritingModelConstraint
|
89 |
+
constraint,
|
90 |
+
pending_receiver<
|
91 |
+
chromeos.machine_learning.web_platform.mojom.HandwritingRecognizer>
|
92 |
+
receiver)
|
93 |
+
=> (LoadHandwritingModelResult result);
|
94 |
+
// Create and initialize a document scanner.
|
95 |
+
[MinVersion=4] LoadDocumentScanner@10(
|
96 |
+
pending_receiver<DocumentScanner> receiver)
|
97 |
+
=> (LoadModelResult result);
|
98 |
+
// Deprecated `LoadHandwritingModelWithSpec`
|
99 |
+
REMOVED_4@4(
|
100 |
+
HandwritingRecognizerSpec spec,
|
101 |
+
pending_receiver<HandwritingRecognizer> receiver)
|
102 |
+
=> (LoadModelResult result);
|
103 |
+
};
|
19/public/mojom/model.mojom
ADDED
@@ -0,0 +1,119 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
// Copyright 2018 The Chromium Authors. All rights reserved.
|
2 |
+
// Use of this source code is governed by a BSD-style license that can be
|
3 |
+
// found in the LICENSE file.
|
4 |
+
|
5 |
+
// Next MinVersion: 2
|
6 |
+
|
7 |
+
// Datatypes and interfaces of models for the Machine Learning API.
|
8 |
+
|
9 |
+
// NOTE: This mojom exists in two places and must be kept in sync:
|
10 |
+
// Chromium: //chromeos/services/machine_learning/public/mojom/
|
11 |
+
// Chrome OS: src/platform2/ml/mojom/
|
12 |
+
// Note: Other repos downstream of Chromium might also use this mojom.
|
13 |
+
// Example: A backwards-compatible mojom change (and corresponding
|
14 |
+
// implementation change) can be made in Chrome OS first, then replicated to the
|
15 |
+
// clients (Chromium, other downstream repos) later.
|
16 |
+
// Use //chromeos/services/machine_learning/public/mojom/roll_mojoms.sh to help
|
17 |
+
// replicate Chrome OS-side changes over to Chromium.
|
18 |
+
|
19 |
+
module chromeos.machine_learning.mojom;
|
20 |
+
|
21 |
+
// NOTE: The base directory for 'import' statements is expected to differ
|
22 |
+
// between Chromium and Chrome OS versions of this file.
|
23 |
+
import "chromeos/services/machine_learning/public/mojom/graph_executor.mojom";
|
24 |
+
|
25 |
+
// These values are persisted to logs. Entries should not be renumbered and
|
26 |
+
// numeric values should never be reused.
|
27 |
+
// ModelIds prefixed with UNSUPPORTED_ are no longer supported. Attempts to load
|
28 |
+
// them will produce an error.
|
29 |
+
[Stable, Extensible]
|
30 |
+
enum BuiltinModelId {
|
31 |
+
// Unknown ML model. It is marked as unsupported.
|
32 |
+
UNSUPPORTED_UNKNOWN = 0,
|
33 |
+
// Test ML model.
|
34 |
+
TEST_MODEL = 1,
|
35 |
+
// The Smart Dim (20181115) ML model.
|
36 |
+
UNSUPPORTED_SMART_DIM_20181115 = 2,
|
37 |
+
// The Smart Dim (20190221) ML model.
|
38 |
+
UNSUPPORTED_SMART_DIM_20190221 = 3,
|
39 |
+
// The Top Cat (20190722) ML model.
|
40 |
+
UNSUPPORTED_TOP_CAT_20190722 = 4,
|
41 |
+
// The Smart Dim (20190521) ML model.
|
42 |
+
SMART_DIM_20190521 = 5,
|
43 |
+
// The Search Ranker (20190923) ML model.
|
44 |
+
SEARCH_RANKER_20190923 = 6,
|
45 |
+
// The Adaptive Charging (20211105) ML model.
|
46 |
+
[MinVersion=1] ADAPTIVE_CHARGING_20211105 = 7,
|
47 |
+
};
|
48 |
+
|
49 |
+
// Options for creating the executor. Options are used for testing and
|
50 |
+
// development. They are not typically used in normal, production code.
|
51 |
+
[Stable]
|
52 |
+
struct GraphExecutorOptions {
|
53 |
+
bool use_nnapi = false;
|
54 |
+
[MinVersion=1] bool use_gpu = false;
|
55 |
+
};
|
56 |
+
|
57 |
+
// These values are persisted to logs. Entries should not be renumbered and
|
58 |
+
// numeric values should never be reused.
|
59 |
+
[Stable, Extensible]
|
60 |
+
enum CreateGraphExecutorResult {
|
61 |
+
OK = 0,
|
62 |
+
MODEL_INTERPRETATION_ERROR = 1,
|
63 |
+
MEMORY_ALLOCATION_ERROR = 2,
|
64 |
+
NNAPI_UNAVAILABLE = 3,
|
65 |
+
NNAPI_USE_ERROR = 4,
|
66 |
+
[MinVersion=1] GPU_UNAVAILABLE = 5,
|
67 |
+
[MinVersion=1] GPU_USE_ERROR = 6,
|
68 |
+
[MinVersion=1] DELEGATE_CONFIG_ERROR = 7,
|
69 |
+
[MinVersion=1] NOT_FULLY_DELEGABLE = 8,
|
70 |
+
};
|
71 |
+
|
72 |
+
// Model specification for builtin models.
|
73 |
+
// Because ml-service can retrieve a builtin model's content and metadata, only
|
74 |
+
// an `id` is needed to specify it.
|
75 |
+
[Stable]
|
76 |
+
struct BuiltinModelSpec {
|
77 |
+
BuiltinModelId id;
|
78 |
+
};
|
79 |
+
|
80 |
+
// Model specification for downloaded models.
|
81 |
+
// For a downloaded model, both of the model content and metadata must be
|
82 |
+
// specified.
|
83 |
+
[Stable]
|
84 |
+
struct FlatBufferModelSpec {
|
85 |
+
// The content of the model's tflite model file.
|
86 |
+
string model_string;
|
87 |
+
// A map from input nodes' names to their indices.
|
88 |
+
map<string, int32> inputs;
|
89 |
+
// A map from output nodes' names to their indices.
|
90 |
+
map<string, int32> outputs;
|
91 |
+
// Used in naming the UMA metric histograms of the model. An example of the
|
92 |
+
// names of the histograms is:
|
93 |
+
//
|
94 |
+
// MachineLearningService.`metrics_model_name`.ExecuteResult.CpuTimeMicrosec
|
95 |
+
//
|
96 |
+
// This variable must NOT be empty.
|
97 |
+
string metrics_model_name;
|
98 |
+
};
|
99 |
+
|
100 |
+
// The lifetime of the cached model is tied to the lifetime of the Model
|
101 |
+
// interface pipe. The Model interface pipe can be used to acquire multiple
|
102 |
+
// separate GraphExecutor instances.
|
103 |
+
// Next ordinal: 2
|
104 |
+
[Stable]
|
105 |
+
interface Model {
|
106 |
+
// Deprecated messages:
|
107 |
+
REMOVED_0@0(pending_receiver<GraphExecutor> receiver) =>
|
108 |
+
(CreateGraphExecutorResult result);
|
109 |
+
|
110 |
+
// Creates a new GraphExecutor with the specified `options` and binds it to
|
111 |
+
// `receiver`. The GraphExecutor can be used to repeatedly evaluate this
|
112 |
+
// `Model`.
|
113 |
+
// * A Model can have more than one GraphExecutor.
|
114 |
+
// * Releasing this GraphExecutor frees the associated memory (but
|
115 |
+
// doesn't free the Model unless its pipe is also closed).
|
116 |
+
CreateGraphExecutor@1(GraphExecutorOptions options,
|
117 |
+
pending_receiver<GraphExecutor> receiver) =>
|
118 |
+
(CreateGraphExecutorResult result);
|
119 |
+
};
|
19/public/mojom/roll_mojoms.sh
ADDED
@@ -0,0 +1,70 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
#!/bin/bash
|
2 |
+
|
3 |
+
# Copyright 2019 The Chromium Authors. All rights reserved.
|
4 |
+
# Use of this source code is governed by a BSD-style license that can be
|
5 |
+
# found in the LICENSE file.
|
6 |
+
|
7 |
+
usage() {
|
8 |
+
echo "Usage: $0 CROS_SRC_DIR"
|
9 |
+
echo ""
|
10 |
+
echo "Rolls (copies) ML Service *.mojom files from Chrome OS to current"
|
11 |
+
echo "directory, with appropriate boilerplate modifications for use in"
|
12 |
+
echo "Chromium."
|
13 |
+
echo ""
|
14 |
+
echo "CROS_SRC_DIR: Path to Chromium OS source, e.g. ~/chromiumos/src."
|
15 |
+
}
|
16 |
+
|
17 |
+
CROS_SRC_DIR="$1"
|
18 |
+
|
19 |
+
if [ -z "$CROS_SRC_DIR" ]; then
|
20 |
+
usage
|
21 |
+
exit 1
|
22 |
+
fi
|
23 |
+
|
24 |
+
if [ ! -d "$CROS_SRC_DIR" ]; then
|
25 |
+
echo "$CROS_SRC_DIR not a directory"
|
26 |
+
usage
|
27 |
+
exit 1
|
28 |
+
fi
|
29 |
+
|
30 |
+
if [ "$(basename $CROS_SRC_DIR)" != "src" ]; then
|
31 |
+
echo "$CROS_SRC_DIR should end with /src"
|
32 |
+
usage
|
33 |
+
exit 1
|
34 |
+
fi
|
35 |
+
|
36 |
+
if ! git diff-index --quiet HEAD -- ; then
|
37 |
+
echo "'git status' not clean. Commit your changes first."
|
38 |
+
exit 1
|
39 |
+
fi
|
40 |
+
|
41 |
+
readonly EXPECTED_PATH="chromeos/services/machine_learning/public/mojom"
|
42 |
+
if [[ "$(pwd)" != *"${EXPECTED_PATH}" ]]; then
|
43 |
+
echo "Please run from within ${EXPECTED_PATH}."
|
44 |
+
exit 1;
|
45 |
+
fi
|
46 |
+
|
47 |
+
echo "Copying mojoms from Chrome OS side ..."
|
48 |
+
cp $1/platform2/ml/mojom/*.mojom . || exit 1
|
49 |
+
|
50 |
+
echo "Removing time.mojom ..."
|
51 |
+
rm time.mojom || exit 1
|
52 |
+
|
53 |
+
echo "Removing shared_memory.mojom ..."
|
54 |
+
rm shared_memory.mojom || exit 1
|
55 |
+
|
56 |
+
echo "Removing geometry.mojom ..."
|
57 |
+
rm geometry.mojom || exit 1
|
58 |
+
|
59 |
+
echo "Changing import paths ..."
|
60 |
+
sed --in-place --regexp-extended \
|
61 |
+
-e 's~^import "ml/mojom/geometry.mojom~import "ui/gfx/geometry/mojom/geometry.mojom~g' \
|
62 |
+
-e 's~^import "ml/mojom/shared_memory.mojom~import "mojo/public/mojom/base/shared_memory.mojom~g' \
|
63 |
+
-e 's~^import "ml/mojom/time.mojom~import "mojo/public/mojom/base/time.mojom~g' \
|
64 |
+
-e 's~^import "ml~import "chromeos/services/machine_learning/public~g' \
|
65 |
+
*.mojom
|
66 |
+
|
67 |
+
echo "OK. Now:"
|
68 |
+
echo "1. Examine 'git diff' to double-check the results of this tool."
|
69 |
+
echo "2. After submitting, also update any google3 files generated from these "
|
70 |
+
echo " mojoms (e.g. javascript bindings)."
|
19/public/mojom/soda.mojom
ADDED
@@ -0,0 +1,214 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
// Copyright 2020 The Chromium Authors. All rights reserved.
|
2 |
+
// Use of this source code is governed by a BSD-style license that can be
|
3 |
+
// found in the LICENSE file.
|
4 |
+
|
5 |
+
// Datatypes and interfaces of speech recognition API.
|
6 |
+
|
7 |
+
// NOTE: This mojom exists in two places and must be kept in sync:
|
8 |
+
// Chromium: //chromeos/services/machine_learning/public/mojom/
|
9 |
+
// Chrome OS: src/platform2/ml/mojom/
|
10 |
+
// Note: Other repos downstream of Chromium might also use this mojom.
|
11 |
+
// Example: A backwards-compatible mojom change (and corresponding
|
12 |
+
// implementation change) can be made in Chrome OS first, then replicated to the
|
13 |
+
// clients (Chromium, other downstream repos) later.
|
14 |
+
// Use //chromeos/services/machine_learning/public/mojom/roll_mojoms.sh to help
|
15 |
+
// replicate Chrome OS-side changes over to Chromium.
|
16 |
+
// Versions list:
|
17 |
+
// Version 0: Initial
|
18 |
+
// Version 1: Include HypothesisPart Info in Final result.
|
19 |
+
// Version 2: Include enable formatting in request config.
|
20 |
+
// Version 3: Include recognition mode in request config.
|
21 |
+
module chromeos.machine_learning.mojom;
|
22 |
+
|
23 |
+
import "mojo/public/mojom/base/time.mojom";
|
24 |
+
|
25 |
+
// Augments a bool to include an 'unknown' value.
|
26 |
+
[Stable, Extensible]
|
27 |
+
enum OptionalBool {
|
28 |
+
[Default] kUnknown = 0,
|
29 |
+
kFalse,
|
30 |
+
kTrue,
|
31 |
+
};
|
32 |
+
|
33 |
+
[Stable, Extensible]
|
34 |
+
enum SodaRecognitionMode {
|
35 |
+
[Default] kCaption,
|
36 |
+
kIme,
|
37 |
+
};
|
38 |
+
|
39 |
+
// The configuration used to load Soda recognizer.
|
40 |
+
[Stable]
|
41 |
+
struct SodaConfig {
|
42 |
+
// Number of channels of the audio that will be sent to Soda recognizer.
|
43 |
+
uint32 channel_count;
|
44 |
+
// Sample rate of the audio that will be sent to Soda recognizer.
|
45 |
+
uint32 sample_rate;
|
46 |
+
// The api key for Soda library.
|
47 |
+
string api_key;
|
48 |
+
// Path to already-installed SODA library.
|
49 |
+
string library_dlc_path;
|
50 |
+
// Path to already-installed SODA language pack to use.
|
51 |
+
string language_dlc_path;
|
52 |
+
// Whether to enable automated punctuation. Defaults to true as this
|
53 |
+
// is the default in the underlying protocol buffer.
|
54 |
+
[MinVersion=2] OptionalBool enable_formatting = kTrue;
|
55 |
+
// Which mode to execute in: IME or CAPTION. Default CAPTION.
|
56 |
+
[MinVersion=3] SodaRecognitionMode recognition_mode = kCaption;
|
57 |
+
};
|
58 |
+
|
59 |
+
// From the endpointer, What kind of endpointer event to record.
|
60 |
+
[Stable, Extensible]
|
61 |
+
enum EndpointerType {
|
62 |
+
// Speech detected.
|
63 |
+
START_OF_SPEECH,
|
64 |
+
// End of speech detected, but audio continues.
|
65 |
+
END_OF_SPEECH,
|
66 |
+
// Audio is terminated.
|
67 |
+
END_OF_AUDIO,
|
68 |
+
// Query is terminated.
|
69 |
+
END_OF_UTTERANCE
|
70 |
+
};
|
71 |
+
|
72 |
+
// Common information about the timing of reported SODA events.
|
73 |
+
[Stable]
|
74 |
+
struct TimingInfo {
|
75 |
+
// Epoch time of the first audio buffer of the main query that is fed into
|
76 |
+
// ASR. This is the wall time read from the system clock when the first audio
|
77 |
+
// buffer is received by the terse processor.
|
78 |
+
mojo_base.mojom.Time audio_start_epoch;
|
79 |
+
|
80 |
+
// Start time in audio time from the start of the SODA session.
|
81 |
+
// This time measures the amount of audio input into SODA.
|
82 |
+
mojo_base.mojom.TimeDelta audio_start_time;
|
83 |
+
|
84 |
+
// Elapsed wall time usec since the first frame.
|
85 |
+
mojo_base.mojom.TimeDelta elapsed_wall_time;
|
86 |
+
|
87 |
+
// Elapsed processed audio usec from first frame after preamble.
|
88 |
+
mojo_base.mojom.TimeDelta event_end_time;
|
89 |
+
|
90 |
+
// On device benchmark latency as defined in go/asr-latency-metrics.
|
91 |
+
mojo_base.mojom.TimeDelta latency;
|
92 |
+
|
93 |
+
// On device counter part of E2E normalized latency as defined in
|
94 |
+
// go/asr-latency-metrics. This metric is mainly for non-continuous
|
95 |
+
// conversation.
|
96 |
+
float normalized_latency;
|
97 |
+
|
98 |
+
// Timing for each word as an offset from audio_start_time_usec.
|
99 |
+
array<mojo_base.mojom.TimeDelta> word_alignments;
|
100 |
+
};
|
101 |
+
|
102 |
+
// Start/end events.
|
103 |
+
[Stable]
|
104 |
+
struct EndpointerEvent {
|
105 |
+
EndpointerType endpointer_type;
|
106 |
+
TimingInfo? timing_event;
|
107 |
+
};
|
108 |
+
|
109 |
+
// A result _during_ a recognition. Could change at any time with the
|
110 |
+
// next partial or the final recognition for this chunk.
|
111 |
+
[Stable]
|
112 |
+
struct PartialResult {
|
113 |
+
// Most likely hypothesis so far. First is the most likely, followed by others.
|
114 |
+
// Note: the relationship from first to other hypothess is not guaranteed in
|
115 |
+
// any way.
|
116 |
+
array<string> partial_text;
|
117 |
+
TimingInfo? timing_event;
|
118 |
+
};
|
119 |
+
|
120 |
+
[Stable, Extensible]
|
121 |
+
enum EndpointReason {
|
122 |
+
// Default value, unknown reason.
|
123 |
+
ENDPOINT_UNKNOWN,
|
124 |
+
// Due to end_of_speech detection by endpointer.
|
125 |
+
ENDPOINT_END_OF_SPEECH,
|
126 |
+
// Due to end_of_utterance detection by endpointer.
|
127 |
+
ENDPOINT_END_OF_UTTERANCE,
|
128 |
+
// Due to the end of mics audio. This could be due to a mic event or SODA
|
129 |
+
// being stopped.
|
130 |
+
ENDPOINT_END_OF_AUDIO,
|
131 |
+
};
|
132 |
+
|
133 |
+
|
134 |
+
// Detail about a part of a hypothesis in a result. Only makes sense
|
135 |
+
// in context of an array of them for a hypothesis.
|
136 |
+
[Stable]
|
137 |
+
struct HypothesisPartInResult {
|
138 |
+
// Typically 1 item for a a word/piece of text. If formatting is
|
139 |
+
// enabled, the raw text is the second item.
|
140 |
+
array<string> text;
|
141 |
+
|
142 |
+
// Offset from the beginning of this part of the hypothesis from
|
143 |
+
// audio_start_time in TimingInfo.
|
144 |
+
mojo_base.mojom.TimeDelta alignment;
|
145 |
+
};
|
146 |
+
|
147 |
+
[Stable]
|
148 |
+
struct FinalResult {
|
149 |
+
// Sorted in decreasing order of probability.
|
150 |
+
array<string> final_hypotheses;
|
151 |
+
EndpointReason endpoint_reason;
|
152 |
+
TimingInfo? timing_event;
|
153 |
+
|
154 |
+
// If populated, this array contains the hypothesis parts for the
|
155 |
+
// first final hypothesis in the array of final_hypotheses.
|
156 |
+
[MinVersion=1] array<HypothesisPartInResult>? hypothesis_part;
|
157 |
+
};
|
158 |
+
|
159 |
+
// Frequent event from recognizer, almost from every frame. Gives an indication
|
160 |
+
// of speechiness and audio level.
|
161 |
+
[Stable]
|
162 |
+
struct AudioLevelEvent {
|
163 |
+
// RMS audio level, from PowerEvaluator . Score is [0, 1)
|
164 |
+
float rms;
|
165 |
+
// Speech likelihood score, from TerseProcessor. Score is [0, 1)
|
166 |
+
float audio_level;
|
167 |
+
};
|
168 |
+
|
169 |
+
// This essentially mirrors the subset of SODA's SodaEvent proto we will
|
170 |
+
// support.
|
171 |
+
[Stable]
|
172 |
+
union SpeechRecognizerEvent {
|
173 |
+
AudioLevelEvent audio_event;
|
174 |
+
PartialResult partial_result;
|
175 |
+
EndpointerEvent endpointer_event;
|
176 |
+
FinalResult final_result;
|
177 |
+
};
|
178 |
+
|
179 |
+
// This interface is called upon by the SodaRecognizer. Implemented by
|
180 |
+
// the client, SODA then calls these as 'events' with appropriate details
|
181 |
+
// when recognition occurs.
|
182 |
+
// Next ordinal: 3
|
183 |
+
[Stable]
|
184 |
+
interface SodaClient {
|
185 |
+
// After SODA successfully starts / warms up / stops, in case the client
|
186 |
+
// cares:
|
187 |
+
OnStart@0();
|
188 |
+
OnStop@1();
|
189 |
+
|
190 |
+
// This is how the client receives actual recognized text as well as other
|
191 |
+
// conclusions from the SODA model like "speech ended".
|
192 |
+
OnSpeechRecognizerEvent@2(SpeechRecognizerEvent event);
|
193 |
+
};
|
194 |
+
|
195 |
+
// The mojom interface for performing the recognition of handwritten text.
|
196 |
+
// Next ordinal: 4
|
197 |
+
[Stable]
|
198 |
+
interface SodaRecognizer {
|
199 |
+
// Add Audio for speech recognition.
|
200 |
+
AddAudio@0(array<uint8> audio);
|
201 |
+
|
202 |
+
// Instruct SODA to stop processing immediately. Stopping is
|
203 |
+
// confirmed when SodaClient::OnStop is called back.
|
204 |
+
Stop@1();
|
205 |
+
|
206 |
+
// Instruct SODA to start processing. Noop if already
|
207 |
+
// processing. When Stopped, causes a SodAclient::OnStart callback.
|
208 |
+
Start@2();
|
209 |
+
|
210 |
+
// Instruct SODA to stop processing after all queued audio is
|
211 |
+
// processed. Will eventually result in a SodaClient::OnStop, but only
|
212 |
+
// after all audio currently in queue is decoded.
|
213 |
+
MarkDone@3();
|
214 |
+
};
|
19/public/mojom/tensor.mojom
ADDED
@@ -0,0 +1,64 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
// Copyright 2018 The Chromium Authors. All rights reserved.
|
2 |
+
// Use of this source code is governed by a BSD-style license that can be
|
3 |
+
// found in the LICENSE file.
|
4 |
+
|
5 |
+
// Datatypes used in the Machine Learning API.
|
6 |
+
// This module is derived from the Feature proto definition of TensorFlow.
|
7 |
+
// See /tensorflow/core/example/feature.proto in the TensorFlow code.
|
8 |
+
|
9 |
+
// NOTE: This mojom exists in two places and must be kept in sync:
|
10 |
+
// Chromium: //chromeos/services/machine_learning/public/mojom/
|
11 |
+
// Chrome OS: src/platform2/ml/mojom/
|
12 |
+
// Note: Other repos downstream of Chromium might also use this mojom.
|
13 |
+
// Example: A backwards-compatible mojom change (and corresponding
|
14 |
+
// implementation change) can be made in Chrome OS first, then replicated to the
|
15 |
+
// clients (Chromium, other downstream repos) later.
|
16 |
+
// Use //chromeos/services/machine_learning/public/mojom/roll_mojoms.sh to help
|
17 |
+
// replicate Chrome OS-side changes over to Chromium.
|
18 |
+
|
19 |
+
module chromeos.machine_learning.mojom;
|
20 |
+
|
21 |
+
[Stable]
|
22 |
+
struct StringList {
|
23 |
+
array<string> value;
|
24 |
+
};
|
25 |
+
|
26 |
+
[Stable]
|
27 |
+
struct FloatList {
|
28 |
+
array<double> value;
|
29 |
+
};
|
30 |
+
|
31 |
+
[Stable]
|
32 |
+
struct Int64List {
|
33 |
+
array<int64> value;
|
34 |
+
};
|
35 |
+
|
36 |
+
// The union of all supported tensor types. Supporting a new type comprises the
|
37 |
+
// following:
|
38 |
+
// - Adding a new struct above (e.g. BoolList),
|
39 |
+
// - Adding this new struct to the union below,
|
40 |
+
// - Adding template specializations for the new type to
|
41 |
+
// platform2/ml/tensor_view.{h,cc}.
|
42 |
+
// - Updating platform2/ml/graph_executor_impl.cc to use a TensorView of the
|
43 |
+
// new type.
|
44 |
+
//
|
45 |
+
// TODO(chromium:836098): add new types (e.g. uint8, bool) as they become
|
46 |
+
// useful.
|
47 |
+
[Stable]
|
48 |
+
union ValueList {
|
49 |
+
StringList string_list;
|
50 |
+
FloatList float_list;
|
51 |
+
Int64List int64_list;
|
52 |
+
};
|
53 |
+
|
54 |
+
// A Tensor is a multi-dimensional array with dimensions `shape`, flattened into
|
55 |
+
// the one-dimensional array `data`.
|
56 |
+
// It is used for both the inputs (in the form of a map<string, Tensor>) and
|
57 |
+
// outputs (in the form of an array<Tensor>) of ML inference.
|
58 |
+
[Stable]
|
59 |
+
struct Tensor {
|
60 |
+
ValueList data;
|
61 |
+
|
62 |
+
// Each integer is the size of that dimension.
|
63 |
+
Int64List shape;
|
64 |
+
};
|
19/public/mojom/text_classifier.mojom
ADDED
@@ -0,0 +1,160 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
// Copyright 2020 The Chromium Authors. All rights reserved.
|
2 |
+
// Use of this source code is governed by a BSD-style license that can be
|
3 |
+
// found in the LICENSE file.
|
4 |
+
|
5 |
+
// API of the text classifier (libtextclassifier).
|
6 |
+
|
7 |
+
// NOTE: This mojom exists in two places and must be kept in sync:
|
8 |
+
// Chromium: //chromeos/services/machine_learning/public/mojom/
|
9 |
+
// Chrome OS: src/platform2/ml/mojom/
|
10 |
+
// Note: Other repos downstream of Chromium might also use this mojom.
|
11 |
+
// Example: A backwards-compatible mojom change (and corresponding
|
12 |
+
// implementation change) can be made in Chrome OS first, then replicated to the
|
13 |
+
// clients (Chromium, other downstream repos) later.
|
14 |
+
// Use //chromeos/services/machine_learning/public/mojom/roll_mojoms.sh to help
|
15 |
+
// replicate Chrome OS-side changes over to Chromium.
|
16 |
+
|
17 |
+
module chromeos.machine_learning.mojom;
|
18 |
+
|
19 |
+
// NOTE: The base directory for 'import' statements is expected to differ
|
20 |
+
// between Chromium and Chrome OS versions of this file.
|
21 |
+
// And for "time.mojom", on the chromium side, we have to use the version
|
22 |
+
// under mojo folder, that is, "mojo/public/mojom/base/time.mojom".
|
23 |
+
import "mojo/public/mojom/base/time.mojom";
|
24 |
+
|
25 |
+
// Enum for specifying the annotation usecase.
|
26 |
+
// Must be consistent with `AnnotationUsecase` in model.fb in libtextclassifier.
|
27 |
+
[Stable, Extensible]
|
28 |
+
enum AnnotationUsecase {
|
29 |
+
// Results are optimized for Smart{Select,Share,Linkify}
|
30 |
+
ANNOTATION_USECASE_SMART = 0,
|
31 |
+
// Results are optimized for using TextClassifier as an infrastructure that
|
32 |
+
// annotates as much as possible.
|
33 |
+
ANNOTATION_USECASE_RAW = 1,
|
34 |
+
};
|
35 |
+
|
36 |
+
// Stores data extracted from each text entity.
|
37 |
+
// Currently, only for "number" type, the real number value is stored in
|
38 |
+
// `numeric_value`. For the other types, the substring annotated is stored
|
39 |
+
// in `string_value`.
|
40 |
+
// The values come from the class `ClassificationResult` of tclib. (See
|
41 |
+
// "tclib/annotator/types.h").
|
42 |
+
// TODO(honglinyu): add data extraction for more types when needed and
|
43 |
+
// available. For example, when "date" data is needed, probably we should add
|
44 |
+
// a new struct "Date" and add a new member "Data date_value" to the following
|
45 |
+
// union.
|
46 |
+
[Stable]
|
47 |
+
union TextEntityData {
|
48 |
+
// A numeric value.
|
49 |
+
// - For "number", it is the value.
|
50 |
+
// e.g. it is "34.3" for input string "34.3".
|
51 |
+
double numeric_value@0;
|
52 |
+
// Could be "url", "address" etc.
|
53 |
+
string string_value@1;
|
54 |
+
};
|
55 |
+
|
56 |
+
// Types of text (can be phone numbers, addresses, emails and urls etc.).
|
57 |
+
// This struct is a distillation of the `ClassificationResult` of tclib. (See
|
58 |
+
// "tclib/annotator/types.h").
|
59 |
+
[Stable]
|
60 |
+
struct TextEntity {
|
61 |
+
// The name of the type (e.g. "phone", "address", "email" and "url" etc.).
|
62 |
+
string name@0;
|
63 |
+
// The confidence score of the entity annotation, and the range is 0-1.
|
64 |
+
float confidence_score@1;
|
65 |
+
// Additional data extracted from the text.
|
66 |
+
TextEntityData data@2;
|
67 |
+
};
|
68 |
+
|
69 |
+
// A substring of the annotated text and possible associated entities.
|
70 |
+
// This struct is a simplification of the `AnnotatedSpan` class of tclib. (See
|
71 |
+
// "tclib/annotator/types.h").
|
72 |
+
[Stable]
|
73 |
+
struct TextAnnotation {
|
74 |
+
// The offset of the first character of the annotation.
|
75 |
+
uint32 start_offset@0;
|
76 |
+
// The offset of the last character of the annotation.
|
77 |
+
uint32 end_offset@1;
|
78 |
+
// The set of entity types associated with the substring.
|
79 |
+
array<TextEntity> entities@2;
|
80 |
+
};
|
81 |
+
|
82 |
+
// Contains the input and parameters used to annotate the text.
|
83 |
+
// This is a combination of string and `AnnotationOptions` in tclib (see
|
84 |
+
// "tclib/annotator/types.h").
|
85 |
+
[Stable]
|
86 |
+
struct TextAnnotationRequest {
|
87 |
+
// The text to be annotated.
|
88 |
+
string text@0;
|
89 |
+
// Comma-delimited locales (e.g., "en", "en,es").
|
90 |
+
string? default_locales@1;
|
91 |
+
// Comma-separated list of language tags.
|
92 |
+
string? detected_text_language_tags@2;
|
93 |
+
// Tailors the output annotations according to the specified use-case.
|
94 |
+
AnnotationUsecase annotation_usecase@3 = ANNOTATION_USECASE_SMART;
|
95 |
+
// For parsing relative datetimes, the reference now time against which the
|
96 |
+
// relative datetimes get resolved.
|
97 |
+
mojo_base.mojom.Time? reference_time@4;
|
98 |
+
// Timezone in which the input text was written (format as accepted by ICU).
|
99 |
+
// If empty (default), will use the system's timezone.
|
100 |
+
string? reference_timezone@5;
|
101 |
+
// Enabled entities. If empty (default), all types of entities will be
|
102 |
+
// enabled.
|
103 |
+
array<string>? enabled_entities@6;
|
104 |
+
};
|
105 |
+
|
106 |
+
// Marks a span in a sequence of codepoints.
|
107 |
+
// This struct is consistent with the type `CodepointSpan` of tclib. (See
|
108 |
+
// "tclib/annotator/types.h").
|
109 |
+
[Stable]
|
110 |
+
struct CodepointSpan {
|
111 |
+
// The offset of the first character of the span.
|
112 |
+
uint32 start_offset@0;
|
113 |
+
// The offset of the last character of the span.
|
114 |
+
uint32 end_offset@1;
|
115 |
+
};
|
116 |
+
|
117 |
+
// Represent a language detection result.
|
118 |
+
[Stable]
|
119 |
+
struct TextLanguage {
|
120 |
+
// The BCP-47 language code like "en", "fr", "zh" etc.
|
121 |
+
string locale;
|
122 |
+
// The confidence score of the language detected (range: 0~1).
|
123 |
+
float confidence;
|
124 |
+
};
|
125 |
+
|
126 |
+
// Contains the input and parameters used to suggest selection.
|
127 |
+
// This is a combination of the inputs of the `SuggestSelection` function
|
128 |
+
// of tclib. (See "tclib/annotator/annotate.h").
|
129 |
+
[Stable, RenamedFrom="chromeos.machine_learning.mojom.TextSuggestSelectionRequest"]
|
130 |
+
struct REMOVED_TextSuggestSelectionRequest {
|
131 |
+
// The candidate text.
|
132 |
+
string text@0;
|
133 |
+
// Where the user selects.
|
134 |
+
CodepointSpan user_selection@1;
|
135 |
+
// Comma-delimited locales (e.g., "en", "en,es").
|
136 |
+
string? default_locales@2;
|
137 |
+
// Comma-separated list of BCP 47 language tags.
|
138 |
+
string? detected_text_language_tags@3;
|
139 |
+
// Tailors the output annotations according to the specified use-case.
|
140 |
+
AnnotationUsecase annotation_usecase@4 = ANNOTATION_USECASE_SMART;
|
141 |
+
};
|
142 |
+
|
143 |
+
// Used to annotate entities within text strings.
|
144 |
+
// Next ordinal: 3
|
145 |
+
[Stable]
|
146 |
+
interface TextClassifier {
|
147 |
+
// Annotate a text string and returns the detected substrings and possible
|
148 |
+
// entities.
|
149 |
+
Annotate@0(TextAnnotationRequest request) =>
|
150 |
+
(array<TextAnnotation> outputs);
|
151 |
+
// Identify the languages the text is possibly written in.
|
152 |
+
// The returned results are sorted according to the confidence score, from the
|
153 |
+
// highest to the lowest.
|
154 |
+
// The maximum number of results returned is determined internally.
|
155 |
+
// Will return an empty array if the language can not be determined.
|
156 |
+
FindLanguages@2(string text) => (array<TextLanguage> outputs);
|
157 |
+
// Deprecated `SuggestSelection`
|
158 |
+
REMOVED_1@1(REMOVED_TextSuggestSelectionRequest request) =>
|
159 |
+
(CodepointSpan outputs);
|
160 |
+
};
|
19/public/mojom/text_suggester.mojom
ADDED
@@ -0,0 +1,131 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
// Copyright 2021 The Chromium Authors. All rights reserved.
|
2 |
+
// Use of this source code is governed by a BSD-style license that can be
|
3 |
+
// found in the LICENSE file.
|
4 |
+
|
5 |
+
// Next MinVersion: 3
|
6 |
+
|
7 |
+
// Datatypes and interfaces of text suggester API.
|
8 |
+
|
9 |
+
// NOTE: This mojom exists in two places and must be kept in sync:
|
10 |
+
// Chromium: //chromeos/services/machine_learning/public/mojom/
|
11 |
+
// Chrome OS: src/platform2/ml/mojom/
|
12 |
+
// Note: Other repos downstream of Chromium might also use this mojom.
|
13 |
+
|
14 |
+
// Example: A backwards-compatible mojom change (and corresponding
|
15 |
+
// implementation change) can be made in Chrome OS first, then replicated to the
|
16 |
+
// clients (Chromium, other downstream repos) later.
|
17 |
+
// Use //chromeos/services/machine_learning/public/mojom/roll_mojoms.sh to help
|
18 |
+
// replicate Chrome OS-side changes over to Chromium.
|
19 |
+
|
20 |
+
module chromeos.machine_learning.mojom;
|
21 |
+
|
22 |
+
// Represents a single completion candidate
|
23 |
+
// Next ordinal: 2
|
24 |
+
[Stable]
|
25 |
+
struct NextWordCompletionCandidate {
|
26 |
+
// The completing text suggested
|
27 |
+
string text@0;
|
28 |
+
|
29 |
+
// The normalized confidence score for the generated candidate
|
30 |
+
float normalized_score@1;
|
31 |
+
};
|
32 |
+
|
33 |
+
// The mode with which a suggestion should be used by a consumer
|
34 |
+
[Stable, Extensible]
|
35 |
+
enum TextSuggestionMode {
|
36 |
+
// A prediction suggestion is the text predicted after a word. For example
|
37 |
+
// the preceding text could be "how are", and the suggested text would be
|
38 |
+
// "you".
|
39 |
+
[Default] kPrediction = 1,
|
40 |
+
|
41 |
+
// A completion suggestion is similar to a prediction, however the suggestion
|
42 |
+
// also completes any unfinished words in the preceding text. For example,
|
43 |
+
// the preceding text could be "how ar", and the suggested text would be
|
44 |
+
// "e you".
|
45 |
+
kCompletion = 2,
|
46 |
+
};
|
47 |
+
|
48 |
+
// Defines a query for text suggestions
|
49 |
+
// Next ordinal: 3
|
50 |
+
[Stable]
|
51 |
+
struct TextSuggesterQuery {
|
52 |
+
// The text used to generate suggestions
|
53 |
+
string text@0;
|
54 |
+
|
55 |
+
// Optional: completion candidates for the final word in the text
|
56 |
+
array<NextWordCompletionCandidate> next_word_candidates@1;
|
57 |
+
|
58 |
+
// The types of suggestions requested
|
59 |
+
[MinVersion=1] TextSuggestionMode suggestion_mode@2;
|
60 |
+
};
|
61 |
+
|
62 |
+
// Represents a single generated multi word suggestion candidate.
|
63 |
+
// Next ordinal: 2
|
64 |
+
[Stable]
|
65 |
+
struct MultiWordSuggestionCandidate {
|
66 |
+
// The text suggested
|
67 |
+
string text@0;
|
68 |
+
|
69 |
+
// The normalized confidence score for this candidate
|
70 |
+
float normalized_score@1;
|
71 |
+
};
|
72 |
+
|
73 |
+
// Represents all types of suggestion candidates generated by the service.
|
74 |
+
//
|
75 |
+
// TODO(crbug/1201949): Note that the Extensible keyword is not supported for
|
76 |
+
// union types. We may need to revisit this type in the future.
|
77 |
+
//
|
78 |
+
// Next ordinal: 1
|
79 |
+
[Stable, Extensible]
|
80 |
+
union TextSuggestionCandidate {
|
81 |
+
MultiWordSuggestionCandidate multi_word@0;
|
82 |
+
};
|
83 |
+
|
84 |
+
// The result to text suggestion queries, contains any candidates generated.
|
85 |
+
// Next ordinal: 2
|
86 |
+
[Stable]
|
87 |
+
struct TextSuggesterResult {
|
88 |
+
// Status of the response
|
89 |
+
[Stable, Extensible, Default=ERROR]
|
90 |
+
enum Status {
|
91 |
+
// Text suggestions generated successfully
|
92 |
+
OK = 0,
|
93 |
+
// There was an error while generating candidates, no candidates will be
|
94 |
+
// returned with this result.
|
95 |
+
ERROR = 1,
|
96 |
+
};
|
97 |
+
|
98 |
+
Status status@0;
|
99 |
+
|
100 |
+
// The list of candidates generated by the text suggester service
|
101 |
+
array<TextSuggestionCandidate> candidates@1;
|
102 |
+
};
|
103 |
+
|
104 |
+
// Experiment groups for multi word suggestions
|
105 |
+
// Next value: 5
|
106 |
+
[Stable, Extensible]
|
107 |
+
enum MultiWordExperimentGroup {
|
108 |
+
[Default] kDefault = 0,
|
109 |
+
kGboard = 1,
|
110 |
+
// Experiment groups used for the relaxed gboard settings finch experiment
|
111 |
+
[MinVersion=2] kGboardRelaxedA = 2,
|
112 |
+
[MinVersion=2] kGboardRelaxedB = 3,
|
113 |
+
[MinVersion=2] kGboardRelaxedC = 4
|
114 |
+
};
|
115 |
+
|
116 |
+
// Encapsulates any settings details for a TextSuggester
|
117 |
+
// Next ordinal: 1
|
118 |
+
[Stable]
|
119 |
+
struct TextSuggesterSpec {
|
120 |
+
// The experimental group for multi word suggestions
|
121 |
+
MultiWordExperimentGroup multi_word_experiment@0;
|
122 |
+
};
|
123 |
+
|
124 |
+
// The top level interface for requesting text based suggestions in the Chromium
|
125 |
+
// browser process from the sandboxed ML service process.
|
126 |
+
// Next ordinal: 1
|
127 |
+
[Stable]
|
128 |
+
interface TextSuggester {
|
129 |
+
// Generates text suggestions from the given context
|
130 |
+
Suggest@0(TextSuggesterQuery query) => (TextSuggesterResult result);
|
131 |
+
};
|
19/public/mojom/web_platform_handwriting.mojom
ADDED
@@ -0,0 +1,134 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
// Copyright 2021 The Chromium Authors. All rights reserved.
|
2 |
+
// Use of this source code is governed by a BSD-style license that can be
|
3 |
+
// found in the LICENSE file.
|
4 |
+
|
5 |
+
// Next MinVersion: 2
|
6 |
+
|
7 |
+
module chromeos.machine_learning.web_platform.mojom;
|
8 |
+
|
9 |
+
// https://github.com/WICG/handwriting-recognition/blob/main/explainer.md
|
10 |
+
|
11 |
+
// This mojom file is copied from the file below in chromium repo,
|
12 |
+
// "//third_party/blink/public/mojom/handwriting/handwriting.mojom"
|
13 |
+
// Notice that some modifications are made,
|
14 |
+
// 1. The module is changed to `chromeos.machine_learning.web_platform.mojom`.
|
15 |
+
// 2. `[Stable]` tags are added.
|
16 |
+
// 3. Interface `HandwritingRecognitionService`
|
17 |
+
// and `CreateHandwritingRecognizerResult` are removed because they not
|
18 |
+
// used here.
|
19 |
+
// 4. The paths of imported mojoms are changed.
|
20 |
+
// 5. Feature query related structs are removed because they are not being
|
21 |
+
// used for now.
|
22 |
+
// For the overlapping definitions, the two files should be kept consistent.
|
23 |
+
|
24 |
+
import "mojo/public/mojom/base/time.mojom";
|
25 |
+
import "ui/gfx/geometry/mojom/geometry.mojom";
|
26 |
+
|
27 |
+
// Represents a single point in a handwriting stroke.
|
28 |
+
// Corresponds to handwriting_point.idl.
|
29 |
+
[Stable]
|
30 |
+
struct HandwritingPoint {
|
31 |
+
// Represent the horizontal (location.x) and vertical (location.y) location
|
32 |
+
// of the point.
|
33 |
+
// The top-left corner coordinate is (location.x=0, location.y=0).
|
34 |
+
gfx.mojom.PointF location;
|
35 |
+
// The time elapsed since the starting time (e.g. when the first ink point
|
36 |
+
// of the drawing is captured).
|
37 |
+
mojo_base.mojom.TimeDelta? t;
|
38 |
+
};
|
39 |
+
|
40 |
+
// Represents a stroke which is just a series of points.
|
41 |
+
// Corresponds to handwriting_stroke.idl.
|
42 |
+
[Stable]
|
43 |
+
struct HandwritingStroke {
|
44 |
+
array<HandwritingPoint> points;
|
45 |
+
};
|
46 |
+
|
47 |
+
// Represents a segment of a handwriting stroke in the grapheme detected.
|
48 |
+
// One `HandwritingDrawingSegment` can only refer one stroke, denoted by
|
49 |
+
// `stroke_index` which is the index of the stroke in the input stroke arrays
|
50 |
+
// (i.e., the first parameter of the `HandwritingRecognizer::GetPrediction`
|
51 |
+
// function).
|
52 |
+
// The reason we need this struct is that different parts of one single stroke
|
53 |
+
// can belong to different grapheme detected.
|
54 |
+
// Corresponds to handwriting_drawing_segment.idl.
|
55 |
+
[Stable]
|
56 |
+
struct HandwritingDrawingSegment {
|
57 |
+
// The index of the corresponding stroke in the input stroke array.
|
58 |
+
uint32 stroke_index;
|
59 |
+
// The index of the first point in the stroke that belongs to this drawing
|
60 |
+
// segment.
|
61 |
+
uint32 begin_point_index;
|
62 |
+
// The index of the last point in the stroke that belongs to this drawing
|
63 |
+
// segment.
|
64 |
+
uint32 end_point_index;
|
65 |
+
};
|
66 |
+
|
67 |
+
// Represents a segment detected.
|
68 |
+
// Corresponds to handwriting_segment.idl.
|
69 |
+
[Stable]
|
70 |
+
struct HandwritingSegment {
|
71 |
+
// The string representation of this grapheme.
|
72 |
+
string grapheme;
|
73 |
+
// HandwritingPrediction.text.slice(begin_index, end_index) === grapheme
|
74 |
+
// If the grapheme spans multiple Unicode code points,
|
75 |
+
// `end_index - begin_index` is greater than 1.
|
76 |
+
uint32 begin_index;
|
77 |
+
uint32 end_index;
|
78 |
+
array<HandwritingDrawingSegment> drawing_segments;
|
79 |
+
};
|
80 |
+
|
81 |
+
// Represents one single prediction result.
|
82 |
+
// The final prediction output is an array of it.
|
83 |
+
// Corresponds to handwriting_prediction.idl.
|
84 |
+
[Stable]
|
85 |
+
struct HandwritingPrediction {
|
86 |
+
string text;
|
87 |
+
array<HandwritingSegment> segmentation_result;
|
88 |
+
};
|
89 |
+
|
90 |
+
// Represents the hints provided to the recognizer for better performance.
|
91 |
+
// Corresponds to handwriting_hints.idl.
|
92 |
+
[Stable]
|
93 |
+
struct HandwritingHints {
|
94 |
+
// The type of content to be recognized. The recognizer may use these to
|
95 |
+
// better rank the recognition results. (e.g. "text", "email", "number",
|
96 |
+
// "per-character").
|
97 |
+
string recognition_type@0;
|
98 |
+
// Identifies how the strokes are captured. (e.g. "touch", "mouse", "pen")
|
99 |
+
string input_type@1;
|
100 |
+
// Deprecated because we want to change `text_context` to be optional, see
|
101 |
+
// the comment of `text_context` below.
|
102 |
+
string deprecated_text_context@2;
|
103 |
+
// The maximum number of alternative predictions to generate.
|
104 |
+
uint32 alternatives@3;
|
105 |
+
// The text that comes before the handwriting. This can be texts that were
|
106 |
+
// previously recognized, or were given as the writing context (e.g.
|
107 |
+
// "Write your name here:"). This is the linguistic context to help
|
108 |
+
// disambiguate the handwriting (e.g. “Hello world” vs. “Hello word”).
|
109 |
+
[MinVersion=1] string? text_context@4;
|
110 |
+
};
|
111 |
+
|
112 |
+
// Used in creating recognizer.
|
113 |
+
// Corresponds to handwriting_model_constraint.idl.
|
114 |
+
[Stable]
|
115 |
+
struct HandwritingModelConstraint {
|
116 |
+
// Languages are IETF BCP 47 language tags, e.g., "en", "zh-CN", "zh-Hans".
|
117 |
+
array<string> languages;
|
118 |
+
};
|
119 |
+
|
120 |
+
// Interface for a renderer to use a specific handwriting recognition backend.
|
121 |
+
// The browser handles the requests and forwards them to the appropriate
|
122 |
+
// backend.
|
123 |
+
[Stable]
|
124 |
+
interface HandwritingRecognizer {
|
125 |
+
// Does the recognition and outputs the prediction result.
|
126 |
+
// This is used by IDL API `blink::HandwritingDrawing::getPrediction`.
|
127 |
+
// The input `strokes` and `hints` should both come from
|
128 |
+
// `blink::HandwritingDrawing`.
|
129 |
+
// If the returned `Optional` has no value, it means there is some error in
|
130 |
+
// recognition. If the returned `Optional` has value but the array is empty,
|
131 |
+
// it means the recognizer can not recognize anything from the input.
|
132 |
+
GetPrediction@0(array<HandwritingStroke> strokes, HandwritingHints hints)
|
133 |
+
=> (array<HandwritingPrediction>? prediction);
|
134 |
+
};
|