graphics_WebGLAquarium.py revision 23c7247fa5d1f7b59fb4c17303699c3f513191a8
1ab19e9793140c5bab16a2b865c796f0789c17446Ricky Liang# Copyright (c) 2013 The Chromium OS Authors. All rights reserved.
2ab19e9793140c5bab16a2b865c796f0789c17446Ricky Liang# Use of this source code is governed by a BSD-style license that can be
3ab19e9793140c5bab16a2b865c796f0789c17446Ricky Liang# found in the LICENSE file.
4639eddc6bf8bb76d102a3fc42833f806e177c3ecRicky Liang
5639eddc6bf8bb76d102a3fc42833f806e177c3ecRicky Liang"""This is a client side WebGL aquarium test.
6639eddc6bf8bb76d102a3fc42833f806e177c3ecRicky Liang
7639eddc6bf8bb76d102a3fc42833f806e177c3ecRicky LiangDescription of some of the test result output:
8639eddc6bf8bb76d102a3fc42833f806e177c3ecRicky Liang    - interframe time: The time elapsed between two frames. It is the elapsed
9639eddc6bf8bb76d102a3fc42833f806e177c3ecRicky Liang            time between two consecutive calls to the render() function.
10639eddc6bf8bb76d102a3fc42833f806e177c3ecRicky Liang    - render time: The time it takes in Javascript to construct a frame and
11639eddc6bf8bb76d102a3fc42833f806e177c3ecRicky Liang            submit all the GL commands. It is the time it takes for a render()
12639eddc6bf8bb76d102a3fc42833f806e177c3ecRicky Liang            function call to complete.
13639eddc6bf8bb76d102a3fc42833f806e177c3ecRicky Liang"""
14ab19e9793140c5bab16a2b865c796f0789c17446Ricky Liang
15ab19e9793140c5bab16a2b865c796f0789c17446Ricky Liangimport logging
16ff9c82b221cbc0cc9d4951fc609479d826067d33Salva Climentimport math
17ab19e9793140c5bab16a2b865c796f0789c17446Ricky Liangimport os
18ff9c82b221cbc0cc9d4951fc609479d826067d33Salva Climentimport sampler
19ab19e9793140c5bab16a2b865c796f0789c17446Ricky Liangimport threading
20ab19e9793140c5bab16a2b865c796f0789c17446Ricky Liangimport time
21ab19e9793140c5bab16a2b865c796f0789c17446Ricky Liang
22ab19e9793140c5bab16a2b865c796f0789c17446Ricky Liangfrom autotest_lib.client.bin import test, utils
23ff9c82b221cbc0cc9d4951fc609479d826067d33Salva Climentfrom autotest_lib.client.common_lib import error
24ab19e9793140c5bab16a2b865c796f0789c17446Ricky Liangfrom autotest_lib.client.common_lib.cros import chrome
2567eac4d97a9e69f3fbe52c78b4d7f7fa35cfe562Ilja H. Friedelfrom autotest_lib.client.cros.graphics import graphics_utils
26e96b8f8d31f21f30028d7d544c82d3817295c8f5Rohit Makasanafrom autotest_lib.client.cros import power_status, power_utils
27e96b8f8d31f21f30028d7d544c82d3817295c8f5Rohit Makasanafrom autotest_lib.client.cros import service_stopper
28e96b8f8d31f21f30028d7d544c82d3817295c8f5Rohit Makasana
29e96b8f8d31f21f30028d7d544c82d3817295c8f5Rohit Makasana# Minimum battery charge percentage to run the test
30e96b8f8d31f21f30028d7d544c82d3817295c8f5Rohit MakasanaBATTERY_INITIAL_CHARGED_MIN = 10
31e96b8f8d31f21f30028d7d544c82d3817295c8f5Rohit Makasana
32e96b8f8d31f21f30028d7d544c82d3817295c8f5Rohit Makasana# Measurement duration in seconds.
33e96b8f8d31f21f30028d7d544c82d3817295c8f5Rohit MakasanaMEASUREMENT_DURATION = 30
34e96b8f8d31f21f30028d7d544c82d3817295c8f5Rohit Makasana
35e96b8f8d31f21f30028d7d544c82d3817295c8f5Rohit MakasanaPOWER_DESCRIPTION = 'avg_energy_rate_1000_fishes'
36e96b8f8d31f21f30028d7d544c82d3817295c8f5Rohit Makasana
37e96b8f8d31f21f30028d7d544c82d3817295c8f5Rohit Makasana# Time to exclude from calculation after playing a webgl demo [seconds].
38e96b8f8d31f21f30028d7d544c82d3817295c8f5Rohit MakasanaSTABILIZATION_DURATION = 10
39ab19e9793140c5bab16a2b865c796f0789c17446Ricky Liang
40ab19e9793140c5bab16a2b865c796f0789c17446Ricky Liang
41ab19e9793140c5bab16a2b865c796f0789c17446Ricky Liangclass graphics_WebGLAquarium(test.test):
42ab19e9793140c5bab16a2b865c796f0789c17446Ricky Liang    """WebGL aquarium graphics test."""
43ab19e9793140c5bab16a2b865c796f0789c17446Ricky Liang    version = 1
44a004701bd4ea9c695fbc4e5d9896061e0811512aIlja H. Friedel
45a004701bd4ea9c695fbc4e5d9896061e0811512aIlja H. Friedel    _backlight = None
46a004701bd4ea9c695fbc4e5d9896061e0811512aIlja H. Friedel    _power_status = None
47a004701bd4ea9c695fbc4e5d9896061e0811512aIlja H. Friedel    _service_stopper = None
48a004701bd4ea9c695fbc4e5d9896061e0811512aIlja H. Friedel    _test_power = False
49a004701bd4ea9c695fbc4e5d9896061e0811512aIlja H. Friedel    active_tab = None
50a004701bd4ea9c695fbc4e5d9896061e0811512aIlja H. Friedel    flip_stats = {}
5167eac4d97a9e69f3fbe52c78b4d7f7fa35cfe562Ilja H. Friedel    GSC = None
52a004701bd4ea9c695fbc4e5d9896061e0811512aIlja H. Friedel    kernel_sampler = None
53a004701bd4ea9c695fbc4e5d9896061e0811512aIlja H. Friedel    perf_keyval = {}
54a004701bd4ea9c695fbc4e5d9896061e0811512aIlja H. Friedel    sampler_lock = None
55a004701bd4ea9c695fbc4e5d9896061e0811512aIlja H. Friedel    test_duration_secs = 30
56a004701bd4ea9c695fbc4e5d9896061e0811512aIlja H. Friedel    test_setting_num_fishes = 50
57a004701bd4ea9c695fbc4e5d9896061e0811512aIlja H. Friedel    test_settings = {50: ('setSetting2', 2), 1000: ('setSetting6', 6),}
58ab19e9793140c5bab16a2b865c796f0789c17446Ricky Liang
59ab19e9793140c5bab16a2b865c796f0789c17446Ricky Liang    def setup(self):
60ab19e9793140c5bab16a2b865c796f0789c17446Ricky Liang        tarball_path = os.path.join(self.bindir,
61ab19e9793140c5bab16a2b865c796f0789c17446Ricky Liang                                    'webgl_aquarium_static.tar.bz2')
62ab19e9793140c5bab16a2b865c796f0789c17446Ricky Liang        utils.extract_tarball_to_dir(tarball_path, self.srcdir)
63ab19e9793140c5bab16a2b865c796f0789c17446Ricky Liang
64ab19e9793140c5bab16a2b865c796f0789c17446Ricky Liang    def initialize(self):
6567eac4d97a9e69f3fbe52c78b4d7f7fa35cfe562Ilja H. Friedel        self.GSC = graphics_utils.GraphicsStateChecker()
66ab19e9793140c5bab16a2b865c796f0789c17446Ricky Liang        self.sampler_lock = threading.Lock()
67a004701bd4ea9c695fbc4e5d9896061e0811512aIlja H. Friedel        # TODO: Create samplers for other platforms (e.g. x86).
68ab19e9793140c5bab16a2b865c796f0789c17446Ricky Liang        if utils.get_board().lower() in ['daisy', 'daisy_spring']:
69ab19e9793140c5bab16a2b865c796f0789c17446Ricky Liang            # Enable ExynosSampler on Exynos platforms.  The sampler looks for
70ab19e9793140c5bab16a2b865c796f0789c17446Ricky Liang            # exynos-drm page flip states: 'wait_kds', 'rendered', 'prepared',
71ab19e9793140c5bab16a2b865c796f0789c17446Ricky Liang            # and 'flipped' in kernel debugfs.
72ab19e9793140c5bab16a2b865c796f0789c17446Ricky Liang
73ab19e9793140c5bab16a2b865c796f0789c17446Ricky Liang            # Sample 3-second durtaion for every 5 seconds.
74ab19e9793140c5bab16a2b865c796f0789c17446Ricky Liang            self.kernel_sampler = sampler.ExynosSampler(period=5, duration=3)
75ab19e9793140c5bab16a2b865c796f0789c17446Ricky Liang            self.kernel_sampler.sampler_callback = self.exynos_sampler_callback
76ab19e9793140c5bab16a2b865c796f0789c17446Ricky Liang            self.kernel_sampler.output_flip_stats = (
77639eddc6bf8bb76d102a3fc42833f806e177c3ecRicky Liang                    self.exynos_output_flip_stats)
78ab19e9793140c5bab16a2b865c796f0789c17446Ricky Liang
7967eac4d97a9e69f3fbe52c78b4d7f7fa35cfe562Ilja H. Friedel    def cleanup(self):
80e96b8f8d31f21f30028d7d544c82d3817295c8f5Rohit Makasana        if self._backlight:
81e96b8f8d31f21f30028d7d544c82d3817295c8f5Rohit Makasana            self._backlight.restore()
82d13b4f4ca7223700c649413393506a89d6c3cfcdRohit Makasana        if self._service_stopper:
83d13b4f4ca7223700c649413393506a89d6c3cfcdRohit Makasana            self._service_stopper.restore_services()
8467eac4d97a9e69f3fbe52c78b4d7f7fa35cfe562Ilja H. Friedel        if self.GSC:
8567eac4d97a9e69f3fbe52c78b4d7f7fa35cfe562Ilja H. Friedel            keyvals = self.GSC.get_memory_keyvals()
86e96b8f8d31f21f30028d7d544c82d3817295c8f5Rohit Makasana            if not self._test_power:
87e96b8f8d31f21f30028d7d544c82d3817295c8f5Rohit Makasana                for key, val in keyvals.iteritems():
88a004701bd4ea9c695fbc4e5d9896061e0811512aIlja H. Friedel                    self.output_perf_value(description=key,
89a004701bd4ea9c695fbc4e5d9896061e0811512aIlja H. Friedel                                           value=val,
90e96b8f8d31f21f30028d7d544c82d3817295c8f5Rohit Makasana                                           units='bytes',
91e96b8f8d31f21f30028d7d544c82d3817295c8f5Rohit Makasana                                           higher_is_better=False)
9267eac4d97a9e69f3fbe52c78b4d7f7fa35cfe562Ilja H. Friedel            self.GSC.finalize()
9367eac4d97a9e69f3fbe52c78b4d7f7fa35cfe562Ilja H. Friedel            self.write_perf_keyval(keyvals)
9467eac4d97a9e69f3fbe52c78b4d7f7fa35cfe562Ilja H. Friedel
95e96b8f8d31f21f30028d7d544c82d3817295c8f5Rohit Makasana    def run_fish_test(self, browser, test_url, num_fishes, perf_log=True):
96ab19e9793140c5bab16a2b865c796f0789c17446Ricky Liang        """Run the test with the given number of fishes.
97ab19e9793140c5bab16a2b865c796f0789c17446Ricky Liang
98ab19e9793140c5bab16a2b865c796f0789c17446Ricky Liang        @param browser: The Browser object to run the test with.
99ab19e9793140c5bab16a2b865c796f0789c17446Ricky Liang        @param test_url: The URL to the aquarium test site.
100ab19e9793140c5bab16a2b865c796f0789c17446Ricky Liang        @param num_fishes: The number of fishes to run the test with.
101e96b8f8d31f21f30028d7d544c82d3817295c8f5Rohit Makasana        @param perf_log: Report perf data only if it's set to True.
102ab19e9793140c5bab16a2b865c796f0789c17446Ricky Liang        """
103ab19e9793140c5bab16a2b865c796f0789c17446Ricky Liang        # Create tab and load page. Set the number of fishes when page is fully
104ab19e9793140c5bab16a2b865c796f0789c17446Ricky Liang        # loaded.
105ab19e9793140c5bab16a2b865c796f0789c17446Ricky Liang        tab = browser.tabs.New()
106ab19e9793140c5bab16a2b865c796f0789c17446Ricky Liang        tab.Navigate(test_url)
107ab19e9793140c5bab16a2b865c796f0789c17446Ricky Liang        tab.Activate()
108ab19e9793140c5bab16a2b865c796f0789c17446Ricky Liang        self.active_tab = tab
109b55c3a375c3584cb18c0c8249aab8095b7eb23eeIlja H. Friedel        tab.WaitForDocumentReadyStateToBeComplete()
110ab19e9793140c5bab16a2b865c796f0789c17446Ricky Liang
111ab19e9793140c5bab16a2b865c796f0789c17446Ricky Liang        # Set the number of fishes when document finishes loading.  Also reset
112ab19e9793140c5bab16a2b865c796f0789c17446Ricky Liang        # our own FPS counter and start recording FPS and rendering time.
113a004701bd4ea9c695fbc4e5d9896061e0811512aIlja H. Friedel        utils.wait_for_value(
114639eddc6bf8bb76d102a3fc42833f806e177c3ecRicky Liang                lambda: tab.EvaluateJavaScript(
115639eddc6bf8bb76d102a3fc42833f806e177c3ecRicky Liang                        'if (document.readyState === "complete") {'
116639eddc6bf8bb76d102a3fc42833f806e177c3ecRicky Liang                        '  setSetting(document.getElementById("%s"), %d);'
117639eddc6bf8bb76d102a3fc42833f806e177c3ecRicky Liang                        '  g_crosFpsCounter.reset();'
118639eddc6bf8bb76d102a3fc42833f806e177c3ecRicky Liang                        '  true;'
119639eddc6bf8bb76d102a3fc42833f806e177c3ecRicky Liang                        '} else {'
120639eddc6bf8bb76d102a3fc42833f806e177c3ecRicky Liang                        '  false;'
121639eddc6bf8bb76d102a3fc42833f806e177c3ecRicky Liang                        '}' % self.test_settings[num_fishes]),
122639eddc6bf8bb76d102a3fc42833f806e177c3ecRicky Liang                expected_value=True,
123639eddc6bf8bb76d102a3fc42833f806e177c3ecRicky Liang                timeout_sec=30)
124ab19e9793140c5bab16a2b865c796f0789c17446Ricky Liang
125ab19e9793140c5bab16a2b865c796f0789c17446Ricky Liang        if self.kernel_sampler:
126ab19e9793140c5bab16a2b865c796f0789c17446Ricky Liang            self.kernel_sampler.start_sampling_thread()
127ab19e9793140c5bab16a2b865c796f0789c17446Ricky Liang        time.sleep(self.test_duration_secs)
128ab19e9793140c5bab16a2b865c796f0789c17446Ricky Liang        if self.kernel_sampler:
129ab19e9793140c5bab16a2b865c796f0789c17446Ricky Liang            self.kernel_sampler.stop_sampling_thread()
130a004701bd4ea9c695fbc4e5d9896061e0811512aIlja H. Friedel            self.kernel_sampler.output_flip_stats('flip_stats_%d' % num_fishes)
131ab19e9793140c5bab16a2b865c796f0789c17446Ricky Liang            self.flip_stats = {}
132ab19e9793140c5bab16a2b865c796f0789c17446Ricky Liang
13323c7247fa5d1f7b59fb4c17303699c3f513191a8Todd Broch        # Get average FPS and rendering time, then close the tab.
13423c7247fa5d1f7b59fb4c17303699c3f513191a8Todd Broch        avg_fps = tab.EvaluateJavaScript('g_crosFpsCounter.getAvgFps();')
13523c7247fa5d1f7b59fb4c17303699c3f513191a8Todd Broch        if math.isnan(float(avg_fps)):
13623c7247fa5d1f7b59fb4c17303699c3f513191a8Todd Broch            raise error.TestFail('Could not get FPS count.')
13723c7247fa5d1f7b59fb4c17303699c3f513191a8Todd Broch
13823c7247fa5d1f7b59fb4c17303699c3f513191a8Todd Broch        avg_interframe_time = tab.EvaluateJavaScript(
13923c7247fa5d1f7b59fb4c17303699c3f513191a8Todd Broch                'g_crosFpsCounter.getAvgInterFrameTime();')
14023c7247fa5d1f7b59fb4c17303699c3f513191a8Todd Broch        avg_render_time = tab.EvaluateJavaScript(
14123c7247fa5d1f7b59fb4c17303699c3f513191a8Todd Broch                'g_crosFpsCounter.getAvgRenderTime();')
14223c7247fa5d1f7b59fb4c17303699c3f513191a8Todd Broch        std_interframe_time = tab.EvaluateJavaScript(
14323c7247fa5d1f7b59fb4c17303699c3f513191a8Todd Broch                'g_crosFpsCounter.getStdInterFrameTime();')
14423c7247fa5d1f7b59fb4c17303699c3f513191a8Todd Broch        std_render_time = tab.EvaluateJavaScript(
14523c7247fa5d1f7b59fb4c17303699c3f513191a8Todd Broch                'g_crosFpsCounter.getStdRenderTime();')
14623c7247fa5d1f7b59fb4c17303699c3f513191a8Todd Broch        self.perf_keyval['avg_fps_%04d_fishes' % num_fishes] = avg_fps
14723c7247fa5d1f7b59fb4c17303699c3f513191a8Todd Broch        self.perf_keyval['avg_interframe_time_%04d_fishes' % num_fishes] = (
14823c7247fa5d1f7b59fb4c17303699c3f513191a8Todd Broch                avg_interframe_time)
14923c7247fa5d1f7b59fb4c17303699c3f513191a8Todd Broch        self.perf_keyval['avg_render_time_%04d_fishes' % num_fishes] = (
15023c7247fa5d1f7b59fb4c17303699c3f513191a8Todd Broch                avg_render_time)
15123c7247fa5d1f7b59fb4c17303699c3f513191a8Todd Broch        self.perf_keyval['std_interframe_time_%04d_fishes' % num_fishes] = (
15223c7247fa5d1f7b59fb4c17303699c3f513191a8Todd Broch                std_interframe_time)
15323c7247fa5d1f7b59fb4c17303699c3f513191a8Todd Broch        self.perf_keyval['std_render_time_%04d_fishes' % num_fishes] = (
15423c7247fa5d1f7b59fb4c17303699c3f513191a8Todd Broch                std_render_time)
15523c7247fa5d1f7b59fb4c17303699c3f513191a8Todd Broch        logging.info('%d fish(es): Average FPS = %f, '
15623c7247fa5d1f7b59fb4c17303699c3f513191a8Todd Broch                     'average render time = %f', num_fishes, avg_fps,
15723c7247fa5d1f7b59fb4c17303699c3f513191a8Todd Broch                     avg_render_time)
158e96b8f8d31f21f30028d7d544c82d3817295c8f5Rohit Makasana        if perf_log:
159a004701bd4ea9c695fbc4e5d9896061e0811512aIlja H. Friedel            self.output_perf_value(
160639eddc6bf8bb76d102a3fc42833f806e177c3ecRicky Liang                    description='avg_fps_%04d_fishes' % num_fishes,
161639eddc6bf8bb76d102a3fc42833f806e177c3ecRicky Liang                    value=avg_fps,
162639eddc6bf8bb76d102a3fc42833f806e177c3ecRicky Liang                    units='fps',
163639eddc6bf8bb76d102a3fc42833f806e177c3ecRicky Liang                    higher_is_better=True)
164e96b8f8d31f21f30028d7d544c82d3817295c8f5Rohit Makasana
16523c7247fa5d1f7b59fb4c17303699c3f513191a8Todd Broch    def run_power_test(self, browser, test_url, ac_ok):
166a004701bd4ea9c695fbc4e5d9896061e0811512aIlja H. Friedel        """Runs the webgl power consumption test and reports the perf results.
167e96b8f8d31f21f30028d7d544c82d3817295c8f5Rohit Makasana
168e96b8f8d31f21f30028d7d544c82d3817295c8f5Rohit Makasana        @param browser: The Browser object to run the test with.
169e96b8f8d31f21f30028d7d544c82d3817295c8f5Rohit Makasana        @param test_url: The URL to the aquarium test site.
17023c7247fa5d1f7b59fb4c17303699c3f513191a8Todd Broch        @param ac_ok: Boolean on whether its ok to have AC power supplied.
171e96b8f8d31f21f30028d7d544c82d3817295c8f5Rohit Makasana        """
172e96b8f8d31f21f30028d7d544c82d3817295c8f5Rohit Makasana
173e96b8f8d31f21f30028d7d544c82d3817295c8f5Rohit Makasana        self._backlight = power_utils.Backlight()
174e96b8f8d31f21f30028d7d544c82d3817295c8f5Rohit Makasana        self._backlight.set_default()
175e96b8f8d31f21f30028d7d544c82d3817295c8f5Rohit Makasana
176e96b8f8d31f21f30028d7d544c82d3817295c8f5Rohit Makasana        self._service_stopper = service_stopper.ServiceStopper(
177639eddc6bf8bb76d102a3fc42833f806e177c3ecRicky Liang                service_stopper.ServiceStopper.POWER_DRAW_SERVICES)
178e96b8f8d31f21f30028d7d544c82d3817295c8f5Rohit Makasana        self._service_stopper.stop_services()
179e96b8f8d31f21f30028d7d544c82d3817295c8f5Rohit Makasana
18023c7247fa5d1f7b59fb4c17303699c3f513191a8Todd Broch        if not ac_ok:
18123c7247fa5d1f7b59fb4c17303699c3f513191a8Todd Broch            self._power_status = power_status.get_status()
18223c7247fa5d1f7b59fb4c17303699c3f513191a8Todd Broch            # Verify that we are running on battery and the battery is
18323c7247fa5d1f7b59fb4c17303699c3f513191a8Todd Broch            # sufficiently charged.
18423c7247fa5d1f7b59fb4c17303699c3f513191a8Todd Broch            self._power_status.assert_battery_state(BATTERY_INITIAL_CHARGED_MIN)
185e96b8f8d31f21f30028d7d544c82d3817295c8f5Rohit Makasana
18623c7247fa5d1f7b59fb4c17303699c3f513191a8Todd Broch            measurements = [
18723c7247fa5d1f7b59fb4c17303699c3f513191a8Todd Broch                power_status.SystemPower(self._power_status.battery_path)
18823c7247fa5d1f7b59fb4c17303699c3f513191a8Todd Broch            ]
189e96b8f8d31f21f30028d7d544c82d3817295c8f5Rohit Makasana
190e96b8f8d31f21f30028d7d544c82d3817295c8f5Rohit Makasana        def get_power():
191e96b8f8d31f21f30028d7d544c82d3817295c8f5Rohit Makasana            power_logger = power_status.PowerLogger(measurements)
192e96b8f8d31f21f30028d7d544c82d3817295c8f5Rohit Makasana            power_logger.start()
193e96b8f8d31f21f30028d7d544c82d3817295c8f5Rohit Makasana            time.sleep(STABILIZATION_DURATION)
194e96b8f8d31f21f30028d7d544c82d3817295c8f5Rohit Makasana            start_time = time.time()
195e96b8f8d31f21f30028d7d544c82d3817295c8f5Rohit Makasana            time.sleep(MEASUREMENT_DURATION)
196e96b8f8d31f21f30028d7d544c82d3817295c8f5Rohit Makasana            power_logger.checkpoint('result', start_time)
197e96b8f8d31f21f30028d7d544c82d3817295c8f5Rohit Makasana            keyval = power_logger.calc()
198e96b8f8d31f21f30028d7d544c82d3817295c8f5Rohit Makasana            logging.info('Power output %s', keyval)
199e96b8f8d31f21f30028d7d544c82d3817295c8f5Rohit Makasana            return keyval['result_' + measurements[0].domain + '_pwr']
200e96b8f8d31f21f30028d7d544c82d3817295c8f5Rohit Makasana
201e96b8f8d31f21f30028d7d544c82d3817295c8f5Rohit Makasana        self.run_fish_test(browser, test_url, 1000, perf_log=False)
20223c7247fa5d1f7b59fb4c17303699c3f513191a8Todd Broch        if not ac_ok:
20323c7247fa5d1f7b59fb4c17303699c3f513191a8Todd Broch            energy_rate = get_power()
20423c7247fa5d1f7b59fb4c17303699c3f513191a8Todd Broch            # This is a power specific test so we are not capturing
20523c7247fa5d1f7b59fb4c17303699c3f513191a8Todd Broch            # avg_fps and avg_render_time in this test.
20623c7247fa5d1f7b59fb4c17303699c3f513191a8Todd Broch            self.perf_keyval[POWER_DESCRIPTION] = energy_rate
20723c7247fa5d1f7b59fb4c17303699c3f513191a8Todd Broch            self.output_perf_value(description=POWER_DESCRIPTION,
20823c7247fa5d1f7b59fb4c17303699c3f513191a8Todd Broch                                   value=energy_rate,
20923c7247fa5d1f7b59fb4c17303699c3f513191a8Todd Broch                                   units='W',
21023c7247fa5d1f7b59fb4c17303699c3f513191a8Todd Broch                                   higher_is_better=False)
21123c7247fa5d1f7b59fb4c17303699c3f513191a8Todd Broch
212e96b8f8d31f21f30028d7d544c82d3817295c8f5Rohit Makasana
213ab19e9793140c5bab16a2b865c796f0789c17446Ricky Liang    def exynos_sampler_callback(self, sampler_obj):
214ab19e9793140c5bab16a2b865c796f0789c17446Ricky Liang        """Sampler callback function for ExynosSampler.
215ab19e9793140c5bab16a2b865c796f0789c17446Ricky Liang
216ab19e9793140c5bab16a2b865c796f0789c17446Ricky Liang        @param sampler_obj: The ExynosSampler object that invokes this callback
217ab19e9793140c5bab16a2b865c796f0789c17446Ricky Liang                function.
218ab19e9793140c5bab16a2b865c796f0789c17446Ricky Liang        """
219ab19e9793140c5bab16a2b865c796f0789c17446Ricky Liang        if sampler_obj.stopped:
220ab19e9793140c5bab16a2b865c796f0789c17446Ricky Liang            return
221ab19e9793140c5bab16a2b865c796f0789c17446Ricky Liang
222ab19e9793140c5bab16a2b865c796f0789c17446Ricky Liang        with self.sampler_lock:
223ab19e9793140c5bab16a2b865c796f0789c17446Ricky Liang            now = time.time()
224ab19e9793140c5bab16a2b865c796f0789c17446Ricky Liang            results = {}
225ab19e9793140c5bab16a2b865c796f0789c17446Ricky Liang            info_str = ['\nfb_id wait_kds flipped']
226ab19e9793140c5bab16a2b865c796f0789c17446Ricky Liang            for value in sampler_obj.frame_buffers.itervalues():
227ab19e9793140c5bab16a2b865c796f0789c17446Ricky Liang                results[value.fb] = {}
228ab19e9793140c5bab16a2b865c796f0789c17446Ricky Liang                for state, stats in value.states.iteritems():
229ab19e9793140c5bab16a2b865c796f0789c17446Ricky Liang                    results[value.fb][state] = (stats.avg, stats.stdev)
230a004701bd4ea9c695fbc4e5d9896061e0811512aIlja H. Friedel                info_str.append('%s: %s %s' %
231a004701bd4ea9c695fbc4e5d9896061e0811512aIlja H. Friedel                                (value.fb, results[value.fb]['wait_kds'][0],
232a004701bd4ea9c695fbc4e5d9896061e0811512aIlja H. Friedel                                 results[value.fb]['flipped'][0]))
233ab19e9793140c5bab16a2b865c796f0789c17446Ricky Liang            results['avg_fps'] = self.active_tab.EvaluateJavaScript(
234639eddc6bf8bb76d102a3fc42833f806e177c3ecRicky Liang                    'g_crosFpsCounter.getAvgFps();')
235ab19e9793140c5bab16a2b865c796f0789c17446Ricky Liang            results['avg_render_time'] = self.active_tab.EvaluateJavaScript(
236639eddc6bf8bb76d102a3fc42833f806e177c3ecRicky Liang                    'g_crosFpsCounter.getAvgRenderTime();')
237ab19e9793140c5bab16a2b865c796f0789c17446Ricky Liang            self.active_tab.ExecuteJavaScript('g_crosFpsCounter.reset();')
238ab19e9793140c5bab16a2b865c796f0789c17446Ricky Liang            info_str.append('avg_fps: %s, avg_render_time: %s' %
239ab19e9793140c5bab16a2b865c796f0789c17446Ricky Liang                            (results['avg_fps'], results['avg_render_time']))
240ab19e9793140c5bab16a2b865c796f0789c17446Ricky Liang            self.flip_stats[now] = results
241ab19e9793140c5bab16a2b865c796f0789c17446Ricky Liang            logging.info('\n'.join(info_str))
242ab19e9793140c5bab16a2b865c796f0789c17446Ricky Liang
243ab19e9793140c5bab16a2b865c796f0789c17446Ricky Liang    def exynos_output_flip_stats(self, file_name):
244ab19e9793140c5bab16a2b865c796f0789c17446Ricky Liang        """Pageflip statistics output function for ExynosSampler.
245ab19e9793140c5bab16a2b865c796f0789c17446Ricky Liang
246ab19e9793140c5bab16a2b865c796f0789c17446Ricky Liang        @param file_name: The output file name.
247ab19e9793140c5bab16a2b865c796f0789c17446Ricky Liang        """
248ab19e9793140c5bab16a2b865c796f0789c17446Ricky Liang        # output format:
249ab19e9793140c5bab16a2b865c796f0789c17446Ricky Liang        # time fb_id avg_rendered avg_prepared avg_wait_kds avg_flipped
250ab19e9793140c5bab16a2b865c796f0789c17446Ricky Liang        # std_rendered std_prepared std_wait_kds std_flipped
251ab19e9793140c5bab16a2b865c796f0789c17446Ricky Liang        with open(file_name, 'w') as f:
252ab19e9793140c5bab16a2b865c796f0789c17446Ricky Liang            for t in sorted(self.flip_stats.keys()):
253ab19e9793140c5bab16a2b865c796f0789c17446Ricky Liang                if ('avg_fps' in self.flip_stats[t] and
254639eddc6bf8bb76d102a3fc42833f806e177c3ecRicky Liang                    'avg_render_time' in self.flip_stats[t]):
255a004701bd4ea9c695fbc4e5d9896061e0811512aIlja H. Friedel                    f.write('%s %s %s\n' %
256a004701bd4ea9c695fbc4e5d9896061e0811512aIlja H. Friedel                            (t, self.flip_stats[t]['avg_fps'],
257a004701bd4ea9c695fbc4e5d9896061e0811512aIlja H. Friedel                             self.flip_stats[t]['avg_render_time']))
258ab19e9793140c5bab16a2b865c796f0789c17446Ricky Liang                for fb, stats in self.flip_stats[t].iteritems():
259ab19e9793140c5bab16a2b865c796f0789c17446Ricky Liang                    if not isinstance(fb, int):
260ab19e9793140c5bab16a2b865c796f0789c17446Ricky Liang                        continue
261ab19e9793140c5bab16a2b865c796f0789c17446Ricky Liang                    f.write('%s %s ' % (t, fb))
262ab19e9793140c5bab16a2b865c796f0789c17446Ricky Liang                    f.write('%s %s %s %s ' % (stats['rendered'][0],
263ab19e9793140c5bab16a2b865c796f0789c17446Ricky Liang                                              stats['prepared'][0],
264ab19e9793140c5bab16a2b865c796f0789c17446Ricky Liang                                              stats['wait_kds'][0],
265ab19e9793140c5bab16a2b865c796f0789c17446Ricky Liang                                              stats['flipped'][0]))
266ab19e9793140c5bab16a2b865c796f0789c17446Ricky Liang                    f.write('%s %s %s %s\n' % (stats['rendered'][1],
267ab19e9793140c5bab16a2b865c796f0789c17446Ricky Liang                                               stats['prepared'][1],
268ab19e9793140c5bab16a2b865c796f0789c17446Ricky Liang                                               stats['wait_kds'][1],
269ab19e9793140c5bab16a2b865c796f0789c17446Ricky Liang                                               stats['flipped'][1]))
270a004701bd4ea9c695fbc4e5d9896061e0811512aIlja H. Friedel    def run_once(self,
271a004701bd4ea9c695fbc4e5d9896061e0811512aIlja H. Friedel                 test_duration_secs=30,
272a004701bd4ea9c695fbc4e5d9896061e0811512aIlja H. Friedel                 test_setting_num_fishes=(50, 1000),
27323c7247fa5d1f7b59fb4c17303699c3f513191a8Todd Broch                 power_test=False, ac_ok=False):
274ab19e9793140c5bab16a2b865c796f0789c17446Ricky Liang        """Find a brower with telemetry, and run the test.
275ab19e9793140c5bab16a2b865c796f0789c17446Ricky Liang
276ab19e9793140c5bab16a2b865c796f0789c17446Ricky Liang        @param test_duration_secs: The duration in seconds to run each scenario
277ab19e9793140c5bab16a2b865c796f0789c17446Ricky Liang                for.
278ab19e9793140c5bab16a2b865c796f0789c17446Ricky Liang        @param test_setting_num_fishes: A list of the numbers of fishes to
279ab19e9793140c5bab16a2b865c796f0789c17446Ricky Liang                enable in the test.
28023c7247fa5d1f7b59fb4c17303699c3f513191a8Todd Broch        @param power_test: Boolean on whether to run power_test
28123c7247fa5d1f7b59fb4c17303699c3f513191a8Todd Broch        @param ac_ok: Boolean on whether its ok to have AC power supplied.
282ab19e9793140c5bab16a2b865c796f0789c17446Ricky Liang        """
283ab19e9793140c5bab16a2b865c796f0789c17446Ricky Liang        self.test_duration_secs = test_duration_secs
284ab19e9793140c5bab16a2b865c796f0789c17446Ricky Liang        self.test_setting_num_fishes = test_setting_num_fishes
285ab19e9793140c5bab16a2b865c796f0789c17446Ricky Liang
2862d4a164e8e583d365bb5fff12defd56687238ee7Ilja Friedel        with chrome.Chrome(logged_in=False) as cr:
287ef97bb821022be8e3930658f2f7e8c3a6daa3e4bRicky Liang            try:
288ef97bb821022be8e3930658f2f7e8c3a6daa3e4bRicky Liang                cr.browser.platform.SetHTTPServerDirectories(self.srcdir)
289ef97bb821022be8e3930658f2f7e8c3a6daa3e4bRicky Liang                test_url = cr.browser.platform.http_server.UrlOf(os.path.join(
290639eddc6bf8bb76d102a3fc42833f806e177c3ecRicky Liang                        self.srcdir, 'aquarium.html'))
291ef97bb821022be8e3930658f2f7e8c3a6daa3e4bRicky Liang
292ef97bb821022be8e3930658f2f7e8c3a6daa3e4bRicky Liang                if not utils.wait_for_idle_cpu(60.0, 0.1):
293ef97bb821022be8e3930658f2f7e8c3a6daa3e4bRicky Liang                    if not utils.wait_for_idle_cpu(20.0, 0.2):
294ef97bb821022be8e3930658f2f7e8c3a6daa3e4bRicky Liang                        raise error.TestFail('Could not get idle CPU.')
295ef97bb821022be8e3930658f2f7e8c3a6daa3e4bRicky Liang                if not utils.wait_for_cool_machine():
296ef97bb821022be8e3930658f2f7e8c3a6daa3e4bRicky Liang                    raise error.TestFail('Could not get cold machine.')
297ef97bb821022be8e3930658f2f7e8c3a6daa3e4bRicky Liang                if power_test:
298ef97bb821022be8e3930658f2f7e8c3a6daa3e4bRicky Liang                    self._test_power = True
29923c7247fa5d1f7b59fb4c17303699c3f513191a8Todd Broch                    self.run_power_test(cr.browser, test_url, ac_ok)
300e96b8f8d31f21f30028d7d544c82d3817295c8f5Rohit Makasana                    with self.sampler_lock:
301e96b8f8d31f21f30028d7d544c82d3817295c8f5Rohit Makasana                        self.active_tab.Close()
302e96b8f8d31f21f30028d7d544c82d3817295c8f5Rohit Makasana                        self.active_tab = None
303ef97bb821022be8e3930658f2f7e8c3a6daa3e4bRicky Liang                else:
304ef97bb821022be8e3930658f2f7e8c3a6daa3e4bRicky Liang                    for n in self.test_setting_num_fishes:
305ef97bb821022be8e3930658f2f7e8c3a6daa3e4bRicky Liang                        self.run_fish_test(cr.browser, test_url, n)
306ef97bb821022be8e3930658f2f7e8c3a6daa3e4bRicky Liang                        # Do not close the tab when the sampler_callback is
307ef97bb821022be8e3930658f2f7e8c3a6daa3e4bRicky Liang                        # doing his work.
308ef97bb821022be8e3930658f2f7e8c3a6daa3e4bRicky Liang                        with self.sampler_lock:
309ef97bb821022be8e3930658f2f7e8c3a6daa3e4bRicky Liang                            self.active_tab.Close()
310ef97bb821022be8e3930658f2f7e8c3a6daa3e4bRicky Liang                            self.active_tab = None
311ef97bb821022be8e3930658f2f7e8c3a6daa3e4bRicky Liang            finally:
312ef97bb821022be8e3930658f2f7e8c3a6daa3e4bRicky Liang                cr.browser.platform.StopAllLocalServers()
313ab19e9793140c5bab16a2b865c796f0789c17446Ricky Liang        self.write_perf_keyval(self.perf_keyval)
314