| // Copyright 2022 The Chromium Authors |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "device/bluetooth/floss/floss_battery_manager_client.h" |
| |
| namespace floss { |
| |
| // Template specializations for dbus parsing |
| |
| template <> |
| bool FlossDBusClient::ReadDBusParam(dbus::MessageReader* reader, |
| Battery* battery) { |
| static FlossDBusClient::StructReader<Battery> struct_reader( |
| {{"percentage", CreateFieldReader(&Battery::percentage)}, |
| {"variant", CreateFieldReader(&Battery::variant)}}); |
| |
| return struct_reader.ReadDBusParam(reader, battery); |
| } |
| |
| template <> |
| const DBusTypeInfo& GetDBusTypeInfo(const Battery*) { |
| static DBusTypeInfo info{"a{sv}", "Battery"}; |
| return info; |
| } |
| |
| template <> |
| void FlossDBusClient::WriteDBusParam(dbus::MessageWriter* writer, |
| const Battery& battery) { |
| dbus::MessageWriter array_writer(nullptr); |
| writer->OpenArray("{sv}", &array_writer); |
| |
| WriteDictEntry(&array_writer, "percentage", battery.percentage); |
| WriteDictEntry(&array_writer, "variant", battery.variant); |
| |
| writer->CloseContainer(&array_writer); |
| } |
| |
| template <> |
| bool FlossDBusClient::ReadDBusParam(dbus::MessageReader* reader, |
| BatterySet* battery_set) { |
| static FlossDBusClient::StructReader<BatterySet> struct_reader( |
| {{"address", CreateFieldReader(&BatterySet::address)}, |
| {"source_uuid", CreateFieldReader(&BatterySet::source_uuid)}, |
| {"source_info", CreateFieldReader(&BatterySet::source_info)}, |
| {"batteries", CreateFieldReader(&BatterySet::batteries)}}); |
| |
| return struct_reader.ReadDBusParam(reader, battery_set); |
| } |
| |
| template <> |
| const DBusTypeInfo& GetDBusTypeInfo(const BatterySet*) { |
| static DBusTypeInfo info{"a{sv}", "BatterySet"}; |
| return info; |
| } |
| |
| template <> |
| void FlossDBusClient::WriteDBusParam(dbus::MessageWriter* writer, |
| const BatterySet& battery_set) { |
| dbus::MessageWriter array_writer(nullptr); |
| writer->OpenArray("{sv}", &array_writer); |
| |
| WriteDictEntry(&array_writer, "address", battery_set.address); |
| WriteDictEntry(&array_writer, "source_uuid", battery_set.source_uuid); |
| WriteDictEntry(&array_writer, "source_info", battery_set.source_info); |
| WriteDictEntry(&array_writer, "batteries", battery_set.batteries); |
| |
| writer->CloseContainer(&array_writer); |
| } |
| |
| Battery::Battery() = default; |
| Battery::~Battery() = default; |
| |
| BatterySet::BatterySet() = default; |
| BatterySet::BatterySet(const BatterySet&) = default; |
| BatterySet::~BatterySet() = default; |
| |
| const char FlossBatteryManagerClient::kExportedCallbacksPath[] = |
| "/org/chromium/bluetooth/battery_manager/callback"; |
| |
| void FlossBatteryManagerClient::AddObserver( |
| FlossBatteryManagerClient::FlossBatteryManagerClientObserver* observer) { |
| observers_.AddObserver(observer); |
| } |
| |
| void FlossBatteryManagerClient::RemoveObserver( |
| FlossBatteryManagerClient::FlossBatteryManagerClientObserver* observer) { |
| observers_.RemoveObserver(observer); |
| } |
| |
| std::unique_ptr<FlossBatteryManagerClient> FlossBatteryManagerClient::Create() { |
| return std::make_unique<FlossBatteryManagerClient>(); |
| } |
| |
| FlossBatteryManagerClient::FlossBatteryManagerClient() = default; |
| FlossBatteryManagerClient::~FlossBatteryManagerClient() { |
| if (battery_manager_callback_id_) { |
| CallBatteryManagerMethod<bool>( |
| base::BindOnce(&FlossBatteryManagerClient::BatteryCallbackUnregistered, |
| weak_ptr_factory_.GetWeakPtr()), |
| battery_manager::kUnregisterBatteryCallback, |
| battery_manager_callback_id_.value()); |
| } |
| if (bus_) { |
| exported_callback_manager_.UnexportCallback( |
| dbus::ObjectPath(kExportedCallbacksPath)); |
| } |
| } |
| |
| void FlossBatteryManagerClient::GetBatteryInformation( |
| ResponseCallback<std::optional<BatterySet>> callback, |
| const FlossDeviceId& device) { |
| CallBatteryManagerMethod<std::optional<BatterySet>>( |
| std::move(callback), battery_manager::kGetBatteryInformation, |
| device.address); |
| } |
| |
| void FlossBatteryManagerClient::Init(dbus::Bus* bus, |
| const std::string& service_name, |
| const int adapter_index, |
| base::Version version, |
| base::OnceClosure on_ready) { |
| bus_ = bus; |
| service_name_ = service_name; |
| battery_manager_adapter_path_ = GenerateBatteryManagerPath(adapter_index); |
| version_ = version; |
| |
| dbus::ObjectProxy* object_proxy = |
| bus_->GetObjectProxy(service_name_, battery_manager_adapter_path_); |
| if (!object_proxy) { |
| LOG(ERROR) |
| << "FlossBatteryManagerClient couldn't init. Object proxy was null."; |
| return; |
| } |
| |
| exported_callback_manager_.Init(bus_.get()); |
| exported_callback_manager_.AddMethod( |
| battery_manager::kOnBatteryInfoUpdated, |
| &FlossBatteryManagerClientObserver::BatteryInfoUpdated); |
| |
| if (!exported_callback_manager_.ExportCallback( |
| dbus::ObjectPath(kExportedCallbacksPath), |
| weak_ptr_factory_.GetWeakPtr(), |
| base::BindOnce(&FlossBatteryManagerClient::OnMethodsExported, |
| weak_ptr_factory_.GetWeakPtr()))) { |
| LOG(ERROR) |
| << "Unable to successfully export FlossBatteryManagerClientObserver."; |
| return; |
| } |
| |
| on_ready_ = std::move(on_ready); |
| } |
| |
| void FlossBatteryManagerClient::OnMethodsExported() { |
| CallBatteryManagerMethod<uint32_t>( |
| base::BindOnce(&FlossBatteryManagerClient::BatteryCallbackRegistered, |
| weak_ptr_factory_.GetWeakPtr()), |
| battery_manager::kRegisterBatteryCallback, |
| dbus::ObjectPath(kExportedCallbacksPath)); |
| } |
| |
| void FlossBatteryManagerClient::BatteryInfoUpdated(std::string remote_address, |
| BatterySet battery_set) { |
| for (auto& observer : observers_) { |
| observer.BatteryInfoUpdated(remote_address, battery_set); |
| } |
| } |
| |
| void FlossBatteryManagerClient::BatteryCallbackRegistered( |
| DBusResult<uint32_t> result) { |
| if (!result.has_value()) { |
| LOG(ERROR) << "RegisterBatteryCallback call failed: " << result.error(); |
| return; |
| } |
| |
| battery_manager_callback_id_ = result.value(); |
| CompleteInit(); |
| } |
| |
| void FlossBatteryManagerClient::BatteryCallbackUnregistered( |
| DBusResult<bool> result) { |
| if (!result.has_value() || *result == false) { |
| LOG(WARNING) << __func__ << ": Failed to unregister callback"; |
| } |
| } |
| |
| void FlossBatteryManagerClient::CompleteInit() { |
| if (on_ready_) { |
| std::move(on_ready_).Run(); |
| } |
| } |
| |
| } // namespace floss |