[Autotest] New test for policy_WilcoUSBPowershare.

Testing the effects of the DeviceUsbPowerShareEnabled policy.

BUG=None
TEST=this

Change-Id: Ib3702f2a61ff8d23691f00d5653a8af2fbcdf532
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/third_party/autotest/+/1832308
Tested-by: Ruben Zakarian <rzakarian@chromium.org>
Reviewed-by: Nick Crews <ncrews@chromium.org>
Reviewed-by: Derek Beckett <dbeckett@chromium.org>
Reviewed-by: Fei Ling <feiling@chromium.org>
Legacy-Commit-Queue: Commit Bot <commit-bot@chromium.org>
diff --git a/server/cros/servo/servo.py b/server/cros/servo/servo.py
index 134e389..71f0ae9 100644
--- a/server/cros/servo/servo.py
+++ b/server/cros/servo/servo.py
@@ -435,6 +435,14 @@
         self.set_nocheck('power_key', press_secs)
 
 
+    def pwr_button(self, action='press'):
+        """Simulate a power button press.
+
+        @param action: str; could be press or could be release.
+        """
+        self.set_nocheck('pwr_button', action)
+
+
     def lid_open(self):
         """Simulate opening the lid and raise exception if all attempts fail"""
         self.set('lid_open', 'yes')
@@ -448,6 +456,12 @@
         self.set('lid_open', 'no')
         time.sleep(Servo.SLEEP_DELAY)
 
