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

Commit 7a05ae5a authored by Dennis Cheng's avatar Dennis Cheng
Browse files

test_vendor_lib: Read controller properties from file.

This upload lets the controller be configured via a JSON file that
specifies the controller attributes. A default configuration is not
currently provided but will be included in a future upload. Also fixes
a few mistakes in test_channel.py.

Bug: 21586676
Change-Id: I9d0e65a9664e179ddb97664a748c766f4f8a554e
parent 68f9d23a
Loading
Loading
Loading
Loading
+5 −1
Original line number Diff line number Diff line
@@ -13,20 +13,24 @@ LOCAL_SRC_FILES := \
    src/packet.cc \
    src/packet_stream.cc \
    src/test_channel_transport.cc \
    src/vendor_manager.cc \
    src/vendor_manager.cc

# We pull in gtest because base/files/file_util.h, which is used to read the
# controller properties file, needs gtest/gtest_prod.h.
LOCAL_C_INCLUDES := \
    $(LOCAL_PATH)/include \
    $(BT_DIR) \
    $(BT_DIR)/hci/include \
    $(BT_DIR)/osi/include \
    $(BT_DIR)/stack/include \
    $(BT_DIR)/third_party/gtest/include

LOCAL_SHARED_LIBRARIES := \
    liblog \
    libchrome

LOCAL_CPP_EXTENSION := .cc
LOCAL_CFLAGS += -std=c++11
LOCAL_MODULE := test-vendor
LOCAL_MODULE_TAGS := optional
LOCAL_MODULE_CLASS := SHARED_LIBRARIES
+13 −0
Original line number Diff line number Diff line
{
  "AclDataPacketSize": "1024",
  "ScoDataPacketSize": "255",
  "NumAclDataPackets": "10",
  "NumScoDataPackets": "10",
  "Version": "4",
  "Revision": "0",
  "LmpPalVersion": "0",
  "ManufacturerName": "0",
  "LmpPalSubversion": "0",
  "MaximumPageNumber": "0",
  "BdAddress": "123456"
}
+85 −5
Original line number Diff line number Diff line
@@ -22,6 +22,8 @@
#include <vector>
#include <unordered_map>

