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

Commit 0a5e8c8f authored by Treehugger Robot's avatar Treehugger Robot Committed by Gerrit Code Review
Browse files

Merge "Initial entry for headless"

parents 9b3ed2a1 eb2e0fdc
Loading
Loading
Loading
Loading
+55 −0
Original line number Diff line number Diff line
cc_test {
    name: "bt_headless",
    test_suites: ["device-tests"],
    defaults: ["fluoride_defaults"],
    srcs: [
        "get_options.cc",
        "headless.cc",
        "sdp/main.cc",
    ],
    include_dirs: [
        "packages/modules/Bluetooth/system",
        "packages/modules/Bluetooth/system/stack/include",
    ],
    whole_static_libs: [
        "libbtcore",
    ],
    static_libs: [
        "libFraunhoferAAC",
        "libbluetooth_gd",
        "libbt-bta",
        "libbt-common",
        "libbt-hci",
        "libbt-protos-lite",
        "libbt-sbc-decoder",
        "libbt-sbc-encoder",
        "libbt-stack",
        "libbt-utils",
        "libbtdevice",
        "libbte",
        "libbtif",
        "libg722codec",
        "libosi",
        "libprotobuf-cpp-lite",
        "libudrv-uipc",
        "libz",
    ],
    shared_libs: [
        "android.hardware.bluetooth.a2dp@1.0",
        "android.hardware.bluetooth.audio@2.0",
        "android.hardware.bluetooth@1.0",
        "android.hardware.bluetooth@1.1",
        "libaaudio",
        "libbase",
        "libcrypto",
        "libcutils",  // property_get_bool
        "libfmq",
        "libhidlbase",
        "libjsoncpp",
        "liblog",  // __android_log_print
        "libprocessgroup",
        "libtinyxml2",
        "libutils",
    ],
    ldflags: ["-rdynamic"],
}
+127 −0
Original line number Diff line number Diff line
/*
 * Copyright 2020 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.
 */

#include "test/headless/get_options.h"

#include <base/logging.h>
#include <getopt.h>
#include <stdio.h>
#include <unistd.h>
#include <list>
#include <string>

namespace {
constexpr struct option long_options[] = {{"device", required_argument, 0, 0},
                                          {"loop", required_argument, 0, 0},
                                          {"uuid", required_argument, 0, 0},
                                          {0, 0, 0, 0}};

enum OptionType {
  kOptionDevice = 0,
  kOptionLoop = 1,
  kOptionUuid = 2,
};

}  // namespace

void bluetooth::test::headless::GetOpt::ParseValue(
    char* optarg, std::list<std::string>& string_list) {
  CHECK(optarg != nullptr);
  char* p = optarg;
  char* pp = optarg;
  while (*p != '\0') {
    if (*p == ',') {
      *p = 0;
      string_list.push_back(std::string(pp));
      pp = p + 1;
    }
    p++;
  }
  if (pp != p) string_list.push_back(std::string(pp));
}

void bluetooth::test::headless::GetOpt::ProcessOption(int option_index,
                                                      char* optarg) {
  std::list<std::string> string_list;
  OptionType option_type = static_cast<OptionType>(option_index);

  if (!optarg) return;
  switch (option_type) {
    case kOptionDevice:
      ParseValue(optarg, string_list);
      for (auto& entry : string_list) {
        if (RawAddress::IsValidAddress(entry)) {
          RawAddress address;
          RawAddress::FromString(entry, address);
          device_.push_back(address);
        }
      }
      break;
    case kOptionLoop:
      loop_ = std::stoul(optarg, nullptr, 0);
      break;
    case kOptionUuid:
      ParseValue(optarg, string_list);
      for (auto& entry : string_list) {
        uuid_.push_back(
            bluetooth::Uuid::From16Bit(std::stoul(entry.c_str(), nullptr, 0)));
      }
      break;
    default:
      fflush(nullptr);
      valid_ = false;
      return;
      break;
  }
}

bluetooth::test::headless::GetOpt::GetOpt(int argc, char** argv)
    : name_(argv[0]) {
  while (1) {
    int option_index = 0;
    int c = getopt_long_only(argc, argv, "d:l:u:", long_options, &option_index);
    if (c == -1) break;

    switch (c) {
      case 0:
        ProcessOption(static_cast<OptionType>(option_index), optarg);
        break;
      case '?':
        Usage();
        valid_ = false;
        return;
      default:
        printf("?? getopt returned character code 0%o ??\n", c);
    }
  }

  if (optind < argc) {
    printf("non-option ARGV-elements: ");
    while (optind < argc) printf("%s ", argv[optind++]);
    printf("\n");
    valid_ = false;
  }
  fflush(nullptr);
}

