Revision control

Copy as Markdown

// Copyright (C) 2026 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qohosbluetoothaccess_p.h"
#include <QtBluetooth/private/qohosbluetoothcommon_p.h>
#include <QtCore/qloggingcategory.h>
#include <QtCore/private/qnapi_p.h>
#include <QtCore/private/qohoscommon_p.h>
#include <QtCore/private/qohosjstools_p.h>
#include <QtCore/private/qohoslogger_p.h>
#include <memory>
#include <optional>
QT_BEGIN_NAMESPACE
Q_DECLARE_LOGGING_CATEGORY(QT_BT_OHOS)
namespace QtOhosBluetooth {
namespace {
using BluetoothState = QOhosBluetoothAccessProxy::BluetoothState;
std::shared_ptr<void> registerBluetoothStateChangeConsumer(
QOhosJsState &jsState, QOhosConsumer<std::optional<BluetoothState>> stateChangeConsumer)
{
return registerQOhosOnOffMethodsBasedEventHandler(
jsState.eval<QNapi::Object>("@ohos.bluetooth.access"), "stateChange",
[stateChangeConsumer = std::move(stateChangeConsumer)](const QOhosCallbackInfo &cbInfo) {
auto ohosBluetoothState = cbInfo.getFirstArg<QNapi::Number>(Q_FUNC_INFO);
stateChangeConsumer(
cbInfo.jsState().tryMapOhosEnumFromJs<BluetoothState>(ohosBluetoothState));
},
{
.optOnCallExceptionHandler = [](const Napi::Error &error) {
if (const auto optErrorCode = tryGetKnownErrorCode(error.Value(), Q_FUNC_INFO)) {
qOhosPrintfWarning(
"%s: cannot register the bluetooth state change consumer, error code: %u",
Q_FUNC_INFO, qToUnderlying(*optErrorCode));
}
},
});
}
QOhosSupplier<std::optional<BluetoothState>> makeBluetoothStateSupplier(
QOhosConsumer<std::optional<BluetoothState>> bluetoothStateChangeConsumer)
{
bool stateChangeEventRegistered = false;
auto cachedBluetoothStateSupplier = makeQOhosDataSource<std::optional<BluetoothState>>(
readBluetoothState,
[&](QOhosJsState &jsState, QOhosConsumer<std::optional<BluetoothState>> stateChangeConsumer) {
auto stateChangeConsumerHandle =
registerBluetoothStateChangeConsumer(jsState, std::move(stateChangeConsumer));
stateChangeEventRegistered = stateChangeConsumerHandle != nullptr;
return stateChangeConsumerHandle;
},
std::move(bluetoothStateChangeConsumer),
QtOhos::invokeInQtThread,
Q_FUNC_INFO);
return [stateChangeEventRegistered,
cachedBluetoothStateSupplier = std::move(cachedBluetoothStateSupplier)]() {
return stateChangeEventRegistered
? cachedBluetoothStateSupplier()
: QOhosJsThreadGateway::eval(readBluetoothState, Q_FUNC_INFO);
};
}
}
QOhosBluetoothAccessProxy::QOhosBluetoothAccessProxy()
{
m_ohosBluetoothStateSupplier = makeBluetoothStateSupplier(
[this](std::optional<BluetoothState> optBluetoothState) {
if (optBluetoothState)
Q_EMIT stateChanged(*optBluetoothState);
});
}
std::shared_ptr<QOhosBluetoothAccessProxy> QOhosBluetoothAccessProxy::instance()
{
static auto instance = std::shared_ptr<QOhosBluetoothAccessProxy>(new QOhosBluetoothAccessProxy());
return instance;
}
std::optional<QOhosBluetoothAccessProxy::BluetoothState> QOhosBluetoothAccessProxy::tryGetBluetoothState() const
{
return m_ohosBluetoothStateSupplier();
}
std::optional<QOhosBluetoothErrorCode> QOhosBluetoothAccessProxy::trySetBluetoothEnabled(bool enabled)
{
if (!checkAccessBluetoothPermissionGranted(Q_FUNC_INFO)) {
Q_EMIT missingPermission();
return QOhosBluetoothErrorCode::PermissionDenied;
}
auto selfRef = QtOhos::makeQThreadSafeRef(this);
const auto optErrorCode = QOhosJsThreadGateway::eval(
[&](QOhosJsState &jsState) -> std::optional<QOhosBluetoothErrorCode> {
try {
jsState.evalToPromiseOrRejectOnThrow(
enabled ? "@ohos.bluetooth.access.enableBluetoothAsync()"
: "@ohos.bluetooth.access.disableBluetoothAsync()")
.onCatch(
[selfRef](const QOhosCallbackInfo &cbInfo) {
const auto errorValue = cbInfo.getFirstArg<QNapi::Value>(Q_FUNC_INFO);
const auto errorCode =
tryGetKnownErrorCode(errorValue, Q_FUNC_INFO)
.value_or(QOhosBluetoothErrorCode::OperationFailed);
qOhosPrintfWarning(
"%s: the bluetooth switch request was rejected, error code: %u",
Q_FUNC_INFO, qToUnderlying(errorCode));
selfRef.visitInQtThreadIfAlive(
[errorCode](auto &self) {
Q_EMIT self.setBluetoothEnabledFailed(errorCode);
});
});
return std::nullopt;
} catch (const Napi::Error &error) {
return tryGetKnownErrorCode(error.Value(), Q_FUNC_INFO);
}
},
Q_FUNC_INFO);
if (!optErrorCode)
return std::nullopt;
if (*optErrorCode == QOhosBluetoothErrorCode::PermissionDenied) {
qCWarning(
QT_BT_OHOS, "%s: no permission to set the bluetooth enabled state %d", Q_FUNC_INFO,
enabled);
Q_EMIT missingPermission();
return optErrorCode;
}
qCWarning(
QT_BT_OHOS, "%s: cannot set the bluetooth enabled state %d, error code: %u", Q_FUNC_INFO,
enabled, qToUnderlying(*optErrorCode));
return optErrorCode;
}
}
QT_END_NAMESPACE
#include "moc_qohosbluetoothaccess_p.cpp"