* Copyright (C) 2021-2022 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <list>
#include <mutex>
#include <thread>
#include "bluetooth_gatt_client_server.h"
#include "bluetooth_hitrace.h"
#include "bluetooth_errorcode.h"
#include "bluetooth_log.h"
#include "hisysevent.h"
#include "interface_adapter_ble.h"
#include "interface_adapter_classic.h"
#include "interface_adapter_manager.h"
#include "interface_profile_gatt_client.h"
#include "interface_profile_manager.h"
#include "bluetooth_utils_server.h"
#include "string_ex.h"
#include "system_ability_definition.h"
#include "ipc_skeleton.h"
#include "permission_manager.h"
using namespace OHOS::bluetooth;
namespace OHOS {
namespace Bluetooth {
constexpr int32_t CONN_UNKNOWN = 4;
inline const std::string GATT_DIS_MSG_CONN_UNKNOWN = "CONN_UNKNOWN";
struct BluetoothGattClientServer::impl {
class GattClientCallbackImpl;
class SystemStateObserver;
IProfileGattClient *clientService_;
std::unique_ptr<SystemStateObserver> systemStateObserver_;
std::list<std::unique_ptr<GattClientCallbackImpl>> callbacks_;
std::mutex registerMutex_;
impl();
~impl();
IProfileGattClient *GetServicePtr()
{
if (IProfileManager::GetInstance() == nullptr) {
return nullptr;
}
return static_cast<IProfileGattClient *>(
IProfileManager::GetInstance()->GetProfileService(PROFILE_NAME_GATT_CLIENT));
}
};
class BluetoothGattClientServer::impl::SystemStateObserver : public ISystemStateObserver {
public:
SystemStateObserver(BluetoothGattClientServer::impl *impl) : impl_(impl){};
~SystemStateObserver() override = default;
void OnSystemStateChange(const BTSystemState state) override
{
std::lock_guard<std::mutex> lck(impl_->registerMutex_);
switch (state) {
case BTSystemState::ON:
impl_->clientService_ = impl_->GetServicePtr();
break;
case BTSystemState::OFF:
impl_->clientService_ = nullptr;
break;
default:
break;
}
}
private:
BluetoothGattClientServer::impl *impl_;
};
namespace {
bool CheckGattClientPermission(uint64_t tokenId, int sdkVersion)
{
if (PermissionManager::IsNativeCaller(tokenId) || sdkVersion >= API_VERSION_10) {
if (!PermissionManager::VerifyPermission(ACCESS_BLUETOOTH, tokenId)) {
HILOGI("check ACCESS_BLUETOOTH permission failed");
return false;
}
} else {
if (!PermissionManager::VerifyPermission(USE_BLUETOOTH, tokenId)) {
HILOGI("check USE_BLUETOOTH permission failed");
return false;
}
}
return true;
}
}
class BluetoothGattClientServer::impl::GattClientCallbackImpl : public IGattClientCallback {
public:
void OnConnectionStateChanged(int state, int newState) override
{
HILOGI("curState(%{public}d) -> newState(%{public}d)", state, newState);
if (!CheckGattClientPermission(tokenId_, PermissionManager::GetApiVersion(tokenId_))) {
return;
}
int32_t pid = IPCSkeleton::GetCallingPid();
int32_t uid = IPCSkeleton::GetCallingUid();
if (state == static_cast<int>(BTConnectState::CONNECTED) ||
state == static_cast<int>(BTConnectState::DISCONNECTED)) {
HiSysEventWrite(OHOS::HiviewDFX::HiSysEvent::Domain::BT_SERVICE, "GATT_CLIENT_CONN_STATE",
OHOS::HiviewDFX::HiSysEvent::EventType::STATISTIC, "PID", pid, "UID", uid, "STATE", state);
}
callback_->OnConnectionStateChanged(state, newState, CONN_UNKNOWN, GATT_DIS_MSG_CONN_UNKNOWN);
}
void OnCharacteristicChanged(const Characteristic &characteristic) override
{
HILOGI("enter");
if (!CheckGattClientPermission(tokenId_, PermissionManager::GetApiVersion(tokenId_))) {
return;
}
callback_->OnCharacteristicChanged((BluetoothGattCharacteristic)characteristic);
}
void OnCharacteristicRead(int ret, const Characteristic &characteristic) override
{
HILOGI("ret: %{public}d", ret);
callback_->OnCharacteristicRead(ret, (BluetoothGattCharacteristic)characteristic);
}
void OnCharacteristicWrite(int ret, const Characteristic &characteristic) override
{
HILOGI("ret: %{public}d", ret);
BluetoothGattRspContext rspContext;
callback_->OnCharacteristicWrite(ret, (BluetoothGattCharacteristic)characteristic, rspContext);
}
void OnDescriptorRead(int ret, const Descriptor &descriptor) override
{
HILOGI("ret: %{public}d", ret);
callback_->OnDescriptorRead(ret, (BluetoothGattDescriptor)descriptor);
}
void OnDescriptorWrite(int ret, const Descriptor &descriptor) override
{
HILOGI("ret: %{public}d", ret);
callback_->OnDescriptorWrite(ret, (BluetoothGattDescriptor)descriptor);
}
void OnMtuChanged(int state, int mtu) override
{
HILOGI("state: %{public}d, mtu: %{public}d", state, mtu);
if (PermissionManager::IsNativeCaller(tokenId_) ||
PermissionManager::GetApiVersion(tokenId_) >= API_VERSION_10) {
if (PermissionManager::VerifyPermission(ACCESS_BLUETOOTH, tokenId_) == false) {
HILOGE("check access permission failed.");
return;
}
}
callback_->OnMtuChanged(state, mtu);
}
void OnReadRemoteRssiValue(const RawAddress &addr, int rssi, int status) override
{
return;
}
void OnServicesDiscovered(int status) override
{
HILOGI("status: %{public}d", status);
callback_->OnServicesDiscovered(status);
}
void OnConnectionParameterChanged(int interval, int latency, int timeout, int status) override
{
HILOGI("interval: %{public}d, latency: %{public}d, timeout: %{public}d, status: %{public}d",
interval, latency, timeout, status);
callback_->OnConnectionParameterChanged(interval, latency, timeout, status);
}
void OnServicesChanged() override
{
HILOGI("enter");
callback_->OnServicesChanged();
}
sptr<IBluetoothGattClientCallback> GetCallback()
{
return callback_;
}
void SetAppId(int appId)
{
applicationId_ = appId;
}
int GetAppId()
{
return applicationId_;
}
GattClientCallbackImpl(const sptr<IBluetoothGattClientCallback> &callback, BluetoothGattClientServer &owner);
~GattClientCallbackImpl()
{
if (!callback_->AsObject()->RemoveDeathRecipient(deathRecipient_)) {
HILOGE("Failed to unlink death recipient to callback");
}
callback_ = nullptr;
deathRecipient_ = nullptr;
};
private:
class CallbackDeathRecipient : public IRemoteObject::DeathRecipient {
public:
CallbackDeathRecipient(const sptr<IBluetoothGattClientCallback> &callback, BluetoothGattClientServer &owner);
sptr<IBluetoothGattClientCallback> GetCallback() const
{
return callback_;
};
void OnRemoteDied(const wptr<IRemoteObject> &remote) override;
private:
sptr<IBluetoothGattClientCallback> callback_;
BluetoothGattClientServer &owner_;
};
sptr<IBluetoothGattClientCallback> callback_;
sptr<CallbackDeathRecipient> deathRecipient_;
int applicationId_;
uint32_t tokenId_;
};
BluetoothGattClientServer::impl::GattClientCallbackImpl::GattClientCallbackImpl(
const sptr<IBluetoothGattClientCallback> &callback, BluetoothGattClientServer &owner)
: callback_(callback), deathRecipient_(new CallbackDeathRecipient(callback, owner))
{
if (!callback_->AsObject()->AddDeathRecipient(deathRecipient_)) {
HILOGE("Failed to link death recipient to callback");
}
tokenId_ = IPCSkeleton::GetCallingTokenID();
}
BluetoothGattClientServer::impl::GattClientCallbackImpl::CallbackDeathRecipient::CallbackDeathRecipient(
const sptr<IBluetoothGattClientCallback> &callback, BluetoothGattClientServer &owner)
: callback_(callback), owner_(owner)
{}
void BluetoothGattClientServer::impl::GattClientCallbackImpl::CallbackDeathRecipient::OnRemoteDied(
const wptr<IRemoteObject> &remote)
{
HILOGI("enter");
if (owner_.pimpl == nullptr || owner_.pimpl->clientService_ == nullptr) {
HILOGE("gattClientServerImpl clientService_ is not support.");
return;
}
std::lock_guard<std::mutex> lck(owner_.pimpl->registerMutex_);
for (auto it = owner_.pimpl->callbacks_.begin(); it != owner_.pimpl->callbacks_.end(); ++it) {
if ((*it)->GetCallback()->AsObject() == remote) {
HILOGI("callback is found from callbacks");
sptr<CallbackDeathRecipient> dr = (*it)->deathRecipient_;
if (!dr->GetCallback()->AsObject()->RemoveDeathRecipient(dr)) {
HILOGE("Failed to unlink death recipient from callback");
}
HILOGI("App id is %{public}d", (*it)->GetAppId());
owner_.pimpl->clientService_->Disconnect((*it)->GetAppId());
owner_.pimpl->clientService_->DeregisterApplication((*it)->GetAppId());
owner_.pimpl->callbacks_.erase(it);
return;
}
}
HILOGE("No callback erased from callbacks");
}
BluetoothGattClientServer::impl::impl() : clientService_(nullptr), systemStateObserver_(new SystemStateObserver(this))
{
IAdapterManager::GetInstance()->RegisterSystemStateObserver(*systemStateObserver_);
}
BluetoothGattClientServer::impl::~impl()
{
IAdapterManager::GetInstance()->DeregisterSystemStateObserver(*systemStateObserver_);
}
BluetoothGattClientServer::BluetoothGattClientServer() : pimpl(new impl())
{
HILOGI("enter");
}
BluetoothGattClientServer::~BluetoothGattClientServer()
{}
int BluetoothGattClientServer::RegisterApplication(
const sptr<IBluetoothGattClientCallback> &callback, const BluetoothRawAddress &addr, int32_t transport)
{
int appId = 0;
int ret = RegisterApplication(callback, addr, transport, appId);
return (ret == NO_ERROR) ? appId : ret;
}
int BluetoothGattClientServer::RegisterApplication(
const sptr<IBluetoothGattClientCallback> &callback, const BluetoothRawAddress &addr, int32_t transport, int &appId)
{
HILOGI("address: %{public}s, transport: %{public}d", GetEncryptAddr(addr.GetAddress()).c_str(), transport);
std::lock_guard<std::mutex> lck(pimpl->registerMutex_);
pimpl->clientService_ = pimpl->GetServicePtr();
if (pimpl->clientService_ == nullptr) {
HILOGE("request not support.");
return BT_ERR_INTERNAL_ERROR;
}
auto it = pimpl->callbacks_.emplace(
pimpl->callbacks_.begin(), std::make_unique<impl::GattClientCallbackImpl>(callback, *this));
appId = pimpl->clientService_->RegisterSharedApplication(*it->get(), (RawAddress)addr, transport);
if (appId >= 0) {
HILOGI("appId: %{public}d", appId);
(*it)->SetAppId(appId);
HiSysEventWrite(OHOS::HiviewDFX::HiSysEvent::Domain::BT_SERVICE, "GATT_APP_REGISTER",
OHOS::HiviewDFX::HiSysEvent::EventType::STATISTIC, "ACTION", "register",
"SIDE", "client", "ADDRESS", GetEncryptAddr(addr.GetAddress()), "PID", OHOS::IPCSkeleton::GetCallingPid(),
"UID", OHOS::IPCSkeleton::GetCallingUid(), "APPID", appId);
} else {
HILOGE("RegisterSharedApplication failed, appId: %{public}d", appId);
pimpl->callbacks_.erase(it);
}
return NO_ERROR;
}
int BluetoothGattClientServer::DeregisterApplication(int32_t appId)
{
HILOGI("appId: %{public}d", appId);
std::lock_guard<std::mutex> lck(pimpl->registerMutex_);
if (pimpl->clientService_ == nullptr) {
HILOGE("request not support.");
return bluetooth::GattStatus::REQUEST_NOT_SUPPORT;
}
HiSysEventWrite(OHOS::HiviewDFX::HiSysEvent::Domain::BT_SERVICE, "GATT_APP_REGISTER",
OHOS::HiviewDFX::HiSysEvent::EventType::STATISTIC, "ACTION", "deregister",
"SIDE", "client", "ADDRESS", "empty", "PID", OHOS::IPCSkeleton::GetCallingPid(),
"UID", OHOS::IPCSkeleton::GetCallingUid(), "APPID", appId);
auto it = std::find_if(pimpl->callbacks_.begin(), pimpl->callbacks_.end(),
[appId](const std::unique_ptr<impl::GattClientCallbackImpl> &p) { return p->GetAppId() == appId; });
if (it == pimpl->callbacks_.end()) {
HILOGE("Unknown appId: %{public}d", appId);
return INVALID_PARAMETER;
}
int ret = pimpl->clientService_->DeregisterApplication(appId);
pimpl->callbacks_.erase(it);
return ret;
}
int BluetoothGattClientServer::Connect(int32_t appId, bool autoConnect)
{
HILOGI("appId: %{public}d, autoConnect: %{public}d", appId, autoConnect);
std::lock_guard<std::mutex> lck(pimpl->registerMutex_);
if (pimpl->clientService_ == nullptr) {
HILOGE("request not support.");
return BT_ERR_INTERNAL_ERROR;
}
OHOS::Bluetooth::BluetoothHiTrace::BluetoothStartAsyncTrace("GATT_CLIENT_CONNECT", 1);
int result = pimpl->clientService_->Connect(appId, autoConnect);
OHOS::Bluetooth::BluetoothHiTrace::BluetoothFinishAsyncTrace("GATT_CLIENT_CONNECT", 1);
return result;
}
int BluetoothGattClientServer::Disconnect(int32_t appId)
{
HILOGI("appId: %{public}d", appId);
std::lock_guard<std::mutex> lck(pimpl->registerMutex_);
if (pimpl->clientService_ == nullptr) {
HILOGE("request not support.");
return BT_ERR_INTERNAL_ERROR;
}
return pimpl->clientService_->Disconnect(appId);
}
int BluetoothGattClientServer::DiscoveryServices(int32_t appId)
{
HILOGI("appId: %{public}d", appId);
std::lock_guard<std::mutex> lck(pimpl->registerMutex_);
if (pimpl->clientService_ == nullptr) {
HILOGE("request not support.");
return BT_ERR_INTERNAL_ERROR;
}
return pimpl->clientService_->DiscoveryServices(appId);
}
int BluetoothGattClientServer::ReadCharacteristic(int32_t appId, const BluetoothGattCharacteristic &characteristic)
{
HILOGI("appId: %{public}d", appId);
std::lock_guard<std::mutex> lck(pimpl->registerMutex_);
if (pimpl->clientService_ == nullptr) {
HILOGE("request not support.");
return BT_ERR_INTERNAL_ERROR;
}
return pimpl->clientService_->ReadCharacteristic(appId, (Characteristic)characteristic);
}
int BluetoothGattClientServer::WriteCharacteristic(
int32_t appId, BluetoothGattCharacteristic *characteristic, bool withoutRespond, bool isWithContext)
{
if (isWithContext) {
HILOGE("API WriteCharacteristicValueWithContext is not supported.");
return BT_ERR_API_NOT_SUPPORT;
}
HILOGI("appId: %{public}d, withoutRespond: %{public}d", appId, withoutRespond);
Characteristic character(characteristic->handle_);
character.length_ = characteristic->length_;
character.value_ = std::move(characteristic->value_);
characteristic->length_ = 0;
std::lock_guard<std::mutex> lck(pimpl->registerMutex_);
if (pimpl->clientService_ == nullptr) {
HILOGE("request not support.");
return BT_ERR_INTERNAL_ERROR;
}
return pimpl->clientService_->WriteCharacteristic(appId, character, withoutRespond);
}
int BluetoothGattClientServer::SignedWriteCharacteristic(int32_t appId, BluetoothGattCharacteristic *characteristic)
{
HILOGI("appId: %{public}d", appId);
Characteristic character(characteristic->handle_);
character.length_ = characteristic->length_;
character.value_ = std::move(characteristic->value_);
characteristic->length_ = 0;
std::lock_guard<std::mutex> lck(pimpl->registerMutex_);
if (pimpl->clientService_ == nullptr) {
HILOGE("request not support.");
return bluetooth::GattStatus::REQUEST_NOT_SUPPORT;
}
return pimpl->clientService_->SignedWriteCharacteristic(appId, character);
}
int BluetoothGattClientServer::ReadDescriptor(int32_t appId, const BluetoothGattDescriptor &descriptor)
{
HILOGI("appId: %{public}d", appId);
std::lock_guard<std::mutex> lck(pimpl->registerMutex_);
if (pimpl->clientService_ == nullptr) {
HILOGE("request not support.");
return BT_ERR_INTERNAL_ERROR;
}
return pimpl->clientService_->ReadDescriptor(appId, (Descriptor)descriptor);
}
int BluetoothGattClientServer::WriteDescriptor(int32_t appId, BluetoothGattDescriptor *descriptor)
{
HILOGI("appId: %{public}d", appId);
Descriptor desc(descriptor->handle_);
desc.length_ = descriptor->length_;
desc.value_ = std::move(descriptor->value_);
descriptor->length_ = 0;
std::lock_guard<std::mutex> lck(pimpl->registerMutex_);
if (pimpl->clientService_ == nullptr) {
HILOGE("request not support.");
return BT_ERR_INTERNAL_ERROR;
}
return pimpl->clientService_->WriteDescriptor(appId, desc);
}
int BluetoothGattClientServer::RequestExchangeMtu(int32_t appId, int32_t mtu)
{
HILOGI("appId: %{public}d, mtu: %{public}d", appId, mtu);
std::lock_guard<std::mutex> lck(pimpl->registerMutex_);
if (pimpl->clientService_ == nullptr) {
HILOGE("request not support.");
return BT_ERR_INTERNAL_ERROR;
}
return pimpl->clientService_->RequestExchangeMtu(appId, mtu);
}
void BluetoothGattClientServer::GetAllDevice(::std::vector<BluetoothGattDevice> &device)
{
HILOGI("enter");
std::lock_guard<std::mutex> lck(pimpl->registerMutex_);
if (pimpl->clientService_ == nullptr) {
HILOGE("request not support.");
return;
}
for (auto &dev : pimpl->clientService_->GetAllDevice()) {
device.push_back(dev);
}
}
int BluetoothGattClientServer::RequestConnectionPriority(int32_t appId, int32_t connPriority)
{
HILOGI("appId: %{public}d, connPriority: %{public}d", appId, connPriority);
std::lock_guard<std::mutex> lck(pimpl->registerMutex_);
if (pimpl->clientService_ == nullptr) {
HILOGE("request not support.");
return 0;
}
return pimpl->clientService_->RequestConnectionPriority(appId, connPriority);
}
int BluetoothGattClientServer::GetServices(int32_t appId, ::std::vector<BluetoothGattService> &service)
{
HILOGI("appId: %{public}d", appId);
std::lock_guard<std::mutex> lck(pimpl->registerMutex_);
if (pimpl->clientService_ == nullptr) {
HILOGE("request not support.");
return BT_ERR_INTERNAL_ERROR;
}
for (auto &svc : pimpl->clientService_->GetServices(appId)) {
service.push_back(svc);
}
return NO_ERROR;
}
int BluetoothGattClientServer::RequestFastestConn(const BluetoothRawAddress &addr)
{
HILOGI("NOT SUPPORT NOW");
return NO_ERROR;
}
int BluetoothGattClientServer::ReadRemoteRssiValue(int32_t appId)
{
HILOGI("NOT SUPPORT NOW");
return NO_ERROR;
}
int BluetoothGattClientServer::RequestNotification(int32_t appId, uint16_t characterHandle, bool enable)
{
HILOGI("NOT SUPPORT NOW");
return NO_ERROR;
}
int BluetoothGattClientServer::GetConnectedState(const std::string &deviceId, int &state)
{
HILOGI("NOT SUPPORT NOW");
return NO_ERROR;
}
int BluetoothGattClientServer::SetPhy(int32_t appId, int32_t txPhy, int32_t rxPhy, int32_t phyOptions)
{
HILOGI("NOT SUPPORT NOW");
return NO_ERROR;
}
int BluetoothGattClientServer::ReadPhy(int32_t appId)
{
HILOGI("NOT SUPPORT NOW");
return NO_ERROR;
}
int BluetoothGattClientServer::ReadCharacteristicByUuid(int32_t appId, const std::string &uuid,
int32_t startHandle, int32_t endHandle)
{
HILOGI("NOT SUPPORT NOW");
return NO_ERROR;
}
}
}