Remove fps_meter from tool library

This patch is a part of a series of patches. The goal is to move
the fps_meter to autotest library and update the ebuild file so
that it is added to the /usr/local/bin and it can be used as a
tool accordingly. In this particular patch, the fps_meter is
removed from the tool library.

BUG=chromium:845378
TEST=Manual tested
CQ-DEPEND=CL:1074781

Change-Id: Ib7ef74fc088cba5ce65dc5b8f1e361a9b63fdb39
Reviewed-on: https://chromium-review.googlesource.com/1073350
Commit-Ready: Yi Xu <yiyix@chromium.org>
Tested-by: Chung-yih Wang <cywang@chromium.org>
Reviewed-by: Chung-yih Wang <cywang@chromium.org>
Reviewed-by: Mike Frysinger <vapier@chromium.org>
diff --git a/fps_meter/fps_meter.py b/fps_meter/fps_meter.py
deleted file mode 100755
index 3826b66..0000000
--- a/fps_meter/fps_meter.py
+++ /dev/null
@@ -1,316 +0,0 @@
-#!/usr/bin/python
-# Copyright 2018 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.
-
-"""Checks kernel tracing events to get the FPS of a CrOS device.
-
-This script requires root privilege to work properly. It may interfere
-Chrome tracing because both use ftrace.
-
-Limitation:
-It doesn't support multi-screen.
-It assumes 60 HZ screen refresh rate.
-
-This script can be used both as a stand alone script or a library.
-
-Sample output (when used as a stand alone script):
-  # ./fps_meter.py
-  trace method: workq
-  [111111111111111111111111111111111111111111111111111111111111] FPS: 60
-  [111111111111111111111111111111111111111111111111111111111111] FPS: 60
-  [11111111111111111111111111111111111111111111111 111111111111] FPS: 59
-  [111111111111111111111111111111111111111111111111111111111111] FPS: 60
-  [11111111111111 11111111111111111111 11111111 111111111111111] FPS: 57
-  [111111111111111111111111111111111    11111111111111111111111] FPS: 56
-  [111   111111111111111111111111111111111111111111111111111111] FPS: 57
-   ^
-     1 : Frame update count detected in this 1/60 sec interval.
-
-Sample Usage (when used as a library).
-  def callback(fps):
-    ...
-
-  with FPSMeter(callback) as fps_meter:
-    ...
-
-When used as a library, it launches two threads to monitor system FPS rate
-periodically. Each time when a FPS rate is sampled, callback() is called with
-the FPS number as its parameter.
-"""
-import argparse
-import atexit
-import collections
-import functools
-import logging
-import os
-import re
-import threading
-import time
-
-TRACE_ROOT = '/sys/kernel/debug/tracing/'
-VBLANK_SWITCH = os.path.join(TRACE_ROOT, 'events/drm/drm_vblank_event/enable')
-FLIP_SWITCH = os.path.join(TRACE_ROOT, 'events/i915/i915_flip_complete/enable')
-WORKQ_SWITCH = os.path.join(
-    TRACE_ROOT, 'events/workqueue/workqueue_execute_start/enable')
-WORKQ_FILTER = os.path.join(
-    TRACE_ROOT, 'events/workqueue/workqueue_execute_start/filter')
-TRACE_SWITCH = os.path.join(TRACE_ROOT, 'tracing_on')
-TRACE_CLOCK = os.path.join(TRACE_ROOT, 'trace_clock')
-TRACE_LOG = os.path.join(TRACE_ROOT, 'trace')
-TRACE_PIPE = os.path.join(TRACE_ROOT, 'trace_pipe')
-TRACE_MARKER = os.path.join(TRACE_ROOT, 'trace_marker')
-REFRESH_RATE = 60
-NOTIFY_STRING = 'notify_collection'
-STOP_STRING = 'stop_tracing'
-
-
-def is_intel_gpu():
-  """Whether is intel GPU."""
-  return os.path.isdir('/sys/bus/pci/drivers/i915')
-
-
-def get_kernel_version():
-  with open('/proc/version') as fin:
-    m = re.match(r'Linux version (\d+.\d+).\d+', fin.read())
-    if m:
-      return m.group(1)
-  return 'unknown'
-
-
-def get_trace_method():
-  """Gets the FPS checking method.
-
-  Checks i915_flip_complete for Intel GPU on Kernel 3.18.
-  Checks intel_atomic_commit_work for Intel GPU on Kernel 4.4.
-  Checks drm_vblank_event otherwise.
-  """
-  if is_intel_gpu():
-    kernel_version = get_kernel_version()
-    if kernel_version == '4.4':
-      return 'workq'
-    elif kernel_version == '3.18':
-      return 'flip'
-  # Fallback.
-  return 'vblank'
-
-
-def write_to_file(content, filename):
-  """Writes content to a file."""
-  with open(filename, 'w') as fout:
-    fout.write(content)
-
-
-def set_simple_switch(value, filename):
-  with open(filename) as fin:
-    orig = fin.read().strip()
-    atexit.register(write_to_file, orig, filename)
-  write_to_file(value, filename)
-
-
-def set_trace_clock():
-  # Set trace clock to mono time as chrome tracing in CrOS.
-  PREFERRED_TRACE_CLOCK = 'mono'
-  with open(TRACE_CLOCK) as trace_clock:
-    m = re.match(r'.*\[(\w+)\]', trace_clock.read())
-    if m:
-      orig_clock = m.group(1)
-      atexit.register(write_to_file, orig_clock, TRACE_CLOCK)
-  write_to_file(PREFERRED_TRACE_CLOCK, TRACE_CLOCK)
-
-
-def get_kernel_symbol_addr(symbol):
-  # Example line in kallsyms:
-  # ffffffffbc46cb03 T sys_exit
-  with open('/proc/kallsyms') as kallsyms:
-    for line in kallsyms:
-      items = line.split()
-      if items[2] == symbol:
-        addr = items[0]
-        return addr
-  return None
-
-
-def set_workq_filter(function_name):
-  addr = get_kernel_symbol_addr(function_name)
-  if addr:
-    filter = 'function == 0x%s' % addr
-    write_to_file(filter, WORKQ_FILTER)
-    # Sets to 0 to remove the filter.
-    atexit.register(write_to_file, '0', WORKQ_FILTER)
-
-
-def enable_tracing(trace_method):
-  """Enables tracing."""
-  if trace_method == 'workq':
-    set_simple_switch('1', WORKQ_SWITCH)
-    # There are many workqueue_execute_start events,
-    # filter to reduce CPU usage.
-    set_workq_filter('intel_atomic_commit_work')
-  elif trace_method == 'flip':
-    set_simple_switch('1', FLIP_SWITCH)
-  else:
-    set_simple_switch('1', VBLANK_SWITCH)
-
-  set_simple_switch('1', TRACE_SWITCH)
-  set_trace_clock()
-
-
-def get_fps_info(trace_buffer, end_time):
-  # Checks all vblanks in the range [end_time - 1.0, end_time].
-  frame_info = []
-  step = 1.0 / REFRESH_RATE
-  step_time = end_time - 1.0 + step
-  frame_times = []
-  for _ in range(REFRESH_RATE):
-    # Checks if there are vblanks in a refresh interval.
-    step_count = 0
-    while trace_buffer and trace_buffer[0] < step_time:
-      frame_times.append(trace_buffer.popleft())
-      step_count += 1
-
-    # Each character represent an 1 / REFRESH_RATE interval.
-    if step_count:
-      if step_count >= 10:
-        frame_info.append('*')
-      else:
-        frame_info.append(str(step_count))
-    else:
-      frame_info.append(' ')
-    step_time += step
-
-  return frame_info, frame_times
-
-
-def start_thread(function, args=()):
-  """Starts a thread with given argument."""
-  new_thread = threading.Thread(target=function, args=args)
-  new_thread.start()
-
-
-class FPSMeter():
-  """A FPSMeter to measure system FPS periodically."""
-  def __init__(self, callback):
-    self.is_stopping = threading.Event()
-    self.callback = callback
-
-  def __enter__(self):
-    self.start()
-    return self
-
-  def __exit__(self, type, value, traceback):
-    self.stop()
-
-  def notify_collection(self, period_sec=1.0):
-    """Writes a notification mark periodically."""
-    logging.info('Notification thread is started')
-    next_notify_time = time.time() + period_sec
-    while True:
-      # Calling time.sleep(1) may suspend for more than 1 second.
-      # Sleeps until a specific time to avoid error accumulation.
-      sleep_time = next_notify_time - time.time()
-      next_notify_time += period_sec
-      # Skips if current time is larger than next_notify_time.
-      if sleep_time > 0:
-        if self.is_stopping.wait(sleep_time):
-          logging.info('Leaving notification thread')
-          # So the main loop doesn't stuck in the readline().
-          write_to_file(STOP_STRING, TRACE_MARKER)
-          break
-        write_to_file(NOTIFY_STRING, TRACE_MARKER)
-
-  def main_loop(self, trace_method):
-    """Main loop to parse the trace.
-
-    There are 2 threads involved:
-    Main thread:
-      Using blocking read to get data from trace_pipe.
-    Notify thread: The main thread may wait indifinitely if there
-      is no new trace. Writes to the pipe once per second to avoid
-      the indefinite waiting.
-    """
-    logging.info('Fps meter main thread is started.')
-
-    # Sample trace:
-    # <idle>-0  [000] dNh3 631.905961: drm_vblank_event: crtc=0, seq=65496
-    # <idle>-0  [000] d.h3 631.922681: drm_vblank_event: crtc=0, seq=65497
-    # fps_meter [003] ...1 632.393953: tracing_mark_write: notify_collection
-    # ...
-    re_notify = re.compile(
-        r'.* (\d+.\d+): tracing_mark_write: ' + NOTIFY_STRING)
-    if trace_method == 'workq':
-      re_trace = re.compile(
-          r'.* (\d+.\d+): workqueue_execute_start: work struct ([\da-f]+): '
-          'function intel_atomic_commit_work')
-    elif trace_method == 'flip':
-      re_trace = re.compile(
-          r'.* (\d+.\d+): i915_flip_complete: plane=(\d+), obj=([\da-f]+)')
-    else:
-      re_trace = re.compile(
-          r'.* (\d+.\d+): drm_vblank_event: crtc=(\d+), seq=(\d+)')
-
-    trace_buffer = collections.deque()
-    with open(TRACE_PIPE) as trace_pipe:
-      # The pipe may block a few seconds if using:
-      # for line in trace_pipe
-      while not self.is_stopping.is_set():
-        line = trace_pipe.readline()
-        m_trace = re_trace.match(line)
-        if m_trace:
-          timestamp = float(m_trace.group(1))
-          trace_buffer.append(timestamp)
-        else:
-          m_notify = re_notify.match(line)
-          if m_notify:
-            timestamp = float(m_notify.group(1))
-            self.callback(get_fps_info(trace_buffer, timestamp))
-      logging.info('Leaving fps meter main thread')
-
-  def start(self):
-    """Starts the FPS meter by launching needed threads."""
-    # The notificaiton thread.
-    start_thread(self.notify_collection)
-
-    # The main thread.
-    trace_method = get_trace_method()
-    enable_tracing(trace_method)
-    start_thread(self.main_loop, [trace_method])
-
-  def stop(self):
-    """Stops the FPS meter. Shut down threads."""
-    logging.info('Shutting down FPS meter')
-    self.is_stopping.set()
-
-
-def output_fps_info(verbose, fps_info):
-  frame_info, frame_times = fps_info
-  fps_count = len([f for f in frame_info if f != ' '])
-  frame_info_str = ''.join(frame_info)
-  print '[%s] FPS: %2d' % (frame_info_str, fps_count)
-  if frame_times and verbose:
-    print ', '.join(['%.3f' % t for t in frame_times])
-
-
-if __name__ == '__main__':
-  # parsing arguments
-  parser = argparse.ArgumentParser(description='Print fps infomation.')
-  parser.add_argument('-v', dest='verbose', action='store_true',
-                      help='print verbose frame time info')
-  parser.add_argument('-d', dest='debug', action='store_true',
-                      help='print debug message')
-  args = parser.parse_args()
-
-  if args.debug:
-    rootLogger = logging.getLogger()
-    rootLogger.setLevel(logging.DEBUG)
-    # StreamHandler() defaults to stderr.
-    rootLogger.addHandler(logging.StreamHandler())
-
-  print 'FPS meter trace method %s' % get_trace_method()
-  with FPSMeter(functools.partial(output_fps_info, args.verbose)) as fps_meter:
-    while True:
-      try:
-        time.sleep(86400)
-      except KeyboardInterrupt:
-        print 'Exiting...'
-        break