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 |
+
alanlxl@chromium.org
|
| 2 |
+
amoylan@chromium.org
|
| 3 |
+
honglinyu@chromium.org
|
| 4 |
+
martis@chromium.org
|
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 |
+
};
|