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

Commit 428397e8 authored by Treehugger Robot's avatar Treehugger Robot Committed by Gerrit Code Review
Browse files

Merge "Revert "Revert "Cert for HAL adapter"""

parents 3b7fc5a4 eae3a797
Loading
Loading
Loading
Loading
+123 −1
Original line number Diff line number Diff line
@@ -102,7 +102,90 @@ cc_library {
        ":BluetoothCommonSources",
        ":BluetoothHalSources",
        ":BluetoothPacketSources",
    ]
    ],
    generated_headers: [
        "BluetoothGeneratedPackets_h",
    ],
}

cc_binary {
    name: "stack_with_facade",
    defaults: [
        "gd_defaults",
    ],
    host_supported: true,
    srcs: [
        "stack_manager.cc",
        "facade/stack_with_grpc_main.cc",
        "facade/facade_manager.cc",
        ":BluetoothCertFacade_hci_hal",
    ],
    generated_headers: [
        "BluetoothGeneratedPackets_h",
        "BluetoothCertFacadeGeneratedStub_h",
    ],
    generated_sources: [
        "BluetoothCertFacadeGeneratedStub_cc",
    ],
    static_libs: [
        "libbluetooth_gd",
    ],
    shared_libs: [
        "libgrpc++_unsecure",
        "libprotobuf-cpp-full",
    ],
    target: {
        android: {
            shared_libs: [
                "android.hardware.bluetooth@1.0",
                "libhwbinder",
                "libhidlbase",
                "libhidltransport",
                "libutils",
            ],
        },
    },
    cflags: [
        "-Wno-unused-parameter",
        "-Wno-implicit-fallthrough",
        "-Wno-unused-result",
    ],
    sanitize: {
        address: true,
    },
}

cc_test {
    name: "bluetooth_cert_test",
    defaults: [
        "gd_defaults",
    ],
    host_supported: true,
    srcs: [
        ":BluetoothCertCppClient_hci_hal",
    ],
    static_libs : [
        "libbluetooth_gd",
    ],
    shared_libs: [
        "libgrpc++_unsecure",
        "libprotobuf-cpp-full",
    ],
    generated_headers: [
        "BluetoothGeneratedPackets_h",
        "BluetoothCertFacadeGeneratedStub_h",
    ],
    generated_sources: [
        "BluetoothCertFacadeGeneratedStub_cc",
    ],
    sanitize: {
        address: true,
    },
    cflags: [
        "-Wno-unused-parameter",
        "-Wno-implicit-fallthrough",
        "-Wno-unused-result",
    ],
}

cc_test {
@@ -204,3 +287,42 @@ genrule {
        "l2cap/l2cap_packets.h",
    ],
}

filegroup {
    name: "BluetoothCertFacadeProto",
    srcs: [
        "hal/facade/api.proto",
    ],
}

genrule {
    name: "BluetoothCertFacadeGeneratedStub_h",
    tools: [
        "aprotoc",
        "protoc-gen-grpc-cpp-plugin",
    ],
    cmd: "$(location aprotoc) -Ipackages/modules/Bluetooth/system/gd -Iexternal/protobuf/src --plugin=protoc-gen-grpc=$(location protoc-gen-grpc-cpp-plugin) $(in) --grpc_out=$(genDir) --cpp_out=$(genDir)",
    srcs: [
        ":BluetoothCertFacadeProto",
    ],
    out: [
        "hal/facade/api.grpc.pb.h",
        "hal/facade/api.pb.h",
    ],
}

genrule {
    name: "BluetoothCertFacadeGeneratedStub_cc",
    tools: [
        "aprotoc",
        "protoc-gen-grpc-cpp-plugin",
    ],
    cmd: "$(location aprotoc) -Ipackages/modules/Bluetooth/system/gd -Iexternal/protobuf/src --plugin=protoc-gen-grpc=$(location protoc-gen-grpc-cpp-plugin) $(in) --grpc_out=$(genDir) --cpp_out=$(genDir)",
    srcs: [
        ":BluetoothCertFacadeProto",
    ],
    out: [
        "hal/facade/api.grpc.pb.cc",
        "hal/facade/api.pb.cc",
    ],
}
+125 −0
Original line number Diff line number Diff line
#!/usr/bin/env python3
#
# Copyright 2019, 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.

import signal
import sys
import subprocess
import os
import argparse

ANDROID_BUILD_TOP = os.environ.get('ANDROID_BUILD_TOP')

if ANDROID_BUILD_TOP is None:
    print("Please lunch a target first")
    sys.exit(1)

HOST_OUT = os.environ.get('ANDROID_HOST_OUT')

BUILD_TARGETS = [
    "root-canal",
    "stack_with_facade",
    "bluetooth_cert_test",
]

