faft: Refactor the delay constants out to a new class FAFTDelayConstants

This refactoring helps the support of per-platform delay constants. Such
that we can use some short-delay-setting for high-speed devices to reduce
unnecessary waiting time.

BUG=chromium-os:35792
TEST=run_remote_tests.sh --board link --remote dut suite:faft

Change-Id: I1080cb6dcff767b0aef869b0f3c4dbf2a949e923
Reviewed-on: https://gerrit.chromium.org/gerrit/36763
Commit-Ready: Tom Wai-Hong Tam <waihong@chromium.org>
Reviewed-by: Tom Wai-Hong Tam <waihong@chromium.org>
Tested-by: Tom Wai-Hong Tam <waihong@chromium.org>
diff --git a/server/cros/faft_delay_constants.py b/server/cros/faft_delay_constants.py
new file mode 100644
index 0000000..4721c11
--- /dev/null
+++ b/server/cros/faft_delay_constants.py
@@ -0,0 +1,60 @@
+# Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+class FAFTDelayConstants(object):
+    """Class that contains the delay constants for FAFT."""
+    version = 1
+
+    DEFAULT_DELAY = {
+        # Delay between power-on and firmware screen
+        'firmware_screen': 10,
+        # Delay between passing firmware screen and text mode warning screen
+        'legacy_text_screen': 20,
+        # The developer screen timeouts fit our spec
+        'dev_screen_timeout': 30,
+        # Delay for waiting beep done
+        'beep': 1,
+        # Delay of loading the USB kernel
+        'load_usb': 10,
+        # Delay between USB plug-out and plug-in
+        'between_usb_plug': 10,
+        # Delay after running the 'sync' command
+        'sync': 5,
+        # Delay for waiting client to shutdown
+        'shutdown': 30,
+        # Delay for waiting client to return before sending EC reboot command
+        'ec_reboot_cmd': 1,
+        # Delay between EC boot and ChromeEC console functional
+        'ec_boot_to_console': 0.5,
+        # Delay between EC boot and pressing power button
+        'ec_boot_to_pwr_button': 0.5,
+        # Delay of EC software sync hash calculating time
+        'software_sync': 6,
+        # Duration of holding cold_reset to reset device
+        'hold_cold_reset': 0.1,
+        # devserver startup time
+        'devserver': 10,
+        # Delay of waiting factory install shim to reset TPM
+        'install_shim_done': 120,
+    }
+
+    def __init__(self, platform=None):
+        """Initialized.
+
+        Args:
+          platform: Optional, platform name returned by FAFT client. If not
+                    given, use the default delay values.
+        """
+        self.__dict__.update(self.DEFAULT_DELAY)
+        if platform:
+            self.__dict__.update(self._get_platform_delay(platform))
+
+
+    def _get_platform_delay(self, platform):
+        """Return platform-specific delay values."""
+        setting = dict()
+
+        # Add the platform-specific delay values here.
+
+        return setting
diff --git a/server/cros/faftsequence.py b/server/cros/faftsequence.py
index 60c2ead..107e3a6 100644
--- a/server/cros/faftsequence.py
+++ b/server/cros/faftsequence.py
@@ -15,6 +15,7 @@
 from autotest_lib.server.cros import vboot_constants as vboot
 from autotest_lib.server.cros.chrome_ec import ChromeEC
 from autotest_lib.server.cros.faft_client_attribute import FAFTClientAttribute
+from autotest_lib.server.cros.faft_delay_constants import FAFTDelayConstants
 from autotest_lib.server.cros.servo_test import ServoTest
 from autotest_lib.site_utils import lab_test
 from autotest_lib.site_utils.chromeos_test.common_util import ChromeOSTestError
@@ -86,38 +87,6 @@
     OTHER_KERNEL_MAP = {'a':'4', 'b':'2', '2':'4', '4':'2', '3':'4', '5':'2'}
     OTHER_ROOTFS_MAP = {'a':'5', 'b':'3', '2':'5', '4':'3', '3':'5', '5':'3'}
 
