1 /*
2  * Copyright 2024 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include <aidl/android/hardware/bluetooth/ranging/BnBluetoothChannelSounding.h>
18 #include <aidl/android/hardware/bluetooth/ranging/BnBluetoothChannelSoundingSession.h>
19 #include <aidl/android/hardware/bluetooth/ranging/BnBluetoothChannelSoundingSessionCallback.h>
20 #include <aidl/android/hardware/bluetooth/ranging/IBluetoothChannelSounding.h>
21 #include <android/binder_manager.h>
22 #include <bluetooth/log.h>
23 
24 #include <unordered_map>
25 
26 // AIDL uses syslog.h, so these defines conflict with os/log.h
27 #undef LOG_DEBUG
28 #undef LOG_INFO
29 #undef LOG_WARNING
30 
31 #include "ranging_hal.h"
32 
33 using aidl::android::hardware::bluetooth::ranging::BluetoothChannelSoundingParameters;
34 using aidl::android::hardware::bluetooth::ranging::BnBluetoothChannelSoundingSessionCallback;
35 using aidl::android::hardware::bluetooth::ranging::ChannelSoudingRawData;
36 using aidl::android::hardware::bluetooth::ranging::ComplexNumber;
37 using aidl::android::hardware::bluetooth::ranging::IBluetoothChannelSounding;
38 using aidl::android::hardware::bluetooth::ranging::IBluetoothChannelSoundingSession;
39 using aidl::android::hardware::bluetooth::ranging::IBluetoothChannelSoundingSessionCallback;
40 using aidl::android::hardware::bluetooth::ranging::StepTonePct;
41 using aidl::android::hardware::bluetooth::ranging::VendorSpecificData;
42 
43 namespace bluetooth {
44 namespace hal {
45 
46 class BluetoothChannelSoundingSessionTracker : public BnBluetoothChannelSoundingSessionCallback {
47  public:
BluetoothChannelSoundingSessionTracker(uint16_t connection_handle,RangingHalCallback * ranging_hal_callback,bool for_vendor_specific_reply)48   BluetoothChannelSoundingSessionTracker(
49       uint16_t connection_handle,
50       RangingHalCallback* ranging_hal_callback,
51       bool for_vendor_specific_reply)
52       : connection_handle_(connection_handle),
53         ranging_hal_callback_(ranging_hal_callback),
54         for_vendor_specific_reply_(for_vendor_specific_reply) {}
55 
onOpened(::aidl::android::hardware::bluetooth::ranging::Reason in_reason)56   ::ndk::ScopedAStatus onOpened(::aidl::android::hardware::bluetooth::ranging::Reason in_reason) {
57     log::info("connection_handle 0x{:04x}, reason {}", connection_handle_, (uint16_t)in_reason);
58     if (for_vendor_specific_reply_) {
59       ranging_hal_callback_->OnHandleVendorSpecificReplyComplete(connection_handle_, true);
60     }
61     return ::ndk::ScopedAStatus::ok();
62   };
63 
onOpenFailed(::aidl::android::hardware::bluetooth::ranging::Reason in_reason)64   ::ndk::ScopedAStatus onOpenFailed(
65       ::aidl::android::hardware::bluetooth::ranging::Reason in_reason) {
66     log::info("connection_handle 0x{:04x}, reason {}", connection_handle_, (uint16_t)in_reason);
67     bluetooth_channel_sounding_session_ = nullptr;
68     if (for_vendor_specific_reply_) {
69       ranging_hal_callback_->OnHandleVendorSpecificReplyComplete(connection_handle_, false);
70     } else {
71       ranging_hal_callback_->OnOpenFailed(connection_handle_);
72     }
73     return ::ndk::ScopedAStatus::ok();
74   };
75 
onResult(const::aidl::android::hardware::bluetooth::ranging::RangingResult & in_result)76   ::ndk::ScopedAStatus onResult(
77       const ::aidl::android::hardware::bluetooth::ranging::RangingResult& in_result) {
78     log::verbose("resultMeters {}", in_result.resultMeters);
79     hal::RangingResult ranging_result;
80     ranging_result.result_meters_ = in_result.resultMeters;
81     ranging_hal_callback_->OnResult(connection_handle_, ranging_result);
82     return ::ndk::ScopedAStatus::ok();
83   };
84 
onClose(::aidl::android::hardware::bluetooth::ranging::Reason in_reason)85   ::ndk::ScopedAStatus onClose(::aidl::android::hardware::bluetooth::ranging::Reason in_reason) {
86     log::info("reason {}", (uint16_t)in_reason);
87     bluetooth_channel_sounding_session_ = nullptr;
88     return ::ndk::ScopedAStatus::ok();
89   };
onCloseFailed(::aidl::android::hardware::bluetooth::ranging::Reason in_reason)90   ::ndk::ScopedAStatus onCloseFailed(
91       ::aidl::android::hardware::bluetooth::ranging::Reason in_reason) {
92     log::info("reason {}", (uint16_t)in_reason);
93     return ::ndk::ScopedAStatus::ok();
94   };
95 
GetSession()96   std::shared_ptr<IBluetoothChannelSoundingSession>& GetSession() {
97     return bluetooth_channel_sounding_session_;
98   };
99 
100  private:
101   std::shared_ptr<IBluetoothChannelSoundingSession> bluetooth_channel_sounding_session_ = nullptr;
102   uint16_t connection_handle_;
103   RangingHalCallback* ranging_hal_callback_;
104   bool for_vendor_specific_reply_;
105 };
106 
107 class RangingHalAndroid : public RangingHal {
108  public:
IsBound()109   bool IsBound() override {
110     return bluetooth_channel_sounding_ != nullptr;
111   }
112 
RegisterCallback(RangingHalCallback * callback)113   void RegisterCallback(RangingHalCallback* callback) {
114     ranging_hal_callback_ = callback;
115   }
116 
GetVendorSpecificCharacteristics()117   std::vector<VendorSpecificCharacteristic> GetVendorSpecificCharacteristics() override {
118     std::vector<VendorSpecificCharacteristic> vendor_specific_characteristics = {};
119     if (bluetooth_channel_sounding_ != nullptr) {
120       std::optional<std::vector<std::optional<VendorSpecificData>>> vendorSpecificDataOptional;
121       bluetooth_channel_sounding_->getVendorSpecificData(&vendorSpecificDataOptional);
122       if (vendorSpecificDataOptional.has_value()) {
123         for (auto vendor_specific_data : vendorSpecificDataOptional.value()) {
124           VendorSpecificCharacteristic vendor_specific_characteristic;
125           vendor_specific_characteristic.characteristicUuid_ =
126               vendor_specific_data->characteristicUuid;
127           vendor_specific_characteristic.value_ = vendor_specific_data->opaqueValue;
128           vendor_specific_characteristics.emplace_back(vendor_specific_characteristic);
129         }
130       }
131       log::info("size {}", vendor_specific_characteristics.size());
132     } else {
133       log::warn("bluetooth_channel_sounding_ is nullptr");
134     }
135 
136     return vendor_specific_characteristics;
137   };
138 
OpenSession(uint16_t connection_handle,uint16_t att_handle,const std::vector<hal::VendorSpecificCharacteristic> & vendor_specific_data)139   void OpenSession(
140       uint16_t connection_handle,
141       uint16_t att_handle,
142       const std::vector<hal::VendorSpecificCharacteristic>& vendor_specific_data) {
143     log::info(
144         "connection_handle 0x{:04x}, att_handle 0x{:04x} size of vendor_specific_data {}",
145         connection_handle,
146         att_handle,
147         vendor_specific_data.size());
148     session_trackers_[connection_handle] =
149         ndk::SharedRefBase::make<BluetoothChannelSoundingSessionTracker>(
150             connection_handle, ranging_hal_callback_, false);
151     BluetoothChannelSoundingParameters parameters;
152     parameters.aclHandle = connection_handle;
153     parameters.role = aidl::android::hardware::bluetooth::ranging::Role::INITIATOR;
154     parameters.realTimeProcedureDataAttHandle = att_handle;
155     CopyVendorSpecificData(vendor_specific_data, parameters.vendorSpecificData);
156 
157     auto& tracker = session_trackers_[connection_handle];
158     bluetooth_channel_sounding_->openSession(parameters, tracker, &tracker->GetSession());
159 
160     if (tracker->GetSession() != nullptr) {
161       std::vector<VendorSpecificCharacteristic> vendor_specific_reply = {};
162       std::optional<std::vector<std::optional<VendorSpecificData>>> vendorSpecificDataOptional;
163       tracker->GetSession()->getVendorSpecificReplies(&vendorSpecificDataOptional);
164 
165       if (vendorSpecificDataOptional.has_value()) {
166         for (auto& data : vendorSpecificDataOptional.value()) {
167           VendorSpecificCharacteristic vendor_specific_characteristic;
168           vendor_specific_characteristic.characteristicUuid_ = data->characteristicUuid;
169           vendor_specific_characteristic.value_ = data->opaqueValue;
170           vendor_specific_reply.emplace_back(vendor_specific_characteristic);
171         }
172       }
173       ranging_hal_callback_->OnOpened(connection_handle, vendor_specific_reply);
174     }
175   }
176 
HandleVendorSpecificReply(uint16_t connection_handle,const std::vector<hal::VendorSpecificCharacteristic> & vendor_specific_reply)177   void HandleVendorSpecificReply(
178       uint16_t connection_handle,
179       const std::vector<hal::VendorSpecificCharacteristic>& vendor_specific_reply) {
180     log::info("connection_handle 0x{:04x}", connection_handle);
181     session_trackers_[connection_handle] =
182         ndk::SharedRefBase::make<BluetoothChannelSoundingSessionTracker>(
183             connection_handle, ranging_hal_callback_, true);
184     BluetoothChannelSoundingParameters parameters;
185     parameters.aclHandle = connection_handle;
186     parameters.role = aidl::android::hardware::bluetooth::ranging::Role::REFLECTOR;
187     CopyVendorSpecificData(vendor_specific_reply, parameters.vendorSpecificData);
188     auto& tracker = session_trackers_[connection_handle];
189     bluetooth_channel_sounding_->openSession(parameters, tracker, &tracker->GetSession());
190   }
191 
WriteRawData(uint16_t connection_handle,const ChannelSoundingRawData & raw_data)192   void WriteRawData(uint16_t connection_handle, const ChannelSoundingRawData& raw_data) {
193     if (session_trackers_.find(connection_handle) == session_trackers_.end()) {
194       log::error("Can't find session for connection_handle:0x{:04x}", connection_handle);
195       return;
196     } else if (session_trackers_[connection_handle]->GetSession() == nullptr) {
197       log::error("Session not opened");
198       return;
199     }
200 
201     ChannelSoudingRawData hal_raw_data;
202     hal_raw_data.numAntennaPaths = raw_data.num_antenna_paths_;
203     hal_raw_data.stepChannels = raw_data.step_channel_;
204     hal_raw_data.initiatorData.stepTonePcts.emplace(std::vector<std::optional<StepTonePct>>{});
205     hal_raw_data.reflectorData.stepTonePcts.emplace(std::vector<std::optional<StepTonePct>>{});
206     for (uint8_t i = 0; i < raw_data.tone_pct_initiator_.size(); i++) {
207       StepTonePct step_tone_pct;
208       for (uint8_t j = 0; j < raw_data.tone_pct_initiator_[i].size(); j++) {
209         ComplexNumber complex_number;
210         complex_number.imaginary = raw_data.tone_pct_initiator_[i][j].imag();
211         complex_number.real = raw_data.tone_pct_initiator_[i][j].real();
212         step_tone_pct.tonePcts.emplace_back(complex_number);
213       }
214       step_tone_pct.toneQualityIndicator = raw_data.tone_quality_indicator_initiator_[i];
215       hal_raw_data.initiatorData.stepTonePcts.value().emplace_back(step_tone_pct);
216     }
217     for (uint8_t i = 0; i < raw_data.tone_pct_reflector_.size(); i++) {
218       StepTonePct step_tone_pct;
219       for (uint8_t j = 0; j < raw_data.tone_pct_reflector_[i].size(); j++) {
220         ComplexNumber complex_number;
221         complex_number.imaginary = raw_data.tone_pct_reflector_[i][j].imag();
222         complex_number.real = raw_data.tone_pct_reflector_[i][j].real();
223         step_tone_pct.tonePcts.emplace_back(complex_number);
224       }
225       step_tone_pct.toneQualityIndicator = raw_data.tone_quality_indicator_reflector_[i];
226       hal_raw_data.reflectorData.stepTonePcts.value().emplace_back(step_tone_pct);
227     }
228     session_trackers_[connection_handle]->GetSession()->writeRawData(hal_raw_data);
229   };
230 
CopyVendorSpecificData(const std::vector<hal::VendorSpecificCharacteristic> & source,std::optional<std::vector<std::optional<VendorSpecificData>>> & dist)231   void CopyVendorSpecificData(
232       const std::vector<hal::VendorSpecificCharacteristic>& source,
233       std::optional<std::vector<std::optional<VendorSpecificData>>>& dist) {
234     dist = std::make_optional<std::vector<std::optional<VendorSpecificData>>>();
235     for (auto& data : source) {
236       VendorSpecificData vendor_specific_data;
237       vendor_specific_data.characteristicUuid = data.characteristicUuid_;
238       vendor_specific_data.opaqueValue = data.value_;
239       dist->push_back(vendor_specific_data);
240     }
241   }
242 
243  protected:
ListDependencies(ModuleList *) const244   void ListDependencies(ModuleList* /*list*/) const {}
245 
Start()246   void Start() override {
247     std::string instance = std::string() + IBluetoothChannelSounding::descriptor + "/default";
248     log::info("AServiceManager_isDeclared {}", AServiceManager_isDeclared(instance.c_str()));
249     if (AServiceManager_isDeclared(instance.c_str())) {
250       ::ndk::SpAIBinder binder(AServiceManager_waitForService(instance.c_str()));
251       bluetooth_channel_sounding_ = IBluetoothChannelSounding::fromBinder(binder);
252       log::info("Bind IBluetoothChannelSounding {}", IsBound() ? "Success" : "Fail");
253     }
254   }
255 
Stop()256   void Stop() override {
257     bluetooth_channel_sounding_ = nullptr;
258   }
259 
ToString() const260   std::string ToString() const override {
261     return std::string("RangingHalAndroid");
262   }
263 
264  private:
265   std::shared_ptr<IBluetoothChannelSounding> bluetooth_channel_sounding_;
266   RangingHalCallback* ranging_hal_callback_;
267   std::unordered_map<uint16_t, std::shared_ptr<BluetoothChannelSoundingSessionTracker>>
268       session_trackers_;
269 };
270 
__anon35c8395a0102() 271 const ModuleFactory RangingHal::Factory = ModuleFactory([]() { return new RangingHalAndroid(); });
272 
273 }  // namespace hal
274 }  // namespace bluetooth
275