Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
qohosbluetoothlocaldevice.cpp
Go to the documentation of this file.
1// Copyright (C) 2026 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
5
6#include <QtBluetooth/private/qohosbluetoothcommon_p.h>
7
8#include <QtCore/private/qcore_ohos_p.h>
9#include <QtCore/private/qnapi_p.h>
10#include <QtCore/private/qohosjstools_p.h>
11#include <QtCore/private/qohoslogger_p.h>
12
13#include <memory>
14
16
17namespace QtOhosBluetooth {
18
19namespace {
20
21constexpr int permanentlyDiscoverableDuration = 0;
22
23template<typename T>
24QOhosSupplier<T> makeQOhosLazySupplier(
25 T fallbackValue, QOhosSupplier<std::optional<QOhosSupplier<T>>> supplierFactory)
26{
27 struct Context
28 {
29 QOhosSupplier<T> supplier;
30 QOhosSupplier<std::optional<QOhosSupplier<T>>> optSupplierFactory;
31 };
32
33 auto context = std::make_shared<Context>();
34 if (auto optSupplier = supplierFactory()) {
35 context->supplier = std::move(*optSupplier);
36 } else {
37 context->supplier = [fallbackValue = std::move(fallbackValue)]() { return fallbackValue; };
38 context->optSupplierFactory = std::move(supplierFactory);
39 }
40
41 return [context]() {
42 if (context->optSupplierFactory) {
43 if (auto optSupplier = context->optSupplierFactory()) {
44 context->supplier = std::move(*optSupplier);
45 context->optSupplierFactory = nullptr;
46 }
47 }
48
49 return context->supplier();
50 };
51}
52
53std::optional<QOhosBluetoothLocalDeviceProxy::ScanMode> readScanMode(QOhosJsState &jsState)
54{
55 if (!isBluetoothEnabled(jsState))
56 return std::nullopt;
57
58 try {
59 return jsState.tryMapOhosEnumFromJs<QOhosBluetoothLocalDeviceProxy::ScanMode>(
60 jsState.eval<QNapi::Number>("@ohos.bluetooth.connection.getBluetoothScanMode()"));
61 } catch (const Napi::Error &error) {
62 if (const auto optErrorCode = tryGetKnownErrorCode(error.Value(), Q_FUNC_INFO)) {
63 qOhosPrintfWarning(
64 "%s: cannot read the bluetooth scan mode, error code: %u", Q_FUNC_INFO, qToUnderlying(*optErrorCode));
65 }
66 return std::nullopt;
67 }
68}
69
70std::shared_ptr<void> registerScanModeChangeConsumer(
71 QOhosJsState &jsState,
72 QOhosConsumer<std::optional<QOhosBluetoothLocalDeviceProxy::ScanMode>> scanModeChangeConsumer)
73{
74 auto sharedScanModeChangeConsumer = QtOhos::moveToSharedPtr(std::move(scanModeChangeConsumer));
75
76 auto connectionModule = jsState.eval<QNapi::Object>("@ohos.bluetooth.connection");
77
78 auto scanModeChangeHandlerRef = QtOhos::moveToSharedPtr(
79 QNapi::Reference<>::makePersistentFrom(
80 QNapi::Function::New(
81 jsState.env(),
82 [weakScanModeChangeConsumer = QtOhos::makeWeakPtr(sharedScanModeChangeConsumer)](const QOhosCallbackInfo &cbInfo) {
83 auto scanModeChangeConsumer = weakScanModeChangeConsumer.lock();
84 if (!scanModeChangeConsumer) {
85 qOhosPrintfWarning(
86 "%s: got unexpected scan mode change callback call for detached handler",
87 Q_FUNC_INFO);
88 return cbInfo.Env().Undefined();
89 }
90
91 auto ohosScanMode = cbInfo.getFirstArg<QNapi::Number>(Q_FUNC_INFO);
92 (*scanModeChangeConsumer)(
93 cbInfo.jsState().tryMapOhosEnumFromJs<QOhosBluetoothLocalDeviceProxy::ScanMode>(ohosScanMode));
94
95 return cbInfo.Env().Undefined();
96 })));
97
98 try {
99 connectionModule.eval("onScanModeChange(*)", {scanModeChangeHandlerRef->Value()});
100 } catch (const Napi::Error &error) {
101 if (const auto optErrorCode = tryGetKnownErrorCode(error.Value(), Q_FUNC_INFO)) {
102 qOhosPrintfWarning(
103 "%s: cannot register the scan mode change consumer, error code: %u", Q_FUNC_INFO,
104 qToUnderlying(*optErrorCode));
105 }
106 return {};
107 }
108
109 return QtOhos::makeDestroyNotifier(
110 [sharedScanModeChangeConsumer, scanModeChangeHandlerRef,
111 connectionModuleWeakRef = QtOhos::moveToSharedPtr(Napi::Weak(connectionModule))]() {
112 auto connectionModuleValue = connectionModuleWeakRef->Value();
113 if (!connectionModuleValue.IsObject()) {
114 qOhosPrintfDebug(
115 "%s: not unregistering the scan mode change consumer, the module is not alive anymore",
116 Q_FUNC_INFO);
117 return;
118 }
119
120 try {
121 QNapi::checkedCast<QNapi::Object>(connectionModuleValue).eval(
122 "offScanModeChange(*)", {scanModeChangeHandlerRef->Value()});
123 } catch (const Napi::Error &error) {
124 if (const auto optErrorCode = tryGetKnownErrorCode(error.Value(), Q_FUNC_INFO)) {
125 qOhosPrintfWarning(
126 "%s: cannot unregister the scan mode change consumer, error code: %u",
127 Q_FUNC_INFO, qToUnderlying(*optErrorCode));
128 }
129 }
130 });
131}
132
133QOhosSupplier<std::optional<QOhosBluetoothLocalDeviceProxy::ScanMode>> makeScanModeSupplier(
134 QOhosConsumer<std::optional<QOhosBluetoothLocalDeviceProxy::ScanMode>> optScanModeChangeConsumer)
135{
136 bool scanModeChangeEventRegistered = false;
137
138 auto cachedScanModeSupplier =
139 makeQOhosDataSource<std::optional<QOhosBluetoothLocalDeviceProxy::ScanMode>>(
140 readScanMode,
141 [&](QOhosJsState &jsState,
142 QOhosConsumer<std::optional<QOhosBluetoothLocalDeviceProxy::ScanMode>> scanModeChangeConsumer) {
143 auto scanModeChangeConsumerHandle =
144 registerScanModeChangeConsumer(jsState, std::move(scanModeChangeConsumer));
145 scanModeChangeEventRegistered = scanModeChangeConsumerHandle != nullptr;
146
147 return scanModeChangeConsumerHandle;
148 },
149 std::move(optScanModeChangeConsumer),
150 QtOhos::invokeInQtThread,
151 Q_FUNC_INFO);
152
153 return [scanModeChangeEventRegistered, cachedScanModeSupplier = std::move(cachedScanModeSupplier)]()
154 -> std::optional<QOhosBluetoothLocalDeviceProxy::ScanMode> {
155 if (scanModeChangeEventRegistered) {
156 if (const auto optCachedScanMode = cachedScanModeSupplier())
157 return optCachedScanMode;
158 }
159
160 return QOhosJsThreadGateway::eval(readScanMode, Q_FUNC_INFO);
161 };
162}
163
164}
165
182
184{
185 static auto instance = std::shared_ptr<QOhosBluetoothLocalDeviceProxy>(new QOhosBluetoothLocalDeviceProxy());
186 return instance;
187}
188
190{
191 if (!checkAccessBluetoothPermissionGranted(Q_FUNC_INFO))
192 return std::nullopt;
193
194 return QOhosJsThreadGateway::eval(
195 [](QOhosJsState &jsState) -> std::optional<QString> {
196 if (!isBluetoothEnabled(jsState))
197 return std::nullopt;
198
199 try {
200 return QString::fromStdString(
201 jsState.eval<QNapi::String>("@ohos.bluetooth.connection.getLocalName()").Utf8Value());
202 } catch (const Napi::Error &error) {
203 if (const auto optErrorCode = tryGetKnownErrorCode(error.Value(), Q_FUNC_INFO)) {
204 qOhosPrintfWarning(
205 "%s: cannot read the local device name, error code: %u", Q_FUNC_INFO,
206 qToUnderlying(*optErrorCode));
207 }
208 return std::nullopt;
209 }
210 });
211}
212
217
219 QOhosBluetoothLocalDeviceProxy::ScanMode scanMode)
220{
221 if (!checkAccessBluetoothPermissionGranted(Q_FUNC_INFO)) {
222 Q_EMIT missingPermission();
223 return QOhosBluetoothErrorCode::PermissionDenied;
224 }
225
226 const auto optErrorCode = QOhosJsThreadGateway::eval(
227 [&](QOhosJsState &jsState) -> std::optional<QOhosBluetoothErrorCode> {
228 if (!isBluetoothEnabled(jsState))
229 return QOhosBluetoothErrorCode::BluetoothDisabled;
230
231 try {
232 jsState.eval(
233 "@ohos.bluetooth.connection.setBluetoothScanMode(*)",
234 {
235 jsState.mapOhosEnumToJs(scanMode),
236 permanentlyDiscoverableDuration,
237 });
238 return std::nullopt;
239 } catch (const Napi::Error &error) {
240 return tryGetKnownErrorCode(error.Value(), Q_FUNC_INFO);
241 }
242 });
243
244 if (optErrorCode == QOhosBluetoothErrorCode::PermissionDenied) {
245 Q_EMIT missingPermission();
246 }
247
248 return optErrorCode;
249}
250
251}
252
253QT_END_NAMESPACE
254
255#include "moc_qohosbluetoothlocaldevice_p.cpp"
std::optional< QOhosBluetoothErrorCode > trySetBluetoothScanMode(ScanMode scanMode)
static std::shared_ptr< QOhosBluetoothLocalDeviceProxy > instance()
Combined button and popup list for selecting options.