Loading system/vendor_libs/test_vendor_lib/include/dual_mode_controller.h +23 −3 Original line number Diff line number Diff line Loading @@ -324,7 +324,19 @@ class DualModeController { // is halted. void HciInquiry(const std::vector<std::uint8_t>& args); void UciTimeoutAll(const std::vector<std::uint8_t>& args); // Test Channel commands: // Clears all test channel modifications. void UciClear(const std::vector<std::string>& args); // Discovers a fake device. void UciDiscover(const std::vector<std::string>& args); // Discovers a fake device on the specified interval (in ms). void UciDiscoverInterval(const std::vector<std::string>& args); // Causes all future HCI commands to timeout. void UciTimeoutAll(const std::vector<std::string>& args); private: enum State { Loading @@ -335,6 +347,11 @@ class DualModeController { kConnection, // In a connection. }; enum TestChannelState { kNone, // The controller is running normally. kTimeoutAll, // All commands should time out, i.e. send no response. }; // Creates a command complete event and sends it back to the HCI. void SendCommandComplete(uint16_t command_opcode, const std::vector<uint8_t>& return_parameters) const; Loading @@ -353,7 +370,8 @@ class DualModeController { void SendInquiryResult() const; // Sends an extended inquiry response for a fake device. void SendExtendedInquiryResult() const; void SendExtendedInquiryResult(const std::string& name, const std::string& address) const; // Callback provided to send events from the controller back to the HCI. std::function<void(std::unique_ptr<EventPacket>)> send_event_; Loading @@ -366,7 +384,7 @@ class DualModeController { active_commands_; std::unordered_map<std::string, std::function<void(const std::vector<std::uint8_t>&)>> std::function<void(const std::vector<std::string>&)>> test_channel_active_commands_; // Specifies the format of Inquiry Result events to be returned during the Loading @@ -380,6 +398,8 @@ class DualModeController { // Current link layer state of the controller. State state_; TestChannelState test_channel_state_; DISALLOW_COPY_AND_ASSIGN(DualModeController); }; Loading system/vendor_libs/test_vendor_lib/include/test_channel_handler.h +3 −3 Original line number Diff line number Diff line Loading @@ -37,14 +37,14 @@ class TestChannelHandler { // Callback to be fired when a command is received from the test channel. void HandleTestCommand(std::string command_name, std::vector<std::uint8_t> args); std::vector<std::string> args); // Creates the mapping from the |command_name| to the method |callback|, // which is provided by the controller and will be fired when its command is // received from the test channel. void RegisterControllerCommand( std::string command_name, std::function<void(const std::vector<std::uint8_t> args)> callback); std::function<void(const std::vector<std::string> args)> callback); void RegisterHandlersWithTransport(TestChannelTransport& transport); Loading @@ -52,7 +52,7 @@ class TestChannelHandler { // Controller callbacks to be executed in handlers and registered in // RegisterControllerCommand(). std::unordered_map<std::string, std::function<void(const std::vector<std::uint8_t> args)> > std::function<void(const std::vector<std::string> args)> > commands_; DISALLOW_COPY_AND_ASSIGN(TestChannelHandler); Loading system/vendor_libs/test_vendor_lib/include/test_channel_transport.h +2 −2 Original line number Diff line number Diff line Loading @@ -52,7 +52,7 @@ class TestChannelTransport : public base::MessageLoopForIO::Watcher { // Sets the callback that fires when data is read in // |OnFileCanReadWithoutBlocking|. void RegisterCommandHandler( std::function<void(std::string, std::vector<std::uint8_t>)> callback); std::function<void(std::string, std::vector<std::string>)> callback); private: // base::MessageLoopForIO::Watcher overrides: Loading @@ -60,7 +60,7 @@ class TestChannelTransport : public base::MessageLoopForIO::Watcher { void OnFileCanWriteWithoutBlocking(int fd) override; std::function<void(std::string, std::vector<std::uint8_t>)> std::function<void(std::string, std::vector<std::string>)> command_handler_; // File descriptor to watch for test hook data. Loading system/vendor_libs/test_vendor_lib/scripts/test_channel.py +63 −5 Original line number Diff line number Diff line Loading @@ -44,6 +44,18 @@ import string import struct import sys DEVICE_NAME_LENGTH = 6 DEVICE_ADDRESS_LENGTH = 6 # Used to generate fake device names and addresses during discovery. def generate_random_name(): return ''.join(random.SystemRandom().choice(string.ascii_uppercase + \ string.digits) for _ in range(DEVICE_NAME_LENGTH)) def generate_random_address(): return ''.join(random.SystemRandom().choice(string.digits) for _ in \ range(DEVICE_ADDRESS_LENGTH)) class Connection(object): """Simple wrapper class for a socket object. Loading Loading @@ -71,6 +83,12 @@ class TestChannel(object): def __init__(self, address, port): self._connection = Connection(address, port) self._discovered_devices = DeviceManager() def discover_new_device(self, name=None, address=None): device = Device(name, address) self._discovered_devices.add_device(device) return device def close(self): self._connection.close() Loading Loading @@ -99,6 +117,40 @@ class TestChannel(object): if len(arg) > 255: raise ValueError # Size must be encodable in one octet. class DeviceManager(object): """Maintains the active fake devices that have been "discovered". Attributes: device_list: Maps device addresses (keys) to devices (values). """ def __init__(self): self.device_list = {} def add_device(self, device): self.device_list[device.get_address()] = device class Device(object): """A fake device to be returned in inquiry and scan results. Note that if an explicit name or address is not provided, a random string of characters is used. Attributes: name: The device name for use in extended results. address: The BD address of the device. """ def __init__(self, name=None, address=None): # TODO(dennischeng): Generate device properties more robustly. self.name = generate_random_name() if name is None else name self.address = generate_random_address() if address is None else address def get_name(self): return self.name def get_address(self): return self.address class TestChannelShell(cmd.Cmd): """Shell for sending test channel data to controller. Loading Loading @@ -139,10 +191,14 @@ class TestChannelShell(cmd.Cmd): random name is used instead. """ if len(args) == 0: # TODO(dennischeng): Generate device properties more robustly. args = ''.join(random.SystemRandom().choice(string.ascii_uppercase + \ string.digits) for _ in range(6)) self._test_channel.send_command('DISCOVER', args.split()) args = generate_random_name() device_list = [self.test_channel.discover_new_device(arg) for arg in \ args.split()] device_names_and_addresses = [] for device in device_list: device_names_and_addresses.append(device.get_name()) device_names_and_addresses.append(device.get_address()) self._test_channel.send_command('DISCOVER', device_names_and_addresses) def do_discover_interval(self, args): """ Loading @@ -150,6 +206,8 @@ class TestChannelShell(cmd.Cmd): Sends an inquiry result for a device with a random name on the interval specified by |interval_in_ms|. """ args.append(generate_random_name()) args.append(generate_random_address()) self._test_channel.send_command('DISCOVER_INTERVAL', args.split()) def do_clear(self, args): Loading system/vendor_libs/test_vendor_lib/src/dual_mode_controller.cc +34 −9 Original line number Diff line number Diff line Loading @@ -156,22 +156,26 @@ void DualModeController::SendInquiryResult() const { send_event_(std::move(inquiry_result)); } void DualModeController::SendExtendedInquiryResult() const { void DualModeController::SendExtendedInquiryResult( const std::string& name, const std::string& address) const { std::vector<uint8_t> rssi = {0}; std::vector<uint8_t> extended_inquiry_data = {7, 0x09, 'F', 'o', 'o', 'B', 'a', 'r'}; std::vector<uint8_t> extended_inquiry_data = {name.length() + 1, 0x09}; std::copy(name.begin(), name.end(), std::back_inserter(extended_inquiry_data)); std::vector<uint8_t> bd_address(address.begin(), address.end()); // TODO(dennischeng): Use constants for parameter sizes, here and elsewhere. while (extended_inquiry_data.size() < 240) { extended_inquiry_data.push_back(0); } std::unique_ptr<EventPacket> extended_inquiry_result = EventPacket::CreateExtendedInquiryResultEvent( kOtherDeviceBdAddress, kPageScanRepetitionMode, kPageScanPeriodMode, kClassOfDevice, kClockOffset, rssi, extended_inquiry_data); bd_address, kPageScanRepetitionMode, kPageScanPeriodMode, kClassOfDevice, kClockOffset, rssi, extended_inquiry_data); send_event_(std::move(extended_inquiry_result)); } DualModeController::DualModeController() : state_(kStandby) { DualModeController::DualModeController() : state_(kStandby), test_channel_state_(kNone) { #define SET_HANDLER(opcode, method) \ active_commands_[opcode] = \ std::bind(&DualModeController::method, this, std::placeholders::_1); Loading Loading @@ -205,7 +209,10 @@ DualModeController::DualModeController() : state_(kStandby) { #define SET_TEST_HANDLER(command_name, method) \ test_channel_active_commands_[command_name] = \ std::bind(&DualModeController::method, this, std::placeholders::_1); SET_TEST_HANDLER("TimeoutAll", UciTimeoutAll); SET_TEST_HANDLER("CLEAR", UciTimeoutAll); SET_TEST_HANDLER("DISCOVER", UciDiscover); SET_TEST_HANDLER("DISCOVER_INTERVAL", UciTimeoutAll); SET_TEST_HANDLER("TIMEOUT_ALL", UciTimeoutAll); #undef SET_TEST_HANDLER } Loading @@ -228,8 +235,26 @@ void DualModeController::RegisterEventChannel( send_event_ = callback; } void DualModeController::UciTimeoutAll(const std::vector<std::uint8_t>& args) { void DualModeController::UciClear(const std::vector<std::string>& args) { LogCommand("Uci Clear"); test_channel_state_ = kNone; } void DualModeController::UciDiscover(const std::vector<std::string>& args) { LogCommand("Uci Discover"); for (size_t i = 0; i < args.size()-1; i+=2) { SendExtendedInquiryResult(args[i], args[i+1]); } } void DualModeController::UciDiscoverInterval( const std::vector<std::string>& args) { LogCommand("Uci Timeout All"); } void DualModeController::UciTimeoutAll(const std::vector<std::string>& args) { LogCommand("Uci Timeout All"); test_channel_state_ = kTimeoutAll; } // TODO(dennischeng): Store relevant arguments from commands as attributes of Loading Loading @@ -405,7 +430,7 @@ void DualModeController::HciInquiry(const std::vector<uint8_t>& /* args */) { break; case (kExtendedOrRssiInquiry): SendExtendedInquiryResult(); SendExtendedInquiryResult("FooBar", "123456"); break; } } Loading Loading
system/vendor_libs/test_vendor_lib/include/dual_mode_controller.h +23 −3 Original line number Diff line number Diff line Loading @@ -324,7 +324,19 @@ class DualModeController { // is halted. void HciInquiry(const std::vector<std::uint8_t>& args); void UciTimeoutAll(const std::vector<std::uint8_t>& args); // Test Channel commands: // Clears all test channel modifications. void UciClear(const std::vector<std::string>& args); // Discovers a fake device. void UciDiscover(const std::vector<std::string>& args); // Discovers a fake device on the specified interval (in ms). void UciDiscoverInterval(const std::vector<std::string>& args); // Causes all future HCI commands to timeout. void UciTimeoutAll(const std::vector<std::string>& args); private: enum State { Loading @@ -335,6 +347,11 @@ class DualModeController { kConnection, // In a connection. }; enum TestChannelState { kNone, // The controller is running normally. kTimeoutAll, // All commands should time out, i.e. send no response. }; // Creates a command complete event and sends it back to the HCI. void SendCommandComplete(uint16_t command_opcode, const std::vector<uint8_t>& return_parameters) const; Loading @@ -353,7 +370,8 @@ class DualModeController { void SendInquiryResult() const; // Sends an extended inquiry response for a fake device. void SendExtendedInquiryResult() const; void SendExtendedInquiryResult(const std::string& name, const std::string& address) const; // Callback provided to send events from the controller back to the HCI. std::function<void(std::unique_ptr<EventPacket>)> send_event_; Loading @@ -366,7 +384,7 @@ class DualModeController { active_commands_; std::unordered_map<std::string, std::function<void(const std::vector<std::uint8_t>&)>> std::function<void(const std::vector<std::string>&)>> test_channel_active_commands_; // Specifies the format of Inquiry Result events to be returned during the Loading @@ -380,6 +398,8 @@ class DualModeController { // Current link layer state of the controller. State state_; TestChannelState test_channel_state_; DISALLOW_COPY_AND_ASSIGN(DualModeController); }; Loading
system/vendor_libs/test_vendor_lib/include/test_channel_handler.h +3 −3 Original line number Diff line number Diff line Loading @@ -37,14 +37,14 @@ class TestChannelHandler { // Callback to be fired when a command is received from the test channel. void HandleTestCommand(std::string command_name, std::vector<std::uint8_t> args); std::vector<std::string> args); // Creates the mapping from the |command_name| to the method |callback|, // which is provided by the controller and will be fired when its command is // received from the test channel. void RegisterControllerCommand( std::string command_name, std::function<void(const std::vector<std::uint8_t> args)> callback); std::function<void(const std::vector<std::string> args)> callback); void RegisterHandlersWithTransport(TestChannelTransport& transport); Loading @@ -52,7 +52,7 @@ class TestChannelHandler { // Controller callbacks to be executed in handlers and registered in // RegisterControllerCommand(). std::unordered_map<std::string, std::function<void(const std::vector<std::uint8_t> args)> > std::function<void(const std::vector<std::string> args)> > commands_; DISALLOW_COPY_AND_ASSIGN(TestChannelHandler); Loading
system/vendor_libs/test_vendor_lib/include/test_channel_transport.h +2 −2 Original line number Diff line number Diff line Loading @@ -52,7 +52,7 @@ class TestChannelTransport : public base::MessageLoopForIO::Watcher { // Sets the callback that fires when data is read in // |OnFileCanReadWithoutBlocking|. void RegisterCommandHandler( std::function<void(std::string, std::vector<std::uint8_t>)> callback); std::function<void(std::string, std::vector<std::string>)> callback); private: // base::MessageLoopForIO::Watcher overrides: Loading @@ -60,7 +60,7 @@ class TestChannelTransport : public base::MessageLoopForIO::Watcher { void OnFileCanWriteWithoutBlocking(int fd) override; std::function<void(std::string, std::vector<std::uint8_t>)> std::function<void(std::string, std::vector<std::string>)> command_handler_; // File descriptor to watch for test hook data. Loading
system/vendor_libs/test_vendor_lib/scripts/test_channel.py +63 −5 Original line number Diff line number Diff line Loading @@ -44,6 +44,18 @@ import string import struct import sys DEVICE_NAME_LENGTH = 6 DEVICE_ADDRESS_LENGTH = 6 # Used to generate fake device names and addresses during discovery. def generate_random_name(): return ''.join(random.SystemRandom().choice(string.ascii_uppercase + \ string.digits) for _ in range(DEVICE_NAME_LENGTH)) def generate_random_address(): return ''.join(random.SystemRandom().choice(string.digits) for _ in \ range(DEVICE_ADDRESS_LENGTH)) class Connection(object): """Simple wrapper class for a socket object. Loading Loading @@ -71,6 +83,12 @@ class TestChannel(object): def __init__(self, address, port): self._connection = Connection(address, port) self._discovered_devices = DeviceManager() def discover_new_device(self, name=None, address=None): device = Device(name, address) self._discovered_devices.add_device(device) return device def close(self): self._connection.close() Loading Loading @@ -99,6 +117,40 @@ class TestChannel(object): if len(arg) > 255: raise ValueError # Size must be encodable in one octet. class DeviceManager(object): """Maintains the active fake devices that have been "discovered". Attributes: device_list: Maps device addresses (keys) to devices (values). """ def __init__(self): self.device_list = {} def add_device(self, device): self.device_list[device.get_address()] = device class Device(object): """A fake device to be returned in inquiry and scan results. Note that if an explicit name or address is not provided, a random string of characters is used. Attributes: name: The device name for use in extended results. address: The BD address of the device. """ def __init__(self, name=None, address=None): # TODO(dennischeng): Generate device properties more robustly. self.name = generate_random_name() if name is None else name self.address = generate_random_address() if address is None else address def get_name(self): return self.name def get_address(self): return self.address class TestChannelShell(cmd.Cmd): """Shell for sending test channel data to controller. Loading Loading @@ -139,10 +191,14 @@ class TestChannelShell(cmd.Cmd): random name is used instead. """ if len(args) == 0: # TODO(dennischeng): Generate device properties more robustly. args = ''.join(random.SystemRandom().choice(string.ascii_uppercase + \ string.digits) for _ in range(6)) self._test_channel.send_command('DISCOVER', args.split()) args = generate_random_name() device_list = [self.test_channel.discover_new_device(arg) for arg in \ args.split()] device_names_and_addresses = [] for device in device_list: device_names_and_addresses.append(device.get_name()) device_names_and_addresses.append(device.get_address()) self._test_channel.send_command('DISCOVER', device_names_and_addresses) def do_discover_interval(self, args): """ Loading @@ -150,6 +206,8 @@ class TestChannelShell(cmd.Cmd): Sends an inquiry result for a device with a random name on the interval specified by |interval_in_ms|. """ args.append(generate_random_name()) args.append(generate_random_address()) self._test_channel.send_command('DISCOVER_INTERVAL', args.split()) def do_clear(self, args): Loading
system/vendor_libs/test_vendor_lib/src/dual_mode_controller.cc +34 −9 Original line number Diff line number Diff line Loading @@ -156,22 +156,26 @@ void DualModeController::SendInquiryResult() const { send_event_(std::move(inquiry_result)); } void DualModeController::SendExtendedInquiryResult() const { void DualModeController::SendExtendedInquiryResult( const std::string& name, const std::string& address) const { std::vector<uint8_t> rssi = {0}; std::vector<uint8_t> extended_inquiry_data = {7, 0x09, 'F', 'o', 'o', 'B', 'a', 'r'}; std::vector<uint8_t> extended_inquiry_data = {name.length() + 1, 0x09}; std::copy(name.begin(), name.end(), std::back_inserter(extended_inquiry_data)); std::vector<uint8_t> bd_address(address.begin(), address.end()); // TODO(dennischeng): Use constants for parameter sizes, here and elsewhere. while (extended_inquiry_data.size() < 240) { extended_inquiry_data.push_back(0); } std::unique_ptr<EventPacket> extended_inquiry_result = EventPacket::CreateExtendedInquiryResultEvent( kOtherDeviceBdAddress, kPageScanRepetitionMode, kPageScanPeriodMode, kClassOfDevice, kClockOffset, rssi, extended_inquiry_data); bd_address, kPageScanRepetitionMode, kPageScanPeriodMode, kClassOfDevice, kClockOffset, rssi, extended_inquiry_data); send_event_(std::move(extended_inquiry_result)); } DualModeController::DualModeController() : state_(kStandby) { DualModeController::DualModeController() : state_(kStandby), test_channel_state_(kNone) { #define SET_HANDLER(opcode, method) \ active_commands_[opcode] = \ std::bind(&DualModeController::method, this, std::placeholders::_1); Loading Loading @@ -205,7 +209,10 @@ DualModeController::DualModeController() : state_(kStandby) { #define SET_TEST_HANDLER(command_name, method) \ test_channel_active_commands_[command_name] = \ std::bind(&DualModeController::method, this, std::placeholders::_1); SET_TEST_HANDLER("TimeoutAll", UciTimeoutAll); SET_TEST_HANDLER("CLEAR", UciTimeoutAll); SET_TEST_HANDLER("DISCOVER", UciDiscover); SET_TEST_HANDLER("DISCOVER_INTERVAL", UciTimeoutAll); SET_TEST_HANDLER("TIMEOUT_ALL", UciTimeoutAll); #undef SET_TEST_HANDLER } Loading @@ -228,8 +235,26 @@ void DualModeController::RegisterEventChannel( send_event_ = callback; } void DualModeController::UciTimeoutAll(const std::vector<std::uint8_t>& args) { void DualModeController::UciClear(const std::vector<std::string>& args) { LogCommand("Uci Clear"); test_channel_state_ = kNone; } void DualModeController::UciDiscover(const std::vector<std::string>& args) { LogCommand("Uci Discover"); for (size_t i = 0; i < args.size()-1; i+=2) { SendExtendedInquiryResult(args[i], args[i+1]); } } void DualModeController::UciDiscoverInterval( const std::vector<std::string>& args) { LogCommand("Uci Timeout All"); } void DualModeController::UciTimeoutAll(const std::vector<std::string>& args) { LogCommand("Uci Timeout All"); test_channel_state_ = kTimeoutAll; } // TODO(dennischeng): Store relevant arguments from commands as attributes of Loading Loading @@ -405,7 +430,7 @@ void DualModeController::HciInquiry(const std::vector<uint8_t>& /* args */) { break; case (kExtendedOrRssiInquiry): SendExtendedInquiryResult(); SendExtendedInquiryResult("FooBar", "123456"); break; } } Loading