[Telemetry] Remove support for automatic record creation in smoothness controller.

Add logic to make sure that page sets paired with
smoothness/repaint only have interaction records with same label & they have repeatable flags enabled.

To make sure that this doesn't crash any smoothness
benchmarks, I modified benchmark_smoke_unittest to run all
smoothness benchmarks (including ones that only support
android) in patch #3. To validate the test runs, see
telemetry_perf_unittest's result in patch #5

smoothness.key_silk_cases: https://codereview.chromium.org/1111543002/

smoothness.polymer:
https://codereview.chromium.org/1060583012

BUG=444701,444703

Review URL: https://codereview.chromium.org/1104573002

Cr-Commit-Position: refs/heads/master@{#327186}
diff --git a/tools/perf/benchmarks/smoothness.py b/tools/perf/benchmarks/smoothness.py
index d9b02b9..c8379c4 100644
--- a/tools/perf/benchmarks/smoothness.py
+++ b/tools/perf/benchmarks/smoothness.py
@@ -77,9 +77,6 @@
   def Name(cls):
     return 'smoothness.maps'
 
-  def CreatePageTest(self, options):  # pylint: disable=unused-argument
-    return smoothness.Smoothness(enable_auto_issuing_marker=False)
-
 
 @benchmark.Disabled('android')
 class SmoothnessKeyDesktopMoveCases(benchmark.Benchmark):
@@ -97,15 +94,13 @@
 
   http://www.chromium.org/developers/design-documents/rendering-benchmarks
   """
+  test = smoothness.Smoothness
   page_set = page_sets.KeyMobileSitesSmoothPageSet
 
   @classmethod
   def Name(cls):
     return 'smoothness.key_mobile_sites_smooth'
 
-  def CreatePageTest(self, options):  # pylint: disable=unused-argument
-    return smoothness.Smoothness(enable_auto_issuing_marker=False)
-
 
 class SmoothnessToughAnimationCases(benchmark.Benchmark):
   test = smoothness.Smoothness
@@ -121,21 +116,20 @@
   """Measures rendering statistics for the key silk cases without GPU
   rasterization.
   """
+  test = smoothness.Smoothness
   page_set = page_sets.KeySilkCasesPageSet
 
   @classmethod
   def Name(cls):
     return 'smoothness.key_silk_cases'
 
-  def CreatePageTest(self, options):  # pylint: disable=unused-argument
-    return smoothness.Smoothness(enable_auto_issuing_marker=False)
-
 
 @benchmark.Enabled('android')
 class SmoothnessGpuRasterizationTop25(benchmark.Benchmark):
   """Measures rendering statistics for the top 25 with GPU rasterization.
   """
   tag = 'gpu_rasterization'
+  test = smoothness.Smoothness
   page_set = page_sets.Top25SmoothPageSet
 
   def CustomizeBrowserOptions(self, options):
@@ -145,9 +139,6 @@
   def Name(cls):
     return 'smoothness.gpu_rasterization.top_25_smooth'
 
-  def CreatePageTest(self, options):  # pylint: disable=unused-argument
-    return smoothness.Smoothness(enable_auto_issuing_marker=False)
-
 
 @benchmark.Enabled('android')
 class SmoothnessGpuRasterizationKeyMobileSites(benchmark.Benchmark):
@@ -155,6 +146,7 @@
   rasterization.
   """
   tag = 'gpu_rasterization'
+  test = smoothness.Smoothness
   page_set = page_sets.KeyMobileSitesSmoothPageSet
 
   def CustomizeBrowserOptions(self, options):
@@ -164,9 +156,6 @@
   def Name(cls):
     return 'smoothness.gpu_rasterization.key_mobile_sites_smooth'
 
-  def CreatePageTest(self, options):  # pylint: disable=unused-argument
-    return smoothness.Smoothness(enable_auto_issuing_marker=False)
-
 
 @benchmark.Enabled('android')
 class SmoothnessSyncScrollKeyMobileSites(benchmark.Benchmark):
@@ -174,6 +163,7 @@
   (main thread) scrolling.
   """
   tag = 'sync_scroll'
+  test = smoothness.Smoothness
   page_set = page_sets.KeyMobileSitesSmoothPageSet
 
   def CustomizeBrowserOptions(self, options):
@@ -183,28 +173,24 @@
   def Name(cls):
     return 'smoothness.sync_scroll.key_mobile_sites_smooth'
 
-  def CreatePageTest(self, options):  # pylint: disable=unused-argument
-    return smoothness.Smoothness(enable_auto_issuing_marker=False)
-
 
 @benchmark.Enabled('android')
 class SmoothnessSimpleMobilePages(benchmark.Benchmark):
   """Measures rendering statistics for simple mobile sites page set.
   """
+  test = smoothness.Smoothness
   page_set = page_sets.SimpleMobileSitesPageSet
 
   @classmethod
   def Name(cls):
     return 'smoothness.simple_mobile_sites'
 
-  def CreatePageTest(self, options):  # pylint: disable=unused-argument
-    return smoothness.Smoothness(enable_auto_issuing_marker=False)
-
 
 @benchmark.Enabled('android')
 class SmoothnessFlingSimpleMobilePages(benchmark.Benchmark):
   """Measures rendering statistics for flinging a simple mobile sites page set.
   """
+  test = smoothness.Smoothness
   page_set = page_sets.SimpleMobileSitesFlingPageSet
 
   def CustomizeBrowserOptions(self, options):
@@ -217,57 +203,49 @@
   def Name(cls):
     return 'smoothness.fling.simple_mobile_sites'
 
-  def CreatePageTest(self, options):  # pylint: disable=unused-argument
-    return smoothness.Smoothness(enable_auto_issuing_marker=False)
-
 
 @benchmark.Enabled('android', 'chromeos')
 class SmoothnessToughPinchZoomCases(benchmark.Benchmark):
   """Measures rendering statistics for pinch-zooming into the tough pinch zoom
   cases.
   """
+  test = smoothness.Smoothness
   page_set = page_sets.ToughPinchZoomCasesPageSet
 
   @classmethod
   def Name(cls):
     return 'smoothness.tough_pinch_zoom_cases'
 
-  def CreatePageTest(self, options):  # pylint: disable=unused-argument
-    return smoothness.Smoothness(enable_auto_issuing_marker=False)
-
 
 @benchmark.Enabled('android', 'chromeos')
 class SmoothnessToughScrollingWhileZoomedInCases(benchmark.Benchmark):
   """Measures rendering statistics for pinch-zooming then diagonal scrolling"""
+  test = smoothness.Smoothness
   page_set = page_sets.ToughScrollingWhileZoomedInCasesPageSet
 
   @classmethod
   def Name(cls):
     return 'smoothness.tough_scrolling_while_zoomed_in_cases'
 
-  def CreatePageTest(self, options):  # pylint: disable=unused-argument
-    return smoothness.Smoothness(enable_auto_issuing_marker=False)
-
 
 @benchmark.Enabled('android')
 class SmoothnessPolymer(benchmark.Benchmark):
   """Measures rendering statistics for Polymer cases.
   """
+  test = smoothness.Smoothness
   page_set = page_sets.PolymerPageSet
 
   @classmethod
   def Name(cls):
     return 'smoothness.polymer'
 
-  def CreatePageTest(self, options):  # pylint: disable=unused-argument
-    return smoothness.Smoothness(enable_auto_issuing_marker=False)
-
 
 @benchmark.Enabled('android')
 class SmoothnessGpuRasterizationPolymer(benchmark.Benchmark):
   """Measures rendering statistics for the Polymer cases with GPU rasterization.
   """
   tag = 'gpu_rasterization'
+  test = smoothness.Smoothness
   page_set = page_sets.PolymerPageSet
 
   def CustomizeBrowserOptions(self, options):
@@ -277,9 +255,6 @@
   def Name(cls):
     return 'smoothness.gpu_rasterization.polymer'
 
-  def CreatePageTest(self, options):  # pylint: disable=unused-argument
-    return smoothness.Smoothness(enable_auto_issuing_marker=False)
-
 
 class SmoothnessToughFastScrollingCases(benchmark.Benchmark):
   test = smoothness.Smoothness
@@ -327,15 +302,13 @@
 class SmoothnessPathologicalMobileSites(benchmark.Benchmark):
   """Measures task execution statistics while scrolling pathological sites.
   """
+  test = smoothness.Smoothness
   page_set = page_sets.PathologicalMobileSitesPageSet
 
   @classmethod
   def Name(cls):
     return 'smoothness.pathological_mobile_sites'
 
-  def CreatePageTest(self, options):  # pylint: disable=unused-argument
-    return smoothness.Smoothness(enable_auto_issuing_marker=False)
-
 
 @benchmark.Enabled('android')
 class SmoothnessSyncScrollPathologicalMobileSites(benchmark.Benchmark):
@@ -343,6 +316,7 @@
   """
   tag = 'sync_scroll'
   page_set = page_sets.PathologicalMobileSitesPageSet
+  test = smoothness.Smoothness
 
   def CustomizeBrowserOptions(self, options):
     silk_flags.CustomizeBrowserOptionsForSyncScrolling(options)
@@ -351,9 +325,6 @@
   def Name(cls):
     return 'smoothness.sync_scroll.pathological_mobile_sites'
 
-  def CreatePageTest(self, options):  # pylint: disable=unused-argument
-    return smoothness.Smoothness(enable_auto_issuing_marker=False)
-
 
 class SmoothnessToughAnimatedImageCases(benchmark.Benchmark):
   test = smoothness.Smoothness
diff --git a/tools/perf/measurements/repaint.py b/tools/perf/measurements/repaint.py
index ec4e5f1..454fcaa 100644
--- a/tools/perf/measurements/repaint.py
+++ b/tools/perf/measurements/repaint.py
@@ -21,10 +21,8 @@
 
   def WillRunActions(self, page, tab):
     tab.WaitForDocumentReadyStateToBeComplete()
-    self._smoothness_controller = smoothness_controller.SmoothnessController(
-        auto_issuing_marker=False)
-    self._smoothness_controller.SetUp(page, tab)
-    self._smoothness_controller.Start(tab)
+    self._smoothness_controller = smoothness_controller.SmoothnessController()
+    self._smoothness_controller.Start(page, tab)
 
   def DidRunActions(self, page, tab):
     self._smoothness_controller.Stop(tab)
diff --git a/tools/perf/measurements/smoothness.py b/tools/perf/measurements/smoothness.py
index 6cf2741..da2392d4 100644
--- a/tools/perf/measurements/smoothness.py
+++ b/tools/perf/measurements/smoothness.py
@@ -8,10 +8,9 @@
 
 
 class Smoothness(page_test.PageTest):
-  def __init__(self, enable_auto_issuing_marker=False):
+  def __init__(self):
     super(Smoothness, self).__init__()
     self._smoothness_controller = None
-    self._enable_auto_issuing_marker = enable_auto_issuing_marker
 
   @classmethod
   def CustomizeBrowserOptions(cls, options):
@@ -20,12 +19,8 @@
     options.AppendExtraBrowserArgs('--running-performance-benchmark')
 
   def WillNavigateToPage(self, page, tab):
-    self._smoothness_controller = smoothness_controller.SmoothnessController(
-        auto_issuing_marker=self._enable_auto_issuing_marker)
-    self._smoothness_controller.SetUp(page, tab)
-
-  def WillRunActions(self, page, tab):
-    self._smoothness_controller.Start(tab)
+    self._smoothness_controller = smoothness_controller.SmoothnessController()
+    self._smoothness_controller.Start(page, tab)
 
   def DidRunActions(self, page, tab):
     self._smoothness_controller.Stop(tab)
diff --git a/tools/perf/measurements/smoothness_controller.py b/tools/perf/measurements/smoothness_controller.py
index 1aa1fd7c..31d2a5a 100644
--- a/tools/perf/measurements/smoothness_controller.py
+++ b/tools/perf/measurements/smoothness_controller.py
@@ -1,19 +1,15 @@
 # Copyright 2014 The Chromium 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 sys
-
 from telemetry.core.platform import tracing_category_filter
 from telemetry.core.platform import tracing_options
-from telemetry.page import action_runner
 from telemetry.timeline.model import TimelineModel
 from telemetry.value import trace
 from telemetry.web_perf.metrics import smoothness
 from telemetry.web_perf import smooth_gesture_util
 from telemetry.web_perf import timeline_interaction_record as tir_module
 
-
-RUN_SMOOTH_ACTIONS = 'RunSmoothAllActions'
+from telemetry.page import page_test
 
 
 class SmoothnessController(object):
@@ -22,9 +18,8 @@
     self._trace_data = None
     self._interaction = None
     self._surface_flinger_trace_data = None
-    self._auto_issuing_marker = auto_issuing_marker
 
-  def SetUp(self, page, tab):
+  def Start(self, page, tab):
     # FIXME: Remove webkit.console when blink.console lands in chromium and
     # the ref builds are updated. crbug.com/386847
     custom_categories = ['webkit.console', 'blink.console', 'benchmark']
@@ -37,18 +32,7 @@
     options.enable_platform_display_trace = True
     tab.browser.platform.tracing_controller.Start(options, category_filter, 60)
 
-  def Start(self, tab):
-    # Start the smooth marker for all smooth actions.
-    runner = action_runner.ActionRunner(tab)
-    if self._auto_issuing_marker:
-      self._interaction = runner.CreateInteraction(
-          RUN_SMOOTH_ACTIONS)
-      self._interaction.Begin()
-
   def Stop(self, tab):
-    # End the smooth marker for  all smooth actions.
-    if self._auto_issuing_marker:
-      self._interaction.End()
     self._trace_data = tab.browser.platform.tracing_controller.Stop()
     self._timeline_model = TimelineModel(self._trace_data)
 
@@ -60,35 +44,35 @@
         results.current_page, self._trace_data))
     renderer_thread = self._timeline_model.GetRendererThreadFromTabId(
         tab.id)
