// // 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 #include #include #include "acl_packet.h" #include "event_packet.h" #include "hci_internals.h" #include "sco_packet.h" namespace android { namespace hardware { namespace bluetooth { namespace V1_0 { namespace sim { using android::hardware::hidl_vec; using test_vendor_lib::AclPacket; using test_vendor_lib::AsyncManager; using test_vendor_lib::AsyncTaskId; using test_vendor_lib::CommandPacket; using test_vendor_lib::DualModeController; using test_vendor_lib::EventPacket; using test_vendor_lib::ScoPacket; using test_vendor_lib::TaskCallback; using test_vendor_lib::TestChannelTransport; class BluetoothDeathRecipient : public hidl_death_recipient { public: BluetoothDeathRecipient(const sp 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 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 BluetoothHci::initialize(const sp& 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& args) { async_manager_.ExecAsync( std::chrono::milliseconds(0), [this, name, args]() { controller_.HandleTestChannelCommand(name, args); }); }); controller_.RegisterEventChannel([cb](std::unique_ptr event) { size_t header_bytes = event->GetHeaderSize(); size_t payload_bytes = event->GetPayloadSize(); hidl_vec hci_event; hci_event.resize(header_bytes + payload_bytes); memcpy(hci_event.data(), event->GetHeader().data(), header_bytes); memcpy(hci_event.data() + header_bytes, event->GetPayload().data(), payload_bytes); cb->hciEventReceived(hci_event); }); controller_.RegisterAclChannel([cb](std::unique_ptr packet) { std::vector acl_vector = packet->GetPacket(); hidl_vec acl_packet = acl_vector; cb->aclDataReceived(acl_packet); }); controller_.RegisterScoChannel([cb](std::unique_ptr packet) { size_t header_bytes = packet->GetHeaderSize(); size_t payload_bytes = packet->GetPayloadSize(); hidl_vec sco_packet; sco_packet.resize(header_bytes + payload_bytes); memcpy(sco_packet.data(), packet->GetHeader().data(), header_bytes); memcpy(sco_packet.data() + header_bytes, packet->GetPayload().data(), payload_bytes); cb->scoDataReceived(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); }); SetUpTestChannel(6111); unlink_cb_ = [cb](sp& death_recipient) { if (death_recipient->getHasDied()) ALOGI("Skipping unlink call, service died."); else cb->unlinkToDeath(death_recipient); }; cb->initializationComplete(Status::SUCCESS); return Void(); } Return BluetoothHci::close() { ALOGI("%s", __func__); return Void(); } Return BluetoothHci::sendHciCommand(const hidl_vec& packet) { async_manager_.ExecAsync(std::chrono::milliseconds(0), [this, packet]() { uint16_t opcode = packet[0] | (packet[1] << 8); std::unique_ptr command = std::unique_ptr(new CommandPacket(opcode)); for (size_t i = 3; i < packet.size(); i++) command->AddPayloadOctets1(packet[i]); controller_.HandleCommand(std::move(command)); }); return Void(); } Return BluetoothHci::sendAclData(const hidl_vec& packet) { async_manager_.ExecAsync(std::chrono::milliseconds(0), [this, packet]() { uint16_t channel = (packet[0] | (packet[1] << 8)) & 0xfff; AclPacket::PacketBoundaryFlags boundary_flags = static_cast((packet[1] & 0x30) >> 4); AclPacket::BroadcastFlags broadcast_flags = static_cast((packet[1] & 0xC0) >> 6); std::unique_ptr acl = std::unique_ptr( new AclPacket(channel, boundary_flags, broadcast_flags)); for (size_t i = 4; i < packet.size(); i++) acl->AddPayloadOctets1(packet[i]); controller_.HandleAcl(std::move(acl)); }); return Void(); } Return BluetoothHci::sendScoData(const hidl_vec& packet) { async_manager_.ExecAsync(std::chrono::milliseconds(0), [this, packet]() { uint16_t channel = (packet[0] | (packet[1] << 8)) & 0xfff; ScoPacket::PacketStatusFlags packet_status = static_cast((packet[1] & 0x30) >> 4); std::unique_ptr sco = std::unique_ptr(new ScoPacket(channel, packet_status)); for (size_t i = 3; i < packet.size(); i++) sco->AddPayloadOctets1(packet[i]); controller_.HandleSco(std::move(sco)); }); return Void(); } void BluetoothHci::SetUpTestChannel(int port) { int socket_fd = test_channel_transport_.SetUp(port); 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."); 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 gce } // namespace V1_0 } // namespace bluetooth } // namespace hardware } // namespace android