Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 03cebc6d authored by Myles Watson's avatar Myles Watson Committed by Automerger Merge Worker
Browse files

Merge changes from topic "hci_aidl_hal" am: 88150368

parents f7e095b2 88150368
Loading
Loading
Loading
Loading
+79 −0
Original line number Diff line number Diff line
package {
    default_applicable_licenses: ["Android-Apache-2.0"],
}

cc_defaults {
    name: "android.hardware.bluetooth-service-build-defaults",
    cflags: [
        "-Wall",
        "-Wextra",
    ],
    shared_libs: [
        "android.hardware.bluetooth-V1-ndk",
        "libbase",
        "libbinder_ndk",
        "libcutils",
        "libhidlbase",
        "liblog",
        "libutils",
    ],
    static_libs: [
        "android.hardware.bluetooth.async",
        "android.hardware.bluetooth.hci",
    ],
}

cc_library_static {
    name: "libbluetoothhcihalimpl",
    vendor_available: true,
    host_supported: true,
    defaults: ["android.hardware.bluetooth-service-build-defaults"],
    srcs: [
        "BluetoothHci.cpp",
    ],
}

cc_binary {
    name: "android.hardware.bluetooth-service.default",
    relative_install_path: "hw",
    init_rc: ["bluetooth-service-default.rc"],
    vintf_fragments: ["bluetooth-service-default.xml"],
    vendor: true,
    defaults: ["android.hardware.bluetooth-service-build-defaults"],
    srcs: [
        "service.cpp",
    ],
    shared_libs: [
        "android.hardware.bluetooth-V1-ndk",
        "libbase",
        "libbinder_ndk",
        "libhidlbase",
        "libutils",
        "liblog",
    ],
    static_libs: [
        "libbluetoothhcihalimpl",
    ],
}

cc_fuzz {
    name: "android.hardware.bluetooth-service.default_fuzzer",
    host_supported: true,
    defaults: ["service_fuzzer_defaults"],
    srcs: [
        "test/fuzzer.cpp",
    ],
    static_libs: [
        "android.hardware.bluetooth.async",
        "android.hardware.bluetooth.hci",
        "android.hardware.bluetooth-V1-ndk",
        "libbluetoothhcihalimpl",
        "liblog",
    ],
    fuzz_config: {
        componentid: 27441,
        cc: [
            "mylesgw@google.com",
        ],
    },
}
+194 −0
Original line number Diff line number Diff line
/*
 * Copyright 2022 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.service.default"

#include "BluetoothHci.h"

#include <cutils/properties.h>
#include <fcntl.h>
#include <netdb.h>
#include <netinet/in.h>
#include <poll.h>
#include <string.h>
#include <sys/uio.h>
#include <termios.h>

#include "log/log.h"

namespace {
int SetTerminalRaw(int fd) {
  termios terminal_settings;
  int rval = tcgetattr(fd, &terminal_settings);
  if (rval < 0) {
    return rval;
  }
  cfmakeraw(&terminal_settings);
  rval = tcsetattr(fd, TCSANOW, &terminal_settings);
  return rval;
}
}  // namespace

using namespace ::android::hardware::bluetooth::hci;
using namespace ::android::hardware::bluetooth::async;

namespace aidl::android::hardware::bluetooth::impl {

void OnDeath(void* cookie);

class BluetoothDeathRecipient {
 public:
  BluetoothDeathRecipient(BluetoothHci* hci) : mHci(hci) {}

  void LinkToDeath(const std::shared_ptr<IBluetoothHciCallbacks>& cb) {
    mCb = cb;
    clientDeathRecipient_ = AIBinder_DeathRecipient_new(OnDeath);
    auto linkToDeathReturnStatus = AIBinder_linkToDeath(
        mCb->asBinder().get(), clientDeathRecipient_, this /* cookie */);
    LOG_ALWAYS_FATAL_IF(linkToDeathReturnStatus != STATUS_OK,
                        "Unable to link to death recipient");
  }

  void UnlinkToDeath(const std::shared_ptr<IBluetoothHciCallbacks>& cb) {
    LOG_ALWAYS_FATAL_IF(cb != mCb, "Unable to unlink mismatched pointers");
  }

  void serviceDied() {
    if (mCb != nullptr && !AIBinder_isAlive(mCb->asBinder().get())) {
      ALOGE("Bluetooth remote service has died");
    } else {
      ALOGE("BluetoothDeathRecipient::serviceDied called but service not dead");
      return;
    }
    has_died_ = true;
    mHci->close();
  }
  BluetoothHci* mHci;
  std::shared_ptr<IBluetoothHciCallbacks> mCb;
  AIBinder_DeathRecipient* clientDeathRecipient_;
  bool getHasDied() const { return has_died_; }

 private:
  bool has_died_;
};

void OnDeath(void* cookie) {
  auto* death_recipient = static_cast<BluetoothDeathRecipient*>(cookie);
  death_recipient->serviceDied();
}

BluetoothHci::BluetoothHci(const std::string& dev_path) {
  char property_bytes[PROPERTY_VALUE_MAX];
  property_get("vendor.ser.bt-uart", property_bytes, dev_path.c_str());
  mDevPath = std::string(property_bytes);
  mDeathRecipient = std::make_shared<BluetoothDeathRecipient>(this);
}