-    # Delay between power-on and firmware screen.
-    FIRMWARE_SCREEN_DELAY = 10
-    # Delay between passing firmware screen and text mode warning screen.
-    TEXT_SCREEN_DELAY = 20
-    # Delay for waiting beep done.
-    BEEP_DELAY = 1
-    # Delay of loading the USB kernel.
-    USB_LOAD_DELAY = 10
-    # Delay between USB plug-out and plug-in.
-    USB_PLUG_DELAY = 10
-    # Delay after running the 'sync' command.
-    SYNC_DELAY = 5
-    # Delay for waiting client to return before EC reboot
-    EC_REBOOT_DELAY = 1
-    # Delay for waiting client to full power off
-    FULL_POWER_OFF_DELAY = 30
-    # Delay between EC reboot and pressing power button
-    POWER_BTN_DELAY = 0.5
-    # Delay of EC software sync hash calculating time
-    SOFTWARE_SYNC_DELAY = 6
-    # Delay between EC boot and ChromeEC console functional
-    EC_BOOT_DELAY = 0.5
-    # Duration of holding cold_reset to reset device
-    COLD_RESET_DELAY = 0.1
-    # devserver startup time
-    DEVSERVER_DELAY = 10
-    # Delay of reseting TPM with factory install shim
-    RESET_TPM_WITH_INSTALL_SHIM_DELAY = 120
-
-    # The developer screen timeouts fit our spec.
-    DEV_SCREEN_TIMEOUT = 30
-
     CHROMEOS_MAGIC = "CHROMEOS"
     CORRUPTED_MAGIC = "CORRUPTD"
 
@@ -211,6 +180,8 @@
         if use_faft:
             self.client_attr = FAFTClientAttribute(
                     self.faft_client.get_platform_name())
+            self.delay = FAFTDelayConstants(
+                    self.faft_client.get_platform_name())
 
             if self.client_attr.chrome_ec:
                 self.ec = ChromeEC(self.servo)
@@ -471,7 +442,7 @@
                         image_base)
 
             # Wait devserver startup completely
-            time.sleep(self.DEVSERVER_DELAY)
+            time.sleep(self.delay.devserver)
             # devserver is a service running forever. If it is terminated,
             # some error does happen.
             if devserver.poll():
@@ -924,33 +895,33 @@
 
     def wait_fw_screen_and_ctrl_d(self):
         """Wait for firmware warning screen and press Ctrl-D."""
-        time.sleep(self.FIRMWARE_SCREEN_DELAY)
+        time.sleep(self.delay.firmware_screen)
         self.send_ctrl_d_to_dut()
 
 
     def wait_fw_screen_and_ctrl_u(self):
         """Wait for firmware warning screen and press Ctrl-U."""
-        time.sleep(self.FIRMWARE_SCREEN_DELAY)
+        time.sleep(self.delay.firmware_screen)
         self.send_ctrl_u_to_dut()
 
 
     def wait_fw_screen_and_trigger_recovery(self, need_dev_transition=False):
         """Wait for firmware warning screen and trigger recovery boot."""
-        time.sleep(self.FIRMWARE_SCREEN_DELAY)
+        time.sleep(self.delay.firmware_screen)
         self.send_enter_to_dut()
 
         # For Alex/ZGB, there is a dev warning screen in text mode.
         # Skip it by pressing Ctrl-D.
         if need_dev_transition:
-            time.sleep(self.TEXT_SCREEN_DELAY)
+            time.sleep(self.delay.legacy_text_screen)
             self.send_ctrl_d_to_dut()
 
 
     def wait_fw_screen_and_unplug_usb(self):
         """Wait for firmware warning screen and then unplug the servo USB."""
-        time.sleep(self.USB_LOAD_DELAY)
+        time.sleep(self.delay.load_usb)
         self.servo.set('usb_mux_sel1', 'servo_sees_usbkey')
-        time.sleep(self.USB_PLUG_DELAY)
+        time.sleep(self.delay.between_usb_plug)
 
 
     def wait_fw_screen_and_plug_usb(self):
