Revert "Remove scripts related to iorap"

Revert "Remove iorap daemon codes"

Revert "Remove configs relevant to iorap"

Revert submission 16528474-remove-iorap

Reason for revert: build break
Reverted Changes:
I464c9e9c4:Remove scripts related to iorap
I0b8b1b064:Remove iorap daemon codes
I848f65908:Remove iorap framework codes
I294f37265:Remove configs relevant to iorap

Change-Id: I4a01c135c1509112116d340f5cfdda579e27cbcd
diff --git a/startop/scripts/lib/logcat_utils.py b/startop/scripts/lib/logcat_utils.py
new file mode 100644
index 0000000..8a3d00b
--- /dev/null
+++ b/startop/scripts/lib/logcat_utils.py
@@ -0,0 +1,104 @@
+#!/usr/bin/env python3
+#
+# Copyright 2019, The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+"""Helper util libraries for parsing logcat logs."""
+
+import asyncio
+import re
+from datetime import datetime
+from typing import Optional, Pattern
+
+# local import
+import lib.print_utils as print_utils
+
+def parse_logcat_datetime(timestamp: str) -> Optional[datetime]:
+  """Parses the timestamp of logcat.
+
+  Params:
+    timestamp: for example "2019-07-01 16:13:55.221".
+
+  Returns:
+    a datetime of timestamp with the year now.
+  """
+  try:
+    # Match the format of logcat. For example: "2019-07-01 16:13:55.221",
+    # because it doesn't have year, set current year to it.
+    timestamp = datetime.strptime(timestamp,
+                                  '%Y-%m-%d %H:%M:%S.%f')
+    return timestamp
+  except ValueError as ve:
+    print_utils.debug_print('Invalid line: ' + timestamp)
+    return None
+
+def _is_time_out(timeout: datetime, line: str) -> bool:
+  """Checks if the timestamp of this line exceeds the timeout.
+
+  Returns:
+    true if the timestamp exceeds the timeout.
+  """
+  # Get the timestampe string.
+  cur_timestamp_str = ' '.join(re.split(r'\s+', line)[0:2])
+  timestamp = parse_logcat_datetime(cur_timestamp_str)
+  if not timestamp:
+    return False
+
+  return timestamp > timeout
+
+async def _blocking_wait_for_logcat_pattern(timestamp: datetime,
+                                            pattern: Pattern,
+                                            timeout: datetime) -> Optional[str]:
+  # Show the year in the timestampe.
+  logcat_cmd = 'adb logcat -v UTC -v year -v threadtime -T'.split()
+  logcat_cmd.append(str(timestamp))
+  print_utils.debug_print('[LOGCAT]:' + ' '.join(logcat_cmd))
+
+  # Create subprocess
+  process = await asyncio.create_subprocess_exec(
+      *logcat_cmd,
+      # stdout must a pipe to be accessible as process.stdout
+      stdout=asyncio.subprocess.PIPE)
+
+  while (True):
+    # Read one line of output.
+    data = await process.stdout.readline()
+    line = data.decode('utf-8').rstrip()
+
+    # 2019-07-01 14:54:21.946 27365 27392 I ActivityTaskManager: Displayed
+    # com.android.settings/.Settings: +927ms
+    # TODO: Detect timeouts even when there is no logcat output.
+    if _is_time_out(timeout, line):
+      print_utils.debug_print('DID TIMEOUT BEFORE SEEING ANYTHING ('
+                              'timeout={timeout} seconds << {pattern} '
+                              '>>'.format(timeout=timeout, pattern=pattern))
+      return None
+
+    if pattern.match(line):
+      print_utils.debug_print(
+          'WE DID SEE PATTERN << "{}" >>.'.format(pattern))
+      return line
+
+def blocking_wait_for_logcat_pattern(timestamp: datetime,
+                                     pattern: Pattern,
+                                     timeout: datetime) -> Optional[str]:
+  """Selects the line that matches the pattern and within the timeout.
+
+  Returns:
+    the line that matches the pattern and within the timeout.
+  """
+  loop = asyncio.get_event_loop()
+  result = loop.run_until_complete(
+      _blocking_wait_for_logcat_pattern(timestamp, pattern, timeout))
+  return result