SOONG_UI_BASH = "build/soong/soong_ui.bash"
ROOTCANAL = HOST_OUT + "/nativetest64/root-canal/root-canal"
STACK_WITH_FACADE = HOST_OUT + "/bin/stack_with_facade"
TEST_SUITE = HOST_OUT + "/nativetest64/bluetooth_cert_test/bluetooth_cert_test"


def _build(num_tasks):
    build_cmd = [SOONG_UI_BASH, "--make-mode"] + BUILD_TARGETS + [
        "-j" + str(num_tasks)]
    print(build_cmd)
    p = subprocess.call(build_cmd, cwd=ANDROID_BUILD_TOP, env=os.environ.copy())
    if p != 0:
        print('BUILD FAILED, return code: {0}'.format(str(p)))
        sys.exit(1)


def main():
    parser = argparse.ArgumentParser(description='Run cert tests.')
    parser.add_argument(
        '--skip-make',
        type=bool,
        nargs='?',
        dest='skip_make',
        const=-1,
        default=False,
        help='skip building and run test immediately')
    parser.add_argument(
        '-j',
        type=int,
        nargs='?',
        dest='num_tasks',
        const=-1,
        default=40,
        help='Number of tasks to run at the same time')
    parser.add_argument(
        '--rootcanal_test_port',
        nargs='?',
        dest='rootcanal_test_port',
        const=-1,
        default="6401",
        help='Rootcanal test channel port')
    parser.add_argument(
        '--rootcanal_hci_port',
        nargs='?',
        dest='rootcanal_hci_port',
        const=-1,
        default="6402",
        help='Rootcanal HCI channel port')
    parser.add_argument(
        '--rootcanal_link_layer_port',
        nargs='?',
        dest='rootcanal_link_layer_port',
        const=-1,
        default="6403",
        help='Rootcanal Link Layer device channel port')
    parser.add_argument(
        '--grpc_port',
        nargs='?',
        dest='grpc_port',
        const=-1,
        default="8899",
        help='gRPC port')
    args = parser.parse_args()
    if not args.skip_make:
        _build(args.num_tasks)
    rootcanal_args = [ROOTCANAL,
                      args.rootcanal_test_port,
                      args.rootcanal_hci_port,
                      args.rootcanal_link_layer_port]
    p_rootcanal = subprocess.Popen(rootcanal_args,
                                   cwd=ANDROID_BUILD_TOP,
                                   env=os.environ.copy())
    stack_with_facade_args = [STACK_WITH_FACADE,
                              "--port=" + args.grpc_port,
                              "--rootcanal-port=" + args.rootcanal_hci_port]
    p_stack_with_facade = subprocess.Popen(stack_with_facade_args,
                                           cwd=ANDROID_BUILD_TOP,
                                           env=os.environ.copy())
    p_test_suite = subprocess.Popen(TEST_SUITE, cwd=ANDROID_BUILD_TOP,
                                    env=os.environ.copy())
    p_test_suite.wait()
    p_stack_with_facade.send_signal(signal.SIGINT)
    p_stack_with_facade.wait()
    p_rootcanal.send_signal(signal.SIGINT)
    p_rootcanal.wait()


if __name__ == '__main__':
    main()