@@ -961,7 +932,7 @@
 
     def wait_fw_screen_and_press_power(self):
         """Wait for firmware warning screen and press power button."""
-        time.sleep(self.FIRMWARE_SCREEN_DELAY)
+        time.sleep(self.delay.firmware_screen)
         # While the firmware screen, the power button probing loop sleeps
         # 0.25 second on every scan. Use the normal delay (1.2 second) for
         # power press.
@@ -970,19 +941,19 @@
 
     def wait_longer_fw_screen_and_press_power(self):
         """Wait for firmware screen without timeout and press power button."""
-        time.sleep(self.DEV_SCREEN_TIMEOUT)
+        time.sleep(self.delay.dev_screen_timeout)
         self.wait_fw_screen_and_press_power()
 
 
     def wait_fw_screen_and_close_lid(self):
         """Wait for firmware warning screen and close lid."""
-        time.sleep(self.FIRMWARE_SCREEN_DELAY)
+        time.sleep(self.delay.firmware_screen)
         self.servo.lid_close()
 
 
     def wait_longer_fw_screen_and_close_lid(self):
         """Wait for firmware screen without timeout and close lid."""
-        time.sleep(self.FIRMWARE_SCREEN_DELAY)
+        time.sleep(self.delay.firmware_screen)
         self.wait_fw_screen_and_close_lid()
 
 
@@ -1036,17 +1007,17 @@
         elif self.client_attr.chrome_ec:
             # Cold reset to clear EC_IN_RW signal
             self.servo.set('cold_reset', 'on')
-            time.sleep(self.COLD_RESET_DELAY)
+            time.sleep(self.delay.hold_cold_reset)
             self.servo.set('cold_reset', 'off')
-            time.sleep(self.EC_BOOT_DELAY)
+            time.sleep(self.delay.ec_boot_to_console)
             self.ec.send_command("reboot ap-off")
-            time.sleep(self.EC_BOOT_DELAY)
+            time.sleep(self.delay.ec_boot_to_console)
             self.ec.send_command("hostevent set 0x4000")
             self.servo.power_short_press()
         else:
             self.servo.enable_recovery_mode()
             self.cold_reboot()
-            time.sleep(self.EC_REBOOT_DELAY)
+            time.sleep(self.delay.ec_reboot_cmd)
             self.servo.disable_recovery_mode()
 
 
@@ -1076,12 +1047,12 @@
         Args:
           dev: True if switching into dev mode. Otherwise, False.
         """
-        time.sleep(self.FIRMWARE_SCREEN_DELAY)
+        time.sleep(self.delay.firmware_screen)
         if dev:
             self.send_ctrl_d_to_dut()
         else:
             self.send_enter_to_dut()
-        time.sleep(self.FIRMWARE_SCREEN_DELAY)
+        time.sleep(self.delay.firmware_screen)
         self.send_enter_to_dut()
 
 
@@ -1185,7 +1156,7 @@
                 (self.KERNEL_MAP[part], root_dev))
         # Safer to sync and wait until the cgpt status written to the disk.
         self.faft_client.run_shell_command('sync')
-        time.sleep(self.SYNC_DELAY)
+        time.sleep(self.delay.sync)
 
 
     def warm_reboot(self):
@@ -1210,7 +1181,7 @@
             self.servo.set('pwr_button', 'press')
             self.servo.set('cold_reset', 'on')
             self.servo.set('cold_reset', 'off')
-            time.sleep(self.POWER_BTN_DELAY)
+            time.sleep(self.delay.ec_boot_to_pwr_button)
             self.servo.set('pwr_button', 'release')
         elif self.check_ec_capability(suppress_warning=True):
             # We don't use servo.cold_reset() here because software sync is
@@ -1226,7 +1197,7 @@
             #    press.
             self.servo.set('cold_reset', 'on')
             self.servo.set('cold_reset', 'off')
-            time.sleep(self.POWER_BTN_DELAY)
+            time.sleep(self.delay.ec_boot_to_pwr_button)
             self.servo.power_short_press()
         else:
             self.servo.cold_reset()
@@ -1238,7 +1209,7 @@
         This is the default reboot action on FAFT.
         """
         self.faft_client.run_shell_command('sync')
