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 "qbluetoothserviceinfo_p.h"
#include <QtBluetooth/qbluetoothserviceinfo.h>
#include <QtBluetooth/private/qbluetoothserver_ohos_p.h>
#include <QtBluetooth/private/qohosbluetoothserver_p.h>
#include <QtCore/qloggingcategory.h>
#include <optional>
QT_BEGIN_NAMESPACE
Q_DECLARE_LOGGING_CATEGORY(QT_BT_OHOS)
namespace {
std::optional<quint16> tryGetRfcommServerPort(int serverChannel)
{
if (serverChannel < 0) {
qCWarning(QT_BT_OHOS, "%s: Only RFCOMM services can be registered on HarmonyOS", Q_FUNC_INFO);
return std::nullopt;
}
if (serverChannel == 0) {
qCCritical(
QT_BT_OHOS, "%s: No RFCOMM port in the service. Cannot register service.", Q_FUNC_INFO);
return std::nullopt;
}
return static_cast<quint16>(serverChannel);
}
}
QBluetoothServiceInfoPrivate::QBluetoothServiceInfoPrivate() = default;
QBluetoothServiceInfoPrivate::~QBluetoothServiceInfoPrivate()
{
unregisterService();
}
bool QBluetoothServiceInfoPrivate::isRegisteredWithServerProxy() const
{
const auto serverProxy = registeredServerProxy.lock();
return serverProxy && optRegisteredServiceId
&& serverProxy->tryGetRegisteredServiceId() == optRegisteredServiceId;
}
bool QBluetoothServiceInfoPrivate::isRegistered() const
{
return registered && isRegisteredWithServerProxy();
}
bool QBluetoothServiceInfoPrivate::unregisterService()
{
if (!registered)
return false;
registered = false;
if (isRegisteredWithServerProxy()) {
registeredServerProxy.lock()->close();
} else {
qCDebug(
QT_BT_OHOS, "%s: the server is already closed. The service is unregistered anyway.",
Q_FUNC_INFO);
}
registeredServerProxy.reset();
optRegisteredServiceId.reset();
return true;
}
bool QBluetoothServiceInfoPrivate::registerService(const QBluetoothAddress &localAdapter)
{
if (!localAdapter.isNull()) {
qCWarning(
QT_BT_OHOS,
"%s: HarmonyOS does not support multi device adapters. Ignoring local adapter address ...",
Q_FUNC_INFO);
}
if (isRegistered())
return false;
registered = false;
registeredServerProxy.reset();
optRegisteredServiceId.reset();
const auto optPort = tryGetRfcommServerPort(serverChannel());
if (!optPort)
return false;
const auto serviceName = attributes.value(QBluetoothServiceInfo::ServiceName).toString();
const auto uuid = attributes.value(QBluetoothServiceInfo::ServiceId).value<QBluetoothUuid>();
if (serviceName.isEmpty()) {
qCCritical(
QT_BT_OHOS, "%s: No service name in the service. Cannot register service.",
Q_FUNC_INFO);
return false;
}
if (uuid.isNull()) {
qCCritical(
QT_BT_OHOS, "%s: No service UUID in the service. Cannot register service.",
Q_FUNC_INFO);
return false;
}
if (QtOhosBluetooth::isServiceNameAlreadyRegistered(serviceName)) {
qCCritical(QT_BT_OHOS, "%s: Server with such service name is registered", Q_FUNC_INFO);
return false;
}
auto serverProxyContext = QtOhosBluetooth::tryGetServerProxyContext(*optPort);
if (!serverProxyContext) {
qCCritical(QT_BT_OHOS, "%s: Server is not active. Cannot register services.", Q_FUNC_INFO);
return false;
}
auto proxy = serverProxyContext->bluetoothServerProxy;
if (proxy->isServiceRegistered()) {
qCCritical(
QT_BT_OHOS, "%s: Server has already registered service. Cannot register services.",
Q_FUNC_INFO);
return false;
}
const auto secure = (serverProxyContext->securityFlags != QBluetooth::Security::NoSecurity);
if (!proxy->listen(serviceName, uuid.toString(QUuid::WithoutBraces), secure))
return false;
if (!proxy->accept()) {
proxy->close();
return false;
}
registered = true;
registeredServerProxy = proxy;
optRegisteredServiceId = proxy->tryGetRegisteredServiceId();
return true;
}
QT_END_NAMESPACE