void bluetooth::test::headless::GetOpt::Usage() const {
  printf("%s: Usage:\n", name_);
  printf("%s  --device=<device,>  Comma separated list of remote devices\n",
         name_);
  printf("%s  --uuid=<uuid,>      Comma separated list of uuids\n", name_);
  printf("%s  --loop=<loop>       Number of loops\n", name_);
  fflush(nullptr);
}
+49 −0
Original line number Diff line number Diff line
/*
 * Copyright 2020 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 <cstddef>
#include <list>
#include "types/bluetooth/uuid.h"
#include "types/raw_address.h"

namespace bluetooth {
namespace test {
namespace headless {

class GetOpt {
 public:
  GetOpt(int argc, char** arv);
  virtual ~GetOpt() = default;

  virtual void Usage() const;
  virtual bool IsValid() const { return valid_; };

  std::list<RawAddress> device_;
  std::list<bluetooth::Uuid> uuid_;
  int loop_;

 private:
  void ParseValue(char* optarg, std::list<std::string>& my_list);
  void ProcessOption(int option_index, char* optarg);
  const char* name_{nullptr};
  bool valid_{true};
};

}  // namespace headless
}  // namespace test
}  // namespace bluetooth
+173 −0
Original line number Diff line number Diff line
/*
 * Copyright 2020 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 "bt_headless"

#include <dlfcn.h>  //  dlopen

#include "base/logging.h"  // LOG() stdout and android log
#include "include/hardware/bluetooth.h"
#include "osi/include/log.h"  // android log only
#include "test/headless/headless.h"

extern bt_interface_t bluetoothInterface;

using namespace bluetooth::test::headless;

namespace {
std::mutex adapter_state_mutex_;
std::condition_variable adapter_state_cv_;
bt_state_t bt_state_{BT_STATE_OFF};

void adapter_state_changed(bt_state_t state) {
  std::unique_lock<std::mutex> lck(adapter_state_mutex_);
  bt_state_ = state;
  adapter_state_cv_.notify_all();
}
void adapter_properties(bt_status_t status, int num_properties,
                        bt_property_t* properties) {
  LOG_INFO(LOG_TAG, "%s", __func__);
}

void remote_device_properties(bt_status_t status, RawAddress* bd_addr,
                              int num_properties, bt_property_t* properties) {
  LOG_INFO(LOG_TAG, "%s", __func__);
}

void device_found(int num_properties, bt_property_t* properties) {
  LOG_INFO(LOG_TAG, "%s", __func__);
}

void discovery_state_changed(bt_discovery_state_t state) {
  LOG_INFO(LOG_TAG, "%s", __func__);
}

/** Bluetooth Legacy PinKey Request callback */
void pin_request(RawAddress* remote_bd_addr, bt_bdname_t* bd_name, uint32_t cod,
                 bool min_16_digit) {
  LOG_INFO(LOG_TAG, "%s", __func__);
}

void ssp_request(RawAddress* remote_bd_addr, bt_bdname_t* bd_name, uint32_t cod,
                 bt_ssp_variant_t pairing_variant, uint32_t pass_key) {
  LOG_INFO(LOG_TAG, "%s", __func__);
}

/** Bluetooth Bond state changed callback */
/* Invoked in response to create_bond, cancel_bond or remove_bond */
void bond_state_changed(bt_status_t status, RawAddress* remote_bd_addr,
                        bt_bond_state_t state) {
  LOG_INFO(LOG_TAG, "%s", __func__);
}

/** Bluetooth ACL connection state changed callback */
void acl_state_changed(bt_status_t status, RawAddress* remote_bd_addr,
                       bt_acl_state_t state) {
  LOG_INFO(LOG_TAG, "%s", __func__);
}

void thread_event(bt_cb_thread_evt evt) { LOG_INFO(LOG_TAG, "%s", __func__); }

void dut_mode_recv(uint16_t opcode, uint8_t* buf, uint8_t len) {
  LOG_INFO(LOG_TAG, "%s", __func__);
}