-        time.sleep(self.SYNC_DELAY)
+        time.sleep(self.delay.sync)
         self.warm_reboot()
 
 
@@ -1248,7 +1219,7 @@
         This reboot action is used to reset EC for recovery mode.
         """
         self.faft_client.run_shell_command('sync')
-        time.sleep(self.SYNC_DELAY)
+        time.sleep(self.delay.sync)
         self.cold_reboot()
 
 
@@ -1262,12 +1233,12 @@
                   cold: Cold/hard reboot.
         """
         self.faft_client.run_shell_command('sync')
-        time.sleep(self.SYNC_DELAY)
+        time.sleep(self.delay.sync)
         # Since EC reboot happens immediately, delay before actual reboot to
         # allow FAFT client returning.
         self.faft_client.run_shell_command('(sleep %d; ectool reboot_ec %s)&' %
-                                           (self.EC_REBOOT_DELAY, args))
-        time.sleep(self.EC_REBOOT_DELAY)
+                                           (self.delay.ec_reboot_cmd, args))
+        time.sleep(self.delay.ec_reboot_cmd)
         self.check_lid_and_power_on()
 
 
@@ -1283,7 +1254,7 @@
             self.enable_dev_mode_and_reboot()
         time.sleep(self.SYNC_DELAY)
         self.enable_rec_mode_and_reboot()
-        time.sleep(self.RESET_TPM_WITH_INSTALL_SHIM_DELAY)
+        time.sleep(self.delay.install_shim_done)
         self.warm_reboot()
 
 
@@ -1291,7 +1262,7 @@
         """Shutdown the device by pressing power button and power on again."""
         # Press power button to trigger Chrome OS normal shutdown process.
         self.servo.power_normal_press()
-        time.sleep(self.FULL_POWER_OFF_DELAY)
+        time.sleep(self.delay.shutdown)
         # Short press power button to boot DUT again.
         self.servo.power_short_press()
 
@@ -1304,7 +1275,7 @@
         necessary.
         """
         if self.servo.get("lid_open") == "no":
-            time.sleep(self.SOFTWARE_SYNC_DELAY)
+            time.sleep(self.delay.software_sync)
             self.servo.power_short_press()
 
 
diff --git a/server/site_tests/firmware_DevBootUSB/firmware_DevBootUSB.py b/server/site_tests/firmware_DevBootUSB/firmware_DevBootUSB.py
index e13b970..c3e0174 100644
--- a/server/site_tests/firmware_DevBootUSB/firmware_DevBootUSB.py
+++ b/server/site_tests/firmware_DevBootUSB/firmware_DevBootUSB.py
@@ -42,7 +42,7 @@
         self.wait_fw_screen_and_ctrl_u()
         # If the above Ctrl-U doesn't work, the firmware beeps twice.
         # Should wait the beep done before pressing Ctrl-D.
-        time.sleep(self.BEEP_DELAY)
+        time.sleep(self.delay.beep)
         self.send_ctrl_d_to_dut()
 
 
diff --git a/server/site_tests/firmware_DevScreenTimeout/firmware_DevScreenTimeout.py b/server/site_tests/firmware_DevScreenTimeout/firmware_DevScreenTimeout.py
index 221a8c9..b0bc111 100644
--- a/server/site_tests/firmware_DevScreenTimeout/firmware_DevScreenTimeout.py
+++ b/server/site_tests/firmware_DevScreenTimeout/firmware_DevScreenTimeout.py
@@ -73,12 +73,13 @@
                        self.fw_time_record['ctrl_d_boot'])
         logging.info('Estimated developer firmware timeout: %s' % got_timeout)
 
-        if got_timeout < self.DEV_SCREEN_TIMEOUT - self.TIMEOUT_MARGIN or \
-                got_timeout > self.DEV_SCREEN_TIMEOUT + self.TIMEOUT_MARGIN:
+        if (abs(got_timeout - self.delay.dev_screen_timeout) >
+                self.TIMEOUT_MARGIN):
             raise error.TestFail(
                     'The developer firmware timeout does not match our spec: ' \
                     'expected %.2f +/- %.2f but got %.2f.' %
-                    (self.DEV_SCREEN_TIMEOUT, self.TIMEOUT_MARGIN, got_timeout))
+                    (self.delay.dev_screen_timeout, self.TIMEOUT_MARGIN,
+                     got_timeout))
 
 
     def setup(self):
diff --git a/server/site_tests/firmware_ECSharedMem/firmware_ECSharedMem.py b/server/site_tests/firmware_ECSharedMem/firmware_ECSharedMem.py
index 0d4d372..f647429 100644
--- a/server/site_tests/firmware_ECSharedMem/firmware_ECSharedMem.py
+++ b/server/site_tests/firmware_ECSharedMem/firmware_ECSharedMem.py
@@ -14,9 +14,6 @@
     """
     version = 1
 
