Add support for initial delay of modem switch operation.
This reintroduces CL:175741 (but fixes a missing header inclusion) that
adds an 'initial_delay_ms' parameter in the mist configuration file for
specifying the initial delay, in milliseconds, that mist should wait
before starting the modem switch operation. Such a delay is required to
reliably switch some dongles (e.g. Micromax MMX 353G) to the modem mode.
BUG=chromium:313211
TEST=Tested the following:
1. Build and run unit tests.
2. Run remote trybots on {x86,amd64,arm-generic}-release builders.
3. Verify on daisy_spring and peppy that mist successfully switches the
Micromax MMX 353G dongle from the mass storage mode to the modem
mode.
Change-Id: Ie82bfe6777b4495b05d304fd78e8d5961041830e
Reviewed-on: https://chromium-review.googlesource.com/175859
Reviewed-by: Ben Chan <benchan@chromium.org>
Commit-Queue: Ben Chan <benchan@chromium.org>
Tested-by: Ben Chan <benchan@chromium.org>
diff --git a/config_loader_unittest.cc b/config_loader_unittest.cc
index 988c26e..efe10ff 100644
--- a/config_loader_unittest.cc
+++ b/config_loader_unittest.cc
@@ -40,6 +40,7 @@
" usb_message: \"fedcba9877654210\"\n"
" usb_message: \"1234\"\n"
" expect_response: true\n"
+ " initial_delay_ms: 2500\n"
"}\n";
} // namespace
@@ -84,6 +85,7 @@
EXPECT_EQ(0, usb_modem_info1->final_usb_id_size());
EXPECT_EQ(0, usb_modem_info1->usb_message_size());
EXPECT_FALSE(usb_modem_info1->expect_response());
+ EXPECT_EQ(0, usb_modem_info1->initial_delay_ms());
const UsbModemInfo* usb_modem_info2 =
config_loader_.GetUsbModemInfo(0x1234, 0xabcd);
@@ -100,6 +102,7 @@
EXPECT_EQ("fedcba9877654210", usb_modem_info2->usb_message(1));
EXPECT_EQ("1234", usb_modem_info2->usb_message(2));
EXPECT_TRUE(usb_modem_info2->expect_response());
+ EXPECT_EQ(2500, usb_modem_info2->initial_delay_ms());
}
TEST_F(ConfigLoaderTest, LoadEmptyConfigFile) {
diff --git a/default.conf b/default.conf
index 7b36aaf..f613823 100644
--- a/default.conf
+++ b/default.conf
@@ -150,6 +150,7 @@
initial_usb_id { vendor_id: 0x1c9e product_id: 0xf000 }
final_usb_id { vendor_id: 0x1c9e product_id: 0x9605 }
usb_message: "55534243123456788000000080000606f50402527000000000000000000000"
+ initial_delay_ms: 1000
}
# Micromax MMX 377G
diff --git a/proto/usb_modem_info.proto b/proto/usb_modem_info.proto
index 2b16d6e..ed70f30 100644
--- a/proto/usb_modem_info.proto
+++ b/proto/usb_modem_info.proto
@@ -25,4 +25,7 @@
// If true, a response is expected from the mass storage interface after
// sending each USB message to the interface.
optional bool expect_response = 4;
+ // Initial delay, in milliseconds, that mist should wait before starting
+ // the modem switch operation.
+ optional uint32 initial_delay_ms = 5;
}
diff --git a/usb_modem_switch_operation.cc b/usb_modem_switch_operation.cc
index c60ebee..0f93d28 100644
--- a/usb_modem_switch_operation.cc
+++ b/usb_modem_switch_operation.cc
@@ -94,10 +94,16 @@
VLOG(1) << "Start modem switch operation for device '"
<< switch_context_->sys_path() << "'.";
- // Defer the execution of the first task as multiple UsbModemSwitchOperation
- // objects may be created and started in a tight loop.
- ScheduleTask(
- &UsbModemSwitchOperation::OpenDeviceAndClaimMassStorageInterface);
+ // Schedule the execution of the first task using the message loop, even when
+ // the initial delay is 0, as multiple UsbModemSwitchOperation objects may be
+ // created and started in a tight loop.
+ base::TimeDelta initial_delay = base::TimeDelta::FromMilliseconds(
+ switch_context_->modem_info()->initial_delay_ms());
+ LOG(INFO) << "Starting the modem switch operation in "
+ << initial_delay.InMilliseconds() << " ms.";
+ ScheduleDelayedTask(
+ &UsbModemSwitchOperation::OpenDeviceAndClaimMassStorageInterface,
+ initial_delay);
}
void UsbModemSwitchOperation::Cancel() {
@@ -114,6 +120,14 @@
context_->event_dispatcher()->PostTask(pending_task_.callback());
}
+void UsbModemSwitchOperation::ScheduleDelayedTask(
+ Task task,
+ const base::TimeDelta& delay) {
+ pending_task_.Reset(Bind(task, Unretained(this)));
+ context_->event_dispatcher()->PostDelayedTask(pending_task_.callback(),
+ delay);
+}
+
void UsbModemSwitchOperation::Complete(bool success) {
CHECK(!completion_callback_.is_null());
diff --git a/usb_modem_switch_operation.h b/usb_modem_switch_operation.h
index 8fbd278..4fe6917 100644
--- a/usb_modem_switch_operation.h
+++ b/usb_modem_switch_operation.h
@@ -13,6 +13,7 @@
#include <base/compiler_specific.h>
#include <base/memory/scoped_ptr.h>
#include <base/memory/weak_ptr.h>
+#include <base/time.h>
#include "mist/usb_device_event_observer.h"
@@ -74,10 +75,18 @@
typedef void (UsbModemSwitchOperation::*UsbTransferCompletionHandler)(
UsbTransfer* transfer);
- // Schedules the next task in the message loop for execution. At most one
- // pending task is allowed at any time.
+ // Schedules the specified |task| in the message loop for execution. At most
+ // one pending task is allowed, so any pending task previously scheduled by
+ // ScheduleTask() or ScheduleDelayedTask() is cancelled before |task| is
+ // scheduled.
void ScheduleTask(Task task);
+ // Schedules the specified |task| in the message loop for execution after the
+ // specified |delay|. At most one pending task is allowed, so any pending
+ // task previously scheduled by ScheduleTask() or ScheduleDelayedTask() is
+ // cancelled before |task| is scheduled.
+ void ScheduleDelayedTask(Task task, const base::TimeDelta& delay);
+
// Completes the operation, which invokes the completion callback with the
// status of the operation as |success|. The completion callback may delete
// this object, so this object should not be accessed after this method