-    run_smooth_actions_record = None
     smooth_records = []
     for event in renderer_thread.async_slices:
       if not tir_module.IsTimelineInteractionRecord(event.name):
         continue
       r = tir_module.TimelineInteractionRecord.FromAsyncEvent(event)
-      if r.label == RUN_SMOOTH_ACTIONS:
-        assert run_smooth_actions_record is None, (
-          'SmoothnessController cannot issue more than 1 %s record' %
-          RUN_SMOOTH_ACTIONS)
-        run_smooth_actions_record = r
-      else:
-        smooth_records.append(
-          smooth_gesture_util.GetAdjustedInteractionIfContainGesture(
-            self._timeline_model, r))
+      smooth_records.append(
+        smooth_gesture_util.GetAdjustedInteractionIfContainGesture(
+          self._timeline_model, r))
 
     # If there is no other smooth records, we make measurements on time range
     # marked smoothness_controller itself.
     # TODO(nednguyen): when crbug.com/239179 is marked fixed, makes sure that
     # page sets are responsible for issueing the markers themselves.
     if len(smooth_records) == 0:
-      if run_smooth_actions_record is None:
-        sys.stderr.write('Raw tracing data:\n')
-        self._trace_data.Serialize(sys.stderr)
-        sys.stderr.write('\n')
-        raise Exception('SmoothnessController failed to issue markers for the '
-                        'whole interaction.')
-      else:
-        smooth_records = [run_smooth_actions_record]
+      raise page_test.Failure('Page failed to issue any markers.')
+
+    # Check to make sure all smooth records have same label and repeatable if
+    # there are more than one.
+    need_repeatable_flag = len(smooth_records) > 1
+    record_label = smooth_records[0].label
+    for r in smooth_records:
+      if r.label != record_label:
+        raise page_test.Failure(
+            'SmoothController does not support multiple interactions with '
+            'different label. Interactions: %s' % repr(smooth_records))
+      if need_repeatable_flag and not r.repeatable:
+        raise page_test.Failure(
+            'If there are more than one interaction record, each interaction '
+            'must has repeatable flag. Interactions: %s' % repr(smooth_records))
 
     # Create an interaction_record for this legacy measurement. Since we don't
     # wrap the results that are sent to smoothness metric, the label will