void le_test_mode(bt_status_t status, uint16_t num_packets) {
  LOG_INFO(LOG_TAG, "%s", __func__);
}

void energy_info(bt_activity_energy_info* energy_info,
                 bt_uid_traffic_t* uid_data) {
  LOG_INFO(LOG_TAG, "%s", __func__);
}

bt_callbacks_t bt_callbacks{
    /** set to sizeof(bt_callbacks_t) */
    .size = sizeof(bt_callbacks_t),
    .adapter_state_changed_cb = adapter_state_changed,
    .adapter_properties_cb = adapter_properties,
    .remote_device_properties_cb = remote_device_properties,
    .device_found_cb = device_found,
    .discovery_state_changed_cb = discovery_state_changed,
    .pin_request_cb = pin_request,
    .ssp_request_cb = ssp_request,
    .bond_state_changed_cb = bond_state_changed,
    .acl_state_changed_cb = acl_state_changed,
    .thread_evt_cb = thread_event,
    .dut_mode_recv_cb = dut_mode_recv,
    .le_test_mode_cb = le_test_mode,
    .energy_info_cb = energy_info,
};
// HAL HARDWARE CALLBACKS

// OS CALLOUTS
bool set_wake_alarm_co(uint64_t delay_millis, bool should_wake, alarm_cb cb,
                       void* data) {
  LOG_INFO(LOG_TAG, "%s", __func__);
  return true;
}
int acquire_wake_lock_co(const char* lock_name) {
  LOG_INFO(LOG_TAG, "%s", __func__);
  return 1;
}

int release_wake_lock_co(const char* lock_name) {
  LOG_INFO(LOG_TAG, "%s", __func__);
  return 0;
}

bt_os_callouts_t bt_os_callouts{
    .size = sizeof(bt_os_callouts_t),
    .set_wake_alarm = set_wake_alarm_co,
    .acquire_wake_lock = acquire_wake_lock_co,
    .release_wake_lock = release_wake_lock_co,
};
}  // namespace

void Headless::SetUp() {
  LOG(INFO) << __func__ << " Entry";

  int status = bluetoothInterface.init(&bt_callbacks, false, false);
  (status == BT_STATUS_SUCCESS)
      ? LOG(INFO) << __func__ << " Initialized bluetooth callbacks"
      : LOG(FATAL) << "Failed to initialize Bluetooth stack";

  status = bluetoothInterface.set_os_callouts(&bt_os_callouts);
  (status == BT_STATUS_SUCCESS)
      ? LOG(INFO) << __func__ << " Initialized os callouts"
      : LOG(ERROR) << "Failed to set up Bluetooth OS callouts";

  bluetoothInterface.enable();
  LOG_INFO(LOG_TAG, "%s Headless stack has enabled", __func__);

  std::unique_lock<std::mutex> lck(adapter_state_mutex_);
  while (bt_state_ != BT_STATE_ON) adapter_state_cv_.wait(lck);
  LOG_INFO(LOG_TAG, "%s Headless stack is operational", __func__);
}

void Headless::TearDown() {
  LOG_INFO(LOG_TAG, "Stack has disabled");
  int status = bluetoothInterface.disable();

  LOG(INFO) << __func__ << " Interface has been disabled status:" << status;

  bluetoothInterface.cleanup();
  LOG(INFO) << __func__ << " Cleaned up hal bluetooth library";

  std::unique_lock<std::mutex> lck(adapter_state_mutex_);
  while (bt_state_ != BT_STATE_OFF) adapter_state_cv_.wait(lck);
  LOG_INFO(LOG_TAG, "%s Headless stack has exited", __func__);
}
+47 −0
Original line number Diff line number Diff line
/*
 * Copyright 2020 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.
 */

namespace bluetooth {
namespace test {
namespace headless {

template <typename T>
using ExecutionUnit = std::function<T()>;

class Headless {
 public:
  Headless() = default;
  virtual ~Headless() = default;

 protected:
  virtual void SetUp();
  virtual void TearDown();
};

class Test : public Headless {
 public:
  template <typename T>
  T Run(ExecutionUnit<T> func) {
    SetUp();
    T rc = func();
    TearDown();
    return rc;
  }
};

}  // namespace headless
}  // namespace test
}  // namespace bluetooth
Loading