1 /*
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
32 namespace {
SetTerminalRaw(int fd)33 int SetTerminalRaw(int fd) {
34 termios terminal_settings;
35 int rval = tcgetattr(fd, &terminal_settings);
36 if (rval < 0) {
37 return rval;
38 }
39 cfmakeraw(&terminal_settings);
40 rval = tcsetattr(fd, TCSANOW, &terminal_settings);
41 return rval;
42 }
43 } // namespace
44
45 using namespace ::android::hardware::bluetooth::hci;
46 using namespace ::android::hardware::bluetooth::async;
47 using aidl::android::hardware::bluetooth::Status;
48
49 namespace aidl::android::hardware::bluetooth::impl {
50
51 void OnDeath(void* cookie);
52
GetSystemProperty(const std::string & property)53 std::optional<std::string> GetSystemProperty(const std::string& property) {
54 std::array<char, PROPERTY_VALUE_MAX> value_array{0};
55 auto value_len = property_get(property.c_str(), value_array.data(), nullptr);
56 if (value_len <= 0) {
57 return std::nullopt;
58 }
59 return std::string(value_array.data(), value_len);
60 }
61
starts_with(const std::string & str,const std::string & prefix)62 bool starts_with(const std::string& str, const std::string& prefix) {
63 return str.compare(0, prefix.length(), prefix) == 0;
64 }
65
66 class BluetoothDeathRecipient {
67 public:
BluetoothDeathRecipient(BluetoothHci * hci)68 BluetoothDeathRecipient(BluetoothHci* hci) : mHci(hci) {}
69
LinkToDeath(const std::shared_ptr<IBluetoothHciCallbacks> & cb)70 void LinkToDeath(const std::shared_ptr<IBluetoothHciCallbacks>& cb) {
71 mCb = cb;
72 clientDeathRecipient_ = AIBinder_DeathRecipient_new(OnDeath);
73 auto linkToDeathReturnStatus = AIBinder_linkToDeath(
74 mCb->asBinder().get(), clientDeathRecipient_, this /* cookie */);
75 LOG_ALWAYS_FATAL_IF(linkToDeathReturnStatus != STATUS_OK,
76 "Unable to link to death recipient");
77 }
78
UnlinkToDeath(const std::shared_ptr<IBluetoothHciCallbacks> & cb)79 void UnlinkToDeath(const std::shared_ptr<IBluetoothHciCallbacks>& cb) {
80 LOG_ALWAYS_FATAL_IF(cb != mCb, "Unable to unlink mismatched pointers");
81 }
82
serviceDied()83 void serviceDied() {
84 if (mCb != nullptr && !AIBinder_isAlive(mCb->asBinder().get())) {
85 ALOGE("Bluetooth remote service has died");
86 } else {
87 ALOGE("BluetoothDeathRecipient::serviceDied called but service not dead");
88 return;
89 }
90 {
91 std::lock_guard<std::mutex> guard(mHasDiedMutex);
92 has_died_ = true;
93 }
94 mHci->close();
95 }
96 BluetoothHci* mHci;
97 std::shared_ptr<IBluetoothHciCallbacks> mCb;
98 AIBinder_DeathRecipient* clientDeathRecipient_;
getHasDied()99 bool getHasDied() {
100 std::lock_guard<std::mutex> guard(mHasDiedMutex);
101 return has_died_;
102 }
103
104 private:
105 std::mutex mHasDiedMutex;
106 bool has_died_{false};
107 };
108
OnDeath(void * cookie)109 void OnDeath(void* cookie) {
110 auto* death_recipient = static_cast<BluetoothDeathRecipient*>(cookie);
111 death_recipient->serviceDied();
112 }
113
BluetoothHci(const std::string & dev_path)114 BluetoothHci::BluetoothHci(const std::string& dev_path) {
115 char property_bytes[PROPERTY_VALUE_MAX];
116 property_get("vendor.ser.bt-uart", property_bytes, dev_path.c_str());
117 mDevPath = std::string(property_bytes);
118 mDeathRecipient = std::make_shared<BluetoothDeathRecipient>(this);
119 }
120
getFdFromDevPath()121 int BluetoothHci::getFdFromDevPath() {
122 int fd = open(mDevPath.c_str(), O_RDWR);
123 if (fd < 0) {
124 ALOGE("Could not connect to bt: %s (%s)", mDevPath.c_str(),
125 strerror(errno));
126 return fd;
127 }
128 if (int ret = SetTerminalRaw(fd) < 0) {
129 ALOGI("Could not make %s a raw terminal %d(%s)", mDevPath.c_str(), ret,
130 strerror(errno));
131 }
132 return fd;
133 }
134
reset()135 void BluetoothHci::reset() {
136 // Send a reset command and wait until the command complete comes back.
137
138 std::vector<uint8_t> reset = {0x03, 0x0c, 0x00};
139
140 auto resetPromise = std::make_shared<std::promise<void>>();
141 auto resetFuture = resetPromise->get_future();
142
143 mH4 = std::make_shared<H4Protocol>(
144 mFd,
145 [](const std::vector<uint8_t>& raw_command) {
146 ALOGI("Discarding %d bytes with command type",
147 static_cast<int>(raw_command.size()));
148 },
149 [](const std::vector<uint8_t>& raw_acl) {
150 ALOGI("Discarding %d bytes with acl type",
151 static_cast<int>(raw_acl.size()));
152 },
153 [](const std::vector<uint8_t>& raw_sco) {
154 ALOGI("Discarding %d bytes with sco type",
155 static_cast<int>(raw_sco.size()));
156 },
157 [resetPromise](const std::vector<uint8_t>& raw_event) {
158 std::vector<uint8_t> reset_complete = {0x0e, 0x04, 0x01,
159 0x03, 0x0c, 0x00};
160 bool valid = raw_event.size() == 6 &&
161 raw_event[0] == reset_complete[0] &&
162 raw_event[1] == reset_complete[1] &&
163 // Don't compare the number of packets field.
164 raw_event[3] == reset_complete[3] &&
165 raw_event[4] == reset_complete[4] &&
166 raw_event[5] == reset_complete[5];
167 if (valid) {
168 resetPromise->set_value();
169 } else {
170 ALOGI("Discarding %d bytes with event type",
171 static_cast<int>(raw_event.size()));
172 }
173 },
174 [](const std::vector<uint8_t>& raw_iso) {
175 ALOGI("Discarding %d bytes with iso type",
176 static_cast<int>(raw_iso.size()));
177 },
178 [this]() {
179 ALOGI("HCI socket device disconnected while waiting for reset");
180 mFdWatcher.StopWatchingFileDescriptors();
181 });
182 mFdWatcher.WatchFdForNonBlockingReads(mFd,
183 [this](int) { mH4->OnDataReady(); });
184
185 ndk::ScopedAStatus result = send(PacketType::COMMAND, reset);
186 if (!result.isOk()) {
187 ALOGE("Error sending reset command");
188 }
189 auto status = resetFuture.wait_for(std::chrono::seconds(1));
190 mFdWatcher.StopWatchingFileDescriptors();
191 if (status == std::future_status::ready) {
192 ALOGI("HCI Reset successful");
193 } else {
194 ALOGE("HCI Reset Response not received in one second");
195 }
196
197 resetPromise.reset();
198 }
199
initialize(const std::shared_ptr<IBluetoothHciCallbacks> & cb)200 ndk::ScopedAStatus BluetoothHci::initialize(
201 const std::shared_ptr<IBluetoothHciCallbacks>& cb) {
202 ALOGI(__func__);
203
204 if (cb == nullptr) {
205 ALOGE("cb == nullptr! -> Unable to call initializationComplete(ERR)");
206 return ndk::ScopedAStatus::fromServiceSpecificError(STATUS_BAD_VALUE);
207 }
208
209 HalState old_state = HalState::READY;
210 {
211 std::lock_guard<std::mutex> guard(mStateMutex);
212 if (mState != HalState::READY) {
213 old_state = mState;
214 } else {
215 mState = HalState::INITIALIZING;
216 }
217 }
218
219 if (old_state != HalState::READY) {
220 ALOGE("initialize: Unexpected State %d", static_cast<int>(old_state));
221 close();
222 cb->initializationComplete(Status::ALREADY_INITIALIZED);
223 return ndk::ScopedAStatus::ok();
224 }
225
226 mCb = cb;
227 management_.reset(new NetBluetoothMgmt);
228 mFd = management_->openHci();
229 if (mFd < 0) {
230 management_.reset();
231
232 ALOGI("Unable to open Linux interface, trying default path.");
233 mFd = getFdFromDevPath();
234 if (mFd < 0) {
235 mState = HalState::READY;
236 cb->initializationComplete(Status::UNABLE_TO_OPEN_INTERFACE);
237 return ndk::ScopedAStatus::ok();
238 }
239 }
240
241 mDeathRecipient->LinkToDeath(mCb);
242
243 // TODO: HCI Reset on emulators since the bluetooth controller
244 // cannot be powered on/off during the HAL setup; and the stack
245 // might received spurious packets/events during boottime.
246 // Proper solution would be to use bt-virtio or vsock to better
247 // control the link to rootcanal and the controller lifetime.
248 const std::string kBoardProperty = "ro.product.board";
249 const std::string kCuttlefishBoard = "cutf";
250 auto board_name = GetSystemProperty(kBoardProperty);
251 if (board_name.has_value() && (
252 starts_with(board_name.value(), "cutf") ||
253 starts_with(board_name.value(), "goldfish"))) {
254 reset();
255 }
256
257 mH4 = std::make_shared<H4Protocol>(
258 mFd,
259 [](const std::vector<uint8_t>& /* raw_command */) {
260 LOG_ALWAYS_FATAL("Unexpected command!");
261 },
262 [this](const std::vector<uint8_t>& raw_acl) {
263 mCb->aclDataReceived(raw_acl);
264 },
265 [this](const std::vector<uint8_t>& raw_sco) {
266 mCb->scoDataReceived(raw_sco);
267 },
268 [this](const std::vector<uint8_t>& raw_event) {
269 mCb->hciEventReceived(raw_event);
270 },
271 [this](const std::vector<uint8_t>& raw_iso) {
272 mCb->isoDataReceived(raw_iso);
273 },
274 [this]() {
275 ALOGI("HCI socket device disconnected");
276 mFdWatcher.StopWatchingFileDescriptors();
277 });
278 mFdWatcher.WatchFdForNonBlockingReads(mFd,
279 [this](int) { mH4->OnDataReady(); });
280
281 {
282 std::lock_guard<std::mutex> guard(mStateMutex);
283 mState = HalState::ONE_CLIENT;
284 }
285 ALOGI("initialization complete");
286 auto status = mCb->initializationComplete(Status::SUCCESS);
287 if (!status.isOk()) {
288 if (!mDeathRecipient->getHasDied()) {
289 ALOGE("Error sending init callback, but no death notification");
290 }
291 close();
292 return ndk::ScopedAStatus::fromServiceSpecificError(
293 STATUS_FAILED_TRANSACTION);
294 }
295
296 return ndk::ScopedAStatus::ok();
297 }
298
close()299 ndk::ScopedAStatus BluetoothHci::close() {
300 ALOGI(__func__);
301 {
302 std::lock_guard<std::mutex> guard(mStateMutex);
303 if (mState != HalState::ONE_CLIENT) {
304 LOG_ALWAYS_FATAL_IF(mState == HalState::INITIALIZING,
305 "mState is INITIALIZING");
306 ALOGI("Already closed");
307 return ndk::ScopedAStatus::ok();
308 }
309 mState = HalState::CLOSING;
310 }
311
312 mFdWatcher.StopWatchingFileDescriptors();
313
314 if (management_) {
315 management_->closeHci();
316 } else {
317 ::close(mFd);
318 }
319
320 {
321 std::lock_guard<std::mutex> guard(mStateMutex);
322 mState = HalState::READY;
323 mH4 = nullptr;
324 }
325 return ndk::ScopedAStatus::ok();
326 }
327
sendHciCommand(const std::vector<uint8_t> & packet)328 ndk::ScopedAStatus BluetoothHci::sendHciCommand(
329 const std::vector<uint8_t>& packet) {
330 return send(PacketType::COMMAND, packet);
331 }
332
sendAclData(const std::vector<uint8_t> & packet)333 ndk::ScopedAStatus BluetoothHci::sendAclData(
334 const std::vector<uint8_t>& packet) {
335 return send(PacketType::ACL_DATA, packet);
336 }
337
sendScoData(const std::vector<uint8_t> & packet)338 ndk::ScopedAStatus BluetoothHci::sendScoData(
339 const std::vector<uint8_t>& packet) {
340 return send(PacketType::SCO_DATA, packet);
341 }
342
sendIsoData(const std::vector<uint8_t> & packet)343 ndk::ScopedAStatus BluetoothHci::sendIsoData(
344 const std::vector<uint8_t>& packet) {
345 return send(PacketType::ISO_DATA, packet);
346 }
347
send(PacketType type,const std::vector<uint8_t> & v)348 ndk::ScopedAStatus BluetoothHci::send(PacketType type,
349 const std::vector<uint8_t>& v) {
350 if (v.empty()) {
351 ALOGE("Packet is empty, no data was found to be sent");
352 return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
353 }
354
355 std::lock_guard<std::mutex> guard(mStateMutex);
356 if (mH4 == nullptr) {
357 return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
358 }
359
360 mH4->Send(type, v);
361 return ndk::ScopedAStatus::ok();
362 }
363
364 } // namespace aidl::android::hardware::bluetooth::impl
365