diff --git a/tools/perf/page_sets/key_silk_cases.py b/tools/perf/page_sets/key_silk_cases.py
index 347ed92..9c35a7cb 100644
--- a/tools/perf/page_sets/key_silk_cases.py
+++ b/tools/perf/page_sets/key_silk_cases.py
@@ -319,13 +319,16 @@
     self.StressHideyBars(action_runner)
 
   def StressHideyBars(self, action_runner):
-    with action_runner.CreateGestureInteraction('ScrollAction'):
+    with action_runner.CreateGestureInteraction(
+        'ScrollAction', repeatable=True):
       action_runner.ScrollElement(
         selector='#messages', direction='down', speed_in_pixels_per_second=200)
-    with action_runner.CreateGestureInteraction('ScrollAction'):
+    with action_runner.CreateGestureInteraction(
+        'ScrollAction', repeatable=True):
       action_runner.ScrollElement(
           selector='#messages', direction='up', speed_in_pixels_per_second=200)
-    with action_runner.CreateGestureInteraction('ScrollAction'):
+    with action_runner.CreateGestureInteraction(
+        'ScrollAction', repeatable=True):
       action_runner.ScrollElement(
           selector='#messages', direction='down',
           speed_in_pixels_per_second=200)
@@ -343,7 +346,7 @@
       self.ToggleDrawer(action_runner)
 
   def ToggleDrawer(self, action_runner):