-    # Delay for EC boot
-    EC_BOOT_DELAY = 0.5
-
 
     def setup(self):
         super(firmware_ECSharedMem, self).setup()
@@ -38,7 +35,7 @@
 
     def jump_checker(self):
         self.ec.send_command("sysjump RW")
-        time.sleep(self.EC_BOOT_DELAY)
+        time.sleep(self.delay.ec_boot_to_console)
         return self.shared_mem_checker()
 
 
diff --git a/server/site_tests/firmware_FwScreenCloseLid/firmware_FwScreenCloseLid.py b/server/site_tests/firmware_FwScreenCloseLid/firmware_FwScreenCloseLid.py
index 25ebae3..f4ec1a7 100644
--- a/server/site_tests/firmware_FwScreenCloseLid/firmware_FwScreenCloseLid.py
+++ b/server/site_tests/firmware_FwScreenCloseLid/firmware_FwScreenCloseLid.py
@@ -31,7 +31,7 @@
         """Wait and trigger yuck screen and clod lid."""
         # Insert a corrupted USB stick. A yuck screen is expected.
         self.servo.set('usb_mux_sel1', 'dut_sees_usbkey')
-        time.sleep(self.USB_LOAD_DELAY)
+        time.sleep(self.delay.load_usb)
         self.wait_longer_fw_screen_and_close_lid()
 
 
diff --git a/server/site_tests/firmware_FwScreenPressPower/firmware_FwScreenPressPower.py b/server/site_tests/firmware_FwScreenPressPower/firmware_FwScreenPressPower.py
index 4b3224e..a9128ca 100644
--- a/server/site_tests/firmware_FwScreenPressPower/firmware_FwScreenPressPower.py
+++ b/server/site_tests/firmware_FwScreenPressPower/firmware_FwScreenPressPower.py
@@ -29,7 +29,7 @@
         """Insert corrupted USB for yuck screen and press power button."""
         # This USB stick will be removed in cleanup phase.
         self.servo.set('usb_mux_sel1', 'dut_sees_usbkey')
-        time.sleep(self.USB_LOAD_DELAY)
+        time.sleep(self.delay.load_usb)
         self.wait_longer_fw_screen_and_press_power()
 
 
diff --git a/server/site_tests/firmware_InvalidUSB/firmware_InvalidUSB.py b/server/site_tests/firmware_InvalidUSB/firmware_InvalidUSB.py
index 63f1a57..70af481 100644
--- a/server/site_tests/firmware_InvalidUSB/firmware_InvalidUSB.py
+++ b/server/site_tests/firmware_InvalidUSB/firmware_InvalidUSB.py
@@ -41,7 +41,7 @@
                 'The USB image is surely unable to boot. Restore it and try...')
 
         self.restore_usb()
-        time.sleep(self.SYNC_DELAY)
+        time.sleep(self.delay.sync)
         self.servo.set('usb_mux_sel1', 'dut_sees_usbkey')