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

Commit 7bdb9a88 authored by Hansong Zhang's avatar Hansong Zhang
Browse files

Remove unused HCI cert

Test: cert/run_cert.sh
Change-Id: I48ce5068ea6f41b053ea5ac2be0441fbd44bca88
parent e757eeb2
Loading
Loading
Loading
Loading
+0 −8
Original line number Diff line number Diff line
@@ -182,7 +182,6 @@ cc_binary {
        "cert/grpc_root_server.cc",
        "cert/read_only_property_server.cc",
        "grpc/grpc_module.cc",
        ":BluetoothCertSource_hci_layer",
        ":BluetoothCertSource_l2cap_layer",
    ],
    generated_headers: [
@@ -542,8 +541,6 @@ genrule {
        "neighbor/facade/facade_pb2_grpc.py",
        "neighbor/facade/facade_pb2.py",
        "hci/cert/__init__.py",
        "hci/cert/api_pb2_grpc.py",
        "hci/cert/api_pb2.py",
        "l2cap/classic/cert/__init__.py",
        "l2cap/classic/cert/api_pb2_grpc.py",
        "l2cap/classic/cert/api_pb2.py",
@@ -557,7 +554,6 @@ filegroup {
    name: "BluetoothCertStackProto",
    srcs: [
        "cert/rootservice.proto",
        "hci/cert/api.proto",
        "l2cap/classic/cert/api.proto",
    ],
}
@@ -578,8 +574,6 @@ genrule {
        "cert/rootservice.pb.h",
        "facade/common.grpc.pb.h",
        "facade/common.pb.h",
        "hci/cert/api.grpc.pb.h",
        "hci/cert/api.pb.h",
        "l2cap/classic/cert/api.grpc.pb.h",
        "l2cap/classic/cert/api.pb.h",
    ],
@@ -601,8 +595,6 @@ genrule {
        "cert/rootservice.pb.cc",
        "facade/common.grpc.pb.cc",
        "facade/common.pb.cc",
        "hci/cert/api.grpc.pb.cc",
        "hci/cert/api.pb.cc",
        "l2cap/classic/cert/api.grpc.pb.cc",
        "l2cap/classic/cert/api.pb.cc",
    ],
+0 −2
Original line number Diff line number Diff line
@@ -18,7 +18,6 @@ from gd_device_base import GdDeviceBase
from gd_device_base import replace_vars

from cert import rootservice_pb2_grpc as cert_rootservice_pb2_grpc
from hci.cert import api_pb2_grpc as hci_cert_pb2_grpc
from l2cap.classic.cert import api_pb2_grpc as l2cap_cert_pb2_grpc

ACTS_CONTROLLER_CONFIG_NAME = "GdCertDevice"
@@ -70,6 +69,5 @@ class GdCertDevice(GdDeviceBase):
            self.grpc_root_server_channel)
        self.controller_read_only_property = cert_rootservice_pb2_grpc.ReadOnlyPropertyStub(
            self.grpc_channel)
        self.hci = hci_cert_pb2_grpc.AclManagerCertStub(self.grpc_channel)
        self.l2cap = l2cap_cert_pb2_grpc.L2capClassicModuleCertStub(
            self.grpc_channel)
+0 −5
Original line number Diff line number Diff line
@@ -21,7 +21,6 @@
#include "cert/read_only_property_server.h"
#include "cert/rootservice.grpc.pb.h"
#include "grpc/grpc_module.h"
#include "hci/cert/cert.h"
#include "l2cap/classic/cert/cert.h"
#include "os/log.h"
#include "os/thread.h"
@@ -49,10 +48,6 @@ class RootCertService : public ::bluetooth::cert::RootCert::Service {

    BluetoothModule module_to_test = request->module_to_test();
    switch (module_to_test) {
      case BluetoothModule::HCI:
        modules.add<::bluetooth::cert::ReadOnlyPropertyServerModule>();
        modules.add<::bluetooth::hci::cert::AclManagerCertModule>();
        break;
      case BluetoothModule::L2CAP:
        modules.add<::bluetooth::cert::ReadOnlyPropertyServerModule>();
        modules.add<::bluetooth::l2cap::classic::cert::L2capClassicModuleCertModule>();
+0 −7
Original line number Diff line number Diff line
@@ -47,13 +47,6 @@ filegroup {
    ],
}

filegroup {
    name: "BluetoothCertSource_hci_layer",
    srcs: [
        "cert/cert.cc",
    ],
}

filegroup {
    name: "BluetoothHciFuzzTestSources",
    srcs: [
+0 −319
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 "hci/cert/cert.h"

#include <condition_variable>
#include <memory>
#include <mutex>
#include <set>

#include "common/blocking_queue.h"
#include "grpc/grpc_event_queue.h"
#include "hci/cert/api.grpc.pb.h"
#include "hci/classic_security_manager.h"
#include "hci/controller.h"
#include "hci/hci_layer.h"
#include "hci/hci_packets.h"
#include "os/queue.h"
#include "packet/raw_builder.h"

using ::grpc::ServerAsyncResponseWriter;
using ::grpc::ServerAsyncWriter;
using ::grpc::ServerContext;

using ::bluetooth::common::Bind;
using ::bluetooth::common::BindOnce;
using ::bluetooth::packet::RawBuilder;

namespace bluetooth {
namespace hci {
namespace cert {

class AclManagerCertService : public AclManagerCert::Service {
 public:
  AclManagerCertService(Controller* controller, HciLayer* hci_layer, ::bluetooth::os::Handler* facade_handler)
      : controller_(controller), hci_layer_(hci_layer), handler_(facade_handler),
        acl_queue_end_(hci_layer_->GetAclQueueEnd()) {
    hci_layer_->RegisterEventHandler(EventCode::CONNECTION_COMPLETE,
                                     Bind(&AclManagerCertService::on_connection_complete, common::Unretained(this)),
                                     handler_);
    hci_layer_->RegisterEventHandler(EventCode::DISCONNECTION_COMPLETE,
                                     Bind(&AclManagerCertService::on_disconnection_complete, common::Unretained(this)),
                                     handler_);
    hci_layer_->RegisterEventHandler(EventCode::CONNECTION_REQUEST,
                                     Bind(&AclManagerCertService::on_incoming_connection, common::Unretained(this)),
                                     handler_);
    hci_layer_->RegisterEventHandler(
        EventCode::CONNECTION_PACKET_TYPE_CHANGED,
        Bind(&AclManagerCertService::on_connection_packet_type_changed, common::Unretained(this)), handler_);
    hci_layer_->RegisterEventHandler(EventCode::QOS_SETUP_COMPLETE,
                                     Bind(&AclManagerCertService::on_qos_setup_complete, common::Unretained(this)),
                                     handler_);
    hci_layer_->RegisterEventHandler(EventCode::ROLE_CHANGE,
                                     Bind(&AclManagerCertService::on_role_change, common::Unretained(this)), handler_);

    controller_->RegisterCompletedAclPacketsCallback(common::Bind([](uint16_t, uint16_t) { /* TODO check */ }),
                                                     handler_);
    acl_queue_end_->RegisterDequeue(handler_,
                                    Bind(&AclManagerCertService::on_incoming_packet, common::Unretained(this)));
  }

  void on_incoming_packet() {
    auto packet = acl_queue_end_->TryDequeue();
    ASSERT(packet->IsValid());
    AclData acl_data;
    if (connected_devices_.find(packet->GetHandle()) == connected_devices_.end()) {
      LOG_ERROR("Can't find remote device");
      return;
    }
    auto address = connected_devices_[packet->GetHandle()];
    acl_data.mutable_remote()->set_address(address.ToString());
    std::string data = std::string(packet->begin(), packet->end());
    acl_data.set_payload(data);
    pending_acl_data_.OnIncomingEvent(acl_data);
  }

  ~AclManagerCertService() {
    acl_queue_end_->UnregisterDequeue();
    hci_layer_->UnregisterEventHandler(EventCode::CONNECTION_REQUEST);
    hci_layer_->UnregisterEventHandler(EventCode::DISCONNECTION_COMPLETE);
    hci_layer_->UnregisterEventHandler(EventCode::CONNECTION_COMPLETE);
  }

  void on_connection_complete(EventPacketView packet) {
    ConnectionCompleteView connection_complete = ConnectionCompleteView::Create(std::move(packet));
    ASSERT(connection_complete.IsValid());
    auto status = connection_complete.GetStatus();
    auto address = connection_complete.GetBdAddr();
    auto handle = connection_complete.GetConnectionHandle();
    if (status == ErrorCode::SUCCESS) {
      connected_devices_.emplace(handle, address);
      ConnectionEvent event;
      event.mutable_remote()->set_address(address.ToString());
      pending_connection_complete_.OnIncomingEvent(event);
    } else {
      ConnectionFailedEvent event;
      event.mutable_remote()->set_address(address.ToString());
      event.set_reason(static_cast<uint32_t>(connection_complete.GetStatus()));
      pending_connection_failed_.OnIncomingEvent(event);
    }
  }

  void on_disconnection_complete(EventPacketView packet) {
    DisconnectionCompleteView disconnection_complete = DisconnectionCompleteView::Create(std::move(packet));
    ASSERT(disconnection_complete.IsValid());
    auto status = disconnection_complete.GetStatus();
    auto handle = disconnection_complete.GetConnectionHandle();
    auto device = connected_devices_.find(handle);

    ASSERT(device != connected_devices_.end());
    auto address = device->second;
    if (status == ErrorCode::SUCCESS) {
      connected_devices_.erase(handle);
      DisconnectionEvent event;
      event.mutable_remote()->set_address(address.ToString());
      event.set_reason(static_cast<uint32_t>(disconnection_complete.GetReason()));
      pending_disconnection_.OnIncomingEvent(event);
    }
  }

  void on_incoming_connection(EventPacketView packet) {
    ConnectionRequestView request = ConnectionRequestView::Create(packet);
    ASSERT(request.IsValid());
    Address address = request.GetBdAddr();
    if (accepted_devices_.find(address) != accepted_devices_.end()) {
      auto role = AcceptConnectionRequestRole::BECOME_MASTER;  // We prefer to be master
      hci_layer_->EnqueueCommand(AcceptConnectionRequestBuilder::Create(address, role),
                                 common::BindOnce([](CommandStatusView status) { /* TODO: check? */ }), handler_);
    } else {
      auto reason = RejectConnectionReason::LIMITED_RESOURCES;
      auto builder = RejectConnectionRequestBuilder::Create(address, reason);
      hci_layer_->EnqueueCommand(std::move(builder), BindOnce([](CommandStatusView status) { /* TODO: check? */ }),
                                 handler_);
    }
  }

  void on_connection_packet_type_changed(EventPacketView packet) { /*TODO*/
  }

  void on_qos_setup_complete(EventPacketView packet) { /*TODO*/
  }

  void on_role_change(EventPacketView packet) { /*TODO*/
  }

  ::grpc::Status SetPageScanMode(::grpc::ServerContext* context, const ::bluetooth::hci::cert::PageScanMode* request,
                                 ::google::protobuf::Empty* response) override {
    ScanEnable scan_enable = request->enabled() ? ScanEnable::PAGE_SCAN_ONLY : ScanEnable::NO_SCANS;
    std::promise<void> promise;
    auto future = promise.get_future();
    hci_layer_->EnqueueCommand(
        WriteScanEnableBuilder::Create(scan_enable),
        common::BindOnce([](std::promise<void> promise, CommandCompleteView) { promise.set_value(); },
                         std::move(promise)),
        handler_);
    future.wait();
    return ::grpc::Status::OK;
  }

  ::grpc::Status SetIncomingConnectionPolicy(::grpc::ServerContext* context,
                                             const ::bluetooth::hci::cert::IncomingConnectionPolicy* request,
                                             ::google::protobuf::Empty* response) override {
    std::unique_lock<std::mutex> lock(mutex_);
    Address peer;
    ASSERT(Address::FromString(request->remote().address(), peer));
    if (request->accepted()) {
      accepted_devices_.insert(peer);
    } else {
      accepted_devices_.erase(peer);
    }
    return ::grpc::Status::OK;
  }

  ::grpc::Status Connect(::grpc::ServerContext* context, const facade::BluetoothAddress* remote,
                         ::google::protobuf::Empty* response) override {
    std::unique_lock<std::mutex> lock(mutex_);

    uint16_t packet_type = 0x4408 /* DM 1,3,5 */ | 0x8810 /*DH 1,3,5 */;
    PageScanRepetitionMode page_scan_repetition_mode = PageScanRepetitionMode::R1;
    uint16_t clock_offset = 0;
    ClockOffsetValid clock_offset_valid = ClockOffsetValid::INVALID;
    CreateConnectionRoleSwitch allow_role_switch = CreateConnectionRoleSwitch::ALLOW_ROLE_SWITCH;

    Address peer;
    ASSERT(Address::FromString(remote->address(), peer));
    std::unique_ptr<CreateConnectionBuilder> packet = CreateConnectionBuilder::Create(
        peer, packet_type, page_scan_repetition_mode, clock_offset, clock_offset_valid, allow_role_switch);

    hci_layer_->EnqueueCommand(std::move(packet), common::BindOnce([](CommandStatusView status) {
                                 ASSERT(status.IsValid());
                                 ASSERT(status.GetCommandOpCode() == OpCode::CREATE_CONNECTION);
                               }),
                               handler_);

    return ::grpc::Status::OK;
  }

  ::grpc::Status Disconnect(::grpc::ServerContext* context, const facade::BluetoothAddress* request,
                            ::google::protobuf::Empty* response) override {
    std::unique_lock<std::mutex> lock(mutex_);
    Address peer;
    Address::FromString(request->address(), peer);
    uint16_t handle = find_connected_device_handle_by_address(peer);
    if (handle == kInvalidHandle) {
      return ::grpc::Status(::grpc::StatusCode::INVALID_ARGUMENT, "Invalid address");
    }

    DisconnectReason reason = DisconnectReason::REMOTE_USER_TERMINATED_CONNECTION;
    std::unique_ptr<DisconnectBuilder> packet = DisconnectBuilder::Create(handle, reason);
    hci_layer_->EnqueueCommand(std::move(packet), BindOnce([](CommandStatusView status) { /* TODO: check? */ }),
                               handler_);
    return ::grpc::Status::OK;
  }

  ::grpc::Status SendAclData(::grpc::ServerContext* context, const AclData* request,
                             ::google::protobuf::Empty* response) override {
    Address peer;
    Address::FromString(request->remote().address(), peer);
    auto handle = find_connected_device_handle_by_address(peer);
    if (handle == kInvalidHandle) {
      return ::grpc::Status(::grpc::StatusCode::INVALID_ARGUMENT, "Invalid address");
    }

    constexpr PacketBoundaryFlag packet_boundary_flag = PacketBoundaryFlag::FIRST_AUTOMATICALLY_FLUSHABLE;
    constexpr BroadcastFlag broadcast_flag = BroadcastFlag::POINT_TO_POINT;
    std::unique_ptr<RawBuilder> packet = std::make_unique<RawBuilder>();
    auto req_string = request->payload();
    packet->AddOctets(std::vector<uint8_t>(req_string.begin(), req_string.end()));
    auto acl_packet = AclPacketBuilder::Create(handle, packet_boundary_flag, broadcast_flag, std::move(packet));
    acl_enqueue_buffer_.Enqueue(std::move(acl_packet), handler_);
    return ::grpc::Status::OK;
  }

  ::grpc::Status FetchAclData(::grpc::ServerContext* context, const ::google::protobuf::Empty* request,
                              ::grpc::ServerWriter<AclData>* writer) override {
    return pending_acl_data_.RunLoop(context, writer);
  }

  ::grpc::Status FetchConnectionComplete(::grpc::ServerContext* context, const ::google::protobuf::Empty* request,
                                         ::grpc::ServerWriter<ConnectionEvent>* writer) override {
    return pending_connection_complete_.RunLoop(context, writer);
  };

  ::grpc::Status FetchConnectionFailed(::grpc::ServerContext* context, const ::google::protobuf::Empty* request,
                                       ::grpc::ServerWriter<ConnectionFailedEvent>* writer) override {
    return pending_connection_failed_.RunLoop(context, writer);
  };

  ::grpc::Status FetchDisconnection(::grpc::ServerContext* context, const ::google::protobuf::Empty* request,
                                    ::grpc::ServerWriter<DisconnectionEvent>* writer) override {
    return pending_disconnection_.RunLoop(context, writer);
  }

 private:
  Controller* controller_;
  HciLayer* hci_layer_;
  ::bluetooth::os::Handler* handler_;
  common::BidiQueueEnd<AclPacketBuilder, AclPacketView>* acl_queue_end_;
  os::EnqueueBuffer<AclPacketBuilder> acl_enqueue_buffer_{acl_queue_end_};
  mutable std::mutex mutex_;
  std::set<Address> accepted_devices_;
  std::map<uint16_t /* handle */, Address> connected_devices_;
  ::bluetooth::grpc::GrpcEventQueue<AclData> pending_acl_data_{"FetchAclData"};
  ::bluetooth::grpc::GrpcEventQueue<ConnectionEvent> pending_connection_complete_{"FetchConnectionComplete"};
  ::bluetooth::grpc::GrpcEventQueue<ConnectionFailedEvent> pending_connection_failed_{"FetchConnectionFailed"};
  ::bluetooth::grpc::GrpcEventQueue<DisconnectionEvent> pending_disconnection_{"FetchDisconnection"};

  constexpr static uint16_t kInvalidHandle = 0xffff;

  uint16_t find_connected_device_handle_by_address(Address address) {
    for (auto device : connected_devices_) {
      if (device.second == address) {
        return device.first;
      }
    }
    return kInvalidHandle;  // Can't find
  }
};

void AclManagerCertModule::ListDependencies(ModuleList* list) {
  ::bluetooth::grpc::GrpcFacadeModule::ListDependencies(list);
  list->add<Controller>();
  list->add<HciLayer>();
  list->add<ClassicSecurityManager>();
}

void AclManagerCertModule::Start() {
  ::bluetooth::grpc::GrpcFacadeModule::Start();
  service_ = new AclManagerCertService(GetDependency<Controller>(), GetDependency<HciLayer>(), GetHandler());
}

void AclManagerCertModule::Stop() {
  delete service_;
  ::bluetooth::grpc::GrpcFacadeModule::Stop();
}

::grpc::Service* AclManagerCertModule::GetService() const {
  return service_;
}

const ModuleFactory AclManagerCertModule::Factory =
    ::bluetooth::ModuleFactory([]() { return new AclManagerCertModule(); });

}  // namespace cert
}  // namespace hci
}  // namespace bluetooth
Loading