| Index: telemetry/telemetry/internal/platform/cros_platform_backend.py
|
| diff --git a/telemetry/telemetry/internal/platform/cros_platform_backend.py b/telemetry/telemetry/internal/platform/cros_platform_backend.py
|
| index 01f2034bd0f30f078cf17b86677e414694a6b436..40d3219c5e9d6b277e662ca9ee1801dcc294b5e0 100644
|
| --- a/telemetry/telemetry/internal/platform/cros_platform_backend.py
|
| +++ b/telemetry/telemetry/internal/platform/cros_platform_backend.py
|
| @@ -13,6 +13,7 @@ from telemetry.internal.platform import cros_device
|
| from telemetry.internal.platform import linux_based_platform_backend
|
| from telemetry.internal.platform.power_monitor import cros_power_monitor
|
| from telemetry.internal.util import ps_util
|
| +from telemetry.internal.util import repeating_timer
|
|
|
|
|
| class CrosPlatformBackend(
|
| @@ -26,6 +27,7 @@ class CrosPlatformBackend(
|
| else:
|
| self._cri = cros_interface.CrOSInterface()
|
| self._powermonitor = cros_power_monitor.CrosPowerMonitor(self)
|
| + self._InitialiseInteractiveBoost()
|
|
|
| @classmethod
|
| def IsPlatformBackendForHost(cls):
|
| @@ -168,3 +170,80 @@ class CrosPlatformBackend(
|
|
|
| def TakeScreenshot(self, file_path):
|
| return self._cri.TakeScreenshot(file_path)
|
| +
|
| + def _InitialiseInteractiveBoost(self):
|
| + """On ChromeOS on ARM, the kernel boosts CPU frequency when an input (key
|
| + press, touch event, etc) is received. For simulated inputs, this doesn't
|
| + happen, so this functionality activates the same boost mechanism by
|
| + using the sysfs controls.
|
| + The boost should be turned on for specific interaction events, for the
|
| + duration of the interaction, to simulate normal system behaviour.
|
| + On systems which do not support frequency boost, this has no effect
|
| + (consistent with normal non-simulated behaviour).
|
| + """
|
| + self._boost_duration = None
|
| + self._boost_timer = None
|
| + governor = self.GetFileContents(
|
| + "/sys/devices/system/cpu/cpu0/cpufreq/scaling_governor").strip()
|
| + if governor != "interactive":
|
| + logging.warning("no interactive cpufreq governor present, not setting"
|
| + " up interactivity boost")
|
| + return
|
| + core = 0
|
| + durations = {}
|
| + while True:
|
| + path = "/sys/devices/system/cpu/cpu" + str(core) + "/cpufreq/interactive"
|
| + if self.PathExists(path + "/boostpulse_duration") \
|
| + and self.PathExists(path + "/boostpulse"):
|
| + durations[core] = self.GetFileContents(path
|
| + + "/boostpulse_duration").strip()
|
| + else:
|
| + break
|
| + core = core + 1
|
| + if durations:
|
| + # Set timer to drive boost every 9 minutes. It lasts for 10 minutes
|
| + # so this ensures it will remain constantly on with minimal
|
| + # overhead, until turned off.
|
| + self._boost_timer = repeating_timer.RepeatingTimer(
|
| + lambda: self._WriteCPUFreqControl("boostpulse", "1"), 9 * 60)
|
| + self._boost_duration = durations
|
| + logging.info("interactivity boost set up")
|
| + else:
|
| + logging.info("kernel does not support frequency boost controls,"
|
| + "interactivity boost could not be set up")
|
| +
|
| + def _WriteCPUFreqControl(self, leaf, content):
|
| + if self._boost_duration is not None:
|
| + cmds = []
|
| + for core in self._boost_duration:
|
| + path = "/sys/devices/system/cpu/cpu" + str(core) \
|
| + + "/cpufreq/interactive"
|
| + value = content if not isinstance(content, dict) else content[core]
|
| + if cmds:
|
| + cmds.append(';')
|
| + cmds.extend(['echo', value, '>', path + "/" + leaf])
|
| + self.RunCommand(cmds)
|
| +
|
| + def SetInteractivityBoost(self, enable):
|
| + if self._boost_duration is not None \
|
| + and self._boost_timer.IsRunning() != enable:
|
| + logging.info('SetInteractivityBoost: %s boost on %d cores',
|
| + ("enabling" if enable else "disabling"), len(self._boost_duration))
|
| +
|
| + # enable a timer to initiate a regular boost pulse
|
| + #
|
| + # the boost pulse duration and timer are such that boost will remain
|
| + # constantly enabled
|
| + if enable:
|
| + # set the boost duration to 10 minutes
|
| + self._WriteCPUFreqControl("boostpulse_duration", "600000000")
|
| + self._WriteCPUFreqControl("boostpulse", "1")
|
| + self._boost_timer.Start()
|
| + else:
|
| + # set the boost duration back to the default setting if disabling.
|
| + self._WriteCPUFreqControl("boostpulse_duration", self._boost_duration)
|
| + self._boost_timer.Stop()
|
| + # this ensures that the pulse continues for the default pulse duration
|
| + # (typically 80 ms) after the input event ends - as would normally
|
| + # happen with real user interaction.
|
| + self._WriteCPUFreqControl("boostpulse", "1")
|
|
|