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