ndk::ScopedAStatus BluetoothHci::initialize(
    const std::shared_ptr<IBluetoothHciCallbacks>& cb) {
  ALOGI(__func__);

  mFd = open(mDevPath.c_str(), O_RDWR);
  if (mFd < 0) {
    ALOGE("Could not connect to bt: %s (%s)", mDevPath.c_str(),
          strerror(errno));
    return ndk::ScopedAStatus::fromServiceSpecificError(STATUS_BAD_VALUE);
  }
  if (int ret = SetTerminalRaw(mFd) < 0) {
    ALOGE("Could not make %s a raw terminal %d(%s)", mDevPath.c_str(), ret,
          strerror(errno));
    return ndk::ScopedAStatus::fromServiceSpecificError(STATUS_BAD_VALUE);
  }

  mCb = cb;
  if (mCb == nullptr) {
    ALOGE("cb == nullptr! -> Unable to call initializationComplete(ERR)");
    return ndk::ScopedAStatus::fromServiceSpecificError(STATUS_BAD_VALUE);
  }

  mDeathRecipient->LinkToDeath(mCb);

  auto init_ret = cb->initializationComplete(Status::SUCCESS);
  if (!init_ret.isOk()) {
    if (!mDeathRecipient->getHasDied()) {
      ALOGE("Error sending init callback, but no death notification.");
    }
    return ndk::ScopedAStatus::fromServiceSpecificError(
        STATUS_FAILED_TRANSACTION);
  }
  mH4 = std::make_shared<H4Protocol>(
      mFd,
      [](const std::vector<uint8_t>& /* raw_command */) {
        LOG_ALWAYS_FATAL("Unexpected command!");
      },
      [this](const std::vector<uint8_t>& raw_event) {
        mCb->hciEventReceived(raw_event);
      },
      [this](const std::vector<uint8_t>& raw_acl) {
        mCb->hciEventReceived(raw_acl);
      },
      [this](const std::vector<uint8_t>& raw_sco) {
        mCb->hciEventReceived(raw_sco);
      },
      [this](const std::vector<uint8_t>& raw_iso) {
        mCb->hciEventReceived(raw_iso);
      },
      [this]() {
        ALOGI("HCI socket device disconnected");
        mFdWatcher.StopWatchingFileDescriptors();
      });
  mFdWatcher.WatchFdForNonBlockingReads(mFd,
                                        [this](int) { mH4->OnDataReady(); });
  return ndk::ScopedAStatus::ok();
}

ndk::ScopedAStatus BluetoothHci::close() {
  ALOGI(__func__);
  mFdWatcher.StopWatchingFileDescriptors();
  ::close(mFd);

  return ndk::ScopedAStatus::ok();
}

ndk::ScopedAStatus BluetoothHci::sendHciCommand(
    const std::vector<uint8_t>& packet) {
  send(PacketType::COMMAND, packet);
  return ndk::ScopedAStatus::ok();
}

ndk::ScopedAStatus BluetoothHci::sendAclData(
    const std::vector<uint8_t>& packet) {
  send(PacketType::ACL_DATA, packet);
  return ndk::ScopedAStatus::ok();
}

ndk::ScopedAStatus BluetoothHci::sendScoData(
    const std::vector<uint8_t>& packet) {
  send(PacketType::SCO_DATA, packet);
  return ndk::ScopedAStatus::ok();
}

ndk::ScopedAStatus BluetoothHci::sendIsoData(
    const std::vector<uint8_t>& packet) {
  send(PacketType::ISO_DATA, packet);
  return ndk::ScopedAStatus::ok();
}

void BluetoothHci::send(PacketType type, const std::vector<uint8_t>& v) {
  mH4->Send(type, v);
}

}  // namespace aidl::android::hardware::bluetooth::impl
+71 −0
Original line number Diff line number Diff line
/*
 * Copyright 2022 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.
 */

#pragma once

#include <aidl/android/hardware/bluetooth/BnBluetoothHci.h>
#include <aidl/android/hardware/bluetooth/IBluetoothHciCallbacks.h>
#include <log/log.h>

#include <string>

#include "async_fd_watcher.h"
#include "h4_protocol.h"

namespace aidl::android::hardware::bluetooth::impl {

class BluetoothDeathRecipient;

// This Bluetooth HAL implementation connects with a serial port at dev_path_.
class BluetoothHci : public BnBluetoothHci {
 public:
  BluetoothHci(const std::string& dev_path = "/dev/hvc5");

  ndk::ScopedAStatus initialize(
      const std::shared_ptr<IBluetoothHciCallbacks>& cb) override;

  ndk::ScopedAStatus sendHciCommand(
      const std::vector<uint8_t>& packet) override;

  ndk::ScopedAStatus sendAclData(const std::vector<uint8_t>& packet) override;

  ndk::ScopedAStatus sendScoData(const std::vector<uint8_t>& packet) override;

  ndk::ScopedAStatus sendIsoData(const std::vector<uint8_t>& packet) override;

  ndk::ScopedAStatus close() override;

  static void OnPacketReady();

  static BluetoothHci* get();

 private:
  int mFd{-1};
  std::shared_ptr<IBluetoothHciCallbacks> mCb = nullptr;

  std::shared_ptr<::android::hardware::bluetooth::hci::H4Protocol> mH4;

  std::shared_ptr<BluetoothDeathRecipient> mDeathRecipient;

  std::string mDevPath;

  ::android::hardware::bluetooth::async::AsyncFdWatcher mFdWatcher;

  void send(::android::hardware::bluetooth::hci::PacketType type,
            const std::vector<uint8_t>& packet);
};

}  // namespace aidl::android::hardware::bluetooth::impl
+6 −0
Original line number Diff line number Diff line
service bluetooth_hal_service /vendor/bin/hw/android.hardware.bluetooth-service.default
    class hal
    capabilities BLOCK_SUSPEND NET_ADMIN SYS_NICE
    user bluetooth
    group bluetooth
    task_profiles HighPerformance
+6 −0
Original line number Diff line number Diff line
<manifest version="1.0" type="device">
    <hal format="aidl">
        <name>android.hardware.bluetooth</name>
        <fqname>IBluetoothHci/default</fqname>
    </hal>
</manifest>
Loading