+108 −0
Original line number Diff line number Diff line
/*
 * Copyright 2019 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 "facade/facade_manager.h"

#include "grpc/async_grpc.h"
#include "hal/facade/facade.h"
#include "os/log.h"
#include "stack_manager.h"

using ::bluetooth::hal::HciPacket;

using ::grpc::Server;
using ::grpc::ServerBuilder;

namespace {

::bluetooth::facade::CertFacade* module_enum_to_module(const ::bluetooth::facade::FacadeManager::Module& module) {
  switch (module) {
    case ::bluetooth::facade::FacadeManager::Module::HciHal:
      return ::bluetooth::hal::facade::GetFacadeModule();
  }
  return nullptr;
}
}  // namespace

namespace bluetooth {
namespace facade {

void FacadeManager::EnableModule(Module module) {
  enabled_modules_.push_back(module);
}

void FacadeManager::StartUp() {
  StackManager::Get()->StartUp();
  LOG_INFO("%d", FacadeConfig::Get()->GetGrpcPort());
  start_server("0.0.0.0", FacadeConfig::Get()->GetGrpcPort());

  for (const auto& enabled_module : enabled_modules_) {
    auto* module = module_enum_to_module(enabled_module);
    module->StartUp(get_grpc_completion_queue());
  }
}

void FacadeManager::start_server(const std::string& address, int port) {
  std::string listening_port = address + ":" + std::to_string(port);
  ServerBuilder builder;
  builder.AddListeningPort(listening_port, ::grpc::InsecureServerCredentials());

  grpc_completion_queue_ = builder.AddCompletionQueue();
  for (const auto& enabled_module : enabled_modules_) {
    auto* module = module_enum_to_module(enabled_module);
    builder.RegisterService(module->GetModuleGrpcService());
  }

  server_ = builder.BuildAndStart();
}

void FacadeManager::ShutDown() {
  stop_server();

  for (const auto& enabled_module : enabled_modules_) {
    auto* module = module_enum_to_module(enabled_module);
    module->ShutDown();
  }

  StackManager::Get()->ShutDown();
}

void FacadeManager::stop_server() {
  server_->Shutdown();
  grpc_completion_queue_->Shutdown();
}

::grpc::ServerCompletionQueue* FacadeManager::get_grpc_completion_queue() {
  auto* queue = grpc_completion_queue_.get();
  ASSERT(queue != nullptr);
  return queue;
}

void FacadeManager::GrpcMainLoop() {
  void* tag;
  bool ok;
  while (true) {
    if (!grpc_completion_queue_->Next(&tag, &ok)) {
      LOG_INFO("gRPC is shutdown");
      break;
    }
    auto* data = static_cast<grpc::GrpcAsyncEventCallback*>(tag);
    (*data)(ok);
  }
}

}  // namespace facade
}  // namespace bluetooth
+97 −0
Original line number Diff line number Diff line
/*
 * Copyright 2019 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 <functional>
#include <list>

#include <grpc++/grpc++.h>

#include "hal/hci_hal.h"

namespace bluetooth {
namespace facade {

class FacadeConfig {
 public:
  static FacadeConfig* Get() {
    static FacadeConfig instance;
    return &instance;
  }

  void SetGrpcPort(int port) {
    grpc_port_ = port;
  }

  int GetGrpcPort() {
    return grpc_port_;
  }

 private:
  FacadeConfig() = default;
  int grpc_port_ = 8899;
};

class FacadeManager {
 public:
  enum class Module {
    HciHal,
  };

  static FacadeManager* Get() {
    static FacadeManager instance;
    return &instance;
  }

  void EnableModule(Module module);

  void StartUp();

  void ShutDown();

  // Blocks for incoming gRPC requests
  void GrpcMainLoop();

 private:
  std::unique_ptr<::grpc::Server> server_ = nullptr;
  std::unique_ptr<::grpc::ServerCompletionQueue> grpc_completion_queue_ = nullptr;
  std::list<Module> enabled_modules_;
  void start_server(const std::string& address, int port);
  void stop_server();
  ::grpc::ServerCompletionQueue* get_grpc_completion_queue();
};

// Cert facade for each layer
class CertFacade {
 public:
  virtual ~CertFacade() = default;

  // Initialize gRPC service, asynchronous request handlers, and other resources here.
  // This should be invoked after CompletionQueue is started.
  virtual void StartUp(::grpc::ServerCompletionQueue* cq) {}

  // Do the clean up here
  // This should be invoked before CompletionQueue is shutdown.
  virtual void ShutDown() {}

  // Each facade has a gRPC service that implements stubs from its api proto. The service instance should exist all
  // the time, so static storage is recommended.
  virtual ::grpc::Service* GetModuleGrpcService() const = 0;
};

}  // namespace facade
}  // namespace bluetooth
+61 −0
Original line number Diff line number Diff line
/*
 * Copyright 2019 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 "facade/facade_manager.h"
#include "hal/hci_hal_host_rootcanal.h"

#include <csignal>
#include <string>
#include <thread>

using ::bluetooth::facade::FacadeConfig;
using ::bluetooth::facade::FacadeManager;
using ::bluetooth::hal::HciHalHostRootcanalConfig;

namespace {
void interrupt_handler(int) {
  FacadeManager::Get()->ShutDown();
}
}  // namespace

// The entry point for the binary with libbluetooth + facades
int main(int argc, const char** argv) {
  signal(SIGINT, interrupt_handler);

  const std::string arg_grpc_port = "--port=";
  const std::string arg_rootcanal_port = "--rootcanal-port=";
  for (int i = 1; i < argc; i++) {
    std::string arg = argv[i];
    if (arg.find(arg_grpc_port) == 0) {
      auto port_number = arg.substr(arg_grpc_port.size());
      FacadeConfig::Get()->SetGrpcPort(std::stoi(port_number));
    }
    if (arg.find(arg_rootcanal_port) == 0) {
      auto port_number = arg.substr(arg_rootcanal_port.size());
      HciHalHostRootcanalConfig::Get()->SetPort(std::stoi(port_number));
    }
  }

  // TODO: This should be run-time configurable
  FacadeManager::Get()->EnableModule(FacadeManager::Module::HciHal);

  FacadeManager::Get()->StartUp();
  auto wait_thread = std::thread([] { FacadeManager::Get()->GrpcMainLoop(); });
  wait_thread.join();
  FacadeManager::Get()->ShutDown();

  return 0;
}
Loading