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

Commit eae3a797 authored by Hansong Zhang's avatar Hansong Zhang
Browse files

Revert "Revert "Cert for HAL adapter""

This reverts commit c5856032.

Reason for revert: Re-landing CL I3cf2f54605ce2709d1c149b1221dedc8dc5dca92

Change-Id: I63d60ab99d3a4a1b369f77d6c48eff0f463506e4
parent c5856032
Loading
Loading
Loading
Loading
+123 −1
Original line number Diff line number Diff line
@@ -101,7 +101,90 @@ cc_library {
        "stack_manager.cc",
        ":BluetoothCommonSources",
        ":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 {
@@ -203,3 +286,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