blob: 013ab7f8745527f5a5ce8e54185f3996a36cd3d6 [file] [log] [blame]
Myles Watson6d5e7722022-09-30 06:22:43 -07001/*
2 * Copyright 2022 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#define LOG_TAG "android.hardware.bluetooth.service.default"
18
19#include "BluetoothHci.h"
20
21#include <cutils/properties.h>
22#include <fcntl.h>
23#include <netdb.h>
24#include <netinet/in.h>
25#include <poll.h>
26#include <string.h>
27#include <sys/uio.h>
28#include <termios.h>
29
30#include "log/log.h"
31
Myles Watson65b47f52023-01-26 12:59:06 -080032// TODO: Remove custom logging defines from PDL packets.
33#undef LOG_INFO
34#undef LOG_DEBUG
35#include "hci/hci_packets.h"
36
Myles Watson6d5e7722022-09-30 06:22:43 -070037namespace {
38int SetTerminalRaw(int fd) {
39 termios terminal_settings;
40 int rval = tcgetattr(fd, &terminal_settings);
41 if (rval < 0) {
42 return rval;
43 }
44 cfmakeraw(&terminal_settings);
45 rval = tcsetattr(fd, TCSANOW, &terminal_settings);
46 return rval;
47}
48} // namespace
49
50using namespace ::android::hardware::bluetooth::hci;
51using namespace ::android::hardware::bluetooth::async;
Myles Watsonefa25d72022-10-03 16:27:32 -070052using aidl::android::hardware::bluetooth::Status;
Myles Watson6d5e7722022-09-30 06:22:43 -070053
54namespace aidl::android::hardware::bluetooth::impl {
55
56void OnDeath(void* cookie);
57
Henri Chataing1267ff22023-08-09 22:38:24 +000058std::optional<std::string> GetSystemProperty(const std::string& property) {
59 std::array<char, PROPERTY_VALUE_MAX> value_array{0};
60 auto value_len = property_get(property.c_str(), value_array.data(), nullptr);
61 if (value_len <= 0) {
62 return std::nullopt;
63 }
64 return std::string(value_array.data(), value_len);
65}
66
67bool starts_with(const std::string& str, const std::string& prefix) {
68 return str.compare(0, prefix.length(), prefix) == 0;
69}
70
Myles Watson6d5e7722022-09-30 06:22:43 -070071class BluetoothDeathRecipient {
72 public:
73 BluetoothDeathRecipient(BluetoothHci* hci) : mHci(hci) {}
74
75 void LinkToDeath(const std::shared_ptr<IBluetoothHciCallbacks>& cb) {
76 mCb = cb;
77 clientDeathRecipient_ = AIBinder_DeathRecipient_new(OnDeath);
78 auto linkToDeathReturnStatus = AIBinder_linkToDeath(
79 mCb->asBinder().get(), clientDeathRecipient_, this /* cookie */);
80 LOG_ALWAYS_FATAL_IF(linkToDeathReturnStatus != STATUS_OK,
81 "Unable to link to death recipient");
82 }
83
84 void UnlinkToDeath(const std::shared_ptr<IBluetoothHciCallbacks>& cb) {
85 LOG_ALWAYS_FATAL_IF(cb != mCb, "Unable to unlink mismatched pointers");
86 }
87
88 void serviceDied() {
89 if (mCb != nullptr && !AIBinder_isAlive(mCb->asBinder().get())) {
90 ALOGE("Bluetooth remote service has died");
91 } else {
92 ALOGE("BluetoothDeathRecipient::serviceDied called but service not dead");
93 return;
94 }
Myles Watson65b47f52023-01-26 12:59:06 -080095 {
96 std::lock_guard<std::mutex> guard(mHasDiedMutex);
97 has_died_ = true;
98 }
Myles Watson6d5e7722022-09-30 06:22:43 -070099 mHci->close();
100 }
101 BluetoothHci* mHci;
102 std::shared_ptr<IBluetoothHciCallbacks> mCb;
103 AIBinder_DeathRecipient* clientDeathRecipient_;
Myles Watson65b47f52023-01-26 12:59:06 -0800104 bool getHasDied() {
105 std::lock_guard<std::mutex> guard(mHasDiedMutex);
106 return has_died_;
107 }
Myles Watson6d5e7722022-09-30 06:22:43 -0700108
109 private:
Myles Watson65b47f52023-01-26 12:59:06 -0800110 std::mutex mHasDiedMutex;
Myles Watson8678c752022-11-03 10:41:44 -0700111 bool has_died_{false};
Myles Watson6d5e7722022-09-30 06:22:43 -0700112};
113
114void OnDeath(void* cookie) {
115 auto* death_recipient = static_cast<BluetoothDeathRecipient*>(cookie);
116 death_recipient->serviceDied();
117}
118
119BluetoothHci::BluetoothHci(const std::string& dev_path) {
120 char property_bytes[PROPERTY_VALUE_MAX];
121 property_get("vendor.ser.bt-uart", property_bytes, dev_path.c_str());
122 mDevPath = std::string(property_bytes);
123 mDeathRecipient = std::make_shared<BluetoothDeathRecipient>(this);
124}
125
Myles Watsonefa25d72022-10-03 16:27:32 -0700126int BluetoothHci::getFdFromDevPath() {
127 int fd = open(mDevPath.c_str(), O_RDWR);
128 if (fd < 0) {
Myles Watson6d5e7722022-09-30 06:22:43 -0700129 ALOGE("Could not connect to bt: %s (%s)", mDevPath.c_str(),
130 strerror(errno));
Myles Watsonefa25d72022-10-03 16:27:32 -0700131 return fd;
Myles Watson6d5e7722022-09-30 06:22:43 -0700132 }
yanggang.yangeb744bc2023-04-21 11:05:42 +0800133 if (int ret = SetTerminalRaw(fd) < 0) {
134 ALOGI("Could not make %s a raw terminal %d(%s)", mDevPath.c_str(), ret,
Myles Watson6d5e7722022-09-30 06:22:43 -0700135 strerror(errno));
Myles Watson6d5e7722022-09-30 06:22:43 -0700136 }
Myles Watsonefa25d72022-10-03 16:27:32 -0700137 return fd;
138}
139
Myles Watson65b47f52023-01-26 12:59:06 -0800140void BluetoothHci::reset() {
141 // Send a reset command and wait until the command complete comes back.
142
143 std::vector<uint8_t> reset;
144 ::bluetooth::packet::BitInserter bi{reset};
145 ::bluetooth::hci::ResetBuilder::Create()->Serialize(bi);
146
147 auto resetPromise = std::make_shared<std::promise<void>>();
148 auto resetFuture = resetPromise->get_future();
149
150 mH4 = std::make_shared<H4Protocol>(
151 mFd,
152 [](const std::vector<uint8_t>& raw_command) {
153 ALOGI("Discarding %d bytes with command type",
154 static_cast<int>(raw_command.size()));
155 },
156 [](const std::vector<uint8_t>& raw_acl) {
157 ALOGI("Discarding %d bytes with acl type",
158 static_cast<int>(raw_acl.size()));
159 },
160 [](const std::vector<uint8_t>& raw_sco) {
161 ALOGI("Discarding %d bytes with sco type",
162 static_cast<int>(raw_sco.size()));
163 },
164 [resetPromise](const std::vector<uint8_t>& raw_event) {
165 bool valid = ::bluetooth::hci::ResetCompleteView::Create(
166 ::bluetooth::hci::CommandCompleteView::Create(
167 ::bluetooth::hci::EventView::Create(
168 ::bluetooth::hci::PacketView<true>(
169 std::make_shared<std::vector<uint8_t>>(
170 raw_event)))))
171 .IsValid();
172 if (valid) {
173 resetPromise->set_value();
174 } else {
175 ALOGI("Discarding %d bytes with event type",
176 static_cast<int>(raw_event.size()));
177 }
178 },
179 [](const std::vector<uint8_t>& raw_iso) {
180 ALOGI("Discarding %d bytes with iso type",
181 static_cast<int>(raw_iso.size()));
182 },
183 [this]() {
184 ALOGI("HCI socket device disconnected while waiting for reset");
185 mFdWatcher.StopWatchingFileDescriptors();
186 });
187 mFdWatcher.WatchFdForNonBlockingReads(mFd,
188 [this](int) { mH4->OnDataReady(); });
189
Elie Kheirallahcd1bf1e2023-04-14 17:49:42 +0000190 ndk::ScopedAStatus result = send(PacketType::COMMAND, reset);
191 if (!result.isOk()) {
192 ALOGE("Error sending reset command");
193 }
Myles Watson65b47f52023-01-26 12:59:06 -0800194 auto status = resetFuture.wait_for(std::chrono::seconds(1));
195 mFdWatcher.StopWatchingFileDescriptors();
196 if (status == std::future_status::ready) {
197 ALOGI("HCI Reset successful");
198 } else {
199 ALOGE("HCI Reset Response not received in one second");
200 }
201
202 resetPromise.reset();
203}
204
Myles Watsonefa25d72022-10-03 16:27:32 -0700205ndk::ScopedAStatus BluetoothHci::initialize(
206 const std::shared_ptr<IBluetoothHciCallbacks>& cb) {
207 ALOGI(__func__);
Myles Watson6d5e7722022-09-30 06:22:43 -0700208
Myles Watson65b47f52023-01-26 12:59:06 -0800209 if (cb == nullptr) {
Myles Watson6d5e7722022-09-30 06:22:43 -0700210 ALOGE("cb == nullptr! -> Unable to call initializationComplete(ERR)");
211 return ndk::ScopedAStatus::fromServiceSpecificError(STATUS_BAD_VALUE);
212 }
213
Myles Watson65b47f52023-01-26 12:59:06 -0800214 HalState old_state = HalState::READY;
215 {
216 std::lock_guard<std::mutex> guard(mStateMutex);
217 if (mState != HalState::READY) {
218 old_state = mState;
219 } else {
220 mState = HalState::INITIALIZING;
221 }
222 }
223
224 if (old_state != HalState::READY) {
225 ALOGE("initialize: Unexpected State %d", static_cast<int>(old_state));
226 close();
227 cb->initializationComplete(Status::ALREADY_INITIALIZED);
228 return ndk::ScopedAStatus::ok();
229 }
230
231 mCb = cb;
Myles Watsonefa25d72022-10-03 16:27:32 -0700232 management_.reset(new NetBluetoothMgmt);
233 mFd = management_->openHci();
234 if (mFd < 0) {
235 management_.reset();
236
237 ALOGI("Unable to open Linux interface, trying default path.");
238 mFd = getFdFromDevPath();
239 if (mFd < 0) {
yanggang.yang6ebe2512023-05-31 13:59:04 +0800240 mState = HalState::READY;
Myles Watson65b47f52023-01-26 12:59:06 -0800241 cb->initializationComplete(Status::UNABLE_TO_OPEN_INTERFACE);
242 return ndk::ScopedAStatus::ok();
Myles Watsonefa25d72022-10-03 16:27:32 -0700243 }
244 }
245
Myles Watson6d5e7722022-09-30 06:22:43 -0700246 mDeathRecipient->LinkToDeath(mCb);
247
Henri Chataing1267ff22023-08-09 22:38:24 +0000248 // TODO: HCI Reset on emulators since the bluetooth controller
249 // cannot be powered on/off during the HAL setup; and the stack
250 // might received spurious packets/events during boottime.
251 // Proper solution would be to use bt-virtio or vsock to better
252 // control the link to rootcanal and the controller lifetime.
253 const std::string kBoardProperty = "ro.product.board";
254 const std::string kCuttlefishBoard = "cutf";
255 auto board_name = GetSystemProperty(kBoardProperty);
256 if (board_name.has_value() && (
257 starts_with(board_name.value(), "cutf") ||
258 starts_with(board_name.value(), "goldfish"))) {
259 reset();
260 }
Myles Watson65b47f52023-01-26 12:59:06 -0800261
Myles Watson6d5e7722022-09-30 06:22:43 -0700262 mH4 = std::make_shared<H4Protocol>(
263 mFd,
264 [](const std::vector<uint8_t>& /* raw_command */) {
265 LOG_ALWAYS_FATAL("Unexpected command!");
266 },
David Duartea58b79d2023-01-19 18:14:32 +0000267 [this](const std::vector<uint8_t>& raw_acl) {
268 mCb->aclDataReceived(raw_acl);
269 },
270 [this](const std::vector<uint8_t>& raw_sco) {
271 mCb->scoDataReceived(raw_sco);
272 },
Myles Watson6d5e7722022-09-30 06:22:43 -0700273 [this](const std::vector<uint8_t>& raw_event) {
274 mCb->hciEventReceived(raw_event);
275 },
Myles Watson6d5e7722022-09-30 06:22:43 -0700276 [this](const std::vector<uint8_t>& raw_iso) {
David Duartea58b79d2023-01-19 18:14:32 +0000277 mCb->isoDataReceived(raw_iso);
Myles Watson6d5e7722022-09-30 06:22:43 -0700278 },
279 [this]() {
280 ALOGI("HCI socket device disconnected");
281 mFdWatcher.StopWatchingFileDescriptors();
282 });
283 mFdWatcher.WatchFdForNonBlockingReads(mFd,
284 [this](int) { mH4->OnDataReady(); });
Myles Watsonefa25d72022-10-03 16:27:32 -0700285
Myles Watson65b47f52023-01-26 12:59:06 -0800286 {
287 std::lock_guard<std::mutex> guard(mStateMutex);
288 mState = HalState::ONE_CLIENT;
289 }
Myles Watsonefa25d72022-10-03 16:27:32 -0700290 ALOGI("initialization complete");
291 auto status = mCb->initializationComplete(Status::SUCCESS);
292 if (!status.isOk()) {
293 if (!mDeathRecipient->getHasDied()) {
294 ALOGE("Error sending init callback, but no death notification");
295 }
296 close();
297 return ndk::ScopedAStatus::fromServiceSpecificError(
298 STATUS_FAILED_TRANSACTION);
299 }
300
Myles Watson6d5e7722022-09-30 06:22:43 -0700301 return ndk::ScopedAStatus::ok();
302}
303
304ndk::ScopedAStatus BluetoothHci::close() {
305 ALOGI(__func__);
Myles Watson65b47f52023-01-26 12:59:06 -0800306 {
307 std::lock_guard<std::mutex> guard(mStateMutex);
308 if (mState != HalState::ONE_CLIENT) {
yanggang.yang6ebe2512023-05-31 13:59:04 +0800309 ASSERT(mState != HalState::INITIALIZING);
Myles Watson65b47f52023-01-26 12:59:06 -0800310 ALOGI("Already closed");
311 return ndk::ScopedAStatus::ok();
312 }
313 mState = HalState::CLOSING;
314 }
315
Myles Watson6d5e7722022-09-30 06:22:43 -0700316 mFdWatcher.StopWatchingFileDescriptors();
Myles Watson65b47f52023-01-26 12:59:06 -0800317
Myles Watsonefa25d72022-10-03 16:27:32 -0700318 if (management_) {
319 management_->closeHci();
320 } else {
321 ::close(mFd);
322 }
Myles Watson6d5e7722022-09-30 06:22:43 -0700323
Myles Watson65b47f52023-01-26 12:59:06 -0800324 {
325 std::lock_guard<std::mutex> guard(mStateMutex);
326 mState = HalState::READY;
327 }
Myles Watson6d5e7722022-09-30 06:22:43 -0700328 return ndk::ScopedAStatus::ok();
329}
330
331ndk::ScopedAStatus BluetoothHci::sendHciCommand(
332 const std::vector<uint8_t>& packet) {
Elie Kheirallahcd1bf1e2023-04-14 17:49:42 +0000333 return send(PacketType::COMMAND, packet);
Myles Watson6d5e7722022-09-30 06:22:43 -0700334}
335
336ndk::ScopedAStatus BluetoothHci::sendAclData(
337 const std::vector<uint8_t>& packet) {
Elie Kheirallahcd1bf1e2023-04-14 17:49:42 +0000338 return send(PacketType::ACL_DATA, packet);
Myles Watson6d5e7722022-09-30 06:22:43 -0700339}
340
341ndk::ScopedAStatus BluetoothHci::sendScoData(
342 const std::vector<uint8_t>& packet) {
Elie Kheirallahcd1bf1e2023-04-14 17:49:42 +0000343 return send(PacketType::SCO_DATA, packet);
Myles Watson6d5e7722022-09-30 06:22:43 -0700344}
345
346ndk::ScopedAStatus BluetoothHci::sendIsoData(
347 const std::vector<uint8_t>& packet) {
Elie Kheirallahcd1bf1e2023-04-14 17:49:42 +0000348 return send(PacketType::ISO_DATA, packet);
Myles Watson6d5e7722022-09-30 06:22:43 -0700349}
350
Elie Kheirallahcd1bf1e2023-04-14 17:49:42 +0000351ndk::ScopedAStatus BluetoothHci::send(PacketType type,
352 const std::vector<uint8_t>& v) {
353 if (mH4 == nullptr) {
354 return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
355 }
356 if (v.empty()) {
357 ALOGE("Packet is empty, no data was found to be sent");
358 return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
359 }
Myles Watson6d5e7722022-09-30 06:22:43 -0700360 mH4->Send(type, v);
Elie Kheirallahcd1bf1e2023-04-14 17:49:42 +0000361 return ndk::ScopedAStatus::ok();
Myles Watson6d5e7722022-09-30 06:22:43 -0700362}
363
364} // namespace aidl::android::hardware::bluetooth::impl