+
+    def vbus_power_get(self):
+        """Get current vbus_power."""
+        return self.get('vbus_power')
+
+
     def volume_up(self, timeout=300):
         """Simulate pushing the volume down button.
 
diff --git a/server/site_tests/policy_WilcoUSBPowershare/control.WilcoUSBPowershare.disabled b/server/site_tests/policy_WilcoUSBPowershare/control.WilcoUSBPowershare.disabled
new file mode 100644
index 0000000..a0db285
--- /dev/null
+++ b/server/site_tests/policy_WilcoUSBPowershare/control.WilcoUSBPowershare.disabled
@@ -0,0 +1,34 @@
+# Copyright (c) 2019 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.
+
+from autotest_lib.server import utils
+
+AUTHOR = "rzakarian"
+NAME = "policy_WilcoUSBPowershare.disabled"
+CRITERIA = "This test will fail if servo does not work as expected."
+TIME = "LONG"
+TEST_CATEGORY = "General"
+TEST_CLASS = "enterprise"
+TEST_TYPE = "server"
+DEPENDENCIES = "servo"
+
+DOC = """
+This test verifies the USB power output when the device is off with the
+DeviceUsbPowerShareEnabled policy set. If the policy is set to True or
+not set, power should be provided. If the policy is set to False power
+should not be provided.
+
+"""
+
+client_test = 'policy_WilcoUSBPowershare'
+case = False
+args_dict = utils.args_to_dict(args)
+servo_args = hosts.CrosHost.get_servo_arguments(args_dict)
+
+def run(machine):
+    host = hosts.create_host(machine, servo_args=servo_args)
+    job.run_test('policy_WilcoUSBPowershare', host=host,
+                 client_test=client_test, case=case)
+
+parallel_simple(run, machines)
diff --git a/server/site_tests/policy_WilcoUSBPowershare/control.WilcoUSBPowershare.enabled b/server/site_tests/policy_WilcoUSBPowershare/control.WilcoUSBPowershare.enabled
new file mode 100644
index 0000000..16faa6f
--- /dev/null
+++ b/server/site_tests/policy_WilcoUSBPowershare/control.WilcoUSBPowershare.enabled
@@ -0,0 +1,34 @@
+# Copyright (c) 2019 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.
+
+from autotest_lib.server import utils
+
+AUTHOR = "rzakarian"
+NAME = "policy_WilcoUSBPowershare.enabled"
+CRITERIA = "This test will fail if servo does not work as expected."
+TIME = "LONG"
+TEST_CATEGORY = "General"
+TEST_CLASS = "enterprise"
+TEST_TYPE = "server"
+DEPENDENCIES = "servo"
+
+DOC = """
+This test verifies the USB power output when the device is off with the
+DeviceUsbPowerShareEnabled policy set. If the policy is set to True or
+not set, power should be provided. If the policy is set to False power
+should not be provided.
+
+"""
+
+client_test = 'policy_WilcoUSBPowershare'
+case = True
+args_dict = utils.args_to_dict(args)
+servo_args = hosts.CrosHost.get_servo_arguments(args_dict)
+
+def run(machine):
+    host = hosts.create_host(machine, servo_args=servo_args)
+    job.run_test('policy_WilcoUSBPowershare', host=host,
+                 client_test=client_test, case=case)
+
+parallel_simple(run, machines)
diff --git a/server/site_tests/policy_WilcoUSBPowershare/control.WilcoUSBPowershare.not_set b/server/site_tests/policy_WilcoUSBPowershare/control.WilcoUSBPowershare.not_set
new file mode 100644
index 0000000..ca7a000
--- /dev/null
+++ b/server/site_tests/policy_WilcoUSBPowershare/control.WilcoUSBPowershare.not_set
@@ -0,0 +1,34 @@
+# Copyright (c) 2019 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.
+
+from autotest_lib.server import utils
+
+AUTHOR = "rzakarian"
+NAME = "policy_WilcoUSBPowershare.not_set"
+CRITERIA = "This test will fail if servo does not work as expected."
+TIME = "LONG"
+TEST_CATEGORY = "General"
+TEST_CLASS = "enterprise"
+TEST_TYPE = "server"
+DEPENDENCIES = "servo"
+
+DOC = """
+This test verifies the USB power output when the device is off with the
+DeviceUsbPowerShareEnabled policy set. If the policy is set to True or
+not set, power should be provided. If the policy is set to False power
+should not be provided.
+
+"""
+
+client_test = 'policy_WilcoUSBPowershare'
+case = None
+args_dict = utils.args_to_dict(args)
+servo_args = hosts.CrosHost.get_servo_arguments(args_dict)
+
+def run(machine):
+    host = hosts.create_host(machine, servo_args=servo_args)
+    job.run_test('policy_WilcoUSBPowershare', host=host,
+                 client_test=client_test, case=case)
+
+parallel_simple(run, machines)
diff --git a/server/site_tests/policy_WilcoUSBPowershare/policy_WilcoUSBPowershare.py b/server/site_tests/policy_WilcoUSBPowershare/policy_WilcoUSBPowershare.py
new file mode 100644
index 0000000..39b602d
--- /dev/null
+++ b/server/site_tests/policy_WilcoUSBPowershare/policy_WilcoUSBPowershare.py
@@ -0,0 +1,97 @@
+# Copyright (c) 2019 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.
+import logging
+import time
+
+from autotest_lib.client.common_lib import error
+from autotest_lib.client.common_lib.cros import tpm_utils
+from autotest_lib.server import autotest
+from autotest_lib.server import test
+
+
+class policy_WilcoUSBPowershare(test.test):
+    """Test that verifies DeviceUsbPowerShareEnabled policy.
+
+    If the policy is enabled or not set, USB provides power when device is off.
+    If the policy is disabled, USB does not provide power when device is off.
+
+    This test uses the servo board to interact with the device once it's
+    powered off.
+
+    Note: This test only checks the behavior of the device when it is off,
+    it doesn't do the part of the policy when the device is asleep.
+
+    This test has to run on a Wilco device.
+    """
+    version = 1
+
+
+    def clear_tpm_if_owned(self):
+        """Clear the TPM only if device is already owned."""
+        tpm_status = tpm_utils.TPMStatus(self.host)
+        logging.info('TPM status: %s', tpm_status)
+        if tpm_status['Owned']:
+            logging.info('Clearing TPM because this device is owned.')
+            tpm_utils.ClearTPMOwnerRequest(self.host)
+
+
+    def initialize(self, host):
+        """Initialize DUT for testing."""
+        pass
+
+
+    def cleanup(self):
+        """Clean up DUT."""
+        self.clear_tpm_if_owned()
+
+
+    def _get_average_power_output(self):
+        """Gets the average of the list.
+
+        When using the vbus_power command with the DeviceUsbPowerShareEnabled
+        policy enabled, it sometimes still returns 0.0. This is why it's safer
+        to run the command multiple times instead of once.
+
+        """
+        vbus_list = []
+        t_end = time.time() + 7
+        while time.time() < t_end:
+            vbus_list.append(self.host.servo.vbus_power_get())
+            time.sleep(1)
+        return sum(vbus_list)/len(vbus_list)
+
+
+    def run_once(self, client_test, host, case):
+        """Run the test.
+
+        @param client_test: the name of the Client test to run.
+        @param case: the case to run for the given Client test.
+        """
+        self.host = host
+        self.clear_tpm_if_owned()
+
+        self.autotest_client = autotest.Autotest(self.host)
+        self.autotest_client.run_test(
+            client_test, case=case, check_client_result=False)
+
+        # Turns off the device.
+        self.host.servo.power_key('long_press')
+        # This makes sure the device is really off before checking power.
+        time.sleep(10)
+
+        vbus_average_power = self._get_average_power_output()
+
+        # Bring device back up. I tried using power_key method to power up the
+        # device but could not consisnently get it to work. pwr_button method
+        # works all the time.
+        self.host.servo.pwr_button()
+        time.sleep(1)
+        self.host.servo.pwr_button('release')
+
+        if case is False:
+            if vbus_average_power > 0.0:
+                raise error.TestFail('USB is providing power, it should not.')
+        else:
+            if vbus_average_power is 0.0:
+                raise error.TestFail('USB is not providing power, it should.')