// // Copyright 2017 The Android Open Source Project // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // #define LOG_TAG "android.hardware.bluetooth@1.0.sim" #include "bluetooth_hci.h" #include <base/logging.h> #include <cutils/properties.h> #include <netdb.h> #include <netinet/in.h> #include <string.h> #include <utils/Log.h> #include "hci_internals.h" namespace android { namespace hardware { namespace bluetooth { namespace V1_0 { namespace sim { using android::hardware::hidl_vec; using test_vendor_lib::AsyncTaskId; using test_vendor_lib::DualModeController; using test_vendor_lib::TaskCallback; namespace { bool BtTestConsoleEnabled() { // Assume enabled by default. return property_get_bool("bt.rootcanal_test_console", true); } } // namespace class BluetoothDeathRecipient : public hidl_death_recipient { public: BluetoothDeathRecipient(const sp<IBluetoothHci> hci) : mHci(hci) {} virtual void serviceDied(uint64_t /* cookie */, const wp<::android::hidl::base::V1_0::IBase>& /* who */) { ALOGE("BluetoothDeathRecipient::serviceDied - Bluetooth service died"); has_died_ = true; mHci->close(); } sp<IBluetoothHci> mHci; bool getHasDied() const { return has_died_; } void setHasDied(bool has_died) { has_died_ = has_died; } private: bool has_died_; }; BluetoothHci::BluetoothHci() : death_recipient_(new BluetoothDeathRecipient(this)) {} Return<void> BluetoothHci::initialize(const sp<IBluetoothHciCallbacks>& cb) { ALOGI("%s", __func__); if (cb == nullptr) { ALOGE("cb == nullptr! -> Unable to call initializationComplete(ERR)"); return Void(); } death_recipient_->setHasDied(false); cb->linkToDeath(death_recipient_, 0); test_channel_transport_.RegisterCommandHandler([this](const std::string& name, const std::vector<std::string>& args) { async_manager_.ExecAsync(std::chrono::milliseconds(0), [this, name, args]() { test_channel_.HandleCommand(name, args); }); }); controller_ = std::make_shared<DualModeController>(); controller_->Initialize({"dmc", "3C:5A:B4:01:02:03"}); controller_->RegisterEventChannel([cb](std::shared_ptr<std::vector<uint8_t>> packet) { hidl_vec<uint8_t> hci_event(packet->begin(), packet->end()); cb->hciEventReceived(hci_event); }); controller_->RegisterAclChannel([cb](std::shared_ptr<std::vector<uint8_t>> packet) { hidl_vec<uint8_t> acl_packet(packet->begin(), packet->end()); cb->aclDataReceived(acl_packet); }); controller_->RegisterScoChannel([cb](std::shared_ptr<std::vector<uint8_t>> packet) { hidl_vec<uint8_t> sco_packet(packet->begin(), packet->end()); cb->aclDataReceived(sco_packet); }); controller_->RegisterTaskScheduler([this](std::chrono::milliseconds delay, const TaskCallback& task) { return async_manager_.ExecAsync(delay, task); }); controller_->RegisterPeriodicTaskScheduler( [this](std::chrono::milliseconds delay, std::chrono::milliseconds period, const TaskCallback& task) { return async_manager_.ExecAsyncPeriodically(delay, period, task); }); controller_->RegisterTaskCancel([this](AsyncTaskId task) { async_manager_.CancelAsyncTask(task); }); test_model_.Reset(); // Add the controller as a device in the model. test_model_.Add(controller_); // Send responses to logcat if the test channel is not configured. test_channel_.RegisterSendResponse([](const std::string& response) { ALOGI("No test channel yet: %s", response.c_str()); }); if (BtTestConsoleEnabled()) { SetUpTestChannel(6111); SetUpHciServer(6211, [this](int fd) { test_model_.IncomingHciConnection(fd); }); SetUpLinkLayerServer( 6311, [this](int fd) { test_model_.IncomingLinkLayerConnection(fd); }); } // Add some default devices for easier debugging test_channel_.AddDefaults(); // This should be configurable in the future. ALOGI("Adding Beacons so the scan list is not empty."); test_channel_.Add({"beacon", "be:ac:10:00:00:01", "1000"}); test_channel_.AddDeviceToPhy({"1", "0"}); test_channel_.Add({"beacon", "be:ac:10:00:00:02", "1000"}); test_channel_.AddDeviceToPhy({"2", "0"}); test_channel_.SetTimerPeriod({"1000"}); unlink_cb_ = [cb](sp<BluetoothDeathRecipient>& death_recipient) { if (death_recipient->getHasDied()) ALOGI("Skipping unlink call, service died."); else cb->unlinkToDeath(death_recipient); }; cb->initializationComplete(Status::SUCCESS); return Void(); } Return<void> BluetoothHci::close() { ALOGI("%s", __func__); return Void(); } Return<void> BluetoothHci::sendHciCommand(const hidl_vec<uint8_t>& packet) { async_manager_.ExecAsync(std::chrono::milliseconds(0), [this, packet]() { std::shared_ptr<std::vector<uint8_t>> packet_copy = std::shared_ptr<std::vector<uint8_t>>(new std::vector<uint8_t>(packet)); controller_->HandleCommand(packet_copy); }); return Void(); } Return<void> BluetoothHci::sendAclData(const hidl_vec<uint8_t>& packet) { async_manager_.ExecAsync(std::chrono::milliseconds(0), [this, packet]() { std::shared_ptr<std::vector<uint8_t>> packet_copy = std::shared_ptr<std::vector<uint8_t>>(new std::vector<uint8_t>(packet)); controller_->HandleAcl(packet_copy); }); return Void(); } Return<void> BluetoothHci::sendScoData(const hidl_vec<uint8_t>& packet) { async_manager_.ExecAsync(std::chrono::milliseconds(0), [this, packet]() { std::shared_ptr<std::vector<uint8_t>> packet_copy = std::shared_ptr<std::vector<uint8_t>>(new std::vector<uint8_t>(packet)); controller_->HandleSco(packet_copy); }); return Void(); } void BluetoothHci::SetUpHciServer(int port, const std::function<void(int)>& connection_callback) { int socket_fd = remote_hci_transport_.SetUp(port); test_channel_.RegisterSendResponse( [](const std::string& response) { ALOGI("No HCI Response channel: %s", response.c_str()); }); if (socket_fd == -1) { ALOGE("Remote HCI channel SetUp(%d) failed.", port); return; } async_manager_.WatchFdForNonBlockingReads(socket_fd, [this, connection_callback](int socket_fd) { int conn_fd = remote_hci_transport_.Accept(socket_fd); if (conn_fd < 0) { ALOGE("Error watching remote HCI channel fd."); return; } int flags = fcntl(conn_fd, F_GETFL, NULL); int ret; ret = fcntl(conn_fd, F_SETFL, flags | O_NONBLOCK); CHECK(ret != -1) << "Error setting O_NONBLOCK " << strerror(errno); connection_callback(conn_fd); }); } void BluetoothHci::SetUpLinkLayerServer(int port, const std::function<void(int)>& connection_callback) { int socket_fd = remote_link_layer_transport_.SetUp(port); test_channel_.RegisterSendResponse( [](const std::string& response) { ALOGI("No LinkLayer Response channel: %s", response.c_str()); }); if (socket_fd == -1) { ALOGE("Remote LinkLayer channel SetUp(%d) failed.", port); return; } async_manager_.WatchFdForNonBlockingReads(socket_fd, [this, connection_callback](int socket_fd) { int conn_fd = remote_link_layer_transport_.Accept(socket_fd); if (conn_fd < 0) { ALOGE("Error watching remote LinkLayer channel fd."); return; } int flags = fcntl(conn_fd, F_GETFL, NULL); int ret = fcntl(conn_fd, F_SETFL, flags | O_NONBLOCK); CHECK(ret != -1) << "Error setting O_NONBLOCK " << strerror(errno); connection_callback(conn_fd); }); } int BluetoothHci::ConnectToRemoteServer(const std::string& server, int port) { int socket_fd = socket(AF_INET, SOCK_STREAM, 0); if (socket_fd < 1) { ALOGI("socket() call failed: %s", strerror(errno)); return -1; } struct hostent* host; host = gethostbyname(server.c_str()); if (host == NULL) { ALOGI("gethostbyname() failed for %s: %s", server.c_str(), strerror(errno)); return -1; } struct sockaddr_in serv_addr; memset((void*)&serv_addr, 0, sizeof(serv_addr)); serv_addr.sin_family = AF_INET; serv_addr.sin_addr.s_addr = INADDR_ANY; serv_addr.sin_port = htons(port); int result = connect(socket_fd, (struct sockaddr*)&serv_addr, sizeof(serv_addr)); if (result < 0) { ALOGI("connect() failed for %s@%d: %s", server.c_str(), port, strerror(errno)); return -1; } int flags = fcntl(socket_fd, F_GETFL, NULL); int ret = fcntl(socket_fd, F_SETFL, flags | O_NONBLOCK); CHECK(ret != -1) << "Error setting O_NONBLOCK " << strerror(errno); return socket_fd; } void BluetoothHci::SetUpTestChannel(int port) { int socket_fd = test_channel_transport_.SetUp(port); test_channel_.RegisterSendResponse( [](const std::string& response) { ALOGI("No test channel: %s", response.c_str()); }); if (socket_fd == -1) { ALOGE("Test channel SetUp(%d) failed.", port); return; } ALOGI("Test channel SetUp() successful"); async_manager_.WatchFdForNonBlockingReads(socket_fd, [this](int socket_fd) { int conn_fd = test_channel_transport_.Accept(socket_fd); if (conn_fd < 0) { ALOGE("Error watching test channel fd."); return; } ALOGI("Test channel connection accepted."); test_channel_.RegisterSendResponse( [this, conn_fd](const std::string& response) { test_channel_transport_.SendResponse(conn_fd, response); }); async_manager_.WatchFdForNonBlockingReads(conn_fd, [this](int conn_fd) { test_channel_transport_.OnCommandReady(conn_fd, [this, conn_fd]() { async_manager_.StopWatchingFileDescriptor(conn_fd); }); }); }); } /* Fallback to shared library if there is no service. */ IBluetoothHci* HIDL_FETCH_IBluetoothHci(const char* /* name */) { return new BluetoothHci(); } } // namespace sim } // namespace V1_0 } // namespace bluetooth } // namespace hardware } // namespace android