• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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