Loading system/vendor_libs/test_vendor_lib/include/dual_mode_controller.h +5 −8 Original line number Diff line number Diff line Loading @@ -396,20 +396,17 @@ class DualModeController { // Clears all test channel modifications. void TestChannelClear(const std::vector<std::string>& args); // Sets the response delay for events to 0. void TestChannelClearEventDelay(const std::vector<std::string>& args); // Discovers a fake device. void TestChannelDiscover(const std::vector<std::string>& args); // Discovers a fake device on the specified interval (in ms). void TestChannelDiscoverInterval(const std::vector<std::string>& args); // Causes all future HCI commands to timeout. 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); // Causes all future HCI commands to timeout. void TestChannelTimeoutAll(const std::vector<std::string>& args); private: // Current link layer state of the controller. Loading system/vendor_libs/test_vendor_lib/include/hci_transport.h +30 −11 Original line number Diff line number Diff line Loading @@ -18,7 +18,7 @@ #include <functional> #include <memory> #include <queue> #include <list> extern "C" { #include <sys/epoll.h> Loading Loading @@ -59,10 +59,8 @@ class HciTransport : public base::MessageLoopForIO::Watcher { std::function<void(std::unique_ptr<CommandPacket>)> callback); // 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); // future when the vendor file descriptor is ready for writing. void PostEventResponse(std::unique_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|. Loading @@ -70,6 +68,29 @@ class HciTransport : public base::MessageLoopForIO::Watcher { base::TimeDelta delay); private: // Wrapper class for sending events on a delay. The TimeStampedEvent object // takes ownership of a given event packet. class TimeStampedEvent { public: TimeStampedEvent(std::unique_ptr<EventPacket> event, base::TimeDelta delay); // Using this constructor is equivalent to calling the 2-argument // constructor with a |delay| of 0. It is used to generate event responses // with no delay. TimeStampedEvent(std::unique_ptr<EventPacket> event); const base::TimeTicks& GetTimeStamp() const; const EventPacket& GetEvent(); private: std::shared_ptr<EventPacket> event_; // The time associated with the event, indicating the earliest time at which // |event_| will be sent. base::TimeTicks time_stamp_; }; // base::MessageLoopForIO::Watcher overrides: void OnFileCanReadWithoutBlocking(int fd) override; Loading @@ -79,14 +100,12 @@ class HciTransport : public base::MessageLoopForIO::Watcher { // |command_handler_|, passing ownership of the command packet to the handler. void ReceiveReadyCommand() const; void AddEventToOutboundEvents(std::unique_ptr<TimeStampedEvent> event); // 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. 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_; // loop. After being written, the event packets are destructed. std::list<std::unique_ptr<TimeStampedEvent>> outbound_events_; // Callback executed in ReceiveReadyCommand() to pass the incoming command // over to the handler for further processing. Loading system/vendor_libs/test_vendor_lib/scripts/test_channel.py +13 −28 Original line number Diff line number Diff line Loading @@ -168,22 +168,24 @@ class TestChannelShell(cmd.Cmd): cmd.Cmd.__init__(self) self._test_channel = test_channel def do_quit(self, arg): """Exits the test channel.""" self._connection.close() self._test_channel = test_channel def do_clear(self, args): """ Arguments: None. Resets the controller to its original, unmodified state. """ self._test_channel.send_command('CLEAR', []) def do_timeout_all(self, args): def do_clear_event_delay(self, args): """ Arguments: None. Causes all HCI commands to timeout. Clears the response delay set by set_event_delay. """ self._test_channel.send_command('TIMEOUT_ALL', []) self._test_channel.send_command('CLEAR_EVENT_DELAY', args.split()) def do_discover(self, args): """ Arguments: name_1 name_2 ... Sends an inquiry result for device(s) |name|. If no names are provided, a Sends an inquiry result for named device(s). If no names are provided, a random name is used instead. """ if len(args) == 0: Loading @@ -196,16 +198,6 @@ class TestChannelShell(cmd.Cmd): device_names_and_addresses.append(device.get_address()) self._test_channel.send_command('DISCOVER', device_names_and_addresses) def do_discover_interval(self, args): """ Arguments: interval_in_ms 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_set_event_delay(self, args): """ Arguments: interval_in_ms Loading @@ -214,19 +206,12 @@ class TestChannelShell(cmd.Cmd): """ self._test_channel.send_command('SET_EVENT_DELAY', args.split()) def do_clear_event_delay(self, args): """ Arguments: None. Clears the response delay set by |do_set_event_delay|. """ self._test_channel.send_command('CLEAR_EVENT_DELAY', args.split()) def do_clear(self, args): def do_timeout_all(self, args): """ Arguments: None. Resets the controller to its original, unmodified state. Causes all HCI commands to timeout. """ self._test_channel.send_command('CLEAR', []) self._test_channel.send_command('TIMEOUT_ALL', []) def do_quit(self, args): """ Loading system/vendor_libs/test_vendor_lib/src/dual_mode_controller.cc +2 −14 Original line number Diff line number Diff line Loading @@ -177,11 +177,10 @@ DualModeController::DualModeController() active_test_channel_commands_[command_name] = \ std::bind(&DualModeController::method, this, std::placeholders::_1); SET_TEST_HANDLER("CLEAR", TestChannelClear); SET_TEST_HANDLER("CLEAR_EVENT_DELAY", TestChannelClearEventDelay); SET_TEST_HANDLER("DISCOVER", TestChannelDiscover); SET_TEST_HANDLER("DISCOVER_INTERVAL", TestChannelDiscoverInterval); SET_TEST_HANDLER("TIMEOUT_ALL", TestChannelTimeoutAll); SET_TEST_HANDLER("SET_EVENT_DELAY", TestChannelSetEventDelay); SET_TEST_HANDLER("CLEAR_EVENT_DELAY", TestChannelClearEventDelay); SET_TEST_HANDLER("TIMEOUT_ALL", TestChannelTimeoutAll); #undef SET_TEST_HANDLER } Loading Loading @@ -258,17 +257,6 @@ void DualModeController::TestChannelDiscover( } } // TODO(dennischeng): This should discover devices continuously at the specified // interval until the user sends an explicit 'stop' command. Each device should // have a unique bd address and name? void DualModeController::TestChannelDiscoverInterval( const std::vector<std::string>& args) { LogCommand("TestChannel Discover Interval"); test_channel_state_ = kDelayedResponse; SetEventDelay(std::stoi(args[2])); SendExtendedInquiryResult(args[0], args[1]); } void DualModeController::TestChannelTimeoutAll( const std::vector<std::string>& args) { LogCommand("TestChannel Timeout All"); Loading system/vendor_libs/test_vendor_lib/src/hci_transport.cc +53 −15 Original line number Diff line number Diff line Loading @@ -101,32 +101,70 @@ void HciTransport::RegisterCommandHandler( void HciTransport::OnFileCanWriteWithoutBlocking(int fd) { CHECK(fd == GetVendorFd()); if (!outbound_events_.empty()) { CHECK(outbound_events_.front().unique()); packet_stream_.SendEvent(*(outbound_events_.front()), fd); outbound_events_.pop(); base::TimeTicks current_time = base::TimeTicks::Now(); auto it = outbound_events_.begin(); // Check outbound events for events that can be sent, i.e. events with a // timestamp before the current time. Stop sending events when // |packet_stream_| fails writing. for (auto it = outbound_events_.begin(); it != outbound_events_.end();) { if ((*it)->GetTimeStamp() > current_time) { ++it; continue; } if (!packet_stream_.SendEvent((*it)->GetEvent(), fd)) return; it = outbound_events_.erase(it); } } } void HciTransport::AddEventToOutboundEvents( std::unique_ptr<TimeStampedEvent> event) { outbound_events_.push_back(std::move(event)); } void HciTransport::PostEventResponse(std::shared_ptr<EventPacket> event) { outbound_events_.push(event); void HciTransport::PostEventResponse(std::unique_ptr<EventPacket> event) { AddEventToOutboundEvents(std::make_unique<TimeStampedEvent>(std::move(event))); } void HciTransport::PostDelayedEventResponse(std::unique_ptr<EventPacket> event, base::TimeDelta delay) { CHECK(base::MessageLoop::current()); CHECK(base::ThreadTaskRunnerHandle::Get()->BelongsToCurrentThread()); CHECK(base::ThreadTaskRunnerHandle::Get()->RunsTasksOnCurrentThread()); // TODO(dennischeng): When it becomes available for MessageLoopForIO, use the // thread's task runner to post |PostEventResponse| as a delayed task, being // sure to CHECK the appropriate task runner attributes using // base::ThreadTaskRunnerHandle. // The system does not support high resolution timing and the clock could be // as coarse as ~15.6 ms so the event is sent without a delay to avoid // inconsistent event responses. if (!base::TimeTicks::IsHighResolution()) { LOG_INFO(LOG_TAG, "System does not support high resolution timing. Sending event " "without delay."); PostEventResponse(std::move(event)); } LOG_INFO(LOG_TAG, "Posting event response with delay of %lld ms.", delay.InMilliseconds()); if (!base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( FROM_HERE, base::Bind(&HciTransport::PostEventResponse, weak_ptr_factory_.GetWeakPtr(), std::shared_ptr<EventPacket>(std::move(event))), delay)) { LOG_ERROR(LOG_TAG, "Couldn't post event response."); AddEventToOutboundEvents( std::make_unique<TimeStampedEvent>(std::move(event), delay)); } HciTransport::TimeStampedEvent::TimeStampedEvent( std::unique_ptr<EventPacket> event, base::TimeDelta delay) : event_(std::move(event)), time_stamp_(base::TimeTicks::Now() + delay) {} HciTransport::TimeStampedEvent::TimeStampedEvent( std::unique_ptr<EventPacket> event) : event_(std::move(event)), time_stamp_(base::TimeTicks::UnixEpoch()) {} const base::TimeTicks& HciTransport::TimeStampedEvent::GetTimeStamp() const { return time_stamp_; } const EventPacket& HciTransport::TimeStampedEvent::GetEvent() { return *(event_.get()); } } // namespace test_vendor_lib Loading
system/vendor_libs/test_vendor_lib/include/dual_mode_controller.h +5 −8 Original line number Diff line number Diff line Loading @@ -396,20 +396,17 @@ class DualModeController { // Clears all test channel modifications. void TestChannelClear(const std::vector<std::string>& args); // Sets the response delay for events to 0. void TestChannelClearEventDelay(const std::vector<std::string>& args); // Discovers a fake device. void TestChannelDiscover(const std::vector<std::string>& args); // Discovers a fake device on the specified interval (in ms). void TestChannelDiscoverInterval(const std::vector<std::string>& args); // Causes all future HCI commands to timeout. 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); // Causes all future HCI commands to timeout. void TestChannelTimeoutAll(const std::vector<std::string>& args); private: // Current link layer state of the controller. Loading
system/vendor_libs/test_vendor_lib/include/hci_transport.h +30 −11 Original line number Diff line number Diff line Loading @@ -18,7 +18,7 @@ #include <functional> #include <memory> #include <queue> #include <list> extern "C" { #include <sys/epoll.h> Loading Loading @@ -59,10 +59,8 @@ class HciTransport : public base::MessageLoopForIO::Watcher { std::function<void(std::unique_ptr<CommandPacket>)> callback); // 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); // future when the vendor file descriptor is ready for writing. void PostEventResponse(std::unique_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|. Loading @@ -70,6 +68,29 @@ class HciTransport : public base::MessageLoopForIO::Watcher { base::TimeDelta delay); private: // Wrapper class for sending events on a delay. The TimeStampedEvent object // takes ownership of a given event packet. class TimeStampedEvent { public: TimeStampedEvent(std::unique_ptr<EventPacket> event, base::TimeDelta delay); // Using this constructor is equivalent to calling the 2-argument // constructor with a |delay| of 0. It is used to generate event responses // with no delay. TimeStampedEvent(std::unique_ptr<EventPacket> event); const base::TimeTicks& GetTimeStamp() const; const EventPacket& GetEvent(); private: std::shared_ptr<EventPacket> event_; // The time associated with the event, indicating the earliest time at which // |event_| will be sent. base::TimeTicks time_stamp_; }; // base::MessageLoopForIO::Watcher overrides: void OnFileCanReadWithoutBlocking(int fd) override; Loading @@ -79,14 +100,12 @@ class HciTransport : public base::MessageLoopForIO::Watcher { // |command_handler_|, passing ownership of the command packet to the handler. void ReceiveReadyCommand() const; void AddEventToOutboundEvents(std::unique_ptr<TimeStampedEvent> event); // 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. 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_; // loop. After being written, the event packets are destructed. std::list<std::unique_ptr<TimeStampedEvent>> outbound_events_; // Callback executed in ReceiveReadyCommand() to pass the incoming command // over to the handler for further processing. Loading
system/vendor_libs/test_vendor_lib/scripts/test_channel.py +13 −28 Original line number Diff line number Diff line Loading @@ -168,22 +168,24 @@ class TestChannelShell(cmd.Cmd): cmd.Cmd.__init__(self) self._test_channel = test_channel def do_quit(self, arg): """Exits the test channel.""" self._connection.close() self._test_channel = test_channel def do_clear(self, args): """ Arguments: None. Resets the controller to its original, unmodified state. """ self._test_channel.send_command('CLEAR', []) def do_timeout_all(self, args): def do_clear_event_delay(self, args): """ Arguments: None. Causes all HCI commands to timeout. Clears the response delay set by set_event_delay. """ self._test_channel.send_command('TIMEOUT_ALL', []) self._test_channel.send_command('CLEAR_EVENT_DELAY', args.split()) def do_discover(self, args): """ Arguments: name_1 name_2 ... Sends an inquiry result for device(s) |name|. If no names are provided, a Sends an inquiry result for named device(s). If no names are provided, a random name is used instead. """ if len(args) == 0: Loading @@ -196,16 +198,6 @@ class TestChannelShell(cmd.Cmd): device_names_and_addresses.append(device.get_address()) self._test_channel.send_command('DISCOVER', device_names_and_addresses) def do_discover_interval(self, args): """ Arguments: interval_in_ms 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_set_event_delay(self, args): """ Arguments: interval_in_ms Loading @@ -214,19 +206,12 @@ class TestChannelShell(cmd.Cmd): """ self._test_channel.send_command('SET_EVENT_DELAY', args.split()) def do_clear_event_delay(self, args): """ Arguments: None. Clears the response delay set by |do_set_event_delay|. """ self._test_channel.send_command('CLEAR_EVENT_DELAY', args.split()) def do_clear(self, args): def do_timeout_all(self, args): """ Arguments: None. Resets the controller to its original, unmodified state. Causes all HCI commands to timeout. """ self._test_channel.send_command('CLEAR', []) self._test_channel.send_command('TIMEOUT_ALL', []) def do_quit(self, args): """ Loading
system/vendor_libs/test_vendor_lib/src/dual_mode_controller.cc +2 −14 Original line number Diff line number Diff line Loading @@ -177,11 +177,10 @@ DualModeController::DualModeController() active_test_channel_commands_[command_name] = \ std::bind(&DualModeController::method, this, std::placeholders::_1); SET_TEST_HANDLER("CLEAR", TestChannelClear); SET_TEST_HANDLER("CLEAR_EVENT_DELAY", TestChannelClearEventDelay); SET_TEST_HANDLER("DISCOVER", TestChannelDiscover); SET_TEST_HANDLER("DISCOVER_INTERVAL", TestChannelDiscoverInterval); SET_TEST_HANDLER("TIMEOUT_ALL", TestChannelTimeoutAll); SET_TEST_HANDLER("SET_EVENT_DELAY", TestChannelSetEventDelay); SET_TEST_HANDLER("CLEAR_EVENT_DELAY", TestChannelClearEventDelay); SET_TEST_HANDLER("TIMEOUT_ALL", TestChannelTimeoutAll); #undef SET_TEST_HANDLER } Loading Loading @@ -258,17 +257,6 @@ void DualModeController::TestChannelDiscover( } } // TODO(dennischeng): This should discover devices continuously at the specified // interval until the user sends an explicit 'stop' command. Each device should // have a unique bd address and name? void DualModeController::TestChannelDiscoverInterval( const std::vector<std::string>& args) { LogCommand("TestChannel Discover Interval"); test_channel_state_ = kDelayedResponse; SetEventDelay(std::stoi(args[2])); SendExtendedInquiryResult(args[0], args[1]); } void DualModeController::TestChannelTimeoutAll( const std::vector<std::string>& args) { LogCommand("TestChannel Timeout All"); Loading
system/vendor_libs/test_vendor_lib/src/hci_transport.cc +53 −15 Original line number Diff line number Diff line Loading @@ -101,32 +101,70 @@ void HciTransport::RegisterCommandHandler( void HciTransport::OnFileCanWriteWithoutBlocking(int fd) { CHECK(fd == GetVendorFd()); if (!outbound_events_.empty()) { CHECK(outbound_events_.front().unique()); packet_stream_.SendEvent(*(outbound_events_.front()), fd); outbound_events_.pop(); base::TimeTicks current_time = base::TimeTicks::Now(); auto it = outbound_events_.begin(); // Check outbound events for events that can be sent, i.e. events with a // timestamp before the current time. Stop sending events when // |packet_stream_| fails writing. for (auto it = outbound_events_.begin(); it != outbound_events_.end();) { if ((*it)->GetTimeStamp() > current_time) { ++it; continue; } if (!packet_stream_.SendEvent((*it)->GetEvent(), fd)) return; it = outbound_events_.erase(it); } } } void HciTransport::AddEventToOutboundEvents( std::unique_ptr<TimeStampedEvent> event) { outbound_events_.push_back(std::move(event)); } void HciTransport::PostEventResponse(std::shared_ptr<EventPacket> event) { outbound_events_.push(event); void HciTransport::PostEventResponse(std::unique_ptr<EventPacket> event) { AddEventToOutboundEvents(std::make_unique<TimeStampedEvent>(std::move(event))); } void HciTransport::PostDelayedEventResponse(std::unique_ptr<EventPacket> event, base::TimeDelta delay) { CHECK(base::MessageLoop::current()); CHECK(base::ThreadTaskRunnerHandle::Get()->BelongsToCurrentThread()); CHECK(base::ThreadTaskRunnerHandle::Get()->RunsTasksOnCurrentThread()); // TODO(dennischeng): When it becomes available for MessageLoopForIO, use the // thread's task runner to post |PostEventResponse| as a delayed task, being // sure to CHECK the appropriate task runner attributes using // base::ThreadTaskRunnerHandle. // The system does not support high resolution timing and the clock could be // as coarse as ~15.6 ms so the event is sent without a delay to avoid // inconsistent event responses. if (!base::TimeTicks::IsHighResolution()) { LOG_INFO(LOG_TAG, "System does not support high resolution timing. Sending event " "without delay."); PostEventResponse(std::move(event)); } LOG_INFO(LOG_TAG, "Posting event response with delay of %lld ms.", delay.InMilliseconds()); if (!base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( FROM_HERE, base::Bind(&HciTransport::PostEventResponse, weak_ptr_factory_.GetWeakPtr(), std::shared_ptr<EventPacket>(std::move(event))), delay)) { LOG_ERROR(LOG_TAG, "Couldn't post event response."); AddEventToOutboundEvents( std::make_unique<TimeStampedEvent>(std::move(event), delay)); } HciTransport::TimeStampedEvent::TimeStampedEvent( std::unique_ptr<EventPacket> event, base::TimeDelta delay) : event_(std::move(event)), time_stamp_(base::TimeTicks::Now() + delay) {} HciTransport::TimeStampedEvent::TimeStampedEvent( std::unique_ptr<EventPacket> event) : event_(std::move(event)), time_stamp_(base::TimeTicks::UnixEpoch()) {} const base::TimeTicks& HciTransport::TimeStampedEvent::GetTimeStamp() const { return time_stamp_; } const EventPacket& HciTransport::TimeStampedEvent::GetEvent() { return *(event_.get()); } } // namespace test_vendor_lib