-    with action_runner.CreateInteraction('Action_TapAction'):
+    with action_runner.CreateInteraction('Action_TapAction', repeatable=True):
       action_runner.TapElement('#menu-button')
       action_runner.Wait(1)
 
@@ -482,12 +485,14 @@
       page_set=page_set, run_no_page_interactions=run_no_page_interactions)
 
   def PerformPageInteractions(self, action_runner):
-    with action_runner.CreateGestureInteraction('ScrollAction'):
+    with action_runner.CreateGestureInteraction('ScrollAction',
+                                                repeatable=True):
       action_runner.ScrollPage(
           distance_expr='window.innerHeight / 2',
           direction='down',
           use_touch=True)
-    with action_runner.CreateInteraction('Wait'):
+    with action_runner.CreateGestureInteraction('ScrollAction',
+                                                repeatable=True):
       action_runner.Wait(1)
 
 
@@ -530,11 +535,11 @@
     action_runner.Wait(1)
 
   def PerformPageInteractions(self, action_runner):
-    with action_runner.CreateGestureInteraction('SwipeAction'):
+    with action_runner.CreateGestureInteraction('SwipeAction', repeatable=True):
       action_runner.SwipeElement(
           direction='left', distance=100,
           element_function='document.getElementById(":f")')
-    with action_runner.CreateInteraction('Wait'):
+    with action_runner.CreateGestureInteraction('SwipeAction', repeatable=True):
       action_runner.Wait(1)
 
 