#include "base/json/json_value_converter.h"
#include "base/time/time.h"
#include "vendor_libs/test_vendor_lib/include/command_packet.h"
#include "vendor_libs/test_vendor_lib/include/hci_transport.h"
#include "vendor_libs/test_vendor_lib/include/test_channel_transport.h"
@@ -41,25 +43,89 @@ namespace test_vendor_lib {
// "Hci" to distinguish it as a controller command.
class DualModeController {
 public:
  class Properties {
   public:
    // TODO(dennischeng): Add default initialization and use that to instantiate
    // a default configured controller if the config file is invalid or not
    // provided.
    Properties(const std::string& file_name);

    // Aggregates and returns the result for the Read Buffer Size command. This
    // result consists of the |acl_data_packet_size_|, |sco_data_packet_size_|,
    // |num_acl_data_packets_|, and |num_sco_data_packets_| properties. See the
    // Bluetooth Core Specification Version 4.2, Volume 2, Part E, Section 7.4.5
    // (page 794).
    const std::vector<std::uint8_t> GetBufferSize();

    // Aggregates and returns the Read Local Version Information result. This
    // consists of the |version_|, |revision_|, |lmp_pal_version_|,
    // |manufacturer_name_|, and |lmp_pal_subversion_|. See the Bluetooth Core
    // Specification Version 4.2, Volume 2, Part E, Section 7.4.1 (page 788).
    const std::vector<std::uint8_t> GetLocalVersionInformation();

    // Aggregates and returns the result for the Read Local Extended Features
    // command. This result contains the |maximum_page_number_| property (among
    // other things not in the Properties object). See the Bluetooth Core
    // Specification Version 4.2, Volume 2, Part E, Section 7.4.4 (page 792).
    const std::vector<std::uint8_t> GetBdAddress();

    // Returns the result for the Read BD_ADDR command. This result is the
    // |bd_address_| property. See the Bluetooth Core Specification Version
    // 4.2, Volume 2, Part E, Section 7.4.6 (page 796).
    const std::vector<std::uint8_t> GetLocalExtendedFeatures(
        std::uint8_t page_number);

    static void RegisterJSONConverter(
        base::JSONValueConverter<Properties>* converter);

   private:
    std::uint16_t acl_data_packet_size_;
    std::uint8_t sco_data_packet_size_;
    std::uint16_t num_acl_data_packets_;
    std::uint16_t num_sco_data_packets_;
    std::uint8_t version_;
    std::uint16_t revision_;
    std::uint8_t lmp_pal_version_;
    std::uint16_t manufacturer_name_;
    std::uint16_t lmp_pal_subversion_;
    std::uint8_t maximum_page_number_;
    std::vector<std::uint8_t> bd_address_;
  };

  // Sets all of the methods to be used as callbacks in the HciHandler.
  DualModeController();

  ~DualModeController() = default;

  // Preprocesses the command, primarily checking testh channel hooks. If
  // possible, dispatches the corresponding controller method corresponding to
  // carry out the command.
  void HandleCommand(std::unique_ptr<CommandPacket> command_packet);

  // Dispatches the test channel action corresponding to the command specified
  // by |name|.
  void HandleTestChannelCommand(const std::string& name,
                                const std::vector<std::string>& args);

  // Sets the controller Handle* methods as callbacks for the transport to call
  // when data is received.
  void RegisterHandlersWithHciTransport(HciTransport& transport);

  // Sets the test channel handler with the transport dedicated to test channel
  // communications.
  void RegisterHandlersWithTestChannelTransport(
      TestChannelTransport& transport);

  // Sets the callback to be used for sending events back to the HCI.
  // TODO(dennischeng): Once PostDelayedTask works, get rid of this and only use
  // |RegisterDelayedEventChannel|.
  void RegisterEventChannel(
      std::function<void(std::unique_ptr<EventPacket>)> send_event);

  void RegisterDelayedEventChannel(
      std::function<void(std::unique_ptr<EventPacket>, base::TimeDelta)>
          send_event);

  // Controller commands. For error codes, see the Bluetooth Core Specification,
  // Version 4.2, Volume 2, Part D (page 370).

@@ -328,18 +394,25 @@ class DualModeController {
  // Test Channel commands:

  // Clears all test channel modifications.
  void UciClear(const std::vector<std::string>& args);
  void TestChannelClear(const std::vector<std::string>& args);

  // Discovers a fake device.
  void UciDiscover(const std::vector<std::string>& args);
  void TestChannelDiscover(const std::vector<std::string>& args);

  // Discovers a fake device on the specified interval (in ms).
  void UciDiscoverInterval(const std::vector<std::string>& args);
  void TestChannelDiscoverInterval(const std::vector<std::string>& args);

  // Causes all future HCI commands to timeout.
  void UciTimeoutAll(const std::vector<std::string>& args);
  void TestChannelTimeoutAll(const std::vector<std::string>& args);

  // Causes events to be sent after a delay.
  void TestChannelSetEventDelay(const std::vector<std::string>& args);

  // Sets the response delay for events to 0.
  void TestChannelClearEventDelay(const std::vector<std::string>& args);

 private:
  // Current link layer state of the controller.
  enum State {
    kStandby,  // Not receiving/transmitting any packets from/to other devices.
    kAdvertising,  // Transmitting advertising packets.
@@ -351,6 +424,7 @@ class DualModeController {
  enum TestChannelState {
    kNone,  // The controller is running normally.
    kTimeoutAll,  // All commands should time out, i.e. send no response.
    kDelayedResponse,  // Event responses are sent after a delay.
  };

  // Creates a command complete event and sends it back to the HCI.
@@ -374,9 +448,14 @@ class DualModeController {
  void SendExtendedInquiryResult(const std::string& name,
                                 const std::string& address) const;

  void SetEventDelay(std::int64_t delay);

  // Callback provided to send events from the controller back to the HCI.
  std::function<void(std::unique_ptr<EventPacket>)> send_event_;

  std::function<void(std::unique_ptr<EventPacket>, base::TimeDelta)>
      send_delayed_event_;

  // Maintains the commands to be registered and used in the HciHandler object.
  // Keys are command opcodes and values are the callbacks to handle each
  // command.
@@ -396,9 +475,10 @@ class DualModeController {
  // 0x03-0xFF: Reserved.
  std::uint8_t inquiry_mode_;

  // Current link layer state of the controller.
  State state_;

  Properties properties_;

  TestChannelState test_channel_state_;

  DISALLOW_COPY_AND_ASSIGN(DualModeController);
+23 −6
Original line number Diff line number Diff line
@@ -25,7 +25,9 @@ extern "C" {
}  // extern "C"

#include "base/files/scoped_file.h"
#include "base/memory/weak_ptr.h"
#include "base/message_loop/message_loop.h"
#include "base/time/time.h"
#include "vendor_libs/test_vendor_lib/include/command_packet.h"
#include "vendor_libs/test_vendor_lib/include/event_packet.h"
#include "vendor_libs/test_vendor_lib/include/packet.h"
@@ -37,7 +39,7 @@ namespace test_vendor_lib {
// socketing mechanisms for reading/writing between the HCI and the controller.
class HciTransport : public base::MessageLoopForIO::Watcher {
 public:
  HciTransport() = default;
  HciTransport();

  virtual ~HciTransport() = default;

@@ -56,9 +58,16 @@ class HciTransport : public base::MessageLoopForIO::Watcher {
  void RegisterCommandHandler(
      std::function<void(std::unique_ptr<CommandPacket>)> callback);

  // Posts the event onto |outgoing_events_| to be written sometime in the
  // future when the vendor file descriptor is ready for writing.
  void SendEvent(std::unique_ptr<EventPacket> event);
  // Posts the event onto |outbound_events_| to be written sometime in the
  // future when the vendor file descriptor is ready for writing. See
  // |outbound_events_| for why |event| is a shared pointer (as opposed to a
  // unique pointer).
  void PostEventResponse(std::shared_ptr<EventPacket> event);

  // Posts the event onto |outbound_events_| after |delay| ms. A call to
  // |PostEventResponse| with |delay| 0 is equivalent to a call to |PostEvent|.
  void PostDelayedEventResponse(std::unique_ptr<EventPacket> event,
                                base::TimeDelta delay);

 private:
  // base::MessageLoopForIO::Watcher overrides:
@@ -72,8 +81,12 @@ class HciTransport : public base::MessageLoopForIO::Watcher {

  // Write queue for sending events to the HCI. Event packets are removed from
  // the queue and written when write-readiness is signalled by the message
  // loop.
  std::queue<std::unique_ptr<EventPacket>> outgoing_events_;
  // loop. Packets are shared pointers because the bind logic in
  // PostEventResponse forces copy semantics to be used on the bound arguments.
  // There will, however, be only a single instance of each EventPacket owned by
  // the HciTransport (i.e. the shared pointer objects are unique) and this will
  // be reinforced with CHECK's.
  std::queue<std::shared_ptr<EventPacket>> outbound_events_;

  // Callback executed in ReceiveReadyCommand() to pass the incoming command
  // over to the handler for further processing.
@@ -90,6 +103,10 @@ class HciTransport : public base::MessageLoopForIO::Watcher {
  std::unique_ptr<base::ScopedFD> hci_fd_;
  std::unique_ptr<base::ScopedFD> vendor_fd_;

  // This should remain the last member so it'll be destroyed and invalidate
  // its weak pointers before any other members are destroyed.
  base::WeakPtrFactory<HciTransport> weak_ptr_factory_;

  DISALLOW_COPY_AND_ASSIGN(HciTransport);
};

+9 −0
Original line number Diff line number Diff line
@@ -17,8 +17,10 @@
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
#include "base/threading/thread.h"
#include "base/time/time.h"
#include "hci/include/bt_vendor_lib.h"
#include "vendor_libs/test_vendor_lib/include/dual_mode_controller.h"
#include "vendor_libs/test_vendor_lib/include/event_packet.h"
#include "vendor_libs/test_vendor_lib/include/hci_transport.h"
#include "vendor_libs/test_vendor_lib/include/test_channel_transport.h"

@@ -66,6 +68,13 @@ class VendorManager {

  ~VendorManager() = default;

  // Posts a callback to |thread_|'s task runner. Equivalent to calling
  // |PostDelayedTask| with a delay of 0.
  bool PostTask(const base::Closure& task);

  // Posts a callback to be run after |delay| ms (or longer) have passed.
  bool PostDelayedTask(const base::Closure& task, base::TimeDelta delay);

  // Starts watching for incoming data from the HCI and the test hook.
  void StartWatchingOnThread();

Loading