@@ -577,7 +582,7 @@
     for i in xrange(9):
       button_func = ('document.getElementById("demo").$.'
                      'buttons.children[%d]') % i
-      with action_runner.CreateInteraction('Action_TapAction'):
+      with action_runner.CreateInteraction('Action_TapAction', repeatable=True):
         action_runner.TapElement(element_function=button_func)
         action_runner.Wait(1)
 
diff --git a/tools/perf/page_sets/polymer.py b/tools/perf/page_sets/polymer.py
index bbab4d4..e75fc09c 100644
--- a/tools/perf/page_sets/polymer.py
+++ b/tools/perf/page_sets/polymer.py
@@ -53,7 +53,7 @@
     self.SlidePanel(action_runner)
 
   def TapButton(self, action_runner):
-    with action_runner.CreateInteraction('Action_TapAction'):
+    with action_runner.CreateInteraction('PolymerAnimation', repeatable=True):
       action_runner.TapElement(element_function='''
           document.querySelector(
               'body /deep/ #outerPanels'
@@ -72,7 +72,7 @@
           return outer.opened || outer.wideMode;
           }());''')
     if not opened:
-      with action_runner.CreateInteraction('Action_SwipeAction'):
+      with action_runner.CreateInteraction('PolymerAnimation', repeatable=True):
         action_runner.SwipeElement(
             left_start_ratio=0.1, top_start_ratio=0.2,
             direction='left', distance=300, speed_in_pixels_per_second=5000,
@@ -155,12 +155,12 @@
   def ScrollContentPane(self, action_runner):
     element_function = (self.iframe_js + '.querySelector('
         '"core-scroll-header-panel").$.mainContainer')
-    with action_runner.CreateInteraction('Scroll_Page'):
+    with action_runner.CreateInteraction('Scroll_Page', repeatable=True):
       action_runner.ScrollElement(use_touch=True,
                                   direction='down',
                                   distance='900',
                                   element_function=element_function)
-    with action_runner.CreateInteraction('Scroll_Page'):
+    with action_runner.CreateInteraction('Scroll_Page', repeatable=True):
       action_runner.ScrollElement(use_touch=True,
                                   direction='up',
                                   distance='900',
@@ -201,7 +201,7 @@
         action_function(action_runner, element_query)
 
   def TapWidget(self, action_runner, element_function):
-    with action_runner.CreateInteraction('Tap_Widget'):
+    with action_runner.CreateInteraction('Tap_Widget', repeatable=True):
       action_runner.TapElement(element_function=element_function)
       action_runner.Wait(1) # wait for e.g. animations on the widget